gui refactoring

This commit is contained in:
neo
2024-02-05 10:00:59 +08:00
parent 8f4ba371a1
commit 0469e5a77b
18 changed files with 1019 additions and 239 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
.venv
.venv*
__pycache__
images/shot/*
dist

16
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python 调试程序: 当前文件",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": false
}
]
}

View File

@@ -1,180 +0,0 @@
import json
from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QRegExp
from PyQt5.QtWidgets import (QWidget, QGroupBox, QPushButton, QHBoxLayout, QLineEdit, QTextEdit, QLabel,
QVBoxLayout, QGridLayout, QComboBox, QListWidget, QMessageBox, QListWidgetItem)
from PyQt5.QtGui import QIcon, QRegExpValidator
from core.maocr import maocr
from core.util import is_valid_email
from core.log import logger
import setting as c
class SFormSignup(QWidget):
def __init__(self, parent):
super().__init__()
self.setWindowIcon(QIcon(c.icon_dir_path))
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
self.initUI()
# 计算并设置新窗口的位置
self.setGeometry(0, 0, 300, 230)
self.move(parent.frameGeometry().topLeft() + parent.rect().center() - self.rect().center())
# 绘制界面
def initUI(self):
self.CreateWindowCommbo()
gridLayout = QGridLayout()
gridLayout.addWidget(self.vWinGroupBox, 0, 0, QtCore.Qt.AlignLeft)
# 调用方法绘制界面
self.setWindowTitle(c.WINTITLE)
mainLayout = QHBoxLayout()
mainLayout.addLayout(gridLayout)
self.setLayout(mainLayout)
def CreateWindowCommbo(self):
layout_outter = QVBoxLayout()
self.vWinGroupBox = QGroupBox('sign up')
self.vWinGroupBox.setMinimumSize(300, 200)
regex = QRegExp("^[A-Za-z0-9]{0,16}$")
validator = QRegExpValidator(regex)
layout = QHBoxLayout()
self.username_le = QLineEdit(self)
self.username_label = QLabel('用户名:', self)
self.username_le.setPlaceholderText("输入用户名")
self.username_le.setValidator(validator)
layout.addWidget(self.username_label, 1)
layout.addWidget(self.username_le, 4)
layout_outter.addLayout(layout)
regex = QRegExp("[A-Za-z0-9@.]{0,32}")
validator = QRegExpValidator(regex)
layout = QHBoxLayout()
self.email_le = QLineEdit(self)
self.email_label = QLabel('Email:', self)
self.email_le.setPlaceholderText("输入Email")
self.email_le.setValidator(validator)
layout.addWidget(self.email_label, 1)
layout.addWidget(self.email_le, 4)
layout_outter.addLayout(layout)
regex = QRegExp("[A-Za-z0-9.]{0,16}")
validator = QRegExpValidator(regex)
layout = QHBoxLayout()
self.password_le = QLineEdit(self)
self.password_label = QLabel('密码:', self)
self.password_le.setPlaceholderText("输入密码")
self.password_le.setValidator(validator)
self.password_le.setEchoMode(QLineEdit.Password)
layout.addWidget(self.password_label, 1)
layout.addWidget(self.password_le, 4)
layout_outter.addLayout(layout)
layout = QHBoxLayout()
self.password2_le = QLineEdit(self)
self.password2_label = QLabel('确认密码:', self)
self.password2_le.setPlaceholderText("再次输入密码")
self.password2_le.setValidator(validator)
self.password2_le.setEchoMode(QLineEdit.Password)
layout.addWidget(self.password2_label, 1)
layout.addWidget(self.password2_le, 4)
layout_outter.addLayout(layout)
layout = QHBoxLayout()
self.invitated_le = QLineEdit(self)
self.invitated_label = QLabel('邀请码:', self)
self.invitated_le.setPlaceholderText("可选")
self.invitated_le.setMaxLength(16)
# self.invitated_le.setValidator(validator)
layout.addWidget(self.invitated_label, 1)
layout.addWidget(self.invitated_le, 4)
layout_outter.addLayout(layout)
layout = QVBoxLayout()
self.tips_label = QLabel('', self)
self.sign_up_btn = QPushButton('完成', self)
self.sign_up_btn.clicked.connect(self.onclick_sign_up)
layout.addWidget(self.tips_label, 1)
layout.addWidget(self.sign_up_btn, 1)
layout_outter.addLayout(layout)
self.vWinGroupBox.setLayout(layout_outter)
def closeEvent(self, event):
# 调用父类的closeEvent方法确保窗口能够正常关闭
super().closeEvent(event)
def Reset(self):
self.username_le.clear()
self.email_le.clear()
self.password_le.clear()
self.password2_le.clear()
self.invitated_le.clear()
self.tips_label.clear()
def setTips(self, tips):
self.tips_label.setText(f"<font color='red'>{tips}</font>")
def onclick_sign_up(self):
username = self.username_le.text()
email = self.email_le.text()
password = self.password_le.text()
password2 = self.password2_le.text()
self.setTips("")
if len(username) < 5:
tips = "用户名至少需要5个字符"
self.setTips(tips)
return
if len(email) == 0:
tips = "请输入Email"
self.setTips(tips)
return
if not is_valid_email(email):
tips = "Email 格式错误"
self.setTips(tips)
return
if password != password2:
tips = "两次密码不一致"
self.setTips(tips)
return
if len(password) < 8:
tips = "密码至少需要8个字符"
self.setTips(tips)
return
invitated = self.invitated_le.text()
res, ok = maocr.signup(username, email, password, invitated)
if not ok:
tips = "网络错误"
self.setTips(tips)
return
try:
info = json.loads(res)
except json.JSONDecodeError:
logger.error(f"wrong json format: {res} ")
return
logger.info(info)
if info['message'] != "":
self.setTips(info['message'])
return
QMessageBox.information(self, "消息", "注册成功")
self.close()

6
core/model_signin.py Normal file
View File

@@ -0,0 +1,6 @@
signin_flag = False
signin_username = None
signin_email = None
signin_invatation = None
signin_token = None

View File

@@ -1,7 +1,7 @@
import os
import setting as c
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout
from PyQt5.QtGui import QPixmap
from PySide6.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout
from PySide6.QtGui import QPixmap
from core.mhdt import download_image

View File

@@ -25,7 +25,7 @@ def timer_elapse(func):
def delete_file(file_path):
try:
os.remove(file_path)
#logger.info(f"文件 {file_path} 删除成功")
logger.info(f"文件 {file_path} 删除成功")
except OSError as e:
logger.info(f"删除文件 {file_path} 失败: {e}")

0
gui/__init__.py Normal file
View File

48
gui/gui_coord.py Normal file
View File

@@ -0,0 +1,48 @@
from PySide6.QtCore import Qt, QSize, QUrl
from PySide6.QtGui import QIcon, QFont, QColor
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, TitleLabel, BodyLabel
class CoordInfoCard(SimpleCardWidget):
""" App information card """
def __init__(self, parent=None):
super().__init__(parent)
self.nameLabel = TitleLabel('CoordInfoCard', self)
self.hBoxLayout = QHBoxLayout(self)
self.initLayout()
def initLayout(self):
self.hBoxLayout.setSpacing(30)
self.hBoxLayout.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout.addWidget(self.nameLabel)
class CoordInterface(SingleDirectionScrollArea):
def __init__(self, parent=None):
super().__init__(parent=None)
self.view = QWidget(self)
self.vBoxLayout = QVBoxLayout(self.view)
self.coordCard = CoordInfoCard(self)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setObjectName('CoordInterface')
self.vBoxLayout.setSpacing(10)
self.vBoxLayout.setContentsMargins(0, 0, 15, 0)
self.vBoxLayout.addWidget(self.coordCard, 0, Qt.AlignTop)
self.setStyleSheet("QScrollArea {border: none; background:transparent}")
self.view.setStyleSheet('QWidget {background:transparent}')
def show(self):
print("show CoordInterface")

246
gui/gui_main.py Normal file
View File

@@ -0,0 +1,246 @@
from PySide6.QtCore import Qt, QSize, QUrl
from PySide6.QtGui import QIcon, QFont, QColor
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, PushButton, TitleLabel, CaptionLabel, MSFluentWindow, FluentIcon, NavigationItemPosition, LineEdit
from gui.gui_qa import QAInterface
from gui.gui_subscribe import SubscribeInterface
from gui.gui_coord import CoordInterface
from gui.gui_setting import SettingInterface
from gui.gui_usercenter import UsercenterInterface
from gui.gui_signup import SFormSignup
from gui.gui_signin import SFormSignin
from core.util import loadini_user, loadini_setting, clearini_user
from core.log import logger
import core.model_signin as u
import setting as c
def clearLayout(layout):
# 移除旧布局中的所有小部件
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget:
widget.setParent(None)
l = item.layout()
if l:
clearLayout(l)
class MainInfoCard(SimpleCardWidget):
""" App information card """
def __init__(self, parent=None):
super().__init__(parent)
self.father = parent
self.main_lb = TitleLabel('')
self.signin_btn = PushButton('登录')
self.signin_btn.clicked.connect(self.onclick_signin)
self.signup_btn = PushButton('注册')
self.signup_btn.clicked.connect(self.onclick_signup)
self.tips_label = CaptionLabel('')
self.sf_signup = SFormSignup(self)
self.sf_signin = SFormSignin(self)
self.username_label = CaptionLabel('用户名: ')
self.username_le = LineEdit()
self.username_le.setReadOnly(True)
self.email_label = CaptionLabel('Email: ')
self.email_le = LineEdit()
self.email_le.setReadOnly(True)
self.invitation_label = CaptionLabel('邀请码: ')
self.invitation_le = LineEdit()
self.invitation_le.setReadOnly(True)
self.logout_btn = PushButton('退出当前用户')
self.logout_btn.clicked.connect(self.onclick_logout)
self.vBoxLayout = QVBoxLayout(self)
self.hBoxLayout_sign = QHBoxLayout()
self.hBoxLayout_tips = QHBoxLayout()
self.hBoxLayout_username = QHBoxLayout()
self.hBoxLayout_email = QHBoxLayout()
self.hBoxLayout_invatation = QHBoxLayout()
self.hBoxLayout_logout = QHBoxLayout()
self.initLayout()
def initLayout(self):
s, u.signin_flag = loadini_user()
if u.signin_flag:
logger.info(f"load user: {s}")
u.signin_username = s[0]
u.signin_email = s[1]
u.signin_token = s[2]
u.signin_invatation = s[3]
if u.signin_flag:
self.username_le.setText(s[0])
self.email_le.setText(s[1])
self.invitation_le.setText(s[3])
self.hBoxLayout_username.setSpacing(30)
self.hBoxLayout_username.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout_username.addWidget(self.username_label, 1)
self.hBoxLayout_username.addWidget(self.username_le, 4)
self.hBoxLayout_email.setSpacing(30)
self.hBoxLayout_email.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout_email.addWidget(self.email_label, 1)
self.hBoxLayout_email.addWidget(self.email_le, 4)
self.hBoxLayout_invatation.setSpacing(30)
self.hBoxLayout_invatation.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout_invatation.addWidget(self.invitation_label, 1)
self.hBoxLayout_invatation.addWidget(self.invitation_le, 4)
self.hBoxLayout_logout.setSpacing(30)
self.hBoxLayout_logout.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout_logout.addWidget(self.logout_btn)
self.vBoxLayout.addLayout(self.hBoxLayout_username)
self.vBoxLayout.addLayout(self.hBoxLayout_email)
self.vBoxLayout.addLayout(self.hBoxLayout_invatation)
self.vBoxLayout.addLayout(self.hBoxLayout_logout)
else:
self.hBoxLayout_sign.setSpacing(30)
self.hBoxLayout_sign.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout_sign.addWidget(self.signin_btn)
self.hBoxLayout_sign.addWidget(self.signup_btn)
self.vBoxLayout.addLayout(self.hBoxLayout_sign, Qt.AlignCenter)
def onclick_signup(self):
# 计算主窗口中心位置
main_window_center = self.LocateCenter()
new_window_geometry = self.sf_signup.frameGeometry()
new_window_geometry.moveCenter(main_window_center)
# 移动新窗口到主窗口中心位置并显示
self.sf_signup.move(new_window_geometry.topLeft())
self.sf_signup.Reset()
self.sf_signup.show()
def onclick_signin(self):
# 计算主窗口中心位置
main_window_center = self.LocateCenter()
new_window_geometry = self.sf_signin.frameGeometry()
new_window_geometry.moveCenter(main_window_center)
# 移动新窗口到主窗口中心位置并显示
self.sf_signin.move(new_window_geometry.topLeft())
self.sf_signin.Reset()
self.sf_signin.show()
def LocateCenter(self):
return self.father.LocateCenter()
def onclick_logout(self):
u.signin_flag = False
u.signin_username = None
u.signin_email = None
u.signin_token = None
u.signin_invatation = None
self.username_le.setText("")
self.email_le.setText("")
self.invitation_le.setText("")
clearini_user()
self.ResetSignin()
def ResetSignin(self):
clearLayout(self.vBoxLayout)
self.initLayout()
class MainInterface(SingleDirectionScrollArea):
def __init__(self, parent=None):
super().__init__(parent=None)
self.father = parent
self.view = QWidget(self)
self.vBoxLayout = QVBoxLayout(self.view)
self.mainCard = MainInfoCard(self)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setObjectName('MainInterface')
self.vBoxLayout.setSpacing(10)
self.vBoxLayout.setContentsMargins(0, 0, 15, 0)
self.vBoxLayout.addWidget(self.mainCard, 0, Qt.AlignTop)
self.setStyleSheet("QScrollArea {border: none; background:transparent}")
self.view.setStyleSheet('QWidget {background:transparent}')
def show(self):
print("show MainInterface")
def LocateCenter(self):
return self.father.LocateCenter()
class MainWindow(MSFluentWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.arInterface =[
MainInterface(self),
QAInterface(self),
SubscribeInterface(self),
CoordInterface(self),
SettingInterface(self),
UsercenterInterface(self),
]
self.resize(c.win_width, c.win_height)
self.setWindowTitle(c.WINTITLE)
self.setWindowIcon(QIcon(c.icon_dir_path))
res, ok = loadini_setting()
if ok:
c.URL_QA = f"http://{res[0]}:{res[1]}"
logger.info(c.URL_QA)
logger.info(c.URL_QA_OCR())
self.addSubInterface(self.arInterface[0], FluentIcon.HOME,
'主页', selectedIcon=FluentIcon.HOME_FILL)
self.addSubInterface(self.arInterface[1], FluentIcon.SEARCH,
'答题', selectedIcon=FluentIcon.SEARCH)
self.addSubInterface(self.arInterface[2], FluentIcon.CLOUD_DOWNLOAD,
'订阅', selectedIcon=FluentIcon.CLOUD_DOWNLOAD)
self.addSubInterface(self.arInterface[3], FluentIcon.ACCEPT_MEDIUM,
'坐标', selectedIcon=FluentIcon.ACCEPT_MEDIUM)
self.addSubInterface(self.arInterface[4], FluentIcon.SETTING,
'设置', selectedIcon=FluentIcon.SETTING,
position=NavigationItemPosition.BOTTOM)
self.stackedWidget.setStyleSheet('QWidget{background: transparent}')
self.stackedWidget.currentChanged.connect(self.on_current_changed)
# 定义槽函数
def on_current_changed(self, value):
# print(f"Current changed to {value}")
self.arInterface[value].show()
def LocateCenter(self):
return self.frameGeometry().center()

293
gui/gui_qa.py Normal file
View File

@@ -0,0 +1,293 @@
import os
import cv2
import win32gui
import Levenshtein
from PIL import Image
from PySide6.QtCore import Qt, QSize, QUrl
from PySide6.QtGui import QIcon, QFont, QColor
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QListWidgetItem, QTextEdit
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, CaptionLabel, BodyLabel, ListWidget, LineEdit, ComboBox, PushButton
from core.maocr import maocr
from core.log import logger
from core.mhdt import dt_nav
from core.qalabel import QALabel
from core.screenshot import hwnd_title, get_all_hwnd, get_screenshot_image
from core.util import time_str, delete_file, loadini_user, loadini_setting
import core.model_signin as u
import setting as c
def custom_sort(item, text):
return Levenshtein.distance(item[1], text)
class QaInfoCard(SimpleCardWidget):
""" App information card """
def __init__(self, parent=None):
super().__init__(parent)
self.server_annc_lb = BodyLabel(self)
self.server_annc_lb.setText(f"{c.TIPS_MAIN_SERVER}")
self.server_annc_lb.setOpenExternalLinks(True)
self.sponsor_annc_lb = BodyLabel(self)
self.sponsor_annc_lb.setText(f"{c.TIPS_MAIN_SPONSOR}")
self.sponsor_annc_lb.setOpenExternalLinks(True)
self.win_nav = ComboBox()
self.win_nav_sub = ComboBox()
for n in dt_nav:
self.win_nav.addItem(n[0])
for ns in dt_nav[0][1]:
self.win_nav_sub.addItem(ns[0])
self.win_nav.currentIndexChanged.connect(self.on_win_nav_changed)
self.win_combo = ComboBox()
self.update_win_combo()
self.recognize_btn = PushButton('RE')
self.recognize_btn.clicked.connect(lambda checked=False: self.onclick_recogize())
self.loc_ocr_te = QTextEdit(self)
self.loc_ocr_te.setPlaceholderText("auto ocr")
self.loc_ocr_te.setReadOnly(True)
self.loc_ocr_te.setMaximumHeight(60)
self.kw_le = LineEdit()
self.kw_le.setPlaceholderText("输入关键字")
self.kw_le.returnPressed.connect(self.onclick_search)
self.search_btn = PushButton('Search')
self.search_btn.clicked.connect(lambda checked=False: self.onclick_search())
self.qa_lw = ListWidget(self)
self.qa_lw.setMinimumHeight(350)
self.label_qa = [QALabel() for i in range(c.DT_QA_LIST_NUM)]
li_height = 80
for i in range(c.DT_QA_LIST_NUM):
listItem = QListWidgetItem(self.qa_lw)
# self.label_qa[i].label_q.setText(f"{i}")
self.label_qa[i].setMaximumHeight(li_height)
qsize = QSize(400, li_height)
listItem.setSizeHint(qsize)
self.qa_lw.setItemWidget(listItem, self.label_qa[i])
self.tips_label = CaptionLabel('123')
self.vBoxLayout = QVBoxLayout(self)
self.vBoxLayout_annc= QVBoxLayout()
self.hBoxLayout_nav = QHBoxLayout()
self.hBoxLayout_re = QHBoxLayout()
self.hBoxLayout_ocr = QHBoxLayout()
self.hBoxLayout_search = QHBoxLayout()
self.vBoxLayout_qa = QVBoxLayout()
self.initLayout()
def initLayout(self):
self.vBoxLayout_annc.setSpacing(10)
self.vBoxLayout_annc.setContentsMargins(5, 5, 3, 3)
self.vBoxLayout_annc.addWidget(self.server_annc_lb)
self.vBoxLayout_annc.addWidget(self.sponsor_annc_lb)
self.hBoxLayout_nav.setSpacing(10)
self.hBoxLayout_nav.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_nav.addWidget(self.win_nav)
self.hBoxLayout_nav.addWidget(self.win_nav_sub)
self.hBoxLayout_re.setSpacing(10)
self.hBoxLayout_re.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_re.addWidget(self.win_combo, 4)
self.hBoxLayout_re.addWidget(self.recognize_btn, 1)
self.hBoxLayout_ocr.setSpacing(10)
self.hBoxLayout_ocr.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_ocr.addWidget(self.loc_ocr_te)
self.hBoxLayout_search.setSpacing(10)
self.hBoxLayout_search.setContentsMargins(5, 5, 3, 5)
self.hBoxLayout_search.addWidget(self.kw_le, 4)
self.hBoxLayout_search.addWidget(self.search_btn, 1)
self.vBoxLayout_qa.setSpacing(10)
self.vBoxLayout_qa.setContentsMargins(5, 5, 3, 5)
self.vBoxLayout_qa.addWidget(self.qa_lw, 4)
self.vBoxLayout_qa.addWidget(self.tips_label, 1)
self.vBoxLayout.addLayout(self.vBoxLayout_annc)
self.vBoxLayout.addLayout(self.hBoxLayout_nav)
self.vBoxLayout.addLayout(self.hBoxLayout_re)
self.vBoxLayout.addLayout(self.hBoxLayout_ocr)
self.vBoxLayout.addLayout(self.hBoxLayout_search)
self.vBoxLayout.addLayout(self.vBoxLayout_qa)
def on_win_nav_changed(self, index):
# logger.info("Selected:", index)
self.win_nav_sub.clear()
for ns in dt_nav[index][1]:
self.win_nav_sub.addItem(ns[0])
def update_win_combo(self):
self.win_combo.clear()
hwnd_title.clear()
win32gui.EnumWindows(get_all_hwnd, 0)
for h, t in hwnd_title.items():
# if t.startswith('梦幻西游 ONLINE'):
if t.startswith('计算器'):
self.win_combo.addItem(str(h)+":"+t)
def clear_qalist(self) :
self.qa_lw.scrollToTop()
for i in range(c.DT_QA_LIST_NUM):
self.label_qa[i].clear()
def setTips(self, tips):
self.tips_label.setText(f"<font color='red'>{tips}</font>")
@logger.catch
def onclick_search(self, checked=False) :
self.setTips("")
n = self.win_nav.currentIndex()
nsub = self.win_nav_sub.currentIndex()
id = dt_nav[n][1][nsub][1]
logger.info(f"{n}-{nsub} id: {id}")
kw = self.kw_le.text()
if kw == "":
msg = "请输入查询关键字!"
logger.warning(msg)
self.setTips(msg)
return
logger.info(f"{n} {nsub} {id} {kw}")
qs, ok = maocr.search(id, kw)
if not ok:
msg = "查找失败"
logger.warning(msg)
self.setTips(msg)
return
self.server_annc_lb.setText(qs[1])
self.sponsor_annc_lb.setText(qs[2])
self.clear_qalist()
if qs[0] == None:
msg = "查找失败"
self.setTips(msg)
logger.warning(msg)
return
for i, q in enumerate(qs[0]):
logger.info(f"{i} {q}")
self.label_qa[i].setText(q)
@logger.catch
def onclick_recogize(self):
self.setTips("")
if not u.signin_flag:
msg = "仅登录用户可用"
self.setTips(msg)
logger.warning(msg)
return
win_text = self.win_combo.currentText()
if win_text == "":
msg = "没有可用窗口"
logger.warning(msg)
self.setTips(msg)
self.update_win_combo()
return
h = win_text.split(':')[0]
t = win_text.split(':')[1]
logger.info(f"{h} {t}")
if not win32gui.IsWindowEnabled(h):
msg = "无效窗口, 请重新选择窗口!"
logger.warning(msg)
self.setTips(msg)
self.update_win_combo()
return
n = self.win_nav.currentIndex()
nsub = self.win_nav_sub.currentIndex()
id = dt_nav[n][1][nsub][1]
ri = dt_nav[n][1][nsub][2]
logger.info(f"{n}-{nsub} id: {id} ri: {ri}")
img_hwnd = get_screenshot_image(int(h))
opencv_image = cv2.imread(os.path.join(c.shot_dir_path, r'q3.png'))
if opencv_image is None:
self.setTips("文件查找失败,避免中文路径")
return
rgb_image = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
img_hwnd = Image.fromarray(rgb_image)
logger.info(f"shot size {img_hwnd.size}")
rect = c.shot_rect[ri]
crop_box = (rect[0], rect[1], rect[2], rect[3])
img_hwnd = img_hwnd.crop(crop_box)
ts = time_str()
file_img = f"{c.shot_dir_path}/{h}_{t}_{ts}.png"
img_hwnd.save(file_img, 'PNG')
logger.info(f'img_desktop save to -> {os.path.abspath(file_img)}')
ok = True
re, ok = maocr.recognize(id, file_img, u.signin_token)
if not ok:
msg = "识别失败"
logger.warning(msg)
self.setTips(msg)
return
text = re[0]
res = re[1]
ocrleftcount = re[2]
message = re[3]
annc_server = re[4]
annc_sponsor = re[5]
if message != "":
self.setTips(message)
self.server_annc_lb.setText(annc_server)
self.sponsor_annc_lb.setText(annc_sponsor)
# logger.info(text)
# logger.info(res)
self.recognize_btn.setText(f"RE({ocrleftcount})")
delete_file(file_img)
if text == "":
self.setTips("识别失败")
return
if ok:
self.loc_ocr_te.setText(text)
sorted_list = sorted(res, key=lambda x: custom_sort(x['Q'], text))
self.clear_qalist()
for i, q in enumerate(sorted_list):
if i > 4:
break
logger.info(f"{i}: {q}")
self.label_qa[i].setText(q)
class QAInterface(SingleDirectionScrollArea):
def __init__(self, parent=None):
super().__init__(parent=None)
self.view = QWidget(self)
self.vBoxLayout = QVBoxLayout(self.view)
self.qaCard = QaInfoCard(self)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setObjectName('QAInterface')
self.vBoxLayout.setSpacing(10)
self.vBoxLayout.setContentsMargins(0, 0, 5, 0)
self.vBoxLayout.addWidget(self.qaCard, 0, Qt.AlignTop)
self.setStyleSheet("QScrollArea {border: none; background:transparent}")
self.view.setStyleSheet('QWidget {background:transparent}')
def show(self):
print("show QAInterface")

47
gui/gui_setting.py Normal file
View File

@@ -0,0 +1,47 @@
from PySide6.QtCore import Qt, QSize, QUrl
from PySide6.QtGui import QIcon, QFont, QColor
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, TitleLabel, BodyLabel
class SettingInfoCard(SimpleCardWidget):
""" App information card """
def __init__(self, parent=None):
super().__init__(parent)
self.nameLabel = TitleLabel('SettingInfoCard', self)
self.hBoxLayout = QHBoxLayout(self)
self.initLayout()
def initLayout(self):
self.hBoxLayout.setSpacing(30)
self.hBoxLayout.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout.addWidget(self.nameLabel)
class SettingInterface(SingleDirectionScrollArea):
def __init__(self, parent=None):
super().__init__(parent=None)
self.view = QWidget(self)
self.vBoxLayout = QVBoxLayout(self.view)
self.settingCard = SettingInfoCard(self)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setObjectName('SettingInterface')
self.vBoxLayout.setSpacing(10)
self.vBoxLayout.setContentsMargins(0, 0, 15, 0)
self.vBoxLayout.addWidget(self.settingCard, 0, Qt.AlignTop)
self.setStyleSheet("QScrollArea {border: none; background:transparent}")
self.view.setStyleSheet('QWidget {background:transparent}')
def show(self):
print("show SettingInterface")

View File

@@ -1,9 +1,10 @@
import json
from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QRegExp
from PyQt5.QtWidgets import (QWidget, QGroupBox, QPushButton, QHBoxLayout, QLineEdit, QTextEdit, QLabel,
QVBoxLayout, QGridLayout, QComboBox, QListWidget, QMessageBox, QListWidgetItem)
from PyQt5.QtGui import QIcon, QRegExpValidator
from PySide6 import QtCore
from PySide6.QtCore import Qt, QRegularExpression
from PySide6.QtWidgets import (QWidget, QGroupBox, QHBoxLayout,
QVBoxLayout, QGridLayout)
from qfluentwidgets import CaptionLabel, LineEdit, PushButton
from PySide6.QtGui import QIcon, QRegularExpressionValidator
from core.maocr import maocr
from core.util import is_valid_email, dumpini_user
import setting as c
@@ -20,7 +21,7 @@ class SFormSignin(QWidget):
self.initUI()
# 计算并设置新窗口的位置
self.setGeometry(0, 0, 300, 130)
self.setGeometry(0, 0, 300, 150)
self.move(father.frameGeometry().topLeft() + father.rect().center() - self.rect().center())
# 绘制界面
@@ -38,45 +39,60 @@ class SFormSignin(QWidget):
self.setLayout(mainLayout)
def CreateWindowCommbo(self):
layout_outter = QVBoxLayout()
self.vWinGroupBox = QGroupBox('sign in')
self.vWinGroupBox.setMinimumSize(300, 130)
self.vWinGroupBox.setMinimumSize(300, 220)
regex = QRegExp("[A-Za-z0-9@.]{0,32}")
validator = QRegExpValidator(regex)
layout = QHBoxLayout()
self.email_le = QLineEdit(self)
self.email_label = QLabel('Email:', self)
regex = QRegularExpression("[A-Za-z0-9@.]{0,32}")
validator = QRegularExpressionValidator(regex)
self.email_le = LineEdit()
self.email_label = CaptionLabel('Email:')
self.email_le.setPlaceholderText("输入Email")
self.email_le.setValidator(validator)
layout.addWidget(self.email_label, 1)
layout.addWidget(self.email_le, 4)
layout_outter.addLayout(layout)
regex = QRegExp("[A-Za-z0-9.]{0,16}")
validator = QRegExpValidator(regex)
layout = QHBoxLayout()
self.password_le = QLineEdit(self)
self.password_label = QLabel('密码:', self)
regex = QRegularExpression("[A-Za-z0-9.]{0,16}")
validator = QRegularExpressionValidator(regex)
self.password_le = LineEdit()
self.password_label = CaptionLabel('密码:')
self.password_le.setPlaceholderText("输入密码")
self.password_le.setValidator(validator)
self.password_le.setEchoMode(QLineEdit.Password)
layout.addWidget(self.password_label, 1)
layout.addWidget(self.password_le, 4)
layout_outter.addLayout(layout)
self.password_le.setEchoMode(LineEdit.Password)
layout = QVBoxLayout()
self.tips_label = QLabel('', self)
self.sign_in_btn = QPushButton('登录', self)
self.tips_label = CaptionLabel('')
self.sign_in_btn = PushButton('登录')
self.sign_in_btn.clicked.connect(self.onclick_sign_in)
layout.addWidget(self.tips_label, 1)
layout.addWidget(self.sign_in_btn, 1)
layout_outter.addLayout(layout)
self.vBoxLayout = QVBoxLayout(self)
self.hBoxLayout_email = QHBoxLayout()
self.hBoxLayout_password = QHBoxLayout()
self.vBoxLayout_signin = QVBoxLayout()
self.vWinGroupBox.setLayout(layout_outter)
self.initLayout()
self.vWinGroupBox.setLayout(self.vBoxLayout)
def initLayout(self):
self.hBoxLayout_email.setSpacing(10)
self.hBoxLayout_email.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_email.addWidget(self.email_label, 1)
self.hBoxLayout_email.addWidget(self.email_le, 4)
self.hBoxLayout_password.setSpacing(10)
self.hBoxLayout_password.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_password.addWidget(self.password_label, 1)
self.hBoxLayout_password.addWidget(self.password_le, 4)
self.vBoxLayout_signin.setSpacing(10)
self.vBoxLayout_signin.setContentsMargins(5, 5, 3, 3)
self.vBoxLayout_signin.addWidget(self.sign_in_btn)
self.vBoxLayout_signin.addWidget(self.tips_label)
self.vBoxLayout.addLayout(self.hBoxLayout_email)
self.vBoxLayout.addLayout(self.hBoxLayout_password)
self.vBoxLayout.addLayout(self.vBoxLayout_signin)
def closeEvent(self, event):
@@ -125,5 +141,5 @@ class SFormSignin(QWidget):
return
# QMessageBox.information(self, "消息", "登录成功")
dumpini_user(info['username'], info['email'], info['token'], info['invitation'])
self.father.ResetSignin(True)
self.father.ResetSignin()
self.close()

205
gui/gui_signup.py Normal file
View File

@@ -0,0 +1,205 @@
import json
from PySide6 import QtCore
from PySide6.QtCore import Qt, QRegularExpression
from PySide6.QtWidgets import (QWidget, QGroupBox, QHBoxLayout, QMessageBox,
QVBoxLayout, QGridLayout)
from PySide6.QtGui import QIcon, QRegularExpressionValidator
from qfluentwidgets import CaptionLabel, LineEdit, PushButton
from core.maocr import maocr
from core.util import is_valid_email
from core.log import logger
import setting as c
class SFormSignup(QWidget):
def __init__(self, parent):
super().__init__()
self.setWindowIcon(QIcon(c.icon_dir_path))
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
self.initUI()
# 计算并设置新窗口的位置
self.setGeometry(0, 0, 300, 230)
self.move(parent.frameGeometry().topLeft() + parent.rect().center() - self.rect().center())
# 绘制界面
def initUI(self):
self.CreateWindowCommbo()
gridLayout = QGridLayout()
gridLayout.addWidget(self.vWinGroupBox, 0, 0, QtCore.Qt.AlignLeft)
# 调用方法绘制界面
self.setWindowTitle(c.WINTITLE)
mainLayout = QHBoxLayout()
mainLayout.addLayout(gridLayout)
self.setLayout(mainLayout)
def CreateWindowCommbo(self):
self.vWinGroupBox = QGroupBox('sign up')
self.vWinGroupBox.setMinimumSize(300, 340)
regex = QRegularExpression("^[A-Za-z0-9]{0,16}$")
validator = QRegularExpressionValidator(regex)
self.username_le = LineEdit(self)
self.username_label = CaptionLabel('用户名:', self)
self.username_le.setPlaceholderText("输入用户名")
self.username_le.setValidator(validator)
regex = QRegularExpression("[A-Za-z0-9@.]{0,32}")
validator = QRegularExpressionValidator(regex)
self.email_le = LineEdit(self)
self.email_label = CaptionLabel('Email:', self)
self.email_le.setPlaceholderText("输入Email")
self.email_le.setValidator(validator)
regex = QRegularExpression("[A-Za-z0-9.]{0,16}")
validator = QRegularExpressionValidator(regex)
self.password_le = LineEdit(self)
self.password_label = CaptionLabel('密码:', self)
self.password_le.setPlaceholderText("输入密码")
self.password_le.setValidator(validator)
self.password_le.setEchoMode(LineEdit.Password)
self.password2_le = LineEdit(self)
self.password2_label = CaptionLabel('确认密码:', self)
self.password2_le.setPlaceholderText("再次输入密码")
self.password2_le.setValidator(validator)
self.password2_le.setEchoMode(LineEdit.Password)
self.invitated_le = LineEdit(self)
self.invitated_label = CaptionLabel('邀请码:', self)
self.invitated_le.setPlaceholderText("可选")
self.invitated_le.setMaxLength(16)
self.tips_label = CaptionLabel('', self)
self.sign_up_btn = PushButton('完成', self)
self.sign_up_btn.clicked.connect(self.onclick_sign_up)
self.vBoxLayout = QVBoxLayout(self)
self.hBoxLayout_username = QHBoxLayout()
self.hBoxLayout_email = QHBoxLayout()
self.hBoxLayout_password = QHBoxLayout()
self.hBoxLayout_password2 = QHBoxLayout()
self.hBoxLayout_invatation = QHBoxLayout()
self.vBoxLayout_signup = QVBoxLayout()
self.initLayout()
self.vWinGroupBox.setLayout(self.vBoxLayout)
def initLayout(self):
self.hBoxLayout_username.setSpacing(10)
self.hBoxLayout_username.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_username.addWidget(self.username_label, 1)
self.hBoxLayout_username.addWidget(self.username_le, 4)
self.hBoxLayout_email.setSpacing(10)
self.hBoxLayout_email.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_email.addWidget(self.email_label, 1)
self.hBoxLayout_email.addWidget(self.email_le, 4)
self.hBoxLayout_password.setSpacing(10)
self.hBoxLayout_password.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_password.addWidget(self.password_label, 1)
self.hBoxLayout_password.addWidget(self.password_le, 4)
self.hBoxLayout_password2.setSpacing(10)
self.hBoxLayout_password2.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_password2.addWidget(self.password2_label, 1)
self.hBoxLayout_password2.addWidget(self.password2_le, 4)
self.hBoxLayout_invatation.setSpacing(10)
self.hBoxLayout_invatation.setContentsMargins(5, 5, 3, 3)
self.hBoxLayout_invatation.addWidget(self.invitated_label, 1)
self.hBoxLayout_invatation.addWidget(self.invitated_le, 4)
self.vBoxLayout_signup.setSpacing(10)
self.vBoxLayout_signup.setContentsMargins(5, 5, 3, 3)
self.vBoxLayout_signup.addWidget(self.sign_up_btn)
self.vBoxLayout_signup.addWidget(self.tips_label)
self.vBoxLayout.addLayout(self.hBoxLayout_username)
self.vBoxLayout.addLayout(self.hBoxLayout_email)
self.vBoxLayout.addLayout(self.hBoxLayout_password)
self.vBoxLayout.addLayout(self.hBoxLayout_password2)
self.vBoxLayout.addLayout(self.hBoxLayout_invatation)
self.vBoxLayout.addLayout(self.vBoxLayout_signup)
def closeEvent(self, event):
# 调用父类的closeEvent方法确保窗口能够正常关闭
super().closeEvent(event)
def Reset(self):
self.username_le.clear()
self.email_le.clear()
self.password_le.clear()
self.password2_le.clear()
self.invitated_le.clear()
self.tips_label.clear()
def setTips(self, tips):
self.tips_label.setText(f"<font color='red'>{tips}</font>")
def onclick_sign_up(self):
username = self.username_le.text()
email = self.email_le.text()
password = self.password_le.text()
password2 = self.password2_le.text()
self.setTips("")
if len(username) < 5:
tips = "用户名至少需要5个字符"
self.setTips(tips)
return
if len(email) == 0:
tips = "请输入Email"
self.setTips(tips)
return
if not is_valid_email(email):
tips = "Email 格式错误"
self.setTips(tips)
return
if password != password2:
tips = "两次密码不一致"
self.setTips(tips)
return
if len(password) < 8:
tips = "密码至少需要8个字符"
self.setTips(tips)
return
invitated = self.invitated_le.text()
res, ok = maocr.signup(username, email, password, invitated)
if not ok:
tips = "网络错误"
self.setTips(tips)
return
try:
info = json.loads(res)
except json.JSONDecodeError:
logger.error(f"wrong json format: {res} ")
return
logger.info(info)
if info['message'] != "":
self.setTips(info['message'])
return
QMessageBox.information(self, "消息", "注册成功")
self.close()

47
gui/gui_subscribe.py Normal file
View File

@@ -0,0 +1,47 @@
from PySide6.QtCore import Qt, QSize, QUrl
from PySide6.QtGui import QIcon, QFont, QColor
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, TitleLabel, BodyLabel
class SubscribeInfoCard(SimpleCardWidget):
""" App information card """
def __init__(self, parent=None):
super().__init__(parent)
self.nameLabel = TitleLabel('SubscribeInfoCard', self)
self.hBoxLayout = QHBoxLayout(self)
self.initLayout()
def initLayout(self):
self.hBoxLayout.setSpacing(30)
self.hBoxLayout.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout.addWidget(self.nameLabel)
class SubscribeInterface(SingleDirectionScrollArea):
def __init__(self, parent=None):
super().__init__(parent=None)
self.view = QWidget(self)
self.vBoxLayout = QVBoxLayout(self.view)
self.subscribeCard = SubscribeInfoCard(self)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setObjectName('SubscribeInterface')
self.vBoxLayout.setSpacing(10)
self.vBoxLayout.setContentsMargins(0, 0, 15, 0)
self.vBoxLayout.addWidget(self.subscribeCard, 0, Qt.AlignTop)
self.setStyleSheet("QScrollArea {border: none; background:transparent}")
self.view.setStyleSheet('QWidget {background:transparent}')
def show(self):
print("show SubscribeInterface")

44
gui/gui_usercenter.py Normal file
View File

@@ -0,0 +1,44 @@
from PySide6.QtCore import Qt, QSize, QUrl
from PySide6.QtGui import QIcon, QFont, QColor
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
from qfluentwidgets import SingleDirectionScrollArea, SimpleCardWidget, TitleLabel, BodyLabel
class UsercenterInfoCard(SimpleCardWidget):
""" App information card """
def __init__(self, parent=None):
super().__init__(parent)
self.nameLabel = TitleLabel('UsercenterInfoCard', self)
self.hBoxLayout = QHBoxLayout(self)
self.initLayout()
def initLayout(self):
self.hBoxLayout.setSpacing(30)
self.hBoxLayout.setContentsMargins(34, 24, 24, 24)
self.hBoxLayout.addWidget(self.nameLabel)
class UsercenterInterface(SingleDirectionScrollArea):
def __init__(self, parent=None):
super().__init__(parent=None)
self.view = QWidget(self)
self.vBoxLayout = QVBoxLayout(self.view)
self.usercenterCard = UsercenterInfoCard(self)
self.setWidget(self.view)
self.setWidgetResizable(True)
self.setObjectName('UsercenterInterface')
self.vBoxLayout.setSpacing(10)
self.vBoxLayout.setContentsMargins(0, 0, 15, 0)
self.vBoxLayout.addWidget(self.usercenterCard, 0, Qt.AlignTop)
self.setStyleSheet("QScrollArea {border: none; background:transparent}")
self.view.setStyleSheet('QWidget {background:transparent}')

Binary file not shown.

View File

@@ -1,25 +1,17 @@
import sys
from core.sform import SForm
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt
from core.util import dir_check
from core.log import logger
from PySide6.QtWidgets import QApplication
from gui.gui_main import MainWindow
import setting as c
app = QApplication(sys.argv)
# 程序启动
if __name__ == '__main__':
logger.info("gui start")
dir_check()
#app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) # 美化界面
sf = SForm()
sf.resize(c.win_width, c.win_height)
sf.setWindowFlags(sf.windowFlags() | Qt.WindowStaysOnTopHint)
app = QApplication(sys.argv)
screen = app.primaryScreen().size()
x = screen.width() - sf.width() # 窗口右对齐
x = screen.width() - c.win_width # 窗口右对齐
y = 100 # 窗口顶对齐
sf.move(x, y)
sf.show()
sys.exit(app.exec_())
w = MainWindow()
w.move(x, y)
w.show()
app.exec()

View File

@@ -15,12 +15,12 @@ def resource_path(relative_path):
screen_width, screen_height = pyautogui.size()
win_width = 480
win_height = 700
win_width = 530
win_height = 750
# version
VERSION = "0.0.2"
WINTITLE = f"mhxy QA {VERSION}"
WINTITLE = f"mhbby {VERSION}"
# 截图存档目录
appdata_path = os.path.join(os.getenv('APPDATA'), r'mhxyQA')