303 lines
12 KiB
Python
303 lines
12 KiB
Python
import json
|
||
from shutil import copy
|
||
from random import choice
|
||
from pathlib import Path
|
||
import sys
|
||
import requests
|
||
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTabWidget, QListWidget, QStackedWidget, QCheckBox, QSpinBox, QToolBox, QLineEdit, QTableWidget, QTreeWidget, QCalendarWidget, QMessageBox, QToolBar, QSizePolicy, QMainWindow, QStatusBar, QListWidgetItem
|
||
from PySide6.QtCore import Qt, QTime, QSize, QRect,QEvent, QThread
|
||
from PySide6.QtGui import QCursor, QFont, QIcon, QImage, QPixmap, QShortcut, QAction, QKeySequence, QResizeEvent
|
||
from codes.common import clibs, db_operation
|
||
from codes.ui.widget_bg_ui import WidgetWithBg
|
||
from codes.common.worker import Worker
|
||
from typing import Callable, Any
|
||
from codes.common.exception_handler import handle_exception
|
||
|
||
|
||
class MainWindow(QMainWindow):
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.predos()
|
||
self.init_ui()
|
||
self.setup_slot()
|
||
self.setup_sc()
|
||
|
||
def predos(self):
|
||
self.m = Path(__file__).stem
|
||
self.home_overlay = None
|
||
db_operation.db_backup()
|
||
clibs.conn, clibs.cursor = db_operation.db_conn()
|
||
|
||
def init_ui(self):
|
||
self.setMinimumSize(clibs.win_width, clibs.win_height)
|
||
self.resize(clibs.win_width, clibs.win_height)
|
||
self.setWindowTitle("Toolbox")
|
||
self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico"))
|
||
self.setFont(QFont("Consolas", 14))
|
||
# 任务栏/主窗口/状态栏
|
||
self.toolBar = QToolBar()
|
||
self.addToolBar(self.toolBar)
|
||
self.toolBar.setMovable(False)
|
||
self.centralW = QWidget()
|
||
self.setCentralWidget(self.centralW)
|
||
self.statusBar = QStatusBar()
|
||
self.statusBar.setStyleSheet("""
|
||
QStatusBar {
|
||
background: #8B8989; /* 背景色 */
|
||
color: #000000; /* 文字色 */
|
||
border: none;
|
||
font: 14px "Consolas";
|
||
}
|
||
""")
|
||
self.setStatusBar(self.statusBar)
|
||
|
||
# toolbar
|
||
# homepage
|
||
self.ac_homepage = QAction()
|
||
self.ac_homepage.setMenuRole(QAction.MenuRole.NoRole)
|
||
self.ac_homepage.setStatusTip("Go to home page")
|
||
self.ac_homepage.setToolTip("Ctrl+Alt+H")
|
||
self.ac_homepage.setText("主页")
|
||
self.ac_homepage.setShortcut(QKeySequence("Ctrl+Alt+H"))
|
||
self.toolBar.addAction(self.ac_homepage)
|
||
# setting
|
||
self.ac_setting = QAction()
|
||
self.ac_setting.setMenuRole(QAction.MenuRole.NoRole)
|
||
self.ac_setting.setStatusTip("Go to setting page")
|
||
self.ac_setting.setToolTip("Ctrl+Alt+S")
|
||
self.ac_setting.setText("设置")
|
||
self.ac_setting.setShortcut(QKeySequence("Ctrl+Alt+S"))
|
||
self.toolBar.addAction(self.ac_setting)
|
||
|
||
# log
|
||
self.ac_log = QAction()
|
||
self.ac_log.setMenuRole(QAction.MenuRole.NoRole)
|
||
self.ac_log.setStatusTip("Go to log page")
|
||
self.ac_log.setToolTip("Ctrl+Alt+L")
|
||
self.ac_log.setText("日志")
|
||
self.ac_log.setShortcut(QKeySequence("Ctrl+Alt+L"))
|
||
self.toolBar.addAction(self.ac_log)
|
||
|
||
# about
|
||
self.ac_about = QAction()
|
||
self.ac_about.setMenuRole(QAction.MenuRole.NoRole)
|
||
self.ac_about.setStatusTip("Go to about page")
|
||
self.ac_about.setToolTip("Ctrl+Alt+A")
|
||
self.ac_about.setText("关于")
|
||
self.ac_about.setShortcut(QKeySequence("Ctrl+Alt+A"))
|
||
self.toolBar.addAction(self.ac_about)
|
||
|
||
layout_h = QHBoxLayout()
|
||
# list widget
|
||
self.listW = QListWidget()
|
||
for item in clibs.listW_items:
|
||
_ = QListWidgetItem(item)
|
||
_.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
||
self.listW.addItem(_)
|
||
|
||
layout_h.addWidget(self.listW)
|
||
|
||
# stacked widget 1x: 10为一级按钮页,其余为二级按钮页,2-9同理 | 0x. 日志/设置/关于等页面
|
||
self.stackedW =QStackedWidget()
|
||
self.w00_setting = QWidget()
|
||
self.stackedW.addWidget(self.w00_setting)
|
||
self.lb_test00 = QLabel("testing text on setting widget", parent=self.w00_setting)
|
||
|
||
self.w08_log = QWidget()
|
||
self.stackedW.addWidget(self.w08_log)
|
||
self.lb_test08 = QLabel("testing text on log widget", parent=self.w08_log)
|
||
|
||
self.w09_about = QWidget()
|
||
self.stackedW.addWidget(self.w09_about)
|
||
self.lb_test09 = QLabel("testing text on about widget", parent=self.w09_about)
|
||
|
||
self.w10_practical = QWidget()
|
||
self.stackedW.addWidget(self.w10_practical)
|
||
self.lb_test10 = QLabel("testing text on practical widget", parent=self.w10_practical)
|
||
|
||
self.w20_efficiency = QWidget()
|
||
self.stackedW.addWidget(self.w20_efficiency)
|
||
self.lb_test20 = QLabel("testing text on efficiency widget", parent=self.w20_efficiency)
|
||
|
||
self.w30_financial = QWidget()
|
||
self.stackedW.addWidget(self.w30_financial)
|
||
self.lb_test30 = QLabel("testing text on financial widget", parent=self.w30_financial)
|
||
|
||
layout_h.addWidget(self.stackedW)
|
||
layout_h.setStretch(0, 1)
|
||
layout_h.setStretch(1, 5)
|
||
self.centralW.setLayout(layout_h)
|
||
|
||
def setup_slot(self):
|
||
self.ac_homepage.triggered.connect(self.ac_hp)
|
||
self.ac_setting.triggered.connect(self.ac_sp)
|
||
self.ac_log.triggered.connect(self.ac_lp)
|
||
self.ac_about.triggered.connect(self.ac_ap)
|
||
self.f11_sc = QShortcut(QKeySequence("F11"), self)
|
||
self.f11_sc.activated.connect(self.sc_F11)
|
||
# self.listW.currentItemChanged.connect(self.change_stackedW)
|
||
self.listW.itemClicked.connect(self.change_stackedW)
|
||
|
||
def setup_sc(self, stat: bool = True):
|
||
if stat:
|
||
self.ac_homepage.setShortcut(QKeySequence("Ctrl+Alt+H"))
|
||
self.f11_sc.setEnabled(True)
|
||
else:
|
||
self.ac_homepage.setShortcut(QKeySequence())
|
||
self.f11_sc.setEnabled(False)
|
||
|
||
def ac_hp(self):
|
||
def get_files(dir_path):
|
||
folder = Path(dir_path)
|
||
files = [p for p in folder.rglob("*") if p.is_file()]
|
||
return choice(files), files
|
||
|
||
def del_repeat_proverb(proverbs: list):
|
||
_proverbs = []
|
||
for proverb in proverbs:
|
||
if proverb not in _proverbs:
|
||
_proverbs.append(proverb)
|
||
return _proverbs
|
||
|
||
def get_resources():
|
||
# background image
|
||
bing = "https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=8"
|
||
req = requests.get(bing)
|
||
res = req.json()
|
||
_, files = get_files(f"{clibs.base_path}/assets/media/bg")
|
||
image_names = []
|
||
for file in files:
|
||
image_names.append(file.name.removesuffix(".jpg"))
|
||
for image in res["images"]:
|
||
startdate = image["startdate"]
|
||
if startdate in image_names:
|
||
continue
|
||
else:
|
||
image_url = f"""https://www.bing.com{image["url"]}"""
|
||
file = Path(f"{clibs.base_path}/assets/media/bg/{startdate}.jpg")
|
||
try:
|
||
req = requests.get(image_url, stream=True, timeout=10)
|
||
with open(file, "wb") as f:
|
||
for chunk in req.iter_content(chunk_size=8192):
|
||
f.write(chunk)
|
||
except Exception as e:
|
||
pass
|
||
# proverbs
|
||
hitokoto = "https://v1.hitokoto.cn/"
|
||
proverbs = []
|
||
try:
|
||
req = requests.get(hitokoto)
|
||
with open(f"{clibs.base_path}/assets/media/hitokoto.json", mode="rt", encoding="utf-8") as f:
|
||
proverbs = json.load(f)
|
||
proverbs.append(eval(req.text))
|
||
proverbs = del_repeat_proverb(proverbs)
|
||
with open(f"{clibs.base_path}/assets/media/hitokoto.json", mode="wt", encoding="utf-8") as f:
|
||
json.dump(proverbs, f, ensure_ascii=False)
|
||
except Exception as e:
|
||
pass
|
||
|
||
@handle_exception(self.m)
|
||
def change_resources():
|
||
# avatar
|
||
src, _ = get_files(f"{clibs.base_path}/assets/media/avatar")
|
||
dst = f"{clibs.base_path}/assets/media/avatar.jpg"
|
||
copy(src, dst)
|
||
# proverbs
|
||
with open(f"{clibs.base_path}/assets/media/hitokoto.json", mode="r", encoding="utf-8") as f:
|
||
proverbs = json.load(f)
|
||
res = choice(proverbs)
|
||
sentence = res["hitokoto"]
|
||
from_where = res["from"]
|
||
from_who = res["from_who"]
|
||
clibs.proverb = f"{sentence}\t\t※⌈{from_where}⌋ | {from_who}※"
|
||
# bg
|
||
src, _ = get_files(f"{clibs.base_path}/assets/media/bg")
|
||
dst = f"{clibs.base_path}/assets/media/bg.jpg"
|
||
copy(src, dst)
|
||
|
||
def gen_page():
|
||
self.setup_sc(False)
|
||
self.home_overlay = WidgetWithBg(parent=self)
|
||
self.home_overlay.on_closed.connect(self.exit_overlay)
|
||
self.home_overlay.on_full_screen.connect(self.toggle_full_screen)
|
||
self.home_overlay.show()
|
||
width, height = self.width(), self.height()
|
||
if width > clibs.win_width:
|
||
self.resize(self.width()-1, self.height()-1)
|
||
else:
|
||
self.resize(clibs.win_width+1, clibs.win_height+1)
|
||
|
||
change_resources()
|
||
self.launch_get_resources(get_resources)
|
||
gen_page()
|
||
|
||
def ac_sp(self):
|
||
self.stackedW.setCurrentWidget(self.w00_setting)
|
||
|
||
def ac_lp(self):
|
||
self.stackedW.setCurrentWidget(self.w08_log)
|
||
|
||
def ac_ap(self):
|
||
self.stackedW.setCurrentWidget(self.w09_about)
|
||
|
||
def toggle_full_screen(self):
|
||
if self.isFullScreen():
|
||
self.setWindowFlags(self.windowFlags() ^ Qt.WindowType.WindowStaysOnTopHint)
|
||
self.show()
|
||
self.showMaximized()
|
||
else:
|
||
self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
|
||
self.showFullScreen()
|
||
|
||
def exit_overlay(self):
|
||
self.setup_sc(True)
|
||
self.home_overlay = None
|
||
if self.isFullScreen():
|
||
self.setWindowFlags(self.windowFlags() ^ Qt.WindowType.WindowStaysOnTopHint)
|
||
self.show()
|
||
self.showMaximized()
|
||
|
||
def change_stackedW(self, w_item):
|
||
if w_item.text() == "实用工具":
|
||
self.stackedW.setCurrentWidget(self.w10_practical)
|
||
elif w_item.text() == "效率提升":
|
||
self.stackedW.setCurrentWidget(self.w20_efficiency)
|
||
elif w_item.text() == "财务分析":
|
||
self.stackedW.setCurrentWidget(self.w30_financial)
|
||
|
||
def launch_get_resources(self, func, on_anything: Callable[..., Any] = None, *args, **kwargs):
|
||
self.td_get_resources = Worker(func, *args, **kwargs)
|
||
self.td_get_resources.started.connect(lambda: None)
|
||
self.td_get_resources.result.connect(lambda: None)
|
||
self.td_get_resources.error.connect(lambda: None)
|
||
self.td_get_resources.finished.connect(lambda: None)
|
||
self.td_get_resources.start()
|
||
|
||
def sc_F11(self):
|
||
if not self.home_overlay:
|
||
self.ac_hp()
|
||
self.toggle_full_screen()
|
||
|
||
def resizeEvent(self, event: QResizeEvent):
|
||
super().resizeEvent(event)
|
||
if self.home_overlay:
|
||
self.home_overlay.setGeometry(self.rect())
|
||
|
||
def closeEvent(self, event):
|
||
if self.isFullScreen():
|
||
event.ignore()
|
||
return
|
||
reply = QMessageBox.question(self, "退出", "\n程序可能在运行,确定要退出吗?")
|
||
if reply == QMessageBox.StandardButton.Yes:
|
||
db_operation.db_close()
|
||
event.accept()
|
||
else:
|
||
event.ignore()
|
||
|
||
|
||
if __name__ == '__main__':
|
||
app = QApplication(sys.argv)
|
||
window = MainWindow()
|
||
window.show()
|
||
sys.exit(app.exec())
|