Files
Projects/gui/main.py

224 lines
8.4 KiB
Python

import json
import random
import sys
from typing import Callable, Any
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QMainWindow, QHBoxLayout, QVBoxLayout, QLineEdit, QLabel
from PySide6.QtGui import QIcon, QPixmap, QShortcut, QResizeEvent, QFont, QKeySequence
from PySide6.QtCore import Qt,QSize
from codes.ui.login import Ui_login
from codes.ui.app import Ui_App
from codes.common.worker import Worker
from codes.common import clibs
from codes.common.secure_encrypt import PassCipher
from codes.common import db_operation
class LoginWindow(QWidget, Ui_login):
def __init__(self):
super().__init__()
self.setupUi(self)
self.pre_dos()
def pre_dos(self):
self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico"))
self.lb_logo.setPixmap(QPixmap(f"{clibs.base_path}/assets/media/avatar.png"))
self.lb_logo.setScaledContents(True)
# bindings
QShortcut("Esc", self).activated.connect(self.close)
self.pb_login.clicked.connect(self.login)
self.pb_cancel.clicked.connect(self.close)
self.le_password.returnPressed.connect(self.login)
def login(self):
def login_failed():
QMessageBox.warning(self, "告警", "\n用户名或密码不正确,请重新输入!")
self.le_username.setText("")
self.le_password.setText("")
def validate_login():
nonlocal username, password
with open(f"{clibs.base_path}/assets/conf/config.json", mode="rt", encoding="utf-8") as f_conf:
clibs.account = json.load(f_conf)
if username != clibs.account["username"] or len(password) < clibs.account["minimum_password_length"]:
login_failed()
return False
salt = PassCipher.gen_salt(password)
cipher = PassCipher(salt)
# password_encrypt = cipher.encrypt(password)
# print(f"password_encrypt = {password_encrypt}")
# exit()
try:
decrypt_password = cipher.decrypt(clibs.account["login_password"])
except ValueError:
login_failed()
return False
if password != decrypt_password:
login_failed()
return False
self.mainWindow = MainWindow()
self.mainWindow.show()
self.deleteLater()
return True
username = self.le_username.text()
password = self.le_password.text()
validate_login()
class MainWindow(QMainWindow, Ui_App):
def __init__(self):
super().__init__()
self.conn = None
self.cursor = None
self.thread = None
self.setupUi(self)
self.pre_dos()
self.lock_overlay = None
def pre_dos(self):
self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico"))
db_operation.db_backup()
self.conn, self.cursor = db_operation.db_conn()
# bindings
self.ac_quit.triggered.connect(self.close)
self.ac_caging.triggered.connect(self.lock_window)
self.ac_logs.triggered.connect(lambda : print("test ac log"))
def launch(self, func, on_anything: Callable[..., Any] = print, *args, **kwargs):
self.thread = Worker(func, *args, **kwargs)
self.thread.started.connect(lambda: on_anything({"started": True}))
self.thread.result.connect(on_anything)
self.thread.error.connect(on_anything)
self.thread.finished.connect(lambda: on_anything({"finished": True}))
self.thread.start()
def lock_window(self):
def unlock():
def check_failed():
QMessageBox.warning(self, "错误", "\n密码错误,请重新输入!")
le_password.clear()
le_password.setFocus()
password = le_password.text()
if len(password) < clibs.account["minimum_password_length"]:
check_failed()
return False
salt = PassCipher.gen_salt(password)
cipher = PassCipher(salt)
try:
decrypt_password = cipher.decrypt(clibs.account["unlock_password"])
except ValueError:
check_failed()
return False
if password != decrypt_password:
check_failed()
return False
self.lock_overlay.deleteLater()
self.lock_overlay = None
self.set_shortcuts(True)
return True
def gen_lock_screen():
# generate lock screen
v_layout = QVBoxLayout(self.lock_overlay) # v layout
v_layout.setObjectName(u"v_layout")
h_layout = QHBoxLayout() # h layout
h_layout.setObjectName(u"h_layout")
h_layout.setContentsMargins(-1, -1, 10, 50)
lb_e_1 = QLabel(self.lock_overlay)
lb_e_1.setObjectName(u"lb_e_1")
h_layout.addWidget(lb_e_1)
lb_password = QLabel(self.lock_overlay)
lb_password.setObjectName(u"lb_password")
lb_password.setMinimumSize(QSize(100, 0))
lb_password.setMaximumSize(QSize(100, 16777215))
font = QFont()
font.setFamilies([u"Consolas"])
font.setPointSize(14)
font.setBold(True)
font.setItalic(True)
lb_password.setFont(font)
lb_password.setAlignment(Qt.AlignmentFlag.AlignCenter)
lb_password.setText("Password")
h_layout.addWidget(lb_password)
le_password = QLineEdit(self.lock_overlay)
le_password.setObjectName(u"le_password")
le_password.setMinimumSize(QSize(200, 0))
le_password.setFont(font)
le_password.setEchoMode(QLineEdit.EchoMode.Password)
h_layout.addWidget(le_password)
lb_e_2 = QLabel(self.lock_overlay)
lb_e_2.setObjectName(u"lb_e_2")
h_layout.addWidget(lb_e_2)
h_layout.setStretch(0, 5)
h_layout.setStretch(1, 2)
h_layout.setStretch(2, 3)
h_layout.setStretch(3, 5)
v_layout.addLayout(h_layout)
return le_password
self.set_shortcuts(False)
if not self.lock_overlay:
self.lock_overlay = QWidget(self)
self.lock_overlay.setObjectName("w_overlay")
cx = random.random()
cy = random.random()
stop1 = random.random()
stop2 = random.random()
angle = random.randint(0, 360)
self.lock_overlay.setStyleSheet(f"""background: qconicalgradient(cx:{cx}, cy:{cy}, angle:{angle}, stop:0 #f6f8fa, stop:{stop1} #eef1f5, stop:{stop2} #dce1e8);""")
# self.lock_overlay.setStyleSheet("""background: qconicalgradient(cx:0.5, cy:0.5, angle:45, stop:0 #f6f8fa, stop:0.5 #eef1f5, stop:1 #dce1e8);""")
le_password = gen_lock_screen()
le_password.returnPressed.connect(unlock)
self.lock_overlay.setGeometry(self.rect())
self.lock_overlay.show()
le_password.setFocus()
def set_shortcuts(self, stat: bool = True):
if stat:
self.ac_homepage.setShortcut(QKeySequence("Ctrl+Alt+H"))
self.ac_settings.setShortcut(QKeySequence("Ctrl+Alt+S"))
self.ac_logs.setShortcut(QKeySequence("Ctrl+Alt+L"))
self.ac_about.setShortcut(QKeySequence("Ctrl+Alt+A"))
self.ac_caging.setShortcut(QKeySequence("Ctrl+Alt+C"))
self.ac_quit.setShortcut(QKeySequence("Ctrl+Alt+Q"))
else:
self.ac_homepage.setShortcut(QKeySequence())
self.ac_settings.setShortcut(QKeySequence())
self.ac_logs.setShortcut(QKeySequence())
self.ac_about.setShortcut(QKeySequence())
self.ac_caging.setShortcut(QKeySequence())
self.ac_quit.setShortcut(QKeySequence())
def resizeEvent(self, event: QResizeEvent):
super().resizeEvent(event)
if self.lock_overlay:
self.lock_overlay.setGeometry(self.rect())
def closeEvent(self, event):
reply = QMessageBox.question(self, "退出", "\n程序可能在运行,确定要退出吗?")
if reply == QMessageBox.StandardButton.Yes:
db_operation.db_close(self.conn, self.cursor)
event.accept()
else:
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
login = LoginWindow()
login.show()
sys.exit(app.exec())