mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-21 01:52:35 +08:00
新增联系人头像组件
This commit is contained in:
parent
37870f1033
commit
07b20a2f21
@ -4,25 +4,17 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="修复无法查找wxid的bug">
|
||||
<change afterPath="$PROJECT_DIR$/app/ui_pc/__init__.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/app/ui_pc/tool/__init__.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/app/ui_pc/tool/toolUI.ui" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/app/ui_pc/tool/tool_window.py" afterDir="false" />
|
||||
<list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="修改UI">
|
||||
<change afterPath="$PROJECT_DIR$/app/components/CAvatar.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/app/components/contact_info_ui.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/app/ui_pc/contact/__init__.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/app/ui_pc/contact/contact_window.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/MyComponents/Button_Contact.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/components/Button_Contact.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/MyComponents/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/components/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/MyComponents/prompt_bar.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/components/prompt_bar.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/Ui/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/chat/chat.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/Ui/chat/chat.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/contact/contact.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/Ui/contact/contact.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/Ui/mainview.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/pc_decrypt/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/pc_decrypt/decryptUi.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/pc_decrypt/decryptUi.ui" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/Ui/pc_decrypt/pc_decrypt.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/decrypt_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/decrypt_window.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/DataBase/micro_msg.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/micro_msg.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/components/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/components/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/person.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/person.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/ui_pc/contact/form.ui" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/app/ui_pc/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/mainview.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@ -119,7 +111,7 @@
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager" selected="Python.decrypt_window">
|
||||
<configuration name="decrypt" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<configuration name="CAvatar" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
@ -127,11 +119,32 @@
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/decrypt" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/components" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/decrypt/decrypt.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/components/CAvatar.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="contact_info_ui" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/components" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/components/contact_info_ui.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
@ -161,27 +174,6 @@
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="get_wx_info" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/decrypt" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/decrypt/get_wx_info.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="main" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
@ -203,27 +195,6 @@
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="micro_msg (1)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/DataBase" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/DataBase/micro_msg.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="pc_decrypt" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
@ -245,13 +216,34 @@
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="test_avatar" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="WeChatMsg" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/components" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/components/test_avatar.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="Python.decrypt_window" />
|
||||
<item itemvalue="Python.contact_info_ui" />
|
||||
<item itemvalue="Python.test_avatar" />
|
||||
<item itemvalue="Python.CAvatar" />
|
||||
<item itemvalue="Python.main" />
|
||||
<item itemvalue="Python.decrypt" />
|
||||
<item itemvalue="Python.get_wx_info" />
|
||||
<item itemvalue="Python.micro_msg (1)" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
@ -267,13 +259,6 @@
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1672848140146</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00010" summary="聊天统计">
|
||||
<created>1675169020409</created>
|
||||
<option name="number" value="00010" />
|
||||
<option name="presentableId" value="LOCAL-00010" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1675169020409</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00011" summary="优化加载页面">
|
||||
<created>1675268807882</created>
|
||||
<option name="number" value="00011" />
|
||||
@ -610,7 +595,14 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1700046106844</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="59" />
|
||||
<task id="LOCAL-00059" summary="修改UI">
|
||||
<created>1700052873083</created>
|
||||
<option name="number" value="00059" />
|
||||
<option name="presentableId" value="LOCAL-00059" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1700052873083</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="60" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="UnknownFeatures">
|
||||
@ -646,7 +638,6 @@
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="readme" />
|
||||
<MESSAGE value="mainwindows文件修正" />
|
||||
<MESSAGE value="match语法说明" />
|
||||
<MESSAGE value="增加群二维码" />
|
||||
@ -671,7 +662,8 @@
|
||||
<MESSAGE value="增加PC端微信解密条件的判断" />
|
||||
<MESSAGE value="删除多余的Word文件" />
|
||||
<MESSAGE value="修复无法查找wxid的bug" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="修复无法查找wxid的bug" />
|
||||
<MESSAGE value="修改UI" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="修改UI" />
|
||||
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
|
||||
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" />
|
||||
</component>
|
||||
|
@ -1,9 +1,17 @@
|
||||
import os.path
|
||||
import sqlite3
|
||||
from pprint import pprint
|
||||
|
||||
DB = sqlite3.connect("./de_MicroMsg.db", check_same_thread=False)
|
||||
# '''创建游标'''
|
||||
cursor = DB.cursor()
|
||||
DB = None
|
||||
cursor = None
|
||||
micromsg_path = "./app/Database/Msg/MicroMsg.db"
|
||||
if os.path.exists(micromsg_path):
|
||||
DB = sqlite3.connect(micromsg_path, check_same_thread=False)
|
||||
# '''创建游标'''
|
||||
cursor = DB.cursor()
|
||||
|
||||
|
||||
def is_database_exist():
|
||||
return os.path.exists(micromsg_path)
|
||||
|
||||
|
||||
def get_contact():
|
||||
@ -14,8 +22,8 @@ def get_contact():
|
||||
'''
|
||||
cursor.execute(sql)
|
||||
result = cursor.fetchall()
|
||||
pprint(result)
|
||||
print(len(result))
|
||||
# pprint(result)
|
||||
# print(len(result))
|
||||
return result
|
||||
|
||||
|
||||
|
283
app/components/CAvatar.py
Normal file
283
app/components/CAvatar.py
Normal file
@ -0,0 +1,283 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2019年7月26日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: CustomWidgets.CAvatar
|
||||
@description: 头像
|
||||
"""
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import QUrl, QRectF, Qt, QSize, QTimer, QPropertyAnimation, \
|
||||
QPointF, pyqtProperty
|
||||
from PyQt5.QtGui import QPixmap, QColor, QPainter, QPainterPath, QMovie
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkDiskCache, \
|
||||
QNetworkRequest
|
||||
from PyQt5.QtWidgets import QWidget, qApp
|
||||
|
||||
__Author__ = 'Irony'
|
||||
__Copyright__ = 'Copyright (c) 2019 Irony'
|
||||
__Version__ = 1.0
|
||||
|
||||
|
||||
class CAvatar(QWidget):
|
||||
Circle = 0 # 圆圈
|
||||
Rectangle = 1 # 圆角矩形
|
||||
SizeLarge = QSize(128, 128)
|
||||
SizeMedium = QSize(64, 64)
|
||||
SizeSmall = QSize(32, 32)
|
||||
StartAngle = 0 # 起始旋转角度
|
||||
EndAngle = 360 # 结束旋转角度
|
||||
|
||||
def __init__(self, *args, shape=0, url='', cacheDir=False, size=QSize(64, 64), animation=False, **kwargs):
|
||||
super(CAvatar, self).__init__(*args, **kwargs)
|
||||
self.url = ''
|
||||
self._angle = 0 # 角度
|
||||
self.pradius = 0 # 加载进度条半径
|
||||
self.animation = animation # 是否使用动画
|
||||
self._movie = None # 动态图
|
||||
self._pixmap = QPixmap() # 图片对象
|
||||
self.pixmap = QPixmap() # 被绘制的对象
|
||||
self.isGif = url.endswith('.gif')
|
||||
# 进度动画定时器
|
||||
self.loadingTimer = QTimer(self, timeout=self.onLoading)
|
||||
# 旋转动画
|
||||
self.rotateAnimation = QPropertyAnimation(
|
||||
self, b'angle', self, loopCount=1)
|
||||
self.setShape(shape)
|
||||
self.setCacheDir(cacheDir)
|
||||
self.setSize(size)
|
||||
self.setUrl(url)
|
||||
|
||||
def paintEvent(self, event):
|
||||
super(CAvatar, self).paintEvent(event)
|
||||
# 画笔
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing, True)
|
||||
painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
|
||||
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
|
||||
# 绘制
|
||||
path = QPainterPath()
|
||||
diameter = min(self.width(), self.height())
|
||||
if self.shape == self.Circle:
|
||||
radius = int(diameter / 2)
|
||||
elif self.shape == self.Rectangle:
|
||||
radius = 4
|
||||
halfW = self.width() / 2
|
||||
halfH = self.height() / 2
|
||||
painter.translate(halfW, halfH)
|
||||
path.addRoundedRect(
|
||||
QRectF(-halfW, -halfH, diameter, diameter), radius, radius)
|
||||
painter.setClipPath(path)
|
||||
# 如果是动画效果
|
||||
if self.rotateAnimation.state() == QPropertyAnimation.Running:
|
||||
painter.rotate(self._angle) # 旋转
|
||||
painter.drawPixmap(
|
||||
QPointF(-self.pixmap.width() / 2, -self.pixmap.height() // 2), self.pixmap)
|
||||
else:
|
||||
painter.drawPixmap(-int(halfW), -int(halfH), self.pixmap)
|
||||
# 如果在加载
|
||||
if self.loadingTimer.isActive():
|
||||
diameter = 2 * self.pradius
|
||||
painter.setBrush(
|
||||
QColor(45, 140, 240, int((1 - self.pradius / 10) * 255)))
|
||||
painter.setPen(Qt.NoPen)
|
||||
painter.drawRoundedRect(
|
||||
QRectF(-self.pradius, -self.pradius, diameter, diameter), self.pradius, self.pradius)
|
||||
|
||||
def enterEvent(self, event):
|
||||
"""鼠标进入动画
|
||||
:param event:
|
||||
"""
|
||||
if not (self.animation and not self.isGif):
|
||||
return
|
||||
self.rotateAnimation.stop()
|
||||
cv = self.rotateAnimation.currentValue() or self.StartAngle
|
||||
self.rotateAnimation.setDuration(
|
||||
540 if cv == 0 else int(cv / self.EndAngle * 540))
|
||||
self.rotateAnimation.setStartValue(cv)
|
||||
self.rotateAnimation.setEndValue(self.EndAngle)
|
||||
self.rotateAnimation.start()
|
||||
|
||||
def leaveEvent(self, event):
|
||||
"""鼠标离开动画
|
||||
:param event:
|
||||
"""
|
||||
if not (self.animation and not self.isGif):
|
||||
return
|
||||
self.rotateAnimation.stop()
|
||||
cv = self.rotateAnimation.currentValue() or self.EndAngle
|
||||
self.rotateAnimation.setDuration(int(cv / self.EndAngle * 540))
|
||||
self.rotateAnimation.setStartValue(cv)
|
||||
self.rotateAnimation.setEndValue(self.StartAngle)
|
||||
self.rotateAnimation.start()
|
||||
|
||||
def onLoading(self):
|
||||
"""更新进度动画
|
||||
"""
|
||||
if self.loadingTimer.isActive():
|
||||
if self.pradius > 9:
|
||||
self.pradius = 0
|
||||
self.pradius += 1
|
||||
else:
|
||||
self.pradius = 0
|
||||
self.update()
|
||||
|
||||
def onFinished(self):
|
||||
"""图片下载完成
|
||||
"""
|
||||
self.loadingTimer.stop()
|
||||
self.pradius = 0
|
||||
reply = self.sender()
|
||||
|
||||
if self.isGif:
|
||||
self._movie = QMovie(reply, b'gif', self)
|
||||
if self._movie.isValid():
|
||||
self._movie.frameChanged.connect(self._resizeGifPixmap)
|
||||
self._movie.start()
|
||||
else:
|
||||
data = reply.readAll().data()
|
||||
reply.deleteLater()
|
||||
del reply
|
||||
self._pixmap.loadFromData(data)
|
||||
if self._pixmap.isNull():
|
||||
self._pixmap = QPixmap(self.size())
|
||||
self._pixmap.fill(QColor(204, 204, 204))
|
||||
self._resizePixmap()
|
||||
|
||||
def onError(self, code):
|
||||
"""下载出错了
|
||||
:param code:
|
||||
"""
|
||||
self._pixmap = QPixmap(self.size())
|
||||
self._pixmap.fill(QColor(204, 204, 204))
|
||||
self._resizePixmap()
|
||||
|
||||
def refresh(self):
|
||||
"""强制刷新
|
||||
"""
|
||||
self._get(self.url)
|
||||
|
||||
def isLoading(self):
|
||||
"""判断是否正在加载
|
||||
"""
|
||||
return self.loadingTimer.isActive()
|
||||
|
||||
def setShape(self, shape):
|
||||
"""设置形状
|
||||
:param shape: 0=圆形, 1=圆角矩形
|
||||
"""
|
||||
self.shape = shape
|
||||
|
||||
def setUrl(self, url):
|
||||
"""设置url,可以是本地路径,也可以是网络地址
|
||||
:param url:
|
||||
"""
|
||||
self.url = url
|
||||
self._get(url)
|
||||
|
||||
def setCacheDir(self, cacheDir=''):
|
||||
"""设置本地缓存路径
|
||||
:param cacheDir:
|
||||
"""
|
||||
self.cacheDir = cacheDir
|
||||
self._initNetWork()
|
||||
|
||||
def setSize(self, size):
|
||||
"""设置固定尺寸
|
||||
:param size:
|
||||
"""
|
||||
if not isinstance(size, QSize):
|
||||
size = self.SizeMedium
|
||||
self.setMinimumSize(size)
|
||||
self.setMaximumSize(size)
|
||||
self._resizePixmap()
|
||||
|
||||
@pyqtProperty(int)
|
||||
def angle(self):
|
||||
return self._angle
|
||||
|
||||
@angle.setter
|
||||
def angle(self, value):
|
||||
self._angle = value
|
||||
self.update()
|
||||
|
||||
def _resizePixmap(self):
|
||||
"""缩放图片
|
||||
"""
|
||||
if not self._pixmap.isNull():
|
||||
self.pixmap = self._pixmap.scaled(
|
||||
self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
|
||||
self.update()
|
||||
|
||||
def _resizeGifPixmap(self, _):
|
||||
"""缩放动画图片
|
||||
"""
|
||||
if self._movie:
|
||||
self.pixmap = self._movie.currentPixmap().scaled(
|
||||
self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
|
||||
self.update()
|
||||
|
||||
def _initNetWork(self):
|
||||
"""初始化异步网络库
|
||||
"""
|
||||
if not hasattr(qApp, '_network'):
|
||||
network = QNetworkAccessManager(self.window())
|
||||
setattr(qApp, '_network', network)
|
||||
# 是否需要设置缓存
|
||||
if self.cacheDir and not qApp._network.cache():
|
||||
cache = QNetworkDiskCache(self.window())
|
||||
cache.setCacheDirectory(self.cacheDir)
|
||||
qApp._network.setCache(cache)
|
||||
|
||||
def _get(self, url):
|
||||
"""设置图片或者请求网络图片
|
||||
:param url:
|
||||
"""
|
||||
if not url:
|
||||
self.onError('')
|
||||
return
|
||||
if url.startswith('http') and not self.loadingTimer.isActive():
|
||||
url = QUrl(url)
|
||||
request = QNetworkRequest(url)
|
||||
# request.setHeader(QNetworkRequest.UserAgentHeader, b'CAvatar')
|
||||
# request.setRawHeader(b'Author', b'Irony')
|
||||
request.setAttribute(
|
||||
QNetworkRequest.FollowRedirectsAttribute, True)
|
||||
if qApp._network.cache():
|
||||
request.setAttribute(
|
||||
QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferNetwork)
|
||||
request.setAttribute(
|
||||
QNetworkRequest.CacheSaveControlAttribute, True)
|
||||
reply = qApp._network.get(request)
|
||||
self.pradius = 0
|
||||
self.loadingTimer.start(50) # 显示进度动画
|
||||
reply.finished.connect(self.onFinished)
|
||||
reply.error.connect(self.onError)
|
||||
return
|
||||
self.pradius = 0
|
||||
if os.path.exists(url) and os.path.isfile(url):
|
||||
if self.isGif:
|
||||
self._movie = QMovie(url, parent=self)
|
||||
if self._movie.isValid():
|
||||
self._movie.frameChanged.connect(self._resizeGifPixmap)
|
||||
self._movie.start()
|
||||
else:
|
||||
self._pixmap = QPixmap(url)
|
||||
self._resizePixmap()
|
||||
else:
|
||||
self.onError('')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
w = CAvatar(
|
||||
url='https://wx.qlogo.cn/mmhead/ver_1/DpDqmvTDORNWfLrMj26YicorEUREffl1G8FapawdKgINVH9g1icudfWesGrH9LqeGAz16z4PmkW9U1KAIM3btWgozZ1GaLF66bdKdxlMdazmibn2hpFeiaa4613dN6HM4Vfk/132')
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
@ -0,0 +1 @@
|
||||
from .contact_info_ui import ContactQListWidgetItem
|
57
app/components/contact_info_ui.py
Normal file
57
app/components/contact_info_ui.py
Normal file
@ -0,0 +1,57 @@
|
||||
import sys
|
||||
|
||||
from PyQt5.Qt import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from .CAvatar import CAvatar
|
||||
|
||||
|
||||
# 自定义的item 继承自QListWidgetItem
|
||||
class ContactQListWidgetItem(QListWidgetItem):
|
||||
def __init__(self, name, url):
|
||||
super().__init__()
|
||||
# 自定义item中的widget 用来显示自定义的内容
|
||||
self.widget = QWidget()
|
||||
# 用来显示name
|
||||
self.nameLabel = QLabel()
|
||||
self.nameLabel.setText(name)
|
||||
# 用来显示avator(图像)
|
||||
self.avatorLabel = CAvatar(None, shape=CAvatar.Rectangle, size=QSize(60, 60),
|
||||
url=url)
|
||||
# 设置布局用来对nameLabel和avatorLabel进行布局
|
||||
self.hbox = QHBoxLayout()
|
||||
self.hbox.addWidget(self.avatorLabel)
|
||||
self.hbox.addWidget(self.nameLabel)
|
||||
self.hbox.addStretch(1)
|
||||
# 设置widget的布局
|
||||
self.widget.setLayout(self.hbox)
|
||||
# 设置自定义的QListWidgetItem的sizeHint,不然无法显示
|
||||
self.setSizeHint(self.widget.sizeHint())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# 主窗口
|
||||
w = QWidget()
|
||||
w.setWindowTitle("QListWindow")
|
||||
# 新建QListWidget
|
||||
listWidget = QListWidget(w)
|
||||
listWidget.resize(300, 300)
|
||||
|
||||
# 新建两个自定义的QListWidgetItem(customQListWidgetItem)
|
||||
item1 = ContactQListWidgetItem("鲤鱼王", "liyuwang.jpg")
|
||||
item2 = ContactQListWidgetItem("可达鸭", "kedaya.jpg")
|
||||
|
||||
# 在listWidget中加入两个自定义的item
|
||||
listWidget.addItem(item1)
|
||||
listWidget.setItemWidget(item1, item1.widget)
|
||||
listWidget.addItem(item2)
|
||||
listWidget.setItemWidget(item2, item2.widget)
|
||||
|
||||
# 绑定点击槽函数 点击显示对应item中的name
|
||||
listWidget.itemClicked.connect(lambda item: print(item.nameLabel.text()))
|
||||
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
@ -1,4 +1,5 @@
|
||||
import os.path
|
||||
from typing import Dict
|
||||
|
||||
from PyQt5.QtGui import QPixmap
|
||||
|
||||
@ -32,6 +33,18 @@ class Me(Person):
|
||||
class Contact(Person):
|
||||
def __init__(self, wxid: str):
|
||||
super(Contact, self).__init__(wxid)
|
||||
self.smallHeadImgUrl = ''
|
||||
self.bigHeadImgUrl = ''
|
||||
|
||||
|
||||
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')
|
||||
self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl')
|
||||
|
||||
|
||||
class Group(Person):
|
||||
|
1
app/ui_pc/contact/__init__.py
Normal file
1
app/ui_pc/contact/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .contact_window import ContactWindow
|
53
app/ui_pc/contact/contactUi.py
Normal file
53
app/ui_pc/contact/contactUi.py
Normal file
@ -0,0 +1,53 @@
|
||||
# -*- 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 = QtWidgets.QHBoxLayout(Form)
|
||||
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.lineEdit = QtWidgets.QLineEdit(Form)
|
||||
self.lineEdit.setMinimumSize(QtCore.QSize(250, 30))
|
||||
self.lineEdit.setMaximumSize(QtCore.QSize(250, 16777215))
|
||||
self.lineEdit.setObjectName("lineEdit")
|
||||
self.verticalLayout.addWidget(self.lineEdit)
|
||||
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.addWidget(self.listWidget)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout)
|
||||
self.stackedWidget = QtWidgets.QStackedWidget(Form)
|
||||
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.addWidget(self.stackedWidget)
|
||||
self.horizontalLayout.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"))
|
84
app/ui_pc/contact/contactUi.ui
Normal file
84
app/ui_pc/contact/contactUi.ui
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>840</width>
|
||||
<height>752</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: rgb(240, 240, 240);</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page"/>
|
||||
<widget class="QWidget" name="page_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
99
app/ui_pc/contact/contact_window.py
Normal file
99
app/ui_pc/contact/contact_window.py
Normal file
@ -0,0 +1,99 @@
|
||||
from random import randint
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QLabel, QMessageBox
|
||||
|
||||
from app.DataBase import micro_msg
|
||||
from app.components import ContactQListWidgetItem
|
||||
from app.person import ContactPC
|
||||
from .contactUi import Ui_Form
|
||||
from ...Ui.Icon import Icon
|
||||
|
||||
# 美化样式表
|
||||
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 ContactWindow(QWidget, Ui_Form):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.setStyleSheet(Stylesheet)
|
||||
self.init_ui()
|
||||
self.show_contacts()
|
||||
|
||||
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, 'None', self.listWidget)
|
||||
myinfo_item = QListWidgetItem(Icon.MyInfo_Icon, 'None', self.listWidget)
|
||||
tool_item = QListWidgetItem(Icon.MyInfo_Icon, 'None', self.listWidget)
|
||||
label = QLabel('我是页面', self)
|
||||
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 show_contacts(self):
|
||||
if not micro_msg.is_database_exist():
|
||||
QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库")
|
||||
return
|
||||
contact_info_lists = micro_msg.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)
|
||||
# pprint(contact.__dict__)
|
||||
contact_item = ContactQListWidgetItem(contact.nickName, contact.smallHeadImgUrl)
|
||||
self.listWidget.addItem(contact_item)
|
||||
self.listWidget.setItemWidget(contact_item, contact_item.widget)
|
||||
|
||||
def setCurrentIndex(self, row):
|
||||
print(row)
|
||||
self.stackedWidget.setCurrentIndex(row)
|
@ -15,6 +15,7 @@ from PyQt5.QtWidgets import *
|
||||
from app import config
|
||||
from app.Ui.Icon import Icon
|
||||
from . import mainwindow
|
||||
from .contact import ContactWindow
|
||||
from .tool import ToolWindow
|
||||
|
||||
# 美化样式表
|
||||
@ -75,22 +76,17 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
|
||||
contact_item = QListWidgetItem(Icon.Contact_Icon, '好友', self.listWidget)
|
||||
myinfo_item = QListWidgetItem(Icon.MyInfo_Icon, '我的', self.listWidget)
|
||||
tool_item = QListWidgetItem(Icon.MyInfo_Icon, '工具', self.listWidget)
|
||||
|
||||
tool_window = ToolWindow()
|
||||
label = QLabel('我是页面', self)
|
||||
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)
|
||||
label = QLabel('我是页面', self)
|
||||
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)
|
||||
contact_window = ContactWindow()
|
||||
self.stackedWidget.addWidget(contact_window)
|
||||
label = QLabel('我是页面', self)
|
||||
label.setAlignment(Qt.AlignCenter)
|
||||
# 设置label的背景颜色(这里随机)
|
||||
|
Loading…
Reference in New Issue
Block a user