-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMainWindow.py
More file actions
402 lines (363 loc) · 13 KB
/
MainWindow.py
File metadata and controls
402 lines (363 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
"""
主窗口类
"""
from dataclasses import dataclass
import sys
from typing import Self
from json import load, dump
from pathlib import Path
import keyboard
from PySide6.QtCore import Signal, Slot, Qt, QEvent
from PySide6.QtWidgets import QApplication, QMessageBox
from PySide6.QtGui import QShortcut, QKeySequence
from loguru import logger
import classes
from UIs import settings
from classes.WindowCloser import kill_windows
from public_functions import *
__all__ = ["MainWindow"]
@dataclass
class Config:
hide_tray: int
forKillExe: list[str]
forKillWindowTitle: list[str]
random_time: list[int]
hold_time: int
# noinspection PyAttributeOutsideInit
class MainWindow(classes.basic_classes.MyQWidget.MyQWidget):
"""
自定义主窗口类
"""
# 定义应用信号
apply_signal = Signal()
status_changed_signal = Signal()
hide_window_signal = Signal()
ensure_quit_signal = Signal()
@logger.catch
def __init__(self, app: QApplication):
super().__init__(False)
# 初始化ui
self.ui = settings.Ui_Form()
self.ui.setupUi(self) # type: ignore
self.app = app
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
set_window_size(window=self, application=app)
# 实例化关闭窗口方法
self.kill_windows = kill_windows
# 初始化日志管理类
self.logger_manager = classes.LogManager(self)
# 软件激活状态
self.status: bool = True
# 退出确认
self.exit_asking: bool = False
# 默认配置文件
self.default_config = Config(
hide_tray=0,
forKillExe=[
"EXCEL.Title",
"EasiCamera.exe",
"POWERPNT.Title",
"WINWORD.Title",
"et.exe",
"wps.exe",
"wpscloudsvr.exe",
],
forKillWindowTitle=[
".pdf",
".ppt",
".pptx",
".xlsx",
"192.168.",
"分享的图片",
"聊天记录",
"文档文件",
],
random_time=[0, 30],
hold_time=0,
)
self.config: Config = Config(**self.default_config.__dict__)
# 下课时间表
self.clock_json_path: str = current_path(relative_path="clock.json", mode="exe")
self.time_config: list[list[classes.basic_classes.Clock.Clock]] = (
classes.DayManager.get_config(config_json=self.clock_json_path)
)
# 软件生命状态
self.life: bool = True
# 测试模式
self.test: bool = False
# 配置文件路径
self.config_json_path: str = current_path(
relative_path="config.json", mode="exe"
)
logger.debug(f"配置文件路径: {self.clock_json_path}")
logger.debug(f"配置文件路径: {self.config_json_path}")
# 设置图片文件路径
self.files: list[str] = [
str(object=Path(current_path(relative_path=i)).resolve())
for i in [
r"icons\active.png",
r"icons\inactive.png",
r"icons\hide_tray.png",
r"icons\active.ico",
]
]
# region 处理配置文件
if Path(self.config_json_path).exists():
with open(file=self.config_json_path, encoding="utf-8") as f:
self.load_config(configure=load(fp=f)) # type: ignore
self.show_config()
# endregion
self.ensure_quit_signal.connect(self.ensure_quit)
self.set_widgets()
self.son_classes_init()
# region 主窗口类方法s
# region 重写的方法s
@logger.catch
def hideEvent(self, event: QEvent, /):
self.hide_window_signal.emit()
event.accept()
@logger.catch
def closeEvent(self, event: QEvent, /):
"""
窗口收到关闭事件时隐藏设置窗口
:param event: 事件对象
:return: 无
"""
self.showMinimized()
event.ignore()
# endregion
# region 槽函数s
@Slot()
@logger.catch
def change_status(self):
"""
切换启用状态
:return:
"""
self.status ^= True
self.ui.is_active.setText("工作中" if self.status else "睡觉中")
self.tray_icon.change_tray_state()
self.status_manager.ui.status.setText(str(self.status))
@Slot()
@logger.catch
def strong_hide_action(self, state: bool):
"""
关联强隐藏托盘图标状态
:param state: 强隐藏状态
:return:
"""
self.ui.if_tray_hide.setDisabled(state)
self.ui.if_tray_hide.setChecked(True)
@Slot()
@logger.catch
def set_flushable(self, *args, **kwargs): # type: ignore
"""
设置应用按钮为可点击状态
:return:
"""
self.ui.apply_button.setEnabled(True)
@Slot()
@logger.catch
def quit_app(self):
"""
退出软件
:return: 无
"""
self.life = False
keyboard.unhook_all()
logger.debug(f"当前软件生命状态: {self.life}")
self.status_manager.destroy()
self.app.quit()
sys.exit()
# endregion
@logger.catch
def ensure_quit(self):
"""
确认退出应用
:return:
"""
if not self.exit_asking:
self.exit_asking = True
reply = QMessageBox.question(
self,
"确认退出",
"真的要退出吗?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No,
)
if reply == QMessageBox.StandardButton.Yes:
self.quit_app()
self.exit_asking = False
@logger.catch
def son_classes_init(self):
"""
初始化子类
:return: 无
"""
# region 初始化状态管理器
self.status_manager = classes.basic_classes.StatusManager.StatusManager(self)
self.status_changed_signal.connect(self.change_status)
# endregion
# region 初始化热键管理器
self.hot_key_manager = classes.HotKeyManager(self)
QShortcut(QKeySequence("Alt+A"), self).activated.connect(
lambda: (
self.flash_state_changed() if self.ui.apply_button.isEnabled() else None
)
)
QShortcut(QKeySequence("Ctrl+Q"), self).activated.connect(self.quit_app)
# endregion
# region 初始化托盘图标
self.tray_icon = classes.Tray(self)
self.tray_icon.flash_tray()
# endregion
# region 初始化weekday管理类
self.day_manager = classes.DayManager(self, self.ui.day, self.time_config)
# endregion
# region 初始化时间列表管理器
self.time_manager = classes.TimeManager(
self, self.ui.time_list, self.day_manager.day
)
# endregion
# region 初始化待杀应用窗口类
self.add_executable = classes.EXE.AddEXE.AddEXE(p_window=self)
self.edit_executable = classes.EXE.EditEXE.EditEXE(p_window=self)
# endregion
# region 初始化待杀窗口标题类
self.add_title = classes.Title.AddTitle.AddTitle(p_window=self)
self.edit_title = classes.Title.EditTitle.EditTitle(p_window=self)
# endregion
# region 初始化消息提示类
self.warner = classes.MessageShower(p_window=self)
# endregion
# region 初始化待杀程序列表
self.ui.for_kill_list.addItems(self.config.forKillExe)
self.ui.for_close_title.addItems(self.config.forKillWindowTitle)
logger.debug("已加载待杀程序列表")
# endregion
@logger.catch
def set_widgets(self):
"""
设置窗口控件
:return: 无
"""
self.ui.if_tray_hide.setChecked(bool(self.config.hide_tray))
self.ui.if_strong_hide.setChecked(self.config.hide_tray == 2)
self.ui.if_tray_hide.setDisabled(self.ui.if_strong_hide.isChecked())
self.ui.a.setValue(self.config.random_time[0])
self.ui.b.setValue(self.config.random_time[1])
self.ui.hold_seconds.setValue(self.config.hold_time)
for widget in [self.ui.if_tray_hide, self.ui.if_strong_hide]:
widget.stateChanged.connect(self.set_flushable)
for widget in [
self.ui.a,
self.ui.b,
self.ui.hold_seconds,
]:
widget.valueChanged.connect(self.set_flushable)
self.ui.apply_button.clicked.connect(self.flash_state_changed)
self.ui.is_active.clicked.connect(self.status_changed_signal.emit)
self.ui.test_button.clicked.connect(lambda: setattr(self, "test", True))
self.ui.exit_button.clicked.connect(self.quit_app)
self.ui.if_strong_hide.stateChanged.connect(self.strong_hide_action)
self.ui.close_button.clicked.connect(self.close)
self.ui.minimize_button.clicked.connect(self.showMinimized)
@logger.catch
def load_config(self, configure: dict): # type: ignore
"""
加载配置
:param configure: 配置字典
:return: 无
"""
self.config.hide_tray = configure.get("hide_tray", self.default_config.hide_tray) # type: ignore
self.config.forKillExe = configure.get("forKillExe", self.default_config.forKillExe) # type: ignore
self.config.random_time = configure.get( # type: ignore
"random_time", self.default_config.random_time # type: ignore
)
self.config.hold_time = configure.get("hold_time", self.default_config.hold_time) # type: ignore
self.config.forKillWindowTitle = configure.get( # type: ignore
"forKillWindowTitle", self.default_config.forKillWindowTitle # type: ignore
)
@logger.catch
def show_config(self):
"""
显示配置
:return: 无
"""
QApplication.processEvents()
logger.debug(f"当前托盘图标透明(0显1透2隐): {self.config.hide_tray}")
logger.debug(f"当前待杀程序: {self.config.forKillExe}")
logger.debug(f"当前随机时间: {self.config.random_time}")
logger.debug(f"当前持续时间: {self.config.hold_time}")
logger.debug(f"当前待杀应用窗口标题: {self.config.forKillWindowTitle}")
@logger.catch
def show_window(self: Self):
"""
显示窗口(获取焦点+活动+前置)
:return:
"""
self.setVisible(True)
self.showNormal()
self.raise_()
self.activateWindow()
self.setFocus()
@logger.catch
def change_window_state(self, hide: bool = False):
"""
显示或隐藏设置窗口
:param hide:
:return:
"""
if hide:
self.showMinimized()
else:
self.show_window()
@logger.catch
def flash_state_changed(self):
"""
刷新配置
:return: 无
"""
QApplication.processEvents()
# 将当前属性设置为GUI控件的值
# region 设置待杀程序列表 和 待杀应用程序窗口标题列表
self.config.forKillExe = flash_list_widget(list_widget=self.ui.for_kill_list)
self.config.forKillWindowTitle = flash_list_widget(
list_widget=self.ui.for_close_title
)
# endregion
self.config.hide_tray = (
2
if self.ui.if_strong_hide.isChecked()
else 1 if self.ui.if_tray_hide.isChecked() else 0
)
self.config.hold_time = self.ui.hold_seconds.value()
# 判断随机时间范围是否正确(whether a<=b or not)
if self.ui.a.value() > self.ui.b.value():
# 不正确,则将两个输入框的值调转
self.config.random_time[0] = self.ui.b.value()
self.config.random_time[1] = self.ui.a.value()
self.ui.a.setValue(self.config.random_time[0])
self.ui.b.setValue(self.config.random_time[1])
else:
# 如果正确,则将两个输入框的值设置为新的值
self.config.random_time[0] = self.ui.a.value()
self.config.random_time[1] = self.ui.b.value()
with open(file=self.config_json_path, mode="w") as f:
dump(
obj={
"hide_tray": self.config.hide_tray,
"forKillExe": self.config.forKillExe,
"random_time": self.config.random_time,
"hold_time": self.config.hold_time,
"forKillWindowTitle": self.config.forKillWindowTitle,
},
fp=f,
indent=4,
)
self.show_config()
# 将应用按钮设置为禁用状态
self.ui.apply_button.setDisabled(True)
# 发送应用信号
self.apply_signal.emit()
# endregion