diff --git a/app/common/icons.py b/app/common/icons.py
index ae394a15..05885c78 100644
--- a/app/common/icons.py
+++ b/app/common/icons.py
@@ -59,6 +59,7 @@ class Icon(FluentIconBase, Enum):
TEXTCHECK = 'TextCheck'
DOCUMENT = 'Document'
ARROWREPEAT = "ArrowRepeat"
+ QUESTION_CIRCLE = 'QuestionCircle'
def path(self, theme=Theme.AUTO):
return f'./app/resource/icons/{self.value}_{getIconColor(theme)}.svg'
diff --git a/app/components/profile_level_icon_widget.py b/app/components/profile_level_icon_widget.py
index 0358d5a3..1417f6fd 100644
--- a/app/components/profile_level_icon_widget.py
+++ b/app/components/profile_level_icon_widget.py
@@ -10,6 +10,7 @@
from app.common.qfluentwidgets import (ProgressRing, ToolTipFilter, ToolTipPosition, isDarkTheme,
themeColor, FlyoutViewBase, TextWrap, FlyoutAnimationType)
from app.components.color_label import ColorLabel
+from app.components.tool_tip import CustomToolTip
from app.common.style_sheet import StyleSheet
@@ -139,13 +140,15 @@ def updateAramInfo(self, info):
if not self.mFlyout or not info:
return
- self.mFlyout.updateInfo(info)
+ self.mFlyout.view.updateInfo(info)
def enterEvent(self, a0):
if not self.aramInfo or self.mFlyout:
return
- self.mFlyout = AramFlyout(self.aramInfo, self)
+ view = AramFlyoutView(self.aramInfo)
+
+ self.mFlyout = CustomToolTip(view, self)
self.mFlyout.show()
super().enterEvent(a0)
@@ -158,118 +161,6 @@ def leaveEvent(self, a0):
self.mFlyout = None
-class AramFlyout(QWidget):
- def __init__(self, info, target: QWidget, parent=None):
- super().__init__(parent)
- self.target = target
-
- self.hBoxLayout = QHBoxLayout(self)
- self.view = AramFlyoutView(info, parent)
- self.setWindowFlags(Qt.ToolTip | Qt.FramelessWindowHint |
- Qt.NoDropShadowWindowHint)
- self.setAttribute(Qt.WA_TranslucentBackground)
-
- self.hBoxLayout.addWidget(self.view)
- self.hBoxLayout.setContentsMargins(15, 8, 15, 20)
-
- self.__initShadowEffect()
- self.__initAnimation()
-
- def __initShadowEffect(self, blurRadius=35, offset=(0, 8)):
- color = QColor(0, 0, 0, 80 if isDarkTheme() else 30)
-
- self.shadowEffect = QGraphicsDropShadowEffect(self.view)
- self.shadowEffect.setBlurRadius(blurRadius)
- self.shadowEffect.setOffset(*offset)
- self.shadowEffect.setColor(color)
-
- self.view.setGraphicsEffect(None)
- self.view.setGraphicsEffect(self.shadowEffect)
-
- def __initAnimation(self):
- self.inOpacityAni = QPropertyAnimation(
- self, b'windowOpacity', self.parent())
- self.inSlideAni = QPropertyAnimation(self, b'pos', self.parent())
-
- self.inOpacityAni.setDuration(187)
- self.inSlideAni.setDuration(187)
-
- self.inOpacityAni.setEasingCurve(QEasingCurve.InOutQuad)
- self.inSlideAni.setEasingCurve(QEasingCurve.InOutQuad)
-
- self.inOpacityAni.setStartValue(0)
- self.inOpacityAni.setEndValue(1)
-
- self.inAniGroup = QParallelAnimationGroup(self)
- self.inAniGroup.addAnimation(self.inOpacityAni)
- self.inAniGroup.addAnimation(self.inSlideAni)
-
- self.outAniGroup = QParallelAnimationGroup(self)
-
- self.outOpacityAni = QPropertyAnimation(
- self, b'windowOpacity', self.parent())
- self.outOpacityAni.setEasingCurve(QEasingCurve.InOutQuad)
- self.outOpacityAni.setStartValue(1)
- self.outOpacityAni.setEndValue(0)
- self.outOpacityAni.setDuration(120)
-
- self.outSlideAni = QPropertyAnimation(self, b'pos', self.parent())
- self.outSlideAni.setEasingCurve(QEasingCurve.InOutQuad)
- self.outSlideAni.setDuration(120)
-
- self.outAniGroup.addAnimation(self.outOpacityAni)
- self.outAniGroup.addAnimation(self.outSlideAni)
-
- self.outAniGroup.finished.connect(self.close)
-
- def showEvent(self, e):
- pos = self.getPosition()
-
- if self.animationType == FlyoutAnimationType.SLIDE_LEFT:
- self.inSlideAni.setStartValue(pos + QPoint(10, 0))
- else:
- self.inSlideAni.setStartValue(pos - QPoint(10, 0))
-
- self.inSlideAni.setEndValue(pos)
- self.inAniGroup.start()
-
- return super().showEvent(e)
-
- def fadeOut(self):
- self.outSlideAni.setStartValue(self.pos())
-
- if self.animationType == FlyoutAnimationType.SLIDE_LEFT:
- self.outSlideAni.setEndValue(self.pos() + QPoint(10, 0))
- else:
- self.outSlideAni.setEndValue(self.pos() - QPoint(10, 0))
-
- self.outAniGroup.finished.connect(self.close)
- self.outAniGroup.start()
-
- def getPosition(self):
- pos = self.target.mapToGlobal(QPoint())
- x, y = pos.x(), pos.y()
-
- hintWidth = self.sizeHint().width()
- hintHeight = self.sizeHint().height()
-
- x += self.target.width() // 2 - hintWidth // 2
- y += self.target.height() // 2 - hintHeight // 2
-
- dx = -hintWidth // 2 - 45
-
- self.animationType = FlyoutAnimationType.SLIDE_LEFT
-
- if x + dx < -15:
- self.animationType = FlyoutAnimationType.SLIDE_RIGHT
- dx = -dx
-
- return QPoint(x + dx, y)
-
- def updateInfo(self, info):
- self.view.updateInfo(info)
-
-
class AramFlyoutView(FlyoutViewBase):
def __init__(self, info, parent=None):
super().__init__(parent=parent)
diff --git a/app/components/tool_tip.py b/app/components/tool_tip.py
new file mode 100644
index 00000000..241f5494
--- /dev/null
+++ b/app/components/tool_tip.py
@@ -0,0 +1,147 @@
+
+from PyQt5.QtCore import (
+ Qt, QPoint, QPropertyAnimation, QParallelAnimationGroup, QEasingCurve,
+ QSize)
+from PyQt5.QtGui import QColor
+from PyQt5.QtWidgets import (QWidget, QHBoxLayout,
+ QGraphicsDropShadowEffect)
+
+from app.common.qfluentwidgets import (isDarkTheme, TransparentToolButton,
+ FlyoutAnimationType, FluentIcon)
+from app.common.icons import Icon
+
+
+class CustomToolTip(QWidget):
+ def __init__(self, view: QWidget, target: QWidget, parent=None):
+ super().__init__(parent)
+ self.target = target
+
+ self.hBoxLayout = QHBoxLayout(self)
+ self.view = view
+ self.setWindowFlags(Qt.ToolTip | Qt.FramelessWindowHint |
+ Qt.NoDropShadowWindowHint)
+ self.setAttribute(Qt.WA_TranslucentBackground)
+
+ self.hBoxLayout.addWidget(self.view)
+ self.hBoxLayout.setContentsMargins(15, 8, 15, 20)
+
+ self.__initShadowEffect()
+ self.__initAnimation()
+
+ def __initShadowEffect(self, blurRadius=35, offset=(0, 8)):
+ color = QColor(0, 0, 0, 80 if isDarkTheme() else 30)
+
+ self.shadowEffect = QGraphicsDropShadowEffect(self.view)
+ self.shadowEffect.setBlurRadius(blurRadius)
+ self.shadowEffect.setOffset(*offset)
+ self.shadowEffect.setColor(color)
+
+ self.view.setGraphicsEffect(None)
+ self.view.setGraphicsEffect(self.shadowEffect)
+
+ def __initAnimation(self):
+ self.inOpacityAni = QPropertyAnimation(
+ self, b'windowOpacity', self.parent())
+ self.inSlideAni = QPropertyAnimation(self, b'pos', self.parent())
+
+ self.inOpacityAni.setDuration(187)
+ self.inSlideAni.setDuration(187)
+
+ self.inOpacityAni.setEasingCurve(QEasingCurve.InOutQuad)
+ self.inSlideAni.setEasingCurve(QEasingCurve.InOutQuad)
+
+ self.inOpacityAni.setStartValue(0)
+ self.inOpacityAni.setEndValue(1)
+
+ self.inAniGroup = QParallelAnimationGroup(self)
+ self.inAniGroup.addAnimation(self.inOpacityAni)
+ self.inAniGroup.addAnimation(self.inSlideAni)
+
+ self.outAniGroup = QParallelAnimationGroup(self)
+
+ self.outOpacityAni = QPropertyAnimation(
+ self, b'windowOpacity', self.parent())
+ self.outOpacityAni.setEasingCurve(QEasingCurve.InOutQuad)
+ self.outOpacityAni.setStartValue(1)
+ self.outOpacityAni.setEndValue(0)
+ self.outOpacityAni.setDuration(120)
+
+ self.outSlideAni = QPropertyAnimation(self, b'pos', self.parent())
+ self.outSlideAni.setEasingCurve(QEasingCurve.InOutQuad)
+ self.outSlideAni.setDuration(120)
+
+ self.outAniGroup.addAnimation(self.outOpacityAni)
+ self.outAniGroup.addAnimation(self.outSlideAni)
+
+ self.outAniGroup.finished.connect(self.close)
+
+ def showEvent(self, e):
+ pos = self.getPosition()
+
+ if self.animationType == FlyoutAnimationType.SLIDE_LEFT:
+ self.inSlideAni.setStartValue(pos + QPoint(10, 0))
+ else:
+ self.inSlideAni.setStartValue(pos - QPoint(10, 0))
+
+ self.inSlideAni.setEndValue(pos)
+ self.inAniGroup.start()
+
+ return super().showEvent(e)
+
+ def fadeOut(self):
+ self.outSlideAni.setStartValue(self.pos())
+
+ if self.animationType == FlyoutAnimationType.SLIDE_LEFT:
+ self.outSlideAni.setEndValue(self.pos() + QPoint(10, 0))
+ else:
+ self.outSlideAni.setEndValue(self.pos() - QPoint(10, 0))
+
+ self.outAniGroup.finished.connect(self.close)
+ self.outAniGroup.start()
+
+ def getPosition(self):
+ pos = self.target.mapToGlobal(QPoint())
+ x, y = pos.x(), pos.y()
+
+ hintWidth = self.sizeHint().width()
+ hintHeight = self.sizeHint().height()
+
+ x += self.target.width() // 2 - hintWidth // 2
+ y += self.target.height() // 2 - hintHeight // 2
+
+ dx = -hintWidth // 2 - 45
+
+ self.animationType = FlyoutAnimationType.SLIDE_LEFT
+
+ if x + dx < -15:
+ self.animationType = FlyoutAnimationType.SLIDE_RIGHT
+ dx = -dx
+
+ return QPoint(x + dx, y)
+
+
+class HelpButton(TransparentToolButton):
+ def __init__(self, view: QWidget, parent: QWidget = None):
+ super().__init__(Icon.QUESTION_CIRCLE, parent=parent)
+
+ self.setFixedSize(QSize(26, 26))
+ self.setFixedSize(QSize(16, 16))
+
+ self.view = view
+ self.mToolTip = None
+
+ def enterEvent(self, e):
+ if self.mToolTip:
+ return
+
+ self.mToolTip = CustomToolTip(self.view, self)
+ self.mToolTip.show()
+
+ return super().enterEvent(e)
+
+ def leaveEvent(self, a0):
+ if not self.mToolTip:
+ return
+
+ self.mToolTip.fadeOut()
+ self.mToolTip = None
diff --git a/app/resource/i18n/Seraphine.zh_CN.qm b/app/resource/i18n/Seraphine.zh_CN.qm
index 352ef0eb..eb57fc63 100644
Binary files a/app/resource/i18n/Seraphine.zh_CN.qm and b/app/resource/i18n/Seraphine.zh_CN.qm differ
diff --git a/app/resource/i18n/Seraphine.zh_CN.ts b/app/resource/i18n/Seraphine.zh_CN.ts
index c92abb2b..714b529e 100644
--- a/app/resource/i18n/Seraphine.zh_CN.ts
+++ b/app/resource/i18n/Seraphine.zh_CN.ts
@@ -42,37 +42,37 @@
AramFlyoutView
-
+
造成伤害:
-
+
承受伤害:
-
+
治疗效果:
-
+
护盾效果:
-
+
技能急速:
-
+
韧性:
-
+
数据来源:jddld.com
@@ -141,12 +141,12 @@
已启用,自动禁用:
-
+
未启用
-
+
启用自动 Ban:
@@ -156,70 +156,79 @@
若队友预选该英雄,则空 Ban:
-
+
在进入禁用阶段后 Ban 人的秒数:
-
+
默认设置
-
+
默认禁用英雄:
-
+
选择
-
+
按照位置设置
-
+
上路:
-
+
打野:
-
+
中路:
-
+
下路:
-
+
辅助:
-
+
若队友预选该英雄,则空 Ban:
-
+
恢复默认
-
+
已启用
+
+
+
+ 必须设置默认英雄
+
+若非排位模式或按位置设置英雄不可用,则将使用默认设置
+
AutoSelectChampionCard
@@ -234,7 +243,7 @@
已启用,自动选择:
-
+
未启用
@@ -244,7 +253,7 @@
将要自动亮起的英雄:
-
+
启用自动亮起:
@@ -254,7 +263,7 @@
在时间结束后确定选择(更换亮起英雄后无效)
-
+
在时间结束时确定选择:
@@ -279,55 +288,64 @@
默认设置
-
+
默认亮起英雄:
-
+
选择
-
+
按照位置设置
-
+
上路:
-
+
打野:
-
+
中路:
-
+
下路:
-
+
辅助:
-
+
已启用
-
+
恢复默认
+
+
+
+ 必须设置默认英雄
+
+若非排位模式或按位置设置英雄不可用,则将使用默认设置
+
AuxiliaryInterface
@@ -941,17 +959,17 @@
GameTab
-
+
重开
-
+
胜利
-
+
失败
@@ -1142,7 +1160,7 @@
对局信息
-
+
启动游戏
@@ -1162,12 +1180,12 @@
客户端已连接
-
+
路径非法
-
+
请在设置页面中设置正确的 LOL 客户端路径
@@ -1177,52 +1195,52 @@
启动页
-
+
启动客户端成功
-
+
游戏大厅
-
+
英雄选择
-
+
游戏中
-
+
等待游戏结果
-
+
游戏结束
-
+
房间组队中
-
+
匹配确认
-
+
匹配中
-
+
程序出现异常 😥
@@ -1232,12 +1250,12 @@
战绩查询 👀
-
+
直接退出
-
+
最小化到任务栏
@@ -1247,7 +1265,7 @@
退出
-
+
你第一次点击了关闭按钮
@@ -1288,17 +1306,17 @@
客户端信息请求失败
-
+
蓝色方
-
+
红色方
-
+
等待重新连接
@@ -1338,22 +1356,22 @@
请确保能连接至 GitHub
-
+
(
-
+
)
-
+
,
-
+
请选择点击关闭按钮的默认行为
@@ -1983,82 +2001,82 @@
客户端路径
-
+
自动启动游戏
-
+
启动 Seraphine 时自动启动 LOL 客户端
-
+
个性化
-
+
应用主题
-
+
调整 Seraphine 的外观主题
-
+
浅色
-
+
深色
-
+
跟随系统设置
-
+
主题色
-
+
调整 Seraphine 的主题色
-
+
界面缩放
-
+
调整部件和字体的大小
-
+
更新成功
-
+
设置在重启软件后生效
-
+
语言
-
+
选择 Seraphine 所使用的语言
@@ -2089,52 +2107,52 @@
在对局详情界面中显示段位图标,启动该选项将影响加载该界面的速度
-
+
关于
-
+
提供反馈
-
+
通过提供反馈帮助我们改善 Seraphine
-
+
版权所有
-
+
当前版本
-
+
删除
-
+
清除缓存
-
+
删除所有游戏资源的缓存(建议在游戏资源有更新时使用)
-
+
查看 GitHub
-
+
真的要删除吗?
@@ -2146,32 +2164,32 @@
这有可能会消耗更多的时间
-
+
确定删除
-
+
云母效果
-
+
窗口和表面显示半透明(仅在 Win11 上可用)
-
+
最小化到任务栏托盘
-
+
点击右上角关闭时将程序最小化到托盘
-
+
设置已应用
@@ -2186,12 +2204,12 @@
打开此选项后,当你在排位时,对局信息界面将只显示排位模式对局战绩
-
+
检查更新
-
+
在 Seraphine 启动时自动检查更新
@@ -2203,20 +2221,20 @@
- 游戏进行时最小化 Seraphine 窗口
+ 游戏进行时最小化 Seraphine 窗口
- 在游戏时通过避免渲染窗口以减少 CPU 使用
+ 在游戏时通过避免渲染窗口以减少 CPU 使用
-
+
日志等级
-
+
修改 Seraphine 记录日志的等级(重启后生效)
@@ -2226,12 +2244,12 @@
HTTP 代理
-
+
连接 GitHub 时启用 HTTP 代理
-
+
软件更新
@@ -2251,17 +2269,17 @@
该值越大数据加载速度越快,但越可能引起客户端闪退
-
+
对局卡片颜色
-
+
改变对局卡片提示胜利 / 失败的颜色
-
+
HTTP 代理
@@ -2271,22 +2289,22 @@
在对局详情界面中显示段位图标,启动该选项将影响加载该界面的速度
-
+
打开文件夹
-
+
日志文件
-
+
打开日志文件夹
-
+
游戏资源将会在它们要被 Seraphine 使用时重新下载
@@ -2425,12 +2443,12 @@ when they are used by Seraphine, which will cost more time
SummonerInfoView
-
+
单 / 双排
-
+
灵活排位
diff --git a/app/resource/icons/QuestionCircle_black.svg b/app/resource/icons/QuestionCircle_black.svg
new file mode 100644
index 00000000..bcf8c728
--- /dev/null
+++ b/app/resource/icons/QuestionCircle_black.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/app/resource/icons/QuestionCircle_white.svg b/app/resource/icons/QuestionCircle_white.svg
new file mode 100644
index 00000000..e910b09d
--- /dev/null
+++ b/app/resource/icons/QuestionCircle_white.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/app/view/auxiliary_interface.py b/app/view/auxiliary_interface.py
index 81272bff..09d4a999 100644
--- a/app/view/auxiliary_interface.py
+++ b/app/view/auxiliary_interface.py
@@ -9,7 +9,7 @@
qconfig, IndicatorPosition, InfoBar, InfoBarPosition,
SpinBox, ExpandGroupSettingCard, TransparentToolButton,
FluentIcon, Flyout, FlyoutAnimationType, TeachingTip,
- MessageBox, CheckBox)
+ MessageBox, CheckBox, ToolTipFilter, ToolTipPosition)
from PyQt5.QtCore import Qt, pyqtSignal, QEvent, QSize
from PyQt5.QtWidgets import (QWidget, QLabel, QCompleter, QVBoxLayout, QHBoxLayout, QGridLayout,
@@ -1208,6 +1208,8 @@ def __init__(self, title, content=None,
self.defaultCfgWidget = QWidget(self.view)
self.defaultCfgLayout = QGridLayout(self.defaultCfgWidget)
self.defaultHintLabel = QLabel(self.tr("Default Configurations"))
+ self.helpLayout = QHBoxLayout()
+ self.helpButotn = TransparentToolButton(Icon.QUESTION_CIRCLE)
self.defaultLabel = QLabel(self.tr("Default champions: "))
self.defaultChampions = ChampionsCard()
@@ -1251,6 +1253,14 @@ def __initWidget(self):
self.defaultHintLabel.setStyleSheet("font: bold")
self.rankLabel.setStyleSheet("font: bold")
+ self.helpButotn.setFixedSize(QSize(26, 26))
+ self.helpButotn.setIconSize(QSize(16, 16))
+
+ self.helpButotn.setToolTip(self.tr(
+ "Default settings must be set.\n\nIf champions set by lane are not available, default settings will be used."))
+ self.helpButotn.installEventFilter(ToolTipFilter(
+ self.helpButotn, 0, ToolTipPosition.RIGHT))
+
# 逻辑是,必须要设置默认,才能设置具体分路和启动功能
selected = qconfig.get(self.defaultChampionsConfigItem) != []
checked = qconfig.get(self.enableConfigItem)
@@ -1286,8 +1296,13 @@ def __initLayout(self):
self.defaultCfgLayout.setContentsMargins(48, 18, 44, 18)
self.defaultCfgLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize)
- self.defaultCfgLayout.addWidget(
- self.defaultHintLabel, 0, 0, Qt.AlignLeft)
+ self.helpLayout.setContentsMargins(0, 0, 0, 0)
+ self.helpLayout.setSpacing(10)
+ self.helpLayout.addWidget(self.defaultHintLabel)
+ self.helpLayout.addWidget(self.helpButotn)
+
+ self.defaultCfgLayout.addLayout(
+ self.helpLayout, 0, 0, Qt.AlignLeft)
self.defaultCfgLayout.addWidget(
self.defaultLabel, 1, 0, Qt.AlignLeft)
@@ -1457,6 +1472,8 @@ def __init__(self, title, content=None,
self.defaultCfgWidget = QWidget(self.view)
self.defaultCfgLayout = QGridLayout(self.defaultCfgWidget)
self.defaultHintLabel = QLabel(self.tr("Default Configurations"))
+ self.helpLayout = QHBoxLayout()
+ self.helpButotn = TransparentToolButton(Icon.QUESTION_CIRCLE)
self.defaultLabel = QLabel(self.tr("Default champions: "))
self.defaultChampions = ChampionsCard()
@@ -1508,6 +1525,14 @@ def __initWidget(self):
delayTime = qconfig.get(self.delayTimeConfigItem)
friendlyEnabled = qconfig.get(self.friendlyConfigItem)
+ self.helpButotn.setFixedSize(QSize(26, 26))
+ self.helpButotn.setIconSize(QSize(16, 16))
+
+ self.helpButotn.setToolTip(self.tr(
+ "Default settings must be set.\n\nIf champions set by lane are not available, default settings will be used."))
+ self.helpButotn.installEventFilter(ToolTipFilter(
+ self.helpButotn, 0, ToolTipPosition.RIGHT))
+
for ty in ['default', 'top', 'jug', 'mid', 'bot', 'sup']:
button: PushButton = getattr(self, f"{ty}SelectButton")
button.setMinimumWidth(100)
@@ -1545,8 +1570,13 @@ def __initLayout(self):
self.defaultCfgLayout.setContentsMargins(48, 18, 44, 18)
self.defaultCfgLayout.setSizeConstraint(QHBoxLayout.SetMinimumSize)
- self.defaultCfgLayout.addWidget(
- self.defaultHintLabel, 0, 0, Qt.AlignLeft)
+ self.helpLayout.setContentsMargins(0, 0, 0, 0)
+ self.helpLayout.setSpacing(10)
+ self.helpLayout.addWidget(self.defaultHintLabel)
+ self.helpLayout.addWidget(self.helpButotn)
+
+ self.defaultCfgLayout.addLayout(
+ self.helpLayout, 0, 0, Qt.AlignLeft)
self.defaultCfgLayout.addWidget(
self.defaultLabel, 1, 0, Qt.AlignLeft)