diff --git a/app/DataBase/config.txt b/app/DataBase/config.txt deleted file mode 100644 index 1a2ee2e..0000000 --- a/app/DataBase/config.txt +++ /dev/null @@ -1,7 +0,0 @@ - - PRAGMA key = '10f35f1'; - PRAGMA cipher_migrate; - ATTACH DATABASE './app/DataBase/Msg.db' AS Msg KEY ''; - SELECT sqlcipher_export('Msg'); - DETACH DATABASE Msg; - \ No newline at end of file diff --git a/app/DataBase/data.py b/app/DataBase/data.py deleted file mode 100644 index df77120..0000000 --- a/app/DataBase/data.py +++ /dev/null @@ -1,584 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : data.py -@Author : Shuaikang Zhou -@Time : 2023/1/5 0:11 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" -import hashlib -import os -import sqlite3 -import threading -import time - -import requests - -DB = None -cursor = None -lock = threading.Lock() -Type = { - 1: '文本内容', - 2: '位置信息', - 3: '图片及视频', - 34: '语音消息', - 42: '名片(公众号名片)', - 43: '图片及视频', - 47: '表情包', - 48: '定位信息', - 49: '小程序链接', - 10000: '撤回消息提醒', - 1048625: '照片', - 16777265: '链接', - 285212721: '文件', - 419430449: '微信转账', - 436207665: '微信红包', - 469762097: '微信红包', - 11879048186: '位置共享', -} - -Type0 = { - '1': '文字', - '3': '图片', - '43': '视频', - '-1879048185': '微信运动排行榜', - '5': '', - '47': '表情包', - '268445456': '撤回的消息', - '34': '语音', - '419430449': '转账', - '50': '语音电话', - '100001': '领取红包', - '10000': '消息已发出,但被对方拒收了。', - '822083633': '回复消息', - '922746929': '拍一拍', - '1090519089': '发送文件', - '318767153': '付款成功', - '436207665': '发红包', -} - - -def mkdir(path): - path = path.strip() - path = path.rstrip("\\") - if os.path.exists(path): - return False - os.makedirs(path) - return True - - -root_path = os.path.abspath('.') -mkdir(os.path.abspath('.') + '/app/DataBase') -mkdir(os.path.abspath('.') + '/app/data/emoji') -if os.path.exists('./app/DataBase/Msg.db'): - DB = sqlite3.connect("./app/DataBase/Msg.db", check_same_thread=False) - # '''创建游标''' - cursor = DB.cursor() -if os.path.exists('./Msg.db'): - DB = sqlite3.connect("./Msg.db", check_same_thread=False) - # '''创建游标''' - cursor = DB.cursor() - - -def is_db_exist() -> bool: - """ - 判断数据库是否正常使用 - """ - global DB - global cursor - if DB and cursor: - try: - sql = 'select * from userinfo where id=2' - cursor.execute(sql) - result = cursor.fetchone() - if result[2]: - return True - else: - return False - except Exception as e: - return False - return False - - -def init_database(): - global DB - global cursor - if os.path.exists('./app/DataBase/Msg.db'): - DB = sqlite3.connect("./app/DataBase/Msg.db", check_same_thread=False) - # '''创建游标''' - cursor = DB.cursor() - if os.path.exists('./Msg.db'): - DB = sqlite3.connect("./Msg.db", check_same_thread=False) - # '''创建游标''' - cursor = DB.cursor() - - -def decrypt(db, key): - if not key: - print('缺少数据库密钥') - return False - if not db: - print('没有数据库文件') - return False - if is_db_exist(): - print('/app/DataBase/Msg.db 已经存在') - return True - cmd = './sqlcipher-3.0.1/bin/sqlcipher-shell32.exe' - param = f""" - PRAGMA key = '{key}'; - PRAGMA cipher_migrate; - ATTACH DATABASE './app/DataBase/Msg.db' AS Msg KEY ''; - SELECT sqlcipher_export('Msg'); - DETACH DATABASE Msg; - """ - with open('./app/data/config.txt', 'w') as f: - f.write(param) - p = os.system(f"{os.path.abspath('.')}{cmd} {db} < ./app/data/config.txt") - global DB - global cursor - DB = sqlite3.connect("./app/DataBase/Msg.db", check_same_thread=False) - # '''创建游标''' - cursor = DB.cursor() - - -def get_myinfo(): - sql = 'select * from userinfo where id=2' - cursor.execute(sql) - result = cursor.fetchone() - return result[2] - - -def get_contacts(): - sql = 'select * from rcontact' - cursor.execute(sql) - result = cursor.fetchall() - return result - - -def get_rconversation(): - sql = ''' - select msgCount,username,unReadCount,chatmode,status,isSend,conversationTime,msgType,digest,digestUser,hasTrunc,attrflag - from rconversation - where chatmode=1 or chatmode=0 and (msgType='1' or msgType='3' or msgType='47') - order by msgCount desc - ''' - '''order by conversationTime desc''' - cursor.execute(sql) - result = cursor.fetchall() - return result - - -def timestamp2str(timestamp): - # t2 = 1586102400 - s_l = time.localtime(timestamp / 1000) - ts = time.strftime("%Y/%m/%d", s_l) - # print(ts) - return ts - - -def get_conRemark(username): - try: - lock.acquire(True) - sql = 'select conRemark,nickname from rcontact where username=?' - cursor.execute(sql, [username]) - result = cursor.fetchone() - if result: - if result[0]: - return result[0] - else: - return result[1] - except: - time.sleep(0.1) - sql = 'select conRemark,nickname from rcontact where username=?' - cursor.execute(sql, [username]) - result = cursor.fetchone() - if result: - if result[0]: - return result[0] - else: - return result[1] - finally: - lock.release() - - return False - - -def get_nickname(username): - sql = 'select nickname,alias from rcontact where username=?' - cursor.execute(sql, [username]) - result = cursor.fetchone() - return result - - -def avatar_md5(wxid): - m = hashlib.md5() - # 参数必须是byte类型,否则报Unicode-objects must be encoded before hashing错误 - m.update(bytes(wxid.encode('utf-8'))) - return m.hexdigest() - - -def get_avator(wxid): - if wxid == None: - return os.path.join(root_path, '/app/data/icons/default_avatar.svg') - wxid = str(wxid) - avatar = avatar_md5(wxid) - path = os.path.join(root_path, 'app', 'data', 'avatar', avatar[:2], avatar[2:4]) - # avatar_path + avatar[:2] + '/' + avatar[2:4] - for root, dirs, files in os.walk(path): - for file in files: - if avatar in file: - avatar = file - break - return os.path.join(path, avatar) - # return f'''{path}/{avatar}''' - # return f'''{path}/user_{avatar}.png''' - - -def get_message(wxid, num): - sql = ''' - select * from message - where talker = ? - order by createTime desc - limit ?,100 - ''' - cursor.execute(sql, [wxid, num * 100]) - return cursor.fetchall() - - -def get_text_by_num(wxid, num): - sql = ''' - SELECT content,strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as days - from message - where talker = ? and type=1 - order by days - ''' - '''group by days''' - cursor.execute(sql, [wxid]) - return cursor.fetchall() - - -def search_send_message(start_time, end_time): - start_time = '2022-1-1 00:00:00' - end_time = '2023-1-1 00:00:00' - start = time.mktime(time.strptime(start_time, '%Y-%m-%d %H:%M:%S')) - end = time.mktime(time.strptime(end_time, '%Y-%m-%d %H:%M:%S')) - sql = ''' - select count(*) from message - where createTime >? and createTime < ? and isSend=0 and talker like '%wxid%'; - ''' - cursor.execute(sql, [start * 1000, end * 1000]) - return cursor.fetchone() - - -def clearImagePath(imgpath): - path = imgpath.split('/') - newPath = '/'.join(path[:-1]) + '/' + path[-1][3:] + '.jpg' - if os.path.exists(newPath): - return newPath - newPath = '/'.join(path[:-1]) + '/' + path[-1][3:] + '.png' - if os.path.exists(newPath): - return newPath - newPath = '/'.join(path[:-1]) + '/' + path[-1] + 'hd' - if os.path.exists(newPath): - return newPath - return imgpath - - -def get_all_message(wxid): - sql = ''' - select * from message - where talker = ? - order by createTime - ''' - cursor.execute(sql, [wxid]) - return cursor.fetchall() - - -def get_emoji(imgPath): - newPath = f"{os.path.abspath('.')}/app/data/emoji/{imgPath}" - if os.path.exists(newPath): - return newPath - else: - sql = ''' - select cdnUrl - from EmojiInfo - where md5=? - ''' - try: - cursor.execute(sql, [imgPath]) - result = cursor.fetchone() - download_emoji(newPath, result[0]) - except sqlite3.ProgrammingError as e: - print(e, imgPath) - return False - return False - - -def download_emoji(imgPath, url): - if not url: - return False - try: - resp = requests.get(url) - with open(imgPath, 'wb') as f: - f.write(resp.content) - except: - return False - return imgPath - - -def get_chatroom_displayname(chatroom, username): - sql = 'select memberlist,displayname from chatroom where chatroomname =?' - cursor.execute(sql, [chatroom]) - result = cursor.fetchone() - wxids = result[0].split(';') - names = result[1].split('、') - id = wxids.index(username) - print(result[0]) - print(wxids) - for i in wxids: - print(get_conRemark(i)) - return names[id] - - -def get_contacts(): - sql = ''' - select * from rcontact - where type=3 or type = 333 - ''' - cursor.execute(sql) - result = cursor.fetchall() - return result - - -def send_nums(username): - sql = ''' - select count(*) from message - where talker = ? and isSend=1 - ''' - cursor.execute(sql, [username]) - return cursor.fetchone()[0] - - -def recv_nums(username): - sql = ''' - select count(*) from message - where talker = ? and isSend=0 - ''' - cursor.execute(sql, [username]) - return cursor.fetchone()[0] - - -def get_imgPath(imgPath): - sql = ''' - select bigImgPath from ImgInfo2 - where thumbImgPath = ?; - ''' - cursor.execute(sql, [imgPath]) - return cursor.fetchone()[0] - - -def get_text(username): - sql = ''' - select content from message - where talker=? and type=1 - ''' - cursor.execute(sql, [username]) - result = cursor.fetchall() - return ''.join(map(lambda x: x[0], result)) - - -def msg_type_num(username): - sql = ''' - select type,count(*) from message - where talker = ? - group by type - ''' - cursor.execute(sql, [username]) - return cursor.fetchall() - - -def get_msg_start_time(username): - sql = ''' - select strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') from message - where talker = ? - order by msgId - limit 1 - ''' - cursor.execute(sql, [username]) - return cursor.fetchone()[0] - - -def get_msg_end_time(username): - sql = ''' - select strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') from message - where talker = ? - order by msgId desc - limit 1 - ''' - cursor.execute(sql, [username]) - try: - return cursor.fetchone()[0] - except: - return None - - -def get_msg_by_days(username, year='2022'): - sql = ''' - SELECT strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as days,count(msgId) - from message - where talker = ? and strftime('%Y',createTime/1000,'unixepoch','localtime') = ? - group by days - ''' - cursor.execute(sql, [username, year]) - result = cursor.fetchall() - return result - - -def get_msg_by_day(username): - sql = ''' - SELECT strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as days,count(msgId) - from message - where talker = ? - group by days - ''' - cursor.execute(sql, [username]) - result = cursor.fetchall() - return result - - -def get_msg_by_month(username, year='2022'): - sql = ''' - SELECT strftime('%Y-%m',createTime/1000,'unixepoch','localtime') as days,count(msgId) - from message - where talker = ? and strftime('%Y',createTime/1000,'unixepoch','localtime') = ? - group by days - ''' - cursor.execute(sql, [username, year]) - result = cursor.fetchall() - return result - - -def get_msg_by_hour(username): - sql = ''' - SELECT strftime('%H:00',createTime/1000,'unixepoch','localtime') as days,count(msgId) - from message - where talker = ? - group by days - ''' - cursor.execute(sql, [username]) - result = cursor.fetchall() - return result - - -def get_sport(): - sql = ''' - SELECT createTime,content,strftime('%Y-%m-%d',createTime/1000,'unixepoch','localtime') as months - from message - where talker = 'gh_43f2581f6fd6' - ''' - cursor.execute(sql) - result = cursor.fetchall() - return result - - -def get_myInfo(): - sql = ''' - select value from userinfo - where id = 4 - ''' - cursor.execute(sql) - name = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 5 - ''' - cursor.execute(sql) - email = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 6 - ''' - cursor.execute(sql) - tel = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 9 - ''' - cursor.execute(sql) - QQ = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 42 - ''' - cursor.execute(sql) - wxid = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 12291 - ''' - cursor.execute(sql) - signature = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 12292 - ''' - cursor.execute(sql) - city = cursor.fetchone()[0] - sql = ''' - select value from userinfo - where id = 12293 - ''' - cursor.execute(sql) - province = cursor.fetchone()[0] - return { - 'name': name, - 'username': wxid, - 'city': city, - 'province': province, - 'email': email, - 'QQ': QQ, - 'signature': signature, - 'tel': tel, - } - - -def search_Latest_chat_time(wxid): - # 查找聊天最晚的消息 - sql = ''' - SELECT strftime('%H:%M:%S',createTime/1000,'unixepoch','localtime') as t,content,strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') - from message - where talker = ? and t>'00:00:00' and t<'05:00:00' and type=1 - order by t desc - ''' - cursor.execute(sql, [wxid]) - result = cursor.fetchall() - return result - - -def search_emoji(wxid): - # 查找聊天最晚的消息 - sql = ''' - SELECT imgPath,strftime('%Y-%m-%d %H:%M:%S',createTime/1000,'unixepoch','localtime') as t,count(imgPath) - from message - where talker = ? and t>'2022-01-01 00:00:00' and t<'2022-12-31 00::00:00' and type=47 and isSend=0 - group by content - order by count(imgPath) desc - ''' - cursor.execute(sql, [wxid]) - result = cursor.fetchall() - return result - - -if __name__ == '__main__': - wxid = 'wxid_8piw6sb4hvfm22' - # wxid = 'wxid_wt2vsktnu4z022' - # emotion_analysis(wxid) - t = search_Latest_chat_time(wxid) - print(t[0]) - d = get_msg_by_days(wxid) - print(len(d)) - e = search_emoji(wxid) - print(e) - p = get_emoji(e[1][0]) - print(p) diff --git a/app/DataBase/media_msg.py b/app/DataBase/media_msg.py index 8e07183..46ba2e7 100644 --- a/app/DataBase/media_msg.py +++ b/app/DataBase/media_msg.py @@ -1,4 +1,6 @@ import os.path +import subprocess +import sys from os import system import sqlite3 import threading @@ -8,7 +10,14 @@ from pilk import decode lock = threading.Lock() db_path = "./app/Database/Msg/MediaMSG.db" +def get_ffmpeg_path(): + # 获取打包后的资源目录 + resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) + # 构建 FFmpeg 可执行文件的路径 + ffmpeg_path = os.path.join(resource_dir, 'app', 'resources', 'ffmpeg.exe') + + return ffmpeg_path def singleton(cls): _instance = {} @@ -64,8 +73,18 @@ class MediaMsg: f.write(buf) # open(silk_path, "wb").write() decode(silk_path, pcm_path, 44100) - cmd = f'''{os.path.join(os.getcwd(),'app','resources','ffmpeg.exe')} -loglevel quiet -y -f s16le -i {pcm_path} -ar 44100 -ac 1 {mp3_path}''' - system(cmd) + try: + # 调用系统上的 ffmpeg 可执行文件 + # 获取 FFmpeg 可执行文件的路径 + ffmpeg_path = get_ffmpeg_path() + # 调用 FFmpeg + # subprocess.run([ffmpeg_path, f'''-loglevel quiet -y -f s16le -i {pcm_path} -ar 44100 -ac 1 {mp3_path}'''], check=True) + cmd = f'''{get_ffmpeg_path()} -loglevel quiet -y -f s16le -i {pcm_path} -ar 44100 -ac 1 {mp3_path}''' + system(cmd) + except subprocess.CalledProcessError as e: + print(f"Error: {e}") + cmd = f'''{os.path.join(os.getcwd(),'app','resources','ffmpeg.exe')} -loglevel quiet -y -f s16le -i {pcm_path} -ar 44100 -ac 1 {mp3_path}''' + system(cmd) system(f'del {silk_path}') system(f'del {pcm_path}') print(mp3_path) diff --git a/app/DataBase/output_pc.py b/app/DataBase/output_pc.py index a509740..cee0ae5 100644 --- a/app/DataBase/output_pc.py +++ b/app/DataBase/output_pc.py @@ -253,6 +253,11 @@ class ChildThread(QThread): doc.write( f'''{{ type:34, text:'{audio_path}',is_send:{is_send},avatar_path:'{avatar}',voice_to_text:'{voice_to_text}'}},''' ) + if self.output_type == Output.TXT: + name = '你' if is_send else self.contact.remark + doc.write( + f'''{str_time} {name}\n[语音]\n\n''' + ) def emoji(self, doc, message): @@ -320,11 +325,6 @@ class ChildThread(QThread): elif self.output_type==Output.TXT: name = '你' if is_send else self.contact.remark if refer_msg: - referText = f"{refer_msg.get('displayname')}:{refer_msg.get('content')}" - emojiText = findall(r"(\[.+?\])", referText) - for emoji_text in emojiText: - if emoji_text in emoji: - referText = referText.replace(emoji_text, emoji[emoji_text]) doc.write( f'''{str_time} {name}\n{content.get('title')}\n引用:{refer_msg.get('displayname')}:{refer_msg.get('content')}\n\n''' ) @@ -469,6 +469,8 @@ class ChildThread(QThread): self.text(f, message) elif type_ == 3 and self.message_types.get(type_): self.image(f, message) + elif type_ == 34 and self.message_types.get(type_): + self.audio(f, message) elif type_ == 43 and self.message_types.get(type_): self.video(f, message) elif type_ == 47 and self.message_types.get(type_): diff --git a/app/ImageBox/__init__.py b/app/ImageBox/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/ImageBox/config.py b/app/ImageBox/config.py deleted file mode 100644 index cdebb51..0000000 --- a/app/ImageBox/config.py +++ /dev/null @@ -1,6 +0,0 @@ -import sys -from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog -from PyQt5.Qt import QPixmap, QPoint, Qt, QPainter, QIcon -from PyQt5.QtCore import QSize -from PyQt5 import QtCore, QtGui, QtWidgets -from PyQt5.QtGui import QImageReader diff --git a/app/ImageBox/icons/zoom_in.jpg b/app/ImageBox/icons/zoom_in.jpg deleted file mode 100644 index 3d8378b..0000000 Binary files a/app/ImageBox/icons/zoom_in.jpg and /dev/null differ diff --git a/app/ImageBox/icons/zoom_out.jpg b/app/ImageBox/icons/zoom_out.jpg deleted file mode 100644 index fde5376..0000000 Binary files a/app/ImageBox/icons/zoom_out.jpg and /dev/null differ diff --git a/app/ImageBox/images/wallhaven-748705.jpg b/app/ImageBox/images/wallhaven-748705.jpg deleted file mode 100644 index 15b690a..0000000 Binary files a/app/ImageBox/images/wallhaven-748705.jpg and /dev/null differ diff --git a/app/ImageBox/images/wallhaven-753155.jpg b/app/ImageBox/images/wallhaven-753155.jpg deleted file mode 100644 index 5139dc4..0000000 Binary files a/app/ImageBox/images/wallhaven-753155.jpg and /dev/null differ diff --git a/app/ImageBox/images/wallhaven-vml6em.jpg b/app/ImageBox/images/wallhaven-vml6em.jpg deleted file mode 100644 index 233957f..0000000 Binary files a/app/ImageBox/images/wallhaven-vml6em.jpg and /dev/null differ diff --git a/app/ImageBox/run.py b/app/ImageBox/run.py deleted file mode 100644 index a3671c7..0000000 --- a/app/ImageBox/run.py +++ /dev/null @@ -1,9 +0,0 @@ -from ui import MainDemo -from config import * - - -if __name__ == '__main__': - app = QApplication(sys.argv) - box = MainDemo() - box.show() - app.exec_() diff --git a/app/ImageBox/ui.py b/app/ImageBox/ui.py deleted file mode 100644 index c78039e..0000000 --- a/app/ImageBox/ui.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- -from .config import * - - -class ImageBox(QWidget): - def __init__(self): - super(ImageBox, self).__init__() - self.img = None - self.scaled_img = None - self.point = QPoint(100, 100) - self.start_pos = None - self.end_pos = None - self.left_click = False - self.scale = 1 - - def init_ui(self): - self.setWindowTitle("ImageBox") - - def set_image(self, img_path): - """ - open image file - :param img_path: image file path - :return: - """ - # img = QImageReader(img_path) - # img.setScaledSize(QSize(self.size().width(), self.size().height())) - # img = img.read() - self.img = QPixmap(img_path) - # print(self.img.size(),self.img.size().width(),self.img.size().height()) - self.scaled_img = self.img - # print(img_size) - img_size = self.scaled_img.size() - x = min(500, max((1000 - img_size.width()) // 2, 0)) - y = min(300, max((600 - img_size.height()) // 2 - 60, 0)) - # print(x,y) - self.point = QPoint(x, y) - - def paintEvent(self, e): - """ - receive paint events - :param e: QPaintEvent - :return: - """ - if self.scaled_img: - painter = QPainter() - painter.begin(self) - painter.scale(self.scale, self.scale) - painter.drawPixmap(self.point, self.scaled_img) - painter.end() - - def wheelEvent(self, event): - angle = event.angleDelta() / 8 # 返回QPoint对象,为滚轮转过的数值,单位为1/8度 - angleY = angle.y() - # 获取当前鼠标相对于view的位置 - if angleY > 0: - self.scale *= 1.1 - else: # 滚轮下滚 - self.scale *= 0.9 - self.adjustSize() - self.update() - - def mouseMoveEvent(self, e): - """ - mouse move events for the widget - :param e: QMouseEvent - :return: - """ - if self.left_click: - self.end_pos = e.pos() - self.start_pos - self.point = self.point + self.end_pos - self.start_pos = e.pos() - self.repaint() - - def mousePressEvent(self, e): - """ - mouse press events for the widget - :param e: QMouseEvent - :return: - """ - if e.button() == Qt.LeftButton: - self.left_click = True - self.start_pos = e.pos() - - def mouseReleaseEvent(self, e): - """ - mouse release events for the widget - :param e: QMouseEvent - :return: - """ - if e.button() == Qt.LeftButton: - self.left_click = False - - -class MainDemo(QWidget): - def __init__(self): - super(MainDemo, self).__init__() - - self.setWindowTitle("Image Viewer") - self.setFixedSize(1000, 600) - self.setWindowIcon(QIcon('./app/data/icons/logo.svg')) - self.zoom_in = QPushButton("") - self.zoom_in.clicked.connect(self.large_click) - self.zoom_in.setFixedSize(30, 30) - in_icon = QIcon("./app/ImageBox/icons/zoom_in.jpg") - self.zoom_in.setIcon(in_icon) - self.zoom_in.setIconSize(QSize(30, 30)) - - self.zoom_out = QPushButton("") - self.zoom_out.clicked.connect(self.small_click) - self.zoom_out.setFixedSize(30, 30) - out_icon = QIcon("./app/ImageBox/icons/zoom_out.jpg") - self.zoom_out.setIcon(out_icon) - self.zoom_out.setIconSize(QSize(30, 30)) - - w = QWidget(self) - layout = QHBoxLayout() - layout.addWidget(self.zoom_in) - layout.addWidget(self.zoom_out) - layout.setAlignment(Qt.AlignLeft) - w.setLayout(layout) - w.setFixedSize(550, 50) - - self.box = ImageBox() - self.box.resize(500, 300) - - layout = QVBoxLayout() - layout.addWidget(w) - layout.addWidget(self.box) - self.setLayout(layout) - - def open_image(self): - """ - select image file and open it - :return: - """ - img_name, _ = QFileDialog.getOpenFileName(self, "Open Image File", "*.jpg;;*.png;;*.jpeg") - self.box.set_image(img_name) - - def large_click(self): - """ - used to enlarge image - :return: - """ - if self.box.scale < 2: - self.box.scale += 0.1 - self.box.adjustSize() - self.update() - - def small_click(self): - """ - used to reduce image - :return: - """ - if self.box.scale > 0.1: - self.box.scale -= 0.2 - self.box.adjustSize() - self.update() diff --git a/app/Ui/Icon.py b/app/Ui/Icon.py deleted file mode 100644 index 808fae3..0000000 --- a/app/Ui/Icon.py +++ /dev/null @@ -1,18 +0,0 @@ -from PyQt5.QtGui import QIcon - - -class Icon: - Default_avatar_path = './app/data/icons/default_avatar.svg' - MainWindow_Icon = QIcon('./app/data/icons/logo.svg') - Default_avatar = QIcon(Default_avatar_path) - Output = QIcon('./app/data/icons/output.svg') - Back = QIcon('./app/data/icons/back.svg') - ToDocx = QIcon('app/data/icons/word.svg') - ToCSV = QIcon('app/data/icons/csv.svg') - ToHTML = QIcon('app/data/icons/html.svg') - Chat_Icon = QIcon('./app/data/icons/chat.svg') - Contact_Icon = QIcon('./app/data/icons/contact.svg') - MyInfo_Icon = QIcon('./app/data/icons/myinfo.svg') - Annual_Report_Icon = QIcon('./app/data/icons/annual_report.svg') - Analysis_Icon = QIcon('./app/data/icons/analysis.svg') - Emotion_Icon = QIcon('./app/data/icons/emotion.svg') diff --git a/app/Ui/__init__.py b/app/Ui/__init__.py deleted file mode 100644 index 730bbfa..0000000 --- a/app/Ui/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : __init__.py.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 14:19 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" -# from .ICON import Icon -# from .chat import chat -from app.Ui import mainview -# 文件__init__.py -# from login import login -from app.Ui.decrypt import decrypt - -__all__ = ["decrypt", 'mainview', 'chat'] diff --git a/app/Ui/chat/__init__.py b/app/Ui/chat/__init__.py deleted file mode 100644 index fa6c268..0000000 --- a/app/Ui/chat/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : __init__.py.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 20:33 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" diff --git a/app/Ui/chat/chat.py b/app/Ui/chat/chat.py deleted file mode 100644 index e913a63..0000000 --- a/app/Ui/chat/chat.py +++ /dev/null @@ -1,499 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : chat.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 17:07 -@IDE : Pycharm -@Version : Python3.10 -@comment : 聊天窗口 -""" -import time -import traceback -from typing import Dict - -import xmltodict -from PIL import Image -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * - -from app.components.Button_Contact import ContactUi -from app.log import logger, log -from .chatUi import * -from ...DataBase import data -from ...ImageBox.ui import MainDemo - - -class ChatController(QWidget, Ui_Form): - exitSignal = pyqtSignal() - urlSignal = pyqtSignal(QUrl) - - # username = '' - - def __init__(self, me, parent=None): - super(ChatController, self).__init__(parent) - self.chatroomFlag = None - self.ta_avatar = None - self.setupUi(self) - self.message = self.message_2 - self.frame = self.frame_2 - self.scrollAreaWidgetContents = self.scrollAreaWidgetContents_2 - self.label_remark = self.label_remark_2 - self.textEdit = self.textEdit_2 - self.setWindowTitle('WeChat') - self.setWindowIcon(QIcon('./app/data/icon.png')) - self.initui() - self.Me = me - - self.Thread = ChatMsg(self.Me.wxid, None) - self.Thread.isSend_signal.connect(self.showMsg) - self.Thread.okSignal.connect(self.setScrollBarPos) - - self.contacts: Dict[str, ContactUi] = {} - self.last_btn = None - self.chat_flag = True - # self.showChat() - - self.message.verticalScrollBar().valueChanged.connect(self.textbrower_verticalScrollBar) - self.show_flag = False - self.ta_username = None - self.last_pos = 0 - self.last_msg_time = 0 # 上次信息的时间 - self.last_talkerId = None - self.now_talkerId = None - self.showChat() - - def initui(self): - self.qurl = QUrl('baidu.com') - # self.urlSignal.connect(self.hyperlink) - self.message.setOpenLinks(False) - self.message.setOpenExternalLinks(False) - # self.message.anchorClicked(self.hyperlink()) - self.message.anchorClicked.connect(self.hyperlink) - self.btn_sendMsg_2.setToolTip('按Enter键发送,按Ctrl+Enter键换行') - - def showChat(self): - """ - 显示联系人界面 - :return: - """ - if self.show_flag: - return - self.show_flag = True - rconversations = data.get_rconversation() - # max_hight = max(len(rconversations) * 80, 680) - max_hight = max(len(rconversations) * 80, self.size().height()) - - self.scrollAreaWidgetContents.setGeometry( - QtCore.QRect(0, 0, 300, max_hight)) - for i in range(len(rconversations)): - rconversation = rconversations[i] - username = rconversation[1] - # print('联系人:', i, rconversation) - pushButton_2 = ContactUi(self.scrollAreaWidgetContents, i, rconversation) - pushButton_2.setGeometry(QtCore.QRect(0, 80 * i, 300, 80)) - pushButton_2.setLayoutDirection(QtCore.Qt.LeftToRight) - pushButton_2.clicked.connect(pushButton_2.show_msg) - pushButton_2.usernameSingal.connect(self.Chat) - self.contacts[username] = pushButton_2 - - def Chat(self, talkerId): - """ - 聊天界面 点击联系人头像时候显示聊天数据 - :param talkerId: - :return: - """ - self.now_talkerId = talkerId - # 把当前按钮设置为灰色 - if self.last_talkerId and self.last_talkerId != talkerId: - print('对方账号:', self.last_talkerId) - self.contacts[self.last_talkerId].setStyleSheet( - "QPushButton {background-color: rgb(220,220,220);}" - "QPushButton:hover{background-color: rgb(208,208,208);}\n" - ) - self.last_talkerId = talkerId - self.contacts[talkerId].setStyleSheet( - "QPushButton {background-color: rgb(198,198,198);}" - "QPushButton:hover{background-color: rgb(209,209,209);}\n" - ) - conRemark = self.contacts[talkerId].contact.conRemark - self.label_remark.setText(conRemark) - self.message.clear() - self.message.append(talkerId) - self.ta_username = talkerId - if '@chatroom' in talkerId: - self.chatroomFlag = True - else: - self.chatroomFlag = False - self.ta_avatar = self.contacts[talkerId].contact.avatar_path - self.textEdit.setFocus() - self.Thread.ta_u = talkerId - self.Thread.msg_id = 0 - self.Thread.start() - # 创建新的线程用于显示聊天记录 - - def closeEvent(self, a0: QtGui.QCloseEvent) -> None: - print("closed") - self.exitSignal.emit() - self.close() - - def textbrower_verticalScrollBar(self, pos): - """ - 滚动条到0之后自动更新聊天记录 - :param pos: - :return: - """ - # print(pos) - if pos > 0: - return - self.last_pos = self.message.verticalScrollBar().maximum() - self.Thread.start() - - def setScrollBarPos(self, pos): - """ - 将滚动条位置设置为上次看到的地方 - :param pos: - :return: - """ - pos = self.message.verticalScrollBar().maximum() - self.last_pos - - print(pos) - self.message.verticalScrollBar().setValue(pos) - - def check_time(self, msg_time): - """ - 判断两次聊天时间是否大于五分钟 - 超过五分钟就显示时间 - :param msg_time: - :return: - """ - dt = msg_time - self.last_msg_time - # print(msg_time) - if abs(dt // 1000) >= 300: - s_l = time.localtime(msg_time / 1000) - ts = time.strftime("%Y-%m-%d %H:%M", s_l) - html = ''' - - - - - - -
%s
''' % (ts) - # print(html) - self.last_msg_time = msg_time - self.message.insertHtml(html) - - @log - def showMsg(self, message): - """ - 显示聊天消息 - :param message: - :return: - """ - msgId = message[0] - # print(msgId, type(msgId)) - self.message.moveCursor(self.message.textCursor().Start) - ta_username = message[7] - msgType = str(message[2]) - isSend = message[4] - content = message[8] - imgPath = message[9] - msg_time = message[6] - self.check_time(msg_time) - - if msgType == '1': - # return - self.show_text(isSend, content) - elif msgType == '3': - # return - self.show_img(isSend, imgPath, content) - elif msgType == '47': - # return - self.show_emoji(isSend, imgPath, content) - elif msgType == '268445456': - self.show_recall_information(content) - elif msgType == '922746929': - self.pat_a_pat(content) - # self.message.moveCursor(self.message.textCursor().End) - - @log - def pat_a_pat(self, content): - try: - pat_data = xmltodict.parse(content) - pat_data = pat_data['msg']['appmsg']['patMsg']['records']['record'] - fromUser = pat_data['fromUser'] - pattedUser = pat_data['pattedUser'] - template = pat_data['template'] - template = ''.join(template.split('${pattedusername@textstatusicon}')) - template = ''.join(template.split('${fromusername@textstatusicon}')) - template = template.replace(f'${{{fromUser}}}', data.get_conRemark(fromUser)) - template = template.replace(f'${{{pattedUser}}}', data.get_conRemark(pattedUser)) - print(template) - except Exception as e: - print(e) - template = '糟糕!出错了。' - - html = ''' - - - - - - -
%s
''' % template - self.message.insertHtml(html) - - @log - def show_recall_information(self, content): - html = ''' - - - - - - -
%s
''' % content - self.message.insertHtml(html) - - @log - def show_emoji(self, isSend, imagePath, content): - imgPath = data.get_emoji(imagePath) - if not imgPath: - return False - try: - image = Image.open(imgPath) - except Exception as e: - logger.error(f"\nshow_emoji is error,here are details:\n{traceback.format_exc()}") - print(e) - return - imagePixmap = image.size # 宽高像素 - # 设置最大宽度 - if imagePixmap[0] < 150: - size = "" - else: - size = '''height="150" width="150"''' - html = ''' - - - - '''.format(imgPath, size) - style = 'vertical-align: top' - if isSend: - self.right(html, style=style) - else: - if self.chatroomFlag: - username = content.split(':')[0] - self.chatroom_left(html, username=username, style=style) - self.left(html, style=style) - - @log - def show_img(self, isSend, imgPath, content): - 'THUMBNAIL_DIRPATH://th_29cd0f0ca87652943be9ede365aabeaa' - # imgPath = imgPath.split('th_')[1] - imgPath = data.get_imgPath(imgPath) - imgPath = f'./app/data/image2/{imgPath[0:2]}/{imgPath[2:4]}/{imgPath}' - html = ''' - - - - - - ''' % (imgPath, imgPath) - style = 'vertical-align: top' - if isSend: - self.right(html, style=style) - else: - if self.chatroomFlag: - username = content.split(':')[0] - self.chatroom_left(html, username=username, style=style) - else: - self.left(html, style=style) - - @log - def show_text(self, isSend, content): - if isSend: - html = ''' -  %s  - ''' % content - self.right(html) - else: - if self.chatroomFlag: - # print(content) - 'wxid_mv4jjhc0w0w521:' - username = content.split(':')[0] - msg = ''.join(content.split(':')[1:]) - # avatar = data.get_avator(username) - html = ''' - - %s - - ''' % (msg) - # self.left(html, avatar=avatar) - self.chatroom_left(html, username=username) - else: - html = ''' -  %s  - ''' % (content) - self.left(html) - - def hyperlink(self, url: QUrl): - """ - 超链接,点击之后放大显示图片 - :param url: - :return: - """ - path = data.clearImagePath(url.path()) - print(url.path(), path) - self.imagebox = MainDemo() - self.imagebox.show() - self.imagebox.box.set_image(path) - - def right(self, content, style='vertical-align: middle'): - html = ''' -
- - - - %s - - - - - -
-
- ''' % (style, content, self.Me.avatar_path) - # print('总的HTML') - # print(html) - self.message.insertHtml(html) - - def left(self, content, avatar=None, style='vertical-align: middle'): - if not avatar: - avatar = self.ta_avatar - if self.chatroomFlag == 5: - try: - username, msg = content.split('\n') - avatar = data.get_avator(username) - html = ''' -
- - - - - - - - - - - - %s - - -
-
- ''' % (style, avatar, msg) - except: - return - else: - html = ''' -
- - - - - - - %s - - -
-
- ''' % (style, avatar, content) - self.message.insertHtml(html) - - def chatroom_left(self, content, username, style='vertical-align: middle'): - # if username: - avatar = data.get_avator(username) - # conRemark = data.get_conRemark(username) - conRemark = data.get_conRemark(username) - html = ''' -
- - - - - - - - - - - - %s - - -
%s
-
- ''' % (style, avatar, conRemark, content) - self.message.insertHtml(html) - - def destroy_me(self): - """注销账户""" - pass - - -class ChatMsg(QThread): - """ - 多线程显示信息 - """ - isSend_signal = pyqtSignal(tuple) - okSignal = pyqtSignal(int) - - def __init__(self, my_u, ta_u, parent=None): - super().__init__(parent) - self.sec = 2 # 默认1000秒 - self.my_u = my_u - self.ta_u = ta_u - self.my_avatar = data.get_avator(my_u) - self.msg_id = 0 - - def run(self): - self.ta_avatar = data.get_avator(self.ta_u) - messages = data.get_message(self.ta_u, self.msg_id) - # messages.reverse() - for message in messages: - self.isSend_signal.emit(message) - self.msg_id += 1 - self.okSignal.emit(1) - - -class myTextEdit(QtWidgets.QTextEdit): # 继承 原本组件 - sendSignal = pyqtSignal(str) - - def __init__(self, parent): - QtWidgets.QTextEdit.__init__(self, parent) - self.parent = parent - _translate = QtCore.QCoreApplication.translate - self.setHtml(_translate("Dialog", - "\n" - "\n" - "


")) - - def keyPressEvent(self, event): - QtWidgets.QTextEdit.keyPressEvent(self, event) - if event.key() == Qt.Key_Return: # 如果是Enter 按钮 - modifiers = event.modifiers() - if modifiers == Qt.ControlModifier: - print('success press ctrl+enter key', self.toPlainText()) - self.append('\0') - return - self.sendSignal.emit(self.toPlainText()) - print('success press enter key', self.toPlainText()) diff --git a/app/Ui/chat/chatUi.py b/app/Ui/chat/chatUi.py deleted file mode 100644 index 6566cf6..0000000 --- a/app/Ui/chat/chatUi.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'chatUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(878, 720) - self.horizontalLayout = QtWidgets.QHBoxLayout(Form) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setSpacing(0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.scrollArea_2 = QtWidgets.QScrollArea(Form) - self.scrollArea_2.setEnabled(True) - self.scrollArea_2.setMaximumSize(QtCore.QSize(325, 150000)) - self.scrollArea_2.setAutoFillBackground(False) - self.scrollArea_2.setFrameShape(QtWidgets.QFrame.NoFrame) - self.scrollArea_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.scrollArea_2.setMidLineWidth(0) - self.scrollArea_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) - self.scrollArea_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.scrollArea_2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow) - self.scrollArea_2.setWidgetResizable(False) - self.scrollArea_2.setObjectName("scrollArea_2") - self.scrollAreaWidgetContents_2 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 300, 12000)) - self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2") - self.pushButton_3 = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2) - self.pushButton_3.setGeometry(QtCore.QRect(0, 0, 300, 80)) - self.pushButton_3.setLayoutDirection(QtCore.Qt.LeftToRight) - self.pushButton_3.setAutoFillBackground(False) - self.pushButton_3.setText("") - self.pushButton_3.setIconSize(QtCore.QSize(80, 80)) - self.pushButton_3.setObjectName("pushButton_3") - self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_2.setGeometry(QtCore.QRect(220, 10, 72, 15)) - self.label_2.setObjectName("label_2") - self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) - self.horizontalLayout.addWidget(self.scrollArea_2) - self.frame_2 = QtWidgets.QFrame(Form) - self.frame_2.setMinimumSize(QtCore.QSize(500, 500)) - self.frame_2.setStyleSheet("background-color: #F5F5F5;") - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_2.setObjectName("frame_2") - self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2) - self.verticalLayout.setContentsMargins(0, 0, 0, 0) - self.verticalLayout.setSpacing(0) - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.label_remark_2 = QtWidgets.QLabel(self.frame_2) - font = QtGui.QFont() - font.setPointSize(12) - self.label_remark_2.setFont(font) - self.label_remark_2.setText("") - self.label_remark_2.setObjectName("label_remark_2") - self.horizontalLayout_3.addWidget(self.label_remark_2) - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_3.addItem(spacerItem) - self.toolButton_2 = QtWidgets.QToolButton(self.frame_2) - self.toolButton_2.setObjectName("toolButton_2") - self.horizontalLayout_3.addWidget(self.toolButton_2) - self.verticalLayout.addLayout(self.horizontalLayout_3) - self.line_5 = QtWidgets.QFrame(self.frame_2) - self.line_5.setFrameShape(QtWidgets.QFrame.HLine) - self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_5.setObjectName("line_5") - self.verticalLayout.addWidget(self.line_5) - self.message_2 = QtWidgets.QTextBrowser(self.frame_2) - self.message_2.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - self.message_2.setStyleSheet("background-color: #F5F5F5;") - self.message_2.setObjectName("message_2") - self.verticalLayout.addWidget(self.message_2) - self.line_6 = QtWidgets.QFrame(self.frame_2) - self.line_6.setFrameShape(QtWidgets.QFrame.HLine) - self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_6.setObjectName("line_6") - self.verticalLayout.addWidget(self.line_6) - self.textEdit_2 = QtWidgets.QTextEdit(self.frame_2) - font = QtGui.QFont() - font.setPointSize(15) - self.textEdit_2.setFont(font) - self.textEdit_2.setAutoFillBackground(False) - self.textEdit_2.setStyleSheet("background-color: #F5F5F5;") - self.textEdit_2.setFrameShape(QtWidgets.QFrame.NoFrame) - self.textEdit_2.setOverwriteMode(False) - self.textEdit_2.setTabStopWidth(80) - self.textEdit_2.setAcceptRichText(True) - self.textEdit_2.setCursorWidth(1) - self.textEdit_2.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction) - self.textEdit_2.setObjectName("textEdit_2") - self.verticalLayout.addWidget(self.textEdit_2) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem1) - self.btn_sendMsg_2 = QtWidgets.QPushButton(self.frame_2) - font = QtGui.QFont() - font.setFamily("黑体") - font.setPointSize(15) - font.setBold(False) - font.setWeight(50) - self.btn_sendMsg_2.setFont(font) - self.btn_sendMsg_2.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.btn_sendMsg_2.setMouseTracking(False) - self.btn_sendMsg_2.setAutoFillBackground(False) - self.btn_sendMsg_2.setStyleSheet("QPushButton {\n" - " background-color:rgb(233,233,233);\n" - " padding: 10px;\n" - " color:rgb(5,180,104);}\n" - " QPushButton:hover{\n" - " background-color:rgb(198,198,198)}\n" - " ") - self.btn_sendMsg_2.setIconSize(QtCore.QSize(40, 40)) - self.btn_sendMsg_2.setCheckable(False) - self.btn_sendMsg_2.setAutoDefault(True) - self.btn_sendMsg_2.setObjectName("btn_sendMsg_2") - self.horizontalLayout_2.addWidget(self.btn_sendMsg_2) - self.horizontalLayout_2.setStretch(0, 7) - self.horizontalLayout_2.setStretch(1, 2) - self.verticalLayout.addLayout(self.horizontalLayout_2) - self.verticalLayout.setStretch(0, 2) - self.verticalLayout.setStretch(1, 2) - self.verticalLayout.setStretch(2, 60) - self.verticalLayout.setStretch(3, 2) - self.verticalLayout.setStretch(4, 2) - self.verticalLayout.setStretch(5, 1) - self.horizontalLayout.addWidget(self.frame_2) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.label_2.setText(_translate("Form", "TextLabel")) - self.toolButton_2.setText(_translate("Form", "...")) - self.textEdit_2.setHtml(_translate("Form", - "\n" - "\n" - "

\n" - "

\n" - "

\n" - "

")) - self.btn_sendMsg_2.setText(_translate("Form", "发送")) diff --git a/app/Ui/chat/form.py b/app/Ui/chat/form.py deleted file mode 100644 index 2172692..0000000 --- a/app/Ui/chat/form.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'form.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(878, 720) - self.horizontalLayout = QtWidgets.QHBoxLayout(Form) - self.horizontalLayout.setObjectName("horizontalLayout") - self.scrollArea_2 = QtWidgets.QScrollArea(Form) - self.scrollArea_2.setEnabled(True) - self.scrollArea_2.setMaximumSize(QtCore.QSize(325, 150000)) - self.scrollArea_2.setAutoFillBackground(False) - self.scrollArea_2.setFrameShape(QtWidgets.QFrame.WinPanel) - self.scrollArea_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.scrollArea_2.setMidLineWidth(0) - self.scrollArea_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) - self.scrollArea_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.scrollArea_2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow) - self.scrollArea_2.setWidgetResizable(False) - self.scrollArea_2.setObjectName("scrollArea_2") - self.scrollAreaWidgetContents_2 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 300, 12000)) - self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2") - self.pushButton_3 = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2) - self.pushButton_3.setGeometry(QtCore.QRect(0, 0, 300, 80)) - self.pushButton_3.setLayoutDirection(QtCore.Qt.LeftToRight) - self.pushButton_3.setAutoFillBackground(False) - self.pushButton_3.setText("") - self.pushButton_3.setIconSize(QtCore.QSize(80, 80)) - self.pushButton_3.setObjectName("pushButton_3") - self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_2.setGeometry(QtCore.QRect(220, 10, 72, 15)) - self.label_2.setObjectName("label_2") - self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) - self.horizontalLayout.addWidget(self.scrollArea_2) - self.frame_2 = QtWidgets.QFrame(Form) - self.frame_2.setMinimumSize(QtCore.QSize(500, 500)) - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_2.setObjectName("frame_2") - self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2) - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.label_remark_2 = QtWidgets.QLabel(self.frame_2) - font = QtGui.QFont() - font.setPointSize(12) - self.label_remark_2.setFont(font) - self.label_remark_2.setText("") - self.label_remark_2.setObjectName("label_remark_2") - self.horizontalLayout_3.addWidget(self.label_remark_2) - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_3.addItem(spacerItem) - self.toolButton_2 = QtWidgets.QToolButton(self.frame_2) - self.toolButton_2.setObjectName("toolButton_2") - self.horizontalLayout_3.addWidget(self.toolButton_2) - self.verticalLayout.addLayout(self.horizontalLayout_3) - self.line_4 = QtWidgets.QFrame(self.frame_2) - self.line_4.setLineWidth(6) - self.line_4.setFrameShape(QtWidgets.QFrame.VLine) - self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_4.setObjectName("line_4") - self.verticalLayout.addWidget(self.line_4) - self.line_5 = QtWidgets.QFrame(self.frame_2) - self.line_5.setFrameShape(QtWidgets.QFrame.HLine) - self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_5.setObjectName("line_5") - self.verticalLayout.addWidget(self.line_5) - self.message_2 = QtWidgets.QTextBrowser(self.frame_2) - self.message_2.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - self.message_2.setStyleSheet("background-color: #F5F5F5;") - self.message_2.setObjectName("message_2") - self.verticalLayout.addWidget(self.message_2) - self.textEdit_2 = QtWidgets.QTextEdit(self.frame_2) - font = QtGui.QFont() - font.setPointSize(15) - self.textEdit_2.setFont(font) - self.textEdit_2.setTabStopWidth(80) - self.textEdit_2.setCursorWidth(1) - self.textEdit_2.setObjectName("textEdit_2") - self.verticalLayout.addWidget(self.textEdit_2) - self.line_6 = QtWidgets.QFrame(self.frame_2) - self.line_6.setFrameShape(QtWidgets.QFrame.HLine) - self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_6.setObjectName("line_6") - self.verticalLayout.addWidget(self.line_6) - self.btn_sendMsg_2 = QtWidgets.QPushButton(self.frame_2) - font = QtGui.QFont() - font.setFamily("黑体") - font.setPointSize(15) - font.setBold(False) - font.setWeight(50) - self.btn_sendMsg_2.setFont(font) - self.btn_sendMsg_2.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.btn_sendMsg_2.setMouseTracking(False) - self.btn_sendMsg_2.setAutoFillBackground(False) - self.btn_sendMsg_2.setStyleSheet("QPushButton {\n" - " background-color: #f0f0f0;\n" - " \n" - " padding: 10px;\n" - " color:rgb(5,180,104);\n" - "}") - self.btn_sendMsg_2.setIconSize(QtCore.QSize(40, 40)) - self.btn_sendMsg_2.setCheckable(False) - self.btn_sendMsg_2.setAutoDefault(True) - self.btn_sendMsg_2.setObjectName("btn_sendMsg_2") - self.verticalLayout.addWidget(self.btn_sendMsg_2) - self.verticalLayout.setStretch(0, 1) - self.verticalLayout.setStretch(2, 3) - self.verticalLayout.setStretch(3, 20) - self.verticalLayout.setStretch(4, 1) - self.verticalLayout.setStretch(6, 1) - self.horizontalLayout.addWidget(self.frame_2) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.label_2.setText(_translate("Form", "TextLabel")) - self.toolButton_2.setText(_translate("Form", "...")) - self.textEdit_2.setHtml(_translate("Form", - "\n" - "\n" - "


")) - self.btn_sendMsg_2.setText(_translate("Form", "发送")) diff --git a/app/Ui/chat/myinfo.zip b/app/Ui/chat/myinfo.zip deleted file mode 100644 index 71c3be3..0000000 Binary files a/app/Ui/chat/myinfo.zip and /dev/null differ diff --git a/app/Ui/contact/__init__.py b/app/Ui/contact/__init__.py deleted file mode 100644 index fa6c268..0000000 --- a/app/Ui/contact/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : __init__.py.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 20:33 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" diff --git a/app/Ui/contact/analysis/analysis.py b/app/Ui/contact/analysis/analysis.py deleted file mode 100644 index abd2c6c..0000000 --- a/app/Ui/contact/analysis/analysis.py +++ /dev/null @@ -1,153 +0,0 @@ -import sys - -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWebEngineWidgets import QWebEngineView -from PyQt5.QtWidgets import * - -QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) -from . import charts - - -class AnalysisController(QWidget): - def __init__(self, username, parent=None): - super().__init__(parent) - self.ta_username = username - # self.setWindowTitle('数据分析') - # self.setWindowIcon(QIcon('./app/data/icon.png')) - - # self.setWindowFlag(Qt.FramelessWindowHint) - self.setStyleSheet('''QWidget{background-color:rgb(255, 255, 255);}''') - self.center() - self.setAttribute(Qt.WA_AttributeCount) - self.label_01() - self.isStart = False - - def center(self): # 定义一个函数使得窗口居中显示 - # 获取屏幕坐标系 - screen = QDesktopWidget().screenGeometry() - # 获取窗口坐标系 - size = self.geometry() - newLeft = (screen.width() - size.width()) / 2 - newTop = (screen.height() - size.height()) / 2 - self.move(int(newLeft), int(newTop)) - - def label_01(self): - self.label = QLabel(self) - size = self.geometry() - self.label.setGeometry(size.width() // 2, self.height() // 2, 100, 100) - self.label.setToolTip("这是一个标签") - self.m_movie() - - def m_movie(self): - movie = QMovie("./app/data/bg.gif") - self.label.setMovie(movie) - movie.start() - - def initUI(self): - self.label.setVisible(False) - # self.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - - main_box = QVBoxLayout(self) - main_box.setContentsMargins(0, 0, 0, 0) - main_box.setSpacing(0) - - self.browser1 = QWebEngineView() - self.browser1.load(QUrl('file:///data/聊天统计/title.html')) - self.browser1.setMinimumSize(810, 60) - self.browser1.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - self.browser2 = QWebEngineView() - self.browser2.load(QUrl('file:///data/聊天统计/wordcloud.html')) - self.browser2.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - # self.browser2.setMinimumWidth(810) - self.browser2.setMinimumSize(810, 810) - self.browser3 = QWebEngineView() - self.browser3.load(QUrl('file:///data/聊天统计/time.html')) - self.browser3.setMaximumSize(810, 100) - self.browser3.adjustSize() - self.browser4 = QWebEngineView() - self.browser4.load(QUrl('http://www.baidu.com')) - self.browser4.resize(800, 600) - self.browser5 = QWebEngineView() - self.browser5.load(QUrl('file:///data/聊天统计/chat_session.html')) - self.browser6 = QWebEngineView() - self.browser6.load(QUrl('file:///data/聊天统计/sports.html')) - self.browser7 = QWebEngineView() - self.browser7.load(QUrl('file:///data/聊天统计/month_num.html')) - self.browser8 = QWebEngineView() - self.browser8.load(QUrl('file:///data/聊天统计/calendar.html')) - self.browser9 = QWebEngineView() - self.browser9.load(QUrl('file:///data/聊天统计/msg_type_rate.html')) - self.browser10 = QWebEngineView() - self.browser10.load(QUrl('file:///data/聊天统计/send_recv_rate.html')) - self.browser10.adjustSize() - # self.browser10. - main_box.addWidget(self.browser1) - - self.scrollArea = QScrollArea() - self.scrollArea.setEnabled(True) - self.scrollArea.adjustSize() - - scrollAreaContent = QWidget(self.scrollArea) - scrollAreaContent.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - Vlayout2 = QVBoxLayout() - Vlayout2.setContentsMargins(0, 0, 0, 0) - Vlayout2.setSpacing(0) - Vlayout2.addWidget(self.browser3) - Vlayout2.addWidget(self.browser2) - Vlayout2.addWidget(self.browser8) - Vlayout2.addWidget(self.browser6) - Vlayout2.addWidget(self.browser5) - Vlayout2.addWidget(self.browser7) - Vlayout2.addWidget(self.browser9) - Vlayout2.addWidget(self.browser10) - scrollAreaContent.setLayout(Vlayout2) - self.scrollArea.setWidget(scrollAreaContent) - main_box.addWidget(self.scrollArea) - main_box.setStretch(0, 1) - main_box.setStretch(1, 10) - self.setLayout(main_box) - - def setBackground(self): - palette = QPalette() - pix = QPixmap("./app/data/bg.png") - pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小 - palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片 - # palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色 - self.setPalette(palette) - - def start(self): - if not self.isStart: - self.Thread = LoadData(self.ta_username) - self.Thread.okSignal.connect(self.initUI) - self.Thread.start() - self.isStart = True - - -class LoadData(QThread): - """ - 发送信息线程 - """ - okSignal = pyqtSignal(int) - - def __init__(self, ta_u, parent=None): - super().__init__(parent) - self.ta_username = ta_u - - def run(self): - charts.chat_start_endTime(self.ta_username) - charts.title(self.ta_username) - charts.send_recv_rate(self.ta_username) - charts.message_word_cloud(self.ta_username) - charts.msg_type_rate(self.ta_username) - charts.calendar_chart(self.ta_username) - charts.month_num(self.ta_username) - charts.sport(self.ta_username) - charts.chat_session(self.ta_username) - self.okSignal.emit(10) - - -if __name__ == '__main__': - app = QApplication(sys.argv) - ex = MainWindow() - sys.exit(app.exec_()) diff --git a/app/Ui/contact/analysis/charts - 副本.zip b/app/Ui/contact/analysis/charts - 副本.zip deleted file mode 100644 index ce2d1b1..0000000 Binary files a/app/Ui/contact/analysis/charts - 副本.zip and /dev/null differ diff --git a/app/Ui/contact/analysis/charts.py b/app/Ui/contact/analysis/charts.py deleted file mode 100644 index 940a1c0..0000000 --- a/app/Ui/contact/analysis/charts.py +++ /dev/null @@ -1,539 +0,0 @@ -import os -import traceback - -import jieba -import pandas as pd -import xmltodict -from pyecharts import options as opts -from pyecharts.charts import Pie, WordCloud, Calendar, Bar, Line, Timeline, Grid - -from app.log import logger, log -from ....DataBase import data - -# from app.DataBase import data - -data.mkdir(os.path.abspath('.') + '/data/聊天统计') - -Type = { - '1': '文字', - '3': '图片', - '43': '视频', - '-1879048185': '微信运动排行榜', - '5': '', - '47': '表情包', - '268445456': '撤回消息', - '34': '语音', - '419430449': '转账', - '50': '语音电话', - '100001': '领取红包', - '10000': '消息已发出,但被对方拒收了。', - '822083633': '回复消息', - '922746929': '拍一拍', - '1090519089': '文件', - '318767153': '付款成功', - '436207665': '发红包', - '49': '分享链接' -} -charts_width = 800 -charts_height = 450 -wordcloud_width = 780 -wordcloud_height = 720 - - -@log -def send_recv_rate(username): - send_num = data.send_nums(username) - recv_num = data.recv_nums(username) - total_num = send_num + recv_num - print(send_num, recv_num) - c = ( - Pie(init_opts=opts.InitOpts( - # bg_color='rgb(240,240,240)', - width=f"{charts_width}px", - height=f"{charts_height}px") - ) - .add( - "", - [ - ('发送', send_num), ('接收', recv_num) - ], - center=["40%", "50%"], - ) - .set_global_opts( - title_opts=opts.TitleOpts(title=f"信息发送接收", subtitle=f"总计:{total_num}条消息", pos_bottom="0%"), - legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"), - ) - .set_series_opts( - label_opts=opts.LabelOpts(formatter="{b}:{d}%"), - ) - .render("./data/聊天统计/send_recv_rate.html") - ) - - -@log -def msg_type_rate(username): - type_data = data.msg_type_num(username) - type_data = sorted(type_data, key=lambda x: x[1], reverse=True) - data1 = type_data[:4] - data2 = sum(map(lambda x: x[1], type_data[4:])) - print(type_data) - new_data = [] - for t in data1: - try: - new_data.append((Type[str(t[0])], t[1])) - except: - new_data.append(('未知类型', t[1])) - new_data.append(('其他', data2)) - - c = ( - Pie(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - .add( - "", - new_data - , - center=["40%", "50%"], - ) - .set_global_opts( - title_opts=opts.TitleOpts(title=f"消息类型占比", pos_bottom="0%"), - legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"), - ) - .set_series_opts( - label_opts=opts.LabelOpts(formatter="{b}:{d}%"), - ) - .render("./data/聊天统计/msg_type_rate.html") - ) - - -@log -def message_word_cloud(username): - text = data.get_text(username) - total_msg_len = len(text) - word_list = jieba.cut(text) - # word = " ".join(word_list) - # print(word) - stopwords = set() - content = [line.strip() for line in open('./app/data/stopwords.txt', 'r', encoding='utf-8').readlines()] - stopwords.update(content) - wordcount = {} - for word in jieba.cut(text): - if len(word) > 1 and word not in stopwords: - wordcount[word] = wordcount.get(word, 0) + 1 - text_data = sorted(wordcount.items(), key=lambda x: x[1], reverse=True) - if len(text_data) > 100: - text_data = text_data[:100] - # print(text_data) - ( - WordCloud(init_opts=opts.InitOpts(width=f"{wordcloud_width}px", height=f"{wordcloud_height}px")) - .add(series_name="聊天文字", data_pair=text_data, word_size_range=[20, 100]) - .set_global_opts( - title_opts=opts.TitleOpts( - title=f"词云图", subtitle=f"总计{total_msg_len}字", - title_textstyle_opts=opts.TextStyleOpts(font_size=23) - ), - tooltip_opts=opts.TooltipOpts(is_show=True), - legend_opts=opts.LegendOpts(is_show=False) - ) - .render("./data/聊天统计/wordcloud.html") - ) - - -@log -def calendar_chart(username): - msg_data = data.get_msg_by_days(username, year='2022') - if not msg_data: - return False - min_ = min(map(lambda x: x[1], msg_data)) - max_ = max(map(lambda x: x[1], msg_data)) - c = ( - Calendar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - .add( - "", - msg_data, - calendar_opts=opts.CalendarOpts(range_="2022") - ) - .set_global_opts( - title_opts=opts.TitleOpts(title="2022年聊天情况"), - visualmap_opts=opts.VisualMapOpts( - max_=max_, - min_=min_, - orient="horizontal", - # is_piecewise=True, - # pos_top="200px", - pos_bottom="0px", - pos_left="0px", - ), - legend_opts=opts.LegendOpts(is_show=False) - ) - .render("./data/聊天统计/calendar.html") - ) - - -@log -def month_num(username): - """ - 每月聊天条数 - """ - msg_data = data.get_msg_by_month(username, year='2022') - y_data = list(map(lambda x: x[1], msg_data)) - x_axis = list(map(lambda x: x[0], msg_data)) - c = ( - Bar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - .add_xaxis(x_axis) - .add_yaxis("消息数量", y_data) - .set_global_opts( - title_opts=opts.TitleOpts(title="逐月统计", subtitle=None), - datazoom_opts=opts.DataZoomOpts(), - toolbox_opts=opts.ToolboxOpts(), - ) - .render("./data/聊天统计/month_num.html") - ) - - -@log -def chat_session(username): - msg_data = data.get_msg_by_hour(username) - x_axis = list(map(lambda x: x[0], msg_data)) - y_data = list(map(lambda x: x[1], msg_data)) - # print(x_axis) - # print(y_data) - # max_ = max(y_data) - c = ( - Line(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - .add_xaxis(xaxis_data=x_axis) - .add_yaxis( - series_name="聊天频率", - y_axis=y_data, - markpoint_opts=opts.MarkPointOpts( - data=[ - opts.MarkPointItem(type_="max", name="最大值"), - opts.MarkPointItem(type_="min", name="最小值", value=int(10)), - ] - ), - markline_opts=opts.MarkLineOpts( - data=[opts.MarkLineItem(type_="average", name="平均值")] - ), - ) - .set_global_opts( - title_opts=opts.TitleOpts(title="聊天时段", subtitle=None), - # datazoom_opts=opts.DataZoomOpts(), - # toolbox_opts=opts.ToolboxOpts(), - ) - .set_series_opts( - label_opts=opts.LabelOpts( - is_show=False - ) - ) - .render("./data/聊天统计/chat_session.html") - ) - - -@log -def sport(username): - sports = data.get_sport() - ranks = [] - steps = [] - date = [] - for sport in sports: - try: - timestamp, content, t = sport - rank_data = xmltodict.parse(content) - sub_data = rank_data['msg']['appmsg']['hardwareinfo']['messagenodeinfo'] - # print(sub_data) - # my_rank = sub_data['rankinfo']['rank']['rankdisplay'] - # my_steps = int(sub_data['rankinfo']['score']['scoredisplay']) - # print(f'rank: {my_rank},steps: {my_steps}') - rank_view = rank_data['msg']['appmsg']['hardwareinfo']['rankview']['rankinfolist']['rankinfo'] - for userinfo in rank_view: - username0 = userinfo['username'] - if username0 == username: - rank_ta = int(userinfo['rank']['rankdisplay']) - steps_ta = int(userinfo['score']['scoredisplay']) - ranks.append(rank_ta) - steps.append(steps_ta) - date.append(t) - except: - logger.error(f"\nsport is error,here are details:\n{traceback.format_exc()}\n") - continue - try: - # todo 可能没有运动信息 - df = pd.DataFrame({'ranks': ranks, 'score': steps, 'date': date}, index=date) - months = pd.date_range(date[0], date[-1], freq='M') - except: - months = [] - tl = Timeline(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - tl.add_schema(is_auto_play=True) - for i in range(len(months) - 1): - da = df[(months[i + 1].strftime("%Y-%m-%d") >= df['date']) & (df['date'] > months[i].strftime("%Y-%m-%d"))] - bar = ( - Bar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - .add_xaxis(list(da['date'])) - .add_yaxis( - "步数", - list(da['score']), - yaxis_index=1, - color="#d14a61", - ) - .extend_axis( - yaxis=opts.AxisOpts( - name="步数", - type_="value", - # grid_index=0, - # min_=0, - # max_=250, - position="right", - axisline_opts=opts.AxisLineOpts( - linestyle_opts=opts.LineStyleOpts(color="#d14a61") - ), - # axislabel_opts=opts.LabelOpts(formatter="{value} ml"), - ) - ) - .extend_axis( - yaxis=opts.AxisOpts( - type_="value", - name="排名", - # min_=0, - # max_=25, - position="left", - is_inverse=True, - is_show=False, - # interval=True, - # grid_index=1, - axisline_opts=opts.AxisLineOpts( - linestyle_opts=opts.LineStyleOpts(color="#675bba") - ), - # axislabel_opts=opts.LabelOpts(formatter="{value} °C"), - splitline_opts=opts.SplitLineOpts( - is_show=True, linestyle_opts=opts.LineStyleOpts(opacity=1) - ), - ) - ) - .set_global_opts( - title_opts=opts.TitleOpts( - title="{}".format(months[i + 1].strftime("%Y-%m")), - - ), - # legend_opts=opts.LegendOpts(is_show=False), - yaxis_opts=opts.AxisOpts(is_inverse=True), - # xaxis_opts=opts.AxisOpts(type_='time') - ) - .set_series_opts( - label_opts=opts.LabelOpts( - is_show=False - ) - ) - ) - # init_opts = opts.InitOpts(width="400px", height="235px") - line = ( - Line(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px")) - .add_xaxis(list(da['date'])) - .add_yaxis( - "排名", - list(da['ranks']), - yaxis_index=0, - color="#675bba", - # label_opts=opts.LabelOpts(is_show=False), - - ) - .set_global_opts( - yaxis_opts=opts.AxisOpts(is_inverse=True), - # xaxis_opts=opts.AxisOpts(type_='time') - ) - .set_series_opts( - label_opts=opts.LabelOpts( - is_show=False - ) - ) - ) - bar.overlap(line) - grid = Grid() - grid.add(bar, opts.GridOpts(pos_left="5%", pos_right="11%"), is_control_axis_index=True) - # grid.render("grid_multi_yaxis.html") - tl.add(grid, "{}".format(months[i].strftime("%Y-%m"))) - tl.render("./data/聊天统计/sports.html") - return { - username: { - 'ranks': ranks, - 'score': steps, - 'date': date, - } - } - - -@log -def chat_start_endTime(username): - start_time = data.get_msg_start_time(username) - end_time = data.get_msg_end_time(username) - year = start_time[:4] - month = start_time[5:7] - day = start_time[8:10] - hour = start_time[11:13] - minute = start_time[14:16] - second = start_time[17:] - html = ''' - - - - 聊天时间 - - - - -
-

- 一次聊天发生 - %s-%s %s:%s:%s -

-
-
- 距今已有 - 626 天 - 6 时 - 26 分 - 26 秒 -
-
-
- - - - - ''' % (year, month + '-' + day, hour, minute, second, start_time) - with open('./data/聊天统计/time.html', 'w', encoding='utf-8') as f: - f.write(html) - - -@log -def title(username): - conRemark = data.get_conRemark(username) - avatar = data.get_avator(username) - html = ''' - - - - 聊天时间 - - - - -
- - - - - -
- - - - -
- Avatar -
-
- - - - -
- %s -
-
-
- - - - -
-
- - - ''' % (avatar, conRemark) - with open('./data/聊天统计/title.html', 'w', encoding='utf-8') as f: - f.write(html) - - -if __name__ == '__main__': - # send_recv_rate('wxid_wt2vsktnu4z022') - sport('wxid_wt2vsktnu4z022') diff --git a/app/Ui/contact/analysis/pie_scroll_legend.html b/app/Ui/contact/analysis/pie_scroll_legend.html deleted file mode 100644 index 7359cf2..0000000 --- a/app/Ui/contact/analysis/pie_scroll_legend.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - Awesome-pyecharts - - - - -
- - - diff --git a/app/Ui/contact/contact.py b/app/Ui/contact/contact.py deleted file mode 100644 index aab92cb..0000000 --- a/app/Ui/contact/contact.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : contact.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 15:07 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" -from typing import Dict - -from PyQt5 import QtCore -from PyQt5.QtCore import * -from PyQt5.QtWidgets import * - -import app.components.Button_Contact as MyLabel -from app import person -from app.DataBase import data -from app.Ui.contact.contactInfo import ContactInfo -from app.Ui.contact.contactUi import Ui_Dialog - -EMOTION = 1 -ANALYSIS = 2 - - -class StackedWidget(): - def __init__(self): - pass - - -class ContactController(QWidget, Ui_Dialog): - exitSignal = pyqtSignal() - urlSignal = pyqtSignal(QUrl) - - # username = '' - - def __init__(self, Me: person.Me, parent=None): - super(ContactController, self).__init__(parent) - self.chatroomFlag = None - self.ta_avatar = None - self.setupUi(self) - self.Me = Me - self.contacts: Dict[str, MyLabel.ContactUi] = {} - self.contactInfo: Dict[str, ContactInfo] = {} - self.show_flag = False - self.last_talkerId = None - self.now_talkerId = None - # self.showContact() - self.show_thread = ShowContactThread() - self.show_thread.showSingal.connect(self.showContact) - self.show_thread.heightSingal.connect(self.setScreenAreaHeight) - self.show_thread.start() - - def showContact(self, data_): - """ - data:Tuple[rconversation,index:int] - 显示联系人 - :return: - """ - rconversation, i = data_ - username = rconversation[1] - # print(username) - pushButton_2 = MyLabel.ContactUi(self.scrollAreaWidgetContents, i, rconversation) - pushButton_2.setGeometry(QtCore.QRect(0, 80 * i, 300, 80)) - pushButton_2.setLayoutDirection(QtCore.Qt.LeftToRight) - pushButton_2.clicked.connect(pushButton_2.show_msg) - pushButton_2.usernameSingal.connect(self.Contact) - self.contacts[username] = pushButton_2 - self.contactInfo[username] = ContactInfo(username, self.Me) - self.stackedWidget.addWidget(self.contactInfo[username]) - - def setScreenAreaHeight(self, height: int): - self.scrollAreaWidgetContents.setGeometry( - QtCore.QRect(0, 0, 300, height)) - - def Contact(self, talkerId): - """ - 聊天界面 点击联系人头像时候显示聊天数据 - :param talkerId: - :return: - """ - self.now_talkerId = talkerId - # 把当前按钮设置为灰色 - if self.last_talkerId and self.last_talkerId != talkerId: - print('对方账号:', self.last_talkerId) - self.contacts[self.last_talkerId].setStyleSheet( - "QPushButton {background-color: rgb(220,220,220);}" - "QPushButton:hover{background-color: rgb(208,208,208);}\n" - ) - self.last_talkerId = talkerId - self.contacts[talkerId].setStyleSheet( - "QPushButton {background-color: rgb(198,198,198);}" - "QPushButton:hover{background-color: rgb(209,209,209);}\n" - ) - self.stackedWidget.setCurrentWidget(self.contactInfo[talkerId]) - - if '@chatroom' in talkerId: - self.chatroomFlag = True - else: - self.chatroomFlag = False - - -class ShowContactThread(QThread): - showSingal = pyqtSignal(tuple) - heightSingal = pyqtSignal(int) - - def __init__(self): - super().__init__() - - def run(self) -> None: - rconversations = data.get_rconversation() - max_height = max(len(rconversations) * 80, 680) - # 设置滚动区域的高度 - self.heightSingal.emit(max_height) - for i in range(len(rconversations)): - self.showSingal.emit((rconversations[i], i)) diff --git a/app/Ui/contact/contactInfo.py b/app/Ui/contact/contactInfo.py deleted file mode 100644 index eaf4db0..0000000 --- a/app/Ui/contact/contactInfo.py +++ /dev/null @@ -1,137 +0,0 @@ -from PyQt5.QtCore import * -from PyQt5.QtWidgets import * - -from app import person -from app.DataBase import output -from app.Ui.Icon import Icon -from .analysis import analysis -from .contactInfoUi import Ui_Form -from .emotion import emotion -from .userinfo import userinfo - - -class ContactInfo(QWidget, Ui_Form): - exitSignal = pyqtSignal() - urlSignal = pyqtSignal(QUrl) - - # username = '' - def __init__(self, wxid, me: person.Me, parent=None): - super(ContactInfo, self).__init__(parent) - self.setupUi(self) - self.contact = person.Contact(wxid) - self.view_userinfo = userinfo.UserinfoController(self.contact) - self.view_analysis = analysis.AnalysisController(wxid) - self.view_emotion = emotion.EmotionController(wxid) - self.btn_analysis.clicked.connect(self.analysis) - self.btn_emotion.clicked.connect(self.emotionale_Analysis) - self.btn_report.clicked.connect(self.annual_report) - self.btn_back.clicked.connect(self.back) - self.Me = me - # self. - self.init_ui() - - def init_ui(self): - self.btn_back.setIcon(Icon.Back) - self.btn_report.setIcon(Icon.Annual_Report_Icon) - self.btn_analysis.setIcon(Icon.Analysis_Icon) - self.btn_emotion.setIcon(Icon.Emotion_Icon) - self.label_remark.setText(self.contact.conRemark) - self.stackedWidget.addWidget(self.view_userinfo) - self.stackedWidget.addWidget(self.view_analysis) - self.stackedWidget.addWidget(self.view_emotion) - self.stackedWidget.setCurrentWidget(self.view_userinfo) - menu = QMenu(self) - self.toDocxAct = QAction(Icon.ToDocx, '导出Docx', self) - self.toCSVAct = QAction(Icon.ToCSV, '导出CSV', self) - self.toHtmlAct = QAction(Icon.ToHTML, '导出HTML', self) - self.toolButton_output.setPopupMode(QToolButton.MenuButtonPopup) - self.toolButton_output.clicked.connect(self.toolButton_show) - menu.addAction(self.toDocxAct) - menu.addAction(self.toCSVAct) - menu.addAction(self.toHtmlAct) - self.toolButton_output.setMenu(menu) - self.toolButton_output.setIcon(Icon.Output) - # self.toolButton_output.addSeparator() - self.toHtmlAct.triggered.connect(self.output) - self.toDocxAct.triggered.connect(self.output) - self.toCSVAct.triggered.connect(self.output) - - def toolButton_show(self): - self.toolButton_output.showMenu() - - def analysis(self): - self.stackedWidget.setCurrentWidget(self.view_analysis) - if 'room' in self.contact.wxid: - QMessageBox.warning( - self, '警告', - '暂不支持群组' - ) - return - self.view_analysis.start() - - def annual_report(self): - QMessageBox.warning( - self, - "提示", - "敬请期待" - ) - return - # self.report = report.ReportController(self.contact) - # self.report.show() - - def emotionale_Analysis(self): - self.stackedWidget.setCurrentWidget(self.view_emotion) - if 'room' in self.contact.wxid: - QMessageBox.warning( - self, '警告', - '暂不支持群组' - ) - return - self.view_emotion.start() - - def back(self): - """ - 将userinfo界面设置为可见,其他界面设置为不可见 - """ - self.stackedWidget.setCurrentWidget(self.view_userinfo) - - def output(self): - """ - 导出聊天记录 - :return: - """ - self.stackedWidget.setCurrentWidget(self.view_userinfo) - if self.sender() == self.toDocxAct: - self.outputThread = output.Output(self.Me, self.contact.wxid) - elif self.sender() == self.toCSVAct: - print('开始导出csv') - self.outputThread = output.Output(self.Me, self.contact.wxid, type_=output.Output.CSV) - print('导出csv') - elif self.sender() == self.toHtmlAct: - print('功能暂未实现') - QMessageBox.warning(self, - "别急别急", - "马上就实现该功能" - ) - return - self.outputThread.progressSignal.connect(self.output_progress) - self.outputThread.rangeSignal.connect(self.set_progressBar_range) - self.outputThread.okSignal.connect(self.hide_progress_bar) - self.outputThread.start() - - def hide_progress_bar(self, int): - reply = QMessageBox(self) - reply.setIcon(QMessageBox.Information) - reply.setWindowTitle('OK') - reply.setText(f"导出聊天记录成功\n在.\\data\\目录下") - reply.addButton("确认", QMessageBox.AcceptRole) - reply.addButton("取消", QMessageBox.RejectRole) - api = reply.exec_() - self.view_userinfo.progressBar.setVisible(False) - - def output_progress(self, value): - self.view_userinfo.progressBar.setProperty('value', value) - - def set_progressBar_range(self, value): - self.view_userinfo.progressBar.setVisible(True) - self.view_userinfo.progressBar.setRange(0, value) diff --git a/app/Ui/contact/contactInfoUi.py b/app/Ui/contact/contactInfoUi.py deleted file mode 100644 index aa973a1..0000000 --- a/app/Ui/contact/contactInfoUi.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'contactInfoUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(817, 748) - self.horizontalLayout = QtWidgets.QHBoxLayout(Form) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setSpacing(0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.frame = QtWidgets.QFrame(Form) - self.frame.setFrameShape(QtWidgets.QFrame.NoFrame) - self.frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame.setObjectName("frame") - self.verticalLayout = QtWidgets.QVBoxLayout(self.frame) - self.verticalLayout.setContentsMargins(0, 0, 0, 0) - self.verticalLayout.setSpacing(0) - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setSpacing(0) - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.label_remark = QtWidgets.QLabel(self.frame) - self.label_remark.setMaximumSize(QtCore.QSize(16777215, 100)) - font = QtGui.QFont() - font.setPointSize(12) - self.label_remark.setFont(font) - self.label_remark.setText("") - self.label_remark.setObjectName("label_remark") - self.horizontalLayout_3.addWidget(self.label_remark) - self.btn_analysis = QtWidgets.QPushButton(self.frame) - self.btn_analysis.setStyleSheet("") - self.btn_analysis.setFlat(True) - self.btn_analysis.setObjectName("btn_analysis") - self.horizontalLayout_3.addWidget(self.btn_analysis) - self.btn_emotion = QtWidgets.QPushButton(self.frame) - self.btn_emotion.setFlat(True) - self.btn_emotion.setObjectName("btn_emotion") - self.horizontalLayout_3.addWidget(self.btn_emotion) - self.btn_report = QtWidgets.QPushButton(self.frame) - self.btn_report.setFlat(True) - self.btn_report.setObjectName("btn_report") - self.horizontalLayout_3.addWidget(self.btn_report) - self.btn_back = QtWidgets.QPushButton(self.frame) - self.btn_back.setFlat(True) - self.btn_back.setObjectName("btn_back") - self.horizontalLayout_3.addWidget(self.btn_back) - self.toolButton_output = QtWidgets.QToolButton(self.frame) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap("../../data/icons/output.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.toolButton_output.setIcon(icon) - self.toolButton_output.setCheckable(False) - self.toolButton_output.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) - self.toolButton_output.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) - self.toolButton_output.setAutoRaise(True) - self.toolButton_output.setArrowType(QtCore.Qt.NoArrow) - self.toolButton_output.setObjectName("toolButton_output") - self.horizontalLayout_3.addWidget(self.toolButton_output) - self.verticalLayout.addLayout(self.horizontalLayout_3) - self.stackedWidget = QtWidgets.QStackedWidget(self.frame) - self.stackedWidget.setObjectName("stackedWidget") - self.page_3 = QtWidgets.QWidget() - self.page_3.setObjectName("page_3") - self.stackedWidget.addWidget(self.page_3) - self.page_4 = QtWidgets.QWidget() - self.page_4.setObjectName("page_4") - self.stackedWidget.addWidget(self.page_4) - self.verticalLayout.addWidget(self.stackedWidget) - self.horizontalLayout.addWidget(self.frame) - - self.retranslateUi(Form) - self.stackedWidget.setCurrentIndex(1) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.btn_analysis.setText(_translate("Form", "统计信息")) - self.btn_emotion.setText(_translate("Form", "情感分析")) - self.btn_report.setText(_translate("Form", "年度报告")) - self.btn_back.setText(_translate("Form", "退出")) - self.toolButton_output.setText(_translate("Form", "导出聊天记录")) diff --git a/app/Ui/contact/contactUi.py b/app/Ui/contact/contactUi.py deleted file mode 100644 index 08798ef..0000000 --- a/app/Ui/contact/contactUi.py +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'contactUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(1141, 740) - Dialog.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - Dialog.setAutoFillBackground(False) - self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setSpacing(0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.frame_2 = QtWidgets.QFrame(Dialog) - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_2.setObjectName("frame_2") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_2) - self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout_2.setSpacing(0) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.scrollArea = QtWidgets.QScrollArea(self.frame_2) - self.scrollArea.setEnabled(True) - self.scrollArea.setMinimumSize(QtCore.QSize(325, 0)) - self.scrollArea.setMaximumSize(QtCore.QSize(325, 150000)) - self.scrollArea.setAutoFillBackground(False) - self.scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame) - self.scrollArea.setFrameShadow(QtWidgets.QFrame.Raised) - self.scrollArea.setMidLineWidth(0) - self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) - self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow) - self.scrollArea.setWidgetResizable(False) - self.scrollArea.setObjectName("scrollArea") - self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 300, 12000)) - self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") - self.pushButton_2 = QtWidgets.QPushButton(self.scrollAreaWidgetContents) - self.pushButton_2.setGeometry(QtCore.QRect(0, 0, 300, 80)) - self.pushButton_2.setLayoutDirection(QtCore.Qt.LeftToRight) - self.pushButton_2.setAutoFillBackground(False) - self.pushButton_2.setText("") - self.pushButton_2.setIconSize(QtCore.QSize(80, 80)) - self.pushButton_2.setObjectName("pushButton_2") - self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label.setGeometry(QtCore.QRect(220, 10, 72, 15)) - self.label.setObjectName("label") - self.scrollArea.setWidget(self.scrollAreaWidgetContents) - self.horizontalLayout_2.addWidget(self.scrollArea) - self.stackedWidget = QtWidgets.QStackedWidget(self.frame_2) - self.stackedWidget.setObjectName("stackedWidget") - self.page = QtWidgets.QWidget() - self.page.setObjectName("page") - self.stackedWidget.addWidget(self.page) - self.page_2 = QtWidgets.QWidget() - self.page_2.setObjectName("page_2") - self.stackedWidget.addWidget(self.page_2) - self.horizontalLayout_2.addWidget(self.stackedWidget) - self.horizontalLayout.addWidget(self.frame_2) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - self.label.setText(_translate("Dialog", "TextLabel")) diff --git a/app/Ui/contact/emotion/__init__.py b/app/Ui/contact/emotion/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/Ui/contact/emotion/emotion.py b/app/Ui/contact/emotion/emotion.py deleted file mode 100644 index c33a4e8..0000000 --- a/app/Ui/contact/emotion/emotion.py +++ /dev/null @@ -1,170 +0,0 @@ -import numpy as np -import pandas as pd -from pyecharts import options as opts -from pyecharts.charts import Line - -from app.log import log -from ....DataBase import data - - -def load_data(wxid): - message_data = data.get_text_by_num(wxid, 1) - df = pd.DataFrame(message_data, columns=['message', 'date']) - # print(df) - d = df.groupby('date') - for key, value in d: - yield key, value['message'].values - - -import snownlp - - -@log -def emotion_analysis(wxid): - dates = [] - emotions = [] - for date, messages in load_data(wxid): - dates.append(date) - s = 0 - for msg in messages: - val = snownlp.SnowNLP(msg).sentiments - s += val - emotions.append(s / len(messages)) - emotions = np.array(emotions) - emotions = np.around(emotions, 3) * 100 - emotions = np.around(emotions, 1) - return dates, emotions - - -@log -def plot_emotion(wxid): - """ - 画图 - """ - datas, emotions = emotion_analysis(wxid) # 获取数据 - max_ = max(emotions) - min_ = min(emotions) - c = ( - Line() - .add_xaxis( - xaxis_data=datas, - ) - .add_yaxis( - series_name="情感趋势", - is_smooth=True, - y_axis=emotions, - markpoint_opts=opts.MarkPointOpts( - data=[ - opts.MarkPointItem(type_="max", name="最大值", value=int(max_ * 100) / 100), - opts.MarkPointItem(type_="min", name="最小值", value=int(min_ * 100) / 100), - ] - ), - markline_opts=opts.MarkLineOpts( - data=[opts.MarkLineItem(type_="average", name="平均值")] - ), - ) - .set_global_opts( - yaxis_opts=opts.AxisOpts( - max_=max_, - min_=min_, - ), - xaxis_opts=opts.AxisOpts( - type_='time' - ), - axispointer_opts=opts.AxisPointerOpts( - is_show=True, link=[{"xAxisIndex": "all"}] - ), - ) - .set_series_opts(label_opts=opts.LabelOpts(is_show=False)) - .render("./data/聊天统计/emotion_chart.html") - ) - - -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWebEngineWidgets import QWebEngineView -from PyQt5.QtWidgets import * - -from . import emotionUi - - -class EmotionController(QWidget, emotionUi.Ui_Dialog): - def __init__(self, username, parent=None): - super().__init__(parent) - self.ta_username = username - - # self.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - # 加载动画 - self.center() - self.label_01() - - def center(self): # 定义一个函数使得窗口居中显示 - # 获取屏幕坐标系 - screen = QDesktopWidget().screenGeometry() - # 获取窗口坐标系 - size = self.geometry() - newLeft = (screen.width() - size.width()) / 2 - newTop = (screen.height() - size.height()) / 2 - self.move(int(newLeft), int(newTop)) - - def label_01(self): - w = self.size().width() - h = self.size().height() - self.label = QLabel(self) - self.label.setGeometry(w // 2, h // 2, 100, 100) - self.label.setToolTip("这是一个标签") - self.m_movie() - - def m_movie(self): - movie = QMovie("./app/data/bg.gif") - self.label.setMovie(movie) - movie.start() - - def initUI(self): - self.label.setVisible(False) - # self.setStyleSheet('''QWidget{background-color:rgb(244, 244, 244);}''') - main_box = QHBoxLayout(self) - self.browser1 = QWebEngineView() - self.browser1.load(QUrl('file:///data/聊天统计/emotion_chart.html')) - # self.browser1.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - - splitter1 = QSplitter(Qt.Vertical) - - splitter1.addWidget(self.browser1) - main_box.addWidget(splitter1) - self.setLayout(main_box) - - def setBackground(self): - palette = QPalette() - pix = QPixmap("./app/data/bg.png") - pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小 - palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片 - # palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色 - self.setPalette(palette) - - def start(self): - # 防止卡死,新建线程处理数据 - self.Thread = LoadData(self.ta_username) - self.Thread.okSignal.connect(self.initUI) - self.Thread.start() - - -class LoadData(QThread): - """ - 发送信息线程 - """ - okSignal = pyqtSignal(int) - - def __init__(self, ta_u, parent=None): - super().__init__(parent) - self.ta_username = ta_u - - def run(self): - plot_emotion(self.ta_username) - self.okSignal.emit(10) - - -if __name__ == '__main__': - # wxid = 'wxid_8piw6sb4hvfm22' - wxid = 'wxid_wt2vsktnu4z022' - load_data(wxid) diff --git a/app/Ui/contact/emotion/emotionUi.py b/app/Ui/contact/emotion/emotionUi.py deleted file mode 100644 index c989dbd..0000000 --- a/app/Ui/contact/emotion/emotionUi.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'emotionUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(400, 300) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) diff --git a/app/Ui/contact/report/__init__.py b/app/Ui/contact/report/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/Ui/contact/report/annual_report.py b/app/Ui/contact/report/annual_report.py deleted file mode 100644 index 3829e96..0000000 --- a/app/Ui/contact/report/annual_report.py +++ /dev/null @@ -1,28 +0,0 @@ -from bs4 import BeautifulSoup - - -def create_title_page(nickname, time, avatar_path): - with open('D:\\Project\\Python\\WeChatMsg\\app\\data\\html\\0.html', 'r+', encoding='utf-8') as f: - html_document = f.read() - # 创建Beautiful Soup对象 - soup = BeautifulSoup(html_document, 'html.parser') - # 找到需要替换的图片元素 - target_image = soup.find(id='avatar') - # 替换图片元素的src属性 - if target_image: - target_image['src'] = avatar_path - # 找到需要替换的元素 - target_element = soup.find(id='nickname') - # 替换元素的文本内容 - if target_element: - target_element.string = nickname - target_element = soup.find(id='first_time') - # 替换元素的文本内容 - if target_element: - target_element.string = time - with open('./data/AnnualReport/0.html', 'w', encoding='utf-8') as f1: - f1.write(soup.prettify()) - - -if __name__ == '__main__': - create_title_page('小学生', '2023-09-18 20:39:08', 'D:\Project\Python\WeChatMsg\\app\data\icons\default_avatar.svg') diff --git a/app/Ui/contact/report/report.py b/app/Ui/contact/report/report.py deleted file mode 100644 index c882900..0000000 --- a/app/Ui/contact/report/report.py +++ /dev/null @@ -1,74 +0,0 @@ -import sys - -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWebEngineWidgets import QWebEngineView -from PyQt5.QtWidgets import * - -from app import person -from app.DataBase import data -from . import annual_report - - -class ReportController(QWidget): - def __init__(self, contact: person.Contact, me: person.Me = None, parent=None): - super().__init__(parent) - self.ta_username = contact.wxid - self.contact = contact - self.Me = me - # self.setStyleSheet('''QWidget{background-color:rgb(240, 240, 240);}''') - # 加载动画 - self.center() - self.label_01() - - def center(self): # 定义一个函数使得窗口居中显示 - # 获取屏幕坐标系 - screen = QDesktopWidget().screenGeometry() - # 获取窗口坐标系 - size = self.geometry() - newLeft = (screen.width() - size.width()) / 2 - newTop = (screen.height() - size.height()) / 2 - self.move(int(newLeft), int(newTop)) - - def label_01(self): - w = self.size().width() - h = self.size().height() - self.label = QLabel(self) - self.label.setGeometry(w // 2, h // 2, 100, 100) - self.label.setToolTip("这是一个标签") - # self.m_movie() - self.initUI() - - def m_movie(self): - movie = QMovie("./app/data/bg.gif") - self.label.setMovie(movie) - movie.start() - - def initUI(self): - start_time = data.get_msg_start_time(self.contact.wxid) - annual_report.create_title_page(self.contact.nickname, start_time, self.contact.avatar_path) - self.label.setVisible(False) - # self.setStyleSheet('''QWidget{background-color:rgb(244, 244, 244);}''') - main_box = QHBoxLayout(self) - self.browser1 = QWebEngineView() - self.browser1.load(QUrl('file:///data/AnnualReport/index.html')) - - splitter1 = QSplitter(Qt.Vertical) - splitter1.addWidget(self.browser1) - main_box.addWidget(splitter1) - self.setLayout(main_box) - - def setBackground(self): - palette = QPalette() - pix = QPixmap("./app/data/bg.png") - pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小 - palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片 - # palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色 - self.setPalette(palette) - - -if __name__ == '__main__': - app = QApplication(sys.argv) - ex = ReportController(1) - ex.show() - sys.exit(app.exec_()) diff --git a/app/Ui/contact/userinfo/__init__.py b/app/Ui/contact/userinfo/__init__.py deleted file mode 100644 index 6d32454..0000000 --- a/app/Ui/contact/userinfo/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : __init__.py.py -@Author : Shuaikang Zhou -@Time : 2022/12/24 10:34 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" diff --git a/app/Ui/contact/userinfo/userinfo.py b/app/Ui/contact/userinfo/userinfo.py deleted file mode 100644 index 5bc3656..0000000 --- a/app/Ui/contact/userinfo/userinfo.py +++ /dev/null @@ -1,15 +0,0 @@ -from PyQt5.QtWidgets import * - -from .userinfoUi import Ui_Frame - - -class UserinfoController(QWidget, Ui_Frame): - def __init__(self, contact, parent=None): - super().__init__(parent) - self.setupUi(self) - self.l_remark.setText(contact.conRemark) - self.l_avatar.setPixmap(contact.avatar) - self.l_nickname.setText(f'昵称:{contact.nickname}') - self.l_username.setText(f'微信号:{contact.alias}') - self.lineEdit.setText(contact.conRemark) - self.progressBar.setVisible(False) diff --git a/app/Ui/contact/userinfo/userinfoUi.py b/app/Ui/contact/userinfo/userinfoUi.py deleted file mode 100644 index 8154cf6..0000000 --- a/app/Ui/contact/userinfo/userinfoUi.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'userinfoUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Frame(object): - def setupUi(self, Frame): - Frame.setObjectName("Frame") - Frame.resize(800, 720) - Frame.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor)) - Frame.setMouseTracking(True) - Frame.setTabletTracking(True) - self.horizontalLayout_3 = QtWidgets.QHBoxLayout(Frame) - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem) - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem1) - self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setHorizontalSpacing(6) - self.gridLayout.setObjectName("gridLayout") - self.l_avatar = QtWidgets.QLabel(Frame) - self.l_avatar.setMinimumSize(QtCore.QSize(80, 80)) - self.l_avatar.setMaximumSize(QtCore.QSize(80, 80)) - self.l_avatar.setText("") - self.l_avatar.setPixmap(QtGui.QPixmap("../../../a_img/be0fa6c0c4707fb5f7b37b660de826d3.jpg")) - self.l_avatar.setScaledContents(True) - self.l_avatar.setObjectName("l_avatar") - self.gridLayout.addWidget(self.l_avatar, 0, 0, 3, 1) - self.l_remark = QtWidgets.QLabel(Frame) - self.l_remark.setMinimumSize(QtCore.QSize(0, 30)) - self.l_remark.setMaximumSize(QtCore.QSize(16777215, 30)) - font = QtGui.QFont() - font.setPointSize(15) - self.l_remark.setFont(font) - self.l_remark.setObjectName("l_remark") - self.gridLayout.addWidget(self.l_remark, 0, 1, 1, 1) - self.l_nickname = QtWidgets.QLabel(Frame) - self.l_nickname.setMinimumSize(QtCore.QSize(0, 30)) - self.l_nickname.setMaximumSize(QtCore.QSize(16777215, 30)) - self.l_nickname.setObjectName("l_nickname") - self.gridLayout.addWidget(self.l_nickname, 1, 1, 1, 1) - self.l_username = QtWidgets.QLabel(Frame) - self.l_username.setMinimumSize(QtCore.QSize(0, 20)) - self.l_username.setMaximumSize(QtCore.QSize(16777215, 20)) - self.l_username.setObjectName("l_username") - self.gridLayout.addWidget(self.l_username, 2, 1, 1, 1) - self.gridLayout.setRowStretch(0, 1) - self.gridLayout.setRowStretch(1, 1) - self.gridLayout.setRowStretch(2, 1) - self.verticalLayout.addLayout(self.gridLayout) - spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem2) - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(Frame) - self.label.setMinimumSize(QtCore.QSize(80, 0)) - self.label.setMaximumSize(QtCore.QSize(80, 16777215)) - font = QtGui.QFont() - font.setPointSize(15) - self.label.setFont(font) - self.label.setObjectName("label") - self.horizontalLayout.addWidget(self.label) - self.lineEdit = QtWidgets.QLineEdit(Frame) - self.lineEdit.setMinimumSize(QtCore.QSize(0, 25)) - self.lineEdit.setMaximumSize(QtCore.QSize(16777215, 25)) - font = QtGui.QFont() - font.setPointSize(15) - self.lineEdit.setFont(font) - self.lineEdit.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.lineEdit.setAutoFillBackground(False) - self.lineEdit.setStyleSheet("background:transparent;border-width:0;border-style:outset") - self.lineEdit.setObjectName("lineEdit") - self.horizontalLayout.addWidget(self.lineEdit) - self.verticalLayout.addLayout(self.horizontalLayout) - spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem3) - self.progressBar = QtWidgets.QProgressBar(Frame) - self.progressBar.setProperty("value", 24) - self.progressBar.setObjectName("progressBar") - self.verticalLayout.addWidget(self.progressBar) - spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem4) - self.verticalLayout.setStretch(0, 2) - self.verticalLayout.setStretch(1, 3) - self.verticalLayout.setStretch(2, 4) - self.verticalLayout.setStretch(3, 1) - self.verticalLayout.setStretch(4, 4) - self.verticalLayout.setStretch(5, 1) - self.verticalLayout.setStretch(6, 2) - self.horizontalLayout_2.addLayout(self.verticalLayout) - spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem5) - self.horizontalLayout_2.setStretch(0, 1) - self.horizontalLayout_2.setStretch(1, 2) - self.horizontalLayout_2.setStretch(2, 1) - self.horizontalLayout_3.addLayout(self.horizontalLayout_2) - - self.retranslateUi(Frame) - QtCore.QMetaObject.connectSlotsByName(Frame) - - def retranslateUi(self, Frame): - _translate = QtCore.QCoreApplication.translate - Frame.setWindowTitle(_translate("Frame", "Frame")) - self.l_remark.setText(_translate("Frame", "曹雨萱")) - self.l_nickname.setText(_translate("Frame", "昵称:997")) - self.l_username.setText(_translate("Frame", "账号:TextLabel")) - self.label.setText(_translate("Frame", "备注名")) - self.lineEdit.setText(_translate("Frame", "曹雨萱")) diff --git a/app/Ui/decrypt/decrypt.py b/app/Ui/decrypt/decrypt.py deleted file mode 100644 index 7204a7c..0000000 --- a/app/Ui/decrypt/decrypt.py +++ /dev/null @@ -1,161 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : decrypt.py -@Author : Shuaikang Zhou -@Time : 2023/1/5 18:13 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· 解密数据库,导出原始数据库文件 -""" -import hashlib -import time -import xml.etree.ElementTree as ET - -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * - -from . import decryptUi -from ...DataBase import data - - -class DecryptControl(QWidget, decryptUi.Ui_Dialog): - DecryptSignal = pyqtSignal(str) - registerSignal = pyqtSignal(str) - - def __init__(self, parent=None): - super(DecryptControl, self).__init__(parent) - self.setupUi(self) - self.setWindowTitle('解密') - self.setWindowIcon(QIcon('./app/data/icons/logo.svg')) - self.btn_db.clicked.connect(self.get_db) - self.btn_xml.clicked.connect(self.get_xml) - self.pushButton_3.clicked.connect(self.decrypt) - self.xml_path: str = None - self.db_path: str = None - - def db_exist(self): - if data.is_db_exist(): - self.btnEnterClicked() - self.close() - - def get_xml(self): - self.xml_path, _ = QFileDialog.getOpenFileName(self, 'Open file', r'..', "Xml files (*.xml)") - if self.xml_path: - self.label_xml.setText('xml已就绪') - key = self.parser_xml() - self.label_key.setText(f'数据库密钥:{key}') - return self.xml_path - return False - - def get_db(self): - self.db_path, _ = QFileDialog.getOpenFileName(self, 'Open file', r'..', "Database files (*.db)") - if self.db_path: - if ' ' in self.db_path: - self.label_db.setText('数据库未就绪') - QMessageBox.critical(self, "错误", "db文件路径请不要带有空格\n可以放在D:\\\\data 目录下") - self.db_path = '' - elif self.db_path.isascii(): - self.label_db.setText('数据库已就绪') - return self.db_path - else: - self.label_db.setText('数据库未就绪') - QMessageBox.critical(self, "错误", "db文件请不要带有中文路径\n可以放在D:\\\\data 目录下") - self.db_path = '' - return False - - def decrypt(self): - if not (self.xml_path and self.db_path): - QMessageBox.critical(self, "错误", "请把两个文件加载进来") - return - key = self.parser_xml() - self.label_key.setText(f'数据库密钥:{key}') - self.thread1 = MyThread() - self.thread1.signal.connect(self.progressBar_view) - self.thread1.start() - self.thread2 = DecryptThread(self.db_path, key) - self.thread2.signal.connect(self.progressBar_view) - self.thread2.start() - - def parser_xml(self): - if not self.xml_path: - return False - pid = self.pid(self.xml_path) - if not pid: - return False - key = self.key(pid) - return key - - def pid(self, xml_path): - tree = ET.parse(xml_path) - # 根节点 - root = tree.getroot() - # 标签名 - for stu in root: - if stu.attrib["name"] == '_auth_uin': - return stu.attrib['value'] - return False - - def key(self, uin, IMEI='1234567890ABCDEF'): - m = hashlib.md5() - m.update(bytes((IMEI + uin).encode('utf-8'))) - psw = m.hexdigest() - return psw[:7] - - def btnEnterClicked(self): - # print("enter clicked") - # 中间可以添加处理逻辑 - self.DecryptSignal.emit('ok') - self.close() - - def progressBar_view(self, value): - """ - 进度条显示 - :param value: 进度0-100 - :return: None - """ - self.progressBar.setProperty('value', value) - if value == '99': - QMessageBox.information(self, "温馨提示", "我知道你很急\n但你先别急") - if value == '100': - QMessageBox.information(self, "解密成功", "请退出该界面", - QMessageBox.Yes) - self.btnExitClicked() - data.init_database() - - def btnExitClicked(self): - # print("Exit clicked") - self.DecryptSignal.emit('ok') - self.close() - - -class DecryptThread(QThread): - signal = pyqtSignal(str) - - def __init__(self, db_path, key): - super(DecryptThread, self).__init__() - self.db_path = db_path - self.key = key - self.textBrowser = None - - def __del__(self): - pass - - def run(self): - data.decrypt(self.db_path, self.key) - self.signal.emit('100') - - -class MyThread(QThread): - signal = pyqtSignal(str) - - def __init__(self): - super(MyThread, self).__init__() - - def __del__(self): - pass - - def run(self): - for i in range(100): - self.signal.emit(str(i)) - time.sleep(0.1) diff --git a/app/Ui/decrypt/decryptUi.py b/app/Ui/decrypt/decryptUi.py deleted file mode 100644 index 433f18c..0000000 --- a/app/Ui/decrypt/decryptUi.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'decryptUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(400, 300) - self.label_3 = QtWidgets.QLabel(Dialog) - self.label_3.setGeometry(QtCore.QRect(110, 20, 221, 51)) - font = QtGui.QFont() - font.setFamily("一纸情书") - font.setPointSize(20) - self.label_3.setFont(font) - self.label_3.setObjectName("label_3") - self.progressBar = QtWidgets.QProgressBar(Dialog) - self.progressBar.setGeometry(QtCore.QRect(90, 260, 271, 23)) - self.progressBar.setProperty("value", 50) - self.progressBar.setObjectName("progressBar") - self.label_key = QtWidgets.QLabel(Dialog) - self.label_key.setGeometry(QtCore.QRect(80, 230, 241, 20)) - self.label_key.setText("") - self.label_key.setObjectName("label_key") - self.widget = QtWidgets.QWidget(Dialog) - self.widget.setGeometry(QtCore.QRect(80, 80, 245, 134)) - self.widget.setObjectName("widget") - self.verticalLayout = QtWidgets.QVBoxLayout(self.widget) - self.verticalLayout.setContentsMargins(0, 0, 0, 0) - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.btn_xml = QtWidgets.QPushButton(self.widget) - self.btn_xml.setObjectName("btn_xml") - self.horizontalLayout.addWidget(self.btn_xml) - self.label_xml = QtWidgets.QLabel(self.widget) - self.label_xml.setObjectName("label_xml") - self.horizontalLayout.addWidget(self.label_xml) - self.verticalLayout.addLayout(self.horizontalLayout) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.btn_db = QtWidgets.QPushButton(self.widget) - self.btn_db.setObjectName("btn_db") - self.horizontalLayout_2.addWidget(self.btn_db) - self.label_db = QtWidgets.QLabel(self.widget) - self.label_db.setObjectName("label_db") - self.horizontalLayout_2.addWidget(self.label_db) - self.verticalLayout.addLayout(self.horizontalLayout_2) - self.pushButton_3 = QtWidgets.QPushButton(self.widget) - self.pushButton_3.setObjectName("pushButton_3") - self.verticalLayout.addWidget(self.pushButton_3) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - self.label_3.setText(_translate("Dialog", "解密数据库")) - self.btn_xml.setText(_translate("Dialog", "点击加载xml文件")) - self.label_xml.setText(_translate("Dialog", "xml未就绪")) - self.btn_db.setText(_translate("Dialog", "点击加载数据库文件")) - self.label_db.setText(_translate("Dialog", "数据库未就绪")) - self.pushButton_3.setText(_translate("Dialog", "开始解密数据库")) diff --git a/app/Ui/mainview.py b/app/Ui/mainview.py deleted file mode 100644 index 74b6129..0000000 --- a/app/Ui/mainview.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : mainview.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 15:07 -@IDE : Pycharm -@Version : Python3.10 -@comment : 主窗口 -""" -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * - -from app import config -from app.DataBase import data -from app.Ui import mainwindow -from app.Ui.Icon import Icon -from app.Ui.chat import chat -from app.Ui.contact import contact -from app.components.prompt_bar import PromptBar -from app.person import Me - - -class MainWinController(QMainWindow, mainwindow.Ui_MainWindow): - exitSignal = pyqtSignal() - - # username = '' - def __init__(self, username, parent=None): - super(MainWinController, self).__init__(parent) - self.setupUi(self) - self.setWindowIcon(Icon.MainWindow_Icon) - - self.setAttribute(Qt.WA_AttributeCount) - self.Me = Me(data.get_myinfo()) - self.chatView = chat.ChatController(self.Me, parent=None) - self.lay = QHBoxLayout() - self.page_chat.setLayout(self.lay) - self.lay.addWidget(self.chatView) - - self.contactView = contact.ContactController(self.Me, parent=None) - self.lay0 = QHBoxLayout() - self.page_contact.setLayout(self.lay0) - self.lay0.addWidget(self.contactView) - - self.btn_chat.clicked.connect(self.chat_view) # 聊天按钮 - self.btn_contact.clicked.connect(self.contact_view) - # self.btn_myinfo.clicked.connect(self.myInfo) - self.btn_about.clicked.connect(self.about) - self.now_btn = self.btn_chat - self.btn_chat.setIcon(Icon.Chat_Icon) - self.btn_contact.setIcon(Icon.Contact_Icon) - self.btn_myinfo.setIcon(Icon.MyInfo_Icon) - self.btn_about.setIcon(Icon.MainWindow_Icon) - self.btn_about.setContextMenuPolicy(Qt.CustomContextMenu) - self.btn_about.customContextMenuRequested.connect(self.create_rightmenu) # 连接到菜单显示函数 - self.last_btn = None - self.lastView = None - self.show_avatar() - self.init_ui() - self.menubar.setVisible(False) - self.statusbar.setVisible(False) - self.prompt_bar = PromptBar(self) - self.chat_view() - - def init_ui(self): - # self.setWindowFlags(QtCore.Qt.FramelessWindowHint) - self.menubar.setStyleSheet("background-color: rgb(240, 240, 240);") - - def create_rightmenu(self): - # 菜单对象 - self.groupBox_menu = QMenu(self) - - self.actionA = QAction(QIcon('image/保存.png'), u'保存数据', - self) # self.actionA = self.contextMenu.addAction(QIcon("images/0.png"),u'| 动作A') - self.actionA.setShortcut('Ctrl+S') # 设置快捷键 - self.groupBox_menu.addAction(self.actionA) # 把动作A选项添加到菜单 - - self.actionB = QAction(QIcon('image/删除.png'), u'删除数据', self) - self.groupBox_menu.addAction(self.actionB) - - # self.actionA.triggered.connect(self.button) # 将动作A触发时连接到槽函数 button - # self.actionB.triggered.connect(self.button_2) - - self.groupBox_menu.popup(QCursor.pos()) # 声明当鼠标在groupBox控件上右击时,在鼠标位置显示右键菜单 ,exec_,popup两个都可以, - - def show_avatar(self): - avatar = self.Me.avatar - pixmap = QPixmap(avatar).scaled(60, 60) # 按指定路径找到图片 - self.myavatar.setPixmap(pixmap) # 在label上显示图片 - - def chat_view(self): - """ - 聊天窗口 - """ - self.now_btn = self.btn_chat - self.now_btn.setStyleSheet( - "QPushButton {background-color: rgb(198,198,198);border:none;}") - if self.last_btn and self.last_btn != self.now_btn: - self.last_btn.setStyleSheet( - "QPushButton {" - "background-color: rgb(240,240,240);" - "border:none;" - "}" - "QPushButton:hover{background-color: rgb(209,209,209);}\n" - ) - self.last_btn = self.btn_chat - # self.state_lable.setGeometry(20, 300, 32, 32) - self.stackedWidget.setCurrentIndex(0) - self.chatView.showChat() - - def contact_view(self): - """ - 联系人窗口 - """ - self.now_btn = self.btn_contact - self.now_btn.setStyleSheet( - "QPushButton {background-color: rgb(198,198,198);border:none;}") - if self.last_btn and self.last_btn != self.now_btn: - self.last_btn.setStyleSheet("QPushButton {background-color: rgb(240,240,240);border:none;}" - "QPushButton:hover{background-color: rgb(209,209,209);}\n") - self.last_btn = self.btn_contact - # geometry = self.btn_chat.geometry() - # self.state_lable.setGeometry(geometry) - self.stackedWidget.setCurrentIndex(1) - - def myInfo(self): - """ - 显示我的个人信息 - """ - self.now_btn = self.btn_myinfo - self.now_btn.setStyleSheet( - "QPushButton {background-color: rgb(198,198,198);}") - if self.last_btn and self.last_btn != self.now_btn: - self.last_btn.setStyleSheet("QPushButton {background-color: rgb(240,240,240);}" - "QPushButton:hover{background-color: rgb(209,209,209);}\n") - self.last_btn = self.now_btn - - def about(self): - """ - 关于 - """ - QMessageBox.about(self, "关于", - f"版本:{config.version}\n" - f"QQ交流群:{config.contact}\n" - "地址:https://github.com/LC044/WeChatMsg" - ) diff --git a/app/Ui/mainwindow.py b/app/Ui/mainwindow.py deleted file mode 100644 index b335a05..0000000 --- a/app/Ui/mainwindow.py +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'mainwindow.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.resize(1280, 779) - MainWindow.setStyleSheet("QPushButton {\n" - "background-color: rgb(240,240,240);\n" - "border:none;\n" - "}\n" - "QPushButton:hover{\n" - "background-color: rgb(209,209,209);\n" - "}\n" - " ") - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setSpacing(0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.frame_info = QtWidgets.QFrame(self.centralwidget) - self.frame_info.setMinimumSize(QtCore.QSize(80, 500)) - self.frame_info.setMaximumSize(QtCore.QSize(80, 16777215)) - self.frame_info.setStyleSheet("background-color:rgb(240,240,240)") - self.frame_info.setFrameShape(QtWidgets.QFrame.NoFrame) - self.frame_info.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame_info.setObjectName("frame_info") - self.verticalLayoutWidget = QtWidgets.QWidget(self.frame_info) - self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 190, 77, 271)) - self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") - self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) - self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) - self.verticalLayout_2.setSpacing(0) - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.btn_chat = QtWidgets.QPushButton(self.verticalLayoutWidget) - self.btn_chat.setMinimumSize(QtCore.QSize(0, 60)) - font = QtGui.QFont() - font.setFamily("微软雅黑") - self.btn_chat.setFont(font) - self.btn_chat.setStyleSheet("QPushButton {\n" - "background-color: rgb(240,240,240);\n" - "border:none;\n" - "}\n" - "QPushButton:hover{background-color: rgb(209,209,209);}\n" - " ") - self.btn_chat.setAutoDefault(True) - self.btn_chat.setDefault(False) - self.btn_chat.setFlat(False) - self.btn_chat.setObjectName("btn_chat") - self.verticalLayout_2.addWidget(self.btn_chat) - self.btn_contact = QtWidgets.QPushButton(self.verticalLayoutWidget) - self.btn_contact.setMinimumSize(QtCore.QSize(0, 60)) - font = QtGui.QFont() - font.setFamily("微软雅黑") - self.btn_contact.setFont(font) - self.btn_contact.setStyleSheet("QPushButton {\n" - "background-color: rgb(240,240,240);\n" - "border:none;\n" - "}\n" - "QPushButton:hover{\n" - "background-color: rgb(209,209,209);\n" - "}\n" - " ") - self.btn_contact.setDefault(True) - self.btn_contact.setFlat(False) - self.btn_contact.setObjectName("btn_contact") - self.verticalLayout_2.addWidget(self.btn_contact) - self.btn_myinfo = QtWidgets.QPushButton(self.verticalLayoutWidget) - self.btn_myinfo.setMinimumSize(QtCore.QSize(60, 60)) - font = QtGui.QFont() - font.setFamily("微软雅黑") - self.btn_myinfo.setFont(font) - self.btn_myinfo.setFlat(False) - self.btn_myinfo.setObjectName("btn_myinfo") - self.verticalLayout_2.addWidget(self.btn_myinfo) - self.btn_about = QtWidgets.QPushButton(self.verticalLayoutWidget) - self.btn_about.setMinimumSize(QtCore.QSize(60, 60)) - font = QtGui.QFont() - font.setFamily("微软雅黑") - self.btn_about.setFont(font) - self.btn_about.setStyleSheet("QPushButton {background-color: rgb(240,240,240);}\n" - " QPushButton:hover{background-color: rgb(209,209,209);}\n" - " ") - self.btn_about.setFlat(False) - self.btn_about.setObjectName("btn_about") - self.verticalLayout_2.addWidget(self.btn_about) - self.verticalLayout_2.setStretch(0, 1) - self.verticalLayout_2.setStretch(1, 1) - self.verticalLayout_2.setStretch(2, 1) - self.verticalLayout_2.setStretch(3, 1) - self.myavatar = QtWidgets.QLabel(self.frame_info) - self.myavatar.setGeometry(QtCore.QRect(10, 40, 60, 60)) - self.myavatar.setObjectName("myavatar") - self.horizontalLayout.addWidget(self.frame_info) - self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget) - font = QtGui.QFont() - font.setFamily("微软雅黑") - font.setBold(False) - font.setWeight(50) - self.stackedWidget.setFont(font) - self.stackedWidget.setObjectName("stackedWidget") - self.page_chat = QtWidgets.QWidget() - self.page_chat.setObjectName("page_chat") - self.stackedWidget.addWidget(self.page_chat) - self.page_contact = QtWidgets.QWidget() - self.page_contact.setObjectName("page_contact") - self.stackedWidget.addWidget(self.page_contact) - self.page_myinfo = QtWidgets.QWidget() - self.page_myinfo.setObjectName("page_myinfo") - self.stackedWidget.addWidget(self.page_myinfo) - self.page_2 = QtWidgets.QWidget() - self.page_2.setObjectName("page_2") - self.stackedWidget.addWidget(self.page_2) - self.horizontalLayout.addWidget(self.stackedWidget) - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 23)) - self.menubar.setObjectName("menubar") - self.menu_F = QtWidgets.QMenu(self.menubar) - self.menu_F.setObjectName("menu_F") - self.menu = QtWidgets.QMenu(self.menubar) - font = QtGui.QFont() - font.setFamily("微软雅黑") - self.menu.setFont(font) - self.menu.setObjectName("menu") - self.menu_2 = QtWidgets.QMenu(self.menubar) - self.menu_2.setObjectName("menu_2") - MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - self.action_3 = QtWidgets.QAction(MainWindow) - self.action_3.setObjectName("action_3") - self.action_4 = QtWidgets.QAction(MainWindow) - self.action_4.setObjectName("action_4") - self.action = QtWidgets.QAction(MainWindow) - font = QtGui.QFont() - font.setFamily("Microsoft YaHei UI") - self.action.setFont(font) - self.action.setObjectName("action") - self.menu_F.addSeparator() - self.menu_F.addSeparator() - self.menu_F.addAction(self.action_3) - self.menu_F.addAction(self.action_4) - self.menu_2.addAction(self.action) - self.menubar.addAction(self.menu_F.menuAction()) - self.menubar.addAction(self.menu.menuAction()) - self.menubar.addAction(self.menu_2.menuAction()) - - self.retranslateUi(MainWindow) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) - self.btn_chat.setText(_translate("MainWindow", "聊天")) - self.btn_contact.setText(_translate("MainWindow", "好友")) - self.btn_myinfo.setText(_translate("MainWindow", "我的")) - self.btn_about.setText(_translate("MainWindow", "关于")) - self.myavatar.setText(_translate("MainWindow", "avatar")) - self.menu_F.setTitle(_translate("MainWindow", "文件(F)")) - self.menu.setTitle(_translate("MainWindow", "编辑")) - self.menu_2.setTitle(_translate("MainWindow", "帮助")) - self.action_3.setText(_translate("MainWindow", "保存")) - self.action_4.setText(_translate("MainWindow", "退出")) - self.action.setText(_translate("MainWindow", "关于")) diff --git a/app/Ui/userinfo/userinfo.py b/app/Ui/userinfo/userinfo.py deleted file mode 100644 index 8435ff4..0000000 --- a/app/Ui/userinfo/userinfo.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : contact.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 15:07 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" -from PyQt5.QtCore import * -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * - -from .userinfoUi import * -from ...DataBase import data - - -class MyinfoController(QWidget, Ui_Dialog): - exitSignal = pyqtSignal() - urlSignal = pyqtSignal(QUrl) - - # username = '' - - def __init__(self, Me, parent=None): - super(MyinfoController, self).__init__(parent) - self.setupUi(self) - self.setWindowTitle('WeChat') - self.setWindowIcon(QIcon('./app/data/icon.png')) - self.Me = Me - self.initui() - - def initui(self): - self.myinfo = data.get_myInfo() - avatar = self.Me.my_avatar - pixmap = QPixmap(avatar).scaled(80, 80) # 按指定路径找到图片 - self.label_avatar.setPixmap(pixmap) # 在label上显示图片 - self.label_name.setText(self.myinfo['name']) - self.label_wxid.setText('微信号:' + self.myinfo['username']) - city = f"地区:{self.myinfo['province']}{self.myinfo['city']}" - self.label_city.setText(city) diff --git a/app/Ui/userinfo/userinfoUi.py b/app/Ui/userinfo/userinfoUi.py deleted file mode 100644 index 81b47fd..0000000 --- a/app/Ui/userinfo/userinfoUi.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'userinfoUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(1120, 720) - Dialog.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - Dialog.setAutoFillBackground(False) - self.frame_2 = QtWidgets.QFrame(Dialog) - self.frame_2.setGeometry(QtCore.QRect(0, 0, 1120, 720)) - self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_2.setObjectName("frame_2") - self.horizontalLayoutWidget = QtWidgets.QWidget(self.frame_2) - self.horizontalLayoutWidget.setGeometry(QtCore.QRect(340, 60, 291, 82)) - self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.label_avatar = QtWidgets.QLabel(self.horizontalLayoutWidget) - self.label_avatar.setMinimumSize(QtCore.QSize(80, 80)) - self.label_avatar.setObjectName("label_avatar") - self.horizontalLayout.addWidget(self.label_avatar) - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.label_name = QtWidgets.QLabel(self.horizontalLayoutWidget) - self.label_name.setObjectName("label_name") - self.verticalLayout.addWidget(self.label_name) - self.label_wxid = QtWidgets.QLabel(self.horizontalLayoutWidget) - self.label_wxid.setObjectName("label_wxid") - self.verticalLayout.addWidget(self.label_wxid) - self.label_city = QtWidgets.QLabel(self.horizontalLayoutWidget) - self.label_city.setObjectName("label_city") - self.verticalLayout.addWidget(self.label_city) - self.horizontalLayout.addLayout(self.verticalLayout) - self.horizontalLayout.setStretch(0, 1) - self.horizontalLayout.setStretch(1, 3) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - self.label_avatar.setText(_translate("Dialog", "TextLabel")) - self.label_name.setText(_translate("Dialog", "TextLabel")) - self.label_wxid.setText(_translate("Dialog", "TextLabel")) - self.label_city.setText(_translate("Dialog", "TextLabel")) diff --git a/app/decrypt/get_wx_info.py b/app/decrypt/get_wx_info.py index 208743f..9b84414 100644 --- a/app/decrypt/get_wx_info.py +++ b/app/decrypt/get_wx_info.py @@ -107,15 +107,29 @@ def get_info_wxid(h_process): def get_info_filePath(wxid="all"): if not wxid: return "None" + w_dir = "MyDocument:" + is_w_dir = False + try: - user_profile = os.environ.get("USERPROFILE") - path_3ebffe94 = os.path.join(user_profile, "AppData", "Roaming", "Tencent", "WeChat", "All Users", "config", - "3ebffe94.ini") - with open(path_3ebffe94, "r", encoding="utf-8") as f: - w_dir = f.read() + key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Tencent\WeChat", 0, winreg.KEY_READ) + value, _ = winreg.QueryValueEx(key, "FileSavePath") + winreg.CloseKey(key) + w_dir = value + is_w_dir = True except Exception as e: w_dir = "MyDocument:" + if not is_w_dir: + try: + user_profile = os.environ.get("USERPROFILE") + path_3ebffe94 = os.path.join(user_profile, "AppData", "Roaming", "Tencent", "WeChat", "All Users", "config", + "3ebffe94.ini") + with open(path_3ebffe94, "r", encoding="utf-8") as f: + w_dir = f.read() + is_w_dir = True + except Exception as e: + w_dir = "MyDocument:" + if w_dir == "MyDocument:": try: # 打开注册表路径 @@ -154,6 +168,8 @@ def get_key(db_path, addr_len): return key_bytes def verify_key(key, wx_db_path): + if not wx_db_path: + return True KEY_SIZE = 32 DEFAULT_PAGESIZE = 4096 DEFAULT_ITER = 64000 diff --git a/app/person.py b/app/person.py deleted file mode 100644 index b6f00bf..0000000 --- a/app/person.py +++ /dev/null @@ -1,108 +0,0 @@ -import os.path -from typing import Dict - -from PyQt5.QtCore import Qt -from PyQt5.QtGui import QPixmap - -from app.DataBase import data -from app.ui_pc.Icon import Icon - - -# from app.Ui.Icon import Icon - - -class Person: - def __init__(self, wxid: str): - - self.wxid = wxid - self.conRemark = data.get_conRemark(wxid) - self.nickname, self.alias = data.get_nickname(wxid) - self.avatar_path = data.get_avator(wxid) - if os.path.exists(self.avatar_path): - self.avatar = QPixmap(self.avatar_path).scaled(60, 60) - else: - self.avatar_path = './app/data/icons/default_avatar.svg' - # self.avatar_path = Icon.Default_avatar_path - self.avatar = QPixmap(self.avatar_path).scaled(60, 60) - - -class Me(Person): - def __init__(self, wxid: str): - super(Me, self).__init__(wxid) - self.city = None - self.province = None - - -class Contact(Person): - def __init__(self, wxid: str): - super(Contact, self).__init__(wxid) - self.smallHeadImgUrl = '' - self.bigHeadImgUrl = '' - - -def singleton(cls): - _instance = {} - - def inner(): - if cls not in _instance: - _instance[cls] = cls() - return _instance[cls] - - return inner - - -@singleton -class MePC: - def __init__(self): - self.avatar = QPixmap(Icon.Default_avatar_path) - self.avatar_path = 'D:\Project\Python\WeChatMsg\\app\data\icons\default_avatar.svg' - self.wxid = '' - self.wx_dir = '' - self.name = '' - self.mobile = '' - - def set_avatar(self, img_bytes): - if not img_bytes: - self.avatar.load(Icon.Default_avatar_path) - return - if img_bytes[:4] == b'\x89PNG': - self.avatar.loadFromData(img_bytes, format='PNG') - else: - self.avatar.loadFromData(img_bytes, format='jfif') - - -class ContactPC: - def __init__(self, contact_info: Dict): - self.wxid = contact_info.get('UserName') - self.remark = contact_info.get('Remark') - # Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl - self.alias = contact_info.get('Alias') - self.nickName = contact_info.get('NickName') - if not self.remark: - self.remark = self.nickName - self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl') - self.smallHeadImgBLOG = b'' - self.avatar = QPixmap() - self.avatar_path = 'D:\Project\Python\WeChatMsg\\app\data\icons\default_avatar.svg' - - def set_avatar(self, img_bytes): - if not img_bytes: - self.avatar.load(Icon.Default_avatar_path) - return - if img_bytes[:4] == b'\x89PNG': - self.avatar.loadFromData(img_bytes, format='PNG') - else: - self.avatar.loadFromData(img_bytes, format='jfif') - - self.avatar.scaled(60, 60, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) - - -class Group(Person): - def __init__(self, wxid: str): - super(Group, self).__init__(wxid) - - -if __name__ == '__main__': - p1 = MePC() - p2 = MePC() - print(p1 == p2) diff --git a/app/person_pc.py b/app/person_pc.py index f1027b3..3671e66 100644 --- a/app/person_pc.py +++ b/app/person_pc.py @@ -5,7 +5,7 @@ from typing import Dict from PyQt5.QtCore import Qt from PyQt5.QtGui import QPixmap -from app.ui_pc.Icon import Icon +from app.ui.Icon import Icon def singleton(cls): diff --git a/app/ui_pc/Icon.py b/app/ui_pc/Icon.py deleted file mode 100644 index 4fbff96..0000000 --- a/app/ui_pc/Icon.py +++ /dev/null @@ -1,28 +0,0 @@ -from PyQt5.QtGui import QIcon - -from app.resources import resource_rc - -var = resource_rc.qt_resource_name - - -class Icon: - Default_avatar_path = ':/icons/icons/default_avatar.svg' - Default_image_path = ':/icons/icons/404.png' - MainWindow_Icon = QIcon(':/icons/icons/logo.svg') - Default_avatar = QIcon(Default_avatar_path) - Output = QIcon(':/icons/icons/output.svg') - Back = QIcon(':/icons/icons/back.svg') - ToDocx = QIcon(':/icons/icons/word.svg') - ToCSV = QIcon(':/icons/icons/csv.svg') - ToHTML = QIcon(':/icons/icons/html.svg') - ToTXT = QIcon(':/icons/icons/txt.svg') - Chat_Icon = QIcon(':/icons/icons/chat.svg') - Contact_Icon = QIcon(':/icons/icons/contact.svg') - MyInfo_Icon = QIcon(':/icons/icons/myinfo.svg') - Annual_Report_Icon = QIcon(':/icons/icons/annual_report.svg') - Analysis_Icon = QIcon(':/icons/icons/analysis.svg') - Emotion_Icon = QIcon(':/icons/icons/emotion.svg') - Search_Icon = QIcon(':/icons/icons/search.svg') - Tool_Icon = QIcon(':/icons/icons/tool.svg') - Home_Icon = QIcon(':/icons/icons/home.svg') - Help_Icon = QIcon(':/icons/icons/help.svg') diff --git a/app/ui_pc/__init__.py b/app/ui_pc/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/ui_pc/chat/__init__.py b/app/ui_pc/chat/__init__.py deleted file mode 100644 index 00e557b..0000000 --- a/app/ui_pc/chat/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .chat_window import ChatWindow diff --git a/app/ui_pc/chat/chatInfoUi.py b/app/ui_pc/chat/chatInfoUi.py deleted file mode 100644 index 62c03c5..0000000 --- a/app/ui_pc/chat/chatInfoUi.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'chatInfoUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - self.verticalLayout = QtWidgets.QVBoxLayout(Form) - self.verticalLayout.setContentsMargins(0, 0, 0, 0) - self.verticalLayout.setSpacing(0) - self.verticalLayout.setObjectName("verticalLayout") - self.frame = QtWidgets.QFrame(Form) - self.frame.setFrameShape(QtWidgets.QFrame.NoFrame) - self.frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame.setObjectName("frame") - self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame) - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.label_reamrk = QtWidgets.QLabel(self.frame) - self.label_reamrk.setObjectName("label_reamrk") - self.horizontalLayout_2.addWidget(self.label_reamrk) - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem) - self.toolButton = QtWidgets.QToolButton(self.frame) - self.toolButton.setObjectName("toolButton") - self.horizontalLayout_2.addWidget(self.toolButton) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - - self.verticalLayout.addWidget(self.frame) - - self.retranslateUi(Form) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.label_reamrk.setText(_translate("Form", "TextLabel")) - self.toolButton.setText(_translate("Form", "...")) diff --git a/app/ui_pc/chat/chatUi.py b/app/ui_pc/chat/chatUi.py deleted file mode 100644 index ddf83ec..0000000 --- a/app/ui_pc/chat/chatUi.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'chatUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(840, 752) - Form.setStyleSheet("background: rgb(240, 240, 240);") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form) - self.horizontalLayout_2.setSpacing(6) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setSpacing(6) - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(Form) - self.label.setText("") - self.label.setObjectName("label") - self.horizontalLayout.addWidget(self.label) - self.lineEdit = QtWidgets.QLineEdit(Form) - self.lineEdit.setMinimumSize(QtCore.QSize(200, 30)) - self.lineEdit.setMaximumSize(QtCore.QSize(200, 16777215)) - self.lineEdit.setStyleSheet("background:transparent;\n" - "border-radius:5px;\n" - "border-top: 0px solid #b2e281;\n" - "border-bottom: 0px solid #b2e281;\n" - "border-right: 0px solid #b2e281;\n" - "border-left: 0px solid #b2e281;\n" - "border-style:outset;\n" - "background-color:rgb(226,226,226);\n" - " ") - self.lineEdit.setCursorMoveStyle(QtCore.Qt.VisualMoveStyle) - self.lineEdit.setObjectName("lineEdit") - self.horizontalLayout.addWidget(self.lineEdit) - self.label_2 = QtWidgets.QLabel(Form) - self.label_2.setMinimumSize(QtCore.QSize(30, 0)) - self.label_2.setText("") - self.label_2.setObjectName("label_2") - self.horizontalLayout.addWidget(self.label_2) - self.verticalLayout.addLayout(self.horizontalLayout) - self.verticalLayout_2.addLayout(self.verticalLayout) - self.listWidget = QtWidgets.QListWidget(Form) - self.listWidget.setMinimumSize(QtCore.QSize(250, 0)) - self.listWidget.setMaximumSize(QtCore.QSize(250, 16777215)) - self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.listWidget.setObjectName("listWidget") - self.verticalLayout_2.addWidget(self.listWidget) - self.verticalLayout_2.setStretch(1, 1) - self.horizontalLayout_2.addLayout(self.verticalLayout_2) - self.stackedWidget = QtWidgets.QStackedWidget(Form) - self.stackedWidget.setObjectName("stackedWidget") - self.horizontalLayout_2.addWidget(self.stackedWidget) - self.horizontalLayout_2.setStretch(1, 1) - - self.retranslateUi(Form) - self.stackedWidget.setCurrentIndex(-1) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) diff --git a/app/ui_pc/chat/chat_info.py b/app/ui_pc/chat/chat_info.py deleted file mode 100644 index 5735824..0000000 --- a/app/ui_pc/chat/chat_info.py +++ /dev/null @@ -1,160 +0,0 @@ -import traceback - -from PyQt5.QtCore import QThread, pyqtSignal -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout - -from app.DataBase import msg_db, hard_link_db -from app.components.bubble_message import BubbleMessage, ChatWidget, Notice -from app.person_pc import MePC -from app.util import get_abs_path -from app.util.emoji import get_emoji - - -class ChatInfo(QWidget): - def __init__(self, contact, parent=None): - super().__init__(parent) - self.last_timestamp = 0 - self.last_str_time = '' - self.last_pos = 0 - self.contact = contact - self.init_ui() - self.show_chats() - - def init_ui(self): - self.label_reamrk = QLabel(self.contact.remark) - - self.hBoxLayout = QHBoxLayout() - self.hBoxLayout.addWidget(self.label_reamrk) - - self.vBoxLayout = QVBoxLayout() - self.vBoxLayout.setSpacing(0) - self.vBoxLayout.addLayout(self.hBoxLayout) - - self.chat_window = ChatWidget() - self.chat_window.scrollArea.verticalScrollBar().valueChanged.connect(self.verticalScrollBar) - self.vBoxLayout.addWidget(self.chat_window) - self.setLayout(self.vBoxLayout) - - def show_chats(self): - self.show_chat_thread = ShowChatThread(self.contact) - self.show_chat_thread.showSingal.connect(self.add_message) - self.show_chat_thread.finishSingal.connect(self.show_finish) - # self.show_chat_thread.start() - - def show_finish(self, ok): - self.setScrollBarPos() - self.show_chat_thread.quit() - - def verticalScrollBar(self, pos): - """ - 滚动条到0之后自动更新聊天记录 - :param pos: - :return: - """ - # print(pos) - if pos > 0: - return - - # 记录当前滚动条最大值 - self.last_pos = self.chat_window.verticalScrollBar().maximum() - self.update_history_messages() - - def update_history_messages(self): - self.show_chat_thread.start() - - def setScrollBarPos(self): - """ - 将滚动条位置设置为上次看到的地方 - :param pos: - :return: - """ - self.chat_window.update() - self.chat_window.show() - pos = self.chat_window.verticalScrollBar().maximum() - self.last_pos - self.chat_window.set_scroll_bar_value(pos) - - def is_5_min(self, timestamp): - if abs(timestamp - self.last_timestamp) > 300: - self.last_timestamp = timestamp - return True - return False - - def add_message(self, message): - try: - type_ = message[2] - str_content = message[7] - str_time = message[8] - # print(type_, type(type_)) - is_send = message[4] - avatar = MePC().avatar if is_send else self.contact.avatar - timestamp = message[5] - BytesExtra = message[10] - if type_ == 1: - if self.is_5_min(timestamp): - time_message = Notice(self.last_str_time) - self.last_str_time = str_time - self.chat_window.add_message_item(time_message, 0) - bubble_message = BubbleMessage( - str_content, - avatar, - type_, - is_send - ) - self.chat_window.add_message_item(bubble_message, 0) - elif type_ == 3: - # return - if self.is_5_min(timestamp): - time_message = Notice(self.last_str_time) - self.last_str_time = str_time - self.chat_window.add_message_item(time_message, 0) - image_path = hard_link_db.get_image(content=str_content,bytesExtra=BytesExtra, thumb=False) - image_path = get_abs_path(image_path) - bubble_message = BubbleMessage( - image_path, - avatar, - type_, - is_send - ) - self.chat_window.add_message_item(bubble_message, 0) - elif type_ == 47: - return - if self.is_5_min(timestamp): - time_message = Notice(self.last_str_time) - self.last_str_time = str_time - self.chat_window.add_message_item(time_message, 0) - image_path = get_emoji(str_content, thumb=True) - bubble_message = BubbleMessage( - image_path, - avatar, - 3, - is_send - ) - self.chat_window.add_message_item(bubble_message, 0) - elif type_ == 10000: - str_content = str_content.lstrip('').rstrip('') - message = Notice(str_content ) - self.chat_window.add_message_item(message, 0) - except: - print(message) - traceback.print_exc() - - -class ShowChatThread(QThread): - showSingal = pyqtSignal(tuple) - finishSingal = pyqtSignal(int) - msg_id = 0 - - # heightSingal = pyqtSignal(int) - def __init__(self, contact): - super().__init__() - self.last_message_id = 9999999999 - self.wxid = contact.wxid - - def run(self) -> None: - messages = msg_db.get_message_by_num(self.wxid, self.last_message_id) - if messages: - self.last_message_id = messages[-1][0] - for message in messages: - self.showSingal.emit(message) - self.msg_id += 1 - self.finishSingal.emit(1) diff --git a/app/ui_pc/chat/chat_window.py b/app/ui_pc/chat/chat_window.py deleted file mode 100644 index b2fa2fb..0000000 --- a/app/ui_pc/chat/chat_window.py +++ /dev/null @@ -1,165 +0,0 @@ -from PyQt5.QtCore import QThread, pyqtSignal -from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit - -from app.DataBase import micro_msg_db, misc_db, msg_db -from app.components import ContactQListWidgetItem -from app.person_pc import ContactPC -from app.ui_pc.Icon import Icon -from app.util import search -from .chatUi import Ui_Form -from .chat_info import ChatInfo - -# 美化样式表 -Stylesheet = """ - -/*去掉item虚线边框*/ -QListWidget, QListView, QTreeWidget, QTreeView { - outline: 0px; - border:none; - background-color:rgb(240,240,240) -} -/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/ -QListWidget { - min-width: 250px; - max-width: 250px; - min-height: 80px; - max-height: 1200px; - color: black; - border:none; -} -QListWidget::item{ - height:60px; - width:250px; -} -/*被选中时的背景颜色和左边框颜色*/ -QListWidget::item:selected { - background: rgb(204, 204, 204); - border-bottom: 2px solid rgb(9, 187, 7); - border-left:none; - color: black; - font-weight: bold; -} -/*鼠标悬停颜色*/ -HistoryPanel::item:hover { - background: rgb(52, 52, 52); -} -""" - - -class ChatWindow(QWidget, Ui_Form): - load_finish_signal = pyqtSignal(bool) - - def __init__(self, parent=None): - super().__init__(parent) - self.show_thread = None - self.setupUi(self) - self.ok_flag = False - self.setStyleSheet(Stylesheet) - self.contacts = [[], []] - self.init_ui() - self.show_chats() - self.visited = set() - - def init_ui(self): - search_action = QAction(self.lineEdit) - search_action.setIcon(Icon.Search_Icon) - self.lineEdit.addAction(search_action, QLineEdit.LeadingPosition) - self.lineEdit.returnPressed.connect(self.search_contact) - self.listWidget.clear() - self.listWidget.currentRowChanged.connect(self.setCurrentIndex) - self.listWidget.setCurrentRow(0) - self.stackedWidget.setCurrentIndex(0) - - def show_chats(self): - # return - if self.ok_flag: - return - msg_db.init_database() - micro_msg_db.init_database() - if not msg_db.open_flag: - QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库") - self.show_thread = ShowThread() - self.show_thread.load_finish_signal.connect(self.load_finish_signal) - self.show_thread.start() - return - self.show_thread = ShowContactThread() - self.show_thread.showSingal.connect(self.show_chat) - self.show_thread.load_finish_signal.connect(self.stop_loading) - self.show_thread.start() - self.ok_flag = True - - def search_contact(self): - content = self.lineEdit.text() - if not content: - return - index = self.search_contact_index(content) - self.select_contact_by_index(index) - - def search_contact_index(self, content: str) -> int: - return search.search_by_content(content, self.contacts) - - def select_contact_by_index(self, index): - self.stackedWidget.setCurrentIndex(index) - self.listWidget.setCurrentRow(index) - - def show_chat(self, contact): - self.contacts[0].append(contact.remark) - self.contacts[1].append(contact.nickName) - contact_item = ContactQListWidgetItem(contact.remark, contact.smallHeadImgUrl, contact.smallHeadImgBLOG) - self.listWidget.addItem(contact_item) - self.listWidget.setItemWidget(contact_item, contact_item.widget) - chat_info_window = ChatInfo(contact) - self.stackedWidget.addWidget(chat_info_window) - - def setCurrentIndex(self, row): - # print(row) - self.stackedWidget.setCurrentIndex(row) - if row not in self.visited: - chat_info_window = self.stackedWidget.currentWidget() - chat_info_window.update_history_messages() - self.visited.add(row) - - def stop_loading(self, a0): - # self.label.setVisible(False) - self.load_finish_signal.emit(True) - - -class ShowContactThread(QThread): - showSingal = pyqtSignal(ContactPC) - load_finish_signal = pyqtSignal(bool) - - # heightSingal = pyqtSignal(int) - def __init__(self): - super().__init__() - - def run(self) -> None: - contact_info_lists = micro_msg_db.get_contact() - for contact_info_list in contact_info_lists: - # UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl - contact_info = { - 'UserName': contact_info_list[0], - 'Alias': contact_info_list[1], - 'Type': contact_info_list[2], - 'Remark': contact_info_list[3], - 'NickName': contact_info_list[4], - 'smallHeadImgUrl': contact_info_list[7] - } - contact = ContactPC(contact_info) - contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid) - contact.set_avatar(contact.smallHeadImgBLOG) - self.showSingal.emit(contact) - # pprint(contact.__dict__) - self.load_finish_signal.emit(True) - - -class ShowThread(QThread): - showSingal = pyqtSignal(ContactPC) - load_finish_signal = pyqtSignal(bool) - - # heightSingal = pyqtSignal(int) - def __init__(self): - super().__init__() - - def run(self) -> None: - QThread.sleep(1) - self.load_finish_signal.emit(True) diff --git a/app/ui_pc/contact/__init__.py b/app/ui_pc/contact/__init__.py deleted file mode 100644 index a83ae0a..0000000 --- a/app/ui_pc/contact/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .contact_window import ContactWindow diff --git a/app/ui_pc/contact/contactInfo.py b/app/ui_pc/contact/contactInfo.py deleted file mode 100644 index 7161478..0000000 --- a/app/ui_pc/contact/contactInfo.py +++ /dev/null @@ -1,162 +0,0 @@ -from PyQt5.QtCore import pyqtSignal, QUrl, QThread -from PyQt5.QtGui import QDesktopServices -from PyQt5.QtWidgets import QWidget, QMenu, QAction, QToolButton, QMessageBox, QDialog - -from app.DataBase.output_pc import Output -from app.ui_pc.Icon import Icon -from .contactInfoUi import Ui_Form -from .userinfo import userinfo -from ...person_pc import ContactPC -from .export_dialog import ExportDialog - - -class ContactInfo(QWidget, Ui_Form): - exitSignal = pyqtSignal() - urlSignal = pyqtSignal(QUrl) - - # username = '' - def __init__(self, contact, parent=None): - super(ContactInfo, self).__init__(parent) - self.setupUi(self) - self.contact: ContactPC = contact - self.view_userinfo = userinfo.UserinfoController(self.contact) - self.btn_back.clicked.connect(self.back) - self.init_ui() - - def init_ui(self): - self.btn_back.setIcon(Icon.Back) - self.btn_report.setIcon(Icon.Annual_Report_Icon) - self.btn_analysis.setIcon(Icon.Analysis_Icon) - self.btn_emotion.setIcon(Icon.Emotion_Icon) - self.btn_report.clicked.connect(self.annual_report) - self.btn_analysis.clicked.connect(self.analysis) - self.btn_emotion.clicked.connect(self.emotionale_Analysis) - self.label_remark.setText(self.contact.remark) - self.stackedWidget.addWidget(self.view_userinfo) - self.stackedWidget.setCurrentWidget(self.view_userinfo) - menu = QMenu(self) - self.toDocxAct = QAction(Icon.ToDocx, '导出Docx', self) - self.toCSVAct = QAction(Icon.ToCSV, '导出CSV', self) - self.toHtmlAct = QAction(Icon.ToHTML, '导出HTML', self) - self.toTxtAct = QAction(Icon.ToTXT, '导出TXT', self) - self.toolButton_output.setPopupMode(QToolButton.MenuButtonPopup) - self.toolButton_output.clicked.connect(self.toolButton_show) - menu.addAction(self.toDocxAct) - menu.addAction(self.toCSVAct) - menu.addAction(self.toHtmlAct) - menu.addAction(self.toTxtAct) - self.toolButton_output.setMenu(menu) - self.toolButton_output.setIcon(Icon.Output) - # self.toolButton_output.addSeparator() - self.toHtmlAct.triggered.connect(self.output) - self.toDocxAct.triggered.connect(self.output) - self.toCSVAct.triggered.connect(self.output) - self.toTxtAct.triggered.connect(self.output) - - def toolButton_show(self): - self.toolButton_output.showMenu() - - def analysis(self): - QMessageBox.warning(self, - "别急别急", - "马上就实现该功能" - ) - return - self.stackedWidget.setCurrentWidget(self.view_analysis) - if 'room' in self.contact.wxid: - QMessageBox.warning( - self, '警告', - '暂不支持群组' - ) - return - self.view_analysis.start() - - def annual_report(self): - # QMessageBox.warning( - # self, - # "提示", - # "敬请期待" - # ) - # return - self.contact.save_avatar() - self.report_thread = ReportThread(self.contact) - self.report_thread.okSignal.connect(lambda x: QDesktopServices.openUrl(QUrl("http://127.0.0.1:21314"))) - self.report_thread.start() - QDesktopServices.openUrl(QUrl("http://127.0.0.1:21314")) - - def emotionale_Analysis(self): - QMessageBox.warning(self, - "别急别急", - "马上就实现该功能" - ) - return - self.stackedWidget.setCurrentWidget(self.view_emotion) - if 'room' in self.contact.wxid: - QMessageBox.warning( - self, '警告', - '暂不支持群组' - ) - return - self.view_emotion.start() - - def back(self): - """ - 将userinfo界面设置为可见,其他界面设置为不可见 - """ - self.stackedWidget.setCurrentWidget(self.view_userinfo) - - def output(self): - """ - 导出聊天记录 - :return: - """ - self.stackedWidget.setCurrentWidget(self.view_userinfo) - if self.sender() == self.toDocxAct: - print('功能暂未实现') - QMessageBox.warning(self, - "别急别急", - "马上就实现该功能" - ) - return - self.outputThread = Output(self.Me, self.contact.wxid) - elif self.sender() == self.toCSVAct: - # self.outputThread = Output(self.contact, type_=Output.CSV) - dialog = ExportDialog(self.contact,title='选择导出的消息类型', file_type='csv', parent=self) - result = dialog.exec_() # 使用exec_()获取用户的操作结果 - elif self.sender() == self.toHtmlAct: - dialog = ExportDialog(self.contact,title='选择导出的消息类型', file_type='html', parent=self) - result = dialog.exec_() # 使用exec_()获取用户的操作结果 - elif self.sender() == self.toTxtAct: - dialog = ExportDialog(self.contact, title='选择导出的消息类型', file_type='txt', parent=self) - result = dialog.exec_() # 使用exec_()获取用户的操作结果 - - def hide_progress_bar(self, int): - reply = QMessageBox(self) - reply.setIcon(QMessageBox.Information) - reply.setWindowTitle('OK') - reply.setText(f"导出聊天记录成功\n在./data/目录下(跟exe文件在一起)") - reply.addButton("确认", QMessageBox.AcceptRole) - reply.addButton("取消", QMessageBox.RejectRole) - api = reply.exec_() - self.view_userinfo.progressBar.setVisible(False) - - def output_progress(self, value): - self.view_userinfo.progressBar.setProperty('value', value) - - def set_progressBar_range(self, value): - self.view_userinfo.progressBar.setVisible(True) - self.view_userinfo.progressBar.setRange(0, value) - - -class ReportThread(QThread): - okSignal = pyqtSignal(bool) - - def __init__(self, contact): - super().__init__() - self.contact = contact - - def run(self): - from app.web_ui import web - web.contact = self.contact - web.run(port='21314') - self.okSignal.emit(True) diff --git a/app/ui_pc/contact/contactInfoUi.py b/app/ui_pc/contact/contactInfoUi.py deleted file mode 100644 index cba0b77..0000000 --- a/app/ui_pc/contact/contactInfoUi.py +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'contactInfoUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(494, 748) - self.verticalLayout = QtWidgets.QVBoxLayout(Form) - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setSpacing(0) - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.label_remark = QtWidgets.QLabel(Form) - self.label_remark.setMaximumSize(QtCore.QSize(120, 100)) - font = QtGui.QFont() - font.setPointSize(12) - self.label_remark.setFont(font) - self.label_remark.setText("") - self.label_remark.setObjectName("label_remark") - self.horizontalLayout_3.addWidget(self.label_remark) - self.btn_analysis = QtWidgets.QPushButton(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.btn_analysis.sizePolicy().hasHeightForWidth()) - self.btn_analysis.setSizePolicy(sizePolicy) - self.btn_analysis.setStyleSheet("") - self.btn_analysis.setFlat(False) - self.btn_analysis.setObjectName("btn_analysis") - self.horizontalLayout_3.addWidget(self.btn_analysis) - self.btn_emotion = QtWidgets.QPushButton(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.btn_emotion.sizePolicy().hasHeightForWidth()) - self.btn_emotion.setSizePolicy(sizePolicy) - self.btn_emotion.setFlat(False) - self.btn_emotion.setObjectName("btn_emotion") - self.horizontalLayout_3.addWidget(self.btn_emotion) - self.btn_report = QtWidgets.QPushButton(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.btn_report.sizePolicy().hasHeightForWidth()) - self.btn_report.setSizePolicy(sizePolicy) - self.btn_report.setFlat(False) - self.btn_report.setObjectName("btn_report") - self.horizontalLayout_3.addWidget(self.btn_report) - self.btn_back = QtWidgets.QPushButton(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.btn_back.sizePolicy().hasHeightForWidth()) - self.btn_back.setSizePolicy(sizePolicy) - self.btn_back.setFlat(False) - self.btn_back.setObjectName("btn_back") - self.horizontalLayout_3.addWidget(self.btn_back) - self.toolButton_output = QtWidgets.QToolButton(Form) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.toolButton_output.sizePolicy().hasHeightForWidth()) - self.toolButton_output.setSizePolicy(sizePolicy) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap("../../data/icons/output.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.toolButton_output.setIcon(icon) - self.toolButton_output.setCheckable(False) - self.toolButton_output.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) - self.toolButton_output.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) - self.toolButton_output.setAutoRaise(True) - self.toolButton_output.setArrowType(QtCore.Qt.NoArrow) - self.toolButton_output.setObjectName("toolButton_output") - self.horizontalLayout_3.addWidget(self.toolButton_output) - self.horizontalLayout_3.setStretch(0, 1) - self.verticalLayout.addLayout(self.horizontalLayout_3) - self.stackedWidget = QtWidgets.QStackedWidget(Form) - self.stackedWidget.setObjectName("stackedWidget") - self.page_3 = QtWidgets.QWidget() - self.page_3.setObjectName("page_3") - self.stackedWidget.addWidget(self.page_3) - self.page_4 = QtWidgets.QWidget() - self.page_4.setObjectName("page_4") - self.stackedWidget.addWidget(self.page_4) - self.verticalLayout.addWidget(self.stackedWidget) - - self.retranslateUi(Form) - self.stackedWidget.setCurrentIndex(1) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) - self.btn_analysis.setText(_translate("Form", "统计信息")) - self.btn_emotion.setText(_translate("Form", "情感分析")) - self.btn_report.setText(_translate("Form", "年度报告")) - self.btn_back.setText(_translate("Form", "退出")) - self.toolButton_output.setText(_translate("Form", "导出聊天记录")) diff --git a/app/ui_pc/contact/contactUi.py b/app/ui_pc/contact/contactUi.py deleted file mode 100644 index ff13d8c..0000000 --- a/app/ui_pc/contact/contactUi.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'contactUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtWidgets - - -class Ui_Form(object): - def setupUi(self, Form): - Form.setObjectName("Form") - Form.resize(840, 752) - Form.setStyleSheet("background: rgb(240, 240, 240);") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setSpacing(6) - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(Form) - self.label.setText("") - self.label.setObjectName("label") - self.horizontalLayout.addWidget(self.label) - self.lineEdit = QtWidgets.QLineEdit(Form) - self.lineEdit.setMinimumSize(QtCore.QSize(200, 30)) - self.lineEdit.setMaximumSize(QtCore.QSize(200, 16777215)) - self.lineEdit.setStyleSheet("background:transparent;\n" - "border-radius:5px;\n" - "border-top: 0px solid #b2e281;\n" - "border-bottom: 0px solid #b2e281;\n" - "border-right: 0px solid #b2e281;\n" - "border-left: 0px solid #b2e281;\n" - "border-style:outset;\n" - "background-color:rgb(226,226,226);\n" - " ") - self.lineEdit.setCursorMoveStyle(QtCore.Qt.VisualMoveStyle) - self.lineEdit.setObjectName("lineEdit") - self.horizontalLayout.addWidget(self.lineEdit) - self.label_2 = QtWidgets.QLabel(Form) - self.label_2.setMinimumSize(QtCore.QSize(30, 0)) - self.label_2.setMaximumSize(QtCore.QSize(30, 16777215)) - self.label_2.setText("") - self.label_2.setObjectName("label_2") - self.horizontalLayout.addWidget(self.label_2) - self.verticalLayout.addLayout(self.horizontalLayout) - self.verticalLayout_2.addLayout(self.verticalLayout) - self.listWidget = QtWidgets.QListWidget(Form) - self.listWidget.setMinimumSize(QtCore.QSize(250, 0)) - self.listWidget.setMaximumSize(QtCore.QSize(250, 16777215)) - self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.listWidget.setObjectName("listWidget") - self.verticalLayout_2.addWidget(self.listWidget) - self.verticalLayout_2.setStretch(1, 1) - self.horizontalLayout_2.addLayout(self.verticalLayout_2) - self.stackedWidget = QtWidgets.QStackedWidget(Form) - self.stackedWidget.setObjectName("stackedWidget") - self.horizontalLayout_2.addWidget(self.stackedWidget) - self.horizontalLayout_2.setStretch(1, 1) - - self.retranslateUi(Form) - self.stackedWidget.setCurrentIndex(-1) - QtCore.QMetaObject.connectSlotsByName(Form) - - def retranslateUi(self, Form): - _translate = QtCore.QCoreApplication.translate - Form.setWindowTitle(_translate("Form", "Form")) diff --git a/app/ui_pc/contact/contact_window.py b/app/ui_pc/contact/contact_window.py deleted file mode 100644 index 73dab32..0000000 --- a/app/ui_pc/contact/contact_window.py +++ /dev/null @@ -1,155 +0,0 @@ -from PyQt5.QtCore import QThread, pyqtSignal -from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit - -from app.DataBase import micro_msg_db, misc_db -from app.components import ContactQListWidgetItem -from app.person_pc import ContactPC -from app.ui_pc.Icon import Icon -from .contactInfo import ContactInfo -from .contactUi import Ui_Form -from ...util import search - -# 美化样式表 -Stylesheet = """ -QPushButton{ - background-color: transparent; -} -QPushButton:hover { - background-color: lightgray; -} -/*去掉item虚线边框*/ -QListWidget, QListView, QTreeWidget, QTreeView { - outline: 0px; - border:none; - background-color:rgb(240,240,240) -} -/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/ -QListWidget { - min-width: 250px; - max-width: 250px; - min-height: 80px; - max-height: 1200px; - color: black; - border:none; -} -QListWidget::item{ - height:60px; - width:250px; -} -/*被选中时的背景颜色和左边框颜色*/ -QListWidget::item:selected { - background: rgb(204, 204, 204); - border-bottom: 2px solid rgb(9, 187, 7); - border-left:none; - color: black; - font-weight: bold; -} -/*鼠标悬停颜色*/ -HistoryPanel::item:hover { - background: rgb(52, 52, 52); -} -""" - - -class ContactWindow(QWidget, Ui_Form): - load_finish_signal = pyqtSignal(bool) - - def __init__(self, parent=None): - super().__init__(parent) - self.show_thread = None - self.setupUi(self) - self.ok_flag = False - self.setStyleSheet(Stylesheet) - self.init_ui() - self.contacts = [[], []] - self.show_contacts() - - def init_ui(self): - search_action = QAction(self.lineEdit) - search_action.setIcon(Icon.Search_Icon) - self.lineEdit.addAction(search_action, QLineEdit.LeadingPosition) - self.lineEdit.returnPressed.connect(self.search_contact) - self.listWidget.clear() - self.listWidget.currentRowChanged.connect(self.setCurrentIndex) - self.listWidget.setCurrentRow(0) - self.stackedWidget.setCurrentIndex(0) - - def show_contacts(self): - # return - if self.ok_flag: - return - micro_msg_db.init_database() - if not micro_msg_db.open_flag: - QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库") - self.show_thread = ShowThread() - self.show_thread.showSingal.connect(self.show_contact) - self.show_thread.load_finish_signal.connect(self.load_finish_signal) - self.show_thread.start() - return - - self.show_thread = ShowContactThread() - self.show_thread.showSingal.connect(self.show_contact) - self.show_thread.load_finish_signal.connect(self.load_finish_signal) - self.show_thread.start() - self.ok_flag = True - - def search_contact(self): - keyword = self.lineEdit.text() - if keyword: - index = search.search_by_content(keyword, self.contacts) - self.listWidget.setCurrentRow(index) - self.stackedWidget.setCurrentIndex(index) - - def show_contact(self, contact: ContactPC): - self.contacts[0].append(contact.remark) - self.contacts[1].append(contact.nickName) - contact_item = ContactQListWidgetItem(contact.remark, contact.smallHeadImgUrl, contact.smallHeadImgBLOG) - self.listWidget.addItem(contact_item) - self.listWidget.setItemWidget(contact_item, contact_item.widget) - contact_info_window = ContactInfo(contact) - self.stackedWidget.addWidget(contact_info_window) - - def setCurrentIndex(self, row): - # print(row) - self.stackedWidget.setCurrentIndex(row) - - -class ShowContactThread(QThread): - showSingal = pyqtSignal(ContactPC) - load_finish_signal = pyqtSignal(bool) - - # heightSingal = pyqtSignal(int) - def __init__(self): - super().__init__() - - def run(self) -> None: - contact_info_lists = micro_msg_db.get_contact() - for contact_info_list in contact_info_lists: - # UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl - contact_info = { - 'UserName': contact_info_list[0], - 'Alias': contact_info_list[1], - 'Type': contact_info_list[2], - 'Remark': contact_info_list[3], - 'NickName': contact_info_list[4], - 'smallHeadImgUrl': contact_info_list[7] - } - contact = ContactPC(contact_info) - contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid) - contact.set_avatar(contact.smallHeadImgBLOG) - self.showSingal.emit(contact) - # pprint(contact.__dict__) - self.load_finish_signal.emit(True) - - -class ShowThread(QThread): - showSingal = pyqtSignal(ContactPC) - load_finish_signal = pyqtSignal(bool) - - # heightSingal = pyqtSignal(int) - def __init__(self): - super().__init__() - - def run(self) -> None: - QThread.sleep(1) - self.load_finish_signal.emit(True) diff --git a/app/ui_pc/contact/export_dialog.py b/app/ui_pc/contact/export_dialog.py deleted file mode 100644 index cf71ec0..0000000 --- a/app/ui_pc/contact/export_dialog.py +++ /dev/null @@ -1,105 +0,0 @@ -from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QDialog, QVBoxLayout, QCheckBox, QHBoxLayout, \ - QProgressBar, QLabel, QMessageBox - -from app.DataBase.output_pc import Output - -types = { - '文本': 1, - '图片': 3, - '语音': 34, - '视频': 43, - '表情包': 47, - '拍一拍等系统消息': 10000 -} -Stylesheet = """ -QPushButton{ - background-color: #ffffff; -} -QPushButton:hover { - background-color: lightgray; -} -""" - -class ExportDialog(QDialog): - def __init__(self, contact=None, title="选择导出的类型", file_type="csv", parent=None): - super(ExportDialog, self).__init__(parent) - self.setStyleSheet(Stylesheet) - self.contact = contact - if file_type == 'html': - self.export_type = Output.HTML - self.export_choices = {"文本": True, "图片": True, "语音": True, "视频": True, "表情包": True, - '拍一拍等系统消息': True} # 定义导出的数据类型,默认全部选择 - elif file_type == 'csv': - self.export_type = Output.CSV - self.export_choices = {"文本": True, "图片": True, "视频": True, "表情包": True} # 定义导出的数据类型,默认全部选择 - elif file_type == 'txt': - self.export_type = Output.TXT - self.export_choices = {"文本": True, "图片": True, "视频": True, "表情包": True} # 定义导出的数据类型,默认全部选择 - else: - self.export_choices = {"文本": True, "图片": True, "视频": True, "表情包": True} # 定义导出的数据类型,默认全部选择 - self.setWindowTitle(title) - layout = QVBoxLayout(self) - self.resize(400, 300) - self.worker = None # 导出线程 - self.progress_bar = QProgressBar(self) - self.progress_label = QLabel(self) - for export_type, default_state in self.export_choices.items(): - checkbox = QCheckBox(export_type) - checkbox.setChecked(default_state) - layout.addWidget(checkbox) - layout.addWidget(self.progress_bar) - layout.addWidget(self.progress_label) - hlayout = QHBoxLayout(self) - self.export_button = QPushButton("导出") - self.export_button.clicked.connect(self.export_data) - hlayout.addWidget(self.export_button) - - self.cancel_button = QPushButton("取消") - self.cancel_button.clicked.connect(self.reject) # 使用reject关闭对话框 - hlayout.addWidget(self.cancel_button) - layout.addLayout(hlayout) - self.setLayout(layout) - - def export_data(self): - self.export_button.setEnabled(False) - self.cancel_button.setEnabled(False) - # 在这里获取用户选择的导出数据类型 - selected_types = {types[export_type]: checkbox.isChecked() for export_type, checkbox in - zip(self.export_choices.keys(), self.findChildren(QCheckBox))} - - # 在这里根据用户选择的数据类型执行导出操作 - print("选择的数据类型:", selected_types) - self.worker = Output(self.contact, type_=self.export_type, message_types=selected_types) - self.worker.progressSignal.connect(self.update_progress) - self.worker.okSignal.connect(self.export_finished) - self.worker.start() - # self.accept() # 使用accept关闭对话框 - - def export_finished(self): - self.export_button.setEnabled(True) - self.cancel_button.setEnabled(True) - reply = QMessageBox(self) - reply.setIcon(QMessageBox.Information) - reply.setWindowTitle('OK') - reply.setText(f"导出聊天记录成功\n在./data/目录下(跟exe文件在一起)") - reply.addButton("确认", QMessageBox.AcceptRole) - reply.addButton("取消", QMessageBox.RejectRole) - api = reply.exec_() - self.accept() - - def update_progress(self, progress_percentage): - self.progress_bar.setValue(progress_percentage) - self.progress_label.setText(f"导出进度: {progress_percentage}%") - - -if __name__ == '__main__': - import sys - - app = QApplication(sys.argv) - dialog = ExportDialog() - result = dialog.exec_() # 使用exec_()获取用户的操作结果 - if result == QDialog.Accepted: - print("用户点击了导出按钮") - else: - print("用户点击了取消按钮") - sys.exit(app.exec_()) diff --git a/app/ui_pc/contact/userinfo/__init__.py b/app/ui_pc/contact/userinfo/__init__.py deleted file mode 100644 index 6d32454..0000000 --- a/app/ui_pc/contact/userinfo/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : __init__.py.py -@Author : Shuaikang Zhou -@Time : 2022/12/24 10:34 -@IDE : Pycharm -@Version : Python3.10 -@comment : ··· -""" diff --git a/app/ui_pc/contact/userinfo/userinfo.py b/app/ui_pc/contact/userinfo/userinfo.py deleted file mode 100644 index 5a6ac0b..0000000 --- a/app/ui_pc/contact/userinfo/userinfo.py +++ /dev/null @@ -1,15 +0,0 @@ -from PyQt5.QtWidgets import * - -from .userinfoUi import Ui_Frame - - -class UserinfoController(QWidget, Ui_Frame): - def __init__(self, contact, parent=None): - super().__init__(parent) - self.setupUi(self) - self.l_remark.setText(contact.remark) - self.l_avatar.setPixmap(contact.avatar) - self.l_nickname.setText(f'昵称:{contact.nickName}') - self.l_username.setText(f'微信号:{contact.alias}') - self.lineEdit.setText(contact.remark) - self.progressBar.setVisible(False) diff --git a/app/ui_pc/contact/userinfo/userinfoUi.py b/app/ui_pc/contact/userinfo/userinfoUi.py deleted file mode 100644 index 8494e5d..0000000 --- a/app/ui_pc/contact/userinfo/userinfoUi.py +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'userinfoUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Frame(object): - def setupUi(self, Frame): - Frame.setObjectName("Frame") - Frame.resize(624, 720) - Frame.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor)) - Frame.setMouseTracking(True) - Frame.setTabletTracking(True) - self.horizontalLayout_3 = QtWidgets.QHBoxLayout(Frame) - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem) - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem1) - self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setHorizontalSpacing(6) - self.gridLayout.setObjectName("gridLayout") - self.l_avatar = QtWidgets.QLabel(Frame) - self.l_avatar.setMinimumSize(QtCore.QSize(80, 80)) - self.l_avatar.setMaximumSize(QtCore.QSize(80, 80)) - self.l_avatar.setText("") - self.l_avatar.setPixmap(QtGui.QPixmap("../../../a_img/be0fa6c0c4707fb5f7b37b660de826d3.jpg")) - self.l_avatar.setScaledContents(True) - self.l_avatar.setObjectName("l_avatar") - self.gridLayout.addWidget(self.l_avatar, 0, 0, 3, 1) - self.l_remark = QtWidgets.QLabel(Frame) - self.l_remark.setMinimumSize(QtCore.QSize(0, 30)) - self.l_remark.setMaximumSize(QtCore.QSize(16777215, 30)) - font = QtGui.QFont() - font.setPointSize(15) - self.l_remark.setFont(font) - self.l_remark.setObjectName("l_remark") - self.gridLayout.addWidget(self.l_remark, 0, 1, 1, 1) - self.l_nickname = QtWidgets.QLabel(Frame) - self.l_nickname.setMinimumSize(QtCore.QSize(0, 30)) - self.l_nickname.setMaximumSize(QtCore.QSize(16777215, 30)) - self.l_nickname.setObjectName("l_nickname") - self.gridLayout.addWidget(self.l_nickname, 1, 1, 1, 1) - self.l_username = QtWidgets.QLabel(Frame) - self.l_username.setMinimumSize(QtCore.QSize(0, 20)) - self.l_username.setMaximumSize(QtCore.QSize(16777215, 20)) - self.l_username.setObjectName("l_username") - self.gridLayout.addWidget(self.l_username, 2, 1, 1, 1) - self.gridLayout.setRowStretch(0, 1) - self.gridLayout.setRowStretch(1, 1) - self.gridLayout.setRowStretch(2, 1) - self.verticalLayout.addLayout(self.gridLayout) - spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem2) - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(Frame) - self.label.setMinimumSize(QtCore.QSize(80, 0)) - self.label.setMaximumSize(QtCore.QSize(80, 16777215)) - font = QtGui.QFont() - font.setPointSize(15) - self.label.setFont(font) - self.label.setObjectName("label") - self.horizontalLayout.addWidget(self.label) - self.lineEdit = QtWidgets.QLineEdit(Frame) - self.lineEdit.setMinimumSize(QtCore.QSize(0, 25)) - self.lineEdit.setMaximumSize(QtCore.QSize(16777215, 25)) - font = QtGui.QFont() - font.setPointSize(15) - self.lineEdit.setFont(font) - self.lineEdit.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.lineEdit.setAutoFillBackground(False) - self.lineEdit.setStyleSheet("\n" -" background:transparent;border-width:0;border-style:outset\n" -" ") - self.lineEdit.setObjectName("lineEdit") - self.horizontalLayout.addWidget(self.lineEdit) - self.verticalLayout.addLayout(self.horizontalLayout) - spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem3) - self.progressBar = QtWidgets.QProgressBar(Frame) - self.progressBar.setProperty("value", 24) - self.progressBar.setObjectName("progressBar") - self.verticalLayout.addWidget(self.progressBar) - spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem4) - self.verticalLayout.setStretch(0, 2) - self.verticalLayout.setStretch(1, 3) - self.verticalLayout.setStretch(2, 4) - self.verticalLayout.setStretch(3, 1) - self.verticalLayout.setStretch(4, 4) - self.verticalLayout.setStretch(5, 1) - self.verticalLayout.setStretch(6, 2) - self.horizontalLayout_2.addLayout(self.verticalLayout) - spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem5) - self.horizontalLayout_2.setStretch(0, 1) - self.horizontalLayout_2.setStretch(1, 2) - self.horizontalLayout_2.setStretch(2, 1) - self.horizontalLayout_3.addLayout(self.horizontalLayout_2) - - self.retranslateUi(Frame) - QtCore.QMetaObject.connectSlotsByName(Frame) - - def retranslateUi(self, Frame): - _translate = QtCore.QCoreApplication.translate - Frame.setWindowTitle(_translate("Frame", "Frame")) - self.l_remark.setText(_translate("Frame", "曹雨萱")) - self.l_nickname.setText(_translate("Frame", "昵称:997")) - self.l_username.setText(_translate("Frame", "账号:TextLabel")) - self.label.setText(_translate("Frame", "备注名")) - self.lineEdit.setText(_translate("Frame", "曹雨萱")) diff --git a/app/ui_pc/mainview.py b/app/ui_pc/mainview.py deleted file mode 100644 index 289640f..0000000 --- a/app/ui_pc/mainview.py +++ /dev/null @@ -1,250 +0,0 @@ -# -*- coding: utf-8 -*- -""" -@File : mainview.py -@Author : Shuaikang Zhou -@Time : 2022/12/13 15:07 -@IDE : Pycharm -@Version : Python3.10 -@comment : 主窗口 -""" -import json -import os.path - -from PyQt5.QtCore import pyqtSignal, QUrl, Qt, QThread, QSize -from PyQt5.QtGui import QPixmap, QFont, QDesktopServices -from PyQt5.QtWidgets import QMainWindow, QLabel, QListWidgetItem, QMessageBox - -from app import config -from app.DataBase import msg_db, misc_db, micro_msg_db, hard_link_db -from app.ui_pc.Icon import Icon -from . import mainwindow -from .chat import ChatWindow -from .contact import ContactWindow -from .tool.tool_window import ToolWindow -from ..DataBase.output_pc import Output -from ..person_pc import MePC - -# 美化样式表 -Stylesheet = """ - -/*去掉item虚线边框*/ -QListWidget, QListView, QTreeWidget, QTreeView { - outline: 0px; -} -/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/ -QListWidget { - min-width: 120px; - max-width: 120px; - color: black; - background: white; - border:none; -} -QListWidget::item{ - height:60; -} -/*被选中时的背景颜色和左边框颜色*/ -QListWidget::item:selected { - background: rgb(204, 204, 204); - border-left: 4px solid rgb(9, 187, 7); - color: black; - font-weight: bold; -} -/*鼠标悬停颜色*/ -HistoryPanel::item:hover { - background: rgb(52, 52, 52); -} -""" - - -class MainWinController(QMainWindow, mainwindow.Ui_MainWindow): - exitSignal = pyqtSignal(bool) - okSignal = pyqtSignal(bool) - - # username = '' - def __init__(self, username, parent=None): - super(MainWinController, self).__init__(parent) - self.outputThread0 = None - self.outputThread = None - self.setupUi(self) - self.setWindowIcon(Icon.MainWindow_Icon) - self.setStyleSheet(Stylesheet) - self.listWidget.clear() - self.resize(QSize(800, 600)) - self.action_desc.triggered.connect(self.about) - self.load_flag = False - self.load_data() - self.load_num = 0 - self.label = QLabel(self) - self.label.setGeometry((self.width() - 300) // 2, (self.height() - 100) // 2, 300, 100) - self.label.setPixmap(QPixmap(':/icons/icons/loading.svg')) - - def load_data(self, flag=True): - if os.path.exists('./app/data/info.json'): - with open('./app/data/info.json', 'r', encoding='utf-8') as f: - dic = json.loads(f.read()) - wxid = dic.get('wxid') - if wxid: - me = MePC() - me.wxid = dic.get('wxid') - me.name = dic.get('name') - me.mobile = dic.get('mobile') - me.wx_dir = dic.get('wx_dir') - self.set_my_info(wxid) - self.load_flag = True - else: - QMessageBox.information( - self, - '温馨提示', - '点击 工具->获取信息 重启后可以显示本人头像哦' - ) - - def init_ui(self): - self.menu_output.setIcon(Icon.Output) - self.action_output_CSV.setIcon(Icon.ToCSV) - self.action_output_CSV.triggered.connect(self.output) - self.action_output_contacts.setIcon(Icon.Output) - self.action_output_contacts.triggered.connect(self.output) - self.action_desc.setIcon(Icon.Help_Icon) - self.action_help_contact.triggered.connect( - lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5"))) - self.action_help_chat.triggered.connect( - lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5"))) - self.action_help_decrypt.triggered.connect( - lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/4"))) - self.listWidget.setVisible(False) - self.stackedWidget.setVisible(False) - self.listWidget.currentRowChanged.connect(self.setCurrentIndex) - tool_item = QListWidgetItem(Icon.Tool_Icon, '工具', self.listWidget) - chat_item = QListWidgetItem(Icon.Chat_Icon, '聊天', self.listWidget) - contact_item = QListWidgetItem(Icon.Contact_Icon, '好友', self.listWidget) - myinfo_item = QListWidgetItem(Icon.Home_Icon, '我的', self.listWidget) - tool_window = ToolWindow() - tool_window.get_info_signal.connect(self.set_my_info) - tool_window.decrypt_success_signal.connect(self.decrypt_success) - tool_window.load_finish_signal.connect(self.loading) - self.stackedWidget.addWidget(tool_window) - self.chat_window = ChatWindow() - # chat_window = QWidget() - self.stackedWidget.addWidget(self.chat_window) - self.contact_window = ContactWindow() - self.stackedWidget.addWidget(self.contact_window) - label = QLabel('该功能暂不支持哦') - label.setFont(QFont("微软雅黑", 50)) - label.setAlignment(Qt.AlignCenter) - self.stackedWidget.addWidget(label) - tool_window.load_finish_signal.connect(self.loading) - self.statusbar.showMessage('聊天窗口上划到顶部会加载新的聊天记录\n一次不行那就多来几次') - self.contact_window.load_finish_signal.connect(self.loading) - self.chat_window.load_finish_signal.connect(self.loading) - - def setCurrentIndex(self, row): - self.stackedWidget.setCurrentIndex(row) - if row == 2: - self.stackedWidget.currentWidget().show_contacts() - if row == 1: - self.stackedWidget.currentWidget().show_chats() - - def setWindow(self, window): - try: - window.load_finish_signal.connect(self.loading) - except: - pass - self.stackedWidget.addWidget(window) - - def set_my_info(self, wxid): - self.avatar = QPixmap() - try: - img_bytes = misc_db.get_avatar_buffer(wxid) - except AttributeError: - return - if not img_bytes: - return - if img_bytes[:4] == b'\x89PNG': - self.avatar.loadFromData(img_bytes, format='PNG') - else: - self.avatar.loadFromData(img_bytes, format='jfif') - self.avatar.scaled(60, 60) - me = MePC() - me.set_avatar(img_bytes) - self.myavatar.setScaledContents(True) - self.myavatar.setPixmap(self.avatar) - - def stop_loading(self, a0): - self.label.setVisible(False) - - def loading(self, a0): - self.load_num += 1 - # self.label.setVisible(False) - print('加载一个了') - if self.load_num == 1: - print('ok了') - self.label.clear() - self.label.hide() - self.okSignal.emit(True) - self.listWidget.setVisible(True) - self.stackedWidget.setVisible(True) - if self.load_flag: - self.listWidget.setCurrentRow(1) - self.stackedWidget.setCurrentIndex(1) - else: - self.listWidget.setCurrentRow(0) - self.stackedWidget.setCurrentIndex(0) - - def output(self): - if self.sender() == self.action_output_CSV: - self.outputThread = Output(None, type_=Output.CSV_ALL) - self.outputThread.okSignal.connect( - lambda x: self.message('聊天记录导出成功')) - self.outputThread.start() - elif self.sender() == self.action_output_contacts: - self.outputThread = Output(None, type_=Output.CONTACT_CSV) - self.outputThread.okSignal.connect( - lambda x: self.message('联系人导出成功')) - self.outputThread.start() - - def message(self, msg): - QMessageBox.about(self, "提醒", msg) - - def about(self): - """ - 关于 - """ - QMessageBox.about(self, "关于", - f'''版本:{config.version}
QQ交流群:{config.contact}
地址:https://github.com/LC044/WeChatMsg
新特性:
{''.join(['' + i for i in config.description])} - ''' - ) - - def decrypt_success(self): - QMessageBox.about(self, "解密成功", "请重新启动") - self.close() - - def close(self) -> bool: - super().close() - misc_db.close() - msg_db.close() - micro_msg_db.close() - hard_link_db.close() - self.contact_window.close() - self.exitSignal.emit(True) - - -class LoadWindowThread(QThread): - okSignal = pyqtSignal(bool) - - def __init__(self): - super().__init__() - self.num = 0 - - def loading(self): - self.num += 1 - print('加载一个了') - if self.num == 2: - self.okSignal.emit(True) - - def run(self): - self.chat_window = ChatWindow() - self.contact_window = ContactWindow() - self.contact_window.load_finish_signal.connect(self.loading) - self.chat_window.load_finish_signal.connect(self.loading) - print('加载完成') - self.okSignal.emit(True) diff --git a/app/ui_pc/mainwindow.py b/app/ui_pc/mainwindow.py deleted file mode 100644 index 20e242c..0000000 --- a/app/ui_pc/mainwindow.py +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'mainwindow.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.resize(1280, 779) - MainWindow.setStyleSheet("\n" -" /*去掉item虚线边框*/\n" -" QListWidget, QListView, QTreeWidget, QTreeView {\n" -" outline: 0px;\n" -" }\n" -" /*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/\n" -" QListWidget {\n" -" min-width: 120px;\n" -" max-width: 120px;\n" -" color: black;\n" -" background: white;\n" -" border:none;\n" -" }\n" -" QListWidget::item{\n" -" height:80;\n" -" }\n" -" /*被选中时的背景颜色和左边框颜色*/\n" -" QListWidget::item:selected {\n" -" background: rgb(204, 204, 204);\n" -" border-left: 4px solid rgb(9, 187, 7);\n" -" }\n" -" /*鼠标悬停颜色*/\n" -" HistoryPanel::item:hover {\n" -" background: rgb(52, 52, 52);\n" -" }\n" -" ") - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) - self.horizontalLayout.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout.setSpacing(0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.frame_info = QtWidgets.QFrame(self.centralwidget) - self.frame_info.setMinimumSize(QtCore.QSize(80, 500)) - self.frame_info.setMaximumSize(QtCore.QSize(80, 16777215)) - self.frame_info.setStyleSheet("background-color:rgb(240,240,240)") - self.frame_info.setFrameShape(QtWidgets.QFrame.NoFrame) - self.frame_info.setFrameShadow(QtWidgets.QFrame.Plain) - self.frame_info.setObjectName("frame_info") - self.myavatar = QtWidgets.QLabel(self.frame_info) - self.myavatar.setGeometry(QtCore.QRect(10, 40, 60, 60)) - self.myavatar.setObjectName("myavatar") - self.listWidget = QtWidgets.QListWidget(self.frame_info) - self.listWidget.setGeometry(QtCore.QRect(0, 230, 120, 331)) - self.listWidget.setMinimumSize(QtCore.QSize(120, 0)) - self.listWidget.setMaximumSize(QtCore.QSize(120, 16777215)) - self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.listWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored) - self.listWidget.setObjectName("listWidget") - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - self.horizontalLayout.addWidget(self.frame_info) - self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget) - font = QtGui.QFont() - font.setFamily("微软雅黑") - font.setBold(False) - font.setWeight(50) - self.stackedWidget.setFont(font) - self.stackedWidget.setObjectName("stackedWidget") - self.horizontalLayout.addWidget(self.stackedWidget) - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 23)) - self.menubar.setObjectName("menubar") - self.menu_F = QtWidgets.QMenu(self.menubar) - self.menu_F.setObjectName("menu_F") - self.menu_data = QtWidgets.QMenu(self.menubar) - font = QtGui.QFont() - font.setFamily("微软雅黑") - self.menu_data.setFont(font) - self.menu_data.setObjectName("menu_data") - self.menu_output = QtWidgets.QMenu(self.menu_data) - self.menu_output.setObjectName("menu_output") - self.menu_2 = QtWidgets.QMenu(self.menubar) - self.menu_2.setObjectName("menu_2") - self.menu_about = QtWidgets.QMenu(self.menubar) - self.menu_about.setObjectName("menu_about") - self.menu_3 = QtWidgets.QMenu(self.menubar) - self.menu_3.setObjectName("menu_3") - MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - self.action_3 = QtWidgets.QAction(MainWindow) - self.action_3.setObjectName("action_3") - self.action_4 = QtWidgets.QAction(MainWindow) - self.action_4.setObjectName("action_4") - self.action_help_decrypt = QtWidgets.QAction(MainWindow) - font = QtGui.QFont() - font.setFamily("Microsoft YaHei UI") - self.action_help_decrypt.setFont(font) - self.action_help_decrypt.setObjectName("action_help_decrypt") - self.action_desc = QtWidgets.QAction(MainWindow) - self.action_desc.setObjectName("action_desc") - self.action_help_chat = QtWidgets.QAction(MainWindow) - self.action_help_chat.setObjectName("action_help_chat") - self.action_help_contact = QtWidgets.QAction(MainWindow) - self.action_help_contact.setObjectName("action_help_contact") - self.action_output_CSV = QtWidgets.QAction(MainWindow) - self.action_output_CSV.setObjectName("action_output_CSV") - self.action_output_contacts = QtWidgets.QAction(MainWindow) - self.action_output_contacts.setObjectName("action_output_contacts") - self.menu_F.addSeparator() - self.menu_F.addSeparator() - self.menu_F.addAction(self.action_3) - self.menu_F.addAction(self.action_4) - self.menu_output.addAction(self.action_output_CSV) - self.menu_data.addAction(self.menu_output.menuAction()) - self.menu_data.addAction(self.action_output_contacts) - self.menu_2.addAction(self.action_help_decrypt) - self.menu_2.addAction(self.action_help_chat) - self.menu_2.addAction(self.action_help_contact) - self.menu_about.addAction(self.action_desc) - self.menubar.addAction(self.menu_F.menuAction()) - self.menubar.addAction(self.menu_data.menuAction()) - self.menubar.addAction(self.menu_2.menuAction()) - self.menubar.addAction(self.menu_about.menuAction()) - self.menubar.addAction(self.menu_3.menuAction()) - - self.retranslateUi(MainWindow) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) - self.myavatar.setText(_translate("MainWindow", "avatar")) - __sortingEnabled = self.listWidget.isSortingEnabled() - self.listWidget.setSortingEnabled(False) - item = self.listWidget.item(0) - item.setText(_translate("MainWindow", "新建项目")) - item = self.listWidget.item(1) - item.setText(_translate("MainWindow", "新建项目")) - item = self.listWidget.item(2) - item.setText(_translate("MainWindow", "新建项目")) - item = self.listWidget.item(3) - item.setText(_translate("MainWindow", "新建项目")) - item = self.listWidget.item(4) - item.setText(_translate("MainWindow", "新建项目")) - self.listWidget.setSortingEnabled(__sortingEnabled) - self.menu_F.setTitle(_translate("MainWindow", "文件(F)")) - self.menu_data.setTitle(_translate("MainWindow", "数据")) - self.menu_output.setTitle(_translate("MainWindow", "导出聊天记录(全部)")) - self.menu_2.setTitle(_translate("MainWindow", "帮助")) - self.menu_about.setTitle(_translate("MainWindow", "关于")) - self.menu_3.setTitle(_translate("MainWindow", "不显示或者显示异常请重启应用、没反应那就多等一会儿")) - self.action_3.setText(_translate("MainWindow", "保存")) - self.action_4.setText(_translate("MainWindow", "退出")) - self.action_help_decrypt.setText(_translate("MainWindow", "解密教程")) - self.action_desc.setText(_translate("MainWindow", "说明")) - self.action_help_chat.setText(_translate("MainWindow", "聊天相关")) - self.action_help_contact.setText(_translate("MainWindow", "好友相关")) - self.action_output_CSV.setText(_translate("MainWindow", "CSV")) - self.action_output_contacts.setText(_translate("MainWindow", "导出联系人")) diff --git a/app/ui_pc/tool/__init__.py b/app/ui_pc/tool/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/app/ui_pc/tool/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/ui_pc/tool/pc_decrypt/__init__.py b/app/ui_pc/tool/pc_decrypt/__init__.py deleted file mode 100644 index ae1c618..0000000 --- a/app/ui_pc/tool/pc_decrypt/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .pc_decrypt import DecryptControl - -__all__ = ['DecryptControl'] diff --git a/app/ui_pc/tool/pc_decrypt/decryptUi.py b/app/ui_pc/tool/pc_decrypt/decryptUi.py deleted file mode 100644 index ac35c66..0000000 --- a/app/ui_pc/tool/pc_decrypt/decryptUi.py +++ /dev/null @@ -1,197 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'decryptUi.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(611, 519) - font = QtGui.QFont() - font.setFamily("微软雅黑") - Dialog.setFont(font) - Dialog.setLayoutDirection(QtCore.Qt.LeftToRight) - self.verticalLayout_3 = QtWidgets.QVBoxLayout(Dialog) - self.verticalLayout_3.setObjectName("verticalLayout_3") - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.horizontalLayout_4 = QtWidgets.QHBoxLayout() - self.horizontalLayout_4.setObjectName("horizontalLayout_4") - spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_4.addItem(spacerItem) - self.btn_help = QtWidgets.QPushButton(Dialog) - self.btn_help.setMaximumSize(QtCore.QSize(200, 16777215)) - self.btn_help.setObjectName("btn_help") - self.horizontalLayout_4.addWidget(self.btn_help) - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_4.addItem(spacerItem1) - self.verticalLayout_2.addLayout(self.horizontalLayout_4) - spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout_2.addItem(spacerItem2) - self.horizontalLayout_3 = QtWidgets.QHBoxLayout() - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_3.addItem(spacerItem3) - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.label_3 = QtWidgets.QLabel(Dialog) - font = QtGui.QFont() - font.setFamily("一纸情书") - font.setPointSize(20) - self.label_3.setFont(font) - self.label_3.setAlignment(QtCore.Qt.AlignCenter) - self.label_3.setObjectName("label_3") - self.verticalLayout.addWidget(self.label_3) - self.label_9 = QtWidgets.QLabel(Dialog) - self.label_9.setAlignment(QtCore.Qt.AlignCenter) - self.label_9.setObjectName("label_9") - self.verticalLayout.addWidget(self.label_9) - self.gridLayout_2 = QtWidgets.QGridLayout() - self.gridLayout_2.setObjectName("gridLayout_2") - self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setObjectName("gridLayout") - self.label_phone = QtWidgets.QLabel(Dialog) - self.label_phone.setText("") - self.label_phone.setObjectName("label_phone") - self.gridLayout.addWidget(self.label_phone, 2, 1, 1, 1) - self.label_7 = QtWidgets.QLabel(Dialog) - self.label_7.setObjectName("label_7") - self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1) - self.lineEdit = QtWidgets.QLineEdit(Dialog) - self.lineEdit.setStyleSheet("background:transparent;\n" -"\n" -" border-radius:5px;\n" -" border-top: 0px solid #b2e281;\n" -" border-bottom: 2px solid black;\n" -" border-right: 0px solid #b2e281;\n" -" border-left: 0px solid #b2e281;\n" -"\n" -"\n" -" border-style:outset\n" -" ") - self.lineEdit.setFrame(False) - self.lineEdit.setObjectName("lineEdit") - self.gridLayout.addWidget(self.lineEdit, 4, 1, 1, 1) - self.label_5 = QtWidgets.QLabel(Dialog) - self.label_5.setObjectName("label_5") - self.gridLayout.addWidget(self.label_5, 3, 0, 1, 1) - self.label_6 = QtWidgets.QLabel(Dialog) - self.label_6.setObjectName("label_6") - self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1) - self.label_key = QtWidgets.QLabel(Dialog) - self.label_key.setMaximumSize(QtCore.QSize(400, 16777215)) - self.label_key.setText("") - self.label_key.setObjectName("label_key") - self.gridLayout.addWidget(self.label_key, 5, 1, 1, 1) - self.label = QtWidgets.QLabel(Dialog) - self.label.setObjectName("label") - self.gridLayout.addWidget(self.label, 0, 0, 1, 1) - self.label_2 = QtWidgets.QLabel(Dialog) - self.label_2.setObjectName("label_2") - self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1) - self.label_pid = QtWidgets.QLabel(Dialog) - self.label_pid.setText("") - self.label_pid.setObjectName("label_pid") - self.gridLayout.addWidget(self.label_pid, 0, 1, 1, 1) - self.label_name = QtWidgets.QLabel(Dialog) - self.label_name.setText("") - self.label_name.setObjectName("label_name") - self.gridLayout.addWidget(self.label_name, 3, 1, 1, 1) - self.label_4 = QtWidgets.QLabel(Dialog) - self.label_4.setObjectName("label_4") - self.gridLayout.addWidget(self.label_4, 4, 0, 1, 1) - self.label_version = QtWidgets.QLabel(Dialog) - self.label_version.setText("") - self.label_version.setObjectName("label_version") - self.gridLayout.addWidget(self.label_version, 1, 1, 1, 1) - self.label_8 = QtWidgets.QLabel(Dialog) - self.label_8.setObjectName("label_8") - self.gridLayout.addWidget(self.label_8, 6, 0, 1, 1) - self.label_db_dir = QtWidgets.QLabel(Dialog) - self.label_db_dir.setMaximumSize(QtCore.QSize(400, 300)) - self.label_db_dir.setText("") - self.label_db_dir.setObjectName("label_db_dir") - self.gridLayout.addWidget(self.label_db_dir, 6, 1, 1, 1) - self.gridLayout.setColumnMinimumWidth(0, 1) - self.gridLayout.setColumnStretch(0, 1) - self.gridLayout.setColumnStretch(1, 10) - self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 2, 1) - self.btn_getinfo = QtWidgets.QPushButton(Dialog) - self.btn_getinfo.setMinimumSize(QtCore.QSize(0, 60)) - self.btn_getinfo.setObjectName("btn_getinfo") - self.gridLayout_2.addWidget(self.btn_getinfo, 0, 1, 1, 1) - self.checkBox = QtWidgets.QCheckBox(Dialog) - self.checkBox.setText("") - self.checkBox.setObjectName("checkBox") - self.gridLayout_2.addWidget(self.checkBox, 0, 2, 1, 1) - self.btn_db_dir = QtWidgets.QPushButton(Dialog) - self.btn_db_dir.setMinimumSize(QtCore.QSize(0, 60)) - self.btn_db_dir.setObjectName("btn_db_dir") - self.gridLayout_2.addWidget(self.btn_db_dir, 1, 1, 1, 1) - self.checkBox_2 = QtWidgets.QCheckBox(Dialog) - self.checkBox_2.setText("") - self.checkBox_2.setObjectName("checkBox_2") - self.gridLayout_2.addWidget(self.checkBox_2, 1, 2, 1, 1) - self.verticalLayout.addLayout(self.gridLayout_2) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem4) - self.pushButton_3 = QtWidgets.QPushButton(Dialog) - self.pushButton_3.setMinimumSize(QtCore.QSize(0, 60)) - self.pushButton_3.setMaximumSize(QtCore.QSize(100, 16777215)) - self.pushButton_3.setObjectName("pushButton_3") - self.horizontalLayout_2.addWidget(self.pushButton_3) - self.label_tip = QtWidgets.QLabel(Dialog) - self.label_tip.setObjectName("label_tip") - self.horizontalLayout_2.addWidget(self.label_tip) - spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_2.addItem(spacerItem5) - self.verticalLayout.addLayout(self.horizontalLayout_2) - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.label_ready = QtWidgets.QLabel(Dialog) - self.label_ready.setObjectName("label_ready") - self.horizontalLayout.addWidget(self.label_ready) - self.progressBar = QtWidgets.QProgressBar(Dialog) - self.progressBar.setProperty("value", 50) - self.progressBar.setObjectName("progressBar") - self.horizontalLayout.addWidget(self.progressBar) - self.verticalLayout.addLayout(self.horizontalLayout) - self.horizontalLayout_3.addLayout(self.verticalLayout) - spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.horizontalLayout_3.addItem(spacerItem6) - self.verticalLayout_2.addLayout(self.horizontalLayout_3) - spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout_2.addItem(spacerItem7) - self.verticalLayout_3.addLayout(self.verticalLayout_2) - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - self.btn_help.setText(_translate("Dialog", "使用说明")) - self.label_3.setText(_translate("Dialog", "解密数据库")) - self.label_9.setText(_translate("Dialog", "以下内容为自动获取,如获取失败请手动填写")) - self.label_7.setText(_translate("Dialog", "版本")) - self.label_5.setText(_translate("Dialog", "微信昵称")) - self.label_6.setText(_translate("Dialog", "密钥")) - self.label.setText(_translate("Dialog", "PID")) - self.label_2.setText(_translate("Dialog", "手机号")) - self.label_4.setText(_translate("Dialog", "wxid")) - self.label_8.setText(_translate("Dialog", "微信路径")) - self.btn_getinfo.setText(_translate("Dialog", "获取信息")) - self.btn_db_dir.setText(_translate("Dialog", "设置微信路径")) - self.pushButton_3.setText(_translate("Dialog", "开始启动")) - self.label_tip.setText(_translate("Dialog", "TextLabel")) - self.label_ready.setText(_translate("Dialog", "未就绪")) diff --git a/app/ui_pc/tool/pc_decrypt/pc_decrypt.py b/app/ui_pc/tool/pc_decrypt/pc_decrypt.py deleted file mode 100644 index 85637e3..0000000 --- a/app/ui_pc/tool/pc_decrypt/pc_decrypt.py +++ /dev/null @@ -1,259 +0,0 @@ -import json -import os.path -import time -import traceback - -from PyQt5.QtCore import pyqtSignal, QThread, QUrl, QFile, QIODevice, QTextStream -from PyQt5.QtGui import QDesktopServices -from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog - -from app.DataBase import msg_db, misc_db -from app.DataBase.merge import merge_databases, merge_MediaMSG_databases -from app.decrypt import get_wx_info, decrypt -from app.log import logger -from app.util import path -from . import decryptUi - - -class DecryptControl(QWidget, decryptUi.Ui_Dialog): - DecryptSignal = pyqtSignal(bool) - get_wxidSignal = pyqtSignal(str) - - def __init__(self, parent=None): - super(DecryptControl, self).__init__(parent) - self.setupUi(self) - - self.pushButton_3.clicked.connect(self.decrypt) - self.btn_getinfo.clicked.connect(self.get_info) - self.btn_db_dir.clicked.connect(self.select_db_dir) - self.lineEdit.returnPressed.connect(self.set_wxid) - self.lineEdit.textChanged.connect(self.set_wxid_) - self.btn_help.clicked.connect(self.show_help) - self.label_tip.setVisible(False) - self.info = {} - self.lineEdit.setFocus() - self.ready = False - self.wx_dir = None - - def show_help(self): - # 定义网页链接 - url = QUrl("https://blog.lc044.love/post/4") - # 使用QDesktopServices打开网页 - QDesktopServices.openUrl(url) - - # @log - def get_info(self): - try: - file = QFile(':/data/version_list.json') - if file.open(QIODevice.ReadOnly | QIODevice.Text): - stream = QTextStream(file) - content = stream.readAll() - file.close() - VERSION_LIST = json.loads(content) - else: - return - result = get_wx_info.get_info(VERSION_LIST) - print(result) - if result == -1: - QMessageBox.critical(self, "错误", "请登录微信") - elif result == -2: - QMessageBox.critical(self, "错误", "微信版本不匹配\n请更新微信版本为:3.9.8.15") - elif result == -3: - QMessageBox.critical(self, "错误", "WeChat WeChatWin.dll Not Found") - else: - self.ready = True - self.info = result[0] - self.label_key.setText(self.info['key']) - self.lineEdit.setText(self.info['wxid']) - self.label_name.setText(self.info['name']) - self.label_phone.setText(self.info['mobile']) - self.label_pid.setText(str(self.info['pid'])) - self.label_version.setText(self.info['version']) - self.lineEdit.setFocus() - self.checkBox.setChecked(True) - self.get_wxidSignal.emit(self.info['wxid']) - directory = os.path.join(path.wx_path(), self.info['wxid']) - if os.path.exists(directory): - self.label_db_dir.setText(directory) - self.wx_dir = directory - self.checkBox_2.setChecked(True) - self.ready = True - if self.ready: - self.label_ready.setText('已就绪') - if self.wx_dir and os.path.exists(os.path.join(self.wx_dir)): - self.label_ready.setText('已就绪') - except Exception as e: - QMessageBox.critical(self, "未知错误", "请收集报错信息,发起issue解决问题") - logger.error(traceback.format_exc()) - - def set_wxid_(self): - self.info['wxid'] = self.lineEdit.text() - - def set_wxid(self): - self.info['wxid'] = self.lineEdit.text() - QMessageBox.information(self, "ok", f"wxid修改成功{self.info['wxid']}") - - def select_db_dir(self): - directory = QFileDialog.getExistingDirectory( - self, "选取微信文件保存目录——能看到Msg文件夹", - path.wx_path() - ) # 起始路径 - db_dir = os.path.join(directory, 'Msg') - if not os.path.exists(db_dir): - QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾") - return - - self.label_db_dir.setText(directory) - self.wx_dir = directory - self.checkBox_2.setChecked(True) - if self.ready: - self.label_ready.setText('已就绪') - - def decrypt(self): - if not self.ready: - QMessageBox.critical(self, "错误", "请先获取密钥") - return - if not self.wx_dir: - QMessageBox.critical(self, "错误", "请先选择微信安装路径") - return - if self.lineEdit.text() == 'None': - QMessageBox.critical(self, "错误", "请填入wxid") - return - db_dir = os.path.join(self.wx_dir, 'Msg') - if self.ready: - if not os.path.exists(db_dir): - QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾") - return - if self.info.get('key') == 'none': - QMessageBox.critical(self, "错误", "密钥错误\n请检查微信版本是否为最新和微信路径是否正确") - self.label_tip.setVisible(True) - self.label_tip.setText('点我之后没有反应那就多等儿吧,不要再点了') - self.thread2 = DecryptThread(db_dir, self.info['key']) - self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum) - self.thread2.signal.connect(self.progressBar_view) - self.thread2.okSignal.connect(self.btnExitClicked) - self.thread2.errorSignal.connect( - lambda x: QMessageBox.critical(self, "错误", "密钥错误\n请检查微信版本是否为最新和微信路径是否正确") - ) - self.thread2.start() - - def btnEnterClicked(self): - # print("enter clicked") - # 中间可以添加处理逻辑 - # QMessageBox.about(self, "解密成功", "数据库文件存储在app/DataBase/Msg文件夹下") - - self.DecryptSignal.emit(True) - # self.close() - - def setProgressBarMaxNum(self, max_val): - self.progressBar.setRange(0, max_val) - - def progressBar_view(self, value): - """ - 进度条显示 - :param value: 进度0-100 - :return: None - """ - self.progressBar.setProperty('value', value) - # self.btnExitClicked() - # data.init_database() - - def btnExitClicked(self): - # print("Exit clicked") - dic = { - 'wxid': self.info['wxid'], - 'wx_dir': self.wx_dir, - 'name': self.info['name'], - 'mobile': self.info['mobile'] - } - try: - os.makedirs('./app/data', exist_ok=True) - with open('./app/data/info.json', 'w', encoding='utf-8') as f: - f.write(json.dumps(dic)) - except: - with open('./info.json', 'w', encoding='utf-8') as f: - f.write(json.dumps(dic)) - # 目标数据库文件 - target_database = "app/DataBase/Msg/MSG.db" - # 源数据库文件列表 - source_databases = [f"app/DataBase/Msg/MSG{i}.db" for i in range(1, 20)] - import shutil - shutil.copy("app/DataBase/Msg/MSG0.db", target_database) # 使用一个数据库文件作为模板 - # 合并数据库 - try: - merge_databases(source_databases, target_database) - except FileNotFoundError: - QMessageBox.critical(self, "错误", "数据库不存在\n请检查微信版本是否为最新") - - # 音频数据库文件 - target_database = "app/DataBase/Msg/MediaMSG.db" - # 源数据库文件列表 - source_databases = [f"app/DataBase/Msg/MediaMSG{i}.db" for i in range(1, 20)] - import shutil - shutil.copy("app/DataBase/Msg/MediaMSG0.db", target_database) # 使用一个数据库文件作为模板 - # 合并数据库 - try: - merge_MediaMSG_databases(source_databases, target_database) - except FileNotFoundError: - QMessageBox.critical(self, "错误", "数据库不存在\n请检查微信版本是否为最新") - - self.DecryptSignal.emit(True) - self.close() - - -class DecryptThread(QThread): - signal = pyqtSignal(str) - maxNumSignal = pyqtSignal(int) - okSignal = pyqtSignal(str) - errorSignal = pyqtSignal(bool) - - def __init__(self, db_path, key): - super(DecryptThread, self).__init__() - self.db_path = db_path - self.key = key - self.textBrowser = None - - def __del__(self): - pass - - def run(self): - misc_db.close() - msg_db.close() - # micro_msg_db.close() - # hard_link_db.close() - output_dir = 'app/DataBase/Msg' - os.makedirs(output_dir, exist_ok=True) - tasks = [] - if os.path.exists(self.db_path): - for root, dirs, files in os.walk(self.db_path): - for file in files: - if '.db' == file[-3:]: - if 'xInfo.db' == file: - continue - inpath = os.path.join(root, file) - # print(inpath) - output_path = os.path.join(output_dir, file) - tasks.append([self.key, inpath, output_path]) - self.maxNumSignal.emit(len(tasks)) - for i, task in enumerate(tasks): - if decrypt.decrypt(*task) == -1: - self.errorSignal.emit(True) - self.signal.emit(str(i)) - # print(self.db_path) - self.okSignal.emit('ok') - # self.signal.emit('100') - - -class MyThread(QThread): - signal = pyqtSignal(str) - - def __init__(self): - super(MyThread, self).__init__() - - def __del__(self): - pass - - def run(self): - for i in range(100): - self.signal.emit(str(i)) - time.sleep(0.1) diff --git a/app/ui_pc/tool/toolUI.py b/app/ui_pc/tool/toolUI.py deleted file mode 100644 index 3f71481..0000000 --- a/app/ui_pc/tool/toolUI.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'toolUI.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# 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. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(590, 547) - font = QtGui.QFont() - font.setFamily("微软雅黑") - Dialog.setFont(font) - self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) - self.verticalLayout.setObjectName("verticalLayout") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) - self.horizontalLayout.setSpacing(0) - self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(Dialog) - self.label.setMaximumSize(QtCore.QSize(80, 80)) - self.label.setText("") - self.label.setObjectName("label") - self.horizontalLayout.addWidget(self.label) - self.listWidget = QtWidgets.QListWidget(Dialog) - self.listWidget.setMinimumSize(QtCore.QSize(100, 80)) - self.listWidget.setMaximumSize(QtCore.QSize(500, 80)) - self.listWidget.setFrameShape(QtWidgets.QFrame.NoFrame) - self.listWidget.setFrameShadow(QtWidgets.QFrame.Plain) - self.listWidget.setLineWidth(0) - self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.listWidget.setFlow(QtWidgets.QListView.LeftToRight) - self.listWidget.setObjectName("listWidget") - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - item = QtWidgets.QListWidgetItem() - self.listWidget.addItem(item) - self.horizontalLayout.addWidget(self.listWidget) - self.label_2 = QtWidgets.QLabel(Dialog) - self.label_2.setMaximumSize(QtCore.QSize(80, 80)) - self.label_2.setText("") - self.label_2.setObjectName("label_2") - self.horizontalLayout.addWidget(self.label_2) - self.verticalLayout.addLayout(self.horizontalLayout) - self.stackedWidget = QtWidgets.QStackedWidget(Dialog) - self.stackedWidget.setObjectName("stackedWidget") - self.verticalLayout.addWidget(self.stackedWidget) - self.verticalLayout.setStretch(1, 1) - - self.retranslateUi(Dialog) - self.stackedWidget.setCurrentIndex(-1) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - __sortingEnabled = self.listWidget.isSortingEnabled() - self.listWidget.setSortingEnabled(False) - item = self.listWidget.item(0) - item.setText(_translate("Dialog", "新建项目")) - item = self.listWidget.item(1) - item.setText(_translate("Dialog", "新建项目")) - item = self.listWidget.item(2) - item.setText(_translate("Dialog", "新建项目")) - item = self.listWidget.item(3) - item.setText(_translate("Dialog", "新建项目")) - item = self.listWidget.item(4) - item.setText(_translate("Dialog", "新建项目")) - self.listWidget.setSortingEnabled(__sortingEnabled) diff --git a/app/ui_pc/tool/tool_window.py b/app/ui_pc/tool/tool_window.py deleted file mode 100644 index af6c549..0000000 --- a/app/ui_pc/tool/tool_window.py +++ /dev/null @@ -1,89 +0,0 @@ -from PyQt5.QtCore import Qt, pyqtSignal -from PyQt5.QtGui import QFont -from PyQt5.QtWidgets import QWidget, QListWidgetItem, QLabel - -from app.ui_pc.Icon import Icon -from .pc_decrypt import DecryptControl -from .toolUI import Ui_Dialog - -# 美化样式表 -Stylesheet = """ -QPushButton{ - background-color: #ffffff; -} -QPushButton:hover { - background-color: lightgray; -} -/*去掉item虚线边框*/ -QListWidget, QListView, QTreeWidget, QTreeView { - outline: 0px; - border:none; - background-color:rgb(240,240,240) -} -/*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/ -QListWidget { - min-width: 400px; - max-width: 400px; - min-height: 80px; - max-height: 80px; - color: black; - border:none; -} -QListWidget::item{ - height:80px; - width:80px; -} -/*被选中时的背景颜色和左边框颜色*/ -QListWidget::item:selected { - background: rgb(204, 204, 204); - border-bottom: 4px solid rgb(9, 187, 7); - border-left:none; - color: black; - font-weight: bold; -} -/*鼠标悬停颜色*/ -HistoryPanel::item:hover { - background: rgb(52, 52, 52); -} -""" - - -class ToolWindow(QWidget, Ui_Dialog): - get_info_signal = pyqtSignal(str) - decrypt_success_signal = pyqtSignal(bool) - load_finish_signal = pyqtSignal(bool) - - def __init__(self, parent=None): - super().__init__(parent) - self.setupUi(self) - self.setStyleSheet(Stylesheet) - self.init_ui() - self.load_finish_signal.emit(True) - - def init_ui(self): - self.listWidget.clear() - self.listWidget.currentRowChanged.connect(self.setCurrentIndex) - chat_item = QListWidgetItem(Icon.Chat_Icon, '解密', self.listWidget) - contact_item = QListWidgetItem(Icon.Contact_Icon, '别点', self.listWidget) - myinfo_item = QListWidgetItem(Icon.MyInfo_Icon, '别点', self.listWidget) - tool_item = QListWidgetItem(Icon.MyInfo_Icon, '别点', self.listWidget) - decrypt_window = DecryptControl() - decrypt_window.get_wxidSignal.connect(self.get_info_signal) - decrypt_window.DecryptSignal.connect(self.decrypt_success_signal) - self.stackedWidget.addWidget(decrypt_window) - label = QLabel('都说了不让你点', self) - label.setFont(QFont("微软雅黑", 50)) - label.setAlignment(Qt.AlignCenter) - # 设置label的背景颜色(这里随机) - # 这里加了一个margin边距(方便区分QStackedWidget和QLabel的颜色) - # label.setStyleSheet('background: rgb(%d, %d, %d);margin: 50px;' % ( - # randint(0, 255), randint(0, 255), randint(0, 255))) - self.stackedWidget.addWidget(label) - self.stackedWidget.addWidget(label) - self.stackedWidget.addWidget(label) - self.listWidget.setCurrentRow(0) - self.stackedWidget.setCurrentIndex(0) - - def setCurrentIndex(self, row): - print(row) - self.stackedWidget.setCurrentIndex(row) diff --git a/decrypt_window.py b/decrypt_window.py deleted file mode 100644 index 696324d..0000000 --- a/decrypt_window.py +++ /dev/null @@ -1,41 +0,0 @@ -import ctypes -import sys - -from PyQt5.QtGui import QIcon -from PyQt5.QtWidgets import QApplication, QMessageBox, QWidget - -from app.resources import resource_rc -from app.ui_pc.tool.pc_decrypt import pc_decrypt - -var = resource_rc.qt_resource_name -ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport") - - -class ViewController(QWidget): - def __init__(self): - super().__init__() - self.setWindowTitle('解密') - self.setWindowIcon(QIcon(':/icons/icons/logo.svg')) - self.viewMainWIn = None - self.viewDecrypt = None - - def loadPCDecryptView(self): - """ - 登录界面 - :return: - """ - self.viewDecrypt = pc_decrypt.DecryptControl(self) - self.viewDecrypt.DecryptSignal.connect(self.show_success) - # self.viewDecrypt.show() - - def show_success(self): - QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下") - self.close() - - -if __name__ == '__main__': - app = QApplication(sys.argv) - view = ViewController() - view.loadPCDecryptView() - view.show() - sys.exit(app.exec_()) diff --git a/doc/电脑端使用教程.md b/doc/电脑端使用教程.md index 9071ee1..6f4b926 100644 --- a/doc/电脑端使用教程.md +++ b/doc/电脑端使用教程.md @@ -56,7 +56,7 @@ pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 1. 运行程序 ```shell -python main_pc.py +python main.py ``` 2. 选择联系人 diff --git a/main.py b/main.py index b21f867..0a49542 100644 --- a/main.py +++ b/main.py @@ -1,40 +1,31 @@ import ctypes import sys import time +import traceback +from PyQt5.QtGui import QFont from PyQt5.QtWidgets import * -import app.DataBase.data as DB -from app.Ui import decrypt, mainview - +from app.log import logger +from app.ui import mainview +from app.ui.tool.pc_decrypt import pc_decrypt +from app.config import version ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport") -class ViewController: +class ViewController(QWidget): def __init__(self): - self.viewMainWIn = None + super().__init__() + self.viewMainWindow = None self.viewDecrypt = None - def loadDecryptView(self): - """ - 登录界面 - :return: - """ - if DB.is_db_exist(): - self.loadMainWinView() - else: - self.viewDecrypt = decrypt.DecryptControl() # 需要将view login设为成员变量 - self.viewDecrypt.DecryptSignal.connect(self.loadMainWinView) - self.viewDecrypt.show() - self.viewDecrypt.db_exist() - def loadPCDecryptView(self): """ 登录界面 :return: """ self.viewDecrypt = pc_decrypt.DecryptControl() - self.viewDecrypt.DecryptSignal.connect(self.loadMainWinView) + self.viewDecrypt.DecryptSignal.connect(self.show_success) self.viewDecrypt.show() def loadMainWinView(self, username=None): @@ -45,21 +36,31 @@ class ViewController: """ username = '' start = time.time() - self.viewMainWIn = mainview.MainWinController(username=username) - self.viewMainWIn.setWindowTitle("Chat") - # print(username) - self.viewMainWIn.username = username - # self.viewMainWIn.exitSignal.connect(self.loadDecryptView) # 不需要回到登录界面可以省略 - self.viewMainWIn.show() - end = time.time() - print('ok', end - start) - # self.viewMainWIn.signUp() + self.viewMainWindow = mainview.MainWinController(username=username) + self.viewMainWindow.exitSignal.connect(self.close) + try: + self.viewMainWindow.setWindowTitle(f"留痕-{version}") + self.viewMainWindow.show() + end = time.time() + print('ok', '本次加载用了', end - start, 's') + self.viewMainWindow.init_ui() + except Exception as e: + print(f"Exception: {e}") + logger.error(traceback.print_exc()) + + def show_success(self): + QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下") if __name__ == '__main__': app = QApplication(sys.argv) view = ViewController() - # view.loadPCDecryptView() - view.loadDecryptView() # 进入登录界面,如果view login不是成员变量,则离开作用域后失效。 - # view.loadMainWinView('102') - sys.exit(app.exec_()) + try: + # view.loadPCDecryptView() + view.loadMainWinView() + # view.show() + # view.show_success() + sys.exit(app.exec_()) + except Exception as e: + print(f"Exception: {e}") + logger.error(traceback.print_exc()) diff --git a/main_pc.py b/main_pc.py deleted file mode 100644 index 2c3d6ee..0000000 --- a/main_pc.py +++ /dev/null @@ -1,66 +0,0 @@ -import ctypes -import sys -import time -import traceback - -from PyQt5.QtGui import QFont -from PyQt5.QtWidgets import * - -from app.log import logger -from app.ui_pc import mainview -from app.ui_pc.tool.pc_decrypt import pc_decrypt -from app.config import version -ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport") - - -class ViewController(QWidget): - def __init__(self): - super().__init__() - self.viewMainWindow = None - self.viewDecrypt = None - - def loadPCDecryptView(self): - """ - 登录界面 - :return: - """ - self.viewDecrypt = pc_decrypt.DecryptControl() - self.viewDecrypt.DecryptSignal.connect(self.show_success) - self.viewDecrypt.show() - - def loadMainWinView(self, username=None): - """ - 聊天界面 - :param username: 账号 - :return: - """ - username = '' - start = time.time() - self.viewMainWindow = mainview.MainWinController(username=username) - self.viewMainWindow.exitSignal.connect(self.close) - try: - self.viewMainWindow.setWindowTitle(f"留痕-{version}") - self.viewMainWindow.show() - end = time.time() - print('ok', '本次加载用了', end - start, 's') - self.viewMainWindow.init_ui() - except Exception as e: - print(f"Exception: {e}") - logger.error(traceback.print_exc()) - - def show_success(self): - QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下") - - -if __name__ == '__main__': - app = QApplication(sys.argv) - view = ViewController() - try: - # view.loadPCDecryptView() - view.loadMainWinView() - # view.show() - # view.show_success() - sys.exit(app.exec_()) - except Exception as e: - print(f"Exception: {e}") - logger.error(traceback.print_exc()) diff --git a/readme.md b/readme.md index 33a1dff..8069448 100644 --- a/readme.md +++ b/readme.md @@ -97,7 +97,7 @@ # Python>=3.10 git clone https://github.com/LC044/WeChatMsg cd WeChatMsg -pip install -r requirements_pc.txt -i https://pypi.tuna.tsinghua.edu.cn/simple +pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple ``` ### 2. 使用 @@ -113,7 +113,7 @@ pip install -r requirements_pc.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 2. 运行程序 ```shell -python main_pc.py +python main.py ``` 3. 点击获取信息 @@ -188,13 +188,6 @@ python main_pc.py ![](./doc/images/login_wx.png) -如果您遇到下图所示的问题,需要先运行`decrypt_window`的可执行文件或者源代码文件 - -``` -python decrypt_window.py -``` - -![](./doc/images/decrypt_wx.png) 如果您在运行可执行程序的时候出现闪退的现象,请右击软件使用管理员权限运行。 @@ -205,7 +198,7 @@ python decrypt_window.py ![](./doc/images/with_wxid_name.png) -如果出现如图所示的报错信息,将`app/database/msg`文件夹删除,重新运行`main_pc.py`。 +如果出现如图所示的报错信息,将`app/database/msg`文件夹删除,重新运行`main.py`。 ![](./doc/images/err_log.png) @@ -221,59 +214,6 @@ python decrypt_window.py -## 使用模拟器(支持可视化分析) - -
- -**不推荐使用,PC端微信可视化功能马上实现** - -1. 根据[教程](https://blog.csdn.net/m0_59452630/article/details/124222235?spm=1001.2014.3001.5501)获得两个文件 - - auth_info_key_prefs.xml——解析数据库密码 - - EnMicroMsg.db——聊天数据库 - - **上面这两个文件就可以** -2. 安装依赖库 - -python版本>=3.10 - -**说明:用到了python3.10的match语法,不方便更换python版本的小伙伴可以把match(运行报错的地方)更改为if else** - -命令行运行以下代码(**建议使用Pycharm打开项目,Pycharm会自动配置好所有东西,直接运行main.py即可**) - -```bash -pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple -``` - -运行main.py - -```bash -python main.py -``` - -3. 出现解密界面 - -![image-20230521001305274](doc/images/image-20230521001305274.png) - -按照提示选择上面获得的两个文件,等待解密完成,重新运行程序 - -4. 进入主界面 - -这时候不显示头像,因为头像文件没有导入进来 - -![image-20230521001547481](doc/images/image-20230521001547481.png) - -根据[教程](https://blog.csdn.net/m0_59452630/article/details/124222235?spm=1001.2014.3001.5501) -将头像文件夹avatar复制到工程目录./app/data/目录下 - -![image-20230521001726799](doc/images/image-20230521001726799.png) - -如果想要显示聊天图像就把[教程](https://blog.csdn.net/m0_59452630/article/details/124222235?spm=1001.2014.3001.5501) -里的image2文件夹复制到./app/data文件夹里,效果跟上图一样 - -复制进来之后再运行程序就有图像了 - -![image-20230520235113261](doc/images/image-20230520235113261.png) - -
# 🏆致谢 diff --git a/requirements.txt b/requirements.txt index f596530..713b142 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/requirements_decrypt.txt b/requirements_decrypt.txt deleted file mode 100644 index 57b92af..0000000 --- a/requirements_decrypt.txt +++ /dev/null @@ -1,10 +0,0 @@ -PyQt5 -psutil -pycryptodomex -pywin32 -pymem -silk-python -pyaudio -fuzzywuzzy -python-Levenshtein -lz4 \ No newline at end of file diff --git a/requirements_pc.txt b/requirements_pc.txt deleted file mode 100644 index 713b142..0000000 --- a/requirements_pc.txt +++ /dev/null @@ -1,19 +0,0 @@ -PyQt5 -psutil -pycryptodomex -pywin32 -pymem -silk-python -pyaudio -fuzzywuzzy -python-Levenshtein -Pillow==10.1.0 -requests -flask==3.0.0 -pyecharts==2.0.1 -jieba==0.42.1 -google==3.0.0 -protobuf==4.25.1 -soupsieve==2.5 -lz4==4.3.2 -pilk==0.2.4 \ No newline at end of file diff --git a/sqlcipher-3.0.1/bin/adb.txt b/sqlcipher-3.0.1/bin/adb.txt deleted file mode 100644 index 184bb5a..0000000 --- a/sqlcipher-3.0.1/bin/adb.txt +++ /dev/null @@ -1,5 +0,0 @@ -PRAGMA key = '10f35f1'; -PRAGMA cipher_migrate; -ATTACH DATABASE 'plaintext.db' AS plaintext KEY ''; -SELECT sqlcipher_export('plaintext'); -DETACH DATABASE plaintext; \ No newline at end of file diff --git a/sqlcipher-3.0.1/bin/bat使用说明.txt b/sqlcipher-3.0.1/bin/bat使用说明.txt deleted file mode 100644 index e99e94c..0000000 --- a/sqlcipher-3.0.1/bin/bat使用说明.txt +++ /dev/null @@ -1,3 +0,0 @@ -1.ҪܵƸΪencrypt.dbŵǰbinĿ¼ -2.༭adb.txt ļ PRAGMA key = 'password';passwordǼݵ -3.޸ı꣬˫sqlcipher.batļ \ No newline at end of file diff --git a/sqlcipher-3.0.1/bin/sqlcipher - 副本.txt b/sqlcipher-3.0.1/bin/sqlcipher - 副本.txt deleted file mode 100644 index cab6c11..0000000 --- a/sqlcipher-3.0.1/bin/sqlcipher - 副本.txt +++ /dev/null @@ -1,3 +0,0 @@ -sqlcipher-shell32.exe encrypt.db < adb.txt -echo -pause diff --git a/sqlcipher-3.0.1/bin/sqlcipher-shell32.exe b/sqlcipher-3.0.1/bin/sqlcipher-shell32.exe deleted file mode 100644 index 53b6fd1..0000000 Binary files a/sqlcipher-3.0.1/bin/sqlcipher-shell32.exe and /dev/null differ diff --git a/sqlcipher-3.0.1/bin/sqlcipher-shell64.exe b/sqlcipher-3.0.1/bin/sqlcipher-shell64.exe deleted file mode 100644 index 4736fc6..0000000 Binary files a/sqlcipher-3.0.1/bin/sqlcipher-shell64.exe and /dev/null differ diff --git a/sqlcipher-3.0.1/bin/sqlcipher.bat b/sqlcipher-3.0.1/bin/sqlcipher.bat deleted file mode 100644 index cab6c11..0000000 --- a/sqlcipher-3.0.1/bin/sqlcipher.bat +++ /dev/null @@ -1,3 +0,0 @@ -sqlcipher-shell32.exe encrypt.db < adb.txt -echo -pause