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