From 448ed32471a40676b80fa5821bcb2d84e7ea41d2 Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Fri, 10 May 2024 21:58:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?1.=20=E7=8E=B0=E5=9C=A8,=20=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=BC=82=E5=B8=B8=E6=97=B6,=20=E4=BC=9A=E6=89=93?= =?UTF-8?q?=E5=8D=B0Seraphine=E7=9A=84=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/view/main_window.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/view/main_window.py b/app/view/main_window.py index f3683820..ade78b90 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -949,6 +949,8 @@ def exceptHook(self, ty, value, tb): logger.error(str(self.auxiliaryFuncInterface), "Crash") logger.error(str(self.settingInterface), "Crash") + content = f"Seraphine ver.{VERSION}\n{'-'*5}\n{content}" + w = ExceptionMessageBox(title, content, self.window()) if w.exec(): From 87e241ce37e3312dd27e9e27dd5a5b1b62749b0c Mon Sep 17 00:00:00 2001 From: Hpero4 Date: Mon, 13 May 2024 00:33:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?1.=20=E7=8E=B0=E5=9C=A8,=20=E6=9E=81?= =?UTF-8?q?=E5=9C=B0=E5=A4=A7=E4=B9=B1=E6=96=97=E6=A8=A1=E5=BC=8F=E4=B8=8B?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=9F=A5=E7=9C=8B=E5=88=B0=E9=92=88=E5=AF=B9?= =?UTF-8?q?=E4=BA=8E=E6=89=80=E9=80=89=E8=8B=B1=E9=9B=84=E7=9A=84Buff(Debu?= =?UTF-8?q?ff)=E4=BA=86=20#314?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO 本地化 --- app/common/util.py | 209 +++++++++++++++++++- app/components/profile_level_icon_widget.py | 208 ++++++++++++++++++- app/lol/tools.py | 2 +- app/view/game_info_interface.py | 26 ++- app/view/main_window.py | 6 +- 5 files changed, 434 insertions(+), 17 deletions(-) diff --git a/app/common/util.py b/app/common/util.py index ad321292..8dfbfeea 100644 --- a/app/common/util.py +++ b/app/common/util.py @@ -1,11 +1,16 @@ import json +import os +import re +from functools import lru_cache, wraps import requests import base64 import subprocess import psutil +import win32api -from app.common.config import cfg, VERSION +from app.common.config import cfg, VERSION, LOCAL_PATH +from app.common.logger import logger class Github: @@ -56,7 +61,6 @@ def __get_ver_info(self): return json_data.get(VERSION, {}) - def getNotice(self): url = f'{self.githubApi}/repos/{self.user}/{self.repositories}/contents/document/notice.md' @@ -75,6 +79,158 @@ def getNotice(self): } +class AramHome: + """ + Power by: 大乱斗之家 + Site: http://www.jddld.com + """ + ARAM_CFG_PATH = f"{LOCAL_PATH}/AramBuff.json" + URL = "http://www.jddld.com" + TAG = "AramHome" + APPID = 1 + APP_SECRET = "PHPCMFBBC77AF8E8FA5" + data = None + + @staticmethod + def needData(func): + """ + TODO 如何优雅地使用它? -- By Hpero4 + """ + @wraps(func) + def wrapper(*args, **kwargs): + if AramHome.data is None: + m = AramHome() + m.__loadData() + return func(*args, **kwargs) + + return wrapper + + @classmethod + async def checkAndUpdate(cls): + m = cls() + if m.__checkUpdate(): + await m.__update() + + @classmethod + def getInfoByHeroId(cls, heroid: str): + return cls.getInfoByField("heroid", heroid) + + @classmethod + def getInfoByHeroName(cls, name: str): + return cls.getInfoByField("name", name) + + @classmethod + def getInfoByCatName(cls, name: str): + return cls.getInfoByField("catname", name) + + @classmethod + def getInfoByCatNameLoose(cls, name: str): + return cls.getInfoByFieldLoose("catname", name) + + @classmethod + # @needData + @lru_cache(maxsize=None) + def getInfoByField(cls, field: str, val: str): + """ + 通过字段值匹配一个item + + 找不到返回 None + """ + if cls.data is None: + m = cls() + m.__loadData() + for item in cls.data.values(): + if item[field] == val: + return item + return None + + @classmethod + # @needData + @lru_cache(maxsize=None) + def getInfoByFieldLoose(cls, field: str, val: str): + """ + 通过字段值匹配一个item + + 宽松匹配, 只要val在field内都认为找到 + + 找不到返回 None + """ + if cls.data is None: + m = cls() + m.__loadData() + for item in cls.data.values(): + if val in item[field]: + return item + return None + + def __loadData(self): + with open(self.ARAM_CFG_PATH, 'r') as f: + AramHome.data = json.loads(f.read()) + + async def __update(self): + logger.info("update info", self.TAG) + url = f"{self.URL}/index.php" + params = { + 'appid': self.APPID, + 'appsecret': self.APP_SECRET, + 's': 'news', + 'c': 'search', + 'api_call_function': 'module_list', + 'pagesize': '200' # FIXME 超过200个英雄会拿不完 -- By Hpero4 + } + data = requests.get(url, params=params, proxies=None, verify=False).json() # 它不需要代理 + if data.get("code") == 1: + with open(self.ARAM_CFG_PATH, "w") as f: + data = data.get("data") + json.dump(data, f) + AramHome.data = data + else: + logger.warning(f"update err: {data}", self.TAG) + + def __checkUpdate(self): + """ + 检查缓存的数据与当前版本是否匹配, 若不匹配尝试更新 + + 尽可能在游戏启动后再调用, 否则当存在多个客户端时, cfg.lolFolder不一定是准确的(外服国服可能版本不同) + + @return : + True -> 需要更新 + False -> 无需更新 + + TODO: 暂未提供历史版本数据查询接口 + """ + gamePath = cfg.get(cfg.lolFolder) + + assert gamePath # 必须有, 否则就是调用逻辑有问题 -- By Hpero4 + + # 特判一下国服 -- By Hpero4 + gamePath = gamePath.replace("/TCLS", "") + + lolExe = f"{gamePath}/Game/League of Legends.exe" + # 判断一下, 客户端特殊? 为啥会没有LOL的主程序 -- By Hpero4 + if not os.path.exists(lolExe): + raise FileNotFoundError(lolExe) + + fileInfo = getFileProperties(lolExe).get("StringFileInfo", {}) + lolVer = fileInfo.get("ProductVersion") or fileInfo.get("FileVersion") + + assert lolVer + + # 缩短至大版本号 + lolVer = re.search(r"\d+\.\d+", lolVer).group(0) + + # 检查一下版本号是否相同, 如果一样, 就不更新了 + if os.path.exists(self.ARAM_CFG_PATH): + with open(self.ARAM_CFG_PATH, "r") as f: + data = json.loads(f.read()) + AramHome.data = data + dataVer = re.search(r"\d+\.\d+", data.get("banben", "")).group(0) + if dataVer and dataVer == lolVer: + return False + + return True + + github = Github() @@ -107,7 +263,7 @@ def getLolClientPid(path): arr = processes.split() try: pos = arr.index(b"LeagueClientUx.exe") - return int(arr[pos+1]) + return int(arr[pos + 1]) except ValueError: raise ValueError(f"Subprocess return exception: {processes}") else: @@ -176,3 +332,50 @@ def getPortTokenServerByPid(pid): break return port, token, server + + +def getFileProperties(fname): + """ + 读取给定文件的所有属性, 返回一个字典. + + returns : {'FixedFileInfo': {'Signature': -17890115, 'StrucVersion': 65536, 'FileVersionMS': 917513, 'FileVersionLS': + 38012988, 'ProductVersionMS': 917513, 'ProductVersionLS': 38012988, 'FileFlagsMask': 23, 'FileFlags': 0, + 'FileOS': 4, 'FileType': 1, 'FileSubtype': 0, 'FileDate': None}, 'StringFileInfo': {'Comments': None, + 'InternalName': 'League of Legends (TM) Client', 'ProductName': 'League of Legends (TM) Client', 'CompanyName': + 'Riot Games, Inc.', 'LegalCopyright': 'Copyright (C) 2009', 'ProductVersion': '14.9.580.2108', 'FileDescription': + 'League of Legends (TM) Client', 'LegalTrademarks': None, 'PrivateBuild': None, 'FileVersion': '14.9.580.2108', + 'OriginalFilename': 'League of Legends.exe', 'SpecialBuild': None}, 'FileVersion': '14.9.580.2108'} + + """ + + propNames = ('Comments', 'InternalName', 'ProductName', + 'CompanyName', 'LegalCopyright', 'ProductVersion', + 'FileDescription', 'LegalTrademarks', 'PrivateBuild', + 'FileVersion', 'OriginalFilename', 'SpecialBuild') + + props = {'FixedFileInfo': None, 'StringFileInfo': None, 'FileVersion': None} + + try: + fixedInfo = win32api.GetFileVersionInfo(fname, '\\') + props['FixedFileInfo'] = fixedInfo + props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536, + fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536, + fixedInfo['FileVersionLS'] % 65536) + + # \VarFileInfo\Translation returns list of available (language, codepage) + # pairs that can be used to retreive string info. We are using only the first pair. + lang, codepage = win32api.GetFileVersionInfo(fname, '\\VarFileInfo\\Translation')[0] + + # any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle + # two are language/codepage pair returned from above + + strInfo = {} + for propName in propNames: + strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName) + strInfo[propName] = win32api.GetFileVersionInfo(fname, strInfoPath) + + props['StringFileInfo'] = strInfo + except: + return {} + else: + return props diff --git a/app/components/profile_level_icon_widget.py b/app/components/profile_level_icon_widget.py index cf77f56c..5a069b9b 100644 --- a/app/components/profile_level_icon_widget.py +++ b/app/components/profile_level_icon_widget.py @@ -1,10 +1,11 @@ import sys -from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QHBoxLayout -from PyQt5.QtGui import QPainter, QImage, QPainterPath, QPen, QFont, QPixmap -from PyQt5.QtCore import Qt, QRectF +from PyQt5.QtCore import Qt, QRectF, QPoint +from PyQt5.QtGui import QPainter, QPainterPath, QPen, QFont, QPixmap +from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QHBoxLayout, QLabel, QVBoxLayout, QGridLayout -from ..common.qfluentwidgets import ProgressRing, ToolTipFilter, ToolTipPosition, isDarkTheme, themeColor +from ..common.qfluentwidgets import ProgressRing, ToolTipFilter, ToolTipPosition, isDarkTheme, themeColor, \ + FlyoutViewBase, TextWrap class ProgressArc(ProgressRing): @@ -52,6 +53,7 @@ def __init__(self, xpUntilNextLevel, diameter=100, text="", + aramInfo=None, parent=None): super().__init__(parent) self.diameter = diameter @@ -65,16 +67,19 @@ def __init__(self, self.xpSinceLastLevel = xpSinceLastLevel self.xpUntilNextLevel = xpUntilNextLevel self.progressRing = ProgressArc( - self, text=text, fontSize=int(.1*diameter)) + self, text=text, fontSize=int(.1 * diameter)) self.progressRing.setTextVisible(False) self.progressRing.setFixedSize(self.diameter, self.diameter) - self.setToolTip(f"Exp: {xpSinceLastLevel} / {xpUntilNextLevel}") + # self.setToolTip(f"Exp: {xpSinceLastLevel} / {xpUntilNextLevel}") self.installEventFilter(ToolTipFilter(self, 250, ToolTipPosition.TOP)) self.paintXpSinceLastLevel = None self.paintXpUntilNextLevel = None self.callUpdate = False + self.mFlyout = None + self.aramInfo = aramInfo + def paintEvent(self, event): if self.paintXpSinceLastLevel != self.xpSinceLastLevel or self.paintXpUntilNextLevel != self.xpUntilNextLevel or self.callUpdate: self.progressRing.setVal(self.xpSinceLastLevel * 100 // @@ -115,7 +120,7 @@ def updateIcon(self, icon: str, xpSinceLastLevel=None, xpUntilNextLevel=None, te self.xpSinceLastLevel = xpSinceLastLevel self.xpUntilNextLevel = xpUntilNextLevel - self.setToolTip(f"Exp: {xpSinceLastLevel} / {xpUntilNextLevel}") + # self.setToolTip(f"Exp: {xpSinceLastLevel} / {xpUntilNextLevel}") if text: self.progressRing.text = text @@ -123,6 +128,195 @@ def updateIcon(self, icon: str, xpSinceLastLevel=None, xpUntilNextLevel=None, te self.callUpdate = True self.repaint() + def updateAramInfo(self, info): + self.aramInfo = info + if self.mFlyout: + self.mFlyout.updateInfo(info) + self.mFlyout.hide() + self.mFlyout.show() + + def enterEvent(self, a0): + if self.aramInfo: + if not self.mFlyout: + self.mFlyout = AramFlyout( + info=self.aramInfo, + target=self, + parent=self.window() + ) + self.mFlyout.show() + # TODO Animation -- By Hpero4 + # aM = FlyoutAnimationManager.make(FlyoutAnimationType.SLIDE_LEFT, self.mFlyout) + # target = aM.position(self) + # aM.exec(target) + super().enterEvent(a0) + + def leaveEvent(self, a0): + if self.aramInfo: + if self.mFlyout: + self.mFlyout.close() + self.mFlyout = None + + +class AramFlyout(FlyoutViewBase): + def __init__(self, info, target, parent=None): + super().__init__(parent=parent) + self.info = info + self.target = target + + self.damageDealt = 0 + self.damageReceived = 0 + self.healingIncrease = 0 + self.shieldIncrease = 0 + self.abilityHaste = 0 + self.tenacity = 0 + self.description = "" + self.catName = "" + + self.vBoxLayout = QVBoxLayout(self) + self.gridBox = QGridLayout() + + self.titleLabel = QLabel(self) # 英雄名字(带称号) + self.damageDealtLabel = QLabel(self.tr('Damage Dealt'), self) # 造成伤害的权重 + self.damageReceivedLabel = QLabel(self.tr('Damage Received'), self) # 受到伤害的权重 + self.healingIncreaseLabel = QLabel(self.tr('Healing Increase'), self) # 治疗增益的权重 + self.shieldIncreaseLabel = QLabel(self.tr('Shield Increase'), self) # 护盾增益的权重 + self.abilityHasteLabel = QLabel(self.tr('Ability Haste'), self) # 技能急速的权重, 是正向属性, 值越大cd越短 + self.tenacityLabel = QLabel(self.tr('Tenacity'), self) # 韧性的权重 + + self.damageDealtValueLabel = QLabel(self) # 造成伤害的权重 + self.damageReceivedValueLabel = QLabel(self) # 受到伤害的权重 + self.healingIncreaseValueLabel = QLabel(self) # 治疗增益的权重 + self.shieldIncreaseValueLabel = QLabel(self) # 护盾增益的权重 + self.abilityHasteValueLabel = QLabel(self) # 技能急速的权重, 是正向属性, 值越大cd越短 + self.tenacityValueLabel = QLabel(self) # 韧性的权重 + + self.descriptionLabel = QLabel(self) # 额外调整 + self.powerByLabel = QLabel("Power By jddld.com", self) + + self.updateInfo(info) + + self.__initWidgets() + + def calcPoints(self): + pos = self.target.mapToGlobal(QPoint()) + windowPos = self.window().mapToGlobal(QPoint()) + x = pos.x() + self.target.width() // 2 - self.sizeHint().width() // 2 - windowPos.x() + y = pos.y() - self.sizeHint().height() - 12 - windowPos.y() + + if x < 5: + x = 5 + + return QPoint(x, y) + + def __initWidgets(self): + self.titleLabel.setVisible(True) + self.damageDealtLabel.setVisible(True) + self.damageReceivedLabel.setVisible(True) + self.healingIncreaseLabel.setVisible(True) + self.shieldIncreaseLabel.setVisible(True) + self.abilityHasteLabel.setVisible(True) + self.tenacityLabel.setVisible(True) + + self.descriptionLabel.setStyleSheet("border-top: 1px solid rgba(0, 0, 0, 80);") + self.powerByLabel.setStyleSheet("color: rgba(0, 0, 0, 70);") + + self.titleLabel.setFont(QFont('Microsoft YaHei', 11, QFont.Bold)) + self.titleLabel.setAlignment(Qt.AlignCenter) + self.powerByLabel.setAlignment(Qt.AlignCenter) + self.descriptionLabel.setFont(QFont('Microsoft YaHei', 9)) + self.powerByLabel.setFont(QFont('Microsoft YaHei', 8)) + + self.damageDealtLabel.setFont(QFont("Source Code Pro", 9, QFont.Bold)) + self.damageReceivedLabel.setFont(QFont("Source Code Pro", 9, QFont.Bold)) + self.healingIncreaseLabel.setFont(QFont("Source Code Pro", 9, QFont.Bold)) + self.shieldIncreaseLabel.setFont(QFont("Source Code Pro", 9, QFont.Bold)) + self.abilityHasteLabel.setFont(QFont("Source Code Pro", 9, QFont.Bold)) + self.tenacityLabel.setFont(QFont("Source Code Pro", 9, QFont.Bold)) + + self.__initLayout() + + def __initLayout(self): + self.vBoxLayout.setSizeConstraint(QVBoxLayout.SetMinimumSize) + self.vBoxLayout.setContentsMargins(10, 8, 10, 8) + self.vBoxLayout.setSpacing(2) + self.gridBox.setHorizontalSpacing(10) + self.gridBox.setVerticalSpacing(4) + + self.vBoxLayout.addWidget(self.titleLabel) + self.vBoxLayout.addLayout(self.gridBox) + self.vBoxLayout.addWidget(self.descriptionLabel) + self.vBoxLayout.addWidget(self.powerByLabel) + + self.gridBox.addWidget(self.damageDealtLabel, 0, 0, Qt.AlignLeft) + self.gridBox.addWidget(self.damageDealtValueLabel, 0, 1, Qt.AlignRight) + self.gridBox.addWidget(self.damageReceivedLabel, 0, 2, Qt.AlignLeft) + self.gridBox.addWidget(self.damageReceivedValueLabel, 0, 3, Qt.AlignRight) + self.gridBox.addWidget(self.healingIncreaseLabel, 1, 0, Qt.AlignLeft) + self.gridBox.addWidget(self.healingIncreaseValueLabel, 1, 1, Qt.AlignRight) + self.gridBox.addWidget(self.shieldIncreaseLabel, 1, 2, Qt.AlignLeft) + self.gridBox.addWidget(self.shieldIncreaseValueLabel, 1, 3, Qt.AlignRight) + self.gridBox.addWidget(self.abilityHasteLabel, 2, 0, Qt.AlignLeft) + self.gridBox.addWidget(self.abilityHasteValueLabel, 2, 1, Qt.AlignRight) + self.gridBox.addWidget(self.tenacityLabel, 2, 2, Qt.AlignLeft) + self.gridBox.addWidget(self.tenacityValueLabel, 2, 3, Qt.AlignRight) + + self.setLayout(self.vBoxLayout) + + def __updateStyle(self): + """ + 数据更新时调用一下, 把样式更新 + """ + self.descriptionLabel.setVisible(bool(self.description)) + self.damageDealtValueLabel.setStyleSheet(self.__getColor(self.damageDealt, 100)) + self.damageReceivedValueLabel.setStyleSheet(self.__getColor(self.damageReceived, 100, False)) + self.healingIncreaseValueLabel.setStyleSheet(self.__getColor(self.healingIncrease, 100)) + self.shieldIncreaseValueLabel.setStyleSheet(self.__getColor(self.shieldIncrease, 100)) + self.abilityHasteValueLabel.setStyleSheet(self.__getColor(self.abilityHaste, 0)) + self.tenacityValueLabel.setStyleSheet(self.__getColor(self.tenacity, 0)) + + def __getColor(self, val, criterion, isPositive=True) -> str: + """ + isPositive: 用于标记该属性是否积极(越大越好) + """ + # 如果值越小越好, 交换一下条件, 让低的标记为绿色 + if not isPositive: + val, criterion = criterion, val + + if val > criterion: + return "color: #2aae0f;" # 绿色 + elif val < criterion: + return "color: #d0021b;" # 红色 + + return "" + + def updateInfo(self, info): + self.catName = info.get("catname", "") + self.damageDealt = int(info.get("zcsh", "100")) + self.damageReceived = int(info.get("sdsh", "100")) + self.healingIncrease = int(info.get("zlxl", "100")) + self.shieldIncrease = int(info.get("hdxn", "100")) + self.abilityHaste = int(info.get("jnjs", "0")) + self.tenacity = int(info.get("renxing", "0")) + self.description = info.get("description", "") + + self.titleLabel.setText(self.catName) + self.damageDealtValueLabel.setText(f"{self.damageDealt}%") + self.damageReceivedValueLabel.setText(f"{self.damageReceived}%") + self.healingIncreaseValueLabel.setText(f"{self.healingIncrease}%") + self.shieldIncreaseValueLabel.setText(f"{self.shieldIncrease}%") + self.abilityHasteValueLabel.setText(f"{self.abilityHaste}") + self.tenacityValueLabel.setText(f"{self.tenacity}") + + self.__updateStyle() + + def showEvent(self, e): + super().showEvent(e) + self.adjustSize() + if self.description: + w = self.vBoxLayout.sizeHint().width() * .16 + self.descriptionLabel.setText(TextWrap.wrap(self.description, int(w), False)[0]) + self.move(self.calcPoints()) + if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/app/lol/tools.py b/app/lol/tools.py index f8de425b..d91c07ef 100644 --- a/app/lol/tools.py +++ b/app/lol/tools.py @@ -773,7 +773,7 @@ async def parseAllyGameInfo(session, currentSummonerId, useSGP=False): for summoner in summoners} order = [summoner['summonerId'] for summoner in summoners] - return {'summoners': summoners, 'champions': champions, 'order': order} + return {'summoners': summoners, 'champions': champions, 'order': order, "isAram": session.get('benchEnabled', False)} def parseSummonerOrder(team): diff --git a/app/view/game_info_interface.py b/app/view/game_info_interface.py index 051acc10..04c4706a 100644 --- a/app/view/game_info_interface.py +++ b/app/view/game_info_interface.py @@ -20,6 +20,7 @@ from app.components.animation_frame import CardWidget, ColorAnimationFrame from app.lol.tools import parseSummonerOrder from app.lol.connector import connector +from ..common.util import AramHome from ..components.seraphine_interface import SeraphineInterface @@ -28,6 +29,7 @@ class GameInfoInterface(SeraphineInterface): def __init__(self, parent=None): super().__init__(parent) + self.isAram = False self.hBoxLayout = QHBoxLayout(self) self.summonersView = SummonersView() @@ -84,11 +86,13 @@ def updateAllySummoners(self, info): if not info or len(info['summoners']) > 5: return + self.isAram = info.get("isAram", False) + self.allyChampions = info['champions'] self.allyOrder = info['order'] # 概览栏 (左侧) - self.summonersView.ally.updateSummoners(info['summoners']) + self.summonersView.ally.updateSummoners(info['summoners'], self.isAram) # 战绩栏 (右侧) self.allyGamesView.updateSummoners(info['summoners']) @@ -125,11 +129,15 @@ async def updateAllyIcon(self, team): icon = await connector.getChampionIcon(newChampionId) self.allyChampions[summonerId] = newChampionId view.updateIcon(icon) + if self.isAram: + view.updateAramInfo(AramHome.getInfoByHeroId(str(newChampionId))) async def clear(self): self.allyChampions = {} self.allyOrder = [] + self.isAram = False + self.summonersView.ally.clear() self.summonersView.enemy.clear() self.allyGamesView.clear() @@ -258,14 +266,19 @@ def updateSummonersOrder(self, order: list): self.vBoxLayout.addSpacing(self.vBoxLayout.spacing()) self.vBoxLayout.addStretch(5 - len(order)) - def updateSummoners(self, summoners): + def updateSummoners(self, summoners, isAram=False): self.clear() for summoner in summoners: if not summoner: continue - summonerView = SummonerInfoView(summoner, self) + if isAram and summoner["championId"]: + aramInfo = AramHome.getInfoByHeroId(str(summoner["championId"])) + else: + aramInfo = None + + summonerView = SummonerInfoView(summoner, aramInfo, self) # 用 summonerId 避免空字符串 self.items[summoner["summonerId"]] = summonerView @@ -304,14 +317,14 @@ class SummonerInfoView(ColorAnimationFrame): 显示了 KDA, 召唤师名称, 经验, 头像 等信息 """ - def __init__(self, info: dict, parent=None): + def __init__(self, info: dict, aramInfo=None, parent=None): super().__init__(type='default', parent=parent) self._pressedBackgroundColor = self._hoverBackgroundColor self.hBoxLayout = QHBoxLayout(self) self.icon = RoundLevelAvatar(info['icon'], info['xpSinceLastLevel'], info['xpUntilNextLevel'], - 70, info["level"]) + 70, info["level"], aramInfo=aramInfo) self.infoVBoxLayout = QVBoxLayout() @@ -461,6 +474,9 @@ def updateTeamColor(self, team): def updateIcon(self, iconPath: str): self.icon.updateIcon(iconPath) + def updateAramInfo(self, info): + self.icon.updateAramInfo(info) + class SummonersGamesView(QFrame): diff --git a/app/view/main_window.py b/app/view/main_window.py index ade78b90..87c423be 100644 --- a/app/view/main_window.py +++ b/app/view/main_window.py @@ -22,7 +22,7 @@ from .search_interface import SearchInterface from .game_info_interface import GameInfoInterface from .auxiliary_interface import AuxiliaryInterface -from ..common.util import github, getLolClientPid, getTasklistPath, getLolClientPidSlowly +from ..common.util import github, getLolClientPid, getTasklistPath, getLolClientPidSlowly, AramHome from ..components.avatar_widget import NavigationAvatarWidget from ..components.temp_system_tray_menu import TmpSystemTrayMenu from ..common.icons import Icon @@ -467,6 +467,9 @@ async def __onLolClientStarted(self, pid): self.auxiliaryFuncInterface.autoBanChampionCard.updateCompleter() self.auxiliaryFuncInterface.lockConfigCard.loadNowMode.emit() + # 加载大乱斗buff -- By Hpero4 + aramInitT = asyncio.create_task(AramHome.checkAndUpdate()) + # ---- 240413 ---- By Hpero4 # 如果你希望 self.__onGameStatusChanged(status) 和 self.__unlockInterface() 并行执行, 可以这样使用: # t = self.__onGameStatusChanged(status) @@ -495,6 +498,7 @@ async def __onLolClientStarted(self, pid): t = self.__onGameStatusChanged(status) self.__unlockInterface() + await aramInitT await t async def __startConnector(self, pid):