Skip to content

Commit

Permalink
Merge pull request #60 from Hpero4/main
Browse files Browse the repository at this point in the history
战绩查询功能新增筛选, 修复进入大乱斗后再打开软件报错问题 (#53)
  • Loading branch information
Zzaphkiel authored Sep 18, 2023
2 parents 06d1173 + 3a40e8a commit 16b504a
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 26 deletions.
92 changes: 92 additions & 0 deletions app/components/mode_filter_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QApplication
from qfluentwidgets import CheckBox
from typing import List, Tuple


# TODO GameInfoInterface添加筛选功能

class ModeFilterWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)

self.selected: List[int] = []

self.hBoxLayout = QHBoxLayout(self)
self.hBoxLayout.setAlignment(Qt.AlignCenter)

# TODO 本地化
self.rankSoloCheckBox = CheckBox(self.tr("Rank solo"))
self.rankFlexCheckBox = CheckBox(self.tr("Rank Flex"))
self.normalCheckBox = CheckBox(self.tr("Normal"))
self.aramCheckBox = CheckBox(self.tr("Aram"))

self.checkBoxDict = {
self.rankSoloCheckBox: 420, # 单双排
self.rankFlexCheckBox: 440, # 灵活组排
self.normalCheckBox: 430, # 匹配模式
self.aramCheckBox: 450 # 大乱斗
}

for checkBox, num in self.checkBoxDict.items():
checkBox.stateChanged.connect(lambda state, num=num: self.updateSelected(state, num))

self.hBoxLayout.addWidget(self.rankSoloCheckBox, alignment=Qt.AlignCenter)
self.hBoxLayout.addWidget(self.rankFlexCheckBox, alignment=Qt.AlignCenter)
self.hBoxLayout.addWidget(self.normalCheckBox, alignment=Qt.AlignCenter)
self.hBoxLayout.addWidget(self.aramCheckBox, alignment=Qt.AlignCenter)

self.setLayout(self.hBoxLayout)

def updateSelected(self, state, num, callback=None):
if state == Qt.Checked:
if num not in self.selected:
self.selected.append(num)
else:
if num in self.selected:
self.selected.remove(num)

if callback:
callback()

def setCallback(self, func):
"""
@param func: check box状态改变时回调该方法
@return:
"""
for checkBox, num in self.checkBoxDict.items():
checkBox.stateChanged.connect(lambda state, num=num, func=func: self.updateSelected(state, num, func))

def getFilterMode(self) -> Tuple[int]:
"""
获取选中的模式
@return:
@rtype: Tuple[int]
"""
return set(self.selected)

def setCheckBoxState(self, data: tuple):
"""
设置复选框状态
@param data:
@return:
"""
for checkBox, num in self.checkBoxDict.items():
if num in data:
checkBox.setChecked(True)
else:
checkBox.setChecked(False)


if __name__ == '__main__':
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)

app = QApplication(sys.argv)
w = ModeFilterWidget()
w.show()
app.exec_()
2 changes: 0 additions & 2 deletions app/components/profile_level_icon_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ def updateIcon(self, icon: str, xpSinceLastLevel=None, xpUntilNextLevel=None, te
if text:
self.progressRing.text = text

self.repaint()


if __name__ == "__main__":
app = QApplication(sys.argv)
Expand Down
5 changes: 5 additions & 0 deletions app/lol/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ def translateTier(orig: str, short=False) -> str:


def timeStampToStr(stamp):
"""
@param stamp: Millisecond timestamp
"""
timeArray = time.localtime(stamp / 1000)
return time.strftime("%Y/%m/%d %H:%M", timeArray)

Expand All @@ -44,6 +47,7 @@ def secsToStr(secs):


def processGameData(game):
timeStamp = game["gameCreation"] # 毫秒级时间戳
time = timeStampToStr(game['gameCreation'])
shortTime = timeStampToShortStr(game['gameCreation'])
gameId = game['gameId']
Expand Down Expand Up @@ -111,6 +115,7 @@ def processGameData(game):
'runeIcon': runeIcon,
'cs': cs,
'gold': gold,
'timeStamp': timeStamp,
}


Expand Down
3 changes: 2 additions & 1 deletion app/view/game_info_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def updateSummoners(self, summoners):

for summoner in summoners:
summonerView = SummonerInfoView(summoner)
self.items[summoner["summonerId"]] = summonerView # 用 summonerId 避免空字符串
self.items[str(summoner["summonerId"])] = summonerView # 用 summonerId 避免空字符串
self.vBoxLayout.addWidget(summonerView, stretch=1)

if len(summoners) < 5:
Expand All @@ -222,6 +222,7 @@ def clear(self):

if item.widget():
item.widget().deleteLater()
self.items = {}


class SummonerInfoView(QFrame):
Expand Down
106 changes: 83 additions & 23 deletions app/view/search_interface.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import threading
import time

import pyperclip
from PyQt5.QtWidgets import (QVBoxLayout, QHBoxLayout, QFrame,
QSpacerItem, QSizePolicy, QLabel, QStackedWidget, QWidget)
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPixmap
from qfluentwidgets import (SmoothScrollArea, LineEdit, PushButton, ToolButton, InfoBar,
InfoBarPosition, ToolTipFilter, ToolTipPosition, Theme, isDarkTheme, FlyoutViewBase, Flyout, CardWidget, IndeterminateProgressRing)
InfoBarPosition, ToolTipFilter, ToolTipPosition, Theme, isDarkTheme, FlyoutViewBase, Flyout,
CardWidget, IndeterminateProgressRing, FlyoutView, FlyoutAnimationType)

from ..common.style_sheet import StyleSheet
from ..common.icons import Icon
from ..common.config import cfg
from ..components.champion_icon_widget import RoundIcon
from ..components.mode_filter_widget import ModeFilterWidget
from ..components.summoner_name_button import SummonerName
from ..lol.connector import LolClientConnector, connector
from ..lol.tools import processGameData, processGameDetailData
Expand Down Expand Up @@ -41,6 +44,8 @@ def __init__(self, parnet=None):
self.puuid = None
self.games = []

self.begIndex = 0

self.triggerByButton = True

self.__initWidget()
Expand Down Expand Up @@ -103,6 +108,9 @@ def __onPrevButtonClicked(self):
self.prevButton.setEnabled(False)

def __onNextButtonClicked(self):
if self.currentIndex == 0:
self.begIndex = 0

self.currentIndex += 1

if len(self.stackWidget) <= self.currentIndex:
Expand Down Expand Up @@ -178,35 +186,52 @@ def updateTabs(self, begin, n):
mainWindow.checkAndSwitchTo(mainWindow.searchInterface)

def updateGames(self, page):
def _():
if self.maxPage != None:
self.gamesInfoReady.emit(page)
return
def _(page, callback=None):
# retry = 0
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

count = 10 * (page + 1) - len(self.games)
if self.games:
# 避免重复添加
if game['gameCreation'] >= self.games[-1]["timeStamp"]:
continue

begin = len(self.games)
end = begin + count - 1
if game["queueId"] in self.window().searchInterface.filterData:
self.games += [processGameData(game)]

games = connector.getSummonerGamesByPuuid(
self.puuid, begin, end)
if len(self.games) - tmp_games_cnt >= 10:
self.maxPage = page + 1
self.games = self.games[:10 * self.maxPage]
break

self.games += [processGameData(game)
for game in games["games"]]
# if retry >= 5:
# self.maxPage = page
# break

if page == 1:
if len(games["games"]) <= 10:
self.maxPage = 1
else:
if len(games["games"]) < 10:
if len(games["games"]) == 0:
self.maxPage = page
else:
self.maxPage = page + 1
self.begIndex = endIndex + 1
endIndex += 10
# retry += 1
if callback:
callback()

# self.gamesInfoReady.emit(page)

if page == 1: # 第一页时加载自身数据, 完成后切换; 并且并发加载下一页数据
threading.Thread(target=_, args=(page, lambda page: self.gamesInfoReady.emit(page))).start()
else: # 除第一页外, 直接切换到该页, 并加载下一页;
self.gamesInfoReady.emit(page)

threading.Thread(target=_).start()
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:
Expand Down Expand Up @@ -304,7 +329,6 @@ def __initLayout(self):

def updateGame(self, game: dict):
isCherry = game["queueId"] == 1700

mapIcon = QPixmap(game["mapIcon"]).scaled(
54, 54, Qt.KeepAspectRatio, Qt.SmoothTransformation)
if game["remake"]:
Expand Down Expand Up @@ -926,12 +950,17 @@ 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.vBoxLayout = QVBoxLayout(self)

self.searchLayout = QHBoxLayout()
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.gamesView = GamesView()
self.currentSummonerName = None
Expand All @@ -956,6 +985,7 @@ def __initLayout(self):
self.searchLayout.addSpacing(5)
self.searchLayout.addWidget(self.searchButton)
self.searchLayout.addWidget(self.careerButton)
self.searchLayout.addWidget(self.filterButton)

self.vBoxLayout.addLayout(self.searchLayout)
self.vBoxLayout.addSpacing(5)
Expand Down Expand Up @@ -1014,3 +1044,33 @@ def setEnabled(self, a0: bool) -> None:
return super().setEnabled(a0)

# def clear(self):

def showFilterFlyout(self):
filterFlyout = FlyoutView("", "")

filterBoxGroup = ModeFilterWidget()
filterBoxGroup.setCheckBoxState(self.filterData)

def _():
self.filterTimer.cancel()

# 将选中状态同步到 interface
self.filterData = filterBoxGroup.getFilterMode()
self.gamesView.gamesTab.currentIndex = 0

# 消除频繁切换筛选条件带来的抖动
self.filterTimer = threading.Timer(.5, self.__onSearchButtonClicked)
self.filterTimer.start()
# self.__onSearchButtonClicked()
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)

0 comments on commit 16b504a

Please sign in to comment.