add lock window function, and did some improvements for the whole structure

This commit is contained in:
2025-09-10 19:28:03 +08:00
parent 648dedb611
commit 34c74bf3d0
19 changed files with 544 additions and 168 deletions

View File

@@ -1,13 +1,12 @@
import json
import random
import sys
import base64
import time
from typing import Callable, Any
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QMainWindow
from PySide6.QtGui import QIcon, QPixmap, QShortcut
from PySide6.QtCore import Qt
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_MainWindow
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
@@ -36,45 +35,40 @@ class LoginWindow(QWidget, Ui_login):
self.le_username.setText("")
self.le_password.setText("")
def gen_salt():
clibs.salt = ""
key = ""
passwd = {idx: char for idx, char in enumerate(self.le_password.text() * 4)}
for idx in range(32):
char_i = 0 if ord(passwd[idx]) - clibs.code_dict[idx] < 0 else ord(passwd[idx]) - clibs.code_dict[idx]
key += chr(char_i)
clibs.salt = base64.urlsafe_b64encode(key.encode()).decode()
def validate_login():
# with open(f"{clibs.base_path}/assets/conf/config.json", mode="rt", encoding="utf-8") as f_conf:
# accounts = json.load(f_conf)["account"]
# username = self.le_username.text()
# if username not in accounts or len(self.le_password.text()) < 8:
# login_failed()
# return False
#
# gen_salt()
# cipher = PassCipher(clibs.salt)
# try:
# password = cipher.decrypt(accounts[username])
# except ValueError:
# login_failed()
# return False
#
# if password != self.le_password.text():
# login_failed()
# return False
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.close()
self.deleteLater()
return True
username = self.le_username.text()
password = self.le_password.text()
validate_login()
class MainWindow(QMainWindow, Ui_MainWindow):
class MainWindow(QMainWindow, Ui_App):
def __init__(self):
super().__init__()
self.conn = None
@@ -82,12 +76,16 @@ class MainWindow(QMainWindow, Ui_MainWindow):
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)
@@ -97,6 +95,127 @@ class MainWindow(QMainWindow, Ui_MainWindow):
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()