mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-23 03:22:17 +08:00
commit
3b277826f8
@ -4,11 +4,13 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="新增聊天记录导出csv格式">
|
<list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="修复聊天气泡不能更改大小的bug">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" 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/person.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/person.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/app/DataBase/msg.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/msg.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/app/ui_pc/chat/chat_info.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/chat/chat_info.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/app/ui_pc/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/mainview.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/app/ui_pc/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/mainview.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/tool_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/tool_window.py" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@ -80,7 +82,7 @@
|
|||||||
<option name="stateVersion" value="1" />
|
<option name="stateVersion" value="1" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProblemsViewState">
|
<component name="ProblemsViewState">
|
||||||
<option name="selectedTabId" value="ProjectErrors" />
|
<option name="selectedTabId" value="CurrentFile" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectId" id="2JrtgPdd86dlNq47HAnVDPZuCVh" />
|
<component name="ProjectId" id="2JrtgPdd86dlNq47HAnVDPZuCVh" />
|
||||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||||
@ -88,15 +90,15 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"DefaultHtmlFileTemplate": "HTML File",
|
"DefaultHtmlFileTemplate": "HTML File",
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"last_opened_file_path": "D:/Program Files/Python310/Scripts/pyuic5.exe",
|
"last_opened_file_path": "D:/Program Files/Python310/Scripts/pyuic5.exe",
|
||||||
"settings.editor.selected.configurable": "preferences.pluginManager"
|
"settings.editor.selected.configurable": "editor.preferences.tabs"
|
||||||
}
|
}
|
||||||
}</component>
|
}]]></component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
<recent name="D:\Project\Python\WeChatMsg\app\ui_pc\tool" />
|
<recent name="D:\Project\Python\WeChatMsg\app\ui_pc\tool" />
|
||||||
@ -104,8 +106,50 @@
|
|||||||
<recent name="D:\Project\PythonProject\WeChatMsg\app\Ui" />
|
<recent name="D:\Project\PythonProject\WeChatMsg\app\Ui" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Python.decrypt_window">
|
<component name="RunManager" selected="Python.main_pc">
|
||||||
<configuration name="decrypt_window" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
<configuration name="bubble_message" 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/bubble_message.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="chat_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/ui_pc/chat" />
|
||||||
|
<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/ui_pc/chat/chat_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_pc" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||||
<module name="WeChatMsg" />
|
<module name="WeChatMsg" />
|
||||||
<option name="INTERPRETER_OPTIONS" value="" />
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
@ -117,7 +161,7 @@
|
|||||||
<option name="IS_MODULE_SDK" value="true" />
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/decrypt_window.py" />
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/main_pc.py" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
<option name="EMULATE_TERMINAL" value="true" />
|
<option name="EMULATE_TERMINAL" value="true" />
|
||||||
@ -126,7 +170,7 @@
|
|||||||
<option name="INPUT_FILE" value="" />
|
<option name="INPUT_FILE" value="" />
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="main" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
<configuration name="mainview" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
||||||
<module name="WeChatMsg" />
|
<module name="WeChatMsg" />
|
||||||
<option name="INTERPRETER_OPTIONS" value="" />
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
@ -134,35 +178,14 @@
|
|||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="" />
|
<option name="SDK_HOME" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/ui_pc" />
|
||||||
<option name="IS_MODULE_SDK" value="true" />
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/ui_pc/mainview.py" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
<option name="EMULATE_TERMINAL" value="false" />
|
<option name="EMULATE_TERMINAL" value="true" />
|
||||||
<option name="MODULE_MODE" value="false" />
|
|
||||||
<option name="REDIRECT_INPUT" value="false" />
|
|
||||||
<option name="INPUT_FILE" value="" />
|
|
||||||
<method v="2" />
|
|
||||||
</configuration>
|
|
||||||
<configuration name="misc" 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/misc.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="MODULE_MODE" value="false" />
|
||||||
<option name="REDIRECT_INPUT" value="false" />
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
<option name="INPUT_FILE" value="" />
|
<option name="INPUT_FILE" value="" />
|
||||||
@ -210,7 +233,7 @@
|
|||||||
<option name="INPUT_FILE" value="" />
|
<option name="INPUT_FILE" value="" />
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration name="test" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
<configuration name="person" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||||
<module name="WeChatMsg" />
|
<module name="WeChatMsg" />
|
||||||
<option name="INTERPRETER_OPTIONS" value="" />
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
@ -218,14 +241,14 @@
|
|||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="" />
|
<option name="SDK_HOME" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app" />
|
||||||
<option name="IS_MODULE_SDK" value="true" />
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/test.py" />
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/person.py" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
<option name="EMULATE_TERMINAL" value="false" />
|
<option name="EMULATE_TERMINAL" value="true" />
|
||||||
<option name="MODULE_MODE" value="false" />
|
<option name="MODULE_MODE" value="false" />
|
||||||
<option name="REDIRECT_INPUT" value="false" />
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
<option name="INPUT_FILE" value="" />
|
<option name="INPUT_FILE" value="" />
|
||||||
@ -233,11 +256,11 @@
|
|||||||
</configuration>
|
</configuration>
|
||||||
<recent_temporary>
|
<recent_temporary>
|
||||||
<list>
|
<list>
|
||||||
<item itemvalue="Python.decrypt_window" />
|
<item itemvalue="Python.main_pc" />
|
||||||
|
<item itemvalue="Python.person" />
|
||||||
|
<item itemvalue="Python.bubble_message" />
|
||||||
|
<item itemvalue="Python.chat_info" />
|
||||||
<item itemvalue="Python.msg" />
|
<item itemvalue="Python.msg" />
|
||||||
<item itemvalue="Python.test" />
|
|
||||||
<item itemvalue="Python.main" />
|
|
||||||
<item itemvalue="Python.misc" />
|
|
||||||
</list>
|
</list>
|
||||||
</recent_temporary>
|
</recent_temporary>
|
||||||
</component>
|
</component>
|
||||||
@ -253,34 +276,6 @@
|
|||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1672848140146</updated>
|
<updated>1672848140146</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00017" summary="修复了Webengine横向小的问题">
|
|
||||||
<created>1680670947385</created>
|
|
||||||
<option name="number" value="00017" />
|
|
||||||
<option name="presentableId" value="LOCAL-00017" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1680670947385</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00018" summary="新增聊天报告">
|
|
||||||
<created>1682305451381</created>
|
|
||||||
<option name="number" value="00018" />
|
|
||||||
<option name="presentableId" value="LOCAL-00018" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1682305451381</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00019" summary="readme">
|
|
||||||
<created>1684598124207</created>
|
|
||||||
<option name="number" value="00019" />
|
|
||||||
<option name="presentableId" value="LOCAL-00019" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1684598124207</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00020" summary="readme">
|
|
||||||
<created>1684598177829</created>
|
|
||||||
<option name="number" value="00020" />
|
|
||||||
<option name="presentableId" value="LOCAL-00020" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1684598177830</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00021" summary="readme">
|
<task id="LOCAL-00021" summary="readme">
|
||||||
<created>1684598440645</created>
|
<created>1684598440645</created>
|
||||||
<option name="number" value="00021" />
|
<option name="number" value="00021" />
|
||||||
@ -596,7 +591,35 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1700145601841</updated>
|
<updated>1700145601841</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="66" />
|
<task id="LOCAL-00066" summary="导出所有数据库的聊天记录">
|
||||||
|
<created>1700147800698</created>
|
||||||
|
<option name="number" value="00066" />
|
||||||
|
<option name="presentableId" value="LOCAL-00066" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1700147800698</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00067" summary="update readme">
|
||||||
|
<created>1700150198343</created>
|
||||||
|
<option name="number" value="00067" />
|
||||||
|
<option name="presentableId" value="LOCAL-00067" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1700150198343</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00068" summary="数据库加锁避免多线程访问报错">
|
||||||
|
<created>1700228064961</created>
|
||||||
|
<option name="number" value="00068" />
|
||||||
|
<option name="presentableId" value="LOCAL-00068" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1700228064961</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00069" summary="修复聊天气泡不能更改大小的bug">
|
||||||
|
<created>1700232296923</created>
|
||||||
|
<option name="number" value="00069" />
|
||||||
|
<option name="presentableId" value="LOCAL-00069" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1700232296923</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="70" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="UnknownFeatures">
|
<component name="UnknownFeatures">
|
||||||
@ -632,9 +655,6 @@
|
|||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="VcsManagerConfiguration">
|
<component name="VcsManagerConfiguration">
|
||||||
<MESSAGE value="修复部分bug" />
|
|
||||||
<MESSAGE value="替换chat里的contact" />
|
|
||||||
<MESSAGE value="增加中文路径提示" />
|
|
||||||
<MESSAGE value="用stackWidget重写contactUI" />
|
<MESSAGE value="用stackWidget重写contactUI" />
|
||||||
<MESSAGE value="修改联系人视图架构" />
|
<MESSAGE value="修改联系人视图架构" />
|
||||||
<MESSAGE value="加快打开速度" />
|
<MESSAGE value="加快打开速度" />
|
||||||
@ -646,7 +666,6 @@
|
|||||||
<MESSAGE value="新增PC数据库解密" />
|
<MESSAGE value="新增PC数据库解密" />
|
||||||
<MESSAGE value="main首次加载解密界面" />
|
<MESSAGE value="main首次加载解密界面" />
|
||||||
<MESSAGE value="增加日志模块" />
|
<MESSAGE value="增加日志模块" />
|
||||||
<MESSAGE value="update readme" />
|
|
||||||
<MESSAGE value="增加PC端微信解密条件的判断" />
|
<MESSAGE value="增加PC端微信解密条件的判断" />
|
||||||
<MESSAGE value="删除多余的Word文件" />
|
<MESSAGE value="删除多余的Word文件" />
|
||||||
<MESSAGE value="修复无法查找wxid的bug" />
|
<MESSAGE value="修复无法查找wxid的bug" />
|
||||||
@ -657,7 +676,11 @@
|
|||||||
<MESSAGE value="修复db文件空格路径的bug" />
|
<MESSAGE value="修复db文件空格路径的bug" />
|
||||||
<MESSAGE value="修复情感分析数值显示过长的bug" />
|
<MESSAGE value="修复情感分析数值显示过长的bug" />
|
||||||
<MESSAGE value="新增聊天记录导出csv格式" />
|
<MESSAGE value="新增聊天记录导出csv格式" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="新增聊天记录导出csv格式" />
|
<MESSAGE value="导出所有数据库的聊天记录" />
|
||||||
|
<MESSAGE value="update readme" />
|
||||||
|
<MESSAGE value="数据库加锁避免多线程访问报错" />
|
||||||
|
<MESSAGE value="修复聊天气泡不能更改大小的bug" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="修复聊天气泡不能更改大小的bug" />
|
||||||
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
|
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
|
||||||
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" />
|
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" />
|
||||||
</component>
|
</component>
|
||||||
@ -679,6 +702,21 @@
|
|||||||
<line>103</line>
|
<line>103</line>
|
||||||
<option name="timeStamp" value="9" />
|
<option name="timeStamp" value="9" />
|
||||||
</line-breakpoint>
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||||
|
<url>file://$PROJECT_DIR$/app/person.py</url>
|
||||||
|
<line>101</line>
|
||||||
|
<option name="timeStamp" value="10" />
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||||
|
<url>file://$PROJECT_DIR$/app/person.py</url>
|
||||||
|
<line>99</line>
|
||||||
|
<option name="timeStamp" value="11" />
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||||
|
<url>file://$PROJECT_DIR$/app/person.py</url>
|
||||||
|
<line>100</line>
|
||||||
|
<option name="timeStamp" value="12" />
|
||||||
|
</line-breakpoint>
|
||||||
</breakpoints>
|
</breakpoints>
|
||||||
<default-breakpoints>
|
<default-breakpoints>
|
||||||
<breakpoint type="python-exception">
|
<breakpoint type="python-exception">
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import time
|
||||||
|
|
||||||
DB = None
|
DB = None
|
||||||
cursor = None
|
cursor = None
|
||||||
@ -25,15 +26,25 @@ def is_database_exist():
|
|||||||
|
|
||||||
|
|
||||||
def get_contact():
|
def get_contact():
|
||||||
sql = '''select UserName,Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl.bigHeadImgUrl
|
try:
|
||||||
from Contact inner join ContactHeadImgUrl on Contact.UserName = ContactHeadImgUrl.usrName
|
sql = '''select UserName,Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl.bigHeadImgUrl
|
||||||
where Type=3 and Alias is not null
|
from Contact inner join ContactHeadImgUrl on Contact.UserName = ContactHeadImgUrl.usrName
|
||||||
order by PYInitial
|
where Type=3 and Alias is not null
|
||||||
'''
|
order by PYInitial
|
||||||
cursor.execute(sql)
|
limit 30
|
||||||
result = cursor.fetchall()
|
'''
|
||||||
# pprint(result)
|
cursor.execute(sql)
|
||||||
# print(len(result))
|
result = cursor.fetchall()
|
||||||
|
except:
|
||||||
|
time.sleep(0.2)
|
||||||
|
sql = '''select UserName,Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl.bigHeadImgUrl
|
||||||
|
from Contact inner join ContactHeadImgUrl on Contact.UserName = ContactHeadImgUrl.usrName
|
||||||
|
where Type=3 and Alias is not null
|
||||||
|
order by PYInitial
|
||||||
|
'''
|
||||||
|
cursor.execute(sql)
|
||||||
|
result = cursor.fetchall()
|
||||||
|
# DB.commit()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import threading
|
||||||
|
|
||||||
|
lock = threading.Lock()
|
||||||
DB = None
|
DB = None
|
||||||
cursor = None
|
cursor = None
|
||||||
misc_path = "./app/Database/Msg/Misc.db"
|
misc_path = "./app/Database/Msg/Misc.db"
|
||||||
@ -17,11 +19,15 @@ def get_avatar_buffer(userName):
|
|||||||
from ContactHeadImg1
|
from ContactHeadImg1
|
||||||
where usrName=?;
|
where usrName=?;
|
||||||
'''
|
'''
|
||||||
cursor.execute(sql, [userName])
|
try:
|
||||||
result = cursor.fetchall()
|
lock.acquire(True)
|
||||||
# print(result[0][0])
|
cursor.execute(sql, [userName])
|
||||||
if result:
|
result = cursor.fetchall()
|
||||||
return result[0][0]
|
# print(result[0][0])
|
||||||
|
if result:
|
||||||
|
return result[0][0]
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import threading
|
||||||
|
|
||||||
DB = []
|
DB = []
|
||||||
cursor = []
|
cursor = []
|
||||||
msg_root_path = "./app/Database/Msg/"
|
msg_root_path = "./app/Database/Msg/"
|
||||||
|
lock = threading.Lock()
|
||||||
# misc_path = './Msg/Misc.db'
|
# misc_path = './Msg/Misc.db'
|
||||||
if os.path.exists(msg_root_path):
|
if os.path.exists(msg_root_path):
|
||||||
for root, dirs, files in os.walk(msg_root_path):
|
for root, dirs, files in os.walk(msg_root_path):
|
||||||
@ -54,18 +56,41 @@ def get_messages(username_):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_message_by_num(username_, n):
|
||||||
|
sql = '''
|
||||||
|
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime
|
||||||
|
from MSG
|
||||||
|
where StrTalker=?
|
||||||
|
order by CreateTime
|
||||||
|
limit 10
|
||||||
|
'''
|
||||||
|
result = []
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
for cur in cursor:
|
||||||
|
cur = cursor[-1]
|
||||||
|
cur.execute(sql, [username_])
|
||||||
|
result_ = cur.fetchall()
|
||||||
|
result += result_
|
||||||
|
return result_
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
result.sort(key=lambda x: x[5])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def close():
|
def close():
|
||||||
for db in DB:
|
for db in DB:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
msg_root_path = './Msg/'
|
msg_root_path = './Msg/'
|
||||||
init_database()
|
init_database()
|
||||||
|
|
||||||
username = 'wxid_0o18ef858vnu22'
|
# username = 'wxid_0o18ef858vnu22'
|
||||||
result = get_messages(username)
|
# result = get_messages(username)
|
||||||
pprint(result)
|
# pprint(result)
|
||||||
pprint(len(result))
|
# pprint(len(result))
|
||||||
|
result = get_message_by_num('wxid_0o18ef858vnu22', 0)
|
||||||
|
print(result)
|
||||||
|
@ -1,87 +1,319 @@
|
|||||||
from Lib import QtNinePatch2
|
from PIL import Image
|
||||||
|
from PyQt5 import QtGui
|
||||||
from PyQt5.QtCore import Qt, QRectF
|
from PyQt5.QtCore import QSize, pyqtSignal, Qt, QThread
|
||||||
from PyQt5.QtGui import QImage, QPainter, QColor, QFont, QPixmap
|
from PyQt5.QtGui import QPainter, QFont, QColor, QPixmap, QPolygon
|
||||||
from PyQt5.QtWidgets import QLabel, QWidget, QHBoxLayout, QVBoxLayout, QSizePolicy
|
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout, QSizePolicy, QVBoxLayout, QSpacerItem, \
|
||||||
|
QScrollArea, QScrollBar
|
||||||
|
|
||||||
|
|
||||||
class Label(QLabel):
|
class TextMessage(QLabel):
|
||||||
|
heightSingal = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, text, is_send=False, parent=None):
|
||||||
super(Label, self).__init__()
|
super(TextMessage, self).__init__(text, parent)
|
||||||
# .9 格式的图片
|
self.setFont(QFont('微软雅黑', 12))
|
||||||
filp = kwargs.get('filp')
|
self.setWordWrap(True)
|
||||||
self.image = QImage('Data/skin_aio_friend_bubble_pressed.9.png')
|
# self.adjustSize()
|
||||||
if filp:
|
self.setMaximumWidth(800)
|
||||||
self.image = self.image.mirrored(True, False)
|
self.setMinimumWidth(100)
|
||||||
self.txt = kwargs.get('text')
|
self.setMinimumHeight(45)
|
||||||
|
# self.resize(QSize(100,40))
|
||||||
|
|
||||||
|
self.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||||
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
|
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
|
||||||
self.adjustSize()
|
# self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Minimum)
|
||||||
|
if is_send:
|
||||||
|
self.setAlignment(Qt.AlignCenter | Qt.AlignRight)
|
||||||
|
self.setStyleSheet(
|
||||||
|
'''
|
||||||
|
background-color:white;
|
||||||
|
border-radius:10px;
|
||||||
|
border-top: 10px solid white;
|
||||||
|
border-bottom: 10px solid white;
|
||||||
|
border-right: 10px solid white;
|
||||||
|
border-left: 10px solid white;
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.setStyleSheet(
|
||||||
|
'''
|
||||||
|
background-color:#b2e281;
|
||||||
|
border-radius:10px;
|
||||||
|
border-top: 10px solid #b2e281;
|
||||||
|
border-bottom: 10px solid #b2e281;
|
||||||
|
border-right: 10px solid #b2e281;
|
||||||
|
border-left: 10px solid #b2e281;
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
w = len(text) * 16 + 30
|
||||||
|
if w < self.width():
|
||||||
|
self.setMaximumWidth(w)
|
||||||
|
|
||||||
def showEvent(self, event):
|
def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
|
||||||
super(Label, self).showEvent(event)
|
super(TextMessage, self).paintEvent(a0)
|
||||||
pixmap = QtNinePatch2.createPixmapFromNinePatchImage(
|
|
||||||
self.image, self.width(), self.height())
|
|
||||||
self.setPixmap(pixmap)
|
|
||||||
|
|
||||||
#
|
|
||||||
def paintEvent(self, event) -> None:
|
|
||||||
super(Label, self).paintEvent(event)
|
|
||||||
painter = QPainter(self)
|
|
||||||
painter.begin(self)
|
|
||||||
painter.setPen(QColor(150, 100, 23))
|
|
||||||
painter.setFont(QFont('SimSun', 20))
|
|
||||||
painter.setRenderHint(QPainter.Antialiasing)
|
|
||||||
painter.setRenderHint(QPainter.SmoothPixmapTransform)
|
|
||||||
rec = QRectF(30, 40, self.width() - 60, self.height() - 60)
|
|
||||||
painter.drawText(rec, Qt.TextWordWrap, self.txt)
|
|
||||||
painter.end()
|
|
||||||
|
|
||||||
#
|
class Triangle(QLabel):
|
||||||
def resizeEvent(self, event):
|
def __init__(self, Type, is_send=False, parent=None):
|
||||||
super(Label, self).resizeEvent(event)
|
super().__init__(parent)
|
||||||
pixmap = QtNinePatch2.createPixmapFromNinePatchImage(
|
self.Type = Type
|
||||||
self.image, self.width(), self.height())
|
self.is_send = is_send
|
||||||
self.setPixmap(pixmap)
|
self.setFixedSize(6, 45)
|
||||||
|
|
||||||
|
def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
|
||||||
|
super(Triangle, self).paintEvent(a0)
|
||||||
|
if self.Type == 1:
|
||||||
|
painter = QPainter(self)
|
||||||
|
triangle = QPolygon()
|
||||||
|
# print(self.width(), self.height())
|
||||||
|
if self.is_send:
|
||||||
|
painter.setPen(QColor('white'))
|
||||||
|
painter.setBrush(QColor('white'))
|
||||||
|
triangle.setPoints(0, 20, 0, 35, 6, 25)
|
||||||
|
else:
|
||||||
|
painter.setPen(QColor('#b2e281'))
|
||||||
|
painter.setBrush(QColor('#b2e281'))
|
||||||
|
triangle.setPoints(0, 25, 6, 20, 6, 35)
|
||||||
|
painter.drawPolygon(triangle)
|
||||||
|
|
||||||
|
|
||||||
|
class Notice(QLabel):
|
||||||
|
def __init__(self, text, type_=3, parent=None):
|
||||||
|
super().__init__(text, parent)
|
||||||
|
self.type_ = type_
|
||||||
|
self.setFont(QFont('微软雅黑', 12))
|
||||||
|
self.setWordWrap(True)
|
||||||
|
self.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||||
|
self.setAlignment(Qt.AlignCenter)
|
||||||
|
|
||||||
|
|
||||||
|
class Avatar(QLabel):
|
||||||
|
def __init__(self, avatar, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
if isinstance(avatar, str):
|
||||||
|
self.setPixmap(QPixmap(avatar).scaled(45, 45))
|
||||||
|
self.image_path = avatar
|
||||||
|
elif isinstance(avatar, QPixmap):
|
||||||
|
self.setPixmap(avatar.scaled(45, 45))
|
||||||
|
self.setFixedSize(QSize(45, 45))
|
||||||
|
|
||||||
|
|
||||||
|
class OpenImageThread(QThread):
|
||||||
|
def __init__(self, image_path):
|
||||||
|
super().__init__()
|
||||||
|
self.image_path = image_path
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
image = Image.open(self.image_path)
|
||||||
|
image.show()
|
||||||
|
|
||||||
|
|
||||||
|
class ImageMessage(QLabel):
|
||||||
|
def __init__(self, avatar, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.image = QLabel(self)
|
||||||
|
if isinstance(avatar, str):
|
||||||
|
self.setPixmap(QPixmap(avatar))
|
||||||
|
self.image_path = avatar
|
||||||
|
elif isinstance(avatar, QPixmap):
|
||||||
|
self.setPixmap(avatar)
|
||||||
|
self.setMaximumWidth(480)
|
||||||
|
self.setMaximumHeight(720)
|
||||||
|
self.setScaledContents(True)
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
if event.buttons() == Qt.LeftButton: # 左键按下
|
||||||
|
self.open_image_thread = OpenImageThread(self.image_path)
|
||||||
|
self.open_image_thread.start()
|
||||||
|
|
||||||
|
|
||||||
class BubbleMessage(QWidget):
|
class BubbleMessage(QWidget):
|
||||||
def __init__(self, text, avatar, isSend=False, parent=None):
|
def __init__(self, str_content, avatar, Type, is_send=False, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.isSend = isSend
|
self.isSend = is_send
|
||||||
|
# self.set
|
||||||
self.txt = text
|
self.setStyleSheet(
|
||||||
|
'''
|
||||||
|
border:none;
|
||||||
|
'''
|
||||||
|
)
|
||||||
layout = QHBoxLayout()
|
layout = QHBoxLayout()
|
||||||
self.avatar = QLabel()
|
layout.setSpacing(0)
|
||||||
self.avatar.setPixmap(avatar)
|
layout.setContentsMargins(0, 5, 5, 5)
|
||||||
self.message = Label(text=text, filp=isSend)
|
self.avatar = Avatar(avatar)
|
||||||
if isSend:
|
triangle = Triangle(Type, is_send)
|
||||||
layout.addWidget(self.message)
|
if Type == 1:
|
||||||
layout.addWidget(self.avatar, 0, Qt.AlignTop)
|
self.message = TextMessage(str_content, is_send)
|
||||||
layout.setStretch(0, 1)
|
# self.message.setMaximumWidth(int(self.width() * 0.6))
|
||||||
else:
|
else:
|
||||||
layout.addWidget(self.avatar, 0, Qt.AlignTop)
|
self.message = ImageMessage(str_content)
|
||||||
layout.addWidget(self.message)
|
# skin_aio_friend_bubble_pressed.9
|
||||||
layout.setStretch(1, 1)
|
'''
|
||||||
|
border-image:url(./Data/截图222.png) 20 20 20 20;
|
||||||
|
border-top: 5px transparent;
|
||||||
|
border-bottom: 5px transparent;
|
||||||
|
border-right: 5px transparent;
|
||||||
|
border-left: 5px transparent;
|
||||||
|
border-radius:10px;
|
||||||
|
'''
|
||||||
|
self.spacerItem = QSpacerItem(45 + 6, 45, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||||
|
if is_send:
|
||||||
|
layout.addItem(self.spacerItem)
|
||||||
|
layout.addWidget(self.message, 1)
|
||||||
|
layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignLeft)
|
||||||
|
else:
|
||||||
|
layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignRight)
|
||||||
|
layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignRight)
|
||||||
|
layout.addWidget(self.message, 1)
|
||||||
|
layout.addItem(self.spacerItem)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def resizeEvent(self, a0) -> None:
|
|
||||||
w = (self.message.width() - 60) // 27
|
class ScrollAreaContent(QWidget):
|
||||||
row = int(len(self.txt) // w) + 1
|
def __init__(self, parent=None):
|
||||||
print('row', row)
|
super().__init__(parent)
|
||||||
self.message.setMaximumHeight(row * 31 + 80)
|
# self.setStyleSheet(
|
||||||
return
|
# '''
|
||||||
|
# background-color:rgb(127,127,127);
|
||||||
|
# '''
|
||||||
|
# )
|
||||||
|
|
||||||
|
def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
|
||||||
|
# print(self.width(),self.height())
|
||||||
|
self.setMinimumSize(self.width(), self.height())
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QWidget):
|
class ScrollArea(QScrollArea):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWidgetResizable(True)
|
||||||
|
self.setStyleSheet(
|
||||||
|
'''
|
||||||
|
border:none;
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
|
def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
|
||||||
|
# return
|
||||||
|
self.widget().setMinimumSize(self.width(), self.widget().height())
|
||||||
|
self.widget().setMaximumSize(self.width(), self.widget().height())
|
||||||
|
self.widget().resize(QSize(self.width(), self.widget().height()))
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
class ScrollBar(QScrollBar):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.setStyleSheet(
|
||||||
|
'''
|
||||||
|
QScrollBar:vertical {
|
||||||
|
border-width: 0px;
|
||||||
|
border: none;
|
||||||
|
background:rgba(64, 65, 79, 0);
|
||||||
|
width:5px;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
QScrollBar::handle:vertical {
|
||||||
|
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||||
|
stop: 0 #DDDDDD, stop: 0.5 #DDDDDD, stop:1 #aaaaff);
|
||||||
|
min-height: 20px;
|
||||||
|
max-height: 20px;
|
||||||
|
margin: 0 0px 0 0px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
QScrollBar::add-line:vertical {
|
||||||
|
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||||
|
stop: 0 rgba(64, 65, 79, 0), stop: 0.5 rgba(64, 65, 79, 0), stop:1 rgba(64, 65, 79, 0));
|
||||||
|
height: 0px;
|
||||||
|
border: none;
|
||||||
|
subcontrol-position: bottom;
|
||||||
|
subcontrol-origin: margin;
|
||||||
|
}
|
||||||
|
QScrollBar::sub-line:vertical {
|
||||||
|
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||||
|
stop: 0 rgba(64, 65, 79, 0), stop: 0.5 rgba(64, 65, 79, 0), stop:1 rgba(64, 65, 79, 0));
|
||||||
|
height: 0 px;
|
||||||
|
border: none;
|
||||||
|
subcontrol-position: top;
|
||||||
|
subcontrol-origin: margin;
|
||||||
|
}
|
||||||
|
QScrollBar::sub-page:vertical {
|
||||||
|
background: rgba(64, 65, 79, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScrollBar::add-page:vertical {
|
||||||
|
background: rgba(64, 65, 79, 0);
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MyWidget(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.resize(500, 200)
|
||||||
txt = '''在工具中单击边缘可以添加黑点,单击可以删掉黑点,拖动可以调整黑点长度。勾选等选项可以查看内容、缩放等区域右侧可预览不同拉伸情况下的效果,拖动可以调整预览的拉伸比例'''
|
txt = '''在工具中单击边缘可以添加黑点,单击可以删掉黑点,拖动可以调整黑点长度。勾选等选项可以查看内容、缩放等区域右侧可预览不同拉伸情况下的效果,拖动可以调整预览的拉伸比例'''
|
||||||
avatar = QPixmap('Data/head.jpg').scaled(60, 60)
|
avatar = '../data/icons/default_avatar.svg'
|
||||||
bubble_mesage = BubbleMessage(txt, avatar, isSend=False)
|
bubble_message = BubbleMessage(txt, avatar, Type=1, is_send=False)
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
bubble_mesage1 = BubbleMessage(txt, avatar, isSend=True)
|
layout.setSpacing(0)
|
||||||
layout.addWidget(bubble_mesage)
|
|
||||||
layout.addWidget(bubble_mesage1)
|
# 生成滚动区域
|
||||||
|
self.scrollArea = ScrollArea()
|
||||||
|
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
|
scrollBar = ScrollBar()
|
||||||
|
self.scrollArea.setVerticalScrollBar(scrollBar)
|
||||||
|
# self.scrollArea.setGeometry(QRect(9, 9, 261, 211))
|
||||||
|
# 生成滚动区域的内容部署层部件
|
||||||
|
self.scrollAreaWidgetContents = ScrollAreaContent()
|
||||||
|
self.scrollAreaWidgetContents.setMinimumSize(50, 100)
|
||||||
|
# 设置滚动区域的内容部署部件为前面生成的内容部署层部件
|
||||||
|
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
|
||||||
|
layout.addWidget(self.scrollArea)
|
||||||
|
layout0 = QVBoxLayout()
|
||||||
|
layout0.setSpacing(0)
|
||||||
|
# self.scrollArea.setLayout(layout0)
|
||||||
|
self.scrollAreaWidgetContents.setLayout(layout0)
|
||||||
|
|
||||||
|
time = Notice("2023-11-17 15:44")
|
||||||
|
layout0.addWidget(time)
|
||||||
|
txt = "你说啥"
|
||||||
|
avatar_2 = '../data/icons/default_avatar.svg'
|
||||||
|
bubble_message1 = BubbleMessage(txt, avatar_2, Type=1, is_send=True)
|
||||||
|
layout0.addWidget(bubble_message)
|
||||||
|
layout0.addWidget(bubble_message1)
|
||||||
|
|
||||||
|
bubble_message2 = BubbleMessage('', avatar_2, Type=1, is_send=True)
|
||||||
|
layout0.addWidget(bubble_message2)
|
||||||
|
txt = "我啥都没说"
|
||||||
|
avatar0 = 'Data/fg1.png'
|
||||||
|
bubble_message1 = BubbleMessage("D:\Project\Python\PyQt-master\QLabel\Data\\fg1.png", avatar, Type=3,
|
||||||
|
is_send=False)
|
||||||
|
layout0.addWidget(bubble_message1)
|
||||||
|
|
||||||
|
self.spacerItem = QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||||
|
layout0.addItem(self.spacerItem)
|
||||||
# layout.setStretch(0, 1)
|
# layout.setStretch(0, 1)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
|
||||||
|
class Test(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
self.resize(500, 600)
|
||||||
|
w1 = MyWidget()
|
||||||
|
w2 = QLabel("nihao")
|
||||||
|
layout.addWidget(w1)
|
||||||
|
layout.addWidget(w2)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication([])
|
||||||
|
widget = Test()
|
||||||
|
# widget = MyWidget()
|
||||||
|
widget.show()
|
||||||
|
app.exec_()
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
version = '0.2.0'
|
version = '0.2.1'
|
||||||
contact = '474379264'
|
contact = '474379264'
|
||||||
|
@ -13,6 +13,7 @@ from app.Ui.Icon import Icon
|
|||||||
|
|
||||||
class Person:
|
class Person:
|
||||||
def __init__(self, wxid: str):
|
def __init__(self, wxid: str):
|
||||||
|
|
||||||
self.wxid = wxid
|
self.wxid = wxid
|
||||||
self.conRemark = data.get_conRemark(wxid)
|
self.conRemark = data.get_conRemark(wxid)
|
||||||
self.nickname, self.alias = data.get_nickname(wxid)
|
self.nickname, self.alias = data.get_nickname(wxid)
|
||||||
@ -39,6 +40,33 @@ class Contact(Person):
|
|||||||
self.bigHeadImgUrl = ''
|
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)
|
||||||
|
|
||||||
|
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 = QPixmap()
|
||||||
|
|
||||||
|
|
||||||
class ContactPC:
|
class ContactPC:
|
||||||
def __init__(self, contact_info: Dict):
|
def __init__(self, contact_info: Dict):
|
||||||
self.wxid = contact_info.get('UserName')
|
self.wxid = contact_info.get('UserName')
|
||||||
@ -46,6 +74,8 @@ class ContactPC:
|
|||||||
# Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
|
# Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
|
||||||
self.alias = contact_info.get('Alias')
|
self.alias = contact_info.get('Alias')
|
||||||
self.nickName = contact_info.get('NickName')
|
self.nickName = contact_info.get('NickName')
|
||||||
|
if not self.remark:
|
||||||
|
self.remark = self.nickName
|
||||||
self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl')
|
self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl')
|
||||||
self.smallHeadImgBLOG = b''
|
self.smallHeadImgBLOG = b''
|
||||||
self.avatar = QPixmap()
|
self.avatar = QPixmap()
|
||||||
@ -64,3 +94,9 @@ class ContactPC:
|
|||||||
class Group(Person):
|
class Group(Person):
|
||||||
def __init__(self, wxid: str):
|
def __init__(self, wxid: str):
|
||||||
super(Group, self).__init__(wxid)
|
super(Group, self).__init__(wxid)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
p1 = MePC()
|
||||||
|
p2 = MePC()
|
||||||
|
print(p1 == p2)
|
||||||
|
1
app/ui_pc/chat/__init__.py
Normal file
1
app/ui_pc/chat/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .chat_window import ChatWindow
|
48
app/ui_pc/chat/chatInfoUi.py
Normal file
48
app/ui_pc/chat/chatInfoUi.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# -*- 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", "..."))
|
96
app/ui_pc/chat/chatInfoUi.ui
Normal file
96
app/ui_pc/chat/chatInfoUi.ui
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?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>817</width>
|
||||||
|
<height>748</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<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>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_reamrk">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="toolButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>797</width>
|
||||||
|
<height>700</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
68
app/ui_pc/chat/chatUi.py
Normal file
68
app/ui_pc/chat/chatUi.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# -*- 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.setObjectName("horizontalLayout_2")
|
||||||
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
|
||||||
|
self.verticalLayout_2.setSpacing(0)
|
||||||
|
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-width:0;\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.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"))
|
105
app/ui_pc/chat/chatUi.ui
Normal file
105
app/ui_pc/chat/chatUi.ui
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<?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_2" stretch="0,1">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background:transparent;
|
||||||
|
border-width:0;
|
||||||
|
border-style:outset;
|
||||||
|
background-color:rgb(226,226,226);
|
||||||
|
</string>
|
||||||
|
</property>
|
||||||
|
<property name="cursorMoveStyle">
|
||||||
|
<enum>Qt::VisualMoveStyle</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</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>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
85
app/ui_pc/chat/chat_info.py
Normal file
85
app/ui_pc/chat/chat_info.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
from PyQt5.QtCore import QThread, pyqtSignal, Qt
|
||||||
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QSpacerItem, QSizePolicy, QLabel, QHBoxLayout
|
||||||
|
|
||||||
|
from app.DataBase import msg
|
||||||
|
from app.components.bubble_message import BubbleMessage, ScrollBar, ScrollArea, ScrollAreaContent
|
||||||
|
from app.person import MePC
|
||||||
|
|
||||||
|
|
||||||
|
class ChatInfo(QWidget):
|
||||||
|
def __init__(self, contact, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
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.scrollArea = ScrollArea()
|
||||||
|
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
|
scrollBar = ScrollBar()
|
||||||
|
self.scrollArea.setVerticalScrollBar(scrollBar)
|
||||||
|
|
||||||
|
self.scrollAreaWidgetContents = ScrollAreaContent()
|
||||||
|
self.scrollAreaWidgetContents.setMinimumSize(200, 10000)
|
||||||
|
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
|
||||||
|
|
||||||
|
self.vBoxLayout.addWidget(self.scrollArea)
|
||||||
|
self.scroolAreaLayout = QVBoxLayout()
|
||||||
|
self.scroolAreaLayout.setSpacing(0)
|
||||||
|
self.scrollAreaWidgetContents.setLayout(self.scroolAreaLayout)
|
||||||
|
|
||||||
|
def show_chats(self):
|
||||||
|
self.show_chat_thread = ShowChatThread(self.contact)
|
||||||
|
self.show_chat_thread.showSingal.connect(self.show_chat)
|
||||||
|
self.show_chat_thread.finishSingal.connect(self.show_finish)
|
||||||
|
self.show_chat_thread.start()
|
||||||
|
|
||||||
|
def show_finish(self, ok):
|
||||||
|
self.spacerItem = QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||||
|
self.scroolAreaLayout.addItem(self.spacerItem)
|
||||||
|
self.setLayout(self.vBoxLayout)
|
||||||
|
|
||||||
|
def show_chat(self, message):
|
||||||
|
try:
|
||||||
|
type_ = message[2]
|
||||||
|
# print(type_, type(type_))
|
||||||
|
is_send = message[4]
|
||||||
|
avatar = MePC().avatar if is_send else self.contact.avatar
|
||||||
|
if type_ == 1:
|
||||||
|
str_content = message[7]
|
||||||
|
bubble_message = BubbleMessage(
|
||||||
|
str_content,
|
||||||
|
avatar,
|
||||||
|
type_,
|
||||||
|
is_send
|
||||||
|
)
|
||||||
|
# print(str_content)
|
||||||
|
self.scroolAreaLayout.addWidget(bubble_message)
|
||||||
|
except:
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowChatThread(QThread):
|
||||||
|
showSingal = pyqtSignal(tuple)
|
||||||
|
finishSingal = pyqtSignal(int)
|
||||||
|
|
||||||
|
# heightSingal = pyqtSignal(int)
|
||||||
|
def __init__(self, contact):
|
||||||
|
super().__init__()
|
||||||
|
self.wxid = contact.wxid
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
messages = msg.get_message_by_num(self.wxid, 0)
|
||||||
|
for message in messages:
|
||||||
|
self.showSingal.emit(message)
|
||||||
|
self.finishSingal.emit(1)
|
115
app/ui_pc/chat/chat_window.py
Normal file
115
app/ui_pc/chat/chat_window.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
from PyQt5.QtCore import QThread, pyqtSignal
|
||||||
|
from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit
|
||||||
|
|
||||||
|
from app.DataBase import micro_msg, misc
|
||||||
|
from app.components import ContactQListWidgetItem
|
||||||
|
from app.person import ContactPC
|
||||||
|
from .chatUi import Ui_Form
|
||||||
|
from .chat_info import ChatInfo
|
||||||
|
from ..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 ChatWindow(QWidget, Ui_Form):
|
||||||
|
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.show_chats()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
search_action = QAction(self.lineEdit)
|
||||||
|
search_action.setIcon(Icon.Search_Icon)
|
||||||
|
self.lineEdit.addAction(search_action, QLineEdit.LeadingPosition)
|
||||||
|
self.listWidget.clear()
|
||||||
|
self.listWidget.currentRowChanged.connect(self.setCurrentIndex)
|
||||||
|
self.listWidget.setCurrentRow(0)
|
||||||
|
self.stackedWidget.setCurrentIndex(0)
|
||||||
|
|
||||||
|
def show_chats(self):
|
||||||
|
print('chat0')
|
||||||
|
if self.ok_flag:
|
||||||
|
return
|
||||||
|
micro_msg.init_database()
|
||||||
|
if not micro_msg.is_database_exist():
|
||||||
|
QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库")
|
||||||
|
return
|
||||||
|
self.show_thread = ShowContactThread()
|
||||||
|
self.show_thread.showSingal.connect(self.show_chat)
|
||||||
|
self.show_thread.start()
|
||||||
|
self.ok_flag = True
|
||||||
|
|
||||||
|
def show_chat(self, contact):
|
||||||
|
contact_item = ContactQListWidgetItem(contact.nickName, 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)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowContactThread(QThread):
|
||||||
|
showSingal = pyqtSignal(ContactPC)
|
||||||
|
|
||||||
|
# heightSingal = pyqtSignal(int)
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
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)
|
||||||
|
contact.smallHeadImgBLOG = misc.get_avatar_buffer(contact.wxid)
|
||||||
|
contact.set_avatar(contact.smallHeadImgBLOG)
|
||||||
|
self.showSingal.emit(contact)
|
||||||
|
# pprint(contact.__dict__)
|
@ -10,14 +10,17 @@
|
|||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
from PyQt5.QtCore import *
|
from PyQt5.QtCore import *
|
||||||
|
from PyQt5.QtGui import QPixmap
|
||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
|
|
||||||
from app import config
|
from app import config
|
||||||
from app.DataBase import msg
|
from app.DataBase import msg, misc
|
||||||
from app.Ui.Icon import Icon
|
from app.Ui.Icon import Icon
|
||||||
from . import mainwindow
|
from . import mainwindow
|
||||||
|
from .chat import ChatWindow
|
||||||
from .contact import ContactWindow
|
from .contact import ContactWindow
|
||||||
from .tool import ToolWindow
|
from .tool import ToolWindow
|
||||||
|
from ..person import MePC
|
||||||
|
|
||||||
# 美化样式表
|
# 美化样式表
|
||||||
Stylesheet = """
|
Stylesheet = """
|
||||||
@ -67,6 +70,7 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.setWindowIcon(Icon.MainWindow_Icon)
|
self.setWindowIcon(Icon.MainWindow_Icon)
|
||||||
self.setStyleSheet(Stylesheet)
|
self.setStyleSheet(Stylesheet)
|
||||||
self.listWidget.clear()
|
self.listWidget.clear()
|
||||||
|
self.resize(QSize(800, 600))
|
||||||
# self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
|
# self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
|
||||||
self.action_desc.triggered.connect(self.about)
|
self.action_desc.triggered.connect(self.about)
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
@ -79,14 +83,11 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
tool_item = QListWidgetItem(Icon.MyInfo_Icon, '工具', self.listWidget)
|
tool_item = QListWidgetItem(Icon.MyInfo_Icon, '工具', self.listWidget)
|
||||||
|
|
||||||
tool_window = ToolWindow()
|
tool_window = ToolWindow()
|
||||||
label = QLabel('我是页面', self)
|
tool_window.get_info_signal.connect(self.set_my_info)
|
||||||
label.setAlignment(Qt.AlignCenter)
|
self.chat_window = ChatWindow()
|
||||||
# 设置label的背景颜色(这里随机)
|
self.stackedWidget.addWidget(self.chat_window)
|
||||||
# 这里加了一个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.contact_window = ContactWindow()
|
self.contact_window = ContactWindow()
|
||||||
|
# self.contact_window = QWidget()
|
||||||
self.stackedWidget.addWidget(self.contact_window)
|
self.stackedWidget.addWidget(self.contact_window)
|
||||||
label = QLabel('我是页面', self)
|
label = QLabel('我是页面', self)
|
||||||
label.setAlignment(Qt.AlignCenter)
|
label.setAlignment(Qt.AlignCenter)
|
||||||
@ -104,6 +105,19 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.contact_window.show_contacts()
|
self.contact_window.show_contacts()
|
||||||
self.stackedWidget.setCurrentIndex(row)
|
self.stackedWidget.setCurrentIndex(row)
|
||||||
|
|
||||||
|
def set_my_info(self, wxid):
|
||||||
|
self.avatar = QPixmap()
|
||||||
|
img_bytes = misc.get_avatar_buffer(wxid)
|
||||||
|
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 about(self):
|
def about(self):
|
||||||
"""
|
"""
|
||||||
关于
|
关于
|
||||||
|
@ -51,7 +51,9 @@ class Ui_Dialog(object):
|
|||||||
self.label_7.setObjectName("label_7")
|
self.label_7.setObjectName("label_7")
|
||||||
self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1)
|
||||||
self.lineEdit = QtWidgets.QLineEdit(Dialog)
|
self.lineEdit = QtWidgets.QLineEdit(Dialog)
|
||||||
self.lineEdit.setStyleSheet("background:transparent;border-width:0;border-style:outset")
|
self.lineEdit.setStyleSheet("\n"
|
||||||
|
" background:transparent;border-width:0;border-style:outset\n"
|
||||||
|
" ")
|
||||||
self.lineEdit.setFrame(False)
|
self.lineEdit.setFrame(False)
|
||||||
self.lineEdit.setObjectName("lineEdit")
|
self.lineEdit.setObjectName("lineEdit")
|
||||||
self.gridLayout.addWidget(self.lineEdit, 4, 1, 1, 1)
|
self.gridLayout.addWidget(self.lineEdit, 4, 1, 1, 1)
|
||||||
@ -62,6 +64,7 @@ class Ui_Dialog(object):
|
|||||||
self.label_6.setObjectName("label_6")
|
self.label_6.setObjectName("label_6")
|
||||||
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
|
||||||
self.label_key = QtWidgets.QLabel(Dialog)
|
self.label_key = QtWidgets.QLabel(Dialog)
|
||||||
|
self.label_key.setMaximumSize(QtCore.QSize(200, 16777215))
|
||||||
self.label_key.setText("")
|
self.label_key.setText("")
|
||||||
self.label_key.setObjectName("label_key")
|
self.label_key.setObjectName("label_key")
|
||||||
self.gridLayout.addWidget(self.label_key, 5, 1, 1, 1)
|
self.gridLayout.addWidget(self.label_key, 5, 1, 1, 1)
|
||||||
@ -90,6 +93,7 @@ class Ui_Dialog(object):
|
|||||||
self.label_8.setObjectName("label_8")
|
self.label_8.setObjectName("label_8")
|
||||||
self.gridLayout.addWidget(self.label_8, 6, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_8, 6, 0, 1, 1)
|
||||||
self.label_db_dir = QtWidgets.QLabel(Dialog)
|
self.label_db_dir = QtWidgets.QLabel(Dialog)
|
||||||
|
self.label_db_dir.setMaximumSize(QtCore.QSize(200, 300))
|
||||||
self.label_db_dir.setText("")
|
self.label_db_dir.setText("")
|
||||||
self.label_db_dir.setObjectName("label_db_dir")
|
self.label_db_dir.setObjectName("label_db_dir")
|
||||||
self.gridLayout.addWidget(self.label_db_dir, 6, 1, 1, 1)
|
self.gridLayout.addWidget(self.label_db_dir, 6, 1, 1, 1)
|
||||||
|
@ -117,6 +117,12 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="QLabel" name="label_key">
|
<widget class="QLabel" name="label_key">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
@ -173,6 +179,12 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QLabel" name="label_db_dir">
|
<widget class="QLabel" name="label_db_dir">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
@ -12,7 +12,7 @@ from . import decryptUi
|
|||||||
|
|
||||||
class DecryptControl(QWidget, decryptUi.Ui_Dialog):
|
class DecryptControl(QWidget, decryptUi.Ui_Dialog):
|
||||||
DecryptSignal = pyqtSignal(str)
|
DecryptSignal = pyqtSignal(str)
|
||||||
registerSignal = pyqtSignal(str)
|
get_wxidSignal = pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(DecryptControl, self).__init__(parent)
|
super(DecryptControl, self).__init__(parent)
|
||||||
@ -46,6 +46,8 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog):
|
|||||||
self.label_pid.setText(str(self.info['pid']))
|
self.label_pid.setText(str(self.info['pid']))
|
||||||
self.label_version.setText(self.info['version'])
|
self.label_version.setText(self.info['version'])
|
||||||
self.lineEdit.setFocus()
|
self.lineEdit.setFocus()
|
||||||
|
self.checkBox.setChecked(True)
|
||||||
|
self.get_wxidSignal.emit(self.info['wxid'])
|
||||||
if self.wx_dir and os.path.exists(os.path.join(self.wx_dir, self.info['wxid'])):
|
if self.wx_dir and os.path.exists(os.path.join(self.wx_dir, self.info['wxid'])):
|
||||||
self.label_ready.setText('已就绪')
|
self.label_ready.setText('已就绪')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -59,6 +61,7 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog):
|
|||||||
if directory:
|
if directory:
|
||||||
self.label_db_dir.setText(directory)
|
self.label_db_dir.setText(directory)
|
||||||
self.wx_dir = directory
|
self.wx_dir = directory
|
||||||
|
self.checkBox_2.setChecked(True)
|
||||||
if self.ready:
|
if self.ready:
|
||||||
self.label_ready.setText('已就绪')
|
self.label_ready.setText('已就绪')
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt, pyqtSignal
|
||||||
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QLabel
|
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QLabel
|
||||||
|
|
||||||
from .pc_decrypt import DecryptControl
|
from .pc_decrypt import DecryptControl
|
||||||
@ -45,6 +45,8 @@ HistoryPanel::item:hover {
|
|||||||
|
|
||||||
|
|
||||||
class ToolWindow(QWidget, Ui_Dialog):
|
class ToolWindow(QWidget, Ui_Dialog):
|
||||||
|
get_info_signal = pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@ -58,8 +60,9 @@ class ToolWindow(QWidget, Ui_Dialog):
|
|||||||
contact_item = QListWidgetItem(Icon.Contact_Icon, 'None', self.listWidget)
|
contact_item = QListWidgetItem(Icon.Contact_Icon, 'None', self.listWidget)
|
||||||
myinfo_item = QListWidgetItem(Icon.MyInfo_Icon, 'None', self.listWidget)
|
myinfo_item = QListWidgetItem(Icon.MyInfo_Icon, 'None', self.listWidget)
|
||||||
tool_item = QListWidgetItem(Icon.MyInfo_Icon, 'None', self.listWidget)
|
tool_item = QListWidgetItem(Icon.MyInfo_Icon, 'None', self.listWidget)
|
||||||
tool_window = DecryptControl()
|
decrypt_window = DecryptControl()
|
||||||
self.stackedWidget.addWidget(tool_window)
|
decrypt_window.get_wxidSignal.connect(self.get_info_signal)
|
||||||
|
self.stackedWidget.addWidget(decrypt_window)
|
||||||
label = QLabel('我是页面', self)
|
label = QLabel('我是页面', self)
|
||||||
label.setAlignment(Qt.AlignCenter)
|
label.setAlignment(Qt.AlignCenter)
|
||||||
# 设置label的背景颜色(这里随机)
|
# 设置label的背景颜色(这里随机)
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import ctypes
|
import ctypes
|
||||||
import sys
|
import sys
|
||||||
import time
|
|
||||||
|
|
||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
|
|
||||||
from app.ui_pc import mainview
|
|
||||||
from app.ui_pc.tool.pc_decrypt import pc_decrypt
|
from app.ui_pc.tool.pc_decrypt import pc_decrypt
|
||||||
|
|
||||||
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
|
||||||
@ -28,23 +26,6 @@ class ViewController(QWidget):
|
|||||||
self.viewDecrypt.DecryptSignal.connect(self.show_success)
|
self.viewDecrypt.DecryptSignal.connect(self.show_success)
|
||||||
self.viewDecrypt.show()
|
self.viewDecrypt.show()
|
||||||
|
|
||||||
def loadMainWinView(self, username=None):
|
|
||||||
"""
|
|
||||||
聊天界面
|
|
||||||
:param username: 账号
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
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)
|
|
||||||
|
|
||||||
def show_success(self):
|
def show_success(self):
|
||||||
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
|
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
|
||||||
|
|
||||||
@ -52,7 +33,5 @@ class ViewController(QWidget):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
view = ViewController()
|
view = ViewController()
|
||||||
# view.loadPCDecryptView()
|
view.loadPCDecryptView()
|
||||||
view.loadMainWinView()
|
|
||||||
# view.show_success()
|
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
BIN
doc/images/messages_demo.png
Normal file
BIN
doc/images/messages_demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
BIN
doc/images/pc_contact.png
Normal file
BIN
doc/images/pc_contact.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
@ -1,3 +1,4 @@
|
|||||||
# 微信数据库介绍
|
# 微信数据库介绍
|
||||||
|
|
||||||
**这个人比较懒,还什么都没写**
|
**这个人比较懒,还什么都没写**
|
||||||
|
|
||||||
|
71
doc/电脑端使用教程.md
Normal file
71
doc/电脑端使用教程.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# 一、解密微信数据库
|
||||||
|
|
||||||
|
## 主要功能
|
||||||
|
|
||||||
|
1. 解密微信数据库
|
||||||
|
2. 查看聊天记录
|
||||||
|
3. 导出聊天记录
|
||||||
|
* CSV
|
||||||
|
* docx(待实现)
|
||||||
|
* HTML(待实现)
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git clone https://github.com/LC044/WeChatMsg
|
||||||
|
cd WeChatMsg
|
||||||
|
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
```
|
||||||
|
|
||||||
|
## 解密
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
解密步骤:
|
||||||
|
|
||||||
|
1. 登录微信
|
||||||
|
|
||||||
|
2. 运行程序
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python decrypt_window.py
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 点击获取信息
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
4. 设置微信安装路径
|
||||||
|
可以到微信->设置->文件管理查看
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击**设置微信路径**按钮,选择该文件夹路径
|
||||||
|
|
||||||
|
5. 获取到密钥和微信路径之后点击开始解密
|
||||||
|
|
||||||
|
6. 解密后的数据库文件保存在./app/DataBase/Msg路径下
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 查看聊天记录
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
1. 运行程序
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python main_pc.py
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 选择联系人
|
||||||
|
|
||||||
|
<img src='./images/pc_contact.png' alt="运行图片"/>
|
||||||
|
|
||||||
|
3. 导出聊天记录
|
||||||
|
|
||||||
|
聊天记录保存在 **/data/聊天记录/** 文件夹下
|
||||||
|
|
||||||
|
<img src='./images/messages_demo.png' />
|
||||||
|
|
||||||
|
</details>
|
58
main_pc.py
Normal file
58
main_pc.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import ctypes
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
from PyQt5.QtGui import QIcon
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
|
||||||
|
from app.ui_pc import mainview
|
||||||
|
from app.ui_pc.tool.pc_decrypt import pc_decrypt
|
||||||
|
|
||||||
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
|
||||||
|
|
||||||
|
|
||||||
|
class ViewController(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setWindowTitle('解密')
|
||||||
|
self.setWindowIcon(QIcon('./app/data/icons/logo.svg'))
|
||||||
|
self.viewMainWIn = 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.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)
|
||||||
|
|
||||||
|
def show_success(self):
|
||||||
|
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
view = ViewController()
|
||||||
|
# view.loadPCDecryptView()
|
||||||
|
view.loadMainWinView()
|
||||||
|
# view.show_success()
|
||||||
|
sys.exit(app.exec_())
|
@ -94,7 +94,8 @@ pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
|||||||
|
|
||||||
随便下载一个SQLite数据库查看软件就能打开数据库,例如[DB Browser for SQLite](https://sqlitebrowser.org/dl/)
|
随便下载一个SQLite数据库查看软件就能打开数据库,例如[DB Browser for SQLite](https://sqlitebrowser.org/dl/)
|
||||||
|
|
||||||
[数据库功能介绍](./doc/数据库介绍.md)
|
* [数据库功能介绍](./doc/数据库介绍.md)
|
||||||
|
* [更多功能介绍](./doc/电脑端使用教程.md)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user