Implement buffer activity sync
[quassel.git] / src / core / corebuffersyncer.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2016 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 "corebuffersyncer.h"
22
23 #include "core.h"
24 #include "coresession.h"
25 #include "corenetwork.h"
26 #include "ircchannel.h"
27
28 class PurgeEvent : public QEvent
29 {
30 public:
31     PurgeEvent() : QEvent(QEvent::User) {}
32 };
33
34
35 INIT_SYNCABLE_OBJECT(CoreBufferSyncer)
36 CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent)
37     : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()), Core::bufferMarkerLineMsgIds(parent->user()), Core::bufferActivities(parent->user()), parent),
38     _coreSession(parent),
39     _purgeBuffers(false)
40 {
41     connect(parent, SIGNAL(displayMsg(Message)), SLOT(addBufferActivity(Message)));
42 }
43
44
45 void CoreBufferSyncer::requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId)
46 {
47     if (setLastSeenMsg(buffer, msgId)) {
48         setBufferActivity(buffer, (int) Core::bufferActivity(buffer, msgId));
49         dirtyLastSeenBuffers << buffer;
50     }
51 }
52
53
54 void CoreBufferSyncer::requestSetMarkerLine(BufferId buffer, const MsgId &msgId)
55 {
56     if (setMarkerLine(buffer, msgId))
57         dirtyMarkerLineBuffers << buffer;
58 }
59
60
61 void CoreBufferSyncer::storeDirtyIds()
62 {
63     UserId userId = _coreSession->user();
64     MsgId msgId;
65     foreach(BufferId bufferId, dirtyLastSeenBuffers) {
66         msgId = lastSeenMsg(bufferId);
67         if (msgId.isValid())
68             Core::setBufferLastSeenMsg(userId, bufferId, msgId);
69     }
70
71     foreach(BufferId bufferId, dirtyMarkerLineBuffers) {
72         msgId = markerLine(bufferId);
73         if (msgId.isValid())
74             Core::setBufferMarkerLineMsg(userId, bufferId, msgId);
75     }
76
77     foreach(BufferId bufferId, dirtyActivities) {
78         Core::setBufferActivity(userId, bufferId, activity(bufferId));
79     }
80
81     dirtyLastSeenBuffers.clear();
82     dirtyMarkerLineBuffers.clear();
83     dirtyActivities.clear();
84 }
85
86
87 void CoreBufferSyncer::removeBuffer(BufferId bufferId)
88 {
89     BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId);
90     if (!bufferInfo.isValid()) {
91         qWarning() << "CoreBufferSyncer::removeBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user();
92         return;
93     }
94
95     if (bufferInfo.type() == BufferInfo::StatusBuffer) {
96         qWarning() << "CoreBufferSyncer::removeBuffer(): Status Buffers cannot be removed!";
97         return;
98     }
99
100     if (bufferInfo.type() == BufferInfo::ChannelBuffer) {
101         CoreNetwork *net = _coreSession->network(bufferInfo.networkId());
102         if (!net) {
103             qWarning() << "CoreBufferSyncer::removeBuffer(): Received BufferInfo with unknown networkId!";
104             return;
105         }
106         IrcChannel *chan = net->ircChannel(bufferInfo.bufferName());
107         if (chan) {
108             qWarning() << "CoreBufferSyncer::removeBuffer(): Unable to remove Buffer for joined Channel:" << bufferInfo.bufferName();
109             return;
110         }
111     }
112     if (Core::removeBuffer(_coreSession->user(), bufferId))
113         BufferSyncer::removeBuffer(bufferId);
114 }
115
116
117 void CoreBufferSyncer::renameBuffer(BufferId bufferId, QString newName)
118 {
119     BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId);
120     if (!bufferInfo.isValid()) {
121         qWarning() << "CoreBufferSyncer::renameBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user();
122         return;
123     }
124
125     if (bufferInfo.type() != BufferInfo::QueryBuffer) {
126         qWarning() << "CoreBufferSyncer::renameBuffer(): only QueryBuffers can be renamed" << bufferId;
127         return;
128     }
129
130     if (Core::renameBuffer(_coreSession->user(), bufferId, newName))
131         BufferSyncer::renameBuffer(bufferId, newName);
132 }
133
134
135 void CoreBufferSyncer::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2)
136 {
137     BufferInfo bufferInfo1 = Core::getBufferInfo(_coreSession->user(), bufferId1);
138     BufferInfo bufferInfo2 = Core::getBufferInfo(_coreSession->user(), bufferId2);
139     if (!bufferInfo1.isValid() || !bufferInfo2.isValid()) {
140         qWarning() << "CoreBufferSyncer::mergeBuffersPermanently(): invalid BufferIds:" << bufferId1 << bufferId2 << "for User:" << _coreSession->user();
141         return;
142     }
143
144     if ((bufferInfo1.type() != BufferInfo::QueryBuffer && bufferInfo1.type() != BufferInfo::ChannelBuffer)
145         || (bufferInfo2.type() != BufferInfo::QueryBuffer && bufferInfo2.type() != BufferInfo::ChannelBuffer)) {
146             qWarning() << "CoreBufferSyncer::mergeBuffersPermanently(): only QueryBuffers and/or ChannelBuffers can be merged!" << bufferId1 << bufferId2;
147             return;
148     }
149
150     if (Core::mergeBuffersPermanently(_coreSession->user(), bufferId1, bufferId2)) {
151         BufferSyncer::mergeBuffersPermanently(bufferId1, bufferId2);
152     }
153 }
154
155
156 void CoreBufferSyncer::customEvent(QEvent *event)
157 {
158     if (event->type() != QEvent::User)
159         return;
160
161     purgeBufferIds();
162     event->accept();
163 }
164
165
166 void CoreBufferSyncer::requestPurgeBufferIds()
167 {
168     if (_purgeBuffers)
169         return;
170
171     _purgeBuffers = true;
172     QCoreApplication::postEvent(this, new PurgeEvent());
173 }
174
175
176 void CoreBufferSyncer::purgeBufferIds()
177 {
178     _purgeBuffers = false;
179     QList<BufferInfo> bufferInfos = Core::requestBuffers(_coreSession->user());
180     QSet<BufferId> actualBuffers;
181     foreach(BufferInfo bufferInfo, bufferInfos) {
182         actualBuffers << bufferInfo.bufferId();
183     }
184
185     QSet<BufferId> storedIds = lastSeenBufferIds().toSet() + markerLineBufferIds().toSet();
186     foreach(BufferId bufferId, storedIds) {
187         if (!actualBuffers.contains(bufferId)) {
188             BufferSyncer::removeBuffer(bufferId);
189         }
190     }
191 }
192
193 void CoreBufferSyncer::setBufferActivity(BufferId buffer, const int &activity) {
194     BufferSyncer::setBufferActivity(buffer, activity);
195     dirtyActivities << buffer;
196 }