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