├── 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 |  
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 | 
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 | 
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
--------------------------------------------------------------------------------