mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-06-17 23:13:03 +08:00
feat(gui): 引入全局设置窗口 ALSettingsWidget
- 新增 ALSettingsWidget,左侧导航+右侧内容的设置面板 - 合并外观主题、界面风格、自定义QSS为单页布局 - 深浅色主题通过 Qt.ColorScheme 官方 API 实现 - 界面风格变更检测基于当前运行的 QStyle 比对 - 使用 qtawesome 提供矢量导航图标 - 风格变更时弹出重启确认对话框 - ALAutoScriptEditDialog 中重置/复制按钮改用 qtawesome 图标 - 外观初始化迁移至 boot.AppInitializer - 菜单栏新增工具→全局设置入口 - GLOBAL 配置扩展 appearance 段(theme/style/custom_qss) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -24,7 +24,6 @@ def main():
|
||||
translator = QTranslator()
|
||||
if translator.load(":/res/translators/qtbase_zh_CN.ts"):
|
||||
app.installTranslator(translator)
|
||||
app.setStyle("Fusion")
|
||||
app.setApplicationName("AutoLibrary")
|
||||
if not initializeApp():
|
||||
sys.exit(-1)
|
||||
|
||||
@@ -10,10 +10,13 @@ See the LICENSE file for details.
|
||||
import os
|
||||
|
||||
from PySide6.QtCore import QStandardPaths, QDir
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
from managers.log.LogManager import instance as logInstance
|
||||
from gui.ALSettingsWidget import _applyTheme
|
||||
from interfaces.ConfigProvider import CfgKey
|
||||
from managers.config.ConfigManager import instance as configInstance
|
||||
from managers.driver.WebDriverManager import instance as webdriverInstance
|
||||
from managers.log.LogManager import instance as logInstance
|
||||
|
||||
|
||||
def _initializeLogManager(
|
||||
@@ -64,13 +67,25 @@ def _initializeWebDriverManager(
|
||||
webdriverInstance(driver_dir)
|
||||
return True
|
||||
|
||||
def _initializeAppearance(
|
||||
):
|
||||
|
||||
app = QApplication.instance()
|
||||
if not app:
|
||||
return
|
||||
cfg = configInstance()
|
||||
saved_style = cfg.get(CfgKey.GLOBAL.APPEARANCE.STYLE, "Fusion")
|
||||
saved_theme = cfg.get(CfgKey.GLOBAL.APPEARANCE.THEME, "system")
|
||||
app.setStyle(saved_style)
|
||||
_applyTheme(saved_theme)
|
||||
|
||||
def initializeApp(
|
||||
) -> bool:
|
||||
"""
|
||||
Initialize the application components
|
||||
|
||||
Order:
|
||||
LogManager -> ConfigManager -> WebDriverManager
|
||||
LogManager -> ConfigManager -> WebDriverManager -> Appearance
|
||||
"""
|
||||
|
||||
if not _initializeLogManager():
|
||||
@@ -79,4 +94,5 @@ def initializeApp(
|
||||
return False
|
||||
if not _initializeWebDriverManager():
|
||||
return False
|
||||
_initializeAppearance()
|
||||
return True
|
||||
|
||||
@@ -9,6 +9,8 @@ See the LICENSE file for details.
|
||||
"""
|
||||
from copy import deepcopy
|
||||
|
||||
import qtawesome as qta
|
||||
|
||||
from PySide6.QtCore import (
|
||||
QDate,
|
||||
QSize,
|
||||
@@ -20,7 +22,6 @@ from PySide6.QtCore import (
|
||||
from PySide6.QtGui import (
|
||||
QColor,
|
||||
QFont,
|
||||
QIcon,
|
||||
QSyntaxHighlighter,
|
||||
QTextCharFormat,
|
||||
)
|
||||
@@ -215,8 +216,8 @@ class ALAutoScriptEditDialog(QDialog):
|
||||
self.ZoomOutBtn = QPushButton("-")
|
||||
self.ZoomOutBtn.setFixedSize(25, 25)
|
||||
self.ZoomResetBtn = QPushButton("")
|
||||
self.ZoomResetBtn.setIcon(QIcon(":/res/icons/Reset.svg"))
|
||||
self.ZoomResetBtn.setIconSize(QSize(20, 20))
|
||||
self.ZoomResetBtn.setIcon(qta.icon("fa5s.undo", color=self._iconColor()))
|
||||
self.ZoomResetBtn.setIconSize(QSize(14, 14))
|
||||
self.ZoomResetBtn.setFixedSize(25, 25)
|
||||
self.ZoomResetBtn.setToolTip("重置缩放")
|
||||
self.ZoomLabel = QLabel(f"{self._fontSize}px")
|
||||
@@ -240,8 +241,8 @@ class ALAutoScriptEditDialog(QDialog):
|
||||
ToolbarLayout.addWidget(self.ZoomLabel)
|
||||
ToolbarLayout.addStretch()
|
||||
self.CopyBtn = QPushButton("")
|
||||
self.CopyBtn.setIcon(QIcon(":/res/icons/Copy.svg"))
|
||||
self.CopyBtn.setIconSize(QSize(20, 20))
|
||||
self.CopyBtn.setIcon(qta.icon("fa5s.copy", color=self._iconColor()))
|
||||
self.CopyBtn.setIconSize(QSize(14, 14))
|
||||
self.CopyBtn.setFixedSize(25, 25)
|
||||
self.CopyBtn.setToolTip("复制脚本")
|
||||
ToolbarLayout.addWidget(self.CopyBtn)
|
||||
@@ -537,6 +538,14 @@ class ALAutoScriptEditDialog(QDialog):
|
||||
else:
|
||||
widget.setText(str(value))
|
||||
|
||||
def _iconColor(
|
||||
self
|
||||
) -> str:
|
||||
|
||||
return QApplication.instance().palette().color(
|
||||
QApplication.instance().palette().ColorRole.WindowText
|
||||
).name()
|
||||
|
||||
def connectSignals(
|
||||
self
|
||||
):
|
||||
|
||||
+31
-1
@@ -33,6 +33,7 @@ from PySide6.QtWidgets import (
|
||||
from base.MsgBase import MsgBase
|
||||
from gui.ALAboutDialog import ALAboutDialog
|
||||
from gui.ALConfigWidget import ALConfigWidget
|
||||
from gui.ALSettingsWidget import ALSettingsWidget
|
||||
from gui.ALMainWorkers import (
|
||||
AutoLibWorker,
|
||||
TimerTaskWorker
|
||||
@@ -60,6 +61,7 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
|
||||
self.__config_paths = ConfigUtils.getAutomationConfigPaths()
|
||||
self.__alTimerTaskManageWidget = None
|
||||
self.__alConfigWidget = None
|
||||
self.__alSettingsWidget = None
|
||||
self.__auto_lib_thread = None
|
||||
self.__current_timer_task_thread = None
|
||||
self.__is_running_timer_task = False
|
||||
@@ -81,6 +83,7 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
|
||||
self.MessageIOTextEdit.setFont(QFont("Courier New", 10))
|
||||
self.ManualAction.triggered.connect(self.onManualActionTriggered)
|
||||
self.AboutAction.triggered.connect(self.onAboutActionTriggered)
|
||||
self.SettingsAction.triggered.connect(self.onSettingsActionTriggered)
|
||||
|
||||
# initialize timer task widget, but not show it
|
||||
try:
|
||||
@@ -125,7 +128,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
|
||||
return
|
||||
self.TrayIcon = QSystemTrayIcon(self.Icon, self)
|
||||
self.TrayIcon.setToolTip("AutoLibrary")
|
||||
|
||||
self.TrayMenu = QMenu()
|
||||
self.TrayMenu.addAction("显示主窗口", self.showNormal)
|
||||
self.TrayMenu.addAction("显示定时窗口", self.onTimerTaskManageWidgetButtonClicked)
|
||||
@@ -190,6 +192,9 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
|
||||
if self.__alConfigWidget:
|
||||
self.__alConfigWidget.close()
|
||||
# the config widget is already deleted in the 'self.onConfigWidgetClosed'
|
||||
if self.__alSettingsWidget:
|
||||
self.__alSettingsWidget.close()
|
||||
# the settings widget is already deleted in the 'self.onSettingsWidgetClosed'
|
||||
self._showLog("主窗口关闭")
|
||||
QMainWindow.closeEvent(self, event)
|
||||
|
||||
@@ -302,6 +307,31 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
|
||||
self.setControlButtons(True, None, None)
|
||||
self._showLog("配置窗口已关闭,配置文件路径已更新")
|
||||
|
||||
@Slot()
|
||||
def onSettingsWidgetClosed(
|
||||
self
|
||||
):
|
||||
|
||||
if self.__alSettingsWidget:
|
||||
self.__alSettingsWidget.settingsWidgetIsClosed.disconnect(self.onSettingsWidgetClosed)
|
||||
self.__alSettingsWidget.deleteLater()
|
||||
self.__alSettingsWidget = None
|
||||
self.SettingsAction.setEnabled(True)
|
||||
|
||||
@Slot()
|
||||
def onSettingsActionTriggered(
|
||||
self
|
||||
):
|
||||
|
||||
if self.__alSettingsWidget is None:
|
||||
self.__alSettingsWidget = ALSettingsWidget(self)
|
||||
self.__alSettingsWidget.settingsWidgetIsClosed.connect(self.onSettingsWidgetClosed)
|
||||
self.__alSettingsWidget.show()
|
||||
self.__alSettingsWidget.raise_()
|
||||
self.__alSettingsWidget.activateWindow()
|
||||
self.SettingsAction.setEnabled(False)
|
||||
self._showLog("打开全局设置窗口")
|
||||
|
||||
@Slot(dict)
|
||||
def onTimerTaskIsReady(
|
||||
self,
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Copyright (c) 2026 KenanZhu.
|
||||
All rights reserved.
|
||||
|
||||
This software is provided "as is", without any warranty of any kind.
|
||||
You may use, modify, and distribute this file under the terms of the MIT License.
|
||||
See the LICENSE file for details.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import qtawesome as qta
|
||||
|
||||
from PySide6.QtCore import (
|
||||
QProcess,
|
||||
Qt,
|
||||
Signal,
|
||||
Slot
|
||||
)
|
||||
from PySide6.QtGui import (
|
||||
QCloseEvent,
|
||||
QShowEvent
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QFileDialog,
|
||||
QMessageBox,
|
||||
QStyle,
|
||||
QStyleFactory,
|
||||
QWidget
|
||||
)
|
||||
|
||||
import managers.config.ConfigManager as ConfigManager
|
||||
|
||||
from gui.resources.ui.Ui_ALSettingsWidget import Ui_ALSettingsWidget
|
||||
from interfaces.ConfigProvider import (
|
||||
CfgKey,
|
||||
ConfigProvider
|
||||
)
|
||||
|
||||
|
||||
def _clearQss(
|
||||
):
|
||||
|
||||
app : QApplication | None = QApplication.instance()
|
||||
if app:
|
||||
app.setStyleSheet("")
|
||||
|
||||
def _loadQss(
|
||||
file_path: str
|
||||
) -> str:
|
||||
|
||||
if not file_path or not os.path.isfile(file_path):
|
||||
return ""
|
||||
try:
|
||||
with open(file_path, "r", encoding="utf-8") as fh:
|
||||
return fh.read()
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
def _applyQss(
|
||||
file_path: str
|
||||
):
|
||||
|
||||
app : QApplication | None = QApplication.instance()
|
||||
if not app:
|
||||
return
|
||||
qss = _loadQss(file_path)
|
||||
if qss:
|
||||
app.setStyleSheet(qss)
|
||||
else:
|
||||
_clearQss()
|
||||
|
||||
def _applyTheme(
|
||||
theme: str
|
||||
):
|
||||
|
||||
app : QApplication | None = QApplication.instance()
|
||||
if not app:
|
||||
return
|
||||
if theme == "dark":
|
||||
app.styleHints().setColorScheme(Qt.ColorScheme.Dark)
|
||||
elif theme == "light":
|
||||
app.styleHints().setColorScheme(Qt.ColorScheme.Light)
|
||||
else:
|
||||
app.styleHints().setColorScheme(Qt.ColorScheme.Unknown)
|
||||
app.setStyle(QStyleFactory.create(app.style().objectName()))
|
||||
|
||||
def _restartApp(
|
||||
):
|
||||
|
||||
QApplication.instance().quit()
|
||||
QProcess.startDetached(sys.executable, sys.argv)
|
||||
|
||||
|
||||
class ALSettingsWidget(QWidget, Ui_ALSettingsWidget):
|
||||
|
||||
settingsWidgetIsClosed = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent=None
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.__cfg_mgr: ConfigProvider = ConfigManager.instance()
|
||||
self.__original_style: QStyle | None = None
|
||||
|
||||
self.setupUi(self)
|
||||
self.modifyUi()
|
||||
self.connectSignals()
|
||||
self.loadSettings()
|
||||
|
||||
def modifyUi(
|
||||
self
|
||||
):
|
||||
|
||||
self.setWindowFlags(Qt.WindowType.Window)
|
||||
self.NavigationList.setCurrentRow(0)
|
||||
self.populateStyles()
|
||||
self.setNavigationIcons()
|
||||
|
||||
def setNavigationIcons(
|
||||
self
|
||||
):
|
||||
|
||||
app : QApplication | None = QApplication.instance()
|
||||
color = app.palette().color(app.palette().ColorRole.WindowText).name()
|
||||
item = self.NavigationList.item(0)
|
||||
if item:
|
||||
item.setIcon(qta.icon("fa5s.palette", color=color))
|
||||
|
||||
def populateStyles(
|
||||
self
|
||||
):
|
||||
|
||||
self.StyleComboBox.clear()
|
||||
self.StyleComboBox.addItems(QStyleFactory.keys())
|
||||
|
||||
def connectSignals(
|
||||
self
|
||||
):
|
||||
|
||||
self.BrowseQssButton.clicked.connect(self.onBrowseQssButtonClicked)
|
||||
self.ApplyQssButton.clicked.connect(self.onApplyQssButtonClicked)
|
||||
self.ResetQssButton.clicked.connect(self.onResetQssButtonClicked)
|
||||
self.CancelButton.clicked.connect(self.onCancelButtonClicked)
|
||||
self.ApplyButton.clicked.connect(self.onApplyButtonClicked)
|
||||
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
|
||||
|
||||
def showEvent(
|
||||
self,
|
||||
event: QShowEvent
|
||||
):
|
||||
|
||||
result = super().showEvent(event)
|
||||
screen_rect = self.screen().geometry()
|
||||
target_pos = self.parent().geometry().center()
|
||||
target_pos.setX(target_pos.x() - self.width()//2)
|
||||
target_pos.setY(target_pos.y() - self.height()//2)
|
||||
if target_pos.x() < 0:
|
||||
target_pos.setX(0)
|
||||
if target_pos.x() + self.width() > screen_rect.width():
|
||||
target_pos.setX(screen_rect.width() - self.width())
|
||||
if target_pos.y() < 0:
|
||||
target_pos.setY(0)
|
||||
if target_pos.y() + self.height() > screen_rect.height():
|
||||
target_pos.setY(screen_rect.height() - self.height())
|
||||
self.move(target_pos)
|
||||
return result
|
||||
|
||||
def closeEvent(
|
||||
self,
|
||||
event: QCloseEvent
|
||||
):
|
||||
|
||||
self.settingsWidgetIsClosed.emit()
|
||||
super().closeEvent(event)
|
||||
|
||||
def loadSettings(
|
||||
self
|
||||
):
|
||||
|
||||
theme = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.THEME, "system")
|
||||
style = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.STYLE, "Fusion")
|
||||
custom_qss = self.__cfg_mgr.get(CfgKey.GLOBAL.APPEARANCE.CUSTOM_QSS, "")
|
||||
self.__original_style = QApplication.instance().style()
|
||||
if theme == "light":
|
||||
self.LightThemeRadio.setChecked(True)
|
||||
elif theme == "dark":
|
||||
self.DarkThemeRadio.setChecked(True)
|
||||
else:
|
||||
self.SystemThemeRadio.setChecked(True)
|
||||
index = self.StyleComboBox.findText(style)
|
||||
if index >= 0:
|
||||
self.StyleComboBox.setCurrentIndex(index)
|
||||
else:
|
||||
self.StyleComboBox.setCurrentIndex(0)
|
||||
self.QssPathEdit.setText(custom_qss)
|
||||
self.updateQssStatus(custom_qss)
|
||||
|
||||
def updateQssStatus(
|
||||
self,
|
||||
qss_path: str
|
||||
):
|
||||
|
||||
if qss_path and os.path.isfile(qss_path):
|
||||
self.QssStatusLabel.setText(f"已加载自定义样式文件:{qss_path}")
|
||||
else:
|
||||
self.QssStatusLabel.setText("当前使用程序默认外观。")
|
||||
|
||||
def collectSettings(
|
||||
self
|
||||
):
|
||||
|
||||
if self.LightThemeRadio.isChecked():
|
||||
theme = "light"
|
||||
elif self.DarkThemeRadio.isChecked():
|
||||
theme = "dark"
|
||||
else:
|
||||
theme = "system"
|
||||
style = QStyleFactory.create(self.StyleComboBox.currentText())
|
||||
custom_qss = self.QssPathEdit.text().strip()
|
||||
return theme, style, custom_qss
|
||||
|
||||
def saveAndApply(
|
||||
self
|
||||
):
|
||||
|
||||
theme, style, custom_qss = self.collectSettings()
|
||||
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.THEME, theme)
|
||||
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.STYLE, style.name())
|
||||
self.__cfg_mgr.set(CfgKey.GLOBAL.APPEARANCE.CUSTOM_QSS, custom_qss)
|
||||
if custom_qss and os.path.isfile(custom_qss):
|
||||
_applyQss(custom_qss)
|
||||
else:
|
||||
_clearQss()
|
||||
_applyTheme(theme)
|
||||
self.setNavigationIcons()
|
||||
self.updateQssStatus(custom_qss)
|
||||
self.__original_style = QApplication.instance().style()
|
||||
|
||||
def maybeRestart(
|
||||
self
|
||||
) -> bool:
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"提示 - AutoLibrary",
|
||||
"界面风格已修改,需要重启程序才能生效。是否立即重启?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes
|
||||
)
|
||||
if reply == QMessageBox.Yes:
|
||||
_restartApp()
|
||||
return True
|
||||
return False
|
||||
|
||||
@Slot()
|
||||
def onBrowseQssButtonClicked(
|
||||
self
|
||||
):
|
||||
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"选择 QSS 样式文件 - AutoLibrary",
|
||||
self.QssPathEdit.text(),
|
||||
"QSS 样式表文件 (*.qss);;所有文件 (*)"
|
||||
)
|
||||
if file_path:
|
||||
self.QssPathEdit.setText(file_path)
|
||||
|
||||
@Slot()
|
||||
def onApplyQssButtonClicked(
|
||||
self
|
||||
):
|
||||
|
||||
qss_path = self.QssPathEdit.text().strip()
|
||||
if not qss_path:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"提示 - AutoLibrary",
|
||||
"请先选择或输入 QSS 样式表文件路径。"
|
||||
)
|
||||
return
|
||||
if not os.path.isfile(qss_path):
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"警告 - AutoLibrary",
|
||||
f"未找到指定的样式文件:\n{qss_path}"
|
||||
)
|
||||
return
|
||||
_applyQss(qss_path)
|
||||
self.updateQssStatus(qss_path)
|
||||
|
||||
@Slot()
|
||||
def onResetQssButtonClicked(
|
||||
self
|
||||
):
|
||||
|
||||
self.QssPathEdit.clear()
|
||||
_clearQss()
|
||||
if self.LightThemeRadio.isChecked():
|
||||
_applyTheme("light")
|
||||
elif self.DarkThemeRadio.isChecked():
|
||||
_applyTheme("dark")
|
||||
else:
|
||||
_applyTheme("system")
|
||||
self.setNavigationIcons()
|
||||
self.updateQssStatus("")
|
||||
|
||||
@Slot()
|
||||
def onCancelButtonClicked(
|
||||
self
|
||||
):
|
||||
|
||||
self.close()
|
||||
|
||||
@Slot()
|
||||
def onApplyButtonClicked(
|
||||
self
|
||||
):
|
||||
|
||||
_, style, _ = self.collectSettings()
|
||||
style_changed = self.__original_style.name() != style.name()
|
||||
self.saveAndApply()
|
||||
if style_changed:
|
||||
self.maybeRestart()
|
||||
|
||||
@Slot()
|
||||
def onConfirmButtonClicked(
|
||||
self
|
||||
):
|
||||
|
||||
_, style, _ = self.collectSettings()
|
||||
style_changed = self.__original_style.name() != style.name()
|
||||
self.saveAndApply()
|
||||
if style_changed:
|
||||
self.maybeRestart()
|
||||
self.close()
|
||||
@@ -281,6 +281,12 @@ font: 700 9pt;</string>
|
||||
<property name="nativeMenuBar">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="ToolsMenu">
|
||||
<property name="title">
|
||||
<string>工具</string>
|
||||
</property>
|
||||
<addaction name="SettingsAction"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="HelpMenu">
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
@@ -291,6 +297,7 @@ font: 700 9pt;</string>
|
||||
<addaction name="ManualAction"/>
|
||||
<addaction name="AboutAction"/>
|
||||
</widget>
|
||||
<addaction name="ToolsMenu"/>
|
||||
<addaction name="HelpMenu"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="StatusBar">
|
||||
@@ -308,6 +315,11 @@ font: 700 9pt;</string>
|
||||
<string>关于</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="SettingsAction">
|
||||
<property name="text">
|
||||
<string>全局设置</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -0,0 +1,480 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ALSettingsWidget</class>
|
||||
<widget class="QWidget" name="ALSettingsWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>420</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>420</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>420</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>全局设置 - AutoLibrary</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="ALSettingsWidgetLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ContentLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListWidget" name="NavigationList">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SelectionMode::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentRow">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>外观</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="preferences-desktop-color"/>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="AppearancePageLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="AppearanceGroupBox">
|
||||
<property name="title">
|
||||
<string>主题模式</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="AppearanceGroupBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="LightThemeRadio">
|
||||
<property name="text">
|
||||
<string>浅色</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="DarkThemeRadio">
|
||||
<property name="text">
|
||||
<string>深色</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SystemThemeRadio">
|
||||
<property name="text">
|
||||
<string>跟随系统</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="InterfaceGroupBox">
|
||||
<property name="title">
|
||||
<string>界面风格</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="InterfaceGroupBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="StyleSelectLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="StyleSelectLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>应用程序样式:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="StyleComboBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>160</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="StyleHintLabel">
|
||||
<property name="text">
|
||||
<string>更改样式将在下次启动应用程序时生效。</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="CustomQssGroupBox">
|
||||
<property name="title">
|
||||
<string>自定义外观</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="CustomQssGroupBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="CustomQssHintLabel">
|
||||
<property name="text">
|
||||
<string>自定义程序外观,文件加载后将立即生效。</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="QssPathLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="QssPathEdit">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>选择或输入 QSS 样式表文件路径...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="BrowseQssButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="QssActionLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ApplyQssButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>应用样式</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ResetQssButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>重置外观</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="QssActionSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="QssStatusLabel">
|
||||
<property name="text">
|
||||
<string>当前使用程序默认外观。</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="AppearancePageSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ButtonLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="ButtonLeftSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="CancelButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>取消</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ApplyButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>应用</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ConfirmButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>确认</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -66,6 +66,12 @@ class CfgKey:
|
||||
CURRENT = ConfigPath(ConfigType.GLOBAL, "automation.user_path.current")
|
||||
PATHS = ConfigPath(ConfigType.GLOBAL, "automation.user_path.paths")
|
||||
|
||||
class APPEARANCE:
|
||||
ROOT = ConfigPath(ConfigType.GLOBAL, "appearance")
|
||||
THEME = ConfigPath(ConfigType.GLOBAL, "appearance.theme")
|
||||
STYLE = ConfigPath(ConfigType.GLOBAL, "appearance.style")
|
||||
CUSTOM_QSS = ConfigPath(ConfigType.GLOBAL, "appearance.custom_qss")
|
||||
|
||||
class TIMERTASK:
|
||||
ROOT = ConfigPath(ConfigType.TIMERTASK, "")
|
||||
TIMER_TASKS = ConfigPath(ConfigType.TIMERTASK, "timer_tasks")
|
||||
|
||||
@@ -54,6 +54,11 @@ class ConfigTemplate:
|
||||
"current": 0,
|
||||
"paths": []
|
||||
}
|
||||
},
|
||||
"appearance": {
|
||||
"theme": "system",
|
||||
"style": "Fusion",
|
||||
"custom_qss": ""
|
||||
}
|
||||
}
|
||||
case ConfigType.BULLETIN:
|
||||
|
||||
Reference in New Issue
Block a user