Merge lp:~phablet-team/history-service/no_participants_on_threads into lp:history-service/staging
- no_participants_on_threads
- Merge into staging
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 |
Related bugs: |
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.
- 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
Preview Diff
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 < QVariantMap >"/> |
283 | + <arg name="participants" type="a(a{sv})" direction="out"/> |
284 | + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList < QVariantMap >"/> |
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 | } |
looks good to me.
thanks.