From c3b6aa379bf84bc1cb335496d810c019e741b1d8 Mon Sep 17 00:00:00 2001 From: shuaikangzhou <863909694@qq.com> Date: Thu, 11 Jan 2024 23:25:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/DataBase/exporter_csv.py | 2 +- app/DataBase/exporter_txt.py | 4 ++-- app/ui/contact/export/exportUi.py | 31 +++++++++++++++--------- app/ui/contact/export/export_dialog.py | 28 +++++++++++++++++++--- app/ui/menu/export.py | 33 ++++++++++++++++++++++++-- app/ui/menu/exportUi.py | 13 ++++++++-- app/util/emoji.py | 27 +++++++++++---------- 7 files changed, 104 insertions(+), 34 deletions(-) diff --git a/app/DataBase/exporter_csv.py b/app/DataBase/exporter_csv.py index d79831f..87a2933 100644 --- a/app/DataBase/exporter_csv.py +++ b/app/DataBase/exporter_csv.py @@ -24,7 +24,7 @@ class CSVExporter(ExporterBase): for msg in messages: other_data = [msg[12].remark, msg[12].nickName, msg[12].wxid] if self.contact.is_chatroom else [] writer.writerow([*msg[:9], *other_data]) - print("【完成导出 CSV {self.contact.remark}】") + print(f"【完成导出 CSV {self.contact.remark}】") self.okSignal.emit(1) def run(self): diff --git a/app/DataBase/exporter_txt.py b/app/DataBase/exporter_txt.py index da494b0..74f4f02 100644 --- a/app/DataBase/exporter_txt.py +++ b/app/DataBase/exporter_txt.py @@ -110,7 +110,7 @@ class TxtExporter(ExporterBase): def export(self): # 实现导出为txt的逻辑 - print("【开始导出 TXT {self.contact.remark}】") + print(f"【开始导出 TXT {self.contact.remark}】") origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" os.makedirs(origin_docx_path, exist_ok=True) filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.txt" @@ -141,5 +141,5 @@ class TxtExporter(ExporterBase): self.music_share(f, message) elif type_ == 49 and sub_type == 5 and self.message_types.get(4905): self.share_card(f, message) - print("【完成导出 TXT {self.contact.remark}】") + print(f"【完成导出 TXT {self.contact.remark}】") self.okSignal.emit(1) \ No newline at end of file diff --git a/app/ui/contact/export/exportUi.py b/app/ui/contact/export/exportUi.py index 05c8549..72482b9 100644 --- a/app/ui/contact/export/exportUi.py +++ b/app/ui/contact/export/exportUi.py @@ -15,8 +15,8 @@ class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") Dialog.resize(553, 394) - self.verticalLayout_3 = QtWidgets.QVBoxLayout(Dialog) - self.verticalLayout_3.setObjectName("verticalLayout_3") + self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) + self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.label_3 = QtWidgets.QLabel(Dialog) @@ -38,7 +38,7 @@ class Ui_Dialog(object): self.comboBox_type.addItem("") self.comboBox_type.addItem("") self.horizontalLayout.addWidget(self.comboBox_type) - self.verticalLayout_3.addLayout(self.horizontalLayout) + self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.verticalLayout_2 = QtWidgets.QVBoxLayout() @@ -48,19 +48,28 @@ class Ui_Dialog(object): self.verticalLayout_2.addWidget(self.label_2) self.horizontalLayout_2.addLayout(self.verticalLayout_2) self.horizontalLayout_2.setStretch(0, 1) - self.verticalLayout_3.addLayout(self.horizontalLayout_2) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.textBrowser = QtWidgets.QTextBrowser(Dialog) + self.textBrowser.setObjectName("textBrowser") + self.verticalLayout.addWidget(self.textBrowser) self.progressBar = QtWidgets.QProgressBar(Dialog) self.progressBar.setProperty("value", 24) self.progressBar.setObjectName("progressBar") - self.verticalLayout_3.addWidget(self.progressBar) - self.label_process = QtWidgets.QLabel(Dialog) - self.label_process.setText("") - self.label_process.setObjectName("label_process") - self.verticalLayout_3.addWidget(self.label_process) + self.verticalLayout.addWidget(self.progressBar) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.label_time = QtWidgets.QLabel(Dialog) self.label_time.setText("") self.label_time.setObjectName("label_time") - self.verticalLayout_3.addWidget(self.label_time) + self.horizontalLayout_4.addWidget(self.label_time) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.horizontalLayout_4.addLayout(self.horizontalLayout_5) + self.label_process = QtWidgets.QLabel(Dialog) + self.label_process.setText("") + self.label_process.setObjectName("label_process") + self.horizontalLayout_4.addWidget(self.label_process) + self.verticalLayout.addLayout(self.horizontalLayout_4) self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) @@ -71,7 +80,7 @@ class Ui_Dialog(object): self.btn_cancel = QtWidgets.QPushButton(Dialog) self.btn_cancel.setObjectName("btn_cancel") self.horizontalLayout_3.addWidget(self.btn_cancel) - self.verticalLayout_3.addLayout(self.horizontalLayout_3) + self.verticalLayout.addLayout(self.horizontalLayout_3) self.retranslateUi(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog) diff --git a/app/ui/contact/export/export_dialog.py b/app/ui/contact/export/export_dialog.py index 11186e8..df56700 100644 --- a/app/ui/contact/export/export_dialog.py +++ b/app/ui/contact/export/export_dialog.py @@ -1,11 +1,14 @@ import os +import sys import time from datetime import datetime, timedelta -from PyQt5.QtCore import QTimer +from PyQt5.QtCore import QTimer, QObject, pyqtSignal +from PyQt5.QtGui import QTextCursor from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QDialog, QVBoxLayout, QCheckBox, QHBoxLayout, \ QProgressBar, QLabel, QMessageBox, QComboBox from app.DataBase import msg_db +from app.components import ScrollBar from app.ui.menu.export_time_range import TimeRangeDialog from .exportUi import Ui_Dialog from app.DataBase.output_pc import Output @@ -29,7 +32,11 @@ QPushButton:hover { background-color: lightgray; } """ +class EmittingStr(QObject): + textWritten = pyqtSignal(str) # 定义一个发送str的信号 + def write(self, text): + self.textWritten.emit(str(text)) class ExportDialog(QDialog, Ui_Dialog): def __init__(self, contact=None, title="选择导出的类型", file_type="csv", parent=None): @@ -37,7 +44,11 @@ class ExportDialog(QDialog, Ui_Dialog): self.select_all_flag = False self.setupUi(self) self.setStyleSheet(Stylesheet) - + # 下面将输出重定向到textBrowser中 + sys.stdout = EmittingStr(textWritten=self.outputWritten) + sys.stderr = EmittingStr(textWritten=self.outputWritten) + scroll_bar = ScrollBar() + self.textBrowser.setVerticalScrollBar(scroll_bar) self.contact = contact if file_type == 'html': self.export_type = Output.HTML @@ -97,7 +108,12 @@ class ExportDialog(QDialog, Ui_Dialog): self.timer.start(1000) self.start_time = time.time() # self.accept() # 使用accept关闭对话框 - + def outputWritten(self, text): + cursor = self.textBrowser.textCursor() + cursor.movePosition(QTextCursor.End) + cursor.insertText(text) + self.textBrowser.setTextCursor(cursor) + self.textBrowser.ensureCursorVisible() def set_export_date(self): date_range = self.comboBox_time.currentText() if date_range == '全部时间': @@ -161,6 +177,8 @@ class ExportDialog(QDialog, Ui_Dialog): reply.addButton("确认", QMessageBox.AcceptRole) reply.addButton("取消", QMessageBox.RejectRole) api = reply.exec_() + # 在任务完成时重置sys.stdout + sys.stdout = sys.__stdout__ self.accept() def select_all(self): @@ -185,6 +203,10 @@ class ExportDialog(QDialog, Ui_Dialog): self.progressBar.setValue(progress_percentage) self.label_process.setText(f"导出进度: {progress_percentage}%") + def close(self): + sys.stdout = sys.__stdout__ + del self.worker + super().close() if __name__ == '__main__': import sys diff --git a/app/ui/menu/export.py b/app/ui/menu/export.py index 84a5480..e5d6cd1 100644 --- a/app/ui/menu/export.py +++ b/app/ui/menu/export.py @@ -1,8 +1,11 @@ +import os +import sys import time from typing import List from PyQt5 import QtWidgets -from PyQt5.QtCore import QTimer, QThread, pyqtSignal +from PyQt5.QtCore import QTimer, QThread, pyqtSignal, QObject +from PyQt5.QtGui import QTextCursor from PyQt5.QtWidgets import QApplication, QDialog, QCheckBox, QMessageBox, QCalendarWidget from app.DataBase import micro_msg_db, misc_db @@ -41,6 +44,13 @@ QPushButton:hover { """ +class EmittingStr(QObject): + textWritten = pyqtSignal(str) # 定义一个发送str的信号 + + def write(self, text): + self.textWritten.emit(str(text)) + + class ExportDialog(QDialog, Ui_Dialog): def __init__(self, contact=None, title="选择导出的类型", file_type="html", parent=None): super(ExportDialog, self).__init__(parent) @@ -52,6 +62,11 @@ class ExportDialog(QDialog, Ui_Dialog): self.select_all_flag = False self.btn_start.clicked.connect(self.export_data) self.comboBox_time.activated.connect(self.set_export_date) + # 下面将输出重定向到textBrowser中 + sys.stdout = EmittingStr(textWritten=self.outputWritten) + sys.stderr = EmittingStr(textWritten=self.outputWritten) + scroll_bar = ScrollBar() + self.textBrowser.setVerticalScrollBar(scroll_bar) self.export_choices = {"文本": True, "图片": True, "语音": False, "视频": False, "表情包": False, '音乐与音频': False, '分享卡片': False, '文件': False, '拍一拍等系统消息': True} # 定义导出的数据类型,默认全部选择 @@ -121,6 +136,13 @@ class ExportDialog(QDialog, Ui_Dialog): self.time_range = time_range self.comboBox_time.setCurrentIndex(2) + def outputWritten(self, text): + cursor = self.textBrowser.textCursor() + cursor.movePosition(QTextCursor.End) + cursor.insertText(text) + self.textBrowser.setTextCursor(cursor) + self.textBrowser.ensureCursorVisible() + def export_data(self): self.btn_start.setEnabled(False) # 在这里获取用户选择的导出数据类型 @@ -194,12 +216,19 @@ class ExportDialog(QDialog, Ui_Dialog): reply = QMessageBox(self) reply.setIcon(QMessageBox.Information) reply.setWindowTitle('OK') - reply.setText(f"导出聊天记录成功\n在./data/目录下(跟exe文件在一起)") + reply.setText(f"导出聊天记录成功\n在./data/目录下(跟exe文件在一起)\n{os.getcwd()}\\data\\") reply.addButton("确认", QMessageBox.AcceptRole) reply.addButton("取消", QMessageBox.RejectRole) api = reply.exec_() + # 在任务完成时重置sys.stdout + sys.stdout = sys.__stdout__ self.accept() + def close(self): + sys.stdout = sys.__stdout__ + del self.worker + super().close() + def show_contact(self, contact): # return # print(contact.remark) diff --git a/app/ui/menu/exportUi.py b/app/ui/menu/exportUi.py index d2a8a2c..15f1381 100644 --- a/app/ui/menu/exportUi.py +++ b/app/ui/menu/exportUi.py @@ -75,18 +75,27 @@ class Ui_Dialog(object): self.horizontalLayout_2.setStretch(1, 1) self.horizontalLayout_2.setStretch(2, 5) self.verticalLayout_3.addLayout(self.horizontalLayout_2) + self.textBrowser = QtWidgets.QTextBrowser(Dialog) + self.textBrowser.setObjectName("textBrowser") + self.verticalLayout_3.addWidget(self.textBrowser) self.progressBar = QtWidgets.QProgressBar(Dialog) self.progressBar.setProperty("value", 24) self.progressBar.setObjectName("progressBar") self.verticalLayout_3.addWidget(self.progressBar) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.label_process = QtWidgets.QLabel(Dialog) self.label_process.setText("") self.label_process.setObjectName("label_process") - self.verticalLayout_3.addWidget(self.label_process) + self.horizontalLayout_4.addWidget(self.label_process) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.horizontalLayout_4.addLayout(self.horizontalLayout_5) self.label_time = QtWidgets.QLabel(Dialog) self.label_time.setText("") self.label_time.setObjectName("label_time") - self.verticalLayout_3.addWidget(self.label_time) + self.horizontalLayout_4.addWidget(self.label_time) + self.verticalLayout_3.addLayout(self.horizontalLayout_4) self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) diff --git a/app/util/emoji.py b/app/util/emoji.py index dfb276d..3dd70e7 100644 --- a/app/util/emoji.py +++ b/app/util/emoji.py @@ -17,7 +17,8 @@ from PyQt5.QtGui import QPixmap import requests from app.log import log, logger - +lock = threading.Lock() +db_path = "./app/Database/Msg/Emotion.db" root_path = './data/emoji/' if not os.path.exists('./data'): os.mkdir('./data') @@ -46,11 +47,7 @@ def get_image_format(header): @log def parser_xml(xml_string): assert type(xml_string) == str - # Parse the XML string - try: - root = ET.fromstring(xml_string) - except: - root = ET.fromstring(xml_string.replace("&", "&")) + root = ET.fromstring(xml_string) emoji = root.find('./emoji') # Accessing attributes of the 'emoji' element fromusername = emoji.get('fromusername') @@ -71,11 +68,18 @@ def parser_xml(xml_string): 'md5': (md5 if md5 else androidmd5).lower(), } +def singleton(cls): + _instance = {} -lock = threading.Lock() -db_path = "./app/Database/Msg/Emotion.db" + def inner(): + if cls not in _instance: + _instance[cls] = cls() + return _instance[cls] + return inner +# 一定要保证只有一个实例对象 +@singleton class Emotion: def __init__(self): self.DB = None @@ -123,10 +127,8 @@ class Emotion: where md5 = ? """ self.cursor.execute(sql, [md5]) - try: - return self.cursor.fetchone()[0] - except: - return "" + res = self.cursor.fetchone() + return res[0] if res else '' finally: lock.release() @@ -156,7 +158,6 @@ class Emotion: return "" finally: lock.release() - def close(self): if self.open_flag: try: