Merge lp:~renatofilho/address-book-app/hide-favorite-if-empty into lp:address-book-app
- hide-favorite-if-empty
- Merge into trunk
Status: | Approved |
---|---|
Approved by: | Gustavo Pichorim Boiko |
Approved revision: | 514 |
Proposed branch: | lp:~renatofilho/address-book-app/hide-favorite-if-empty |
Merge into: | lp:address-book-app |
Diff against target: |
989 lines (+678/-78) 13 files modified
src/imports/ABContactEditorPage.qml (+0/-1) src/imports/ABContactListPage.qml (+20/-1) src/imports/Ubuntu/Contacts/CMakeLists.txt (+2/-0) src/imports/Ubuntu/Contacts/ContactListView.qml (+11/-0) src/imports/Ubuntu/Contacts/MostCalledList.qml (+5/-1) src/imports/Ubuntu/Contacts/contactmap.cpp (+293/-0) src/imports/Ubuntu/Contacts/contactmap.h (+96/-0) src/imports/Ubuntu/Contacts/mostcalledproxymodel.cpp (+8/-69) src/imports/Ubuntu/Contacts/mostcalledproxymodel.h (+0/-4) src/imports/Ubuntu/Contacts/plugin.cpp (+2/-0) tests/qml/CMakeLists.txt (+6/-0) tests/qml/ContactUtil.js (+9/-2) tests/qml/tst_ContactMap.qml (+226/-0) |
To merge this branch: | bzr merge lp:~renatofilho/address-book-app/hide-favorite-if-empty |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gustavo Pichorim Boiko (community) | Approve | ||
PS Jenkins bot | continuous-integration | Needs Fixing | |
Review via email: mp+276126@code.launchpad.net |
Commit message
Only show favorite sections if the list contains favorite contacts.
Description of the change
- 494. By Renato Araujo Oliveira Filho
-
Only show header section if there is favorite contacts.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:494
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 495. By Renato Araujo Oliveira Filho
-
Trunk merged.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:495
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 496. By Renato Araujo Oliveira Filho
-
Implemented contacts map.
Used to map contacts in groups, necessary to show groups in the page header.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:496
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 497. By Renato Araujo Oliveira Filho
-
Update unit test to work with the new SDK API.
- 498. By Renato Araujo Oliveira Filho
-
Implemented unit test for ContactMap.
- 499. By Renato Araujo Oliveira Filho
-
Renamed ContactsMap to ContactMap.
[Header.sections] Reset selectedIndex to 0 if model changes, to avoid it to stay on 'Favorite' Section
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:499
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 500. By Renato Araujo Oliveira Filho
-
Notify hasFavorites changed only if it really changed.
- 501. By Renato Araujo Oliveira Filho
-
[ContactMap] Fetch contacts async.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:501
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 502. By Renato Araujo Oliveira Filho
-
[ContactMap] Fixed contact population.
- 503. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 504. By Renato Araujo Oliveira Filho
-
Removed debug messages.
Fixed code style.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:503
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:504
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 505. By Renato Araujo Oliveira Filho
-
Full load contacts before populate contact map.
This is necessary to avoid problems if the contact map changes while it still loading.
- 506. By Renato Araujo Oliveira Filho
-
Does not request contact name on ContactMap.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:506
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 507. By Renato Araujo Oliveira Filho
-
Optimize contact map.
Fetch only favorite contacts on first query, to show the favorite information as soon as possible.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:507
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 508. By Renato Araujo Oliveira Filho
-
Trunk merged.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:508
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 509. By Renato Araujo Oliveira Filho
-
Revert changes on contact map to fetch favorites first.
- 510. By Renato Araujo Oliveira Filho
-
Async load contacts on ContactMap.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:510
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 511. By Renato Araujo Oliveira Filho
-
Updated mostcalledproxy
model to work with the new history API. - 512. By Renato Araujo Oliveira Filho
-
Show favorite section if the most called model is not empty.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:512
http://
Executed test runs:
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 513. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 514. By Renato Araujo Oliveira Filho
-
Trunk merged.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:514
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Gustavo Pichorim Boiko (boiko) wrote : | # |
Looks good!
- 515. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 516. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 517. By Renato Araujo Oliveira Filho
-
Revert wrong change on last commit.
- 518. By Renato Araujo Oliveira Filho
-
Show all contacts if the header model is reseted.
- 519. By Renato Araujo Oliveira Filho
-
Trunk merged.
Unmerged revisions
- 519. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 518. By Renato Araujo Oliveira Filho
-
Show all contacts if the header model is reseted.
- 517. By Renato Araujo Oliveira Filho
-
Revert wrong change on last commit.
- 516. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 515. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 514. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 513. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 512. By Renato Araujo Oliveira Filho
-
Show favorite section if the most called model is not empty.
- 511. By Renato Araujo Oliveira Filho
-
Updated mostcalledproxy
model to work with the new history API. - 510. By Renato Araujo Oliveira Filho
-
Async load contacts on ContactMap.
Preview Diff
1 | === modified file 'src/imports/ABContactEditorPage.qml' |
2 | --- src/imports/ABContactEditorPage.qml 2016-01-04 20:03:58 +0000 |
3 | +++ src/imports/ABContactEditorPage.qml 2016-05-16 15:05:43 +0000 |
4 | @@ -26,7 +26,6 @@ |
5 | objectName: "contactEditorPage" |
6 | |
7 | property alias backIconName: backAction.iconName |
8 | - // Property used on unit tests |
9 | readonly property alias saveActionEnabled: saveAction.enabled |
10 | |
11 | leadingActions: [ |
12 | |
13 | === modified file 'src/imports/ABContactListPage.qml' |
14 | --- src/imports/ABContactListPage.qml 2016-03-21 12:33:51 +0000 |
15 | +++ src/imports/ABContactListPage.qml 2016-05-16 15:05:43 +0000 |
16 | @@ -214,6 +214,19 @@ |
17 | } |
18 | } |
19 | |
20 | + function filterContactsBySection() { |
21 | + switch (mainPage.head.sections.selectedIndex) { |
22 | + case 0: |
23 | + contactList.showAllContacts() |
24 | + break; |
25 | + case 1: |
26 | + contactList.showFavoritesContacts() |
27 | + break; |
28 | + default: |
29 | + break; |
30 | + } |
31 | + } |
32 | + |
33 | // Delay contact fetch for some msecs (check 'fetchNewContactTimer') |
34 | function delayFetchContact() |
35 | { |
36 | @@ -263,6 +276,7 @@ |
37 | } |
38 | onSelectedIndexChanged: { |
39 | switch (selectedIndex) { |
40 | + case -1: |
41 | case 0: |
42 | contactList.showAllContacts() |
43 | break; |
44 | @@ -474,7 +488,8 @@ |
45 | target: pageHeader |
46 | |
47 | // TRANSLATORS: this refers to all contacts |
48 | - sectionsModel: [i18n.tr("All"), i18n.tr("Favorites")] |
49 | + sectionsModel: contactMap.hasFavorites || (contactList.mostCalledCount > 0) ? |
50 | + [ i18n.tr("All"), i18n.tr("Favorites") ] : [] |
51 | leadingActions: defaultState.leadingActions |
52 | trailingActions: defaultState.trailingActions |
53 | } |
54 | @@ -823,6 +838,10 @@ |
55 | when: bottomEdgeLoader.status == Loader.Ready |
56 | } |
57 | |
58 | + ContactsUI.ContactMap { |
59 | + id: contactMap |
60 | + } |
61 | + |
62 | Connections { |
63 | target: mainPage.contactModel |
64 | |
65 | |
66 | === modified file 'src/imports/Ubuntu/Contacts/CMakeLists.txt' |
67 | --- src/imports/Ubuntu/Contacts/CMakeLists.txt 2016-01-22 14:51:39 +0000 |
68 | +++ src/imports/Ubuntu/Contacts/CMakeLists.txt 2016-05-16 15:05:43 +0000 |
69 | @@ -38,6 +38,8 @@ |
70 | set(CONTACT_COMPONENTS_SRC |
71 | contacts.h |
72 | contacts.cpp |
73 | + contactmap.h |
74 | + contactmap.cpp |
75 | imagescalethread.h |
76 | imagescalethread.cpp |
77 | mostcalledproxymodel.h |
78 | |
79 | === modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml' |
80 | --- src/imports/Ubuntu/Contacts/ContactListView.qml 2016-03-21 12:32:15 +0000 |
81 | +++ src/imports/Ubuntu/Contacts/ContactListView.qml 2016-05-16 15:05:43 +0000 |
82 | @@ -247,6 +247,10 @@ |
83 | |
84 | property alias highlightSelected: view.highlightSelected |
85 | |
86 | + property alias mostCalledCount: view.mostCalledCount |
87 | + |
88 | + readonly property bool favouritesIsSelected: view.favouritesIsSelected |
89 | + |
90 | property var _busyDialog: null |
91 | |
92 | //WORKAROUND: SDK does not allow us to disable focus for items due bug: #1514822 |
93 | @@ -380,6 +384,7 @@ |
94 | property bool showFavourites: true |
95 | property alias favouritesIsSelected: contactsModel.onlyFavorites |
96 | property bool contactsLoaded: false |
97 | + property int mostCalledCount: 0 |
98 | |
99 | function getSectionText(index) { |
100 | var tag = listModel.contacts[index].tag.tag |
101 | @@ -553,6 +558,12 @@ |
102 | parentView: view |
103 | visible: view.favouritesIsSelected |
104 | height: visible && (count > 0) ? childrenRect.height : 0 |
105 | + |
106 | + Binding { |
107 | + target: view |
108 | + property: "mostCalledCount" |
109 | + value: mostCalledView.count |
110 | + } |
111 | } |
112 | } |
113 | onError: root.error(message) |
114 | |
115 | === modified file 'src/imports/Ubuntu/Contacts/MostCalledList.qml' |
116 | --- src/imports/Ubuntu/Contacts/MostCalledList.qml 2015-10-26 13:18:11 +0000 |
117 | +++ src/imports/Ubuntu/Contacts/MostCalledList.qml 2016-05-16 15:05:43 +0000 |
118 | @@ -25,6 +25,10 @@ |
119 | /* internal */ |
120 | property int _nextCurrentIndex: -1 |
121 | |
122 | + function update() |
123 | + { |
124 | + calledModel.model.update() |
125 | + } |
126 | |
127 | function makeItemVisible(item) |
128 | { |
129 | @@ -113,7 +117,7 @@ |
130 | // update the model every time that it became visible |
131 | // in fact calling update only reloads the model data if it has changed |
132 | if (visible) { |
133 | - calledModel.model.update() |
134 | + root.update() |
135 | } |
136 | } |
137 | } |
138 | |
139 | === added file 'src/imports/Ubuntu/Contacts/contactmap.cpp' |
140 | --- src/imports/Ubuntu/Contacts/contactmap.cpp 1970-01-01 00:00:00 +0000 |
141 | +++ src/imports/Ubuntu/Contacts/contactmap.cpp 2016-05-16 15:05:43 +0000 |
142 | @@ -0,0 +1,293 @@ |
143 | +#include "contactmap.h" |
144 | + |
145 | +#include <QtContacts/QContactName> |
146 | +#include <QtContacts/QContactFavorite> |
147 | +#include <QtContacts/QContactTag> |
148 | +#include <QtContacts/QContactFetchRequest> |
149 | +#include <QtContacts/QContactDetailFilter> |
150 | +#include <QDebug> |
151 | + |
152 | + |
153 | +#define FAVORITE_GROUP_NAME QStringLiteral("favorite") |
154 | + |
155 | +ContactMap::ContactMap(QObject *parent) |
156 | + : QObject(parent), |
157 | + m_loadTags(false), |
158 | + m_currentFetch(0) |
159 | +{ |
160 | +} |
161 | + |
162 | +ContactMap::~ContactMap() |
163 | +{ |
164 | + if (m_currentFetch) { |
165 | + m_currentFetch->disconnect(this); |
166 | + m_currentFetch->cancel(); |
167 | + m_currentFetch->deleteLater(); |
168 | + } |
169 | +} |
170 | + |
171 | +// The manager paramentar can contains a dict that can be passsed to contact managar |
172 | +// supported format is: managername[:<paramenter0-name>=<paramenter0-value>;<paramenter1-name>=<paramenter1-value>;...] |
173 | +void ContactMap::setManager(const QString &manager) |
174 | +{ |
175 | + QStringList paramenters = manager.split(":", QString::SkipEmptyParts); |
176 | + QString managerName = paramenters.takeFirst(); |
177 | + qDebug() << "Loading map from" << managerName; |
178 | + |
179 | + QMap<QString, QString> paramenterMap; |
180 | + while (!paramenters.isEmpty()) { |
181 | + QStringList param = paramenters.takeFirst().split("="); |
182 | + paramenterMap.insert(param.first(), param.last()); |
183 | + } |
184 | + |
185 | + m_contactManager.reset(new QContactManager(managerName, paramenterMap)); |
186 | + m_fetchHint.setDetailTypesHint(QList<QContactDetail::DetailType>() |
187 | + << QContactFavorite::Type); |
188 | + |
189 | + connect(m_contactManager.data(), |
190 | + SIGNAL(contactsAdded(QList<QContactId>)), |
191 | + SLOT(onContactsAdded(QList<QContactId>))); |
192 | + connect(m_contactManager.data(), |
193 | + SIGNAL(contactsRemoved(QList<QContactId>)), |
194 | + SLOT(onContactsRemoved(QList<QContactId>))); |
195 | + connect(m_contactManager.data(), |
196 | + SIGNAL(contactsChanged(QList<QContactId>)), |
197 | + SLOT(onContactsChanged(QList<QContactId>))); |
198 | + connect(m_contactManager.data(), |
199 | + SIGNAL(dataChanged()), |
200 | + SLOT(onDataChanged())); |
201 | + reload(); |
202 | + Q_EMIT managerChanged(); |
203 | +} |
204 | + |
205 | +QString ContactMap::manager() const |
206 | +{ |
207 | + if (m_contactManager) |
208 | + return m_contactManager->managerName(); |
209 | + else |
210 | + return QString(); |
211 | +} |
212 | + |
213 | +QStringList ContactMap::groupNames() const |
214 | +{ |
215 | + return m_groupMap.keys(); |
216 | +} |
217 | + |
218 | +QVariantMap ContactMap::groupsMap() const |
219 | +{ |
220 | + QVariantMap result; |
221 | + Q_FOREACH(const QString &key, m_groupMap.keys()) |
222 | + result.insert(key, m_groupMap[key].size()); |
223 | + |
224 | + return result; |
225 | +} |
226 | + |
227 | +QVariantMap ContactMap::managerParameters() const |
228 | +{ |
229 | + QVariantMap map; |
230 | + |
231 | + if (m_contactManager) { |
232 | + QMap<QString, QString> parameters = m_contactManager->managerParameters(); |
233 | + Q_FOREACH(const QString &key, parameters.keys()) |
234 | + map.insert(key, parameters[key]); |
235 | + } |
236 | + return map; |
237 | +} |
238 | + |
239 | +bool ContactMap::hasFavorites() const |
240 | +{ |
241 | + return (m_groupMap.contains(FAVORITE_GROUP_NAME) && !m_groupMap.value(FAVORITE_GROUP_NAME).isEmpty()); |
242 | +} |
243 | + |
244 | +void ContactMap::setLoadTags(bool flag) |
245 | +{ |
246 | + if (m_loadTags != flag) { |
247 | + m_loadTags = flag; |
248 | + Q_EMIT loadTagsChanged(); |
249 | + } |
250 | +} |
251 | + |
252 | +bool ContactMap::loadTags() const |
253 | +{ |
254 | + return m_loadTags; |
255 | +} |
256 | + |
257 | +void ContactMap::classBegin() |
258 | +{ |
259 | +} |
260 | + |
261 | +void ContactMap::componentComplete() |
262 | +{ |
263 | + if (!m_contactManager) { |
264 | + QByteArray defaultManager("galera"); |
265 | + if (qEnvironmentVariableIsSet("QTCONTACTS_MANAGER_OVERRIDE")) |
266 | + defaultManager = qgetenv("QTCONTACTS_MANAGER_OVERRIDE"); |
267 | + |
268 | + setManager(defaultManager); |
269 | + } |
270 | +} |
271 | + |
272 | +void ContactMap::onContactsAdded(const QList<QContactId> addedContacts) |
273 | +{ |
274 | + if (m_currentFetch) { |
275 | + m_pendingActions.append(qMakePair<>(ContactMap::ActionAdd, addedContacts)); |
276 | + return; |
277 | + } |
278 | + |
279 | + QList<QContact> contacts = m_contactManager->contacts(addedContacts, m_fetchHint); |
280 | + if (insertContacts(contacts)) |
281 | + Q_EMIT groupsMapChanged(); |
282 | +} |
283 | + |
284 | +void ContactMap::onContactsRemoved(const QList<QContactId> removedContacts) |
285 | +{ |
286 | + if (m_currentFetch) { |
287 | + m_pendingActions.append(qMakePair<>(ContactMap::ActionRemoved, removedContacts)); |
288 | + return; |
289 | + } |
290 | + |
291 | + bool changed = false; |
292 | + bool hasFavoritesBefore = hasFavorites(); |
293 | + int groupSize = m_groupMap.size(); |
294 | + |
295 | + QStringList emptyKeys; |
296 | + Q_FOREACH(const QString &key, m_groupMap.keys()) { |
297 | + QList<QContactId> &ids = m_groupMap[key]; |
298 | + Q_FOREACH(const QContactId &id, removedContacts) { |
299 | + if (ids.removeOne(id)) |
300 | + changed = true; |
301 | + } |
302 | + if (ids.isEmpty()) |
303 | + emptyKeys << key; |
304 | + } |
305 | + |
306 | + Q_FOREACH(const QString &key, emptyKeys) |
307 | + m_groupMap.remove(key); |
308 | + |
309 | + if (groupSize != m_groupMap.size()) |
310 | + Q_EMIT groupNamesChanged(); |
311 | + |
312 | + if (hasFavoritesBefore != hasFavorites()) |
313 | + Q_EMIT hasFavoritesChanged(); |
314 | + |
315 | + if (changed) |
316 | + Q_EMIT groupsMapChanged(); |
317 | +} |
318 | + |
319 | +void ContactMap::onContactsChanged(const QList<QContactId> changedContacts) |
320 | +{ |
321 | + if (m_currentFetch) { |
322 | + m_pendingActions.append(qMakePair<>(ContactMap::ActionRemoved, changedContacts)); |
323 | + return; |
324 | + } |
325 | + |
326 | + onContactsRemoved(changedContacts); |
327 | + onContactsAdded(changedContacts); |
328 | +} |
329 | + |
330 | +void ContactMap::onDataChanged() |
331 | +{ |
332 | + reload(); |
333 | +} |
334 | + |
335 | +bool ContactMap::insertContacts(const QList<QContact> &contacts) |
336 | +{ |
337 | + bool changed = false; |
338 | + bool hasFavoritesBefore = hasFavorites(); |
339 | + int groupSize = m_groupMap.size(); |
340 | + |
341 | + Q_FOREACH(const QContact &contact, contacts) { |
342 | + if (m_loadTags) { |
343 | + Q_FOREACH(const QContactTag &tag, contact.details<QContactTag>()) { |
344 | + bool inserted = insertTag(contact.id(), tag.tag()); |
345 | + changed = changed || inserted; |
346 | + } |
347 | + } |
348 | + |
349 | + bool isFavorite = contact.detail<QContactFavorite>().isFavorite(); |
350 | + if (isFavorite) { |
351 | + bool inserted = insertTag(contact.id() , FAVORITE_GROUP_NAME); |
352 | + changed = changed || inserted; |
353 | + } |
354 | + } |
355 | + |
356 | + if (groupSize != m_groupMap.size()) |
357 | + Q_EMIT groupNamesChanged(); |
358 | + |
359 | + if (hasFavoritesBefore != hasFavorites()) |
360 | + Q_EMIT hasFavoritesChanged(); |
361 | + |
362 | + return changed; |
363 | +} |
364 | + |
365 | +bool ContactMap::insertTag(const QContactId &id, const QString &tag) |
366 | +{ |
367 | + QList<QContactId> tags = m_groupMap.value(tag); |
368 | + if (!tags.contains(id)) { |
369 | + tags << id; |
370 | + m_groupMap[tag] = tags; |
371 | + return true; |
372 | + } |
373 | + return false; |
374 | +} |
375 | + |
376 | +void ContactMap::reload() |
377 | +{ |
378 | + if (m_currentFetch) { |
379 | + m_currentFetch->disconnect(this); |
380 | + m_currentFetch->cancel(); |
381 | + m_currentFetch->deleteLater(); |
382 | + } |
383 | + |
384 | + if (!m_groupMap.isEmpty()) { |
385 | + bool hasFavoritesBefore = hasFavorites(); |
386 | + m_groupMap.clear(); |
387 | + |
388 | + Q_EMIT groupNamesChanged(); |
389 | + Q_EMIT groupsMapChanged(); |
390 | + if (hasFavoritesBefore) |
391 | + Q_EMIT hasFavoritesChanged(); |
392 | + } |
393 | + |
394 | + m_currentFetch = new QContactFetchRequest(this); |
395 | + m_currentFetch->setManager(m_contactManager.data()); |
396 | + m_currentFetch->setFetchHint(m_fetchHint); |
397 | + connect(m_currentFetch, |
398 | + SIGNAL(resultsAvailable()), |
399 | + SLOT(onFetchResultsAvailable())); |
400 | + connect(m_currentFetch, |
401 | + SIGNAL(stateChanged(QContactAbstractRequest::State)), |
402 | + SLOT(onFetchStateChanged(QContactAbstractRequest::State))); |
403 | + m_currentFetch->start(); |
404 | +} |
405 | + |
406 | +void ContactMap::onFetchStateChanged(QContactAbstractRequest::State state) |
407 | +{ |
408 | + if (state == QContactAbstractRequest::FinishedState) { |
409 | + m_currentFetch->deleteLater(); |
410 | + m_currentFetch = 0; |
411 | + |
412 | + while(!m_pendingActions.isEmpty()) { |
413 | + PendingAction action = m_pendingActions.dequeue(); |
414 | + |
415 | + switch(action.first) { |
416 | + case ContactMap::ActionAdd: |
417 | + onContactsAdded(action.second); |
418 | + break; |
419 | + case ContactMap::ActionRemoved: |
420 | + onContactsRemoved(action.second); |
421 | + break; |
422 | + case ContactMap::ActionChanged: |
423 | + onContactsChanged(action.second); |
424 | + break; |
425 | + } |
426 | + } |
427 | + } |
428 | +} |
429 | + |
430 | +void ContactMap::onFetchResultsAvailable() |
431 | +{ |
432 | + bool changed = insertContacts(m_currentFetch->contacts()); |
433 | + if (changed) |
434 | + Q_EMIT groupsMapChanged(); |
435 | +} |
436 | |
437 | === added file 'src/imports/Ubuntu/Contacts/contactmap.h' |
438 | --- src/imports/Ubuntu/Contacts/contactmap.h 1970-01-01 00:00:00 +0000 |
439 | +++ src/imports/Ubuntu/Contacts/contactmap.h 2016-05-16 15:05:43 +0000 |
440 | @@ -0,0 +1,96 @@ |
441 | +/* |
442 | + * Copyright (C) 2015 Canonical, Ltd. |
443 | + * |
444 | + * This program is free software; you can redistribute it and/or modify |
445 | + * it under the terms of the GNU General Public License as published by |
446 | + * the Free Software Foundation; version 3. |
447 | + * |
448 | + * This program is distributed in the hope that it will be useful, |
449 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
450 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
451 | + * GNU General Public License for more details. |
452 | + * |
453 | + * You should have received a copy of the GNU General Public License |
454 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
455 | + */ |
456 | + |
457 | +#ifndef _UBUNTU_CONTACT_MAP_ |
458 | +#define _UBUNTU_CONTACT_MAP_ |
459 | + |
460 | +#include <QtCore/QObject> |
461 | +#include <QtCore/QString> |
462 | +#include <QtCore/QMap> |
463 | +#include <QtCore/QScopedPointer> |
464 | +#include <QtCore/QQueue> |
465 | + |
466 | +#include <QtQml/QQmlParserStatus> |
467 | + |
468 | +#include <QtContacts/QContactManager> |
469 | +#include <QtContacts/QContactFetchRequest> |
470 | + |
471 | +using namespace QtContacts; |
472 | + |
473 | +class ContactMap : public QObject, public QQmlParserStatus |
474 | +{ |
475 | + Q_OBJECT |
476 | + Q_INTERFACES(QQmlParserStatus) |
477 | + Q_PROPERTY(QStringList groupNames READ groupNames NOTIFY groupNamesChanged) |
478 | + Q_PROPERTY(QVariantMap groupsMap READ groupsMap NOTIFY groupsMapChanged) |
479 | + Q_PROPERTY(bool hasFavorites READ hasFavorites NOTIFY hasFavoritesChanged) |
480 | + Q_PROPERTY(QString manager READ manager WRITE setManager NOTIFY managerChanged) |
481 | + Q_PROPERTY(QVariantMap managerParameters READ managerParameters) |
482 | + Q_PROPERTY(bool loadTags READ loadTags WRITE setLoadTags NOTIFY loadTagsChanged) |
483 | + |
484 | +public: |
485 | + ContactMap(QObject *parent = 0); |
486 | + ~ContactMap(); |
487 | + |
488 | + void setManager(const QString &manager); |
489 | + QString manager() const; |
490 | + QStringList groupNames() const; |
491 | + QVariantMap groupsMap() const; |
492 | + QVariantMap managerParameters() const; |
493 | + bool hasFavorites() const; |
494 | + void setLoadTags(bool flag); |
495 | + bool loadTags() const; |
496 | + |
497 | + void classBegin(); |
498 | + void componentComplete(); |
499 | + |
500 | +Q_SIGNALS: |
501 | + void groupNamesChanged(); |
502 | + void groupsMapChanged(); |
503 | + void managerChanged(); |
504 | + void loadTagsChanged(); |
505 | + void hasFavoritesChanged(); |
506 | + |
507 | +private Q_SLOTS: |
508 | + void onContactsAdded(const QList<QContactId> addedContacts); |
509 | + void onContactsRemoved(const QList<QContactId> removedContacts); |
510 | + void onContactsChanged(const QList<QContactId> changedContacts); |
511 | + void onDataChanged(); |
512 | + void onFetchResultsAvailable(); |
513 | + void onFetchStateChanged(QContactAbstractRequest::State state); |
514 | + |
515 | +private: |
516 | + enum ContactAction { |
517 | + ActionAdd, |
518 | + ActionRemoved, |
519 | + ActionChanged |
520 | + }; |
521 | + typedef QPair<ContactAction, QList<QtContacts::QContactId> > PendingAction; |
522 | + typedef QQueue<PendingAction> PendingActionQueue; |
523 | + |
524 | + bool m_loadTags; |
525 | + QtContacts::QContactFetchHint m_fetchHint; |
526 | + QMap<QString, QList<QtContacts::QContactId> > m_groupMap; |
527 | + QScopedPointer<QtContacts::QContactManager> m_contactManager; |
528 | + PendingActionQueue m_pendingActions; |
529 | + QtContacts::QContactFetchRequest *m_currentFetch; |
530 | + |
531 | + bool insertContacts(const QList<QtContacts::QContact> &contacts); |
532 | + bool insertTag(const QtContacts::QContactId &id, const QString &tag); |
533 | + void reload(); |
534 | +}; |
535 | + |
536 | +#endif |
537 | |
538 | === modified file 'src/imports/Ubuntu/Contacts/mostcalledproxymodel.cpp' |
539 | --- src/imports/Ubuntu/Contacts/mostcalledproxymodel.cpp 2015-05-07 17:27:16 +0000 |
540 | +++ src/imports/Ubuntu/Contacts/mostcalledproxymodel.cpp 2016-05-16 15:05:43 +0000 |
541 | @@ -49,7 +49,6 @@ |
542 | MostCalledContactsModel::~MostCalledContactsModel() |
543 | { |
544 | m_aboutToQuit = true; |
545 | - m_phones.clear(); |
546 | |
547 | if (m_currentFetch) { |
548 | m_currentFetch->cancel(); |
549 | @@ -195,8 +194,6 @@ |
550 | } |
551 | |
552 | m_totalCalls = 0; |
553 | - m_phones.clear(); |
554 | - m_phoneToContactCache.clear(); |
555 | m_contactsData.clear(); |
556 | queryContacts(); |
557 | } |
558 | @@ -227,8 +224,13 @@ |
559 | |
560 | QVariant participants = getSourceData(row, participantsRole); |
561 | if (participants.isValid()) { |
562 | - Q_FOREACH(const QString phone, participants.toStringList()) { |
563 | - m_phones << phone; |
564 | + Q_FOREACH(const QVariant participantI, participants.toList()) { |
565 | + QVariantMap participant = participantI.toMap(); |
566 | + QString contactId = participant.value("contactId").toString(); |
567 | + if (!contactId.isEmpty()) { |
568 | + QString phone = participant.value("identifier").toString(); |
569 | + registerCall(phone, contactId); |
570 | + } |
571 | } |
572 | } |
573 | |
574 | @@ -236,70 +238,11 @@ |
575 | row++; |
576 | } |
577 | |
578 | - // query for all phones |
579 | - nextContact(); |
580 | -} |
581 | - |
582 | -void MostCalledContactsModel::nextContact() |
583 | -{ |
584 | - if (m_phones.isEmpty()) { |
585 | - parseResult(); |
586 | - return; |
587 | - } |
588 | - |
589 | - QString nextPhone = m_phones.takeFirst(); |
590 | - |
591 | - if (m_phoneToContactCache.contains(nextPhone)) { |
592 | - registerCall(nextPhone, m_phoneToContactCache.value(nextPhone)); |
593 | - nextContact(); |
594 | - return; |
595 | - } else { |
596 | - QContactFilter filter(QContactPhoneNumber::match(nextPhone)); |
597 | - QContactFetchHint hint; |
598 | - hint.setDetailTypesHint(QList<QContactDetail::DetailType>() << QContactDetail::TypeGuid); |
599 | - |
600 | - m_currentFetch = new QContactFetchRequest; |
601 | - m_currentFetch->setProperty("PHONE", nextPhone); |
602 | - m_currentFetch->setFilter(filter); |
603 | - m_currentFetch->setFetchHint(hint); |
604 | - m_currentFetch->setManager(m_manager.data()); |
605 | - |
606 | - connect(m_currentFetch, |
607 | - SIGNAL(stateChanged(QContactAbstractRequest::State)), |
608 | - SLOT(fetchContactIdDone())); |
609 | - |
610 | - m_currentFetch->start(); |
611 | - } |
612 | -} |
613 | - |
614 | -void MostCalledContactsModel::fetchContactIdDone() |
615 | -{ |
616 | - Q_ASSERT(m_currentFetch); |
617 | - |
618 | - if (m_aboutToQuit) { |
619 | - m_currentFetch->deleteLater(); |
620 | - m_currentFetch = 0; |
621 | - return; |
622 | - } |
623 | - |
624 | - if (m_currentFetch->state() == QContactAbstractRequest::ActiveState) { |
625 | - return; |
626 | - } |
627 | - |
628 | - if (!m_currentFetch->contacts().isEmpty()) { |
629 | - QString id = m_currentFetch->contacts().at(0).id().toString(); |
630 | - registerCall(m_currentFetch->property("PHONE").toString(), id); |
631 | - } |
632 | - m_currentFetch->deleteLater(); |
633 | - m_currentFetch = 0; |
634 | - nextContact(); |
635 | + parseResult(); |
636 | } |
637 | |
638 | void MostCalledContactsModel::registerCall(const QString &phone, const QString &contactId) |
639 | { |
640 | - // update cache |
641 | - m_phoneToContactCache.insert(phone, contactId); |
642 | - |
643 | if (m_contactsData.contains(contactId)) { |
644 | MostCalledContactsModelData &data = m_contactsData[contactId]; |
645 | data.callCount++; |
646 | @@ -344,8 +287,6 @@ |
647 | } |
648 | |
649 | m_totalCalls = 0; |
650 | - m_phones.clear(); |
651 | - m_phoneToContactCache.clear(); |
652 | m_contactsData.clear(); |
653 | |
654 | Q_EMIT endResetModel(); |
655 | @@ -367,5 +308,3 @@ |
656 | Q_EMIT outdatedChange(m_outdated); |
657 | } |
658 | } |
659 | - |
660 | - |
661 | |
662 | === modified file 'src/imports/Ubuntu/Contacts/mostcalledproxymodel.h' |
663 | --- src/imports/Ubuntu/Contacts/mostcalledproxymodel.h 2015-05-07 17:27:16 +0000 |
664 | +++ src/imports/Ubuntu/Contacts/mostcalledproxymodel.h 2016-05-16 15:05:43 +0000 |
665 | @@ -80,7 +80,6 @@ |
666 | |
667 | private Q_SLOTS: |
668 | void markAsOutdated(); |
669 | - void fetchContactIdDone(); |
670 | |
671 | private: |
672 | QAbstractItemModel *m_sourceModel; |
673 | @@ -95,12 +94,9 @@ |
674 | bool m_reloadingModel; |
675 | bool m_aboutToQuit; |
676 | |
677 | - QStringList m_phones; |
678 | - QMap<QString, QString> m_phoneToContactCache; |
679 | QMap<QString, MostCalledContactsModelData > m_contactsData; |
680 | int m_totalCalls; |
681 | |
682 | - void fetchContactId(const QString &phoneNumber); |
683 | QVariant getSourceData(int row, int role); |
684 | void queryContacts(); |
685 | void nextContact(); |
686 | |
687 | === modified file 'src/imports/Ubuntu/Contacts/plugin.cpp' |
688 | --- src/imports/Ubuntu/Contacts/plugin.cpp 2015-05-07 17:27:16 +0000 |
689 | +++ src/imports/Ubuntu/Contacts/plugin.cpp 2016-05-16 15:05:43 +0000 |
690 | @@ -18,6 +18,7 @@ |
691 | #include "mostcalledproxymodel.h" |
692 | #include "contacts.h" |
693 | #include "simcardcontacts.h" |
694 | +#include "contactmap.h" |
695 | |
696 | #include <QQmlEngine> |
697 | #include <qqml.h> |
698 | @@ -41,4 +42,5 @@ |
699 | qmlRegisterSingletonType<UbuntuContacts>(uri, 0, 1, "Contacts", contactsProvider); |
700 | qmlRegisterType<MostCalledContactsModel>(uri, 0, 1, "MostCalledContactsModel"); |
701 | qmlRegisterType<SimCardContacts>(uri, 0, 1, "SimCardContacts"); |
702 | + qmlRegisterType<ContactMap>(uri, 0, 1, "ContactMap"); |
703 | } |
704 | |
705 | === modified file 'tests/qml/CMakeLists.txt' |
706 | --- tests/qml/CMakeLists.txt 2015-06-29 15:35:07 +0000 |
707 | +++ tests/qml/CMakeLists.txt 2016-05-16 15:05:43 +0000 |
708 | @@ -18,6 +18,10 @@ |
709 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} |
710 | COMMAND ${COMMAND_PREFIX} ${QMLTESTRUNNER_BIN} -import ${imports_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE} |
711 | ) |
712 | + set(TEST_ENVIRONMENT ) |
713 | + set_tests_properties(${TST_NAME} PROPERTIES |
714 | + ENVIRONMENT "QTCONTACTS_MANAGER_OVERRIDE=memory") |
715 | + |
716 | endmacro() |
717 | |
718 | if(QMLTESTRUNNER_BIN AND XVFB_RUN_BIN) |
719 | @@ -30,6 +34,7 @@ |
720 | declare_qml_test("contact_preview_page" tst_ContactPreviewPage.qml) |
721 | declare_qml_test("vcard_parser" tst_VCardParser.qml) |
722 | declare_qml_test("ubuntu_contact" tst_UbuntuContacts.qml) |
723 | + declare_qml_test("contact_map" tst_ContactMap.qml) |
724 | else() |
725 | if (NOT QMLTESTRUNNER_BIN) |
726 | message(WARNING "Qml tests disabled: qmltestrunner not found") |
727 | @@ -45,6 +50,7 @@ |
728 | tst_ContactList.qml |
729 | tst_ContactListModel.qml |
730 | tst_ContactListView.qml |
731 | + tst_ContactMap.qml |
732 | tst_ListWithActions.qml |
733 | tst_ContactPreviewPage.qml |
734 | tst_VCardParser.qml |
735 | |
736 | === modified file 'tests/qml/ContactUtil.js' |
737 | --- tests/qml/ContactUtil.js 2014-07-05 22:00:45 +0000 |
738 | +++ tests/qml/ContactUtil.js 2016-05-16 15:05:43 +0000 |
739 | @@ -18,10 +18,17 @@ |
740 | var newContact = Qt.createQmlObject( |
741 | 'import QtContacts 5.0; Contact{ }', parent); |
742 | var detailSourceTemplate = 'import QtContacts 5.0; %1{ %2: "%3" }'; |
743 | + var detailNonStringSourceTemplate = 'import QtContacts 5.0; %1{ %2: (%3 == 1) }'; |
744 | for (var i=0; i < detailsMap.length; i++) { |
745 | var detailMetaData = detailsMap[i]; |
746 | - var template = detailSourceTemplate.arg(detailMetaData.detail).arg( |
747 | - detailMetaData.field).arg(detailMetaData.value); |
748 | + var template; |
749 | + if (detailMetaData.detail === 'Favorite') { |
750 | + template = detailNonStringSourceTemplate.arg(detailMetaData.detail).arg( |
751 | + detailMetaData.field).arg(detailMetaData.value === 0); |
752 | + } else { |
753 | + template = detailSourceTemplate.arg(detailMetaData.detail).arg( |
754 | + detailMetaData.field).arg(detailMetaData.value); |
755 | + } |
756 | var newDetail = Qt.createQmlObject(template, parent); |
757 | newContact.addDetail(newDetail); |
758 | } |
759 | |
760 | === added file 'tests/qml/tst_ContactMap.qml' |
761 | --- tests/qml/tst_ContactMap.qml 1970-01-01 00:00:00 +0000 |
762 | +++ tests/qml/tst_ContactMap.qml 2016-05-16 15:05:43 +0000 |
763 | @@ -0,0 +1,226 @@ |
764 | +/* |
765 | + * Copyright (C) 2014 Canonical, Ltd. |
766 | + * |
767 | + * This program is free software; you can redistribute it and/or modify |
768 | + * it under the terms of the GNU General Public License as published by |
769 | + * the Free Software Foundation; version 3. |
770 | + * |
771 | + * This program is distributed in the hope that it will be useful, |
772 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
773 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
774 | + * GNU General Public License for more details. |
775 | + * |
776 | + * You should have received a copy of the GNU General Public License |
777 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
778 | + */ |
779 | + |
780 | +import QtQuick 2.4 |
781 | +import QtTest 1.0 |
782 | +import QtContacts 5.0 |
783 | +import Ubuntu.Contacts 0.1 |
784 | + |
785 | +import "ContactUtil.js" as ContactUtilJS |
786 | + |
787 | +Item { |
788 | + id: root |
789 | + |
790 | + function createContact(firstName, phoneNumber, email, favorite) { |
791 | + var details = [ |
792 | + {detail: 'PhoneNumber', field: 'number', value: phoneNumber}, |
793 | + {detail: 'EmailAddress', field: 'emailAddress', value: email}, |
794 | + {detail: 'Name', field: 'firstName', value: firstName}, |
795 | + {detail: 'Favorite', field: 'favorite', value: favorite === 0}, |
796 | + ]; |
797 | + if (favorite) { |
798 | + details.push({detail: 'Tag', field: 'tag', value: 'favorite'}) |
799 | + } |
800 | + |
801 | + return ContactUtilJS.createContact(details, root) |
802 | + } |
803 | + |
804 | + function createSignalSpy(target, signalName) { |
805 | + var spy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', root, "") |
806 | + spy.target = target |
807 | + spy.signalName = signalName |
808 | + return spy |
809 | + } |
810 | + |
811 | + Component { |
812 | + id: contactMapCmp |
813 | + |
814 | + ContactMap { |
815 | + loadTags: true |
816 | + } |
817 | + } |
818 | + |
819 | + Component { |
820 | + id: contactModelCmp |
821 | + |
822 | + ContactModel { |
823 | + readonly property bool ready: memoryId != "" |
824 | + property string memoryId: "" |
825 | + |
826 | + manager: "memory" |
827 | + |
828 | + // we use this to identify the id used by the memory manager created by |
829 | + // ContactModel to use the same in the contactMap component |
830 | + function updateMemoryId() { |
831 | + var newContact = createContact('foo', '123', '', false) |
832 | + saveContact(newContact) |
833 | + var contactIds = newContact.contactId.split(":") |
834 | + var memoryIdValue = contactIds[contactIds.length - 2] |
835 | + memoryIdValue = memoryIdValue.split("=") |
836 | + memoryId = memoryIdValue[memoryIdValue.length - 1] |
837 | + console.debug("Memory Id:" + memoryId) |
838 | + } |
839 | + } |
840 | + } |
841 | + |
842 | + TestCase { |
843 | + id: uContactsTest |
844 | + name: 'ContactMapTestCase' |
845 | + |
846 | + property var contactModel |
847 | + property var contactMap |
848 | + |
849 | + function init() |
850 | + { |
851 | + contactModel = contactModelCmp.createObject(root) |
852 | + contactModel.updateMemoryId() |
853 | + tryCompare(contactModel, 'ready', true) |
854 | + |
855 | + contactMap = contactMapCmp.createObject(root, {"manager": "memory:id=" + contactModel.memoryId}) |
856 | + } |
857 | + |
858 | + function test_map_parameters() |
859 | + { |
860 | + tryCompare(contactMap, 'manager', 'memory') |
861 | + tryCompare(contactMap, 'managerParameters', {'id': contactModel.memoryId } ) |
862 | + } |
863 | + |
864 | + function test_empty_model() |
865 | + { |
866 | + compare(contactMap.groupNames, []) |
867 | + compare(contactMap.groupsMap, {}) |
868 | + compare(contactMap.hasFavorites, false) |
869 | + } |
870 | + |
871 | + function test_add_a_non_favoriteContact() |
872 | + { |
873 | + var spyGroupNamesChanged = createSignalSpy(contactMap, 'groupNamesChanged') |
874 | + var spyGroupMapsChanged = createSignalSpy(contactMap, 'groupsMapChanged') |
875 | + var spyHasFavoritesChanged = createSignalSpy(contactMap, 'hasFavoritesChanged') |
876 | + |
877 | + var newContact = createContact('foo', '12345678', 'foo@bar.com', false) |
878 | + contactModel.saveContact(newContact) |
879 | + |
880 | + // check if singnals was not fired |
881 | + tryCompare(spyGroupNamesChanged, 'count', 0) |
882 | + tryCompare(spyGroupMapsChanged, 'count', 0) |
883 | + tryCompare(spyHasFavoritesChanged, 'count', 0) |
884 | + |
885 | + compare(contactMap.groupNames, []) |
886 | + compare(contactMap.groupsMap, {}) |
887 | + compare(contactMap.hasFavorites, false) |
888 | + } |
889 | + |
890 | + function test_add_a_favoriteContact() |
891 | + { |
892 | + var spyGroupNamesChanged = createSignalSpy(contactMap, 'groupNamesChanged') |
893 | + var spyGroupMapsChanged = createSignalSpy(contactMap, 'groupsMapChanged') |
894 | + var spyHasFavoritesChanged = createSignalSpy(contactMap, 'hasFavoritesChanged') |
895 | + |
896 | + var newContact = createContact('favorite foo', '12345678', 'favorite_foo@bar.com', true) |
897 | + contactModel.saveContact(newContact) |
898 | + |
899 | + // check if singnals was fired once |
900 | + tryCompare(spyGroupNamesChanged, 'count', 1) |
901 | + tryCompare(spyGroupMapsChanged, 'count', 1) |
902 | + tryCompare(spyHasFavoritesChanged, 'count', 1) |
903 | + |
904 | + tryCompare(contactMap, 'groupNames', ['favorite']) |
905 | + tryCompare(contactMap, 'hasFavorites', true) |
906 | + } |
907 | + |
908 | + function test_add_and_remove_a_favorite() |
909 | + { |
910 | + var spyGroupNamesChanged = createSignalSpy(contactMap, 'groupNamesChanged') |
911 | + var spyGroupMapsChanged = createSignalSpy(contactMap, 'groupsMapChanged') |
912 | + var spyHasFavoritesChanged = createSignalSpy(contactMap, 'hasFavoritesChanged') |
913 | + |
914 | + var newContact = createContact('favorite foo', '12345678', 'favorite_foo@bar.com', true) |
915 | + contactModel.saveContact(newContact) |
916 | + |
917 | + // wait contact be added |
918 | + tryCompare(spyHasFavoritesChanged, 'count', 1) |
919 | + tryCompare(contactMap, 'hasFavorites', true) |
920 | + |
921 | + // remove contact |
922 | + contactModel.removeContact(newContact.contactId) |
923 | + |
924 | + // check if singnals was fired twice (when contact added and removed) |
925 | + tryCompare(spyGroupNamesChanged, 'count', 2) |
926 | + tryCompare(spyGroupMapsChanged, 'count', 2) |
927 | + tryCompare(spyHasFavoritesChanged, 'count', 2) |
928 | + |
929 | + tryCompare(contactMap, 'groupNames', []) |
930 | + tryCompare(contactMap, 'groupsMap', {}) |
931 | + tryCompare(contactMap, 'hasFavorites', false) |
932 | + } |
933 | + |
934 | + function test_add_two_favorite_contacts() |
935 | + { |
936 | + var spyGroupNamesChanged = createSignalSpy(contactMap, 'groupNamesChanged') |
937 | + var spyGroupMapsChanged = createSignalSpy(contactMap, 'groupsMapChanged') |
938 | + var spyHasFavoritesChanged = createSignalSpy(contactMap, 'hasFavoritesChanged') |
939 | + |
940 | + var contactFoo = createContact('favorite foo', '12345678', 'favorite_foo@bar.com', true) |
941 | + contactModel.saveContact(contactFoo) |
942 | + tryCompare(spyGroupNamesChanged, 'count', 1) |
943 | + tryCompare(spyGroupMapsChanged, 'count', 1) |
944 | + tryCompare(spyHasFavoritesChanged, 'count', 1) |
945 | + |
946 | + var contactBar = createContact('favorite bar', '87654321', 'favorite_bar@bar.com', true) |
947 | + contactModel.saveContact(contactBar) |
948 | + tryCompare(spyGroupNamesChanged, 'count', 1) |
949 | + tryCompare(spyGroupMapsChanged, 'count', 2) |
950 | + tryCompare(spyHasFavoritesChanged, 'count', 1) |
951 | + } |
952 | + |
953 | + function test_modify_contact() |
954 | + { |
955 | + var spyGroupNamesChanged = createSignalSpy(contactMap, 'groupNamesChanged') |
956 | + var spyGroupMapsChanged = createSignalSpy(contactMap, 'groupsMapChanged') |
957 | + var spyHasFavoritesChanged = createSignalSpy(contactMap, 'hasFavoritesChanged') |
958 | + |
959 | + var contactFoo = createContact('favorite foo', '12345678', 'favorite_foo@bar.com', true) |
960 | + contactModel.saveContact(contactFoo) |
961 | + |
962 | + // wait contact to be saved |
963 | + tryCompare(spyHasFavoritesChanged, 'count', 1) |
964 | + |
965 | + // remove tag 'favorite' |
966 | + var details = contactFoo.contactDetails |
967 | + var found = false |
968 | + for(var i=0; i < details.length; i++) { |
969 | + var det = details[i] |
970 | + if ((det.type === ContactDetail.Tag) && |
971 | + (det.tag === "favorite")) { |
972 | + contactFoo.removeDetail(det) |
973 | + found = true |
974 | + break; |
975 | + } |
976 | + } |
977 | + compare(found, true) |
978 | + contactModel.saveContact(contactFoo) |
979 | + |
980 | + // check signal and hasFavorite |
981 | + tryCompare(spyGroupNamesChanged, 'count', 2) |
982 | + tryCompare(spyGroupMapsChanged, 'count', 2) |
983 | + tryCompare(spyHasFavoritesChanged, 'count', 2) |
984 | + compare(contactMap.groupNames, []) |
985 | + compare(contactMap.groupsMap, {}) |
986 | + compare(contactMap.hasFavorites, false) |
987 | + } |
988 | + } |
989 | +} |
FAILED: Continuous integration, rev:493 jenkins. qa.ubuntu. com/job/ address- book-app- ci/989/ jenkins. qa.ubuntu. com/job/ address- book-app- vivid-i386- ci/292 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 4919/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4916/console
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/address- book-app- ci/989/ rebuild
http://