diff --git a/app2.py b/app2.py
index 226e3271086ff3197ffe3a9bb54912a099ccc384..3299b8653d48f48631cb2c7d7d4bf1d3cde2a156 100644
--- a/app2.py
+++ b/app2.py
@@ -15,6 +15,7 @@ import platform
import sys
import time
import traceback
+from multiprocessing import shared_memory
sys.path.append(os.path.dirname(__file__))
sys.path.append(os.path.join(os.path.dirname(__file__), "resources"))
@@ -342,6 +343,21 @@ class MainWindow(BaseMainWindow):
self.main_first_form = base.FirstForm(parent=self)
self.main_first_form.show()
+ def login_form_display(self):
+ """
+ 显示"登录"窗口
+ Displays the "Quick Action" window
+ """
+ shared_memo = shared_memory.SharedMemory(name="sharedMemory") # 通过name找到共享内存token
+ buff = shared_memo.buf
+ token = bytes(buff[:199]).decode().replace("\x00", "")
+ if token != "":
+ self.main_login_form = base.LoginedForm(parent=self)
+ self.main_login_form.exec_()
+ else:
+ self.main_login_form = base.LoginForm(parent=self)
+ self.main_login_form.show()
+
def main_appstore_dispaly(self):
"""
显示"应用商店"窗口
diff --git a/features/main_window/base.py b/features/main_window/base.py
index 57d2f341542631290a96bc4ec7184d0585bafd07..b3555ecabc3717f56f31c84b176bb9baaafea449 100644
--- a/features/main_window/base.py
+++ b/features/main_window/base.py
@@ -3,16 +3,19 @@ import sys
import time
import subprocess
import webbrowser
+import base64
+import json
from typing import Tuple, List
import qdarkstyle
from PySide2.QtCore import QPoint, QRectF
-from PySide2.QtGui import QMouseEvent, QPainter, QLinearGradient
+from PySide2.QtGui import QMouseEvent, QPainter, QLinearGradient, QCursor
from PySide2.QtGui import QCloseEvent
from PySide2.QtCore import Signal, Qt, QUrl, QPropertyAnimation
from PySide2.QtWidgets import QApplication, QListWidgetItem, QWizard, QHeaderView, QMessageBox
from PySide2.QtWebEngineWidgets import *
from PySide2.QtWidgets import QWidget, QDesktopWidget, QFileDialog, QApplication, QDialog
+
from pmgwidgets import PMGPanel
from features.ui.ui_option import Ui_Form as Option_Ui_Form
@@ -20,11 +23,14 @@ from features.ui.ui_appstore import Ui_Form as appStore_Ui_Form
from features.ui.ui_aboutme import Ui_Form as About_Ui_Form
from features.ui.ui_project_wizard import Ui_Wizard as Project_Ui_Form
from features.ui.ui_first_form import Ui_Form as first_Ui_Form
+from features.ui.ui_login import Ui_Form as login_Ui_Form
+from features.ui.ui_logined import Ui_Form as logined_Ui_Form
import utils
-from utils import get_main_window
+from utils import get_main_window, http_client
from features.io.settings import Settings
from features.extensions.extensionlib.extension_lib import extension_lib
+from multiprocessing import shared_memory
class OptionForm(QDialog, Option_Ui_Form):
@@ -593,9 +599,109 @@ class FirstForm(QDialog, first_Ui_Form):
self.close()
+class LoginForm(QDialog, login_Ui_Form):
+ """
+ 登录窗口
+ """
+ def __init__(self, parent=None):
+ super(LoginForm, self).__init__(parent)
+ self.setupUi(self)
+ self.init()
+
+ def init(self):
+ self.loginButton.clicked.connect(self.login)
+ self.forgetPwdButton.clicked.connect(self.forgetPwd)
+ self.usernameLineEdit.textChanged.connect(self.usernameErrorChange)
+
+ def login(self):
+ username = self.usernameLineEdit.text()
+ password = self.passwordLineEdit.text()
+ flag = False
+ if username == "":
+ self.usernameError.setText("用户名不能为空")
+ flag = True
+ if password == "":
+ self.passwordError.setText("密码不能为空")
+ flag = True
+ if not flag:
+ data = {
+ "usr": username,
+ "password": base64.b64encode(password.encode())
+ }
+ url = http_client.API + http_client.LOGIN_URL
+ resp = http_client.client(url, "post", data)
+ resp_info = json.loads(resp.text)
+ if resp.status_code == 200:
+ if resp_info["code"] == 10000:
+ token = resp_info["token"]
+ token_len = len(token)
+ username_len = len(username.encode("utf-8"))
+ """
+ 将登录后django返回的token令牌保存在共享内存token中,共享内存token在启动pyminer主程序时附带启动了本地flask服务然后
+ 创建共享内存token,详情见pmlocalserver/server.py
+ """
+ shared_memo = shared_memory.SharedMemory(name="sharedMemory") # 通过name找到共享内存token
+ buff = shared_memo.buf
+ # token长度随着用户名长度的增加而增加,用户名最长为21个汉字加一个字符
+ # buff[:3]存放token长度,目前最长的用户名21汉字加一字符生成的token长度为343
+ # buff[3:5]存放用户名长度,用户名字段最长为64字节,最多21个汉字(字符集utf8)
+ # buff[5:token_len+5]位存放token
+ # buff[token_len+5:实际用户名长度(用utf8转换为bytes后的长度)]存放用户名
+ buff[:3] = str(token_len).encode("utf-8") # 存放token长度
+ buff[3:5] = str(username_len).encode("utf-8") # 将用户名长度存放共享内存
+ buff[5:token_len+5] = token.encode("utf-8") # 将token存放进共享内存中,工作空间重启后也能获取到
+ buff[token_len+5:token_len+5+username_len] = username.encode("utf-8") # 存放用户名
+ self.usernameError.setText("登录成功")
+ time.sleep(0.5)
+ self.close()
+ else:
+ self.usernameError.setText(resp_info["msg"][0])
+
+ def forgetPwd(self):
+ utils.open_url("http://pyminer.com/forgetpassword")
+
+ def usernameErrorChange(self):
+ self.usernameError.setText("")
+ self.passwordError.setText("")
+ username = self.usernameLineEdit.text()
+ if len(username.encode("utf-8")) > 64:
+ self.usernameError.setText("最多只能输入21个汉字")
+ self.loginButton.setEnabled(False)
+ self.loginButton.setCursor(QCursor(Qt.ForbiddenCursor))
+ else:
+ self.usernameError.setText("")
+ self.loginButton.setEnabled(True)
+ self.loginButton.setCursor(QCursor(Qt.PointingHandCursor))
+
+
+class LoginedForm(QDialog, logined_Ui_Form):
+
+ def __init__(self, parent=None):
+ super(LoginedForm, self).__init__(parent)
+ self.setupUi(self)
+ self.init()
+ shared_memo = shared_memory.SharedMemory(name="sharedMemory") # 通过name找到共享内存token
+ buff = shared_memo.buf
+ token_len = int(bytes(buff[:3]).decode())
+ username_len = int(bytes(buff[3:5]).decode())
+ username = bytes(buff[token_len+5:token_len+5+username_len]).decode("utf-8")
+ self.usernameLabel.setText(username)
+
+ def init(self):
+ self.loginOutButton.clicked.connect(self.logout)
+
+ def logout(self):
+ shared_memo = shared_memory.SharedMemory(name="sharedMemory") # 通过name找到共享内存token
+ buff = shared_memo.buf
+ for i in range(0, len(buff)):
+ buff[i:i+1] = "\x00".encode()
+ time.sleep(0.5)
+ self.close()
+
+
if __name__ == '__main__':
app = QApplication(sys.argv)
# form = FirstForm()
- form = ProjectWizardForm()
+ form = LoginedForm()
form.show()
sys.exit(app.exec_())
diff --git a/features/ui/ui_login.py b/features/ui/ui_login.py
new file mode 100644
index 0000000000000000000000000000000000000000..843dd6abdd09f4667a8a1c1dcc386d045dfc5809
--- /dev/null
+++ b/features/ui/ui_login.py
@@ -0,0 +1,204 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'ui_login.ui'
+##
+## Created by: Qt User Interface Compiler version 5.15.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide2.QtCore import *
+from PySide2.QtGui import *
+from PySide2.QtWidgets import *
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ if not Form.objectName():
+ Form.setObjectName(u"Form")
+ Form.setWindowModality(Qt.ApplicationModal)
+ Form.resize(407, 361)
+ sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+ Form.setSizePolicy(sizePolicy)
+ Form.setMinimumSize(QSize(407, 361))
+ Form.setMaximumSize(QSize(407, 361))
+ Form.setStyleSheet(u"")
+ self.verticalLayout = QVBoxLayout(Form)
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ self.widget = QWidget(Form)
+ self.widget.setObjectName(u"widget")
+ self.widget.setMaximumSize(QSize(407, 361))
+ self.widget.setSizeIncrement(QSize(407, 361))
+ self.widget.setBaseSize(QSize(407, 361))
+ self.widget.setStyleSheet(u"QPushButton{\n"
+" padding: 8px 20px;\n"
+" font-size: 13px;\n"
+" line-height: 1.65;\n"
+" border-radius: 20px;\n"
+" display: inline-block;\n"
+" margin-bottom: 0;\n"
+" font-weight: 600;\n"
+" text-align: center;\n"
+" vertical-align: middle;\n"
+" touch-action: manipulation;\n"
+" cursor: pointer;\n"
+" background-image: none;\n"
+" border: 1px solid transparent;\n"
+" white-space: nowrap;\n"
+" font-family: inherit;\n"
+" text-transform: none;\n"
+" background-color: #00a6fd;\n"
+" border-color: #00a6fd;\n"
+" color: #fff;\n"
+" \n"
+"}")
+ self.layoutWidget = QWidget(self.widget)
+ self.layoutWidget.setObjectName(u"layoutWidget")
+ self.layoutWidget.setGeometry(QRect(0, 0, 452, 331))
+ self.verticalLayout_2 = QVBoxLayout(self.layoutWidget)
+ self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+ self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout_6 = QVBoxLayout()
+ self.verticalLayout_6.setObjectName(u"verticalLayout_6")
+ self.usernameError = QLabel(self.layoutWidget)
+ self.usernameError.setObjectName(u"usernameError")
+ self.usernameError.setEnabled(True)
+ self.usernameError.setMinimumSize(QSize(380, 32))
+ self.usernameError.setMaximumSize(QSize(380, 32))
+ font = QFont()
+ font.setFamily(u"18thCentury")
+ font.setPointSize(10)
+ font.setBold(False)
+ font.setWeight(50)
+ self.usernameError.setFont(font)
+ self.usernameError.setAutoFillBackground(False)
+ self.usernameError.setStyleSheet(u"*{\n"
+"color:red;\n"
+"}")
+ self.usernameError.setAlignment(Qt.AlignCenter)
+
+ self.verticalLayout_6.addWidget(self.usernameError)
+
+ self.horizontalLayout_2 = QHBoxLayout()
+ self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
+ self.label = QLabel(self.layoutWidget)
+ self.label.setObjectName(u"label")
+ self.label.setMinimumSize(QSize(70, 0))
+ self.label.setMaximumSize(QSize(70, 16777215))
+ self.label.setBaseSize(QSize(70, 0))
+ self.label.setAlignment(Qt.AlignCenter)
+
+ self.horizontalLayout_2.addWidget(self.label)
+
+ self.usernameLineEdit = QLineEdit(self.layoutWidget)
+ self.usernameLineEdit.setObjectName(u"usernameLineEdit")
+ self.usernameLineEdit.setMinimumSize(QSize(300, 32))
+ self.usernameLineEdit.setMaximumSize(QSize(300, 32))
+ self.usernameLineEdit.setStyleSheet(u"QLineEdit{\n"
+"background-color: white;\n"
+"selection-color: white;\n"
+"selection-background-color: blue;\n"
+"}")
+ self.usernameLineEdit.setMaxLength(64)
+
+ self.horizontalLayout_2.addWidget(self.usernameLineEdit)
+
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+ self.horizontalLayout_2.addItem(self.horizontalSpacer)
+
+
+ self.verticalLayout_6.addLayout(self.horizontalLayout_2)
+
+ self.passwordError = QLabel(self.layoutWidget)
+ self.passwordError.setObjectName(u"passwordError")
+ self.passwordError.setMinimumSize(QSize(380, 32))
+ self.passwordError.setMaximumSize(QSize(380, 32))
+ self.passwordError.setFont(font)
+ self.passwordError.setStyleSheet(u"*{\n"
+"color:red;\n"
+"}")
+ self.passwordError.setAlignment(Qt.AlignCenter)
+
+ self.verticalLayout_6.addWidget(self.passwordError)
+
+ self.horizontalLayout_3 = QHBoxLayout()
+ self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
+ self.label_2 = QLabel(self.layoutWidget)
+ self.label_2.setObjectName(u"label_2")
+ self.label_2.setMinimumSize(QSize(70, 0))
+ self.label_2.setMaximumSize(QSize(70, 16777215))
+ self.label_2.setBaseSize(QSize(70, 0))
+ self.label_2.setAlignment(Qt.AlignCenter)
+
+ self.horizontalLayout_3.addWidget(self.label_2)
+
+ self.passwordLineEdit = QLineEdit(self.layoutWidget)
+ self.passwordLineEdit.setObjectName(u"passwordLineEdit")
+ self.passwordLineEdit.setMinimumSize(QSize(300, 0))
+ self.passwordLineEdit.setMaximumSize(QSize(300, 32))
+ self.passwordLineEdit.setBaseSize(QSize(300, 32))
+ self.passwordLineEdit.setStyleSheet(u"QLineEdit{\n"
+"background-color: white;\n"
+"selection-color: white;\n"
+"selection-background-color: blue;\n"
+"}")
+ self.passwordLineEdit.setEchoMode(QLineEdit.Password)
+
+ self.horizontalLayout_3.addWidget(self.passwordLineEdit)
+
+ self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+ self.horizontalLayout_3.addItem(self.horizontalSpacer_2)
+
+
+ self.verticalLayout_6.addLayout(self.horizontalLayout_3)
+
+
+ self.verticalLayout_2.addLayout(self.verticalLayout_6)
+
+ self.horizontalLayout = QHBoxLayout()
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
+ self.loginButton = QPushButton(self.layoutWidget)
+ self.loginButton.setObjectName(u"loginButton")
+ self.loginButton.setMaximumSize(QSize(150, 16777215))
+ self.loginButton.setCursor(QCursor(Qt.PointingHandCursor))
+ self.loginButton.setStyleSheet(u"")
+
+ self.horizontalLayout.addWidget(self.loginButton)
+
+ self.forgetPwdButton = QPushButton(self.layoutWidget)
+ self.forgetPwdButton.setObjectName(u"forgetPwdButton")
+ self.forgetPwdButton.setMaximumSize(QSize(150, 16777215))
+ self.forgetPwdButton.setCursor(QCursor(Qt.PointingHandCursor))
+
+ self.horizontalLayout.addWidget(self.forgetPwdButton)
+
+
+ self.verticalLayout_2.addLayout(self.horizontalLayout)
+
+
+ self.verticalLayout.addWidget(self.widget)
+
+
+ self.retranslateUi(Form)
+
+ QMetaObject.connectSlotsByName(Form)
+ # setupUi
+
+ def retranslateUi(self, Form):
+ Form.setWindowTitle(QCoreApplication.translate("Form", u"\u7528\u6237\u767b\u5f55", None))
+ self.usernameError.setText("")
+ self.label.setText(QCoreApplication.translate("Form", u"\u7528 \u6237 \u540d", None))
+ self.usernameLineEdit.setPlaceholderText(QCoreApplication.translate("Form", u"\u8bf7\u8f93\u5165\u7528\u6237\u540d", None))
+ self.passwordError.setText("")
+ self.label_2.setText(QCoreApplication.translate("Form", u"\u5bc6 \u7801", None))
+ self.passwordLineEdit.setPlaceholderText(QCoreApplication.translate("Form", u"\u8bf7\u8f93\u5165\u5bc6\u7801", None))
+ self.loginButton.setText(QCoreApplication.translate("Form", u"\u767b\u5f55", None))
+ self.forgetPwdButton.setText(QCoreApplication.translate("Form", u"\u5fd8\u8bb0\u5bc6\u7801\uff1f", None))
+ # retranslateUi
+
diff --git a/features/ui/ui_login.ui b/features/ui/ui_login.ui
new file mode 100644
index 0000000000000000000000000000000000000000..290a39b5b485e97a2993a33c6ef100e07b4d21fa
--- /dev/null
+++ b/features/ui/ui_login.ui
@@ -0,0 +1,376 @@
+
+
+ Form
+
+
+ Qt::ApplicationModal
+
+
+
+ 0
+ 0
+ 407
+ 361
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 407
+ 361
+
+
+
+
+ 407
+ 361
+
+
+
+ 用户登录
+
+
+
+
+
+ -
+
+
+
+ 407
+ 361
+
+
+
+
+ 407
+ 361
+
+
+
+
+ 407
+ 361
+
+
+
+ QPushButton{
+ padding: 8px 20px;
+ font-size: 13px;
+ line-height: 1.65;
+ border-radius: 20px;
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: 600;
+ text-align: center;
+ vertical-align: middle;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ font-family: inherit;
+ text-transform: none;
+ background-color: #00a6fd;
+ border-color: #00a6fd;
+ color: #fff;
+
+}
+
+
+
+
+ 0
+ 0
+ 452
+ 331
+
+
+
+
-
+
+
-
+
+
+ true
+
+
+
+ 380
+ 32
+
+
+
+
+ 380
+ 32
+
+
+
+
+ 18thCentury
+ 10
+ 50
+ false
+
+
+
+ false
+
+
+ *{
+color:red;
+}
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
-
+
+
+
+ 70
+ 0
+
+
+
+
+ 70
+ 16777215
+
+
+
+
+ 70
+ 0
+
+
+
+ 用 户 名
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 300
+ 32
+
+
+
+
+ 300
+ 32
+
+
+
+ QLineEdit{
+background-color: white;
+selection-color: white;
+selection-background-color: blue;
+}
+
+
+ 64
+
+
+ 请输入用户名
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+
+ 380
+ 32
+
+
+
+
+ 380
+ 32
+
+
+
+
+ 18thCentury
+ 10
+ 50
+ false
+
+
+
+ *{
+color:red;
+}
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
-
+
+
+
+ 70
+ 0
+
+
+
+
+ 70
+ 16777215
+
+
+
+
+ 70
+ 0
+
+
+
+ 密 码
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 300
+ 0
+
+
+
+
+ 300
+ 32
+
+
+
+
+ 300
+ 32
+
+
+
+ QLineEdit{
+background-color: white;
+selection-color: white;
+selection-background-color: blue;
+}
+
+
+ QLineEdit::Password
+
+
+ 请输入密码
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 150
+ 16777215
+
+
+
+ PointingHandCursor
+
+
+
+
+
+ 登录
+
+
+
+ -
+
+
+
+ 150
+ 16777215
+
+
+
+ PointingHandCursor
+
+
+ 忘记密码?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/ui/ui_logined.py b/features/ui/ui_logined.py
new file mode 100644
index 0000000000000000000000000000000000000000..8d469fb4a4838c23747f684cb92c94b4b328be25
--- /dev/null
+++ b/features/ui/ui_logined.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'ui_logined.ui'
+##
+## Created by: Qt User Interface Compiler version 5.15.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide2.QtCore import *
+from PySide2.QtGui import *
+from PySide2.QtWidgets import *
+
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ if not Form.objectName():
+ Form.setObjectName(u"Form")
+ Form.resize(407, 361)
+ Form.setMinimumSize(QSize(407, 361))
+ Form.setMaximumSize(QSize(407, 361))
+ Form.setBaseSize(QSize(407, 361))
+ Form.setStyleSheet(u"QPushButton{\n"
+" padding: 8px 20px;\n"
+" font-size: 13px;\n"
+" line-height: 1.65;\n"
+" border-radius: 20px;\n"
+" display: inline-block;\n"
+" margin-bottom: 0;\n"
+" font-weight: 600;\n"
+" text-align: center;\n"
+" vertical-align: middle;\n"
+" touch-action: manipulation;\n"
+" cursor: pointer;\n"
+" background-image: none;\n"
+" border: 1px solid transparent;\n"
+" white-space: nowrap;\n"
+" font-family: inherit;\n"
+" text-transform: none;\n"
+" background-color: #00a6fd;\n"
+" border-color: #00a6fd;\n"
+" color: #fff;\n"
+" \n"
+"}")
+ self.layoutWidget = QWidget(Form)
+ self.layoutWidget.setObjectName(u"layoutWidget")
+ self.layoutWidget.setGeometry(QRect(10, 0, 391, 341))
+ self.verticalLayout = QVBoxLayout(self.layoutWidget)
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout = QHBoxLayout()
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
+ self.label = QLabel(self.layoutWidget)
+ self.label.setObjectName(u"label")
+ self.label.setFrameShape(QFrame.NoFrame)
+ self.label.setFrameShadow(QFrame.Plain)
+ self.label.setTextFormat(Qt.AutoText)
+ self.label.setAlignment(Qt.AlignCenter)
+ self.label.setMargin(0)
+
+ self.horizontalLayout.addWidget(self.label)
+
+ self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+ self.horizontalLayout.addItem(self.verticalSpacer_2)
+
+ self.usernameLabel = QLabel(self.layoutWidget)
+ self.usernameLabel.setObjectName(u"usernameLabel")
+ self.usernameLabel.setCursor(QCursor(Qt.IBeamCursor))
+ self.usernameLabel.setLayoutDirection(Qt.LeftToRight)
+ self.usernameLabel.setWordWrap(True)
+ self.usernameLabel.setMargin(0)
+ self.usernameLabel.setTextInteractionFlags(Qt.TextSelectableByMouse)
+
+ self.horizontalLayout.addWidget(self.usernameLabel)
+
+
+ self.verticalLayout.addLayout(self.horizontalLayout)
+
+ self.horizontalLayout_2 = QHBoxLayout()
+ self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+ self.horizontalLayout_2.addItem(self.horizontalSpacer)
+
+ self.loginOutButton = QPushButton(self.layoutWidget)
+ self.loginOutButton.setObjectName(u"loginOutButton")
+ self.loginOutButton.setCursor(QCursor(Qt.PointingHandCursor))
+
+ self.horizontalLayout_2.addWidget(self.loginOutButton)
+
+ self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+ self.horizontalLayout_2.addItem(self.verticalSpacer)
+
+
+ self.verticalLayout.addLayout(self.horizontalLayout_2)
+
+
+ self.retranslateUi(Form)
+
+ QMetaObject.connectSlotsByName(Form)
+ # setupUi
+
+ def retranslateUi(self, Form):
+ Form.setWindowTitle(QCoreApplication.translate("Form", u"\u7528\u6237\u4fe1\u606f", None))
+ self.label.setText(QCoreApplication.translate("Form", u"\u7528 \u6237 \u540d", None))
+ self.usernameLabel.setText("")
+ self.loginOutButton.setText(QCoreApplication.translate("Form", u"\u6ce8 \u9500", None))
+ # retranslateUi
+
diff --git a/features/ui/ui_logined.ui b/features/ui/ui_logined.ui
new file mode 100644
index 0000000000000000000000000000000000000000..45a4af71e0e0b09d7f4db3eab6ad02247804f348
--- /dev/null
+++ b/features/ui/ui_logined.ui
@@ -0,0 +1,174 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 407
+ 361
+
+
+
+
+ 407
+ 361
+
+
+
+
+ 407
+ 361
+
+
+
+
+ 407
+ 361
+
+
+
+ 用户信息
+
+
+ QPushButton{
+ padding: 8px 20px;
+ font-size: 13px;
+ line-height: 1.65;
+ border-radius: 20px;
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: 600;
+ text-align: center;
+ vertical-align: middle;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ font-family: inherit;
+ text-transform: none;
+ background-color: #00a6fd;
+ border-color: #00a6fd;
+ color: #fff;
+
+}
+
+
+
+
+ 10
+ 0
+ 391
+ 341
+
+
+
+ -
+
+
-
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ 用 户 名
+
+
+ Qt::AutoText
+
+
+ Qt::AlignCenter
+
+
+ 0
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ IBeamCursor
+
+
+ Qt::LeftToRight
+
+
+
+
+
+ true
+
+
+ 0
+
+
+ Qt::TextSelectableByMouse
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ PointingHandCursor
+
+
+ 注 销
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pmgui.py b/pmgui.py
index a6b0c97dd0dd0d34ca202eca276c4c0ad64b5e87..52f2bddc5d7f9a1db8c15a2678236d3e3730a57f 100644
--- a/pmgui.py
+++ b/pmgui.py
@@ -24,6 +24,7 @@ from features.util.update import perform_update, UpdateTipClient
from features.feedback import FeedbackClient
from features.ui.widgets.controlpanel import PMPageExt
from features.ui.pmwidgets import BaseMainWindow
+from multiprocessing import shared_memory
import utils
import logging
@@ -104,6 +105,13 @@ class PMToolBarHome(PMGToolBar):
self.add_tool_button('button_settings', self.tr('Settings'), self.tr('Modify program Settings items'),
create_icon(
':/color/theme/default/icons/setting.svg'))
+ self.addSeparator()
+ self.add_tool_button(
+ 'button_login',
+ self.tr('用户管理'),
+ self.tr('用户管理'),
+ create_icon(':/color/theme/default/icons/mActionUserRoleManager.svg')
+ )
def process_visibility_actions(self, e: ActionWithMessage):
"""
@@ -132,6 +140,7 @@ class PMToolBarHome(PMGToolBar):
self.get_control_widget('button_help').clicked.connect(lambda: get_main_window().main_help_display())
self.get_control_widget('button_community').clicked.connect(lambda: get_main_window().main_community_display())
self.get_control_widget('button_feedback').clicked.connect(lambda: get_main_window().main_feedback_display())
+ self.get_control_widget('button_login').clicked.connect(lambda: get_main_window().login_form_display())
self.append_menu('button_new_script', 'Python',
lambda: get_main_window().main_new_script_display(),
@@ -389,6 +398,21 @@ class MainWindow(BaseMainWindow):
self.main_first_form = base.FirstForm(parent=self)
self.main_first_form.show()
+ def login_form_display(self):
+ """
+ 显示"登录"窗口
+ Displays the "Quick Action" window
+ """
+ shared_memo = shared_memory.SharedMemory(name="sharedMemory") # 通过name找到共享内存token
+ buff = shared_memo.buf
+ token = bytes(buff[:199]).decode().replace("\x00", "")
+ if token != "":
+ self.main_login_form = base.LoginedForm(parent=self)
+ self.main_login_form.exec_()
+ else:
+ self.main_login_form = base.LoginForm(parent=self)
+ self.main_login_form.exec_()
+
def main_appstore_dispaly(self):
"""
显示"应用商店"窗口
diff --git a/pmlocalserver/server.py b/pmlocalserver/server.py
index 9d86addd0d57ed30d5dca89f692c2fdda3e08a8a..80e2d11a18462b9bd5d77eabe54cb70a5f4d3cb8 100644
--- a/pmlocalserver/server.py
+++ b/pmlocalserver/server.py
@@ -2,6 +2,7 @@ from flask import Flask
from flask_cors import CORS
import threading
+from multiprocessing import shared_memory
server = Flask(__name__, static_folder='static', static_url_path='/static')
CORS(server, supports_credentials=True) # 解决跨域
@@ -9,5 +10,10 @@ CORS(server, supports_credentials=True) # 解决跨域
server_thread = threading.Thread(target=server.run) # 这个线程与主界面没有任何交互,直接用系统内建的线程库即可,保证其安全性。
server_thread.setDaemon(True)
+"""
+创建共享内存sharedMemory,用于存放登录后返回的token和其他信息,token长度为199,索引为0-198,在用户登录后请勿将其覆盖
+"""
+shared_memo = shared_memory.SharedMemory(name="sharedMemory", create=True, size=4096)
+
if __name__ == '__main__':
server_thread.start()
diff --git a/pyminer_comm/data_client/data_client.py b/pyminer_comm/data_client/data_client.py
index 2ad6c31c9dcd472c9220ad82dfe3396d0694935f..6f3a71d9b64e4218a2b7a1e153be636404903aeb 100644
--- a/pyminer_comm/data_client/data_client.py
+++ b/pyminer_comm/data_client/data_client.py
@@ -1,5 +1,4 @@
import logging
-import time
import typing
from typing import Dict, Any, List
@@ -29,7 +28,15 @@ def http_get_vars(var_names: typing.List[str], preview: bool) -> typing.Dict[str
return msg
-def shm_get_vars(var_names: List[str]):
+def shm_get_vars(var_names: List[str]) -> Dict[str, Any]:
+ """
+ 通过共享内存获取多个变量,以字典的形式返回。
+ Args:
+ var_names:
+
+ Returns:
+
+ """
protocol = get_protocol()
shm_name = get('/start_share_variables',
dict_to_b64({'var_names': var_names}, protocol),
@@ -37,16 +44,24 @@ def shm_get_vars(var_names: List[str]):
logger.info('get shared variables %s from shmname%s' % (var_names, shm_name))
from multiprocessing import shared_memory
shm_b = shared_memory.SharedMemory(shm_name.decode(encoding='utf8'))
- b = shm_b.buf.tobytes()
- df = pickle_to_dict(b)
+ buf_bytes = shm_b.buf.tobytes()
+ shm_vars_dict = pickle_to_dict(buf_bytes)
shm_b.close() # Close each SharedMemory instance
response = get('/end_share_variables',
shm_name.decode(encoding='utf8'),
protocol=str(protocol))
- return df
+ return shm_vars_dict
+
+def shm_set_vars(var_dic: Dict[str, Any]) -> None:
+ """
+ 通过共享内存,设置多个变量的值。
+ Args:
+ var_dic:
-def shm_set_vars(var_dic: Dict[str, Any]):
+ Returns:
+
+ """
from multiprocessing import shared_memory
protocol = get_protocol()
dmp = dict_to_pickle(var_dic, protocol)
@@ -92,22 +107,30 @@ def get_var(var_name: str, preview=False) -> object:
"""
try:
- if preview or not shm_allowed():
- if preview:
- var = http_get_vars([var_name], preview=True).get(var_name)
- else:
- var = http_get_vars([var_name], preview=False).get(var_name)
- return var
- else:
- return shm_get_vars([var_name]).get(var_name)
+ return get_vars([var_name], preview).get(var_name)
except ConnectionRefusedError:
raise ConnectionRefusedError('Cannot connect to workspace. Please confirm that PyMiner has been started!')
-def get_vars(var_names: List, preview: bool = False) -> object:
+def get_vars(var_names: List, preview: bool = False) -> Dict[str, Any]:
+ """
+ 获取多个数据
+ Args:
+ var_names: 变量名称列表
+ preview: 是否进行预览
+
+ Returns:
+
+ """
try:
if shm_allowed() and not preview:
- return shm_get_vars(var_names)
+ try:
+ return shm_get_vars(var_names)
+ except Exception as e:
+ logger.error("共享内存传输失效,退回到http传输。")
+ import traceback
+ traceback.print_exc()
+ return http_get_vars(var_names, False)
else:
return http_get_vars(var_names, preview=preview)
except ConnectionRefusedError:
@@ -145,10 +168,12 @@ def set_var(var_name: str, var: object, provider: str = 'external') -> None:
人为添加代码。
当然,在IPython中调用了这个函数也不会出现错误,只是会降低效率。
+ 在允许使用共享内存的情况下,会尽量使用共享内存。如果共享内存无法成功,那么就降级到http传输方式。
+ http传输方式在传输较小的数据时,反而会比共享内存快一点。
+
Examples
---------
- >>> from pyminer_algorithms import *
>>> set_var('x',[1,2,3,4,5])
>>> get_var('x')
[1,2,3,4,5]
@@ -158,14 +183,7 @@ def set_var(var_name: str, var: object, provider: str = 'external') -> None:
"""
try:
- # try:
- # get_ipython().neglect_post_run = True # 检测是否在Ipython中,如果是,就将这个标志位置为True防止重复更改。
- # except NameError:
- # pass
- if shm_allowed():
- shm_set_vars({var_name: var})
- else:
- http_set_vars({var_name: var})
+ set_vars({var_name: var})
except ConnectionRefusedError:
raise ConnectionRefusedError('Cannot connect to workspace. Please confirm that PyMiner has been started!')
@@ -215,7 +233,12 @@ def set_vars(var_dic: Dict[str, Any]):
if not shm_allowed():
http_set_vars(var_dic)
else:
- shm_set_vars(var_dic)
+ try:
+ shm_set_vars(var_dic)
+ except Exception as e:
+ import traceback
+ traceback.print_exc()
+ http_set_vars(var_dic)
except:
import traceback
traceback.print_exc()
@@ -259,7 +282,7 @@ def get_var_names(filter: str = '') -> typing.List[str]:
return var_names
-def get_data_descs() -> typing.Dict[str,DataDesc]:
+def get_data_descs() -> typing.Dict[str, DataDesc]:
protocol = get_protocol()
msg = get('/get_data_descs', "", protocol=str(protocol))
var_names = b64_to_dict(msg).get('data_descs')
diff --git a/utils/http_client.py b/utils/http_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..d86d27d96ba365dcd7249557ec3e57fa0248c5b4
--- /dev/null
+++ b/utils/http_client.py
@@ -0,0 +1,16 @@
+import requests
+
+API = "http://pyminer.com/"
+LOGIN_URL = 'api/v1/user/login/'
+
+
+def client(url, method, data):
+ conn = requests.session()
+ if method == "post":
+ headers = {
+ "Content-type": "application/json; charset=utf-8;"
+ }
+ resp = conn.post(url, data, headers)
+ elif method == "get":
+ pass
+ return resp