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