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

Proposed by Gustavo Pichorim Boiko
Status: Merged
Approved by: Tiago Salem Herrmann
Approved revision: 284
Merged at revision: 263
Proposed branch: lp:~phablet-team/history-service/no_participants_on_threads
Merge into: lp:history-service/staging
Prerequisite: lp:~phablet-team/history-service/single_instance_using_lock_file
Diff against target: 1213 lines (+419/-172)
26 files modified
Ubuntu/History/historyeventmodel.cpp (+1/-1)
Ubuntu/History/historygroupedthreadsmodel.cpp (+54/-2)
Ubuntu/History/historygroupedthreadsmodel.h (+5/-0)
Ubuntu/History/historymodel.cpp (+14/-0)
Ubuntu/History/historymodel.h (+1/-0)
Ubuntu/History/historythreadmodel.cpp (+30/-9)
Ubuntu/History/historythreadmodel.h (+1/-0)
daemon/HistoryService.xml (+9/-0)
daemon/historydaemon.cpp (+119/-65)
daemon/historydaemon.h (+2/-0)
daemon/historyservicedbus.cpp (+6/-1)
daemon/historyservicedbus.h (+1/-0)
plugins/sqlite/sqlitehistoryplugin.cpp (+82/-52)
plugins/sqlite/sqlitehistoryplugin.h (+5/-5)
src/contactmatcher.cpp (+21/-8)
src/eventview.cpp (+1/-1)
src/manager.cpp (+14/-0)
src/manager.h (+1/-1)
src/managerdbus.cpp (+25/-0)
src/managerdbus_p.h (+1/-2)
src/plugin.h (+1/-0)
src/utils.cpp (+8/-4)
src/utils_p.h (+1/-0)
tests/daemon/DaemonTest.cpp (+0/-8)
tests/libhistoryservice/ManagerTest.cpp (+16/-11)
tests/plugins/sqlite/SqlitePluginTest.cpp (+0/-2)
To merge this branch: bzr merge lp:~phablet-team/history-service/no_participants_on_threads
Reviewer Review Type Date Requested Status
Tiago Salem Herrmann (community) Approve
Review via email: mp+319376@code.launchpad.net

Commit message

Do not load the participants from threads automatically. If the client really needs it, it can use the newly added API to fetch the participants.

Description of the change

Do not load the participants from threads automatically. If the client really needs it, it can use the newly added API to fetch the participants.

To post a comment you must log in.
275. By Tiago Salem Herrmann

merge parent branch

276. By Tiago Salem Herrmann

merge parent branch

277. By Gustavo Pichorim Boiko

Deliver the threads with the participants filled for the threads we know will need it.

278. By Gustavo Pichorim Boiko

Cache the requests that didn't match any contact, and fix a wrong condition.

279. By Gustavo Pichorim Boiko

Merge parent

280. By Gustavo Pichorim Boiko

When extracting properties from text channels, avoid parsing participants when
there is no need for it.

281. By Gustavo Pichorim Boiko

Fix filtering of events emitted in signals.

282. By Tiago Salem Herrmann

Avoid duplicate join and leave events

283. By Gustavo Pichorim Boiko

Only mark threads as read if it has unread events.

284. By Gustavo Pichorim Boiko

Fix thread ack query

Revision history for this message
Tiago Salem Herrmann (tiagosh) wrote :

looks good to me.
thanks.

review: Approve

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 2017-03-20 14:27:34 +0000
3+++ Ubuntu/History/historyeventmodel.cpp 2017-03-20 14:27:35 +0000
4@@ -335,7 +335,7 @@
5 mView->disconnect(this);
6 }
7
8- if (mFilter) {
9+ if (mFilter && mFilter->filter().isValid()) {
10 queryFilter = mFilter->filter();
11 } else {
12 // we should not return anything if there is no filter
13
14=== modified file 'Ubuntu/History/historygroupedthreadsmodel.cpp'
15--- Ubuntu/History/historygroupedthreadsmodel.cpp 2015-10-08 19:35:40 +0000
16+++ Ubuntu/History/historygroupedthreadsmodel.cpp 2017-03-20 14:27:35 +0000
17@@ -199,6 +199,21 @@
18 }
19 }
20
21+History::Threads HistoryGroupedThreadsModel::restoreParticipants(const History::Threads &oldThreads, const History::Threads &newThreads)
22+{
23+ History::Threads updated = newThreads;
24+ for(History::Thread &thread : updated) {
25+ if (!thread.participants().isEmpty()) {
26+ continue;
27+ }
28+ int i = oldThreads.indexOf(thread);
29+ if (i >=0) {
30+ thread.addParticipants(oldThreads[i].participants());
31+ }
32+ }
33+ return updated;
34+}
35+
36 void HistoryGroupedThreadsModel::updateQuery()
37 {
38 // remove all entries and call the query update
39@@ -217,6 +232,7 @@
40 processThreadGrouping(thread);
41 }
42
43+ fetchParticipantsIfNeeded(threads);
44 notifyDataChanged();
45 }
46
47@@ -225,7 +241,7 @@
48 Q_FOREACH(const History::Thread &thread, threads) {
49 processThreadGrouping(thread);
50 }
51-
52+ fetchParticipantsIfNeeded(threads);
53 notifyDataChanged();
54 }
55
56@@ -238,6 +254,42 @@
57 notifyDataChanged();
58 }
59
60+void HistoryGroupedThreadsModel::onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified)
61+{
62+ int pos = existingPositionForEntry(thread);
63+ if (pos >= 0) {
64+ HistoryThreadGroup &group = mGroups[pos];
65+ if (group.displayedThread == thread) {
66+ group.displayedThread.removeParticipants(removed);
67+ group.displayedThread.removeParticipants(modified);
68+ group.displayedThread.addParticipants(added);
69+ group.displayedThread.addParticipants(modified);
70+ }
71+
72+ Q_FOREACH(const History::Thread &existingThread, group.threads) {
73+ if (existingThread == thread) {
74+ History::Thread modifiedThread = existingThread;
75+ group.threads.removeOne(existingThread);
76+ modifiedThread.removeParticipants(removed);
77+ modifiedThread.removeParticipants(modified);
78+ modifiedThread.addParticipants(added);
79+ modifiedThread.addParticipants(modified);
80+ group.threads.append(modifiedThread);
81+ }
82+ }
83+ QModelIndex idx = index(pos);
84+ Q_EMIT dataChanged(idx, idx);
85+ }
86+
87+ // watch the contact info for the received participants
88+ Q_FOREACH(const History::Participant &participant, added) {
89+ watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
90+ }
91+ Q_FOREACH(const History::Participant &participant, modified) {
92+ watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
93+ }
94+}
95+
96 void HistoryGroupedThreadsModel::processThreadGrouping(const History::Thread &thread)
97 {
98 QVariantMap queryProperties;
99@@ -262,7 +314,7 @@
100 }
101
102 HistoryThreadGroup &group = mGroups[pos];
103- group.threads = groupedThread.groupedThreads();
104+ group.threads = restoreParticipants(group.threads, groupedThread.groupedThreads());
105
106 updateDisplayedThread(group);
107 markGroupAsChanged(group);
108
109=== modified file 'Ubuntu/History/historygroupedthreadsmodel.h'
110--- Ubuntu/History/historygroupedthreadsmodel.h 2015-09-29 20:34:22 +0000
111+++ Ubuntu/History/historygroupedthreadsmodel.h 2017-03-20 14:27:35 +0000
112@@ -67,12 +67,17 @@
113 int existingPositionForEntry(const History::Thread &thread) const;
114 void removeGroup(const HistoryThreadGroup &group);
115 void updateDisplayedThread(HistoryThreadGroup &group);
116+ History::Threads restoreParticipants(const History::Threads &oldThreads, const History::Threads &newThreads);
117
118 protected Q_SLOTS:
119 virtual void updateQuery();
120 virtual void onThreadsAdded(const History::Threads &threads);
121 virtual void onThreadsModified(const History::Threads &threads);
122 virtual void onThreadsRemoved(const History::Threads &threads);
123+ void onThreadParticipantsChanged(const History::Thread &thread,
124+ const History::Participants &added,
125+ const History::Participants &removed,
126+ const History::Participants &modified) override;
127
128 private Q_SLOTS:
129 void processThreadGrouping(const History::Thread &thread);
130
131=== modified file 'Ubuntu/History/historymodel.cpp'
132--- Ubuntu/History/historymodel.cpp 2017-03-20 14:27:34 +0000
133+++ Ubuntu/History/historymodel.cpp 2017-03-20 14:27:35 +0000
134@@ -342,6 +342,20 @@
135 return QString::null;
136 }
137
138+void HistoryModel::requestThreadParticipants(const QVariantList &threads)
139+{
140+ History::Threads theThreads;
141+ Q_FOREACH(const QVariant &threadVariant, threads) {
142+ History::Thread theThread = History::Thread::fromProperties(threadVariant.toMap());
143+ // if the given thread already has the list of participants, there is no point
144+ // in fetching it again
145+ if (theThread.participants().isEmpty()) {
146+ theThreads << theThread;
147+ }
148+ }
149+ History::Manager::instance()->requestThreadParticipants(theThreads);
150+}
151+
152 bool HistoryModel::writeTextInformationEvent(const QString &accountId, const QString &threadId, const QStringList &participants, const QString &message, int informationType, const QString &subject)
153 {
154 if (participants.isEmpty() || threadId.isEmpty() || accountId.isEmpty()) {
155
156=== modified file 'Ubuntu/History/historymodel.h'
157--- Ubuntu/History/historymodel.h 2017-03-20 14:27:34 +0000
158+++ Ubuntu/History/historymodel.h 2017-03-20 14:27:35 +0000
159@@ -168,6 +168,7 @@
160 const QStringList &participants,
161 int matchFlags = (int)History::MatchCaseSensitive,
162 bool create = false);
163+ Q_INVOKABLE void requestThreadParticipants(const QVariantList &threads);
164 Q_INVOKABLE bool writeTextInformationEvent(const QString &accountId,
165 const QString &threadId,
166 const QStringList &participants,
167
168=== modified file 'Ubuntu/History/historythreadmodel.cpp'
169--- Ubuntu/History/historythreadmodel.cpp 2017-03-20 14:27:34 +0000
170+++ Ubuntu/History/historythreadmodel.cpp 2017-03-20 14:27:35 +0000
171@@ -26,6 +26,8 @@
172 #include "voiceevent.h"
173 #include <QDBusMetaType>
174
175+#include <QDebug>
176+
177 Q_DECLARE_METATYPE(History::TextEventAttachments)
178 Q_DECLARE_METATYPE(QList<QVariantMap>)
179
180@@ -190,7 +192,6 @@
181 }
182 break;
183 }
184-
185 return result;
186 }
187
188@@ -214,13 +215,6 @@
189 mCanFetchMore = false;
190 Q_EMIT canFetchMoreChanged();
191 } else {
192- Q_FOREACH(const History::Thread &thread, threads) {
193- // insert the identifiers in the contact map
194- Q_FOREACH(const History::Participant &participant, thread.participants()) {
195- watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
196- }
197- }
198-
199 beginInsertRows(QModelIndex(), mThreads.count(), mThreads.count() + threads.count() - 1);
200 mThreads << threads;
201 endInsertRows();
202@@ -327,6 +321,29 @@
203 QModelIndex idx = index(pos);
204 Q_EMIT dataChanged(idx, idx);
205 }
206+
207+ // watch the contact info for the received participants
208+ Q_FOREACH(const History::Participant &participant, added) {
209+ watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
210+ }
211+ Q_FOREACH(const History::Participant &participant, modified) {
212+ watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
213+ }
214+}
215+
216+void HistoryThreadModel::fetchParticipantsIfNeeded(const History::Threads &threads)
217+{
218+ History::Threads filtered;
219+ Q_FOREACH(const History::Thread &thread, threads) {
220+ if (thread.type() == History::EventTypeText && thread.participants().isEmpty() &&
221+ (thread.chatType() != History::ChatTypeRoom || thread.accountId().startsWith("ofono"))) {
222+ filtered << thread;
223+ }
224+ }
225+ if (filtered.isEmpty()) {
226+ return;
227+ }
228+ History::Manager::instance()->requestThreadParticipants(filtered);
229 }
230
231 void HistoryThreadModel::onThreadsAdded(const History::Threads &threads)
232@@ -346,6 +363,7 @@
233 mThreads.insert(pos, thread);
234 endInsertRows();
235 }
236+ fetchParticipantsIfNeeded(threads);
237 }
238
239 void HistoryThreadModel::onThreadsModified(const History::Threads &threads)
240@@ -367,6 +385,7 @@
241 if (!newThreads.isEmpty()) {
242 onThreadsAdded(newThreads);
243 }
244+ fetchParticipantsIfNeeded(threads);
245 }
246
247 void HistoryThreadModel::onThreadsRemoved(const History::Threads &threads)
248@@ -387,5 +406,7 @@
249
250 History::Threads HistoryThreadModel::fetchNextPage()
251 {
252- return mThreadView->nextPage();
253+ History::Threads threads = mThreadView->nextPage();
254+ fetchParticipantsIfNeeded(threads);
255+ return threads;
256 }
257
258=== modified file 'Ubuntu/History/historythreadmodel.h'
259--- Ubuntu/History/historythreadmodel.h 2017-03-20 14:27:34 +0000
260+++ Ubuntu/History/historythreadmodel.h 2017-03-20 14:27:35 +0000
261@@ -79,6 +79,7 @@
262 virtual void onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified);
263
264 protected:
265+ void fetchParticipantsIfNeeded(const History::Threads &threads);
266 History::Threads fetchNextPage();
267 bool mCanFetchMore;
268 bool mGroupThreads;
269
270=== modified file 'daemon/HistoryService.xml'
271--- daemon/HistoryService.xml 2017-03-20 14:27:34 +0000
272+++ daemon/HistoryService.xml 2017-03-20 14:27:35 +0000
273@@ -35,6 +35,15 @@
274 <arg type="a{sv}" direction="out"/>
275 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
276 </method>
277+ <method name="ParticipantsForThreads">
278+ <dox:d><![CDATA[
279+ Return the participants for the given threads
280+ ]]></dox:d>
281+ <arg name="threadIds" type="a(a{sv})" direction="in"/>
282+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList &lt; QVariantMap &gt;"/>
283+ <arg name="participants" type="a(a{sv})" direction="out"/>
284+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList &lt; QVariantMap &gt;"/>
285+ </method>
286 <method name="WriteEvents">
287 <dox:d><![CDATA[
288 Write the given events to the storage.
289
290=== modified file 'daemon/historydaemon.cpp'
291--- daemon/historydaemon.cpp 2017-03-20 14:27:34 +0000
292+++ daemon/historydaemon.cpp 2017-03-20 14:27:35 +0000
293@@ -85,10 +85,11 @@
294 {
295 Q_FOREACH (QVariant participant, thread[History::FieldParticipants].toList()) {
296 // found if same identifier and as member into thread info
297+ QVariantMap participantMap = participant.toMap();
298 if (History::Utils::compareIds(thread[History::FieldAccountId].toString(),
299 contact->id(),
300- participant.toMap()[History::FieldIdentifier].toString()) &&
301- participant.toMap()[History::FieldParticipantState].toUInt() == History::ParticipantStateRegular)
302+ participantMap[History::FieldIdentifier].toString()) &&
303+ participantMap[History::FieldParticipantState].toUInt() == History::ParticipantStateRegular)
304 {
305 return true;
306 }
307@@ -205,56 +206,58 @@
308 QStringList participantIds;
309 QString accountId = textChannel->property(History::FieldAccountId).toString();
310
311- ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>();
312- RolesMap roles;
313- if (roles_interface) {
314- if (mRolesMap.contains(textChannel->objectPath())) {
315- roles = mRolesMap[textChannel->objectPath()];
316- }
317- }
318-
319- Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) {
320- QVariantMap contactProperties;
321- contactProperties[History::FieldAlias] = contact->alias();
322- contactProperties[History::FieldAccountId] = accountId;
323- contactProperties[History::FieldIdentifier] = contact->id();
324- contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
325- contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
326- participantIds << contact->id();
327- participants << contactProperties;
328- }
329-
330- Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(false)) {
331- QVariantMap contactProperties;
332- contactProperties[History::FieldAlias] = contact->alias();
333- contactProperties[History::FieldAccountId] = accountId;
334- contactProperties[History::FieldIdentifier] = contact->id();
335- contactProperties[History::FieldParticipantState] = History::ParticipantStateRemotePending;
336- contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
337- participantIds << contact->id();
338- participants << contactProperties;
339- }
340-
341- Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(false)) {
342- QVariantMap contactProperties;
343- contactProperties[History::FieldAlias] = contact->alias();
344- contactProperties[History::FieldAccountId] = accountId;
345- contactProperties[History::FieldIdentifier] = contact->id();
346- contactProperties[History::FieldParticipantState] = History::ParticipantStateLocalPending;
347- contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
348- participantIds << contact->id();
349- participants << contactProperties;
350- }
351-
352- if (participants.isEmpty() && textChannel->targetHandleType() == Tp::HandleTypeContact &&
353- textChannel->targetContact() == textChannel->connection()->selfContact()) {
354- QVariantMap contactProperties;
355- contactProperties[History::FieldAlias] = textChannel->targetContact()->alias();
356- contactProperties[History::FieldAccountId] = accountId;
357- contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id();
358- contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
359- participantIds << textChannel->targetContact()->id();
360- participants << contactProperties;
361+ if (History::Utils::shouldIncludeParticipants(accountId, fromTelepathyHandleType(textChannel->targetHandleType()))) {
362+ ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>();
363+ RolesMap roles;
364+ if (roles_interface) {
365+ if (mRolesMap.contains(textChannel->objectPath())) {
366+ roles = mRolesMap[textChannel->objectPath()];
367+ }
368+ }
369+
370+ Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) {
371+ QVariantMap contactProperties;
372+ contactProperties[History::FieldAlias] = contact->alias();
373+ contactProperties[History::FieldAccountId] = accountId;
374+ contactProperties[History::FieldIdentifier] = contact->id();
375+ contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
376+ contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
377+ participantIds << contact->id();
378+ participants << contactProperties;
379+ }
380+
381+ Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(false)) {
382+ QVariantMap contactProperties;
383+ contactProperties[History::FieldAlias] = contact->alias();
384+ contactProperties[History::FieldAccountId] = accountId;
385+ contactProperties[History::FieldIdentifier] = contact->id();
386+ contactProperties[History::FieldParticipantState] = History::ParticipantStateRemotePending;
387+ contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
388+ participantIds << contact->id();
389+ participants << contactProperties;
390+ }
391+
392+ Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(false)) {
393+ QVariantMap contactProperties;
394+ contactProperties[History::FieldAlias] = contact->alias();
395+ contactProperties[History::FieldAccountId] = accountId;
396+ contactProperties[History::FieldIdentifier] = contact->id();
397+ contactProperties[History::FieldParticipantState] = History::ParticipantStateLocalPending;
398+ contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
399+ participantIds << contact->id();
400+ participants << contactProperties;
401+ }
402+
403+ if (participants.isEmpty() && textChannel->targetHandleType() == Tp::HandleTypeContact &&
404+ textChannel->targetContact() == textChannel->connection()->selfContact()) {
405+ QVariantMap contactProperties;
406+ contactProperties[History::FieldAlias] = textChannel->targetContact()->alias();
407+ contactProperties[History::FieldAccountId] = accountId;
408+ contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id();
409+ contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
410+ participantIds << textChannel->targetContact()->id();
411+ participants << contactProperties;
412+ }
413 }
414
415 // We map chatType directly from telepathy targetHandleType: None, Contact, Room
416@@ -358,6 +361,14 @@
417 return threadId;
418 }
419
420+QList<QVariantMap> HistoryDaemon::participantsForThreads(const QList<QVariantMap> &threadIds)
421+{
422+ if (!mBackend) {
423+ return QList<QVariantMap>();
424+ }
425+ return mBackend->participantsForThreads(threadIds);
426+}
427+
428 QString HistoryDaemon::queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties)
429 {
430 if (!mBackend) {
431@@ -665,6 +676,24 @@
432 void HistoryDaemon::onTextChannelInvalidated(const Tp::TextChannelPtr channel)
433 {
434 mRolesMap.remove(channel->objectPath());
435+ QString accountId = channel->property(History::FieldAccountId).toString();
436+ QVariantMap properties = propertiesFromChannel(channel);
437+
438+ // first try to fetch the existing thread to see if there is any.
439+ QVariantMap thread = threadForProperties(accountId,
440+ History::EventTypeText,
441+ properties,
442+ matchFlagsForChannel(channel),
443+ false);
444+
445+ QVariantMap roomInfo = thread[History::FieldChatRoomInfo].toMap();
446+ if ((roomInfo.contains("Persistent") && !roomInfo["Persistent"].toBool()) && History::TelepathyHelper::instance()->accountForId(accountId)->protocolName() != "ofono") {
447+ writeInformationEvent(thread, History::InformationTypeSelfLeaving);
448+ // update backend
449+ updateRoomProperties(channel, QVariantMap{{"Joined", false}});
450+ }
451+
452+ channel->disconnect(this);
453 }
454
455 void HistoryDaemon::onTextChannelAvailable(const Tp::TextChannelPtr channel)
456@@ -791,7 +820,8 @@
457 if (hasMembersAdded) {
458 Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) {
459 // if this member was not previously regular member in thread, notify about his join
460- if (!foundAsMemberInThread(contact, thread)) {
461+ if (!foundAsMemberInThread(contact, thread) && contact->id() != channel->groupSelfContact()->id()) {
462+
463 writeInformationEvent(thread, History::InformationTypeJoined, contact->alias(), QString(), QString(), true);
464
465 QVariantMap participant;
466@@ -817,9 +847,11 @@
467 break;
468 }
469 }
470- writeInformationEvent(thread, type);
471- // update backend
472- updateRoomProperties(channel, QVariantMap{{"Joined", false}}, true);
473+ if (thread[History::FieldChatRoomInfo].toMap()["Joined"].toBool()) {
474+ writeInformationEvent(thread, type);
475+ // update backend
476+ updateRoomProperties(channel, QVariantMap{{"Joined", false}}, true);
477+ }
478 }
479 else // don't notify any other group member removal if we are leaving the group
480 {
481@@ -977,9 +1009,20 @@
482 void HistoryDaemon::onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message)
483 {
484 QString eventId;
485- Tp::MessagePart header = message.header();
486 QString senderId;
487+
488+ QString accountId = textChannel->property(History::FieldAccountId).toString();
489+ QString threadId = textChannel->property(History::FieldThreadId).toString();
490 QVariantMap properties = propertiesFromChannel(textChannel);
491+
492+ if (threadId.isNull()) {
493+ threadId = threadIdForProperties(accountId,
494+ History::EventTypeText,
495+ properties,
496+ matchFlagsForChannel(textChannel),
497+ true);
498+ }
499+
500 History::MessageStatus status = History::MessageStatusUnknown;
501 if (!message.sender() || message.sender()->handle().at(0) == textChannel->connection()->selfHandle()) {
502 senderId = "self";
503@@ -1002,7 +1045,7 @@
504 if (message.isDeliveryReport() && message.deliveryDetails().hasOriginalToken()) {
505 // at this point we assume the delivery report is for a message that was already
506 // sent and properly saved at our database, so we can safely get it here to update
507- QVariantMap textEvent = getSingleEventFromTextChannel(textChannel, message.deliveryDetails().originalToken());
508+ QVariantMap textEvent = getSingleEvent(History::EventTypeText, accountId, threadId, message.deliveryDetails().originalToken());
509 if (textEvent.isEmpty()) {
510 qWarning() << "Cound not find the original event to update with delivery details.";
511 return;
512@@ -1022,13 +1065,6 @@
513
514 return;
515 }
516-
517- QString accountId = textChannel->property(History::FieldAccountId).toString();
518- QString threadId = threadIdForProperties(accountId,
519- History::EventTypeText,
520- properties,
521- matchFlagsForChannel(textChannel),
522- true);
523 int count = 1;
524 QList<QVariantMap> attachments;
525 History::MessageType type = History::MessageTypeText;
526@@ -1348,3 +1384,21 @@
527
528 return status;
529 }
530+
531+History::ChatType HistoryDaemon::fromTelepathyHandleType(const Tp::HandleType &type)
532+{
533+ History::ChatType chatType;
534+ switch(type) {
535+ case Tp::HandleTypeContact:
536+ chatType = History::ChatTypeContact;
537+ break;
538+ case Tp::HandleTypeNone:
539+ chatType = History::ChatTypeNone;
540+ break;
541+ case Tp::HandleTypeRoom:
542+ chatType = History::ChatTypeRoom;
543+ break;
544+ }
545+
546+ return chatType;
547+}
548
549=== modified file 'daemon/historydaemon.h'
550--- daemon/historydaemon.h 2017-03-20 14:27:34 +0000
551+++ daemon/historydaemon.h 2017-03-20 14:27:35 +0000
552@@ -53,6 +53,7 @@
553 const QVariantMap &properties,
554 History::MatchFlags matchFlags = History::MatchCaseSensitive,
555 bool create = true);
556+ QList<QVariantMap> participantsForThreads(const QList<QVariantMap> &threadIds);
557 QString queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties);
558 QString queryEvents(int type, const QVariantMap &sort, const QVariantMap &filter);
559 QVariantMap getSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties);
560@@ -93,6 +94,7 @@
561 void writeRolesChangesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap);
562
563 static History::MessageStatus fromTelepathyDeliveryStatus(Tp::DeliveryStatus deliveryStatus);
564+ static History::ChatType fromTelepathyHandleType(const Tp::HandleType &type);
565 private:
566 HistoryDaemon(QObject *parent = 0);
567
568
569=== modified file 'daemon/historyservicedbus.cpp'
570--- daemon/historyservicedbus.cpp 2017-03-20 14:27:34 +0000
571+++ daemon/historyservicedbus.cpp 2017-03-20 14:27:35 +0000
572@@ -105,7 +105,12 @@
573 (History::EventType) type,
574 properties,
575 (History::MatchFlags) matchFlags,
576- create);
577+ create);
578+}
579+
580+QList<QVariantMap> HistoryServiceDBus::ParticipantsForThreads(const QList<QVariantMap> &threadIds)
581+{
582+ return HistoryDaemon::instance()->participantsForThreads(threadIds);
583 }
584
585 QVariantMap HistoryServiceDBus::ThreadForParticipants(const QString &accountId,
586
587=== modified file 'daemon/historyservicedbus.h'
588--- daemon/historyservicedbus.h 2017-03-20 14:27:34 +0000
589+++ daemon/historyservicedbus.h 2017-03-20 14:27:35 +0000
590@@ -59,6 +59,7 @@
591 const QVariantMap &properties,
592 int matchFlags,
593 bool create);
594+ QList<QVariantMap> ParticipantsForThreads(const QList<QVariantMap> &threadIds);
595 bool WriteEvents(const QList <QVariantMap> &events);
596 bool RemoveThreads(const QList <QVariantMap> &threads);
597 bool RemoveEvents(const QList <QVariantMap> &events);
598
599=== modified file 'plugins/sqlite/sqlitehistoryplugin.cpp'
600--- plugins/sqlite/sqlitehistoryplugin.cpp 2017-03-20 14:27:34 +0000
601+++ plugins/sqlite/sqlitehistoryplugin.cpp 2017-03-20 14:27:35 +0000
602@@ -315,13 +315,30 @@
603 return QVariantMap();
604 }
605
606+ // first check if the thread actually has anything to change
607+ query.prepare("SELECT unreadCount from threads WHERE accountId=:accountId AND threadId=:threadId AND type=:type");
608+ query.bindValue(":accountId", thread[History::FieldAccountId].toString());
609+ query.bindValue(":threadId", thread[History::FieldThreadId].toString());
610+ query.bindValue(":type", (uint)History::EventTypeText);
611+ if (!query.exec() || !query.next()) {
612+ qCritical() << "Failed to verify the unread messages of the thread. Error:" << query.lastError();
613+ return QVariantMap();
614+ }
615+
616+
617+ int unreadCount = query.value(0).toUInt();
618+ if (unreadCount == 0) {
619+ // no messages to ack, so no need to update anything
620+ return QVariantMap();
621+ }
622+
623 query.prepare("UPDATE text_events SET newEvent=:newEvent WHERE accountId=:accountId AND threadId=:threadId AND newEvent=1");
624 query.bindValue(":accountId", thread[History::FieldAccountId].toString());
625 query.bindValue(":threadId", thread[History::FieldThreadId].toString());
626 query.bindValue(":newEvent", false);
627
628 if (!query.exec()) {
629- qCritical() << "Failed to mark thread as read: Error:" << query.lastError() << query.lastQuery() << query.executedQuery();
630+ qCritical() << "Failed to mark thread as read: Error:" << query.lastError();
631 return QVariantMap();
632 }
633
634@@ -379,6 +396,44 @@
635 return threadForParticipants(accountId, type, participants.identifiers(), matchFlags)[History::FieldThreadId].toString();
636 }
637
638+QList<QVariantMap> SQLiteHistoryPlugin::participantsForThreads(const QList<QVariantMap> &threadIds)
639+{
640+ QList<QVariantMap> results;
641+ Q_FOREACH(const QVariantMap &thread, threadIds) {
642+ QString accountId = thread[History::FieldAccountId].toString();
643+ QString threadId = thread[History::FieldThreadId].toString();
644+ History::EventType type = (History::EventType)thread[History::FieldType].toUInt();
645+ QVariantMap result = thread;
646+
647+ QSqlQuery query;
648+ query.prepare("SELECT normalizedId, alias, state, roles FROM thread_participants "
649+ "WHERE accountId=:accountId AND threadId=:threadId AND type=:type");
650+ query.bindValue(":accountId", accountId);
651+ query.bindValue(":threadId", threadId);
652+ query.bindValue(":type", type);
653+ QVariantList participants;
654+ if (!query.exec()) {
655+ qWarning() << "Failed to retrieve participants. Error:" << query.lastError().text() << query.lastQuery();
656+ results << result;
657+ continue;
658+ }
659+
660+ while (query.next()) {
661+ QVariantMap participant;
662+ QString identifier = query.value(0).toString();
663+ participant[History::FieldIdentifier] = identifier;
664+ participant[History::FieldAlias] = query.value(1);
665+ participant[History::FieldParticipantState] = query.value(2);
666+ participant[History::FieldParticipantRoles] = query.value(3);
667+ participants << History::ContactMatcher::instance()->contactInfo(accountId, identifier, true, participant);
668+ }
669+
670+ result[History::FieldParticipants] = participants;
671+ results << result;
672+ }
673+ return results;
674+}
675+
676 QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId,
677 History::EventType type,
678 const QStringList &participants,
679@@ -1140,22 +1195,6 @@
680 << "threads.unreadCount"
681 << "threads.lastEventTimestamp";
682
683- // get the participants in the query already
684- fields << "(SELECT group_concat(thread_participants.participantId, \"|,|\") "
685- "FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
686- "AND thread_participants.threadId=threads.threadId "
687- "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as participants";
688-
689- fields << "(SELECT group_concat(thread_participants.state, \"|,|\") "
690- "FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
691- "AND thread_participants.threadId=threads.threadId "
692- "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as state";
693-
694- fields << "(SELECT group_concat(thread_participants.roles, \"|,|\") "
695- "FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
696- "AND thread_participants.threadId=threads.threadId "
697- "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as roles";
698-
699 QStringList extraFields;
700 QString table;
701
702@@ -1183,6 +1222,7 @@
703 QList<QVariantMap> SQLiteHistoryPlugin::parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties)
704 {
705 QList<QVariantMap> threads;
706+ QList<QVariantMap> threadsWithoutParticipants;
707 QSqlQuery attachmentsQuery(SQLiteDatabase::instance()->database());
708 QList<QVariantMap> attachments;
709 bool grouped = false;
710@@ -1217,31 +1257,11 @@
711 thread[History::FieldEventId] = query.value(2);
712 thread[History::FieldCount] = query.value(3);
713 thread[History::FieldUnreadCount] = query.value(4);
714- QStringList participants = query.value(6).toString().split("|,|", QString::SkipEmptyParts);
715- QList<int> participantStatus;
716- QStringList participantStatusString = query.value(7).toString().split("|,|", QString::SkipEmptyParts);
717- Q_FOREACH(const QString &statusString, participantStatusString) {
718- participantStatus << statusString.toUInt();
719- }
720- QStringList participantRolesString = query.value(8).toString().split("|,|", QString::SkipEmptyParts);
721- QList<int> participantRoles;
722- Q_FOREACH(const QString &rolesString, participantRolesString) {
723- participantRoles << rolesString.toUInt();
724- }
725- QVariantList contactList;
726- QVariantList contactInfo = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
727- for (int i = 0; i < contactInfo.count(); ++i) {
728- QVariantMap map = contactInfo[i].toMap();
729- map["state"] = participantStatus[i];
730- map["roles"] = participantRoles[i];
731- contactList << map;
732- }
733- thread[History::FieldParticipants] = contactList;
734
735 // the generic event fields
736- thread[History::FieldSenderId] = query.value(9);
737+ thread[History::FieldSenderId] = query.value(6);
738 thread[History::FieldTimestamp] = toLocalTimeString(query.value(5).toDateTime());
739- thread[History::FieldNewEvent] = query.value(10).toBool();
740+ thread[History::FieldNewEvent] = query.value(7).toBool();
741
742 // the next step is to get the last event
743 switch (type) {
744@@ -1272,13 +1292,13 @@
745 thread[History::FieldAttachments] = QVariant::fromValue(attachments);
746 attachments.clear();
747 }
748- thread[History::FieldMessage] = query.value(11);
749- thread[History::FieldMessageType] = query.value(12);
750- thread[History::FieldMessageStatus] = query.value(13);
751- thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(14).toDateTime());
752- thread[History::FieldChatType] = query.value(15).toUInt();
753+ thread[History::FieldMessage] = query.value(8);
754+ thread[History::FieldMessageType] = query.value(9);
755+ thread[History::FieldMessageStatus] = query.value(10);
756+ thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(11).toDateTime());
757+ thread[History::FieldChatType] = query.value(12).toUInt();
758
759- if (thread[History::FieldChatType].toInt() == 2) {
760+ if (thread[History::FieldChatType].toInt() == History::ChatTypeRoom) {
761 QVariantMap chatRoomInfo;
762 QSqlQuery query1(SQLiteDatabase::instance()->database());
763
764@@ -1337,19 +1357,29 @@
765 chatRoomInfo["SelfRoles"] = query1.value(20).toInt();
766
767 thread[History::FieldChatRoomInfo] = chatRoomInfo;
768- if (!History::Utils::shouldIncludeParticipants(History::Thread::fromProperties(thread))) {
769- thread.remove(History::FieldParticipants);
770- }
771+ }
772+ if (!History::Utils::shouldIncludeParticipants(History::Thread::fromProperties(thread))) {
773+ thread.remove(History::FieldParticipants);
774+ threadsWithoutParticipants << thread;
775+ } else {
776+ threads << thread;
777 }
778 break;
779 case History::EventTypeVoice:
780- thread[History::FieldMissed] = query.value(12);
781- thread[History::FieldDuration] = query.value(11);
782- thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(13).toString(), true);
783+ thread[History::FieldMissed] = query.value(9);
784+ thread[History::FieldDuration] = query.value(8);
785+ thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(10).toString(), true);
786+ threads << thread;
787 break;
788 }
789- threads << thread;
790 }
791+
792+ // get the participants
793+ threads = participantsForThreads(threads);
794+
795+ // and append the threads with no participants
796+ threads << threadsWithoutParticipants;
797+
798 return threads;
799 }
800
801
802=== modified file 'plugins/sqlite/sqlitehistoryplugin.h'
803--- plugins/sqlite/sqlitehistoryplugin.h 2017-03-20 14:27:34 +0000
804+++ plugins/sqlite/sqlitehistoryplugin.h 2017-03-20 14:27:35 +0000
805@@ -59,11 +59,11 @@
806 History::EventType type,
807 const QVariantMap &properties,
808 History::MatchFlags matchFlags = History::MatchCaseSensitive);
809- virtual QString threadIdForProperties(const QString &accountId,
810- History::EventType type,
811- const QVariantMap &properties,
812- History::MatchFlags matchFlags = History::MatchCaseSensitive) override;
813-
814+ QString threadIdForProperties(const QString &accountId,
815+ History::EventType type,
816+ const QVariantMap &properties,
817+ History::MatchFlags matchFlags = History::MatchCaseSensitive) override;
818+ QList<QVariantMap> participantsForThreads(const QList<QVariantMap> &threadIds) override;
819 QList<QVariantMap> eventsForThread(const QVariantMap &thread);
820
821 QVariantMap getSingleThread(History::EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap());
822
823=== modified file 'src/contactmatcher.cpp'
824--- src/contactmatcher.cpp 2017-03-20 14:27:34 +0000
825+++ src/contactmatcher.cpp 2017-03-20 14:27:35 +0000
826@@ -102,14 +102,12 @@
827
828 QString normalizedId = normalizeId(identifier);
829
830+ QVariantMap map;
831 // first do a simple string match on the map
832 if (internalMap.contains(normalizedId)) {
833- return internalMap[normalizedId];
834- }
835-
836- QVariantMap map;
837- // and if there was no match, asynchronously request the info, and return an empty map for now
838- if (History::TelepathyHelper::instance()->ready()) {
839+ map = internalMap[normalizedId];
840+ } else if (History::TelepathyHelper::instance()->ready()) {
841+ // and if there was no match, asynchronously request the info, and return an empty map for now
842 map = requestContactInfo(accountId, normalizedId, synchronous);
843 } else if (!synchronous) {
844 RequestInfo info{accountId, normalizedId};
845@@ -314,9 +312,15 @@
846 {
847 QString normalizedId = normalizeId(identifier);
848 QStringList addressableVCardFields = addressableFields(accountId);
849+
850+ QVariantMap contactInfo;
851+ contactInfo[History::FieldIdentifier] = identifier;
852+ contactInfo[History::FieldAccountId] = accountId;
853+
854 if (addressableVCardFields.isEmpty()) {
855+ mContactMap[accountId][identifier] = contactInfo;
856 // FIXME: add support for generic accounts
857- return QVariantMap();
858+ return contactInfo;
859 }
860
861 bool phoneCompare = addressableVCardFields.contains("tel");
862@@ -357,7 +361,8 @@
863 if (synchronous) {
864 QList<QContact> contacts = mManager->contacts(topLevelFilter, QList<QContactSortOrder>(), hint);
865 if (contacts.isEmpty()) {
866- return QVariantMap();
867+ mContactMap[accountId][identifier] = contactInfo;
868+ return contactInfo;
869 }
870 // for synchronous requests, return the results right away.
871 return matchAndUpdate(accountId, normalizedId, contacts.first());
872@@ -466,6 +471,14 @@
873 return mAddressableFields[accountId];
874 }
875
876+ // FIXME: hardcoding account IDs here is not a good idea, we have to fix addressable fields on
877+ // the protocols themselves
878+ if (accountId.startsWith("irc/irc")) {
879+ QStringList empty;
880+ mAddressableFields[accountId] = empty;
881+ return empty;
882+ }
883+
884 Tp::AccountPtr account = History::TelepathyHelper::instance()->accountForId(accountId);
885 QStringList fields;
886 if (!account.isNull()) {
887
888=== modified file 'src/eventview.cpp'
889--- src/eventview.cpp 2017-03-20 14:27:34 +0000
890+++ src/eventview.cpp 2017-03-20 14:27:35 +0000
891@@ -53,7 +53,7 @@
892 }
893
894 if (filterNull || filter.match(event.properties())) {
895- filtered << events;
896+ filtered << event;
897 }
898 }
899
900
901=== modified file 'src/manager.cpp'
902--- src/manager.cpp 2017-03-20 14:27:34 +0000
903+++ src/manager.cpp 2017-03-20 14:27:35 +0000
904@@ -164,6 +164,20 @@
905 return d->dbus->threadForProperties(accountId, type, properties, matchFlags, create);
906 }
907
908+/**
909+ * @brief Request the list of participants of the given threads to the service
910+ * @param threads The threads to be filled
911+ *
912+ * This is an asychronous request. When finished, the signal @ref threadParticipantsChanged
913+ * will be emitted for the given threads.
914+ */
915+void Manager::requestThreadParticipants(const Threads &threads)
916+{
917+ Q_D(Manager);
918+
919+ d->dbus->requestThreadParticipants(threads);
920+}
921+
922 Thread Manager::getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties)
923 {
924 Q_D(Manager);
925
926=== modified file 'src/manager.h'
927--- src/manager.h 2017-03-20 14:27:34 +0000
928+++ src/manager.h 2017-03-20 14:27:35 +0000
929@@ -66,7 +66,7 @@
930 const QVariantMap &properties,
931 History::MatchFlags matchFlags = History::MatchCaseSensitive,
932 bool create = false);
933-
934+ void requestThreadParticipants(const History::Threads &threads);
935 Thread getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap());
936
937 bool writeEvents(const History::Events &events);
938
939=== modified file 'src/managerdbus.cpp'
940--- src/managerdbus.cpp 2017-03-20 14:27:34 +0000
941+++ src/managerdbus.cpp 2017-03-20 14:27:35 +0000
942@@ -28,6 +28,8 @@
943 #include <QDBusReply>
944 #include <QDBusMetaType>
945
946+#include <QDebug>
947+
948 Q_DECLARE_METATYPE(QList< QVariantMap >)
949
950 namespace History
951@@ -103,6 +105,29 @@
952 return thread;
953 }
954
955+void ManagerDBus::requestThreadParticipants(const Threads &threads)
956+{
957+ QList<QVariantMap> ids;
958+ Q_FOREACH(const Thread &thread, threads) {
959+ QVariantMap id;
960+ id[History::FieldAccountId] = thread.accountId();
961+ id[History::FieldThreadId] = thread.threadId();
962+ id[History::FieldType] = thread.type();
963+ ids << id;
964+ }
965+
966+ QDBusPendingCall call = mInterface.asyncCall("ParticipantsForThreads", QVariant::fromValue(ids));
967+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
968+ connect(watcher, &QDBusPendingCallWatcher::finished, [this, threads](QDBusPendingCallWatcher *watcher) {
969+ QDBusPendingReply<QList<QVariantMap> > reply = *watcher;
970+ Q_FOREACH(const QVariantMap &map, reply.value()) {
971+ History::Thread thread = History::Thread::fromProperties(map);
972+ Q_EMIT threadParticipantsChanged(thread, History::Participants(), History::Participants(), thread.participants());
973+ watcher->deleteLater();
974+ }
975+ });
976+}
977+
978 bool ManagerDBus::writeEvents(const Events &events)
979 {
980 QList<QVariantMap> eventMap = eventsToProperties(events);
981
982=== modified file 'src/managerdbus_p.h'
983--- src/managerdbus_p.h 2017-03-20 14:27:34 +0000
984+++ src/managerdbus_p.h 2017-03-20 14:27:35 +0000
985@@ -50,7 +50,7 @@
986 const QVariantMap &properties,
987 History::MatchFlags matchFlags,
988 bool create);
989-
990+ void requestThreadParticipants(const History::Threads &threads);
991 bool writeEvents(const History::Events &events);
992 bool removeThreads(const Threads &threads);
993 bool removeEvents(const Events &events);
994@@ -80,7 +80,6 @@
995 const QList<QVariantMap> &added,
996 const QList<QVariantMap> &removed,
997 const QList<QVariantMap> &modified);
998-
999 void onEventsAdded(const QList<QVariantMap> &events);
1000 void onEventsModified(const QList<QVariantMap> &events);
1001 void onEventsRemoved(const QList<QVariantMap> &events);
1002
1003=== modified file 'src/plugin.h'
1004--- src/plugin.h 2017-03-20 14:27:34 +0000
1005+++ src/plugin.h 2017-03-20 14:27:35 +0000
1006@@ -69,6 +69,7 @@
1007 EventType type,
1008 const QVariantMap &properties,
1009 History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0;
1010+ virtual QList<QVariantMap> participantsForThreads(const QList<QVariantMap> &threadIds) = 0;
1011
1012 virtual QList<QVariantMap> eventsForThread(const QVariantMap &thread) = 0;
1013
1014
1015=== modified file 'src/utils.cpp'
1016--- src/utils.cpp 2017-03-20 14:27:34 +0000
1017+++ src/utils.cpp 2017-03-20 14:27:35 +0000
1018@@ -178,10 +178,14 @@
1019
1020 bool Utils::shouldIncludeParticipants(const Thread &thread)
1021 {
1022- // FIXME
1023- // this is obviously incorrect. we have to query the protocol files as a final solution
1024- if (protocolFromAccountId(thread.accountId()) == "irc") {
1025- return thread.chatType() != History::ChatTypeRoom;
1026+ return shouldIncludeParticipants(thread.accountId(), thread.chatType());
1027+}
1028+
1029+bool Utils::shouldIncludeParticipants(const QString &accountId, const ChatType &type)
1030+{
1031+ // FIXME: this is obviously incorrect. we have to query the protocol files as a final solution
1032+ if (protocolFromAccountId(accountId) == "irc") {
1033+ return type != ChatTypeRoom;
1034 }
1035 return true;
1036 }
1037
1038=== modified file 'src/utils_p.h'
1039--- src/utils_p.h 2017-03-20 14:27:34 +0000
1040+++ src/utils_p.h 2017-03-20 14:27:35 +0000
1041@@ -37,6 +37,7 @@
1042 static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags);
1043 static bool shouldGroupThread(const Thread &thread);
1044 static bool shouldIncludeParticipants(const Thread &thread);
1045+ static bool shouldIncludeParticipants(const QString &accountId, const History::ChatType &type);
1046 static QString normalizeId(const QString &accountId, const QString &id);
1047 static QVariant getUserValue(const QString &interface, const QString &propName);
1048
1049
1050=== modified file 'tests/daemon/DaemonTest.cpp'
1051--- tests/daemon/DaemonTest.cpp 2016-11-03 13:20:17 +0000
1052+++ tests/daemon/DaemonTest.cpp 2017-03-20 14:27:35 +0000
1053@@ -141,8 +141,6 @@
1054 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
1055 QCOMPARE(threads.count(), 1);
1056 History::Thread thread = threads.first();
1057- QCOMPARE(thread.participants().count(), 1);
1058- QCOMPARE(thread.participants().first().identifier(), sender);
1059
1060 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
1061 threads = threadsModifiedSpy.first().first().value<History::Threads>();
1062@@ -252,8 +250,6 @@
1063 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
1064 QCOMPARE(threads.count(), 1);
1065 History::Thread thread = threads.first();
1066- QCOMPARE(thread.participants().count(), 1);
1067- QCOMPARE(thread.participants().first().identifier(), recipient);
1068
1069 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
1070 threads = threadsModifiedSpy.first().first().value<History::Threads>();
1071@@ -296,8 +292,6 @@
1072 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
1073 QCOMPARE(threads.count(), 1);
1074 History::Thread thread = threads.first();
1075- QCOMPARE(thread.participants().count(), 1);
1076- QCOMPARE(thread.participants().first().identifier(), callerId);
1077
1078 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
1079 threads = threadsModifiedSpy.first().first().value<History::Threads>();
1080@@ -357,8 +351,6 @@
1081 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
1082 QCOMPARE(threads.count(), 1);
1083 History::Thread thread = threads.first();
1084- QCOMPARE(thread.participants().count(), 1);
1085- QCOMPARE(thread.participants().first().identifier(), phoneNumber);
1086
1087 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
1088 threads = threadsModifiedSpy.first().first().value<History::Threads>();
1089
1090=== modified file 'tests/libhistoryservice/ManagerTest.cpp'
1091--- tests/libhistoryservice/ManagerTest.cpp 2017-03-20 14:27:34 +0000
1092+++ tests/libhistoryservice/ManagerTest.cpp 2017-03-20 14:27:35 +0000
1093@@ -96,7 +96,6 @@
1094
1095 QCOMPARE(thread.accountId(), accountId);
1096 QCOMPARE(thread.type(), type);
1097- QCOMPARE(thread.participants().identifiers(), participants);
1098
1099 // now try to get the thread again to see if it is returned correctly
1100 History::Thread sameThread = mManager->threadForParticipants(accountId, type, participantsToMatch, matchFlags, false);
1101@@ -137,14 +136,16 @@
1102
1103 void ManagerTest::testWriteEvents()
1104 {
1105+ QString textParticipant("textParticipant");
1106+ QString voiceParticipant("voiceParticipant");
1107 // create two threads, one for voice and one for text
1108 History::Thread textThread = mManager->threadForParticipants("textAccountId",
1109 History::EventTypeText,
1110- QStringList()<< "textParticipant",
1111+ QStringList()<< textParticipant,
1112 History::MatchCaseSensitive, true);
1113 History::Thread voiceThread = mManager->threadForParticipants("voiceAccountId",
1114 History::EventTypeVoice,
1115- QStringList()<< "voiceParticipant",
1116+ QStringList()<< voiceParticipant,
1117 History::MatchCaseSensitive, true);
1118 // insert some text and voice events
1119 History::Events events;
1120@@ -152,7 +153,7 @@
1121 History::TextEvent textEvent(textThread.accountId(),
1122 textThread.threadId(),
1123 QString("eventId%1").arg(i),
1124- textThread.participants().first().identifier(),
1125+ textParticipant,
1126 QDateTime::currentDateTime(),
1127 true,
1128 QString("Hello world %1").arg(i),
1129@@ -163,7 +164,7 @@
1130 History::VoiceEvent voiceEvent(voiceThread.accountId(),
1131 voiceThread.threadId(),
1132 QString("eventId%1").arg(i),
1133- voiceThread.participants().first().identifier(),
1134+ voiceParticipant,
1135 QDateTime::currentDateTime(),
1136 true,
1137 true);
1138@@ -214,14 +215,16 @@
1139
1140 void ManagerTest::testRemoveEvents()
1141 {
1142+ QString textParticipant("textParticipant");
1143+ QString voiceParticipant("voiceParticipant");
1144 // create two threads, one for voice and one for text
1145 History::Thread textThread = mManager->threadForParticipants("textRemovableAccount",
1146 History::EventTypeText,
1147- QStringList()<< "textParticipant",
1148+ QStringList()<< textParticipant,
1149 History::MatchCaseSensitive, true);
1150 History::Thread voiceThread = mManager->threadForParticipants("voiceRemovableAccount",
1151 History::EventTypeVoice,
1152- QStringList()<< "voiceParticipant",
1153+ QStringList()<< voiceParticipant,
1154 History::MatchCaseSensitive, true);
1155 // insert some text and voice events
1156 History::Events events;
1157@@ -229,7 +232,7 @@
1158 History::TextEvent textEvent(textThread.accountId(),
1159 textThread.threadId(),
1160 QString("eventToBeRemoved%1").arg(i),
1161- textThread.participants().first().identifier(),
1162+ textParticipant,
1163 QDateTime::currentDateTime(),
1164 true,
1165 QString("Hello world %1").arg(i),
1166@@ -239,7 +242,7 @@
1167 History::VoiceEvent voiceEvent(voiceThread.accountId(),
1168 voiceThread.threadId(),
1169 QString("eventToBeRemoved%1").arg(i),
1170- voiceThread.participants().first().identifier(),
1171+ voiceParticipant,
1172 QDateTime::currentDateTime(),
1173 true,
1174 true);
1175@@ -280,14 +283,16 @@
1176
1177 void ManagerTest::testGetSingleEvent()
1178 {
1179+ QString textParticipant("textSingleParticipant");
1180+ QString voiceParticipant("voiceSingleParticipant");
1181 // create two threads, one for voice and one for text
1182 History::Thread textThread = mManager->threadForParticipants("textSingleAccount",
1183 History::EventTypeText,
1184- QStringList()<< "textSingleParticipant",
1185+ QStringList()<< textParticipant,
1186 History::MatchCaseSensitive, true);
1187 History::Thread voiceThread = mManager->threadForParticipants("voiceSingleAccount",
1188 History::EventTypeVoice,
1189- QStringList()<< "voiceSingleParticipant",
1190+ QStringList()<< voiceParticipant,
1191 History::MatchCaseSensitive, true);
1192
1193 // now add two events
1194
1195=== modified file 'tests/plugins/sqlite/SqlitePluginTest.cpp'
1196--- tests/plugins/sqlite/SqlitePluginTest.cpp 2016-09-09 20:00:09 +0000
1197+++ tests/plugins/sqlite/SqlitePluginTest.cpp 2017-03-20 14:27:35 +0000
1198@@ -189,7 +189,6 @@
1199 QCOMPARE(retrievedThread[History::FieldType], thread[History::FieldType]);
1200 QCOMPARE(retrievedThread[History::FieldCount], thread[History::FieldCount]);
1201 QCOMPARE(retrievedThread[History::FieldUnreadCount], thread[History::FieldUnreadCount]);
1202- QCOMPARE(retrievedThread[History::FieldParticipants], thread[History::FieldParticipants]);
1203 }
1204
1205 void SqlitePluginTest::testEmptyThreadForParticipants()
1206@@ -219,7 +218,6 @@
1207 QCOMPARE(retrievedThread[History::FieldType], thread[History::FieldType]);
1208 QCOMPARE(retrievedThread[History::FieldCount], thread[History::FieldCount]);
1209 QCOMPARE(retrievedThread[History::FieldUnreadCount], thread[History::FieldUnreadCount]);
1210- QCOMPARE(retrievedThread[History::FieldParticipants], thread[History::FieldParticipants]);
1211
1212 // FIXME: check that the last event data is also present
1213 }

Subscribers

People subscribed via source and target branches

to all changes: