From 9b0caaf78f2181d6cca87c8e72fe96f52490ded3 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Tue, 19 Sep 2023 01:06:25 +0800 Subject: [PATCH 01/10] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0=20"=E6=8E=92?= =?UTF-8?q?=E4=BD=8D=E6=A8=A1=E5=BC=8F=E4=B8=8B=20=E5=AF=B9=E5=B1=80?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=20=E9=A1=B5=E8=BF=87=E6=BB=A4=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=A8=A1=E5=BC=8F"=20=E8=AE=BE=E7=BD=AE=E9=80=89?= =?UTF-8?q?=E9=A1=B9=202.=20=E4=BF=AE=E6=AD=A3=20mode=5Ffilter=5Fwidget.py?= =?UTF-8?q?=20=E4=B8=AD=20vBoxLayout=20=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/config.py | 2 ++ app/common/icons.py | 1 + app/components/mode_filter_widget.py | 15 +++++++-------- app/resource/icons/Filter_black.svg | 1 + app/resource/icons/Filter_white.svg | 1 + app/view/setting_interface.py | 9 +++++++++ 6 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 app/resource/icons/Filter_black.svg create mode 100644 app/resource/icons/Filter_white.svg diff --git a/app/common/config.py b/app/common/config.py index 6dc5b7e7..b276bc0f 100644 --- a/app/common/config.py +++ b/app/common/config.py @@ -55,6 +55,8 @@ class Config(QConfig): teamGamesNumber = RangeConfigItem("Functions", "TeamGamesNumber", 1, RangeValidator(1, 10)) + gameInfoFilter = ConfigItem("Functions", "GameInfoFilter", False, BoolValidator()) + showTierInGameInfo = ConfigItem("Functions", "ShowTierInGameInfo", False, BoolValidator()) enableAutoAcceptMatching = ConfigItem("Functions", diff --git a/app/common/icons.py b/app/common/icons.py index 165063a7..dd077a32 100644 --- a/app/common/icons.py +++ b/app/common/icons.py @@ -41,6 +41,7 @@ class Icon(FluentIconBase, Enum): LOCK = 'Lock' TEAM = 'Team' SETTING = 'Setting' + FILTER = 'Filter' def path(self, theme=Theme.AUTO): return f'./app/resource/icons/{self.value}_{getIconColor(theme)}.svg' diff --git a/app/components/mode_filter_widget.py b/app/components/mode_filter_widget.py index a734f0c9..0b6d4185 100644 --- a/app/components/mode_filter_widget.py +++ b/app/components/mode_filter_widget.py @@ -14,10 +14,9 @@ def __init__(self, parent=None): self.selected: List[int] = [] - self.hBoxLayout = QVBoxLayout(self) - self.hBoxLayout.setAlignment(Qt.AlignCenter) + self.vBoxLayout = QVBoxLayout(self) + self.vBoxLayout.setAlignment(Qt.AlignCenter) - # TODO 本地化 self.rankSoloCheckBox = CheckBox(self.tr("Ranked solo")) self.rankFlexCheckBox = CheckBox(self.tr("Ranked Flex")) self.normalCheckBox = CheckBox(self.tr("Normal")) @@ -34,15 +33,15 @@ def __init__(self, parent=None): checkBox.stateChanged.connect( lambda state, num=num: self.updateSelected(state, num)) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.rankSoloCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.rankFlexCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.normalCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignLeft) + self.vBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignLeft) - self.setLayout(self.hBoxLayout) + self.setLayout(self.vBoxLayout) def updateSelected(self, state, num, callback=None): if state == Qt.Checked: diff --git a/app/resource/icons/Filter_black.svg b/app/resource/icons/Filter_black.svg new file mode 100644 index 00000000..7551c780 --- /dev/null +++ b/app/resource/icons/Filter_black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/resource/icons/Filter_white.svg b/app/resource/icons/Filter_white.svg new file mode 100644 index 00000000..f38884dc --- /dev/null +++ b/app/resource/icons/Filter_white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/view/setting_interface.py b/app/view/setting_interface.py index 31c6c366..693783bd 100644 --- a/app/view/setting_interface.py +++ b/app/view/setting_interface.py @@ -69,6 +69,14 @@ def __init__(self, parent=None): self. tr("Setting the maximum number of games shows in the career interface" ), self.functionGroup) + + # TODO 逻辑 + self.gameInfoFilterCard = SwitchSettingCard( + Icon.FILTER, self.tr("Rank filter other mode"), + self.tr("When in ranked mode, filter out other modes on the GameInfo page"), + cfg.gameInfoFilter + ) + self.gameInfoShowTierCard = SwitchSettingCard( Icon.TROPHY, self.tr("Show tier in game information"), self. @@ -192,6 +200,7 @@ def __initLayout(self): # add cards to group self.functionGroup.addSettingCard(self.careerGamesCount) self.functionGroup.addSettingCard(self.teamGamesNumberCard) + self.functionGroup.addSettingCard(self.gameInfoFilterCard) self.functionGroup.addSettingCard(self.gameInfoShowTierCard) self.generalGroup.addSettingCard(self.lolFolderCard) From 92da2308f1fda65a11a401b0a17aaf00868466be Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Tue, 19 Sep 2023 01:06:25 +0800 Subject: [PATCH 02/10] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0=20"=E6=8E=92?= =?UTF-8?q?=E4=BD=8D=E6=A8=A1=E5=BC=8F=E4=B8=8B=20=E5=AF=B9=E5=B1=80?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=20=E9=A1=B5=E8=BF=87=E6=BB=A4=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=A8=A1=E5=BC=8F"=20=E8=AE=BE=E7=BD=AE=E9=80=89?= =?UTF-8?q?=E9=A1=B9=202.=20=E4=BF=AE=E6=AD=A3=20mode=5Ffilter=5Fwidget.py?= =?UTF-8?q?=20=E4=B8=AD=20vBoxLayout=20=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/config.py | 2 ++ app/common/icons.py | 1 + app/components/mode_filter_widget.py | 15 +++++++-------- app/resource/icons/Filter_black.svg | 1 + app/resource/icons/Filter_white.svg | 1 + app/view/setting_interface.py | 9 +++++++++ 6 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 app/resource/icons/Filter_black.svg create mode 100644 app/resource/icons/Filter_white.svg diff --git a/app/common/config.py b/app/common/config.py index 6dc5b7e7..b276bc0f 100644 --- a/app/common/config.py +++ b/app/common/config.py @@ -55,6 +55,8 @@ class Config(QConfig): teamGamesNumber = RangeConfigItem("Functions", "TeamGamesNumber", 1, RangeValidator(1, 10)) + gameInfoFilter = ConfigItem("Functions", "GameInfoFilter", False, BoolValidator()) + showTierInGameInfo = ConfigItem("Functions", "ShowTierInGameInfo", False, BoolValidator()) enableAutoAcceptMatching = ConfigItem("Functions", diff --git a/app/common/icons.py b/app/common/icons.py index 165063a7..dd077a32 100644 --- a/app/common/icons.py +++ b/app/common/icons.py @@ -41,6 +41,7 @@ class Icon(FluentIconBase, Enum): LOCK = 'Lock' TEAM = 'Team' SETTING = 'Setting' + FILTER = 'Filter' def path(self, theme=Theme.AUTO): return f'./app/resource/icons/{self.value}_{getIconColor(theme)}.svg' diff --git a/app/components/mode_filter_widget.py b/app/components/mode_filter_widget.py index a734f0c9..0b6d4185 100644 --- a/app/components/mode_filter_widget.py +++ b/app/components/mode_filter_widget.py @@ -14,10 +14,9 @@ def __init__(self, parent=None): self.selected: List[int] = [] - self.hBoxLayout = QVBoxLayout(self) - self.hBoxLayout.setAlignment(Qt.AlignCenter) + self.vBoxLayout = QVBoxLayout(self) + self.vBoxLayout.setAlignment(Qt.AlignCenter) - # TODO 本地化 self.rankSoloCheckBox = CheckBox(self.tr("Ranked solo")) self.rankFlexCheckBox = CheckBox(self.tr("Ranked Flex")) self.normalCheckBox = CheckBox(self.tr("Normal")) @@ -34,15 +33,15 @@ def __init__(self, parent=None): checkBox.stateChanged.connect( lambda state, num=num: self.updateSelected(state, num)) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.rankSoloCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.rankFlexCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.normalCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignLeft) + self.vBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignLeft) - self.setLayout(self.hBoxLayout) + self.setLayout(self.vBoxLayout) def updateSelected(self, state, num, callback=None): if state == Qt.Checked: diff --git a/app/resource/icons/Filter_black.svg b/app/resource/icons/Filter_black.svg new file mode 100644 index 00000000..7551c780 --- /dev/null +++ b/app/resource/icons/Filter_black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/resource/icons/Filter_white.svg b/app/resource/icons/Filter_white.svg new file mode 100644 index 00000000..f38884dc --- /dev/null +++ b/app/resource/icons/Filter_white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/view/setting_interface.py b/app/view/setting_interface.py index 31c6c366..693783bd 100644 --- a/app/view/setting_interface.py +++ b/app/view/setting_interface.py @@ -69,6 +69,14 @@ def __init__(self, parent=None): self. tr("Setting the maximum number of games shows in the career interface" ), self.functionGroup) + + # TODO 逻辑 + self.gameInfoFilterCard = SwitchSettingCard( + Icon.FILTER, self.tr("Rank filter other mode"), + self.tr("When in ranked mode, filter out other modes on the GameInfo page"), + cfg.gameInfoFilter + ) + self.gameInfoShowTierCard = SwitchSettingCard( Icon.TROPHY, self.tr("Show tier in game information"), self. @@ -192,6 +200,7 @@ def __initLayout(self): # add cards to group self.functionGroup.addSettingCard(self.careerGamesCount) self.functionGroup.addSettingCard(self.teamGamesNumberCard) + self.functionGroup.addSettingCard(self.gameInfoFilterCard) self.functionGroup.addSettingCard(self.gameInfoShowTierCard) self.generalGroup.addSettingCard(self.lolFolderCard) From 9986b543599bfdcd924a76fee300c8935dadfbb6 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Tue, 19 Sep 2023 13:29:13 +0800 Subject: [PATCH 03/10] =?UTF-8?q?1.=20=E6=96=B0=E5=A2=9Egameinfo=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E9=80=BB=E8=BE=91=202.=20=E8=A7=84=E8=8C=83=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 23 +++++++++++++++++++++++ app/view/search_interface.py | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index 2dcbf5cf..3f5f37cf 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -797,6 +797,18 @@ def process_item(item): origGamesInfo = connector.getSummonerGamesByPuuid( puuid, 0, 14) + # FIXME getChampSelectSession 接口没有 queueId的信息 + # if cfg.get(cfg.gameInfoFilter) and queueId in (420, 440): + # origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] + # begIdx = 15 + # while len(origGamesInfo["games"]) < 11: + # endIdx = begIdx + 5 + # origGamesInfo["games"].extend([ + # game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] + # if game["queueId"] in (420, 440) + # ]) + # begIdx = endIdx + 1 + gamesInfo = [processGameData(game) for game in origGamesInfo["games"][:11]] @@ -937,6 +949,17 @@ def process_item(item): origGamesInfo = connector.getSummonerGamesByPuuid( puuid, 0, 14) + if cfg.get(cfg.gameInfoFilter) and queueId in (420, 440): + origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] + begIdx = 15 + while len(origGamesInfo["games"]) < 11: + endIdx = begIdx + 5 + origGamesInfo["games"].extend([ + game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] + if game["queueId"] in (420, 440) + ]) + begIdx = endIdx + 1 + gamesInfo = [processGameData(game) for game in origGamesInfo["games"][0:11]] diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 933a088a..37ff2195 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -959,7 +959,6 @@ def __init__(self, parent=None): self.searchButton = PushButton(self.tr("Search 🔍")) self.careerButton = PushButton(self.tr("Career")) self.filterButton = PushButton(self.tr("Filter")) - self.filterButton.clicked.connect(self.showFilterFlyout) self.gamesView = GamesView() self.currentSummonerName = None @@ -1022,6 +1021,7 @@ def __onSummonerPuuidGetted(self, puuid): def __connectSignalToSlot(self): self.searchButton.clicked.connect(self.__onSearchButtonClicked) self.summonerPuuidGetted.connect(self.__onSummonerPuuidGetted) + self.filterButton.clicked.connect(self.__onShowFilterFlyout) def __showSummonerNotFoundMessage(self): InfoBar.error( @@ -1052,7 +1052,7 @@ def fillterTimerRun(self): self.filterOld = None - def showFilterFlyout(self): + def __onShowFilterFlyout(self): filterFlyout = FlyoutView("", "") filterBoxGroup = ModeFilterWidget() From 74045463364f45e41db0edf801870740c41096f0 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Wed, 20 Sep 2023 02:24:10 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=88=98=E7=BB=A9?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 3 + app/view/search_interface.py | 236 +++++++++++++++++++++++++++++++---- 2 files changed, 214 insertions(+), 25 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index 2dcbf5cf..8622aa53 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -778,6 +778,9 @@ def updateGameInfoInterface(callback=None): summoners = [] data = connector.getChampSelectSession() + # TODO queueId查询逻辑 + isRank = bool(data["myTeam"][0]["assignedPosition"]) # 排位会有预选位 + def process_item(item): summonerId = item["summonerId"] diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 933a088a..3467b620 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -8,7 +8,7 @@ from PyQt5.QtGui import QPixmap from qfluentwidgets import (SmoothScrollArea, LineEdit, PushButton, ToolButton, InfoBar, InfoBarPosition, ToolTipFilter, ToolTipPosition, Theme, isDarkTheme, FlyoutViewBase, Flyout, - CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType) + CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType, ComboBox) from ..common.style_sheet import StyleSheet from ..common.icons import Icon @@ -107,22 +107,86 @@ def __onPrevButtonClicked(self): if self.currentIndex == 1: self.prevButton.setEnabled(False) - def __onNextButtonClicked(self): - if self.currentIndex == 0: - self.begIndex = 0 + def questionPage(self, page, queueId=None) -> bool: + """ - self.currentIndex += 1 + @param page: 需要查询的页码 + @param queueId: 过滤条件 + @return: True -> 此页可以直接返回, False -> 此页未加载完成或超出最大页码 + """ + games = self.window().searchInterface.games - if len(self.stackWidget) <= self.currentIndex: - self.nextButton.setEnabled(False) - self.prevButton.setEnabled(False) - self.updateGames(self.currentIndex) + if queueId is None: + maxPage = int(len(games) / 10) else: - self.stackWidget.setCurrentIndex(self.currentIndex) - self.pageLabel.setText(f"{self.currentIndex}") - if self.currentIndex == self.maxPage: - self.nextButton.setEnabled(False) - self.prevButton.setEnabled(True) + buffer = self.window().searchInterface.queueIdBuffer.get(queueId, []) + maxPage = int(len(buffer) / 10) + + return page < maxPage + + # TODO 信号部分未声明参数 + def __onNextButtonClicked(self, page=1, queueId=None): + + def waitLoadPage(): + while not self.questionPage(page, queueId): + time.sleep(.5) + self.nextButton.setEnabled(True) + self.__onNextButtonClicked(page, queueId) + + games = self.window().searchInterface.games + loadThread = self.window().searchInterface.loadGamesThread # 用于判断还有无获取新数据 + + # TODO 页码判断部分封装为方法, 便于复用 + if queueId is None: + maxPage = int(len(games) / 10) + if page >= maxPage: + if loadThread.is_alive(): + self.nextButton.setEnabled(False) + # TODO 等待加载提示 + threading.Thread(target=waitLoadPage).start() + return + else: # 已到最后一页 + data = games[(page - 1) * 10:] + self.nextButton.setEnabled(False) + else: + data = games[(page - 1) * 10: page * 10] + else: + buffer = self.window().searchInterface.queueIdBuffer.get(queueId, []) + maxPage = int(len(buffer) / 10) + if page >= maxPage: + if loadThread.is_alive(): + self.nextButton.setEnabled(False) + # TODO 等待加载提示 + threading.Thread(target=waitLoadPage).start() + return + else: + tmpBuf = buffer[(page - 1) * 10:] + self.nextButton.setEnabled(False) + else: + tmpBuf = buffer[(page - 1) * 10: page * 10] + + data = [] + for idx in tmpBuf: + data.append(games[idx]) + + self.updateNextPageTabs(data) + self.stackWidget.setCurrentIndex(self.currentIndex) + self.pageLabel.setText(f"{self.currentIndex}") + # if self.currentIndex == self.maxPage: + # self.nextButton.setEnabled(False) + self.prevButton.setEnabled(True) + self.currentIndex += 1 + + # if len(self.stackWidget) <= self.currentIndex: + # self.nextButton.setEnabled(False) + # self.prevButton.setEnabled(False) + # self.updateGames(self.currentIndex) + # else: + # self.stackWidget.setCurrentIndex(self.currentIndex) + # self.pageLabel.setText(f"{self.currentIndex}") + # if self.currentIndex == self.maxPage: + # self.nextButton.setEnabled(False) + # self.prevButton.setEnabled(True) def backToDefaultPage(self): self.currentIndex = 0 @@ -144,6 +208,23 @@ def backToDefaultPage(self): self.prevButton.setVisible(False) self.nextButton.setVisible(False) + def firstCall(self, puuid): + if self.puuid != None: + self.backToDefaultPage() + + self.puuid = puuid + self.first = True + self.prevButton.setVisible(True) + self.nextButton.setVisible(True) + self.__onNextButtonClicked() + # self.currentIndex += 1 + # self.stackWidget.setCurrentIndex(self.currentIndex) + # self.pageLabel.setText(f"{self.currentIndex}") + # if self.currentIndex == self.maxPage: + # self.nextButton.setEnabled(False) + # if len(self.games) == 0: + # self.__showEmptyPage() + def updatePuuid(self, puuid): if self.puuid != None: self.backToDefaultPage() @@ -154,6 +235,37 @@ def updatePuuid(self, puuid): self.nextButton.setVisible(True) self.__onNextButtonClicked() + def updateNextPageTabs(self, data): + widget = QWidget() + layout = QVBoxLayout(widget) + layout.setContentsMargins(0, 0, 0, 0) + + for game in data: + tab = GameTab(game) + layout.addWidget(tab) + + if len(data) < self.gamesNumberPerPage: + layout.addSpacerItem(QSpacerItem( + 1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)) + + self.stackWidget.addWidget(widget) + self.stackWidget.setCurrentIndex(self.currentIndex) + self.pageLabel.setText(f"{self.currentIndex}") + + if self.currentIndex != self.maxPage: + self.nextButton.setEnabled(True) + + if self.currentIndex != 1: + self.prevButton.setEnabled(True) + + if self.first and self.triggerByButton: + gameId = layout.itemAt(0).widget().gameId + self.tabClicked.emit(str(gameId)) + self.first = False + + mainWindow = self.window() + mainWindow.checkAndSwitchTo(mainWindow.searchInterface) + def updateTabs(self, begin, n): widget = QWidget() layout = QVBoxLayout(widget) @@ -948,9 +1060,14 @@ class SearchInterface(SmoothScrollArea): def __init__(self, parent=None): super().__init__(parent) - self.filterData = (420, 440, 430, 450) # 默认全选 - self.filterTimer = threading.Timer(.5, self.__onSearchButtonClicked) - self.filterOld = None # 条件改动前后若无变化, 则不触发更新逻辑 + # self.filterData = (420, 440, 430, 450) # 默认全选 + # self.filterTimer = threading.Timer(.5, self.__onSearchButtonClicked) + # self.filterOld = None # 条件改动前后若无变化, 则不触发更新逻辑 + + self.games = [] + self.queueIdBuffer = {} + self.loadGamesThread = None + self.loadGamesThreadStop = threading.Event() self.vBoxLayout = QVBoxLayout(self) @@ -958,8 +1075,10 @@ def __init__(self, parent=None): self.searchLineEdit = LineEdit() self.searchButton = PushButton(self.tr("Search 🔍")) self.careerButton = PushButton(self.tr("Career")) - self.filterButton = PushButton(self.tr("Filter")) - self.filterButton.clicked.connect(self.showFilterFlyout) + self.filterComboBox = ComboBox() + + # self.filterButton = PushButton(self.tr("Filter")) + # self.filterButton.clicked.connect(self.showFilterFlyout) self.gamesView = GamesView() self.currentSummonerName = None @@ -974,18 +1093,29 @@ def __initWidget(self): self.searchLineEdit.setPlaceholderText( self.tr("Please input summoner name")) self.careerButton.setEnabled(False) - self.filterButton.setEnabled(False) + # self.filterButton.setEnabled(False) + self.filterComboBox.setEnabled(False) self.searchButton.setShortcut("Return") StyleSheet.SEARCH_INTERFACE.apply(self) + self.filterComboBox.addItems([ + self.tr('All'), + self.tr('Normal'), + self.tr("A.R.A.M."), + self.tr("Ranked Solo"), + self.tr("Ranked Flex") + ]) + self.filterComboBox.setCurrentIndex(0) + def __initLayout(self): self.searchLayout.addWidget(self.searchLineEdit) self.searchLayout.addSpacing(5) self.searchLayout.addWidget(self.searchButton) self.searchLayout.addWidget(self.careerButton) - self.searchLayout.addWidget(self.filterButton) + # self.searchLayout.addWidget(self.filterButton) + self.searchLayout.addWidget(self.filterComboBox) self.vBoxLayout.addLayout(self.searchLayout) self.vBoxLayout.addSpacing(5) @@ -997,22 +1127,77 @@ def __onSearchButtonClicked(self): if targetName == "": return + if self.loadGamesThread: + self.loadGamesThreadStop.set() + def _(): try: summoner = connector.getSummonerByName(targetName) puuid = summoner["puuid"] self.currentSummonerName = targetName + self.loadGamesThread = threading.Thread(target=self.loadGames, args=(puuid,)) + self.loadGamesThread.start() + + while len(self.games) < 10 and self.loadGamesThread.is_alive(): + ... + + self.careerButton.setEnabled(True) + # self.filterButton.setEnabled(True) + self.filterComboBox.setEnabled(True) + self.gamesView.gameDetailView.clear() + self.gamesView.gamesTab.triggerByButton = True + self.gamesView.gamesTab.firstCall(puuid) except: - puuid = "-1" + # puuid = "-1" + self.__showSummonerNotFoundMessage() - self.summonerPuuidGetted.emit(puuid) + # self.summonerPuuidGetted.emit(puuid) threading.Thread(target=_).start() + + def loadGames(self, puuid): + """ + + @warning 该方法会导致线程阻塞 + + @param puuid: + @return: + """ + gameIdx = 0 + begIdx = 0 + endIdx = begIdx + 9 + while True: + games = connector.getSummonerGamesByPuuid( + puuid, begIdx, endIdx) + + for game in games["games"]: + if time.time() - game['gameCreation'] / 1000 > 60 * 60 * 24 * 365: + return + + if self.loadGamesThreadStop.isSet(): + self.games = [] + self.loadGamesThreadStop.clear() + return + + self.games.append(processGameData(game)) + + if self.queueIdBuffer.get(game["queueId"]): + self.queueIdBuffer[game["queueId"]].append(gameIdx) + else: + self.queueIdBuffer[game["queueId"]] = [gameIdx] + # self.queueIdBuffer[game["queueId"]] = self.queueIdBuffer.get(game["queueId"], []).append(gameIdx) + + gameIdx += 1 + + begIdx = endIdx + 1 + endIdx += 9 + def __onSummonerPuuidGetted(self, puuid): if puuid != "-1": self.careerButton.setEnabled(True) - self.filterButton.setEnabled(True) + # self.filterButton.setEnabled(True) + self.filterComboBox.setEnabled(True) self.gamesView.gameDetailView.clear() self.gamesView.gamesTab.triggerByButton = True self.gamesView.gamesTab.updatePuuid(puuid) @@ -1042,7 +1227,8 @@ def setEnabled(self, a0: bool) -> None: self.searchLineEdit.setEnabled(a0) self.searchButton.setEnabled(a0) - self.filterButton.setEnabled(a0) + self.filterComboBox.setEnabled(a0) + # self.filterButton.setEnabled(a0) return super().setEnabled(a0) From 650b28e9322e0d3ce51db12396417c30a8b63663 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Wed, 20 Sep 2023 14:50:47 +0800 Subject: [PATCH 05/10] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0BP=E6=97=B6,=20?= =?UTF-8?q?=E6=8E=92=E4=BD=8D=E7=AD=9B=E9=80=89=E9=80=BB=E8=BE=91=202.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=88=98=E7=BB=A9=E6=9F=A5=E8=AF=A2=E6=97=B6?= =?UTF-8?q?,=20=E4=BB=8D=E5=9C=A8=E5=8A=A0=E8=BD=BD=E7=9A=84=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 22 +++++++-------- app/view/search_interface.py | 55 +++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index c23c63af..49f29a5a 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -778,7 +778,6 @@ def updateGameInfoInterface(callback=None): summoners = [] data = connector.getChampSelectSession() - # TODO queueId查询逻辑 isRank = bool(data["myTeam"][0]["assignedPosition"]) # 排位会有预选位 def process_item(item): @@ -800,17 +799,16 @@ def process_item(item): origGamesInfo = connector.getSummonerGamesByPuuid( puuid, 0, 14) - # FIXME getChampSelectSession 接口没有 queueId的信息 - # if cfg.get(cfg.gameInfoFilter) and queueId in (420, 440): - # origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] - # begIdx = 15 - # while len(origGamesInfo["games"]) < 11: - # endIdx = begIdx + 5 - # origGamesInfo["games"].extend([ - # game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] - # if game["queueId"] in (420, 440) - # ]) - # begIdx = endIdx + 1 + if cfg.get(cfg.gameInfoFilter) and isRank: + origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] + begIdx = 15 + while len(origGamesInfo["games"]) < 11: + endIdx = begIdx + 5 + origGamesInfo["games"].extend([ + game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] + if game["queueId"] in (420, 440) + ]) + begIdx = endIdx + 1 gamesInfo = [processGameData(game) for game in origGamesInfo["games"][:11]] diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 3467b620..7e9ab00b 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -8,7 +8,8 @@ from PyQt5.QtGui import QPixmap from qfluentwidgets import (SmoothScrollArea, LineEdit, PushButton, ToolButton, InfoBar, InfoBarPosition, ToolTipFilter, ToolTipPosition, Theme, isDarkTheme, FlyoutViewBase, Flyout, - CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType, ComboBox) + CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType, ComboBox, + StateToolTip) from ..common.style_sheet import StyleSheet from ..common.icons import Icon @@ -30,6 +31,8 @@ def __init__(self, parnet=None): self.setFixedWidth(160) self.vBoxLayout = QVBoxLayout(self) + self.stateTooltip = None + self.stackWidget = QStackedWidget() self.buttonsLayout = QHBoxLayout() @@ -124,25 +127,39 @@ def questionPage(self, page, queueId=None) -> bool: return page < maxPage - # TODO 信号部分未声明参数 - def __onNextButtonClicked(self, page=1, queueId=None): + # FIXME 信号部分未声明参数 + def __onNextButtonClicked(self, page: int = 1, queueId=None): + """ + + @param page: 目标页 + """ + + assert page > 0 def waitLoadPage(): while not self.questionPage(page, queueId): time.sleep(.5) + if self.stateTooltip: + self.stateTooltip.setContent( + self.tr('Data loading completed!') + ' 😆') + self.stateTooltip.setState(True) + self.stateTooltip = None self.nextButton.setEnabled(True) self.__onNextButtonClicked(page, queueId) games = self.window().searchInterface.games loadThread = self.window().searchInterface.loadGamesThread # 用于判断还有无获取新数据 - # TODO 页码判断部分封装为方法, 便于复用 if queueId is None: maxPage = int(len(games) / 10) if page >= maxPage: if loadThread.is_alive(): self.nextButton.setEnabled(False) - # TODO 等待加载提示 + if not self.stateTooltip: + self.stateTooltip = StateToolTip( + self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) + self.stateTooltip.move(self.stateTooltip.getSuitablePos()) + self.stateTooltip.show() threading.Thread(target=waitLoadPage).start() return else: # 已到最后一页 @@ -156,7 +173,11 @@ def waitLoadPage(): if page >= maxPage: if loadThread.is_alive(): self.nextButton.setEnabled(False) - # TODO 等待加载提示 + if not self.stateTooltip: + self.stateTooltip = StateToolTip( + self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) + self.stateTooltip.move(self.stateTooltip.getSuitablePos()) + self.stateTooltip.show() threading.Thread(target=waitLoadPage).start() return else: @@ -170,12 +191,12 @@ def waitLoadPage(): data.append(games[idx]) self.updateNextPageTabs(data) - self.stackWidget.setCurrentIndex(self.currentIndex) - self.pageLabel.setText(f"{self.currentIndex}") + # self.stackWidget.setCurrentIndex(self.currentIndex) + # self.pageLabel.setText(f"{self.currentIndex}") # if self.currentIndex == self.maxPage: # self.nextButton.setEnabled(False) self.prevButton.setEnabled(True) - self.currentIndex += 1 + self.currentIndex = page # if len(self.stackWidget) <= self.currentIndex: # self.nextButton.setEnabled(False) @@ -252,11 +273,11 @@ def updateNextPageTabs(self, data): self.stackWidget.setCurrentIndex(self.currentIndex) self.pageLabel.setText(f"{self.currentIndex}") - if self.currentIndex != self.maxPage: - self.nextButton.setEnabled(True) - - if self.currentIndex != 1: - self.prevButton.setEnabled(True) + # if self.currentIndex != self.maxPage: + # self.nextButton.setEnabled(True) + # + # if self.currentIndex != 1: + # self.prevButton.setEnabled(True) if self.first and self.triggerByButton: gameId = layout.itemAt(0).widget().gameId @@ -463,7 +484,8 @@ def updateGame(self, game: dict): result = self.tr("4th") self.titleBar.updateTitleBar( - mapIcon, result, game["mapName"], game["modeName"], game["gameDuration"], game["gameCreation"], game["gameId"], color + mapIcon, result, game["mapName"], game["modeName"], game["gameDuration"], game["gameCreation"], + game["gameId"], color ) team1 = game["teams"][100] @@ -1139,7 +1161,7 @@ def _(): self.loadGamesThread.start() while len(self.games) < 10 and self.loadGamesThread.is_alive(): - ... + time.sleep(.1) self.careerButton.setEnabled(True) # self.filterButton.setEnabled(True) @@ -1155,7 +1177,6 @@ def _(): threading.Thread(target=_).start() - def loadGames(self, puuid): """ From e943cbdbd631fb2bf2124f2d183ed388d4ad2ad8 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Tue, 19 Sep 2023 01:06:25 +0800 Subject: [PATCH 06/10] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0=20"=E6=8E=92?= =?UTF-8?q?=E4=BD=8D=E6=A8=A1=E5=BC=8F=E4=B8=8B=20=E5=AF=B9=E5=B1=80?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=20=E9=A1=B5=E8=BF=87=E6=BB=A4=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=A8=A1=E5=BC=8F"=20=E8=AE=BE=E7=BD=AE=E9=80=89?= =?UTF-8?q?=E9=A1=B9=202.=20=E4=BF=AE=E6=AD=A3=20mode=5Ffilter=5Fwidget.py?= =?UTF-8?q?=20=E4=B8=AD=20vBoxLayout=20=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/config.py | 2 ++ app/common/icons.py | 1 + app/components/mode_filter_widget.py | 15 +++++++-------- app/resource/icons/Filter_black.svg | 1 + app/resource/icons/Filter_white.svg | 1 + app/view/setting_interface.py | 9 +++++++++ 6 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 app/resource/icons/Filter_black.svg create mode 100644 app/resource/icons/Filter_white.svg diff --git a/app/common/config.py b/app/common/config.py index 6dc5b7e7..b276bc0f 100644 --- a/app/common/config.py +++ b/app/common/config.py @@ -55,6 +55,8 @@ class Config(QConfig): teamGamesNumber = RangeConfigItem("Functions", "TeamGamesNumber", 1, RangeValidator(1, 10)) + gameInfoFilter = ConfigItem("Functions", "GameInfoFilter", False, BoolValidator()) + showTierInGameInfo = ConfigItem("Functions", "ShowTierInGameInfo", False, BoolValidator()) enableAutoAcceptMatching = ConfigItem("Functions", diff --git a/app/common/icons.py b/app/common/icons.py index 165063a7..dd077a32 100644 --- a/app/common/icons.py +++ b/app/common/icons.py @@ -41,6 +41,7 @@ class Icon(FluentIconBase, Enum): LOCK = 'Lock' TEAM = 'Team' SETTING = 'Setting' + FILTER = 'Filter' def path(self, theme=Theme.AUTO): return f'./app/resource/icons/{self.value}_{getIconColor(theme)}.svg' diff --git a/app/components/mode_filter_widget.py b/app/components/mode_filter_widget.py index a734f0c9..0b6d4185 100644 --- a/app/components/mode_filter_widget.py +++ b/app/components/mode_filter_widget.py @@ -14,10 +14,9 @@ def __init__(self, parent=None): self.selected: List[int] = [] - self.hBoxLayout = QVBoxLayout(self) - self.hBoxLayout.setAlignment(Qt.AlignCenter) + self.vBoxLayout = QVBoxLayout(self) + self.vBoxLayout.setAlignment(Qt.AlignCenter) - # TODO 本地化 self.rankSoloCheckBox = CheckBox(self.tr("Ranked solo")) self.rankFlexCheckBox = CheckBox(self.tr("Ranked Flex")) self.normalCheckBox = CheckBox(self.tr("Normal")) @@ -34,15 +33,15 @@ def __init__(self, parent=None): checkBox.stateChanged.connect( lambda state, num=num: self.updateSelected(state, num)) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.rankSoloCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.rankFlexCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget( + self.vBoxLayout.addWidget( self.normalCheckBox, alignment=Qt.AlignLeft) - self.hBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignLeft) + self.vBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignLeft) - self.setLayout(self.hBoxLayout) + self.setLayout(self.vBoxLayout) def updateSelected(self, state, num, callback=None): if state == Qt.Checked: diff --git a/app/resource/icons/Filter_black.svg b/app/resource/icons/Filter_black.svg new file mode 100644 index 00000000..7551c780 --- /dev/null +++ b/app/resource/icons/Filter_black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/resource/icons/Filter_white.svg b/app/resource/icons/Filter_white.svg new file mode 100644 index 00000000..f38884dc --- /dev/null +++ b/app/resource/icons/Filter_white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/view/setting_interface.py b/app/view/setting_interface.py index 31c6c366..693783bd 100644 --- a/app/view/setting_interface.py +++ b/app/view/setting_interface.py @@ -69,6 +69,14 @@ def __init__(self, parent=None): self. tr("Setting the maximum number of games shows in the career interface" ), self.functionGroup) + + # TODO 逻辑 + self.gameInfoFilterCard = SwitchSettingCard( + Icon.FILTER, self.tr("Rank filter other mode"), + self.tr("When in ranked mode, filter out other modes on the GameInfo page"), + cfg.gameInfoFilter + ) + self.gameInfoShowTierCard = SwitchSettingCard( Icon.TROPHY, self.tr("Show tier in game information"), self. @@ -192,6 +200,7 @@ def __initLayout(self): # add cards to group self.functionGroup.addSettingCard(self.careerGamesCount) self.functionGroup.addSettingCard(self.teamGamesNumberCard) + self.functionGroup.addSettingCard(self.gameInfoFilterCard) self.functionGroup.addSettingCard(self.gameInfoShowTierCard) self.generalGroup.addSettingCard(self.lolFolderCard) From 24e51a039d7a24228367fd27d897b82650a527a4 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Tue, 19 Sep 2023 13:29:13 +0800 Subject: [PATCH 07/10] =?UTF-8?q?1.=20=E6=96=B0=E5=A2=9Egameinfo=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E9=80=BB=E8=BE=91=202.=20=E8=A7=84=E8=8C=83=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 23 +++++++++++++++++++++++ app/view/search_interface.py | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index 2dcbf5cf..3f5f37cf 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -797,6 +797,18 @@ def process_item(item): origGamesInfo = connector.getSummonerGamesByPuuid( puuid, 0, 14) + # FIXME getChampSelectSession 接口没有 queueId的信息 + # if cfg.get(cfg.gameInfoFilter) and queueId in (420, 440): + # origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] + # begIdx = 15 + # while len(origGamesInfo["games"]) < 11: + # endIdx = begIdx + 5 + # origGamesInfo["games"].extend([ + # game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] + # if game["queueId"] in (420, 440) + # ]) + # begIdx = endIdx + 1 + gamesInfo = [processGameData(game) for game in origGamesInfo["games"][:11]] @@ -937,6 +949,17 @@ def process_item(item): origGamesInfo = connector.getSummonerGamesByPuuid( puuid, 0, 14) + if cfg.get(cfg.gameInfoFilter) and queueId in (420, 440): + origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] + begIdx = 15 + while len(origGamesInfo["games"]) < 11: + endIdx = begIdx + 5 + origGamesInfo["games"].extend([ + game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] + if game["queueId"] in (420, 440) + ]) + begIdx = endIdx + 1 + gamesInfo = [processGameData(game) for game in origGamesInfo["games"][0:11]] diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 6b37e7d8..6a3fb61a 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -960,7 +960,6 @@ def __init__(self, parent=None): self.searchButton = PushButton(self.tr("Search 🔍")) self.careerButton = PushButton(self.tr("Career")) self.filterButton = PushButton(self.tr("Filter")) - self.filterButton.clicked.connect(self.showFilterFlyout) self.gamesView = GamesView() self.currentSummonerName = None @@ -1023,6 +1022,7 @@ def __onSummonerPuuidGetted(self, puuid): def __connectSignalToSlot(self): self.searchButton.clicked.connect(self.__onSearchButtonClicked) self.summonerPuuidGetted.connect(self.__onSummonerPuuidGetted) + self.filterButton.clicked.connect(self.__onShowFilterFlyout) def __showSummonerNotFoundMessage(self): InfoBar.error( @@ -1053,7 +1053,7 @@ def fillterTimerRun(self): self.filterOld = None - def showFilterFlyout(self): + def __onShowFilterFlyout(self): filterFlyout = FlyoutView("", "") filterBoxGroup = ModeFilterWidget() From a32e321288f0f36204eac88d49959b69c78064d4 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Wed, 20 Sep 2023 02:24:10 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=88=98=E7=BB=A9?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 3 + app/view/search_interface.py | 260 ++++++++++++++++++++++++++++++----- 2 files changed, 225 insertions(+), 38 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index 3f5f37cf..c23c63af 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -778,6 +778,9 @@ def updateGameInfoInterface(callback=None): summoners = [] data = connector.getChampSelectSession() + # TODO queueId查询逻辑 + isRank = bool(data["myTeam"][0]["assignedPosition"]) # 排位会有预选位 + def process_item(item): summonerId = item["summonerId"] diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 6a3fb61a..3467b620 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -8,7 +8,7 @@ from PyQt5.QtGui import QPixmap from qfluentwidgets import (SmoothScrollArea, LineEdit, PushButton, ToolButton, InfoBar, InfoBarPosition, ToolTipFilter, ToolTipPosition, Theme, isDarkTheme, FlyoutViewBase, Flyout, - CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType) + CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType, ComboBox) from ..common.style_sheet import StyleSheet from ..common.icons import Icon @@ -107,22 +107,86 @@ def __onPrevButtonClicked(self): if self.currentIndex == 1: self.prevButton.setEnabled(False) - def __onNextButtonClicked(self): - if self.currentIndex == 0: - self.begIndex = 0 + def questionPage(self, page, queueId=None) -> bool: + """ - self.currentIndex += 1 + @param page: 需要查询的页码 + @param queueId: 过滤条件 + @return: True -> 此页可以直接返回, False -> 此页未加载完成或超出最大页码 + """ + games = self.window().searchInterface.games - if len(self.stackWidget) <= self.currentIndex: - self.nextButton.setEnabled(False) - self.prevButton.setEnabled(False) - self.updateGames(self.currentIndex) + if queueId is None: + maxPage = int(len(games) / 10) else: - self.stackWidget.setCurrentIndex(self.currentIndex) - self.pageLabel.setText(f"{self.currentIndex}") - if self.currentIndex == self.maxPage: - self.nextButton.setEnabled(False) - self.prevButton.setEnabled(True) + buffer = self.window().searchInterface.queueIdBuffer.get(queueId, []) + maxPage = int(len(buffer) / 10) + + return page < maxPage + + # TODO 信号部分未声明参数 + def __onNextButtonClicked(self, page=1, queueId=None): + + def waitLoadPage(): + while not self.questionPage(page, queueId): + time.sleep(.5) + self.nextButton.setEnabled(True) + self.__onNextButtonClicked(page, queueId) + + games = self.window().searchInterface.games + loadThread = self.window().searchInterface.loadGamesThread # 用于判断还有无获取新数据 + + # TODO 页码判断部分封装为方法, 便于复用 + if queueId is None: + maxPage = int(len(games) / 10) + if page >= maxPage: + if loadThread.is_alive(): + self.nextButton.setEnabled(False) + # TODO 等待加载提示 + threading.Thread(target=waitLoadPage).start() + return + else: # 已到最后一页 + data = games[(page - 1) * 10:] + self.nextButton.setEnabled(False) + else: + data = games[(page - 1) * 10: page * 10] + else: + buffer = self.window().searchInterface.queueIdBuffer.get(queueId, []) + maxPage = int(len(buffer) / 10) + if page >= maxPage: + if loadThread.is_alive(): + self.nextButton.setEnabled(False) + # TODO 等待加载提示 + threading.Thread(target=waitLoadPage).start() + return + else: + tmpBuf = buffer[(page - 1) * 10:] + self.nextButton.setEnabled(False) + else: + tmpBuf = buffer[(page - 1) * 10: page * 10] + + data = [] + for idx in tmpBuf: + data.append(games[idx]) + + self.updateNextPageTabs(data) + self.stackWidget.setCurrentIndex(self.currentIndex) + self.pageLabel.setText(f"{self.currentIndex}") + # if self.currentIndex == self.maxPage: + # self.nextButton.setEnabled(False) + self.prevButton.setEnabled(True) + self.currentIndex += 1 + + # if len(self.stackWidget) <= self.currentIndex: + # self.nextButton.setEnabled(False) + # self.prevButton.setEnabled(False) + # self.updateGames(self.currentIndex) + # else: + # self.stackWidget.setCurrentIndex(self.currentIndex) + # self.pageLabel.setText(f"{self.currentIndex}") + # if self.currentIndex == self.maxPage: + # self.nextButton.setEnabled(False) + # self.prevButton.setEnabled(True) def backToDefaultPage(self): self.currentIndex = 0 @@ -144,6 +208,23 @@ def backToDefaultPage(self): self.prevButton.setVisible(False) self.nextButton.setVisible(False) + def firstCall(self, puuid): + if self.puuid != None: + self.backToDefaultPage() + + self.puuid = puuid + self.first = True + self.prevButton.setVisible(True) + self.nextButton.setVisible(True) + self.__onNextButtonClicked() + # self.currentIndex += 1 + # self.stackWidget.setCurrentIndex(self.currentIndex) + # self.pageLabel.setText(f"{self.currentIndex}") + # if self.currentIndex == self.maxPage: + # self.nextButton.setEnabled(False) + # if len(self.games) == 0: + # self.__showEmptyPage() + def updatePuuid(self, puuid): if self.puuid != None: self.backToDefaultPage() @@ -154,6 +235,37 @@ def updatePuuid(self, puuid): self.nextButton.setVisible(True) self.__onNextButtonClicked() + def updateNextPageTabs(self, data): + widget = QWidget() + layout = QVBoxLayout(widget) + layout.setContentsMargins(0, 0, 0, 0) + + for game in data: + tab = GameTab(game) + layout.addWidget(tab) + + if len(data) < self.gamesNumberPerPage: + layout.addSpacerItem(QSpacerItem( + 1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)) + + self.stackWidget.addWidget(widget) + self.stackWidget.setCurrentIndex(self.currentIndex) + self.pageLabel.setText(f"{self.currentIndex}") + + if self.currentIndex != self.maxPage: + self.nextButton.setEnabled(True) + + if self.currentIndex != 1: + self.prevButton.setEnabled(True) + + if self.first and self.triggerByButton: + gameId = layout.itemAt(0).widget().gameId + self.tabClicked.emit(str(gameId)) + self.first = False + + mainWindow = self.window() + mainWindow.checkAndSwitchTo(mainWindow.searchInterface) + def updateTabs(self, begin, n): widget = QWidget() layout = QVBoxLayout(widget) @@ -223,15 +335,13 @@ def firstPageCallback(): """ self.gamesInfoReady.emit(page) self.nextButton.setEnabled(False) - threading.Thread(target=_, args=( - page + 1, lambda: self.nextButton.setEnabled(True))).start() + threading.Thread(target=_, args=(page + 1, lambda: self.nextButton.setEnabled(True))).start() threading.Thread(target=_, args=(page, firstPageCallback)).start() else: # 除第一页外, 直接切换到该页, 并加载下一页; self.gamesInfoReady.emit(page) self.nextButton.setEnabled(False) - threading.Thread(target=_, args=( - page + 1, lambda: self.nextButton.setEnabled(True))).start() + threading.Thread(target=_, args=(page + 1, lambda: self.nextButton.setEnabled(True))).start() def __onGamesInfoReady(self, page): if len(self.games) == 0: @@ -825,12 +935,13 @@ def updateTitleBar(self, mapIcon, result, mapName, modeName, duration, creation, f"{mapName} · {modeName} · {duration} · {creation} · " + self.tr("Game ID: ") + f"{gameId}") self.copyGameIdButton.setVisible(True) - self.setStyleSheet(f""" - GameTitleBar {{ - border-radius: 6px; - border: 1px solid rgb({color}); - background-color: rgba({color}, 0.15); - }}""") + self.setStyleSheet( + f""" GameTitleBar {{ + border-radius: 6px; + border: 1px solid rgb({color}); + background-color: rgba({color}, 0.15); + }}""" + ) def __connectSignalToSlot(self): self.copyGameIdButton.clicked.connect( @@ -949,9 +1060,14 @@ class SearchInterface(SmoothScrollArea): def __init__(self, parent=None): super().__init__(parent) - self.filterData = (420, 440, 430, 450) # 默认全选 - self.filterTimer = threading.Timer(.5, self.__onSearchButtonClicked) - self.filterOld = None # 条件改动前后若无变化, 则不触发更新逻辑 + # self.filterData = (420, 440, 430, 450) # 默认全选 + # self.filterTimer = threading.Timer(.5, self.__onSearchButtonClicked) + # self.filterOld = None # 条件改动前后若无变化, 则不触发更新逻辑 + + self.games = [] + self.queueIdBuffer = {} + self.loadGamesThread = None + self.loadGamesThreadStop = threading.Event() self.vBoxLayout = QVBoxLayout(self) @@ -959,7 +1075,10 @@ def __init__(self, parent=None): self.searchLineEdit = LineEdit() self.searchButton = PushButton(self.tr("Search 🔍")) self.careerButton = PushButton(self.tr("Career")) - self.filterButton = PushButton(self.tr("Filter")) + self.filterComboBox = ComboBox() + + # self.filterButton = PushButton(self.tr("Filter")) + # self.filterButton.clicked.connect(self.showFilterFlyout) self.gamesView = GamesView() self.currentSummonerName = None @@ -974,18 +1093,29 @@ def __initWidget(self): self.searchLineEdit.setPlaceholderText( self.tr("Please input summoner name")) self.careerButton.setEnabled(False) - self.filterButton.setEnabled(False) + # self.filterButton.setEnabled(False) + self.filterComboBox.setEnabled(False) self.searchButton.setShortcut("Return") StyleSheet.SEARCH_INTERFACE.apply(self) + self.filterComboBox.addItems([ + self.tr('All'), + self.tr('Normal'), + self.tr("A.R.A.M."), + self.tr("Ranked Solo"), + self.tr("Ranked Flex") + ]) + self.filterComboBox.setCurrentIndex(0) + def __initLayout(self): self.searchLayout.addWidget(self.searchLineEdit) self.searchLayout.addSpacing(5) self.searchLayout.addWidget(self.searchButton) self.searchLayout.addWidget(self.careerButton) - self.searchLayout.addWidget(self.filterButton) + # self.searchLayout.addWidget(self.filterButton) + self.searchLayout.addWidget(self.filterComboBox) self.vBoxLayout.addLayout(self.searchLayout) self.vBoxLayout.addSpacing(5) @@ -997,22 +1127,77 @@ def __onSearchButtonClicked(self): if targetName == "": return + if self.loadGamesThread: + self.loadGamesThreadStop.set() + def _(): try: summoner = connector.getSummonerByName(targetName) puuid = summoner["puuid"] self.currentSummonerName = targetName + self.loadGamesThread = threading.Thread(target=self.loadGames, args=(puuid,)) + self.loadGamesThread.start() + + while len(self.games) < 10 and self.loadGamesThread.is_alive(): + ... + + self.careerButton.setEnabled(True) + # self.filterButton.setEnabled(True) + self.filterComboBox.setEnabled(True) + self.gamesView.gameDetailView.clear() + self.gamesView.gamesTab.triggerByButton = True + self.gamesView.gamesTab.firstCall(puuid) except: - puuid = "-1" + # puuid = "-1" + self.__showSummonerNotFoundMessage() - self.summonerPuuidGetted.emit(puuid) + # self.summonerPuuidGetted.emit(puuid) threading.Thread(target=_).start() + + def loadGames(self, puuid): + """ + + @warning 该方法会导致线程阻塞 + + @param puuid: + @return: + """ + gameIdx = 0 + begIdx = 0 + endIdx = begIdx + 9 + while True: + games = connector.getSummonerGamesByPuuid( + puuid, begIdx, endIdx) + + for game in games["games"]: + if time.time() - game['gameCreation'] / 1000 > 60 * 60 * 24 * 365: + return + + if self.loadGamesThreadStop.isSet(): + self.games = [] + self.loadGamesThreadStop.clear() + return + + self.games.append(processGameData(game)) + + if self.queueIdBuffer.get(game["queueId"]): + self.queueIdBuffer[game["queueId"]].append(gameIdx) + else: + self.queueIdBuffer[game["queueId"]] = [gameIdx] + # self.queueIdBuffer[game["queueId"]] = self.queueIdBuffer.get(game["queueId"], []).append(gameIdx) + + gameIdx += 1 + + begIdx = endIdx + 1 + endIdx += 9 + def __onSummonerPuuidGetted(self, puuid): if puuid != "-1": self.careerButton.setEnabled(True) - self.filterButton.setEnabled(True) + # self.filterButton.setEnabled(True) + self.filterComboBox.setEnabled(True) self.gamesView.gameDetailView.clear() self.gamesView.gamesTab.triggerByButton = True self.gamesView.gamesTab.updatePuuid(puuid) @@ -1022,7 +1207,6 @@ def __onSummonerPuuidGetted(self, puuid): def __connectSignalToSlot(self): self.searchButton.clicked.connect(self.__onSearchButtonClicked) self.summonerPuuidGetted.connect(self.__onSummonerPuuidGetted) - self.filterButton.clicked.connect(self.__onShowFilterFlyout) def __showSummonerNotFoundMessage(self): InfoBar.error( @@ -1043,7 +1227,8 @@ def setEnabled(self, a0: bool) -> None: self.searchLineEdit.setEnabled(a0) self.searchButton.setEnabled(a0) - self.filterButton.setEnabled(a0) + self.filterComboBox.setEnabled(a0) + # self.filterButton.setEnabled(a0) return super().setEnabled(a0) @@ -1053,7 +1238,7 @@ def fillterTimerRun(self): self.filterOld = None - def __onShowFilterFlyout(self): + def showFilterFlyout(self): filterFlyout = FlyoutView("", "") filterBoxGroup = ModeFilterWidget() @@ -1070,8 +1255,7 @@ def _(): self.gamesView.gamesTab.currentIndex = 0 # 消除频繁切换筛选条件带来的抖动 - self.filterTimer = threading.Timer(.7, - lambda obj=self: obj.fillterTimerRun()) + self.filterTimer = threading.Timer(.7, lambda obj=self: obj.fillterTimerRun()) self.filterTimer.start() filterBoxGroup.setCallback(_) From c03f2035a2216bee91921a31c6a2b74e41d66e14 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Wed, 20 Sep 2023 14:50:47 +0800 Subject: [PATCH 09/10] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0BP=E6=97=B6,=20?= =?UTF-8?q?=E6=8E=92=E4=BD=8D=E7=AD=9B=E9=80=89=E9=80=BB=E8=BE=91=202.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=88=98=E7=BB=A9=E6=9F=A5=E8=AF=A2=E6=97=B6?= =?UTF-8?q?,=20=E4=BB=8D=E5=9C=A8=E5=8A=A0=E8=BD=BD=E7=9A=84=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 22 +++++++-------- app/view/search_interface.py | 55 +++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index c23c63af..49f29a5a 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -778,7 +778,6 @@ def updateGameInfoInterface(callback=None): summoners = [] data = connector.getChampSelectSession() - # TODO queueId查询逻辑 isRank = bool(data["myTeam"][0]["assignedPosition"]) # 排位会有预选位 def process_item(item): @@ -800,17 +799,16 @@ def process_item(item): origGamesInfo = connector.getSummonerGamesByPuuid( puuid, 0, 14) - # FIXME getChampSelectSession 接口没有 queueId的信息 - # if cfg.get(cfg.gameInfoFilter) and queueId in (420, 440): - # origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] - # begIdx = 15 - # while len(origGamesInfo["games"]) < 11: - # endIdx = begIdx + 5 - # origGamesInfo["games"].extend([ - # game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] - # if game["queueId"] in (420, 440) - # ]) - # begIdx = endIdx + 1 + if cfg.get(cfg.gameInfoFilter) and isRank: + origGamesInfo["games"] = [game for game in origGamesInfo["games"] if game["queueId"] in (420, 440)] + begIdx = 15 + while len(origGamesInfo["games"]) < 11: + endIdx = begIdx + 5 + origGamesInfo["games"].extend([ + game for game in connector.getSummonerGamesByPuuid(puuid, begIdx, endIdx)["games"] + if game["queueId"] in (420, 440) + ]) + begIdx = endIdx + 1 gamesInfo = [processGameData(game) for game in origGamesInfo["games"][:11]] diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 3467b620..7e9ab00b 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -8,7 +8,8 @@ from PyQt5.QtGui import QPixmap from qfluentwidgets import (SmoothScrollArea, LineEdit, PushButton, ToolButton, InfoBar, InfoBarPosition, ToolTipFilter, ToolTipPosition, Theme, isDarkTheme, FlyoutViewBase, Flyout, - CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType, ComboBox) + CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType, ComboBox, + StateToolTip) from ..common.style_sheet import StyleSheet from ..common.icons import Icon @@ -30,6 +31,8 @@ def __init__(self, parnet=None): self.setFixedWidth(160) self.vBoxLayout = QVBoxLayout(self) + self.stateTooltip = None + self.stackWidget = QStackedWidget() self.buttonsLayout = QHBoxLayout() @@ -124,25 +127,39 @@ def questionPage(self, page, queueId=None) -> bool: return page < maxPage - # TODO 信号部分未声明参数 - def __onNextButtonClicked(self, page=1, queueId=None): + # FIXME 信号部分未声明参数 + def __onNextButtonClicked(self, page: int = 1, queueId=None): + """ + + @param page: 目标页 + """ + + assert page > 0 def waitLoadPage(): while not self.questionPage(page, queueId): time.sleep(.5) + if self.stateTooltip: + self.stateTooltip.setContent( + self.tr('Data loading completed!') + ' 😆') + self.stateTooltip.setState(True) + self.stateTooltip = None self.nextButton.setEnabled(True) self.__onNextButtonClicked(page, queueId) games = self.window().searchInterface.games loadThread = self.window().searchInterface.loadGamesThread # 用于判断还有无获取新数据 - # TODO 页码判断部分封装为方法, 便于复用 if queueId is None: maxPage = int(len(games) / 10) if page >= maxPage: if loadThread.is_alive(): self.nextButton.setEnabled(False) - # TODO 等待加载提示 + if not self.stateTooltip: + self.stateTooltip = StateToolTip( + self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) + self.stateTooltip.move(self.stateTooltip.getSuitablePos()) + self.stateTooltip.show() threading.Thread(target=waitLoadPage).start() return else: # 已到最后一页 @@ -156,7 +173,11 @@ def waitLoadPage(): if page >= maxPage: if loadThread.is_alive(): self.nextButton.setEnabled(False) - # TODO 等待加载提示 + if not self.stateTooltip: + self.stateTooltip = StateToolTip( + self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) + self.stateTooltip.move(self.stateTooltip.getSuitablePos()) + self.stateTooltip.show() threading.Thread(target=waitLoadPage).start() return else: @@ -170,12 +191,12 @@ def waitLoadPage(): data.append(games[idx]) self.updateNextPageTabs(data) - self.stackWidget.setCurrentIndex(self.currentIndex) - self.pageLabel.setText(f"{self.currentIndex}") + # self.stackWidget.setCurrentIndex(self.currentIndex) + # self.pageLabel.setText(f"{self.currentIndex}") # if self.currentIndex == self.maxPage: # self.nextButton.setEnabled(False) self.prevButton.setEnabled(True) - self.currentIndex += 1 + self.currentIndex = page # if len(self.stackWidget) <= self.currentIndex: # self.nextButton.setEnabled(False) @@ -252,11 +273,11 @@ def updateNextPageTabs(self, data): self.stackWidget.setCurrentIndex(self.currentIndex) self.pageLabel.setText(f"{self.currentIndex}") - if self.currentIndex != self.maxPage: - self.nextButton.setEnabled(True) - - if self.currentIndex != 1: - self.prevButton.setEnabled(True) + # if self.currentIndex != self.maxPage: + # self.nextButton.setEnabled(True) + # + # if self.currentIndex != 1: + # self.prevButton.setEnabled(True) if self.first and self.triggerByButton: gameId = layout.itemAt(0).widget().gameId @@ -463,7 +484,8 @@ def updateGame(self, game: dict): result = self.tr("4th") self.titleBar.updateTitleBar( - mapIcon, result, game["mapName"], game["modeName"], game["gameDuration"], game["gameCreation"], game["gameId"], color + mapIcon, result, game["mapName"], game["modeName"], game["gameDuration"], game["gameCreation"], + game["gameId"], color ) team1 = game["teams"][100] @@ -1139,7 +1161,7 @@ def _(): self.loadGamesThread.start() while len(self.games) < 10 and self.loadGamesThread.is_alive(): - ... + time.sleep(.1) self.careerButton.setEnabled(True) # self.filterButton.setEnabled(True) @@ -1155,7 +1177,6 @@ def _(): threading.Thread(target=_).start() - def loadGames(self, puuid): """ From ce8bb3fb8fff858713de264182329a0ae5087800 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Thu, 21 Sep 2023 02:52:25 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=88=98=E7=BB=A9?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E4=BB=A3=E7=A0=81=20=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E5=A4=84=E7=90=86,=20=E5=89=8D=E5=90=8E=E7=AB=AF=E5=88=86?= =?UTF-8?q?=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 6 +- app/view/search_interface.py | 359 +++++++++++------------------------ 2 files changed, 109 insertions(+), 256 deletions(-) diff --git a/app/view/main_window.py b/app/view/main_window.py index 49f29a5a..bc368907 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -1075,10 +1075,8 @@ def _(): def __onCareerInterfaceGameInfoBarClicked(self, gameId): name = self.careerInterface.name.text() self.searchInterface.searchLineEdit.setText(name) - self.searchInterface.gamesView.gamesTab.triggerByButton = False - self.searchInterface.gamesView.gamesTab.updatePuuid( - self.careerInterface.puuid) - self.searchInterface.gamesView.gamesTab.tabClicked.emit(gameId) + self.searchInterface.gamesView.gamesTab.triggerGameId = gameId + self.searchInterface.searchButton.click() def __onCareerInterfaceRefreshButtonClicked(self): self.__onSearchInterfaceSummonerNameClicked( diff --git a/app/view/search_interface.py b/app/view/search_interface.py index 7e9ab00b..d31ae884 100644 --- a/app/view/search_interface.py +++ b/app/view/search_interface.py @@ -22,15 +22,16 @@ class GamesTab(QFrame): - gamesInfoReady = pyqtSignal(int) tabClicked = pyqtSignal(str) gameDetailReady = pyqtSignal(dict) + loadFinish = pyqtSignal() def __init__(self, parnet=None): super().__init__(parnet) self.setFixedWidth(160) self.vBoxLayout = QVBoxLayout(self) + self.first = True self.stateTooltip = None self.stackWidget = QStackedWidget() @@ -41,6 +42,7 @@ def __init__(self, parnet=None): self.nextButton = ToolButton(Icon.CHEVRONRIGHT) self.currentIndex = 0 + self.queueId = 0 self.gamesNumberPerPage = 10 self.maxPage = None @@ -49,7 +51,7 @@ def __init__(self, parnet=None): self.begIndex = 0 - self.triggerByButton = True + self.triggerGameId = 0 self.__initWidget() self.__initLayout() @@ -82,9 +84,18 @@ def __connectSignalToSlot(self): self.prevButton.clicked.connect(self.__onPrevButtonClicked) self.nextButton.clicked.connect(self.__onNextButtonClicked) - self.gamesInfoReady.connect(self.__onGamesInfoReady) self.tabClicked.connect(self.__onTabClicked) self.gameDetailReady.connect(self.__onGameDetailReady) + self.loadFinish.connect(self.__onLoadFinish) + + def __onLoadFinish(self): + if self.stateTooltip: + self.stateTooltip.setContent( + self.tr('Data loading completed!') + ' 😆') + self.stateTooltip.setState(True) + self.stateTooltip = None + self.nextButton.setEnabled(True) + self.__onNextButtonClicked() def __onTabClicked(self, gameId): @@ -110,104 +121,93 @@ def __onPrevButtonClicked(self): if self.currentIndex == 1: self.prevButton.setEnabled(False) - def questionPage(self, page, queueId=None) -> bool: + def questionPage(self) -> bool: """ - - @param page: 需要查询的页码 - @param queueId: 过滤条件 @return: True -> 此页可以直接返回, False -> 此页未加载完成或超出最大页码 """ + games = self.window().searchInterface.games - if queueId is None: - maxPage = int(len(games) / 10) - else: - buffer = self.window().searchInterface.queueIdBuffer.get(queueId, []) + if self.queueId: + buffer = self.window().searchInterface.queueIdBuffer.get(self.queueId, []) maxPage = int(len(buffer) / 10) + else: + maxPage = int(len(games) / 10) - return page < maxPage - - # FIXME 信号部分未声明参数 - def __onNextButtonClicked(self, page: int = 1, queueId=None): - """ + return self.currentIndex < maxPage - @param page: 目标页 - """ + def __showStateTooltip(self): + # FIXME 右上角弹出会挡交互, 改为右下角 - assert page > 0 + if not self.stateTooltip: + self.stateTooltip = StateToolTip( + self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) + self.stateTooltip.move(self.stateTooltip.getSuitablePos()) + self.stateTooltip.show() + def __onNextButtonClicked(self): + self.currentIndex += 1 def waitLoadPage(): - while not self.questionPage(page, queueId): - time.sleep(.5) - if self.stateTooltip: - self.stateTooltip.setContent( - self.tr('Data loading completed!') + ' 😆') - self.stateTooltip.setState(True) - self.stateTooltip = None - self.nextButton.setEnabled(True) - self.__onNextButtonClicked(page, queueId) + while not self.questionPage() and self.window().searchInterface.loadGamesThread.is_alive(): + time.sleep(.2) + self.currentIndex -= 1 + self.loadFinish.emit() games = self.window().searchInterface.games loadThread = self.window().searchInterface.loadGamesThread # 用于判断还有无获取新数据 - if queueId is None: - maxPage = int(len(games) / 10) - if page >= maxPage: + if self.queueId: + buffer = self.window().searchInterface.queueIdBuffer.get(self.queueId, []) + maxPage = int(len(buffer) / 10) + if self.currentIndex > maxPage: if loadThread.is_alive(): self.nextButton.setEnabled(False) - if not self.stateTooltip: - self.stateTooltip = StateToolTip( - self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) - self.stateTooltip.move(self.stateTooltip.getSuitablePos()) - self.stateTooltip.show() + self.__showStateTooltip() threading.Thread(target=waitLoadPage).start() return - else: # 已到最后一页 - data = games[(page - 1) * 10:] + else: + tmpBuf = buffer[(self.currentIndex - 1) * 10:] self.nextButton.setEnabled(False) else: - data = games[(page - 1) * 10: page * 10] + self.nextButton.setEnabled(True) + tmpBuf = buffer[(self.currentIndex - 1) * 10: self.currentIndex * 10] + + data = [] + for idx in tmpBuf: + data.append(games[idx]) else: - buffer = self.window().searchInterface.queueIdBuffer.get(queueId, []) - maxPage = int(len(buffer) / 10) - if page >= maxPage: + maxPage = int(len(games) / 10) + if self.currentIndex > maxPage: if loadThread.is_alive(): self.nextButton.setEnabled(False) - if not self.stateTooltip: - self.stateTooltip = StateToolTip( - self.tr('Data is loading'), self.tr('Please wait patiently'), self.window()) - self.stateTooltip.move(self.stateTooltip.getSuitablePos()) - self.stateTooltip.show() + self.__showStateTooltip() threading.Thread(target=waitLoadPage).start() return - else: - tmpBuf = buffer[(page - 1) * 10:] + else: # 已到最后一页 + data = games[(self.currentIndex - 1) * 10:] self.nextButton.setEnabled(False) else: - tmpBuf = buffer[(page - 1) * 10: page * 10] + self.nextButton.setEnabled(True) + data = games[(self.currentIndex - 1) * 10: self.currentIndex * 10] - data = [] - for idx in tmpBuf: - data.append(games[idx]) + if data: + self.updateNextPageTabs(data) + else: + self.clear() + self.parent().gameDetailView.clear() - self.updateNextPageTabs(data) - # self.stackWidget.setCurrentIndex(self.currentIndex) - # self.pageLabel.setText(f"{self.currentIndex}") - # if self.currentIndex == self.maxPage: - # self.nextButton.setEnabled(False) - self.prevButton.setEnabled(True) - self.currentIndex = page - - # if len(self.stackWidget) <= self.currentIndex: - # self.nextButton.setEnabled(False) - # self.prevButton.setEnabled(False) - # self.updateGames(self.currentIndex) - # else: - # self.stackWidget.setCurrentIndex(self.currentIndex) - # self.pageLabel.setText(f"{self.currentIndex}") - # if self.currentIndex == self.maxPage: - # self.nextButton.setEnabled(False) - # self.prevButton.setEnabled(True) + if self.currentIndex > 1: + self.prevButton.setEnabled(True) + + def clear(self): + for i in reversed(range(len(self.stackWidget))): + if i != 0: + widget = self.stackWidget.widget(i) + self.stackWidget.removeWidget(widget) + widget.deleteLater() + + self.stackWidget.setCurrentIndex(0) + self.pageLabel.setText(" ") def backToDefaultPage(self): self.currentIndex = 0 @@ -229,31 +229,28 @@ def backToDefaultPage(self): self.prevButton.setVisible(False) self.nextButton.setVisible(False) - def firstCall(self, puuid): + def updatePuuid(self, puuid, queueId=0): if self.puuid != None: self.backToDefaultPage() - self.puuid = puuid self.first = True + self.puuid = puuid + self.queueId = queueId self.prevButton.setVisible(True) self.nextButton.setVisible(True) self.__onNextButtonClicked() - # self.currentIndex += 1 - # self.stackWidget.setCurrentIndex(self.currentIndex) - # self.pageLabel.setText(f"{self.currentIndex}") - # if self.currentIndex == self.maxPage: - # self.nextButton.setEnabled(False) - # if len(self.games) == 0: - # self.__showEmptyPage() - - def updatePuuid(self, puuid): - if self.puuid != None: - self.backToDefaultPage() - self.puuid = puuid + def updateFilter(self, queueId=0): + assert self.puuid + + self.currentIndex = 0 self.first = True + self.queueId = queueId self.prevButton.setVisible(True) self.nextButton.setVisible(True) + self.prevButton.setEnabled(False) + self.clear() + self.parent().gameDetailView.clear() self.__onNextButtonClicked() def updateNextPageTabs(self, data): @@ -270,113 +267,21 @@ def updateNextPageTabs(self, data): 1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.stackWidget.addWidget(widget) - self.stackWidget.setCurrentIndex(self.currentIndex) - self.pageLabel.setText(f"{self.currentIndex}") - - # if self.currentIndex != self.maxPage: - # self.nextButton.setEnabled(True) - # - # if self.currentIndex != 1: - # self.prevButton.setEnabled(True) - if self.first and self.triggerByButton: - gameId = layout.itemAt(0).widget().gameId - self.tabClicked.emit(str(gameId)) - self.first = False - - mainWindow = self.window() - mainWindow.checkAndSwitchTo(mainWindow.searchInterface) - - def updateTabs(self, begin, n): - widget = QWidget() - layout = QVBoxLayout(widget) - layout.setContentsMargins(0, 0, 0, 0) - - for i in range(begin, begin + n): - tab = GameTab(self.games[i]) - layout.addWidget(tab) - - if n < self.gamesNumberPerPage: - layout.addSpacerItem(QSpacerItem( - 1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)) - - self.stackWidget.addWidget(widget) self.stackWidget.setCurrentIndex(self.currentIndex) self.pageLabel.setText(f"{self.currentIndex}") - if self.currentIndex != self.maxPage: - self.nextButton.setEnabled(True) - - if self.currentIndex != 1: - self.prevButton.setEnabled(True) - - if self.first and self.triggerByButton: + if self.first: gameId = layout.itemAt(0).widget().gameId self.tabClicked.emit(str(gameId)) self.first = False + elif self.triggerGameId: + self.tabClicked.emit(str(self.triggerGameId)) + self.triggerGameId = 0 mainWindow = self.window() mainWindow.checkAndSwitchTo(mainWindow.searchInterface) - def updateGames(self, page): - def _(page, callback=None): - tmp_games_cnt = len(self.games) - endIndex = self.begIndex + 9 - while True: - games = connector.getSummonerGamesByPuuid( - self.puuid, self.begIndex, endIndex) - - for game in games["games"]: - if time.time() - game['gameCreation'] / 1000 > 60 * 60 * 24 * 365: - self.maxPage = page - break - - if self.games: - # 避免重复添加 - if game['gameCreation'] >= self.games[-1]["timeStamp"]: - continue - - if game["queueId"] in self.window().searchInterface.filterData: - self.games += [processGameData(game)] - - if len(self.games) - tmp_games_cnt >= 10: - self.maxPage = page + 1 - self.games = self.games[:10 * self.maxPage] - break - - self.begIndex = endIndex + 1 - endIndex += 10 - if callback: - callback() - - if page == 1: # 第一页时加载自身数据, 完成后切换; 并且并发加载下一页数据 - def firstPageCallback(): - """ - 禁用下一页按钮必须在gamesInfoReady信号之后, 所以要另外拿出来做回调 - """ - self.gamesInfoReady.emit(page) - self.nextButton.setEnabled(False) - threading.Thread(target=_, args=(page + 1, lambda: self.nextButton.setEnabled(True))).start() - - threading.Thread(target=_, args=(page, firstPageCallback)).start() - else: # 除第一页外, 直接切换到该页, 并加载下一页; - self.gamesInfoReady.emit(page) - self.nextButton.setEnabled(False) - threading.Thread(target=_, args=(page + 1, lambda: self.nextButton.setEnabled(True))).start() - - def __onGamesInfoReady(self, page): - if len(self.games) == 0: - self.__showEmptyPage() - return - - m = self.gamesNumberPerPage - begin = m * (page - 1) - - n = 10 if self.currentIndex != self.maxPage else min( - m, (len(self.games) - 1) % m + 1) - - self.updateTabs(begin, n) - def __showEmptyPage(self): widget = QWidget() layout = QVBoxLayout(widget) @@ -1082,10 +987,7 @@ class SearchInterface(SmoothScrollArea): def __init__(self, parent=None): super().__init__(parent) - # self.filterData = (420, 440, 430, 450) # 默认全选 - # self.filterTimer = threading.Timer(.5, self.__onSearchButtonClicked) - # self.filterOld = None # 条件改动前后若无变化, 则不触发更新逻辑 - + self.comboBoxQueueId = (0, 430, 450, 420, 440) self.games = [] self.queueIdBuffer = {} self.loadGamesThread = None @@ -1099,9 +1001,6 @@ def __init__(self, parent=None): self.careerButton = PushButton(self.tr("Career")) self.filterComboBox = ComboBox() - # self.filterButton = PushButton(self.tr("Filter")) - # self.filterButton.clicked.connect(self.showFilterFlyout) - self.gamesView = GamesView() self.currentSummonerName = None @@ -1115,7 +1014,6 @@ def __initWidget(self): self.searchLineEdit.setPlaceholderText( self.tr("Please input summoner name")) self.careerButton.setEnabled(False) - # self.filterButton.setEnabled(False) self.filterComboBox.setEnabled(False) self.searchButton.setShortcut("Return") @@ -1136,7 +1034,6 @@ def __initLayout(self): self.searchLayout.addSpacing(5) self.searchLayout.addWidget(self.searchButton) self.searchLayout.addWidget(self.careerButton) - # self.searchLayout.addWidget(self.filterButton) self.searchLayout.addWidget(self.filterComboBox) self.vBoxLayout.addLayout(self.searchLayout) @@ -1145,11 +1042,13 @@ def __initLayout(self): self.vBoxLayout.setContentsMargins(30, 32, 30, 30) def __onSearchButtonClicked(self): + self.filterComboBox.setCurrentIndex(0) + targetName = self.searchLineEdit.text() if targetName == "": return - if self.loadGamesThread: + if self.loadGamesThread and self.loadGamesThread.is_alive(): self.loadGamesThreadStop.set() def _(): @@ -1159,21 +1058,10 @@ def _(): self.currentSummonerName = targetName self.loadGamesThread = threading.Thread(target=self.loadGames, args=(puuid,)) self.loadGamesThread.start() - - while len(self.games) < 10 and self.loadGamesThread.is_alive(): - time.sleep(.1) - - self.careerButton.setEnabled(True) - # self.filterButton.setEnabled(True) - self.filterComboBox.setEnabled(True) - self.gamesView.gameDetailView.clear() - self.gamesView.gamesTab.triggerByButton = True - self.gamesView.gamesTab.firstCall(puuid) except: - # puuid = "-1" - self.__showSummonerNotFoundMessage() + puuid = "-1" - # self.summonerPuuidGetted.emit(puuid) + self.summonerPuuidGetted.emit(puuid) threading.Thread(target=_).start() @@ -1185,19 +1073,23 @@ def loadGames(self, puuid): @param puuid: @return: """ + self.games = [] + self.queueIdBuffer = {} gameIdx = 0 begIdx = 0 - endIdx = begIdx + 9 + endIdx = begIdx + 99 while True: games = connector.getSummonerGamesByPuuid( puuid, begIdx, endIdx) + if not games["games"]: # 所有对局都在一年内, 查完了 + return + for game in games["games"]: if time.time() - game['gameCreation'] / 1000 > 60 * 60 * 24 * 365: return if self.loadGamesThreadStop.isSet(): - self.games = [] self.loadGamesThreadStop.clear() return @@ -1207,27 +1099,31 @@ def loadGames(self, puuid): self.queueIdBuffer[game["queueId"]].append(gameIdx) else: self.queueIdBuffer[game["queueId"]] = [gameIdx] - # self.queueIdBuffer[game["queueId"]] = self.queueIdBuffer.get(game["queueId"], []).append(gameIdx) gameIdx += 1 begIdx = endIdx + 1 - endIdx += 9 + endIdx += 99 def __onSummonerPuuidGetted(self, puuid): if puuid != "-1": self.careerButton.setEnabled(True) - # self.filterButton.setEnabled(True) self.filterComboBox.setEnabled(True) self.gamesView.gameDetailView.clear() - self.gamesView.gamesTab.triggerByButton = True - self.gamesView.gamesTab.updatePuuid(puuid) + self.gamesView.gamesTab.updatePuuid( + puuid, self.comboBoxQueueId[self.filterComboBox.currentIndex()] + ) else: self.__showSummonerNotFoundMessage() def __connectSignalToSlot(self): self.searchButton.clicked.connect(self.__onSearchButtonClicked) self.summonerPuuidGetted.connect(self.__onSummonerPuuidGetted) + self.filterComboBox.currentIndexChanged.connect( + self.__onFilterComboBoxChanged) + + def __onFilterComboBoxChanged(self): + self.gamesView.gamesTab.updateFilter(self.comboBoxQueueId[self.filterComboBox.currentIndex()]) def __showSummonerNotFoundMessage(self): InfoBar.error( @@ -1249,46 +1145,5 @@ def setEnabled(self, a0: bool) -> None: self.searchButton.setEnabled(a0) self.filterComboBox.setEnabled(a0) - # self.filterButton.setEnabled(a0) return super().setEnabled(a0) - - def fillterTimerRun(self): - if self.filterOld != self.filterData: - self.__onSearchButtonClicked() - - self.filterOld = None - - def showFilterFlyout(self): - filterFlyout = FlyoutView("", "") - - filterBoxGroup = ModeFilterWidget() - filterBoxGroup.setCheckBoxState(self.filterData) - - def _(): - self.filterTimer.cancel() - - if not self.filterOld: - self.filterOld = self.filterData - - # 将选中状态同步到 interface - self.filterData = filterBoxGroup.getFilterMode() - self.gamesView.gamesTab.currentIndex = 0 - - # 消除频繁切换筛选条件带来的抖动 - self.filterTimer = threading.Timer(.7, lambda obj=self: obj.fillterTimerRun()) - self.filterTimer.start() - - filterBoxGroup.setCallback(_) - - filterFlyout.widgetLayout.addWidget(filterBoxGroup, 0, Qt.AlignCenter) - - filterFlyout.widgetLayout.setContentsMargins(1, 1, 1, 1) - filterFlyout.widgetLayout.setAlignment(Qt.AlignCenter) - - filterFlyout.viewLayout.setSpacing(0) - filterFlyout.viewLayout.setContentsMargins(1, 1, 1, 1) - - w = Flyout.make(filterFlyout, self.filterButton, - self.window(), FlyoutAnimationType.DROP_DOWN) - filterFlyout.closed.connect(w.close)