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