Merge lp:~phablet-team/history-service/improve_participant_changes_notification into lp:history-service/staging
- improve_participant_changes_notification
- Merge into staging
Proposed by
Tiago Salem Herrmann
Status: | Superseded |
---|---|
Proposed branch: | lp:~phablet-team/history-service/improve_participant_changes_notification |
Merge into: | lp:history-service/staging |
Diff against target: |
1002 lines (+285/-64) 27 files modified
Ubuntu/History/historyeventmodel.cpp (+2/-2) Ubuntu/History/historymodel.cpp (+1/-1) Ubuntu/History/historythreadmodel.cpp (+18/-0) Ubuntu/History/historythreadmodel.h (+1/-0) daemon/HistoryService.xml (+13/-0) daemon/callchannelobserver.cpp (+16/-2) daemon/callchannelobserver.h (+2/-1) daemon/historydaemon.cpp (+66/-33) daemon/historydaemon.h (+7/-7) daemon/historyservicedbus.cpp (+8/-0) daemon/historyservicedbus.h (+8/-0) plugins/sqlite/sqlitehistoryplugin.cpp (+7/-2) src/contactmatcher.cpp (+37/-15) src/contactmatcher_p.h (+2/-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/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 (+12/-1) src/utils_p.h (+1/-0) |
To merge this branch: | bzr merge lp:~phablet-team/history-service/improve_participant_changes_notification |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phablet Team | Pending | ||
Review via email: mp+316150@code.launchpad.net |
This proposal supersedes a proposal from 2017-01-26.
This proposal has been superseded by a proposal from 2017-03-22.
Commit message
Improve the notifications of participants changing
Description of the change
Improve the notifications of participants changing
To post a comment you must log in.
- 257. By Tiago Salem Herrmann
-
merge parent branch
- 258. By Tiago Salem Herrmann
-
only remove participants from irc rooms
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-21 15:00:24 +0000 |
4 | @@ -95,7 +95,7 @@ |
5 | result = event.eventId(); |
6 | break; |
7 | case SenderIdRole: |
8 | - result = event.senderId(); |
9 | + result = History::ContactMatcher::normalizeId(event.senderId()); |
10 | break; |
11 | case SenderRole: |
12 | result = History::ContactMatcher::instance()->contactInfo(event.accountId(), event.senderId()); |
13 | @@ -168,7 +168,7 @@ |
14 | break; |
15 | case RemoteParticipantRole: |
16 | if (!voiceEvent.isNull()) { |
17 | - result = voiceEvent.remoteParticipant(); |
18 | + result = History::ContactMatcher::normalizeId(voiceEvent.remoteParticipant()); |
19 | } |
20 | break; |
21 | case SubjectAsAliasRole: |
22 | |
23 | === modified file 'Ubuntu/History/historymodel.cpp' |
24 | --- Ubuntu/History/historymodel.cpp 2016-11-24 12:22:11 +0000 |
25 | +++ Ubuntu/History/historymodel.cpp 2017-02-21 15:00:24 +0000 |
26 | @@ -385,7 +385,7 @@ |
27 | // FIXME: right now we might be grouping threads from different accounts, so we are not enforcing |
28 | // the accountId to be the same as the one from the contact info, but maybe we need to do that |
29 | // in the future? |
30 | - if (History::Utils::compareIds(accountId, participant.identifier(), identifier)) { |
31 | + if (History::Utils::compareIds(accountId, History::ContactMatcher::normalizeId(participant.identifier()), identifier)) { |
32 | changedIndexes << idx; |
33 | } |
34 | } |
35 | |
36 | === modified file 'Ubuntu/History/historythreadmodel.cpp' |
37 | --- Ubuntu/History/historythreadmodel.cpp 2016-06-17 01:49:46 +0000 |
38 | +++ Ubuntu/History/historythreadmodel.cpp 2017-02-21 15:00:24 +0000 |
39 | @@ -294,6 +294,10 @@ |
40 | SIGNAL(threadsRemoved(History::Threads)), |
41 | SLOT(onThreadsRemoved(History::Threads))); |
42 | connect(mThreadView.data(), |
43 | + SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)), |
44 | + SLOT(onThreadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants))); |
45 | + |
46 | + connect(mThreadView.data(), |
47 | SIGNAL(invalidated()), |
48 | SLOT(triggerQueryUpdate())); |
49 | |
50 | @@ -311,6 +315,20 @@ |
51 | fetchMore(QModelIndex()); |
52 | } |
53 | |
54 | + |
55 | +void HistoryThreadModel::onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified) |
56 | +{ |
57 | + int pos = mThreads.indexOf(thread); |
58 | + if (pos >= 0) { |
59 | + mThreads[pos].removeParticipants(removed); |
60 | + mThreads[pos].removeParticipants(modified); |
61 | + mThreads[pos].addParticipants(added); |
62 | + mThreads[pos].addParticipants(modified); |
63 | + QModelIndex idx = index(pos); |
64 | + Q_EMIT dataChanged(idx, idx); |
65 | + } |
66 | +} |
67 | + |
68 | void HistoryThreadModel::onThreadsAdded(const History::Threads &threads) |
69 | { |
70 | if (threads.isEmpty()) { |
71 | |
72 | === modified file 'Ubuntu/History/historythreadmodel.h' |
73 | --- Ubuntu/History/historythreadmodel.h 2016-06-17 01:49:46 +0000 |
74 | +++ Ubuntu/History/historythreadmodel.h 2017-02-21 15:00:24 +0000 |
75 | @@ -76,6 +76,7 @@ |
76 | virtual void onThreadsAdded(const History::Threads &threads); |
77 | virtual void onThreadsModified(const History::Threads &threads); |
78 | virtual void onThreadsRemoved(const History::Threads &threads); |
79 | + virtual void onThreadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified); |
80 | |
81 | protected: |
82 | History::Threads fetchNextPage(); |
83 | |
84 | === modified file 'daemon/HistoryService.xml' |
85 | --- daemon/HistoryService.xml 2016-04-15 22:23:21 +0000 |
86 | +++ daemon/HistoryService.xml 2017-02-21 15:00:24 +0000 |
87 | @@ -159,5 +159,18 @@ |
88 | <arg name="events" type="a(a{sv})"/> |
89 | <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList < QVariantMap >"/> |
90 | </signal> |
91 | + <signal name="ThreadParticipantsChanged"> |
92 | + <dox:d><![CDATA[ |
93 | + Participants changed in a certain thread changed. |
94 | + ]]></dox:d> |
95 | + <arg name="thread" type="a{sv}"/> |
96 | + <arg name="added" type="a(a{sv})"/> |
97 | + <arg name="removed" type="a(a{sv})"/> |
98 | + <arg name="modified" type="a(a{sv})"/> |
99 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/> |
100 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QList < QVariantMap >"/> |
101 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QList < QVariantMap >"/> |
102 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QList < QVariantMap >"/> |
103 | + </signal> |
104 | </interface> |
105 | </node> |
106 | |
107 | === modified file 'daemon/callchannelobserver.cpp' |
108 | --- daemon/callchannelobserver.cpp 2013-07-12 14:30:18 +0000 |
109 | +++ daemon/callchannelobserver.cpp 2017-02-21 15:00:24 +0000 |
110 | @@ -40,6 +40,7 @@ |
111 | SLOT(onCallStateChanged(Tp::CallState))); |
112 | |
113 | mChannels.append(callChannel); |
114 | + mCallStates[callChannel.data()] = callChannel->callState(); |
115 | } |
116 | |
117 | |
118 | @@ -51,11 +52,24 @@ |
119 | } |
120 | |
121 | switch (state) { |
122 | - case Tp::CallStateEnded: |
123 | - Q_EMIT callEnded(Tp::CallChannelPtr(channel)); |
124 | + case Tp::CallStateEnded: { |
125 | + bool incoming = !channel->isRequested(); |
126 | + bool missed = incoming && channel->callStateReason().reason == Tp::CallStateChangeReasonNoAnswer; |
127 | + |
128 | + // If the call state is not missed at this point, we need to check from which state we transitioned to ended, |
129 | + // if from Initialised, it means it was indeed missed |
130 | + if (incoming && !missed) { |
131 | + missed = mCallStates[channel] == Tp::CallStateInitialised; |
132 | + } |
133 | + mCallStates.remove(channel); |
134 | + mChannels.removeOne(Tp::CallChannelPtr(channel)); |
135 | + Q_EMIT callEnded(Tp::CallChannelPtr(channel), missed); |
136 | break; |
137 | + } |
138 | case Tp::CallStateActive: |
139 | channel->setProperty("activeTimestamp", QDateTime::currentDateTime()); |
140 | + default: |
141 | + mCallStates[channel] = state; |
142 | break; |
143 | } |
144 | } |
145 | |
146 | === modified file 'daemon/callchannelobserver.h' |
147 | --- daemon/callchannelobserver.h 2013-07-12 14:30:18 +0000 |
148 | +++ daemon/callchannelobserver.h 2017-02-21 15:00:24 +0000 |
149 | @@ -35,13 +35,14 @@ |
150 | void onCallChannelAvailable(Tp::CallChannelPtr callChannel); |
151 | |
152 | Q_SIGNALS: |
153 | - void callEnded(Tp::CallChannelPtr callChannel); |
154 | + void callEnded(Tp::CallChannelPtr callChannel, bool missed); |
155 | |
156 | protected Q_SLOTS: |
157 | void onCallStateChanged(Tp::CallState state); |
158 | |
159 | private: |
160 | QList<Tp::CallChannelPtr> mChannels; |
161 | + QMap<Tp::CallChannel*,Tp::CallState> mCallStates; |
162 | }; |
163 | |
164 | #endif // CALLCHANNELOBSERVER_H |
165 | |
166 | === modified file 'daemon/historydaemon.cpp' |
167 | --- daemon/historydaemon.cpp 2016-11-24 02:02:32 +0000 |
168 | +++ daemon/historydaemon.cpp 2017-02-21 15:00:24 +0000 |
169 | @@ -131,8 +131,8 @@ |
170 | History::TelepathyHelper::instance()->registerChannelObserver(); |
171 | |
172 | connect(&mCallObserver, |
173 | - SIGNAL(callEnded(Tp::CallChannelPtr)), |
174 | - SLOT(onCallEnded(Tp::CallChannelPtr))); |
175 | + SIGNAL(callEnded(Tp::CallChannelPtr, bool)), |
176 | + SLOT(onCallEnded(Tp::CallChannelPtr, bool))); |
177 | connect(&mTextObserver, |
178 | SIGNAL(messageReceived(Tp::TextChannelPtr,Tp::ReceivedMessage)), |
179 | SLOT(onMessageReceived(Tp::TextChannelPtr,Tp::ReceivedMessage))); |
180 | @@ -187,6 +187,7 @@ |
181 | QVariantMap properties; |
182 | QVariantList participants; |
183 | QStringList participantIds; |
184 | + QString accountId = textChannel->property(History::FieldAccountId).toString(); |
185 | |
186 | ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>(); |
187 | RolesMap roles; |
188 | @@ -197,7 +198,7 @@ |
189 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) { |
190 | QVariantMap contactProperties; |
191 | contactProperties[History::FieldAlias] = contact->alias(); |
192 | - contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString(); |
193 | + contactProperties[History::FieldAccountId] = accountId; |
194 | contactProperties[History::FieldIdentifier] = contact->id(); |
195 | contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular; |
196 | contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; |
197 | @@ -208,7 +209,7 @@ |
198 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(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::ParticipantStateRemotePending; |
205 | contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; |
206 | @@ -219,7 +220,7 @@ |
207 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(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::ParticipantStateLocalPending; |
214 | contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; |
215 | @@ -231,7 +232,7 @@ |
216 | textChannel->targetContact() == textChannel->connection()->selfContact()) { |
217 | QVariantMap contactProperties; |
218 | contactProperties[History::FieldAlias] = textChannel->targetContact()->alias(); |
219 | - contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString(); |
220 | + contactProperties[History::FieldAccountId] = accountId; |
221 | contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id(); |
222 | contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular; |
223 | participantIds << textChannel->targetContact()->id(); |
224 | @@ -370,7 +371,7 @@ |
225 | return mBackend->getSingleEvent((History::EventType)type, accountId, threadId, eventId); |
226 | } |
227 | |
228 | -bool HistoryDaemon::writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties) |
229 | +bool HistoryDaemon::writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties, bool notify) |
230 | { |
231 | if (!mBackend) { |
232 | return false; |
233 | @@ -427,13 +428,13 @@ |
234 | mBackend->endBatchOperation(); |
235 | |
236 | // and last but not least, notify the results |
237 | - if (!newEvents.isEmpty()) { |
238 | + if (!newEvents.isEmpty() && notify) { |
239 | mDBus.notifyEventsAdded(newEvents); |
240 | } |
241 | - if (!modifiedEvents.isEmpty()) { |
242 | + if (!modifiedEvents.isEmpty() && notify) { |
243 | mDBus.notifyEventsModified(modifiedEvents); |
244 | } |
245 | - if (!threads.isEmpty()) { |
246 | + if (!threads.isEmpty() && notify) { |
247 | mDBus.notifyThreadsModified(threads.values()); |
248 | } |
249 | return true; |
250 | @@ -562,7 +563,7 @@ |
251 | &mTextObserver, SLOT(onTextChannelAvailable(Tp::TextChannelPtr))); |
252 | } |
253 | |
254 | -void HistoryDaemon::onCallEnded(const Tp::CallChannelPtr &channel) |
255 | +void HistoryDaemon::onCallEnded(const Tp::CallChannelPtr &channel, bool missed) |
256 | { |
257 | QVariantMap properties = propertiesFromChannel(channel); |
258 | QVariantList participants; |
259 | @@ -592,7 +593,6 @@ |
260 | // FIXME: check if checking for isRequested() is enough |
261 | bool incoming = !channel->isRequested(); |
262 | int duration; |
263 | - bool missed = incoming && channel->callStateReason().reason == Tp::CallStateChangeReasonNoAnswer; |
264 | |
265 | if (!missed) { |
266 | QDateTime activeTime = channel->property("activeTimestamp").toDateTime(); |
267 | @@ -620,6 +620,7 @@ |
268 | // for Rooms we need to explicitly create the thread to allow users to send messages to groups even |
269 | // before they receive any message. |
270 | // for other types, we can wait until messages are received |
271 | + bool notify = false; |
272 | if (channel->targetHandleType() == Tp::HandleTypeRoom) { |
273 | QString accountId = channel->property(History::FieldAccountId).toString(); |
274 | QVariantMap properties = propertiesFromChannel(channel); |
275 | @@ -641,12 +642,13 @@ |
276 | |
277 | // write information event including all initial invitees |
278 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) { |
279 | - writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias()); |
280 | + writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias(), QString(), QString(), false); |
281 | } |
282 | |
283 | // update participants only if the thread is not available previously. Otherwise we'll wait for membersChanged event |
284 | // for reflect in conversation information events for modified participants. |
285 | - updateRoomParticipants(channel); |
286 | + updateRoomParticipants(channel, false); |
287 | + notify = true; |
288 | } |
289 | |
290 | // write an entry saying you joined the group if 'joined' flag in thread is false and modify that flag. |
291 | @@ -657,7 +659,8 @@ |
292 | writeInformationEvent(thread, History::InformationTypeSelfJoined); |
293 | } |
294 | // update backend |
295 | - updateRoomProperties(channel, QVariantMap{{"Joined", true}}); |
296 | + updateRoomProperties(channel, QVariantMap{{"Joined", true}}, false); |
297 | + notify = true; |
298 | } |
299 | |
300 | Tp::AbstractInterface *room_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomInterface>(); |
301 | @@ -685,6 +688,10 @@ |
302 | |
303 | connect(roles_interface, SIGNAL(RolesChanged(const HandleRolesMap&, const HandleRolesMap&)), SLOT(onRolesChanged(const HandleRolesMap&, const HandleRolesMap&))); |
304 | } |
305 | + |
306 | + if (notify) { |
307 | + updateRoomParticipants(channel, true); |
308 | + } |
309 | } |
310 | |
311 | void HistoryDaemon::onGroupMembersChanged(const Tp::Contacts &groupMembersAdded, |
312 | @@ -711,18 +718,33 @@ |
313 | matchFlagsForChannel(channel), |
314 | false); |
315 | if (!thread.isEmpty()) { |
316 | + QList<QVariantMap> added; |
317 | + QList<QVariantMap> removed; |
318 | + QList<QVariantMap> modified; |
319 | if (hasRemotePendingMembersAdded) { |
320 | Q_FOREACH (const Tp::ContactPtr& contact, groupRemotePendingMembersAdded) { |
321 | if (!foundInThread(contact, thread)) { |
322 | - writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias()); |
323 | + writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias(), QString(), QString(), true); |
324 | + QVariantMap participant; |
325 | + participant[History::FieldIdentifier] = contact->id(); |
326 | + participant[History::FieldAlias] = contact->alias(); |
327 | + participant[History::FieldParticipantState] = History::ParticipantStateRemotePending; |
328 | + added << participant; |
329 | } |
330 | } |
331 | + |
332 | } |
333 | if (hasMembersAdded) { |
334 | Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) { |
335 | // if this member was not previously regular member in thread, notify about his join |
336 | if (!foundAsMemberInThread(contact, thread)) { |
337 | - writeInformationEvent(thread, History::InformationTypeJoined, contact->alias()); |
338 | + writeInformationEvent(thread, History::InformationTypeJoined, contact->alias(), QString(), QString(), true); |
339 | + |
340 | + QVariantMap participant; |
341 | + participant[History::FieldIdentifier] = contact->id(); |
342 | + participant[History::FieldAlias] = contact->alias(); |
343 | + participant[History::FieldParticipantState] = History::ParticipantStateRegular; |
344 | + added << participant; |
345 | } |
346 | } |
347 | } |
348 | @@ -743,25 +765,30 @@ |
349 | } |
350 | writeInformationEvent(thread, type); |
351 | // update backend |
352 | - updateRoomProperties(channel, QVariantMap{{"Joined", false}}); |
353 | + updateRoomProperties(channel, QVariantMap{{"Joined", false}}, true); |
354 | } |
355 | else // don't notify any other group member removal if we are leaving the group |
356 | { |
357 | Q_FOREACH (const Tp::ContactPtr& contact, groupMembersRemoved) { |
358 | // inform about removed members other than us |
359 | if (contact->id() != channel->groupSelfContact()->id()) { |
360 | - writeInformationEvent(thread, History::InformationTypeLeaving, contact->alias()); |
361 | + writeInformationEvent(thread, History::InformationTypeLeaving, contact->alias(), QString(), QString(), true); |
362 | } |
363 | + QVariantMap participant; |
364 | + participant[History::FieldIdentifier] = contact->id(); |
365 | + participant[History::FieldAlias] = contact->alias(); |
366 | + removed << participant; |
367 | } |
368 | } |
369 | } |
370 | + mDBus.notifyThreadParticipantsChanged(thread, added, removed, QList<QVariantMap>()); |
371 | } |
372 | } |
373 | |
374 | - updateRoomParticipants(channel); |
375 | + updateRoomParticipants(channel, true); |
376 | } |
377 | |
378 | -void HistoryDaemon::updateRoomParticipants(const Tp::TextChannelPtr channel) |
379 | +void HistoryDaemon::updateRoomParticipants(const Tp::TextChannelPtr channel, bool notify) |
380 | { |
381 | if (!channel) { |
382 | return; |
383 | @@ -811,12 +838,14 @@ |
384 | QString accountId = channel->property(History::FieldAccountId).toString(); |
385 | QString threadId = channel->targetId(); |
386 | if (mBackend->updateRoomParticipants(accountId, threadId, History::EventTypeText, participants)) { |
387 | - QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); |
388 | - mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); |
389 | + if (notify) { |
390 | + QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); |
391 | + mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); |
392 | + } |
393 | } |
394 | } |
395 | |
396 | -void HistoryDaemon::updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap) |
397 | +void HistoryDaemon::updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap, bool notify) |
398 | { |
399 | if (!channel) { |
400 | return; |
401 | @@ -841,8 +870,10 @@ |
402 | QString accountId = channel->property(History::FieldAccountId).toString(); |
403 | QString threadId = channel->targetId(); |
404 | if (mBackend->updateRoomParticipantsRoles(accountId, threadId, History::EventTypeText, participantsRoles)) { |
405 | - QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); |
406 | - mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); |
407 | + if (notify) { |
408 | + QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); |
409 | + mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); |
410 | + } |
411 | } |
412 | |
413 | // update self roles in room properties |
414 | @@ -865,19 +896,21 @@ |
415 | updateRoomProperties(accountId, threadId, type, properties, invalidated); |
416 | } |
417 | |
418 | -void HistoryDaemon::updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties) |
419 | +void HistoryDaemon::updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties, bool notify) |
420 | { |
421 | QString accountId = channel->property(History::FieldAccountId).toString(); |
422 | QString threadId = channel->targetId(); |
423 | History::EventType type = History::EventTypeText; |
424 | - updateRoomProperties(accountId, threadId, type, properties, QStringList()); |
425 | + updateRoomProperties(accountId, threadId, type, properties, QStringList(), notify); |
426 | } |
427 | |
428 | -void HistoryDaemon::updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated) |
429 | +void HistoryDaemon::updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated, bool notify) |
430 | { |
431 | if (mBackend->updateRoomInfo(accountId, threadId, type, properties, invalidated)) { |
432 | - QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); |
433 | - mDBus.notifyThreadsModified(QList<QVariantMap>() << thread); |
434 | + if (notify) { |
435 | + QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); |
436 | + mDBus.notifyThreadsModified(QList<QVariantMap>() << thread); |
437 | + } |
438 | } |
439 | } |
440 | |
441 | @@ -1191,7 +1224,7 @@ |
442 | return reply.value(); |
443 | } |
444 | |
445 | -void HistoryDaemon::writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject, const QString &sender, const QString &text) |
446 | +void HistoryDaemon::writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject, const QString &sender, const QString &text, bool notify) |
447 | { |
448 | History::TextEvent historyEvent = History::TextEvent(thread[History::FieldAccountId].toString(), |
449 | thread[History::FieldThreadId].toString(), |
450 | @@ -1207,7 +1240,7 @@ |
451 | QDateTime::currentDateTime(), |
452 | subject, |
453 | type); |
454 | - writeEvents(QList<QVariantMap>() << historyEvent.properties(), thread); |
455 | + writeEvents(QList<QVariantMap>() << historyEvent.properties(), thread, notify); |
456 | } |
457 | |
458 | void HistoryDaemon::writeRoomChangesInformationEvents(const QVariantMap &thread, const QVariantMap &interfaceProperties) |
459 | |
460 | === modified file 'daemon/historydaemon.h' |
461 | --- daemon/historydaemon.h 2016-10-20 13:56:10 +0000 |
462 | +++ daemon/historydaemon.h 2017-02-21 15:00:24 +0000 |
463 | @@ -54,13 +54,13 @@ |
464 | QVariantMap getSingleEvent(int type, const QString &accountId, const QString &threadId, const QString &eventId); |
465 | QVariantMap getSingleEventFromTextChannel(const Tp::TextChannelPtr textChannel, const QString &messageId); |
466 | |
467 | - bool writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties); |
468 | + bool writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties, bool notify = true); |
469 | bool removeEvents(const QList<QVariantMap> &events); |
470 | bool removeThreads(const QList<QVariantMap> &threads); |
471 | |
472 | private Q_SLOTS: |
473 | void onObserverCreated(); |
474 | - void onCallEnded(const Tp::CallChannelPtr &channel); |
475 | + void onCallEnded(const Tp::CallChannelPtr &channel, bool missed); |
476 | void onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); |
477 | void onMessageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); |
478 | void onMessageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken); |
479 | @@ -73,14 +73,14 @@ |
480 | |
481 | protected: |
482 | History::MatchFlags matchFlagsForChannel(const Tp::ChannelPtr &channel); |
483 | - void updateRoomParticipants(const Tp::TextChannelPtr channel); |
484 | - void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap); |
485 | + void updateRoomParticipants(const Tp::TextChannelPtr channel, bool notify = true); |
486 | + void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap, bool notify = true); |
487 | QString hashThread(const QVariantMap &thread); |
488 | static QVariantMap getInterfaceProperties(const Tp::AbstractInterface *interface); |
489 | - void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties); |
490 | - void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated); |
491 | + void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties, bool notify = true); |
492 | + void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated, bool notify = true); |
493 | |
494 | - void writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject = QString(), const QString &sender = QString("self"), const QString &text = QString()); |
495 | + void writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject = QString(), const QString &sender = QString("self"), const QString &text = QString(), bool notify = true); |
496 | |
497 | void writeRoomChangesInformationEvents(const QVariantMap &thread, const QVariantMap &interfaceProperties); |
498 | void writeRolesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap); |
499 | |
500 | === modified file 'daemon/historyservicedbus.cpp' |
501 | --- daemon/historyservicedbus.cpp 2016-11-24 01:56:01 +0000 |
502 | +++ daemon/historyservicedbus.cpp 2017-02-21 15:00:24 +0000 |
503 | @@ -75,6 +75,14 @@ |
504 | Q_EMIT EventsRemoved(events); |
505 | } |
506 | |
507 | +void HistoryServiceDBus::notifyThreadParticipantsChanged(const QVariantMap &thread, |
508 | + const QList<QVariantMap> &added, |
509 | + const QList<QVariantMap> &removed, |
510 | + const QList<QVariantMap> &modified) |
511 | +{ |
512 | + Q_EMIT ThreadParticipantsChanged(thread, added, removed, modified); |
513 | +} |
514 | + |
515 | QVariantMap HistoryServiceDBus::ThreadForProperties(const QString &accountId, |
516 | int type, |
517 | const QVariantMap &properties, |
518 | |
519 | === modified file 'daemon/historyservicedbus.h' |
520 | --- daemon/historyservicedbus.h 2016-06-17 01:49:46 +0000 |
521 | +++ daemon/historyservicedbus.h 2017-02-21 15:00:24 +0000 |
522 | @@ -39,6 +39,10 @@ |
523 | void notifyThreadsAdded(const QList<QVariantMap> &threads); |
524 | void notifyThreadsModified(const QList<QVariantMap> &threads); |
525 | void notifyThreadsRemoved(const QList<QVariantMap> &threads); |
526 | + void notifyThreadParticipantsChanged(const QVariantMap &thread, |
527 | + const QList<QVariantMap> &added, |
528 | + const QList<QVariantMap> &removed, |
529 | + const QList<QVariantMap> &modified); |
530 | |
531 | void notifyEventsAdded(const QList<QVariantMap> &events); |
532 | void notifyEventsModified(const QList<QVariantMap> &events); |
533 | @@ -70,6 +74,10 @@ |
534 | void ThreadsAdded(const QList<QVariantMap> &threads); |
535 | void ThreadsModified(const QList<QVariantMap> &threads); |
536 | void ThreadsRemoved(const QList<QVariantMap> &threads); |
537 | + void ThreadParticipantsChanged(const QVariantMap &thread, |
538 | + const QList<QVariantMap> &added, |
539 | + const QList<QVariantMap> &removed, |
540 | + const QList<QVariantMap> &modified); |
541 | |
542 | void EventsAdded(const QList<QVariantMap> &events); |
543 | void EventsModified(const QList<QVariantMap> &events); |
544 | |
545 | === modified file 'plugins/sqlite/sqlitehistoryplugin.cpp' |
546 | --- plugins/sqlite/sqlitehistoryplugin.cpp 2016-11-24 01:50:48 +0000 |
547 | +++ plugins/sqlite/sqlitehistoryplugin.cpp 2017-02-21 15:00:24 +0000 |
548 | @@ -1290,6 +1290,9 @@ |
549 | chatRoomInfo["SelfRoles"] = query1.value(20).toInt(); |
550 | |
551 | thread[History::FieldChatRoomInfo] = chatRoomInfo; |
552 | + if (!History::Utils::shouldIncludeParticipants(thread)) { |
553 | + thread.remove(History::FieldParticipants); |
554 | + } |
555 | } |
556 | break; |
557 | case History::EventTypeVoice: |
558 | @@ -1353,8 +1356,10 @@ |
559 | event[History::FieldSenderId] = query.value(3); |
560 | event[History::FieldTimestamp] = toLocalTimeString(query.value(4).toDateTime()); |
561 | event[History::FieldNewEvent] = query.value(5).toBool(); |
562 | - QStringList participants = query.value(6).toString().split("|,|"); |
563 | - event[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true); |
564 | + if (type != History::EventTypeText) { |
565 | + QStringList participants = query.value(6).toString().split("|,|"); |
566 | + event[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true); |
567 | + } |
568 | |
569 | switch (type) { |
570 | case History::EventTypeText: |
571 | |
572 | === modified file 'src/contactmatcher.cpp' |
573 | --- src/contactmatcher.cpp 2016-06-17 01:49:46 +0000 |
574 | +++ src/contactmatcher.cpp 2017-02-21 15:00:24 +0000 |
575 | @@ -99,21 +99,24 @@ |
576 | { |
577 | InternalContactMap &internalMap = mContactMap[accountId]; |
578 | |
579 | + |
580 | + QString normalizedId = normalizeId(identifier); |
581 | + |
582 | // first do a simple string match on the map |
583 | - if (internalMap.contains(identifier)) { |
584 | - return internalMap[identifier]; |
585 | + if (internalMap.contains(normalizedId)) { |
586 | + return internalMap[normalizedId]; |
587 | } |
588 | |
589 | QVariantMap map; |
590 | - |
591 | // and if there was no match, asynchronously request the info, and return an empty map for now |
592 | if (History::TelepathyHelper::instance()->ready()) { |
593 | - map = requestContactInfo(accountId, identifier, synchronous); |
594 | + map = requestContactInfo(accountId, normalizedId, synchronous); |
595 | } else if (!synchronous) { |
596 | - RequestInfo info{accountId, identifier}; |
597 | + RequestInfo info{accountId, normalizedId}; |
598 | mPendingRequests.append(info); |
599 | } |
600 | - map[History::FieldIdentifier] = identifier; |
601 | + |
602 | + map[History::FieldIdentifier] = normalizedId; |
603 | map[History::FieldAccountId] = accountId; |
604 | |
605 | QMapIterator<QString, QVariant> i(properties); |
606 | @@ -124,7 +127,7 @@ |
607 | } |
608 | } |
609 | |
610 | - mContactMap[accountId][identifier] = map; |
611 | + mContactMap[accountId][normalizedId] = map; |
612 | return map; |
613 | } |
614 | |
615 | @@ -309,6 +312,7 @@ |
616 | */ |
617 | QVariantMap ContactMatcher::requestContactInfo(const QString &accountId, const QString &identifier, bool synchronous) |
618 | { |
619 | + QString normalizedId = normalizeId(identifier); |
620 | QStringList addressableVCardFields = addressableFields(accountId); |
621 | if (addressableVCardFields.isEmpty()) { |
622 | // FIXME: add support for generic accounts |
623 | @@ -328,7 +332,7 @@ |
624 | QContactUnionFilter topLevelFilter; |
625 | Q_FOREACH(const QString &field, addressableVCardFields) { |
626 | if (field == "tel") { |
627 | - topLevelFilter.append(QContactPhoneNumber::match(identifier)); |
628 | + topLevelFilter.append(QContactPhoneNumber::match(normalizedId)); |
629 | } else { |
630 | // FIXME: handle more fields |
631 | // rely on a generic field filter |
632 | @@ -340,7 +344,7 @@ |
633 | QContactDetailFilter valueFilter = QContactDetailFilter(); |
634 | valueFilter.setDetailType(QContactExtendedDetail::Type, QContactExtendedDetail::FieldData); |
635 | valueFilter.setMatchFlags(QContactFilter::MatchExactly); |
636 | - valueFilter.setValue(identifier); |
637 | + valueFilter.setValue(normalizedId); |
638 | |
639 | QContactIntersectionFilter intersectionFilter; |
640 | intersectionFilter.append(nameFilter); |
641 | @@ -356,7 +360,7 @@ |
642 | return QVariantMap(); |
643 | } |
644 | // for synchronous requests, return the results right away. |
645 | - return matchAndUpdate(accountId, identifier, contacts.first()); |
646 | + return matchAndUpdate(accountId, normalizedId, contacts.first()); |
647 | } else { |
648 | // check if there is a request already going on for the given contact |
649 | Q_FOREACH(const RequestInfo &info, mRequests.values()) { |
650 | @@ -365,7 +369,7 @@ |
651 | continue; |
652 | } |
653 | |
654 | - if (info.identifier == identifier) { |
655 | + if (info.identifier == normalizedId) { |
656 | // if so, just wait for it to finish |
657 | return QVariantMap(); |
658 | } |
659 | @@ -381,7 +385,7 @@ |
660 | |
661 | RequestInfo info; |
662 | info.accountId = accountId; |
663 | - info.identifier = identifier; |
664 | + info.identifier = normalizedId; |
665 | mRequests[request] = info; |
666 | request->start(); |
667 | } |
668 | @@ -414,7 +418,6 @@ |
669 | QStringList fields = addressableFields(accountId); |
670 | bool match = false; |
671 | |
672 | - int fieldsCount = fields.count(); |
673 | Q_FOREACH(const QString &field, fields) { |
674 | if (field == "tel") { |
675 | QList<QContactDetail> details = contact.details(QContactDetail::TypePhoneNumber); |
676 | @@ -467,8 +470,14 @@ |
677 | QStringList fields; |
678 | if (!account.isNull()) { |
679 | fields = account->protocolInfo().addressableVCardFields(); |
680 | - mAddressableFields[accountId] = fields; |
681 | - } |
682 | + } |
683 | + |
684 | + // fallback to phone number matching in case everything else fails |
685 | + if (fields.isEmpty()) { |
686 | + fields << "tel"; |
687 | + } |
688 | + |
689 | + mAddressableFields[accountId] = fields; |
690 | |
691 | return fields; |
692 | } |
693 | @@ -478,4 +487,17 @@ |
694 | return (map.contains(History::FieldContactId) && !map[History::FieldContactId].toString().isEmpty()); |
695 | } |
696 | |
697 | +QString ContactMatcher::normalizeId(const QString &id) |
698 | +{ |
699 | + QString normalizedId = id; |
700 | + |
701 | + // FIXME: this is a hack so that SIP URIs get converted into phone numbers for contact matching |
702 | + if (normalizedId.startsWith("sip:")) { |
703 | + normalizedId.remove("sip:").remove(QRegularExpression("@.*$")); |
704 | + } |
705 | + |
706 | + return normalizedId; |
707 | +} |
708 | + |
709 | + |
710 | } |
711 | |
712 | === modified file 'src/contactmatcher_p.h' |
713 | --- src/contactmatcher_p.h 2016-06-17 01:49:46 +0000 |
714 | +++ src/contactmatcher_p.h 2017-02-21 15:00:24 +0000 |
715 | @@ -51,6 +51,8 @@ |
716 | // this will only watch for contact changes affecting the identifier, but won't fetch contact info |
717 | void watchIdentifier(const QString &accountId, const QString &identifier, const QVariantMap ¤tInfo = QVariantMap()); |
718 | |
719 | + static QString normalizeId(const QString &id); |
720 | + |
721 | Q_SIGNALS: |
722 | void contactInfoChanged(const QString &acountId, const QString &identifier, const QVariantMap &contactInfo); |
723 | |
724 | |
725 | === modified file 'src/manager.cpp' |
726 | --- src/manager.cpp 2016-06-17 01:49:46 +0000 |
727 | +++ src/manager.cpp 2017-02-21 15:00:24 +0000 |
728 | @@ -65,6 +65,9 @@ |
729 | SIGNAL(threadsRemoved(History::Threads)), |
730 | SIGNAL(threadsRemoved(History::Threads))); |
731 | connect(d->dbus.data(), |
732 | + SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)), |
733 | + SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants))); |
734 | + connect(d->dbus.data(), |
735 | SIGNAL(eventsAdded(History::Events)), |
736 | SIGNAL(eventsAdded(History::Events))); |
737 | connect(d->dbus.data(), |
738 | |
739 | === modified file 'src/manager.h' |
740 | --- src/manager.h 2016-06-17 01:49:46 +0000 |
741 | +++ src/manager.h 2017-02-21 15:00:24 +0000 |
742 | @@ -79,6 +79,7 @@ |
743 | void threadsAdded(const History::Threads &threads); |
744 | void threadsModified(const History::Threads &threads); |
745 | void threadsRemoved(const History::Threads &threads); |
746 | + void threadParticipantsChanged(const History::Thread &thread, const History::Participants &added, const History::Participants &removed, const History::Participants &modified); |
747 | |
748 | void eventsAdded(const History::Events &events); |
749 | void eventsModified(const History::Events &events); |
750 | |
751 | === modified file 'src/managerdbus.cpp' |
752 | --- src/managerdbus.cpp 2016-06-17 01:49:46 +0000 |
753 | +++ src/managerdbus.cpp 2017-02-21 15:00:24 +0000 |
754 | @@ -50,6 +50,12 @@ |
755 | connection.connect(DBusService, DBusObjectPath, DBusInterface, "ThreadsRemoved", |
756 | this, SLOT(onThreadsRemoved(QList<QVariantMap>))); |
757 | |
758 | + connection.connect(DBusService, DBusObjectPath, DBusInterface, "ThreadParticipantsChanged", |
759 | + this, SLOT(onThreadParticipantsChanged(QVariantMap, |
760 | + QList<QVariantMap>, |
761 | + QList<QVariantMap>, |
762 | + QList<QVariantMap>))); |
763 | + |
764 | connection.connect(DBusService, DBusObjectPath, DBusInterface, "EventsAdded", |
765 | this, SLOT(onEventsAdded(QList<QVariantMap>))); |
766 | connection.connect(DBusService, DBusObjectPath, DBusInterface, "EventsModified", |
767 | @@ -168,6 +174,17 @@ |
768 | Q_EMIT threadsRemoved(threadsFromProperties(threads)); |
769 | } |
770 | |
771 | +void ManagerDBus::onThreadParticipantsChanged(const QVariantMap &thread, |
772 | + const QList<QVariantMap> &added, |
773 | + const QList<QVariantMap> &removed, |
774 | + const QList<QVariantMap> &modified) |
775 | +{ |
776 | + Q_EMIT threadParticipantsChanged(threadsFromProperties(QList<QVariantMap>() << thread).first(), |
777 | + Participants::fromVariantMapList(added), |
778 | + Participants::fromVariantMapList(removed), |
779 | + Participants::fromVariantMapList(modified)); |
780 | +} |
781 | + |
782 | void ManagerDBus::onEventsAdded(const QList<QVariantMap> &events) |
783 | { |
784 | Q_EMIT eventsAdded(eventsFromProperties(events)); |
785 | |
786 | === modified file 'src/managerdbus_p.h' |
787 | --- src/managerdbus_p.h 2016-06-17 01:49:46 +0000 |
788 | +++ src/managerdbus_p.h 2017-02-21 15:00:24 +0000 |
789 | @@ -62,6 +62,10 @@ |
790 | void threadsAdded(const History::Threads &threads); |
791 | void threadsModified(const History::Threads &threads); |
792 | void threadsRemoved(const History::Threads &threads); |
793 | + void threadParticipantsChanged(const History::Thread &thread, |
794 | + const History::Participants &added, |
795 | + const History::Participants &removed, |
796 | + const History::Participants &modified); |
797 | |
798 | void eventsAdded(const History::Events &events); |
799 | void eventsModified(const History::Events &events); |
800 | @@ -71,6 +75,10 @@ |
801 | void onThreadsAdded(const QList<QVariantMap> &threads); |
802 | void onThreadsModified(const QList<QVariantMap> &threads); |
803 | void onThreadsRemoved(const QList<QVariantMap> &threads); |
804 | + void onThreadParticipantsChanged(const QVariantMap &thread, |
805 | + const QList<QVariantMap> &added, |
806 | + const QList<QVariantMap> &removed, |
807 | + const QList<QVariantMap> &modified); |
808 | |
809 | void onEventsAdded(const QList<QVariantMap> &events); |
810 | void onEventsModified(const QList<QVariantMap> &events); |
811 | |
812 | === modified file 'src/participant.cpp' |
813 | --- src/participant.cpp 2016-11-24 01:04:37 +0000 |
814 | +++ src/participant.cpp 2017-02-21 15:00:24 +0000 |
815 | @@ -233,6 +233,15 @@ |
816 | return participants; |
817 | } |
818 | |
819 | +Participants Participants::fromVariantMapList(const QList<QVariantMap> &list) |
820 | +{ |
821 | + Participants participants; |
822 | + Q_FOREACH(const QVariantMap& entry, list) { |
823 | + participants << Participant::fromProperties(entry); |
824 | + } |
825 | + return participants; |
826 | +} |
827 | + |
828 | QVariantList Participants::toVariantList() const |
829 | { |
830 | QVariantList list; |
831 | |
832 | === modified file 'src/participant.h' |
833 | --- src/participant.h 2016-11-24 01:04:37 +0000 |
834 | +++ src/participant.h 2017-02-21 15:00:24 +0000 |
835 | @@ -79,6 +79,7 @@ |
836 | QStringList identifiers() const; |
837 | static Participants fromVariant(const QVariant &variant); |
838 | static Participants fromVariantList(const QVariantList &list); |
839 | + static Participants fromVariantMapList(const QList<QVariantMap> &list); |
840 | static Participants fromStringList(const QStringList &list); |
841 | QVariantList toVariantList() const; |
842 | History::Participants filterByState(uint state) const; |
843 | |
844 | === modified file 'src/thread.cpp' |
845 | --- src/thread.cpp 2016-07-12 02:08:11 +0000 |
846 | +++ src/thread.cpp 2017-02-21 15:00:24 +0000 |
847 | @@ -192,6 +192,22 @@ |
848 | return selfData < otherData; |
849 | } |
850 | |
851 | +void Thread::removeParticipants(const Participants &participants) |
852 | +{ |
853 | + Q_D(Thread); |
854 | + Q_FOREACH(const Participant &participant, participants) { |
855 | + d->participants.removeAll(participant); |
856 | + } |
857 | +} |
858 | + |
859 | +void Thread::addParticipants(const Participants &participants) |
860 | +{ |
861 | + Q_D(Thread); |
862 | + Q_FOREACH(const Participant &participant, participants) { |
863 | + d->participants.append(participant); |
864 | + } |
865 | +} |
866 | + |
867 | QVariantMap Thread::properties() const |
868 | { |
869 | Q_D(const Thread); |
870 | |
871 | === modified file 'src/thread.h' |
872 | --- src/thread.h 2016-07-12 01:59:06 +0000 |
873 | +++ src/thread.h 2017-02-21 15:00:24 +0000 |
874 | @@ -73,6 +73,8 @@ |
875 | ChatType chatType() const; |
876 | Threads groupedThreads() const; |
877 | QVariantMap chatRoomInfo() const; |
878 | + void addParticipants(const History::Participants &participants); |
879 | + void removeParticipants(const History::Participants &participants); |
880 | |
881 | bool isNull() const; |
882 | bool operator==(const Thread &other) const; |
883 | |
884 | === modified file 'src/threadview.cpp' |
885 | --- src/threadview.cpp 2015-10-01 19:44:45 +0000 |
886 | +++ src/threadview.cpp 2017-02-21 15:00:24 +0000 |
887 | @@ -89,6 +89,18 @@ |
888 | } |
889 | } |
890 | |
891 | +void ThreadViewPrivate::_d_threadParticipantsChanged(const History::Thread &thread, |
892 | + const History::Participants &added, |
893 | + const History::Participants &removed, |
894 | + const History::Participants &modified) |
895 | +{ |
896 | + Q_Q(ThreadView); |
897 | + Threads filtered = filteredThreads(History::Threads() << thread); |
898 | + if (!filtered.isEmpty()) { |
899 | + Q_EMIT q->threadParticipantsChanged(filtered.first(), added, removed, modified); |
900 | + } |
901 | +} |
902 | + |
903 | // ------------- ThreadView ------------------------------------------------------- |
904 | |
905 | ThreadView::ThreadView(History::EventType type, |
906 | @@ -132,6 +144,9 @@ |
907 | connect(Manager::instance(), |
908 | SIGNAL(threadsRemoved(History::Threads)), |
909 | SLOT(_d_threadsRemoved(History::Threads))); |
910 | + connect(Manager::instance(), |
911 | + SIGNAL(threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants)), |
912 | + SLOT(_d_threadParticipantsChanged(History::Thread, History::Participants, History::Participants, History::Participants))); |
913 | } |
914 | |
915 | ThreadView::~ThreadView() |
916 | |
917 | === modified file 'src/threadview.h' |
918 | --- src/threadview.h 2015-09-21 20:05:06 +0000 |
919 | +++ src/threadview.h 2017-02-21 15:00:24 +0000 |
920 | @@ -52,12 +52,20 @@ |
921 | void threadsAdded(const History::Threads &threads); |
922 | void threadsModified(const History::Threads &threads); |
923 | void threadsRemoved(const History::Threads &threads); |
924 | + void threadParticipantsChanged(const History::Thread &thread, |
925 | + const History::Participants &added, |
926 | + const History::Participants &removed, |
927 | + const History::Participants &modified); |
928 | void invalidated(); |
929 | |
930 | private: |
931 | Q_PRIVATE_SLOT(d_func(), void _d_threadsAdded(const History::Threads &threads)) |
932 | Q_PRIVATE_SLOT(d_func(), void _d_threadsModified(const History::Threads &threads)) |
933 | Q_PRIVATE_SLOT(d_func(), void _d_threadsRemoved(const History::Threads &threads)) |
934 | + Q_PRIVATE_SLOT(d_func(), void _d_threadParticipantsChanged(const History::Thread &thread, |
935 | + const History::Participants &added, |
936 | + const History::Participants &removed, |
937 | + const History::Participants &modified)) |
938 | QScopedPointer<ThreadViewPrivate> d_ptr; |
939 | |
940 | }; |
941 | |
942 | === modified file 'src/threadview_p.h' |
943 | --- src/threadview_p.h 2013-09-17 21:33:34 +0000 |
944 | +++ src/threadview_p.h 2017-02-21 15:00:24 +0000 |
945 | @@ -50,6 +50,10 @@ |
946 | void _d_threadsAdded(const History::Threads &threads); |
947 | void _d_threadsModified(const History::Threads &threads); |
948 | void _d_threadsRemoved(const History::Threads &threads); |
949 | + void _d_threadParticipantsChanged(const History::Thread &thread, |
950 | + const History::Participants &added, |
951 | + const History::Participants &removed, |
952 | + const History::Participants &modified); |
953 | |
954 | ThreadView *q_ptr; |
955 | }; |
956 | |
957 | === modified file 'src/utils.cpp' |
958 | --- src/utils.cpp 2016-11-08 16:02:18 +0000 |
959 | +++ src/utils.cpp 2017-02-21 15:00:24 +0000 |
960 | @@ -50,6 +50,7 @@ |
961 | if (protocolFlags.isEmpty()) { |
962 | protocolFlags["ofono"] = MatchPhoneNumber; |
963 | protocolFlags["multimedia"] = MatchPhoneNumber; |
964 | + protocolFlags["sip"] = MatchPhoneNumber; |
965 | } |
966 | |
967 | QString protocol = protocolFromAccountId(accountId); |
968 | @@ -57,7 +58,7 @@ |
969 | return protocolFlags[protocol]; |
970 | } |
971 | |
972 | - // default to this value |
973 | + // default to phone number matching for now |
974 | return History::MatchCaseSensitive; |
975 | } |
976 | |
977 | @@ -175,4 +176,14 @@ |
978 | return QVariant(); |
979 | } |
980 | |
981 | +bool Utils::shouldIncludeParticipants(const Thread &thread) |
982 | +{ |
983 | + // FIXME |
984 | + // this is obviously incorrect. we have to query the protocol files as a final solution |
985 | + if (protocolFromAccountId(thread.accountId()) == "irc") { |
986 | + return thread.chatType() != History::ChatTypeRoom; |
987 | + } |
988 | + return true; |
989 | +} |
990 | + |
991 | } |
992 | |
993 | === modified file 'src/utils_p.h' |
994 | --- src/utils_p.h 2016-11-08 16:02:18 +0000 |
995 | +++ src/utils_p.h 2017-02-21 15:00:24 +0000 |
996 | @@ -36,6 +36,7 @@ |
997 | static bool compareParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags); |
998 | static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags); |
999 | static bool shouldGroupThread(const Thread &thread); |
1000 | + static bool shouldIncludeParticipants(const Thread &thread); |
1001 | static QString normalizeId(const QString &accountId, const QString &id); |
1002 | static QVariant getUserValue(const QString &interface, const QString &propName); |
1003 |