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 "messagefilter.h" |
22 | |
23 | #include "buffersettings.h" |
24 | #include "client.h" |
25 | #include "buffermodel.h" |
26 | #include "messagemodel.h" |
27 | #include "networkmodel.h" |
28 | #include "clientignorelistmanager.h" |
29 | |
30 | MessageFilter::MessageFilter(QAbstractItemModel *source, QObject *parent) |
31 | : QSortFilterProxyModel(parent), |
32 | _messageTypeFilter(0) |
33 | { |
34 | init(); |
35 | setSourceModel(source); |
36 | } |
37 | |
38 | |
39 | MessageFilter::MessageFilter(MessageModel *source, const QList<BufferId> &buffers, QObject *parent) |
40 | : QSortFilterProxyModel(parent), |
41 | _validBuffers(buffers.toSet()), |
42 | _messageTypeFilter(0) |
43 | { |
44 | init(); |
45 | setSourceModel(source); |
46 | } |
47 | |
48 | |
49 | void MessageFilter::init() |
50 | { |
51 | setDynamicSortFilter(true); |
52 | |
53 | _userNoticesTarget = _serverNoticesTarget = _errorMsgsTarget = -1; |
54 | |
55 | BufferSettings defaultSettings; |
56 | defaultSettings.notify("UserNoticesTarget" , this, SLOT(messageRedirectionChanged())); |
57 | defaultSettings.notify("ServerNoticesTarget" , this, SLOT(messageRedirectionChanged())); |
58 | defaultSettings.notify("ErrorMsgsTarget" , this, SLOT(messageRedirectionChanged())); |
59 | messageRedirectionChanged(); |
60 | |
61 | _messageTypeFilter = defaultSettings.messageFilter(); |
62 | defaultSettings.notify("MessageTypeFilter" , this, SLOT(messageTypeFilterChanged())); |
63 | |
64 | BufferSettings mySettings(idString()); |
65 | if (mySettings.hasFilter()) |
66 | _messageTypeFilter = mySettings.messageFilter(); |
67 | mySettings.notify("MessageTypeFilter" , this, SLOT(messageTypeFilterChanged())); |
68 | mySettings.notify("hasMessageTypeFilter" , this, SLOT(messageTypeFilterChanged())); |
69 | } |
70 | |
71 | |
72 | void MessageFilter::messageTypeFilterChanged() |
73 | { |
74 | int newFilter; |
75 | BufferSettings defaultSettings; |
76 | newFilter = BufferSettings().messageFilter(); |
77 | |
78 | BufferSettings mySettings(idString()); |
79 | if (mySettings.hasFilter()) |
80 | newFilter = mySettings.messageFilter(); |
81 | |
82 | if (_messageTypeFilter != newFilter) { |
83 | _messageTypeFilter = newFilter; |
84 | _filteredQuitMsgs.clear(); |
85 | invalidateFilter(); |
86 | } |
87 | } |
88 | |
89 | |
90 | void MessageFilter::messageRedirectionChanged() |
91 | { |
92 | BufferSettings bufferSettings; |
93 | bool changed = false; |
94 | |
95 | if (_userNoticesTarget != bufferSettings.userNoticesTarget()) { |
96 | _userNoticesTarget = bufferSettings.userNoticesTarget(); |
97 | changed = true; |
98 | } |
99 | |
100 | if (_serverNoticesTarget != bufferSettings.serverNoticesTarget()) { |
101 | _serverNoticesTarget = bufferSettings.serverNoticesTarget(); |
102 | changed = true; |
103 | } |
104 | |
105 | if (_errorMsgsTarget != bufferSettings.errorMsgsTarget()) { |
106 | _errorMsgsTarget = bufferSettings.errorMsgsTarget(); |
107 | changed = true; |
108 | } |
109 | |
110 | if (changed) |
111 | invalidateFilter(); |
112 | } |
113 | |
114 | |
115 | QString MessageFilter::idString() const |
116 | { |
117 | if (_validBuffers.isEmpty()) |
118 | return "*" ; |
119 | |
120 | QList<BufferId> bufferIds = _validBuffers.toList(); |
121 | qSort(bufferIds); |
122 | |
123 | QStringList bufferIdStrings; |
124 | foreach(BufferId id, bufferIds) |
125 | bufferIdStrings << QString::number(id.toInt()); |
126 | |
127 | return bufferIdStrings.join("|" ); |
128 | } |
129 | |
130 | |
131 | bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const |
132 | { |
133 | Q_UNUSED(sourceParent); |
134 | QModelIndex sourceIdx = sourceModel()->index(sourceRow, 2); |
135 | Message::Type messageType = (Message::Type)sourceIdx.data(MessageModel::TypeRole).toInt(); |
136 | |
137 | // apply message type filter |
138 | if (_messageTypeFilter & messageType) |
139 | return false; |
140 | |
141 | if (_validBuffers.isEmpty()) |
142 | return true; |
143 | |
144 | BufferId bufferId = sourceIdx.data(MessageModel::BufferIdRole).value<BufferId>(); |
145 | if (!bufferId.isValid()) { |
146 | return true; |
147 | } |
148 | |
149 | // MsgId msgId = sourceIdx.data(MessageModel::MsgIdRole).value<MsgId>(); |
150 | Message::Flags flags = (Message::Flags)sourceIdx.data(MessageModel::FlagsRole).toInt(); |
151 | |
152 | NetworkId myNetworkId = networkId(); |
153 | NetworkId msgNetworkId = Client::networkModel()->networkId(bufferId); |
154 | if (myNetworkId != msgNetworkId) |
155 | return false; |
156 | |
157 | // ignorelist handling |
158 | // only match if message is not flagged as server msg |
159 | if (!(flags & Message::ServerMsg) && Client::ignoreListManager() |
160 | && Client::ignoreListManager()->match(sourceIdx.data(MessageModel::MessageRole).value<Message>(), Client::networkModel()->networkName(bufferId))) |
161 | return false; |
162 | |
163 | if (flags & Message::Redirected) { |
164 | int redirectionTarget = 0; |
165 | switch (messageType) { |
166 | case Message::Notice: |
167 | if (Client::networkModel()->bufferType(bufferId) != BufferInfo::ChannelBuffer) { |
168 | if (flags & Message::ServerMsg) { |
169 | // server notice |
170 | redirectionTarget = _serverNoticesTarget; |
171 | } |
172 | else { |
173 | redirectionTarget = _userNoticesTarget; |
174 | } |
175 | } |
176 | break; |
177 | case Message::Error: |
178 | redirectionTarget = _errorMsgsTarget; |
179 | break; |
180 | default: |
181 | break; |
182 | } |
183 | |
184 | if (redirectionTarget & BufferSettings::DefaultBuffer && _validBuffers.contains(bufferId)) |
185 | return true; |
186 | |
187 | if (redirectionTarget & BufferSettings::CurrentBuffer && !(flags & Message::Backlog)) { |
188 | BufferId redirectedTo = sourceModel()->data(sourceIdx, MessageModel::RedirectedToRole).value<BufferId>(); |
189 | if (!redirectedTo.isValid()) { |
190 | BufferId redirectedTo = Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value<BufferId>(); |
191 | if (redirectedTo.isValid()) |
192 | sourceModel()->setData(sourceIdx, QVariant::fromValue<BufferId>(redirectedTo), MessageModel::RedirectedToRole); |
193 | } |
194 | |
195 | if (_validBuffers.contains(redirectedTo)) |
196 | return true; |
197 | } |
198 | |
199 | if (redirectionTarget & BufferSettings::StatusBuffer) { |
200 | QSet<BufferId>::const_iterator idIter = _validBuffers.constBegin(); |
201 | while (idIter != _validBuffers.constEnd()) { |
202 | if (Client::networkModel()->bufferType(*idIter) == BufferInfo::StatusBuffer) |
203 | return true; |
204 | idIter++; |
205 | } |
206 | } |
207 | |
208 | return false; |
209 | } |
210 | |
211 | if (_validBuffers.contains(bufferId)) { |
212 | return true; |
213 | } |
214 | else { |
215 | // show Quit messages in Query buffers: |
216 | if (bufferType() != BufferInfo::QueryBuffer) |
217 | return false; |
218 | if (!(messageType & Message::Quit)) |
219 | return false; |
220 | |
221 | if (myNetworkId != msgNetworkId) |
222 | return false; |
223 | |
224 | uint messageTimestamp = sourceModel()->data(sourceIdx, MessageModel::TimestampRole).value<QDateTime>().toTime_t(); |
225 | QString quiter = sourceModel()->data(sourceIdx, Qt::DisplayRole).toString().section(' ', 0, 0, QString::SectionSkipEmpty).toLower(); |
226 | if (quiter != bufferName().toLower()) |
227 | return false; |
228 | |
229 | if (_filteredQuitMsgs.contains(quiter, messageTimestamp)) |
230 | return false; |
231 | |
232 | MessageFilter *that = const_cast<MessageFilter *>(this); |
233 | that->_filteredQuitMsgs.insert(quiter, messageTimestamp); |
234 | return true; |
235 | } |
236 | } |
237 | |
238 | |
239 | void MessageFilter::requestBacklog() |
240 | { |
241 | QSet<BufferId>::const_iterator bufferIdIter = _validBuffers.constBegin(); |
242 | while (bufferIdIter != _validBuffers.constEnd()) { |
243 | Client::messageModel()->requestBacklog(*bufferIdIter); |
244 | bufferIdIter++; |
245 | } |
246 | } |
247 | |