modernize: Use auto where the type is clear from context
[quassel.git] / src / client / bufferviewoverlay.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 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 "bufferviewoverlay.h"
22
23 #include <QEvent>
24
25 #include "bufferviewconfig.h"
26 #include "client.h"
27 #include "clientbacklogmanager.h"
28 #include "clientbufferviewmanager.h"
29 #include "networkmodel.h"
30
31 const int BufferViewOverlay::_updateEventId = QEvent::registerEventType();
32
33 BufferViewOverlay::BufferViewOverlay(QObject *parent)
34     : QObject(parent)
35 {
36 }
37
38
39 void BufferViewOverlay::reset()
40 {
41     _aboutToUpdate = false;
42
43     _bufferViewIds.clear();
44     _uninitializedViewCount = 0;
45
46     _networkIds.clear();
47     _allowedBufferTypes = 0;
48     _minimumActivity = 0;
49
50     _buffers.clear();
51     _removedBuffers.clear();
52     _tempRemovedBuffers.clear();
53 }
54
55
56 void BufferViewOverlay::save()
57 {
58     CoreAccountSettings().setBufferViewOverlay(_bufferViewIds);
59 }
60
61
62 void BufferViewOverlay::restore()
63 {
64     QSet<int> currentIds = _bufferViewIds;
65     reset();
66     currentIds += CoreAccountSettings().bufferViewOverlay();
67
68     QSet<int>::const_iterator iter;
69     for (iter = currentIds.constBegin(); iter != currentIds.constEnd(); ++iter) {
70         addView(*iter);
71     }
72 }
73
74
75 void BufferViewOverlay::addView(int viewId)
76 {
77     if (_bufferViewIds.contains(viewId))
78         return;
79
80     BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId);
81     if (!config) {
82         qDebug() << "BufferViewOverlay::addView(): no such buffer view:" << viewId;
83         return;
84     }
85
86     _bufferViewIds << viewId;
87     bool wasInitialized = isInitialized();
88     _uninitializedViewCount++;
89
90     if (config->isInitialized()) {
91         viewInitialized(config);
92
93         if (wasInitialized) {
94             BufferIdList buffers;
95             if (config->networkId().isValid()) {
96                 foreach(BufferId bufferId, config->bufferList()) {
97                     if (Client::networkModel()->networkId(bufferId) == config->networkId())
98                         buffers << bufferId;
99                 }
100                 foreach(BufferId bufferId, config->temporarilyRemovedBuffers().toList()) {
101                     if (Client::networkModel()->networkId(bufferId) == config->networkId())
102                         buffers << bufferId;
103                 }
104             }
105             else {
106                 buffers = BufferIdList::fromSet(config->bufferList().toSet() + config->temporarilyRemovedBuffers());
107             }
108             Client::backlogManager()->checkForBacklog(buffers);
109         }
110     }
111     else {
112         disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()));
113         // we use a queued connection here since manipulating the connection list of a sending object
114         // doesn't seem to be such a good idea while executing a connected slots.
115         connect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()), Qt::QueuedConnection);
116     }
117     save();
118 }
119
120
121 void BufferViewOverlay::removeView(int viewId)
122 {
123     if (!_bufferViewIds.contains(viewId))
124         return;
125
126     _bufferViewIds.remove(viewId);
127     BufferViewConfig *config = Client::bufferViewManager()->bufferViewConfig(viewId);
128     if (config)
129         disconnect(config, nullptr, this, nullptr);
130
131     // update initialized State:
132     bool wasInitialized = isInitialized();
133     _uninitializedViewCount = 0;
134     QSet<int>::iterator viewIter = _bufferViewIds.begin();
135     while (viewIter != _bufferViewIds.end()) {
136         config = Client::bufferViewManager()->bufferViewConfig(*viewIter);
137         if (!config) {
138             viewIter = _bufferViewIds.erase(viewIter);
139         }
140         else {
141             if (!config->isInitialized())
142                 _uninitializedViewCount++;
143             ++viewIter;
144         }
145     }
146
147     update();
148     if (!wasInitialized && isInitialized())
149         emit initDone();
150     save();
151 }
152
153
154 void BufferViewOverlay::viewInitialized(BufferViewConfig *config)
155 {
156     if (!config) {
157         qWarning() << "BufferViewOverlay::viewInitialized() received invalid view!";
158         return;
159     }
160     disconnect(config, SIGNAL(initDone()), this, SLOT(viewInitialized()));
161
162     connect(config, SIGNAL(configChanged()), this, SLOT(update()));
163
164     // check if the view was removed in the meantime...
165     if (_bufferViewIds.contains(config->bufferViewId()))
166         update();
167
168     _uninitializedViewCount--;
169     if (isInitialized())
170         emit initDone();
171 }
172
173
174 void BufferViewOverlay::viewInitialized()
175 {
176     auto *config = qobject_cast<BufferViewConfig *>(sender());
177     Q_ASSERT(config);
178
179     viewInitialized(config);
180 }
181
182
183 void BufferViewOverlay::update()
184 {
185     if (_aboutToUpdate) {
186         return;
187     }
188     _aboutToUpdate = true;
189     QCoreApplication::postEvent(this, new QEvent((QEvent::Type)_updateEventId));
190 }
191
192
193 void BufferViewOverlay::updateHelper()
194 {
195     if (!_aboutToUpdate)
196         return;
197
198     bool changed = false;
199
200     int allowedBufferTypes = 0;
201     int minimumActivity = -1;
202     QSet<NetworkId> networkIds;
203     QSet<BufferId> buffers;
204     QSet<BufferId> removedBuffers;
205     QSet<BufferId> tempRemovedBuffers;
206
207     if (Client::bufferViewManager()) {
208         BufferViewConfig *config = nullptr;
209         QSet<int>::const_iterator viewIter;
210         for (viewIter = _bufferViewIds.constBegin(); viewIter != _bufferViewIds.constEnd(); ++viewIter) {
211             config = Client::bufferViewManager()->bufferViewConfig(*viewIter);
212             if (!config)
213                 continue;
214
215             allowedBufferTypes |= config->allowedBufferTypes();
216             if (minimumActivity == -1 || config->minimumActivity() < minimumActivity)
217                 minimumActivity = config->minimumActivity();
218
219             networkIds << config->networkId();
220
221             // we have to apply several filters before we can add a buffer to a category (visible, removed, ...)
222             buffers += filterBuffersByConfig(config->bufferList(), config);
223             tempRemovedBuffers += filterBuffersByConfig(config->temporarilyRemovedBuffers().toList(), config);
224             removedBuffers += config->removedBuffers();
225         }
226
227         // prune the sets from overlap
228         QSet<BufferId> availableBuffers = Client::networkModel()->allBufferIds().toSet();
229
230         buffers.intersect(availableBuffers);
231
232         tempRemovedBuffers.intersect(availableBuffers);
233         tempRemovedBuffers.subtract(buffers);
234
235         removedBuffers.intersect(availableBuffers);
236         removedBuffers.subtract(tempRemovedBuffers);
237         removedBuffers.subtract(buffers);
238     }
239
240     changed |= (allowedBufferTypes != _allowedBufferTypes);
241     changed |= (minimumActivity != _minimumActivity);
242     changed |= (networkIds != _networkIds);
243     changed |= (buffers != _buffers);
244     changed |= (removedBuffers != _removedBuffers);
245     changed |= (tempRemovedBuffers != _tempRemovedBuffers);
246
247     _allowedBufferTypes = allowedBufferTypes;
248     _minimumActivity = minimumActivity;
249     _networkIds = networkIds;
250     _buffers = buffers;
251     _removedBuffers = removedBuffers;
252     _tempRemovedBuffers = tempRemovedBuffers;
253
254     _aboutToUpdate = false;
255
256     if (changed)
257         emit hasChanged();
258 }
259
260
261 QSet<BufferId> BufferViewOverlay::filterBuffersByConfig(const QList<BufferId> &buffers, const BufferViewConfig *config)
262 {
263     Q_ASSERT(config);
264
265     QSet<BufferId> bufferIds;
266     BufferInfo bufferInfo;
267     foreach(BufferId bufferId, buffers) {
268         bufferInfo = Client::networkModel()->bufferInfo(bufferId);
269         if (!(bufferInfo.type() & config->allowedBufferTypes()))
270             continue;
271         if (config->networkId().isValid() && bufferInfo.networkId() != config->networkId())
272             continue;
273         bufferIds << bufferId;
274     }
275
276     return bufferIds;
277 }
278
279
280 void BufferViewOverlay::customEvent(QEvent *event)
281 {
282     if (event->type() == _updateEventId) {
283         updateHelper();
284     }
285 }
286
287
288 bool BufferViewOverlay::allNetworks()
289 {
290     updateHelper();
291     return _networkIds.contains(NetworkId());
292 }
293
294
295 const QSet<NetworkId> &BufferViewOverlay::networkIds()
296 {
297     updateHelper();
298     return _networkIds;
299 }
300
301
302 const QSet<BufferId> &BufferViewOverlay::bufferIds()
303 {
304     updateHelper();
305     return _buffers;
306 }
307
308
309 const QSet<BufferId> &BufferViewOverlay::removedBufferIds()
310 {
311     updateHelper();
312     return _removedBuffers;
313 }
314
315
316 const QSet<BufferId> &BufferViewOverlay::tempRemovedBufferIds()
317 {
318     updateHelper();
319     return _tempRemovedBuffers;
320 }
321
322
323 int BufferViewOverlay::allowedBufferTypes()
324 {
325     updateHelper();
326     return _allowedBufferTypes;
327 }
328
329
330 int BufferViewOverlay::minimumActivity()
331 {
332     updateHelper();
333     return _minimumActivity;
334 }