1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 by the Quassel Project * |
3 | * devel@quassel-irc.org * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) version 3. * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
19 | ***************************************************************************/ |
20 | |
21 | #include "qtuimessageprocessor.h" |
22 | |
23 | #include "client.h" |
24 | #include "clientsettings.h" |
25 | #include "identity.h" |
26 | #include "messagemodel.h" |
27 | #include "network.h" |
28 | |
29 | QtUiMessageProcessor::QtUiMessageProcessor(QObject *parent) |
30 | : AbstractMessageProcessor(parent), |
31 | _processing(false), |
32 | _processMode(TimerBased) |
33 | { |
34 | NotificationSettings notificationSettings; |
35 | _nicksCaseSensitive = notificationSettings.nicksCaseSensitive(); |
36 | _highlightNick = notificationSettings.highlightNick(); |
37 | highlightListChanged(notificationSettings.highlightList()); |
38 | notificationSettings.notify("Highlights/NicksCaseSensitive" , this, SLOT(nicksCaseSensitiveChanged(const QVariant &))); |
39 | notificationSettings.notify("Highlights/CustomList" , this, SLOT(highlightListChanged(const QVariant &))); |
40 | notificationSettings.notify("Highlights/HighlightNick" , this, SLOT(highlightNickChanged(const QVariant &))); |
41 | |
42 | _processTimer.setInterval(0); |
43 | connect(&_processTimer, SIGNAL(timeout()), this, SLOT(processNextMessage())); |
44 | } |
45 | |
46 | |
47 | void QtUiMessageProcessor::reset() |
48 | { |
49 | if (processMode() == TimerBased) { |
50 | if (_processTimer.isActive()) _processTimer.stop(); |
51 | _processing = false; |
52 | _currentBatch.clear(); |
53 | _processQueue.clear(); |
54 | } |
55 | } |
56 | |
57 | |
58 | void QtUiMessageProcessor::process(Message &msg) |
59 | { |
60 | checkForHighlight(msg); |
61 | preProcess(msg); |
62 | Client::messageModel()->insertMessage(msg); |
63 | } |
64 | |
65 | |
66 | void QtUiMessageProcessor::process(QList<Message> &msgs) |
67 | { |
68 | QList<Message>::iterator msgIter = msgs.begin(); |
69 | QList<Message>::iterator msgIterEnd = msgs.end(); |
70 | while (msgIter != msgIterEnd) { |
71 | checkForHighlight(*msgIter); |
72 | preProcess(*msgIter); |
73 | msgIter++; |
74 | } |
75 | Client::messageModel()->insertMessages(msgs); |
76 | return; |
77 | |
78 | if (msgs.isEmpty()) return; |
79 | _processQueue.append(msgs); |
80 | if (!isProcessing()) |
81 | startProcessing(); |
82 | } |
83 | |
84 | |
85 | void QtUiMessageProcessor::startProcessing() |
86 | { |
87 | if (processMode() == TimerBased) { |
88 | if (_currentBatch.isEmpty() && _processQueue.isEmpty()) |
89 | return; |
90 | _processing = true; |
91 | if (!_processTimer.isActive()) |
92 | _processTimer.start(); |
93 | } |
94 | } |
95 | |
96 | |
97 | void QtUiMessageProcessor::processNextMessage() |
98 | { |
99 | if (_currentBatch.isEmpty()) { |
100 | if (_processQueue.isEmpty()) { |
101 | _processTimer.stop(); |
102 | _processing = false; |
103 | return; |
104 | } |
105 | _currentBatch = _processQueue.takeFirst(); |
106 | } |
107 | Message msg = _currentBatch.takeFirst(); |
108 | process(msg); |
109 | } |
110 | |
111 | |
112 | void QtUiMessageProcessor::checkForHighlight(Message &msg) |
113 | { |
114 | if (!((msg.type() & (Message::Plain | Message::Notice | Message::Action)) && !(msg.flags() & Message::Self))) |
115 | return; |
116 | |
117 | // TODO: Cache this (per network) |
118 | const Network *net = Client::network(msg.bufferInfo().networkId()); |
119 | if (net && !net->myNick().isEmpty()) { |
120 | QStringList nickList; |
121 | if (_highlightNick == NotificationSettings::CurrentNick) { |
122 | nickList << net->myNick(); |
123 | } |
124 | else if (_highlightNick == NotificationSettings::AllNicks) { |
125 | const Identity *myIdentity = Client::identity(net->identity()); |
126 | if (myIdentity) |
127 | nickList = myIdentity->nicks(); |
128 | if (!nickList.contains(net->myNick())) |
129 | nickList.prepend(net->myNick()); |
130 | } |
131 | foreach(QString nickname, nickList) { |
132 | QRegExp nickRegExp("(^|\\W)" + QRegExp::escape(nickname) + "(\\W|$)" , _nicksCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); |
133 | if (nickRegExp.indexIn(msg.contents()) >= 0) { |
134 | msg.setFlags(msg.flags() | Message::Highlight); |
135 | return; |
136 | } |
137 | } |
138 | |
139 | for (int i = 0; i < _highlightRules.count(); i++) { |
140 | const HighlightRule &rule = _highlightRules.at(i); |
141 | if (!rule.isEnabled) |
142 | continue; |
143 | |
144 | if (rule.chanName.size() > 0 && rule.chanName.compare(".*" ) != 0) { |
145 | if (rule.chanName.startsWith("!" )) { |
146 | QRegExp rx(rule.chanName.mid(1), Qt::CaseInsensitive); |
147 | if (rx.exactMatch(msg.bufferInfo().bufferName())) |
148 | continue; |
149 | } |
150 | else { |
151 | QRegExp rx(rule.chanName, Qt::CaseInsensitive); |
152 | if (!rx.exactMatch(msg.bufferInfo().bufferName())) |
153 | continue; |
154 | } |
155 | } |
156 | |
157 | QRegExp rx; |
158 | if (rule.isRegExp) { |
159 | rx = QRegExp(rule.name, rule.caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); |
160 | } |
161 | else { |
162 | rx = QRegExp("(^|\\W)" + QRegExp::escape(rule.name) + "(\\W|$)" , rule.caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); |
163 | } |
164 | bool match = (rx.indexIn(msg.contents()) >= 0); |
165 | if (match) { |
166 | msg.setFlags(msg.flags() | Message::Highlight); |
167 | return; |
168 | } |
169 | } |
170 | } |
171 | } |
172 | |
173 | |
174 | void QtUiMessageProcessor::nicksCaseSensitiveChanged(const QVariant &variant) |
175 | { |
176 | _nicksCaseSensitive = variant.toBool(); |
177 | } |
178 | |
179 | |
180 | void QtUiMessageProcessor::highlightListChanged(const QVariant &variant) |
181 | { |
182 | QVariantList varList = variant.toList(); |
183 | |
184 | _highlightRules.clear(); |
185 | QVariantList::const_iterator iter = varList.constBegin(); |
186 | while (iter != varList.constEnd()) { |
187 | QVariantMap rule = iter->toMap(); |
188 | _highlightRules << HighlightRule(rule["Name" ].toString(), |
189 | rule["Enable" ].toBool(), |
190 | rule["CS" ].toBool() ? Qt::CaseSensitive : Qt::CaseInsensitive, |
191 | rule["RegEx" ].toBool(), |
192 | rule["Channel" ].toString()); |
193 | iter++; |
194 | } |
195 | } |
196 | |
197 | |
198 | void QtUiMessageProcessor::highlightNickChanged(const QVariant &variant) |
199 | { |
200 | _highlightNick = (NotificationSettings::HighlightNickType)variant.toInt(); |
201 | } |
202 | |