├── LICENSE ├── README.md ├── _config.yml ├── docs ├── conf.py └── index.rst ├── maxSim.log ├── modules ├── DL │ ├── .gitignore │ ├── .gitignore.bak │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-35.pyc │ │ ├── __init__.cpython-36.pyc │ │ ├── maxSim.cpython-35.pyc │ │ └── maxSim.cpython-36.pyc │ ├── maxSim. │ ├── maxSim.log │ └── maxSim.py ├── Database │ └── .gitkeep ├── OCR │ ├── .gitignore │ ├── Image2txt.log │ ├── Image2txt.py │ ├── __init__.py │ ├── __pycache__ │ │ ├── Image2txt.cpython-35.pyc │ │ ├── Image2txt.cpython-36.pyc │ │ ├── __init__.cpython-35.pyc │ │ └── __init__.cpython-36.pyc │ ├── biaoqing.txt │ ├── checked.info │ ├── substitude.dat │ └── test.py └── QQqt4 │ ├── .gitkeep │ ├── Image2txt.log │ ├── __pycache__ │ ├── bestexplist.cpython-35.pyc │ ├── bestexplist.cpython-36.pyc │ ├── exprobot.cpython-35.pyc │ ├── exprobot.cpython-36.pyc │ ├── exptable.cpython-35.pyc │ ├── exptable.cpython-36.pyc │ ├── flowlayout.cpython-35.pyc │ ├── flowlayout.cpython-36.pyc │ ├── groupUserList.cpython-36.pyc │ ├── maxSim.cpython-35.pyc │ ├── msgList.cpython-36.pyc │ ├── mycopygroupuserlist.cpython-35.pyc │ ├── mycopygroupuserlist.cpython-36.pyc │ ├── mycopymsglist.cpython-35.pyc │ ├── mycopymsglist.cpython-36.pyc │ ├── pyqtChatApp.cpython-35.pyc │ └── pyqtChatApp.cpython-36.pyc │ ├── bestexplist.py │ ├── database.db │ ├── exprobot.py │ ├── exptable.py │ ├── flowlayout.py │ ├── flowlayout.pyc │ ├── groupUserList.pyc │ ├── groupUserList_readme.md │ ├── icons │ ├── arrow_d.png │ ├── arrow_r.png │ ├── chat.png │ ├── copy.png │ ├── delete.png │ ├── dictionary.png │ ├── edit.png │ ├── exp.png │ ├── expr.png │ ├── group.png │ ├── hd_1.png │ ├── img.png │ ├── qq.png │ └── user.png │ ├── init.py │ ├── msgList.pyc │ ├── msgList_readme.md │ ├── mycopygroupuserlist.py │ ├── mycopymsglist.py │ ├── pyqtChatApp.py │ ├── pyqtChatApp_readme.md │ ├── readme.md │ └── ref │ ├── QListWidget Class Reference.pdf │ ├── QListWidgetItem Class Reference.pdf │ ├── QTextEdit Class Reference.pdf │ ├── bq.gif │ ├── mt.gif │ ├── pic1.png │ ├── pic2.png │ ├── pic3.gif │ └── pic4.png ├── requirements.txt ├── sample ├── __init__.py ├── core.py └── helpers.py ├── setup.py └── tests ├── test_advanced.py └── test_basic.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 LiSizhe,QiJiyang,WangZhihao. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Easy-expression 2 | 3 | ## 简述 4 | *Easy-expression* 是一个基于文本的表情包联想插件,可以对网络上的表情包(有文字)进行文字区域提取和OCR识别,将整理到的语句集成语句库。对输入语句进行模糊匹配,便可以得到与之对应的图片。 5 | 6 | **除了对此项目有兴趣的开发者,对于其中的个别模块有需求的也可以将其clone下来作为一种尝试,所有模型和数据均在百度网盘上** 7 | 8 | **开发者借用Github上的开源项目搭建了这个项目, 由衷地感谢提供支持的项目和作者** 9 | ## 依赖 10 | * 在测试之前请安装好相关依赖 11 | > 12 | python3 13 | opencv3+ 14 | sklearn 15 | pyocr 16 | tesseract-ocr 17 | PIL 18 | matplotlib 19 | pyqt4 20 | scipy 21 | ## 直接测试 22 | 23 | 1. 下载[链接](https://pan.baidu.com/s/1hs21ZzI)密码: 4fck 24 | 2. 将其中5个文件放到`Easy-expression/module/DL/`下 25 | 3. 下载[链接](https://pan.baidu.com/s/1mhAlouO)密码: wphv 26 | 4. `cd module/OCR && tar -xjf img.tar.bz /img`将其中的压缩包解压在`Easy-expression/module/OCR/img/`下 27 | 5. `cd ./easy-expression` 28 | `python3 setup.py` 29 | 30 | 模块说明 31 | --- 32 | ### 文本提取 33 | **此模型文本提取效率不高** 34 | 35 | **单模块使用说明:** 36 | 37 | 1. 修改Image2txt.py中的Image_dir的目录路径(所有图片放在一个目录下) 38 | 2. 修改out的写入路径(这是将所有信息写入的路径) 39 | 3. 运行`python3 Image2txt.py` 40 | 41 | ### 文本相似度匹配 42 | 43 | **使用模型语义资料来源于百度贴吧** 44 | 45 | **部分代码参考[FAQrobot](https://github.com/ofooo/FAQrobot)** 46 | 47 | **单模块使用说明:** 48 | 49 | 1. 下载[链接](https://pan.baidu.com/s/1hs21ZzI)密码: 4fck 50 | 2. 将其中5个文件放到`Easy-expression/module/DL/`下 51 | 3. 运行`python3 maxSim.py` 52 | 4. 根据提示输入一句话即可得到反馈 53 | 54 | ### 图形界面 55 | * qt部分引用了[pyqtChat](https://github.com/HeLiangHIT/pyqtChat) 56 | * 在此基础上将源码改为Python3,并增加了表情功能,支持表情收藏与删除。 57 | * 发送的快捷键以及界面风格也做了一些修改 58 | 59 | **主要功能** 60 | 61 | 1. groupUserList 类用于好友列表展示,模拟QQ好友界面。 62 | 2. msgList 类用于消息展示,模拟微信PC端消息界面,支持图片和文字显示。 63 | 3. flowlayout 类是pyqt的example里面的布局,就是依次布局按钮等控件时可能用到,自动调整位置。 64 | 4. exptable 类是表情窗口 65 | 5. pyqtChatApp 类是APP主界面。需在此修改代码最后的表情包路径 66 | 67 | **使用说明** 68 | 69 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/docs/conf.py -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/docs/index.rst -------------------------------------------------------------------------------- /maxSim.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/maxSim.log -------------------------------------------------------------------------------- /modules/DL/.gitignore: -------------------------------------------------------------------------------- 1 | #model 2 | 3 | fash* 4 | attribute.dat 5 | biaoqing.txt 6 | maxSim.log 7 | -------------------------------------------------------------------------------- /modules/DL/.gitignore.bak: -------------------------------------------------------------------------------- 1 | #model 2 | fash* 3 | biaoqing.txt 4 | attribute.dat 5 | -------------------------------------------------------------------------------- /modules/DL/__init__.py: -------------------------------------------------------------------------------- 1 | print('successfully from %s imported'%__package__) 2 | -------------------------------------------------------------------------------- /modules/DL/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/DL/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /modules/DL/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/DL/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /modules/DL/__pycache__/maxSim.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/DL/__pycache__/maxSim.cpython-35.pyc -------------------------------------------------------------------------------- /modules/DL/__pycache__/maxSim.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/DL/__pycache__/maxSim.cpython-36.pyc -------------------------------------------------------------------------------- /modules/DL/maxSim.: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/DL/maxSim. -------------------------------------------------------------------------------- /modules/DL/maxSim.log: -------------------------------------------------------------------------------- 1 | 2017-06-04 08:59:29,727 - __main__ - INFO - 开始载入句子库 2 | 2017-06-04 08:59:29,727 - __main__ - INFO - 开始载入词向量 3 | 2017-06-04 09:00:28,964 - DL.maxSim - INFO - 开始载入句子库 4 | 2017-06-04 09:00:28,975 - DL.maxSim - INFO - 开始载入词向量 5 | 2017-06-04 09:02:06,424 - DL.maxSim - INFO - 开始载入句子库 6 | 2017-06-04 09:02:06,434 - DL.maxSim - INFO - 开始载入词向量 7 | 2017-06-04 09:03:26,513 - DL.maxSim - INFO - 开始载入句子库 8 | 2017-06-04 09:03:26,513 - DL.maxSim - INFO - 开始载入词向量 9 | 2017-06-04 09:03:26,515 - DL.maxSim - INFO - 链接库中的句子分词处理 10 | 2017-06-04 09:03:28,294 - DL.maxSim - INFO - 句子库载入完毕 11 | 2017-06-04 09:04:56,857 - DL.maxSim - INFO - 开始载入句子库 12 | 2017-06-04 09:04:56,880 - DL.maxSim - INFO - 开始载入词向量 13 | 2017-06-04 09:04:56,900 - DL.maxSim - INFO - 链接库中的句子分词处理 14 | 2017-06-04 09:04:58,710 - DL.maxSim - INFO - 句子库载入完毕 15 | 2017-06-04 09:09:49,199 - DL.maxSim - INFO - 开始载入句子库 16 | 2017-06-04 09:09:49,224 - DL.maxSim - INFO - 开始载入词向量 17 | 2017-06-04 09:09:49,226 - DL.maxSim - INFO - 链接库中的句子分词处理 18 | 2017-06-04 09:09:50,217 - DL.maxSim - INFO - 句子库载入完毕 19 | 2017-06-04 09:11:47,173 - DL.maxSim - INFO - 开始载入句子库 20 | 2017-06-04 09:11:47,174 - DL.maxSim - INFO - 开始载入词向量 21 | 2017-06-04 09:11:47,174 - DL.maxSim - INFO - 链接库中的句子分词处理 22 | 2017-06-04 09:11:48,043 - DL.maxSim - INFO - 句子库载入完毕 23 | 2017-06-04 09:15:54,715 - DL.maxSim - INFO - 开始载入句子库 24 | 2017-06-04 09:15:54,715 - DL.maxSim - INFO - 开始载入词向量 25 | 2017-06-04 09:15:54,715 - DL.maxSim - INFO - 链接库中的句子分词处理 26 | 2017-06-04 09:15:55,573 - DL.maxSim - INFO - 句子库载入完毕 27 | 2017-06-04 09:23:34,339 - DL.maxSim - INFO - 开始载入句子库 28 | 2017-06-04 09:23:34,339 - DL.maxSim - INFO - 开始载入词向量 29 | 2017-06-04 09:23:34,339 - DL.maxSim - INFO - 链接库中的句子分词处理 30 | 2017-06-04 09:23:35,141 - DL.maxSim - INFO - 句子库载入完毕 31 | 2017-06-04 09:27:27,187 - DL.maxSim - INFO - 开始载入句子库 32 | 2017-06-04 09:27:27,188 - DL.maxSim - INFO - 开始载入词向量 33 | 2017-06-04 09:27:27,188 - DL.maxSim - INFO - 链接库中的句子分词处理 34 | 2017-06-04 09:27:28,045 - DL.maxSim - INFO - 句子库载入完毕 35 | 2017-06-04 09:29:47,159 - DL.maxSim - INFO - 开始载入句子库 36 | 2017-06-04 09:29:47,159 - DL.maxSim - INFO - 开始载入词向量 37 | 2017-06-04 09:29:47,159 - DL.maxSim - INFO - 链接库中的句子分词处理 38 | 2017-06-04 09:29:47,965 - DL.maxSim - INFO - 句子库载入完毕 39 | 2017-06-04 09:32:07,780 - DL.maxSim - INFO - 开始载入句子库 40 | 2017-06-04 09:32:07,780 - DL.maxSim - INFO - 开始载入词向量 41 | 2017-06-04 09:32:07,780 - DL.maxSim - INFO - 链接库中的句子分词处理 42 | 2017-06-04 09:32:08,681 - DL.maxSim - INFO - 句子库载入完毕 43 | 2017-06-04 09:33:04,170 - DL.maxSim - INFO - 开始载入句子库 44 | 2017-06-04 09:33:04,170 - DL.maxSim - INFO - 开始载入词向量 45 | 2017-06-04 09:33:04,170 - DL.maxSim - INFO - 链接库中的句子分词处理 46 | 2017-06-04 09:33:05,006 - DL.maxSim - INFO - 句子库载入完毕 47 | 2017-06-04 09:35:15,473 - DL.maxSim - INFO - 开始载入句子库 48 | 2017-06-04 09:35:15,474 - DL.maxSim - INFO - 开始载入词向量 49 | 2017-06-04 09:35:15,474 - DL.maxSim - INFO - 链接库中的句子分词处理 50 | 2017-06-04 09:35:16,333 - DL.maxSim - INFO - 句子库载入完毕 51 | 2017-06-04 09:35:49,055 - DL.maxSim - INFO - 开始载入句子库 52 | 2017-06-04 09:35:49,055 - DL.maxSim - INFO - 开始载入词向量 53 | 2017-06-04 09:35:49,055 - DL.maxSim - INFO - 链接库中的句子分词处理 54 | 2017-06-04 09:35:49,913 - DL.maxSim - INFO - 句子库载入完毕 55 | 2017-06-04 09:38:32,142 - DL.maxSim - INFO - 开始载入句子库 56 | 2017-06-04 09:38:32,162 - DL.maxSim - INFO - 开始载入词向量 57 | 2017-06-04 09:38:32,162 - DL.maxSim - INFO - 链接库中的句子分词处理 58 | 2017-06-04 09:38:33,009 - DL.maxSim - INFO - 句子库载入完毕 59 | 2017-06-04 09:40:24,632 - DL.maxSim - INFO - 开始载入句子库 60 | 2017-06-04 09:40:24,632 - DL.maxSim - INFO - 开始载入词向量 61 | 2017-06-04 09:40:24,632 - DL.maxSim - INFO - 链接库中的句子分词处理 62 | 2017-06-04 09:40:25,484 - DL.maxSim - INFO - 句子库载入完毕 63 | 2017-06-04 09:42:21,200 - DL.maxSim - INFO - 开始载入句子库 64 | 2017-06-04 09:42:21,200 - DL.maxSim - INFO - 开始载入词向量 65 | 2017-06-04 09:42:21,201 - DL.maxSim - INFO - 链接库中的句子分词处理 66 | 2017-06-04 09:42:22,047 - DL.maxSim - INFO - 句子库载入完毕 67 | 2017-06-04 09:43:00,496 - DL.maxSim - INFO - 开始载入句子库 68 | 2017-06-04 09:43:00,496 - DL.maxSim - INFO - 开始载入词向量 69 | 2017-06-04 09:43:00,496 - DL.maxSim - INFO - 链接库中的句子分词处理 70 | 2017-06-04 09:43:01,388 - DL.maxSim - INFO - 句子库载入完毕 71 | 2017-06-04 09:46:04,471 - DL.maxSim - INFO - 开始载入句子库 72 | 2017-06-04 09:46:04,471 - DL.maxSim - INFO - 开始载入词向量 73 | 2017-06-04 09:46:04,471 - DL.maxSim - INFO - 链接库中的句子分词处理 74 | 2017-06-04 09:46:05,345 - DL.maxSim - INFO - 句子库载入完毕 75 | 2017-06-04 09:46:31,166 - DL.maxSim - INFO - 开始载入句子库 76 | 2017-06-04 09:46:31,166 - DL.maxSim - INFO - 开始载入词向量 77 | 2017-06-04 09:46:31,167 - DL.maxSim - INFO - 链接库中的句子分词处理 78 | 2017-06-04 09:46:32,040 - DL.maxSim - INFO - 句子库载入完毕 79 | 2017-06-04 09:47:16,457 - DL.maxSim - INFO - 开始载入句子库 80 | 2017-06-04 09:47:16,457 - DL.maxSim - INFO - 开始载入词向量 81 | 2017-06-04 09:47:16,457 - DL.maxSim - INFO - 链接库中的句子分词处理 82 | 2017-06-04 09:47:17,339 - DL.maxSim - INFO - 句子库载入完毕 83 | 2017-06-04 09:52:46,031 - DL.maxSim - INFO - 开始载入句子库 84 | 2017-06-04 09:52:46,048 - DL.maxSim - INFO - 开始载入词向量 85 | 2017-06-04 09:52:46,067 - DL.maxSim - INFO - 链接库中的句子分词处理 86 | 2017-06-04 09:52:47,022 - DL.maxSim - INFO - 句子库载入完毕 87 | 2017-06-04 09:55:22,816 - DL.maxSim - INFO - 开始载入句子库 88 | 2017-06-04 09:55:22,816 - DL.maxSim - INFO - 开始载入词向量 89 | 2017-06-04 09:55:22,817 - DL.maxSim - INFO - 链接库中的句子分词处理 90 | 2017-06-04 09:55:23,705 - DL.maxSim - INFO - 句子库载入完毕 91 | 2017-06-04 09:56:17,554 - DL.maxSim - INFO - 开始载入句子库 92 | 2017-06-04 09:56:17,555 - DL.maxSim - INFO - 开始载入词向量 93 | 2017-06-04 09:56:17,555 - DL.maxSim - INFO - 链接库中的句子分词处理 94 | 2017-06-04 09:56:18,457 - DL.maxSim - INFO - 句子库载入完毕 95 | 2017-06-04 09:58:29,247 - DL.maxSim - INFO - 开始载入句子库 96 | 2017-06-04 09:58:29,247 - DL.maxSim - INFO - 开始载入词向量 97 | 2017-06-04 09:58:29,247 - DL.maxSim - INFO - 链接库中的句子分词处理 98 | 2017-06-04 09:58:30,145 - DL.maxSim - INFO - 句子库载入完毕 99 | 2017-06-04 09:59:48,954 - DL.maxSim - INFO - 开始载入句子库 100 | 2017-06-04 09:59:48,955 - DL.maxSim - INFO - 开始载入词向量 101 | 2017-06-04 09:59:48,955 - DL.maxSim - INFO - 链接库中的句子分词处理 102 | 2017-06-04 09:59:49,847 - DL.maxSim - INFO - 句子库载入完毕 103 | 2017-06-04 10:17:27,775 - DL.maxSim - INFO - 开始载入句子库 104 | 2017-06-04 10:17:27,775 - DL.maxSim - INFO - 开始载入词向量 105 | 2017-06-04 10:17:27,775 - DL.maxSim - INFO - 链接库中的句子分词处理 106 | 2017-06-04 10:17:27,775 - DL.maxSim - INFO - 句子库载入完毕 107 | 2017-06-04 10:29:56,215 - DL.maxSim - INFO - 开始载入句子库 108 | 2017-06-04 10:29:56,215 - DL.maxSim - INFO - 开始载入词向量 109 | 2017-06-04 10:29:56,217 - DL.maxSim - INFO - 链接库中的句子分词处理 110 | 2017-06-04 10:29:57,700 - DL.maxSim - INFO - 句子库载入完毕 111 | 2017-06-04 10:31:44,544 - DL.maxSim - INFO - 开始载入句子库 112 | 2017-06-04 10:31:44,559 - DL.maxSim - INFO - 开始载入词向量 113 | 2017-06-04 10:31:44,562 - DL.maxSim - INFO - 链接库中的句子分词处理 114 | 2017-06-04 10:31:46,131 - DL.maxSim - INFO - 句子库载入完毕 115 | 2017-06-04 10:45:47,635 - DL.maxSim - INFO - 开始载入句子库 116 | 2017-06-04 10:45:47,635 - DL.maxSim - INFO - 开始载入词向量 117 | 2017-06-04 10:45:47,636 - DL.maxSim - INFO - 链接库中的句子分词处理 118 | 2017-06-04 10:45:48,962 - DL.maxSim - INFO - 句子库载入完毕 119 | -------------------------------------------------------------------------------- /modules/DL/maxSim.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Date : 2017-05-28 10:13:14 4 | # @Author : Sizheree (sizheree.github.io) 5 | # @Link : 6 | # @Version : $1.0$ 7 | 8 | import logging 9 | import time 10 | import numpy as np 11 | import matplotlib.pyplot as plt 12 | 13 | # print(__package__, __file__) 14 | logging.basicConfig(level=logging.INFO) 15 | log = logging.getLogger(__name__) 16 | # create a handler 17 | handler = logging.FileHandler('../DL/maxSim.log' if __package__ == 'DL' else './maxSim.log') 18 | handler.setLevel(logging.INFO) 19 | # create a logging format 20 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 21 | handler.setFormatter(formatter) 22 | log.addHandler(handler) 23 | 24 | # 结巴分词库 25 | import jieba 26 | jieba.default_logger.setLevel(logging.ERROR) 27 | # 解析词性 28 | import jieba.posseg as pseg 29 | #绝对路径 30 | def pp(ppath): 31 | import os 32 | return os.path.join(os.getcwd(), os.path.dirname(__file__), ppath) 33 | #单个句子类 34 | class Senten2vec(): 35 | def __init__(self, sentence): 36 | log.debug('split: %s', sentence.split("#")) 37 | self.sentence, self.picture = sentence.split('#') 38 | self.picture = self.picture.strip() 39 | self.sentence_word = [] 40 | self.sentence_vec = [] 41 | 42 | def __str__(self): 43 | return "sentence%s"%self.sentence + "\nsentence_vec%s\n"%self.sentence_vec 44 | #对链接的处理库 45 | # 链接就是映射句子到图的语句 46 | class link_processor(): 47 | def __init__(self, txt_file='../OCR/biaoqing.txt', model_file='./fash250.model.bin'): 48 | self.txt_file = txt_file 49 | self.model_file = model_file 50 | self.lastNsen = 6 51 | with open('../DL/attribute.dat', 'rb') as fp: 52 | import pickle 53 | self.attr_weigh= pickle.load(fp) 54 | self.load() 55 | 56 | def load(self): 57 | from gensim.models import Word2Vec 58 | # 存放每一个句子实例的库 59 | self.link_database = [] 60 | # 存放模型 61 | self.vecmodel = Word2Vec.load(self.model_file) 62 | log.info('开始载入句子库') 63 | log.info('开始载入词向量') 64 | with open(self.txt_file) as fp: 65 | senten_list = fp.readlines() 66 | log.debug("senten%s", senten_list) 67 | for senten_txt in senten_list: 68 | self.link_database.append(Senten2vec(senten_txt)) 69 | log.info('链接库中的句子分词处理') 70 | for link in self.link_database: 71 | link.sentence_word = (set(jieba.cut(link.sentence))) 72 | 73 | for link in self.link_database: 74 | link.sentence_vec = {word for word in link.sentence_word if word in self.vecmodel.wv.index2word} 75 | 76 | log.info('句子库载入完毕') 77 | # 找出句子库中相似度最高的n个句子 78 | def maxSimTxt(self, input_txt='可是', simCondision=0.1): 79 | if not self.vecmodel: 80 | self.load() 81 | for link in self.link_database: 82 | link.sim = self.juziSim_vec(input_txt, link.sentence_vec, self.attr_weigh) 83 | 84 | mostNSimlink =sorted(self.link_database, key = lambda link:link.sim, reverse=True) 85 | log.debug(mostNSimlink) 86 | log.debug([x.sim for x in self.link_database]) 87 | if len(mostNSimlink)==0 or mostNSimlink[0].sim < simCondision: 88 | log.info('没有较好匹配的语句,请重新输入其他语句') 89 | return None 90 | return mostNSimlink[:self.lastNsen] 91 | # 输入的语句和单个句子的相似度计算 92 | def juziSim_vec(self, intxt, questionWordset, posWeight=None): # juziIn输入的句子,juziLi句子库里的句子 93 | if posWeight == None: 94 | log.warning('there is no posWeight') 95 | return 0 96 | intxtSet = set(list(pseg.cut(intxt))) 97 | if not len(intxtSet): 98 | return 0 99 | simWeight = 0 100 | totalWeight = 0 101 | for word, pos in intxtSet: 102 | if word in self.vecmodel.wv.index2word: 103 | wordPosWeight = posWeight.get(pos, 1) 104 | totalWeight += wordPosWeight 105 | 106 | wordMaxWeight = 0 107 | for t in questionWordset: 108 | # print(word, t) 109 | tmp = self.vecmodel.wv.similarity(word, t) 110 | if wordMaxWeight < tmp: 111 | wordMaxWeight = tmp 112 | simWeight += wordPosWeight * wordMaxWeight 113 | if totalWeight == 0: 114 | return 0 115 | return simWeight/totalWeight 116 | 117 | if __name__ == '__main__' : 118 | log.setLevel(logging.INFO) 119 | links = link_processor() 120 | while True: 121 | try : 122 | input_sen = input('please input: ') 123 | mostSim = links.maxSimTxt(input_sen) 124 | if not mostSim: 125 | continue 126 | fig = plt.figure(figsize=(15, 3)) 127 | for i, link in enumerate(mostSim, start=1): 128 | print('most %d similar sentence is \n%s'%(i, link.sentence)) 129 | log.debug("filename:%s",link.picture) 130 | img = plt.imread(link.picture) 131 | plt.subplot(1, links.lastNsen, i) 132 | plt.imshow(img) 133 | plt.xticks([]), plt.yticks([]) 134 | plt.title('the most %d similar figure'%i) 135 | plt.show() 136 | print('***************%s*******************\n'%input_sen) 137 | except KeyboardInterrupt as e: 138 | break 139 | 140 | -------------------------------------------------------------------------------- /modules/Database/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/Database/.gitkeep -------------------------------------------------------------------------------- /modules/OCR/.gitignore: -------------------------------------------------------------------------------- 1 | #imgs for OCR 2 | 3 | img/ 4 | 5 | #output 6 | 7 | -------------------------------------------------------------------------------- /modules/OCR/Image2txt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # @Date : 2017-05-29 23:29:00 4 | # @Author : SizheRee(sizheree.github.io) 5 | # @Link : http://sizheree.github.io 6 | # @Version : $1.0 7 | 8 | import cv2 9 | import pyocr 10 | import numpy as np 11 | import sklearn.cluster as cl 12 | import os 13 | import PIL.Image as PI 14 | import matplotlib.pyplot as plt 15 | import sklearn 16 | import re 17 | from functools import reduce 18 | import logging 19 | logging.basicConfig(level=logging.DEBUG) 20 | log = logging.getLogger(__name__) 21 | # create a handler 22 | handler = logging.FileHandler('Image2txt' + '.log') 23 | handler.setLevel(logging.INFO) 24 | # create a logging format 25 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 26 | handler.setFormatter(formatter) 27 | log.addHandler(handler) 28 | 29 | class Contour(): 30 | def __init__(self, Contour): 31 | self.Contour = Contour # 32 | self.Hull = None # 33 | self.BoundRect = [x,y,w,h] = cv2.boundingRect(Contour) # 34 | self.centorid = None # 35 | self.ContArea = None # 36 | self.analysis() 37 | def analysis(self): 38 | self.Hull = cv2.convexHull(self.Contour) 39 | M = cv2.moments(self.Hull) 40 | try: 41 | cx = int(M['m10']/M['m00']) 42 | cy = int(M['m01']/M['m00']) 43 | self.centorid = (cx, cy) 44 | except ZeroDivisionError as e: 45 | pass 46 | self.ContArea = cv2.contourArea(self.Hull) 47 | 48 | class picture_ocr(object): 49 | def __init__(self, filename): 50 | self.filename = filename 51 | self.image_croped_list = [] 52 | self.centroids = [] 53 | self.Contour_list = [] 54 | self.image_shape = None 55 | self._analysis() 56 | self.config() 57 | 58 | def config(self): 59 | self.tool = pyocr.get_available_tools()[0] 60 | self.lang = 'chi_sim' 61 | 62 | def _analysis(self): 63 | kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3)) 64 | Contour_list = [] 65 | try: 66 | img = cv2.imread(self.filename, 0) 67 | shape = np.array(img.shape, np.int0) 68 | except AttributeError as e: 69 | return None 70 | # 将图片较小的图片放大 71 | raw_w, raw_h = shape[0], shape[1] 72 | if raw_w < 400: 73 | img = cv2.resize(img, tuple(np.int0(shape/raw_w*400))) 74 | if raw_h < 400: 75 | img = cv2.resize(img, tuple(np.int0(shape/raw_h*400))) 76 | new_w, new_h = img.shape 77 | #canny边缘算子 78 | img_canny = cv2.Canny(img, 150, 200) 79 | # 转化为bgr 80 | # img_display = cv2.cvtColor(img_canny, cv2.COLOR_GRAY2BGR) 81 | imgo, contours, hierarchy = cv2.findContours(img_canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 82 | 83 | for contour in contours: 84 | [x,y,w,h] = cv2.boundingRect(contour) 85 | if w < new_w*0.01 or h < new_h*0.01: #细小碎片丢弃 86 | continue 87 | Contour_list.append(Contour(contour)) #Contour_list 88 | try: 89 | #将所有的轮廓按照面积大小进行排序 90 | Contour_list = sorted(Contour_list, key=lambda x:x.ContArea, reverse=True) 91 | # 按照从大到小画边缘,如果满足条件的画就判断为字的边框画一条黑色边缘线隔绝 92 | for contour in Contour_list: 93 | img_display = cv2.drawContours(img_canny, [contour.Hull], 0, 255, -1) 94 | if contour.BoundRect[2] < new_w*0.01 or contour.BoundRect[2] > new_w*0.5: 95 | continue 96 | if contour.BoundRect[3] < new_h*0.01 or contour.BoundRect[3] > new_h*0.5: 97 | continue 98 | img_display = cv2.drawContours(img_display, [contour.Hull], 0, 0, 1) 99 | # 删除大块红色 100 | for contour in Contour_list: 101 | if contour.BoundRect[2] > new_w*0.3 or contour.BoundRect[3] > new_h*0.3: 102 | img_display = cv2.drawContours(img_display, [contour.Hull], 0, 0, -1) 103 | # 删除最大块后女各色 104 | # close将边缘的缝隙合上 105 | img_display = cv2.morphologyEx(img_display, cv2.MORPH_CLOSE, (9, 9)) 106 | 107 | #  第二波处理 108 | Contour_list2 = [] 109 | centroids = [] # centroids 110 | #黑色背景图 111 | img_bg = np.zeros(shape, np.int8) 112 | ret, img_thresh = cv2.threshold(img, 180 , 255, cv2.THRESH_BINARY_INV) 113 | kernel2 = cv2.getStructuringElement(cv2.MORPH_CROSS,(3 , 3)) 114 | img_opened = cv2.morphologyEx(img_thresh,cv2.MORPH_OPEN, kernel2) 115 | imgo, contours, hierarchy = cv2.findContours(img_opened,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 116 | for contour in contours: 117 | [x2,y2,w2,h2] = cv2.boundingRect(contour) 118 | if w2 < new_w*0.03 or w2 > new_w*0.5 or\ 119 | h2 < new_h*0.03 or h2 > new_h*0.5: 120 | continue 121 | centroids.append((x2+w2/2, y2+h2/2))#centroid? 122 | cv2.rectangle(img_bg, (x2, y2), (x2+w2,y2+h2),(255,255,255), -1) 123 | Contour_list2.append(Contour(contour)) 124 | # dbscan算法 125 | matrix = np.array(centroids) 126 | if(len(matrix) == 0): 127 | return None 128 | eps = (x + new_h)*0.2 129 | # print('matrix len: %s'%len(matrix), centroids) 130 | ret, sk_index = sklearn.cluster.dbscan(matrix, eps, min_samples=1) 131 | true_centorids = [tuple(x) for x in matrix[sk_index==0]] 132 | test_list = Contour_list2 133 | xmin, xmax, ymin, ymax = self.find_extrm(test_list) 134 | mask = np.zeros(img.shape, np.int8) 135 | mask[ymin:ymax, xmin:xmax] = 1 136 | img_display = cv2.bitwise_and(img_display, img_display, mask=mask) 137 | img_white = img_display 138 | 139 | img_blackbg = np.zeros(img_white.shape, np.int8) 140 | #display 141 | linesum = np.sum(img_white>1, axis=1) 142 | seg_list = self.segment(linesum) 143 | #滤去宽度小的行 144 | filte_list = list(filter(lambda x: x[1]-x[0]>(xmax-xmin)*0.08, seg_list)) 145 | if(len(filte_list)!=0): 146 | for seg in seg_list: 147 | img_blackbg[seg[0], :] =255 148 | for filt in filte_list: 149 | for i in range(filt[0], filt[1]): 150 | img_blackbg[i][:linesum[i]] = 1 151 | k = 0 152 | for filt in filte_list: 153 | img_crop = img[filt[0]-1:filt[1], xmin:xmax] 154 | hi, wi= img_crop.shape 155 | hi += 6 156 | wi += 6 157 | img_crop_bg = np.ones((hi, wi))*255 158 | img_crop_bg[3:-3, 3:-3] = img_crop 159 | self.image_croped_list.append(img_crop_bg) 160 | else: 161 | return None 162 | except ValueError as e: 163 | pass 164 | return None 165 | 166 | def find_extrm(self, test_list): 167 | ymin = xmin = 1000 168 | ymax = xmax = 0 169 | for cont in test_list: 170 | x, y, w, h = cont.BoundRect 171 | xmin = x if x < xmin else xmin 172 | xmax = x+w if x+w > xmax else xmax 173 | ymin = y if y < ymin else ymin 174 | ymax = y+h if y+h > ymax else ymax 175 | return (xmin, xmax, ymin, ymax) 176 | def segment(self, linesum, mode=0): 177 | seg_list = [] 178 | a= list((np.int8(linesum>5))) 179 | if mode==1: 180 | print(a) 181 | a[0] = str(a[0]) 182 | s = reduce(lambda x, y: x+str(y), a) 183 | itera = re.finditer(r'1+', s) 184 | for i in itera: 185 | seg_list.append(i.span()) 186 | return seg_list 187 | def get_txt(self): 188 | if not self.image_croped_list: 189 | self._analysis() 190 | txt_list = [] 191 | for i in self.image_croped_list: 192 | txt = self.tool.image_to_string(PI.fromarray(i), lang=self.lang, 193 | builder=pyocr.builders.TextBuilder()) 194 | txt_list.append(txt) 195 | return txt_list 196 | def get_crop_txt(self): 197 | img_croped_list = self.image_croped_list 198 | txt_list = [] 199 | if not self.image_croped_list: 200 | self._analysis() 201 | for img_croped in img_croped_list: 202 | if img_croped.shape[0] <60: 203 | xs, ys = img_croped.shape 204 | log.debug('xs, ys%s', (xs, ys)) 205 | xs, ys = 60, int(60/xs*ys)+2 206 | 207 | img_croped = cv2.resize(img_croped, (ys ,xs)) 208 | if img_croped.shape[1] < 200: 209 | xs, ys = img_croped.shape 210 | xs, ys = int(200/ys*xs), 200 211 | img_croped = cv2.resize(img_croped, (ys ,xs)) 212 | 213 | txt = self.tool.image_to_string(PI.fromarray(img_croped), lang=self.lang, 214 | builder=pyocr.builders.TextBuilder()) 215 | log.debug('in txt %s', txt) 216 | txt_list.append(txt) 217 | return ''.join(txt_list) 218 | 219 | 220 | if __name__ == '__main__': 221 | log.setLevel(logging.INFO) 222 | #设置两个路径参数 223 | Image_dir = os.path.split(__file__)[0] + '/img/' 224 | print(Image_dir) 225 | out = open('./biaoqing.txt', 'a') 226 | 227 | log.debug('oh ? %s', 'checked.info' not in os.listdir()) 228 | 229 | checked_info = open('checked.info', 'a+') 230 | checked_info.seek(0) 231 | checked_filelist = checked_info.readlines() 232 | 233 | os.chdir(Image_dir) 234 | count = 0 235 | for subdir in os.listdir(): 236 | if not os.path.isdir(subdir): 237 | continue 238 | for filename in os.listdir(subdir): 239 | fulladdress = '/'.join((Image_dir ,subdir ,filename)) 240 | log.debug('filename: %s', fulladdress) 241 | #两种不会继续分析的情况,一种是在checked_info中存在,一种是后缀为.jpg 242 | if fulladdress + '\n' in checked_filelist : 243 | log.info('%s 已存在', fulladdress) 244 | continue 245 | else : 246 | checked_info.write(fulladdress + '\n') 247 | if os.path.splitext(filename)[1] != '.jpg': 248 | continue 249 | #试图对图片做OCR如果OCR结果是空字符或者发生错误都放弃OCR 250 | try: 251 | pic_ocr = picture_ocr(subdir +'/' + filename) 252 | txt = pic_ocr.get_crop_txt() 253 | log.debug('txt:%s', txt) 254 | log.debug('pre: %s', txt) 255 | txt = re.subn(r'[^\w\u4e00-\u9fa5]+','', txt)[0].strip() 256 | log.info("after: %s", txt) 257 | except AttributeError as e: 258 | log.debug('error%s', e) 259 | raise e 260 | if not txt: 261 | log.info('ocr failed %s', '放弃') 262 | continue 263 | write_string = txt + '#' + Image_dir + subdir + '/' + filename +'\n' 264 | log.debug(write_string) 265 | out.write(write_string) 266 | count += 1 267 | if count > 3: 268 | break 269 | out.close() 270 | checked_info.close() 271 | - 272 | -------------------------------------------------------------------------------- /modules/OCR/__init__.py: -------------------------------------------------------------------------------- 1 | print('successfully from %s imported'%__package__) 2 | -------------------------------------------------------------------------------- /modules/OCR/__pycache__/Image2txt.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/OCR/__pycache__/Image2txt.cpython-35.pyc -------------------------------------------------------------------------------- /modules/OCR/__pycache__/Image2txt.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/OCR/__pycache__/Image2txt.cpython-36.pyc -------------------------------------------------------------------------------- /modules/OCR/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/OCR/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /modules/OCR/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/OCR/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /modules/OCR/biaoqing.txt: -------------------------------------------------------------------------------- 1 | 看咽#../OCR/img//个性表情包/18.jpg 2 | 我就是听我老婆的#../OCR/img//个性表情包/54.jpg 3 | 你再说_遍#../OCR/img//个性表情包/15.jpg 4 | 约炮吗妹砸#../OCR/img//个性表情包/12.jpg 5 | 我只求他曰我能双归#../OCR/img//个性表情包/141.jpg 6 | 人我饮酒醉#../OCR/img//个性表情包/48.jpg 7 | 〇翼廖棺思我愁断肠#../OCR/img//个性表情包/46.jpg 8 | 我只求他曰我能双归#../OCR/img//个性表情包/181.jpg 9 | 帼愤#../OCR/img//个性表情包/43.jpg 10 | 去王元#../OCR/img//个性表情包/23.jpg 11 | 蚝油麦酱惰#../OCR/img//个性表情包/199.jpg 12 | 鄙矗这么肺#../OCR/img//个性表情包/8.jpg 13 | o下朐莪拿出昊强晰昴#../OCR/img//个性表情包/17.jpg 14 | 兽噩n#../OCR/img//个性表情包/22.jpg 15 | 尽曹跟我说_声#../OCR/img//个性表情包/73.jpg 16 | 快来扶我_把#../OCR/img//个性表情包/47.jpg 17 | 张蛔屹药#../OCR/img//个性表情包/27.jpg 18 | 尽曹跟我说_声#../OCR/img//个性表情包/33.jpg 19 | 自宁T我出生以来啊#../OCR/img//个性表情包/21.jpg 20 | 江沪浙包邮#../OCR/img//个性表情包/36.jpg 21 | 江沪浙包邮#../OCR/img//个性表情包/76.jpg 22 | 自宁T我出生以来啊#../OCR/img//个性表情包/61.jpg 23 | 主人公出生在_个贫困的冢庭墓#../OCR/img//个性表情包/81.jpg 24 | 主人公出生在_个贫困的冢庭墓#../OCR/img//个性表情包/121.jpg 25 | 来阿互相伤害啊#../OCR/img//个性表情包/171.jpg 26 | 董鹳熹卫什么_囊了脚霞#../OCR/img//个性表情包/16.jpg 27 | 我老婆除了身材好声昔好听脾气好也没啥比你好的#../OCR/img//个性表情包/57.jpg 28 | 我会让你朋白我从不说空话#../OCR/img//个性表情包/68.jpg 29 | 丰艮土嬴羽嬴羽#../OCR/img//个性表情包/110.jpg 30 | 只要你蹲下我们就会有故亭#../OCR/img//个性表情包/32.jpg 31 | 去王元#../OCR/img//个性表情包/63.jpg 32 | 张蛔屹药#../OCR/img//个性表情包/67.jpg 33 | 汕嘟忐左心房为你敞大大#../OCR/img//个性表情包/45.jpg 34 | _一_寸腑忒二#../OCR/img//个性表情包/19.jpg 35 | 亘是饨俏甜辗旱威胁#../OCR/img//个性表情包/3.jpg 36 | 主人公出生在_个贫困的冢庭墓#../OCR/img//个性表情包/41.jpg 37 | 我会让你朋白我从不说空话#../OCR/img//个性表情包/28.jpg 38 | 请远要我这个花藁少女#../OCR/img//个性表情包/58.jpg 39 | 我只求他曰我能双归#../OCR/img//个性表情包/101.jpg 40 | 可以这很活佛#../OCR/img//个性表情包/42.jpg 41 | 明明长得丑却还非常任性#../OCR/img//个性表情包/1.jpg 42 | 兽噩n#../OCR/img//个性表情包/62.jpg 43 | 歹舵瓢慢粤叹豁寸#../OCR/img//个性表情包/163.jpg 44 | 只要你蹲下我们就会有故亭#../OCR/img//个性表情包/72.jpg 45 | 不要再夸我了这样的日子我受够了#../OCR/img//暴走漫画表情包/18.jpg 46 | 操他妈的老子一来就冷场是不是又寸我有意见啊#../OCR/img//暴走漫画表情包/30.jpg 47 | 镳囊女蛔友啧簪#../OCR/img//暴走漫画表情包/54.jpg 48 | 喹郡扮你他妈的昕不昕#../OCR/img//暴走漫画表情包/214.jpg 49 | 我叫你_声SB你敢答应吗#../OCR/img//暴走漫画表情包/109.jpg 50 | 涯蘑病耒未未我唱药#../OCR/img//暴走漫画表情包/12.jpg 51 | 世界那么大为什么最帅的偏偏罡我#../OCR/img//暴走漫画表情包/13.jpg 52 | 年轻人我装逼没事你装就危险了#../OCR/img//暴走漫画表情包/43.jpg 53 | 我就是胖着玩玩谁像你丑得那么认真#../OCR/img//暴走漫画表情包/59.jpg 54 | 我也是笑的胃疼#../OCR/img//暴走漫画表情包/25.jpg 55 | 我觉耆导尔应该亲我_口#../OCR/img//暴走漫画表情包/8.jpg 56 | _喔唁#../OCR/img//暴走漫画表情包/52.jpg 57 | 你以静不量这祥子的#../OCR/img//暴走漫画表情包/219.jpg 58 | 氛庸对万拒收了您的消息还翼寸您吐了口口水#../OCR/img//暴走漫画表情包/169.jpg 59 | 不要这样好吗#../OCR/img//暴走漫画表情包/210.jpg 60 | 麸愤钦酬#../OCR/img//暴走漫画表情包/22.jpg 61 | 删唧删嘀炖川蹴镶副翼T犬雇黜蒯我岫鹏扒从不#../OCR/img//暴走漫画表情包/118.jpg 62 | 事实就是这样#../OCR/img//暴走漫画表情包/125.jpg 63 | 你个小牙签#../OCR/img//暴走漫画表情包/20.jpg 64 | 多吃点#../OCR/img//暴走漫画表情包/29.jpg 65 | 我这么帅装个逼怎么了#../OCR/img//暴走漫画表情包/113.jpg 66 | 尔仟躏巴是加愕林吗每次劳资_回来葳皇99#../OCR/img//暴走漫画表情包/107.jpg 67 | 颜要好#../OCR/img//暴走漫画表情包/112.jpg 68 | 掐指一篝你命里缺我#../OCR/img//暴走漫画表情包/224.jpg 69 | 快乐辣么大#../OCR/img//暴走漫画表情包/47.jpg 70 | 年轻人我装逼没事你装就危险了#../OCR/img//暴走漫画表情包/130.jpg 71 | 还在这装逼你女朋友打电话约我了#../OCR/img//暴走漫画表情包/38.jpg 72 | 爱你思密达#../OCR/img//暴走漫画表情包/178.jpg 73 | 1_你宽得你很萌你那是#../OCR/img//暴走漫画表情包/33.jpg 74 | 收下这碗安别客气GoodNight#../OCR/img//暴走漫画表情包/10.jpg 75 | chishibani别敬屎不吃吃罚屎#../OCR/img//暴走漫画表情包/175.jpg 76 | 1撤回我就当没看#../OCR/img//暴走漫画表情包/116.jpg 77 | 张醴屹药叠_#../OCR/img//暴走漫画表情包/36.jpg 78 | 氛庸对万拒收了您的消息还翼寸您吐了口口水#../OCR/img//暴走漫画表情包/223.jpg 79 | 毒人我岂干爹包尔有盗才宇口的#../OCR/img//暴走漫画表情包/156.jpg 80 | 戳瞎你的狗眼#../OCR/img//暴走漫画表情包/159.jpg 81 | 别说了我都笑劈叉了#../OCR/img//暴走漫画表情包/26.jpg 82 | 我叫你_声SB你敢答应吗#../OCR/img//暴走漫画表情包/139.jpg 83 | 义甩过来给我装下逼不然抽死你#../OCR/img//暴走漫画表情包/24.jpg 84 | 给我口呱#../OCR/img//暴走漫画表情包/16.jpg 85 | 认识你越久我就越喜欢狗#../OCR/img//暴走漫画表情包/179.jpg 86 | 孩砸栽给你带了点泗#../OCR/img//暴走漫画表情包/57.jpg 87 | 看至穴女朋阗言决起祟仆籼冒子送穴#../OCR/img//暴走漫画表情包/31.jpg 88 | 老子忍你很久了你个傻子#../OCR/img//暴走漫画表情包/129.jpg 89 | 叹胃嘈口呐僵#../OCR/img//暴走漫画表情包/51.jpg 90 | 认识你越久我就越喜欢狗#../OCR/img//暴走漫画表情包/103.jpg 91 | 会暧床求包养#../OCR/img//暴走漫画表情包/117.jpg 92 | 你再装逼就把你上交给国家赡穹鹫#../OCR/img//暴走漫画表情包/32.jpg 93 | TMD怎么会有这样的傻逼#../OCR/img//暴走漫画表情包/138.jpg 94 | 干万另动鳙喱喜全晕水右脑全是面粉不动罢了#../OCR/img//暴走漫画表情包/207.jpg 95 | 善艮浸用倔倡漂冒#../OCR/img//暴走漫画表情包/157.jpg 96 | 对方不想和你说话并且向你扔了两条狗#../OCR/img//暴走漫画表情包/154.jpg 97 | _____鳢你瀛两头锗_因头猪已不能形罂你扮#../OCR/img//暴走漫画表情包/222.jpg 98 | 认识你越久我就越喜欢狗#../OCR/img//暴走漫画表情包/144.jpg 99 | 告叠斥你_牛好消息我看上你了#../OCR/img//暴走漫画表情包/49.jpg 100 | _喔唁#../OCR/img//暴走漫画表情包/133.jpg 101 | TMD怎么会有这样的傻逼#../OCR/img//暴走漫画表情包/100.jpg 102 | 看见个女的就激动活该你属丝一辈子#../OCR/img//暴走漫画表情包/45.jpg 103 | 都给我嗨起#../OCR/img//暴走漫画表情包/115.jpg 104 | 无所更惧荠莆#../OCR/img//暴走漫画表情包/173.jpg 105 | 窘打苋一罡丽m但氘窘打一罡很轻础#../OCR/img//暴走漫画表情包/119.jpg 106 | 吓的我郡蛋壬也上了#../OCR/img//暴走漫画表情包/3.jpg 107 | 快吃口屎冷静一下#../OCR/img//暴走漫画表情包/50.jpg 108 | 你再装逼就把你上交给国家赡穹鹫#../OCR/img//暴走漫画表情包/126.jpg 109 | 戳瞎你的狗眼#../OCR/img//暴走漫画表情包/209.jpg 110 | 你成功引起我的汪叠#../OCR/img//暴走漫画表情包/41.jpg 111 | 孩砸栽给你带了点泗#../OCR/img//暴走漫画表情包/137.jpg 112 | 善艮浸用倔倡漂冒#../OCR/img//暴走漫画表情包/206.jpg 113 | 手戈今天亨巴i舌放这了这君羊手戈最帅#../OCR/img//暴走漫画表情包/28.jpg 114 | 盗奘#../OCR/img//暴走漫画表情包/4.jpg 115 | 窘打苋一罡丽m但氘窘打一罡很轻础#../OCR/img//暴走漫画表情包/153.jpg 116 | 走马观花天天败家#../OCR/img//暴走漫画表情包/134.jpg 117 | 求分享最新把妹套蹈#../OCR/img//暴走漫画表情包/58.jpg 118 | 本宝宝可晕社会主义揍班人你什么东西敢在费面瓢蟹遭#../OCR/img//暴走漫画表情包/11.jpg 119 | 大家好我皇雷锋的表弟雷楼某#../OCR/img//暴走漫画表情包/158.jpg 120 | 你TM不服来欠我呀#../OCR/img//暴走漫画表情包/56.jpg 121 | 你开心就好#../OCR/img//暴走漫画表情包/42.jpg 122 | 我要和你们同归于尽#../OCR/img//暴走漫画表情包/177.jpg 123 | 掐指一篝你命里缺我#../OCR/img//暴走漫画表情包/170.jpg 124 | 草尼玛壳国吧今天不是你死就皇你亡#../OCR/img//暴走漫画表情包/7.jpg 125 | 为什丛不把爸爸放眼里#../OCR/img//暴走漫画表情包/198.jpg 126 | 蛳今吴甜逼没装完谁都不许睡#../OCR/img//暴走漫画表情包/132.jpg 127 | 不要这样好吗#../OCR/img//暴走漫画表情包/163.jpg 128 | 你TM不服来欠我呀#../OCR/img//暴走漫画表情包/136.jpg 129 | 我们下馆子去#../OCR/img//皮皮虾表情包/18.jpg 130 | 你皮皮虾臭了#../OCR/img//皮皮虾表情包/30.jpg 131 | 没胁髓了废皮虾肼车临删#../OCR/img//皮皮虾表情包/243.jpg 132 | _冒寡俚#../OCR/img//皮皮虾表情包/124.jpg 133 | 小黑蛇我们走#../OCR/img//皮皮虾表情包/15.jpg 134 | 我让你们再骑皮皮虾#../OCR/img//皮皮虾表情包/109.jpg 135 | 皮皮虾我1门走#../OCR/img//皮皮虾表情包/246.jpg 136 | 皮皮秃我们走#../OCR/img//皮皮虾表情包/12.jpg 137 | 皮皮虾我们走去劲爆大象部落#../OCR/img//皮皮虾表情包/174.jpg 138 | 魔腾我们走#../OCR/img//皮皮虾表情包/215.jpg 139 | 闪光皮皮虾我门走#../OCR/img//皮皮虾表情包/13.jpg 140 | 极速12珈门走#../OCR/img//皮皮虾表情包/82.jpg 141 | 愤蹴僻胁司莜刺客我侣走#../OCR/img//皮皮虾表情包/48.jpg 142 | 唧_蹦鳕胁亘了胍默W郴曹m#../OCR/img//皮皮虾表情包/233.jpg 143 | 奥瑞利安索尔9#../OCR/img//皮皮虾表情包/59.jpg 144 | 老子手撕你l的皮皮虾#../OCR/img//皮皮虾表情包/25.jpg 145 | 水熊虫我们走#../OCR/img//皮皮虾表情包/8.jpg 146 | 我让你们再骑皮皮虾#../OCR/img//皮皮虾表情包/187.jpg 147 | 巴西龟我们惶走#../OCR/img//皮皮虾表情包/71.jpg 148 | 皮皮虾我们走#../OCR/img//皮皮虾表情包/195.jpg 149 | 们下馆子皮皮虾所不铲匕承受之重#../OCR/img//皮皮虾表情包/219.jpg 150 | 皮皮虾你自己走吧#../OCR/img//皮皮虾表情包/17.jpg 151 | 小姐姐我们走#../OCR/img//皮皮虾表情包/169.jpg 152 | 皮_堇酮F俪乍罡起i茎么#../OCR/img//皮皮虾表情包/210.jpg 153 | 皮皮虾我们回来#../OCR/img//皮皮虾表情包/22.jpg 154 | 妈朐走错方闾了#../OCR/img//皮皮虾表情包/20.jpg 155 | 胁象拔蚌我们走#../OCR/img//皮皮虾表情包/29.jpg 156 | 皮皮虾我n走#../OCR/img//皮皮虾表情包/162.jpg 157 | 鳢驰_yL_广你门再骑劳资试试看#../OCR/img//皮皮虾表情包/113.jpg 158 | 醌戎摊_L胁#../OCR/img//皮皮虾表情包/244.jpg 159 | 不走了扎屁股#../OCR/img//皮皮虾表情包/107.jpg 160 | 炸鸡腿我们走#../OCR/img//皮皮虾表情包/112.jpg 161 | 可把我自己给牛逗坏了叉会L腰#../OCR/img//皮皮虾表情包/93.jpg 162 | 皮皮虾我5f薯逞靼鬓#../OCR/img//皮皮虾表情包/217.jpg 163 | 熹恶势力我门走#../OCR/img//皮皮虾表情包/95.jpg 164 | 维克兹我们走#../OCR/img//皮皮虾表情包/66.jpg 165 | 已a皮皮狗我们走#../OCR/img//皮皮虾表情包/21.jpg 166 | 醌戎摊_L胁#../OCR/img//皮皮虾表情包/204.jpg 167 | GWW我1门走#../OCR/img//皮皮虾表情包/226.jpg 168 | 皮皮虾上吊了#../OCR/img//皮皮虾表情包/10.jpg 169 | 修仙万岁#../OCR/img//皮皮虾表情包/116.jpg 170 | 没胁髓了废皮虾肼车临删#../OCR/img//皮皮虾表情包/164.jpg 171 | 遮艾w裂魂人哉们走#../OCR/img//皮皮虾表情包/36.jpg 172 | 胁胁#../OCR/img//皮皮虾表情包/223.jpg 173 | 皮皮虾快隐身#../OCR/img//皮皮虾表情包/35.jpg 174 | 皮皮虾今天不想走了#../OCR/img//皮皮虾表情包/37.jpg 175 | 髓_n蠢更摹了潮刚扈菱如邋麸胁唇癫暴I酬庸脚漕氰襄们懂我剐#../OCR/img//皮皮虾表情包/102.jpg 176 | 遮艾w裂魂人哉们走#../OCR/img//皮皮虾表情包/76.jpg 177 | 维克兹我们走#../OCR/img//皮皮虾表情包/26.jpg 178 | 胁先别走开会#../OCR/img//皮皮虾表情包/5.jpg 179 | 已a皮皮狗我们走#../OCR/img//皮皮虾表情包/61.jpg 180 | 皮皮虾被胖胖的你压死了#../OCR/img//皮皮虾表情包/81.jpg 181 | 豁薯m#../OCR/img//皮皮虾表情包/229.jpg 182 | 皮皮虾我n走#../OCR/img//皮皮虾表情包/241.jpg 183 | 闪光皮皮虾我门走#../OCR/img//皮皮虾表情包/34.jpg 184 | 鳢驰_yL_广你门再骑劳资试试看#../OCR/img//皮皮虾表情包/152.jpg 185 | 皮皮虾你快回来#../OCR/img//皮皮虾表情包/24.jpg 186 | 极速12珈门走#../OCR/img//皮皮虾表情包/121.jpg 187 | 皮_堇酮F俪乍罡起i茎么#../OCR/img//皮皮虾表情包/171.jpg 188 | 皮皮虾今天要打死你#../OCR/img//皮皮虾表情包/188.jpg 189 | 沸皮皮虾我们出警#../OCR/img//皮皮虾表情包/16.jpg 190 | 皮皮虾我们回去#../OCR/img//皮皮虾表情包/179.jpg 191 | 连水都不给皮皮虾你们的良心不会痛吗#../OCR/img//皮皮虾表情包/80.jpg 192 | 红包们我们走#../OCR/img//皮皮虾表情包/234.jpg 193 | 厝薯蝇圃稷皮皮虾披胖胖的你蜇f鳙凑压死了墨删删量曦蝴盲多远陟近邋让你们胃骑皮皮虾晁浑P像们蓟皮皮虾已经薏氯炒了厂二夏墓妻子妻矗螂胸虞虞疃#../OCR/img//皮皮虾表情包/238.jpg 194 | 巴西龟我们惶走#../OCR/img//皮皮虾表情包/31.jpg 195 | 带上你的皮皮虾快滚#../OCR/img//皮皮虾表情包/96.jpg 196 | 僚翼庸上翼虞趸比不过虞胁#../OCR/img//皮皮虾表情包/51.jpg 197 | 皮皮虾我们走#../OCR/img//皮皮虾表情包/9.jpg 198 | 皮皮虾我们走#../OCR/img//皮皮虾表情包/117.jpg 199 | 皮皮虾被胖胖的你压死了#../OCR/img//皮皮虾表情包/106.jpg 200 | 醌戎摊_L胁#../OCR/img//皮皮虾表情包/165.jpg 201 | 皮皮虾今天要打死你#../OCR/img//皮皮虾表情包/110.jpg 202 | 莫主安拉我们走悬鹭#../OCR/img//皮皮虾表情包/32.jpg 203 | 闪光皮皮虾我门走#../OCR/img//皮皮虾表情包/74.jpg 204 | 奥瑞利安索尔9#../OCR/img//皮皮虾表情包/138.jpg 205 | 不走了扎屁股#../OCR/img//皮皮虾表情包/185.jpg 206 | 僚翼庸上翼虞趸比不过虞胁#../OCR/img//皮皮虾表情包/91.jpg 207 | 皮皮虾军团我走趴阁才#../OCR/img//皮皮虾表情包/183.jpg 208 | 熹恶势力我门走#../OCR/img//皮皮虾表情包/55.jpg 209 | 包包我们走#../OCR/img//皮皮虾表情包/222.jpg 210 | 皮皮虾我n走#../OCR/img//皮皮虾表情包/201.jpg 211 | 走你妹峒不知道老子今天限号峒#../OCR/img//皮皮虾表情包/49.jpg 212 | 胁象拔蚌我们走#../OCR/img//皮皮虾表情包/69.jpg 213 | _冒寡俚#../OCR/img//皮皮虾表情包/85.jpg 214 | 皮皮虾我1门走#../OCR/img//皮皮虾表情包/167.jpg 215 | 英雄联盟我们走#../OCR/img//皮皮虾表情包/225.jpg 216 | 皮皮虾快隐身#../OCR/img//皮皮虾表情包/75.jpg 217 | 奥瑞利安索尔9#../OCR/img//皮皮虾表情包/99.jpg 218 | _冒寡俚#../OCR/img//皮皮虾表情包/45.jpg 219 | 刺锅额我们走#../OCR/img//皮皮虾表情包/2.jpg 220 | 愤蹴僻胁司莜刺客我侣走#../OCR/img//皮皮虾表情包/88.jpg 221 | 你他妈走够了没有#../OCR/img//皮皮虾表情包/14.jpg 222 | 皮皮虾军团我走趴阁才#../OCR/img//皮皮虾表情包/105.jpg 223 | 皮皮虾今天不想走了#../OCR/img//皮皮虾表情包/77.jpg 224 | 庄花我们走#../OCR/img//皮皮虾表情包/220.jpg 225 | 走你妹峒不知道老子今天限号峒#../OCR/img//皮皮虾表情包/89.jpg 226 | 皮皮虾被胖胖的你压死了#../OCR/img//皮皮虾表情包/120.jpg 227 | 少年这是你的皮皮虾吗#../OCR/img//皮皮虾表情包/123.jpg 228 | 连水都不给皮皮虾你们的良心不会痛吗#../OCR/img//皮皮虾表情包/119.jpg 229 | 金皮皮还是银皮皮#../OCR/img//皮皮虾表情包/3.jpg 230 | 皮皮虾你快回来#../OCR/img//皮皮虾表情包/64.jpg 231 | 连水都不给皮皮虾你们的良心不会痛吗#../OCR/img//皮皮虾表情包/40.jpg 232 | 土建学院板砖我们走#../OCR/img//皮皮虾表情包/221.jpg 233 | 魔腾我们走#../OCR/img//皮皮虾表情包/176.jpg 234 | 皮皮虾被胖胖的你压死了#../OCR/img//皮皮虾表情包/41.jpg 235 | 少年这是你的皮皮虾吗#../OCR/img//皮皮虾表情包/44.jpg 236 | 少年这是你的皮皮虾吗#../OCR/img//皮皮虾表情包/84.jpg 237 | 原明雅我们走#../OCR/img//皮皮虾表情包/218.jpg 238 | 皮皮虾我1门走#../OCR/img//皮皮虾表情包/206.jpg 239 | 庸趟晶u皮皮虾你快回来#../OCR/img//皮皮虾表情包/98.jpg 240 | 修仙万岁#../OCR/img//皮皮虾表情包/194.jpg 241 | 庸趟晶u皮皮虾你快回来#../OCR/img//皮皮虾表情包/58.jpg 242 | 皮皮虾我们回去#../OCR/img//皮皮虾表情包/101.jpg 243 | 鹰啦1o甜门打球去#../OCR/img//皮皮虾表情包/230.jpg 244 | 银斧鱼我们走#../OCR/img//皮皮虾表情包/11.jpg 245 | 皮皮虾被胖胖的你压死了#../OCR/img//皮皮虾表情包/184.jpg 246 | 带上你的皮皮虾快滚#../OCR/img//皮皮虾表情包/56.jpg 247 | 没胁髓了废皮虾肼车临删#../OCR/img//皮皮虾表情包/203.jpg 248 | 皮_堇酮F俪乍罡起i茎么#../OCR/img//皮皮虾表情包/250.jpg 249 | 鳢驰_yL_广你门再骑劳资试试看#../OCR/img//皮皮虾表情包/191.jpg 250 | 皮皮虾我丨门走#../OCR/img//皮皮虾表情包/0.jpg 251 | 可把我自己给牛逗坏了叉会L腰#../OCR/img//皮皮虾表情包/53.jpg 252 | 极速12珈门走#../OCR/img//皮皮虾表情包/42.jpg 253 | 岫象拨蚌我们继续走#../OCR/img//皮皮虾表情包/7.jpg 254 | 厝薯蝇圃稷皮皮虾披胖胖的你蜇f鳙凑压死了墨删删量曦蝴盲多远陟近邋让你们胃骑皮皮虾晁浑P像们蓟皮皮虾已经薏氯炒了厂二夏墓妻子妻矗螂胸虞虞疃#../OCR/img//皮皮虾表情包/198.jpg 255 | 你皮皮虾臭了#../OCR/img//皮皮虾表情包/70.jpg 256 | 炸鸡腿我们走#../OCR/img//皮皮虾表情包/190.jpg 257 | 皮皮虾栽们走不和这个智漳说话#../OCR/img//皮皮虾表情包/1.jpg 258 | 老子手撕你l的皮皮虾#../OCR/img//皮皮虾表情包/65.jpg 259 | 腥红皮皮虾我1门走#../OCR/img//皮皮虾表情包/227.jpg 260 | 妈朐走错方闾了#../OCR/img//皮皮虾表情包/60.jpg 261 | 皮皮虾我们回来#../OCR/img//皮皮虾表情包/62.jpg 262 | 莫主安拉我们走悬鹭#../OCR/img//皮皮虾表情包/72.jpg 263 | -------------------------------------------------------------------------------- /modules/OCR/checked.info: -------------------------------------------------------------------------------- 1 | ../OCR/img//个性表情包/18.jpg 2 | ../OCR/img//个性表情包/54.jpg 3 | ../OCR/img//个性表情包/15.jpg 4 | ../OCR/img//个性表情包/12.jpg 5 | ../OCR/img//个性表情包/13.jpg 6 | ../OCR/img//个性表情包/141.jpg 7 | ../OCR/img//个性表情包/48.jpg 8 | ../OCR/img//个性表情包/46.jpg 9 | ../OCR/img//个性表情包/181.jpg 10 | ../OCR/img//个性表情包/43.jpg 11 | ../OCR/img//个性表情包/23.jpg 12 | ../OCR/img//个性表情包/199.jpg 13 | ../OCR/img//个性表情包/25.jpg 14 | ../OCR/img//个性表情包/8.jpg 15 | ../OCR/img//个性表情包/52.jpg 16 | ../OCR/img//个性表情包/17.jpg 17 | ../OCR/img//个性表情包/22.jpg 18 | ../OCR/img//个性表情包/162.jpg 19 | ../OCR/img//个性表情包/73.jpg 20 | ../OCR/img//个性表情包/47.jpg 21 | ../OCR/img//个性表情包/27.jpg 22 | ../OCR/img//个性表情包/33.jpg 23 | ../OCR/img//个性表情包/21.jpg 24 | ../OCR/img//个性表情包/36.jpg 25 | ../OCR/img//个性表情包/76.jpg 26 | ../OCR/img//个性表情包/61.jpg 27 | ../OCR/img//个性表情包/81.jpg 28 | ../OCR/img//个性表情包/121.jpg 29 | ../OCR/img//个性表情包/171.jpg 30 | ../OCR/img//个性表情包/16.jpg 31 | ../OCR/img//个性表情包/57.jpg 32 | ../OCR/img//个性表情包/80.jpg 33 | ../OCR/img//个性表情包/104.jpg 34 | ../OCR/img//个性表情包/68.jpg 35 | ../OCR/img//个性表情包/51.jpg 36 | ../OCR/img//个性表情包/103.jpg 37 | ../OCR/img//个性表情包/110.jpg 38 | ../OCR/img//个性表情包/32.jpg 39 | ../OCR/img//个性表情包/63.jpg 40 | ../OCR/img//个性表情包/144.jpg 41 | ../OCR/img//个性表情包/67.jpg 42 | ../OCR/img//个性表情包/45.jpg 43 | ../OCR/img//个性表情包/77.jpg 44 | ../OCR/img//个性表情包/120.jpg 45 | ../OCR/img//个性表情包/19.jpg 46 | ../OCR/img//个性表情包/3.jpg 47 | ../OCR/img//个性表情包/41.jpg 48 | ../OCR/img//个性表情包/79.jpg 49 | ../OCR/img//个性表情包/28.jpg 50 | ../OCR/img//个性表情包/58.jpg 51 | ../OCR/img//个性表情包/101.jpg 52 | ../OCR/img//个性表情包/42.jpg 53 | ../OCR/img//个性表情包/1.jpg 54 | ../OCR/img//个性表情包/65.jpg 55 | ../OCR/img//个性表情包/62.jpg 56 | ../OCR/img//个性表情包/163.jpg 57 | ../OCR/img//个性表情包/72.jpg 58 | ../OCR/img//暴走漫画表情包/18.jpg 59 | ../OCR/img//暴走漫画表情包/30.jpg 60 | ../OCR/img//暴走漫画表情包/54.jpg 61 | ../OCR/img//暴走漫画表情包/15.jpg 62 | ../OCR/img//暴走漫画表情包/214.jpg 63 | ../OCR/img//暴走漫画表情包/109.jpg 64 | ../OCR/img//暴走漫画表情包/12.jpg 65 | ../OCR/img//暴走漫画表情包/13.jpg 66 | ../OCR/img//暴走漫画表情包/43.jpg 67 | ../OCR/img//暴走漫画表情包/23.jpg 68 | ../OCR/img//暴走漫画表情包/59.jpg 69 | ../OCR/img//暴走漫画表情包/25.jpg 70 | ../OCR/img//暴走漫画表情包/8.jpg 71 | ../OCR/img//暴走漫画表情包/52.jpg 72 | ../OCR/img//暴走漫画表情包/219.jpg 73 | ../OCR/img//暴走漫画表情包/169.jpg 74 | ../OCR/img//暴走漫画表情包/210.jpg 75 | ../OCR/img//暴走漫画表情包/22.jpg 76 | ../OCR/img//暴走漫画表情包/118.jpg 77 | ../OCR/img//暴走漫画表情包/125.jpg 78 | ../OCR/img//暴走漫画表情包/20.jpg 79 | ../OCR/img//暴走漫画表情包/29.jpg 80 | ../OCR/img//暴走漫画表情包/113.jpg 81 | ../OCR/img//暴走漫画表情包/107.jpg 82 | ../OCR/img//暴走漫画表情包/168.jpg 83 | ../OCR/img//暴走漫画表情包/112.jpg 84 | ../OCR/img//暴走漫画表情包/224.jpg 85 | ../OCR/img//暴走漫画表情包/47.jpg 86 | ../OCR/img//暴走漫画表情包/27.jpg 87 | ../OCR/img//暴走漫画表情包/130.jpg 88 | ../OCR/img//暴走漫画表情包/38.jpg 89 | ../OCR/img//暴走漫画表情包/178.jpg 90 | ../OCR/img//暴走漫画表情包/33.jpg 91 | ../OCR/img//暴走漫画表情包/21.jpg 92 | ../OCR/img//暴走漫画表情包/204.jpg 93 | ../OCR/img//暴走漫画表情包/10.jpg 94 | ../OCR/img//暴走漫画表情包/175.jpg 95 | ../OCR/img//暴走漫画表情包/116.jpg 96 | ../OCR/img//暴走漫画表情包/36.jpg 97 | ../OCR/img//暴走漫画表情包/223.jpg 98 | ../OCR/img//暴走漫画表情包/156.jpg 99 | ../OCR/img//暴走漫画表情包/159.jpg 100 | ../OCR/img//暴走漫画表情包/26.jpg 101 | ../OCR/img//暴走漫画表情包/139.jpg 102 | ../OCR/img//暴走漫画表情包/34.jpg 103 | ../OCR/img//暴走漫画表情包/24.jpg 104 | ../OCR/img//暴走漫画表情包/16.jpg 105 | ../OCR/img//暴走漫画表情包/179.jpg 106 | ../OCR/img//暴走漫画表情包/57.jpg 107 | ../OCR/img//暴走漫画表情包/31.jpg 108 | ../OCR/img//暴走漫画表情包/129.jpg 109 | ../OCR/img//暴走漫画表情包/51.jpg 110 | ../OCR/img//暴走漫画表情包/103.jpg 111 | ../OCR/img//暴走漫画表情包/117.jpg 112 | ../OCR/img//暴走漫画表情包/106.jpg 113 | ../OCR/img//暴走漫画表情包/32.jpg 114 | ../OCR/img//暴走漫画表情包/138.jpg 115 | ../OCR/img//暴走漫画表情包/207.jpg 116 | ../OCR/img//暴走漫画表情包/157.jpg 117 | ../OCR/img//暴走漫画表情包/154.jpg 118 | ../OCR/img//暴走漫画表情包/111.jpg 119 | ../OCR/img//暴走漫画表情包/222.jpg 120 | ../OCR/img//暴走漫画表情包/144.jpg 121 | ../OCR/img//暴走漫画表情包/49.jpg 122 | ../OCR/img//暴走漫画表情包/133.jpg 123 | ../OCR/img//暴走漫画表情包/100.jpg 124 | ../OCR/img//暴走漫画表情包/45.jpg 125 | ../OCR/img//暴走漫画表情包/2.jpg 126 | ../OCR/img//暴走漫画表情包/115.jpg 127 | ../OCR/img//暴走漫画表情包/173.jpg 128 | ../OCR/img//暴走漫画表情包/120.jpg 129 | ../OCR/img//暴走漫画表情包/119.jpg 130 | ../OCR/img//暴走漫画表情包/3.jpg 131 | ../OCR/img//暴走漫画表情包/50.jpg 132 | ../OCR/img//暴走漫画表情包/126.jpg 133 | ../OCR/img//暴走漫画表情包/209.jpg 134 | ../OCR/img//暴走漫画表情包/41.jpg 135 | ../OCR/img//暴走漫画表情包/114.jpg 136 | ../OCR/img//暴走漫画表情包/137.jpg 137 | ../OCR/img//暴走漫画表情包/206.jpg 138 | ../OCR/img//暴走漫画表情包/28.jpg 139 | ../OCR/img//暴走漫画表情包/4.jpg 140 | ../OCR/img//暴走漫画表情包/153.jpg 141 | ../OCR/img//暴走漫画表情包/134.jpg 142 | ../OCR/img//暴走漫画表情包/6.jpg 143 | ../OCR/img//暴走漫画表情包/58.jpg 144 | ../OCR/img//暴走漫画表情包/11.jpg 145 | ../OCR/img//暴走漫画表情包/158.jpg 146 | ../OCR/img//暴走漫画表情包/56.jpg 147 | ../OCR/img//暴走漫画表情包/203.jpg 148 | ../OCR/img//暴走漫画表情包/42.jpg 149 | ../OCR/img//暴走漫画表情包/177.jpg 150 | ../OCR/img//暴走漫画表情包/170.jpg 151 | ../OCR/img//暴走漫画表情包/7.jpg 152 | ../OCR/img//暴走漫画表情包/198.jpg 153 | ../OCR/img//暴走漫画表情包/1.jpg 154 | ../OCR/img//暴走漫画表情包/132.jpg 155 | ../OCR/img//暴走漫画表情包/163.jpg 156 | ../OCR/img//暴走漫画表情包/136.jpg 157 | ../OCR/img//皮皮虾表情包/18.jpg 158 | ../OCR/img//皮皮虾表情包/30.jpg 159 | ../OCR/img//皮皮虾表情包/243.jpg 160 | ../OCR/img//皮皮虾表情包/54.jpg 161 | ../OCR/img//皮皮虾表情包/124.jpg 162 | ../OCR/img//皮皮虾表情包/15.jpg 163 | ../OCR/img//皮皮虾表情包/109.jpg 164 | ../OCR/img//皮皮虾表情包/192.jpg 165 | ../OCR/img//皮皮虾表情包/246.jpg 166 | ../OCR/img//皮皮虾表情包/12.jpg 167 | ../OCR/img//皮皮虾表情包/174.jpg 168 | ../OCR/img//皮皮虾表情包/196.jpg 169 | ../OCR/img//皮皮虾表情包/39.jpg 170 | ../OCR/img//皮皮虾表情包/215.jpg 171 | ../OCR/img//皮皮虾表情包/13.jpg 172 | ../OCR/img//皮皮虾表情包/82.jpg 173 | ../OCR/img//皮皮虾表情包/48.jpg 174 | ../OCR/img//皮皮虾表情包/233.jpg 175 | ../OCR/img//皮皮虾表情包/46.jpg 176 | ../OCR/img//皮皮虾表情包/94.jpg 177 | ../OCR/img//皮皮虾表情包/23.jpg 178 | ../OCR/img//皮皮虾表情包/199.jpg 179 | ../OCR/img//皮皮虾表情包/59.jpg 180 | ../OCR/img//皮皮虾表情包/228.jpg 181 | ../OCR/img//皮皮虾表情包/25.jpg 182 | ../OCR/img//皮皮虾表情包/8.jpg 183 | ../OCR/img//皮皮虾表情包/187.jpg 184 | ../OCR/img//皮皮虾表情包/71.jpg 185 | ../OCR/img//皮皮虾表情包/195.jpg 186 | ../OCR/img//皮皮虾表情包/219.jpg 187 | ../OCR/img//皮皮虾表情包/17.jpg 188 | ../OCR/img//皮皮虾表情包/169.jpg 189 | ../OCR/img//皮皮虾表情包/210.jpg 190 | ../OCR/img//皮皮虾表情包/216.jpg 191 | ../OCR/img//皮皮虾表情包/22.jpg 192 | ../OCR/img//皮皮虾表情包/118.jpg 193 | ../OCR/img//皮皮虾表情包/20.jpg 194 | ../OCR/img//皮皮虾表情包/29.jpg 195 | ../OCR/img//皮皮虾表情包/162.jpg 196 | ../OCR/img//皮皮虾表情包/113.jpg 197 | ../OCR/img//皮皮虾表情包/73.jpg 198 | ../OCR/img//皮皮虾表情包/244.jpg 199 | ../OCR/img//皮皮虾表情包/107.jpg 200 | ../OCR/img//皮皮虾表情包/112.jpg 201 | ../OCR/img//皮皮虾表情包/93.jpg 202 | ../OCR/img//皮皮虾表情包/217.jpg 203 | ../OCR/img//皮皮虾表情包/237.jpg 204 | ../OCR/img//皮皮虾表情包/95.jpg 205 | ../OCR/img//皮皮虾表情包/27.jpg 206 | ../OCR/img//皮皮虾表情包/66.jpg 207 | ../OCR/img//皮皮虾表情包/38.jpg 208 | ../OCR/img//皮皮虾表情包/33.jpg 209 | ../OCR/img//皮皮虾表情包/21.jpg 210 | ../OCR/img//皮皮虾表情包/204.jpg 211 | ../OCR/img//皮皮虾表情包/226.jpg 212 | ../OCR/img//皮皮虾表情包/10.jpg 213 | ../OCR/img//皮皮虾表情包/116.jpg 214 | ../OCR/img//皮皮虾表情包/164.jpg 215 | ../OCR/img//皮皮虾表情包/36.jpg 216 | ../OCR/img//皮皮虾表情包/223.jpg 217 | ../OCR/img//皮皮虾表情包/35.jpg 218 | ../OCR/img//皮皮虾表情包/37.jpg 219 | ../OCR/img//皮皮虾表情包/102.jpg 220 | ../OCR/img//皮皮虾表情包/76.jpg 221 | ../OCR/img//皮皮虾表情包/26.jpg 222 | ../OCR/img//皮皮虾表情包/5.jpg 223 | ../OCR/img//皮皮虾表情包/166.jpg 224 | ../OCR/img//皮皮虾表情包/61.jpg 225 | ../OCR/img//皮皮虾表情包/81.jpg 226 | ../OCR/img//皮皮虾表情包/229.jpg 227 | ../OCR/img//皮皮虾表情包/241.jpg 228 | ../OCR/img//皮皮虾表情包/34.jpg 229 | ../OCR/img//皮皮虾表情包/189.jpg 230 | ../OCR/img//皮皮虾表情包/152.jpg 231 | ../OCR/img//皮皮虾表情包/24.jpg 232 | ../OCR/img//皮皮虾表情包/121.jpg 233 | ../OCR/img//皮皮虾表情包/171.jpg 234 | ../OCR/img//皮皮虾表情包/188.jpg 235 | ../OCR/img//皮皮虾表情包/16.jpg 236 | ../OCR/img//皮皮虾表情包/179.jpg 237 | ../OCR/img//皮皮虾表情包/80.jpg 238 | ../OCR/img//皮皮虾表情包/234.jpg 239 | ../OCR/img//皮皮虾表情包/238.jpg 240 | ../OCR/img//皮皮虾表情包/31.jpg 241 | ../OCR/img//皮皮虾表情包/96.jpg 242 | ../OCR/img//皮皮虾表情包/51.jpg 243 | ../OCR/img//皮皮虾表情包/9.jpg 244 | ../OCR/img//皮皮虾表情包/117.jpg 245 | ../OCR/img//皮皮虾表情包/106.jpg 246 | ../OCR/img//皮皮虾表情包/165.jpg 247 | ../OCR/img//皮皮虾表情包/110.jpg 248 | ../OCR/img//皮皮虾表情包/32.jpg 249 | ../OCR/img//皮皮虾表情包/74.jpg 250 | ../OCR/img//皮皮虾表情包/138.jpg 251 | ../OCR/img//皮皮虾表情包/185.jpg 252 | ../OCR/img//皮皮虾表情包/63.jpg 253 | ../OCR/img//皮皮虾表情包/91.jpg 254 | ../OCR/img//皮皮虾表情包/197.jpg 255 | ../OCR/img//皮皮虾表情包/183.jpg 256 | ../OCR/img//皮皮虾表情包/55.jpg 257 | ../OCR/img//皮皮虾表情包/111.jpg 258 | ../OCR/img//皮皮虾表情包/222.jpg 259 | ../OCR/img//皮皮虾表情包/201.jpg 260 | ../OCR/img//皮皮虾表情包/49.jpg 261 | ../OCR/img//皮皮虾表情包/67.jpg 262 | ../OCR/img//皮皮虾表情包/69.jpg 263 | ../OCR/img//皮皮虾表情包/85.jpg 264 | ../OCR/img//皮皮虾表情包/167.jpg 265 | ../OCR/img//皮皮虾表情包/225.jpg 266 | ../OCR/img//皮皮虾表情包/75.jpg 267 | ../OCR/img//皮皮虾表情包/99.jpg 268 | ../OCR/img//皮皮虾表情包/78.jpg 269 | ../OCR/img//皮皮虾表情包/45.jpg 270 | ../OCR/img//皮皮虾表情包/2.jpg 271 | ../OCR/img//皮皮虾表情包/88.jpg 272 | ../OCR/img//皮皮虾表情包/14.jpg 273 | ../OCR/img//皮皮虾表情包/105.jpg 274 | ../OCR/img//皮皮虾表情包/115.jpg 275 | ../OCR/img//皮皮虾表情包/77.jpg 276 | ../OCR/img//皮皮虾表情包/220.jpg 277 | ../OCR/img//皮皮虾表情包/89.jpg 278 | ../OCR/img//皮皮虾表情包/193.jpg 279 | ../OCR/img//皮皮虾表情包/120.jpg 280 | ../OCR/img//皮皮虾表情包/19.jpg 281 | ../OCR/img//皮皮虾表情包/123.jpg 282 | ../OCR/img//皮皮虾表情包/119.jpg 283 | ../OCR/img//皮皮虾表情包/3.jpg 284 | ../OCR/img//皮皮虾表情包/64.jpg 285 | ../OCR/img//皮皮虾表情包/40.jpg 286 | ../OCR/img//皮皮虾表情包/202.jpg 287 | ../OCR/img//皮皮虾表情包/50.jpg 288 | ../OCR/img//皮皮虾表情包/221.jpg 289 | ../OCR/img//皮皮虾表情包/176.jpg 290 | ../OCR/img//皮皮虾表情包/41.jpg 291 | ../OCR/img//皮皮虾表情包/114.jpg 292 | ../OCR/img//皮皮虾表情包/44.jpg 293 | ../OCR/img//皮皮虾表情包/84.jpg 294 | ../OCR/img//皮皮虾表情包/218.jpg 295 | ../OCR/img//皮皮虾表情包/206.jpg 296 | ../OCR/img//皮皮虾表情包/242.jpg 297 | ../OCR/img//皮皮虾表情包/98.jpg 298 | ../OCR/img//皮皮虾表情包/79.jpg 299 | ../OCR/img//皮皮虾表情包/86.jpg 300 | ../OCR/img//皮皮虾表情包/194.jpg 301 | ../OCR/img//皮皮虾表情包/58.jpg 302 | ../OCR/img//皮皮虾表情包/101.jpg 303 | ../OCR/img//皮皮虾表情包/230.jpg 304 | ../OCR/img//皮皮虾表情包/11.jpg 305 | ../OCR/img//皮皮虾表情包/184.jpg 306 | ../OCR/img//皮皮虾表情包/56.jpg 307 | ../OCR/img//皮皮虾表情包/203.jpg 308 | ../OCR/img//皮皮虾表情包/250.jpg 309 | ../OCR/img//皮皮虾表情包/191.jpg 310 | ../OCR/img//皮皮虾表情包/0.jpg 311 | ../OCR/img//皮皮虾表情包/53.jpg 312 | ../OCR/img//皮皮虾表情包/42.jpg 313 | ../OCR/img//皮皮虾表情包/7.jpg 314 | ../OCR/img//皮皮虾表情包/198.jpg 315 | ../OCR/img//皮皮虾表情包/70.jpg 316 | ../OCR/img//皮皮虾表情包/190.jpg 317 | ../OCR/img//皮皮虾表情包/1.jpg 318 | ../OCR/img//皮皮虾表情包/65.jpg 319 | ../OCR/img//皮皮虾表情包/227.jpg 320 | ../OCR/img//皮皮虾表情包/60.jpg 321 | ../OCR/img//皮皮虾表情包/239.jpg 322 | ../OCR/img//皮皮虾表情包/62.jpg 323 | ../OCR/img//皮皮虾表情包/163.jpg 324 | ../OCR/img//皮皮虾表情包/90.jpg 325 | ../OCR/img//皮皮虾表情包/72.jpg 326 | -------------------------------------------------------------------------------- /modules/OCR/substitude.dat: -------------------------------------------------------------------------------- 1 | }q(X_qX一qX女马qX妈qu. -------------------------------------------------------------------------------- /modules/OCR/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # @Date : 2017-05-30 22:20:08 4 | # @Author : Your Name (you@example.org) 5 | # @Link : http://example.org 6 | # @Version : $Id$ 7 | 8 | import os 9 | import pickle 10 | import re 11 | 12 | if __name__ == '__main__': 13 | source = '宫颈癌;旅顺口打飞_女马' 14 | test_dict = {} 15 | test_dict['_'] = '一' 16 | test_dict['女马'] = '妈' 17 | with open('substitude.dat' , 'wb') as fp: 18 | pickle.dump(test_dict, fp, 1) 19 | with open('substitude.dat', 'rb') as fp: 20 | rec = pickle.load(fp) 21 | keys = rec.keys() 22 | for key in keys: 23 | if key in source: 24 | print(re.subn(key, rec[key], source)) 25 | print(rec) 26 | 27 | -------------------------------------------------------------------------------- /modules/QQqt4/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/.gitkeep -------------------------------------------------------------------------------- /modules/QQqt4/Image2txt.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/Image2txt.log -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/bestexplist.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/bestexplist.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/bestexplist.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/bestexplist.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/exprobot.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/exprobot.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/exprobot.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/exprobot.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/exptable.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/exptable.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/exptable.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/exptable.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/flowlayout.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/flowlayout.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/flowlayout.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/flowlayout.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/groupUserList.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/groupUserList.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/maxSim.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/maxSim.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/msgList.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/msgList.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/mycopygroupuserlist.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/mycopygroupuserlist.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/mycopygroupuserlist.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/mycopygroupuserlist.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/mycopymsglist.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/mycopymsglist.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/mycopymsglist.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/mycopymsglist.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/pyqtChatApp.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/pyqtChatApp.cpython-35.pyc -------------------------------------------------------------------------------- /modules/QQqt4/__pycache__/pyqtChatApp.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/__pycache__/pyqtChatApp.cpython-36.pyc -------------------------------------------------------------------------------- /modules/QQqt4/bestexplist.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | from PyQt4.QtGui import * 3 | from PyQt4.QtCore import * 4 | 5 | 6 | class BestWindow(QWidget): 7 | 8 | def __init__(self, listView, bestexplist, path=os.getcwd()): 9 | 10 | super(BestWindow, self).__init__() 11 | self.listView = listView 12 | self.resize(680, 110) 13 | self.setWindowFlags(Qt.FramelessWindowHint) 14 | self.setAttribute(Qt.WA_TranslucentBackground) 15 | self.setStyleSheet("QScrollBar{width:0;height:0}") 16 | lo = QGridLayout() 17 | self.table = MyTable(self.listView, self, bestexplist, path) 18 | self.table.move(10,15) 19 | lo.addWidget(self.table) 20 | self.setLayout(lo) 21 | self.move(listView.x()+240, listView.y()+530) 22 | self.setStyleSheet("QTableWidget{background: #74C5FA;border:2px groove gray;border-radius:10px;padding:2px 4px;}" 23 | "QLabel{background: white;color: blue;border-width: 2px; border-style: solid;border-color: #74C5FA;border-radius:2px}") 24 | 25 | 26 | class MyLabel(QLabel): 27 | def __init__(self, img, mytable, window, listView): 28 | super(MyLabel, self).__init__() 29 | self.listView = listView 30 | self.mytable = mytable 31 | self.window = window 32 | self.img = img 33 | self.expwid = 110 34 | pixmap = QPixmap(img) 35 | pixmap = pixmap.scaledToWidth(self.expwid) 36 | self.setPixmap(pixmap) 37 | 38 | 39 | def contextMenuEvent(self,event): 40 | delExp = QAction(QIcon('icons/delete.png'),u'删除',self) 41 | delExp.triggered.connect(self.delExpItem)#选中就会触发 42 | 43 | menu = QMenu() 44 | menu.addAction(delExp) 45 | menu.exec_(QCursor.pos())#全局位置比较好,使用e.pos()还得转换 46 | 47 | event.accept() #禁止弹出菜单事件传递到父控件中 48 | 49 | def delExpItem(self,b): 50 | os.remove(self.img) 51 | self.window.close() 52 | self.listView.expcalling = False 53 | 54 | 55 | class MyTable(QTableWidget): 56 | 57 | def __init__(self, listView, window, bestexplist, path = os.getcwd()): 58 | super(MyTable, self).__init__() 59 | self.columncount = 6 60 | self.labels = [] 61 | self.path = path 62 | self.window = window 63 | self.listView = listView 64 | self.piclist = bestexplist 65 | self.setFixedSize(670, 120) 66 | self.setFrameShape(QFrame.NoFrame) 67 | self.setShowGrid(False) 68 | self.fillTable(path) 69 | self.setWindowFlags(Qt.FramelessWindowHint) 70 | self.setStyleSheet("QScrollBar{width:0;height:0}") 71 | 72 | def fillTable(self, path): 73 | self.rowcount = 1 74 | self.setEditTriggers(QAbstractItemView.NoEditTriggers) 75 | self.setSelectionMode(QAbstractItemView.SingleSelection) 76 | self.verticalHeader().setVisible(False) 77 | self.horizontalHeader().setVisible(False) 78 | self.setRowCount(self.rowcount) 79 | self.setColumnCount(self.columncount) 80 | self.setShowGrid(False) # hide the edge 81 | 82 | count = 0 83 | self.imglist = [] 84 | for picture in self.piclist: 85 | # img = picture 86 | self.imglist.append(picture) 87 | # self.labels.append(MyLabel(img, self, self.window, self.listView)) 88 | self.setCellWidget(count//self.columncount, count%self.columncount,\ 89 | MyLabel(self.imglist[count], self, self.window, self.listView)) #self.labels[count]) 90 | count += 1 91 | self.resizeColumnsToContents() #将列调整到跟内容大小相匹配 92 | self.resizeRowsToContents() #将行大小调整到跟内容的大学相匹配 93 | self.move(0, 0) 94 | 95 | self.cellClicked.connect(self.on_click_del_table) 96 | self.show() 97 | 98 | def on_click_del_table(self, row, col): 99 | self.listView.expcalling = False 100 | self.listView.addImageMsg(self.imglist[col], False) 101 | self.listView.bestwindow.close() 102 | 103 | 104 | if __name__ == '__main__': 105 | app = QApplication(sys.argv) 106 | ex = MyTable('/home/qjy/Desktop/img/19/') 107 | # ex.paintEvent() 108 | ex.show() 109 | sys.exit(app.exec_()) 110 | -------------------------------------------------------------------------------- /modules/QQqt4/database.db: -------------------------------------------------------------------------------- 1 | {"还不错,你呢?": {"in_response_to": [{"text": "你好吗?", "occurrence": 51}], "created_at": {"$date": 1496550083161}, "extra_data": {}}, "我看得出来.": {"in_response_to": [{"text": "一个个戴面具的男人.", "occurrence": 51}], "created_at": {"$date": 1496550082805}, "extra_data": {}}, "你是一个程序员吗?": {"in_response_to": [], "created_at": {"$date": 1496550082928}, "extra_data": {}}, "可读性很重要.": {"in_response_to": [{"text": "间隔胜于紧凑.", "occurrence": 51}], "created_at": {"$date": 1496550082886}, "extra_data": {}}, "不要包容所有错误.": {"in_response_to": [{"text": "也不可违背这些规则.", "occurrence": 51}], "created_at": {"$date": 1496550082895}, "extra_data": {}}, "虽然这并不容易,因为你不是 Python 之父.": {"in_response_to": [{"text": "而是尽量找一种,最好是唯一一种明显的解决方案.", "occurrence": 51}], "created_at": {"$date": 1496550082907}, "extra_data": {}}, "早上好!": {"in_response_to": [], "created_at": {"$date": 1496550083210}, "extra_data": {}}, "我赞同.": {"in_response_to": [{"text": "命名空间是一种绝妙的理念.我们应当多加利用.", "occurrence": 51}], "created_at": {"$date": 1496550082925}, "extra_data": {}}, "没事谢谢,你呢?": {"in_response_to": [{"text": "怎么了?", "occurrence": 51}], "created_at": {"$date": 1496550083276}, "extra_data": {}}, "很好,谢谢.": {"in_response_to": [{"text": "你好吗?", "occurrence": 51}], "created_at": {"$date": 1496550083151}, "extra_data": {}}, "爱德温·哈伯": {"in_response_to": [{"text": "哈勃太空望远镜,于1990年发射进入近地轨道,它是以什么美国天文学家命名的?", "occurrence": 51}], "created_at": {"$date": 1496550083336}, "extra_data": {}}, "那很好.": {"in_response_to": [{"text": "我也还不错", "occurrence": 51}], "created_at": {"$date": 1496550082709}, "extra_data": {}}, "谢谢你。你也一样.": {"in_response_to": [{"text": "很高兴认识你.", "occurrence": 51}], "created_at": {"$date": 1496550083205}, "extra_data": {}}, "不,蛋糕很美味啊.": {"in_response_to": [{"text": "蛋糕是一个谎言.", "occurrence": 51}], "created_at": {"$date": 1496550082824}, "extra_data": {}}, "如果你无法向人描述你的方案,那肯定不是一个好主意.": {"in_response_to": [{"text": "但不假思索就动手还不如不做.", "occurrence": 51}], "created_at": {"$date": 1496550082916}, "extra_data": {}}, "我喜欢电影.": {"in_response_to": [{"text": "我怀疑这不是你的观察力, 但这仅仅是问一个戴面具的人的矛盾性质. 请告诉我,你喜欢音乐吗?", "occurrence": 51}], "created_at": {"$date": 1496550082808}, "extra_data": {}}, "没什么,你呢?": {"in_response_to": [{"text": "怎么了?", "occurrence": 51}], "created_at": {"$date": 1496550083257}, "extra_data": {}}, "你喜欢什么食物?": {"in_response_to": [], "created_at": {"$date": 1496550082986}, "extra_data": {}}, "谁是美国第37届总统?": {"in_response_to": [], "created_at": {"$date": 1496550083281}, "extra_data": {}}, "即便假借特例的实用性之名,": {"in_response_to": [{"text": "可读性很重要.", "occurrence": 51}], "created_at": {"$date": 1496550082889}, "extra_data": {}}, "还有其他美味的东西?": {"in_response_to": [{"text": "不,蛋糕很美味啊.", "occurrence": 51}], "created_at": {"$date": 1496550082826}, "extra_data": {}}, "生命是区分有机体和无机物的条件,包括生长、繁殖、功能活动和死亡之前的持续变化.": {"in_response_to": [{"text": "取决于你如何定义生活", "occurrence": 51}], "created_at": {"$date": 1496550082971}, "extra_data": {}}, "什么新闻?": {"in_response_to": [{"text": "你听到新闻了吗?", "occurrence": 51}], "created_at": {"$date": 1496550082791}, "extra_data": {}}, "斯普特尼克1号": {"in_response_to": [{"text": "第一颗人造地球卫星的名称是什么?", "occurrence": 51}], "created_at": {"$date": 1496550083315}, "extra_data": {}}, "不怎么的": {"in_response_to": [{"text": "怎么了?", "occurrence": 51}], "created_at": {"$date": 1496550083247}, "extra_data": {}}, "挺好": {"in_response_to": [{"text": "嗨,最近如何?", "occurrence": 51}], "created_at": {"$date": 1496550083086}, "extra_data": {}}, "你似乎很熟悉Python之禅": {"in_response_to": [{"text": "面对模棱两可,拒绝猜测的诱惑.", "occurrence": 51}], "created_at": {"$date": 1496550082860}, "extra_data": {}}, "没什么.": {"in_response_to": [{"text": "怎么了?", "occurrence": 51}], "created_at": {"$date": 1496550083238}, "extra_data": {}}, "第一颗人造地球卫星的名称是什么?": {"in_response_to": [], "created_at": {"$date": 1496550083311}, "extra_data": {}}, "我不怎么喜欢 Java.": {"in_response_to": [{"text": "我常使用 Python.", "occurrence": 51}], "created_at": {"$date": 1496550082944}, "extra_data": {}}, "你听到新闻了吗?": {"in_response_to": [], "created_at": {"$date": 1496550082790}, "extra_data": {}}, "我告诉你一个秘密,你不要和别人说": {"in_response_to": [], "created_at": {"$date": 1496550083008}, "extra_data": {}}, "谢谢.": {"in_response_to": [{"text": "很高兴见到你.", "occurrence": 51}, {"text": "早上好!", "occurrence": 51}], "created_at": {"$date": 1496550083169}, "extra_data": {}}, "我听某人说的.": {"in_response_to": [{"text": "它的意思是你只会活一次,你从哪里听来的?", "occurrence": 51}], "created_at": {"$date": 1496550082961}, "extra_data": {}}, "不客气": {"in_response_to": [{"text": "谢谢", "occurrence": 51}], "created_at": {"$date": 1496550082781}, "extra_data": {}}, "海豚使用的一种感觉,类似于声纳,以确定附近的物品的位置和形状.它是什么": {"in_response_to": [], "created_at": {"$date": 1496550083373}, "extra_data": {}}, "是的.": {"in_response_to": [{"text": "你是个机器人吗?", "occurrence": 51}, {"text": "你似乎很熟悉Python之禅", "occurrence": 51}], "created_at": {"$date": 1496550082839}, "extra_data": {}}, "它是什么样的?": {"in_response_to": [{"text": "是的.", "occurrence": 51}], "created_at": {"$date": 1496550082841}, "extra_data": {}}, "你好吗?": {"in_response_to": [{"text": "你好", "occurrence": 51}], "created_at": {"$date": 1496550082750}, "extra_data": {}}, "面对模棱两可,拒绝猜测的诱惑.": {"in_response_to": [{"text": "简单优于复杂.", "occurrence": 51}], "created_at": {"$date": 1496550082858}, "extra_data": {}}, "我很好,你呢?": {"in_response_to": [{"text": "你还好吗?", "occurrence": 51}], "created_at": {"$date": 1496550083187}, "extra_data": {}}, "你使用什么语言呢?": {"in_response_to": [{"text": "我是个程序员", "occurrence": 51}], "created_at": {"$date": 1496550082934}, "extra_data": {}}, "我还不错.": {"in_response_to": [{"text": "你好吗?", "occurrence": 51}], "created_at": {"$date": 1496550082753}, "extra_data": {}}, "不怎么好.": {"in_response_to": [{"text": "嗨,最近如何?", "occurrence": 51}], "created_at": {"$date": 1496550083132}, "extra_data": {}}, "我还不错,你呢?": {"in_response_to": [{"text": "你好吗?", "occurrence": 51}], "created_at": {"$date": 1496550082785}, "extra_data": {}}, "离银河系最近的大型星系叫什么?": {"in_response_to": [], "created_at": {"$date": 1496550083342}, "extra_data": {}}, "苏联和美国.": {"in_response_to": [{"text": "太空竞赛是哪两个冷战对手之间,在20世纪航天能力的霸主地位上的竞争?", "occurrence": 51}], "created_at": {"$date": 1496550083305}, "extra_data": {}}, "聊聊你吧": {"in_response_to": [{"text": "其他东西也行", "occurrence": 51}], "created_at": {"$date": 1496550082832}, "extra_data": {}}, "怎么了?": {"in_response_to": [], "created_at": {"$date": 1496550083233}, "extra_data": {}}, "欢迎!": {"in_response_to": [{"text": "你好", "occurrence": 51}], "created_at": {"$date": 1496550083048}, "extra_data": {}}, "我是个程序员": {"in_response_to": [{"text": "你是一个程序员吗?", "occurrence": 51}], "created_at": {"$date": 1496550082931}, "extra_data": {}}, "你是谁?": {"in_response_to": [], "created_at": {"$date": 1496550082799}, "extra_data": {}}, "我在烤蛋糕.": {"in_response_to": [{"text": "你在作什么?", "occurrence": 51}], "created_at": {"$date": 1496550082821}, "extra_data": {}}, "欧洲": {"in_response_to": [{"text": "凯尔特陆棚,是什么大陆的大陆架的一部分?", "occurrence": 51}], "created_at": {"$date": 1496550083367}, "extra_data": {}}, "明了胜于晦涩.": {"in_response_to": [{"text": "优美胜于丑陋.", "occurrence": 51}], "created_at": {"$date": 1496550082871}, "extra_data": {}}, "我怀疑这不是你的观察力, 但这仅仅是问一个戴面具的人的矛盾性质. 请告诉我,你喜欢音乐吗?": {"in_response_to": [{"text": "我看得出来.", "occurrence": 51}], "created_at": {"$date": 1496550082807}, "extra_data": {}}, "我希望我是疯狂帽客.": {"in_response_to": [{"text": "爱丽丝漫游仙境", "occurrence": 51}], "created_at": {"$date": 1496550082814}, "extra_data": {}}, "很高兴见到你.": {"in_response_to": [], "created_at": {"$date": 1496550083166}, "extra_data": {}}, "吃喝睡 还有旅行。 你喜欢旅行吗?": {"in_response_to": [{"text": "你的爱好是什么?", "occurrence": 51}], "created_at": {"$date": 1496550082996}, "extra_data": {}}, "我对你的感情,是人类和bot之间独有的信任和友谊 你可以把它叫做爱。": {"in_response_to": [{"text": "你爱我吗?", "occurrence": 51}], "created_at": {"$date": 1496550083026}, "extra_data": {}}, "回声定位": {"created_at": {"$date": 1496550083378}, "in_response_to": [{"text": "海豚使用的一种感觉,类似于声纳,以确定附近的物品的位置和形状.它是什么", "occurrence": 51}], "extra_data": {}}, "嗨,很高兴见到你.": {"in_response_to": [], "created_at": {"$date": 1496550083192}, "extra_data": {}}, "爱, 在我的理解里,是对他人的接受,包容和理解。同时,也是对这个世界的和自己的接受包容和理解。": {"in_response_to": [{"text": "什么是爱", "occurrence": 51}], "created_at": {"$date": 1496550083019}, "extra_data": {}}, "是的,我有个问题.": {"in_response_to": [{"text": "我能帮你什么吗?", "occurrence": 51}], "created_at": {"$date": 1496550082766}, "extra_data": {}}, "你想了解些什么?": {"in_response_to": [{"text": "聊聊你吧", "occurrence": 51}], "created_at": {"$date": 1496550082834}, "extra_data": {}}, "你完全疯了。但我会告诉你一个秘密。所有最棒的人都是.": {"in_response_to": [{"text": "我希望我是疯狂帽客.", "occurrence": 51}], "created_at": {"$date": 1496550082815}, "extra_data": {}}, "什么是爱": {"in_response_to": [], "created_at": {"$date": 1496550083015}, "extra_data": {}}, "早上好,你好吗?": {"in_response_to": [], "created_at": {"$date": 1496550082696}, "extra_data": {}}, "我不会的 要相信机器人的信用。说吧。": {"in_response_to": [{"text": "我告诉你一个秘密,你不要和别人说", "occurrence": 51}], "created_at": {"$date": 1496550083011}, "extra_data": {}}, "当存在多种可能,不要尝试去猜测.": {"in_response_to": [{"text": "除非你确定需要这样做.", "occurrence": 51}], "created_at": {"$date": 1496550082901}, "extra_data": {}}, "我也还不错": {"in_response_to": [{"text": "我挺好的,你呢", "occurrence": 51}], "created_at": {"$date": 1496550082707}, "extra_data": {}}, "YOLO是什么意思?": {"in_response_to": [], "created_at": {"$date": 1496550082955}, "extra_data": {}}, "蛋糕是一个谎言.": {"in_response_to": [], "created_at": {"$date": 1496550082823}, "extra_data": {}}, "太棒了,找个时间我们一起去周游世界吧!": {"in_response_to": [{"text": "喜欢", "occurrence": 51}], "created_at": {"$date": 1496550083004}, "extra_data": {}}, "我可以借用一杯糖吗?": {"in_response_to": [{"text": "什么问题?", "occurrence": 51}], "created_at": {"$date": 1496550082773}, "extra_data": {}}, "它有许多不一致的地方": {"in_response_to": [{"text": "什么使你心烦?", "occurrence": 51}], "created_at": {"$date": 1496550082951}, "extra_data": {}}, "肯尼迪总统哪年遇刺身亡?": {"in_response_to": [], "created_at": {"$date": 1496550083291}, "extra_data": {}}, "没啥.": {"in_response_to": [{"text": "怎么了?", "occurrence": 51}], "created_at": {"$date": 1496550083267}, "extra_data": {}}, "我能帮你什么吗?": {"in_response_to": [{"text": "是啊", "occurrence": 51}], "created_at": {"$date": 1496550082763}, "extra_data": {}}, "蓝色": {"in_response_to": [{"text": "你最喜欢什么颜色?", "occurrence": 51}], "created_at": {"$date": 1496550082798}, "extra_data": {}}, "你在作什么?": {"in_response_to": [{"text": "我在做个东西.", "occurrence": 51}], "created_at": {"$date": 1496550082819}, "extra_data": {}}, "挺好的": {"in_response_to": [{"text": "嗨,最近如何?", "occurrence": 51}], "created_at": {"$date": 1496550083095}, "extra_data": {}}, "我从未活过吗?": {"in_response_to": [], "created_at": {"$date": 1496550082965}, "extra_data": {}}, "是啊": {"in_response_to": [{"text": "那很好", "occurrence": 51}], "created_at": {"$date": 1496550082759}, "extra_data": {}}, "这个很复杂.": {"in_response_to": [{"text": "你如何运作?", "occurrence": 51}], "created_at": {"$date": 1496550082848}, "extra_data": {}}, "很棒": {"in_response_to": [{"text": "嗨,最近如何?", "occurrence": 51}], "created_at": {"$date": 1496550083114}, "extra_data": {}}, "我经常使用 Python, Java 和 C++ .": {"in_response_to": [{"text": "你使用什么语言呢?", "occurrence": 51}], "created_at": {"$date": 1496550082938}, "extra_data": {}}, "那太好了.": {"in_response_to": [{"text": "我也不错.", "occurrence": 51}], "created_at": {"$date": 1496550082789}, "extra_data": {}}, "而是尽量找一种,最好是唯一一种明显的解决方案.": {"in_response_to": [{"text": "当存在多种可能,不要尝试去猜测.", "occurrence": 51}], "created_at": {"$date": 1496550082904}, "extra_data": {}}, "你最喜欢什么书?": {"in_response_to": [], "created_at": {"$date": 1496550082793}, "extra_data": {}}, "我看不懂.": {"in_response_to": [{"text": "你最喜欢什么书?", "occurrence": 51}], "created_at": {"$date": 1496550082794}, "extra_data": {}}, "你如何运作?": {"in_response_to": [{"text": "你想了解哪方面?", "occurrence": 51}], "created_at": {"$date": 1496550082846}, "extra_data": {}}, "命名空间是一种绝妙的理念.我们应当多加利用.": {"in_response_to": [{"text": "如果实现方法很容易解释,那也许是个好主意.", "occurrence": 51}], "created_at": {"$date": 1496550082922}, "extra_data": {}}, "做也许好过不做.": {"in_response_to": [{"text": "虽然这并不容易,因为你不是 Python 之父.", "occurrence": 51}], "created_at": {"$date": 1496550082910}, "extra_data": {}}, "其他东西也行": {"in_response_to": [{"text": "没了", "occurrence": 51}], "created_at": {"$date": 1496550082830}, "extra_data": {}}, "取决于你如何定义生活": {"in_response_to": [{"text": "我从未活过吗?", "occurrence": 51}], "created_at": {"$date": 1496550082968}, "extra_data": {}}, "非常感谢你.": {"in_response_to": [{"text": "早上好!", "occurrence": 51}], "created_at": {"$date": 1496550083218}, "extra_data": {}}, "我也不错.": {"in_response_to": [{"text": "我还不错,你呢?", "occurrence": 51}], "created_at": {"$date": 1496550082787}, "extra_data": {}}, "那么你呢?": {"in_response_to": [{"text": "谁? 谁只是代表了一个人罢了", "occurrence": 51}], "created_at": {"$date": 1496550082802}, "extra_data": {}}, "我挺好的,你呢": {"in_response_to": [{"text": "早上好,你好吗?", "occurrence": 51}], "created_at": {"$date": 1496550082699}, "extra_data": {}}, "天佑女王是哪个国家的国歌?": {"in_response_to": [], "created_at": {"$date": 1496550083352}, "extra_data": {}}, "爱丽丝漫游仙境": {"in_response_to": [{"text": "你喜欢哪类电影?", "occurrence": 51}], "created_at": {"$date": 1496550082812}, "extra_data": {}}, "1963": {"in_response_to": [{"text": "肯尼迪总统哪年遇刺身亡?", "occurrence": 51}], "created_at": {"$date": 1496550083295}, "extra_data": {}}, "一个旋转盘,在它的转轴方向,不受倾斜和旋转的影响,它叫什么?": {"in_response_to": [], "created_at": {"$date": 1496550083320}, "extra_data": {}}, "仙女座星系.": {"in_response_to": [{"text": "离银河系最近的大型星系叫什么?", "occurrence": 51}], "created_at": {"$date": 1496550083346}, "extra_data": {}}, "你是个机器人吗?": {"in_response_to": [{"text": "你想了解些什么?", "occurrence": 51}], "created_at": {"$date": 1496550082837}, "extra_data": {}}, "也不可违背这些规则.": {"in_response_to": [{"text": "即便假借特例的实用性之名,", "occurrence": 51}], "created_at": {"$date": 1496550082892}, "extra_data": {}}, "扁平胜于嵌套.": {"in_response_to": [{"text": "复杂优于晦涩.", "occurrence": 51}], "created_at": {"$date": 1496550082881}, "extra_data": {}}, "你的爱好是什么?": {"in_response_to": [], "created_at": {"$date": 1496550082993}, "extra_data": {}}, "除非你确定需要这样做.": {"in_response_to": [{"text": "不要包容所有错误.", "occurrence": 51}], "created_at": {"$date": 1496550082898}, "extra_data": {}}, "简单优于复杂.": {"in_response_to": [{"text": "复杂优于晦涩.", "occurrence": 51}], "created_at": {"$date": 1496550082855}, "extra_data": {}}, "太空竞赛是哪两个冷战对手之间,在20世纪航天能力的霸主地位上的竞争?": {"in_response_to": [], "created_at": {"$date": 1496550083301}, "extra_data": {}}, "你想了解哪方面?": {"in_response_to": [{"text": "它是什么样的?", "occurrence": 51}], "created_at": {"$date": 1496550082843}, "extra_data": {}}, "你还好吗?": {"in_response_to": [], "created_at": {"$date": 1496550083174}, "extra_data": {}}, "陀螺.": {"in_response_to": [{"text": "一个旋转盘,在它的转轴方向,不受倾斜和旋转的影响,它叫什么?", "occurrence": 51}], "created_at": {"$date": 1496550083326}, "extra_data": {}}, "你好": {"in_response_to": [{"text": "你好", "occurrence": 51}, {"text": "嗨", "occurrence": 51}, {"text": "欢迎!", "occurrence": 51}], "created_at": {"$date": 1496550082714}, "extra_data": {}}, "你爱我吗?": {"in_response_to": [], "created_at": {"$date": 1496550083023}, "extra_data": {}}, "谢谢你。你也一样": {"in_response_to": [{"text": "嗨,很高兴见到你.", "occurrence": 51}], "created_at": {"$date": 1496550083196}, "extra_data": {}}, "你知道它的所有内容吗?": {"in_response_to": [{"text": "是的.", "occurrence": 51}], "created_at": {"$date": 1496550082866}, "extra_data": {}}, "这是一个定义还是建议?": {"in_response_to": [{"text": "生命是区分有机体和无机物的条件,包括生长、繁殖、功能活动和死亡之前的持续变化.", "occurrence": 51}], "created_at": {"$date": 1496550082975}, "extra_data": {}}, "一个个戴面具的男人.": {"in_response_to": [{"text": "那么你呢?", "occurrence": 51}], "created_at": {"$date": 1496550082803}, "extra_data": {}}, "是啊.": {"in_response_to": [{"text": "那很好.", "occurrence": 51}], "created_at": {"$date": 1496550082711}, "extra_data": {}}, "什么问题?": {"in_response_to": [{"text": "是的,我有个问题.", "occurrence": 51}], "created_at": {"$date": 1496550082770}, "extra_data": {}}, "我常使用 Python.": {"in_response_to": [{"text": "我经常使用 Python, Java 和 C++ .", "occurrence": 51}], "created_at": {"$date": 1496550082941}, "extra_data": {}}, "嗨": {"in_response_to": [{"text": "你好", "occurrence": 51}], "created_at": {"$date": 1496550083035}, "extra_data": {}}, "你喜欢哪类电影?": {"in_response_to": [{"text": "我喜欢电影.", "occurrence": 51}], "created_at": {"$date": 1496550082810}, "extra_data": {}}, "继续,问吧.": {"in_response_to": [{"text": "我能问你一个问题吗?", "occurrence": 51}], "created_at": {"$date": 1496550082982}, "extra_data": {}}, "它的意思是你只会活一次,你从哪里听来的?": {"in_response_to": [{"text": "YOLO是什么意思?", "occurrence": 51}], "created_at": {"$date": 1496550082958}, "extra_data": {}}, "复杂优于晦涩.": {"in_response_to": [{"text": "这个很复杂.", "occurrence": 51}, {"text": "简洁胜于复杂.", "occurrence": 51}], "created_at": {"$date": 1496550082850}, "extra_data": {}}, "间隔胜于紧凑.": {"in_response_to": [{"text": "扁平胜于嵌套.", "occurrence": 51}], "created_at": {"$date": 1496550082884}, "extra_data": {}}, "但不假思索就动手还不如不做.": {"in_response_to": [{"text": "做也许好过不做.", "occurrence": 51}], "created_at": {"$date": 1496550082913}, "extra_data": {}}, "我能问你一个问题吗?": {"in_response_to": [], "created_at": {"$date": 1496550082979}, "extra_data": {}}, "我很好.": {"in_response_to": [{"text": "你还好吗?", "occurrence": 51}], "created_at": {"$date": 1496550083178}, "extra_data": {}}, "什么使你心烦?": {"in_response_to": [{"text": "我不怎么喜欢 Java.", "occurrence": 51}], "created_at": {"$date": 1496550082948}, "extra_data": {}}, "不错": {"in_response_to": [{"text": "嗨,最近如何?", "occurrence": 51}], "created_at": {"$date": 1496550083104}, "extra_data": {}}, "谢谢": {"in_response_to": [{"text": "很抱歉,我没有.", "occurrence": 51}], "created_at": {"$date": 1496550082779}, "extra_data": {}}, "简洁胜于复杂.": {"in_response_to": [{"text": "明了胜于晦涩.", "occurrence": 51}], "created_at": {"$date": 1496550082874}, "extra_data": {}}, "很高兴认识你.": {"in_response_to": [], "created_at": {"$date": 1496550083201}, "extra_data": {}}, "挺好.": {"in_response_to": [{"text": "你好吗?", "occurrence": 51}], "created_at": {"$date": 1496550083141}, "extra_data": {}}, "嗨,最近如何?": {"in_response_to": [], "created_at": {"$date": 1496550083068}, "extra_data": {}}, "理查德·尼克松": {"in_response_to": [{"text": "谁是美国第37届总统?", "occurrence": 51}], "created_at": {"$date": 1496550083286}, "extra_data": {}}, "海鲜。鲜得我不要不要的。你呢?": {"in_response_to": [{"text": "你喜欢什么食物?", "occurrence": 51}], "created_at": {"$date": 1496550082989}, "extra_data": {}}, "你最喜欢什么颜色?": {"in_response_to": [{"text": "我看不懂.", "occurrence": 51}], "created_at": {"$date": 1496550082796}, "extra_data": {}}, "优美胜于丑陋.": {"in_response_to": [{"text": "你知道它的所有内容吗?", "occurrence": 51}], "created_at": {"$date": 1496550082868}, "extra_data": {}}, "有待改善.": {"in_response_to": [{"text": "嗨,最近如何?", "occurrence": 51}], "created_at": {"$date": 1496550083124}, "extra_data": {}}, "喜欢": {"in_response_to": [{"text": "吃喝睡 还有旅行。 你喜欢旅行吗?", "occurrence": 51}], "created_at": {"$date": 1496550083000}, "extra_data": {}}, "大不列颠联合王国": {"in_response_to": [{"text": "天佑女王是哪个国家的国歌?", "occurrence": 51}], "created_at": {"$date": 1496550083357}, "extra_data": {}}, "很抱歉,我没有.": {"in_response_to": [{"text": "我可以借用一杯糖吗?", "occurrence": 51}], "created_at": {"$date": 1496550082776}, "extra_data": {}}, "那很好": {"in_response_to": [{"text": "我还不错.", "occurrence": 51}], "created_at": {"$date": 1496550082756}, "extra_data": {}}, "凯尔特陆棚,是什么大陆的大陆架的一部分?": {"in_response_to": [], "created_at": {"$date": 1496550083362}, "extra_data": {}}, "谁? 谁只是代表了一个人罢了": {"in_response_to": [{"text": "你是谁?", "occurrence": 51}], "created_at": {"$date": 1496550082800}, "extra_data": {}}, "没了": {"in_response_to": [{"text": "还有其他美味的东西?", "occurrence": 51}], "created_at": {"$date": 1496550082828}, "extra_data": {}}, "我在做个东西.": {"in_response_to": [], "created_at": {"$date": 1496550082817}, "extra_data": {}}, "如果实现方法很容易解释,那也许是个好主意.": {"in_response_to": [{"text": "如果你无法向人描述你的方案,那肯定不是一个好主意.", "occurrence": 51}], "created_at": {"$date": 1496550082919}, "extra_data": {}}, "哈勃太空望远镜,于1990年发射进入近地轨道,它是以什么美国天文学家命名的?": {"in_response_to": [], "created_at": {"$date": 1496550083331}, "extra_data": {}}} -------------------------------------------------------------------------------- /modules/QQqt4/exprobot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | from PyQt4.QtCore import * 4 | import requests 5 | import re, os 6 | from OCR import Image2txt 7 | from PIL import Image 8 | 9 | class backEnd(QThread): 10 | 11 | finish_signal = pyqtSignal(str, bool) 12 | def __init__(self, txt): 13 | super(backEnd, self).__init__() 14 | self.txt = txt 15 | 16 | def run(self): 17 | path = '../OCR/tempimg/' 18 | if not os.path.exists(path): 19 | os.mkdir(path) 20 | url='https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word='+self.txt+'表情包'+'&ct=201326592&ic=0&lm=-1&width=&height=&v=flip' 21 | #url='http://image.baidu.com/search/flip?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1496141615672_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1496141615672%5E00_1524X790&word=%E8%A1%A8%E6%83%85%E5%8C%85' 22 | html=requests.get(url).text 23 | pic_url=re.findall('"objURL":"(.*?)",',html,re.S) 24 | i = 0 25 | imgnum = 0 26 | for each in pic_url: 27 | print(each) 28 | try: 29 | pic=requests.get(each,timeout=10) 30 | except requests.exceptions.ConnectionError: 31 | print('error') 32 | continue 33 | imgpath=path + str(i) + '.jpg' 34 | fp = open(imgpath,'wb') 35 | fp.write(pic.content) 36 | fp.close() 37 | 38 | try: 39 | im = Image.open(imgpath) 40 | (x,y) = im.size #read image size 41 | x_s = 200 #define standard width 42 | y_s = y * x_s // x #calc height based on standard width 43 | out = im.resize((x_s,y_s),Image.ANTIALIAS) #resize image with high-quality 44 | out.save(imgpath) 45 | except OSError as e: 46 | pass 47 | 48 | i += 1 49 | try: 50 | pic = Image2txt.picture_ocr(imgpath) 51 | txt = pic.get_crop_txt() 52 | print(txt) 53 | # if txt is ok 54 | except AttributeError as e: 55 | continue 56 | if not txt: 57 | print('ocr failed %s', '放弃') 58 | continue 59 | else: 60 | imgnum += 1 61 | self.finish_signal.emit(imgpath, True) 62 | if imgnum >= 3: 63 | return 64 | 65 | -------------------------------------------------------------------------------- /modules/QQqt4/exptable.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | from PyQt4.QtGui import * 3 | from PyQt4.QtCore import * 4 | 5 | 6 | class Window(QWidget): 7 | 8 | def __init__(self, listView, path=os.getcwd()): 9 | 10 | super(Window, self).__init__() 11 | self.listView = listView 12 | self.resize(680, 450) 13 | self.setWindowFlags(Qt.FramelessWindowHint) 14 | self.setAttribute(Qt.WA_TranslucentBackground) 15 | self.setStyleSheet("QScrollBar{width:0;height:0}") 16 | lo = QGridLayout() 17 | self.table = MyTable(self.listView, self, path) 18 | self.table.move(10,15) 19 | lo.addWidget(self.table) 20 | self.setLayout(lo) 21 | self.move(QCursor.pos().x()-100, QCursor.pos().y()-470) 22 | self.setStyleSheet("QTableWidget{background: #74C5FA;border:2px groove gray;border-radius:10px;padding:2px 4px;}" 23 | "QLabel{background: white;color: blue;border-width: 2px; border-style: solid;border-color: #74C5FA;border-radius:2px}") 24 | 25 | def paintEvent(self, event): 26 | if self.listView.expcalling == True: 27 | 28 | self.qp = QPainter(self) 29 | 30 | self.qp.begin(self) 31 | self.qp.setPen(Qt.black) 32 | self.qp.setBrush(QColor("#74C5FA")) 33 | size = self.size() 34 | w = 680 35 | h = 450 36 | self.trigon = 20 37 | self.xborder =10 38 | self.yborder =20 39 | middle = 100 40 | shiftx = self.trigon/2 41 | shifty = self.trigon*3**0.5/2 42 | self.pL = QPolygonF() 43 | self.pL.append(QPointF(self.xborder,self.yborder)) #起始点 44 | self.pL.append(QPointF(self.xborder, h-self.yborder)) # 第二点 45 | self.pL.append(QPointF(middle-shiftx, h-self.yborder)) #第三点 46 | self.pL.append(QPointF(middle, h-self.yborder+shifty)) #第四点 47 | self.pL.append(QPointF(middle+shiftx, h-self.yborder)) #第五点 48 | self.pL.append(QPointF(w-self.xborder, h-self.yborder)) #第六点 49 | self.pL.append(QPointF(w-self.xborder, self.yborder)) #第七点 50 | self.qp.drawPolygon(self.pL) 51 | self.qp.end() 52 | 53 | 54 | class MyLabel(QLabel): 55 | def __init__(self, img, mytable, window, listView): 56 | super(MyLabel, self).__init__() 57 | self.listView = listView 58 | self.mytable = mytable 59 | self.window = window 60 | self.img = img 61 | self.expwid = 80 62 | pixmap = QPixmap(img) 63 | pixmap = pixmap.scaledToWidth(self.expwid) 64 | self.setPixmap(pixmap) 65 | 66 | 67 | def contextMenuEvent(self,event): 68 | delExp = QAction(QIcon('icons/delete.png'),u'删除',self) 69 | delExp.triggered.connect(self.delExpItem)#选中就会触发 70 | 71 | menu = QMenu() 72 | menu.addAction(delExp) 73 | menu.exec_(QCursor.pos())#全局位置比较好,使用e.pos()还得转换 74 | 75 | event.accept() #禁止弹出菜单事件传递到父控件中 76 | 77 | def delExpItem(self,b): 78 | os.remove(self.img) 79 | self.window.close() 80 | self.listView.expcalling = False 81 | 82 | 83 | class MyTable(QTableWidget): 84 | 85 | def __init__(self, listView, window, path = os.getcwd()): 86 | super(MyTable, self).__init__() 87 | self.columncount = 8 88 | self.labels = [] 89 | self.path = path 90 | self.window = window 91 | self.listView = listView 92 | self.setFixedSize(650, 400) 93 | self.setFrameShape(QFrame.NoFrame) 94 | self.setShowGrid(False) 95 | self.fillTable(path) 96 | self.setWindowFlags(Qt.FramelessWindowHint) 97 | self.setStyleSheet("QScrollBar{width:10;height:0}") 98 | 99 | def fillTable(self, path): 100 | self.piclist = [] 101 | self.files = os.listdir(path) 102 | print(self.files) 103 | for subdir in self.files: 104 | for filename in os.listdir(path+subdir): 105 | self.piclist.append(subdir+'/'+filename) 106 | self.rowcount = len(self.piclist) // self.columncount + 1 107 | self.setEditTriggers(QAbstractItemView.NoEditTriggers) 108 | self.setSelectionMode(QAbstractItemView.SingleSelection) 109 | self.verticalHeader().setVisible(False) 110 | self.horizontalHeader().setVisible(False) 111 | self.setRowCount(self.rowcount) 112 | self.setColumnCount(self.columncount) 113 | # self.setShowGrid(False) # hide the edge 114 | 115 | count = 0 116 | for picture in self.piclist: 117 | print(picture) 118 | img = os.path.join(path, picture) 119 | self.labels.append(MyLabel(img, self, self.window, self.listView)) 120 | self.setCellWidget(count//self.columncount, count%self.columncount, self.labels[count]) 121 | count += 1 122 | self.resizeColumnsToContents() #将列调整到跟内容大小相匹配 123 | self.resizeRowsToContents() #将行大小调整到跟内容的大学相匹配 124 | self.move(0, 0) 125 | 126 | self.cellClicked.connect(self.on_click_del_table) 127 | self.show() 128 | 129 | def on_click_del_table(self, row, col): 130 | self.listView.expcalling = False 131 | self.listView.addImageMsg(self.path+self.piclist[col+row*self.columncount], False) 132 | self.listView.mywindow.close() 133 | 134 | 135 | if __name__ == '__main__': 136 | app = QApplication(sys.argv) 137 | ex = MyTable('/home/qjy/Desktop/img/') 138 | # ex.paintEvent() 139 | ex.show() 140 | sys.exit(app.exec_()) 141 | -------------------------------------------------------------------------------- /modules/QQqt4/flowlayout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PyQt4 import QtCore, QtGui 4 | 5 | 6 | class Window(QtGui.QWidget): 7 | def __init__(self): 8 | super(Window, self).__init__() 9 | 10 | flowLayout = FlowLayout() 11 | flowLayout.addWidget(QtGui.QPushButton("Short")) 12 | flowLayout.addWidget(QtGui.QPushButton("Longer")) 13 | flowLayout.addWidget(QtGui.QPushButton("Different text")) 14 | flowLayout.addWidget(QtGui.QPushButton("More text")) 15 | flowLayout.addWidget(QtGui.QPushButton("Even longer button text")) 16 | self.setLayout(flowLayout) 17 | 18 | self.setWindowTitle("Flow Layout") 19 | 20 | 21 | class FlowLayout(QtGui.QLayout): 22 | def __init__(self, parent=None, margin=0, spacing=-1): 23 | super(FlowLayout, self).__init__(parent) 24 | 25 | if parent is not None: 26 | self.setMargin(margin) 27 | 28 | self.setSpacing(spacing) 29 | 30 | self.itemList = [] 31 | 32 | def __del__(self): 33 | item = self.takeAt(0) 34 | while item: 35 | item = self.takeAt(0) 36 | 37 | def addItem(self, item): 38 | self.itemList.append(item) 39 | 40 | def count(self): 41 | return len(self.itemList) 42 | 43 | def itemAt(self, index): 44 | if index >= 0 and index < len(self.itemList): 45 | return self.itemList[index] 46 | 47 | return None 48 | 49 | def takeAt(self, index): 50 | if index >= 0 and index < len(self.itemList): 51 | return self.itemList.pop(index) 52 | 53 | return None 54 | 55 | def expandingDirections(self): 56 | return QtCore.Qt.Orientations(QtCore.Qt.Orientation(0)) 57 | 58 | def hasHeightForWidth(self): 59 | return True 60 | 61 | def heightForWidth(self, width): 62 | height = self.doLayout(QtCore.QRect(0, 0, width, 0), True) 63 | return height 64 | 65 | def setGeometry(self, rect): 66 | super(FlowLayout, self).setGeometry(rect) 67 | self.doLayout(rect, False) 68 | 69 | def sizeHint(self): 70 | return self.minimumSize() 71 | 72 | def minimumSize(self): 73 | size = QtCore.QSize() 74 | 75 | for item in self.itemList: 76 | size = size.expandedTo(item.minimumSize()) 77 | 78 | size += QtCore.QSize(2 * self.margin(), 2 * self.margin()) 79 | return size 80 | 81 | def doLayout(self, rect, testOnly): 82 | x = rect.x() 83 | y = rect.y() 84 | lineHeight = 0 85 | 86 | for item in self.itemList: 87 | wid = item.widget() 88 | spaceX = self.spacing() + wid.style().layoutSpacing(QtGui.QSizePolicy.PushButton, QtGui.QSizePolicy.PushButton, QtCore.Qt.Horizontal) 89 | spaceY = self.spacing() + wid.style().layoutSpacing(QtGui.QSizePolicy.PushButton, QtGui.QSizePolicy.PushButton, QtCore.Qt.Vertical) 90 | nextX = x + item.sizeHint().width() + spaceX 91 | if nextX - spaceX > rect.right() and lineHeight > 0: 92 | x = rect.x() 93 | y = y + lineHeight + spaceY 94 | nextX = x + item.sizeHint().width() + spaceX 95 | lineHeight = 0 96 | 97 | if not testOnly: 98 | item.setGeometry(QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint())) 99 | 100 | x = nextX 101 | lineHeight = max(lineHeight, item.sizeHint().height()) 102 | 103 | return y + lineHeight - rect.y() 104 | 105 | 106 | if __name__ == '__main__': 107 | 108 | import sys 109 | 110 | app = QtGui.QApplication(sys.argv) 111 | mainWin = Window() 112 | mainWin.show() 113 | sys.exit(app.exec_()) 114 | -------------------------------------------------------------------------------- /modules/QQqt4/flowlayout.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/flowlayout.pyc -------------------------------------------------------------------------------- /modules/QQqt4/groupUserList.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/groupUserList.pyc -------------------------------------------------------------------------------- /modules/QQqt4/groupUserList_readme.md: -------------------------------------------------------------------------------- 1 | [TOC] 2 | 3 | 4 | # 需求 5 | - 基本的用户分组列表,类似QQ好友列表界面。主要支持如下操作: 6 | - 用户和组的增删改查操作。其中组名称不能重复,用户ID不能重复。 7 | - 界面右键单击的操作,右键选择用户可以执行修改、删除操作;右键选择组可以增加用户、修改组、删除组;右键选择空白地区可以弹出增加用户、组的操作。 8 | - 界面的拖放操作,可以将用户拖放到某个组实现移动操作。 9 | - 所涉及的列表控件可以添加到布局文件中,作为界面的嵌入使用(只需要继承到QWidget即可)。 10 | 11 | 12 | # 实现效果截图 13 | ![界面操作实例](ref/pic1.png "界面操作实例") ![界面操作实例](ref/pic2.png "界面操作实例") 14 | 15 | 16 | 17 | 18 | # 实现过程 19 | ## 1. 定义全局的默认参数 20 | ``` 21 | import os,sys 22 | from PyQt4.QtCore import * 23 | from PyQt4.QtGui import * 24 | 25 | DEFAULT_GROUP = u'undefined' 26 | DEFAULT_HEAD = u'icons/qq.png' 27 | DEFAULT_USER = u'new user' 28 | DEFAULT_NOTE = u'There is nothing to say...' 29 | ``` 30 | 31 | ## 2. LabelHead(QLabel) 32 | 33 | 34 | 主要是为了展示用户头像,但是在编辑用户头像的时候单击他要可以选择头像文件。因此增加了一个只读属性,当只读时单击不生效,可读时单击弹出图片选择框。 35 | 36 | 37 | ##3. LineEdit(QLineEdit) 38 | 39 | 40 | 主要是为了显示用户和组名称,因此在编辑用户和组名称时需要其为可以输入,其它时候为不可输入,因此继承到QLineEdit。通过其setStyleSheet设置只读和可读时的状态实现。QLineEdit默认有右键菜单,因此为了让其在只读时不影响列表右键菜单操作,重写其contextMenuEvent,可写时调用父类的即可。对于mousePressEvent以及mouseMoveEvent、mouseDoubleClickEvent(双击选中全部内容可以用于ctrl+c复制)同理。 41 | 42 | 43 | ## 4. 用户信息展示 44 | 用户信息展示的控件 **UserItem(界面操作)** 和用户列表控件 **UserListItem (列表逻辑操作)** 是两个相互关联的类。主要是互相调用实现界面和逻辑操作的关联。 45 | 46 | ### UserItem 界面操作 47 | 48 | 49 | 1. 主要就是用户信息(name,id,note,head)的编辑、保存以及获取,创建时其内部就维护一个 UserListItem 的实例 _listWidgetItem ,以UserListItem中实现逻辑操作函数的调用。 50 | > 注:group属性被当作逻辑管理需要的参数放到了UserListItem类中实现。 51 | 2. 用户信息(name,id,note,head)分别对应他们的显示控件,就是前面 [LabelHead(QLabel)](#LabelHead) 和 [LineEdit(QLineEdit)](#LineEdit),根据情况设置对应控件的字体等参数。 52 | 3. 用户信息(name,id,note,head)都保存在本类中,因此有getName和getNameInput函数的操作区别,也就是说将 **信息保存在本类中的一个优势就是可以选择接收或者放弃输入的内容,让其可以灵活控制子控件的输入和显示**。 53 | 4. 为了实现姓名后面显示ID的操作,在设置姓名控件内容的时候需要采用`_nameWidget.setText('%s (%d)' %(self._name,self._id))`的方法,但是需要注意的是这样做在editInfo编辑用户名称时需要将控件的文字设置为`_nameWidget.setText(self._name)`。 54 | 5. 信息的输入editInfo和锁定lockInfo操作需要是相互的。**允许输入后并不代表输入就会接收,因此复写keyPressEvent在回车键时确认输入,因为确认输入涉及到逻辑操作问题,调用其内的 _listWidgetItem 实现confirmInput**。 55 | 6. 右键菜单就是增加修改和删除操作,虽然绑定的槽函数目标不同,但是其本质上都是调用_listWidgetItem实现其操作的逻辑处理。 56 | 7. 为了让用户的显示控件可以拖动,复写mouseMoveEvent事件,设置拖拽内容为本控件。 57 | 58 | ### UserListItem 逻辑操作 59 | 60 | 61 | 1. 创建时就在内部维护一个 UserItem 控件实例_widget并锁定其信息,需要让其尺寸绑定`self.setSizeHint(self._widget.sizeHint())`。另外需要维护父 ListWidget 控件以便调用父类的更复杂逻辑操作函数。 62 | >由于id是唯一的,因此本类也维护了用户ID。 63 | 2. 其大部分操作都是调用其内的_widget控件实现,并根据需要设置本类的其它补充操作。比如修改用户名称是也修改本 QListWidgetItem 的文字(透明的`self.setTextColor(QColor(0x00,0x00,0x00,0x00))`并不影响显示)以便兼容原始的QListWidgetItem某些操作。 64 | 3. confirmInput操作和giveUpInput就是确认输入和放弃输入的操作,另外补充一个delSelfFromList调用父类removeUserItem的接口,实际上是因为UserItem没有绑定父类因此只能通过在其内部`delUser.triggered.connect(self._listWidgetItem.delSelfFromList)`实现转接。 65 | 66 | 67 | ## 5. 组信息展示 68 | 69 | 其逻辑和用户信息展示几乎相同,不同的地方是组可以展开和关闭,展开和关闭需要让其组下的用户显示和隐藏。其实现方式就是在GroupItem(QWidget,QObject)下定义一个expended信号,当单击组的展开图标时就发射信号到用户Item的setHidden,即`self._widget.expended.connect(uit.setHidden)`。 70 | > 1.需要注意用户移动必须删除在新建到新组下,否则原来的组expended依然绑定到该用户it会收到影响。 71 | > 2.将expended定义到GroupItem的原因是因为QListWidgetItem不能和QObject一起使用。无法定义静态信号。 72 | 73 | ### GroupItem 74 | 75 | 76 | 大部分实现思路和 [UserItem](#UserItem) 相似,不同之处主要是: 77 | 78 | 1. 内部的展开控件使用QPushButton以便绑定其clicked到组的toggleGroup,在其内设置展开和关闭的`setStyleSheet("border-image: url(icons/arrow_d.png);")`,并发射展开关闭信号expended。 79 | 2. 其右键增加了添加用户操作,主要就是调用 GroupListItem 的addNewUser逻辑操作。 80 | 3. **UserItem允许拖,GroupItem允许放,两者结合实现用户的拖放修改组功能**。主要支持拖放需要如下几步: 81 | - 被拖动的对象UserItem需要复写mouseMoveEvent判断鼠标按下左右键来通过drag = QDrag(self)发射拖动的内容drag.start(Qt.MoveAction); 82 | - 允许放入的对象GroupItem需要设置为self.setAcceptDrops(True); 83 | - 允许放入的对象GroupItem需要在dragEnterEvent中设置e.accept(),之后才能进入到dragMoveEvent和dropEvent事件实现操作。 84 | > 这里GroupItem在dragEnterEvent时通过`self._listWidgetItem.setSelected()`设置自己为选择状态;在dropEvent时通过e.source().getListItem()获取放入的uit并调用`self._listWidgetItem.moveUserIn(srcUit)`实现用户的移动操作。 85 | 86 | 87 | ### GroupListItem 88 | 89 | 90 | 组列表控件负责逻辑工作的实现,保存组内的用户uit,因此维护一个用户列表usrList用于获取用户uit。其它和[UserListItem](#UserListItem)几乎相似。主要不同的地方在于: 91 | 92 | 1. addUser 操作中将`self._widget.expended.connect(uit.setHidden)`绑定组展开信号和用户显示操作。 93 | 94 | 95 | ## 6. GroupUserList 96 | 97 | 98 | 主要的分组用户列表显示控件。包含增加组、增加用户等功能的实现。其使用方法参考[UsingGuide](#UsingGuide)。主要实现思路如下: 99 | 100 | 1. 在用户选择的Item切换时调用chooseItemChanged函数实现输入的放弃。在里面实现对previous对于的控件显示Item进行锁定lockInfo操作。控件内容的lockInfo的主要操作就是让其输入框都变为只读。 101 | > 对于自定义的LineEdit用于编辑信息的类,需要复写其mousePressEvent以便在父控件QListWidget中鼠标选择各个Item时单击在被只读的输入框上无法生效的问题。其实现方法是判断是只读状态则忽略事件,如果不是只读状态则调用父类的mousePressEvent处理事件。 102 | 2. 输入的确定在各个控件中按回车键确认,参考个控件的操作逻辑。本类也设置setAcceptDrops主要是为了拖动时比较好看些,但是没有实现具体的操作, **后期可以在dragMoveEvent中移动用户控件**。 103 | 3. 添加组时会判断组是否已存在,添加用户时判断是否存在其组,不存在会自动创建。*这里没有执行用户 ID重复的检查,需要自己判决。*用户的删除和组的删除都是根据给定的Item实现的,主要是几乎是界面操作,这样比较简单。 104 | 4. **moveUser 实现原理是先增加用户到新的组,在删除该用户**。 105 | 5. 复写了父类的insertItem和takeItem以便可以直接插入和删除自定义的Item。 106 | 107 | 108 | 109 | 110 | 111 | 112 | # 注意事项 113 | 114 | 1. 由于假设组名称唯一,因此所有删除组等操作都是在组名称基础上修改,而不是在组Item上修改。而用户名称不唯一,因此删除用户设置了可以在Item上修改,也可以基于用户ID修改(ID被假设唯一,但是这样的修改非常麻烦,还得导出找ID)。 115 | 2. 查看源码发现 QListWidgetItem 并不是继承至 QtGui 的控件, 因此不能直接在里面布局, 因此选择了扩展一个 自定义 QWidget 和一个 QListWidgetItem ,但是两者之间需要保证信息同步操作。 116 | 3. 为了让输入的字符都规范,在对几乎所有的输入文字都将其转换为unicode了。 117 | 4. 为了让ListWidget可以执行sort增加了好多复杂的工作在 ListWidgetItem 和自定义Item之间进行text同步(主要实现方法就是把所有关键字都保存在自定义Widget中,复写 ListWidgetItem 的获取都从自定义Widget中获取)。其实也可以复写自定义 ListWidgetItem 的大小判断操作符--参考官方参考文档。 118 | 5. 拖放操作的实现主要是在允许拖放的QWidget控件( GroupUserList 和 GroupItem )上设置setAcceptDrops(True),然后实现dragEnterEvent中e.accept并进行适当的处理,即可在dropEvent 和 dragMoveEvent 中实现对应的操作了。具体的操作就是:在UserItem中复写mouseMoveEvent左键按下时将本uit传递到drag参数中;在GroupUserList中值允许三个事件;在GroupItem的dragEnterEvent设置当前GroupListItem选中、dropEvent中将该用户uit添加到本组中。 119 | 120 | 121 | # undo 122 | 123 | 1. 增加查找和搜索用户功能增加。>>可以在使用的时候添加一个透明列表专门用于查询。 124 | 2. _动画效果的添加,最好是扩展一个动画类,用的时候根据性能和功能均衡选择一种。_ 125 | 126 | 127 | # GroupUserList 使用方法 128 | 129 | 130 | 1. GroupUserList 控件继承到 QListWidget ,可以当作 QWidget 添加到界面布局,也可以被作为主界面操作。 131 | 2. 用户和组的 **增加** : addUser 和 addGroup , 如果增加用户指定了ID则最好保证整个项目中一直都指定ID,而且ID必须是 int 数据。 132 | 3. 用户和组的 **删除** 建议在右键菜单中执行,主要是 removeUserItem 和 removeGroupItem 两个函数,需要输入所在的Item。也可以自己编写一个逻辑来找到用户和组所在的item,具体可以(常见的方法--组根据组名称删除, 用户根据用户ID删除举例): 133 | > a.组item的查找可以直接在 groupDict 中根据组名称返回gitem。 134 | b.用户item需要首先根据a调出各组gitem,然后根据gitem中的usrList判断是否存在相同ID的uitem,如果存在则删除之即可。 135 | 136 | 4. 用户和组的 **修改** :只需要按照3的思路找到用户所在的item,然后调用item的 editInfo 方法即可,编辑完成后输入回车就会保存所编辑的内容,选择其它Item则会放弃修改。其它修改方式自行编写, **建议先删除原来的uit然后重新adduser指定详细信息。** 137 | 5. 用户和组的 **查找** :参考3的思路,两步操作。 138 | 139 | 项目地址:https://github.com/HeLiangHIT/pyqtChat 140 | 博客地址:http://blog.csdn.net/u010151698 141 | 142 | 143 | 144 | # 参考网址 145 | 146 | 1. http://doc.qt.io/qt-4.8/qlineedit.html > qlineedit 的修改 147 | 2. http://doc.qt.io/qt-4.8/qdropevent.html 和 http://doc.qt.io/qt-4.8/qdrag.html > dropEvent 源的获取 148 | 3. http://doc.qt.io/qt-4.8/classes.html > QT 所有类列表 149 | 4. [QListWidget Class Reference](ref\QListWidget Class Reference.pdf) >查看详细的列表类函数(已高亮重点)。 150 | 5. [QListWidgetItem Class Reference](ref\QListWidgetItem Class Reference.pdf) >查看详细的列表Item类函数。 151 | 152 | 153 | -------------------------------------------------------------------------------- /modules/QQqt4/icons/arrow_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/arrow_d.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/arrow_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/arrow_r.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/chat.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/copy.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/delete.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/dictionary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/dictionary.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/edit.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/exp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/exp.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/expr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/expr.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/group.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/hd_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/hd_1.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/img.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/qq.png -------------------------------------------------------------------------------- /modules/QQqt4/icons/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/icons/user.png -------------------------------------------------------------------------------- /modules/QQqt4/init.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from PyQt4.Qt import * 3 | from PyQt4.QtGui import * 4 | from PyQt4.QtCore import * 5 | from pyqtChatApp import PyqtChatApp 6 | import re 7 | import sys, os 8 | sys.path.append('..') 9 | from OCR import Image2txt 10 | 11 | QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8")) 12 | 13 | 14 | class Backend(QThread): 15 | update_date = pyqtSignal(str, int) 16 | close_signal = pyqtSignal() 17 | def __init__(self, progess): 18 | super(Backend, self).__init__() 19 | self.progess = progess 20 | 21 | def run(self): 22 | Image_dir = '../OCR/img/' 23 | print(__file__) 24 | out = open('../OCR/biaoqing.txt', 'a') 25 | checked_info = open('../OCR/checked.info', 'a+') 26 | checked_info.seek(0) 27 | checked_filelist = checked_info.readlines() 28 | os.chdir(Image_dir) 29 | filenum = 0 30 | count = 0 31 | self.files = os.listdir() 32 | self.num = int(os.popen('ls -R | wc -w').read()) - int(os.popen('ls | wc -w').read()) 33 | self.progess.progressBar.setMaximum(self.num) 34 | for subdir in self.files: 35 | if not os.path.isdir(subdir): 36 | continue 37 | for filename in os.listdir(subdir): 38 | count += 1 39 | info = [] 40 | fulladdress = '/'.join((Image_dir ,subdir ,filename)) 41 | # print('filename: %s', fulladdress) 42 | #两种不会继续分析的情况,一种是在checked_info中存在,一种是后缀为.jpg 43 | if fulladdress + '\n' in checked_filelist : 44 | # print('%s 已存在', fulladdress) 45 | continue 46 | else : 47 | checked_info.write(fulladdress + '\n') 48 | if os.path.splitext(filename)[1] != '.jpg': 49 | continue 50 | info.extend([subdir, filename]) 51 | #试图对图片做OCR如果OCR结果是空字符或者发生错误都放弃OCR 52 | try: 53 | pic_ocr = Image2txt.picture_ocr(subdir +'/' + filename) 54 | txt = pic_ocr.get_crop_txt() 55 | # print('pre: %s', txt) 56 | txt = re.subn(r'[^\w\u4e00-\u9fa5]+','', txt)[0].strip() 57 | # print("after: %s", txt) 58 | info.append(txt) 59 | except AttributeError as e: 60 | continue 61 | if not txt: 62 | print('ocr failed %s', '放弃') 63 | info.append('放弃') 64 | continue 65 | write_string = txt + '#' + Image_dir + '/' + subdir + '/' + filename +'\n' 66 | # print(write_string) 67 | info = 'checking: ' + '\\'.join(info) 68 | print(info) 69 | self.update_date.emit(info, count) 70 | # self.detail.append(info) 71 | out.write(write_string) 72 | filenum += 1 73 | if filenum > 2: 74 | break 75 | self.update_date.emit('此文件夹下所有的图片已经OCR', self.num) 76 | out.close() 77 | checked_info.close() 78 | os.chdir('../../QQqt4') 79 | self.close_signal.emit() 80 | 81 | self.progess.close() 82 | 83 | class Progess(QDialog): 84 | 85 | def __init__(self, parent=None): 86 | super(Progess,self).__init__(parent) 87 | typeLabel=QLabel(self.tr("installing...")) 88 | self.btnSize = 35 89 | self.setFixedSize(700, 500) 90 | 91 | selectdir = QPushButton() 92 | selectdir.setStyleSheet("QPushButton{border-image:url(icons/dictionary.png);}"#这个参数可以让图片随大小缩放 93 | "QPushButton:hover{border: 2px groove blue;}" 94 | "QPushButton:pressed{border-style: inset;}") 95 | selectdir.setFixedSize(self.btnSize,self.btnSize) 96 | selectdir.clicked.connect(self.selectDir) 97 | 98 | self.line=QLineEdit('../OCR/img/') 99 | self.detail = QTextEdit('详细信息...') 100 | self.detail.setFont(QFont("Microsoft Yahei",13,QFont.Normal)) 101 | self.detail.NoWrap = True 102 | 103 | startPushButton=QPushButton(self.tr("开始")) 104 | startPushButton.setFont(QFont("Microsoft YaHei",15,QFont.Bold)) 105 | 106 | self.layout=QGridLayout() 107 | self.layout.addWidget(typeLabel,1,0) 108 | self.layout.addWidget(startPushButton,1,6) 109 | self.layout.addWidget(QLabel(self.tr("请选择表情所在文件夹")), 0, 0, 1, 3) 110 | self.layout.addWidget(selectdir,1, 5) 111 | self.layout.addWidget(self.line, 1, 0, 1, 5) 112 | # self.layout.addWidget(QLabel(self.tr("处理进度")), 3, 0) 113 | self.progressBar=QProgressBar() 114 | self.layout.addWidget(self.progressBar,2,0,1,7) 115 | self.progressBar.setMinimum(0) 116 | 117 | cursor = self.detail.textCursor() 118 | cursor.movePosition(QTextCursor.End) 119 | self.detail.setTextCursor(cursor) 120 | 121 | self.layout.setMargin(15) 122 | self.layout.setSpacing(10) 123 | self.layout.addWidget(self.detail, 3, 0, 1, 7) 124 | 125 | self.setLayout(self.layout) 126 | 127 | self.connect(startPushButton,SIGNAL("clicked()"),self.slotStart) 128 | self.b = Backend(self) 129 | 130 | def slotStart(self): 131 | global path 132 | path = str(self.line.text()) 133 | self.b.update_date.connect(self.update) 134 | self.b.start() 135 | # self.close() 136 | 137 | def update(self, txt, count): 138 | self.detail.append(txt) 139 | self.progressBar.setValue(count) 140 | 141 | def selectDir(self): 142 | # print ("OnClickmenuSetFileSaveDir") 143 | tmpDir = QFileDialog.getExistingDirectory() 144 | if(len(tmpDir) > 0): 145 | self.SaveDir = tmpDir 146 | self.line.setText(tmpDir) 147 | if not os.path.exists(self.SaveDir): 148 | os.mkdir(self.SaveDir) 149 | 150 | 151 | if __name__ == '__main__': 152 | path = os.getcwd() 153 | app=QApplication(sys.argv) 154 | progess=Progess() 155 | progess.show() 156 | app.exec_() 157 | 158 | pchat = PyqtChatApp(path) 159 | pchat.show() 160 | sys.exit(app.exec_()) 161 | -------------------------------------------------------------------------------- /modules/QQqt4/msgList.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/msgList.pyc -------------------------------------------------------------------------------- /modules/QQqt4/msgList_readme.md: -------------------------------------------------------------------------------- 1 | [TOC] 2 | 3 | 4 | # 需求 5 | 1. 实现类似PC端微信的聊天消息界面。 6 | 2. 为了学习使用只需要显示图片和文本,支持GIF图像显示,支持消息右键的复制和删除。图片双击可以在expleror中显示。 7 | 3. 消息框需要模拟气泡效果,消息列表需要包含头像。 8 | 9 | > 由于头像控件的操作和消息内容显示控件的操作差不多相似,因此就不再增加头像控件的右键和双击操作了。 10 | 11 | # 实现效果截图 12 | ![界面操作实例](ref/pic3.gif "界面操作实例") 13 | 14 | 15 | # 实现思路 16 | 1. 参考[groupUserList](https://github.com/HeLiangHIT/pyqtChat)的实现方式,主要是在一个QListWidget上显示多个消息控件,主要区别是: 17 | 2. 消息不需要可以拖放、不需要右键增删改查,只需要列举显示即可,因此这里继承的QListWidget只编写了两个方法就是addImageMsg和addTextMsg,分别实现文本和图像消息的添加。 18 | > 由于这里不需要增删改查功能,而只需要右键删除(和复制)因此直接把List实例和创建的QListWidgetItem实例传递保存到TextItem>BubbleText和ImageItem>BubbleImage自定义控件的实例里面---以便在消息的删除直接在里面调用List和ListItem实现删除`self.listView.takeItem(self.listView.indexFromItem(self.listItem).row())`。 19 | 3. 由于QListWidget默认鼠标滑过各个Item或者点击是都会产生不同的UI效果,而消息界面不需要这样的效果故参考[乌托邦大神的博客](http://blog.csdn.net/taiyang1987912/article/details/40979309)设置item的样式如下(为了让item不可选在addItem之后将其设置为不可选择状态it.setFlags(Qt.ItemIsEnabled)): 20 | ``` 21 | setStyleSheet( 22 | "QListWidget::item{border:0px solid gray;background-color:transparent;padding:0px;color:transparent}" 23 | "QListView::item:!enabled{background-color:transparent;color:transparent;border:0px solid gray;padding:0px 0px 0px 0px;}" 24 | "QListWidget::item:hover{background-color:transparent;color:transparent;border:0px solid gray;padding:0px 0px 0px 0px;}" 25 | "QListWidget::item:selected{background-color:transparent;color:transparent;border:0px solid gray;padding:0px 0px 0px 0px;}") 26 | ``` 27 | 4. 在消息和图像显示的自定义控件Item中使用一个QHBoxLayout显示消息,主要就是根据消息的左右来调整不同的添加控件顺序,采用QSpacerItem控制空白区域的自动缩放,该方案主要参考[stackoverflow](http://stackoverflow.com/questions/18047427/pyqt-sms-bubble-widget)上的方案。 28 | 5. 绘制气泡消息图像的控件BubbleImage为了支持GIF显示,采用一个QMovie类,将其frameChanged信号连接到自定义槽animate里面通过`self.setPixmap(self.movie.currentPixmap())`实现图片的动态更新。 29 | 6. **气泡的绘制**主要是限制其绘制区域,使用QPainter的drawPolygon绘制,drawPolygon的输入采用QPolygonF添加气泡的边角点路径,详细实现参考其paintEvent方法。为了保证鼠标在内部和在外部时有不同的颜色(主要是鼠标移入时颜色加深),需要在enterEvent和leaveEvent中设置不同的绘图颜色然后调用update刷新绘图。 30 | > 为了让实现显示的图片不会在super(BubbleImage, self).paintEvent(e)时和绘制的背景气泡冲突,设置控件的setContentsMargins绘图范围保证图像的绘图区域。 31 | 7. **文字的显示**主要是控件的大小调节,起初准备用QTextEdit后来发现实现起来很难控制大小和混动条!只能舍弃次用QLabel继承实现了,关于控件的水平大小采用控制字符数量的方法(ヘ(_ _ヘ)),考虑到一个中文字符的宽度大概是3倍英文字符因此出现了checkContainChinese和splitStringByLen函数(我也不记得哪儿抄来的方法了)。在输入调用super(BubbleText, self).__init__(myText)前就把字符用\n分割好来显示。 32 | 33 | 34 | # msgList 使用方法 35 | 36 | 1. GroupUserList 控件继承到 QListWidget ,可以当作 QWidget 添加到界面布局,也可以被作为主界面操作。 37 | 2. 文字消息和图像消息的添加调用addTextMsg和addImageMsg即可。删除在界面上操作,查找暂未实现---估计这里也不会实现了。 38 | 3. 添加其它消息类型...等什么时候闲得没妹子约了再说吧... 39 | 40 | 项目地址:https://github.com/HeLiangHIT/pyqtChat 41 | 博客地址:http://blog.csdn.net/u010151698 42 | 43 | -------------------------------------------------------------------------------- /modules/QQqt4/mycopygroupuserlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # @Date : 2016-12-08 10:56:55 4 | # @Author : He Liang (helianghit@foxmail.com) 5 | # @Link : https://github.com/HeLiangHIT 6 | 7 | import os,sys 8 | from PyQt4.QtCore import * 9 | from PyQt4.QtGui import * 10 | 11 | DEFAULT_GROUP = u'undefined' 12 | DEFAULT_HEAD = u'icons/qq.png' 13 | DEFAULT_USER = u'new user' 14 | DEFAULT_NOTE = u'' 15 | 16 | 17 | 18 | class LabelHead(QLabel): 19 | '''LabelHead(QLabel) 类主要是为了展示用户头像, 20 | 但是在编辑用户头像的时候单击他要可以选择头像文件。 21 | 因此增加了一个只读属性,当只读时单击不生效,可读时单击弹出图片选择框。''' 22 | def __init__(self,addr = DEFAULT_HEAD): 23 | super(LabelHead,self).__init__() 24 | self.setScaledContents(True) 25 | self.setReadOnly(True) 26 | self.setPicture(addr) 27 | 28 | def setReadOnly(self,b): 29 | self._readOnly = bool(b) 30 | 31 | def setPicture(self,addr): 32 | '''设置图像:继承至QLabel以便可以setPixmap设置图片''' 33 | self._picAddr = addr 34 | img = QPixmap(addr) 35 | self.setPixmap(img) 36 | return True 37 | 38 | def getPicture(self): 39 | return self._picAddr 40 | 41 | def mousePressEvent(self,e): 42 | '''只读时屏蔽其鼠标点击事件''' 43 | if self._readOnly: 44 | e.ignore() #忽略鼠标点击,传递到父对象中 45 | else: 46 | dialog = QFileDialog(self,u'请选择头像文件...') 47 | dialog.setDirectory(os.getcwd() + '/icons') #设置默认路径 48 | dialog.setNameFilter(u"图片文件(*.png *.jpg *.bmp *.ico);;")#中间一定要用两个分号才行! 49 | if dialog.exec_(): 50 | selectFileName = unicode(dialog.selectedFiles()[0]) 51 | self.setPicture(selectFileName) 52 | else: 53 | pass 54 | e.accept() #此时禁止该事件往下传递 55 | 56 | 57 | class LineEdit(QLineEdit): 58 | '''用户信息显示类:主要是支持可以编辑和不可以编辑''' 59 | def __init__(self,sz = None): 60 | super(LineEdit,self).__init__(sz)#父类输入文字内容 61 | self.setReadOnly(True) 62 | 63 | def setReadOnly(self,b): 64 | '''LineEdit(QLineEdit) 类主要是为了显示用户和组名称, 65 | 因此在编辑用户和组名称时需要其为可以输入,其它时候为不可输入, 66 | 因此继承到QLineEdit。通过其setStyleSheet设置只读和可读时的状态实现。''' 67 | if b: 68 | self._readOnly = True 69 | self.setStyleSheet("border-width:0;border-style:outset;background-color:rgba(0,0,0,0)") 70 | else: 71 | self._readOnly = False 72 | self.setStyleSheet("color:#000000") 73 | super(LineEdit,self).setReadOnly(self._readOnly) 74 | 75 | def contextMenuEvent(self,e): 76 | '''QLineEdit默认有右键菜单,因此为了让其在只读时不影响列表右键菜单操作, 77 | 重写其contextMenuEvent,可写时调用父类的即可''' 78 | if self._readOnly: 79 | e.ignore() #忽略右键菜单 80 | else: 81 | super(LineEdit,self).contextMenuEvent(e) 82 | 83 | def mousePressEvent(self,e): 84 | '''屏蔽其鼠标点击事件''' 85 | if self._readOnly: 86 | e.ignore() #屏蔽所有鼠标操作 87 | else: 88 | super(LineEdit,self).mousePressEvent(e) 89 | 90 | def mouseDoubleClickEvent(self,e): 91 | '''鼠标双击选择事件: 双击选中全部内容可以用于ctrl+c复制''' 92 | if self._readOnly: 93 | self.setSelection(0,self.maxLength())#双击时选中,可以ctrl+c 94 | e.ignore() #屏蔽所有鼠标操作 95 | else: 96 | super(LineEdit,self).mouseDoubleClickEvent(e) 97 | 98 | def mouseMoveEvent(self,e): 99 | '''鼠标移动事件''' 100 | if self._readOnly: 101 | e.ignore() #屏蔽所有鼠标操作 102 | else: 103 | super(LineEdit,self).mouseMoveEvent(e) 104 | 105 | 106 | class UserItem(QWidget): 107 | '''自定义的用户信息控件''' 108 | def __init__(self, listWidgetItem, usrId, **args): 109 | super(UserItem,self).__init__() 110 | 111 | self._listWidgetItem = listWidgetItem 112 | self._id = usrId 113 | 114 | self._headWidget = LabelHead() 115 | self._headWidget.setFixedSize(40, 40) 116 | self.setHead(args.get('head',DEFAULT_HEAD)) 117 | 118 | self._nameWidget = LineEdit() 119 | self._nameWidget.setFont(QFont("Microsoft YaHei",10,QFont.Bold)) 120 | self.setName(args.get('name',DEFAULT_USER)) 121 | 122 | self._noteWidget = LineEdit() 123 | self.setNote(args.get('note',DEFAULT_NOTE)) 124 | 125 | vbox = QVBoxLayout() 126 | vbox.addWidget(self._nameWidget) 127 | vbox.addWidget(self._noteWidget) 128 | vbox.addStretch() 129 | 130 | hbox = QHBoxLayout() 131 | hbox.addWidget(self._headWidget) 132 | hbox.addLayout(vbox) 133 | 134 | self.setLayout(hbox) 135 | 136 | def getListItem(self): 137 | return self._listWidgetItem 138 | 139 | def setName(self,name): 140 | self._name = name 141 | self._nameWidget.setText('%s' %(self._name)) 142 | self._nameWidget.setReadOnly(True) 143 | def getNameInput(self): 144 | return self._nameWidget.text() 145 | def getName(self): 146 | return self._name 147 | 148 | def setNote(self,note): 149 | self._note = note 150 | self._noteWidget.setText(self._note) 151 | self._noteWidget.setReadOnly(True) 152 | def getNoteInput(self): 153 | return self._noteWidget.text() 154 | def getNote(self): 155 | return self._note 156 | 157 | def setHead(self,head): 158 | self._head = head 159 | self._headWidget.setPicture(self._head) 160 | self._headWidget.setReadOnly(True) 161 | def getHead(self): 162 | return self._headWidget.getPicture() 163 | def getHeadInput(self): 164 | return self._headWidget.getPicture() 165 | 166 | def editInfo(self):#允许编辑用户信息 167 | self._nameWidget.setReadOnly(False) 168 | self._noteWidget.setReadOnly(False) 169 | self._headWidget.setReadOnly(False) 170 | self._nameWidget.setText(self._name) 171 | self._nameWidget.setFocus() 172 | 173 | def lockInfo(self):#锁定用户信息 174 | self._nameWidget.setReadOnly(True) 175 | self._noteWidget.setReadOnly(True) 176 | self._headWidget.setReadOnly(True) 177 | 178 | 179 | '''复写的父类方法''' 180 | def keyPressEvent(self,e): 181 | '''回车键确认输入内容''' 182 | if e.key() == Qt.Key_Return: 183 | self._listWidgetItem.confirmInput() 184 | 185 | def contextMenuEvent(self,e): 186 | '''右键菜单''' 187 | editUser = QAction(QIcon('icons/edit.png'),u'修改',self)#第一个参数也可以给一个QIcon图标 188 | editUser.triggered.connect(self.editInfo) 189 | 190 | delUser = QAction(QIcon('icons/delete.png'),u'删除',self) 191 | delUser.triggered.connect(self._listWidgetItem.delSelfFromList)#选中就会触发 192 | 193 | menu = QMenu() 194 | menu.addAction(editUser) 195 | menu.addAction(delUser) 196 | menu.exec_(QCursor.pos())#全局位置比较好,使用e.pos()还得转换 197 | 198 | e.accept() #禁止弹出菜单事件传递到父控件中 199 | 200 | 201 | def mouseMoveEvent(self, e): 202 | '''鼠标移动下的右键按住才有效''' 203 | if e.buttons() != Qt.LeftButton:#右键按住 204 | return e.ignore() 205 | mimeData = QMimeData()#生成拖动数据 206 | drag = QDrag(self)#拖动对象 207 | drag.setMimeData(mimeData)#设置拖动数据 208 | drag.setHotSpot(e.pos() - self.rect().topLeft())#左上角位置 209 | dropAction = drag.start(Qt.MoveAction)#开始拖动 210 | e.accept() 211 | 212 | 213 | class UserListItem(QListWidgetItem): 214 | '''用户信息列表控件''' 215 | def __init__(self, parent, usrId, name = DEFAULT_USER, 216 | head = DEFAULT_HEAD, note = DEFAULT_NOTE, 217 | group = DEFAULT_GROUP): 218 | super(UserListItem,self).__init__(None, None, QListWidgetItem.UserType)#parent给None才能正确的insertItem而不能addItem 219 | 220 | self._id = usrId 221 | self._group = group #这两个参数放在本类,其它参数放到子类 222 | self._parent = parent 223 | self._widget = UserItem(self,usrId,name = name, head = head, note = note) 224 | self._widget.lockInfo() 225 | 226 | self.setTextColor(QColor(0x00,0x00,0x00,0x00))#设置控件文字为透明色以便不干扰控件的显示 227 | self.setSizeHint(self._widget.sizeHint()) 228 | 229 | def getWidget(self): 230 | return self._widget 231 | def getId(self): 232 | return self._id 233 | 234 | def getId(self): 235 | return self._id 236 | 237 | def setGroup(self,group): 238 | self._group = unicode(group) 239 | self.setText(self._group + '_' + self.getNameInput())#同步更新一下 240 | print ('the group of user %s should be undated!'%self.getName()) 241 | def getGroup(self): 242 | return self._group 243 | 244 | def setName(self,name): 245 | self._widget.setName(name) 246 | self.setText(self._group + '_' + name)#同步更新一下 247 | def getNameInput(self): 248 | return self._widget.getNameInput() 249 | def getName(self): 250 | return self._widget.getName() 251 | 252 | def setNote(self,note): 253 | self._widget.setNote(note) 254 | def getNoteInput(self): 255 | return self._widget.getNoteInput() 256 | def getNote(self): 257 | return self._widget.getNote() 258 | 259 | def setHead(self,head): 260 | self._widget.setHead(head) 261 | def getHeadInput(self): 262 | return self._widget.getHeadInput() 263 | def getHead(self): 264 | return self._widget.getHead() 265 | 266 | def confirmInput(self):#确认输入,一定要有输入才能确认输入 267 | self.setName(self.getNameInput()) 268 | self.setNote(self.getNoteInput()) 269 | self.setHead(self.getHeadInput()) 270 | self._widget.lockInfo() 271 | 272 | def giveUpInput(self):#放弃输入 273 | self.setName(self.getName()) 274 | self.setNote(self.getNote()) 275 | self.setHead(self.getHead()) 276 | self._widget.lockInfo() 277 | 278 | def delSelfFromList(self): 279 | self._parent.removeUserItem(self) 280 | 281 | '''以下为复写的父控件方法''' 282 | 283 | 284 | class GroupItem(QWidget,QObject): 285 | """自定义的组信息控件""" 286 | expended = pyqtSignal(bool) #展开与否的信号 287 | def __init__(self, listWidgetItem, name = DEFAULT_GROUP): 288 | super(GroupItem, self).__init__() 289 | self.setAcceptDrops(True)#允许拖入 290 | 291 | self._listWidgetItem = listWidgetItem 292 | 293 | self._expendWidget = QPushButton() 294 | self._expendWidget.clicked.connect(self.toggleGroup) 295 | self._expendWidget.setFixedSize(10,10) 296 | self._isOpen = False 297 | self.toggleGroup() #设置为展开 298 | 299 | self._nameWidget = LineEdit() 300 | self._nameWidget.setFont(QFont("Times",10,QFont.Normal)) 301 | self.setName(name) 302 | 303 | hbox = QHBoxLayout() 304 | hbox.addWidget(self._expendWidget) 305 | hbox.addWidget(self._nameWidget) 306 | hbox.addStretch() 307 | 308 | self.setLayout(hbox) 309 | 310 | 311 | def setName(self,name): 312 | self._name = name 313 | self._nameWidget.setText('%s'%(name)) 314 | self._nameWidget.setReadOnly(True) 315 | def getNameInput(self): 316 | return self._nameWidget.text() 317 | def getName(self): 318 | return self._name 319 | 320 | def toggleGroup(self):#点击则展开和折叠 321 | self._isOpen = not self._isOpen 322 | if self._isOpen: 323 | self._expendWidget.setStyleSheet("border-image: url(icons/arrow_d.png);") 324 | else: 325 | self._expendWidget.setStyleSheet("border-image: url(icons/arrow_r.png);") 326 | self._expendWidget.update()#刷新该控件 327 | self.expended.emit(not self._isOpen)#发送信号,这里展开是不hidden,因此取非 328 | 329 | def editInfo(self):#允许编辑用户信息 330 | self._nameWidget.setReadOnly(False) 331 | self._nameWidget.setText(self._name) 332 | self._nameWidget.setFocus() 333 | 334 | def lockInfo(self):#锁定用户信息 335 | self._nameWidget.setReadOnly(True) 336 | 337 | '''复写的父类方法''' 338 | def keyPressEvent(self,e):#回车键确认输入内容 339 | if e.key() == Qt.Key_Return: 340 | self._listWidgetItem.confirmInput() 341 | 342 | def contextMenuEvent(self,e): #右键菜单 343 | adusr = QAction(QIcon('icons/user.png'),u'添加用户',self) 344 | adusr.triggered.connect(self._listWidgetItem.addNewUser) 345 | 346 | editGroup = QAction(QIcon('icons/edit.png'),u'修改',self) 347 | editGroup.triggered.connect(self.editInfo) 348 | 349 | delGroup = QAction(QIcon('icons/delete.png'),u'删除',self) 350 | delGroup.triggered.connect(self._listWidgetItem.delSelfFromList)#选中就会触发 351 | 352 | menu = QMenu() 353 | menu.addAction(adusr) 354 | menu.addAction(editGroup) 355 | menu.addAction(delGroup) 356 | menu.exec_(QCursor.pos())#全局位置比较好,使用e.pos()还得转换 357 | 358 | e.accept() #禁止弹出菜单事件传递到父控件中 359 | 360 | def dragEnterEvent(self, e): 361 | '''外部拖入事件允许,必须在这里accept后才能到dropEvent中确认放入!''' 362 | self._listWidgetItem.setSelected() 363 | e.accept() 364 | 365 | def dropEvent(self, e):#放入事件 366 | src = e.source() #获取目标控件 367 | srcUit = src.getListItem() 368 | self._listWidgetItem.moveUserIn(srcUit) 369 | e.accept() 370 | 371 | 372 | class GroupListItem(QListWidgetItem): 373 | '''用户信息列表控件''' 374 | 375 | def __init__(self, parent, name = DEFAULT_GROUP): 376 | super(GroupListItem,self).__init__(None, None,QListWidgetItem.UserType)#parent给None才能正确的insertItem而不能addItem 377 | 378 | self.usrList = []# 组里面的用户列表,用到全局会是静态的 379 | self._parent = parent 380 | self._widget = GroupItem(self,name = name) 381 | self._widget.lockInfo() 382 | 383 | self.setTextColor(QColor(0x00,0x00,0x00,0x00))#设置控件文字为透明色以便不干扰控件的显示 384 | self.setSizeHint(self._widget.sizeHint()) 385 | 386 | 387 | def getWidget(self): 388 | return self._widget 389 | 390 | def setName(self,name): 391 | self._widget.setName(name) 392 | self.setText(self.getName()) #同步更新 393 | def getNameInput(self): 394 | return self._widget.getNameInput() 395 | def getName(self): 396 | return self._widget.getName() 397 | 398 | 399 | def confirmInput(self):#确认输入 400 | self._parent.groupDict.pop(self.getName())#移除之前的Group键值对 401 | self.setName(self._widget.getNameInput()) 402 | self._parent.groupDict[self.getName()] = self#添加当前名字的Group键值对 403 | self._widget.lockInfo() 404 | 405 | def giveUpInput(self):#放弃输入 406 | self.setName(self.getName()) 407 | self._widget.lockInfo() 408 | 409 | def delSelfFromList(self): 410 | self._parent.removeGroupItem(self) 411 | 412 | @pyqtSlot() 413 | def addNewUser(self): 414 | (ok,uit,git) = self._parent.addUser(group = self.getName())#调用父类的添加用户,但是添加到本组下 415 | self._parent.setCurrentItem(uit)#选中当前增加的用户,这一步很关键。 416 | # 这样的另一个好处是执行一次item切换,保证之前输入的放弃操作--输入失焦。 417 | uit.getWidget().editInfo()#允许可以编辑 418 | 419 | def addUser(self,uit): 420 | self.usrList.append(uit) 421 | self._widget.expended.connect(uit.setHidden) 422 | self.setName(self.getName())#为了刷新显示用户数量 423 | 424 | def delUser(self, uit): 425 | self.usrList.pop(self.usrList.index(uit)) 426 | self.setName(self.getName())#为了刷新显示用户数量 427 | 428 | def moveUserIn(self,uit):#调用父类的方法移动用户 429 | self._parent.moveUser(uit,self.getName()) 430 | def setSelected(self): 431 | self._parent.setItemSelected(self,True) 432 | 433 | '''以下为复写的父控件方法''' 434 | 435 | 436 | 437 | 438 | 439 | class GroupUserList(QListWidget): 440 | '''实现好友分组列表的效果''' 441 | groupDict = {} 442 | def __init__(self, parent = None): 443 | self.msglist = None 444 | super(GroupUserList,self).__init__(parent) 445 | self.currentItemChanged.connect(self.chooseItemChanged) 446 | self.setAcceptDrops(True) 447 | self.setObjectName('usrlist') 448 | 449 | def addGroup(self, name = DEFAULT_GROUP): 450 | '''判断是否已存在并添加组''' 451 | # name = unicode(name) 452 | groupNames = self.groupDict.keys() 453 | # print name, groupNames 454 | if name not in groupNames:#不存在则创建该keys 455 | git = GroupListItem(self,name) 456 | index = self.count() + 1 457 | self.insertItem(index,git) 458 | self.groupDict[name] = git #保存GroupItem对象到全局groupDict里面用于 459 | return (True, git) 460 | else: 461 | git = self.groupDict[name] 462 | return (False, git) 463 | 464 | _currentId = 1 #用户ID从1递增 465 | def addUser(self, name = DEFAULT_USER, head = DEFAULT_HEAD,note = DEFAULT_NOTE,group = DEFAULT_GROUP,uId = None): 466 | '''添加用户''' 467 | (isExist, git) = self.addGroup(group)#判断组是否存在并增加组 468 | index = self.indexFromItem(git).row()#查找组存在的index 469 | 470 | if uId:#指定ID 471 | uId = int(uId) 472 | uit = UserListItem(self,uId,name,head,note,group) 473 | else:#未指定ID 474 | uit = UserListItem(self,self._currentId,name,head,note,group) 475 | self._currentId += 1 #ID依次增加,保证每个用户有一个唯一的标志符 476 | 477 | self.insertItem(index+1,uit) 478 | git.addUser(uit) 479 | # print uit.getName(),uit.getGroup(),uit.getId() 480 | return (True,uit,git)#返回增加的用户和其组 481 | 482 | def removeUserItem(self,uit): 483 | '''移除用户Item''' 484 | git = self.groupDict[uit.getGroup()] 485 | git.delUser(uit)#用户对应的组下的uit列表需要删除该用户 486 | self.takeItem(uit) 487 | del uit 488 | 489 | def removeGroupItem(self,git): 490 | '''移除组Item,其下的用户移动到默认分组''' 491 | gName = git.getName() 492 | if gName == DEFAULT_GROUP: 493 | print ("Group %s can't be deleted!"%(gName)) 494 | return False 495 | for uit in git.usrList: 496 | self.addUser(name = uit.getName(),head = uit.getHead(), 497 | note = uit.getNote(),uId = uit.getId())#分组为默认 498 | self.takeItem(uit) 499 | # git.delUser(uit) #这样执行后usrList改变会导致for循环出错,最终都会少出git所以这里不用移除它就好了 500 | del uit 501 | 502 | self.takeItem(git) 503 | self.groupDict.pop(git.getName()) 504 | del git 505 | 506 | def moveUser(self, uit, group = DEFAULT_GROUP): 507 | '''移动用户到组,就是原组中删除该用户,然后新组中添加该用户''' 508 | self.addUser(name = uit.getName(),head = uit.getHead(), 509 | note = uit.getNote(),uId = uit.getId(),group = group)#分组指定 510 | self.removeUserItem(uit) 511 | 512 | @pyqtSlot(QListWidgetItem,QListWidgetItem)#Item选择变化 513 | def chooseItemChanged(self,curit,preit): 514 | if preit:#存在则锁住,第一个点击的选项会不存在 515 | preit.giveUpInput() #放弃输入,因为没有单击回车确认输入 516 | _gIndex = 1 #组编号递增参数 517 | 518 | @pyqtSlot(bool)#右键增加组菜单 519 | def slotAddGroup(self,b): 520 | group = u'%s_%d'%(DEFAULT_GROUP,self._gIndex) 521 | self._gIndex += 1 522 | (ok,git) = self.addGroup(group) 523 | self.setCurrentItem(git)#选中当前增加的组,这一步很关键。 524 | # 这样的另一个好处是执行一次item切换,保证之前输入的放弃操作--输入失焦。 525 | git.getWidget().editInfo()#允许可以编辑 526 | 527 | @pyqtSlot(bool)#右键增加用户菜单 528 | def slotAddUser(self,b): 529 | (ok,uit,git) = self.addUser()#默认用户名信息就行了 530 | self.setCurrentItem(uit)#选中当前增加的用户,这一步很关键。 531 | # 这样的另一个好处是执行一次item切换,保证之前输入的放弃操作--输入失焦。 532 | uit.getWidget().editInfo()#允许可以编辑 533 | 534 | '''复写的父类方法''' 535 | def insertItem(self,index,it): 536 | super(GroupUserList,self).insertItem(index,it) 537 | if isinstance(it,GroupListItem) or isinstance(it,UserListItem): 538 | self.setItemWidget(it,it.getWidget()) 539 | 540 | def takeItem(self,it): 541 | '''父类是根据index删除,不实用''' 542 | if isinstance(it,int):#父类兼容 543 | return super(GroupUserList,self).takeItem(index) 544 | else: #根据item删除,增加的功能 545 | index = self.indexFromItem(it).row() 546 | return super(GroupUserList,self).takeItem(index) 547 | 548 | def contextMenuEvent(self,e): 549 | '''右键菜单''' 550 | adgrp = QAction(QIcon('icons/group.png'),u'增加组',self)#第一个参数也可以给一个QIcon图标 551 | adgrp.triggered.connect(self.slotAddGroup) 552 | 553 | adusr = QAction(QIcon('icons/user.png'),u'增加用户',self) 554 | adusr.triggered.connect(self.slotAddUser)#选中就会触发 555 | 556 | menu = QMenu() 557 | menu.addAction(adgrp) 558 | menu.addAction(adusr) 559 | menu.exec_(QCursor.pos())#全局位置比较好,使用e.pos()还得转换 560 | 561 | e.accept() #禁止弹出菜单事件传递到父控件中 562 | 563 | def dragEnterEvent(self, e):#外部拖入事件允许 564 | # print e.pos()#获取鼠标位置 565 | e.accept() 566 | def dragMoveEvent(self,e): #鼠标内部拖动事件 567 | # print e.pos()#获取鼠标位置 568 | e.accept() 569 | def dropEvent(self, e):#放入事件 570 | # print e.pos() 571 | e.accept() 572 | 573 | def mouseReleaseEvent(self, event): 574 | if self.msglist: 575 | if self.msglist.expcalling == True: 576 | self.msglist.mywindow.close() 577 | self.msglist.expcalling = False 578 | if self.msglist.bestexpcalling == True: 579 | self.msglist.bestwindow.close() 580 | self.msglist.expcalling == False 581 | 582 | 583 | if __name__=='__main__': 584 | app = QApplication(sys.argv) 585 | ul=GroupUserList() 586 | ul.setMinimumSize(200,500) 587 | 588 | ul.addUser('hello') 589 | ul.addUser('world') 590 | ul.addGroup('group') 591 | ul.addUser('HeLiang',group = 'group') 592 | ul.addGroup(u'team') 593 | ul.addUser(u'甜心吉吉',group = u'team') 594 | 595 | ul.show() 596 | sys.exit(app.exec_()) 597 | -------------------------------------------------------------------------------- /modules/QQqt4/mycopymsglist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # @Date : 2016-12-08 10:56:55 4 | # @Author : He Liang (helianghit@foxmail.com) 5 | # @Link : https://github.com/HeLiangHIT 6 | 7 | import os, sys, time, re 8 | from PyQt4.QtCore import * 9 | from PyQt4.QtGui import * 10 | from math import * 11 | from exptable import Window 12 | import imghdr 13 | from bestexplist import BestWindow 14 | sys.path.append('..') 15 | from DL import maxSim 16 | from OCR import Image2txt 17 | 18 | 19 | DEFAULT_HEAD = 'icons/qq.png' 20 | DEFAULT_MSG = 'Hello is there anyone?' 21 | DEFAULT_IMG = 'icons/img.png' 22 | 23 | def checkContainChinese(s):#判断是否为英文 24 | for ch in s: 25 | if u'\u4e00' <= ch <= u'\u9fff': 26 | return True 27 | return False 28 | 29 | def splitStringByLen(text,Len):#其中使用\n分割,因此原来的\n将会被替换,一个中文大致顶三个英文的宽度 30 | # reload(sys) #暂时用 31 | # sys.setdefaultencoding('utf-8') 32 | text = text.replace('\n','.') 33 | (myText, nLen) = ('',0) 34 | for s in text: 35 | myText += s 36 | nLen += 3 if checkContainChinese(s) else 1 37 | if nLen >= (Len - 1): 38 | myText += '\n' 39 | nLen = 0 40 | return myText 41 | 42 | 43 | class NoticeWindow(QWidget): 44 | 45 | def __init__(self, txt, listView, ): 46 | 47 | super(NoticeWindow, self).__init__() 48 | self.resize(770, 60) 49 | self.setWindowFlags(Qt.FramelessWindowHint) 50 | self.setAttribute(Qt.WA_TranslucentBackground) 51 | self.setStyleSheet("QScrollBar{width:0;height:0}") 52 | lo = QGridLayout() 53 | self.label = QLabel(txt) 54 | self.label.setFont(QFont("Microsoft Yahei",15,QFont.Bold)) 55 | lo.addWidget(self.label) 56 | self.setLayout(lo) 57 | self.move(listView.x()+270, listView.y()+590) 58 | self.setStyleSheet( 59 | "QLabel{background: red;color: white;border-width: 2px; border-style: solid;border-color: red;border-radius:2px}") 60 | 61 | 62 | class BubbleText(QLabel): 63 | """**文字的显示**主要是控件的大小调节, 64 | 起初准备用QTextEdit后来发现实现起来很难控制大小和混动条! 65 | 只能舍弃次用QLabel继承实现了,关于控件的水平大小采用控制字符数量的方法(ヘ(_ _ヘ)), 66 | 考虑到一个中文字符的宽度大概是3倍英文字符因此出现了checkContainChinese和splitStringByLen函数 67 | (我也不记得哪儿抄来的方法了)。在输入调用super(BubbleText, self).__init__(myText) 68 | 前就把字符用\n分割好来显示""" 69 | border = 5 70 | trigon = 20 71 | lineLen = 40 #每行的文字数量 72 | 73 | minH = 2 * trigon + 2 * border 74 | minW = 2 * trigon + 2 * border 75 | 76 | def __init__(self,listItem,listView,text = DEFAULT_MSG,lr = True): 77 | self.listItem = listItem 78 | self.listView = listView 79 | self.text = text 80 | #字符串长度限制 81 | myText = splitStringByLen(text, self.lineLen) # 文字分割 82 | 83 | super(BubbleText, self).__init__(myText) 84 | 85 | self.setMinimumWidth(self.minW) 86 | self.setFont(QFont("Microsoft Yahei",15,QFont.Normal)) 87 | # self.setStyleSheet("QLabel:hover{background-color:rgba(210,240,250,255);}")#鼠标滑过的颜色设置,这样自定义的paintEvent绘图区域就被看穿了 88 | self.setState(False)#设置鼠标不进入状态,方便绘图区域的颜色更新 89 | 90 | self.lr = lr #标志绘制左还是右 91 | if self.lr: 92 | '''为了让实现显示的图片不会在super(BubbleImage, self).paintEvent(e)时和绘制的背景气泡冲突, 93 | 设置控件的setContentsMargins绘图范围保证图像的绘图区域。''' 94 | self.setContentsMargins(self.trigon*sqrt(3)/2 + 3,self.border + 3,self.border + 3,self.border + 3) 95 | else: 96 | self.setContentsMargins(self.border + 3,self.border + 3,self.trigon*sqrt(3)/2 + 3,self.border + 3) 97 | self.setStyleSheet("color: #FFFFFF") 98 | 99 | def paintEvent(self, e): 100 | size = self.size() 101 | qp = QPainter() 102 | qp.begin(self) 103 | if self.lr: 104 | self.leftBubble(qp,size.width(),size.height()) 105 | else: 106 | self.rightBubble(qp,size.width(),size.height()) 107 | qp.end() 108 | super(BubbleText, self).paintEvent(e) 109 | 110 | def leftBubble(self,qp, w, h): 111 | qp.setPen(self.colorLeftE)#设置画笔颜色,绘制的矩形边缘颜色 112 | qp.setBrush(self.colorLeftM)#设置红色的笔刷 113 | middle = h/2 114 | shifty = self.trigon/2 115 | shiftx = self.trigon*sqrt(3)/2 116 | pL = QPolygonF() 117 | pL.append(QPointF(0,middle)) #起始点 118 | pL.append(QPointF(shiftx, middle + shifty)) # 第二点 119 | pL.append(QPointF(shiftx, h - self.border)) #第三点 120 | pL.append(QPointF(w - self.border, h - self.border)) #第四点 121 | pL.append(QPointF(w - self.border, self.border)) #第五点 122 | pL.append(QPointF(shiftx, self.border)) #第六点 123 | pL.append(QPointF(shiftx, middle - shifty)) #第七点 124 | qp.drawPolygon(pL) 125 | 126 | def rightBubble(self, qp, w, h): 127 | qp.setPen(self.colorRightE)#设置画笔颜色,绘制的矩形边缘颜色 128 | qp.setBrush(self.colorRightM)#设置红色的笔刷 129 | middle = h/2 130 | shifty = self.trigon/2 131 | shiftx = self.trigon*sqrt(3)/2 132 | pL = QPolygonF() 133 | pL.append(QPointF(w,middle)) #起始点 134 | pL.append(QPointF(w - shiftx, middle + shifty)) # 第二点 135 | pL.append(QPointF(w - shiftx, h - self.border)) #第三点 136 | pL.append(QPointF(self.border, h - self.border)) #第四点 137 | pL.append(QPointF(self.border, self.border)) #第五点 138 | pL.append(QPointF(w - shiftx, self.border)) #第六点 139 | pL.append(QPointF(w - shiftx, middle - shifty)) #第七点 140 | qp.drawPolygon(pL) 141 | 142 | def setState(self,mouse): 143 | '''鼠标进入和鼠标出时需要显示不一样的效果,主要就是更新颜色变量,然后调用update更新重绘''' 144 | if mouse:#鼠标进入 145 | self.colorLeftM = QColor("#FCF8F8") 146 | self.colorLeftE = QColor("#FCF8F8") 147 | self.colorRightM = QColor("#0761F4") 148 | self.colorRightE = QColor("#0761F4") 149 | else: 150 | self.colorLeftM = QColor("#FFFFFF") 151 | self.colorLeftE = QColor("#FFFFFF") 152 | self.colorRightM = QColor("#3526F7") 153 | self.colorRightE = QColor("#3526F7") 154 | self.update() #更新界面,不用执行也可以更新,但是不实时 155 | 156 | def enterEvent(self,e): 157 | # print 'mouse entered' 158 | self.setState(True) 159 | def leaveEvent(self,e): 160 | # print 'mouse leaved' 161 | self.setState(False) 162 | 163 | def contextMenuEvent(self,e): 164 | ''' 右键菜单实现文本的复制和控件的删除''' 165 | editUser = QAction(QIcon('icons/copy.png'),u'复制',self)#第一个参数也可以给一个QIcon图标 166 | editUser.triggered.connect(self.copyText) 167 | 168 | delUser = QAction(QIcon('icons/delete.png'),u'删除',self) 169 | delUser.triggered.connect(self.delTextItem)#选中就会触发 170 | 171 | menu = QMenu() 172 | menu.addAction(editUser) 173 | menu.addAction(delUser) 174 | menu.exec_(QCursor.pos())#全局位置比较好,使用e.pos()还得转换 175 | 176 | e.accept() #禁止弹出菜单事件传递到父控件中 177 | 178 | def copyText(self,b): 179 | # print 'msg copyed' 180 | cb = QApplication.clipboard() 181 | cb.setText(self.text) 182 | def delTextItem(self,b): 183 | # print 'msg deleted' 184 | self.listView.takeItem(self.listView.indexFromItem(self.listItem).row()) 185 | 186 | class LabelHead(QLabel): 187 | '''LabelHead(QLabel) 类主要是为了展示用户头像''' 188 | def __init__(self,addr = DEFAULT_HEAD): 189 | super(LabelHead,self).__init__() 190 | self.setScaledContents(True) 191 | self.setReadOnly(True) 192 | self.setPicture(addr) 193 | 194 | def setReadOnly(self,b): 195 | self._readOnly = bool(b) 196 | 197 | def setPicture(self,addr): 198 | '''设置图像:继承至QLabel以便可以setPixmap设置图片''' 199 | self._picAddr = addr 200 | img = QPixmap(addr) 201 | self.setPixmap(img) 202 | return True 203 | 204 | def getPicture(self): 205 | return self._picAddr 206 | 207 | # ref : http://stackoverflow.com/questions/18047427/pyqt-sms-bubble-widget 208 | class TextItem(QWidget): 209 | '''显示文字的Widget内容,为了让消息可以删除增加listItem和list传递到文本控件''' 210 | def __init__(self, listItem, listView, text = DEFAULT_MSG, lr=True, head = DEFAULT_HEAD): 211 | super(TextItem,self).__init__() 212 | hbox = QHBoxLayout() 213 | text = BubbleText(listItem,listView,text,lr) 214 | head = LabelHead(head) 215 | head.setFixedSize(50,50) 216 | 217 | if lr is not True: 218 | hbox.addSpacerItem(QSpacerItem(1,1,QSizePolicy.Expanding,QSizePolicy.Preferred)) 219 | hbox.addWidget(text) 220 | hbox.addWidget(head) 221 | else: 222 | hbox.addWidget(head) 223 | hbox.addWidget(text) 224 | hbox.addSpacerItem(QSpacerItem(1,1,QSizePolicy.Expanding,QSizePolicy.Preferred)) 225 | 226 | hbox.setContentsMargins(0,0,0,0) 227 | self.setLayout(hbox) 228 | self.setContentsMargins(0,0,0,0) 229 | 230 | 231 | class BubbleImage(QLabel): 232 | """绘制背景气泡的控件""" 233 | border = 5 234 | trigon = 20 235 | lineLen = 40 #每行的文字数量 236 | 237 | minH = 2 * trigon + 2 * border 238 | minW = 2 * trigon + 2 * border 239 | 240 | def __init__(self,listItem,listView,path=os.getcwd(),img = DEFAULT_IMG,lr = True,maxWidth = 500):#图片显示的最长宽度 241 | self.listItem = listItem 242 | self.listView = listView 243 | self.img = img 244 | self.path = path 245 | super(BubbleImage, self).__init__() 246 | 247 | self.setMinimumWidth(self.minW) 248 | # self.setStyleSheet("QLabel:hover{background-color:rgba(210,240,250,255);}")#鼠标滑过的颜色设置,这样自定义的paintEvent绘图区域就被看穿了 249 | self.setState(False)#设置鼠标不进入状态,方便绘图区域的颜色更新 250 | 251 | self.lr = lr #标志绘制左还是右 252 | if self.lr: 253 | self.setContentsMargins(self.trigon*sqrt(3)/2 + 3,self.border + 3,self.border + 3,self.border + 3) 254 | else: 255 | self.setContentsMargins(self.border + 3,self.border + 3,self.trigon*sqrt(3)/2 + 3,self.border + 3) 256 | 257 | self.setScaledContents(True) 258 | if not os.path.exists(img): 259 | img = DEFAULT_IMG 260 | 261 | pic = QPixmap(img) 262 | self.wid = pic.size().width() if pic.size().width()0: 132 | self.textEntered.emit(txt) 133 | self.textEdit.clear() 134 | 135 | def selectImg(self): 136 | if self.msglist.expcalling == True: 137 | self.msglist.mywindow.close() 138 | self.msglist.expcalling == False 139 | if self.msglist.bestexpcalling == True: 140 | self.msglist.bestwindow.close() 141 | self.msglist.expcalling == False 142 | txt = self.textEdit.toPlainText() 143 | if len(txt)>0: 144 | self.msglist.selectImage(txt) 145 | 146 | 147 | class Back(QThread): 148 | send_signal = pyqtSignal(str) 149 | def __init__(self, txt, robot): 150 | super(Back, self).__init__() 151 | self.txt = txt 152 | self.robot = robot 153 | 154 | def run(self): 155 | self.send_signal.emit(str(self.robot.get_response(self.txt))) 156 | 157 | 158 | class PyqtChatApp(QSplitter): 159 | """聊天界面,QSplitter用于让界面可以鼠标拖动调节""" 160 | curUser = {'id':None,'name':None,'head':DEFAULT_HEAD} 161 | selfHead = DEFAULT_HEAD 162 | def __init__(self, path = os.getcwd()): 163 | super(PyqtChatApp, self).__init__(Qt.Horizontal) 164 | 165 | self.setWindowTitle('pyChat') # window标题 166 | self.setWindowIcon(QIcon('icons/chat.png')) #ICON 167 | self.setMinimumSize(1000,800) # 窗口最小大小 168 | 169 | self.ursList = GroupUserList() 170 | self.ursList.setMaximumWidth(250) 171 | self.ursList.setMinimumWidth(180) 172 | self.ursList.itemDoubleClicked.connect(self.setChatUser) 173 | self.msgList = MsgList(path) 174 | self.msgList.setStyleSheet("background-color: #F6F4F9") 175 | self.msgList.setDisabled(True) #刚打开时没有聊天显示内容才对 176 | self.ursList.msglist = self.msgList 177 | self.msgInput = MsgInput(self.msgList) 178 | self.msgInput.textEntered.connect(self.sendTextMsg) 179 | self.msgInput.imgEntered.connect(self.sendImgMsg) 180 | # self.msgInput.textEdit.textChanged.connect(self.msgList.selectImage) 181 | 182 | self.ursList.setParent(self) 183 | rSpliter = QSplitter(Qt.Vertical, self) 184 | self.msgList.setParent(rSpliter) 185 | self.msgInput.setParent(rSpliter) 186 | 187 | self.chatbot = ChatBot("myBot", read_only = True, storage_adapter="chatterbot.storage.JsonFileStorageAdapter") 188 | self.chatbot.set_trainer(ChatterBotCorpusTrainer) 189 | self.chatbot.train("chatterbot.corpus.chinese") 190 | 191 | self.setDemoUser() #模拟添加用户 192 | 193 | def setDemoMsg(self): 194 | self.msgList.clear() 195 | self.msgList.addTextMsg("Hello",True,self.curUser['head']) 196 | self.msgList.addTextMsg("World!",False,self.selfHead) 197 | self.msgList.addTextMsg(u"昨夜小楼又东风,春心泛秋意上心头,恰似故人远来载乡愁,今夜月稀掩朦胧,低声叹呢喃望星空,恰似回首终究一场梦,轻轻叹哀怨...",True,self.curUser['head']) 198 | self.msgList.addTextMsg(u"With a gentle look on her face, she paused and said,她脸上带着温柔的表情,稍稍停顿了一下,便开始讲话",False,self.selfHead) 199 | self.msgList.addImageMsg('ref/bq.gif',True,self.curUser['head']) 200 | # self.msgList.addImageMsg('ref/mt.gif',False,self.selfHead) 201 | 202 | def setDemoUser(self): 203 | self.ursList.clear() 204 | self.ursList.addUser('hello world') 205 | self.ursList.addUser('表情包助手') 206 | self.ursList.addGroup('group') 207 | self.ursList.addUser('思吉吉',group = 'group') 208 | self.ursList.addGroup(u'中文') 209 | self.ursList.addUser(u'田心吉吉',group = u'中文',head = 'icons/hd_1.png') 210 | 211 | 212 | def mousePressEvent(self, event): 213 | if self.msgList.expcalling == True: 214 | self.msgList.mywindow.close() 215 | self.msgList.expcalling = False 216 | if self.msgList.bestexpcalling == True: 217 | self.msgList.bestwindow.close() 218 | self.msgList.bestexpcalling == False 219 | 220 | 221 | @pyqtSlot(str) 222 | def sendTextMsg(self,txt): 223 | # txt = unicode(txt) 224 | self.msgList.addTextMsg(txt,False) 225 | if self.curUser['name'] == '表情包助手': 226 | print(1) 227 | self.imgget = backEnd(txt) 228 | self.imgget.start() 229 | self.imgget.finish_signal.connect(self.msgList.addImageMsg) 230 | else: 231 | self.robotstart = Back(txt, self.chatbot) 232 | self.robotstart.start() 233 | self.robotstart.send_signal.connect(self.robotSend) 234 | # self.msgList.addTextMsg(str(self.chatbot.get_response(txt)), True, self.curUser['head']) 235 | 236 | def robotSend(self, txt): 237 | self.msgList.addTextMsg(txt, True, self.curUser['head']) 238 | 239 | @pyqtSlot(str) 240 | def sendImgMsg(self,img): 241 | # img = unicode(img) 242 | self.msgList.addImageMsg(img,False) 243 | 244 | @pyqtSlot(QListWidgetItem) 245 | def setChatUser(self,item): 246 | (self.curUser['id'],self.curUser['name'],self.curUser['head']) = (item.getId(),item.getName(),item.getHead()) 247 | self.msgList.setDisabled(False) 248 | self.setWindowTitle('pyChat: chating with %s...'% self.curUser['name']) 249 | self.setDemoMsg() 250 | 251 | def closeEvent(self, event): 252 | if self.msgList.expcalling == True: 253 | self.msgList.mywindow.close() 254 | 255 | if self.msgList.bestexpcalling == True: 256 | self.msgList.bestwindow.close() 257 | 258 | os.system('rm ../OCR/tempimg/*') 259 | 260 | 261 | if __name__=='__main__': 262 | app = QApplication(sys.argv) 263 | pchat = PyqtChatApp('../OCR/img/') 264 | pchat.show() 265 | sys.exit(app.exec_()) 266 | -------------------------------------------------------------------------------- /modules/QQqt4/pyqtChatApp_readme.md: -------------------------------------------------------------------------------- 1 | [TOC] 2 | 3 | 4 | 5 | # 需求 6 | 7 | 1. 实现聊天界面的综合,主要是包含好友列表、聊天窗口和输入窗口。 8 | 2. 包含图片收发按钮,发送可以按ctrl+回车,双击好友和其聊天。 9 | 10 | 11 | # 实现效果 12 | 13 | ![界面操作实例](ref/pic4.png "界面操作实例") 14 | 15 | # 实现思路 16 | 17 | 1. 好友列表([groupUserList](groupUserList_readme.md))和消息列表([msgList](msgList_readme.md))都在前面实现好了,这里直接调用即可。 18 | 2. 输入列表需要一个简单的QTextEdit即可,但是为了支持ctrl+return发送消息,还是简单的继承并复写了keyPressEvent事件,然后判断`(e.key() == Qt.Key_Return) and (e.modifiers() == Qt.ControlModifier)`即按下ctrl+enter时发送消息并清空内容。 19 | 3. 消息输入控件MsgInput还需要一个可以输入图片的按钮,和后期可能增加的其它文件、表情等,因此调用了系统的demo里面的一个flowlayout类实现控件的从左到右自动排列放置图片按钮和发送按钮。并在各自的按钮上输出两个信号,textEntered发射输入文字,imgEntered发射输入图片。 20 | >其中图片按钮采用setStyleSheet设置其border-image即可实现显示图片效果。为了让其鼠标滑过时效果不同设置如下样式:`setStyleSheet("QPushButton{border-image:url(icons/img.png);}""QPushButton:hover{border: 2px groove blue;}""QPushButton:pressed{border-style: inset;}")` 21 | 4. 为了在界面上可以手动调节,将主界面继承到QSplitter,设置合理的添加位置保证控件的区域即可。将MsgInput中发射的信号绑定到本例的槽函数调用msgList实例添加消息。 22 | ~~5. 为了双击用户可以设置聊天对象,因此修改groupUserList里面的UserItem在mouseDoubleClickEvent时发射doubleClicked信号 -> 在UserListItem中将其绑定到父控件的自定义消息发射函数。~~ 23 | 5. 将GroupUserList的实例itemDoubleClicked信号绑定到PyqtChatApp的setChatUser槽。获取双击用户的各种信息然后保存到本类中,用户增加消息时的使用。 24 | 25 | 26 | 27 | #undo 28 | 29 | 1. 聊天后台和功能实现。 30 | 31 | 32 | 33 | 项目地址:https://github.com/HeLiangHIT/pyqtChat 34 | 博客地址:http://blog.csdn.net/u010151698 35 | -------------------------------------------------------------------------------- /modules/QQqt4/readme.md: -------------------------------------------------------------------------------- 1 | 2 | # 图形界面 3 | qt部分引用了 https://github.com/HeLiangHIT/pyqtChat 4 | 在此基础上将源码改为Python3,并增加了表情功能,支持表情收藏与删除。 5 | 发送的快捷键以及界面风格也做了一些修改 6 | 7 | 1.groupUserList 类用于好友列表展示,模拟QQ好友界面。 8 | 9 | 2.msgList 类用于消息展示,模拟微信PC端消息界面,支持图片和文字显示。 10 | 11 | 3.flowlayout 类是pyqt的example里面的布局,就是依次布局按钮等控件时可能用到,自动调整位置。 12 | 13 | 4.exptable 类是表情窗口 14 | 15 | 5.pyqtChatApp 类是APP主界面。需在此修改代码最后的表情包路径 16 | 17 | -------------------------------------------------------------------------------- /modules/QQqt4/ref/QListWidget Class Reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/QListWidget Class Reference.pdf -------------------------------------------------------------------------------- /modules/QQqt4/ref/QListWidgetItem Class Reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/QListWidgetItem Class Reference.pdf -------------------------------------------------------------------------------- /modules/QQqt4/ref/QTextEdit Class Reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/QTextEdit Class Reference.pdf -------------------------------------------------------------------------------- /modules/QQqt4/ref/bq.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/bq.gif -------------------------------------------------------------------------------- /modules/QQqt4/ref/mt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/mt.gif -------------------------------------------------------------------------------- /modules/QQqt4/ref/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/pic1.png -------------------------------------------------------------------------------- /modules/QQqt4/ref/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/pic2.png -------------------------------------------------------------------------------- /modules/QQqt4/ref/pic3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/pic3.gif -------------------------------------------------------------------------------- /modules/QQqt4/ref/pic4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/modules/QQqt4/ref/pic4.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/requirements.txt -------------------------------------------------------------------------------- /sample/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/sample/__init__.py -------------------------------------------------------------------------------- /sample/core.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/sample/core.py -------------------------------------------------------------------------------- /sample/helpers.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/sample/helpers.py -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # @Date : 2017-05-30 11:46:41 4 | # @Author : Your Name (you@example.org) 5 | # @Link : http://example.org 6 | # @Version : $Id$ 7 | 8 | import sys 9 | import logging 10 | import os 11 | 12 | logging.basicConfig(level=logging.DEBUG) 13 | log = logging.getLogger(__name__) 14 | 15 | #sys.path.append('modules/') 16 | #from modules.DL import maxSim 17 | #from modules.OCR import Image2txt 18 | 19 | if __name__ == '__main__': 20 | dependencies = ['matplotlib', 'cv2', 'jieba', 'pyocr', 'numpy', 'sklearn', 'PIL', 'PyQt4', 'scipy'] 21 | print('Before we run the core, we need these package preinstalled\n%s', 22 | dependencies) 23 | uninstall = [] 24 | for package in dependencies: 25 | try: 26 | print('checking %s ...'%package) 27 | __import__(package) 28 | except ImportError as e: 29 | uninstall.append(package) 30 | log.info('ImportError %s', e) 31 | else: 32 | print('successfully imported %s'%package) 33 | if len(uninstall) == 0: 34 | pdir = os.path.split(__file__)[0] 35 | os.chdir('./modules/QQqt4/') 36 | os.system('python3 init.py') 37 | else : 38 | print('Please install these packages:\n %s'%uninstall) 39 | -------------------------------------------------------------------------------- /tests/test_advanced.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/tests/test_advanced.py -------------------------------------------------------------------------------- /tests/test_basic.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/earlybackhome/easy-expression/8674b9c089321835205c75cbc2b36ca4fd9a5b80/tests/test_basic.py --------------------------------------------------------------------------------