From 684211c1296d9b3e2443cc3d5785abbac9d360e1 Mon Sep 17 00:00:00 2001 From: DLmaster Date: Sun, 5 Jan 2025 19:24:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=E9=98=9F=E5=88=97=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/__init__.py | 6 +- app/config.py | 113 +++- app/services/__init__.py | 3 +- app/services/notification.py | 87 +-- app/services/security.py | 2 +- app/services/system.py | 125 ++++ app/ui/Widget.py | 137 +++- app/ui/else.py | 848 +++-------------------- app/ui/main_window.py | 81 ++- app/ui/member_manager.py | 1227 +++++++++++++++++++++++++++++++--- app/ui/queue_manager.py | 714 ++++++++++++++++++++ app/ui/setting.py | 135 +++- main.py | 4 +- resources/gui/main.ui | 2 +- 14 files changed, 2527 insertions(+), 957 deletions(-) create mode 100644 app/services/system.py create mode 100644 app/ui/queue_manager.py diff --git a/app/__init__.py b/app/__init__.py index 38b0e75..4ec17e7 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -29,18 +29,20 @@ __version__ = "4.2.0" __author__ = "DLmaster361 " __license__ = "GPL-3.0 license" -from .config import AppConfig, MaaConfig +from .config import AppConfig, QueueConfig, MaaConfig from .models import MaaManager -from .services import Notification, CryptoHandler +from .services import Notification, CryptoHandler, SystemHandler from .ui import AUTO_MAA from .utils import Updater, version_text __all__ = [ "AppConfig", + "QueueConfig", "MaaConfig", "MaaManager", "Notification", "CryptoHandler", + "SystemHandler", "AUTO_MAA", "Updater", "version_text", diff --git a/app/config.py b/app/config.py index 35c95b3..14bd977 100644 --- a/app/config.py +++ b/app/config.py @@ -59,6 +59,9 @@ class AppConfig: self.gameid_path = self.app_path / "data/gameid.txt" self.version_path = self.app_path / "resources/version.json" + self.PASSWORD = "" + self.if_database_opened = False + # 检查文件完整性 self.initialize() @@ -87,16 +90,16 @@ class AppConfig: encoding="utf-8", ) - self.check_config() - self.check_database() + self.get_config() + # self.check_database() - def check_config(self) -> None: - """检查配置文件字段完整性并补全""" + def get_config(self) -> None: + """创建配置类""" self.global_config = GlobalConfig() qconfig.load(self.config_path, self.global_config) - self.global_config.save() + self.queue_config = QueueConfig() self.maa_config = MaaConfig() def check_database(self) -> None: @@ -178,48 +181,44 @@ class AppConfig: cur.close() db.close() - def open_database(self) -> None: + def init_database(self, mode: str) -> None: + """初始化用户数据库""" + + if mode == "Maa": + self.cur.execute( + "CREATE TABLE adminx(admin text,id text,server text,day int,status text,last date,game text,game_1 text,game_2 text,routine text,annihilation text,infrastructure text,password byte,notes text,numb int,mode text,uid int)" + ) + self.cur.execute("CREATE TABLE version(v text)") + self.cur.execute("INSERT INTO version VALUES(?)", ("v1.3",)) + self.db.commit() + + def open_database(self, mode: str, index: str = None) -> None: """打开数据库""" - self.db = sqlite3.connect(self.database_path) + if self.if_database_opened: + self.close_database() + + if mode == "Maa": + self.db = sqlite3.connect( + self.app_path / f"config/{mode}Config/{index}/user_date.db" + ) self.cur = self.db.cursor() + self.if_database_opened = True def close_database(self) -> None: """关闭数据库""" self.cur.close() self.db.close() + self.if_database_opened = False class GlobalConfig(QConfig): """全局配置""" - # ["TimeSet.set1", "False"], - # ["TimeSet.run1", "00:00"], - # ["TimeSet.set2", "False"], - # ["TimeSet.run2", "00:00"], - # ["TimeSet.set3", "False"], - # ["TimeSet.run3", "00:00"], - # ["TimeSet.set4", "False"], - # ["TimeSet.run4", "00:00"], - # ["TimeSet.set5", "False"], - # ["TimeSet.run5", "00:00"], - # ["TimeSet.set6", "False"], - # ["TimeSet.run6", "00:00"], - # ["TimeSet.set7", "False"], - # ["TimeSet.run7", "00:00"], - # ["TimeSet.set8", "False"], - # ["TimeSet.run8", "00:00"], - # ["TimeSet.set9", "False"], - # ["TimeSet.run9", "00:00"], - # ["TimeSet.set10", "False"], - # ["TimeSet.run10", "00:00"], - # ["MaaSet.path", ""], - # ["TimeLimit.routine", 10], - # ["TimeLimit.annihilation", 40], - # ["TimesLimit.run", 3], - - function_IfSleep = ConfigItem("Function", "IfSleep", False, BoolValidator()) + function_IfAllowSleep = ConfigItem( + "Function", "IfAllowSleep", False, BoolValidator() + ) function_IfSilence = ConfigItem("Function", "IfSilence", False, BoolValidator()) function_BossKey = ConfigItem("Function", "BossKey", "") @@ -243,6 +242,54 @@ class GlobalConfig(QConfig): update_IfAutoUpdate = ConfigItem("Update", "IfAutoUpdate", False, BoolValidator()) +class QueueConfig(QConfig): + """队列配置""" + + queueSet_Name = ConfigItem("QueueSet", "Name", "") + queueSet_Enabled = ConfigItem("QueueSet", "Enabled", False, BoolValidator()) + + time_TimeEnabled_0 = ConfigItem("Time", "TimeEnabled_0", False, BoolValidator()) + time_TimeSet_0 = ConfigItem("Time", "TimeSet_0", "00:00") + + time_TimeEnabled_1 = ConfigItem("Time", "TimeEnabled_1", False, BoolValidator()) + time_TimeSet_1 = ConfigItem("Time", "TimeSet_1", "00:00") + + time_TimeEnabled_2 = ConfigItem("Time", "TimeEnabled_2", False, BoolValidator()) + time_TimeSet_2 = ConfigItem("Time", "TimeSet_2", "00:00") + + time_TimeEnabled_3 = ConfigItem("Time", "TimeEnabled_3", False, BoolValidator()) + time_TimeSet_3 = ConfigItem("Time", "TimeSet_3", "00:00") + + time_TimeEnabled_4 = ConfigItem("Time", "TimeEnabled_4", False, BoolValidator()) + time_TimeSet_4 = ConfigItem("Time", "TimeSet_4", "00:00") + + time_TimeEnabled_5 = ConfigItem("Time", "TimeEnabled_5", False, BoolValidator()) + time_TimeSet_5 = ConfigItem("Time", "TimeSet_5", "00:00") + + time_TimeEnabled_6 = ConfigItem("Time", "TimeEnabled_6", False, BoolValidator()) + time_TimeSet_6 = ConfigItem("Time", "TimeSet_6", "00:00") + + time_TimeEnabled_7 = ConfigItem("Time", "TimeEnabled_7", False, BoolValidator()) + time_TimeSet_7 = ConfigItem("Time", "TimeSet_7", "00:00") + + time_TimeEnabled_8 = ConfigItem("Time", "TimeEnabled_8", False, BoolValidator()) + time_TimeSet_8 = ConfigItem("Time", "TimeSet_8", "00:00") + + time_TimeEnabled_9 = ConfigItem("Time", "TimeEnabled_9", False, BoolValidator()) + time_TimeSet_9 = ConfigItem("Time", "TimeSet_9", "00:00") + + queue_Member_1 = OptionsConfigItem("Queue", "Member_1", "禁用") + queue_Member_2 = OptionsConfigItem("Queue", "Member_2", "禁用") + queue_Member_3 = OptionsConfigItem("Queue", "Member_3", "禁用") + queue_Member_4 = OptionsConfigItem("Queue", "Member_4", "禁用") + queue_Member_5 = OptionsConfigItem("Queue", "Member_5", "禁用") + queue_Member_6 = OptionsConfigItem("Queue", "Member_6", "禁用") + queue_Member_7 = OptionsConfigItem("Queue", "Member_7", "禁用") + queue_Member_8 = OptionsConfigItem("Queue", "Member_8", "禁用") + queue_Member_9 = OptionsConfigItem("Queue", "Member_9", "禁用") + queue_Member_10 = OptionsConfigItem("Queue", "Member_10", "禁用") + + class MaaConfig(QConfig): """MAA配置""" diff --git a/app/services/__init__.py b/app/services/__init__.py index cf23c93..2ca32a7 100644 --- a/app/services/__init__.py +++ b/app/services/__init__.py @@ -31,5 +31,6 @@ __license__ = "GPL-3.0 license" from .notification import Notification from .security import CryptoHandler +from .system import SystemHandler -__all__ = ["Notification", "CryptoHandler"] +__all__ = ["Notification", "CryptoHandler", "SystemHandler"] diff --git a/app/services/notification.py b/app/services/notification.py index 4afd7f5..6ea9ff7 100644 --- a/app/services/notification.py +++ b/app/services/notification.py @@ -44,15 +44,17 @@ class Notification: def push_notification(self, title, message, ticker, t): """推送系统通知""" - notification.notify( - title=title, - message=message, - app_name="AUTO_MAA", - app_icon=str(self.config.app_path / "resources/icons/AUTO_MAA.ico"), - timeout=t, - ticker=ticker, - toast=True, - ) + if self.config.global_config.get(self.config.global_config.notify_IfPushPlyer): + + notification.notify( + title=title, + message=message, + app_name="AUTO_MAA", + app_icon=str(self.config.app_path / "resources/icons/AUTO_MAA.ico"), + timeout=t, + ticker=ticker, + toast=True, + ) return True @@ -62,34 +64,43 @@ class Notification: # 声明:此邮箱为AUTO_MAA项目组资产,未经授权不得私自使用 # 注意:此声明注释只有使用者更换发信邮箱时才能删除,本条规则优先级高于GPLv3 - # 第三方 SMTP 服务配置 - mail_host = "smtp.163.com" # 设置服务器 - mail_sender = "AUTO_MAA_server@163.com" # 用户名 - mail_key = "SYrq87nDLD4RNB5T" # 授权码 24/11/15 + if self.config.global_config.get(self.config.global_config.notify_IfSendMail): - # 定义邮件正文 - message = MIMEText(content, "plain", "utf-8") - message["From"] = formataddr( - (Header("AUTO_MAA通知服务", "utf-8").encode(), "AUTO_MAA_server@163.com") - ) # 发件人显示的名字 - message["To"] = formataddr( - ( - Header("AUTO_MAA用户", "utf-8").encode(), - self.config.content["Default"]["SelfSet.MailAddress"], - ) - ) # 收件人显示的名字 - message["Subject"] = Header(title, "utf-8") + # 第三方 SMTP 服务配置 + mail_host = "smtp.163.com" # 设置服务器 + mail_sender = "AUTO_MAA_server@163.com" # 用户名 + mail_key = "SYrq87nDLD4RNB5T" # 授权码 24/11/15 - try: - smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 465为SMTP_SSL默认端口 - smtpObj.login(mail_sender, mail_key) - smtpObj.sendmail( - mail_sender, - self.config.content["Default"]["SelfSet.MailAddress"], - message.as_string(), - ) - return True - except smtplib.SMTPException as e: - return f"发送邮件时出错:\n{e}" - finally: - smtpObj.quit() + # 定义邮件正文 + message = MIMEText(content, "plain", "utf-8") + message["From"] = formataddr( + ( + Header("AUTO_MAA通知服务", "utf-8").encode(), + "AUTO_MAA_server@163.com", + ) + ) # 发件人显示的名字 + message["To"] = formataddr( + ( + Header("AUTO_MAA用户", "utf-8").encode(), + self.config.global_config.get( + self.config.global_config.notify_MailAddress + ), + ) + ) # 收件人显示的名字 + message["Subject"] = Header(title, "utf-8") + + try: + smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 465为SMTP_SSL默认端口 + smtpObj.login(mail_sender, mail_key) + smtpObj.sendmail( + mail_sender, + self.config.global_config.get( + self.config.global_config.notify_MailAddress + ), + message.as_string(), + ) + return True + except smtplib.SMTPException as e: + return f"发送邮件时出错:\n{e}" + finally: + smtpObj.quit() diff --git a/app/services/security.py b/app/services/security.py index b39dc00..236ed0a 100644 --- a/app/services/security.py +++ b/app/services/security.py @@ -20,7 +20,7 @@ """ AUTO_MAA -AUTO_MAA主程序 +AUTO_MAA安全服务 v4.2 作者:DLmaster_361 """ diff --git a/app/services/system.py b/app/services/system.py new file mode 100644 index 0000000..583d641 --- /dev/null +++ b/app/services/system.py @@ -0,0 +1,125 @@ +# +# Copyright © <2024> + +# This file is part of AUTO_MAA. + +# AUTO_MAA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, +# or (at your option) any later version. + +# AUTO_MAA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with AUTO_MAA. If not, see . + +# DLmaster_361@163.com + +""" +AUTO_MAA +AUTO_MAA系统服务 +v4.2 +作者:DLmaster_361 +""" + +import ctypes +import win32gui +import win32process +import winreg +import psutil + +from app import AppConfig + + +class SystemHandler: + + ES_CONTINUOUS = 0x80000000 + ES_SYSTEM_REQUIRED = 0x00000001 + + def __init__(self, config: AppConfig): + + self.config = config + + self.set_Sleep() + self.set_SelfStart() + + def set_Sleep(self): + """同步系统休眠状态""" + + if self.config.global_config.get( + self.config.global_config.function_IfAllowSleep + ): + # 设置系统电源状态 + ctypes.windll.kernel32.SetThreadExecutionState( + self.ES_CONTINUOUS | self.ES_SYSTEM_REQUIRED + ) + else: + # 恢复系统电源状态 + ctypes.windll.kernel32.SetThreadExecutionState(self.ES_CONTINUOUS) + + def set_SelfStart(self): + """同步开机自启""" + + if ( + self.config.global_config.get(self.config.global_config.start_IfSelfStart) + and not self.is_startup() + ): + key = winreg.OpenKey( + winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Run", + winreg.KEY_SET_VALUE, + winreg.KEY_ALL_ACCESS | winreg.KEY_WRITE | winreg.KEY_CREATE_SUB_KEY, + ) + winreg.SetValueEx( + key, self.config.app_name, 0, winreg.REG_SZ, self.config.app_path_sys + ) + winreg.CloseKey(key) + elif ( + not self.config.global_config.get( + self.config.global_config.start_IfSelfStart + ) + and self.is_startup() + ): + key = winreg.OpenKey( + winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Run", + winreg.KEY_SET_VALUE, + winreg.KEY_ALL_ACCESS | winreg.KEY_WRITE | winreg.KEY_CREATE_SUB_KEY, + ) + winreg.DeleteValue(key, self.config.app_name) + winreg.CloseKey(key) + + def is_startup(self): + """判断程序是否已经开机自启""" + + key = winreg.OpenKey( + winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Run", + 0, + winreg.KEY_READ, + ) + + try: + value, _ = winreg.QueryValueEx(key, self.config.app_name) + winreg.CloseKey(key) + return True + except FileNotFoundError: + winreg.CloseKey(key) + return False + + def get_window_info(self): + """获取当前窗口信息""" + + def callback(hwnd, window_info): + if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd): + _, pid = win32process.GetWindowThreadProcessId(hwnd) + process = psutil.Process(pid) + window_info.append((win32gui.GetWindowText(hwnd), process.exe())) + return True + + window_info = [] + win32gui.EnumWindows(callback, window_info) + return window_info diff --git a/app/ui/Widget.py b/app/ui/Widget.py index 6ed0a41..1ec5a8f 100644 --- a/app/ui/Widget.py +++ b/app/ui/Widget.py @@ -25,8 +25,9 @@ v4.2 作者:DLmaster_361 """ -from PySide6.QtCore import Qt +from PySide6.QtCore import Qt, QTime from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QWidget, QHBoxLayout from qfluentwidgets import ( LineEdit, PasswordLineEdit, @@ -37,11 +38,14 @@ from qfluentwidgets import ( FluentIconBase, Signal, ComboBox, + CheckBox, qconfig, ConfigItem, + TimeEdit, + OptionsConfigItem, ) -from typing import Union +from typing import Union, List class InputMessageBox(MessageBoxBase): @@ -68,6 +72,31 @@ class InputMessageBox(MessageBoxBase): self.viewLayout.addWidget(self.input) +class SetMessageBox(MessageBoxBase): + """输入对话框""" + + def __init__(self, parent, title: str, content: List[str], list: List[List[str]]): + super().__init__(parent) + self.title = SubtitleLabel(title) + + Widget = QWidget() + Layout = QHBoxLayout(Widget) + + self.input: List[ComboBox] = [] + + for i in range(len(content)): + + self.input.append(ComboBox()) + self.input[i].addItems(list[i]) + self.input[i].setCurrentIndex(-1) + self.input[i].setPlaceholderText(content[i]) + Layout.addWidget(self.input[i]) + + # 将组件添加到布局中 + self.viewLayout.addWidget(self.title) + self.viewLayout.addWidget(Widget) + + class LineEditSettingCard(SettingCard): """Setting card with switch button""" @@ -147,3 +176,107 @@ class SpinBoxSettingCard(SettingCard): qconfig.set(self.configItem, value) self.SpinBox.setValue(value) + + +class NoOptionComboBoxSettingCard(SettingCard): + + def __init__( + self, + configItem: OptionsConfigItem, + icon: Union[str, QIcon, FluentIconBase], + title, + content=None, + value=None, + texts=None, + parent=None, + ): + + super().__init__(icon, title, content, parent) + self.configItem = configItem + self.comboBox = ComboBox(self) + self.comboBox.setMinimumWidth(250) + self.hBoxLayout.addWidget(self.comboBox, 0, Qt.AlignRight) + self.hBoxLayout.addSpacing(16) + + self.optionToText = {o: t for o, t in zip(value, texts)} + for text, option in zip(texts, value): + self.comboBox.addItem(text, userData=option) + + self.comboBox.setCurrentText(self.optionToText[qconfig.get(configItem)]) + self.comboBox.currentIndexChanged.connect(self._onCurrentIndexChanged) + configItem.valueChanged.connect(self.setValue) + + def _onCurrentIndexChanged(self, index: int): + + qconfig.set(self.configItem, self.comboBox.itemData(index)) + + def setValue(self, value): + if value not in self.optionToText: + return + + self.comboBox.setCurrentText(self.optionToText[value]) + qconfig.set(self.configItem, value) + + +class TimeEditSettingCard(SettingCard): + + enabledChanged = Signal(bool) + timeChanged = Signal(str) + + def __init__( + self, + icon: Union[str, QIcon, FluentIconBase], + title, + content=None, + configItem_bool: ConfigItem = None, + configItem_time: ConfigItem = None, + parent=None, + ): + + super().__init__(icon, title, content, parent) + self.configItem_bool = configItem_bool + self.configItem_time = configItem_time + self.CheckBox = CheckBox(self) + self.CheckBox.setTristate(False) + self.TimeEdit = TimeEdit(self) + self.TimeEdit.setDisplayFormat("HH:mm") + self.TimeEdit.setMinimumWidth(150) + + if configItem_bool: + self.setValue_bool(qconfig.get(configItem_bool)) + configItem_bool.valueChanged.connect(self.setValue_bool) + + if configItem_time: + self.setValue_time(qconfig.get(configItem_time)) + configItem_time.valueChanged.connect(self.setValue_time) + + self.hBoxLayout.addWidget(self.CheckBox, 0, Qt.AlignRight) + self.hBoxLayout.addWidget(self.TimeEdit, 0, Qt.AlignRight) + self.hBoxLayout.addSpacing(16) + + self.CheckBox.stateChanged.connect(self.__enableChanged) + self.TimeEdit.timeChanged.connect(self.__timeChanged) + + def __timeChanged(self, value: QTime): + self.setValue_time(value.toString("HH:mm")) + self.timeChanged.emit(value.toString("HH:mm")) + + def __enableChanged(self, value: int): + if value == 0: + self.setValue_bool(False) + self.enabledChanged.emit(False) + else: + self.setValue_bool(True) + self.enabledChanged.emit(True) + + def setValue_bool(self, value: bool): + if self.configItem_bool: + qconfig.set(self.configItem_bool, value) + + self.CheckBox.setChecked(value) + + def setValue_time(self, value: str): + if self.configItem_time: + qconfig.set(self.configItem_time, value) + + self.TimeEdit.setTime(QTime.fromString(value, "HH:mm")) diff --git a/app/ui/else.py b/app/ui/else.py index 04994bd..501b815 100644 --- a/app/ui/else.py +++ b/app/ui/else.py @@ -10,68 +10,7 @@ class Main(QWidget): self.notify = notify self.crypto = crypto - self.PASSWORD = "" - self.if_user_list_editable = True - self.if_update_database = True - self.if_update_config = True - self.user_mode_list = ["simple", "beta"] - self.user_column = [ - "admin", - "id", - "server", - "day", - "status", - "last", - "game", - "game_1", - "game_2", - "routine", - "annihilation", - "infrastructure", - "password", - "notes", - "numb", - "mode", - "uid", - ] - self.userlist_simple_index = [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - "-", - 9, - 10, - 11, - 12, - "-", - "-", - "-", - ] - self.userlist_beta_index = [ - 0, - "-", - "-", - 1, - 2, - 3, - "-", - "-", - "-", - 4, - 5, - "-", - 6, - 7, - "-", - "-", - "-", - ] + # uiLoader.registerCustomWidget(PushButton) # uiLoader.registerCustomWidget(LineEdit) @@ -172,7 +111,7 @@ class Main(QWidget): # ) # self.if_self_start.stateChanged.connect(self.change_config) - # self.if_sleep: CheckBox = self.ui.findChild(CheckBox, "checkBox_ifsleep") + # self.if_sleep: CheckBox = self.ui.findChild(CheckBox, "checkBox_IfAllowSleep") # self.if_sleep.stateChanged.connect(self.change_config) # self.if_proxy_directly: CheckBox = self.ui.findChild( @@ -262,279 +201,79 @@ class Main(QWidget): if self.config.content["Default"]["SelfSet.IfProxyDirectly"] == "True": self.maa_starter("日常代理") - def check_PASSWORD(self) -> None: - """检查并配置管理密钥""" - if self.config.key_path.exists(): - return None - while True: + # def update_config(self): + # """将self.config中的程序配置同步至GUI界面""" - if self.read("setkey"): - self.crypto.get_PASSWORD(self.PASSWORD) - break - else: - choice = MessageBox( - "确认", "您没有输入管理密钥,确定要暂时跳过这一步吗?", self.ui - ) - if choice.exec(): - break + # # 阻止GUI程序配置被立即读入程序形成死循环 + # self.if_update_config = False - def update_user_info(self, operation: str) -> None: - """将本地数据库中的用户配置同步至GUI的用户管理界面""" + # self.main_tab.setCurrentIndex( + # self.config.content["Default"]["SelfSet.MainIndex"] + # ) - # 读入本地数据库 - self.config.cur.execute("SELECT * FROM adminx WHERE True") - data = self.config.cur.fetchall() + # self.maa_path.setText(str(Path(self.config.content["Default"]["MaaSet.path"]))) + # self.routine.setValue(self.config.content["Default"]["TimeLimit.routine"]) + # self.annihilation.setValue( + # self.config.content["Default"]["TimeLimit.annihilation"] + # ) + # self.num.setValue(self.config.content["Default"]["TimesLimit.run"]) + # self.mail_address.setText(self.config.content["Default"]["SelfSet.MailAddress"]) + # self.boss_key.setText(self.config.content["Default"]["SelfSet.BossKey"]) - # 处理部分模式调整 - if operation == "clear": - self.PASSWORD = "" - elif operation == "read_only": - self.if_user_list_editable = False - elif operation == "editable": - self.if_user_list_editable = True + # self.if_self_start.setChecked( + # bool(self.config.content["Default"]["SelfSet.IfSelfStart"] == "True") + # ) - # 阻止GUI用户数据被立即写入数据库形成死循环 - self.if_update_database = False + # self.if_sleep.setChecked( + # bool(self.config.content["Default"]["SelfSet.IfAllowSleep"] == "True") + # ) - user_switch_list = ["转为高级", "转为简洁"] - self.user_switch.setText(user_switch_list[self.user_set.currentIndex()]) + # self.if_proxy_directly.setChecked( + # bool(self.config.content["Default"]["SelfSet.IfProxyDirectly"] == "True") + # ) - # 同步简洁用户配置列表 - data_simple = [_ for _ in data if _[15] == "simple"] - self.user_list_simple.setRowCount(len(data_simple)) + # self.if_send_mail.setChecked( + # bool(self.config.content["Default"]["SelfSet.IfSendMail"] == "True") + # ) - for i, row in enumerate(data_simple): + # self.mail_address.setVisible( + # bool(self.config.content["Default"]["SelfSet.IfSendMail"] == "True") + # ) - for j, value in enumerate(row): + # self.if_send_error_only.setChecked( + # bool( + # self.config.content["Default"]["SelfSet.IfSendMail.OnlyError"] == "True" + # ) + # ) - if self.userlist_simple_index[j] == "-": - continue + # self.if_send_error_only.setVisible( + # bool(self.config.content["Default"]["SelfSet.IfSendMail"] == "True") + # ) - # 生成表格组件 - if j == 2: - item = ComboBox() - item.addItems(["官服", "B服"]) - if value == "Official": - item.setCurrentIndex(0) - elif value == "Bilibili": - item.setCurrentIndex(1) - item.currentIndexChanged.connect( - partial( - self.change_user_CellWidget, - data_simple[i][16], - self.user_column[j], - ) - ) - elif j in [4, 10, 11]: - item = QComboBox() - if j in [4, 10]: - item.addItems(["启用", "禁用"]) - elif j == 11: - item.addItems(["启用", "禁用", "更改配置文件"]) - if value == "y": - item.setCurrentIndex(0) - elif value == "n": - item.setCurrentIndex(1) - item.currentIndexChanged.connect( - partial( - self.change_user_CellWidget, - data_simple[i][16], - self.user_column[j], - ) - ) - elif j == 3 and value == -1: - item = QTableWidgetItem("无限") - elif j == 5: - curdate = self.server_date() - if curdate != value: - item = QTableWidgetItem("今日未代理") - else: - item = QTableWidgetItem(f"今日已代理{data_simple[i][14]}次") - item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - elif j == 12: - if self.PASSWORD == "": - item = QTableWidgetItem("******") - item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - else: - result = self.crypto.decryptx(value, self.PASSWORD) - item = QTableWidgetItem(result) - if result == "管理密钥错误": - item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - else: - item = QTableWidgetItem(str(value)) + # self.if_silence.setChecked( + # bool(self.config.content["Default"]["SelfSet.IfSilence"] == "True") + # ) - # 组件录入表格 - if j in [2, 4, 10, 11]: - if not self.if_user_list_editable: - item.setEnabled(False) - self.user_list_simple.setCellWidget( - data_simple[i][16], self.userlist_simple_index[j], item - ) - else: - self.user_list_simple.setItem( - data_simple[i][16], self.userlist_simple_index[j], item - ) + # self.boss_key.setVisible( + # bool(self.config.content["Default"]["SelfSet.IfSilence"] == "True") + # ) - # 同步高级用户配置列表 - data_beta = [_ for _ in data if _[15] == "beta"] - self.user_list_beta.setRowCount(len(data_beta)) + # self.if_to_tray.setChecked( + # bool(self.config.content["Default"]["SelfSet.IfToTray"] == "True") + # ) - for i, row in enumerate(data_beta): - - for j, value in enumerate(row): - - if self.userlist_beta_index[j] == "-": - continue - - # 生成表格组件 - if j in [4, 9, 10]: - item = ComboBox() - if j == 4: - item.addItems(["启用", "禁用"]) - elif j in [9, 10]: - item.addItems(["启用", "禁用", "修改MAA配置"]) - if value == "y": - item.setCurrentIndex(0) - elif value == "n": - item.setCurrentIndex(1) - item.currentIndexChanged.connect( - partial( - self.change_user_CellWidget, - data_beta[i][16], - self.user_column[j], - ) - ) - elif j == 3 and value == -1: - item = QTableWidgetItem("无限") - elif j == 5: - curdate = self.server_date() - if curdate != value: - item = QTableWidgetItem("今日未代理") - else: - item = QTableWidgetItem(f"今日已代理{data_beta[i][14]}次") - item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - elif j == 12: - if self.PASSWORD == "": - item = QTableWidgetItem("******") - item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - else: - result = self.crypto.decryptx(value, self.PASSWORD) - item = QTableWidgetItem(result) - if result == "管理密钥错误": - item.setFlags( - QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled - ) - else: - item = QTableWidgetItem(str(value)) - - # 组件录入表格 - if j in [4, 9, 10]: - if not self.if_user_list_editable: - item.setEnabled(False) - self.user_list_beta.setCellWidget( - data_beta[i][16], self.userlist_beta_index[j], item - ) - else: - self.user_list_beta.setItem( - data_beta[i][16], self.userlist_beta_index[j], item - ) - - # 设置列表可编辑状态 - if self.if_user_list_editable: - self.user_list_simple.setEditTriggers(TableWidget.AllEditTriggers) - self.user_list_beta.setEditTriggers(TableWidget.AllEditTriggers) - else: - self.user_list_simple.setEditTriggers(TableWidget.NoEditTriggers) - self.user_list_beta.setEditTriggers(TableWidget.NoEditTriggers) - - # 允许GUI改变被同步到本地数据库 - self.if_update_database = True - - # 设置用户配置列表的标题栏宽度 - self.user_list_simple.horizontalHeader().setSectionResizeMode( - QHeaderView.Stretch - ) - self.user_list_beta.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) - - def update_config(self): - """将self.config中的程序配置同步至GUI界面""" - - # 阻止GUI程序配置被立即读入程序形成死循环 - self.if_update_config = False - - self.main_tab.setCurrentIndex( - self.config.content["Default"]["SelfSet.MainIndex"] - ) - - self.maa_path.setText(str(Path(self.config.content["Default"]["MaaSet.path"]))) - self.routine.setValue(self.config.content["Default"]["TimeLimit.routine"]) - self.annihilation.setValue( - self.config.content["Default"]["TimeLimit.annihilation"] - ) - self.num.setValue(self.config.content["Default"]["TimesLimit.run"]) - self.mail_address.setText(self.config.content["Default"]["SelfSet.MailAddress"]) - self.boss_key.setText(self.config.content["Default"]["SelfSet.BossKey"]) - - self.if_self_start.setChecked( - bool(self.config.content["Default"]["SelfSet.IfSelfStart"] == "True") - ) - - self.if_sleep.setChecked( - bool(self.config.content["Default"]["SelfSet.IfSleep"] == "True") - ) - - self.if_proxy_directly.setChecked( - bool(self.config.content["Default"]["SelfSet.IfProxyDirectly"] == "True") - ) - - self.if_send_mail.setChecked( - bool(self.config.content["Default"]["SelfSet.IfSendMail"] == "True") - ) - - self.mail_address.setVisible( - bool(self.config.content["Default"]["SelfSet.IfSendMail"] == "True") - ) - - self.if_send_error_only.setChecked( - bool( - self.config.content["Default"]["SelfSet.IfSendMail.OnlyError"] == "True" - ) - ) - - self.if_send_error_only.setVisible( - bool(self.config.content["Default"]["SelfSet.IfSendMail"] == "True") - ) - - self.if_silence.setChecked( - bool(self.config.content["Default"]["SelfSet.IfSilence"] == "True") - ) - - self.boss_key.setVisible( - bool(self.config.content["Default"]["SelfSet.IfSilence"] == "True") - ) - - self.if_to_tray.setChecked( - bool(self.config.content["Default"]["SelfSet.IfToTray"] == "True") - ) - - for i in range(10): - self.start_time[i][0].setChecked( - bool(self.config.content["Default"][f"TimeSet.set{i + 1}"] == "True") - ) - time = QtCore.QTime( - int(self.config.content["Default"][f"TimeSet.run{i + 1}"][:2]), - int(self.config.content["Default"][f"TimeSet.run{i + 1}"][3:]), - ) - self.start_time[i][1].setTime(time) - self.if_update_config = True + # for i in range(10): + # self.start_time[i][0].setChecked( + # bool(self.config.content["Default"][f"TimeSet.set{i + 1}"] == "True") + # ) + # time = QtCore.QTime( + # int(self.config.content["Default"][f"TimeSet.run{i + 1}"][:2]), + # int(self.config.content["Default"][f"TimeSet.run{i + 1}"][3:]), + # ) + # self.start_time[i][1].setTime(time) + # self.if_update_config = True def update_board(self, run_text, wait_text, over_text, error_text, log_text): """写入数据至GUI执行界面的调度台面板""" @@ -548,372 +287,6 @@ class Main(QWidget): self.log_text.verticalScrollBar().maximum() ) - def add_user(self): - """添加一位新用户""" - - # 判断是否已设置管理密钥 - if not self.config.key_path.exists(): - choice = MessageBox( - "错误", - "请先设置管理密钥再执行添加用户操作", - self.ui, - ) - choice.cancelButton.hide() - choice.buttonLayout.insertStretch(1) - if choice.exec(): - return None - - # 插入预设用户数据 - set_book = [ - ["simple", self.user_list_simple.rowCount()], - ["beta", self.user_list_beta.rowCount()], - ] - self.config.cur.execute( - "INSERT INTO adminx VALUES('新用户','手机号码(官服)/B站ID(B服)','Official',-1,'y','2000-01-01','1-7','-','-','n','n','n',?,'无',0,?,?)", - ( - self.crypto.encryptx("未设置"), - set_book[self.user_set.currentIndex()][0], - set_book[self.user_set.currentIndex()][1], - ), - ) - self.config.db.commit(), - - # 同步新用户至GUI - self.update_user_info("normal") - - def del_user(self): - """删除选中的首位用户""" - - # 获取对应的行索引 - if self.user_set.currentIndex() == 0: - row = self.user_list_simple.currentRow() - elif self.user_set.currentIndex() == 1: - row = self.user_list_beta.currentRow() - - # 判断选择合理性 - if row == -1: - choice = MessageBox("错误", "请选中一个用户后再执行删除操作", self.ui) - choice.cancelButton.hide() - choice.buttonLayout.insertStretch(1) - if choice.exec(): - return None - - # 确认待删除用户信息 - self.config.cur.execute( - "SELECT * FROM adminx WHERE mode = ? AND uid = ?", - ( - self.user_mode_list[self.user_set.currentIndex()], - row, - ), - ) - data = self.config.cur.fetchall() - choice = MessageBox("确认", f"确定要删除用户 {data[0][0]} 吗?", self.ui) - - # 删除用户 - if choice.exec(): - # 删除所选用户 - self.config.cur.execute( - "DELETE FROM adminx WHERE mode = ? AND uid = ?", - ( - self.user_mode_list[self.user_set.currentIndex()], - row, - ), - ) - self.config.db.commit() - if ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{row}" - ).exists(): - shutil.rmtree( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{row}" - ) - # 后续用户补位 - if self.user_set.currentIndex() == 0: - current_numb = self.user_list_simple.rowCount() - elif self.user_set.currentIndex() == 1: - current_numb = self.user_list_beta.rowCount() - for i in range(row + 1, current_numb): - self.config.cur.execute( - "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", - (i - 1, self.user_mode_list[self.user_set.currentIndex()], i), - ) - self.config.db.commit() - if ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{i}" - ).exists(): - ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{i}" - ).rename( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{i - 1}", - ) - - # 同步最终结果至GUI - self.update_user_info("normal") - - def switch_user(self): - """切换用户配置模式""" - - # 获取当前用户配置模式信息 - if self.user_set.currentIndex() == 0: - row = self.user_list_simple.currentRow() - elif self.user_set.currentIndex() == 1: - row = self.user_list_beta.currentRow() - - # 判断选择合理性 - if row == -1: - choice = MessageBox("错误", "请选中一个用户后再执行切换操作", self.ui) - choice.cancelButton.hide() - choice.buttonLayout.insertStretch(1) - if choice.exec(): - return None - - # 确认待切换用户信息 - self.config.cur.execute( - "SELECT * FROM adminx WHERE mode = ? AND uid = ?", - ( - self.user_mode_list[self.user_set.currentIndex()], - row, - ), - ) - data = self.config.cur.fetchall() - - mode_list = ["简洁", "高级"] - choice = MessageBox( - "确认", - f"确定要将用户 {data[0][0]} 转为{mode_list[1 - self.user_set.currentIndex()]}配置模式吗?", - self.ui, - ) - - # 切换用户 - if choice.exec(): - self.config.cur.execute("SELECT * FROM adminx WHERE True") - data = self.config.cur.fetchall() - if self.user_set.currentIndex() == 0: - current_numb = self.user_list_simple.rowCount() - elif self.user_set.currentIndex() == 1: - current_numb = self.user_list_beta.rowCount() - # 切换所选用户 - other_numb = len(data) - current_numb - self.config.cur.execute( - "UPDATE adminx SET mode = ?, uid = ? WHERE mode = ? AND uid = ?", - ( - self.user_mode_list[1 - self.user_set.currentIndex()], - other_numb, - self.user_mode_list[self.user_set.currentIndex()], - row, - ), - ) - self.config.db.commit() - if ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{row}" - ).exists(): - shutil.move( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{row}", - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[1 - self.user_set.currentIndex()]}/{other_numb}", - ) - # 后续用户补位 - for i in range(row + 1, current_numb): - self.config.cur.execute( - "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", - (i - 1, self.user_mode_list[self.user_set.currentIndex()], i), - ) - self.config.db.commit(), - if ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{i}" - ).exists(): - ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{i}" - ).rename( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{i - 1}" - ) - - self.update_user_info("normal") - - def get_maa_config(self, info): - """获取MAA配置文件""" - - # 获取全局MAA配置文件 - if info == ["Default"]: - shutil.copy( - Path(self.config.content["Default"]["MaaSet.path"]) / "config/gui.json", - self.config.app_path / "data/MAAconfig/Default", - ) - # 获取基建配置文件 - elif info[2] == "infrastructure": - infrastructure_path = self.read("file_path_infrastructure") - if infrastructure_path: - ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[info[0]]}/{info[1]}/infrastructure" - ).mkdir(parents=True, exist_ok=True) - shutil.copy( - infrastructure_path, - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[info[0]]}/{info[1]}/infrastructure/infrastructure.json", - ) - return True - else: - choice = MessageBox( - "错误", - "未选择自定义基建文件", - self.ui, - ) - choice.cancelButton.hide() - choice.buttonLayout.insertStretch(1) - if choice.exec(): - return False - # 获取高级用户MAA配置文件 - elif info[2] in ["routine", "annihilation"]: - ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[info[0]]}/{info[1]}/{info[2]}" - ).mkdir(parents=True, exist_ok=True) - shutil.copy( - Path(self.config.content["Default"]["MaaSet.path"]) / "config/gui.json", - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[info[0]]}/{info[1]}/{info[2]}", - ) - - def change_user_Item(self, item: TableWidget, mode): - """将GUI中发生修改的用户配置表中的一般信息同步至本地数据库""" - - # 验证能否写入本地数据库 - if not self.if_update_database: - return None - - text = item.text() - # 简洁用户配置列表 - if mode == "simple": - # 待写入信息预处理 - if item.column() == 3: # 代理天数 - try: - text = max(int(text), -1) - except ValueError: - self.update_user_info("normal") - return None - if item.column() in [6, 7, 8]: # 关卡号 - # 导入与应用特殊关卡规则 - games = {} - with self.config.gameid_path.open(mode="r", encoding="utf-8") as f: - gameids = f.readlines() - for line in gameids: - if ":" in line: - game_in, game_out = line.split(":", 1) - games[game_in.strip()] = game_out.strip() - text = games.get(text, text) - if item.column() == 11: # 密码 - text = self.crypto.encryptx(text) - - # 保存至本地数据库 - if text != "": - self.config.cur.execute( - f"UPDATE adminx SET {self.user_column[self.userlist_simple_index.index(item.column())]} = ? WHERE mode = 'simple' AND uid = ?", - (text, item.row()), - ) - # 高级用户配置列表 - elif mode == "beta": - # 待写入信息预处理 - if item.column() == 1: # 代理天数 - try: - text = max(int(text), -1) - except ValueError: - self.update_user_info("normal") - return None - if item.column() == 6: # 密码 - text = self.crypto.encryptx(text) - - # 保存至本地数据库 - if text != "": - self.config.cur.execute( - f"UPDATE adminx SET {self.user_column[self.userlist_beta_index.index(item.column())]} = ? WHERE mode = 'beta' AND uid = ?", - (text, item.row()), - ) - self.config.db.commit() - - # 同步一般用户信息更改到GUI - self.update_user_info("normal") - - def change_user_CellWidget(self, row, column, index): - """将GUI中发生修改的用户配置表中的CellWidget类信息同步至本地数据库""" - - # 验证能否写入本地数据库 - if not self.if_update_database: - return None - - # 初次开启自定义基建或选择修改配置文件时选择配置文件 - if ( - self.user_set.currentIndex() == 0 - and column == "infrastructure" - and ( - index == 2 - or ( - index == 0 - and not ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{row}/infrastructure/infrastructure.json" - ).exists() - ) - ) - ): - result = self.get_maa_config([0, row, "infrastructure"]) - if index == 0 and not result: - index = 1 - - # 初次开启自定义MAA配置或选择修改MAA配置时调起MAA配置任务 - if ( - self.user_set.currentIndex() == 1 - and column in ["routine", "annihilation"] - and ( - index == 2 - or ( - index == 0 - and not ( - self.config.app_path - / f"data/MAAconfig/{self.user_mode_list[self.user_set.currentIndex()]}/{row}/{column}/gui.json" - ).exists() - ) - ) - ): - self.MaaManager.get_json_path = [ - self.user_set.currentIndex(), - row, - column, - ] - self.maa_starter("设置MAA_用户") - - # 服务器 - if self.user_set.currentIndex() == 0 and column == "server": - server_list = ["Official", "Bilibili"] - self.config.cur.execute( - f"UPDATE adminx SET server = ? WHERE mode = 'simple' AND uid = ?", - (server_list[index], row), - ) - # 其它(启用/禁用) - elif index in [0, 1]: - index_list = ["y", "n"] - self.config.cur.execute( - f"UPDATE adminx SET {column} = ? WHERE mode = ? AND uid = ?", - ( - index_list[index], - self.user_mode_list[self.user_set.currentIndex()], - row, - ), - ) - self.config.db.commit() - - # 同步用户组件信息修改到GUI - self.update_user_info("normal") - def change_user_info(self, modes, uids, days, lasts, notes, numbs): """将代理完成后发生改动的用户信息同步至本地数据库""" @@ -978,9 +351,9 @@ class Main(QWidget): self.config.content["Default"]["SelfSet.BossKey"] = self.boss_key.text() if self.if_sleep.isChecked(): - self.config.content["Default"]["SelfSet.IfSleep"] = "True" + self.config.content["Default"]["SelfSet.IfAllowSleep"] = "True" else: - self.config.content["Default"]["SelfSet.IfSleep"] = "False" + self.config.content["Default"]["SelfSet.IfAllowSleep"] = "False" if self.if_self_start.isChecked(): self.config.content["Default"]["SelfSet.IfSelfStart"] = "True" @@ -1026,6 +399,32 @@ class Main(QWidget): # 同步程序配置至GUI self.update_config() + + def get_maa_config(self, info): + """获取MAA配置文件""" + + # 获取全局MAA配置文件 + if info == ["Default"]: + shutil.copy( + Path(self.config.content["Default"]["MaaSet.path"]) + / "config/gui.json", + self.config.app_path / "data/MAAconfig/Default", + ) + # 获取基建配置文件 + + # 获取高级用户MAA配置文件 + elif info[2] in ["routine", "annihilation"]: + ( + self.config.app_path + / f"data/MAAconfig/{self.user_mode_list[info[0]]}/{info[1]}/{info[2]}" + ).mkdir(parents=True, exist_ok=True) + shutil.copy( + Path(self.config.content["Default"]["MaaSet.path"]) + / "config/gui.json", + self.config.app_path + / f"data/MAAconfig/{self.user_mode_list[info[0]]}/{info[1]}/{info[2]}", + ) + def set_theme(self): """手动更新主题色到组件""" @@ -1122,65 +521,6 @@ class Main(QWidget): ) return file_path - def set_system(self): - """设置系统相关配置""" - - # 同步系统休眠状态 - if self.config.content["Default"]["SelfSet.IfSleep"] == "True": - # 设置系统电源状态 - ctypes.windll.kernel32.SetThreadExecutionState( - self.ES_CONTINUOUS | self.ES_SYSTEM_REQUIRED - ) - elif self.config.content["Default"]["SelfSet.IfSleep"] == "False": - # 恢复系统电源状态 - ctypes.windll.kernel32.SetThreadExecutionState(self.ES_CONTINUOUS) - - # 同步开机自启 - if ( - self.config.content["Default"]["SelfSet.IfSelfStart"] == "True" - and not self.is_startup() - ): - key = winreg.OpenKey( - winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Run", - winreg.KEY_SET_VALUE, - winreg.KEY_ALL_ACCESS | winreg.KEY_WRITE | winreg.KEY_CREATE_SUB_KEY, - ) - winreg.SetValueEx( - key, self.config.app_name, 0, winreg.REG_SZ, self.config.app_path_sys - ) - winreg.CloseKey(key) - elif ( - self.config.content["Default"]["SelfSet.IfSelfStart"] == "False" - and self.is_startup() - ): - key = winreg.OpenKey( - winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Run", - winreg.KEY_SET_VALUE, - winreg.KEY_ALL_ACCESS | winreg.KEY_WRITE | winreg.KEY_CREATE_SUB_KEY, - ) - winreg.DeleteValue(key, self.config.app_name) - winreg.CloseKey(key) - - def is_startup(self): - """判断程序是否已经开机自启""" - - key = winreg.OpenKey( - winreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Run", - 0, - winreg.KEY_READ, - ) - - try: - value, _ = winreg.QueryValueEx(key, self.config.app_name) - winreg.CloseKey(key) - return True - except FileNotFoundError: - winreg.CloseKey(key) - return False - def timed_start(self): """定时启动代理任务""" @@ -1228,20 +568,6 @@ class Main(QWidget): # 执行日志记录,暂时缺省 pass - def get_window_info(self): - """获取当前窗口信息""" - - def callback(hwnd, window_info): - if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd): - _, pid = win32process.GetWindowThreadProcessId(hwnd) - process = psutil.Process(pid) - window_info.append((win32gui.GetWindowText(hwnd), process.exe())) - return True - - window_info = [] - win32gui.EnumWindows(callback, window_info) - return window_info - def maa_starter(self, mode): """启动MaaManager线程运行任务""" diff --git a/app/ui/main_window.py b/app/ui/main_window.py index 7dd66f3..45090f0 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -33,7 +33,6 @@ from PySide6.QtWidgets import ( QFileDialog, # QTabWidget, # QToolBox, # - QComboBox, # QTableWidgetItem, # QHeaderView, # QVBoxLayout, @@ -55,11 +54,14 @@ from qfluentwidgets import ( RoundMenu, MessageBox, MessageBoxBase, - HeaderCardWidget, + InfoBar, + InfoBarPosition, BodyLabel, Dialog, - SingleDirectionScrollArea, - SubtitleLabel, + setTheme, + Theme, + SystemThemeListener, + qconfig, MSFluentWindow, NavigationItemPosition, ) @@ -85,36 +87,46 @@ import requests uiLoader = QUiLoader() from app import AppConfig, MaaConfig -from app.services import Notification, CryptoHandler +from app.services import Notification, CryptoHandler, SystemHandler from app.utils import Updater, version_text from .Widget import InputMessageBox, LineEditSettingCard, SpinBoxSettingCard from .setting import Setting from .member_manager import MemberManager +from .queue_manager import QueueManager class AUTO_MAA(MSFluentWindow): if_save = True - def __init__(self, config: AppConfig, notify: Notification, crypto: CryptoHandler): - super(AUTO_MAA, self).__init__() + def __init__( + self, + config: AppConfig, + notify: Notification, + crypto: CryptoHandler, + system: SystemHandler, + ): + super().__init__() self.config = config self.notify = notify - - self.config.open_database() + self.crypto = crypto + self.system = system self.setWindowIcon( QIcon(str(self.config.app_path / "resources/icons/AUTO_MAA.ico")) ) self.setWindowTitle("AUTO_MAA") + setTheme(Theme.AUTO) + self.splashScreen = SplashScreen(self.windowIcon(), self) self.show() # 创建主窗口 - self.setting = Setting(config=config, notify=notify, crypto=crypto) - self.member_manager = MemberManager(config=config, notify=notify, crypto=crypto) + self.setting = Setting(self.config, self.notify, self.crypto, self.system, self) + self.member_manager = MemberManager(self.config, self.notify, self.crypto, self) + self.queue_manager = QueueManager(self.config, self.notify, self) self.addSubInterface( self.setting, @@ -130,6 +142,13 @@ class AUTO_MAA(MSFluentWindow): FluentIcon.ROBOT, NavigationItemPosition.TOP, ) + self.addSubInterface( + self.queue_manager, + FluentIcon.BOOK_SHELF, + "调度队列", + FluentIcon.BOOK_SHELF, + NavigationItemPosition.TOP, + ) # 创建系统托盘及其菜单 self.tray = QSystemTrayIcon( @@ -137,7 +156,7 @@ class AUTO_MAA(MSFluentWindow): self, ) self.tray.setToolTip("AUTO_MAA") - self.tray_menu = SystemTrayMenu() + self.tray_menu = SystemTrayMenu("AUTO_MAA", self) # 显示主界面菜单项 self.tray_menu.addAction( @@ -171,10 +190,43 @@ class AUTO_MAA(MSFluentWindow): # 设置托盘菜单 self.tray.setContextMenu(self.tray_menu) self.tray.activated.connect(self.on_tray_activated) + self.setting.ui.card_IfShowTray.checkedChanged.connect( + lambda x: self.tray.show() if x else self.tray.hide() + ) self.splashScreen.finish() self.show_main() + if self.config.global_config.get(self.config.global_config.update_IfAutoUpdate): + result = self.setting.check_update() + if result == "已是最新版本~": + InfoBar.success( + title="更新检查", + content=result, + orient=QtCore.Qt.Horizontal, + isClosable=True, + position=InfoBarPosition.TOP_RIGHT, + duration=3000, + parent=self, + ) + else: + info = InfoBar.info( + title="更新检查", + content=result, + orient=QtCore.Qt.Horizontal, + isClosable=True, + position=InfoBarPosition.BOTTOM_LEFT, + duration=-1, + parent=self, + ) + Up = PushButton("更新") + Up.clicked.connect( + lambda: self.setting.check_version(if_question=False) + ) + Up.clicked.connect(info.close) + info.addWidget(Up) + info.show() + def show_tray(self): """最小化到托盘""" if self.if_save: @@ -185,7 +237,10 @@ class AUTO_MAA(MSFluentWindow): def show_main(self): """显示主界面""" self.set_ui("配置") - self.tray.hide() + if self.config.global_config.get(self.config.global_config.ui_IfShowTray): + self.tray.show() + else: + self.tray.hide() def on_tray_activated(self, reason): """双击返回主界面""" diff --git a/app/ui/member_manager.py b/app/ui/member_manager.py index a3e78a9..4c8c9ad 100644 --- a/app/ui/member_manager.py +++ b/app/ui/member_manager.py @@ -20,7 +20,7 @@ """ AUTO_MAA -AUTO_MAA设置界面 +AUTO_MAA脚本管理界面 v4.2 作者:DLmaster_361 """ @@ -61,8 +61,8 @@ from qfluentwidgets import ( HeaderCardWidget, BodyLabel, CommandBar, - SubtitleLabel, - GroupHeaderCardWidget, + setTheme, + Theme, SwitchSettingCard, ExpandGroupSettingCard, SingleDirectionScrollArea, @@ -92,13 +92,24 @@ uiLoader = QUiLoader() from app import AppConfig, MaaConfig from app.services import Notification, CryptoHandler from app.utils import Updater, version_text -from .Widget import InputMessageBox, LineEditSettingCard, SpinBoxSettingCard +from .Widget import ( + InputMessageBox, + LineEditSettingCard, + SpinBoxSettingCard, + SetMessageBox, +) class MemberManager(QWidget): - def __init__(self, config: AppConfig, notify: Notification, crypto: CryptoHandler): - super(MemberManager, self).__init__() + def __init__( + self, + config: AppConfig, + notify: Notification, + crypto: CryptoHandler, + parent=None, + ): + super().__init__(parent) self.setObjectName("脚本管理") @@ -106,11 +117,13 @@ class MemberManager(QWidget): self.notify = notify self.crypto = crypto + setTheme(Theme.AUTO) + layout = QVBoxLayout(self) self.tools = CommandBar() - self.member_manager = MemberSettingBox(self.config) + self.member_manager = MemberSettingBox(self.config, self.crypto, self) # 逐个添加动作 self.tools.addActions( @@ -132,21 +145,19 @@ class MemberManager(QWidget): FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_setting_box ), Action( - FluentIcon.RIGHT_ARROW, - "向右移动", - triggered=self.right_setting_box, + FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_setting_box ), ] ) - - # 批量添加动作 + self.tools.addSeparator() + self.key = Action( + FluentIcon.HIDE, + "显示/隐藏密码", + checkable=True, + triggered=self.show_password, + ) self.tools.addAction( - Action( - FluentIcon.HIDE, - "显示/隐藏密码", - checkable=True, - triggered=self.show_password, - ), + self.key, ) layout.addWidget(self.tools) @@ -156,7 +167,11 @@ class MemberManager(QWidget): """添加一个脚本实例""" choice = InputMessageBox( - self, "选择一个脚本类型并添加相应脚本实例", "选择脚本类型", "选择", ["MAA"] + self, + "选择一个脚本类型并添加相应脚本实例", + "选择脚本类型", + "选择", + ["MAA"], ) if choice.exec() and choice.input.currentIndex() != -1: @@ -185,6 +200,8 @@ class MemberManager(QWidget): self.config.maa_config.set(self.config.maa_config.MaaSet_Name, "") self.config.maa_config.save() + self.config.open_database("Maa", f"脚本_{index}") + self.config.init_database("Maa") self.member_manager.add_MaaSettingBox(index) self.member_manager.switch_SettingBox(index) @@ -209,6 +226,8 @@ class MemberManager(QWidget): type = [_[1] for _ in member_list if _[0] == name] index = max(int(name[3:]) - 1, 1) + self.member_manager.clear_SettingBox() + shutil.rmtree(self.config.app_path / f"config/{type[0]}Config/{name}") for member in move_list: if ( @@ -221,9 +240,7 @@ class MemberManager(QWidget): / f"config/{member[1]}Config/{member[0][:3]}{int(member[0][3:])-1}", ) - self.member_manager.clear_SettingBox() - self.member_manager.show_SettingBox() - self.member_manager.switch_SettingBox(index, if_after_clear=True) + self.member_manager.show_SettingBox(index) def left_setting_box(self): """向左移动脚本实例""" @@ -242,22 +259,23 @@ class MemberManager(QWidget): type_right = [_[1] for _ in member_list if _[0] == name] type_left = [_[1] for _ in member_list if _[0] == f"脚本_{index-1}"] + self.member_manager.clear_SettingBox() + (self.config.app_path / f"config/{type_right[0]}Config/脚本_{index}").rename( self.config.app_path / f"config/{type_right[0]}Config/脚本_0", ) - (self.config.app_path / f"config/{type_left[0]}Config/脚本_{index-1}").rename( - self.config.app_path / f"config/{type_left[0]}Config/脚本_{index}", + shutil.move( + str(self.config.app_path / f"config/{type_left[0]}Config/脚本_{index-1}"), + str(self.config.app_path / f"config/{type_left[0]}Config/脚本_{index}"), ) (self.config.app_path / f"config/{type_right[0]}Config/脚本_0").rename( self.config.app_path / f"config/{type_right[0]}Config/脚本_{index-1}", ) - self.member_manager.clear_SettingBox() - self.member_manager.show_SettingBox() - self.member_manager.switch_SettingBox(index - 1, if_after_clear=True) + self.member_manager.show_SettingBox(index - 1) def right_setting_box(self): - """向左移动脚本实例""" + """向右移动脚本实例""" name = self.member_manager.pivot.currentRouteKey() @@ -273,6 +291,8 @@ class MemberManager(QWidget): type_left = [_[1] for _ in member_list if _[0] == name] type_right = [_[1] for _ in member_list if _[0] == f"脚本_{index+1}"] + self.member_manager.clear_SettingBox() + (self.config.app_path / f"config/{type_left[0]}Config/脚本_{index}").rename( self.config.app_path / f"config/{type_left[0]}Config/脚本_0", ) @@ -283,58 +303,78 @@ class MemberManager(QWidget): self.config.app_path / f"config/{type_left[0]}Config/脚本_{index+1}", ) - self.member_manager.clear_SettingBox() - self.member_manager.show_SettingBox() - self.member_manager.switch_SettingBox(index + 1, if_after_clear=True) + self.member_manager.show_SettingBox(index + 1) def show_password(self): - pass + if self.config.PASSWORD == "": + choice = InputMessageBox( + self, + "请输入管理密钥", + "管理密钥", + "密码", + ) + if choice.exec() and choice.input.text() != "": + self.config.PASSWORD = choice.input.text() + self.member_manager.script_list[ + int(self.member_manager.pivot.currentRouteKey()[3:]) - 1 + ].user_setting.user_list.update_user_info("normal") + self.key.setIcon(FluentIcon.VIEW) + self.key.setChecked(True) + else: + self.config.PASSWORD = "" + self.member_manager.script_list[ + int(self.member_manager.pivot.currentRouteKey()[3:]) - 1 + ].user_setting.user_list.update_user_info("normal") + self.key.setIcon(FluentIcon.HIDE) + self.key.setChecked(False) + else: + self.config.PASSWORD = "" + self.member_manager.script_list[ + int(self.member_manager.pivot.currentRouteKey()[3:]) - 1 + ].user_setting.user_list.update_user_info("normal") + self.key.setIcon(FluentIcon.HIDE) + self.key.setChecked(False) class MemberSettingBox(QWidget): - def __init__(self, config: AppConfig): - super().__init__() + def __init__(self, config: AppConfig, crypto: CryptoHandler, parent=None): + super().__init__(parent) self.setObjectName("脚本管理") self.config = config + self.crypto = crypto self.pivot = Pivot(self) self.stackedWidget = QStackedWidget(self) self.Layout = QVBoxLayout(self) - self.SubInterface: List[MaaSettingBox] = [] + self.script_list: List[MaaSettingBox] = [] self.Layout.addWidget(self.pivot, 0, QtCore.Qt.AlignHCenter) self.Layout.addWidget(self.stackedWidget) self.Layout.setContentsMargins(0, 0, 0, 0) self.pivot.currentItemChanged.connect( - lambda index: self.stackedWidget.setCurrentWidget( - self.findChild(QWidget, index) - ) - ) - self.pivot.currentItemChanged.connect( - lambda index: qconfig.load( - self.config.app_path / f"config/MaaConfig/{index}/config.json", - self.config.maa_config, - ) + lambda index: self.switch_SettingBox(int(index[3:]), if_chang_pivot=False) ) - self.show_SettingBox() - self.switch_SettingBox(1) + self.show_SettingBox(1) - def show_SettingBox(self) -> None: + def show_SettingBox(self, index) -> None: """加载所有子界面""" member_list = self.search_member() for member in member_list: if member[1] == "Maa": + self.config.open_database(member[1], member[0]) self.add_MaaSettingBox(int(member[0][3:])) - def switch_SettingBox(self, index: int, if_after_clear: bool = False) -> None: + self.switch_SettingBox(index) + + def switch_SettingBox(self, index: int, if_chang_pivot: bool = True) -> None: """切换到指定的子界面""" member_list = self.search_member() @@ -344,47 +384,36 @@ class MemberSettingBox(QWidget): type = [_[1] for _ in member_list if _[0] == f"脚本_{index}"] - if if_after_clear: - self.pivot.currentItemChanged.disconnect() - - self.stackedWidget.setCurrentWidget(self.SubInterface[index - 1]) - self.pivot.setCurrentItem(self.SubInterface[index - 1].objectName()) qconfig.load( self.config.app_path - / f"config/{type[0]}Config/{self.SubInterface[index-1].objectName()}/config.json", + / f"config/{type[0]}Config/{self.script_list[index-1].objectName()}/config.json", self.config.maa_config, ) + self.config.open_database(type[0], self.script_list[index - 1].objectName()) + self.script_list[index - 1].user_setting.user_list.update_user_info("normal") - if if_after_clear: - self.pivot.currentItemChanged.connect( - lambda index: self.stackedWidget.setCurrentWidget( - self.findChild(QWidget, index) - ) - ) - self.pivot.currentItemChanged.connect( - lambda index: qconfig.load( - self.config.app_path / f"config/MaaConfig/{index}/config.json", - self.config.maa_config, - ) - ) + if if_chang_pivot: + self.pivot.setCurrentItem(self.script_list[index - 1].objectName()) + self.stackedWidget.setCurrentWidget(self.script_list[index - 1]) def clear_SettingBox(self) -> None: """清空所有子界面""" - for sub_interface in self.SubInterface: + for sub_interface in self.script_list: self.stackedWidget.removeWidget(sub_interface) sub_interface.deleteLater() - self.SubInterface.clear() + self.script_list.clear() self.pivot.clear() + self.config.close_database() def add_MaaSettingBox(self, uid: int) -> None: """添加一个MAA设置界面""" - maa_setting_box = MaaSettingBox(self.config, uid) + maa_setting_box = MaaSettingBox(self.config, self.crypto, uid, self) - self.SubInterface.append(maa_setting_box) + self.script_list.append(maa_setting_box) - self.stackedWidget.addWidget(self.SubInterface[-1]) + self.stackedWidget.addWidget(self.script_list[-1]) self.pivot.addItem(routeKey=f"脚本_{uid}", text=f"脚本 {uid}") @@ -403,12 +432,13 @@ class MemberSettingBox(QWidget): class MaaSettingBox(QWidget): - def __init__(self, config: AppConfig, uid: int): - super().__init__() + def __init__(self, config: AppConfig, crypto: CryptoHandler, uid: int, parent=None): + super().__init__(parent) self.setObjectName(f"脚本_{uid}") self.config = config + self.crypto = crypto layout = QVBoxLayout() @@ -419,8 +449,12 @@ class MaaSettingBox(QWidget): content_layout = QVBoxLayout(content_widget) self.app_setting = self.AppSettingCard(self, self.config.maa_config) + self.user_setting = self.UserSettingCard( + self, self.objectName(), self.config, self.crypto + ) content_layout.addWidget(self.app_setting) + content_layout.addWidget(self.user_setting) content_layout.addStretch(1) scrollArea.setWidget(content_widget) @@ -497,7 +531,7 @@ class MaaSettingBox(QWidget): (1, 1024), FluentIcon.PAGE_RIGHT, "剿灭代理超时限制", - "MAA日志无变化时间超过该阈值视为超时", + "MAA日志无变化时间超过该阈值视为超时,单位为分钟", self.maa_config.RunSet_AnnihilationTimeLimit, ) @@ -505,7 +539,7 @@ class MaaSettingBox(QWidget): (1, 1024), FluentIcon.PAGE_RIGHT, "日常代理超时限制", - "MAA日志无变化时间超过该阈值视为超时", + "MAA日志无变化时间超过该阈值视为超时,单位为分钟", self.maa_config.RunSet_RoutineTimeLimit, ) @@ -525,3 +559,1046 @@ class MaaSettingBox(QWidget): self.viewLayout.setSpacing(0) self.addGroupWidget(widget) + + class UserSettingCard(HeaderCardWidget): + + def __init__( + self, + parent=None, + name: str = None, + config: AppConfig = None, + crypto: CryptoHandler = None, + ): + super().__init__(parent) + + self.setTitle("用户列表") + + self.config = config + self.crypto = crypto + self.name = name + + Layout = QVBoxLayout() + + self.user_list = self.UserListBox(self.name, self.config, self.crypto, self) + + self.tools = CommandBar() + self.tools.addActions( + [ + Action( + FluentIcon.ADD, "新建用户", triggered=self.user_list.add_user + ), + Action( + FluentIcon.REMOVE, "删除用户", triggered=self.user_list.del_user + ), + ] + ) + self.tools.addSeparator() + self.tools.addActions( + [ + Action(FluentIcon.UP, "向上移动", triggered=self.user_list.up_user), + Action( + FluentIcon.DOWN, "向下移动", triggered=self.user_list.down_user + ), + ] + ) + self.tools.addSeparator() + self.tools.addAction( + Action( + FluentIcon.SCROLL, "模式转换", triggered=self.user_list.switch_user + ) + ) + self.tools.addSeparator() + self.tools.addAction( + Action( + FluentIcon.DEVELOPER_TOOLS, "用户选项配置", triggered=self.set_more + ) + ) + + Layout.addWidget(self.tools) + Layout.addWidget(self.user_list) + + self.viewLayout.addLayout(Layout) + + def set_more(self): + + self.config.cur.execute("SELECT * FROM adminx WHERE True") + data = self.config.cur.fetchall() + + if self.user_list.pivot.currentRouteKey() == f"{self.name}_简洁用户列表": + + user_list = [_[0] for _ in data if _[15] == "simple"] + set_list = ["自定义基建"] + + choice = SetMessageBox( + self.parent().parent().parent().parent().parent().parent().parent(), + "用户选项配置", + ["选择要配置的用户", "选择要配置的选项"], + [user_list, set_list], + ) + if ( + choice.exec() + and choice.input[0].currentIndex() != -1 + and choice.input[1].currentIndex() != -1 + ): + + if choice.input[1].currentIndex() == 0: + file_path, _ = QFileDialog.getOpenFileName( + self, + "选择自定义基建文件", + ".", + "JSON 文件 (*.json)", + ) + if file_path != "": + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/simple/{choice.input[0].currentIndex()}/infrastructure" + ).mkdir(parents=True, exist_ok=True) + shutil.copy( + file_path, + self.config.app_path + / f"config/MaaConfig/{self.name}/simple/{choice.input[0].currentIndex()}/infrastructure", + ) + else: + choice = MessageBox( + "错误", + "未选择自定义基建文件", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + choice.cancelButton.hide() + choice.buttonLayout.insertStretch(1) + if choice.exec(): + pass + + class UserListBox(QWidget): + + def __init__( + self, name: str, config: AppConfig, crypto: CryptoHandler, parent=None + ): + super().__init__(parent) + self.setObjectName(f"{name}_用户列表") + self.config = config + self.crypto = crypto + + self.name = name + + self.if_user_list_editable = True + self.if_update_database = True + self.if_update_config = True + + self.user_mode_list = ["simple", "beta"] + self.user_column = [ + "admin", + "id", + "server", + "day", + "status", + "last", + "game", + "game_1", + "game_2", + "routine", + "annihilation", + "infrastructure", + "password", + "notes", + "numb", + "mode", + "uid", + ] + self.userlist_simple_index = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + "-", + 9, + 10, + 11, + 12, + "-", + "-", + "-", + ] + self.userlist_beta_index = [ + 0, + "-", + "-", + 1, + 2, + 3, + "-", + "-", + "-", + 4, + 5, + "-", + 6, + 7, + "-", + "-", + "-", + ] + + self.pivot = Pivot(self) + self.stackedWidget = QStackedWidget(self) + self.Layout = QVBoxLayout(self) + + self.user_list_simple = TableWidget() + self.user_list_simple.setObjectName(f"{self.name}_简洁用户列表") + self.user_list_simple.setColumnCount(13) + self.user_list_simple.setBorderVisible(True) + self.user_list_simple.setBorderRadius(10) + self.user_list_simple.setWordWrap(False) + self.user_list_simple.setVerticalScrollBarPolicy( + QtCore.Qt.ScrollBarAlwaysOff + ) + self.user_list_simple.setHorizontalHeaderLabels( + [ + "用户名", + "账号ID", + "服务器", + "代理天数", + "状态", + "执行情况", + "关卡", + "备选关卡-1", + "备选关卡-2", + "剿灭", + "自定义基建", + "密码", + "备注", + ] + ) + + self.user_list_beta = TableWidget() + self.user_list_beta.setObjectName(f"{name}_高级用户列表") + self.user_list_beta.setColumnCount(8) + self.user_list_beta.setBorderVisible(True) + self.user_list_beta.setBorderRadius(10) + self.user_list_beta.setWordWrap(False) + self.user_list_beta.setVerticalScrollBarPolicy( + QtCore.Qt.ScrollBarAlwaysOff + ) + self.user_list_beta.setHorizontalHeaderLabels( + [ + "用户名", + "代理天数", + "状态", + "执行情况", + "日常", + "剿灭", + "密码", + "备注", + ] + ) + + self.user_list_simple.itemChanged.connect( + lambda item: self.change_user_Item(item, "simple") + ) + + self.stackedWidget.addWidget(self.user_list_simple) + self.pivot.addItem( + routeKey=f"{name}_简洁用户列表", text=f"简洁用户列表" + ) + self.stackedWidget.addWidget(self.user_list_beta) + self.pivot.addItem( + routeKey=f"{name}_高级用户列表", text=f"高级用户列表" + ) + + self.Layout.addWidget(self.pivot, 0, QtCore.Qt.AlignHCenter) + self.Layout.addWidget(self.stackedWidget) + self.Layout.setContentsMargins(0, 0, 0, 0) + + self.update_user_info("normal") + self.switch_SettingBox(f"{name}_简洁用户列表") + self.pivot.currentItemChanged.connect( + lambda index: self.switch_SettingBox(index) + ) + + def switch_SettingBox(self, index: str) -> None: + """切换到指定的子界面""" + + self.pivot.setCurrentItem(index) + if "简洁用户列表" in index: + self.stackedWidget.setCurrentWidget(self.user_list_simple) + elif "高级用户列表" in index: + self.stackedWidget.setCurrentWidget(self.user_list_beta) + + def update_user_info(self, operation: str) -> None: + """将本地数据库中的用户配置同步至GUI的用户管理界面""" + + # 读入本地数据库 + self.config.cur.execute("SELECT * FROM adminx WHERE True") + data = self.config.cur.fetchall() + + # 处理部分模式调整 + if operation == "read_only": + self.if_user_list_editable = False + elif operation == "editable": + self.if_user_list_editable = True + + # 阻止GUI用户数据被立即写入数据库形成死循环 + self.if_update_database = False + + # user_switch_list = ["转为高级", "转为简洁"] + # self.user_switch.setText(user_switch_list[index]) + + # 同步简洁用户配置列表 + data_simple = [_ for _ in data if _[15] == "simple"] + self.user_list_simple.setRowCount(len(data_simple)) + height = self.user_list_simple.horizontalHeader().height() + + for i, row in enumerate(data_simple): + + height += self.user_list_simple.rowHeight(i) + + for j, value in enumerate(row): + + if self.userlist_simple_index[j] == "-": + continue + + # 生成表格组件 + if j == 2: + item = ComboBox() + item.addItems(["官服", "B服"]) + if value == "Official": + item.setCurrentIndex(0) + elif value == "Bilibili": + item.setCurrentIndex(1) + item.currentIndexChanged.connect( + partial( + self.change_user_CellWidget, + data_simple[i][16], + self.user_column[j], + ) + ) + elif j in [4, 10, 11]: + item = ComboBox() + item.addItems(["启用", "禁用"]) + if value == "y": + item.setCurrentIndex(0) + elif value == "n": + item.setCurrentIndex(1) + item.currentIndexChanged.connect( + partial( + self.change_user_CellWidget, + data_simple[i][16], + self.user_column[j], + ) + ) + elif j == 3 and value == -1: + item = QTableWidgetItem("无限") + elif j == 5: + curdate = server_date() + if curdate != value: + item = QTableWidgetItem("今日未代理") + else: + item = QTableWidgetItem( + f"今日已代理{data_simple[i][14]}次" + ) + item.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled + ) + elif j == 12: + if self.config.PASSWORD == "": + item = QTableWidgetItem("******") + item.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled + ) + else: + result = self.crypto.decryptx( + value, self.config.PASSWORD + ) + item = QTableWidgetItem(result) + if result == "管理密钥错误": + item.setFlags( + QtCore.Qt.ItemIsSelectable + | QtCore.Qt.ItemIsEnabled + ) + else: + item = QTableWidgetItem(str(value)) + + # 组件录入表格 + if j in [2, 4, 10, 11]: + if not self.if_user_list_editable: + item.setEnabled(False) + self.user_list_simple.setCellWidget( + data_simple[i][16], self.userlist_simple_index[j], item + ) + else: + self.user_list_simple.setItem( + data_simple[i][16], self.userlist_simple_index[j], item + ) + self.user_list_simple.setFixedHeight( + height + self.user_list_simple.frameWidth() * 2 + 10 + ) + + # 同步高级用户配置列表 + data_beta = [_ for _ in data if _[15] == "beta"] + self.user_list_beta.setRowCount(len(data_beta)) + height = self.user_list_beta.horizontalHeader().height() + + for i, row in enumerate(data_beta): + + height += self.user_list_beta.rowHeight(i) + + for j, value in enumerate(row): + + if self.userlist_beta_index[j] == "-": + continue + + # 生成表格组件 + if j in [4, 9, 10]: + item = ComboBox() + item.addItems(["启用", "禁用"]) + if value == "y": + item.setCurrentIndex(0) + elif value == "n": + item.setCurrentIndex(1) + item.currentIndexChanged.connect( + partial( + self.change_user_CellWidget, + data_beta[i][16], + self.user_column[j], + ) + ) + elif j == 3 and value == -1: + item = QTableWidgetItem("无限") + elif j == 5: + curdate = server_date() + if curdate != value: + item = QTableWidgetItem("今日未代理") + else: + item = QTableWidgetItem( + f"今日已代理{data_beta[i][14]}次" + ) + item.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled + ) + elif j == 12: + if self.config.PASSWORD == "": + item = QTableWidgetItem("******") + item.setFlags( + QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled + ) + else: + result = self.crypto.decryptx( + value, self.config.PASSWORD + ) + item = QTableWidgetItem(result) + if result == "管理密钥错误": + item.setFlags( + QtCore.Qt.ItemIsSelectable + | QtCore.Qt.ItemIsEnabled + ) + else: + item = QTableWidgetItem(str(value)) + + # 组件录入表格 + if j in [4, 9, 10]: + if not self.if_user_list_editable: + item.setEnabled(False) + self.user_list_beta.setCellWidget( + data_beta[i][16], self.userlist_beta_index[j], item + ) + else: + self.user_list_beta.setItem( + data_beta[i][16], self.userlist_beta_index[j], item + ) + self.user_list_beta.setFixedHeight( + height + self.user_list_beta.frameWidth() * 2 + 10 + ) + + # 设置列表可编辑状态 + if self.if_user_list_editable: + self.user_list_simple.setEditTriggers(TableWidget.AllEditTriggers) + self.user_list_beta.setEditTriggers(TableWidget.AllEditTriggers) + else: + self.user_list_simple.setEditTriggers(TableWidget.NoEditTriggers) + self.user_list_beta.setEditTriggers(TableWidget.NoEditTriggers) + + # 允许GUI改变被同步到本地数据库 + self.if_update_database = True + + # 设置用户配置列表的标题栏宽度 + self.user_list_simple.horizontalHeader().setSectionResizeMode( + QHeaderView.Stretch + ) + self.user_list_beta.horizontalHeader().setSectionResizeMode( + QHeaderView.Stretch + ) + + def change_user_Item(self, item: QTableWidgetItem, mode): + """将GUI中发生修改的用户配置表中的一般信息同步至本地数据库""" + + # 验证能否写入本地数据库 + if not self.if_update_database: + return None + + text = item.text() + # 简洁用户配置列表 + if mode == "simple": + # 待写入信息预处理 + if item.column() == 3: # 代理天数 + try: + text = max(int(text), -1) + except ValueError: + self.update_user_info("normal") + return None + if item.column() in [6, 7, 8]: # 关卡号 + # 导入与应用特殊关卡规则 + games = {} + with self.config.gameid_path.open( + mode="r", encoding="utf-8" + ) as f: + gameids = f.readlines() + for line in gameids: + if ":" in line: + game_in, game_out = line.split(":", 1) + games[game_in.strip()] = game_out.strip() + text = games.get(text, text) + if item.column() == 11: # 密码 + text = self.crypto.encryptx(text) + + # 保存至本地数据库 + if text != "": + self.config.cur.execute( + f"UPDATE adminx SET {self.user_column[self.userlist_simple_index.index(item.column())]} = ? WHERE mode = 'simple' AND uid = ?", + (text, item.row()), + ) + # 高级用户配置列表 + elif mode == "beta": + # 待写入信息预处理 + if item.column() == 1: # 代理天数 + try: + text = max(int(text), -1) + except ValueError: + self.update_user_info("normal") + return None + if item.column() == 6: # 密码 + text = self.crypto.encryptx(text) + + # 保存至本地数据库 + if text != "": + self.config.cur.execute( + f"UPDATE adminx SET {self.user_column[self.userlist_beta_index.index(item.column())]} = ? WHERE mode = 'beta' AND uid = ?", + (text, item.row()), + ) + self.config.db.commit() + + # 同步一般用户信息更改到GUI + self.update_user_info("normal") + + def change_user_CellWidget(self, row, column, index): + """将GUI中发生修改的用户配置表中的CellWidget类信息同步至本地数据库""" + + # 验证能否写入本地数据库 + if not self.if_update_database: + return None + + if "简洁用户列表" in self.pivot.currentRouteKey(): + mode = 0 + elif "高级用户列表" in self.pivot.currentRouteKey(): + mode = 1 + + # 初次开启自定义MAA配置或选择修改MAA配置时调起MAA配置任务 + # if ( + # mode == 1 + # and column in ["routine", "annihilation"] + # and ( + # index == 2 + # or ( + # index == 0 + # and not ( + # self.config.app_path + # / f"data/MAAconfig/{self.user_mode_list[index]}/{row}/{column}/gui.json" + # ).exists() + # ) + # ) + # ): + # pass + # self.MaaManager.get_json_path = [ + # index, + # row, + # column, + # ] + # self.maa_starter("设置MAA_用户") + + # 服务器 + if mode == 0 and column == "server": + server_list = ["Official", "Bilibili"] + self.config.cur.execute( + f"UPDATE adminx SET server = ? WHERE mode = 'simple' AND uid = ?", + (server_list[index], row), + ) + # 其它(启用/禁用) + elif index in [0, 1]: + index_list = ["y", "n"] + self.config.cur.execute( + f"UPDATE adminx SET {column} = ? WHERE mode = ? AND uid = ?", + ( + index_list[index], + self.user_mode_list[mode], + row, + ), + ) + self.config.db.commit() + + # 同步用户组件信息修改到GUI + self.update_user_info("normal") + + def add_user(self): + """添加一位新用户""" + + # 插入预设用户数据 + if "简洁用户列表" in self.pivot.currentRouteKey(): + set_book = ["simple", self.user_list_simple.rowCount()] + elif "高级用户列表" in self.pivot.currentRouteKey(): + set_book = ["beta", self.user_list_beta.rowCount()] + self.config.cur.execute( + "INSERT INTO adminx VALUES('新用户','手机号码(官服)/B站ID(B服)','Official',-1,'y','2000-01-01','1-7','-','-','n','n','n',?,'无',0,?,?)", + ( + self.crypto.encryptx("未设置"), + set_book[0], + set_book[1], + ), + ) + self.config.db.commit(), + + # 同步新用户至GUI + self.update_user_info("normal") + + def del_user(self) -> None: + """删除选中的首位用户""" + + # 获取对应的行索引 + if "简洁用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_simple.currentRow() + current_numb = self.user_list_simple.rowCount() + mode = 0 + elif "高级用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_beta.currentRow() + current_numb = self.user_list_beta.rowCount() + mode = 1 + + # 判断选择合理性 + if row == -1: + choice = MessageBox( + "错误", + "请选中一个用户后再执行删除操作", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + choice.cancelButton.hide() + choice.buttonLayout.insertStretch(1) + if choice.exec(): + return None + + # 确认待删除用户信息 + self.config.cur.execute( + "SELECT * FROM adminx WHERE mode = ? AND uid = ?", + ( + self.user_mode_list[mode], + row, + ), + ) + data = self.config.cur.fetchall() + choice = MessageBox( + "确认", + f"确定要删除用户 {data[0][0]} 吗?", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + + # 删除用户 + if choice.exec(): + # 删除所选用户 + self.config.cur.execute( + "DELETE FROM adminx WHERE mode = ? AND uid = ?", + ( + self.user_mode_list[mode], + row, + ), + ) + self.config.db.commit() + + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ).exists(): + shutil.rmtree( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ) + # 后续用户补位 + for i in range(row + 1, current_numb): + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + i - 1, + self.user_mode_list[mode], + i, + ), + ) + self.config.db.commit() + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{i}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{i}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{i}" + ) + + # 同步最终结果至GUI + self.update_user_info("normal") + + def up_user(self): + """向上移动用户""" + + # 获取对应的行索引 + if "简洁用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_simple.currentRow() + mode = 0 + elif "高级用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_beta.currentRow() + mode = 1 + + # 判断选择合理性 + if row == -1: + choice = MessageBox( + "错误", + "请选中一个用户后再执行向下移动操作", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + choice.cancelButton.hide() + choice.buttonLayout.insertStretch(1) + if choice.exec(): + return None + + if row == 0: + return None + + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + -1, + self.user_mode_list[mode], + row, + ), + ) + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + row, + self.user_mode_list[mode], + row - 1, + ), + ) + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + row - 1, + self.user_mode_list[mode], + -1, + ), + ) + self.config.db.commit() + + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{-1}" + ) + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row - 1}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row - 1}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ) + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{-1}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{-1}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row - 1}" + ) + + self.update_user_info("normal") + if "简洁用户列表" in self.pivot.currentRouteKey(): + self.user_list_simple.selectRow(row - 1) + elif "高级用户列表" in self.pivot.currentRouteKey(): + self.user_list_beta.selectRow(row - 1) + + def down_user(self): + """向下移动用户""" + + # 获取对应的行索引 + if "简洁用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_simple.currentRow() + current_numb = self.user_list_simple.rowCount() + mode = 0 + elif "高级用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_beta.currentRow() + current_numb = self.user_list_beta.rowCount() + mode = 1 + + # 判断选择合理性 + if row == -1: + choice = MessageBox( + "错误", + "请选中一个用户后再执行向下移动操作", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + choice.cancelButton.hide() + choice.buttonLayout.insertStretch(1) + if choice.exec(): + return None + + if row == current_numb - 1: + return None + + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + -1, + self.user_mode_list[mode], + row, + ), + ) + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + row, + self.user_mode_list[mode], + row + 1, + ), + ) + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + row + 1, + self.user_mode_list[mode], + -1, + ), + ) + self.config.db.commit() + + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{-1}" + ) + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row + 1}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row + 1}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ) + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{-1}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{-1}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row + 1}" + ) + + self.update_user_info("normal") + if "简洁用户列表" in self.pivot.currentRouteKey(): + self.user_list_simple.selectRow(row + 1) + elif "高级用户列表" in self.pivot.currentRouteKey(): + self.user_list_beta.selectRow(row + 1) + + def switch_user(self) -> None: + """切换用户配置模式""" + + # 获取当前用户配置模式信息 + if "简洁用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_simple.currentRow() + mode = 0 + elif "高级用户列表" in self.pivot.currentRouteKey(): + row = self.user_list_beta.currentRow() + mode = 1 + + # 判断选择合理性 + if row == -1: + choice = MessageBox( + "错误", + "请选中一个用户后再执行切换操作", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + choice.cancelButton.hide() + choice.buttonLayout.insertStretch(1) + if choice.exec(): + return None + + # 确认待切换用户信息 + self.config.cur.execute( + "SELECT * FROM adminx WHERE mode = ? AND uid = ?", + ( + self.user_mode_list[mode], + row, + ), + ) + data = self.config.cur.fetchall() + + mode_list = ["简洁", "高级"] + choice = MessageBox( + "确认", + f"确定要将用户 {data[0][0]} 转为{mode_list[1 - mode]}配置模式吗?", + self.parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent() + .parent(), + ) + + # 切换用户 + if choice.exec(): + self.config.cur.execute("SELECT * FROM adminx WHERE True") + data = self.config.cur.fetchall() + if mode == 0: + current_numb = self.user_list_simple.rowCount() + elif mode == 1: + current_numb = self.user_list_beta.rowCount() + # 切换所选用户 + other_numb = len(data) - current_numb + self.config.cur.execute( + "UPDATE adminx SET mode = ?, uid = ? WHERE mode = ? AND uid = ?", + ( + self.user_mode_list[1 - mode], + other_numb, + self.user_mode_list[mode], + row, + ), + ) + self.config.db.commit() + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}" + ).exists(): + shutil.move( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{row}", + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[1 - mode]}/{other_numb}", + ) + # 后续用户补位 + for i in range(row + 1, current_numb): + self.config.cur.execute( + "UPDATE adminx SET uid = ? WHERE mode = ? AND uid = ?", + ( + i - 1, + self.user_mode_list[mode], + i, + ), + ) + self.config.db.commit(), + if ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{i}" + ).exists(): + ( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{i}" + ).rename( + self.config.app_path + / f"config/MaaConfig/{self.name}/{self.user_mode_list[mode]}/{i - 1}" + ) + + self.update_user_info("normal") + + +def server_date() -> str: + """获取当前的服务器日期""" + + dt = datetime.datetime.now() + if dt.time() < datetime.datetime.min.time().replace(hour=4): + dt = dt - datetime.timedelta(days=1) + return dt.strftime("%Y-%m-%d") diff --git a/app/ui/queue_manager.py b/app/ui/queue_manager.py new file mode 100644 index 0000000..6a2c75e --- /dev/null +++ b/app/ui/queue_manager.py @@ -0,0 +1,714 @@ +# +# Copyright © <2024> + +# This file is part of AUTO_MAA. + +# AUTO_MAA is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, +# or (at your option) any later version. + +# AUTO_MAA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with AUTO_MAA. If not, see . + +# DLmaster_361@163.com + +""" +AUTO_MAA +AUTO_MAA调度队列界面 +v4.2 +作者:DLmaster_361 +""" + +from PySide6.QtWidgets import ( + QWidget, # + QMainWindow, # + QApplication, # + QSystemTrayIcon, # + QFileDialog, # + QTabWidget, # + QToolBox, # + QComboBox, # + QTableWidgetItem, # + QHeaderView, # + QVBoxLayout, + QStackedWidget, + QHBoxLayout, +) +from qfluentwidgets import ( + Action, + PushButton, + LineEdit, + PasswordLineEdit, + qconfig, + TableWidget, + Pivot, + TimePicker, + ComboBox, + CheckBox, + ScrollArea, + SpinBox, + FluentIcon, + SwitchButton, + RoundMenu, + MessageBox, + MessageBoxBase, + HeaderCardWidget, + BodyLabel, + CommandBar, + setTheme, + Theme, + SwitchSettingCard, + ExpandGroupSettingCard, + SingleDirectionScrollArea, +) +from PySide6.QtUiTools import QUiLoader +from PySide6.QtGui import QIcon, QCloseEvent +from PySide6 import QtCore +from functools import partial +from typing import List, Tuple +from pathlib import Path +import os +import datetime +import json +import subprocess +import shutil +import win32gui +import win32process +import psutil +import pyautogui +import time +import winreg +import requests + +uiLoader = QUiLoader() + +from app import AppConfig, QueueConfig, MaaConfig +from app.services import Notification, CryptoHandler +from app.utils import Updater, version_text +from .Widget import ( + InputMessageBox, + LineEditSettingCard, + SpinBoxSettingCard, + TimeEditSettingCard, + NoOptionComboBoxSettingCard, +) + + +class QueueManager(QWidget): + + def __init__( + self, + config: AppConfig, + notify: Notification, + parent=None, + ): + super().__init__(parent) + + self.setObjectName("调度队列") + + self.config = config + self.notify = notify + + setTheme(Theme.AUTO) + + layout = QVBoxLayout(self) + + self.tools = CommandBar() + + self.queue_manager = QueueSettingBox(self.config, self) + + # 逐个添加动作 + self.tools.addActions( + [ + Action( + FluentIcon.ADD_TO, "新建调度队列", triggered=self.add_setting_box + ), + Action( + FluentIcon.REMOVE_FROM, + "删除调度队列", + triggered=self.del_setting_box, + ), + ] + ) + self.tools.addSeparator() + self.tools.addActions( + [ + Action( + FluentIcon.LEFT_ARROW, "向左移动", triggered=self.left_setting_box + ), + Action( + FluentIcon.RIGHT_ARROW, "向右移动", triggered=self.right_setting_box + ), + ] + ) + self.tools.addSeparator() + self.tools.addAction(Action(FluentIcon.ROTATE, "刷新", triggered=self.refresh)) + + layout.addWidget(self.tools) + layout.addWidget(self.queue_manager) + + def add_setting_box(self): + """添加一个调度队列""" + + index = len(self.queue_manager.search_queue()) + 1 + + qconfig.load( + self.config.app_path / f"config/QueueConfig/调度队列_{index}.json", + self.config.queue_config, + ) + + self.config.queue_config.set(self.config.queue_config.queueSet_Name, "") + self.config.queue_config.set(self.config.queue_config.queueSet_Enabled, False) + + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_0, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_0, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_1, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_1, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_2, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_2, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_3, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_3, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_4, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_4, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_5, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_5, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_6, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_6, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_7, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_7, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_8, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_8, "00:00") + self.config.queue_config.set(self.config.queue_config.time_TimeEnabled_9, False) + self.config.queue_config.set(self.config.queue_config.time_TimeSet_9, "00:00") + + self.config.queue_config.set(self.config.queue_config.queue_Member_1, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_2, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_3, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_4, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_5, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_6, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_7, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_8, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_9, "禁用") + self.config.queue_config.set(self.config.queue_config.queue_Member_10, "禁用") + + self.config.queue_config.save() + + self.queue_manager.add_QueueSettingBox(index) + self.queue_manager.switch_SettingBox(index) + + def del_setting_box(self): + """删除一个调度队列实例""" + + name = self.queue_manager.pivot.currentRouteKey() + + if name == None: + return None + + choice = MessageBox( + "确认", + f"确定要删除 {name} 吗?", + self, + ) + if choice.exec(): + + queue_list = self.queue_manager.search_queue() + move_list = [_ for _ in queue_list if int(_[0][3:]) > int(name[3:])] + + index = max(int(name[3:]) - 1, 1) + + self.queue_manager.clear_SettingBox() + + os.remove(self.config.app_path / f"config/QueueConfig/{name}.json") + for queue in move_list: + if ( + self.config.app_path / f"config/QueueConfig/{queue[0]}.json" + ).exists(): + ( + self.config.app_path / f"config/QueueConfig/{queue[0]}.json" + ).rename( + self.config.app_path + / f"config/QueueConfig/调度队列_{int(queue[0][5:])-1}.json", + ) + + self.queue_manager.show_SettingBox(index) + + def left_setting_box(self): + """向左移动调度队列实例""" + + name = self.queue_manager.pivot.currentRouteKey() + + if name == None: + return None + + index = int(name[5:]) + + if index == 1: + return None + + self.queue_manager.clear_SettingBox() + + (self.config.app_path / f"config/QueueConfig/调度队列_{index}.json").rename( + self.config.app_path / f"config/QueueConfig/调度队列_0.json", + ) + shutil.move( + str(self.config.app_path / f"config/QueueConfig/调度队列_{index-1}.json"), + str(self.config.app_path / f"config/QueueConfig/调度队列_{index}.json"), + ) + (self.config.app_path / f"config/QueueConfig/调度队列_0.json").rename( + self.config.app_path / f"config/QueueConfig/调度队列_{index-1}.json", + ) + + self.queue_manager.show_SettingBox(index - 1) + + def right_setting_box(self): + """向右移动调度队列实例""" + + name = self.queue_manager.pivot.currentRouteKey() + + if name == None: + return None + + queue_list = self.queue_manager.search_queue() + index = int(name[5:]) + + if index == len(queue_list): + return None + + self.queue_manager.clear_SettingBox() + + (self.config.app_path / f"config/QueueConfig/调度队列_{index}.json").rename( + self.config.app_path / f"config/QueueConfig/调度队列_0.json", + ) + (self.config.app_path / f"config/QueueConfig/调度队列_{index+1}.json").rename( + self.config.app_path / f"config/QueueConfig/调度队列_{index}.json", + ) + (self.config.app_path / f"config/QueueConfig/调度队列_0.json").rename( + self.config.app_path / f"config/QueueConfig/调度队列_{index+1}.json", + ) + + self.queue_manager.show_SettingBox(index + 1) + + def refresh(self): + """刷新调度队列界面""" + + index = int(self.queue_manager.pivot.currentRouteKey()[5:]) + self.queue_manager.clear_SettingBox() + self.queue_manager.show_SettingBox(index) + + +class QueueSettingBox(QWidget): + + def __init__(self, config: AppConfig, parent=None): + super().__init__(parent) + + self.setObjectName("调度队列管理") + self.config = config + + self.pivot = Pivot(self) + self.stackedWidget = QStackedWidget(self) + self.Layout = QVBoxLayout(self) + + self.script_list: List[QueueMemberSettingBox] = [] + + self.Layout.addWidget(self.pivot, 0, QtCore.Qt.AlignHCenter) + self.Layout.addWidget(self.stackedWidget) + self.Layout.setContentsMargins(0, 0, 0, 0) + + self.pivot.currentItemChanged.connect( + lambda index: self.switch_SettingBox(int(index[5:]), if_chang_pivot=False) + ) + + self.show_SettingBox(1) + + def show_SettingBox(self, index) -> None: + """加载所有子界面""" + + queue_list = self.search_queue() + + for queue in queue_list: + self.add_QueueSettingBox(int(queue[0][5:])) + + self.switch_SettingBox(index) + + def switch_SettingBox(self, index: int, if_chang_pivot: bool = True) -> None: + """切换到指定的子界面""" + + queue_list = self.search_queue() + + if index > len(queue_list): + return None + + qconfig.load( + self.config.app_path + / f"config/QueueConfig/{self.script_list[index-1].objectName()}.json", + self.config.queue_config, + ) + + if if_chang_pivot: + self.pivot.setCurrentItem(self.script_list[index - 1].objectName()) + self.stackedWidget.setCurrentWidget(self.script_list[index - 1]) + + def clear_SettingBox(self) -> None: + """清空所有子界面""" + + for sub_interface in self.script_list: + self.stackedWidget.removeWidget(sub_interface) + sub_interface.deleteLater() + self.script_list.clear() + self.pivot.clear() + + def add_QueueSettingBox(self, uid: int) -> None: + """添加一个调度队列设置界面""" + + maa_setting_box = QueueMemberSettingBox(self.config, uid, self) + + self.script_list.append(maa_setting_box) + + self.stackedWidget.addWidget(self.script_list[-1]) + + self.pivot.addItem(routeKey=f"调度队列_{uid}", text=f"调度队列 {uid}") + + def search_queue(self) -> list: + """搜索所有调度队列实例""" + + queue_list = [] + + if (self.config.app_path / "config/QueueConfig").exists(): + for json_file in (self.config.app_path / "config/QueueConfig").glob( + "*.json" + ): + with json_file.open("r", encoding="utf-8") as f: + info = json.load(f) + queue_list.append([json_file.stem, info["QueueSet"]["Name"]]) + + return queue_list + + +class QueueMemberSettingBox(QWidget): + + def __init__(self, config: AppConfig, uid: int, parent=None): + super().__init__(parent) + + self.setObjectName(f"调度队列_{uid}") + + self.config = config + + layout = QVBoxLayout() + + scrollArea = ScrollArea() + scrollArea.setWidgetResizable(True) + + content_widget = QWidget() + content_layout = QVBoxLayout(content_widget) + + self.queue_set = self.QueueSetSettingCard(self, self.config.queue_config) + self.time = self.TimeSettingCard(self, self.config.queue_config) + self.task = self.TaskSettingCard(self, self.config) + + content_layout.addWidget(self.queue_set) + content_layout.addWidget(self.time) + content_layout.addWidget(self.task) + content_layout.addStretch(1) + + scrollArea.setWidget(content_widget) + + layout.addWidget(scrollArea) + + self.setLayout(layout) + + class QueueSetSettingCard(HeaderCardWidget): + + def __init__(self, parent=None, queue_config: QueueConfig = None): + super().__init__(parent) + + self.setTitle("队列设置") + + self.queue_config = queue_config + + Layout = QVBoxLayout() + + self.card_Name = LineEditSettingCard( + "调度队列名称", + FluentIcon.EDIT, + "调度队列名称", + "用于标识调度队列的名称", + self.queue_config.queueSet_Name, + ) + self.card_Enable = SwitchSettingCard( + FluentIcon.HOME, + "状态", + "调度队列状态", + self.queue_config.queueSet_Enabled, + ) + + Layout.addWidget(self.card_Name) + Layout.addWidget(self.card_Enable) + + self.viewLayout.addLayout(Layout) + + class TimeSettingCard(HeaderCardWidget): + + def __init__(self, parent=None, queue_config: QueueConfig = None): + super().__init__(parent) + + self.setTitle("定时设置") + + self.queue_config = queue_config + + widget_1 = QWidget() + Layout_1 = QVBoxLayout(widget_1) + widget_2 = QWidget() + Layout_2 = QVBoxLayout(widget_2) + Layout = QHBoxLayout() + + self.card_Time_0 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 1", + "", + self.queue_config.time_TimeEnabled_0, + self.queue_config.time_TimeSet_0, + ) + self.card_Time_1 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 2", + "", + self.queue_config.time_TimeEnabled_1, + self.queue_config.time_TimeSet_1, + ) + self.card_Time_2 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 3", + "", + self.queue_config.time_TimeEnabled_2, + self.queue_config.time_TimeSet_2, + ) + self.card_Time_3 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 4", + "", + self.queue_config.time_TimeEnabled_3, + self.queue_config.time_TimeSet_3, + ) + self.card_Time_4 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 5", + "", + self.queue_config.time_TimeEnabled_4, + self.queue_config.time_TimeSet_4, + ) + self.card_Time_5 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 6", + "", + self.queue_config.time_TimeEnabled_5, + self.queue_config.time_TimeSet_5, + ) + self.card_Time_6 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 7", + "", + self.queue_config.time_TimeEnabled_6, + self.queue_config.time_TimeSet_6, + ) + self.card_Time_7 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 8", + "", + self.queue_config.time_TimeEnabled_7, + self.queue_config.time_TimeSet_7, + ) + self.card_Time_8 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 9", + "", + self.queue_config.time_TimeEnabled_8, + self.queue_config.time_TimeSet_8, + ) + self.card_Time_9 = TimeEditSettingCard( + FluentIcon.STOP_WATCH, + "定时 10", + "", + self.queue_config.time_TimeEnabled_9, + self.queue_config.time_TimeSet_9, + ) + + Layout_1.addWidget(self.card_Time_0) + Layout_1.addWidget(self.card_Time_1) + Layout_1.addWidget(self.card_Time_2) + Layout_1.addWidget(self.card_Time_3) + Layout_1.addWidget(self.card_Time_4) + Layout_2.addWidget(self.card_Time_5) + Layout_2.addWidget(self.card_Time_6) + Layout_2.addWidget(self.card_Time_7) + Layout_2.addWidget(self.card_Time_8) + Layout_2.addWidget(self.card_Time_9) + Layout.addWidget(widget_1) + Layout.addWidget(widget_2) + + self.viewLayout.addLayout(Layout) + + class QueueSetSettingCard(HeaderCardWidget): + + def __init__(self, parent=None, queue_config: QueueConfig = None): + super().__init__(parent) + + self.setTitle("队列设置") + + self.queue_config = queue_config + + Layout = QVBoxLayout() + + self.card_Name = LineEditSettingCard( + "调度队列名称", + FluentIcon.EDIT, + "调度队列名称", + "用于标识调度队列的名称", + self.queue_config.queueSet_Name, + ) + self.card_Enable = SwitchSettingCard( + FluentIcon.HOME, + "状态", + "调度队列状态", + self.queue_config.queueSet_Enabled, + ) + + Layout.addWidget(self.card_Name) + Layout.addWidget(self.card_Enable) + + self.viewLayout.addLayout(Layout) + + class TaskSettingCard(HeaderCardWidget): + + def __init__(self, parent=None, config: AppConfig = None): + super().__init__(parent) + + self.setTitle("定时设置") + + self.config = config + self.queue_config = config.queue_config + + Layout = QVBoxLayout() + + member_list = self.search_member() + + self.card_Member_1 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_1, + FluentIcon.APPLICATION, + "任务实例1", + "第一个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_2 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_2, + FluentIcon.APPLICATION, + "任务实例2", + "第二个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_3 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_3, + FluentIcon.APPLICATION, + "任务实例3", + "第三个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_4 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_4, + FluentIcon.APPLICATION, + "任务实例4", + "第四个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_5 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_5, + FluentIcon.APPLICATION, + "任务实例5", + "第五个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_6 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_6, + FluentIcon.APPLICATION, + "任务实例6", + "第六个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_7 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_7, + FluentIcon.APPLICATION, + "任务实例7", + "第七个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_8 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_8, + FluentIcon.APPLICATION, + "任务实例8", + "第八个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_9 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_9, + FluentIcon.APPLICATION, + "任务实例9", + "第九个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + self.card_Member_10 = NoOptionComboBoxSettingCard( + self.queue_config.queue_Member_10, + FluentIcon.APPLICATION, + "任务实例10", + "第十个调起的脚本任务实例", + member_list[0], + member_list[1], + ) + + Layout.addWidget(self.card_Member_1) + Layout.addWidget(self.card_Member_2) + Layout.addWidget(self.card_Member_3) + Layout.addWidget(self.card_Member_4) + Layout.addWidget(self.card_Member_5) + Layout.addWidget(self.card_Member_6) + Layout.addWidget(self.card_Member_7) + Layout.addWidget(self.card_Member_8) + Layout.addWidget(self.card_Member_9) + Layout.addWidget(self.card_Member_10) + + self.viewLayout.addLayout(Layout) + + def search_member(self) -> list: + """搜索所有脚本实例""" + + member_list_name = ["禁用"] + member_list_text = ["未启用"] + + if (self.config.app_path / "config/MaaConfig").exists(): + for subdir in (self.config.app_path / "config/MaaConfig").iterdir(): + if subdir.is_dir(): + member_list_name.append(subdir.name) + with (subdir / "config.json").open("r", encoding="utf-8") as f: + info = json.load(f) + if info["MaaSet"]["Name"] != "": + member_list_text.append( + f"{subdir.name} - {info["MaaSet"]["Name"]}" + ) + else: + member_list_text.append(subdir.name) + + return [member_list_name, member_list_text] diff --git a/app/ui/setting.py b/app/ui/setting.py index d261f2b..c2b768c 100644 --- a/app/ui/setting.py +++ b/app/ui/setting.py @@ -52,13 +52,14 @@ from qfluentwidgets import ( ScrollArea, SpinBox, FluentIcon, - SwitchButton, - RoundMenu, + setTheme, + Theme, MessageBox, MessageBoxBase, HeaderCardWidget, BodyLabel, - Dialog, + InfoBar, + InfoBarPosition, SubtitleLabel, GroupHeaderCardWidget, SwitchSettingCard, @@ -88,21 +89,31 @@ import requests uiLoader = QUiLoader() from app import AppConfig -from app.services import Notification, CryptoHandler +from app.services import Notification, CryptoHandler, SystemHandler from app.utils import Updater, version_text from .Widget import InputMessageBox, LineEditSettingCard class Setting(QWidget): - def __init__(self, config: AppConfig, notify: Notification, crypto: CryptoHandler): - super(Setting, self).__init__() + def __init__( + self, + config: AppConfig, + notify: Notification, + crypto: CryptoHandler, + system: SystemHandler, + parent=None, + ): + super().__init__(parent) self.setObjectName("设置") self.config = config self.notify = notify self.crypto = crypto + self.system = system + + setTheme(Theme.AUTO) layout = QVBoxLayout() @@ -120,6 +131,8 @@ class Setting(QWidget): self.updater = UpdaterSettingCard(self, self.config) self.other = OtherSettingCard(self, self.config) + self.function.card_IfAllowSleep.checkedChanged.connect(self.system.set_Sleep) + self.start.card_IfSelfStart.checkedChanged.connect(self.system.set_SelfStart) self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD) self.updater.card_CheckUpdate.clicked.connect(self.check_version) self.other.card_Tips.clicked.connect(self.show_tips) @@ -147,7 +160,7 @@ class Setting(QWidget): while True: choice = InputMessageBox( - self, + self.parent().parent().parent(), "未检测到管理密钥,请设置您的管理密钥", "管理密钥", "密码", @@ -157,10 +170,14 @@ class Setting(QWidget): break else: choice = MessageBox( - "确认", "您没有输入管理密钥,确定要暂时跳过这一步吗?", self + "警告", + "您没有设置管理密钥,无法使用本软件,请先设置管理密钥", + self.parent().parent().parent(), ) + choice.cancelButton.hide() + choice.buttonLayout.insertStretch(1) if choice.exec(): - break + pass def change_PASSWORD(self) -> None: """修改管理密钥""" @@ -180,13 +197,20 @@ class Setting(QWidget): while True: - a = InputMessageBox( - self, "请输入新的管理密钥", "新管理密钥", "密码" + choice = InputMessageBox( + self, + "请输入新的管理密钥", + "新管理密钥", + "密码", ) - if a.exec() and a.input.text() != "": + if choice.exec() and choice.input.text() != "": # 修改管理密钥 - self.crypto.get_PASSWORD(a.input.text()) - choice = MessageBox("操作成功", "管理密钥修改成功", self) + self.crypto.get_PASSWORD(choice.input.text()) + choice = MessageBox( + "操作成功", + "管理密钥修改成功", + self, + ) choice.cancelButton.hide() choice.buttonLayout.insertStretch(1) if choice.exec(): @@ -207,7 +231,10 @@ class Setting(QWidget): while if_change: choice = InputMessageBox( - self, "请输入旧的管理密钥", "旧管理密钥", "密码" + self, + "请输入旧的管理密钥", + "旧管理密钥", + "密码", ) if choice.exec() and choice.input.text() != "": @@ -219,7 +246,10 @@ class Setting(QWidget): while True: choice = InputMessageBox( - self, "请输入新的管理密钥", "新管理密钥", "密码" + self, + "请输入新的管理密钥", + "新管理密钥", + "密码", ) if choice.exec() and choice.input.text() != "": @@ -228,7 +258,9 @@ class Setting(QWidget): data, PASSWORD_old, choice.input.text() ) choice = MessageBox( - "操作成功", "管理密钥修改成功", self + "操作成功", + "管理密钥修改成功", + self, ) choice.cancelButton.hide() choice.buttonLayout.insertStretch(1) @@ -262,7 +294,43 @@ class Setting(QWidget): if choice.exec(): break - def check_version(self): + def check_update(self) -> str: + """检查主程序版本更新,返回更新信息""" + + # 从本地版本信息文件获取当前版本信息 + with self.config.version_path.open(mode="r", encoding="utf-8") as f: + version_current = json.load(f) + main_version_current = list( + map(int, version_current["main_version"].split(".")) + ) + + # 从远程服务器获取最新版本信息 + for _ in range(3): + try: + response = requests.get( + "https://gitee.com/DLmaster_361/AUTO_MAA/raw/main/resources/version.json" + ) + version_remote = response.json() + break + except Exception as e: + err = e + time.sleep(0.1) + else: + return f"获取版本信息时出错:\n{err}" + + main_version_remote = list(map(int, version_remote["main_version"].split("."))) + + # 有版本更新 + if main_version_remote > main_version_current: + + main_version_info = f" 主程序:{version_text(main_version_current)} --> {version_text(main_version_remote)}\n" + + return f"发现新版本:\n{main_version_info} 更新说明:\n{version_remote['announcement'].replace("\n# ","\n !").replace("\n## ","\n - ").replace("\n- ","\n · ")}\n\n是否开始更新?\n\n 注意:主程序更新时AUTO_MAA将自动关闭" + + else: + return "已是最新版本~" + + def check_version(self, if_question: bool = True) -> None: """检查版本更新,调起文件下载进程""" # 从本地版本信息文件获取当前版本信息 @@ -325,13 +393,14 @@ class Setting(QWidget): ) # 询问是否开始版本更新 - choice = MessageBox( - "版本更新", - f"发现新版本:\n{main_version_info}{updater_version_info} 更新说明:\n{version_remote['announcement'].replace("\n# ","\n !").replace("\n## ","\n - ").replace("\n- ","\n · ")}\n\n是否开始更新?\n\n 注意:主程序更新时AUTO_MAA将自动关闭", - self, - ) - if not choice.exec(): - return None + if if_question: + choice = MessageBox( + "版本更新", + f"发现新版本:\n{main_version_info}{updater_version_info} 更新说明:\n{version_remote['announcement'].replace("\n# ","\n !").replace("\n## ","\n - ").replace("\n- ","\n · ")}\n\n是否开始更新?\n\n 注意:主程序更新时AUTO_MAA将自动关闭", + self, + ) + if not choice.exec(): + return None # 更新更新器 if updater_version_remote > updater_version_current: @@ -354,7 +423,15 @@ class Setting(QWidget): # 无版本更新 else: - self.notify.push_notification("已是最新版本~", " ", " ", 3) + InfoBar.success( + title="更新检查", + content="已是最新版本~", + orient=QtCore.Qt.Horizontal, + isClosable=True, + position=InfoBarPosition.TOP_RIGHT, + duration=3000, + parent=self, + ) def update_main(self): """更新主程序""" @@ -388,11 +465,11 @@ class FunctionSettingCard(HeaderCardWidget): Layout = QVBoxLayout() - self.card_IfSleep = SwitchSettingCard( + self.card_IfAllowSleep = SwitchSettingCard( icon=FluentIcon.PAGE_RIGHT, title="启动时阻止系统休眠", content="仅阻止电脑自动休眠,不会影响屏幕是否熄灭", - configItem=self.config.function_IfSleep, + configItem=self.config.function_IfAllowSleep, ) self.card_IfSilence = SwitchSettingCard( @@ -403,7 +480,7 @@ class FunctionSettingCard(HeaderCardWidget): ) # 添加各组到设置卡中 - Layout.addWidget(self.card_IfSleep) + Layout.addWidget(self.card_IfAllowSleep) Layout.addWidget(self.card_IfSilence) self.viewLayout.addLayout(Layout) diff --git a/main.py b/main.py index 9bbb470..51163da 100644 --- a/main.py +++ b/main.py @@ -32,6 +32,7 @@ import sys from app.config import AppConfig from app.services.notification import Notification from app.services.security import CryptoHandler +from app.services.system import SystemHandler from app.ui.main_window import AUTO_MAA if __name__ == "__main__": @@ -39,12 +40,13 @@ if __name__ == "__main__": config = AppConfig() notify = Notification(config) crypto = CryptoHandler(config) + system = SystemHandler(config) application = QApplication(sys.argv) translator = FluentTranslator() application.installTranslator(translator) - window = AUTO_MAA(config=config, notify=notify, crypto=crypto) + window = AUTO_MAA(config=config, notify=notify, crypto=crypto, system=system) window.setting.check_PASSWORD() sys.exit(application.exec()) diff --git a/resources/gui/main.ui b/resources/gui/main.ui index eb11ac9..6bf706e 100644 --- a/resources/gui/main.ui +++ b/resources/gui/main.ui @@ -1279,7 +1279,7 @@ - + AUTO_MAA启动时禁止电脑休眠