Adds nicer ircuser tooltips
[quassel.git] / src / client / messagefilter.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2015 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 }