2023-02-10 21:51:03 +08:00

210 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PyQt5.QtCore import QSettings, pyqtSignal, Qt
from PyQt5.QtGui import QIcon, QTextBlock, QTextCursor
from PyQt5.QtWidgets import QDialog, QLabel,QComboBox, QDialogButtonBox, QFileDialog, QHBoxLayout, QMessageBox, QProgressBar, QPushButton, QTextEdit, QVBoxLayout
import subprocess
import threading
import sys
from rscder.utils.icons import IconInstance
import os
import sys
import ai_method.subprcess_python as sp
from ai_method import AI_METHOD
from misc.main import AlgFrontend
import abc
class AIMethodDialog(QDialog):
stage_end = pyqtSignal(int)
stage_log = pyqtSignal(str)
ENV = 'base'
name = ''
stages = []
setting_widget = None
def __init__(self, parent = None) -> None:
super().__init__(parent)
# self.setting_widget:AlgFrontend = setting_widget
vlayout = QVBoxLayout()
hlayout = QHBoxLayout()
select_label = QLabel('模式选择:')
self.select_mode = QComboBox()
self.select_mode.addItem('----------', 'NoValue')
for stage in self.stages:
self.select_mode.addItem(stage[1], stage[0])
setting_btn = QPushButton(IconInstance().SELECT, '配置')
hlayout.addWidget(select_label)
hlayout.addWidget(self.select_mode, 2)
hlayout.addWidget(setting_btn)
self.setting_args = []
def show_setting():
if self.setting_widget is None:
return
dialog = QDialog(parent)
vlayout = QVBoxLayout()
dialog.setLayout(vlayout)
widget = self.setting_widget.get_widget(dialog)
vlayout.addWidget(widget)
dbtn_box = QDialogButtonBox(dialog)
dbtn_box.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
dbtn_box.button(QDialogButtonBox.Ok).setText('确定')
dbtn_box.button(QDialogButtonBox.Cancel).setText('取消')
dbtn_box.button(QDialogButtonBox.Ok).clicked.connect(dialog.accept)
dbtn_box.button(QDialogButtonBox.Cancel).clicked.connect(dialog.reject)
vlayout.addWidget(dbtn_box, 1, Qt.AlignRight)
dialog.setMinimumHeight(500)
dialog.setMinimumWidth(900)
if dialog.exec_() == QDialog.Accepted:
self.setting_args = self.setting_widget.get_params(widget)
setting_btn.clicked.connect(show_setting)
btnbox = QDialogButtonBox(self)
btnbox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
btnbox.button(QDialogButtonBox.Ok).setText('确定')
btnbox.button(QDialogButtonBox.Cancel).setText('取消')
processbar = QProgressBar(self)
processbar.setMaximum(1)
processbar.setMinimum(0)
processbar.setEnabled(False)
def run_stage():
self.log = f'开始{self.current_stage}...\n'
btnbox.button(QDialogButtonBox.Cancel).setEnabled(True)
processbar.setMaximum(0)
processbar.setValue(0)
processbar.setEnabled(True)
q = threading.Thread(target=self.run_stage, args=(self.current_stage,))
q.start()
pass
btnbox.button(QDialogButtonBox.Cancel).setEnabled(False)
btnbox.accepted.connect(run_stage)
btnbox.rejected.connect(self._stage_stop)
self.processbar = processbar
vlayout.addLayout(hlayout)
self.detail = QTextEdit(self)
vlayout.addWidget(self.detail)
vlayout.addWidget(processbar)
vlayout.addWidget(btnbox)
self.detail.setReadOnly(True)
# self.detail.copyAvailable(True)
self.detail.setText(f'等待开始...')
self.setLayout(vlayout)
self.setMinimumHeight(500)
self.setMinimumWidth(500)
self.setWindowIcon(IconInstance().AI_DETECT)
self.setWindowTitle(self.name)
self.stage_end.connect(self._stage_end)
self.log = f'等待开始...\n'
self.stage_log.connect(self._stage_log)
self.p = None
@property
def current_stage(self):
if self.select_mode.currentData() == 'NoValue':
return None
return self.select_mode.currentData()
@property
def _python_base(self):
return os.path.abspath(os.path.join(os.path.dirname(sys.executable), '..', '..'))
@property
def activate_env(self):
script = os.path.join(self._python_base, 'Scripts','activate')
if self.ENV == 'base':
return script
else:
return script + ' ' + self.ENV
@property
def python_path(self):
if self.ENV == 'base':
return self._python_base
return os.path.join(self._python_base, 'envs', self.ENV, 'python.exe')
@property
def workdir(self):
raise NotImplementedError()
@abc.abstractmethod
def stage_script(self, stage):
return None
def _stage_log(self, l):
self.log += l + '\n'
self.detail.setText(self.log)
cursor = self.detail.textCursor()
# QTextCursor
cursor.movePosition(QTextCursor.End)
self.detail.setTextCursor(cursor)
def closeEvent(self, e) -> None:
if self.p is None:
return super().closeEvent(e)
dialog = QMessageBox(QMessageBox.Warning, '警告', '关闭窗口将停止' + self.current_stage + '', QMessageBox.Ok | QMessageBox.Cancel)
dialog.button(QMessageBox.Ok).clicked.connect(dialog.accepted)
dialog.button(QMessageBox.Cancel).clicked.connect(dialog.rejected)
dialog.show()
r = dialog.exec()
# print(r)
# print(QMessageBox.Rejected)
# print(QMessageBox.Accepted)
if r == QMessageBox.Cancel:
e.ignore()
return
return super().closeEvent(e)
def _stage_stop(self):
if self.p is not None:
try:
self.stage_log.emit(f'用户停止{self.stage}...')
self.p.kill()
except:
pass
def _stage_end(self, c):
self.processbar.setMaximum(1)
self.processbar.setValue(0)
self.processbar.setEnabled(False)
self.log += '完成!'
self.detail.setText(self.log)
def run_stage(self, stage):
if stage is None:
return
ss = self.stage_script(stage)
if ss is None:
self.stage_log.emit(f'开始{stage}时未发现脚本')
self.stage_end.emit(1)
return
if self.workdir is None:
self.stage_log.emit(f'未配置工作目录!')
self.stage_end.emit(2)
return
args = [ss, *self.setting_args]
self.p = sp.SubprocessWraper(self.python_path, self.workdir, args, self.activate_env)
for line in self.p.run():
self.stage_log.emit(line)
self.stage_end.emit(self.p.returncode)
from collections import OrderedDict
def option_to_gui(parent, options:OrderedDict):
for key in options:
pass
def gui_to_option(widget, options:OrderedDict):
pass