diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..a6880baff19c77898949d06f6bedc1b68d449d88 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/debian/files +/debian/nfs-ai.debhelper.log +/debian/nfs-ai.substvars +/debian/.debhelper +/debian/nfs-ai +.idea +__pycache__/ diff --git a/usr/share/aiassistant/ApikeyConfigPage.py b/usr/share/aiassistant/ApikeyConfigPage.py new file mode 100644 index 0000000000000000000000000000000000000000..41e6b868874f58b37581485a4bfc4bcde80469d4 --- /dev/null +++ b/usr/share/aiassistant/ApikeyConfigPage.py @@ -0,0 +1,221 @@ +from PyQt5.QtWidgets import ( + QWidget, QLabel, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QApplication, QMessageBox, QFrame +) +from PyQt5.QtCore import Qt, QSize +from PyQt5.QtGui import QIcon +from Config import Config + +class ApiKeyConfigPage(QWidget): + def __init__(self, parent=None): + super(ApiKeyConfigPage, self).__init__(parent) + self.resize(490, 555) + self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) + + # 内容框 + main_layout = QVBoxLayout(self) + + # 顶部栏 + top_bar = self.create_top_bar() + main_layout.addLayout(top_bar) + + # 横线 + separator_line = QFrame() + separator_line.setFrameShape(QFrame.HLine) + separator_line.setFrameShadow(QFrame.Plain) + separator_line.setStyleSheet("color:lightgray;") + main_layout.addWidget(separator_line) + + # 创建服务配置项的输入框,并存储它们的引用 + self.bailian_service_box, self.bailian_inputs = self.create_service_box( + "百炼-问答绘画服务", [("api-key", "API Key")] + ) + main_layout.addWidget(self.bailian_service_box) + + self.tongyi_service_box, self.tongyi_inputs = self.create_service_box( + "通义听悟·会议纪要服务", + [("app-key", "App Key"), ("access key id", "Access Key ID"), + ("access key secret", "Access Key Secret")]) + main_layout.addWidget(self.tongyi_service_box) + + # 确定和清空框 + button_layout = self.create_buttons() + main_layout.addLayout(button_layout) + + def create_top_bar(self): + # 顶部栏 + top_bar_layout = QHBoxLayout() + + # 设置 + title_label = QLabel("设置") + title_label.setStyleSheet("font-size: 18px; color: black;") + + # 关闭按钮 + close_btn = QPushButton() + close_btn.setFixedSize(24, 24) + close_btn.setStyleSheet( + ''' + QPushButton{background-color:transparent;border:none;color:white;} + ''' + ) + close_btn.setIcon(QIcon('./data/close.png')) + close_btn.setIconSize(QSize(24, 24)); + close_btn.clicked.connect(self.close) + close_btn.setFixedSize(24, 24) + + top_bar_layout.addWidget(title_label) + top_bar_layout.addStretch(1) + top_bar_layout.addWidget(close_btn) + + return top_bar_layout + + def create_ai_model_section(self): + # ai大模型 + ai_model_layout = QVBoxLayout() + ai_model_layout.setSpacing(15) + ai_model_layout.setContentsMargins(10, 10, 10, 10) + + ai_model_label = QLabel("AI大模型") + ai_model_label.setStyleSheet("font-weight: bold;") + ai_model_layout.addWidget(ai_model_label) + + + return ai_model_layout + + def create_service_box(self, service_name, fields): + service_box = QWidget() + service_box_layout = QVBoxLayout(service_box) + service_box_layout.setSpacing(10) + + service_label = QLabel(service_name) + service_label.setStyleSheet("font-weight: bold; font-size:16px;") + service_box_layout.addWidget(service_label) + + # 创建一个字典来保存字段名称与对应的 QLineEdit 控件 + field_inputs = {} + + for field_name, placeholder in fields: + field_label = QLabel(field_name) + field_input = QLineEdit() + + # 检查配置文件中是否存在该键 + existing_value = None + if field_name == "api-key": + existing_value = Config.get_api_key() + elif field_name == "app-key": + existing_value = Config.get_app_key() + elif field_name == "access key id": + existing_value = Config.get_ALIBABA_CLOUD_ACCESS_KEY_ID() + elif field_name == "access key secret": + existing_value = Config.get_ALIBABA_CLOUD_ACCESS_KEY_SECRET() + + # 根据是否存在键来设置 placeholder + if existing_value: + field_input.setPlaceholderText(f"已存在{field_name},输入将会覆盖原有{field_name}") + else: + field_input.setPlaceholderText(placeholder) + + # 保存输入框的引用 + field_inputs[field_name] = field_input + + service_box_layout.addWidget(field_input) + + service_box.setStyleSheet( + "QWidget { border: none; border-radius: 8px; padding: 10px; }" + ) + + return service_box, field_inputs + + def create_buttons(self): + + button_layout = QHBoxLayout() + + clear_button = QPushButton("清空") + clear_button.setStyleSheet( + "background-color: #f0f0f0; color: #4d4f53; font-weight: bold; padding: 10px 20px; border-radius: 5px;border:0.5px solid #7d7d7d" + ) + clear_button.setFixedWidth(80) + clear_button.clicked.connect(self.clear_inputs) + + confirm_button = QPushButton("确认") + confirm_button.setStyleSheet( + "background-color: #00aaff; color: white; font-weight: bold; padding: 10px 20px; border-radius: 5px;" + ) + confirm_button.setFixedWidth(80) + confirm_button.clicked.connect(self.confirm) + + + button_layout.addStretch(1) + button_layout.addWidget(clear_button) + button_layout.addWidget(confirm_button) + + return button_layout + + + def confirm(self): + # 从字段字典中获取 QLineEdit 控件的值 + bailian_api_key = self.bailian_inputs['api-key'].text() + tongyi_app_key = self.tongyi_inputs['app-key'].text() + tongyi_access_key_id = self.tongyi_inputs['access key id'].text() + tongyi_access_key_secret = self.tongyi_inputs['access key secret'].text() + + # 输出结果 + # print(f"百炼 API Key: {bailian_api_key}") + # print(f"通义 App Key: {tongyi_app_key}") + # print(f"通义 Access Key ID: {tongyi_access_key_id}") + # print(f"通义 Access Key Secret: {tongyi_access_key_secret}") + + if not bailian_api_key and not tongyi_app_key and not tongyi_access_key_id and not tongyi_access_key_secret: + QMessageBox.warning(self, "警告", "请输入至少一个API Key或App Key或Access Key ID或Access Key Secret") + return + + # 检查并设置配置,记录成功或失败的状态 + success = True + + if bailian_api_key: + if not Config.set_api_key(bailian_api_key): + success = False + + if tongyi_app_key: + if not Config.set_app_key(tongyi_app_key): + success = False + + if tongyi_access_key_id: + if not Config.set_ALIBABA_CLOUD_ACCESS_KEY_ID(tongyi_access_key_id): + success = False + + if tongyi_access_key_secret: + if not Config.set_ALIBABA_CLOUD_ACCESS_KEY_SECRET(tongyi_access_key_secret): + success = False + + # 弹出结果提示框 + if success: + QMessageBox.information(self, "配置成功", "所有配置项已成功保存。") + else: + QMessageBox.warning(self, "配置失败", "部分配置项保存失败,请重试。") + + def clear_inputs(self): + # 清空按钮 + for widget in self.findChildren(QLineEdit): + widget.clear() + + # 鼠标移动,拖拽窗口实现 + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + self.moving = True + self.offset = event.pos() + + def mouseMoveEvent(self, event): + if (self.moving): + self.move(event.globalPos() - self.offset) + + def mouseReleaseEvent(self, event): + if (event.button() == Qt.LeftButton): + self.moving = False + + +if __name__ == "__main__": + import sys + app = QApplication(sys.argv) + api_key_config_page = ApiKeyConfigPage() + api_key_config_page.show() + sys.exit(app.exec_()) diff --git a/usr/share/aiassistant/Config.py b/usr/share/aiassistant/Config.py index 613eb46bed0dc60b391299d1b69dc787d009644c..c454da46f362bb060e14f6c5be9aa073757237d4 100644 --- a/usr/share/aiassistant/Config.py +++ b/usr/share/aiassistant/Config.py @@ -50,4 +50,60 @@ class Config: config.read("/usr/share/aiassistant/config.ini") app_key = config.get('DEFAULT', 'app_key') # print(local_model) - return app_key \ No newline at end of file + return app_key + + @staticmethod + def set_api_key(api_key): + try: + config = configparser.ConfigParser() + with open("/usr/share/aiassistant/config.ini", "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'api_key', api_key) + with open("/usr/share/aiassistant/config.ini", "w") as configfile: + config.write(configfile) + return True + except Exception as e: + print(f"Failed to set API Key: {e}") + return False + + @staticmethod + def set_app_key(app_key): + try: + config = configparser.ConfigParser() + with open("/usr/share/aiassistant/config.ini", "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'app_key', app_key) + with open("/usr/share/aiassistant/config.ini", "w") as configfile: + config.write(configfile) + return True + except Exception as e: + print(f"Failed to set App Key: {e}") + return False + + @staticmethod + def set_ALIBABA_CLOUD_ACCESS_KEY_ID(access_key_id): + try: + config = configparser.ConfigParser() + with open("/usr/share/aiassistant/config.ini", "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'access_key_id', access_key_id) + with open("/usr/share/aiassistant/config.ini", "w") as configfile: + config.write(configfile) + return True + except Exception as e: + print(f"Failed to set Alibaba Cloud Access Key ID: {e}") + return False + + @staticmethod + def set_ALIBABA_CLOUD_ACCESS_KEY_SECRET(access_key_secret): + try: + config = configparser.ConfigParser() + with open("/usr/share/aiassistant/config.ini", "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'access_key_secret', access_key_secret) + with open("/usr/share/aiassistant/config.ini", "w") as configfile: + config.write(configfile) + return True + except Exception as e: + print(f"Failed to set Alibaba Cloud Access Key Secret: {e}") + return False \ No newline at end of file diff --git a/usr/share/aiassistant/PublicTypes.py b/usr/share/aiassistant/PublicTypes.py index f1c6f15d2835423af1742a1d7a5b30c56b3c8f9f..0524deb36b234e2a4b6807e500d6bfa1f054cff2 100644 --- a/usr/share/aiassistant/PublicTypes.py +++ b/usr/share/aiassistant/PublicTypes.py @@ -1,6 +1,13 @@ class PublicTypes: + viewType = "sidebar" + def __init__(self): self.mainwin_width = 480 self.mainwin_height = 1150 + + self.mainwin_windows_width = 1200 + self.mainwin_windows_height = 600 + + \ No newline at end of file diff --git a/usr/share/aiassistant/SettingPage.py b/usr/share/aiassistant/SettingPage.py new file mode 100644 index 0000000000000000000000000000000000000000..0e8778565990b0d5adbdc26ffefd99e4870f4c97 --- /dev/null +++ b/usr/share/aiassistant/SettingPage.py @@ -0,0 +1,167 @@ +from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QFrame +from PyQt5.QtCore import Qt, QSize +from PyQt5.QtGui import QIcon + +from ApikeyConfigPage import ApiKeyConfigPage +from Config import Config + + +class SettingsPage(QWidget): + def __init__(self, parent=None): + super(SettingsPage, self).__init__(parent) + self.moving = False + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) + self.resize(450, 330) + main_layout = QVBoxLayout(self) + + # 顶部栏 + top_bar = self.create_top_bar() + main_layout.addLayout(top_bar) + + #横线 + separator_line = QFrame() + separator_line.setFrameShape(QFrame.HLine) + separator_line.setFrameShadow(QFrame.Plain) + separator_line.setStyleSheet("color:lightgray;") + main_layout.addWidget(separator_line) + + + # 初始化服务状态字典 + self.services_status = { + "百炼-问答绘图服务": "待添加", + "通义听悟·会议纪要服务": "待添加" + } + + # 检查并更新服务状态并创建对应模块 + self.check_and_update_services_status() + ai_model_section = self.create_ai_model_section() + main_layout.addLayout(ai_model_section) + + #获取模型攻略按钮 + model_strategy_button = self.create_model_strategy_button() + main_layout.addWidget(model_strategy_button) + + def create_top_bar(self): + top_bar_layout = QHBoxLayout() + + title_label = QLabel("设置") + title_label.setStyleSheet("font-size: 18px; color: black;") + + close_btn = QPushButton() + close_btn.setFixedSize(24, 24) + close_btn.setStyleSheet( + ''' + QPushButton{background-color:transparent;border:none;color:white;} + ''' + ) + + close_btn.setIcon(QIcon('./data/close.png')) + close_btn.setIconSize(QSize(24, 24)); + close_btn.clicked.connect(self.close) + close_btn.setFixedSize(24, 24) + + top_bar_layout.addWidget(title_label) + top_bar_layout.addStretch(1) + top_bar_layout.addWidget(close_btn) + + return top_bar_layout + + def create_ai_model_section(self): + #ai大模型以及配置按钮 + ai_model_layout = QVBoxLayout() + ai_model_layout.setSpacing(20) + ai_model_layout.setContentsMargins(10, 10, 10, 10) + + header_layout = QHBoxLayout() + ai_model_label = QLabel("AI大模型") + ai_model_label.setStyleSheet("font-size: 9x; color: black;") + configure_button = QPushButton("配置") + # 添加按钮的点击事件 + configure_button.clicked.connect(self.openApiKeyConfigPage) + + configure_button.setStyleSheet("color: #2e8ff4; font-weight: bold;border: none;") + configure_button.setFixedWidth(60) + + header_layout.addWidget(ai_model_label) + header_layout.addStretch(1) + header_layout.addWidget(configure_button) + + ai_model_layout.addLayout(header_layout) + + services_box = self.create_services_box() + ai_model_layout.addWidget(services_box) + + return ai_model_layout + + def create_services_box(self): + #每个AI模型配置对应布局 + services_box = QWidget() + services_layout = QVBoxLayout(services_box) + services_layout.setSpacing(10) + + for service, status in self.services_status.items(): + service_item_layout = QHBoxLayout() + service_label = QLabel(service) + service_label.setStyleSheet(f"color: black; border:none;") + status_label = QLabel(status) + status_label.setStyleSheet(f"color: #a4a4a4; border:none; font-weight:bold;") + service_item_layout.addWidget(service_label) + service_item_layout.addStretch(1) + service_item_layout.addWidget(status_label) + services_layout.addLayout(service_item_layout) + + # 外面大框样式 + services_box.setStyleSheet( + "QWidget { border: 1px solid lightgray; border-radius: 8px; padding: 5px; }" + ) + return services_box + + def create_model_strategy_button(self): + # 获取模型攻略按钮 + bottom_widget = QWidget() + bottom_layout = QHBoxLayout(bottom_widget) + guide_button = QPushButton("获取模型攻略") + guide_button.setStyleSheet( + "color: #2e8ff4; font-size: 16px; border:none;" + ) + bottom_layout.addWidget(guide_button) + bottom_layout.addStretch(1) # 将按钮放在布局的左侧 + return bottom_widget + + def openApiKeyConfigPage(self): + # 创建并显示 APIKeyConfigPage 窗口 + self.apiKeyConfigPage = ApiKeyConfigPage() + self.apiKeyConfigPage.show() + self.hide() + + def check_and_update_services_status(self): + # 检查百炼-问答绘图服务的API Key是否已配置 + if Config.get_api_key(): + self.services_status["百炼-问答绘图服务"] = "已添加" + + # 检查通义听悟·会议纪要服务的App Key是否已配置 + if Config.get_app_key(): + self.services_status["通义听悟·会议纪要服务"] = "已添加" + + #鼠标移动,拖拽窗口实现 + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + self.moving = True + self.offset = event.pos() + + def mouseMoveEvent(self, event): + if(self.moving): + self.move(event.globalPos() - self.offset) + + def mouseReleaseEvent(self, event): + if(event.button() == Qt.LeftButton): + self.moving = False + + +if __name__ == "__main__": + import sys + from PyQt5.QtWidgets import QApplication + app = QApplication(sys.argv) + settings_page = SettingsPage() + settings_page.show() + sys.exit(app.exec_()) diff --git a/usr/share/aiassistant/__pycache__/AiDrawing.cpython-39.pyc b/usr/share/aiassistant/__pycache__/AiDrawing.cpython-39.pyc deleted file mode 100644 index 33af7a09cbdaba8186021c434e96c2fcf365179b..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/AiDrawing.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/AiDrawingTask.cpython-39.pyc b/usr/share/aiassistant/__pycache__/AiDrawingTask.cpython-39.pyc deleted file mode 100644 index c84c2d9b6813e9c404a6a984248d482bd84d79da..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/AiDrawingTask.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/ChatPlainTextEdit.cpython-39.pyc b/usr/share/aiassistant/__pycache__/ChatPlainTextEdit.cpython-39.pyc deleted file mode 100644 index 78742bea28e1fd8e2aef2d09c42a03692c8fd975..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/ChatPlainTextEdit.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/ChatTalk.cpython-39.pyc b/usr/share/aiassistant/__pycache__/ChatTalk.cpython-39.pyc deleted file mode 100644 index 908931cdfd0cb408e88c3470120e5b02fced0217..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/ChatTalk.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/ChatTask.cpython-39.pyc b/usr/share/aiassistant/__pycache__/ChatTask.cpython-39.pyc deleted file mode 100644 index a39b8d786b3e7777247b0c2f47bc07675dccf029..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/ChatTask.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/Config.cpython-39.pyc b/usr/share/aiassistant/__pycache__/Config.cpython-39.pyc deleted file mode 100644 index 716e5d39a735e6691652477d275bee95edcbd8c7..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/Config.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/LocalAppTask.cpython-39.pyc b/usr/share/aiassistant/__pycache__/LocalAppTask.cpython-39.pyc deleted file mode 100644 index 1679a701a006d58c261bf568f9f28b7ee15b0a4a..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/LocalAppTask.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/LocalTalk.cpython-39.pyc b/usr/share/aiassistant/__pycache__/LocalTalk.cpython-39.pyc deleted file mode 100644 index a7e3affb17b63cd6a8b5b07cb52fdda4b6f00dae..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/LocalTalk.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/LocalTask.cpython-39.pyc b/usr/share/aiassistant/__pycache__/LocalTask.cpython-39.pyc deleted file mode 100644 index 9ccf03b6f154da4bbcefc7a0a8a57e7308972c5b..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/LocalTask.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/MeetingBottomWgt.cpython-39.pyc b/usr/share/aiassistant/__pycache__/MeetingBottomWgt.cpython-39.pyc deleted file mode 100644 index 1d59b7c1978a17dc0f54a33ab2df505972d1781c..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/MeetingBottomWgt.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/MeetingFile.cpython-39.pyc b/usr/share/aiassistant/__pycache__/MeetingFile.cpython-39.pyc deleted file mode 100644 index 5ce63ad8a92eda1ec9ca8a409c92dbefdd01158e..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/MeetingFile.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/MeetingTask.cpython-39.pyc b/usr/share/aiassistant/__pycache__/MeetingTask.cpython-39.pyc deleted file mode 100644 index 41f23f2776fa743a8be93f9fe4b156df8f57b163..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/MeetingTask.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/PublicTypes.cpython-39.pyc b/usr/share/aiassistant/__pycache__/PublicTypes.cpython-39.pyc deleted file mode 100644 index fcc36042123db6f48c0059955a55867a99e26197..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/PublicTypes.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/ServerCheck.cpython-39.pyc b/usr/share/aiassistant/__pycache__/ServerCheck.cpython-39.pyc deleted file mode 100644 index d03854d467aacf8ad394358b2cd9c83738a26714..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/ServerCheck.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/Speech.cpython-39.pyc b/usr/share/aiassistant/__pycache__/Speech.cpython-39.pyc deleted file mode 100644 index 8185b21fc481447a18c14ab436a40ec98e115f31..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/Speech.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/SpeechTask.cpython-39.pyc b/usr/share/aiassistant/__pycache__/SpeechTask.cpython-39.pyc deleted file mode 100644 index 9d399963bc97e22a76f31caab173e3cd52749089..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/SpeechTask.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/VoiceRecognition.cpython-39.pyc b/usr/share/aiassistant/__pycache__/VoiceRecognition.cpython-39.pyc deleted file mode 100644 index 8050cc8974c24a9cd2646b21aa54443c6d3fe6af..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/VoiceRecognition.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/bottomWgt.cpython-39.pyc b/usr/share/aiassistant/__pycache__/bottomWgt.cpython-39.pyc deleted file mode 100644 index c28349fb7b5b1150dac9aaaa3605bf58046a1a5b..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/bottomWgt.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/bubble_message.cpython-39.pyc b/usr/share/aiassistant/__pycache__/bubble_message.cpython-39.pyc deleted file mode 100644 index 2d7ef5d3ecfc248a0c4decb66b4fb51e9e655cb6..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/bubble_message.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/mainwin.cpython-39.pyc b/usr/share/aiassistant/__pycache__/mainwin.cpython-39.pyc deleted file mode 100644 index f87751ae71ceae13f59b55f950aa3d78a99c8fd9..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/mainwin.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/__pycache__/preGuidWidget.cpython-39.pyc b/usr/share/aiassistant/__pycache__/preGuidWidget.cpython-39.pyc deleted file mode 100644 index a6ec6a96eb423db6dcf4fcec937a92f792c9adc3..0000000000000000000000000000000000000000 Binary files a/usr/share/aiassistant/__pycache__/preGuidWidget.cpython-39.pyc and /dev/null differ diff --git a/usr/share/aiassistant/bubble_message.py b/usr/share/aiassistant/bubble_message.py index fba27a418c2f35a205f86c989cf28d317315fa6c..3a27cbd1965374c2759383be18da446902c28a41 100644 --- a/usr/share/aiassistant/bubble_message.py +++ b/usr/share/aiassistant/bubble_message.py @@ -326,7 +326,7 @@ class ChatWidget(QWidget): print(self.width) h = self.height - 280 - self.setFixedHeight(h) + # self.setFixedHeight(h) layout = QVBoxLayout() layout.setSpacing(0) self.adjustSize() @@ -441,7 +441,7 @@ class MeetingWidget(QWidget): print(self.width) h = self.height - 280 - self.setFixedHeight(h) + # self.setFixedHeight(h) layout = QVBoxLayout() layout.setSpacing(0) self.adjustSize() diff --git a/usr/share/aiassistant/data/icon_setting.png b/usr/share/aiassistant/data/icon_setting.png new file mode 100644 index 0000000000000000000000000000000000000000..54d88bf0bf53dfce77c8c24a0b8ba6c27cfdcb44 Binary files /dev/null and b/usr/share/aiassistant/data/icon_setting.png differ diff --git a/usr/share/aiassistant/data/icon_win.png b/usr/share/aiassistant/data/icon_win.png new file mode 100644 index 0000000000000000000000000000000000000000..00e6ae09b30000000c0a36fd94280b09a715b618 Binary files /dev/null and b/usr/share/aiassistant/data/icon_win.png differ diff --git a/usr/share/aiassistant/data/menu_select.png b/usr/share/aiassistant/data/menu_select.png new file mode 100644 index 0000000000000000000000000000000000000000..b62242050f1f428dc7ef0b2862f328b39a6e6d4c Binary files /dev/null and b/usr/share/aiassistant/data/menu_select.png differ diff --git a/usr/share/aiassistant/mainwin.py b/usr/share/aiassistant/mainwin.py index bd634096a0770e2dd86ed5360c594a6bd2d39761..6eb75b9019340cd98389c266d3ffb7743c2227c4 100644 --- a/usr/share/aiassistant/mainwin.py +++ b/usr/share/aiassistant/mainwin.py @@ -25,6 +25,9 @@ from ChatTalk import ChatTalk from MeetingBottomWgt import MeetingBottomWidget from MeetingTask import MeetingTask from MeetingFile import MeetingFile +from SettingPage import SettingsPage +from PyQt5 import QtWidgets + app_list = Config.get_app_list() public_types = PublicTypes() @@ -33,6 +36,17 @@ class ShadowWindow(QWidget): super().__init__() self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) #Qt.Dialog主要用于在任务栏隐藏图标 self.setAttribute(Qt.WA_TranslucentBackground) + self.setObjectName('shadowindow') + self.setStyleSheet( + ''' + #shadowindow{ + border-top-left-radius: 15px; + border-top-right-radius: 15px; + border-bottom-left-radius: 15px; + border-bottom-right-radius: 15px; + } + ''' + ) self.resize(public_types.mainwin_width + 10, public_types.mainwin_height + 12) layout = QVBoxLayout(self) layout.setContentsMargins(0,0,0,0) @@ -44,44 +58,10 @@ class ShadowWindow(QWidget): self.setWindowIcon(QIcon('./data/icon.png')) # 设置窗口图标 #title - title = QWidget() - title.setObjectName('title') - title.setStyleSheet( - ''' - #title{ - border-top-left-radius: 5px; - border-top-right-radius: 5px; - background:transparent; - } - ''' - ) - title.installEventFilter(title) - title.setFixedHeight(36) - icon = QLabel(title) - icon.setFixedSize(16,16) - pixmap = QPixmap('./data/icon.png') - icon.setPixmap(pixmap) - icon.setScaledContents(True) - title_layout = QHBoxLayout(title) - title_layout.setContentsMargins(18, 12, 18, 0) - title_layout.addWidget(icon) - - title_name = QLabel() - title_name.setText('NFS AI') - title_name.setStyleSheet( - ''' - color:white; - font-size:16px; - font-weight:bold; - ''' - ) + self.title = MianWinTitle() - title_layout.addWidget(title_name) - - title_spacer = QSpacerItem(40, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) - title_layout.addItem(title_spacer) - - home_btn = QPushButton(title) + # home button + home_btn = QPushButton(self.title) home_btn.setFixedSize(24, 24) home_btn.setFlat(True) home_btn.setStyleSheet( @@ -96,9 +76,39 @@ class ShadowWindow(QWidget): lambda: self.widget.shift_model(False) ) home_btn.setFixedSize(24, 24) - title_layout.addWidget(home_btn) - - close_btn = QPushButton(title) + self.title.title_layout.addWidget(home_btn) + + # setting_ button + setting_btn = QPushButton(self.title) + setting_btn.setIcon(QIcon('./data/icon_setting.png')) + setting_btn.setIconSize(QSize(24, 24)); + setting_btn.setFixedSize(24, 24) + self.title.title_layout.addWidget(setting_btn) + setting_btn.setStyleSheet( + ''' + QPushButton{background-color:transparent;border:none;color:white;} + ''' + ) + + + menu = SettingMenu(self) + + # 添加二级菜单 + sub_menu = menu.addMenu("显示模式") + self.action_window = QAction("窗口模式", self) + sub_menu.addAction(self.action_window) + self.action_window.triggered.connect(self.switchToWindow) + self.action_sidebar = QAction("侧边栏模式", self) + sub_menu.addAction(self.action_sidebar) + self.action_sidebar.triggered.connect(self.switchToSidebar) + + menu.addAction("设置", self.openSettingPage) + menu.addSeparator() + menu.addAction("关于") + setting_btn.setMenu(menu) + + # close button + close_btn = QPushButton(self.title) close_btn.setFixedSize(24, 24) close_btn.setStyleSheet( ''' @@ -110,9 +120,9 @@ class ShadowWindow(QWidget): close_btn.setIconSize(QSize(24, 24)); close_btn.clicked.connect(self.close) close_btn.setFixedSize(24, 24) - title_layout.addWidget(close_btn) + self.title.title_layout.addWidget(close_btn) - layout.addWidget(title) + layout.addWidget(self.title) layout.addWidget(self.widget) self.initDrag() self.move_to_right_bottom() @@ -145,12 +155,69 @@ class ShadowWindow(QWidget): right = target_screen_geometry.right() bottom = target_screen_geometry.bottom() self.move(right - self.width(), bottom - self.height()) + + def move_to_center(self): + # 获取屏幕总数和屏幕几何数据 + desktop = QDesktopWidget() + screen_count = desktop.screenCount() + if screen_count > 1: + # 多屏情况下,用第一个屏幕 + target_screen_index = 0 + # 获取目标屏幕的几何信息 + target_screen_geometry = desktop.screenGeometry(target_screen_index) + else: + # 单屏情况下使用默认屏幕 + target_screen_geometry = desktop.screenGeometry() + + # 计算窗口移动位置到屏幕右下角 + right = target_screen_geometry.right() + bottom = target_screen_geometry.bottom() + self.move(right/2 - self.width()/2, bottom/2 - self.height()/2) + + # 切换到窗口模式 + def switchToWindow(self): + if PublicTypes.viewType != "windows": + PublicTypes.viewType = "windows" + self.widget.resize(public_types.mainwin_windows_width, public_types.mainwin_windows_height) + self.resize(public_types.mainwin_windows_width, public_types.mainwin_windows_height) + self.move_to_center() + self.widget.guidWgt.switchViewType() + self.title.switchViewType() + else: + pass + + # 切换到侧边栏模式 + def switchToSidebar(self): + if PublicTypes.viewType != "sidebar": + PublicTypes.viewType = "sidebar" + self.widget.guidWgt.switchViewType() + self.resize(public_types.mainwin_width, public_types.mainwin_height) + self.widget.resize(public_types.mainwin_width, public_types.mainwin_height) + self.resize(public_types.mainwin_width, public_types.mainwin_height) + self.move_to_right_bottom() + self.title.switchViewType() + else: + pass + def paintEvent(self, event): # 创建一个QPainter对象,并为当前窗口提供绘图功能 - painter = QPainter(self) - pixmap = QPixmap('./data/bg.png').scaled(self.size()) - painter.drawPixmap(0, 0, pixmap) + if PublicTypes.viewType == "sidebar": + #侧边栏模式背景 + painter = QPainter(self) + pixmap = QPixmap('./data/bg.png').scaled(self.size()) + painter.drawPixmap(0, 0, pixmap) + elif PublicTypes.viewType == "windows": + #窗口模式背景 + painter = QPainter(self) + self.setAttribute(Qt.WA_TranslucentBackground, False) + painter.setBrush(self.palette().window().color()) # 设置画刷为窗口背景颜色 + + radius = 15 # 设置圆角半径 + painter.drawRoundedRect(self.rect(), radius, radius) + else: + raise NotImplementedError("illegal type") + def initDrag(self): # 设置鼠标跟踪判断默认值 @@ -182,6 +249,12 @@ class ShadowWindow(QWidget): # 鼠标释放后,各扳机复位 self._move_drag = False + def openSettingPage(self): + #创建并显示设置页面 + self.settingPage = SettingsPage() + self.settingPage.setWindowFlags(Qt.WindowStaysOnTopHint) + self.settingPage.show() + class Mainwin(QWidget): def __init__(self): super().__init__() @@ -189,7 +262,7 @@ class Mainwin(QWidget): self.setStyleSheet( ''' #mainwindow{ - border-top-left-radius: 15px; + border-top-left-radius: 15px; border-top-right-radius: 15px; border-bottom-left-radius: 15px; border-bottom-right-radius: 15px; @@ -675,3 +748,156 @@ class Mainwin(QWidget): # widget.show() # app.exec_() + +#菜单类 +class SettingMenu(QMenu): + def __init__(self, *args, **kwargs): + super(SettingMenu, self).__init__() + self.radius = 5 + self.setStyleSheet( + ''' + QMenu {{ + /* 半透明效果 */ + border-radius: {radius}; + border: 2px solid rgb(255, 255, 255); + background-color: rgba(255, 255, 255, 230); + }} + + QMenu::item {{ + border-radius: {radius}; + /* 这个距离很麻烦需要根据菜单的长度和图标等因素微调 */ + padding: 8px 48px 8px 12px; /* 12px是文字距离左侧距离*/ + background-color: transparent; + }} + + /* 鼠标悬停和按下效果 */ + QMenu::item:selected {{ + border-radius: {radius}; + /* 半透明效果 */ + background-color: rgba(230, 240, 255, 232); + }} + + /* 禁用效果 */ + QMenu::item:disabled {{ + border-radius: {radius}; + background-color: transparent; + }} + + /* 图标距离左侧距离 */ + QMenu::icon {{ + left: 15px; + }} + + /* 分割线效果 */ + QMenu::separator {{ + height: 1px; + background-color: rgb(232, 236, 243); + }} + '''.format(radius=self.radius)) + + def resizeEvent(self, event): + # 添加蒙版 + path = QPainterPath() + path.addRoundedRect(QRectF(self.rect()), self.radius, self.radius) + region = QRegion(path.toFillPolygon(QTransform()).toPolygon()) + self.setMask(region) + +# 上方标题栏 +class MianWinTitle(QWidget): + def __init__(self, *args, **kwargs): + super(MianWinTitle, self).__init__() + self.setAttribute(Qt.WA_StyledBackground) + self.setObjectName('title') + self.setStyleSheet( + ''' + #title{ + border-top-left-radius: 5px; + border-top-right-radius: 5px; + background:transparent; + } + ''' + ) + self.installEventFilter(self) + self.setFixedHeight(36) + self.icon = QLabel(self) + self.icon.setFixedSize(16,16) + pixmap = QPixmap('./data/icon.png') + self.icon.setPixmap(pixmap) + self.icon.setScaledContents(True) + self.title_layout = QHBoxLayout(self) + self.title_layout.setContentsMargins(18, 12, 18, 0) + self.title_layout.addWidget(self.icon) + + self.title_name = QLabel() + self.title_name.setText('NFS AI') + self.title_name.setStyleSheet( + ''' + color:white; + font-size:16px; + font-weight:bold; + ''' + ) + + self.title_layout.addWidget(self.title_name) + + title_spacer = QSpacerItem(40, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.title_layout.addItem(title_spacer) + + def switchViewType(self): + if PublicTypes.viewType == "sidebar": + self.title_layout.setContentsMargins(18, 12, 18, 0) + self.setStyleSheet( + ''' + #title{ + border-top-left-radius: 5px; + border-top-right-radius: 5px; + background:transparent; + } + ''' + ) + self.icon.setFixedSize(16,16) + pixmap = QPixmap('./data/icon.png') + self.icon.setPixmap(pixmap) + self.icon.setScaledContents(True) + self.title_name.setStyleSheet( + ''' + color:white; + font-size:16px; + font-weight:bold; + ''' + ) + self.title_layout.setSpacing(10) + + elif PublicTypes.viewType == "windows": + self.title_layout.setContentsMargins(18, 6, 18, 6) + self.setStyleSheet( + ''' + #title{ + border-left: 2px solid transparent; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + background-color: white; + background-clip: padding-box; + } + ''' + ) + self.icon.setFixedSize(20,20) + pixmap = QPixmap('./data/icon_win.png') + self.icon.setPixmap(pixmap) + self.icon.setScaledContents(True) + + self.title_name.setStyleSheet( + ''' + color:black; + font-size: 16px; + font-weight: 400; + ''' + ) + self.title_layout.setSpacing(10) + + + else: + raise NotImplementedError("illegal type") + + + diff --git a/usr/share/aiassistant/preGuidWidget.py b/usr/share/aiassistant/preGuidWidget.py index 6122324b8c04e443e857b0549e27539e84bfa4f2..e528bbd8ce0c1f237e2afd9272b8944b18928a85 100644 --- a/usr/share/aiassistant/preGuidWidget.py +++ b/usr/share/aiassistant/preGuidWidget.py @@ -13,6 +13,9 @@ from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * from bubble_message import BubbleMessage,MessageType +from PublicTypes import PublicTypes + +public_types = PublicTypes() class ModelType: Chat = 1 @@ -42,7 +45,7 @@ class PreWidget(QWidget): self.screenRect = self.desktop.screenGeometry() self.height = self.screenRect.height() h = self.height - 380 - self.setFixedHeight(h) + # self.setFixedHeight(h) # self.setWindowFlags(Qt.FramelessWindowHint) @@ -70,6 +73,42 @@ class PreWidget(QWidget): self.chatGuidWgt.clicked.connect(self.chat_model_signal) self.paintGuidWgt.clicked.connect(self.paint_model_signal) self.meetingMinutsGuidWgt.clicked.connect(self.meeting_minuts_model_signal) + + + def switchViewType(self): + if PublicTypes.viewType == "sidebar": + self.verticalLayout.setSpacing(10) + + self.chatGuidWgt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.paintGuidWgt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.meetingMinutsGuidWgt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.guid_title.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored) + self.guid_content.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored) + + self.verticalLayout.setAlignment(self.chatGuidWgt,Qt.AlignLeft) + self.verticalLayout.setAlignment(self.paintGuidWgt,Qt.AlignLeft) + self.verticalLayout.setAlignment(self.meetingMinutsGuidWgt,Qt.AlignLeft) + self.verticalLayout.setAlignment(self.guid_title,Qt.AlignLeft) + self.verticalLayout.setAlignment(self.guid_content,Qt.AlignLeft) + + + elif PublicTypes.viewType == "windows": + self.verticalLayout.setSpacing(15) + self.chatGuidWgt.setFixedWidth(440) + self.paintGuidWgt.setFixedWidth(440) + self.meetingMinutsGuidWgt.setFixedWidth(440) + self.guid_title.setFixedWidth(440) + self.guid_content.setFixedSize(440, 120) + + self.verticalLayout.setAlignment(self.chatGuidWgt,Qt.AlignCenter) + self.verticalLayout.setAlignment(self.paintGuidWgt,Qt.AlignCenter) + self.verticalLayout.setAlignment(self.meetingMinutsGuidWgt,Qt.AlignCenter) + self.verticalLayout.setAlignment(self.guid_title,Qt.AlignCenter) + self.verticalLayout.setAlignment(self.guid_content,Qt.AlignCenter) + + else: + raise NotImplementedError("illegal type") + class OptionWidget(QWidget): clicked = pyqtSignal() @@ -93,8 +132,14 @@ class OptionWidget(QWidget): painter.setOpacity(0.80) painter.setRenderHint(QPainter.Antialiasing) # 设置抗锯齿,让圆角更加平滑 # # 定义画笔和填充 - painter.setBrush(QBrush(QColor(235,235,235))) # 画刷颜色设置为白色 - painter.setPen(QPen(QColor(235, 235, 235), 0)) # 画笔颜色和粗细 + if PublicTypes.viewType == "sidebar": + painter.setBrush(QBrush(QColor(235,235,235))) # 画刷颜色设置为白色 + painter.setPen(QPen(QColor(235, 235, 235), 0)) # 画笔颜色和粗细 + elif PublicTypes.viewType == "windows": + painter.setBrush(QBrush(QColor(255,255,255))) # 画刷颜色设置为白色 + painter.setPen(QPen(QColor(255, 255, 255), 0)) # 画笔颜色和粗细 + else: + raise NotImplementedError("illegal type") # # 绘制圆角矩形 painter.drawRoundedRect(self.rect(), 10, 10) # 设置边角为10像素的圆度 @@ -102,7 +147,7 @@ class OptionWidget(QWidget): class Ui_optWgt(object): def setupUi(self, optWgt): # optWgt.resize(492, 108) - optWgt.setMinimumSize(QtCore.QSize(360, 108)) + # optWgt.setMinimumSize(QtCore.QSize(360, 108)) self.horizontalLayout = QtWidgets.QHBoxLayout(optWgt) self.horizontalLayout.setContentsMargins(24, 10, 24, 18) self.horizontalLayout.setObjectName("horizontalLayout")