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
=== modified file 'Ubuntu/History/historyeventmodel.cpp'
--- Ubuntu/History/historyeventmodel.cpp 2017-03-20 14:27:34 +0000
+++ Ubuntu/History/historyeventmodel.cpp 2017-03-20 14:27:35 +0000
@@ -335,7 +335,7 @@
335 mView->disconnect(this);335 mView->disconnect(this);
336 }336 }
337337
338 if (mFilter) {338 if (mFilter && mFilter->filter().isValid()) {
339 queryFilter = mFilter->filter();339 queryFilter = mFilter->filter();
340 } else {340 } else {
341 // we should not return anything if there is no filter341 // we should not return anything if there is no filter
342342
=== modified file 'Ubuntu/History/historygroupedthreadsmodel.cpp'
--- Ubuntu/History/historygroupedthreadsmodel.cpp 2015-10-08 19:35:40 +0000
+++ Ubuntu/History/historygroupedthreadsmodel.cpp 2017-03-20 14:27:35 +0000
@@ -199,6 +199,21 @@
199 }199 }
200}200}
201201
202History::Threads HistoryGroupedThreadsModel::restoreParticipants(const History::Threads &oldThreads, const History::Threads &newThreads)
203{
204 History::Threads updated = newThreads;
205 for(History::Thread &thread : updated) {
206 if (!thread.participants().isEmpty()) {
207 continue;
208 }
209 int i = oldThreads.indexOf(thread);
210 if (i >=0) {
211 thread.addParticipants(oldThreads[i].participants());
212 }
213 }
214 return updated;
215}
216
202void HistoryGroupedThreadsModel::updateQuery()217void HistoryGroupedThreadsModel::updateQuery()
203{218{
204 // remove all entries and call the query update219 // remove all entries and call the query update
@@ -217,6 +232,7 @@
217 processThreadGrouping(thread);232 processThreadGrouping(thread);
218 }233 }
219234
235 fetchParticipantsIfNeeded(threads);
220 notifyDataChanged();236 notifyDataChanged();
221}237}
222238
@@ -225,7 +241,7 @@
225 Q_FOREACH(const History::Thread &thread, threads) {241 Q_FOREACH(const History::Thread &thread, threads) {
226 processThreadGrouping(thread);242 processThreadGrouping(thread);
227 }243 }
228244 fetchParticipantsIfNeeded(threads);
229 notifyDataChanged();245 notifyDataChanged();
230}246}
231247
@@ -238,6 +254,42 @@
238 notifyDataChanged();254 notifyDataChanged();
239}255}
240256
257void HistoryGroupedThreadsModel::onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified)
258{
259 int pos = existingPositionForEntry(thread);
260 if (pos >= 0) {
261 HistoryThreadGroup &group = mGroups[pos];
262 if (group.displayedThread == thread) {
263 group.displayedThread.removeParticipants(removed);
264 group.displayedThread.removeParticipants(modified);
265 group.displayedThread.addParticipants(added);
266 group.displayedThread.addParticipants(modified);
267 }
268
269 Q_FOREACH(const History::Thread &existingThread, group.threads) {
270 if (existingThread == thread) {
271 History::Thread modifiedThread = existingThread;
272 group.threads.removeOne(existingThread);
273 modifiedThread.removeParticipants(removed);
274 modifiedThread.removeParticipants(modified);
275 modifiedThread.addParticipants(added);
276 modifiedThread.addParticipants(modified);
277 group.threads.append(modifiedThread);
278 }
279 }
280 QModelIndex idx = index(pos);
281 Q_EMIT dataChanged(idx, idx);
282 }
283
284 // watch the contact info for the received participants
285 Q_FOREACH(const History::Participant &participant, added) {
286 watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
287 }
288 Q_FOREACH(const History::Participant &participant, modified) {
289 watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
290 }
291}
292
241void HistoryGroupedThreadsModel::processThreadGrouping(const History::Thread &thread)293void HistoryGroupedThreadsModel::processThreadGrouping(const History::Thread &thread)
242{294{
243 QVariantMap queryProperties;295 QVariantMap queryProperties;
@@ -262,7 +314,7 @@
262 }314 }
263315
264 HistoryThreadGroup &group = mGroups[pos];316 HistoryThreadGroup &group = mGroups[pos];
265 group.threads = groupedThread.groupedThreads();317 group.threads = restoreParticipants(group.threads, groupedThread.groupedThreads());
266318
267 updateDisplayedThread(group);319 updateDisplayedThread(group);
268 markGroupAsChanged(group);320 markGroupAsChanged(group);
269321
=== modified file 'Ubuntu/History/historygroupedthreadsmodel.h'
--- Ubuntu/History/historygroupedthreadsmodel.h 2015-09-29 20:34:22 +0000
+++ Ubuntu/History/historygroupedthreadsmodel.h 2017-03-20 14:27:35 +0000
@@ -67,12 +67,17 @@
67 int existingPositionForEntry(const History::Thread &thread) const;67 int existingPositionForEntry(const History::Thread &thread) const;
68 void removeGroup(const HistoryThreadGroup &group);68 void removeGroup(const HistoryThreadGroup &group);
69 void updateDisplayedThread(HistoryThreadGroup &group);69 void updateDisplayedThread(HistoryThreadGroup &group);
70 History::Threads restoreParticipants(const History::Threads &oldThreads, const History::Threads &newThreads);
7071
71protected Q_SLOTS:72protected Q_SLOTS:
72 virtual void updateQuery();73 virtual void updateQuery();
73 virtual void onThreadsAdded(const History::Threads &threads);74 virtual void onThreadsAdded(const History::Threads &threads);
74 virtual void onThreadsModified(const History::Threads &threads);75 virtual void onThreadsModified(const History::Threads &threads);
75 virtual void onThreadsRemoved(const History::Threads &threads);76 virtual void onThreadsRemoved(const History::Threads &threads);
77 void onThreadParticipantsChanged(const History::Thread &thread,
78 const History::Participants &added,
79 const History::Participants &removed,
80 const History::Participants &modified) override;
7681
77private Q_SLOTS:82private Q_SLOTS:
78 void processThreadGrouping(const History::Thread &thread);83 void processThreadGrouping(const History::Thread &thread);
7984
=== modified file 'Ubuntu/History/historymodel.cpp'
--- Ubuntu/History/historymodel.cpp 2017-03-20 14:27:34 +0000
+++ Ubuntu/History/historymodel.cpp 2017-03-20 14:27:35 +0000
@@ -342,6 +342,20 @@
342 return QString::null;342 return QString::null;
343}343}
344344
345void HistoryModel::requestThreadParticipants(const QVariantList &threads)
346{
347 History::Threads theThreads;
348 Q_FOREACH(const QVariant &threadVariant, threads) {
349 History::Thread theThread = History::Thread::fromProperties(threadVariant.toMap());
350 // if the given thread already has the list of participants, there is no point
351 // in fetching it again
352 if (theThread.participants().isEmpty()) {
353 theThreads << theThread;
354 }
355 }
356 History::Manager::instance()->requestThreadParticipants(theThreads);
357}
358
345bool HistoryModel::writeTextInformationEvent(const QString &accountId, const QString &threadId, const QStringList &participants, const QString &message, int informationType, const QString &subject)359bool HistoryModel::writeTextInformationEvent(const QString &accountId, const QString &threadId, const QStringList &participants, const QString &message, int informationType, const QString &subject)
346{360{
347 if (participants.isEmpty() || threadId.isEmpty() || accountId.isEmpty()) {361 if (participants.isEmpty() || threadId.isEmpty() || accountId.isEmpty()) {
348362
=== modified file 'Ubuntu/History/historymodel.h'
--- Ubuntu/History/historymodel.h 2017-03-20 14:27:34 +0000
+++ Ubuntu/History/historymodel.h 2017-03-20 14:27:35 +0000
@@ -168,6 +168,7 @@
168 const QStringList &participants,168 const QStringList &participants,
169 int matchFlags = (int)History::MatchCaseSensitive,169 int matchFlags = (int)History::MatchCaseSensitive,
170 bool create = false);170 bool create = false);
171 Q_INVOKABLE void requestThreadParticipants(const QVariantList &threads);
171 Q_INVOKABLE bool writeTextInformationEvent(const QString &accountId,172 Q_INVOKABLE bool writeTextInformationEvent(const QString &accountId,
172 const QString &threadId,173 const QString &threadId,
173 const QStringList &participants,174 const QStringList &participants,
174175
=== modified file 'Ubuntu/History/historythreadmodel.cpp'
--- Ubuntu/History/historythreadmodel.cpp 2017-03-20 14:27:34 +0000
+++ Ubuntu/History/historythreadmodel.cpp 2017-03-20 14:27:35 +0000
@@ -26,6 +26,8 @@
26#include "voiceevent.h"26#include "voiceevent.h"
27#include <QDBusMetaType>27#include <QDBusMetaType>
2828
29#include <QDebug>
30
29Q_DECLARE_METATYPE(History::TextEventAttachments)31Q_DECLARE_METATYPE(History::TextEventAttachments)
30Q_DECLARE_METATYPE(QList<QVariantMap>)32Q_DECLARE_METATYPE(QList<QVariantMap>)
3133
@@ -190,7 +192,6 @@
190 }192 }
191 break;193 break;
192 }194 }
193
194 return result;195 return result;
195}196}
196197
@@ -214,13 +215,6 @@
214 mCanFetchMore = false;215 mCanFetchMore = false;
215 Q_EMIT canFetchMoreChanged();216 Q_EMIT canFetchMoreChanged();
216 } else {217 } else {
217 Q_FOREACH(const History::Thread &thread, threads) {
218 // insert the identifiers in the contact map
219 Q_FOREACH(const History::Participant &participant, thread.participants()) {
220 watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
221 }
222 }
223
224 beginInsertRows(QModelIndex(), mThreads.count(), mThreads.count() + threads.count() - 1);218 beginInsertRows(QModelIndex(), mThreads.count(), mThreads.count() + threads.count() - 1);
225 mThreads << threads;219 mThreads << threads;
226 endInsertRows();220 endInsertRows();
@@ -327,6 +321,29 @@
327 QModelIndex idx = index(pos);321 QModelIndex idx = index(pos);
328 Q_EMIT dataChanged(idx, idx);322 Q_EMIT dataChanged(idx, idx);
329 }323 }
324
325 // watch the contact info for the received participants
326 Q_FOREACH(const History::Participant &participant, added) {
327 watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
328 }
329 Q_FOREACH(const History::Participant &participant, modified) {
330 watchContactInfo(thread.accountId(), participant.identifier(), participant.properties());
331 }
332}
333
334void HistoryThreadModel::fetchParticipantsIfNeeded(const History::Threads &threads)
335{
336 History::Threads filtered;
337 Q_FOREACH(const History::Thread &thread, threads) {
338 if (thread.type() == History::EventTypeText && thread.participants().isEmpty() &&
339 (thread.chatType() != History::ChatTypeRoom || thread.accountId().startsWith("ofono"))) {
340 filtered << thread;
341 }
342 }
343 if (filtered.isEmpty()) {
344 return;
345 }
346 History::Manager::instance()->requestThreadParticipants(filtered);
330}347}
331348
332void HistoryThreadModel::onThreadsAdded(const History::Threads &threads)349void HistoryThreadModel::onThreadsAdded(const History::Threads &threads)
@@ -346,6 +363,7 @@
346 mThreads.insert(pos, thread);363 mThreads.insert(pos, thread);
347 endInsertRows();364 endInsertRows();
348 }365 }
366 fetchParticipantsIfNeeded(threads);
349}367}
350368
351void HistoryThreadModel::onThreadsModified(const History::Threads &threads)369void HistoryThreadModel::onThreadsModified(const History::Threads &threads)
@@ -367,6 +385,7 @@
367 if (!newThreads.isEmpty()) {385 if (!newThreads.isEmpty()) {
368 onThreadsAdded(newThreads);386 onThreadsAdded(newThreads);
369 }387 }
388 fetchParticipantsIfNeeded(threads);
370}389}
371390
372void HistoryThreadModel::onThreadsRemoved(const History::Threads &threads)391void HistoryThreadModel::onThreadsRemoved(const History::Threads &threads)
@@ -387,5 +406,7 @@
387406
388History::Threads HistoryThreadModel::fetchNextPage()407History::Threads HistoryThreadModel::fetchNextPage()
389{408{
390 return mThreadView->nextPage();409 History::Threads threads = mThreadView->nextPage();
410 fetchParticipantsIfNeeded(threads);
411 return threads;
391}412}
392413
=== modified file 'Ubuntu/History/historythreadmodel.h'
--- Ubuntu/History/historythreadmodel.h 2017-03-20 14:27:34 +0000
+++ Ubuntu/History/historythreadmodel.h 2017-03-20 14:27:35 +0000
@@ -79,6 +79,7 @@
79 virtual void onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified);79 virtual void onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified);
8080
81protected:81protected:
82 void fetchParticipantsIfNeeded(const History::Threads &threads);
82 History::Threads fetchNextPage();83 History::Threads fetchNextPage();
83 bool mCanFetchMore;84 bool mCanFetchMore;
84 bool mGroupThreads;85 bool mGroupThreads;
8586
=== modified file 'daemon/HistoryService.xml'
--- daemon/HistoryService.xml 2017-03-20 14:27:34 +0000
+++ daemon/HistoryService.xml 2017-03-20 14:27:35 +0000
@@ -35,6 +35,15 @@
35 <arg type="a{sv}" direction="out"/>35 <arg type="a{sv}" direction="out"/>
36 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>36 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
37 </method>37 </method>
38 <method name="ParticipantsForThreads">
39 <dox:d><![CDATA[
40 Return the participants for the given threads
41 ]]></dox:d>
42 <arg name="threadIds" type="a(a{sv})" direction="in"/>
43 <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList &lt; QVariantMap &gt;"/>
44 <arg name="participants" type="a(a{sv})" direction="out"/>
45 <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList &lt; QVariantMap &gt;"/>
46 </method>
38 <method name="WriteEvents">47 <method name="WriteEvents">
39 <dox:d><![CDATA[48 <dox:d><![CDATA[
40 Write the given events to the storage.49 Write the given events to the storage.
4150
=== modified file 'daemon/historydaemon.cpp'
--- daemon/historydaemon.cpp 2017-03-20 14:27:34 +0000
+++ daemon/historydaemon.cpp 2017-03-20 14:27:35 +0000
@@ -85,10 +85,11 @@
85{85{
86 Q_FOREACH (QVariant participant, thread[History::FieldParticipants].toList()) {86 Q_FOREACH (QVariant participant, thread[History::FieldParticipants].toList()) {
87 // found if same identifier and as member into thread info87 // found if same identifier and as member into thread info
88 QVariantMap participantMap = participant.toMap();
88 if (History::Utils::compareIds(thread[History::FieldAccountId].toString(),89 if (History::Utils::compareIds(thread[History::FieldAccountId].toString(),
89 contact->id(),90 contact->id(),
90 participant.toMap()[History::FieldIdentifier].toString()) &&91 participantMap[History::FieldIdentifier].toString()) &&
91 participant.toMap()[History::FieldParticipantState].toUInt() == History::ParticipantStateRegular)92 participantMap[History::FieldParticipantState].toUInt() == History::ParticipantStateRegular)
92 {93 {
93 return true;94 return true;
94 }95 }
@@ -205,56 +206,58 @@
205 QStringList participantIds;206 QStringList participantIds;
206 QString accountId = textChannel->property(History::FieldAccountId).toString();207 QString accountId = textChannel->property(History::FieldAccountId).toString();
207208
208 ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>();209 if (History::Utils::shouldIncludeParticipants(accountId, fromTelepathyHandleType(textChannel->targetHandleType()))) {
209 RolesMap roles;210 ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>();
210 if (roles_interface) {211 RolesMap roles;
211 if (mRolesMap.contains(textChannel->objectPath())) {212 if (roles_interface) {
212 roles = mRolesMap[textChannel->objectPath()];213 if (mRolesMap.contains(textChannel->objectPath())) {
213 }214 roles = mRolesMap[textChannel->objectPath()];
214 }215 }
215216 }
216 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) {217
217 QVariantMap contactProperties;218 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) {
218 contactProperties[History::FieldAlias] = contact->alias();219 QVariantMap contactProperties;
219 contactProperties[History::FieldAccountId] = accountId;220 contactProperties[History::FieldAlias] = contact->alias();
220 contactProperties[History::FieldIdentifier] = contact->id();221 contactProperties[History::FieldAccountId] = accountId;
221 contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;222 contactProperties[History::FieldIdentifier] = contact->id();
222 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];223 contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
223 participantIds << contact->id();224 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
224 participants << contactProperties;225 participantIds << contact->id();
225 }226 participants << contactProperties;
226227 }
227 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(false)) {228
228 QVariantMap contactProperties;229 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(false)) {
229 contactProperties[History::FieldAlias] = contact->alias();230 QVariantMap contactProperties;
230 contactProperties[History::FieldAccountId] = accountId;231 contactProperties[History::FieldAlias] = contact->alias();
231 contactProperties[History::FieldIdentifier] = contact->id();232 contactProperties[History::FieldAccountId] = accountId;
232 contactProperties[History::FieldParticipantState] = History::ParticipantStateRemotePending;233 contactProperties[History::FieldIdentifier] = contact->id();
233 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];234 contactProperties[History::FieldParticipantState] = History::ParticipantStateRemotePending;
234 participantIds << contact->id();235 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
235 participants << contactProperties;236 participantIds << contact->id();
236 }237 participants << contactProperties;
237238 }
238 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(false)) {239
239 QVariantMap contactProperties;240 Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(false)) {
240 contactProperties[History::FieldAlias] = contact->alias();241 QVariantMap contactProperties;
241 contactProperties[History::FieldAccountId] = accountId;242 contactProperties[History::FieldAlias] = contact->alias();
242 contactProperties[History::FieldIdentifier] = contact->id();243 contactProperties[History::FieldAccountId] = accountId;
243 contactProperties[History::FieldParticipantState] = History::ParticipantStateLocalPending;244 contactProperties[History::FieldIdentifier] = contact->id();
244 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];245 contactProperties[History::FieldParticipantState] = History::ParticipantStateLocalPending;
245 participantIds << contact->id();246 contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)];
246 participants << contactProperties;247 participantIds << contact->id();
247 }248 participants << contactProperties;
248249 }
249 if (participants.isEmpty() && textChannel->targetHandleType() == Tp::HandleTypeContact &&250
250 textChannel->targetContact() == textChannel->connection()->selfContact()) {251 if (participants.isEmpty() && textChannel->targetHandleType() == Tp::HandleTypeContact &&
251 QVariantMap contactProperties;252 textChannel->targetContact() == textChannel->connection()->selfContact()) {
252 contactProperties[History::FieldAlias] = textChannel->targetContact()->alias();253 QVariantMap contactProperties;
253 contactProperties[History::FieldAccountId] = accountId;254 contactProperties[History::FieldAlias] = textChannel->targetContact()->alias();
254 contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id();255 contactProperties[History::FieldAccountId] = accountId;
255 contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;256 contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id();
256 participantIds << textChannel->targetContact()->id();257 contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular;
257 participants << contactProperties;258 participantIds << textChannel->targetContact()->id();
259 participants << contactProperties;
260 }
258 }261 }
259262
260 // We map chatType directly from telepathy targetHandleType: None, Contact, Room263 // We map chatType directly from telepathy targetHandleType: None, Contact, Room
@@ -358,6 +361,14 @@
358 return threadId;361 return threadId;
359}362}
360363
364QList<QVariantMap> HistoryDaemon::participantsForThreads(const QList<QVariantMap> &threadIds)
365{
366 if (!mBackend) {
367 return QList<QVariantMap>();
368 }
369 return mBackend->participantsForThreads(threadIds);
370}
371
361QString HistoryDaemon::queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties)372QString HistoryDaemon::queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties)
362{373{
363 if (!mBackend) {374 if (!mBackend) {
@@ -665,6 +676,24 @@
665void HistoryDaemon::onTextChannelInvalidated(const Tp::TextChannelPtr channel)676void HistoryDaemon::onTextChannelInvalidated(const Tp::TextChannelPtr channel)
666{677{
667 mRolesMap.remove(channel->objectPath());678 mRolesMap.remove(channel->objectPath());
679 QString accountId = channel->property(History::FieldAccountId).toString();
680 QVariantMap properties = propertiesFromChannel(channel);
681
682 // first try to fetch the existing thread to see if there is any.
683 QVariantMap thread = threadForProperties(accountId,
684 History::EventTypeText,
685 properties,
686 matchFlagsForChannel(channel),
687 false);
688
689 QVariantMap roomInfo = thread[History::FieldChatRoomInfo].toMap();
690 if ((roomInfo.contains("Persistent") && !roomInfo["Persistent"].toBool()) && History::TelepathyHelper::instance()->accountForId(accountId)->protocolName() != "ofono") {
691 writeInformationEvent(thread, History::InformationTypeSelfLeaving);
692 // update backend
693 updateRoomProperties(channel, QVariantMap{{"Joined", false}});
694 }
695
696 channel->disconnect(this);
668}697}
669698
670void HistoryDaemon::onTextChannelAvailable(const Tp::TextChannelPtr channel)699void HistoryDaemon::onTextChannelAvailable(const Tp::TextChannelPtr channel)
@@ -791,7 +820,8 @@
791 if (hasMembersAdded) {820 if (hasMembersAdded) {
792 Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) {821 Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) {
793 // if this member was not previously regular member in thread, notify about his join822 // if this member was not previously regular member in thread, notify about his join
794 if (!foundAsMemberInThread(contact, thread)) {823 if (!foundAsMemberInThread(contact, thread) && contact->id() != channel->groupSelfContact()->id()) {
824
795 writeInformationEvent(thread, History::InformationTypeJoined, contact->alias(), QString(), QString(), true);825 writeInformationEvent(thread, History::InformationTypeJoined, contact->alias(), QString(), QString(), true);
796826
797 QVariantMap participant;827 QVariantMap participant;
@@ -817,9 +847,11 @@
817 break;847 break;
818 }848 }
819 }849 }
820 writeInformationEvent(thread, type);850 if (thread[History::FieldChatRoomInfo].toMap()["Joined"].toBool()) {
821 // update backend851 writeInformationEvent(thread, type);
822 updateRoomProperties(channel, QVariantMap{{"Joined", false}}, true);852 // update backend
853 updateRoomProperties(channel, QVariantMap{{"Joined", false}}, true);
854 }
823 }855 }
824 else // don't notify any other group member removal if we are leaving the group856 else // don't notify any other group member removal if we are leaving the group
825 {857 {
@@ -977,9 +1009,20 @@
977void HistoryDaemon::onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message)1009void HistoryDaemon::onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message)
978{1010{
979 QString eventId;1011 QString eventId;
980 Tp::MessagePart header = message.header();
981 QString senderId;1012 QString senderId;
1013
1014 QString accountId = textChannel->property(History::FieldAccountId).toString();
1015 QString threadId = textChannel->property(History::FieldThreadId).toString();
982 QVariantMap properties = propertiesFromChannel(textChannel);1016 QVariantMap properties = propertiesFromChannel(textChannel);
1017
1018 if (threadId.isNull()) {
1019 threadId = threadIdForProperties(accountId,
1020 History::EventTypeText,
1021 properties,
1022 matchFlagsForChannel(textChannel),
1023 true);
1024 }
1025
983 History::MessageStatus status = History::MessageStatusUnknown;1026 History::MessageStatus status = History::MessageStatusUnknown;
984 if (!message.sender() || message.sender()->handle().at(0) == textChannel->connection()->selfHandle()) {1027 if (!message.sender() || message.sender()->handle().at(0) == textChannel->connection()->selfHandle()) {
985 senderId = "self";1028 senderId = "self";
@@ -1002,7 +1045,7 @@
1002 if (message.isDeliveryReport() && message.deliveryDetails().hasOriginalToken()) {1045 if (message.isDeliveryReport() && message.deliveryDetails().hasOriginalToken()) {
1003 // at this point we assume the delivery report is for a message that was already1046 // at this point we assume the delivery report is for a message that was already
1004 // sent and properly saved at our database, so we can safely get it here to update1047 // sent and properly saved at our database, so we can safely get it here to update
1005 QVariantMap textEvent = getSingleEventFromTextChannel(textChannel, message.deliveryDetails().originalToken());1048 QVariantMap textEvent = getSingleEvent(History::EventTypeText, accountId, threadId, message.deliveryDetails().originalToken());
1006 if (textEvent.isEmpty()) {1049 if (textEvent.isEmpty()) {
1007 qWarning() << "Cound not find the original event to update with delivery details.";1050 qWarning() << "Cound not find the original event to update with delivery details.";
1008 return;1051 return;
@@ -1022,13 +1065,6 @@
10221065
1023 return;1066 return;
1024 }1067 }
1025
1026 QString accountId = textChannel->property(History::FieldAccountId).toString();
1027 QString threadId = threadIdForProperties(accountId,
1028 History::EventTypeText,
1029 properties,
1030 matchFlagsForChannel(textChannel),
1031 true);
1032 int count = 1;1068 int count = 1;
1033 QList<QVariantMap> attachments;1069 QList<QVariantMap> attachments;
1034 History::MessageType type = History::MessageTypeText;1070 History::MessageType type = History::MessageTypeText;
@@ -1348,3 +1384,21 @@
13481384
1349 return status;1385 return status;
1350}1386}
1387
1388History::ChatType HistoryDaemon::fromTelepathyHandleType(const Tp::HandleType &type)
1389{
1390 History::ChatType chatType;
1391 switch(type) {
1392 case Tp::HandleTypeContact:
1393 chatType = History::ChatTypeContact;
1394 break;
1395 case Tp::HandleTypeNone:
1396 chatType = History::ChatTypeNone;
1397 break;
1398 case Tp::HandleTypeRoom:
1399 chatType = History::ChatTypeRoom;
1400 break;
1401 }
1402
1403 return chatType;
1404}
13511405
=== modified file 'daemon/historydaemon.h'
--- daemon/historydaemon.h 2017-03-20 14:27:34 +0000
+++ daemon/historydaemon.h 2017-03-20 14:27:35 +0000
@@ -53,6 +53,7 @@
53 const QVariantMap &properties,53 const QVariantMap &properties,
54 History::MatchFlags matchFlags = History::MatchCaseSensitive,54 History::MatchFlags matchFlags = History::MatchCaseSensitive,
55 bool create = true);55 bool create = true);
56 QList<QVariantMap> participantsForThreads(const QList<QVariantMap> &threadIds);
56 QString queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties);57 QString queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties);
57 QString queryEvents(int type, const QVariantMap &sort, const QVariantMap &filter);58 QString queryEvents(int type, const QVariantMap &sort, const QVariantMap &filter);
58 QVariantMap getSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties);59 QVariantMap getSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties);
@@ -93,6 +94,7 @@
93 void writeRolesChangesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap);94 void writeRolesChangesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap);
9495
95 static History::MessageStatus fromTelepathyDeliveryStatus(Tp::DeliveryStatus deliveryStatus);96 static History::MessageStatus fromTelepathyDeliveryStatus(Tp::DeliveryStatus deliveryStatus);
97 static History::ChatType fromTelepathyHandleType(const Tp::HandleType &type);
96private:98private:
97 HistoryDaemon(QObject *parent = 0);99 HistoryDaemon(QObject *parent = 0);
98100
99101
=== modified file 'daemon/historyservicedbus.cpp'
--- daemon/historyservicedbus.cpp 2017-03-20 14:27:34 +0000
+++ daemon/historyservicedbus.cpp 2017-03-20 14:27:35 +0000
@@ -105,7 +105,12 @@
105 (History::EventType) type,105 (History::EventType) type,
106 properties,106 properties,
107 (History::MatchFlags) matchFlags,107 (History::MatchFlags) matchFlags,
108 create);108 create);
109}
110
111QList<QVariantMap> HistoryServiceDBus::ParticipantsForThreads(const QList<QVariantMap> &threadIds)
112{
113 return HistoryDaemon::instance()->participantsForThreads(threadIds);
109}114}
110115
111QVariantMap HistoryServiceDBus::ThreadForParticipants(const QString &accountId,116QVariantMap HistoryServiceDBus::ThreadForParticipants(const QString &accountId,
112117
=== modified file 'daemon/historyservicedbus.h'
--- daemon/historyservicedbus.h 2017-03-20 14:27:34 +0000
+++ daemon/historyservicedbus.h 2017-03-20 14:27:35 +0000
@@ -59,6 +59,7 @@
59 const QVariantMap &properties,59 const QVariantMap &properties,
60 int matchFlags,60 int matchFlags,
61 bool create);61 bool create);
62 QList<QVariantMap> ParticipantsForThreads(const QList<QVariantMap> &threadIds);
62 bool WriteEvents(const QList <QVariantMap> &events);63 bool WriteEvents(const QList <QVariantMap> &events);
63 bool RemoveThreads(const QList <QVariantMap> &threads);64 bool RemoveThreads(const QList <QVariantMap> &threads);
64 bool RemoveEvents(const QList <QVariantMap> &events);65 bool RemoveEvents(const QList <QVariantMap> &events);
6566
=== modified file 'plugins/sqlite/sqlitehistoryplugin.cpp'
--- plugins/sqlite/sqlitehistoryplugin.cpp 2017-03-20 14:27:34 +0000
+++ plugins/sqlite/sqlitehistoryplugin.cpp 2017-03-20 14:27:35 +0000
@@ -315,13 +315,30 @@
315 return QVariantMap();315 return QVariantMap();
316 }316 }
317317
318 // first check if the thread actually has anything to change
319 query.prepare("SELECT unreadCount from threads WHERE accountId=:accountId AND threadId=:threadId AND type=:type");
320 query.bindValue(":accountId", thread[History::FieldAccountId].toString());
321 query.bindValue(":threadId", thread[History::FieldThreadId].toString());
322 query.bindValue(":type", (uint)History::EventTypeText);
323 if (!query.exec() || !query.next()) {
324 qCritical() << "Failed to verify the unread messages of the thread. Error:" << query.lastError();
325 return QVariantMap();
326 }
327
328
329 int unreadCount = query.value(0).toUInt();
330 if (unreadCount == 0) {
331 // no messages to ack, so no need to update anything
332 return QVariantMap();
333 }
334
318 query.prepare("UPDATE text_events SET newEvent=:newEvent WHERE accountId=:accountId AND threadId=:threadId AND newEvent=1");335 query.prepare("UPDATE text_events SET newEvent=:newEvent WHERE accountId=:accountId AND threadId=:threadId AND newEvent=1");
319 query.bindValue(":accountId", thread[History::FieldAccountId].toString());336 query.bindValue(":accountId", thread[History::FieldAccountId].toString());
320 query.bindValue(":threadId", thread[History::FieldThreadId].toString());337 query.bindValue(":threadId", thread[History::FieldThreadId].toString());
321 query.bindValue(":newEvent", false);338 query.bindValue(":newEvent", false);
322339
323 if (!query.exec()) {340 if (!query.exec()) {
324 qCritical() << "Failed to mark thread as read: Error:" << query.lastError() << query.lastQuery() << query.executedQuery();341 qCritical() << "Failed to mark thread as read: Error:" << query.lastError();
325 return QVariantMap();342 return QVariantMap();
326 }343 }
327344
@@ -379,6 +396,44 @@
379 return threadForParticipants(accountId, type, participants.identifiers(), matchFlags)[History::FieldThreadId].toString();396 return threadForParticipants(accountId, type, participants.identifiers(), matchFlags)[History::FieldThreadId].toString();
380}397}
381398
399QList<QVariantMap> SQLiteHistoryPlugin::participantsForThreads(const QList<QVariantMap> &threadIds)
400{
401 QList<QVariantMap> results;
402 Q_FOREACH(const QVariantMap &thread, threadIds) {
403 QString accountId = thread[History::FieldAccountId].toString();
404 QString threadId = thread[History::FieldThreadId].toString();
405 History::EventType type = (History::EventType)thread[History::FieldType].toUInt();
406 QVariantMap result = thread;
407
408 QSqlQuery query;
409 query.prepare("SELECT normalizedId, alias, state, roles FROM thread_participants "
410 "WHERE accountId=:accountId AND threadId=:threadId AND type=:type");
411 query.bindValue(":accountId", accountId);
412 query.bindValue(":threadId", threadId);
413 query.bindValue(":type", type);
414 QVariantList participants;
415 if (!query.exec()) {
416 qWarning() << "Failed to retrieve participants. Error:" << query.lastError().text() << query.lastQuery();
417 results << result;
418 continue;
419 }
420
421 while (query.next()) {
422 QVariantMap participant;
423 QString identifier = query.value(0).toString();
424 participant[History::FieldIdentifier] = identifier;
425 participant[History::FieldAlias] = query.value(1);
426 participant[History::FieldParticipantState] = query.value(2);
427 participant[History::FieldParticipantRoles] = query.value(3);
428 participants << History::ContactMatcher::instance()->contactInfo(accountId, identifier, true, participant);
429 }
430
431 result[History::FieldParticipants] = participants;
432 results << result;
433 }
434 return results;
435}
436
382QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId,437QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId,
383 History::EventType type,438 History::EventType type,
384 const QStringList &participants,439 const QStringList &participants,
@@ -1140,22 +1195,6 @@
1140 << "threads.unreadCount"1195 << "threads.unreadCount"
1141 << "threads.lastEventTimestamp";1196 << "threads.lastEventTimestamp";
11421197
1143 // get the participants in the query already
1144 fields << "(SELECT group_concat(thread_participants.participantId, \"|,|\") "
1145 "FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
1146 "AND thread_participants.threadId=threads.threadId "
1147 "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as participants";
1148
1149 fields << "(SELECT group_concat(thread_participants.state, \"|,|\") "
1150 "FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
1151 "AND thread_participants.threadId=threads.threadId "
1152 "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as state";
1153
1154 fields << "(SELECT group_concat(thread_participants.roles, \"|,|\") "
1155 "FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
1156 "AND thread_participants.threadId=threads.threadId "
1157 "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as roles";
1158
1159 QStringList extraFields;1198 QStringList extraFields;
1160 QString table;1199 QString table;
11611200
@@ -1183,6 +1222,7 @@
1183QList<QVariantMap> SQLiteHistoryPlugin::parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties)1222QList<QVariantMap> SQLiteHistoryPlugin::parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties)
1184{1223{
1185 QList<QVariantMap> threads;1224 QList<QVariantMap> threads;
1225 QList<QVariantMap> threadsWithoutParticipants;
1186 QSqlQuery attachmentsQuery(SQLiteDatabase::instance()->database());1226 QSqlQuery attachmentsQuery(SQLiteDatabase::instance()->database());
1187 QList<QVariantMap> attachments;1227 QList<QVariantMap> attachments;
1188 bool grouped = false;1228 bool grouped = false;
@@ -1217,31 +1257,11 @@
1217 thread[History::FieldEventId] = query.value(2);1257 thread[History::FieldEventId] = query.value(2);
1218 thread[History::FieldCount] = query.value(3);1258 thread[History::FieldCount] = query.value(3);
1219 thread[History::FieldUnreadCount] = query.value(4);1259 thread[History::FieldUnreadCount] = query.value(4);
1220 QStringList participants = query.value(6).toString().split("|,|", QString::SkipEmptyParts);
1221 QList<int> participantStatus;
1222 QStringList participantStatusString = query.value(7).toString().split("|,|", QString::SkipEmptyParts);
1223 Q_FOREACH(const QString &statusString, participantStatusString) {
1224 participantStatus << statusString.toUInt();
1225 }
1226 QStringList participantRolesString = query.value(8).toString().split("|,|", QString::SkipEmptyParts);
1227 QList<int> participantRoles;
1228 Q_FOREACH(const QString &rolesString, participantRolesString) {
1229 participantRoles << rolesString.toUInt();
1230 }
1231 QVariantList contactList;
1232 QVariantList contactInfo = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
1233 for (int i = 0; i < contactInfo.count(); ++i) {
1234 QVariantMap map = contactInfo[i].toMap();
1235 map["state"] = participantStatus[i];
1236 map["roles"] = participantRoles[i];
1237 contactList << map;
1238 }
1239 thread[History::FieldParticipants] = contactList;
12401260
1241 // the generic event fields1261 // the generic event fields
1242 thread[History::FieldSenderId] = query.value(9);1262 thread[History::FieldSenderId] = query.value(6);
1243 thread[History::FieldTimestamp] = toLocalTimeString(query.value(5).toDateTime());1263 thread[History::FieldTimestamp] = toLocalTimeString(query.value(5).toDateTime());
1244 thread[History::FieldNewEvent] = query.value(10).toBool();1264 thread[History::FieldNewEvent] = query.value(7).toBool();
12451265
1246 // the next step is to get the last event1266 // the next step is to get the last event
1247 switch (type) {1267 switch (type) {
@@ -1272,13 +1292,13 @@
1272 thread[History::FieldAttachments] = QVariant::fromValue(attachments);1292 thread[History::FieldAttachments] = QVariant::fromValue(attachments);
1273 attachments.clear();1293 attachments.clear();
1274 }1294 }
1275 thread[History::FieldMessage] = query.value(11);1295 thread[History::FieldMessage] = query.value(8);
1276 thread[History::FieldMessageType] = query.value(12);1296 thread[History::FieldMessageType] = query.value(9);
1277 thread[History::FieldMessageStatus] = query.value(13);1297 thread[History::FieldMessageStatus] = query.value(10);
1278 thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(14).toDateTime());1298 thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(11).toDateTime());
1279 thread[History::FieldChatType] = query.value(15).toUInt();1299 thread[History::FieldChatType] = query.value(12).toUInt();
12801300
1281 if (thread[History::FieldChatType].toInt() == 2) {1301 if (thread[History::FieldChatType].toInt() == History::ChatTypeRoom) {
1282 QVariantMap chatRoomInfo;1302 QVariantMap chatRoomInfo;
1283 QSqlQuery query1(SQLiteDatabase::instance()->database());1303 QSqlQuery query1(SQLiteDatabase::instance()->database());
12841304
@@ -1337,19 +1357,29 @@
1337 chatRoomInfo["SelfRoles"] = query1.value(20).toInt();1357 chatRoomInfo["SelfRoles"] = query1.value(20).toInt();
13381358
1339 thread[History::FieldChatRoomInfo] = chatRoomInfo;1359 thread[History::FieldChatRoomInfo] = chatRoomInfo;
1340 if (!History::Utils::shouldIncludeParticipants(History::Thread::fromProperties(thread))) {1360 }
1341 thread.remove(History::FieldParticipants);1361 if (!History::Utils::shouldIncludeParticipants(History::Thread::fromProperties(thread))) {
1342 }1362 thread.remove(History::FieldParticipants);
1363 threadsWithoutParticipants << thread;
1364 } else {
1365 threads << thread;
1343 }1366 }
1344 break;1367 break;
1345 case History::EventTypeVoice:1368 case History::EventTypeVoice:
1346 thread[History::FieldMissed] = query.value(12);1369 thread[History::FieldMissed] = query.value(9);
1347 thread[History::FieldDuration] = query.value(11);1370 thread[History::FieldDuration] = query.value(8);
1348 thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(13).toString(), true);1371 thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(10).toString(), true);
1372 threads << thread;
1349 break;1373 break;
1350 }1374 }
1351 threads << thread;
1352 }1375 }
1376
1377 // get the participants
1378 threads = participantsForThreads(threads);
1379
1380 // and append the threads with no participants
1381 threads << threadsWithoutParticipants;
1382
1353 return threads;1383 return threads;
1354}1384}
13551385
13561386
=== modified file 'plugins/sqlite/sqlitehistoryplugin.h'
--- plugins/sqlite/sqlitehistoryplugin.h 2017-03-20 14:27:34 +0000
+++ plugins/sqlite/sqlitehistoryplugin.h 2017-03-20 14:27:35 +0000
@@ -59,11 +59,11 @@
59 History::EventType type,59 History::EventType type,
60 const QVariantMap &properties,60 const QVariantMap &properties,
61 History::MatchFlags matchFlags = History::MatchCaseSensitive);61 History::MatchFlags matchFlags = History::MatchCaseSensitive);
62 virtual QString threadIdForProperties(const QString &accountId,62 QString threadIdForProperties(const QString &accountId,
63 History::EventType type,63 History::EventType type,
64 const QVariantMap &properties,64 const QVariantMap &properties,
65 History::MatchFlags matchFlags = History::MatchCaseSensitive) override;65 History::MatchFlags matchFlags = History::MatchCaseSensitive) override;
6666 QList<QVariantMap> participantsForThreads(const QList<QVariantMap> &threadIds) override;
67 QList<QVariantMap> eventsForThread(const QVariantMap &thread);67 QList<QVariantMap> eventsForThread(const QVariantMap &thread);
6868
69 QVariantMap getSingleThread(History::EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap());69 QVariantMap getSingleThread(History::EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap());
7070
=== modified file 'src/contactmatcher.cpp'
--- src/contactmatcher.cpp 2017-03-20 14:27:34 +0000
+++ src/contactmatcher.cpp 2017-03-20 14:27:35 +0000
@@ -102,14 +102,12 @@
102102
103 QString normalizedId = normalizeId(identifier);103 QString normalizedId = normalizeId(identifier);
104104
105 QVariantMap map;
105 // first do a simple string match on the map106 // first do a simple string match on the map
106 if (internalMap.contains(normalizedId)) {107 if (internalMap.contains(normalizedId)) {
107 return internalMap[normalizedId];108 map = internalMap[normalizedId];
108 }109 } else if (History::TelepathyHelper::instance()->ready()) {
109 110 // and if there was no match, asynchronously request the info, and return an empty map for now
110 QVariantMap map;
111 // and if there was no match, asynchronously request the info, and return an empty map for now
112 if (History::TelepathyHelper::instance()->ready()) {
113 map = requestContactInfo(accountId, normalizedId, synchronous);111 map = requestContactInfo(accountId, normalizedId, synchronous);
114 } else if (!synchronous) {112 } else if (!synchronous) {
115 RequestInfo info{accountId, normalizedId};113 RequestInfo info{accountId, normalizedId};
@@ -314,9 +312,15 @@
314{312{
315 QString normalizedId = normalizeId(identifier);313 QString normalizedId = normalizeId(identifier);
316 QStringList addressableVCardFields = addressableFields(accountId);314 QStringList addressableVCardFields = addressableFields(accountId);
315
316 QVariantMap contactInfo;
317 contactInfo[History::FieldIdentifier] = identifier;
318 contactInfo[History::FieldAccountId] = accountId;
319
317 if (addressableVCardFields.isEmpty()) {320 if (addressableVCardFields.isEmpty()) {
321 mContactMap[accountId][identifier] = contactInfo;
318 // FIXME: add support for generic accounts322 // FIXME: add support for generic accounts
319 return QVariantMap();323 return contactInfo;
320 }324 }
321325
322 bool phoneCompare = addressableVCardFields.contains("tel");326 bool phoneCompare = addressableVCardFields.contains("tel");
@@ -357,7 +361,8 @@
357 if (synchronous) {361 if (synchronous) {
358 QList<QContact> contacts = mManager->contacts(topLevelFilter, QList<QContactSortOrder>(), hint);362 QList<QContact> contacts = mManager->contacts(topLevelFilter, QList<QContactSortOrder>(), hint);
359 if (contacts.isEmpty()) {363 if (contacts.isEmpty()) {
360 return QVariantMap();364 mContactMap[accountId][identifier] = contactInfo;
365 return contactInfo;
361 }366 }
362 // for synchronous requests, return the results right away.367 // for synchronous requests, return the results right away.
363 return matchAndUpdate(accountId, normalizedId, contacts.first());368 return matchAndUpdate(accountId, normalizedId, contacts.first());
@@ -466,6 +471,14 @@
466 return mAddressableFields[accountId];471 return mAddressableFields[accountId];
467 }472 }
468473
474 // FIXME: hardcoding account IDs here is not a good idea, we have to fix addressable fields on
475 // the protocols themselves
476 if (accountId.startsWith("irc/irc")) {
477 QStringList empty;
478 mAddressableFields[accountId] = empty;
479 return empty;
480 }
481
469 Tp::AccountPtr account = History::TelepathyHelper::instance()->accountForId(accountId);482 Tp::AccountPtr account = History::TelepathyHelper::instance()->accountForId(accountId);
470 QStringList fields;483 QStringList fields;
471 if (!account.isNull()) {484 if (!account.isNull()) {
472485
=== modified file 'src/eventview.cpp'
--- src/eventview.cpp 2017-03-20 14:27:34 +0000
+++ src/eventview.cpp 2017-03-20 14:27:35 +0000
@@ -53,7 +53,7 @@
53 }53 }
5454
55 if (filterNull || filter.match(event.properties())) {55 if (filterNull || filter.match(event.properties())) {
56 filtered << events;56 filtered << event;
57 }57 }
58 }58 }
5959
6060
=== modified file 'src/manager.cpp'
--- src/manager.cpp 2017-03-20 14:27:34 +0000
+++ src/manager.cpp 2017-03-20 14:27:35 +0000
@@ -164,6 +164,20 @@
164 return d->dbus->threadForProperties(accountId, type, properties, matchFlags, create);164 return d->dbus->threadForProperties(accountId, type, properties, matchFlags, create);
165}165}
166166
167/**
168 * @brief Request the list of participants of the given threads to the service
169 * @param threads The threads to be filled
170 *
171 * This is an asychronous request. When finished, the signal @ref threadParticipantsChanged
172 * will be emitted for the given threads.
173 */
174void Manager::requestThreadParticipants(const Threads &threads)
175{
176 Q_D(Manager);
177
178 d->dbus->requestThreadParticipants(threads);
179}
180
167Thread Manager::getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties)181Thread Manager::getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties)
168{182{
169 Q_D(Manager);183 Q_D(Manager);
170184
=== modified file 'src/manager.h'
--- src/manager.h 2017-03-20 14:27:34 +0000
+++ src/manager.h 2017-03-20 14:27:35 +0000
@@ -66,7 +66,7 @@
66 const QVariantMap &properties,66 const QVariantMap &properties,
67 History::MatchFlags matchFlags = History::MatchCaseSensitive,67 History::MatchFlags matchFlags = History::MatchCaseSensitive,
68 bool create = false);68 bool create = false);
6969 void requestThreadParticipants(const History::Threads &threads);
70 Thread getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap());70 Thread getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap());
7171
72 bool writeEvents(const History::Events &events);72 bool writeEvents(const History::Events &events);
7373
=== modified file 'src/managerdbus.cpp'
--- src/managerdbus.cpp 2017-03-20 14:27:34 +0000
+++ src/managerdbus.cpp 2017-03-20 14:27:35 +0000
@@ -28,6 +28,8 @@
28#include <QDBusReply>28#include <QDBusReply>
29#include <QDBusMetaType>29#include <QDBusMetaType>
3030
31#include <QDebug>
32
31Q_DECLARE_METATYPE(QList< QVariantMap >)33Q_DECLARE_METATYPE(QList< QVariantMap >)
3234
33namespace History35namespace History
@@ -103,6 +105,29 @@
103 return thread;105 return thread;
104}106}
105107
108void ManagerDBus::requestThreadParticipants(const Threads &threads)
109{
110 QList<QVariantMap> ids;
111 Q_FOREACH(const Thread &thread, threads) {
112 QVariantMap id;
113 id[History::FieldAccountId] = thread.accountId();
114 id[History::FieldThreadId] = thread.threadId();
115 id[History::FieldType] = thread.type();
116 ids << id;
117 }
118
119 QDBusPendingCall call = mInterface.asyncCall("ParticipantsForThreads", QVariant::fromValue(ids));
120 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
121 connect(watcher, &QDBusPendingCallWatcher::finished, [this, threads](QDBusPendingCallWatcher *watcher) {
122 QDBusPendingReply<QList<QVariantMap> > reply = *watcher;
123 Q_FOREACH(const QVariantMap &map, reply.value()) {
124 History::Thread thread = History::Thread::fromProperties(map);
125 Q_EMIT threadParticipantsChanged(thread, History::Participants(), History::Participants(), thread.participants());
126 watcher->deleteLater();
127 }
128 });
129}
130
106bool ManagerDBus::writeEvents(const Events &events)131bool ManagerDBus::writeEvents(const Events &events)
107{132{
108 QList<QVariantMap> eventMap = eventsToProperties(events);133 QList<QVariantMap> eventMap = eventsToProperties(events);
109134
=== modified file 'src/managerdbus_p.h'
--- src/managerdbus_p.h 2017-03-20 14:27:34 +0000
+++ src/managerdbus_p.h 2017-03-20 14:27:35 +0000
@@ -50,7 +50,7 @@
50 const QVariantMap &properties,50 const QVariantMap &properties,
51 History::MatchFlags matchFlags,51 History::MatchFlags matchFlags,
52 bool create);52 bool create);
5353 void requestThreadParticipants(const History::Threads &threads);
54 bool writeEvents(const History::Events &events);54 bool writeEvents(const History::Events &events);
55 bool removeThreads(const Threads &threads);55 bool removeThreads(const Threads &threads);
56 bool removeEvents(const Events &events);56 bool removeEvents(const Events &events);
@@ -80,7 +80,6 @@
80 const QList<QVariantMap> &added,80 const QList<QVariantMap> &added,
81 const QList<QVariantMap> &removed,81 const QList<QVariantMap> &removed,
82 const QList<QVariantMap> &modified);82 const QList<QVariantMap> &modified);
83
84 void onEventsAdded(const QList<QVariantMap> &events);83 void onEventsAdded(const QList<QVariantMap> &events);
85 void onEventsModified(const QList<QVariantMap> &events);84 void onEventsModified(const QList<QVariantMap> &events);
86 void onEventsRemoved(const QList<QVariantMap> &events);85 void onEventsRemoved(const QList<QVariantMap> &events);
8786
=== modified file 'src/plugin.h'
--- src/plugin.h 2017-03-20 14:27:34 +0000
+++ src/plugin.h 2017-03-20 14:27:35 +0000
@@ -69,6 +69,7 @@
69 EventType type,69 EventType type,
70 const QVariantMap &properties,70 const QVariantMap &properties,
71 History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0;71 History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0;
72 virtual QList<QVariantMap> participantsForThreads(const QList<QVariantMap> &threadIds) = 0;
7273
73 virtual QList<QVariantMap> eventsForThread(const QVariantMap &thread) = 0;74 virtual QList<QVariantMap> eventsForThread(const QVariantMap &thread) = 0;
7475
7576
=== modified file 'src/utils.cpp'
--- src/utils.cpp 2017-03-20 14:27:34 +0000
+++ src/utils.cpp 2017-03-20 14:27:35 +0000
@@ -178,10 +178,14 @@
178178
179bool Utils::shouldIncludeParticipants(const Thread &thread)179bool Utils::shouldIncludeParticipants(const Thread &thread)
180{180{
181 // FIXME181 return shouldIncludeParticipants(thread.accountId(), thread.chatType());
182 // this is obviously incorrect. we have to query the protocol files as a final solution182}
183 if (protocolFromAccountId(thread.accountId()) == "irc") {183
184 return thread.chatType() != History::ChatTypeRoom;184bool Utils::shouldIncludeParticipants(const QString &accountId, const ChatType &type)
185{
186 // FIXME: this is obviously incorrect. we have to query the protocol files as a final solution
187 if (protocolFromAccountId(accountId) == "irc") {
188 return type != ChatTypeRoom;
185 }189 }
186 return true;190 return true;
187}191}
188192
=== modified file 'src/utils_p.h'
--- src/utils_p.h 2017-03-20 14:27:34 +0000
+++ src/utils_p.h 2017-03-20 14:27:35 +0000
@@ -37,6 +37,7 @@
37 static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags);37 static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags);
38 static bool shouldGroupThread(const Thread &thread);38 static bool shouldGroupThread(const Thread &thread);
39 static bool shouldIncludeParticipants(const Thread &thread);39 static bool shouldIncludeParticipants(const Thread &thread);
40 static bool shouldIncludeParticipants(const QString &accountId, const History::ChatType &type);
40 static QString normalizeId(const QString &accountId, const QString &id);41 static QString normalizeId(const QString &accountId, const QString &id);
41 static QVariant getUserValue(const QString &interface, const QString &propName);42 static QVariant getUserValue(const QString &interface, const QString &propName);
4243
4344
=== modified file 'tests/daemon/DaemonTest.cpp'
--- tests/daemon/DaemonTest.cpp 2016-11-03 13:20:17 +0000
+++ tests/daemon/DaemonTest.cpp 2017-03-20 14:27:35 +0000
@@ -141,8 +141,6 @@
141 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();141 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
142 QCOMPARE(threads.count(), 1);142 QCOMPARE(threads.count(), 1);
143 History::Thread thread = threads.first();143 History::Thread thread = threads.first();
144 QCOMPARE(thread.participants().count(), 1);
145 QCOMPARE(thread.participants().first().identifier(), sender);
146144
147 QTRY_COMPARE(threadsModifiedSpy.count(), 1);145 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
148 threads = threadsModifiedSpy.first().first().value<History::Threads>();146 threads = threadsModifiedSpy.first().first().value<History::Threads>();
@@ -252,8 +250,6 @@
252 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();250 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
253 QCOMPARE(threads.count(), 1);251 QCOMPARE(threads.count(), 1);
254 History::Thread thread = threads.first();252 History::Thread thread = threads.first();
255 QCOMPARE(thread.participants().count(), 1);
256 QCOMPARE(thread.participants().first().identifier(), recipient);
257253
258 QTRY_COMPARE(threadsModifiedSpy.count(), 1);254 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
259 threads = threadsModifiedSpy.first().first().value<History::Threads>();255 threads = threadsModifiedSpy.first().first().value<History::Threads>();
@@ -296,8 +292,6 @@
296 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();292 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
297 QCOMPARE(threads.count(), 1);293 QCOMPARE(threads.count(), 1);
298 History::Thread thread = threads.first();294 History::Thread thread = threads.first();
299 QCOMPARE(thread.participants().count(), 1);
300 QCOMPARE(thread.participants().first().identifier(), callerId);
301295
302 QTRY_COMPARE(threadsModifiedSpy.count(), 1);296 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
303 threads = threadsModifiedSpy.first().first().value<History::Threads>();297 threads = threadsModifiedSpy.first().first().value<History::Threads>();
@@ -357,8 +351,6 @@
357 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();351 History::Threads threads = threadsAddedSpy.first().first().value<History::Threads>();
358 QCOMPARE(threads.count(), 1);352 QCOMPARE(threads.count(), 1);
359 History::Thread thread = threads.first();353 History::Thread thread = threads.first();
360 QCOMPARE(thread.participants().count(), 1);
361 QCOMPARE(thread.participants().first().identifier(), phoneNumber);
362354
363 QTRY_COMPARE(threadsModifiedSpy.count(), 1);355 QTRY_COMPARE(threadsModifiedSpy.count(), 1);
364 threads = threadsModifiedSpy.first().first().value<History::Threads>();356 threads = threadsModifiedSpy.first().first().value<History::Threads>();
365357
=== modified file 'tests/libhistoryservice/ManagerTest.cpp'
--- tests/libhistoryservice/ManagerTest.cpp 2017-03-20 14:27:34 +0000
+++ tests/libhistoryservice/ManagerTest.cpp 2017-03-20 14:27:35 +0000
@@ -96,7 +96,6 @@
9696
97 QCOMPARE(thread.accountId(), accountId);97 QCOMPARE(thread.accountId(), accountId);
98 QCOMPARE(thread.type(), type);98 QCOMPARE(thread.type(), type);
99 QCOMPARE(thread.participants().identifiers(), participants);
10099
101 // now try to get the thread again to see if it is returned correctly100 // now try to get the thread again to see if it is returned correctly
102 History::Thread sameThread = mManager->threadForParticipants(accountId, type, participantsToMatch, matchFlags, false);101 History::Thread sameThread = mManager->threadForParticipants(accountId, type, participantsToMatch, matchFlags, false);
@@ -137,14 +136,16 @@
137136
138void ManagerTest::testWriteEvents()137void ManagerTest::testWriteEvents()
139{138{
139 QString textParticipant("textParticipant");
140 QString voiceParticipant("voiceParticipant");
140 // create two threads, one for voice and one for text141 // create two threads, one for voice and one for text
141 History::Thread textThread = mManager->threadForParticipants("textAccountId",142 History::Thread textThread = mManager->threadForParticipants("textAccountId",
142 History::EventTypeText,143 History::EventTypeText,
143 QStringList()<< "textParticipant",144 QStringList()<< textParticipant,
144 History::MatchCaseSensitive, true);145 History::MatchCaseSensitive, true);
145 History::Thread voiceThread = mManager->threadForParticipants("voiceAccountId",146 History::Thread voiceThread = mManager->threadForParticipants("voiceAccountId",
146 History::EventTypeVoice,147 History::EventTypeVoice,
147 QStringList()<< "voiceParticipant",148 QStringList()<< voiceParticipant,
148 History::MatchCaseSensitive, true);149 History::MatchCaseSensitive, true);
149 // insert some text and voice events150 // insert some text and voice events
150 History::Events events;151 History::Events events;
@@ -152,7 +153,7 @@
152 History::TextEvent textEvent(textThread.accountId(),153 History::TextEvent textEvent(textThread.accountId(),
153 textThread.threadId(),154 textThread.threadId(),
154 QString("eventId%1").arg(i),155 QString("eventId%1").arg(i),
155 textThread.participants().first().identifier(),156 textParticipant,
156 QDateTime::currentDateTime(),157 QDateTime::currentDateTime(),
157 true,158 true,
158 QString("Hello world %1").arg(i),159 QString("Hello world %1").arg(i),
@@ -163,7 +164,7 @@
163 History::VoiceEvent voiceEvent(voiceThread.accountId(),164 History::VoiceEvent voiceEvent(voiceThread.accountId(),
164 voiceThread.threadId(),165 voiceThread.threadId(),
165 QString("eventId%1").arg(i),166 QString("eventId%1").arg(i),
166 voiceThread.participants().first().identifier(),167 voiceParticipant,
167 QDateTime::currentDateTime(),168 QDateTime::currentDateTime(),
168 true,169 true,
169 true);170 true);
@@ -214,14 +215,16 @@
214215
215void ManagerTest::testRemoveEvents()216void ManagerTest::testRemoveEvents()
216{217{
218 QString textParticipant("textParticipant");
219 QString voiceParticipant("voiceParticipant");
217 // create two threads, one for voice and one for text220 // create two threads, one for voice and one for text
218 History::Thread textThread = mManager->threadForParticipants("textRemovableAccount",221 History::Thread textThread = mManager->threadForParticipants("textRemovableAccount",
219 History::EventTypeText,222 History::EventTypeText,
220 QStringList()<< "textParticipant",223 QStringList()<< textParticipant,
221 History::MatchCaseSensitive, true);224 History::MatchCaseSensitive, true);
222 History::Thread voiceThread = mManager->threadForParticipants("voiceRemovableAccount",225 History::Thread voiceThread = mManager->threadForParticipants("voiceRemovableAccount",
223 History::EventTypeVoice,226 History::EventTypeVoice,
224 QStringList()<< "voiceParticipant",227 QStringList()<< voiceParticipant,
225 History::MatchCaseSensitive, true);228 History::MatchCaseSensitive, true);
226 // insert some text and voice events229 // insert some text and voice events
227 History::Events events;230 History::Events events;
@@ -229,7 +232,7 @@
229 History::TextEvent textEvent(textThread.accountId(),232 History::TextEvent textEvent(textThread.accountId(),
230 textThread.threadId(),233 textThread.threadId(),
231 QString("eventToBeRemoved%1").arg(i),234 QString("eventToBeRemoved%1").arg(i),
232 textThread.participants().first().identifier(),235 textParticipant,
233 QDateTime::currentDateTime(),236 QDateTime::currentDateTime(),
234 true,237 true,
235 QString("Hello world %1").arg(i),238 QString("Hello world %1").arg(i),
@@ -239,7 +242,7 @@
239 History::VoiceEvent voiceEvent(voiceThread.accountId(),242 History::VoiceEvent voiceEvent(voiceThread.accountId(),
240 voiceThread.threadId(),243 voiceThread.threadId(),
241 QString("eventToBeRemoved%1").arg(i),244 QString("eventToBeRemoved%1").arg(i),
242 voiceThread.participants().first().identifier(),245 voiceParticipant,
243 QDateTime::currentDateTime(),246 QDateTime::currentDateTime(),
244 true,247 true,
245 true);248 true);
@@ -280,14 +283,16 @@
280283
281void ManagerTest::testGetSingleEvent()284void ManagerTest::testGetSingleEvent()
282{285{
286 QString textParticipant("textSingleParticipant");
287 QString voiceParticipant("voiceSingleParticipant");
283 // create two threads, one for voice and one for text288 // create two threads, one for voice and one for text
284 History::Thread textThread = mManager->threadForParticipants("textSingleAccount",289 History::Thread textThread = mManager->threadForParticipants("textSingleAccount",
285 History::EventTypeText,290 History::EventTypeText,
286 QStringList()<< "textSingleParticipant",291 QStringList()<< textParticipant,
287 History::MatchCaseSensitive, true);292 History::MatchCaseSensitive, true);
288 History::Thread voiceThread = mManager->threadForParticipants("voiceSingleAccount",293 History::Thread voiceThread = mManager->threadForParticipants("voiceSingleAccount",
289 History::EventTypeVoice,294 History::EventTypeVoice,
290 QStringList()<< "voiceSingleParticipant",295 QStringList()<< voiceParticipant,
291 History::MatchCaseSensitive, true);296 History::MatchCaseSensitive, true);
292297
293 // now add two events298 // now add two events
294299
=== modified file 'tests/plugins/sqlite/SqlitePluginTest.cpp'
--- tests/plugins/sqlite/SqlitePluginTest.cpp 2016-09-09 20:00:09 +0000
+++ tests/plugins/sqlite/SqlitePluginTest.cpp 2017-03-20 14:27:35 +0000
@@ -189,7 +189,6 @@
189 QCOMPARE(retrievedThread[History::FieldType], thread[History::FieldType]);189 QCOMPARE(retrievedThread[History::FieldType], thread[History::FieldType]);
190 QCOMPARE(retrievedThread[History::FieldCount], thread[History::FieldCount]);190 QCOMPARE(retrievedThread[History::FieldCount], thread[History::FieldCount]);
191 QCOMPARE(retrievedThread[History::FieldUnreadCount], thread[History::FieldUnreadCount]);191 QCOMPARE(retrievedThread[History::FieldUnreadCount], thread[History::FieldUnreadCount]);
192 QCOMPARE(retrievedThread[History::FieldParticipants], thread[History::FieldParticipants]);
193}192}
194193
195void SqlitePluginTest::testEmptyThreadForParticipants()194void SqlitePluginTest::testEmptyThreadForParticipants()
@@ -219,7 +218,6 @@
219 QCOMPARE(retrievedThread[History::FieldType], thread[History::FieldType]);218 QCOMPARE(retrievedThread[History::FieldType], thread[History::FieldType]);
220 QCOMPARE(retrievedThread[History::FieldCount], thread[History::FieldCount]);219 QCOMPARE(retrievedThread[History::FieldCount], thread[History::FieldCount]);
221 QCOMPARE(retrievedThread[History::FieldUnreadCount], thread[History::FieldUnreadCount]);220 QCOMPARE(retrievedThread[History::FieldUnreadCount], thread[History::FieldUnreadCount]);
222 QCOMPARE(retrievedThread[History::FieldParticipants], thread[History::FieldParticipants]);
223221
224 // FIXME: check that the last event data is also present222 // FIXME: check that the last event data is also present
225}223}

Subscribers

People subscribed via source and target branches

to all changes: