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