Yearly copyright bump :)
[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("UserNoticesInDefaultBuffer", this, SLOT(messageRedirectionChanged()));
51   defaultSettings.notify("UserNoticesInStatusBuffer", this, SLOT(messageRedirectionChanged()));
52   defaultSettings.notify("UserNoticesInCurrentBuffer", this, SLOT(messageRedirectionChanged()));
53
54   defaultSettings.notify("serverNoticesInDefaultBuffer", this, SLOT(messageRedirectionChanged()));
55   defaultSettings.notify("serverNoticesInStatusBuffer", this, SLOT(messageRedirectionChanged()));
56   defaultSettings.notify("serverNoticesInCurrentBuffer", this, SLOT(messageRedirectionChanged()));
57
58   defaultSettings.notify("ErrorMsgsInDefaultBuffer", this, SLOT(messageRedirectionChanged()));
59   defaultSettings.notify("ErrorMsgsInStatusBuffer", this, SLOT(messageRedirectionChanged()));
60   defaultSettings.notify("ErrorMsgsInCurrentBuffer", this, SLOT(messageRedirectionChanged()));
61   messageRedirectionChanged();
62
63   _messageTypeFilter = defaultSettings.messageFilter();
64   defaultSettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged()));
65
66   BufferSettings mySettings(idString());
67   if(mySettings.hasFilter())
68     _messageTypeFilter = mySettings.messageFilter();
69   mySettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged()));
70   mySettings.notify("hasMessageTypeFilter", this, SLOT(messageTypeFilterChanged()));
71 }
72
73 void MessageFilter::messageTypeFilterChanged() {
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 void MessageFilter::messageRedirectionChanged() {
90   BufferSettings bufferSettings;
91   _userNoticesInDefaultBuffer = bufferSettings.value("UserNoticesInDefaultBuffer", QVariant(true)).toBool();
92   _userNoticesInStatusBuffer = bufferSettings.value("UserNoticesInStatusBuffer", QVariant(false)).toBool();
93   _userNoticesInCurrentBuffer = bufferSettings.value("UserNoticesInCurrentBuffer", QVariant(false)).toBool();
94
95   _serverNoticesInDefaultBuffer = bufferSettings.value("ServerNoticesInDefaultBuffer", QVariant(false)).toBool();
96   _serverNoticesInStatusBuffer = bufferSettings.value("ServerNoticesInStatusBuffer", QVariant(true)).toBool();
97   _serverNoticesInCurrentBuffer = bufferSettings.value("ServerNoticesInCurrentBuffer", QVariant(false)).toBool();
98
99   _errorMsgsInDefaultBuffer = bufferSettings.value("ErrorMsgsInDefaultBuffer", QVariant(true)).toBool();
100   _errorMsgsInStatusBuffer = bufferSettings.value("ErrorMsgsInStatusBuffer", QVariant(false)).toBool();
101   _errorMsgsInCurrentBuffer = bufferSettings.value("ErrorMsgsInCurrentBuffer", QVariant(false)).toBool();
102
103   invalidateFilter();
104 }
105
106 QString MessageFilter::idString() const {
107   if(_validBuffers.isEmpty())
108     return "*";
109
110   QList<BufferId> bufferIds = _validBuffers.toList();
111   qSort(bufferIds);
112
113   QStringList bufferIdStrings;
114   foreach(BufferId id, bufferIds)
115     bufferIdStrings << QString::number(id.toInt());
116
117   return bufferIdStrings.join("|");
118 }
119
120 bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
121   Q_UNUSED(sourceParent);
122   QModelIndex sourceIdx = sourceModel()->index(sourceRow, 2);
123   Message::Type messageType = (Message::Type)sourceModel()->data(sourceIdx, MessageModel::TypeRole).toInt();
124
125   // apply message type filter
126   if(_messageTypeFilter & messageType)
127     return false;
128
129   if(_validBuffers.isEmpty())
130     return true;
131
132   BufferId bufferId = sourceModel()->data(sourceIdx, MessageModel::BufferIdRole).value<BufferId>();
133   if(!bufferId.isValid()) {
134     return true;
135   }
136
137   MsgId msgId = sourceModel()->data(sourceIdx, MessageModel::MsgIdRole).value<MsgId>();
138   Message::Flags flags = (Message::Flags)sourceModel()->data(sourceIdx, MessageModel::FlagsRole).toInt();
139
140   NetworkId myNetworkId = networkId();
141   NetworkId msgNetworkId = Client::networkModel()->networkId(bufferId);
142   if(myNetworkId != msgNetworkId)
143     return false;
144
145   bool redirect = false;
146   bool inDefaultBuffer;
147   bool inStatusBuffer;
148   bool inCurrentBuffer;
149
150   switch(messageType) {
151   case Message::Notice:
152     if(Client::networkModel()->bufferType(bufferId) != BufferInfo::ChannelBuffer) {
153       redirect = true;
154       if(flags & Message::ServerMsg) {
155         // server notice
156         inDefaultBuffer = _serverNoticesInDefaultBuffer;
157         inStatusBuffer = _serverNoticesInStatusBuffer;
158         inCurrentBuffer = _serverNoticesInCurrentBuffer;
159       } else {
160         inDefaultBuffer = _userNoticesInDefaultBuffer;
161         inStatusBuffer = _userNoticesInStatusBuffer;
162         inCurrentBuffer = _userNoticesInCurrentBuffer;
163       }
164     }
165     break;
166   case Message::Error:
167     redirect = true;
168     inDefaultBuffer = _errorMsgsInDefaultBuffer;
169     inStatusBuffer = _errorMsgsInStatusBuffer;
170     inCurrentBuffer = _errorMsgsInCurrentBuffer;
171     break;
172   default:
173     break;
174   }
175
176   if(redirect) {
177     if(_redirectedMsgs.contains(msgId))
178       return true;
179
180     if(inDefaultBuffer && _validBuffers.contains(bufferId))
181       return true;
182
183     if(inCurrentBuffer && !(flags & Message::Backlog) && _validBuffers.contains(Client::bufferModel()->currentIndex().data(NetworkModel::BufferIdRole).value<BufferId>())) {
184       BufferId redirectedTo = sourceModel()->data(sourceIdx, MessageModel::RedirectedToRole).value<BufferId>();
185       if(!redirectedTo.isValid()) {
186         sourceModel()->setData(sourceIdx, QVariant::fromValue<BufferId>(singleBufferId()), MessageModel::RedirectedToRole);
187         _redirectedMsgs << msgId;
188         return true;
189       } else if(_validBuffers.contains(redirectedTo)) {
190         return true;
191       }
192     }
193
194     QSet<BufferId>::const_iterator idIter = _validBuffers.constBegin();
195     while(idIter != _validBuffers.constEnd()) {
196       if(inStatusBuffer && Client::networkModel()->bufferType(*idIter) == BufferInfo::StatusBuffer)
197         return true;
198       idIter++;
199     }
200
201     return false;
202   }
203
204
205   if(_validBuffers.contains(bufferId)) {
206     return true;
207   } else {
208     // show Quit messages in Query buffers:
209     if(bufferType() != BufferInfo::QueryBuffer)
210       return false;
211     if(!(messageType & Message::Quit))
212       return false;
213
214     if(myNetworkId != msgNetworkId)
215       return false;
216
217     uint messageTimestamp = sourceModel()->data(sourceIdx, MessageModel::TimestampRole).value<QDateTime>().toTime_t();
218     QString quiter = sourceModel()->data(sourceIdx, Qt::DisplayRole).toString().section(' ', 0, 0, QString::SectionSkipEmpty).toLower();
219     if(quiter != bufferName().toLower())
220       return false;
221
222     if(_filteredQuitMsgs.contains(quiter, messageTimestamp))
223       return false;
224
225     MessageFilter *that = const_cast<MessageFilter *>(this);
226     that->_filteredQuitMsgs.insert(quiter,  messageTimestamp);
227     return true;
228   }
229 }
230
231 void MessageFilter::requestBacklog() {
232   QSet<BufferId>::const_iterator bufferIdIter = _validBuffers.constBegin();
233   while(bufferIdIter != _validBuffers.constEnd()) {
234     Client::messageModel()->requestBacklog(*bufferIdIter);
235     bufferIdIter++;
236   }
237 }