在action_base.py中添加了ActionSignal和RunActionThread类,以及修改了ActionBase类,将执行动作放到线程中,从而提高了程序的响应性和用户体验。在action_list.py中修复了一个样式表的错误。在chat_page.py中修改了ChatPage和ActionList类,增加了与动作执行相关的功能。

This commit is contained in:
yuruo
2024-05-27 15:51:03 +08:00
parent efb038cea5
commit bfe8ac0a05
3 changed files with 55 additions and 107 deletions

View File

@@ -1,45 +1,43 @@
from typing import Type, Any, ClassVar
import uuid
from PyQt6.QtCore import Qt
from typing import Type, Any
from PyQt6.QtCore import Qt, pyqtSignal, QObject
from PyQt6.QtWidgets import QHBoxLayout, QLabel, QLineEdit, QPushButton
from pydantic import BaseModel
from utils.global_util import GlobalUtil
from utils.qt_util import QtUtil
from utils.undo_command import ActionListAddCommand
from PyQt6.QtCore import QThread
class ActionSignal(QObject):
finish_run_signal = pyqtSignal(object)
start_run_signal = pyqtSignal()
def finish_run_signal_emit(self, res):
self.finish_run_signal.emit(res)
def start_run_signal_emit(self):
self.start_run_signal.emit()
class RunActionThread(QThread):
def __init__(self, action):
super().__init__()
self.action = action
def run(self):
res = self.action.run_with_out_arg()
self.action.get_signal().finish_run_signal_emit(res)
class ActionBase(BaseModel):
name: str = ""
description: str = ""
# 用于标识 action 类型include 和 single 两种类型
action_type: str = ""
args: Type[BaseModel]
output_save_name: str = ""
action_pos: int = -1
action_level: int = -1
uuid: str = ""
parent_uuid: str = ""
def __init__(self, output_save_name_from_drag: str = None, **data: Any):
def __init__(self, **data: Any):
super().__init__(**data)
# 为每个实例生成唯一的 UUID
self.uuid = str(uuid.uuid4())
self._ui_name_and_line_edit = {}
self._output_edit = None
self._config_ui = QtUtil.load_ui("action_config_page.ui")
self._parent = None
self._is_config_page_init = False
# 如果拖动过 action则使用传进来的 output_save_name
self._output_save_name_from_drag = output_save_name_from_drag
def set_output_save_name_from_drag(self, output_save_name_from_drag: str):
self._output_save_name_from_drag = output_save_name_from_drag
self._action_signal = ActionSignal()
def get_signal(self):
return self._action_signal
def get_parent(self):
return GlobalUtil.get_widget_by_uuid(self.parent_uuid, "action_list_item")
def run(self, *args, **kwargs):
raise TypeError("Not realize run function")
@@ -47,10 +45,10 @@ class ActionBase(BaseModel):
def run_with_out_arg(self):
print("运行中...")
res = self.run(**self.args.model_dump())
# 保存输出结果
if self.output_save_name:
GlobalUtil.current_page.output_save_dict[self.uuid][self.output_save_name] = res
GlobalUtil.current_page.update_runing_terminal()
# # 保存输出结果
# if self.output_save_name:
# GlobalUtil.current_page.output_save_dict[self.uuid][self.output_save_name] = res
# GlobalUtil.current_page.update_runing_terminal()
return res
# 设置配置界面的布局
@@ -72,75 +70,17 @@ class ActionBase(BaseModel):
self._ui_name_and_line_edit[field] = line_edit
def save_out_put_ui(self):
# 判断是否需要保存输出
if self.output_save_name != "":
output_label = QLabel(self._config_ui)
output_label.setText("保存结果至")
output_line_edit = QLineEdit("output_save_name")
self._output_edit = output_line_edit
# 使用外部传进来的 output_save_name
if self._output_save_name_from_drag:
self.output_save_name = self._output_save_name_from_drag
# 设置编辑框的默认名称
output_line_edit.setText(self.output_save_name)
else:
output_save_name = self.output_save_name
# 为输出结果自动取名
i = 1
# 获取 editPage 页面的 output_save_dict
output_save_dict = GlobalUtil.current_page.get_output_dict()
# 找到一个不存在的名称
while True:
if output_save_name in output_save_dict.keys():
output_save_name = self.output_save_name + "_" + str(i)
i += 1
continue
else:
self.output_save_name = output_save_name
# 设置编辑框的默认名称
output_line_edit.setText(output_save_name)
break
self._config_ui.output_config.addWidget(output_label)
self._config_ui.output_config.addWidget(output_line_edit)
else:
self._config_ui.output_config.addWidget(QLabel("当前行为不包含输出项"))
def __cancel_button_clicked(self):
self._config_ui.hide()
def get_action_list(self):
return self.get_parent().get_parent()
def get_action_list_item(self):
return self.get_parent()
def _save_button_clicked(self):
arg = {}
for arg_name in self._ui_name_and_line_edit:
arg[arg_name] = self._ui_name_and_line_edit[arg_name].text()
self.args = self.args.model_validate(arg)
self.action_level = 0
# 如果设置了output_save_name向全局中插入该变量
if self.output_save_name != "":
self.output_save_name = self._output_edit.text()
GlobalUtil.current_page.output_save_dict[self.uuid] = {}
GlobalUtil.current_page.output_save_dict[self.uuid][self.output_save_name] = ""
GlobalUtil.current_page.update_send_to_ai_selection()
# 判断 item 是否在 action_list 中
def item_in_action_list():
action_list = self.get_action_list()
for item in action_list.get_action_list_items(action_list):
if item == self.get_action_list_item():
return True
return False
# 插入新的 acton
if not item_in_action_list():
GlobalUtil.current_page.q_undo_stack.push(ActionListAddCommand(self.get_action_list(), self.action_pos, self.get_action_list_item()))
thread = RunActionThread(self)
thread.start()
self._action_signal.start_run_signal_emit()
self._config_ui.hide()
@@ -154,9 +94,6 @@ class ActionBase(BaseModel):
# 居上对齐
self._config_ui.config_list.layout().setAlignment(Qt.AlignmentFlag.AlignTop)
# 如果配置页面未加载过,就进行加载
if not self._is_config_page_init:
self.save_out_put_ui()
self.config_page_ui()
self.config_page_ui()
# 如果已经加载过,就直接显示
self._is_config_page_init = True
self._config_ui.show()

View File

@@ -83,7 +83,7 @@ class ActionList(QListWidget):
self.setSpacing(1)
self.setStyleSheet(
"QListView{background:rgb(220,220,220); border:0px; margin:0px 0px 0px 0px;}"
"QListView::Item{height:40px; border:0px; background:rgb(255,255,255);margin-left: 3px;}"
"QListViewf::Item{height:40px; border:0px; background:rgb(255,255,255);margin-left: 3px;}"
# "QListView::Item:hover{color:rgba(40, 40, 200, 255); padding-left:14px;})"
# 选中时为透明,否则会全白
"QListView::Item:selected{color:rgb(0, 0, 0);outline: none;}"

View File

@@ -9,27 +9,38 @@ from pages.config_page import ConfigPage
from utils.qt_util import QtUtil
class ActionItems(QListWidgetItem):
def __init__(self, action):
def __init__(self, action, chat_page):
super().__init__()
self.action = action
self.chat_page = chat_page
self.action.get_signal().finish_run_signal.connect(self.save_output)
self.action.get_signal().start_run_signal.connect(self.start_run)
# 创建一个 QLabel 作为列表项的小部件
self.label = QLabel()
text = f"<p style='font-size:15px;color:blue;margin-bottom:0;'>{self.action.name}</p><p style='font-size:11px;color:gray;margin-top:0;'>{self.action.description}</p>"
self.label.setText(text)
self.setSizeHint(self.label.sizeHint())
def save_output(self, res):
self.chat_page.new_conversation(f"执行成功,执行结果:{str(res)}", "system")
def start_run(self):
self.chat_page.action_list.set_visibility(False)
self.chat_page.chat_input.clear()
self.chat_page.new_conversation(f"执行{self.action.name}动作中:\n执行动作描述:{self.action.description}\n执行参数:{self.action.args}", "system")
class ActionList(QListWidget):
def __init__(self, parent=None):
def __init__(self, parent=None, chat_page=None):
super().__init__(parent)
self.chat_page = chat_page
self.setVisible(False)
self.setFocusPolicy(Qt.FocusPolicy.TabFocus)
actions = ActionUtil.get_funcs()
self.setSpacing(3)
for i in range(len(actions)):
action = actions[i]
item = ActionItems(action(args={}))
item = ActionItems(action(args={}), chat_page=self.chat_page)
self.insertItem(i, item)
self.setItemWidget(item, item.label)
@@ -150,14 +161,14 @@ class ChatPage(QMainWindow, interface_ui):
def setup_up(self):
# self = QtUtil.load_ui("chat_page.ui")
chat_input = ChatInput(parent=self.centralwidget, chat_page=self)
chat_input.setGeometry(QtCore.QRect(40, 580, 601, 51))
chat_input.setStyleSheet("border-radius: 30px")
chat_input.setObjectName("chat_input")
chat_input.setPlaceholderText("请输入“/”,选择运行的指令")
self.chat_input = ChatInput(parent=self.centralwidget, chat_page=self)
self.chat_input.setGeometry(QtCore.QRect(40, 580, 601, 51))
self.chat_input.setStyleSheet("border-radius: 30px")
self.chat_input.setObjectName("chat_input")
self.chat_input.setPlaceholderText("请输入“/”,选择运行的指令")
self.chat_list = ChatList(parent=self.centralwidget, chat_page=self)
self.action_list = ActionList(parent=self.centralwidget)
self.action_list = ActionList(parent=self.centralwidget, chat_page=self)
self.action_list.setGeometry(QtCore.QRect(40, 390, 251, 181))
self.action_list.setStyleSheet("border: none;")
self.action_list.setObjectName("action_list")