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/debian/postinst b/debian/postinst index d08ed3723afaaeb870a6285637c646d4a2b77181..a55c13f6caeb42aefb66551b63ba2dbc77f07616 100644 --- a/debian/postinst +++ b/debian/postinst @@ -5,3 +5,5 @@ set -e pip3 install dashscope pip3 install pyaudio pip3 install pyqt5 + +cp /usr/share/aiassistant/config.ini "/home/$SUDO_USER/.config/aiassistant/config.ini" diff --git a/usr/share/aiassistant/AboutPage.py b/usr/share/aiassistant/AboutPage.py new file mode 100644 index 0000000000000000000000000000000000000000..7d09cfb6b93370a95a6e37e6a2c990fcb6328f0b --- /dev/null +++ b/usr/share/aiassistant/AboutPage.py @@ -0,0 +1,222 @@ +from PyQt5 import QtCore +from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QFrame, QDesktopWidget, \ + QGraphicsBlurEffect, QGraphicsDropShadowEffect +from PyQt5.QtCore import Qt, QSize, QRectF, pyqtSignal +from PyQt5.QtGui import QIcon, QPainter, QPainterPath, QRegion, QTransform, QPalette, QColor, QLinearGradient, QPen, QPixmap, QIcon + +from ApikeyConfigPage import ApiKeyConfigPage +from Config import Config + + +class AboutPage(QWidget): + # 定义关闭信号 + closed = pyqtSignal() + def __init__(self, parent=None): + super(AboutPage, self).__init__(parent) + layout = QVBoxLayout(self) # 包含顶栏和主要内容 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) #Qt.Dialog主要用于在任务栏隐藏图标 + self.resize(450, 350) + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + # 顶部栏 + top_bar = self.create_top_bar() + layout.addWidget(top_bar) + + #主要内容 + self.setting_main_window = AboutMainWindow() + layout.addWidget(self.setting_main_window) + + + layout.setContentsMargins(0, 0, 0, 0) + + def openApiKeyConfigPage(self): + # 创建并显示 APIKeyConfigPage 窗口 + self.apiKeyConfigPage = ApiKeyConfigPage() + self.hide() + self.apiKeyConfigPage.show() + # 将窗口置顶 + self.apiKeyConfigPage.raise_() + # self.hide() + + def create_top_bar(self): + setting_page_title = BoxTitle(self) + + #创建顶部栏 + top_bar_layout = QHBoxLayout() + + title_label = QLabel("关于") + title_label.setStyleSheet("font-size: 16px; 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) + + setting_page_title.setLayout(top_bar_layout) + + return setting_page_title + + + 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 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 + + def paintEvent(self, event): + #画圆角 + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) # 设置抗锯齿,让圆角更加平滑 + self.setAttribute(Qt.WA_TranslucentBackground, False) + painter.setPen(QColor(0, 0, 0, 10)) # 黑色,透明度设置为10 + painter.setBrush(self.palette().window().color())#设置画刷为窗口背景颜色 + radius = 15 #设置圆角半径 + + bounds = self.rect() # 获取窗口的边界 + # 绘制阴影 + shadow = QLinearGradient(bounds.topLeft(), bounds.bottomLeft()) + shadow.setColorAt(0, QColor(100, 100, 100, 50)) + + # 设置阴影的模糊半径 + painter.setPen(QPen(shadow, 1)) + painter.drawRoundedRect(self.rect(), radius, radius) + + def closeEvent(self, event): + # 重写关闭事件,以便在关闭时通知父窗口 + self.closed.emit() + super().closeEvent(event) + + +class AboutMainWindow(QWidget): + # 定义关闭信号 + closed = pyqtSignal() + def __init__(self, parent=None): + super(AboutMainWindow, self).__init__(parent) + self.moving = False + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(50, 20, 50, 50) + + #实现圆角 + self.setObjectName('mainwindow') + self.radius = 10 + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + + # 检查并更新服务状态并创建对应模块 + titile_about_section = self.create_titile_about_section() + main_layout.addLayout(titile_about_section) + + titile_about_section = self.create_content_about_section() + main_layout.addLayout(titile_about_section) + + + def create_titile_about_section(self): + #ai大模型以及配置按钮 + title_layout = QHBoxLayout() + # ai_model_layout.setSpacing(10) + + word_layout = QVBoxLayout() + word_label_one = QLabel("NFS AI") + word_label_one.setStyleSheet("font-size: 16px; color: black;") + + word_label_two = QLabel("1.0.0") + word_label_two.setStyleSheet("font-size: 10px; color: black;") + + word_layout.addWidget(word_label_one) + word_layout.addWidget(word_label_two) + + icon_label = QLabel() + icon_pixmap = QPixmap('./data/logo_about.png') # 替换为你的图标文件路径 + icon_label.setPixmap(icon_pixmap) + + title_layout.addLayout(word_layout) + title_layout.addStretch(1) + title_layout.addWidget(icon_label) + + return title_layout + + def create_content_about_section(self): + content_layout = QVBoxLayout() + word_label_one = QLabel("""NFS AI是一款集成了自然语言处理、智能绘图及会议纪要等多种功能的AI代理\n智能助手, 以优质的AI大模型接入效果为用户打造丰富的服务体验。\n\n\n© 2024中科方德软件有限公司 + """) + + word_label_one.setStyleSheet("font-size: 14px; color: black;") + + content_layout.addWidget(word_label_one) + return content_layout + + + + + +class BoxTitle(QWidget): + def __init__(self, *args, **kwargs): + super(BoxTitle, self).__init__() + self.setAttribute(Qt.WA_StyledBackground) + self.setObjectName('box_title') + self.setStyleSheet( + ''' + #box_title{ + border-left: 2px solid transparent; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + background-color: white; + background-clip: padding-box; + } + ''' + ) + self.installEventFilter(self) + self.setFixedHeight(36) + + + +if __name__ == "__main__": + import sys + from PyQt5.QtWidgets import QApplication + app = QApplication(sys.argv) + settings_page = AboutPage() + settings_page.show() + sys.exit(app.exec_()) diff --git a/usr/share/aiassistant/ApikeyConfigPage.py b/usr/share/aiassistant/ApikeyConfigPage.py new file mode 100644 index 0000000000000000000000000000000000000000..23a9c339625abcc64da263110765caeabc8802fc --- /dev/null +++ b/usr/share/aiassistant/ApikeyConfigPage.py @@ -0,0 +1,321 @@ +from PyQt5.QtWidgets import ( + QWidget, QLabel, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QApplication, QMessageBox, QFrame, + QDesktopWidget, QGraphicsDropShadowEffect +) +from PyQt5.QtCore import Qt, QSize, QRectF, pyqtSignal +from PyQt5.QtGui import QIcon, QPainter, QPainterPath, QTransform, QRegion, QColor, QLinearGradient, QPen +from Config import Config +from SettingStatusPage import SettingStatusPage + +class ApiKeyConfigPage(QWidget): + # 定义关闭信号 + closed = pyqtSignal() + def __init__(self, parent=None): + super(ApiKeyConfigPage, self).__init__(parent) + layout = QVBoxLayout(self) # 包含顶栏和主要内容 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) #Qt.Dialog主要用于在任务栏隐藏图标 + self.resize(450, 350) + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + # 顶部栏 + top_bar = self.create_top_bar() + layout.addWidget(top_bar) + + #主要内容 + self.setting_main_window = ApiKeyConfigMainWindow() + layout.addWidget(self.setting_main_window) + + + layout.setContentsMargins(0, 0, 0, 0) + + + def create_top_bar(self): + setting_page_title = BoxTitle(self) + + #创建顶部栏 + top_bar_layout = QHBoxLayout() + + title_label = QLabel("设置") + title_label.setStyleSheet("font-size: 16px; 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) + + setting_page_title.setLayout(top_bar_layout) + + return setting_page_title + + + 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 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 + + def paintEvent(self, event): + #画圆角 + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) # 设置抗锯齿,让圆角更加平滑 + self.setAttribute(Qt.WA_TranslucentBackground, False) + painter.setPen(QColor(0, 0, 0, 10)) # 黑色,透明度设置为10 + painter.setBrush(self.palette().window().color())#设置画刷为窗口背景颜色 + radius = 15 #设置圆角半径 + + bounds = self.rect() # 获取窗口的边界 + # 绘制阴影 + shadow = QLinearGradient(bounds.topLeft(), bounds.bottomLeft()) + shadow.setColorAt(0, QColor(100, 100, 100, 50)) + + # 设置阴影的模糊半径 + painter.setPen(QPen(shadow, 1)) + painter.drawRoundedRect(self.rect(), radius, radius) + + def closeEvent(self, event): + # 重写关闭事件,以便在关闭时通知父窗口 + self.closed.emit() + super().closeEvent(event) + + +class ApiKeyConfigMainWindow(QWidget): + def __init__(self, parent=None): + super(ApiKeyConfigMainWindow, self).__init__(parent) + self.resize(490, 500) + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) #Qt.Dialog主要用于在任务栏隐藏图标 + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + # 实现圆角 + self.setObjectName('mainwindow') + self.radius = 15 + + # 内容框 + main_layout = QVBoxLayout(self) + + + # 创建服务配置项的输入框,并存储它们的引用 + 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_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.setContentsMargins(20,0,20,0) + + 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) + button_layout.setContentsMargins(0, 150, 0, 0) + + 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: + self.openSettingStatusPage(False) + 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 + + # 弹出结果提示框 + self.openSettingStatusPage(success) + + + + def clear_inputs(self): + # 清空按钮 + for widget in self.findChildren(QLineEdit): + widget.clear() + + def openSettingStatusPage(self,success): + # 创建并显示SettingStatusPage窗口 + self.settingStatusPage = SettingStatusPage(success,self) + self.settingStatusPage.show() + + +class BoxTitle(QWidget): + def __init__(self, *args, **kwargs): + super(BoxTitle, self).__init__() + self.setAttribute(Qt.WA_StyledBackground) + self.setObjectName('box_title') + self.setStyleSheet( + ''' + #box_title{ + border-left: 2px solid transparent; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + background-color: white; + background-clip: padding-box; + } + ''' + ) + self.installEventFilter(self) + self.setFixedHeight(36) + + +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..423ece357263fc4ef43ae48f5ecd14b863eea96f 100644 --- a/usr/share/aiassistant/Config.py +++ b/usr/share/aiassistant/Config.py @@ -1,13 +1,22 @@ import configparser import json +import dashscope +from PublicTypes import PublicTypes +public_types = PublicTypes() +import os +# 获取家目录路径 +home_dir = os.path.expanduser('~') + +# 指定配置文件路径 +CONFIG_PATH = os.path.join(home_dir, PublicTypes.CONFIG_PATH) class Config: @staticmethod def get_api_key(): config = configparser.ConfigParser() - config.read("/usr/share/aiassistant/config.ini") + config.read(CONFIG_PATH) api_key = config.get('DEFAULT', 'api_key') # print(api_key) return api_key @@ -15,7 +24,7 @@ class Config: @staticmethod def get_app_list(): config = configparser.ConfigParser() - config.read("/usr/share/aiassistant/config.ini") + config.read(CONFIG_PATH) data = config.get('DEFAULT', 'app_list') app_list = json.loads(data) return app_list @@ -23,7 +32,7 @@ class Config: @staticmethod def get_local_model(): config = configparser.ConfigParser() - config.read("/usr/share/aiassistant/config.ini") + config.read(CONFIG_PATH) local_model = config.get('DEFAULT', 'local_model') # print(local_model) return local_model @@ -31,7 +40,7 @@ class Config: @staticmethod def get_ALIBABA_CLOUD_ACCESS_KEY_ID(): config = configparser.ConfigParser() - config.read("/usr/share/aiassistant/config.ini") + config.read(CONFIG_PATH) access_key_id = config.get('DEFAULT', 'access_key_id') # print(local_model) return access_key_id @@ -39,7 +48,7 @@ class Config: @staticmethod def get_ALIBABA_CLOUD_ACCESS_KEY_SECRET(): config = configparser.ConfigParser() - config.read("/usr/share/aiassistant/config.ini") + config.read(CONFIG_PATH) access_key_secret = config.get('DEFAULT', 'access_key_secret') # print(local_model) return access_key_secret @@ -47,7 +56,64 @@ class Config: @staticmethod def get_app_key(): config = configparser.ConfigParser() - config.read("/usr/share/aiassistant/config.ini") + config.read(CONFIG_PATH) 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(CONFIG_PATH, "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'api_key', api_key) + with open(CONFIG_PATH, "w") as configfile: + config.write(configfile) + dashscope.api_key = Config.get_api_key() + 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(CONFIG_PATH, "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'app_key', app_key) + with open(CONFIG_PATH, "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(CONFIG_PATH, "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'access_key_id', access_key_id) + with open(CONFIG_PATH, "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(CONFIG_PATH, "r") as configfile: + config.read_file(configfile) + config.set('DEFAULT', 'access_key_secret', access_key_secret) + with open(CONFIG_PATH, "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/MeetingBottomWgt.py b/usr/share/aiassistant/MeetingBottomWgt.py index fbbfbddaee1dd6a7a203700b95275566fa788557..7f0bcb9fbd22a6e0f4a385bdef42a43de74e0764 100644 --- a/usr/share/aiassistant/MeetingBottomWgt.py +++ b/usr/share/aiassistant/MeetingBottomWgt.py @@ -17,6 +17,9 @@ from PyQt5.QtGui import * from MeetingTask import MeetingTask from bubble_message import BubbleMessage, MessageType from MeetingFile import MeetingFile +from PublicTypes import PublicTypes + +public_types = PublicTypes() class MeetingBottomWidget(QWidget): switch_signal = pyqtSignal(bool) @@ -79,6 +82,17 @@ class MeetingBottomWidget(QWidget): # print(filename) if os.path.exists(filename): MeetingFile.open_file(filename) + + def switchViewType(self): + if PublicTypes.viewType == "sidebar": + self.ui.meetingSwitchBtn.setGeometry(183, 74, 114, 36) + self.ui.exportMeetingBtn.setGeometry(10, 140, 114, 36) + elif PublicTypes.viewType == "windows": + self.ui.meetingSwitchBtn.setGeometry(550, 34, 114, 36) + self.ui.exportMeetingBtn.setGeometry(10, 80, 114, 36) + else: + raise NotImplementedError("illegal type") + class Ui_meetingBottomWidget(QWidget): def setupUi(self, bottomWidget): diff --git a/usr/share/aiassistant/ModelGuidePage.html b/usr/share/aiassistant/ModelGuidePage.html new file mode 100644 index 0000000000000000000000000000000000000000..0b337f2aa18b559f867b6dca6c343081b0a36b24 --- /dev/null +++ b/usr/share/aiassistant/ModelGuidePage.html @@ -0,0 +1,26 @@ + + + + + AI大模型账号申请攻略 + + + + AI大模型账号申请攻略 + + + diff --git a/usr/share/aiassistant/PublicTypes.py b/usr/share/aiassistant/PublicTypes.py index f1c6f15d2835423af1742a1d7a5b30c56b3c8f9f..be0e934c88f7d1defc849842bf9b9fc215ee6414 100644 --- a/usr/share/aiassistant/PublicTypes.py +++ b/usr/share/aiassistant/PublicTypes.py @@ -1,6 +1,14 @@ class PublicTypes: + viewType = "sidebar" + CONFIG_PATH = ".config/aiassistant/config.ini" + def __init__(self): self.mainwin_width = 480 self.mainwin_height = 1150 + + self.mainwin_windows_width = 1200 + self.mainwin_windows_height = 700 + + \ 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..74e51794cf22e01da82c2dc4c34b53ffdff91d00 --- /dev/null +++ b/usr/share/aiassistant/SettingPage.py @@ -0,0 +1,283 @@ +import webbrowser + +from PyQt5 import QtCore +from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QFrame, QDesktopWidget, \ + QGraphicsBlurEffect, QGraphicsDropShadowEffect +from PyQt5.QtCore import Qt, QSize, QRectF, pyqtSignal +from PyQt5.QtGui import QIcon, QPainter, QPainterPath, QRegion, QTransform, QPalette, QColor, QLinearGradient, QPen + +from ApikeyConfigPage import ApiKeyConfigPage +from Config import Config + + +class SettingsPage(QWidget): + # 定义关闭信号 + closed = pyqtSignal() + def __init__(self, parent=None): + super(SettingsPage, self).__init__(parent) + layout = QVBoxLayout(self) # 包含顶栏和主要内容 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) #Qt.Dialog主要用于在任务栏隐藏图标 + self.resize(450, 350) + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + # 顶部栏 + top_bar = self.create_top_bar() + layout.addWidget(top_bar) + + #主要内容 + self.setting_main_window = SettingsMainWindow() + layout.addWidget(self.setting_main_window) + + # 添加按钮的点击事件 + self.setting_main_window.configure_button.clicked.connect(self.openApiKeyConfigPage) + + layout.setContentsMargins(0, 0, 0, 0) + + def openApiKeyConfigPage(self): + # 创建并显示 APIKeyConfigPage 窗口 + self.apiKeyConfigPage = ApiKeyConfigPage() + self.hide() + self.apiKeyConfigPage.show() + # 将窗口置顶 + self.apiKeyConfigPage.raise_() + # self.hide() + + def create_top_bar(self): + setting_page_title = BoxTitle(self) + + #创建顶部栏 + top_bar_layout = QHBoxLayout() + + title_label = QLabel("设置") + title_label.setStyleSheet("font-size: 16px; 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) + + setting_page_title.setLayout(top_bar_layout) + + return setting_page_title + + + 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 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 + + def paintEvent(self, event): + #画圆角 + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) # 设置抗锯齿,让圆角更加平滑 + self.setAttribute(Qt.WA_TranslucentBackground, False) + painter.setPen(QColor(0, 0, 0, 10)) # 黑色,透明度设置为10 + painter.setBrush(self.palette().window().color())#设置画刷为窗口背景颜色 + radius = 15 #设置圆角半径 + + bounds = self.rect() # 获取窗口的边界 + # 绘制阴影 + shadow = QLinearGradient(bounds.topLeft(), bounds.bottomLeft()) + shadow.setColorAt(0, QColor(100, 100, 100, 50)) + + # 设置阴影的模糊半径 + painter.setPen(QPen(shadow, 1)) + painter.drawRoundedRect(self.rect(), radius, radius) + + def closeEvent(self, event): + # 重写关闭事件,以便在关闭时通知父窗口 + self.closed.emit() + super().closeEvent(event) + + +class SettingsMainWindow(QWidget): + # 定义关闭信号 + closed = pyqtSignal() + def __init__(self, parent=None): + super(SettingsMainWindow, self).__init__(parent) + self.moving = False + main_layout = QVBoxLayout(self) + + #实现圆角 + self.setObjectName('mainwindow') + self.radius = 10 + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + + # 初始化服务状态字典 + 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_ai_model_section(self): + #ai大模型以及配置按钮 + ai_model_layout = QVBoxLayout() + # ai_model_layout.setSpacing(10) + ai_model_layout.setContentsMargins(10, 10, 10, 10) + + header_layout = QHBoxLayout() + ai_model_label = QLabel("AI大模型") + ai_model_label.setStyleSheet("font-size: 16px; color: black;") + self.configure_button = QPushButton("配置") + + self.configure_button.setStyleSheet("font-size: 16px;color: #2e8ff4;font-weight: bold;border: none;") + self.configure_button.setFixedWidth(60) + + header_layout.addWidget(ai_model_label) + header_layout.addStretch(1) + header_layout.addWidget(self.configure_button) + header_layout.setContentsMargins(20,20,0,0) + + 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"font-size: 14px;color: black; border:none;") + status_label = QLabel(status) + status_label.setStyleSheet(f"font-size: 14px;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.setIcon(QIcon('./data/icon_strategy.png')) + guide_button.setIconSize(QSize(24, 24)) + guide_button.setText("获取模型攻略") + guide_button.setStyleSheet( + "color: #2e8ff4; font-size: 16px; border:none;" + ) + guide_button.setFixedSize(guide_button.sizeHint()) + + #点击进入对应网页 + guide_button.clicked.connect(self.open_model_guide) + + bottom_layout.setContentsMargins(30, 0, 0, 130) + + bottom_layout.addWidget(guide_button) + bottom_layout.addStretch(1) # 将按钮放在布局的左侧 + return bottom_widget + + + + 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 open_model_guide(self): + # 打开模型攻略网页 + webbrowser.open("ModelGuidePage.html") + + + +class BoxTitle(QWidget): + def __init__(self, *args, **kwargs): + super(BoxTitle, self).__init__() + self.setAttribute(Qt.WA_StyledBackground) + self.setObjectName('box_title') + self.setStyleSheet( + ''' + #box_title{ + border-left: 2px solid transparent; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + background-color: white; + background-clip: padding-box; + } + ''' + ) + self.installEventFilter(self) + self.setFixedHeight(36) + + + +# 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/SettingStatusPage.py b/usr/share/aiassistant/SettingStatusPage.py new file mode 100644 index 0000000000000000000000000000000000000000..0032bf38b20021a9a1d97507cac55c5745e5ef02 --- /dev/null +++ b/usr/share/aiassistant/SettingStatusPage.py @@ -0,0 +1,157 @@ +from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QHBoxLayout, QDesktopWidget +from PyQt5.QtCore import Qt, QSize, pyqtSignal +from PyQt5.QtGui import QIcon, QPixmap, QFont, QPainter, QColor, QLinearGradient, QPen + + +class SettingStatusPage(QWidget): + def __init__(self, success=True,parent=None): + super().__init__() + + self.setFixedSize(400, 200) + # self.move_to_center() + self.success = success # 保存 success 状态 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + + # 主布局 + main_layout = QVBoxLayout() + + # 添加各个部分到主布局 + main_layout.addLayout(self.create_close_button()) + main_layout.addLayout(self.create_icon_and_title(success)) + main_layout.addLayout(self.create_detail_info(success)) + main_layout.addLayout(self.create_confirm_button()) + + + # 设置窗口样式 + self.setStyleSheet("background-color: white; border-radius: 10px;") + self.setLayout(main_layout) + + + def create_close_button(self): + # 关闭按钮 + 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) + + # 关闭按钮的布局 + close_button_layout = QHBoxLayout() + close_button_layout.addStretch(1) + close_button_layout.addWidget(close_btn) + return close_button_layout + def create_icon_and_title(self, success): + # 水平布局:图标 + 状态消息 + status_layout = QHBoxLayout() + + # 图标 + icon_label = QLabel() + icon_pixmap = QPixmap('success_icon.png').scaled(30, 30, Qt.KeepAspectRatio) if success else QPixmap( + 'error_icon.png').scaled(30, 30, Qt.KeepAspectRatio) + icon_label.setPixmap(icon_pixmap) + + # 状态标题 + status_label = QLabel("配置成功" if success else "配置失败") + status_label.setFont(QFont('Arial', 14, QFont.Bold)) + status_label.setStyleSheet("color: black;") + + # 添加图标和状态消息到布局中 + status_layout.addWidget(icon_label) + status_layout.addWidget(status_label) + status_layout.addStretch(1) + status_layout.setContentsMargins(30, 0, 10, 0) + return status_layout + + def create_detail_info(self, success): + # 水平布局:详细信息 + detail_layout = QHBoxLayout() + + # 状态详细信息 + detail_label = QLabel("所有配置项已成功保存" if success else "所有配置项保存失败") + detail_label.setFont(QFont('Arial', 11)) + detail_label.setStyleSheet("color: gray;") + + # 将详细信息添加到布局中 + detail_layout.addWidget(detail_label) + detail_layout.addStretch(1) + detail_layout.setContentsMargins(45, 0, 10, 45) + return detail_layout + + def create_confirm_button(self): + # 确定按钮 + confirm_button = QPushButton("确定") + confirm_button.setFont(QFont('Arial', 12)) + confirm_button.setFixedSize(130, 40) # 宽度为100像素,高度为40像素 + confirm_button.setStyleSheet(""" + QPushButton { + background-color: #007BFF; + color: white; + border-radius: 8px; + padding: 5px 20px; + } + } + """) + confirm_button.clicked.connect(self.close) + + # 确定按钮的布局 + confirm_button_layout = QHBoxLayout() + confirm_button_layout.addStretch(1) + confirm_button_layout.addWidget(confirm_button) + confirm_button_layout.setContentsMargins(0, 0, 20, 10) + return confirm_button_layout + + def paintEvent(self, event): + #画圆角 + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) # 设置抗锯齿,让圆角更加平滑 + self.setAttribute(Qt.WA_TranslucentBackground, False) + painter.setPen(QColor(0, 0, 0, 10)) # 黑色,透明度设置为10 + painter.setBrush(self.palette().window().color())#设置画刷为窗口背景颜色 + radius = 15 #设置圆角半径 + + bounds = self.rect() # 获取窗口的边界 + # 绘制阴影 + shadow = QLinearGradient(bounds.topLeft(), bounds.bottomLeft()) + shadow.setColorAt(0, QColor(100, 100, 100, 50)) + + # 设置阴影的模糊半径 + painter.setPen(QPen(shadow, 1)) + painter.drawRoundedRect(self.rect(), radius, radius) + + 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.width() + bottom = target_screen_geometry.height() + self.move(int(right / 2 - self.width() / 2), int(bottom / 2 - self.height() / 2)) + +# if __name__ == "__main__": +# import sys +# app = QApplication(sys.argv) +# +# # 创建对话框实例,传入 True 显示成功信息,传入 False 显示失败信息 +# success_dialog = SettingStatusPage(success=True) +# success_dialog.show() +# +# sys.exit(app.exec_()) diff --git a/usr/share/aiassistant/VoiceRecognition.py b/usr/share/aiassistant/VoiceRecognition.py index 86f12b71a46dd58c787af9ed8b93d86e2fe84a6f..e62a7663f36d1d67c37df360101228fbfabce259 100644 --- a/usr/share/aiassistant/VoiceRecognition.py +++ b/usr/share/aiassistant/VoiceRecognition.py @@ -10,7 +10,7 @@ from Config import Config dashscope.api_key = Config.get_api_key() -mic = None +mic = None #管理麦克风对象pyaudio.PyAudio stream = None class VoiceCallback(RecognitionCallback): @@ -19,6 +19,7 @@ class VoiceCallback(RecognitionCallback): def __init__(self): super().__init__() self.openAudioSuccess = False + self.input_voice_message = "" def on_open(self) -> None: global mic @@ -64,6 +65,7 @@ class VoiceCallback(RecognitionCallback): voice = data.get('text') self.callback(voice) print('RecognitionCallback sentence: ', voice) + self.input_voice_message+= voice def set_callback(self, callback): self.callback = callback 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..1878f733a8c17fc7975b9ae9de25eb03cc7b9eda 100644 --- a/usr/share/aiassistant/bubble_message.py +++ b/usr/share/aiassistant/bubble_message.py @@ -3,6 +3,7 @@ from PyQt5 import QtGui from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * +from PublicTypes import PublicTypes class MessageType: Text = 1 @@ -37,7 +38,7 @@ class TextMessage(QLabel): else: self.setStyleSheet( ''' - background-color: rgba(235,235,235,204); + background-color: rgba(255,255,255,204); border-radius:10px; padding:10px; color: #333333; @@ -228,8 +229,9 @@ class BubbleMessage(QWidget): self.playBtn.show() layout.addWidget(self.playBtn, 0, Qt.AlignCenter) + if Type != MessageType.Guid: layout.addItem(self.spacerItem) - + self.setLayout(layout) def playAudio(self): @@ -335,6 +337,7 @@ class ChatWidget(QWidget): self.scrollArea = ScrollArea(self) scrollBar = ScrollBar() self.scrollArea.setVerticalScrollBar(scrollBar) + self.scrollArea.setFixedHeight(720) # self.scrollArea.setGeometry(QRect(9, 9, 261, 211)) # 生成滚动区域的内容部署层部件 self.scrollAreaWidgetContents = ScrollAreaContent(self.scrollArea) @@ -424,6 +427,29 @@ class ChatWidget(QWidget): super().update() self.scrollAreaWidgetContents.adjustSize() self.scrollArea.update() + + def switchViewType(self): + if PublicTypes.viewType == "sidebar": + h = self.height - 280 + self.setFixedHeight(h) + self.scrollArea.setFixedHeight(h) + + self.setMaximumWidth(480 - 36) + self.setFixedWidth(480 - 36) + self.scrollAreaWidgetContents.setFixedWidth(480 - 36) + self.scrollArea.setFixedWidth(480 - 36) + self.update() + elif PublicTypes.viewType == "windows": + self.setFixedHeight(560) + self.scrollArea.setFixedHeight(560) + + self.setFixedWidth(1164) + self.scrollAreaWidgetContents.setFixedWidth(1164) + self.scrollArea.setFixedWidth(1164) + self.update() + else: + raise NotImplementedError("illegal type") + class MeetingWidget(QWidget): def __init__(self): @@ -456,6 +482,8 @@ class MeetingWidget(QWidget): self.scrollAreaWidgetContents.setMinimumSize(50, 100) # 设置滚动区域的内容部署部件为前面生成的内容部署层部件 self.scrollArea.setWidget(self.scrollAreaWidgetContents) + + self.scrollArea.setFixedHeight(720) layout.addWidget(self.scrollArea) self.layout0 = QVBoxLayout() self.layout0.setSpacing(0) @@ -500,4 +528,21 @@ class MeetingWidget(QWidget): def add_vertical_spacer(self): if not self.spacerItemAdded: self.layout0.addItem(QSpacerItem(10, 100, QSizePolicy.Preferred, QSizePolicy.Expanding)) - self.spacerItemAdded = True \ No newline at end of file + self.spacerItemAdded = True + + def switchViewType(self): + if PublicTypes.viewType == "sidebar": + h = self.height - 280 + self.setFixedHeight(h) + self.scrollArea.setFixedHeight(h) + self.setFixedWidth(480 - 36) + self.scrollArea.setFixedWidth(480 - 36) + self.scrollAreaWidgetContents.setFixedWidth(480 - 36) + elif PublicTypes.viewType == "windows": + self.setFixedHeight(560) + self.scrollArea.setFixedHeight(560) + self.setFixedWidth(1164) + self.scrollArea.setFixedWidth(1164) + self.scrollAreaWidgetContents.setFixedWidth(1164) + else: + raise NotImplementedError("illegal type") \ No newline at end of file diff --git a/usr/share/aiassistant/data/AIFace/AIFace_01.png b/usr/share/aiassistant/data/AIFace/AIFace_01.png new file mode 100644 index 0000000000000000000000000000000000000000..65147043cd90261ac3c127b6be288025ccce447a Binary files /dev/null and b/usr/share/aiassistant/data/AIFace/AIFace_01.png differ diff --git a/usr/share/aiassistant/data/AIFace/AIFace_02.png b/usr/share/aiassistant/data/AIFace/AIFace_02.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf53cc83fbebdb98914363ad0d2a5177c2c6e32 Binary files /dev/null and b/usr/share/aiassistant/data/AIFace/AIFace_02.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_00.png b/usr/share/aiassistant/data/AILight/Light_00.png new file mode 100644 index 0000000000000000000000000000000000000000..483b1743bc342f14e20500329e8e17048f7aed26 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_00.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_01.png b/usr/share/aiassistant/data/AILight/Light_01.png new file mode 100644 index 0000000000000000000000000000000000000000..221b462932b9352a2ddd1db8b7fd7c2bfe54525e Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_01.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_02.png b/usr/share/aiassistant/data/AILight/Light_02.png new file mode 100644 index 0000000000000000000000000000000000000000..83de5fceed0ecc2cfe9429adad0099728b3be24b Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_02.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_03.png b/usr/share/aiassistant/data/AILight/Light_03.png new file mode 100644 index 0000000000000000000000000000000000000000..54c010a2621f1f15e4e3da42f66c66a5b54c0ef2 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_03.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_04.png b/usr/share/aiassistant/data/AILight/Light_04.png new file mode 100644 index 0000000000000000000000000000000000000000..dc8ec326104beb067fc4abbe0573a541a802658c Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_04.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_05.png b/usr/share/aiassistant/data/AILight/Light_05.png new file mode 100644 index 0000000000000000000000000000000000000000..17d61f302552f2f716372031f8ba42da18bb94a8 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_05.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_06.png b/usr/share/aiassistant/data/AILight/Light_06.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd42fbe082ab102650119cd4c3ce5ed80ad867a Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_06.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_07.png b/usr/share/aiassistant/data/AILight/Light_07.png new file mode 100644 index 0000000000000000000000000000000000000000..e0a1f58ecc56c43babb6d0059fbd47905b8eb8dc Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_07.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_08.png b/usr/share/aiassistant/data/AILight/Light_08.png new file mode 100644 index 0000000000000000000000000000000000000000..797cef3b197d64ba0c2b167480e953a2ccf2ea26 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_08.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_09.png b/usr/share/aiassistant/data/AILight/Light_09.png new file mode 100644 index 0000000000000000000000000000000000000000..3e2c215e051c2c4d3b2930b9db11f5230f397290 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_09.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_10.png b/usr/share/aiassistant/data/AILight/Light_10.png new file mode 100644 index 0000000000000000000000000000000000000000..16ea2dd2e26550fa708feb7f0e8fd9c25ac5baa3 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_10.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_11.png b/usr/share/aiassistant/data/AILight/Light_11.png new file mode 100644 index 0000000000000000000000000000000000000000..18568b8a986d52dd19cdb9768701d88d9dbb8f76 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_11.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_12.png b/usr/share/aiassistant/data/AILight/Light_12.png new file mode 100644 index 0000000000000000000000000000000000000000..2a61a9853a453f9635e4d5607973b54532f2b601 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_12.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_13.png b/usr/share/aiassistant/data/AILight/Light_13.png new file mode 100644 index 0000000000000000000000000000000000000000..92bbaa506a0b94df7237074ac5ddd42de6d5f1a5 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_13.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_14.png b/usr/share/aiassistant/data/AILight/Light_14.png new file mode 100644 index 0000000000000000000000000000000000000000..e75037bfc9c14e35ab114e4f3abe9b0153cb01fd Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_14.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_15.png b/usr/share/aiassistant/data/AILight/Light_15.png new file mode 100644 index 0000000000000000000000000000000000000000..2f8d78649dfabdc5c0cffa243fa0fe307f767eb8 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_15.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_16.png b/usr/share/aiassistant/data/AILight/Light_16.png new file mode 100644 index 0000000000000000000000000000000000000000..c566cc0117f412409b6752b46a47975ff5203da2 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_16.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_17.png b/usr/share/aiassistant/data/AILight/Light_17.png new file mode 100644 index 0000000000000000000000000000000000000000..ed556f541372ceb65979c338020dd3ce56a333cf Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_17.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_18.png b/usr/share/aiassistant/data/AILight/Light_18.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8f08ddf05222d74da8b924db150f6f987a1190 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_18.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_19.png b/usr/share/aiassistant/data/AILight/Light_19.png new file mode 100644 index 0000000000000000000000000000000000000000..072985da7d765324c73d41fa05baecaa65395f76 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_19.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_20.png b/usr/share/aiassistant/data/AILight/Light_20.png new file mode 100644 index 0000000000000000000000000000000000000000..36070cccfcab8d4ee9f63271b20b7a10de38eb64 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_20.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_21.png b/usr/share/aiassistant/data/AILight/Light_21.png new file mode 100644 index 0000000000000000000000000000000000000000..381fb01fcb205d75066435c1daa1240cafde6921 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_21.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_22.png b/usr/share/aiassistant/data/AILight/Light_22.png new file mode 100644 index 0000000000000000000000000000000000000000..7ecb495061d8fb04c255ed83efc1e63c7119a715 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_22.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_23.png b/usr/share/aiassistant/data/AILight/Light_23.png new file mode 100644 index 0000000000000000000000000000000000000000..19657f06353dbd07e22cbb9b689a29131e615730 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_23.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_24.png b/usr/share/aiassistant/data/AILight/Light_24.png new file mode 100644 index 0000000000000000000000000000000000000000..057f1b7463934a0c06bb3c1cfa578b7f0d9eabab Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_24.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_25.png b/usr/share/aiassistant/data/AILight/Light_25.png new file mode 100644 index 0000000000000000000000000000000000000000..ecf80ce0b97126e16d0c0a196d11664902cbe3da Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_25.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_26.png b/usr/share/aiassistant/data/AILight/Light_26.png new file mode 100644 index 0000000000000000000000000000000000000000..a71040248d34caf111787cdd1483279c3c310184 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_26.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_27.png b/usr/share/aiassistant/data/AILight/Light_27.png new file mode 100644 index 0000000000000000000000000000000000000000..94360eb73c38c276041185a87d127cb802705707 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_27.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_28.png b/usr/share/aiassistant/data/AILight/Light_28.png new file mode 100644 index 0000000000000000000000000000000000000000..a06c23aa96ba9d24d4ef0b6e3aa8b895a36a2815 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_28.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_29.png b/usr/share/aiassistant/data/AILight/Light_29.png new file mode 100644 index 0000000000000000000000000000000000000000..bcf08ed2deb4a985c63409f175de99d122755d7f Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_29.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_30.png b/usr/share/aiassistant/data/AILight/Light_30.png new file mode 100644 index 0000000000000000000000000000000000000000..f72472bdfb2aa7eaefa25118008a1dfa448b572a Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_30.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_31.png b/usr/share/aiassistant/data/AILight/Light_31.png new file mode 100644 index 0000000000000000000000000000000000000000..678e6c73f258afc84967fc7308bec7cb55a9c030 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_31.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_32.png b/usr/share/aiassistant/data/AILight/Light_32.png new file mode 100644 index 0000000000000000000000000000000000000000..fe476e0155725f107e0c3d992fee588bd1580ce9 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_32.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_33.png b/usr/share/aiassistant/data/AILight/Light_33.png new file mode 100644 index 0000000000000000000000000000000000000000..2f3e3ec6edda6d4729aa25299376c76995f33f91 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_33.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_34.png b/usr/share/aiassistant/data/AILight/Light_34.png new file mode 100644 index 0000000000000000000000000000000000000000..0efde579824da414281365e7839d140c35090d1e Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_34.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_35.png b/usr/share/aiassistant/data/AILight/Light_35.png new file mode 100644 index 0000000000000000000000000000000000000000..50edb5ad1fe176daf5f0d4c26f9bc5dec9a40b40 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_35.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_36.png b/usr/share/aiassistant/data/AILight/Light_36.png new file mode 100644 index 0000000000000000000000000000000000000000..566372784f77f48498e4eb920b442f81155c6857 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_36.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_37.png b/usr/share/aiassistant/data/AILight/Light_37.png new file mode 100644 index 0000000000000000000000000000000000000000..5090a1b5c5276d2c5a2ff5e20c0311a6abd8aae0 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_37.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_38.png b/usr/share/aiassistant/data/AILight/Light_38.png new file mode 100644 index 0000000000000000000000000000000000000000..8156689af492a8e10de5794257d6b445a4ada953 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_38.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_39.png b/usr/share/aiassistant/data/AILight/Light_39.png new file mode 100644 index 0000000000000000000000000000000000000000..662e337e4fc2fbaa2fc76185094a158067e6689d Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_39.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_40.png b/usr/share/aiassistant/data/AILight/Light_40.png new file mode 100644 index 0000000000000000000000000000000000000000..630b9a903ae1cbb7c16841086a45e0714c0a10a9 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_40.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_41.png b/usr/share/aiassistant/data/AILight/Light_41.png new file mode 100644 index 0000000000000000000000000000000000000000..a13046f5ed2b42a30dc0460c1d81c472120cc29d Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_41.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_42.png b/usr/share/aiassistant/data/AILight/Light_42.png new file mode 100644 index 0000000000000000000000000000000000000000..c0cf3d9e6c2141bd49bc641c1fd3b2c1be44916a Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_42.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_43.png b/usr/share/aiassistant/data/AILight/Light_43.png new file mode 100644 index 0000000000000000000000000000000000000000..d48fe3e840119f7f7207cc1115da1e3dbecac6bf Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_43.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_44.png b/usr/share/aiassistant/data/AILight/Light_44.png new file mode 100644 index 0000000000000000000000000000000000000000..4fe09c8d0b6bbc2e10678ef56fa3b0bb3484aa77 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_44.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_45.png b/usr/share/aiassistant/data/AILight/Light_45.png new file mode 100644 index 0000000000000000000000000000000000000000..344560e3e2e6d5eda10179814e762b96f97a9903 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_45.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_46.png b/usr/share/aiassistant/data/AILight/Light_46.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba1886ee28d33d90e367546d796ae81ccb238cf Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_46.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_47.png b/usr/share/aiassistant/data/AILight/Light_47.png new file mode 100644 index 0000000000000000000000000000000000000000..10f611ce4e442f21a8bdf230cce5149c4fd2e1c3 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_47.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_48.png b/usr/share/aiassistant/data/AILight/Light_48.png new file mode 100644 index 0000000000000000000000000000000000000000..14e9c95a15bf7fca8568f8b44463a424d274ffc9 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_48.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_49.png b/usr/share/aiassistant/data/AILight/Light_49.png new file mode 100644 index 0000000000000000000000000000000000000000..fc01905b77d001b3f8c62dac76956c679a553bbe Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_49.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_50.png b/usr/share/aiassistant/data/AILight/Light_50.png new file mode 100644 index 0000000000000000000000000000000000000000..71093b697633c6090b7f5894f044aec4364df3b1 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_50.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_51.png b/usr/share/aiassistant/data/AILight/Light_51.png new file mode 100644 index 0000000000000000000000000000000000000000..cecaa12a926cd037cbc8d38c9ae6d77a6e354b35 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_51.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_52.png b/usr/share/aiassistant/data/AILight/Light_52.png new file mode 100644 index 0000000000000000000000000000000000000000..3dfd7365a9981414d2de59bc9ad82f7bfe0d72cc Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_52.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_53.png b/usr/share/aiassistant/data/AILight/Light_53.png new file mode 100644 index 0000000000000000000000000000000000000000..96d09c235ce5867fa187fc386ef498c4e526f645 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_53.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_54.png b/usr/share/aiassistant/data/AILight/Light_54.png new file mode 100644 index 0000000000000000000000000000000000000000..21b0be8aacc79fe77a0a1f62c883fd2da0fa3ebe Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_54.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_55.png b/usr/share/aiassistant/data/AILight/Light_55.png new file mode 100644 index 0000000000000000000000000000000000000000..16fe8106935e7432d49f1a07a890da559ee37900 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_55.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_56.png b/usr/share/aiassistant/data/AILight/Light_56.png new file mode 100644 index 0000000000000000000000000000000000000000..422913830fc8070bf4c350e3ba08e01467120787 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_56.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_57.png b/usr/share/aiassistant/data/AILight/Light_57.png new file mode 100644 index 0000000000000000000000000000000000000000..8e52df57fd8a4d1d2d19ac043af94844af93b1b6 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_57.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_58.png b/usr/share/aiassistant/data/AILight/Light_58.png new file mode 100644 index 0000000000000000000000000000000000000000..095a4d7cb74fdd89b8c251f032a4980f19b29d59 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_58.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_59.png b/usr/share/aiassistant/data/AILight/Light_59.png new file mode 100644 index 0000000000000000000000000000000000000000..92d8d700bd7c3aa0fc737b660e1f375b8ff96307 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_59.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_60.png b/usr/share/aiassistant/data/AILight/Light_60.png new file mode 100644 index 0000000000000000000000000000000000000000..2189f9a2f95f2797fb7cb3ead1a4c52cd419a3bb Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_60.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_61.png b/usr/share/aiassistant/data/AILight/Light_61.png new file mode 100644 index 0000000000000000000000000000000000000000..841d315d613b2054306fbd6c6af46d37a5281581 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_61.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_62.png b/usr/share/aiassistant/data/AILight/Light_62.png new file mode 100644 index 0000000000000000000000000000000000000000..1c985ddc943572b5d250e8101318000f51779bd8 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_62.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_63.png b/usr/share/aiassistant/data/AILight/Light_63.png new file mode 100644 index 0000000000000000000000000000000000000000..3635868dd9d642c5ffad854fabbabb25adb856c0 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_63.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_64.png b/usr/share/aiassistant/data/AILight/Light_64.png new file mode 100644 index 0000000000000000000000000000000000000000..988aaab3b2314225ad95f9073850db4e5538ece7 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_64.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_65.png b/usr/share/aiassistant/data/AILight/Light_65.png new file mode 100644 index 0000000000000000000000000000000000000000..eb543584d59e9302a44517a1f04e8ad6e89aa197 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_65.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_66.png b/usr/share/aiassistant/data/AILight/Light_66.png new file mode 100644 index 0000000000000000000000000000000000000000..38c7dfdde89d712a7caf0188d36802b62a606b61 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_66.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_67.png b/usr/share/aiassistant/data/AILight/Light_67.png new file mode 100644 index 0000000000000000000000000000000000000000..6a1f699b1157a10c2fd315dc9761c078fa2935c8 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_67.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_68.png b/usr/share/aiassistant/data/AILight/Light_68.png new file mode 100644 index 0000000000000000000000000000000000000000..bb02cac7d6cb31f9ba17fc4a671988892f6f901e Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_68.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_69.png b/usr/share/aiassistant/data/AILight/Light_69.png new file mode 100644 index 0000000000000000000000000000000000000000..3ef59a4c193aa7a23fc792904bf4e71e17806213 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_69.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_70.png b/usr/share/aiassistant/data/AILight/Light_70.png new file mode 100644 index 0000000000000000000000000000000000000000..c7234af0e081c320941e446ad865dcd002c0026b Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_70.png differ diff --git a/usr/share/aiassistant/data/AILight/Light_71.png b/usr/share/aiassistant/data/AILight/Light_71.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e6d1e53ae49ad342ed43102c9c8c7684e4f0b6 Binary files /dev/null and b/usr/share/aiassistant/data/AILight/Light_71.png differ diff --git a/usr/share/aiassistant/data/ai_model_guide.png b/usr/share/aiassistant/data/ai_model_guide.png new file mode 100644 index 0000000000000000000000000000000000000000..62cbb9202d6854b32785132928289e6845696499 Binary files /dev/null and b/usr/share/aiassistant/data/ai_model_guide.png differ diff --git a/usr/share/aiassistant/data/icon_audio_window.png b/usr/share/aiassistant/data/icon_audio_window.png new file mode 100644 index 0000000000000000000000000000000000000000..bed9545e0e429a662de31bb69eee068992b6fbaa Binary files /dev/null and b/usr/share/aiassistant/data/icon_audio_window.png differ diff --git a/usr/share/aiassistant/data/icon_audio_window_sidebar.png b/usr/share/aiassistant/data/icon_audio_window_sidebar.png new file mode 100644 index 0000000000000000000000000000000000000000..e5075cea18ba5c56ee71ef1b459e58311d026c61 Binary files /dev/null and b/usr/share/aiassistant/data/icon_audio_window_sidebar.png differ 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_strategy.png b/usr/share/aiassistant/data/icon_strategy.png new file mode 100644 index 0000000000000000000000000000000000000000..990bc7bd71c279664bc4520eb455157cabf0bd22 Binary files /dev/null and b/usr/share/aiassistant/data/icon_strategy.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/logo_about.png b/usr/share/aiassistant/data/logo_about.png new file mode 100644 index 0000000000000000000000000000000000000000..ee67bb08c384ba26af0f4637e449fb129958c645 Binary files /dev/null and b/usr/share/aiassistant/data/logo_about.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/exchangePage.py b/usr/share/aiassistant/exchangePage.py new file mode 100644 index 0000000000000000000000000000000000000000..04cad8b226c791f1168a6bef7ac33bf90d58980d --- /dev/null +++ b/usr/share/aiassistant/exchangePage.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'pre.ui' +# +# Created by: PyQt5 UI code generator 5.15.2 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. +import os + +from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt5.QtWidgets import * +from PyQt5.QtCore import * +from PyQt5.QtGui import * +from bubble_message import BubbleMessage, MessageType +from PublicTypes import PublicTypes + + + + +class exChange(QWidget): + collect_voice_signal = pyqtSignal() + collect_voice_flag = False + + def __init__(self): + super().__init__() + self.setObjectName('exChangeWindow') + self.setStyleSheet( + ''' + #mainwindow{ + border-top-left-radius: 15px; + border-top-right-radius: 15px; + border-bottom-left-radius: 15px; + border-bottom-right-radius: 15px; + } + ''' + ) + + # 背景透明 + self.setAttribute(Qt.WA_TranslucentBackground, True) + self.setMaximumHeight(922) + # 获取显示器分辨率大小 + self.desktop = QApplication.desktop() + self.screenRect = self.desktop.screenGeometry() + self.height = self.screenRect.height() + h = self.height - 380 + self.setFixedHeight(h) + + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setSpacing(10) + + # AIFace + self.imageLabel = QLabel(self) + self.imageLabel.setAlignment(Qt.AlignCenter) + self.imageLabel.setStyleSheet("QLabel { padding: 0px;}") + self.imageLabel.setAlignment(Qt.AlignCenter) + # self.imageLabel.setScaledContents(True) + + # 图片列表和索引 + self.image_folder1 = './data/AIFace' + self.image_files1 = [os.path.join(self.image_folder1, f) for f in os.listdir(self.image_folder1) if + f.endswith(('.png', '.jpg', '.jpeg'))] + self.current_image_index1 = 0 + self.image_timer1 = QTimer(self) + self.image_timer1.timeout.connect(self.updateImage) + self.image_timer1.start(500) + + self.textLabel = QLabel(self) + self.textLabel.setText(''' +

欢迎使用NFS AI语音助手

+

可以点击下方按钮唤醒

+ ''') + + self.textLabel.setAlignment(Qt.AlignCenter) + + # 状态标签 + + self.statusLabel = QLabel('当前状态:休眠中', self) + self.statusLabel.setStyleSheet(""" + QLabel { + font-size: 16px; + font-weight: bold; + color: black; + padding: 0px; + } + """) + self.statusLabel.setAlignment(Qt.AlignCenter) + + + # 按钮 + self.startButton = QPushButton('', self) + self.startButton.setIconSize(QSize(300, 150)) + self.startButton.setStyleSheet("QPushButton { border: none; }") + # AILight + self.image_folder = './data/AILight' + self.image_files = sorted([os.path.join(self.image_folder, f) for f in os.listdir(self.image_folder) if + f.endswith(('.png', '.jpg', '.jpeg'))]) + self.current_image_index = 0 + + # 定时器 + self.image_timer = QTimer(self) + self.image_timer.timeout.connect(self.updateButton) + self.image_timer.start(50) # 每500毫秒更换一次图片 + + self.verticalLayout.addStretch(1) + self.verticalLayout.addWidget(self.imageLabel) + self.verticalLayout.addWidget(self.textLabel) + self.verticalLayout.addStretch(1) + # self.verticalLayout.addWidget(self.opLabel) + self.verticalLayout.addWidget(self.statusLabel) + self.verticalLayout.addStretch(1) + self.verticalLayout.addWidget(self.startButton) + self.verticalLayout.addStretch(4) + + + self.startButton.clicked.connect(self.startConversation) + self.state = '休眠中' + + + def capture_voice(self): + self.collect_voice_signal.emit() + def updateButton(self): + # 更新按钮的图标 + if self.current_image_index < len(self.image_files): + icon = QIcon(self.image_files[self.current_image_index]) + self.startButton.setIcon(icon) + self.current_image_index = (self.current_image_index + 1) % len(self.image_files) + + def updateImage(self): + if self.current_image_index1 < len(self.image_files1): + pixmap = QPixmap(self.image_files1[self.current_image_index1]) + + self.imageLabel.setPixmap(pixmap) + self.current_image_index1 = (self.current_image_index1 + 1) % len(self.image_files1) + + def startConversation(self): + # if self.state == '聆听中': + # self.capture_voice() + if self.state == '休眠中': + self.updateStatus('聆听中') + QApplication.processEvents() + self.capture_voice() #获取声音信息 + # self.respondToUser() + #self.timer.start(5000) # 3秒 + + + def updateStatus(self, new_status): + self.state = new_status + print(self.state) + self.statusLabel.setText(f'当前状态:{self.state}') + self.statusLabel.repaint() + + def switchViewType(self): + if PublicTypes.viewType == "sidebar": + h = self.height - 380 + self.setFixedHeight(h) + self.setFixedWidth(480 - 36) + elif PublicTypes.viewType == "windows": + self.setFixedHeight(560) + self.setFixedWidth(1164) + else: + raise NotImplementedError("illegal type") + +# 测试布局和交互效果 +from PyQt5.QtWidgets import * +from PyQt5.QtCore import * +from PyQt5.QtGui import * + +if __name__ == '__main__': + app = QApplication([]) + widget = exChange() + widget.show() + app.exec_() + + diff --git a/usr/share/aiassistant/mainwin.py b/usr/share/aiassistant/mainwin.py index bd634096a0770e2dd86ed5360c594a6bd2d39761..b835530a43bd3ae8ab455cc7c988eb102bbb420c 100644 --- a/usr/share/aiassistant/mainwin.py +++ b/usr/share/aiassistant/mainwin.py @@ -25,7 +25,14 @@ from ChatTalk import ChatTalk from MeetingBottomWgt import MeetingBottomWidget from MeetingTask import MeetingTask from MeetingFile import MeetingFile +from SettingPage import SettingsPage +from AboutPage import AboutPage +from PyQt5 import QtWidgets +from exchangePage import exChange +from ApikeyConfigPage import ApiKeyConfigPage + app_list = Config.get_app_list() +api_key = Config.get_api_key() public_types = PublicTypes() class ShadowWindow(QWidget): @@ -33,7 +40,19 @@ 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) + self.setMaximumWidth(public_types.mainwin_width) layout = QVBoxLayout(self) layout.setContentsMargins(0,0,0,0) self.widget = Mainwin() @@ -42,46 +61,16 @@ class ShadowWindow(QWidget): self.widget.chatWgt.verticalScrollBar().setValue(200) self.setWindowTitle("NFS AI") # 设置窗口名 self.setWindowIcon(QIcon('./data/icon.png')) # 设置窗口图标 + + self.right_bottom_index = self.get_right_bottom_index() - #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; - ''' - ) - - title_layout.addWidget(title_name) + self.stack = QStackedWidget(self) - title_spacer = QSpacerItem(40, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) - title_layout.addItem(title_spacer) + #title + self.title = MianWinTitle() - 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 +85,56 @@ class ShadowWindow(QWidget): lambda: self.widget.shift_model(False) ) home_btn.setFixedSize(24, 24) - title_layout.addWidget(home_btn) + self.title.title_layout.addWidget(home_btn) - close_btn = QPushButton(title) + #切换按钮 + exchange_btn = QPushButton() + exchange_btn.setFixedSize(24, 24) + exchange_btn.setFlat(True) + exchange_btn.setStyleSheet( + ''' + QPushButton{background-color: transparent;border:none;color:white;} + ''' + ) + exchange_btn.setIcon(QIcon('./data/icon_audio_window.png')) + exchange_btn.setIconSize(QSize(24, 24)); + exchange_btn.clicked.connect(self.navigate_to_exchange) + + self.title.title_layout.addWidget(exchange_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(QIcon('./data/menu_select.png'), "侧边栏模式", self) + sub_menu.addAction(self.action_sidebar) + self.action_sidebar.triggered.connect(self.switchToSidebar) + menu.sub_menu = sub_menu + menu.setSubMenu() + + menu.addAction("设置", self.openSettingPage) + menu.addSeparator() + menu.addAction("关于", self.openAboutPage) + setting_btn.setMenu(menu) + + # close button + close_btn = QPushButton(self.title) close_btn.setFixedSize(24, 24) close_btn.setStyleSheet( ''' @@ -110,31 +146,88 @@ 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.switchToSidebar() self.move_to_right_bottom() + + + print("2 self.widget", self.widget.width()) + print("2 self.widget.guidWgt", self.widget.guidWgt.width()) + print("2 self.widget.chatWgt", self.widget.chatWgt.width()) + print("2 self.widget.exchange", self.widget.exchange.width()) + print("2 self.widget.meetingWgt", self.widget.meetingWgt.width()) + print("2 self.widget.chatWgt", self.widget.chatWgt.scrollArea.width()) + print("2 self.widget.chatWgt", self.widget.chatWgt.scrollAreaWidgetContents.width()) + # 检测api-key是否存在,不存在,调用apikey配置页面 + # if api_key == "": + # self.openApiKeyConfigPage() + + + #切换功能跳转函数 + def navigate_to_exchange(self): + if self.widget.exchange.isHidden(): + self.widget.set_chat_model() + self.widget.contentStackWgt.setCurrentIndex(1) + self.widget.bottomStackWgt.setCurrentIndex(0) + self.widget.exchange.show() + self.widget.chatWgt.hide() + self.widget.bottom_ui.hide() + self.widget.meetingWgt.hide() + self.widget.meeting_bottom_ui.hide() + else: + self.widget.set_chat_model() + self.widget.shift_model(True) + + def get_right_bottom_index(self): + # 获取屏幕总数和屏幕几何数据 + desktop = QDesktopWidget() + screen_count = desktop.screenCount() + target_screen_index = 0 + if screen_count > 1: + # 多屏情况下,寻找最右下角的屏幕 + right_most = 0 + bottom_most = 0 + for i in range(screen_count): + screen_geo = desktop.screenGeometry(i) + if screen_geo.right() > right_most: + right_most = screen_geo.right() + target_screen_index = i + if screen_geo.bottom() > bottom_most: + bottom_most = screen_geo.bottom() + target_screen_index = i + else: + target_screen_index = 0 + + return target_screen_index + def move_to_right_bottom(self): # 获取屏幕总数和屏幕几何数据 desktop = QDesktopWidget() screen_count = desktop.screenCount() if screen_count > 1: - # 多屏情况下,寻找最右下角的屏幕 - right_most = 0 - bottom_most = 0 - target_screen_index = 0 - for i in range(screen_count): - screen_geo = desktop.screenGeometry(i) - if screen_geo.right() > right_most: - right_most = screen_geo.right() - target_screen_index = i - if screen_geo.bottom() > bottom_most: - bottom_most = screen_geo.bottom() - target_screen_index = i + # 获取目标屏幕的几何信息 + target_screen_geometry = desktop.screenGeometry(self.right_bottom_index) + else: + # 单屏情况下使用默认屏幕 + target_screen_geometry = desktop.screenGeometry() + # 计算窗口移动位置到屏幕右下角 + 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: @@ -144,13 +237,100 @@ class ShadowWindow(QWidget): # 计算窗口移动位置到屏幕右下角 right = target_screen_geometry.right() bottom = target_screen_geometry.bottom() - self.move(right - self.width(), bottom - self.height()) + self.move(right/2 - self.width()/2, bottom/2 - self.height()/2) + + # 切换到窗口模式 + def switchToWindow(self): + if PublicTypes.viewType != "windows": + PublicTypes.viewType = "windows" + self.action_window.setIcon(QIcon('./data/menu_select.png')) + self.action_sidebar.setIcon(QIcon("")) + self.setMaximumWidth(1200) + + self.widget.resize(public_types.mainwin_windows_width, public_types.mainwin_windows_height) + self.widget.setMaximumHeight(public_types.mainwin_windows_height) + self.resize(public_types.mainwin_windows_width, public_types.mainwin_windows_height) + self.setMaximumHeight(public_types.mainwin_windows_height) + self.move_to_center() + self.widget.guidWgt.switchViewType() + self.widget.chatWgt.switchViewType() + self.widget.exchange.switchViewType() + self.widget.meetingWgt.switchViewType() + self.widget.meeting_bottom_ui.switchViewType() + self.title.switchViewType() + + print("1 self.widget", self.width()) + print("2 self.widget", self.widget.width()) + print("2 self.widget.guidWgt", self.widget.guidWgt.width()) + print("2 self.widget.chatWgt", self.widget.chatWgt.width()) + print("2 self.widget.exchange", self.widget.exchange.width()) + print("2 self.widget.meetingWgt", self.widget.meetingWgt.width()) + print("2 self.widget.chatWgt", self.widget.chatWgt.scrollArea.width()) + print("2 self.widget.chatWgt", self.widget.chatWgt.scrollAreaWidgetContents.width()) + + self.widget.bottom_ui.setFixedHeight(120) + self.widget.meeting_bottom_ui.setFixedHeight(120) + self.widget.bottomStackWgt.setFixedHeight(120) + + else: + pass + + # 切换到侧边栏模式 + def switchToSidebar(self): + if PublicTypes.viewType != "sidebar": + PublicTypes.viewType = "sidebar" + self.action_window.setIcon(QIcon("")) + self.action_sidebar.setIcon(QIcon('./data/menu_select.png')) + self.widget.guidWgt.switchViewType() + self.widget.chatWgt.switchViewType() + self.widget.exchange.switchViewType() + self.widget.meetingWgt.switchViewType() + self.widget.meeting_bottom_ui.switchViewType() + self.widget.setMaximumHeight(public_types.mainwin_height) + self.widget.resize(public_types.mainwin_width, public_types.mainwin_height) + + + self.widget.bottomStackWgt.setFixedHeight(180) + self.widget.bottom_ui.setFixedHeight(180) + self.widget.meeting_bottom_ui.setFixedHeight(180) + + self.setMaximumHeight(public_types.mainwin_height) + self.resize(public_types.mainwin_width, public_types.mainwin_height) + self.title.switchViewType() + self.setMaximumWidth(public_types.mainwin_width) + print("1 self.widget", self.width()) + print("1 self.widget", self.widget.width()) + print("1 self.widget.guidWgt", self.widget.guidWgt.width()) + print("1 self.widget.chatWgt", self.widget.chatWgt.width()) + print("1 self.widget.exchange", self.widget.exchange.width()) + print("1 self.widget.meetingWgt", self.widget.meetingWgt.width()) + print("1 self.widget.chatWgt", self.widget.chatWgt.scrollArea.width()) + print("1 self.widget.chatWgt", self.widget.chatWgt.scrollAreaWidgetContents.width()) + + self.move_to_right_bottom() + + 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 +362,45 @@ class ShadowWindow(QWidget): # 鼠标释放后,各扳机复位 self._move_drag = False + def openApiKeyConfigPage(self): + self.apiKeyConfigPage = ApiKeyConfigPage() + self.apiKeyConfigPage.show() + + def openSettingPage(self): + #创建并显示设置页面 + self.settingPage = SettingsPage(self) + self.settingPage.show() + # 绑定设置页面的关闭信号到槽函数 + self.settingPage.closed.connect(self.onSettingPageClosed) + # 设置窗口置顶 + self.settingPage.raise_() + # #修改一直置顶 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) + # 移到画面中间 + self.settingPage.move_to_center() + self.show() + + def openAboutPage(self): + #创建并显示设置页面 + self.aboutPage = AboutPage(self) + self.aboutPage.show() + # 绑定设置页面的关闭信号到槽函数 + self.aboutPage.closed.connect(self.onSettingPageClosed) + # 设置窗口置顶 + self.aboutPage.raise_() + # #修改一直置顶 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) + # 移到画面中间 + self.aboutPage.move_to_center() + self.show() + + def onSettingPageClosed(self): + # 设置窗口置顶标志 + self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint) + # 重新置顶主窗口 + self.raise_() + self.show() + class Mainwin(QWidget): def __init__(self): super().__init__() @@ -189,7 +408,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; @@ -206,6 +425,9 @@ class Mainwin(QWidget): self.chatWgt = ChatWidget() self.chatWgt.hide() self.guidWgt = PreWidget() + #新建exchage对象 + self.exchange = exChange() + self.exchange.hide() self.meetingWgt = MeetingWidget() self.meetingWgt.hide() TEXT = MessageType.Text @@ -264,6 +486,8 @@ class Mainwin(QWidget): self.bottom_ui.send_text_signal.connect(self.send_message_to_ai) # self.bottom_ui.send_text_signal.connect(self.send_message_to_ai) + self.exchange.collect_voice_signal.connect(self.collect_voice_handle) + self.guidWgt.chat_model_signal.connect(self.set_chat_model) self.guidWgt.paint_model_signal.connect(self.set_paint_model) self.guidWgt.meeting_minuts_model_signal.connect(self.set_meeting_minuts_model) @@ -273,9 +497,11 @@ class Mainwin(QWidget): bottom_spacer = QSpacerItem(10, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.contentStackWgt = QStackedWidget() self.contentStackWgt.addWidget(self.guidWgt) + self.contentStackWgt.addWidget(self.exchange) self.contentStackWgt.addWidget(self.chatWgt) self.contentStackWgt.addWidget(self.meetingWgt) self.contentStackWgt.setCurrentIndex(0) + layout.addWidget(self.contentStackWgt) # layout.addWidget(self.meetingWgt) # layout.addWidget(self.guidWgt) @@ -293,6 +519,19 @@ class Mainwin(QWidget): self.timer = QTimer(self) # 定义定时器 self.timer.timeout.connect(self.start_meeting) # 定时器信号连接到updateImage方法 + # # 聆听中到等待中的自动转换 + self.last_voice_message = "" + self.timerSend = QTimer(self) + self.timerSend.timeout.connect(self.listeningToWaiting) + + + # # 聆听中到等待中的自动转换函数 + def listeningToWaiting(self): + if self.voice_message != self.last_voice_message: + self.last_voice_message = self.voice_message + else: + self.exchange.capture_voice() + # self.exchange.updateStatus('等待中') def show_meeting_waiting_message(self, show): #总是和BubbleMessage成对出现,send为True则显示,否则隐藏,待优化 if show: @@ -380,6 +619,7 @@ class Mainwin(QWidget): def speechTaskCallback(self, bubble_message): print("speechTaskCallback") bubble_message.playComplete() + self.exchange.updateStatus('休眠中') def showExample(self): print('show example') @@ -409,18 +649,20 @@ class Mainwin(QWidget): def shift_model(self, toModel): if toModel == True: if self.modeType == ModelType.MeetingMinuts: - self.contentStackWgt.setCurrentIndex(2) + self.contentStackWgt.setCurrentIndex(3) self.bottomStackWgt.setCurrentIndex(1) self.meetingWgt.show() self.meeting_bottom_ui.show() self.showExample() + self.exchange.hide() self.bottom_ui.hide() self.chatWgt.hide() else: - self.contentStackWgt.setCurrentIndex(1) + self.contentStackWgt.setCurrentIndex(2) self.bottomStackWgt.setCurrentIndex(0) self.chatWgt.show() + self.exchange.hide() self.showExample() self.bottom_ui.setEnabled(True) self.bottom_ui.show() @@ -432,6 +674,8 @@ class Mainwin(QWidget): self.bottomStackWgt.setCurrentIndex(0) self.guidWgt.show() self.chatWgt.hide() + + self.exchange.hide() # self.bottom_ui.setEnabled(False) self.bottom_ui.hide() self.meetingWgt.hide() @@ -439,18 +683,30 @@ class Mainwin(QWidget): def set_chat_model (self): print("set_chat_model") + if Config.get_api_key() == "": + self.parent().openSettingPage() self.modeType = ModelType.Chat self.shift_model(True) def set_paint_model (self): print("set_paint_model") + if Config.get_api_key() == "": + self.parent().openSettingPage() self.modeType = ModelType.Paint self.shift_model(True) def set_meeting_minuts_model (self): print("set_meeting_minuts_model") + if Config.get_ALIBABA_CLOUD_ACCESS_KEY_ID() == "" or Config.get_app_key == "" or Config.get_ALIBABA_CLOUD_ACCESS_KEY_SECRET() == "": + self.parent().openSettingPage() self.modeType = ModelType.MeetingMinuts self.shift_model(True) + + def set_AiAss_model(self): + print("set_AiAss_model") + self.modeType = ModelType.AiAss + self.shift_model(True) + def show_waiting_message(self,show): #总是和BubbleMessage成对出现,send为True则显示,否则隐藏,待优化 if show: @@ -480,6 +736,7 @@ class Mainwin(QWidget): self.voiceInput.stop_recognition() self.bottom_ui.stop_timer() self.send_voice_message_to_ai(self.voice_message) + self.timerSend.stop() self.voice_message = "" self.bottom_ui.ui.inputLineEdit.setPlainText("") else: @@ -488,6 +745,7 @@ class Mainwin(QWidget): self.bottom_ui.collect_voice_flag = True self.bottom_ui.start_timer() self.voiceInput.start() + self.timerSend.start(3000) def start_local_app(self, text): flag = False @@ -534,6 +792,7 @@ class Mainwin(QWidget): self.bottom_ui.set_send_button_status(True) def send_quest_to_ai(self, message): + self.exchange.updateStatus('等待中') if self.serverCheck.internet_status(): Speech.short_text_play("好的,请稍等") self.sendTask.set_topic(message) @@ -547,9 +806,12 @@ class Mainwin(QWidget): bubble_message.playBtn.hide() self.show_waiting_message(False) self.bottom_ui.set_send_button_status(True) + self.exchange.updateStatus('休眠中') def send_voice_message_to_ai(self, message): if len(message) == 0: + self.exchange.updateStatus('休眠中') + self.bottom_ui.collect_voice_flag = False return bubble_message = BubbleMessage(message, '', Type=MessageType.Text, font_size=12, is_send=True) @@ -587,6 +849,7 @@ class Mainwin(QWidget): def ai_callback(self, result): self.show_waiting_message(False) bubble_message = BubbleMessage(result, '', Type=MessageType.Text, font_size=12, is_send=False) + self.exchange.updateStatus('应答中') bubble_message.switch_signal.connect(self.switch_signal_handle) self.chatWgt.add_message_item(bubble_message) @@ -595,8 +858,10 @@ class Mainwin(QWidget): self.speechTask.start() if "Invalid API-key provided" in result: bubble_message.playBtn.hide() + self.exchange.updateStatus('休眠中') else: bubble_message.playBtn.hide() + self.exchange.updateStatus('休眠中') # if not self.voiceStatus: self.bottom_ui.set_send_button_status(True) @@ -669,9 +934,157 @@ class Mainwin(QWidget): print('pos:', val) print('滚动条最大值', self.chatWgt.verticalScrollBar().maximum()) + +#菜单类 +class SettingMenu(QMenu): + def __init__(self, *args, **kwargs): + super(SettingMenu, self).__init__() + self.radius = 10 + self.setting_menu_sytle = ''' + 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) + self.setStyleSheet(self.setting_menu_sytle) + self.setAttribute(Qt.WA_TranslucentBackground, True) + self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint ) + + def setSubMenu(self): + self.sub_menu.setStyleSheet(self.setting_menu_sytle) + self.sub_menu.setAttribute(Qt.WA_TranslucentBackground, True) + self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint ) + +# 上方标题栏 +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") + # if __name__ == '__main__': # app = QApplication([]) # widget = ShadowWindow() # widget.show() # app.exec_() - diff --git a/usr/share/aiassistant/preGuidWidget.py b/usr/share/aiassistant/preGuidWidget.py index 6122324b8c04e443e857b0549e27539e84bfa4f2..911b275efc2d7c3ad6a474b359573303f84792f9 100644 --- a/usr/share/aiassistant/preGuidWidget.py +++ b/usr/share/aiassistant/preGuidWidget.py @@ -13,6 +13,10 @@ from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * from bubble_message import BubbleMessage,MessageType +from PublicTypes import PublicTypes +import os + +public_types = PublicTypes() class ModelType: Chat = 1 @@ -45,15 +49,34 @@ class PreWidget(QWidget): self.setFixedHeight(h) # self.setWindowFlags(Qt.FramelessWindowHint) + + # AIFace + self.imageLabel = QLabel(self) + self.imageLabel.setAlignment(Qt.AlignCenter) + self.imageLabel.setStyleSheet("QLabel { padding: 0px;}") + self.imageLabel.setAlignment(Qt.AlignCenter) + + # 图片列表和索引 + self.image_folder1 = './data/AIFace' + self.image_files1 = [os.path.join(self.image_folder1, f) for f in os.listdir(self.image_folder1) if + f.endswith(('.png', '.jpg', '.jpeg'))] + self.current_image_index1 = 0 + self.image_timer1 = QTimer(self) + self.image_timer1.timeout.connect(self.updateImage) + self.image_timer1.start(500) ## 调用气泡信息 - self.guid_title = BubbleMessage('Hi, 我是NFS AI', '', MessageType.Guid, 16, is_send=False) - self.guid_content = BubbleMessage('作为您的智能助手,我将为您提供个性化的操作系统体验,帮助您完成各种任务、回答问题、提供实用信息,以及提供智能建议和提示。', '',MessageType.Guid, 12, is_send=False) + self.guid_title = BubbleMessage('欢迎使用NFS AI', '', MessageType.Guid, 14, is_send=False) + self.guid_content = BubbleMessage('作为您的智能助手,我将为您提供个性化的操作系统体验,帮助您完成各种任务、回答问题、提供实用信息,以及提供智能建议和提示。', '',MessageType.Guid, 11, is_send=False) + + self.guid_title.setFixedHeight(40) + self.guid_content.setFixedHeight(85) self.verticalLayout = QtWidgets.QVBoxLayout(self) - self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setContentsMargins(0, 20, 0, 0) self.verticalLayout.setSpacing(10) + self.verticalLayout.addWidget(self.imageLabel) self.verticalLayout.addWidget(self.guid_title) self.verticalLayout.addWidget(self.guid_content) @@ -66,10 +89,69 @@ class PreWidget(QWidget): self.meetingMinutsGuidWgt = OptionWidget() self.meetingMinutsGuidWgt.set_ui('./data/icon_meeting minutes.png', 'NFS AI秘书', '帮助您智能管理会议,不漏掉工作中每一个细节。') self.verticalLayout.addWidget(self.meetingMinutsGuidWgt) + 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.setFixedWidth(440) + # self.paintGuidWgt.setFixedWidth(440) + # self.meetingMinutsGuidWgt.setFixedWidth(440) + self.guid_title.setFixedWidth(440) + self.guid_content.setFixedWidth(440) + + self.guid_title.setFixedHeight(40) + self.guid_content.setFixedHeight(85) + + 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) + # self.setFixedHeight(600) + h = self.height - 380 + self.setFixedHeight(h) + self.setFixedWidth(480 - 36) + + + + elif PublicTypes.viewType == "windows": + self.verticalLayout.setSpacing(10) + self.chatGuidWgt.setFixedWidth(440) + self.paintGuidWgt.setFixedWidth(440) + self.meetingMinutsGuidWgt.setFixedWidth(440) + self.guid_title.setFixedWidth(480) + self.guid_content.setFixedWidth(480) + + self.guid_title.setFixedHeight(40) + self.guid_content.setFixedHeight(80) + + 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) + self.setFixedHeight(560) + self.setFixedWidth(1164) + + + else: + raise NotImplementedError("illegal type") + + def updateImage(self): + if self.current_image_index1 < len(self.image_files1): + pixmap = QPixmap(self.image_files1[self.current_image_index1]) + + self.imageLabel.setPixmap(pixmap) + self.current_image_index1 = (self.current_image_index1 + 1) % len(self.image_files1) + + + class OptionWidget(QWidget): clicked = pyqtSignal() @@ -93,8 +175,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 +190,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")