Merge lp:~phablet-team/history-service/thread_search_model into lp:history-service
- thread_search_model
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~phablet-team/history-service/thread_search_model |
Merge into: | lp:history-service |
Diff against target: |
1280 lines (+645/-114) 21 files modified
Ubuntu/History/CMakeLists.txt (+1/-1) Ubuntu/History/historygroupedthreadsmodel.cpp (+25/-8) Ubuntu/History/historythreadmodel.cpp (+172/-16) Ubuntu/History/historythreadmodel.h (+24/-0) daemon/historydaemon.cpp (+37/-11) daemon/historydaemon.h (+11/-0) daemon/historyservicedbus.cpp (+0/-30) daemon/historyservicedbus.h (+0/-8) plugins/sqlite/sqlitehistoryplugin.cpp (+5/-5) plugins/sqlite/sqlitehistoryplugin.h (+1/-1) plugins/sqlite/sqlitehistorythreadview.cpp (+226/-4) plugins/sqlite/sqlitehistorythreadview.h (+28/-1) src/PluginThreadView.xml (+28/-0) src/contactmatcher.cpp (+9/-1) src/pluginthreadview.cpp (+19/-1) src/pluginthreadview.h (+11/-2) src/thread.cpp (+13/-4) src/thread.h (+1/-0) src/threadview.cpp (+25/-15) src/threadview.h (+3/-3) src/threadview_p.h (+6/-3) |
To merge this branch: | bzr merge lp:~phablet-team/history-service/thread_search_model |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
system-apps-ci-bot | continuous-integration | Needs Fixing | |
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+286656@code.launchpad.net |
Commit message
Add search capabilities to the thread models.
Description of the change
Add search capabilities to the thread models.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 231. By Gustavo Pichorim Boiko
-
Fix the interaction with the cached thread grouping.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:231
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 232. By Gustavo Pichorim Boiko
-
Instead of having NextPage() as virtual directly, add a fetchNextPage() virtual
function so that we can use NextPage to preprocess the results. - 233. By Gustavo Pichorim Boiko
-
Revert the approach: the grouping will have to be implemented in the plugin itself.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:233
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 234. By Gustavo Pichorim Boiko
-
Start implementing the grouping all in server side.
- 235. By Gustavo Pichorim Boiko
-
Emit the signals in the manager itself so that they can be used in the views.
- 236. By Gustavo Pichorim Boiko
-
Make it possible to handle thread changes in the server side view.
- 237. By Gustavo Pichorim Boiko
-
Get the signals from the thread view itself and not from the manager as
it will have the threads already filtered.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:237
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 238. By Gustavo Pichorim Boiko
-
Start to add code to handle thread changes in the server side of the thread view.
Also fix the SqlitePluginTest.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:238
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 239. By Gustavo Pichorim Boiko
-
Fix ContactMatcher.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:239
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 240. By Gustavo Pichorim Boiko
-
Fix parsing grouped threads.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:240
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 241. By Gustavo Pichorim Boiko
-
Implement the group updating.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:241
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 242. By Gustavo Pichorim Boiko
-
Fix the dbus connection of signals.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:242
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 243. By Gustavo Pichorim Boiko
-
Handle thread removing and adding.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:243
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:243
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 244. By Gustavo Pichorim Boiko
-
Merge trunk
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:244
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 244. By Gustavo Pichorim Boiko
-
Merge trunk
- 243. By Gustavo Pichorim Boiko
-
Handle thread removing and adding.
- 242. By Gustavo Pichorim Boiko
-
Fix the dbus connection of signals.
- 241. By Gustavo Pichorim Boiko
-
Implement the group updating.
- 240. By Gustavo Pichorim Boiko
-
Fix parsing grouped threads.
- 239. By Gustavo Pichorim Boiko
-
Fix ContactMatcher.
- 238. By Gustavo Pichorim Boiko
-
Start to add code to handle thread changes in the server side of the thread view.
Also fix the SqlitePluginTest. - 237. By Gustavo Pichorim Boiko
-
Get the signals from the thread view itself and not from the manager as
it will have the threads already filtered. - 236. By Gustavo Pichorim Boiko
-
Make it possible to handle thread changes in the server side view.
- 235. By Gustavo Pichorim Boiko
-
Emit the signals in the manager itself so that they can be used in the views.
Preview Diff
1 | === modified file 'Ubuntu/History/CMakeLists.txt' | |||
2 | --- Ubuntu/History/CMakeLists.txt 2015-09-28 14:26:09 +0000 | |||
3 | +++ Ubuntu/History/CMakeLists.txt 2017-01-26 18:33:44 +0000 | |||
4 | @@ -26,7 +26,7 @@ | |||
5 | 26 | historyqmltexteventattachment.h | 26 | historyqmltexteventattachment.h |
6 | 27 | historyqmlunionfilter.h | 27 | historyqmlunionfilter.h |
7 | 28 | historythreadmodel.h | 28 | historythreadmodel.h |
9 | 29 | ) | 29 | ) |
10 | 30 | 30 | ||
11 | 31 | include_directories( | 31 | include_directories( |
12 | 32 | ${CMAKE_SOURCE_DIR}/src | 32 | ${CMAKE_SOURCE_DIR}/src |
13 | 33 | 33 | ||
14 | === modified file 'Ubuntu/History/historygroupedthreadsmodel.cpp' | |||
15 | --- Ubuntu/History/historygroupedthreadsmodel.cpp 2015-10-08 19:35:40 +0000 | |||
16 | +++ Ubuntu/History/historygroupedthreadsmodel.cpp 2017-01-26 18:33:44 +0000 | |||
17 | @@ -247,25 +247,42 @@ | |||
18 | 247 | removeThreadFromGroup(thread); | 247 | removeThreadFromGroup(thread); |
19 | 248 | return; | 248 | return; |
20 | 249 | } | 249 | } |
21 | 250 | |||
22 | 251 | // now filter the threads according to the search term | ||
23 | 252 | History::Threads filtered = filterThreads(groupedThread.groupedThreads()); | ||
24 | 253 | if (filtered.isEmpty()) { | ||
25 | 254 | return; | ||
26 | 255 | } | ||
27 | 256 | |||
28 | 257 | bool needsUpdating = false; | ||
29 | 258 | if (!filtered.contains(groupedThread)) { | ||
30 | 259 | groupedThread = filtered.first(); | ||
31 | 260 | needsUpdating = true; | ||
32 | 261 | } else { | ||
33 | 262 | // call matchThread just to get the event updated | ||
34 | 263 | matchThread(groupedThread); | ||
35 | 264 | } | ||
36 | 265 | |||
37 | 250 | int pos = existingPositionForEntry(groupedThread); | 266 | int pos = existingPositionForEntry(groupedThread); |
38 | 251 | 267 | ||
39 | 252 | // if the group is empty, we need to insert it into the map | 268 | // if the group is empty, we need to insert it into the map |
40 | 253 | if (pos < 0) { | 269 | if (pos < 0) { |
41 | 254 | HistoryThreadGroup group; | 270 | HistoryThreadGroup group; |
42 | 255 | int newPos = positionForItem(groupedThread.properties()); | 271 | int newPos = positionForItem(groupedThread.properties()); |
44 | 256 | group.threads = groupedThread.groupedThreads(); | 272 | group.threads = filtered; |
45 | 257 | group.displayedThread = groupedThread; | 273 | group.displayedThread = groupedThread; |
46 | 258 | beginInsertRows(QModelIndex(), newPos, newPos); | 274 | beginInsertRows(QModelIndex(), newPos, newPos); |
47 | 259 | mGroups.insert(newPos, group); | 275 | mGroups.insert(newPos, group); |
48 | 260 | endInsertRows(); | 276 | endInsertRows(); |
50 | 261 | return; | 277 | if (needsUpdating) { |
51 | 278 | updateDisplayedThread(mGroups[newPos]); | ||
52 | 279 | } | ||
53 | 280 | } else { | ||
54 | 281 | HistoryThreadGroup &group = mGroups[pos]; | ||
55 | 282 | group.threads = filtered; | ||
56 | 283 | updateDisplayedThread(group); | ||
57 | 284 | markGroupAsChanged(group); | ||
58 | 262 | } | 285 | } |
59 | 263 | |||
60 | 264 | HistoryThreadGroup &group = mGroups[pos]; | ||
61 | 265 | group.threads = groupedThread.groupedThreads(); | ||
62 | 266 | |||
63 | 267 | updateDisplayedThread(group); | ||
64 | 268 | markGroupAsChanged(group); | ||
65 | 269 | } | 286 | } |
66 | 270 | 287 | ||
67 | 271 | void HistoryGroupedThreadsModel::removeThreadFromGroup(const History::Thread &thread) | 288 | void HistoryGroupedThreadsModel::removeThreadFromGroup(const History::Thread &thread) |
68 | 272 | 289 | ||
69 | === modified file 'Ubuntu/History/historythreadmodel.cpp' | |||
70 | --- Ubuntu/History/historythreadmodel.cpp 2016-06-17 01:49:46 +0000 | |||
71 | +++ Ubuntu/History/historythreadmodel.cpp 2017-01-26 18:33:44 +0000 | |||
72 | @@ -19,10 +19,13 @@ | |||
73 | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
74 | 20 | */ | 20 | */ |
75 | 21 | 21 | ||
76 | 22 | #include "eventview.h" | ||
77 | 22 | #include "historythreadmodel.h" | 23 | #include "historythreadmodel.h" |
78 | 23 | #include "historyqmltexteventattachment.h" | 24 | #include "historyqmltexteventattachment.h" |
79 | 25 | #include "intersectionfilter.h" | ||
80 | 24 | #include "manager.h" | 26 | #include "manager.h" |
81 | 25 | #include "threadview.h" | 27 | #include "threadview.h" |
82 | 28 | #include "utils_p.h" | ||
83 | 26 | #include "voiceevent.h" | 29 | #include "voiceevent.h" |
84 | 27 | #include <QDBusMetaType> | 30 | #include <QDBusMetaType> |
85 | 28 | 31 | ||
86 | @@ -38,6 +41,7 @@ | |||
87 | 38 | mRoles = HistoryModel::roleNames(); | 41 | mRoles = HistoryModel::roleNames(); |
88 | 39 | mRoles[CountRole] = "count"; | 42 | mRoles[CountRole] = "count"; |
89 | 40 | mRoles[UnreadCountRole] = "unreadCount"; | 43 | mRoles[UnreadCountRole] = "unreadCount"; |
90 | 44 | mRoles[ThreadsRole] = "threads"; | ||
91 | 41 | mRoles[ChatType] = "chatType"; | 45 | mRoles[ChatType] = "chatType"; |
92 | 42 | mRoles[ChatRoomInfo] = "chatRoomInfo"; | 46 | mRoles[ChatRoomInfo] = "chatRoomInfo"; |
93 | 43 | 47 | ||
94 | @@ -100,12 +104,38 @@ | |||
95 | 100 | 104 | ||
96 | 101 | QVariant result; | 105 | QVariant result; |
97 | 102 | switch (role) { | 106 | switch (role) { |
104 | 103 | case CountRole: | 107 | case CountRole: { |
105 | 104 | result = thread.count(); | 108 | if (thread.groupedThreads().isEmpty()) { |
106 | 105 | break; | 109 | result = thread.count(); |
107 | 106 | case UnreadCountRole: | 110 | } else { |
108 | 107 | result = thread.unreadCount(); | 111 | int count = 0; |
109 | 108 | break; | 112 | Q_FOREACH(const History::Thread &groupedThread, thread.groupedThreads()) { |
110 | 113 | count += groupedThread.count(); | ||
111 | 114 | } | ||
112 | 115 | result = count; | ||
113 | 116 | } | ||
114 | 117 | break; | ||
115 | 118 | } | ||
116 | 119 | case UnreadCountRole: { | ||
117 | 120 | if (thread.groupedThreads().isEmpty()) { | ||
118 | 121 | result = thread.unreadCount(); | ||
119 | 122 | } else { | ||
120 | 123 | int count = 0; | ||
121 | 124 | Q_FOREACH(const History::Thread &groupedThread, thread.groupedThreads()) { | ||
122 | 125 | count += groupedThread.unreadCount(); | ||
123 | 126 | } | ||
124 | 127 | result = count; | ||
125 | 128 | } | ||
126 | 129 | break; | ||
127 | 130 | } | ||
128 | 131 | case ThreadsRole: { | ||
129 | 132 | QVariantList threads; | ||
130 | 133 | Q_FOREACH(const History::Thread &groupedThread, thread.groupedThreads()) { | ||
131 | 134 | threads << groupedThread.properties(); | ||
132 | 135 | } | ||
133 | 136 | result = threads; | ||
134 | 137 | break; | ||
135 | 138 | } | ||
136 | 109 | case ChatType: | 139 | case ChatType: |
137 | 110 | result = thread.chatType(); | 140 | result = thread.chatType(); |
138 | 111 | break; | 141 | break; |
139 | @@ -251,6 +281,32 @@ | |||
140 | 251 | return History::Manager::instance()->removeThreads(threads); | 281 | return History::Manager::instance()->removeThreads(threads); |
141 | 252 | } | 282 | } |
142 | 253 | 283 | ||
143 | 284 | QString HistoryThreadModel::searchTerm() const | ||
144 | 285 | { | ||
145 | 286 | return mSearchTerm; | ||
146 | 287 | } | ||
147 | 288 | |||
148 | 289 | void HistoryThreadModel::setSearchTerm(const QString &term) | ||
149 | 290 | { | ||
150 | 291 | mSearchTerm = term.toLower().trimmed(); | ||
151 | 292 | Q_EMIT searchTermChanged(); | ||
152 | 293 | updateQuery(); | ||
153 | 294 | } | ||
154 | 295 | |||
155 | 296 | QString HistoryThreadModel::groupingProperty() const | ||
156 | 297 | { | ||
157 | 298 | return mGroupingProperty; | ||
158 | 299 | } | ||
159 | 300 | |||
160 | 301 | void HistoryThreadModel::setGroupingProperty(const QString &value) | ||
161 | 302 | { | ||
162 | 303 | mGroupingProperty = value; | ||
163 | 304 | mGroupThreads = !mGroupingProperty.isEmpty(); | ||
164 | 305 | Q_EMIT groupingPropertyChanged(); | ||
165 | 306 | |||
166 | 307 | triggerQueryUpdate(); | ||
167 | 308 | } | ||
168 | 309 | |||
169 | 254 | void HistoryThreadModel::updateQuery() | 310 | void HistoryThreadModel::updateQuery() |
170 | 255 | { | 311 | { |
171 | 256 | // remove all events from the model | 312 | // remove all events from the model |
172 | @@ -280,19 +336,25 @@ | |||
173 | 280 | 336 | ||
174 | 281 | QVariantMap properties; | 337 | QVariantMap properties; |
175 | 282 | if (mGroupThreads) { | 338 | if (mGroupThreads) { |
177 | 283 | properties[History::FieldGroupingProperty] = History::FieldParticipants; | 339 | properties[History::FieldGroupingProperty] = mGroupingProperty; |
178 | 284 | } | 340 | } |
179 | 285 | 341 | ||
180 | 286 | mThreadView = History::Manager::instance()->queryThreads((History::EventType)mType, querySort, queryFilter, properties); | 342 | mThreadView = History::Manager::instance()->queryThreads((History::EventType)mType, querySort, queryFilter, properties); |
181 | 287 | connect(mThreadView.data(), | 343 | connect(mThreadView.data(), |
190 | 288 | SIGNAL(threadsAdded(History::Threads)), | 344 | &History::ThreadView::threadsAdded, |
191 | 289 | SLOT(onThreadsAdded(History::Threads))); | 345 | [&](History::Threads threads){ |
192 | 290 | connect(mThreadView.data(), | 346 | onThreadsAdded(filterThreads(threads)); |
193 | 291 | SIGNAL(threadsModified(History::Threads)), | 347 | }); |
194 | 292 | SLOT(onThreadsModified(History::Threads))); | 348 | connect(mThreadView.data(), |
195 | 293 | connect(mThreadView.data(), | 349 | &History::ThreadView::threadsModified, |
196 | 294 | SIGNAL(threadsRemoved(History::Threads)), | 350 | [&](History::Threads threads){ |
197 | 295 | SLOT(onThreadsRemoved(History::Threads))); | 351 | onThreadsModified(filterThreads(threads)); |
198 | 352 | }); | ||
199 | 353 | connect(mThreadView.data(), | ||
200 | 354 | &History::ThreadView::threadsRemoved, | ||
201 | 355 | [&](History::Threads threads){ | ||
202 | 356 | onThreadsRemoved(filterThreads(threads)); | ||
203 | 357 | }); | ||
204 | 296 | connect(mThreadView.data(), | 358 | connect(mThreadView.data(), |
205 | 297 | SIGNAL(invalidated()), | 359 | SIGNAL(invalidated()), |
206 | 298 | SLOT(triggerQueryUpdate())); | 360 | SLOT(triggerQueryUpdate())); |
207 | @@ -369,5 +431,99 @@ | |||
208 | 369 | 431 | ||
209 | 370 | History::Threads HistoryThreadModel::fetchNextPage() | 432 | History::Threads HistoryThreadModel::fetchNextPage() |
210 | 371 | { | 433 | { |
212 | 372 | return mThreadView->nextPage(); | 434 | History::Threads filtered; |
213 | 435 | while (filtered.isEmpty()) { | ||
214 | 436 | History::Threads threads = mThreadView->nextPage(); | ||
215 | 437 | if (threads.isEmpty()) { | ||
216 | 438 | return threads; | ||
217 | 439 | } | ||
218 | 440 | filtered = filterThreads(threads); | ||
219 | 441 | } | ||
220 | 442 | return filtered; | ||
221 | 443 | } | ||
222 | 444 | |||
223 | 445 | bool HistoryThreadModel::matchThread(History::Thread &thread) | ||
224 | 446 | { | ||
225 | 447 | if (mSearchTerm.isEmpty()) { | ||
226 | 448 | return true; | ||
227 | 449 | } | ||
228 | 450 | |||
229 | 451 | // first try to match the contact alias or the identifier | ||
230 | 452 | Q_FOREACH(const History::Participant &participant, thread.participants()) { | ||
231 | 453 | if (participant.alias().toLower().contains(mSearchTerm)) { | ||
232 | 454 | return true; | ||
233 | 455 | } | ||
234 | 456 | |||
235 | 457 | if (History::Utils::compareIds(thread.accountId(), participant.identifier(), mSearchTerm)) { | ||
236 | 458 | return true; | ||
237 | 459 | } else if (participant.identifier().contains(mSearchTerm)) { | ||
238 | 460 | return true; | ||
239 | 461 | } | ||
240 | 462 | } | ||
241 | 463 | |||
242 | 464 | // now the more expensive search: query the events to see if any match | ||
243 | 465 | History::Sort sort; | ||
244 | 466 | sort.setSortField(History::FieldTimestamp); | ||
245 | 467 | sort.setSortOrder(Qt::DescendingOrder); | ||
246 | 468 | |||
247 | 469 | History::IntersectionFilter topLevelFilter; | ||
248 | 470 | |||
249 | 471 | // we need to match accountId, threadId and the text | ||
250 | 472 | History::Filter filter; | ||
251 | 473 | filter.setFilterProperty(History::FieldAccountId); | ||
252 | 474 | filter.setFilterValue(thread.accountId()); | ||
253 | 475 | topLevelFilter.append(filter); | ||
254 | 476 | |||
255 | 477 | filter.setFilterProperty(History::FieldThreadId); | ||
256 | 478 | filter.setFilterValue(thread.threadId()); | ||
257 | 479 | topLevelFilter.append(filter); | ||
258 | 480 | |||
259 | 481 | filter.setFilterProperty(History::FieldMessage); | ||
260 | 482 | filter.setFilterValue(mSearchTerm); | ||
261 | 483 | filter.setMatchFlags(History::MatchContains); | ||
262 | 484 | topLevelFilter.append(filter); | ||
263 | 485 | |||
264 | 486 | History::EventViewPtr eventView = History::Manager::instance()->queryEvents(History::EventTypeText, | ||
265 | 487 | sort, | ||
266 | 488 | topLevelFilter); | ||
267 | 489 | if (eventView.isNull()) { | ||
268 | 490 | return false; | ||
269 | 491 | } | ||
270 | 492 | |||
271 | 493 | if (!eventView->isValid()) { | ||
272 | 494 | eventView->deleteLater(); | ||
273 | 495 | return false; | ||
274 | 496 | } | ||
275 | 497 | |||
276 | 498 | // now check if we have events | ||
277 | 499 | History::Events events = eventView->nextPage(); | ||
278 | 500 | if (events.isEmpty()) { | ||
279 | 501 | eventView->deleteLater(); | ||
280 | 502 | return false; | ||
281 | 503 | } | ||
282 | 504 | |||
283 | 505 | QVariantMap threadProperties = thread.properties(); | ||
284 | 506 | History::TextEvent event = events.first(); | ||
285 | 507 | QVariantMap eventProperties = event.properties(); | ||
286 | 508 | Q_FOREACH(const QString &key, eventProperties.keys()) { | ||
287 | 509 | threadProperties[key] = eventProperties[key]; | ||
288 | 510 | } | ||
289 | 511 | |||
290 | 512 | // overwrite the thread with the one matching the search | ||
291 | 513 | thread = History::Thread::fromProperties(threadProperties); | ||
292 | 514 | eventView->deleteLater(); | ||
293 | 515 | |||
294 | 516 | // if we got here, the thread already contains the matching event and matches the filters | ||
295 | 517 | return true; | ||
296 | 518 | } | ||
297 | 519 | |||
298 | 520 | History::Threads HistoryThreadModel::filterThreads(const History::Threads &threads) | ||
299 | 521 | { | ||
300 | 522 | History::Threads filtered; | ||
301 | 523 | Q_FOREACH(History::Thread thread, threads) { | ||
302 | 524 | if (matchThread(thread)) { | ||
303 | 525 | filtered << thread; | ||
304 | 526 | } | ||
305 | 527 | } | ||
306 | 528 | return filtered; | ||
307 | 373 | } | 529 | } |
308 | 374 | 530 | ||
309 | === modified file 'Ubuntu/History/historythreadmodel.h' | |||
310 | --- Ubuntu/History/historythreadmodel.h 2016-06-17 01:49:46 +0000 | |||
311 | +++ Ubuntu/History/historythreadmodel.h 2017-01-26 18:33:44 +0000 | |||
312 | @@ -34,11 +34,21 @@ | |||
313 | 34 | { | 34 | { |
314 | 35 | Q_OBJECT | 35 | Q_OBJECT |
315 | 36 | Q_ENUMS(ThreadRole) | 36 | Q_ENUMS(ThreadRole) |
316 | 37 | Q_PROPERTY(QString searchTerm | ||
317 | 38 | READ searchTerm | ||
318 | 39 | WRITE setSearchTerm | ||
319 | 40 | NOTIFY searchTermChanged) | ||
320 | 41 | Q_PROPERTY(QString groupingProperty | ||
321 | 42 | READ groupingProperty | ||
322 | 43 | WRITE setGroupingProperty | ||
323 | 44 | NOTIFY groupingPropertyChanged) | ||
324 | 45 | |||
325 | 37 | 46 | ||
326 | 38 | public: | 47 | public: |
327 | 39 | 48 | ||
328 | 40 | enum ThreadRole { | 49 | enum ThreadRole { |
329 | 41 | CountRole = HistoryModel::LastRole, | 50 | CountRole = HistoryModel::LastRole, |
330 | 51 | ThreadsRole, | ||
331 | 42 | UnreadCountRole, | 52 | UnreadCountRole, |
332 | 43 | ChatType, | 53 | ChatType, |
333 | 44 | ChatRoomInfo, | 54 | ChatRoomInfo, |
334 | @@ -71,6 +81,16 @@ | |||
335 | 71 | 81 | ||
336 | 72 | Q_INVOKABLE bool removeThreads(const QVariantList &threadsProperties); | 82 | Q_INVOKABLE bool removeThreads(const QVariantList &threadsProperties); |
337 | 73 | 83 | ||
338 | 84 | QString searchTerm() const; | ||
339 | 85 | void setSearchTerm(const QString &term); | ||
340 | 86 | |||
341 | 87 | QString groupingProperty() const; | ||
342 | 88 | void setGroupingProperty(const QString &value); | ||
343 | 89 | |||
344 | 90 | Q_SIGNALS: | ||
345 | 91 | void searchTermChanged(); | ||
346 | 92 | void groupingPropertyChanged(); | ||
347 | 93 | |||
348 | 74 | protected Q_SLOTS: | 94 | protected Q_SLOTS: |
349 | 75 | virtual void updateQuery(); | 95 | virtual void updateQuery(); |
350 | 76 | virtual void onThreadsAdded(const History::Threads &threads); | 96 | virtual void onThreadsAdded(const History::Threads &threads); |
351 | @@ -79,12 +99,16 @@ | |||
352 | 79 | 99 | ||
353 | 80 | protected: | 100 | protected: |
354 | 81 | History::Threads fetchNextPage(); | 101 | History::Threads fetchNextPage(); |
355 | 102 | virtual bool matchThread(History::Thread &thread); | ||
356 | 103 | virtual History::Threads filterThreads(const History::Threads &threads); | ||
357 | 82 | bool mCanFetchMore; | 104 | bool mCanFetchMore; |
358 | 83 | bool mGroupThreads; | 105 | bool mGroupThreads; |
359 | 106 | QString mSearchTerm; | ||
360 | 84 | 107 | ||
361 | 85 | private: | 108 | private: |
362 | 86 | History::ThreadViewPtr mThreadView; | 109 | History::ThreadViewPtr mThreadView; |
363 | 87 | History::Threads mThreads; | 110 | History::Threads mThreads; |
364 | 111 | QString mGroupingProperty; | ||
365 | 88 | QHash<int, QByteArray> mRoles; | 112 | QHash<int, QByteArray> mRoles; |
366 | 89 | mutable QMap<History::TextEvent, QList<QVariant> > mAttachmentCache; | 113 | mutable QMap<History::TextEvent, QList<QVariant> > mAttachmentCache; |
367 | 90 | }; | 114 | }; |
368 | 91 | 115 | ||
369 | === modified file 'daemon/historydaemon.cpp' | |||
370 | --- daemon/historydaemon.cpp 2016-11-24 02:02:32 +0000 | |||
371 | +++ daemon/historydaemon.cpp 2017-01-26 18:33:44 +0000 | |||
372 | @@ -146,6 +146,20 @@ | |||
373 | 146 | SIGNAL(channelAvailable(Tp::TextChannelPtr)), | 146 | SIGNAL(channelAvailable(Tp::TextChannelPtr)), |
374 | 147 | SLOT(onTextChannelAvailable(Tp::TextChannelPtr))); | 147 | SLOT(onTextChannelAvailable(Tp::TextChannelPtr))); |
375 | 148 | 148 | ||
376 | 149 | // connect the signals that need to be relayed into DBus | ||
377 | 150 | connect(this, SIGNAL(threadsAdded(QList<QVariantMap>)), | ||
378 | 151 | &mDBus, SIGNAL(ThreadsAdded(QList<QVariantMap>))); | ||
379 | 152 | connect(this, SIGNAL(threadsModified(QList<QVariantMap>)), | ||
380 | 153 | &mDBus, SIGNAL(ThreadsModified(QList<QVariantMap>))); | ||
381 | 154 | connect(this, SIGNAL(threadsRemoved(QList<QVariantMap>)), | ||
382 | 155 | &mDBus, SIGNAL(ThreadsRemoved(QList<QVariantMap>))); | ||
383 | 156 | connect(this, SIGNAL(eventsAdded(QList<QVariantMap>)), | ||
384 | 157 | &mDBus, SIGNAL(EventsAdded(QList<QVariantMap>))); | ||
385 | 158 | connect(this, SIGNAL(eventsModified(QList<QVariantMap>)), | ||
386 | 159 | &mDBus, SIGNAL(EventsModified(QList<QVariantMap>))); | ||
387 | 160 | connect(this, SIGNAL(eventsRemoved(QList<QVariantMap>)), | ||
388 | 161 | &mDBus, SIGNAL(EventsRemoved(QList<QVariantMap>))); | ||
389 | 162 | |||
390 | 149 | // FIXME: we need to do this in a better way, but for now this should do | 163 | // FIXME: we need to do this in a better way, but for now this should do |
391 | 150 | mProtocolFlags["ofono"] = History::MatchPhoneNumber; | 164 | mProtocolFlags["ofono"] = History::MatchPhoneNumber; |
392 | 151 | mProtocolFlags["multimedia"] = History::MatchPhoneNumber; | 165 | mProtocolFlags["multimedia"] = History::MatchPhoneNumber; |
393 | @@ -308,7 +322,7 @@ | |||
394 | 308 | map["Requested"] = properties["Requested"]; | 322 | map["Requested"] = properties["Requested"]; |
395 | 309 | thread[History::FieldChatRoomInfo] = map; | 323 | thread[History::FieldChatRoomInfo] = map; |
396 | 310 | } | 324 | } |
398 | 311 | mDBus.notifyThreadsAdded(QList<QVariantMap>() << thread); | 325 | Q_EMIT threadsAdded(QList<QVariantMap>() << thread); |
399 | 312 | } | 326 | } |
400 | 313 | } | 327 | } |
401 | 314 | return thread; | 328 | return thread; |
402 | @@ -328,6 +342,8 @@ | |||
403 | 328 | return QString::null; | 342 | return QString::null; |
404 | 329 | } | 343 | } |
405 | 330 | 344 | ||
406 | 345 | setupThreadView(view); | ||
407 | 346 | |||
408 | 331 | // FIXME: maybe we should keep a list of views to manually remove them at some point? | 347 | // FIXME: maybe we should keep a list of views to manually remove them at some point? |
409 | 332 | view->setParent(this); | 348 | view->setParent(this); |
410 | 333 | return view->objectPath(); | 349 | return view->objectPath(); |
411 | @@ -428,13 +444,13 @@ | |||
412 | 428 | 444 | ||
413 | 429 | // and last but not least, notify the results | 445 | // and last but not least, notify the results |
414 | 430 | if (!newEvents.isEmpty()) { | 446 | if (!newEvents.isEmpty()) { |
416 | 431 | mDBus.notifyEventsAdded(newEvents); | 447 | Q_EMIT eventsAdded(newEvents); |
417 | 432 | } | 448 | } |
418 | 433 | if (!modifiedEvents.isEmpty()) { | 449 | if (!modifiedEvents.isEmpty()) { |
420 | 434 | mDBus.notifyEventsModified(modifiedEvents); | 450 | Q_EMIT eventsModified(modifiedEvents); |
421 | 435 | } | 451 | } |
422 | 436 | if (!threads.isEmpty()) { | 452 | if (!threads.isEmpty()) { |
424 | 437 | mDBus.notifyThreadsModified(threads.values()); | 453 | Q_EMIT threadsModified(threads.values()); |
425 | 438 | } | 454 | } |
426 | 439 | return true; | 455 | return true; |
427 | 440 | } | 456 | } |
428 | @@ -502,12 +518,12 @@ | |||
429 | 502 | 518 | ||
430 | 503 | mBackend->endBatchOperation(); | 519 | mBackend->endBatchOperation(); |
431 | 504 | 520 | ||
433 | 505 | mDBus.notifyEventsRemoved(events); | 521 | Q_EMIT eventsRemoved(events); |
434 | 506 | if (!removedThreads.isEmpty()) { | 522 | if (!removedThreads.isEmpty()) { |
436 | 507 | mDBus.notifyThreadsRemoved(removedThreads.values()); | 523 | Q_EMIT threadsRemoved(removedThreads.values()); |
437 | 508 | } | 524 | } |
438 | 509 | if (!modifiedThreads.isEmpty()) { | 525 | if (!modifiedThreads.isEmpty()) { |
440 | 510 | mDBus.notifyThreadsModified(modifiedThreads.values()); | 526 | Q_EMIT threadsModified(modifiedThreads.values()); |
441 | 511 | } | 527 | } |
442 | 512 | return true; | 528 | return true; |
443 | 513 | } | 529 | } |
444 | @@ -540,7 +556,7 @@ | |||
445 | 540 | } | 556 | } |
446 | 541 | 557 | ||
447 | 542 | if (!removedEmptyThreads.isEmpty()) { | 558 | if (!removedEmptyThreads.isEmpty()) { |
449 | 543 | mDBus.notifyThreadsRemoved(removedEmptyThreads.values()); | 559 | Q_EMIT threadsRemoved(removedEmptyThreads.values()); |
450 | 544 | } | 560 | } |
451 | 545 | 561 | ||
452 | 546 | if (events.size() > 0) { | 562 | if (events.size() > 0) { |
453 | @@ -812,7 +828,7 @@ | |||
454 | 812 | QString threadId = channel->targetId(); | 828 | QString threadId = channel->targetId(); |
455 | 813 | if (mBackend->updateRoomParticipants(accountId, threadId, History::EventTypeText, participants)) { | 829 | if (mBackend->updateRoomParticipants(accountId, threadId, History::EventTypeText, participants)) { |
456 | 814 | QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); | 830 | QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); |
458 | 815 | mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); | 831 | Q_EMIT threadsModified(QList<QVariantMap>() << updatedThread); |
459 | 816 | } | 832 | } |
460 | 817 | } | 833 | } |
461 | 818 | 834 | ||
462 | @@ -842,7 +858,7 @@ | |||
463 | 842 | QString threadId = channel->targetId(); | 858 | QString threadId = channel->targetId(); |
464 | 843 | if (mBackend->updateRoomParticipantsRoles(accountId, threadId, History::EventTypeText, participantsRoles)) { | 859 | if (mBackend->updateRoomParticipantsRoles(accountId, threadId, History::EventTypeText, participantsRoles)) { |
465 | 844 | QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); | 860 | QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); |
467 | 845 | mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); | 861 | Q_EMIT threadsModified(QList<QVariantMap>() << updatedThread); |
468 | 846 | } | 862 | } |
469 | 847 | 863 | ||
470 | 848 | // update self roles in room properties | 864 | // update self roles in room properties |
471 | @@ -877,7 +893,7 @@ | |||
472 | 877 | { | 893 | { |
473 | 878 | if (mBackend->updateRoomInfo(accountId, threadId, type, properties, invalidated)) { | 894 | if (mBackend->updateRoomInfo(accountId, threadId, type, properties, invalidated)) { |
474 | 879 | QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); | 895 | QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); |
476 | 880 | mDBus.notifyThreadsModified(QList<QVariantMap>() << thread); | 896 | Q_EMIT threadsModified(QList<QVariantMap>() << thread); |
477 | 881 | } | 897 | } |
478 | 882 | } | 898 | } |
479 | 883 | 899 | ||
480 | @@ -1181,6 +1197,16 @@ | |||
481 | 1181 | return hash; | 1197 | return hash; |
482 | 1182 | } | 1198 | } |
483 | 1183 | 1199 | ||
484 | 1200 | void HistoryDaemon::setupThreadView(History::PluginThreadView *view) | ||
485 | 1201 | { | ||
486 | 1202 | connect(this, SIGNAL(threadsAdded(QList<QVariantMap>)), | ||
487 | 1203 | view, SLOT(onThreadsAdded(QList<QVariantMap>))); | ||
488 | 1204 | connect(this, SIGNAL(threadsModified(QList<QVariantMap>)), | ||
489 | 1205 | view, SLOT(onThreadsModified(QList<QVariantMap>))); | ||
490 | 1206 | connect(this, SIGNAL(threadsRemoved(QList<QVariantMap>)), | ||
491 | 1207 | view, SLOT(onThreadsRemoved(QList<QVariantMap>))); | ||
492 | 1208 | } | ||
493 | 1209 | |||
494 | 1184 | QVariantMap HistoryDaemon::getInterfaceProperties(const Tp::AbstractInterface *interface) | 1210 | QVariantMap HistoryDaemon::getInterfaceProperties(const Tp::AbstractInterface *interface) |
495 | 1185 | { | 1211 | { |
496 | 1186 | QDBusInterface propsInterface(interface->service(), interface->path(), "org.freedesktop.DBus.Properties"); | 1212 | QDBusInterface propsInterface(interface->service(), interface->path(), "org.freedesktop.DBus.Properties"); |
497 | 1187 | 1213 | ||
498 | === modified file 'daemon/historydaemon.h' | |||
499 | --- daemon/historydaemon.h 2016-10-20 13:56:10 +0000 | |||
500 | +++ daemon/historydaemon.h 2017-01-26 18:33:44 +0000 | |||
501 | @@ -58,6 +58,15 @@ | |||
502 | 58 | bool removeEvents(const QList<QVariantMap> &events); | 58 | bool removeEvents(const QList<QVariantMap> &events); |
503 | 59 | bool removeThreads(const QList<QVariantMap> &threads); | 59 | bool removeThreads(const QList<QVariantMap> &threads); |
504 | 60 | 60 | ||
505 | 61 | Q_SIGNALS: | ||
506 | 62 | void threadsAdded(const QList<QVariantMap> &threads); | ||
507 | 63 | void threadsModified(const QList<QVariantMap> &threads); | ||
508 | 64 | void threadsRemoved(const QList<QVariantMap> &threads); | ||
509 | 65 | |||
510 | 66 | void eventsAdded(const QList<QVariantMap> &events); | ||
511 | 67 | void eventsModified(const QList<QVariantMap> &events); | ||
512 | 68 | void eventsRemoved(const QList<QVariantMap> &events); | ||
513 | 69 | |||
514 | 61 | private Q_SLOTS: | 70 | private Q_SLOTS: |
515 | 62 | void onObserverCreated(); | 71 | void onObserverCreated(); |
516 | 63 | void onCallEnded(const Tp::CallChannelPtr &channel); | 72 | void onCallEnded(const Tp::CallChannelPtr &channel); |
517 | @@ -76,6 +85,8 @@ | |||
518 | 76 | void updateRoomParticipants(const Tp::TextChannelPtr channel); | 85 | void updateRoomParticipants(const Tp::TextChannelPtr channel); |
519 | 77 | void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap); | 86 | void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap); |
520 | 78 | QString hashThread(const QVariantMap &thread); | 87 | QString hashThread(const QVariantMap &thread); |
521 | 88 | void setupThreadView(History::PluginThreadView *view); | ||
522 | 89 | |||
523 | 79 | static QVariantMap getInterfaceProperties(const Tp::AbstractInterface *interface); | 90 | static QVariantMap getInterfaceProperties(const Tp::AbstractInterface *interface); |
524 | 80 | void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties); | 91 | void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties); |
525 | 81 | void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated); | 92 | void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated); |
526 | 82 | 93 | ||
527 | === modified file 'daemon/historyservicedbus.cpp' | |||
528 | --- daemon/historyservicedbus.cpp 2016-11-24 01:56:01 +0000 | |||
529 | +++ daemon/historyservicedbus.cpp 2017-01-26 18:33:44 +0000 | |||
530 | @@ -45,36 +45,6 @@ | |||
531 | 45 | return QDBusConnection::sessionBus().registerService(History::DBusService); | 45 | return QDBusConnection::sessionBus().registerService(History::DBusService); |
532 | 46 | } | 46 | } |
533 | 47 | 47 | ||
534 | 48 | void HistoryServiceDBus::notifyThreadsAdded(const QList<QVariantMap> &threads) | ||
535 | 49 | { | ||
536 | 50 | Q_EMIT ThreadsAdded(threads); | ||
537 | 51 | } | ||
538 | 52 | |||
539 | 53 | void HistoryServiceDBus::notifyThreadsModified(const QList<QVariantMap> &threads) | ||
540 | 54 | { | ||
541 | 55 | Q_EMIT ThreadsModified(threads); | ||
542 | 56 | } | ||
543 | 57 | |||
544 | 58 | void HistoryServiceDBus::notifyThreadsRemoved(const QList<QVariantMap> &threads) | ||
545 | 59 | { | ||
546 | 60 | Q_EMIT ThreadsRemoved(threads); | ||
547 | 61 | } | ||
548 | 62 | |||
549 | 63 | void HistoryServiceDBus::notifyEventsAdded(const QList<QVariantMap> &events) | ||
550 | 64 | { | ||
551 | 65 | Q_EMIT EventsAdded(events); | ||
552 | 66 | } | ||
553 | 67 | |||
554 | 68 | void HistoryServiceDBus::notifyEventsModified(const QList<QVariantMap> &events) | ||
555 | 69 | { | ||
556 | 70 | Q_EMIT EventsModified(events); | ||
557 | 71 | } | ||
558 | 72 | |||
559 | 73 | void HistoryServiceDBus::notifyEventsRemoved(const QList<QVariantMap> &events) | ||
560 | 74 | { | ||
561 | 75 | Q_EMIT EventsRemoved(events); | ||
562 | 76 | } | ||
563 | 77 | |||
564 | 78 | QVariantMap HistoryServiceDBus::ThreadForProperties(const QString &accountId, | 48 | QVariantMap HistoryServiceDBus::ThreadForProperties(const QString &accountId, |
565 | 79 | int type, | 49 | int type, |
566 | 80 | const QVariantMap &properties, | 50 | const QVariantMap &properties, |
567 | 81 | 51 | ||
568 | === modified file 'daemon/historyservicedbus.h' | |||
569 | --- daemon/historyservicedbus.h 2016-06-17 01:49:46 +0000 | |||
570 | +++ daemon/historyservicedbus.h 2017-01-26 18:33:44 +0000 | |||
571 | @@ -36,14 +36,6 @@ | |||
572 | 36 | 36 | ||
573 | 37 | bool connectToBus(); | 37 | bool connectToBus(); |
574 | 38 | 38 | ||
575 | 39 | void notifyThreadsAdded(const QList<QVariantMap> &threads); | ||
576 | 40 | void notifyThreadsModified(const QList<QVariantMap> &threads); | ||
577 | 41 | void notifyThreadsRemoved(const QList<QVariantMap> &threads); | ||
578 | 42 | |||
579 | 43 | void notifyEventsAdded(const QList<QVariantMap> &events); | ||
580 | 44 | void notifyEventsModified(const QList<QVariantMap> &events); | ||
581 | 45 | void notifyEventsRemoved(const QList<QVariantMap> &events); | ||
582 | 46 | |||
583 | 47 | // functions exposed on DBUS | 39 | // functions exposed on DBUS |
584 | 48 | QVariantMap ThreadForParticipants(const QString &accountId, | 40 | QVariantMap ThreadForParticipants(const QString &accountId, |
585 | 49 | int type, | 41 | int type, |
586 | 50 | 42 | ||
587 | === modified file 'plugins/sqlite/sqlitehistoryplugin.cpp' | |||
588 | --- plugins/sqlite/sqlitehistoryplugin.cpp 2016-11-24 01:50:48 +0000 | |||
589 | +++ plugins/sqlite/sqlitehistoryplugin.cpp 2017-01-26 18:33:44 +0000 | |||
590 | @@ -479,10 +479,10 @@ | |||
591 | 479 | return result; | 479 | return result; |
592 | 480 | } | 480 | } |
593 | 481 | 481 | ||
595 | 482 | QList<QVariantMap> results = parseThreadResults(type, query, properties); | 482 | History::Threads results = parseThreadResults(type, query, properties); |
596 | 483 | query.clear(); | 483 | query.clear(); |
597 | 484 | if (!results.isEmpty()) { | 484 | if (!results.isEmpty()) { |
599 | 485 | result = results.first(); | 485 | result = results.first().properties(); |
600 | 486 | } | 486 | } |
601 | 487 | 487 | ||
602 | 488 | return result; | 488 | return result; |
603 | @@ -1133,9 +1133,9 @@ | |||
604 | 1133 | return queryText; | 1133 | return queryText; |
605 | 1134 | } | 1134 | } |
606 | 1135 | 1135 | ||
608 | 1136 | QList<QVariantMap> SQLiteHistoryPlugin::parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties) | 1136 | History::Threads SQLiteHistoryPlugin::parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties) |
609 | 1137 | { | 1137 | { |
611 | 1138 | QList<QVariantMap> threads; | 1138 | History::Threads threads; |
612 | 1139 | QSqlQuery attachmentsQuery(SQLiteDatabase::instance()->database()); | 1139 | QSqlQuery attachmentsQuery(SQLiteDatabase::instance()->database()); |
613 | 1140 | QList<QVariantMap> attachments; | 1140 | QList<QVariantMap> attachments; |
614 | 1141 | bool grouped = false; | 1141 | bool grouped = false; |
615 | @@ -1298,7 +1298,7 @@ | |||
616 | 1298 | thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(13).toString(), true); | 1298 | thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(13).toString(), true); |
617 | 1299 | break; | 1299 | break; |
618 | 1300 | } | 1300 | } |
620 | 1301 | threads << thread; | 1301 | threads << History::Thread::fromProperties(thread); |
621 | 1302 | } | 1302 | } |
622 | 1303 | return threads; | 1303 | return threads; |
623 | 1304 | } | 1304 | } |
624 | 1305 | 1305 | ||
625 | === modified file 'plugins/sqlite/sqlitehistoryplugin.h' | |||
626 | --- plugins/sqlite/sqlitehistoryplugin.h 2016-09-21 17:44:39 +0000 | |||
627 | +++ plugins/sqlite/sqlitehistoryplugin.h 2017-01-26 18:33:44 +0000 | |||
628 | @@ -86,7 +86,7 @@ | |||
629 | 86 | 86 | ||
630 | 87 | // functions to be used internally | 87 | // functions to be used internally |
631 | 88 | QString sqlQueryForThreads(History::EventType type, const QString &condition, const QString &order); | 88 | QString sqlQueryForThreads(History::EventType type, const QString &condition, const QString &order); |
633 | 89 | QList<QVariantMap> parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties = QVariantMap()); | 89 | History::Threads parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties = QVariantMap()); |
634 | 90 | 90 | ||
635 | 91 | QString sqlQueryForEvents(History::EventType type, const QString &condition, const QString &order); | 91 | QString sqlQueryForEvents(History::EventType type, const QString &condition, const QString &order); |
636 | 92 | QList<QVariantMap> parseEventResults(History::EventType type, QSqlQuery &query); | 92 | QList<QVariantMap> parseEventResults(History::EventType type, QSqlQuery &query); |
637 | 93 | 93 | ||
638 | === modified file 'plugins/sqlite/sqlitehistorythreadview.cpp' | |||
639 | --- plugins/sqlite/sqlitehistorythreadview.cpp 2016-11-24 01:56:01 +0000 | |||
640 | +++ plugins/sqlite/sqlitehistorythreadview.cpp 2017-01-26 18:33:44 +0000 | |||
641 | @@ -1,5 +1,5 @@ | |||
642 | 1 | /* | 1 | /* |
644 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
645 | 3 | * | 3 | * |
646 | 4 | * Authors: | 4 | * Authors: |
647 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
648 | @@ -35,6 +35,10 @@ | |||
649 | 35 | : History::PluginThreadView(), mPlugin(plugin), mType(type), mSort(sort), | 35 | : History::PluginThreadView(), mPlugin(plugin), mType(type), mSort(sort), |
650 | 36 | mFilter(filter), mPageSize(15), mQuery(SQLiteDatabase::instance()->database()), mOffset(0), mValid(true), mQueryProperties(properties) | 36 | mFilter(filter), mPageSize(15), mQuery(SQLiteDatabase::instance()->database()), mOffset(0), mValid(true), mQueryProperties(properties) |
651 | 37 | { | 37 | { |
652 | 38 | qDebug() << __PRETTY_FUNCTION__; | ||
653 | 39 | |||
654 | 40 | // connect to the thread signals in the daemon to filter the threads | ||
655 | 41 | |||
656 | 38 | mTemporaryTable = QString("threadview%1%2").arg(QString::number((qulonglong)this), QDateTime::currentDateTimeUtc().toString("yyyyMMddhhmmsszzz")); | 42 | mTemporaryTable = QString("threadview%1%2").arg(QString::number((qulonglong)this), QDateTime::currentDateTimeUtc().toString("yyyyMMddhhmmsszzz")); |
657 | 39 | mQuery.setForwardOnly(true); | 43 | mQuery.setForwardOnly(true); |
658 | 40 | 44 | ||
659 | @@ -80,7 +84,9 @@ | |||
660 | 80 | 84 | ||
661 | 81 | QList<QVariantMap> SQLiteHistoryThreadView::NextPage() | 85 | QList<QVariantMap> SQLiteHistoryThreadView::NextPage() |
662 | 82 | { | 86 | { |
664 | 83 | QList<QVariantMap> threads; | 87 | qDebug() << __PRETTY_FUNCTION__; |
665 | 88 | History::Threads threads; | ||
666 | 89 | QList<QVariantMap> props; | ||
667 | 84 | 90 | ||
668 | 85 | // now prepare for selecting from it | 91 | // now prepare for selecting from it |
669 | 86 | mQuery.prepare(QString("SELECT * FROM %1 LIMIT %2 OFFSET %3").arg(mTemporaryTable, | 92 | mQuery.prepare(QString("SELECT * FROM %1 LIMIT %2 OFFSET %3").arg(mTemporaryTable, |
670 | @@ -89,17 +95,233 @@ | |||
671 | 89 | qCritical() << "Error:" << mQuery.lastError() << mQuery.lastQuery(); | 95 | qCritical() << "Error:" << mQuery.lastError() << mQuery.lastQuery(); |
672 | 90 | mValid = false; | 96 | mValid = false; |
673 | 91 | Q_EMIT Invalidated(); | 97 | Q_EMIT Invalidated(); |
675 | 92 | return threads; | 98 | return props; |
676 | 93 | } | 99 | } |
677 | 94 | 100 | ||
678 | 95 | threads = mPlugin->parseThreadResults(mType, mQuery, mQueryProperties); | 101 | threads = mPlugin->parseThreadResults(mType, mQuery, mQueryProperties); |
679 | 96 | mOffset += mPageSize; | 102 | mOffset += mPageSize; |
680 | 97 | mQuery.clear(); | 103 | mQuery.clear(); |
681 | 98 | 104 | ||
683 | 99 | return threads; | 105 | Q_FOREACH(const History::Thread &thread, threads) { |
684 | 106 | if (threadIsInGroup(thread)) { | ||
685 | 107 | continue; | ||
686 | 108 | } | ||
687 | 109 | createThreadGroup(thread); | ||
688 | 110 | props << thread.properties(); | ||
689 | 111 | } | ||
690 | 112 | return props; | ||
691 | 100 | } | 113 | } |
692 | 101 | 114 | ||
693 | 102 | bool SQLiteHistoryThreadView::IsValid() const | 115 | bool SQLiteHistoryThreadView::IsValid() const |
694 | 103 | { | 116 | { |
695 | 104 | return mValid; | 117 | return mValid; |
696 | 105 | } | 118 | } |
697 | 119 | |||
698 | 120 | bool SQLiteHistoryThreadView::threadIsInGroup(const History::Thread &thread) | ||
699 | 121 | { | ||
700 | 122 | Q_FOREACH(const HistoryThreadGroup &group, mGroups) { | ||
701 | 123 | if (group.threads.contains(thread)) { | ||
702 | 124 | return true; | ||
703 | 125 | } | ||
704 | 126 | } | ||
705 | 127 | return false; | ||
706 | 128 | } | ||
707 | 129 | |||
708 | 130 | void SQLiteHistoryThreadView::createThreadGroup(const History::Thread &thread) | ||
709 | 131 | { | ||
710 | 132 | HistoryThreadGroup group; | ||
711 | 133 | group.displayedThread = thread; | ||
712 | 134 | group.threads = thread.groupedThreads(); | ||
713 | 135 | mGroups << group; | ||
714 | 136 | } | ||
715 | 137 | |||
716 | 138 | History::Threads SQLiteHistoryThreadView::fromList(const QList<QVariantMap> &threads) | ||
717 | 139 | { | ||
718 | 140 | History::Threads result; | ||
719 | 141 | Q_FOREACH(const QVariantMap &map, threads) { | ||
720 | 142 | result << History::Thread::fromProperties(map); | ||
721 | 143 | } | ||
722 | 144 | return result; | ||
723 | 145 | } | ||
724 | 146 | |||
725 | 147 | QList<QVariantMap> SQLiteHistoryThreadView::getGroupedThreads(const QList<QVariantMap> &originalThreads) | ||
726 | 148 | { | ||
727 | 149 | bool needsGrouping = mQueryProperties.contains(History::FieldGroupingProperty); | ||
728 | 150 | QList<QVariantMap> grouped; | ||
729 | 151 | Q_FOREACH(const QVariantMap &originalThread, originalThreads) { | ||
730 | 152 | if (needsGrouping) { | ||
731 | 153 | QVariantMap groupedThread = mPlugin->getSingleThread((History::EventType)originalThread[History::FieldType].toInt(), | ||
732 | 154 | originalThread[History::FieldAccountId].toString(), | ||
733 | 155 | originalThread[History::FieldThreadId].toString(), | ||
734 | 156 | mQueryProperties); | ||
735 | 157 | grouped << groupedThread; | ||
736 | 158 | } else { | ||
737 | 159 | grouped << originalThread; | ||
738 | 160 | } | ||
739 | 161 | } | ||
740 | 162 | return grouped; | ||
741 | 163 | } | ||
742 | 164 | |||
743 | 165 | HistoryThreadGroup SQLiteHistoryThreadView::updateDisplayedThread(HistoryThreadGroup group) | ||
744 | 166 | { | ||
745 | 167 | if (group.threads.isEmpty()) { | ||
746 | 168 | return group; | ||
747 | 169 | } | ||
748 | 170 | |||
749 | 171 | History::Thread displayedThread = group.threads.first(); | ||
750 | 172 | Q_FOREACH(const History::Thread &thread, group.threads) { | ||
751 | 173 | if (thread.lastEvent().timestamp() > displayedThread.lastEvent().timestamp()) { | ||
752 | 174 | displayedThread = thread; | ||
753 | 175 | } | ||
754 | 176 | } | ||
755 | 177 | group.displayedThread = displayedThread; | ||
756 | 178 | return group; | ||
757 | 179 | } | ||
758 | 180 | |||
759 | 181 | void SQLiteHistoryThreadView::notifyChanges(const QList<QVariantMap> added, const QList<QVariantMap> removed, const QList<QVariantMap> modified) | ||
760 | 182 | { | ||
761 | 183 | qDebug() << "Added:" << added.count() << "Removed:" << removed.count() << "Modified:" << modified.count(); | ||
762 | 184 | |||
763 | 185 | if (!removed.isEmpty()) { | ||
764 | 186 | Q_EMIT ThreadsRemoved(removed); | ||
765 | 187 | } | ||
766 | 188 | |||
767 | 189 | if (!added.isEmpty()) { | ||
768 | 190 | Q_EMIT ThreadsAdded(added); | ||
769 | 191 | } | ||
770 | 192 | |||
771 | 193 | if (!modified.isEmpty()) { | ||
772 | 194 | Q_EMIT ThreadsModified(modified); | ||
773 | 195 | } | ||
774 | 196 | } | ||
775 | 197 | |||
776 | 198 | void SQLiteHistoryThreadView::onThreadsAdded(const QList<QVariantMap> &threads) | ||
777 | 199 | { | ||
778 | 200 | qDebug() << __PRETTY_FUNCTION__; | ||
779 | 201 | |||
780 | 202 | History::Threads groupedThreads = fromList(getGroupedThreads(threads)); | ||
781 | 203 | |||
782 | 204 | QList<QVariantMap> addedThreads; | ||
783 | 205 | QList<QVariantMap> modifiedThreads; | ||
784 | 206 | QList<QVariantMap> removedThreads; | ||
785 | 207 | |||
786 | 208 | // now we need to iterate over the existing groups to see if this new thread belongs to any existing group | ||
787 | 209 | Q_FOREACH(const History::Thread &groupedThread, groupedThreads) { | ||
788 | 210 | bool found = false; | ||
789 | 211 | for (int i = 0; i < mGroups.count(); ++i) { | ||
790 | 212 | HistoryThreadGroup &group = mGroups[i]; | ||
791 | 213 | if (groupedThread.groupedThreads().contains(group.displayedThread)) { | ||
792 | 214 | // append the new thread to the group. | ||
793 | 215 | group.threads.append(groupedThread); | ||
794 | 216 | HistoryThreadGroup updatedGroup = updateDisplayedThread(group); | ||
795 | 217 | if (updatedGroup.displayedThread != group.displayedThread) { | ||
796 | 218 | // as the displayed thread changed, we need to remove the old thread | ||
797 | 219 | // and add the new one | ||
798 | 220 | removedThreads << group.displayedThread.properties(); | ||
799 | 221 | addedThreads << updatedGroup.displayedThread.properties(); | ||
800 | 222 | } else { | ||
801 | 223 | // the thread was just updated, notify as such | ||
802 | 224 | modifiedThreads << updatedGroup.displayedThread.properties(); | ||
803 | 225 | } | ||
804 | 226 | group = updatedGroup; | ||
805 | 227 | found = true; | ||
806 | 228 | break; | ||
807 | 229 | } | ||
808 | 230 | } | ||
809 | 231 | |||
810 | 232 | // in case it is not found, we need to create a group for the thread | ||
811 | 233 | if (!found) { | ||
812 | 234 | HistoryThreadGroup group; | ||
813 | 235 | group.displayedThread = groupedThread; | ||
814 | 236 | group.threads = groupedThread.groupedThreads(); | ||
815 | 237 | mGroups << group; | ||
816 | 238 | addedThreads << groupedThread.properties(); | ||
817 | 239 | } | ||
818 | 240 | } | ||
819 | 241 | |||
820 | 242 | // the modified threads here are threads that are currently displayed but they need updating | ||
821 | 243 | // since the group itself got one extra thread, so get the latest version of them. | ||
822 | 244 | notifyChanges(addedThreads, removedThreads, getGroupedThreads(modifiedThreads)); | ||
823 | 245 | } | ||
824 | 246 | |||
825 | 247 | void SQLiteHistoryThreadView::onThreadsModified(const QList<QVariantMap> &threads) | ||
826 | 248 | { | ||
827 | 249 | qDebug() << __PRETTY_FUNCTION__; | ||
828 | 250 | History::Threads groupedThreads = fromList(getGroupedThreads(threads)); | ||
829 | 251 | |||
830 | 252 | QList<QVariantMap> addedThreads; | ||
831 | 253 | QList<QVariantMap> modifiedThreads; | ||
832 | 254 | QList<QVariantMap> removedThreads; | ||
833 | 255 | |||
834 | 256 | // now we need to check if the thread is already displayed and if so, | ||
835 | 257 | // check if the displayed thread changed. | ||
836 | 258 | Q_FOREACH(const History::Thread &groupedThread, groupedThreads) { | ||
837 | 259 | bool found = false; | ||
838 | 260 | for (int i = 0; i < mGroups.count(); ++i) { | ||
839 | 261 | HistoryThreadGroup &group = mGroups[i]; | ||
840 | 262 | if (group.threads.contains(groupedThread)) { | ||
841 | 263 | // remove the old instance and append the new one | ||
842 | 264 | group.threads.removeOne(groupedThread); | ||
843 | 265 | group.threads.append(groupedThread); | ||
844 | 266 | HistoryThreadGroup updatedGroup = updateDisplayedThread(group); | ||
845 | 267 | if (updatedGroup.displayedThread != group.displayedThread) { | ||
846 | 268 | // as the displayed thread changed, we need to remove the old thread | ||
847 | 269 | // and add the new one | ||
848 | 270 | removedThreads << group.displayedThread.properties(); | ||
849 | 271 | addedThreads << updatedGroup.displayedThread.properties(); | ||
850 | 272 | } else { | ||
851 | 273 | // the thread was just updated, notify as such | ||
852 | 274 | modifiedThreads << updatedGroup.displayedThread.properties(); | ||
853 | 275 | } | ||
854 | 276 | group = updatedGroup; | ||
855 | 277 | found = true; | ||
856 | 278 | break; | ||
857 | 279 | } | ||
858 | 280 | } | ||
859 | 281 | |||
860 | 282 | // in case it is not found, we need to create a group for the thread | ||
861 | 283 | if (!found) { | ||
862 | 284 | HistoryThreadGroup group; | ||
863 | 285 | group.displayedThread = groupedThread; | ||
864 | 286 | group.threads = groupedThread.groupedThreads(); | ||
865 | 287 | mGroups << group; | ||
866 | 288 | addedThreads << groupedThread.properties(); | ||
867 | 289 | } | ||
868 | 290 | } | ||
869 | 291 | |||
870 | 292 | // the threads marked as "added" are existing threads that were not displayed before | ||
871 | 293 | // and that are displayed now. So in order to make sure they are up-to-date, get the latest | ||
872 | 294 | // version of the grouping for each of them. | ||
873 | 295 | notifyChanges(getGroupedThreads(addedThreads), removedThreads, modifiedThreads); | ||
874 | 296 | } | ||
875 | 297 | |||
876 | 298 | void SQLiteHistoryThreadView::onThreadsRemoved(const QList<QVariantMap> &threads) | ||
877 | 299 | { | ||
878 | 300 | qDebug() << __PRETTY_FUNCTION__; | ||
879 | 301 | QList<QVariantMap> addedThreads; | ||
880 | 302 | QList<QVariantMap> modifiedThreads; | ||
881 | 303 | QList<QVariantMap> removedThreads; | ||
882 | 304 | |||
883 | 305 | // try to find the thread in the groups to notify its removal | ||
884 | 306 | Q_FOREACH(const History::Thread &thread, fromList(threads)) { | ||
885 | 307 | for (int i = 0; i < mGroups.count(); ++i) { | ||
886 | 308 | HistoryThreadGroup &group = mGroups[i]; | ||
887 | 309 | if (group.threads.contains(thread)) { | ||
888 | 310 | group.threads.removeOne(thread); | ||
889 | 311 | if (group.displayedThread == thread) { | ||
890 | 312 | removedThreads << thread.properties(); | ||
891 | 313 | if (!group.threads.isEmpty()) { | ||
892 | 314 | group = updateDisplayedThread(group); | ||
893 | 315 | addedThreads << group.displayedThread.properties(); | ||
894 | 316 | } | ||
895 | 317 | } else { | ||
896 | 318 | modifiedThreads << group.displayedThread.properties(); | ||
897 | 319 | } | ||
898 | 320 | break; | ||
899 | 321 | } | ||
900 | 322 | } | ||
901 | 323 | } | ||
902 | 324 | |||
903 | 325 | // we need to update the added and modified threads to get the correct group buddies | ||
904 | 326 | notifyChanges(getGroupedThreads(addedThreads), removedThreads, getGroupedThreads(modifiedThreads)); | ||
905 | 327 | } | ||
906 | 106 | 328 | ||
907 | === modified file 'plugins/sqlite/sqlitehistorythreadview.h' | |||
908 | --- plugins/sqlite/sqlitehistorythreadview.h 2015-09-21 20:05:06 +0000 | |||
909 | +++ plugins/sqlite/sqlitehistorythreadview.h 2017-01-26 18:33:44 +0000 | |||
910 | @@ -1,5 +1,5 @@ | |||
911 | 1 | /* | 1 | /* |
913 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
914 | 3 | * | 3 | * |
915 | 4 | * Authors: | 4 | * Authors: |
916 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
917 | @@ -30,6 +30,16 @@ | |||
918 | 30 | 30 | ||
919 | 31 | class SQLiteHistoryPlugin; | 31 | class SQLiteHistoryPlugin; |
920 | 32 | 32 | ||
921 | 33 | class HistoryThreadGroup { | ||
922 | 34 | public: | ||
923 | 35 | History::Thread displayedThread; | ||
924 | 36 | History::Threads threads; | ||
925 | 37 | |||
926 | 38 | bool operator==(const HistoryThreadGroup &other) const; | ||
927 | 39 | }; | ||
928 | 40 | |||
929 | 41 | typedef QList<HistoryThreadGroup> HistoryThreadGroupList; | ||
930 | 42 | |||
931 | 33 | class SQLiteHistoryThreadView : public History::PluginThreadView | 43 | class SQLiteHistoryThreadView : public History::PluginThreadView |
932 | 34 | { | 44 | { |
933 | 35 | Q_OBJECT | 45 | Q_OBJECT |
934 | @@ -44,6 +54,22 @@ | |||
935 | 44 | QList<QVariantMap> NextPage(); | 54 | QList<QVariantMap> NextPage(); |
936 | 45 | bool IsValid() const; | 55 | bool IsValid() const; |
937 | 46 | 56 | ||
938 | 57 | public Q_SLOTS: | ||
939 | 58 | virtual void onThreadsAdded(const QList<QVariantMap> &threads); | ||
940 | 59 | virtual void onThreadsModified(const QList<QVariantMap> &threads); | ||
941 | 60 | virtual void onThreadsRemoved(const QList<QVariantMap> &threads); | ||
942 | 61 | |||
943 | 62 | protected: | ||
944 | 63 | bool threadIsInGroup(const History::Thread &thread); | ||
945 | 64 | void createThreadGroup(const History::Thread &thread); | ||
946 | 65 | History::Threads fromList(const QList<QVariantMap> &threads); | ||
947 | 66 | QList<QVariantMap> getGroupedThreads(const QList<QVariantMap> &originalThreads); | ||
948 | 67 | HistoryThreadGroup updateDisplayedThread(HistoryThreadGroup group); | ||
949 | 68 | |||
950 | 69 | void notifyChanges(const QList<QVariantMap> added, | ||
951 | 70 | const QList<QVariantMap> removed, | ||
952 | 71 | const QList<QVariantMap> modified); | ||
953 | 72 | |||
954 | 47 | private: | 73 | private: |
955 | 48 | History::EventType mType; | 74 | History::EventType mType; |
956 | 49 | History::Sort mSort; | 75 | History::Sort mSort; |
957 | @@ -55,6 +81,7 @@ | |||
958 | 55 | int mOffset; | 81 | int mOffset; |
959 | 56 | bool mValid; | 82 | bool mValid; |
960 | 57 | QVariantMap mQueryProperties; | 83 | QVariantMap mQueryProperties; |
961 | 84 | HistoryThreadGroupList mGroups; | ||
962 | 58 | }; | 85 | }; |
963 | 59 | 86 | ||
964 | 60 | #endif // SQLITEHISTORYTHREADVIEW_H | 87 | #endif // SQLITEHISTORYTHREADVIEW_H |
965 | 61 | 88 | ||
966 | === modified file 'src/PluginThreadView.xml' | |||
967 | --- src/PluginThreadView.xml 2013-09-13 19:24:03 +0000 | |||
968 | +++ src/PluginThreadView.xml 2017-01-26 18:33:44 +0000 | |||
969 | @@ -33,5 +33,33 @@ | |||
970 | 33 | Notifies that this view is no longer valid. | 33 | Notifies that this view is no longer valid. |
971 | 34 | ]]></dox:d> | 34 | ]]></dox:d> |
972 | 35 | </signal> | 35 | </signal> |
973 | 36 | <signal name="ThreadsAdded"> | ||
974 | 37 | <dox:d><![CDATA[ | ||
975 | 38 | Notifies that new threads were added. | ||
976 | 39 | ]]></dox:d> | ||
977 | 40 | <arg type="a(a{sv})" direction="in"/> | ||
978 | 41 | <arg type="a(a{sv})" direction="out"/> | ||
979 | 42 | <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList < QVariantMap >"/> | ||
980 | 43 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList < QVariantMap >"/> | ||
981 | 44 | </signal> | ||
982 | 45 | <signal name="ThreadsModified"> | ||
983 | 46 | <dox:d><![CDATA[ | ||
984 | 47 | Notifies that threads were modified. | ||
985 | 48 | ]]></dox:d> | ||
986 | 49 | <arg type="a(a{sv})" direction="in"/> | ||
987 | 50 | <arg type="a(a{sv})" direction="out"/> | ||
988 | 51 | <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList < QVariantMap >"/> | ||
989 | 52 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList < QVariantMap >"/> | ||
990 | 53 | </signal> | ||
991 | 54 | <signal name="ThreadsRemoved"> | ||
992 | 55 | <dox:d><![CDATA[ | ||
993 | 56 | Notifies that threads were removed. | ||
994 | 57 | ]]></dox:d> | ||
995 | 58 | <arg type="a(a{sv})" direction="in"/> | ||
996 | 59 | <arg type="a(a{sv})" direction="out"/> | ||
997 | 60 | <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QList < QVariantMap >"/> | ||
998 | 61 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList < QVariantMap >"/> | ||
999 | 62 | </signal> | ||
1000 | 63 | |||
1001 | 36 | </interface> | 64 | </interface> |
1002 | 37 | </node> | 65 | </node> |
1003 | 38 | 66 | ||
1004 | === modified file 'src/contactmatcher.cpp' | |||
1005 | --- src/contactmatcher.cpp 2016-06-17 01:49:46 +0000 | |||
1006 | +++ src/contactmatcher.cpp 2017-01-26 18:33:44 +0000 | |||
1007 | @@ -112,6 +112,10 @@ | |||
1008 | 112 | } else if (!synchronous) { | 112 | } else if (!synchronous) { |
1009 | 113 | RequestInfo info{accountId, identifier}; | 113 | RequestInfo info{accountId, identifier}; |
1010 | 114 | mPendingRequests.append(info); | 114 | mPendingRequests.append(info); |
1011 | 115 | map[History::FieldAlias] = ""; | ||
1012 | 116 | map[History::FieldAvatar] = ""; | ||
1013 | 117 | map[History::FieldContactId] = ""; | ||
1014 | 118 | map[History::FieldDetailProperties] = QVariantMap(); | ||
1015 | 115 | } | 119 | } |
1016 | 116 | map[History::FieldIdentifier] = identifier; | 120 | map[History::FieldIdentifier] = identifier; |
1017 | 117 | map[History::FieldAccountId] = accountId; | 121 | map[History::FieldAccountId] = accountId; |
1018 | @@ -196,7 +200,7 @@ | |||
1019 | 196 | QString identifier = it2.key(); | 200 | QString identifier = it2.key(); |
1020 | 197 | 201 | ||
1021 | 198 | Q_FOREACH(const QContact &contact, contacts) { | 202 | Q_FOREACH(const QContact &contact, contacts) { |
1023 | 199 | bool previousMatch = (contactInfo.contains(History::FieldContactId) && | 203 | bool previousMatch = (hasMatch(contactInfo) && |
1024 | 200 | contactInfo[History::FieldContactId].toString() == contact.id().toString()); | 204 | contactInfo[History::FieldContactId].toString() == contact.id().toString()); |
1025 | 201 | QVariantMap map = matchAndUpdate(accountId, identifier, contact); | 205 | QVariantMap map = matchAndUpdate(accountId, identifier, contact); |
1026 | 202 | if (hasMatch(map)){ | 206 | if (hasMatch(map)){ |
1027 | @@ -406,6 +410,10 @@ | |||
1028 | 406 | QVariantMap contactInfo; | 410 | QVariantMap contactInfo; |
1029 | 407 | contactInfo[History::FieldIdentifier] = identifier; | 411 | contactInfo[History::FieldIdentifier] = identifier; |
1030 | 408 | contactInfo[History::FieldAccountId] = accountId; | 412 | contactInfo[History::FieldAccountId] = accountId; |
1031 | 413 | contactInfo[History::FieldAlias] = ""; | ||
1032 | 414 | contactInfo[History::FieldAvatar] = ""; | ||
1033 | 415 | contactInfo[History::FieldContactId] = ""; | ||
1034 | 416 | contactInfo[History::FieldDetailProperties] = QVariantMap(); | ||
1035 | 409 | 417 | ||
1036 | 410 | if (contact.isEmpty()) { | 418 | if (contact.isEmpty()) { |
1037 | 411 | return contactInfo; | 419 | return contactInfo; |
1038 | 412 | 420 | ||
1039 | === modified file 'src/pluginthreadview.cpp' | |||
1040 | --- src/pluginthreadview.cpp 2016-11-24 01:56:01 +0000 | |||
1041 | +++ src/pluginthreadview.cpp 2017-01-26 18:33:44 +0000 | |||
1042 | @@ -1,5 +1,5 @@ | |||
1043 | 1 | /* | 1 | /* |
1045 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
1046 | 3 | * | 3 | * |
1047 | 4 | * Authors: | 4 | * Authors: |
1048 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1049 | @@ -71,4 +71,22 @@ | |||
1050 | 71 | return d->objectPath; | 71 | return d->objectPath; |
1051 | 72 | } | 72 | } |
1052 | 73 | 73 | ||
1053 | 74 | void PluginThreadView::onThreadsAdded(const QList<QVariantMap> &threads) | ||
1054 | 75 | { | ||
1055 | 76 | // the default implementation just relay the signal | ||
1056 | 77 | Q_EMIT ThreadsAdded(threads); | ||
1057 | 78 | } | ||
1058 | 79 | |||
1059 | 80 | void PluginThreadView::onThreadsModified(const QList<QVariantMap> &threads) | ||
1060 | 81 | { | ||
1061 | 82 | // the default implementation just relay the signal | ||
1062 | 83 | Q_EMIT ThreadsModified(threads); | ||
1063 | 84 | } | ||
1064 | 85 | |||
1065 | 86 | void PluginThreadView::onThreadsRemoved(const QList<QVariantMap> &threads) | ||
1066 | 87 | { | ||
1067 | 88 | // the default implementation just relay the signal | ||
1068 | 89 | Q_EMIT ThreadsRemoved(threads); | ||
1069 | 90 | } | ||
1070 | 91 | |||
1071 | 74 | } | 92 | } |
1072 | 75 | 93 | ||
1073 | === modified file 'src/pluginthreadview.h' | |||
1074 | --- src/pluginthreadview.h 2013-11-19 17:52:53 +0000 | |||
1075 | +++ src/pluginthreadview.h 2017-01-26 18:33:44 +0000 | |||
1076 | @@ -1,5 +1,5 @@ | |||
1077 | 1 | /* | 1 | /* |
1079 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
1080 | 3 | * | 3 | * |
1081 | 4 | * Authors: | 4 | * Authors: |
1082 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1083 | @@ -26,6 +26,7 @@ | |||
1084 | 26 | #include <QDBusContext> | 26 | #include <QDBusContext> |
1085 | 27 | #include <QScopedPointer> | 27 | #include <QScopedPointer> |
1086 | 28 | #include <QVariantMap> | 28 | #include <QVariantMap> |
1087 | 29 | #include <Thread> | ||
1088 | 29 | 30 | ||
1089 | 30 | namespace History { | 31 | namespace History { |
1090 | 31 | 32 | ||
1091 | @@ -41,14 +42,22 @@ | |||
1092 | 41 | 42 | ||
1093 | 42 | // DBus exposed methods | 43 | // DBus exposed methods |
1094 | 43 | Q_NOREPLY void Destroy(); | 44 | Q_NOREPLY void Destroy(); |
1095 | 45 | virtual bool IsValid() const; | ||
1096 | 44 | virtual QList<QVariantMap> NextPage() = 0; | 46 | virtual QList<QVariantMap> NextPage() = 0; |
1097 | 45 | virtual bool IsValid() const; | ||
1098 | 46 | 47 | ||
1099 | 47 | // other methods | 48 | // other methods |
1100 | 48 | QString objectPath() const; | 49 | QString objectPath() const; |
1101 | 49 | 50 | ||
1102 | 50 | Q_SIGNALS: | 51 | Q_SIGNALS: |
1103 | 51 | void Invalidated(); | 52 | void Invalidated(); |
1104 | 53 | void ThreadsAdded(const QList<QVariantMap> &threads); | ||
1105 | 54 | void ThreadsModified(const QList<QVariantMap> &threads); | ||
1106 | 55 | void ThreadsRemoved(const QList<QVariantMap> &threads); | ||
1107 | 56 | |||
1108 | 57 | public Q_SLOTS: | ||
1109 | 58 | virtual void onThreadsAdded(const QList<QVariantMap> &threads); | ||
1110 | 59 | virtual void onThreadsModified(const QList<QVariantMap> &threads); | ||
1111 | 60 | virtual void onThreadsRemoved(const QList<QVariantMap> &threads); | ||
1112 | 52 | 61 | ||
1113 | 53 | private: | 62 | private: |
1114 | 54 | QScopedPointer<PluginThreadViewPrivate> d_ptr; | 63 | QScopedPointer<PluginThreadViewPrivate> d_ptr; |
1115 | 55 | 64 | ||
1116 | === modified file 'src/thread.cpp' | |||
1117 | --- src/thread.cpp 2016-07-12 02:08:11 +0000 | |||
1118 | +++ src/thread.cpp 2017-01-26 18:33:44 +0000 | |||
1119 | @@ -185,6 +185,11 @@ | |||
1120 | 185 | return true; | 185 | return true; |
1121 | 186 | } | 186 | } |
1122 | 187 | 187 | ||
1123 | 188 | bool Thread::operator!=(const Thread &other) const | ||
1124 | 189 | { | ||
1125 | 190 | return !(*this == other); | ||
1126 | 191 | } | ||
1127 | 192 | |||
1128 | 188 | bool Thread::operator<(const Thread &other) const | 193 | bool Thread::operator<(const Thread &other) const |
1129 | 189 | { | 194 | { |
1130 | 190 | QString selfData = QString::number(type()) + accountId() + threadId(); | 195 | QString selfData = QString::number(type()) + accountId() + threadId(); |
1131 | @@ -280,10 +285,14 @@ | |||
1132 | 280 | while (!argument.atEnd()) { | 285 | while (!argument.atEnd()) { |
1133 | 281 | QVariantMap props; | 286 | QVariantMap props; |
1134 | 282 | QVariant variant; | 287 | QVariant variant; |
1139 | 283 | argument >> variant; | 288 | if (argument.currentType() == QDBusArgument::MapType) { |
1140 | 284 | QDBusArgument innerArgument = variant.value<QDBusArgument>(); | 289 | argument >> props; |
1141 | 285 | if (!innerArgument.atEnd()) { | 290 | } else { |
1142 | 286 | innerArgument >> props; | 291 | argument >> variant; |
1143 | 292 | QDBusArgument innerArgument = variant.value<QDBusArgument>(); | ||
1144 | 293 | if (!innerArgument.atEnd()) { | ||
1145 | 294 | innerArgument >> props; | ||
1146 | 295 | } | ||
1147 | 287 | } | 296 | } |
1148 | 288 | threads << Thread::fromProperties(props); | 297 | threads << Thread::fromProperties(props); |
1149 | 289 | } | 298 | } |
1150 | 290 | 299 | ||
1151 | === modified file 'src/thread.h' | |||
1152 | --- src/thread.h 2016-07-12 01:59:06 +0000 | |||
1153 | +++ src/thread.h 2017-01-26 18:33:44 +0000 | |||
1154 | @@ -76,6 +76,7 @@ | |||
1155 | 76 | 76 | ||
1156 | 77 | bool isNull() const; | 77 | bool isNull() const; |
1157 | 78 | bool operator==(const Thread &other) const; | 78 | bool operator==(const Thread &other) const; |
1158 | 79 | bool operator!=(const Thread &other) const; | ||
1159 | 79 | bool operator<(const Thread &other) const; | 80 | bool operator<(const Thread &other) const; |
1160 | 80 | 81 | ||
1161 | 81 | virtual QVariantMap properties() const; | 82 | virtual QVariantMap properties() const; |
1162 | 82 | 83 | ||
1163 | === modified file 'src/threadview.cpp' | |||
1164 | --- src/threadview.cpp 2015-10-01 19:44:45 +0000 | |||
1165 | +++ src/threadview.cpp 2017-01-26 18:33:44 +0000 | |||
1166 | @@ -59,36 +59,48 @@ | |||
1167 | 59 | return filtered; | 59 | return filtered; |
1168 | 60 | } | 60 | } |
1169 | 61 | 61 | ||
1171 | 62 | void ThreadViewPrivate::_d_threadsAdded(const History::Threads &threads) | 62 | void ThreadViewPrivate::_d_threadsAdded(const QList<QVariantMap> &threads) |
1172 | 63 | { | 63 | { |
1173 | 64 | qDebug() << __PRETTY_FUNCTION__ << threads.count(); | ||
1174 | 64 | Q_Q(ThreadView); | 65 | Q_Q(ThreadView); |
1175 | 65 | 66 | ||
1177 | 66 | Threads filtered = filteredThreads(threads); | 67 | Threads filtered = filteredThreads(parseThreads(threads)); |
1178 | 67 | if (!filtered.isEmpty()) { | 68 | if (!filtered.isEmpty()) { |
1179 | 68 | Q_EMIT q->threadsAdded(filtered); | 69 | Q_EMIT q->threadsAdded(filtered); |
1180 | 69 | } | 70 | } |
1181 | 70 | } | 71 | } |
1182 | 71 | 72 | ||
1184 | 72 | void ThreadViewPrivate::_d_threadsModified(const Threads &threads) | 73 | void ThreadViewPrivate::_d_threadsModified(const QList<QVariantMap> &threads) |
1185 | 73 | { | 74 | { |
1186 | 75 | qDebug() << __PRETTY_FUNCTION__ << threads.count(); | ||
1187 | 74 | Q_Q(ThreadView); | 76 | Q_Q(ThreadView); |
1188 | 75 | 77 | ||
1190 | 76 | Threads filtered = filteredThreads(threads); | 78 | Threads filtered = filteredThreads(parseThreads(threads)); |
1191 | 77 | if (!filtered.isEmpty()) { | 79 | if (!filtered.isEmpty()) { |
1192 | 78 | Q_EMIT q->threadsModified(filtered); | 80 | Q_EMIT q->threadsModified(filtered); |
1193 | 79 | } | 81 | } |
1194 | 80 | } | 82 | } |
1195 | 81 | 83 | ||
1197 | 82 | void ThreadViewPrivate::_d_threadsRemoved(const Threads &threads) | 84 | void ThreadViewPrivate::_d_threadsRemoved(const QList<QVariantMap> &threads) |
1198 | 83 | { | 85 | { |
1199 | 86 | qDebug() << __PRETTY_FUNCTION__ << threads.count(); | ||
1200 | 84 | Q_Q(ThreadView); | 87 | Q_Q(ThreadView); |
1201 | 85 | 88 | ||
1203 | 86 | Threads filtered = filteredThreads(threads); | 89 | Threads filtered = filteredThreads(parseThreads(threads)); |
1204 | 87 | if (!filtered.isEmpty()) { | 90 | if (!filtered.isEmpty()) { |
1205 | 88 | Q_EMIT q->threadsRemoved(filtered); | 91 | Q_EMIT q->threadsRemoved(filtered); |
1206 | 89 | } | 92 | } |
1207 | 90 | } | 93 | } |
1208 | 91 | 94 | ||
1209 | 95 | Threads ThreadViewPrivate::parseThreads(const QList<QVariantMap> &threads) | ||
1210 | 96 | { | ||
1211 | 97 | Threads result; | ||
1212 | 98 | Q_FOREACH(const QVariantMap &thread, threads) { | ||
1213 | 99 | result << Thread::fromProperties(thread); | ||
1214 | 100 | } | ||
1215 | 101 | return result; | ||
1216 | 102 | } | ||
1217 | 103 | |||
1218 | 92 | // ------------- ThreadView ------------------------------------------------------- | 104 | // ------------- ThreadView ------------------------------------------------------- |
1219 | 93 | 105 | ||
1220 | 94 | ThreadView::ThreadView(History::EventType type, | 106 | ThreadView::ThreadView(History::EventType type, |
1221 | @@ -123,15 +135,13 @@ | |||
1222 | 123 | d_ptr->dbus = new QDBusInterface(History::DBusService, d_ptr->objectPath, History::ThreadViewInterface, | 135 | d_ptr->dbus = new QDBusInterface(History::DBusService, d_ptr->objectPath, History::ThreadViewInterface, |
1223 | 124 | QDBusConnection::sessionBus(), this); | 136 | QDBusConnection::sessionBus(), this); |
1224 | 125 | 137 | ||
1234 | 126 | connect(Manager::instance(), | 138 | QDBusConnection connection = QDBusConnection::sessionBus(); |
1235 | 127 | SIGNAL(threadsAdded(History::Threads)), | 139 | connection.connect(d_ptr->dbus->service(), d_ptr->dbus->path(), d_ptr->dbus->interface(), "ThreadsAdded", |
1236 | 128 | SLOT(_d_threadsAdded(History::Threads))); | 140 | this, SLOT(_d_threadsAdded(QList<QVariantMap>))); |
1237 | 129 | connect(Manager::instance(), | 141 | connection.connect(d_ptr->dbus->service(), d_ptr->dbus->path(), d_ptr->dbus->interface(), "ThreadsModified", |
1238 | 130 | SIGNAL(threadsModified(History::Threads)), | 142 | this, SLOT(_d_threadsModified(QList<QVariantMap>))); |
1239 | 131 | SLOT(_d_threadsModified(History::Threads))); | 143 | connection.connect(d_ptr->dbus->service(), d_ptr->dbus->path(), d_ptr->dbus->interface(), "ThreadsRemoved", |
1240 | 132 | connect(Manager::instance(), | 144 | this, SLOT(_d_threadsRemoved(QList<QVariantMap>))); |
1232 | 133 | SIGNAL(threadsRemoved(History::Threads)), | ||
1233 | 134 | SLOT(_d_threadsRemoved(History::Threads))); | ||
1241 | 135 | } | 145 | } |
1242 | 136 | 146 | ||
1243 | 137 | ThreadView::~ThreadView() | 147 | ThreadView::~ThreadView() |
1244 | 138 | 148 | ||
1245 | === modified file 'src/threadview.h' | |||
1246 | --- src/threadview.h 2015-09-21 20:05:06 +0000 | |||
1247 | +++ src/threadview.h 2017-01-26 18:33:44 +0000 | |||
1248 | @@ -55,9 +55,9 @@ | |||
1249 | 55 | void invalidated(); | 55 | void invalidated(); |
1250 | 56 | 56 | ||
1251 | 57 | private: | 57 | private: |
1255 | 58 | Q_PRIVATE_SLOT(d_func(), void _d_threadsAdded(const History::Threads &threads)) | 58 | Q_PRIVATE_SLOT(d_func(), void _d_threadsAdded(const QList<QVariantMap> &threads)) |
1256 | 59 | Q_PRIVATE_SLOT(d_func(), void _d_threadsModified(const History::Threads &threads)) | 59 | Q_PRIVATE_SLOT(d_func(), void _d_threadsModified(const QList<QVariantMap> &threads)) |
1257 | 60 | Q_PRIVATE_SLOT(d_func(), void _d_threadsRemoved(const History::Threads &threads)) | 60 | Q_PRIVATE_SLOT(d_func(), void _d_threadsRemoved(const QList<QVariantMap> &threads)) |
1258 | 61 | QScopedPointer<ThreadViewPrivate> d_ptr; | 61 | QScopedPointer<ThreadViewPrivate> d_ptr; |
1259 | 62 | 62 | ||
1260 | 63 | }; | 63 | }; |
1261 | 64 | 64 | ||
1262 | === modified file 'src/threadview_p.h' | |||
1263 | --- src/threadview_p.h 2013-09-17 21:33:34 +0000 | |||
1264 | +++ src/threadview_p.h 2017-01-26 18:33:44 +0000 | |||
1265 | @@ -47,9 +47,12 @@ | |||
1266 | 47 | Threads filteredThreads(const Threads &threads); | 47 | Threads filteredThreads(const Threads &threads); |
1267 | 48 | 48 | ||
1268 | 49 | // private slots | 49 | // private slots |
1272 | 50 | void _d_threadsAdded(const History::Threads &threads); | 50 | void _d_threadsAdded(const QList<QVariantMap> &threads); |
1273 | 51 | void _d_threadsModified(const History::Threads &threads); | 51 | void _d_threadsModified(const QList<QVariantMap> &threads); |
1274 | 52 | void _d_threadsRemoved(const History::Threads &threads); | 52 | void _d_threadsRemoved(const QList<QVariantMap> &threads); |
1275 | 53 | |||
1276 | 54 | protected: | ||
1277 | 55 | Threads parseThreads(const QList<QVariantMap> &threads); | ||
1278 | 53 | 56 | ||
1279 | 54 | ThreadView *q_ptr; | 57 | ThreadView *q_ptr; |
1280 | 55 | }; | 58 | }; |
PASSED: Continuous integration, rev:230 jenkins. qa.ubuntu. com/job/ history- service- ci/322/ jenkins. qa.ubuntu. com/job/ history- service- vivid-amd64- ci/160 jenkins. qa.ubuntu. com/job/ history- service- vivid-armhf- ci/161 jenkins. qa.ubuntu. com/job/ history- service- vivid-armhf- ci/161/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ history- service- vivid-i386- ci/160
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/history- service- ci/322/ rebuild
http://