Merge lp:~phablet-team/history-service/sort_by_multiple_fields into lp:history-service/staging

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~phablet-team/history-service/sort_by_multiple_fields
Merge into: lp:history-service/staging
Diff against target: 1105 lines (+369/-74)
27 files modified
Ubuntu/History/historyeventmodel.cpp (+17/-6)
Ubuntu/History/historythreadmodel.cpp (+18/-0)
Ubuntu/History/historythreadmodel.h (+1/-0)
daemon/HistoryService.xml (+13/-0)
daemon/historydaemon.cpp (+150/-54)
daemon/historydaemon.h (+15/-8)
daemon/historyservicedbus.cpp (+8/-0)
daemon/historyservicedbus.h (+8/-0)
daemon/textchannelobserver.cpp (+1/-0)
daemon/textchannelobserver.h (+1/-0)
plugins/sqlite/sqlitehistoryeventview.cpp (+10/-1)
plugins/sqlite/sqlitehistoryplugin.cpp (+27/-5)
plugins/sqlite/sqlitehistoryplugin.h (+4/-0)
src/manager.cpp (+3/-0)
src/manager.h (+1/-0)
src/managerdbus.cpp (+17/-0)
src/managerdbus_p.h (+8/-0)
src/participant.cpp (+9/-0)
src/participant.h (+1/-0)
src/plugin.h (+4/-0)
src/thread.cpp (+16/-0)
src/thread.h (+2/-0)
src/threadview.cpp (+15/-0)
src/threadview.h (+8/-0)
src/threadview_p.h (+4/-0)
src/utils.cpp (+7/-0)
src/utils_p.h (+1/-0)
To merge this branch: bzr merge lp:~phablet-team/history-service/sort_by_multiple_fields
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+316579@code.launchpad.net

This proposal has been superseded by a proposal from 2017-02-07.

To post a comment you must log in.
258. By Renato Araujo Oliveira Filho

Create unit test for multiple fields sort query.

259. By Renato Araujo Oliveira Filho

Update comments.

260. By Renato Araujo Oliveira Filho

Keep history model sorted if multiple fields are specified.

261. By Tiago Salem Herrmann

merge parent branch

262. By Tiago Salem Herrmann

merge parent branch

263. By Renato Araujo Oliveira Filho

Code optimize.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Ubuntu/History/historyeventmodel.cpp'
2--- Ubuntu/History/historyeventmodel.cpp 2016-09-16 11:59:52 +0000
3+++ Ubuntu/History/historyeventmodel.cpp 2017-02-07 15:39:44 +0000
4@@ -98,7 +98,14 @@
5 result = event.senderId();
6 break;
7 case SenderRole:
8- result = History::ContactMatcher::instance()->contactInfo(event.accountId(), event.senderId());
9+ if (mMatchContacts) {
10+ result = History::ContactMatcher::instance()->contactInfo(event.accountId(), event.senderId());
11+ } else {
12+ QVariantMap map;
13+ map[History::FieldIdentifier] = event.senderId();
14+ map[History::FieldAccountId] = event.accountId();
15+ result = map;
16+ }
17 break;
18 case TimestampRole:
19 result = event.timestamp();
20@@ -173,12 +180,16 @@
21 break;
22 case SubjectAsAliasRole:
23 if (!textEvent.isNull()) {
24- QVariantMap contactInfo = History::ContactMatcher::instance()->contactInfo(event.accountId(), textEvent.subject());
25- QString returnValue = contactInfo[History::FieldAlias].toString();
26- if (returnValue.isEmpty()) {
27- returnValue = contactInfo[History::FieldIdentifier].toString();
28+ if (mMatchContacts) {
29+ QVariantMap contactInfo = History::ContactMatcher::instance()->contactInfo(event.accountId(), textEvent.subject());
30+ QString returnValue = contactInfo[History::FieldAlias].toString();
31+ if (returnValue.isEmpty()) {
32+ returnValue = contactInfo[History::FieldIdentifier].toString();
33+ }
34+ return returnValue;
35+
36 }
37- return returnValue;
38+ return textEvent.subject();
39 }
40 break;
41 }
42
43=== modified file 'Ubuntu/History/historythreadmodel.cpp'
44--- Ubuntu/History/historythreadmodel.cpp 2016-06-17 01:49:46 +0000
45+++ Ubuntu/History/historythreadmodel.cpp 2017-02-07 15:39:44 +0000
46@@ -294,6 +294,10 @@
47 SIGNAL(threadsRemoved(History::Threads)),
48 SLOT(onThreadsRemoved(History::Threads)));
49 connect(mThreadView.data(),
50+ SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)),
51+ SLOT(onThreadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)));
52+
53+ connect(mThreadView.data(),
54 SIGNAL(invalidated()),
55 SLOT(triggerQueryUpdate()));
56
57@@ -311,6 +315,20 @@
58 fetchMore(QModelIndex());
59 }
60
61+
62+void HistoryThreadModel::onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified)
63+{
64+ int pos = mThreads.indexOf(thread);
65+ if (pos >= 0) {
66+ mThreads[pos].removeParticipants(removed);
67+ mThreads[pos].removeParticipants(modified);
68+ mThreads[pos].addParticipants(added);
69+ mThreads[pos].addParticipants(modified);
70+ QModelIndex idx = index(pos);
71+ Q_EMIT dataChanged(idx, idx);
72+ }
73+}
74+
75 void HistoryThreadModel::onThreadsAdded(const History::Threads &threads)
76 {
77 if (threads.isEmpty()) {
78
79=== modified file 'Ubuntu/History/historythreadmodel.h'
80--- Ubuntu/History/historythreadmodel.h 2016-06-17 01:49:46 +0000
81+++ Ubuntu/History/historythreadmodel.h 2017-02-07 15:39:44 +0000
82@@ -76,6 +76,7 @@
83 virtual void onThreadsAdded(const History::Threads &threads);
84 virtual void onThreadsModified(const History::Threads &threads);
85 virtual void onThreadsRemoved(const History::Threads &threads);
86+ virtual void onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified);
87
88 protected:
89 History::Threads fetchNextPage();
90
91=== modified file 'daemon/HistoryService.xml'
92--- daemon/HistoryService.xml 2016-04-15 22:23:21 +0000
93+++ daemon/HistoryService.xml 2017-02-07 15:39:44 +0000
94@@ -159,5 +159,18 @@
95 <arg name="events" type="a(a{sv})"/>
96 <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList &lt; QVariantMap &gt;"/>
97 </signal>
98+ <signal name="ThreadParticipantsChanged">
99+ <dox:d><![CDATA[
100+ Participants changed in a certain thread changed.
101+ ]]></dox:d>
102+ <arg name="thread" type="a{sv}"/>
103+ <arg name="added" type="a(a{sv})"/>
104+ <arg name="removed" type="a(a{sv})"/>
105+ <arg name="modified" type="a(a{sv})"/>
106+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
107+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QList &lt; QVariantMap &gt;"/>
108+ <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QList &lt; QVariantMap &gt;"/>
109+ <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QList &lt; QVariantMap &gt;"/>
110+ </signal>
111 </interface>
112 </node>
113
114=== modified file 'daemon/historydaemon.cpp'
115--- daemon/historydaemon.cpp 2016-11-24 02:02:32 +0000
116+++ daemon/historydaemon.cpp 2017-02-07 15:39:44 +0000
117@@ -1,5 +1,5 @@
118 /*
119- * Copyright (C) 2013-2016 Canonical, Ltd.
120+ * Copyright (C) 2013-2017 Canonical, Ltd.
121 *
122 * Authors:
123 * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
124@@ -145,6 +145,9 @@
125 connect(&mTextObserver,
126 SIGNAL(channelAvailable(Tp::TextChannelPtr)),
127 SLOT(onTextChannelAvailable(Tp::TextChannelPtr)));
128+ connect(&mTextObserver,
129+ SIGNAL(textChannelInvalidated(Tp::TextChannelPtr)),
130+ SLOT(onTextChannelInvalidated(Tp::TextChannelPtr)));
131
132 // FIXME: we need to do this in a better way, but for now this should do
133 mProtocolFlags["ofono"] = History::MatchPhoneNumber;
134@@ -163,23 +166,39 @@
135
136 void HistoryDaemon::onRolesChanged(const HandleRolesMap &added, const HandleRolesMap &removed)
137 {
138- Q_UNUSED(added);
139- Q_UNUSED(removed);
140-
141 ChannelInterfaceRolesInterface *roles_interface = qobject_cast<ChannelInterfaceRolesInterface*>(sender());
142- RolesMap roles = roles_interface->getRoles();
143-
144 Tp::TextChannelPtr channel(qobject_cast<Tp::TextChannel*>(sender()->parent()));
145+ RolesMap rolesMap;
146+ if (!mRolesMap.contains(channel->objectPath())) {
147+ rolesMap = roles_interface->getRoles();
148+ } else {
149+ rolesMap = mRolesMap[channel->objectPath()];
150+ }
151+
152+ QMapIterator<uint, uint> it(removed);
153+ while (it.hasNext()) {
154+ it.next();
155+ rolesMap.remove(it.key());
156+ }
157+
158+ QMapIterator<uint, uint> it2(added);
159+ while (it2.hasNext()) {
160+ it2.next();
161+ rolesMap[it2.key()] = it2.value();
162+ }
163+
164+ mRolesMap[channel->objectPath()] = rolesMap;
165+
166 QVariantMap properties = propertiesFromChannel(channel);
167 QVariantMap thread = threadForProperties(channel->property(History::FieldAccountId).toString(),
168 History::EventTypeText,
169 properties,
170 matchFlagsForChannel(channel),
171 false);
172-
173- writeRolesInformationEvents(thread, channel, roles);
174-
175- updateRoomRoles(channel, roles);
176+ if (!thread.isEmpty()) {
177+ writeRolesInformationEvents(thread, channel, rolesMap);
178+ updateRoomRoles(channel, rolesMap);
179+ }
180 }
181
182 QVariantMap HistoryDaemon::propertiesFromChannel(const Tp::ChannelPtr &textChannel)
183@@ -187,17 +206,20 @@
184 QVariantMap properties;
185 QVariantList participants;
186 QStringList participantIds;
187+ QString accountId = textChannel->property(History::FieldAccountId).toString();
188
189 ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>();
190 RolesMap roles;
191 if (roles_interface) {
192- roles = roles_interface->getRoles();
193+ if (mRolesMap.contains(textChannel->objectPath())) {
194+ roles = mRolesMap[textChannel->objectPath()];
195+ }
196 }
197
198 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) {
199 QVariantMap contactProperties;
200 contactProperties[History::FieldAlias] = contact->alias();
201- contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString();
202+ contactProperties[History::FieldAccountId] = accountId;
203 contactProperties[History::FieldIdentifier] = contact->id();
204 contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
205 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
206@@ -208,7 +230,7 @@
207 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(false)) {
208 QVariantMap contactProperties;
209 contactProperties[History::FieldAlias] = contact->alias();
210- contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString();
211+ contactProperties[History::FieldAccountId] = accountId;
212 contactProperties[History::FieldIdentifier] = contact->id();
213 contactProperties[History::FieldParticipantState] = History::ParticipantStateRemotePending;
214 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
215@@ -219,7 +241,7 @@
216 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(false)) {
217 QVariantMap contactProperties;
218 contactProperties[History::FieldAlias] = contact->alias();
219- contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString();
220+ contactProperties[History::FieldAccountId] = accountId;
221 contactProperties[History::FieldIdentifier] = contact->id();
222 contactProperties[History::FieldParticipantState] = History::ParticipantStateLocalPending;
223 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
224@@ -231,7 +253,7 @@
225 textChannel->targetContact() == textChannel->connection()->selfContact()) {
226 QVariantMap contactProperties;
227 contactProperties[History::FieldAlias] = textChannel->targetContact()->alias();
228- contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString();
229+ contactProperties[History::FieldAccountId] = accountId;
230 contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id();
231 contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
232 participantIds << textChannel->targetContact()->id();
233@@ -314,6 +336,31 @@
234 return thread;
235 }
236
237+QString HistoryDaemon::threadIdForProperties(const QString &accountId, History::EventType type, const QVariantMap &properties, History::MatchFlags matchFlags, bool create)
238+{
239+ if (!mBackend) {
240+ return QString::null;
241+ }
242+
243+ QString threadId = mBackend->threadIdForProperties(accountId,
244+ type,
245+ properties,
246+ matchFlags);
247+ if (threadId.isEmpty() && create) {
248+ QVariantMap thread = mBackend->createThreadForProperties(accountId, type, properties);
249+ if (!thread.isEmpty()) {
250+ if (properties.contains("Requested") && properties[History::FieldChatType].toInt() == History::ChatTypeRoom) {
251+ QVariantMap map = thread[History::FieldChatRoomInfo].toMap();
252+ map["Requested"] = properties["Requested"];
253+ thread[History::FieldChatRoomInfo] = map;
254+ }
255+ mDBus.notifyThreadsAdded(QList<QVariantMap>() << thread);
256+ threadId = thread[History::FieldThreadId].toString();
257+ }
258+ }
259+ return threadId;
260+}
261+
262 QString HistoryDaemon::queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties)
263 {
264 if (!mBackend) {
265@@ -370,7 +417,7 @@
266 return mBackend->getSingleEvent((History::EventType)type, accountId, threadId, eventId);
267 }
268
269-bool HistoryDaemon::writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties)
270+bool HistoryDaemon::writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties, bool notify)
271 {
272 if (!mBackend) {
273 return false;
274@@ -407,7 +454,9 @@
275 threads[hash] = thread;
276
277 // set the participants field in the event
278- savedEvent[History::FieldParticipants] = thread[History::FieldParticipants];
279+ if (type == History::EventTypeVoice) {
280+ savedEvent[History::FieldParticipants] = thread[History::FieldParticipants];
281+ }
282
283
284 // check if the event was a new one or a modification to an existing one
285@@ -427,13 +476,13 @@
286 mBackend->endBatchOperation();
287
288 // and last but not least, notify the results
289- if (!newEvents.isEmpty()) {
290+ if (!newEvents.isEmpty() && notify) {
291 mDBus.notifyEventsAdded(newEvents);
292 }
293- if (!modifiedEvents.isEmpty()) {
294+ if (!modifiedEvents.isEmpty() && notify) {
295 mDBus.notifyEventsModified(modifiedEvents);
296 }
297- if (!threads.isEmpty()) {
298+ if (!threads.isEmpty() && notify) {
299 mDBus.notifyThreadsModified(threads.values());
300 }
301 return true;
302@@ -615,11 +664,17 @@
303 writeEvents(QList<QVariantMap>() << event, properties);
304 }
305
306+void HistoryDaemon::onTextChannelInvalidated(const Tp::TextChannelPtr channel)
307+{
308+ mRolesMap.remove(channel->objectPath());
309+}
310+
311 void HistoryDaemon::onTextChannelAvailable(const Tp::TextChannelPtr channel)
312 {
313 // for Rooms we need to explicitly create the thread to allow users to send messages to groups even
314 // before they receive any message.
315 // for other types, we can wait until messages are received
316+ bool notify = false;
317 if (channel->targetHandleType() == Tp::HandleTypeRoom) {
318 QString accountId = channel->property(History::FieldAccountId).toString();
319 QVariantMap properties = propertiesFromChannel(channel);
320@@ -641,12 +696,13 @@
321
322 // write information event including all initial invitees
323 Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) {
324- writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias());
325+ writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias(), QString(), QString(), false);
326 }
327
328 // update participants only if the thread is not available previously. Otherwise we'll wait for membersChanged event
329 // for reflect in conversation information events for modified participants.
330- updateRoomParticipants(channel);
331+ updateRoomParticipants(channel, false);
332+ notify = true;
333 }
334
335 // write an entry saying you joined the group if 'joined' flag in thread is false and modify that flag.
336@@ -657,7 +713,8 @@
337 writeInformationEvent(thread, History::InformationTypeSelfJoined);
338 }
339 // update backend
340- updateRoomProperties(channel, QVariantMap{{"Joined", true}});
341+ updateRoomProperties(channel, QVariantMap{{"Joined", true}}, false);
342+ notify = true;
343 }
344
345 Tp::AbstractInterface *room_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomInterface>();
346@@ -685,6 +742,10 @@
347
348 connect(roles_interface, SIGNAL(RolesChanged(const HandleRolesMap&, const HandleRolesMap&)), SLOT(onRolesChanged(const HandleRolesMap&, const HandleRolesMap&)));
349 }
350+
351+ if (notify) {
352+ updateRoomParticipants(channel, true);
353+ }
354 }
355
356 void HistoryDaemon::onGroupMembersChanged(const Tp::Contacts &groupMembersAdded,
357@@ -702,6 +763,8 @@
358 bool hasRemotePendingMembersAdded = groupRemotePendingMembersAdded.size() > 0;
359 bool hasMembersAdded = groupMembersAdded.size() > 0;
360 bool hasMembersRemoved = groupMembersRemoved.size() > 0;
361+ Tp::ContactPtr selfContact = channel->connection()->selfContact();
362+ bool selfContactIsPending = channel->groupRemotePendingContacts(true).contains(selfContact);
363
364 if (hasRemotePendingMembersAdded || hasMembersAdded || hasMembersRemoved) {
365 properties = propertiesFromChannel(channel);
366@@ -710,19 +773,34 @@
367 properties,
368 matchFlagsForChannel(channel),
369 false);
370- if (!thread.isEmpty()) {
371+ if (!thread.isEmpty() && !selfContactIsPending) {
372+ QList<QVariantMap> added;
373+ QList<QVariantMap> removed;
374+ QList<QVariantMap> modified;
375 if (hasRemotePendingMembersAdded) {
376 Q_FOREACH (const Tp::ContactPtr& contact, groupRemotePendingMembersAdded) {
377 if (!foundInThread(contact, thread)) {
378- writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias());
379+ writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias(), QString(), QString(), true);
380+ QVariantMap participant;
381+ participant[History::FieldIdentifier] = contact->id();
382+ participant[History::FieldAlias] = contact->alias();
383+ participant[History::FieldParticipantState] = History::ParticipantStateRemotePending;
384+ added << participant;
385 }
386 }
387+
388 }
389 if (hasMembersAdded) {
390 Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) {
391 // if this member was not previously regular member in thread, notify about his join
392 if (!foundAsMemberInThread(contact, thread)) {
393- writeInformationEvent(thread, History::InformationTypeJoined, contact->alias());
394+ writeInformationEvent(thread, History::InformationTypeJoined, contact->alias(), QString(), QString(), true);
395+
396+ QVariantMap participant;
397+ participant[History::FieldIdentifier] = contact->id();
398+ participant[History::FieldAlias] = contact->alias();
399+ participant[History::FieldParticipantState] = History::ParticipantStateRegular;
400+ added << participant;
401 }
402 }
403 }
404@@ -743,25 +821,30 @@
405 }
406 writeInformationEvent(thread, type);
407 // update backend
408- updateRoomProperties(channel, QVariantMap{{"Joined", false}});
409+ updateRoomProperties(channel, QVariantMap{{"Joined", false}}, true);
410 }
411 else // don't notify any other group member removal if we are leaving the group
412 {
413 Q_FOREACH (const Tp::ContactPtr& contact, groupMembersRemoved) {
414 // inform about removed members other than us
415 if (contact->id() != channel->groupSelfContact()->id()) {
416- writeInformationEvent(thread, History::InformationTypeLeaving, contact->alias());
417+ writeInformationEvent(thread, History::InformationTypeLeaving, contact->alias(), QString(), QString(), true);
418 }
419+ QVariantMap participant;
420+ participant[History::FieldIdentifier] = contact->id();
421+ participant[History::FieldAlias] = contact->alias();
422+ removed << participant;
423 }
424 }
425 }
426+ mDBus.notifyThreadParticipantsChanged(thread, added, removed, QList<QVariantMap>());
427 }
428 }
429
430- updateRoomParticipants(channel);
431+ updateRoomParticipants(channel, !selfContactIsPending);
432 }
433
434-void HistoryDaemon::updateRoomParticipants(const Tp::TextChannelPtr channel)
435+void HistoryDaemon::updateRoomParticipants(const Tp::TextChannelPtr channel, bool notify)
436 {
437 if (!channel) {
438 return;
439@@ -772,8 +855,14 @@
440
441 ChannelInterfaceRolesInterface *roles_interface = channel->optionalInterface<ChannelInterfaceRolesInterface>();
442 RolesMap roles;
443+
444 if (roles_interface) {
445- roles = roles_interface->getRoles();
446+ if (!mRolesMap.contains(channel->objectPath())) {
447+ roles = roles_interface->getRoles();
448+ mRolesMap[channel->objectPath()] = roles;
449+ } else {
450+ roles = mRolesMap[channel->objectPath()];
451+ }
452 }
453
454 Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) {
455@@ -811,12 +900,14 @@
456 QString accountId = channel->property(History::FieldAccountId).toString();
457 QString threadId = channel->targetId();
458 if (mBackend->updateRoomParticipants(accountId, threadId, History::EventTypeText, participants)) {
459- QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap());
460- mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread);
461+ if (notify) {
462+ QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap());
463+ mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread);
464+ }
465 }
466 }
467
468-void HistoryDaemon::updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap)
469+void HistoryDaemon::updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap, bool notify)
470 {
471 if (!channel) {
472 return;
473@@ -841,8 +932,10 @@
474 QString accountId = channel->property(History::FieldAccountId).toString();
475 QString threadId = channel->targetId();
476 if (mBackend->updateRoomParticipantsRoles(accountId, threadId, History::EventTypeText, participantsRoles)) {
477- QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap());
478- mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread);
479+ if (notify) {
480+ QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap());
481+ mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread);
482+ }
483 }
484
485 // update self roles in room properties
486@@ -865,19 +958,21 @@
487 updateRoomProperties(accountId, threadId, type, properties, invalidated);
488 }
489
490-void HistoryDaemon::updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties)
491+void HistoryDaemon::updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties, bool notify)
492 {
493 QString accountId = channel->property(History::FieldAccountId).toString();
494 QString threadId = channel->targetId();
495 History::EventType type = History::EventTypeText;
496- updateRoomProperties(accountId, threadId, type, properties, QStringList());
497+ updateRoomProperties(accountId, threadId, type, properties, QStringList(), notify);
498 }
499
500-void HistoryDaemon::updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated)
501+void HistoryDaemon::updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated, bool notify)
502 {
503 if (mBackend->updateRoomInfo(accountId, threadId, type, properties, invalidated)) {
504- QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap());
505- mDBus.notifyThreadsModified(QList<QVariantMap>() << thread);
506+ if (notify) {
507+ QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap());
508+ mDBus.notifyThreadsModified(QList<QVariantMap>() << thread);
509+ }
510 }
511 }
512
513@@ -955,19 +1050,20 @@
514 return;
515 }
516
517- QVariantMap thread = threadForProperties(textChannel->property(History::FieldAccountId).toString(),
518- History::EventTypeText,
519- properties,
520- matchFlagsForChannel(textChannel),
521- true);
522+ QString accountId = textChannel->property(History::FieldAccountId).toString();
523+ QString threadId = threadIdForProperties(accountId,
524+ History::EventTypeText,
525+ properties,
526+ matchFlagsForChannel(textChannel),
527+ true);
528 int count = 1;
529 QList<QVariantMap> attachments;
530 History::MessageType type = History::MessageTypeText;
531 QString subject;
532
533 if (message.hasNonTextContent()) {
534- QString normalizedAccountId = QString(QCryptographicHash::hash(thread[History::FieldAccountId].toString().toLatin1(), QCryptographicHash::Md5).toHex());
535- QString normalizedThreadId = QString(QCryptographicHash::hash(thread[History::FieldThreadId].toString().toLatin1(), QCryptographicHash::Md5).toHex());
536+ QString normalizedAccountId = QString(QCryptographicHash::hash(accountId.toLatin1(), QCryptographicHash::Md5).toHex());
537+ QString normalizedThreadId = QString(QCryptographicHash::hash(threadId.toLatin1(), QCryptographicHash::Md5).toHex());
538 QString normalizedEventId = QString(QCryptographicHash::hash(eventId.toLatin1(), QCryptographicHash::Md5).toHex());
539 QString mmsStoragePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
540
541@@ -1000,8 +1096,8 @@
542 file.close();
543
544 QVariantMap attachment;
545- attachment[History::FieldAccountId] = thread[History::FieldAccountId];
546- attachment[History::FieldThreadId] = thread[History::FieldThreadId];
547+ attachment[History::FieldAccountId] = accountId;
548+ attachment[History::FieldThreadId] = threadId;
549 attachment[History::FieldEventId] = eventId;
550 attachment[History::FieldAttachmentId] = part["identifier"].variant();
551 attachment[History::FieldContentType] = part["content-type"].variant();
552@@ -1013,8 +1109,8 @@
553
554 QVariantMap event;
555 event[History::FieldType] = History::EventTypeText;
556- event[History::FieldAccountId] = thread[History::FieldAccountId];
557- event[History::FieldThreadId] = thread[History::FieldThreadId];
558+ event[History::FieldAccountId] = accountId;
559+ event[History::FieldThreadId] = threadId;
560 event[History::FieldEventId] = eventId;
561 event[History::FieldSenderId] = senderId;
562 event[History::FieldTimestamp] = message.received().toString("yyyy-MM-ddTHH:mm:ss.zzz");
563@@ -1191,7 +1287,7 @@
564 return reply.value();
565 }
566
567-void HistoryDaemon::writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject, const QString &sender, const QString &text)
568+void HistoryDaemon::writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject, const QString &sender, const QString &text, bool notify)
569 {
570 History::TextEvent historyEvent = History::TextEvent(thread[History::FieldAccountId].toString(),
571 thread[History::FieldThreadId].toString(),
572@@ -1207,7 +1303,7 @@
573 QDateTime::currentDateTime(),
574 subject,
575 type);
576- writeEvents(QList<QVariantMap>() << historyEvent.properties(), thread);
577+ writeEvents(QList<QVariantMap>() << historyEvent.properties(), thread, notify);
578 }
579
580 void HistoryDaemon::writeRoomChangesInformationEvents(const QVariantMap &thread, const QVariantMap &interfaceProperties)
581
582=== modified file 'daemon/historydaemon.h'
583--- daemon/historydaemon.h 2016-10-20 13:56:10 +0000
584+++ daemon/historydaemon.h 2017-02-07 15:39:44 +0000
585@@ -1,5 +1,5 @@
586 /*
587- * Copyright (C) 2013-2016 Canonical, Ltd.
588+ * Copyright (C) 2013-2017 Canonical, Ltd.
589 *
590 * Authors:
591 * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
592@@ -42,19 +42,24 @@
593
594 static HistoryDaemon *instance();
595
596- static QVariantMap propertiesFromChannel(const Tp::ChannelPtr &textChannel);
597+ QVariantMap propertiesFromChannel(const Tp::ChannelPtr &textChannel);
598 QVariantMap threadForProperties(const QString &accountId,
599 History::EventType type,
600 const QVariantMap &properties,
601 History::MatchFlags matchFlags = History::MatchCaseSensitive,
602 bool create = true);
603+ QString threadIdForProperties(const QString &accountId,
604+ History::EventType type,
605+ const QVariantMap &properties,
606+ History::MatchFlags matchFlags = History::MatchCaseSensitive,
607+ bool create = true);
608 QString queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties);
609 QString queryEvents(int type, const QVariantMap &sort, const QVariantMap &filter);
610 QVariantMap getSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties);
611 QVariantMap getSingleEvent(int type, const QString &accountId, const QString &threadId, const QString &eventId);
612 QVariantMap getSingleEventFromTextChannel(const Tp::TextChannelPtr textChannel, const QString &messageId);
613
614- bool writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties);
615+ bool writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties, bool notify = true);
616 bool removeEvents(const QList<QVariantMap> &events);
617 bool removeThreads(const QList<QVariantMap> &threads);
618
619@@ -65,6 +70,7 @@
620 void onMessageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message);
621 void onMessageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken);
622 void onTextChannelAvailable(const Tp::TextChannelPtr channel);
623+ void onTextChannelInvalidated(const Tp::TextChannelPtr channel);
624 void onRoomPropertiesChanged(const QVariantMap &properties,const QStringList &invalidated);
625 void onGroupMembersChanged(const Tp::Contacts &groupMembersAdded, const Tp::Contacts &groupLocalPendingMembersAdded,
626 const Tp::Contacts &groupRemotePendingMembersAdded, const Tp::Contacts &groupMembersRemoved,
627@@ -73,14 +79,14 @@
628
629 protected:
630 History::MatchFlags matchFlagsForChannel(const Tp::ChannelPtr &channel);
631- void updateRoomParticipants(const Tp::TextChannelPtr channel);
632- void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap);
633+ void updateRoomParticipants(const Tp::TextChannelPtr channel, bool notify = true);
634+ void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap, bool notify = true);
635 QString hashThread(const QVariantMap &thread);
636 static QVariantMap getInterfaceProperties(const Tp::AbstractInterface *interface);
637- void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties);
638- void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated);
639+ void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties, bool notify = true);
640+ void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated, bool notify = true);
641
642- void writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject = QString(), const QString &sender = QString("self"), const QString &text = QString());
643+ void writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject = QString(), const QString &sender = QString("self"), const QString &text = QString(), bool notify = true);
644
645 void writeRoomChangesInformationEvents(const QVariantMap &thread, const QVariantMap &interfaceProperties);
646 void writeRolesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap);
647@@ -93,6 +99,7 @@
648 QMap<QString, History::MatchFlags> mProtocolFlags;
649 History::PluginPtr mBackend;
650 HistoryServiceDBus mDBus;
651+ QMap<QString, RolesMap> mRolesMap;
652 };
653
654 #endif
655
656=== modified file 'daemon/historyservicedbus.cpp'
657--- daemon/historyservicedbus.cpp 2016-11-24 01:56:01 +0000
658+++ daemon/historyservicedbus.cpp 2017-02-07 15:39:44 +0000
659@@ -75,6 +75,14 @@
660 Q_EMIT EventsRemoved(events);
661 }
662
663+void HistoryServiceDBus::notifyThreadParticipantsChanged(const QVariantMap &thread,
664+ const QList<QVariantMap> &added,
665+ const QList<QVariantMap> &removed,
666+ const QList<QVariantMap> &modified)
667+{
668+ Q_EMIT ThreadParticipantsChanged(thread, added, removed, modified);
669+}
670+
671 QVariantMap HistoryServiceDBus::ThreadForProperties(const QString &accountId,
672 int type,
673 const QVariantMap &properties,
674
675=== modified file 'daemon/historyservicedbus.h'
676--- daemon/historyservicedbus.h 2016-06-17 01:49:46 +0000
677+++ daemon/historyservicedbus.h 2017-02-07 15:39:44 +0000
678@@ -39,6 +39,10 @@
679 void notifyThreadsAdded(const QList<QVariantMap> &threads);
680 void notifyThreadsModified(const QList<QVariantMap> &threads);
681 void notifyThreadsRemoved(const QList<QVariantMap> &threads);
682+ void notifyThreadParticipantsChanged(const QVariantMap &thread,
683+ const QList<QVariantMap> &added,
684+ const QList<QVariantMap> &removed,
685+ const QList<QVariantMap> &modified);
686
687 void notifyEventsAdded(const QList<QVariantMap> &events);
688 void notifyEventsModified(const QList<QVariantMap> &events);
689@@ -70,6 +74,10 @@
690 void ThreadsAdded(const QList<QVariantMap> &threads);
691 void ThreadsModified(const QList<QVariantMap> &threads);
692 void ThreadsRemoved(const QList<QVariantMap> &threads);
693+ void ThreadParticipantsChanged(const QVariantMap &thread,
694+ const QList<QVariantMap> &added,
695+ const QList<QVariantMap> &removed,
696+ const QList<QVariantMap> &modified);
697
698 void EventsAdded(const QList<QVariantMap> &events);
699 void EventsModified(const QList<QVariantMap> &events);
700
701=== modified file 'daemon/textchannelobserver.cpp'
702--- daemon/textchannelobserver.cpp 2016-08-26 14:10:25 +0000
703+++ daemon/textchannelobserver.cpp 2017-02-07 15:39:44 +0000
704@@ -57,6 +57,7 @@
705 {
706 Tp::TextChannelPtr textChannel(qobject_cast<Tp::TextChannel*>(sender()));
707 mChannels.removeAll(textChannel);
708+ Q_EMIT textChannelInvalidated(textChannel);
709 }
710
711 void TextChannelObserver::onMessageReceived(const Tp::ReceivedMessage &message)
712
713=== modified file 'daemon/textchannelobserver.h'
714--- daemon/textchannelobserver.h 2016-08-26 14:10:25 +0000
715+++ daemon/textchannelobserver.h 2017-02-07 15:39:44 +0000
716@@ -37,6 +37,7 @@
717
718 Q_SIGNALS:
719 void channelAvailable(const Tp::TextChannelPtr textChannel);
720+ void textChannelInvalidated(const Tp::TextChannelPtr textChannel);
721 void messageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message);
722 void messageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message);
723 void messageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken);
724
725=== modified file 'plugins/sqlite/sqlitehistoryeventview.cpp'
726--- plugins/sqlite/sqlitehistoryeventview.cpp 2015-01-28 23:08:01 +0000
727+++ plugins/sqlite/sqlitehistoryeventview.cpp 2017-02-07 15:39:44 +0000
728@@ -42,7 +42,16 @@
729 QString condition = mPlugin->filterToString(filter, filterValues);
730 QString order;
731 if (!sort.sortField().isNull()) {
732- order = QString("ORDER BY %1 %2").arg(sort.sortField(), sort.sortOrder() == Qt::AscendingOrder ? "ASC" : "DESC");
733+ // WORKAROUND: Supports multiple fields split by ','
734+ // The idea is to implement a list of sort from the top of the API
735+ Q_FOREACH(const QString& field, sort.sortField().split(",")) {
736+ order += QString("%1 %2, ")
737+ .arg(field)
738+ .arg(sort.sortOrder() == Qt::AscendingOrder ? "ASC" : "DESC");
739+ }
740+
741+ order = QString("ORDER BY %1").arg(order.lastIndexOf(","));
742+ qDebug() << "ORDER" << order;
743 // FIXME: check case sensitiviy
744 }
745
746
747=== modified file 'plugins/sqlite/sqlitehistoryplugin.cpp'
748--- plugins/sqlite/sqlitehistoryplugin.cpp 2016-11-24 01:50:48 +0000
749+++ plugins/sqlite/sqlitehistoryplugin.cpp 2017-02-07 15:39:44 +0000
750@@ -315,8 +315,6 @@
751 return QVariantMap();
752 }
753
754- QSqlQuery query(SQLiteDatabase::instance()->database());
755-
756 History::ChatType chatType = (History::ChatType)properties[History::FieldChatType].toUInt();
757
758 if (chatType == History::ChatTypeRoom) {
759@@ -332,6 +330,24 @@
760 return threadForParticipants(accountId, type, participants.identifiers(), matchFlags);
761 }
762
763+QString SQLiteHistoryPlugin::threadIdForProperties(const QString &accountId, History::EventType type, const QVariantMap &properties, History::MatchFlags matchFlags)
764+{
765+ if (properties.isEmpty()) {
766+ return QString::null;
767+ }
768+
769+ // if chat type is room, just get the threadId directly
770+ History::ChatType chatType = (History::ChatType)properties[History::FieldChatType].toUInt();
771+ if (chatType == History::ChatTypeRoom) {
772+ QString threadId = properties[History::FieldThreadId].toString();
773+ return threadId;
774+ }
775+
776+ // if chat type is anything else, fallback to returning the threadId from the participants list
777+ History::Participants participants = History::Participants::fromVariant(properties[History::FieldParticipantIds]);
778+ return threadForParticipants(accountId, type, participants.identifiers(), matchFlags)[History::FieldThreadId].toString();
779+}
780+
781 QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId,
782 History::EventType type,
783 const QStringList &participants,
784@@ -1290,6 +1306,9 @@
785 chatRoomInfo["SelfRoles"] = query1.value(20).toInt();
786
787 thread[History::FieldChatRoomInfo] = chatRoomInfo;
788+ if (!History::Utils::shouldIncludeParticipants(accountId)) {
789+ thread.remove(History::FieldParticipants);
790+ }
791 }
792 break;
793 case History::EventTypeVoice:
794@@ -1317,7 +1336,8 @@
795 QString queryText;
796 switch (type) {
797 case History::EventTypeText:
798- participantsField = participantsField.arg("text_events", QString::number(type));
799+ // for text events we don't need the participants at all
800+ participantsField = "\"\" as participants";
801 queryText = QString("SELECT accountId, threadId, eventId, senderId, timestamp, newEvent, %1, "
802 "message, messageType, messageStatus, readTimestamp, subject, informationType FROM text_events %2 %3").arg(participantsField, modifiedCondition, order);
803 break;
804@@ -1353,8 +1373,10 @@
805 event[History::FieldSenderId] = query.value(3);
806 event[History::FieldTimestamp] = toLocalTimeString(query.value(4).toDateTime());
807 event[History::FieldNewEvent] = query.value(5).toBool();
808- QStringList participants = query.value(6).toString().split("|,|");
809- event[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
810+ if (type != History::EventTypeText) {
811+ QStringList participants = query.value(6).toString().split("|,|");
812+ event[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
813+ }
814
815 switch (type) {
816 case History::EventTypeText:
817
818=== modified file 'plugins/sqlite/sqlitehistoryplugin.h'
819--- plugins/sqlite/sqlitehistoryplugin.h 2016-09-21 17:44:39 +0000
820+++ plugins/sqlite/sqlitehistoryplugin.h 2017-02-07 15:39:44 +0000
821@@ -59,6 +59,10 @@
822 History::EventType type,
823 const QVariantMap &properties,
824 History::MatchFlags matchFlags = History::MatchCaseSensitive);
825+ virtual QString threadIdForProperties(const QString &accountId,
826+ History::EventType type,
827+ const QVariantMap &properties,
828+ History::MatchFlags matchFlags = History::MatchCaseSensitive) override;
829
830 QList<QVariantMap> eventsForThread(const QVariantMap &thread);
831
832
833=== modified file 'src/manager.cpp'
834--- src/manager.cpp 2016-06-17 01:49:46 +0000
835+++ src/manager.cpp 2017-02-07 15:39:44 +0000
836@@ -65,6 +65,9 @@
837 SIGNAL(threadsRemoved(History::Threads)),
838 SIGNAL(threadsRemoved(History::Threads)));
839 connect(d->dbus.data(),
840+ SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)),
841+ SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)));
842+ connect(d->dbus.data(),
843 SIGNAL(eventsAdded(History::Events)),
844 SIGNAL(eventsAdded(History::Events)));
845 connect(d->dbus.data(),
846
847=== modified file 'src/manager.h'
848--- src/manager.h 2016-06-17 01:49:46 +0000
849+++ src/manager.h 2017-02-07 15:39:44 +0000
850@@ -79,6 +79,7 @@
851 void threadsAdded(const History::Threads &threads);
852 void threadsModified(const History::Threads &threads);
853 void threadsRemoved(const History::Threads &threads);
854+ void threadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified);
855
856 void eventsAdded(const History::Events &events);
857 void eventsModified(const History::Events &events);
858
859=== modified file 'src/managerdbus.cpp'
860--- src/managerdbus.cpp 2016-06-17 01:49:46 +0000
861+++ src/managerdbus.cpp 2017-02-07 15:39:44 +0000
862@@ -50,6 +50,12 @@
863 connection.connect(DBusService, DBusObjectPath, DBusInterface, "ThreadsRemoved",
864 this, SLOT(onThreadsRemoved(QList<QVariantMap>)));
865
866+ connection.connect(DBusService, DBusObjectPath, DBusInterface, "ThreadParticipantsChanged",
867+ this, SLOT(onThreadParticipantsChanged(QVariantMap,
868+ QList<QVariantMap>,
869+ QList<QVariantMap>,
870+ QList<QVariantMap>)));
871+
872 connection.connect(DBusService, DBusObjectPath, DBusInterface, "EventsAdded",
873 this, SLOT(onEventsAdded(QList<QVariantMap>)));
874 connection.connect(DBusService, DBusObjectPath, DBusInterface, "EventsModified",
875@@ -168,6 +174,17 @@
876 Q_EMIT threadsRemoved(threadsFromProperties(threads));
877 }
878
879+void ManagerDBus::onThreadParticipantsChanged(const QVariantMap &thread,
880+ const QList<QVariantMap> &added,
881+ const QList<QVariantMap> &removed,
882+ const QList<QVariantMap> &modified)
883+{
884+ Q_EMIT threadParticipantsChanged(threadsFromProperties(QList<QVariantMap>() << thread).first(),
885+ Participants::fromVariantMapList(added),
886+ Participants::fromVariantMapList(removed),
887+ Participants::fromVariantMapList(modified));
888+}
889+
890 void ManagerDBus::onEventsAdded(const QList<QVariantMap> &events)
891 {
892 Q_EMIT eventsAdded(eventsFromProperties(events));
893
894=== modified file 'src/managerdbus_p.h'
895--- src/managerdbus_p.h 2016-06-17 01:49:46 +0000
896+++ src/managerdbus_p.h 2017-02-07 15:39:44 +0000
897@@ -62,6 +62,10 @@
898 void threadsAdded(const History::Threads &threads);
899 void threadsModified(const History::Threads &threads);
900 void threadsRemoved(const History::Threads &threads);
901+ void threadParticipantsChanged(const History::Thread &thread,
902+ const History::Participants &added,
903+ const History::Participants &removed,
904+ const History::Participants &modified);
905
906 void eventsAdded(const History::Events &events);
907 void eventsModified(const History::Events &events);
908@@ -71,6 +75,10 @@
909 void onThreadsAdded(const QList<QVariantMap> &threads);
910 void onThreadsModified(const QList<QVariantMap> &threads);
911 void onThreadsRemoved(const QList<QVariantMap> &threads);
912+ void onThreadParticipantsChanged(const QVariantMap &thread,
913+ const QList<QVariantMap> &added,
914+ const QList<QVariantMap> &removed,
915+ const QList<QVariantMap> &modified);
916
917 void onEventsAdded(const QList<QVariantMap> &events);
918 void onEventsModified(const QList<QVariantMap> &events);
919
920=== modified file 'src/participant.cpp'
921--- src/participant.cpp 2016-11-24 01:04:37 +0000
922+++ src/participant.cpp 2017-02-07 15:39:44 +0000
923@@ -233,6 +233,15 @@
924 return participants;
925 }
926
927+Participants Participants::fromVariantMapList(const QList<QVariantMap> &list)
928+{
929+ Participants participants;
930+ Q_FOREACH(const QVariantMap& entry, list) {
931+ participants << Participant::fromProperties(entry);
932+ }
933+ return participants;
934+}
935+
936 QVariantList Participants::toVariantList() const
937 {
938 QVariantList list;
939
940=== modified file 'src/participant.h'
941--- src/participant.h 2016-11-24 01:04:37 +0000
942+++ src/participant.h 2017-02-07 15:39:44 +0000
943@@ -79,6 +79,7 @@
944 QStringList identifiers() const;
945 static Participants fromVariant(const QVariant &variant);
946 static Participants fromVariantList(const QVariantList &list);
947+ static Participants fromVariantMapList(const QList<QVariantMap> &list);
948 static Participants fromStringList(const QStringList &list);
949 QVariantList toVariantList() const;
950 History::Participants filterByState(uint state) const;
951
952=== modified file 'src/plugin.h'
953--- src/plugin.h 2016-09-21 17:44:39 +0000
954+++ src/plugin.h 2017-02-07 15:39:44 +0000
955@@ -65,6 +65,10 @@
956 EventType type,
957 const QVariantMap &properties,
958 History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0;
959+ virtual QString threadIdForProperties(const QString &accountId,
960+ EventType type,
961+ const QVariantMap &properties,
962+ History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0;
963
964 virtual QList<QVariantMap> eventsForThread(const QVariantMap &thread) = 0;
965
966
967=== modified file 'src/thread.cpp'
968--- src/thread.cpp 2016-07-12 02:08:11 +0000
969+++ src/thread.cpp 2017-02-07 15:39:44 +0000
970@@ -192,6 +192,22 @@
971 return selfData < otherData;
972 }
973
974+void Thread::removeParticipants(const Participants &participants)
975+{
976+ Q_D(Thread);
977+ Q_FOREACH(const Participant &participant, participants) {
978+ d->participants.removeAll(participant);
979+ }
980+}
981+
982+void Thread::addParticipants(const Participants &participants)
983+{
984+ Q_D(Thread);
985+ Q_FOREACH(const Participant &participant, participants) {
986+ d->participants.append(participant);
987+ }
988+}
989+
990 QVariantMap Thread::properties() const
991 {
992 Q_D(const Thread);
993
994=== modified file 'src/thread.h'
995--- src/thread.h 2016-07-12 01:59:06 +0000
996+++ src/thread.h 2017-02-07 15:39:44 +0000
997@@ -73,6 +73,8 @@
998 ChatType chatType() const;
999 Threads groupedThreads() const;
1000 QVariantMap chatRoomInfo() const;
1001+ void addParticipants(const History::Participants &participants);
1002+ void removeParticipants(const History::Participants &participants);
1003
1004 bool isNull() const;
1005 bool operator==(const Thread &other) const;
1006
1007=== modified file 'src/threadview.cpp'
1008--- src/threadview.cpp 2015-10-01 19:44:45 +0000
1009+++ src/threadview.cpp 2017-02-07 15:39:44 +0000
1010@@ -89,6 +89,18 @@
1011 }
1012 }
1013
1014+void ThreadViewPrivate::_d_threadParticipantsChanged(const History::Thread &thread,
1015+ const History::Participants &added,
1016+ const History::Participants &removed,
1017+ const History::Participants &modified)
1018+{
1019+ Q_Q(ThreadView);
1020+ Threads filtered = filteredThreads(History::Threads() << thread);
1021+ if (!filtered.isEmpty()) {
1022+ Q_EMIT q->threadParticipantsChanged(filtered.first(), added, removed, modified);
1023+ }
1024+}
1025+
1026 // ------------- ThreadView -------------------------------------------------------
1027
1028 ThreadView::ThreadView(History::EventType type,
1029@@ -132,6 +144,9 @@
1030 connect(Manager::instance(),
1031 SIGNAL(threadsRemoved(History::Threads)),
1032 SLOT(_d_threadsRemoved(History::Threads)));
1033+ connect(Manager::instance(),
1034+ SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)),
1035+ SLOT(_d_threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)));
1036 }
1037
1038 ThreadView::~ThreadView()
1039
1040=== modified file 'src/threadview.h'
1041--- src/threadview.h 2015-09-21 20:05:06 +0000
1042+++ src/threadview.h 2017-02-07 15:39:44 +0000
1043@@ -52,12 +52,20 @@
1044 void threadsAdded(const History::Threads &threads);
1045 void threadsModified(const History::Threads &threads);
1046 void threadsRemoved(const History::Threads &threads);
1047+ void threadParticipantsChanged(const History::Thread &thread,
1048+ const History::Participants &added,
1049+ const History::Participants &removed,
1050+ const History::Participants &modified);
1051 void invalidated();
1052
1053 private:
1054 Q_PRIVATE_SLOT(d_func(), void _d_threadsAdded(const History::Threads &threads))
1055 Q_PRIVATE_SLOT(d_func(), void _d_threadsModified(const History::Threads &threads))
1056 Q_PRIVATE_SLOT(d_func(), void _d_threadsRemoved(const History::Threads &threads))
1057+ Q_PRIVATE_SLOT(d_func(), void _d_threadParticipantsChanged(const History::Thread &thread,
1058+ const History::Participants &added,
1059+ const History::Participants &removed,
1060+ const History::Participants &modified))
1061 QScopedPointer<ThreadViewPrivate> d_ptr;
1062
1063 };
1064
1065=== modified file 'src/threadview_p.h'
1066--- src/threadview_p.h 2013-09-17 21:33:34 +0000
1067+++ src/threadview_p.h 2017-02-07 15:39:44 +0000
1068@@ -50,6 +50,10 @@
1069 void _d_threadsAdded(const History::Threads &threads);
1070 void _d_threadsModified(const History::Threads &threads);
1071 void _d_threadsRemoved(const History::Threads &threads);
1072+ void _d_threadParticipantsChanged(const History::Thread &thread,
1073+ const History::Participants &added,
1074+ const History::Participants &removed,
1075+ const History::Participants &modified);
1076
1077 ThreadView *q_ptr;
1078 };
1079
1080=== modified file 'src/utils.cpp'
1081--- src/utils.cpp 2016-11-08 16:02:18 +0000
1082+++ src/utils.cpp 2017-02-07 15:39:44 +0000
1083@@ -175,4 +175,11 @@
1084 return QVariant();
1085 }
1086
1087+bool Utils::shouldIncludeParticipants(const QString &accountId)
1088+{
1089+ // FIXME
1090+ // this is obviously incorrect. we have to query the protocol files as a final solution
1091+ return protocolFromAccountId(accountId) != "irc";
1092+}
1093+
1094 }
1095
1096=== modified file 'src/utils_p.h'
1097--- src/utils_p.h 2016-11-08 16:02:18 +0000
1098+++ src/utils_p.h 2017-02-07 15:39:44 +0000
1099@@ -36,6 +36,7 @@
1100 static bool compareParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags);
1101 static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags);
1102 static bool shouldGroupThread(const Thread &thread);
1103+ static bool shouldIncludeParticipants(const QString &accountId);
1104 static QString normalizeId(const QString &accountId, const QString &id);
1105 static QVariant getUserValue(const QString &interface, const QString &propName);
1106

Subscribers

People subscribed via source and target branches

to all changes: