Merge lp:~renatofilho/address-book-service/fix-1268040_1312263_1235971 into lp:address-book-service
- fix-1268040_1312263_1235971
- Merge into trunk
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Tiago Salem Herrmann | ||||||||||||
Approved revision: | 126 | ||||||||||||
Merged at revision: | 116 | ||||||||||||
Proposed branch: | lp:~renatofilho/address-book-service/fix-1268040_1312263_1235971 | ||||||||||||
Merge into: | lp:address-book-service | ||||||||||||
Prerequisite: | lp:~renatofilho/address-book-service/dummy-mode | ||||||||||||
Diff against target: |
814 lines (+445/-73) 18 files modified
common/fetch-hint.cpp (+1/-0) common/filter.cpp (+2/-1) common/sort-clause.cpp (+10/-0) common/sort-clause.h (+1/-0) common/vcard-parser.cpp (+16/-0) common/vcard-parser.h (+1/-0) contacts/contacts-service.cpp (+0/-10) lib/CMakeLists.txt (+2/-0) lib/addressbook.cpp (+2/-0) lib/contact-less-than.cpp (+47/-0) lib/contact-less-than.h (+46/-0) lib/qindividual.cpp (+40/-0) lib/view.cpp (+20/-24) tests/unittest/CMakeLists.txt (+1/-0) tests/unittest/addressbook-test.cpp (+1/-0) tests/unittest/qcontacts-create-source-test.cpp (+83/-0) tests/unittest/qcontacts-test.cpp (+159/-38) tests/unittest/sort-clause-test.cpp (+13/-0) |
||||||||||||
To merge this branch: | bzr merge lp:~renatofilho/address-book-service/fix-1268040_1312263_1235971 | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tiago Salem Herrmann (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+217301@code.launchpad.net |
This proposal supersedes a proposal from 2014-04-25.
Commit message
Used displayLabel with contact fullname.
Uses company name as fallback for contacts with empty names.
Description of the change
To test this you will need: https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
- 117. By Renato Araujo Oliveira Filho
-
Export tag to be used in alphabetical section.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:117
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 118. By Renato Araujo Oliveira Filho
-
Sort contacts with names starting with symbols/numbers in the end of the list.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:118
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 119. By Renato Araujo Oliveira Filho
-
Added TAG support into hint helper class.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:119
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 120. By Renato Araujo Oliveira Filho
-
Make the contact tag used into the sections caseFolded string.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:120
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 121. By Renato Araujo Oliveira Filho
-
Added unit test for display name.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:121
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 122. By Renato Araujo Oliveira Filho
-
Keep contacts starting with symbols or number in the begginer or the list.
- 123. By Renato Araujo Oliveira Filho
-
Removed unecessary code.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:123
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 124. By Renato Araujo Oliveira Filho
-
Keep empty tags for contact names starting with symbols or numbers.
- 125. By Renato Araujo Oliveira Filho
-
Updated comments about the tag WORKAROUND.
- 126. By Renato Araujo Oliveira Filho
-
Fixed unit test.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:125
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:126
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
* Are there any related MPs required for this MP to build/function as expected? YES
- https:/
* Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes): YES
* Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator? YES
* Did you successfully run all tests found in your component's Test Plan on device or emulator? YES
* If you changed the UI, was the change specified/approved by design? N/A
* If you changed the packaging (debian), did you subscribe a core-dev to this MP? N/A
Tiago Salem Herrmann (tiagosh) wrote : | # |
Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?
Yes
Did CI run pass? If not, please explain why.
Yes
Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
Yes
- 127. By Renato Araujo Oliveira Filho
-
Use phone number as contact display label if the company is empty.
Preview Diff
1 | === modified file 'common/fetch-hint.cpp' |
2 | --- common/fetch-hint.cpp 2014-03-27 16:47:09 +0000 |
3 | +++ common/fetch-hint.cpp 2014-05-05 14:42:08 +0000 |
4 | @@ -103,6 +103,7 @@ |
5 | map.insert("PHOTO", QContactAvatar::Type); |
6 | map.insert("TEL", QContactPhoneNumber::Type); |
7 | map.insert("URL", QContactUrl::Type); |
8 | + map.insert("TAG", QContactTag::Type); |
9 | } |
10 | return map; |
11 | } |
12 | |
13 | === modified file 'common/filter.cpp' |
14 | --- common/filter.cpp 2014-03-05 18:43:32 +0000 |
15 | +++ common/filter.cpp 2014-05-05 14:42:08 +0000 |
16 | @@ -59,7 +59,8 @@ |
17 | |
18 | bool Filter::isValid() const |
19 | { |
20 | - return (m_filter.type() != QContactFilter::InvalidFilter); |
21 | + return ((m_filter.type() != QContactFilter::InvalidFilter) && |
22 | + (m_filter.type() != QContactFilter::DefaultFilter)); |
23 | } |
24 | |
25 | QString Filter::toString(const QtContacts::QContactFilter &filter) |
26 | |
27 | === modified file 'common/sort-clause.cpp' |
28 | --- common/sort-clause.cpp 2014-02-04 19:12:46 +0000 |
29 | +++ common/sort-clause.cpp 2014-05-05 14:42:08 +0000 |
30 | @@ -53,6 +53,11 @@ |
31 | initialize(); |
32 | } |
33 | |
34 | +bool SortClause::isEmpty() const |
35 | +{ |
36 | + return m_sortOrders.isEmpty(); |
37 | +} |
38 | + |
39 | QString SortClause::toString() const |
40 | { |
41 | QString result; |
42 | @@ -128,6 +133,7 @@ |
43 | clauseFieldMap["ADDR_POST_OFFICE_BOX"] = QPair<QContactDetail::DetailType, int>(QContactDetail::TypeAddress, QContactAddress::FieldPostOfficeBox); |
44 | clauseFieldMap["IM_URI"] = QPair<QContactDetail::DetailType, int>(QContactDetail::TypeOnlineAccount, QContactOnlineAccount::FieldAccountUri); |
45 | clauseFieldMap["IM_PROTOCOL"] = QPair<QContactDetail::DetailType, int>(QContactDetail::TypeOnlineAccount, QContactOnlineAccount::FieldProtocol); |
46 | + clauseFieldMap["TAG"] = QPair<QContactDetail::DetailType, int>(QContactDetail::TypeTag, QContactTag::FieldTag); |
47 | clauseFieldMap["URL"] = QPair<QContactDetail::DetailType, int>(QContactDetail::TypeUrl, QContactUrl::FieldUrl); |
48 | } |
49 | } |
50 | @@ -142,6 +148,10 @@ |
51 | } |
52 | } |
53 | |
54 | + if (sort.isValid()) { |
55 | + qWarning() << "No sorting support for" << sort; |
56 | + } |
57 | + |
58 | return ""; |
59 | } |
60 | |
61 | |
62 | === modified file 'common/sort-clause.h' |
63 | --- common/sort-clause.h 2013-06-18 18:40:40 +0000 |
64 | +++ common/sort-clause.h 2014-05-05 14:42:08 +0000 |
65 | @@ -35,6 +35,7 @@ |
66 | SortClause(QList<QtContacts::QContactSortOrder> sort); |
67 | SortClause(const SortClause &other); |
68 | |
69 | + bool isEmpty() const; |
70 | QString toString() const; |
71 | QList<QtContacts::QContactSortOrder> toContactSortOrder() const; |
72 | |
73 | |
74 | === modified file 'common/vcard-parser.cpp' |
75 | --- common/vcard-parser.cpp 2014-03-20 22:06:09 +0000 |
76 | +++ common/vcard-parser.cpp 2014-05-05 14:42:08 +0000 |
77 | @@ -57,6 +57,14 @@ |
78 | *toBeAdded << prop; |
79 | } |
80 | |
81 | + if (detail.type() == QContactDetail::TypeTag) { |
82 | + QContactTag tag = static_cast<QContactTag>(detail); |
83 | + QVersitProperty prop; |
84 | + prop.setName(galera::VCardParser::TagFieldName); |
85 | + prop.setValue(tag.tag()); |
86 | + *toBeAdded << prop; |
87 | + } |
88 | + |
89 | if (toBeAdded->size() == 0) { |
90 | return; |
91 | } |
92 | @@ -138,6 +146,13 @@ |
93 | *alreadyProcessed = true; |
94 | } |
95 | |
96 | + if (!*alreadyProcessed && (property.name() == galera::VCardParser::TagFieldName)) { |
97 | + QContactTag tag; |
98 | + tag.setTag(property.value<QString>()); |
99 | + *updatedDetails << tag; |
100 | + *alreadyProcessed = true; |
101 | + } |
102 | + |
103 | if (!*alreadyProcessed) { |
104 | return; |
105 | } |
106 | @@ -220,6 +235,7 @@ |
107 | const QString VCardParser::PrefParamName = QStringLiteral("PREF"); |
108 | const QString VCardParser::IrremovableFieldName = QStringLiteral("IRREMOVABLE"); |
109 | const QString VCardParser::ReadOnlyFieldName = QStringLiteral("READ-ONLY"); |
110 | +const QString VCardParser::TagFieldName = QStringLiteral("TAG"); |
111 | |
112 | static QMap<QtContacts::QContactDetail::DetailType, QString> prefferedActions() |
113 | { |
114 | |
115 | === modified file 'common/vcard-parser.h' |
116 | --- common/vcard-parser.h 2014-04-09 13:03:21 +0000 |
117 | +++ common/vcard-parser.h 2014-05-05 14:42:08 +0000 |
118 | @@ -46,6 +46,7 @@ |
119 | static const QString PrefParamName; |
120 | static const QString IrremovableFieldName; |
121 | static const QString ReadOnlyFieldName; |
122 | + static const QString TagFieldName; |
123 | static const QMap<QtContacts::QContactDetail::DetailType, QString> PreferredActionNames; |
124 | |
125 | static QtContacts::QContact vcardToContact(const QString &vcard); |
126 | |
127 | === modified file 'contacts/contacts-service.cpp' |
128 | --- contacts/contacts-service.cpp 2014-04-30 16:26:04 +0000 |
129 | +++ contacts/contacts-service.cpp 2014-05-05 14:42:08 +0000 |
130 | @@ -285,7 +285,6 @@ |
131 | QString sortStr = SortClause(request->sorting()).toString(); |
132 | QString filterStr = Filter(request->filter()).toString(); |
133 | FetchHint fetchHint = FetchHint(request->fetchHint()).toString(); |
134 | - |
135 | QDBusPendingCall pcall = m_iface->asyncCall("query", filterStr, sortStr, QStringList()); |
136 | if (pcall.isError()) { |
137 | qWarning() << pcall.error().name() << pcall.error().message(); |
138 | @@ -402,15 +401,6 @@ |
139 | GaleraEngineId *engineId = new GaleraEngineId(detailId.guid(), m_managerUri); |
140 | QContactId newId = QContactId(engineId); |
141 | contact->setId(newId); |
142 | - // set tag to be used when creating sections |
143 | - QContactName detailName = contact->detail<QContactName>(); |
144 | - if (!detailName.firstName().isEmpty() && QString(detailName.firstName().at(0)).contains(QRegExp("([a-z]|[A-Z])"))) { |
145 | - contact->addTag(detailName.firstName().at(0).toUpper()); |
146 | - } else if (!detailName.lastName().isEmpty() && QString(detailName.lastName().at(0)).contains(QRegExp("([a-z]|[A-Z])"))) { |
147 | - contact->addTag(detailName.lastName().at(0).toUpper()); |
148 | - } else { |
149 | - contact->addTag("#"); |
150 | - } |
151 | } |
152 | } |
153 | |
154 | |
155 | === modified file 'lib/CMakeLists.txt' |
156 | --- lib/CMakeLists.txt 2014-03-19 16:44:03 +0000 |
157 | +++ lib/CMakeLists.txt 2014-05-05 14:42:08 +0000 |
158 | @@ -5,6 +5,7 @@ |
159 | set(CONTACTS_SERVICE_LIB_SRC |
160 | addressbook.cpp |
161 | addressbook-adaptor.cpp |
162 | + contact-less-than.cpp |
163 | contacts-map.cpp |
164 | detail-context-parser.cpp |
165 | dirtycontact-notify.cpp |
166 | @@ -18,6 +19,7 @@ |
167 | set(CONTACTS_SERVICE_LIB_HEADERS |
168 | addressbook.h |
169 | addressbook-adaptor.h |
170 | + contact-less-than.h |
171 | contacts-map.h |
172 | detail-context-parser.h |
173 | dirtycontact-notify.h |
174 | |
175 | === modified file 'lib/addressbook.cpp' |
176 | --- lib/addressbook.cpp 2014-04-09 13:03:21 +0000 |
177 | +++ lib/addressbook.cpp 2014-05-05 14:42:08 +0000 |
178 | @@ -405,6 +405,7 @@ |
179 | QContact qcontact = VCardParser::vcardToContact(contact); |
180 | if (!qcontact.isEmpty()) { |
181 | GHashTable *details = QIndividual::parseDetails(qcontact); |
182 | + Q_ASSERT(details); |
183 | CreateContactData *data = new CreateContactData; |
184 | data->m_message = message; |
185 | data->m_addressbook = this; |
186 | @@ -464,6 +465,7 @@ |
187 | |
188 | if (!result) { |
189 | result = folks_individual_aggregator_get_primary_store(m_individualAggregator); |
190 | + Q_ASSERT(result); |
191 | g_object_ref(result); |
192 | } |
193 | return result; |
194 | |
195 | === added file 'lib/contact-less-than.cpp' |
196 | --- lib/contact-less-than.cpp 1970-01-01 00:00:00 +0000 |
197 | +++ lib/contact-less-than.cpp 2014-05-05 14:42:08 +0000 |
198 | @@ -0,0 +1,47 @@ |
199 | +/* |
200 | + * Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). |
201 | + * Copyright (C) 2013 Canonical Ltd. |
202 | + * |
203 | + * This file is part of contact-service-app. |
204 | + * |
205 | + * contact-service-app is free software; you can redistribute it and/or modify |
206 | + * it under the terms of the GNU General Public License as published by |
207 | + * the Free Software Foundation; version 3. |
208 | + * |
209 | + * contact-service-app is distributed in the hope that it will be useful, |
210 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
211 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
212 | + * GNU General Public License for more details. |
213 | + * |
214 | + * You should have received a copy of the GNU General Public License |
215 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
216 | + * |
217 | + * Based on QContactManagerEngine code by Digia |
218 | + */ |
219 | + |
220 | +#include "contact-less-than.h" |
221 | +#include "contacts-map.h" |
222 | +#include "qindividual.h" |
223 | + |
224 | +#include <QtCore/QTime> |
225 | +#include <QtCore/QDebug> |
226 | + |
227 | +#include <QtContacts/QContactManagerEngine> |
228 | + |
229 | +using namespace QtContacts; |
230 | + |
231 | +namespace galera { |
232 | + |
233 | +ContactLessThan::ContactLessThan(const galera::SortClause &sortClause) |
234 | + : m_sortClause(sortClause) |
235 | +{ |
236 | +} |
237 | + |
238 | +bool ContactLessThan::operator()(ContactEntry *entryA, ContactEntry *entryB) |
239 | +{ |
240 | + return QContactManagerEngine::compareContact(entryA->individual()->contact(), |
241 | + entryB->individual()->contact(), |
242 | + m_sortClause.toContactSortOrder()) < 0; |
243 | +} |
244 | + |
245 | +} // namespace |
246 | |
247 | === added file 'lib/contact-less-than.h' |
248 | --- lib/contact-less-than.h 1970-01-01 00:00:00 +0000 |
249 | +++ lib/contact-less-than.h 2014-05-05 14:42:08 +0000 |
250 | @@ -0,0 +1,46 @@ |
251 | +/* |
252 | + * Copyright 2013 Canonical Ltd. |
253 | + * |
254 | + * This file is part of contact-service-app. |
255 | + * |
256 | + * contact-service-app is free software; you can redistribute it and/or modify |
257 | + * it under the terms of the GNU General Public License as published by |
258 | + * the Free Software Foundation; version 3. |
259 | + * |
260 | + * contact-service-app is distributed in the hope that it will be useful, |
261 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
262 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
263 | + * GNU General Public License for more details. |
264 | + * |
265 | + * You should have received a copy of the GNU General Public License |
266 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
267 | + */ |
268 | + |
269 | +#ifndef __GALERA_CONTACT_LESS_THAN_H__ |
270 | +#define __GALERA_CONTACT_LESS_THAN_H__ |
271 | + |
272 | +#include "common/sort-clause.h" |
273 | + |
274 | +#include <QtCore/QString> |
275 | +#include <QtCore/QVariant> |
276 | + |
277 | +#include <QtContacts/QContact> |
278 | + |
279 | +namespace galera { |
280 | + |
281 | +class ContactEntry; |
282 | + |
283 | +class ContactLessThan |
284 | +{ |
285 | +public: |
286 | + ContactLessThan(const SortClause &sortClause); |
287 | + |
288 | + bool operator()(ContactEntry *entryA, ContactEntry *entryB); |
289 | + |
290 | +private: |
291 | + SortClause m_sortClause; |
292 | +}; |
293 | + |
294 | +} // namespace |
295 | + |
296 | +#endif //__GALERA_CONTACT_LESS_THAN_H__ |
297 | |
298 | === modified file 'lib/qindividual.cpp' |
299 | --- lib/qindividual.cpp 2014-04-04 15:48:16 +0000 |
300 | +++ lib/qindividual.cpp 2014-05-05 14:42:08 +0000 |
301 | @@ -275,10 +275,12 @@ |
302 | displayName += QString::fromUtf8(name); |
303 | } |
304 | } |
305 | + |
306 | if (!displayName.isEmpty()) { |
307 | detail.setLabel(displayName); |
308 | detail.setDetailUri(QString("%1.1").arg(index)); |
309 | } |
310 | + |
311 | return detail; |
312 | } |
313 | |
314 | @@ -751,6 +753,12 @@ |
315 | } |
316 | } |
317 | |
318 | + if (fields.contains(QContactDetail::TypeTag)) { |
319 | + Q_FOREACH(QContactDetail det, fullContact.details<QContactTag>()) { |
320 | + details << det; |
321 | + } |
322 | + } |
323 | + |
324 | Q_FOREACH(QContactDetail det, details) { |
325 | result.appendDetail(det); |
326 | } |
327 | @@ -883,8 +891,40 @@ |
328 | VCardParser::PreferredActionNames[QContactUrl::Type], |
329 | prefDetail, |
330 | !wPropList.contains("urls")); |
331 | + |
332 | personaIndex++; |
333 | } |
334 | + |
335 | + // if contact name is empty use org name otherwise try phone number as fallback |
336 | + QContactDisplayLabel displayName = contact->detail<QContactDisplayLabel>(); |
337 | + QString label = displayName.label().trimmed(); |
338 | + |
339 | + if (label.isEmpty()) { |
340 | + QContactOrganization org = contact->detail<QContactOrganization>(); |
341 | + label = org.name().trimmed(); |
342 | + if (label.isEmpty()) { |
343 | + QContactPhoneNumber phone = contact->detail<QContactPhoneNumber>(); |
344 | + label = phone.number().trimmed(); |
345 | + } |
346 | + |
347 | + displayName.setLabel(label); |
348 | + contact->saveDetail(&displayName); |
349 | + } |
350 | + |
351 | + // WORKAROUND: add a extra tag to help on alphabetic list |
352 | + // On the Ubuntu Address Book, contacts which the name starts with |
353 | + // number or symbol should be moved to bottom of the list. Since the standard |
354 | + // string sort put symbols and numbers on the top, we use the tag to sort, |
355 | + // and keep empty tags for the especial case. |
356 | + QContactTag tag; |
357 | + label = label.toUpper(); |
358 | + if (label.isEmpty() || |
359 | + !label.at(0).isLetter()) { |
360 | + tag.setTag(""); |
361 | + } else { |
362 | + tag.setTag(label); |
363 | + } |
364 | + contact->saveDetail(&tag); |
365 | } |
366 | |
367 | bool QIndividual::update(const QtContacts::QContact &newContact, QObject *object, const char *slot) |
368 | |
369 | === modified file 'lib/view.cpp' |
370 | --- lib/view.cpp 2014-04-09 12:57:07 +0000 |
371 | +++ lib/view.cpp 2014-05-05 14:42:08 +0000 |
372 | @@ -19,6 +19,7 @@ |
373 | #include "view.h" |
374 | #include "view-adaptor.h" |
375 | #include "contacts-map.h" |
376 | +#include "contact-less-than.h" |
377 | #include "qindividual.h" |
378 | |
379 | #include "common/vcard-parser.h" |
380 | @@ -38,24 +39,6 @@ |
381 | |
382 | namespace galera |
383 | { |
384 | -class ContactLessThan |
385 | -{ |
386 | -public: |
387 | - ContactLessThan(const SortClause &sortClause) |
388 | - : m_sortClause(sortClause) |
389 | - { |
390 | - |
391 | - } |
392 | - |
393 | - bool operator()(galera::ContactEntry *entryA, galera::ContactEntry *entryB) |
394 | - { |
395 | - return QContactManagerEngine::compareContact(entryA->individual()->contact(), |
396 | - entryB->individual()->contact(), |
397 | - m_sortClause.toContactSortOrder()) < 0; |
398 | - } |
399 | -private: |
400 | - SortClause m_sortClause; |
401 | -}; |
402 | |
403 | class FilterThread: public QThread |
404 | { |
405 | @@ -80,8 +63,7 @@ |
406 | bool appendContact(ContactEntry *entry) |
407 | { |
408 | if (checkContact(entry)) { |
409 | - //TODO: append sorted |
410 | - m_contacts << entry; |
411 | + addSorted(&m_contacts, entry, m_sortClause); |
412 | return true; |
413 | } |
414 | return false; |
415 | @@ -95,8 +77,22 @@ |
416 | void chageSort(SortClause clause) |
417 | { |
418 | m_sortClause = clause; |
419 | - ContactLessThan lessThan(m_sortClause); |
420 | - qSort(m_contacts.begin(), m_contacts.end(), lessThan); |
421 | + if (!clause.isEmpty()) { |
422 | + ContactLessThan lessThan(m_sortClause); |
423 | + qSort(m_contacts.begin(), m_contacts.end(), lessThan); |
424 | + } |
425 | + } |
426 | + |
427 | + void addSorted(QList<ContactEntry*>* sorted, ContactEntry* toAdd, const SortClause& sortOrder) |
428 | + { |
429 | + if (!sortOrder.isEmpty()) { |
430 | + ContactLessThan lessThan(sortOrder); |
431 | + QList<ContactEntry*>::iterator it(std::upper_bound(sorted->begin(), sorted->end(), toAdd, lessThan)); |
432 | + sorted->insert(it, toAdd); |
433 | + } else { |
434 | + // no sort order? just add it to the end |
435 | + sorted->append(toAdd); |
436 | + } |
437 | } |
438 | |
439 | void stop() |
440 | @@ -124,14 +120,14 @@ |
441 | m_stoppedLock.unlock(); |
442 | |
443 | if (checkContact(entry)) { |
444 | - m_contacts << entry; |
445 | + addSorted(&m_contacts, entry, m_sortClause); |
446 | } |
447 | } |
448 | } else { |
449 | m_contacts = m_allContacts->values(); |
450 | + chageSort(m_sortClause); |
451 | } |
452 | |
453 | - chageSort(m_sortClause); |
454 | m_allContacts->unlock(); |
455 | } |
456 | |
457 | |
458 | === modified file 'tests/unittest/CMakeLists.txt' |
459 | --- tests/unittest/CMakeLists.txt 2014-03-19 16:44:03 +0000 |
460 | +++ tests/unittest/CMakeLists.txt 2014-05-05 14:42:08 +0000 |
461 | @@ -75,6 +75,7 @@ |
462 | declare_test(readonly-prop-test True ${BASE_CLIENT_TEST_SRC}) |
463 | declare_test(contact-link-test True ${BASE_CLIENT_TEST_SRC}) |
464 | declare_test(qcontacts-test True ${BASE_CLIENT_TEST_SRC}) |
465 | + declare_test(qcontacts-create-source-test True ${BASE_CLIENT_TEST_SRC}) |
466 | elseif() |
467 | message(STATUS "DBus test runner not found. Some tests will be disabled") |
468 | endif() |
469 | |
470 | === modified file 'tests/unittest/addressbook-test.cpp' |
471 | --- tests/unittest/addressbook-test.cpp 2014-03-24 20:11:26 +0000 |
472 | +++ tests/unittest/addressbook-test.cpp 2014-05-05 14:42:08 +0000 |
473 | @@ -147,6 +147,7 @@ |
474 | << "ORG_TITLE" |
475 | << "PHONE" |
476 | << "PHOTO" |
477 | + << "TAG" |
478 | << "URL"; |
479 | QDBusReply<QStringList> reply = m_serverIface->call("sortFields"); |
480 | QCOMPARE(reply.value(), defaultSortFields); |
481 | |
482 | === added file 'tests/unittest/qcontacts-create-source-test.cpp' |
483 | --- tests/unittest/qcontacts-create-source-test.cpp 1970-01-01 00:00:00 +0000 |
484 | +++ tests/unittest/qcontacts-create-source-test.cpp 2014-05-05 14:42:08 +0000 |
485 | @@ -0,0 +1,83 @@ |
486 | +/* |
487 | + * Copyright 2013 Canonical Ltd. |
488 | + * |
489 | + * This file is part of contact-service-app. |
490 | + * |
491 | + * contact-service-app is free software; you can redistribute it and/or modify |
492 | + * it under the terms of the GNU General Public License as published by |
493 | + * the Free Software Foundation; version 3. |
494 | + * |
495 | + * contact-service-app is distributed in the hope that it will be useful, |
496 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
497 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
498 | + * GNU General Public License for more details. |
499 | + * |
500 | + * You should have received a copy of the GNU General Public License |
501 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
502 | + */ |
503 | + |
504 | +#include "base-client-test.h" |
505 | +#include "common/source.h" |
506 | +#include "common/dbus-service-defs.h" |
507 | +#include "common/vcard-parser.h" |
508 | + |
509 | +#include <QObject> |
510 | +#include <QtDBus> |
511 | +#include <QtTest> |
512 | +#include <QDebug> |
513 | +#include <QtContacts> |
514 | + |
515 | +#include "config.h" |
516 | + |
517 | +using namespace QtContacts; |
518 | + |
519 | +class QContactsCreateSourceTest : public BaseClientTest |
520 | +{ |
521 | + Q_OBJECT |
522 | +private Q_SLOTS: |
523 | + void initTestCase() |
524 | + { |
525 | + BaseClientTest::initTestCase(); |
526 | + QCoreApplication::setLibraryPaths(QStringList() << QT_PLUGINS_BINARY_DIR); |
527 | + } |
528 | + |
529 | + /* |
530 | + * Test create a contact source using the contact group |
531 | + */ |
532 | + void testCreateGroup() |
533 | + { |
534 | + QContactManager manager("galera"); |
535 | + |
536 | + // create a contact |
537 | + QContact contact; |
538 | + contact.setType(QContactType::TypeGroup); |
539 | + |
540 | + QContactDisplayLabel label; |
541 | + label.setLabel("test group"); |
542 | + contact.saveDetail(&label); |
543 | + |
544 | + bool result = manager.saveContact(&contact); |
545 | + QCOMPARE(result, true); |
546 | + |
547 | + // query for new contacts |
548 | + QContactDetailFilter filter; |
549 | + filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); |
550 | + filter.setValue(QContactType::TypeGroup); |
551 | + QList<QContact> contacts = manager.contacts(filter); |
552 | + |
553 | + // will be two sources since we have the main source already created |
554 | + QCOMPARE(contacts.size(), 2); |
555 | + |
556 | + QContact createdContact = contacts[0]; |
557 | + // id |
558 | + QVERIFY(!createdContact.id().isNull()); |
559 | + |
560 | + // label |
561 | + QContactDisplayLabel createdlabel = createdContact.detail<QContactDisplayLabel>(); |
562 | + QCOMPARE(createdlabel.label(), label.label()); |
563 | + } |
564 | +}; |
565 | + |
566 | +QTEST_MAIN(QContactsCreateSourceTest) |
567 | + |
568 | +#include "qcontacts-create-source-test.moc" |
569 | |
570 | === modified file 'tests/unittest/qcontacts-test.cpp' |
571 | --- tests/unittest/qcontacts-test.cpp 2014-03-20 22:06:09 +0000 |
572 | +++ tests/unittest/qcontacts-test.cpp 2014-05-05 14:42:08 +0000 |
573 | @@ -121,7 +121,7 @@ |
574 | QContactSyncTarget target = contact.detail<QContactSyncTarget>(); |
575 | QCOMPARE(target.syncTarget(), QString("Dummy personas")); |
576 | } |
577 | -#if 0 |
578 | + |
579 | /* |
580 | * Test create a new contact |
581 | */ |
582 | @@ -160,42 +160,6 @@ |
583 | } |
584 | |
585 | /* |
586 | - * Test create a contact source using the contact group |
587 | - */ |
588 | - void testCreateGroup() |
589 | - { |
590 | - QContactManager manager("galera"); |
591 | - |
592 | - // create a contact |
593 | - QContact contact; |
594 | - contact.setType(QContactType::TypeGroup); |
595 | - |
596 | - QContactDisplayLabel label; |
597 | - label.setLabel("test group"); |
598 | - contact.saveDetail(&label); |
599 | - |
600 | - bool result = manager.saveContact(&contact); |
601 | - QCOMPARE(result, true); |
602 | - |
603 | - // query for new contacts |
604 | - QContactDetailFilter filter; |
605 | - filter.setDetailType(QContactDetail::TypeType, QContactType::FieldType); |
606 | - filter.setValue(QContactType::TypeGroup); |
607 | - QList<QContact> contacts = manager.contacts(filter); |
608 | - |
609 | - // will be two sources since we have the main source already created |
610 | - QCOMPARE(contacts.size(), 2); |
611 | - |
612 | - QContact createdContact = contacts[0]; |
613 | - // id |
614 | - QVERIFY(!createdContact.id().isNull()); |
615 | - |
616 | - // label |
617 | - QContactDisplayLabel createdlabel = createdContact.detail<QContactDisplayLabel>(); |
618 | - QCOMPARE(createdlabel.label(), label.label()); |
619 | - } |
620 | - |
621 | - /* |
622 | * Test query a contact source using the contact group |
623 | */ |
624 | void testQueryGroups() |
625 | @@ -216,7 +180,164 @@ |
626 | QContactDisplayLabel label = contacts[0].detail(QContactDisplayLabel::Type); |
627 | QCOMPARE(label.label(), QStringLiteral("Dummy personas")); |
628 | } |
629 | -#endif |
630 | + |
631 | + /* |
632 | + * Test sort contacts by with symbols in the end |
633 | + */ |
634 | + void testQuerySortedWithSymbolsInTheEnd() |
635 | + { |
636 | + QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>))); |
637 | + |
638 | + // create a contact "" |
639 | + QContact contact; |
640 | + QContactName name = contact.detail<QContactName>(); |
641 | + name.setFirstName(""); |
642 | + name.setMiddleName(""); |
643 | + name.setLastName(""); |
644 | + contact.saveDetail(&name); |
645 | + bool result = m_manager->saveContact(&contact); |
646 | + QCOMPARE(result, true); |
647 | + |
648 | + // create contact "Aa" |
649 | + contact = QContact(); |
650 | + name = contact.detail<QContactName>(); |
651 | + name.setFirstName("Aa"); |
652 | + contact.saveDetail(&name); |
653 | + result = m_manager->saveContact(&contact); |
654 | + QCOMPARE(result, true); |
655 | + |
656 | + // create contact "Ba" |
657 | + contact = QContact(); |
658 | + name = contact.detail<QContactName>(); |
659 | + name.setFirstName("Ba"); |
660 | + contact.saveDetail(&name); |
661 | + result = m_manager->saveContact(&contact); |
662 | + QCOMPARE(result, true); |
663 | + |
664 | + // create contact "Bb" |
665 | + contact = QContact(); |
666 | + name = contact.detail<QContactName>(); |
667 | + name.setFirstName("Bb"); |
668 | + contact.saveDetail(&name); |
669 | + result = m_manager->saveContact(&contact); |
670 | + QCOMPARE(result, true); |
671 | + |
672 | + // create contact "321" |
673 | + contact = QContact(); |
674 | + name = contact.detail<QContactName>(); |
675 | + name.setFirstName("321"); |
676 | + contact.saveDetail(&name); |
677 | + result = m_manager->saveContact(&contact); |
678 | + QCOMPARE(result, true); |
679 | + |
680 | + // create contact "*" |
681 | + contact = QContact(); |
682 | + name = contact.detail<QContactName>(); |
683 | + name.setFirstName("*"); |
684 | + contact.saveDetail(&name); |
685 | + result = m_manager->saveContact(&contact); |
686 | + QCOMPARE(result, true); |
687 | + |
688 | + // create contact "" with company "x" |
689 | + contact = QContact(); |
690 | + name = contact.detail<QContactName>(); |
691 | + name.setFirstName(""); |
692 | + name.setMiddleName(""); |
693 | + name.setLastName(""); |
694 | + contact.saveDetail(&name); |
695 | + |
696 | + QContactOrganization org; |
697 | + org.setName("x"); |
698 | + contact.saveDetail(&org); |
699 | + result = m_manager->saveContact(&contact); |
700 | + QCOMPARE(result, true); |
701 | + |
702 | + QTRY_COMPARE(spyContactAdded.count(), 1); |
703 | + |
704 | + // sort contact by tag and display name |
705 | + QContactFilter filter; |
706 | + QContactSortOrder sortTag; |
707 | + sortTag.setDetailType(QContactDetail::TypeTag, QContactTag::FieldTag); |
708 | + sortTag.setDirection(Qt::AscendingOrder); |
709 | + sortTag.setCaseSensitivity(Qt::CaseInsensitive); |
710 | + sortTag.setBlankPolicy(QContactSortOrder::BlanksLast); |
711 | + |
712 | + QContactSortOrder sortDisplayName; |
713 | + sortDisplayName.setDetailType(QContactDetail::TypeDisplayLabel, QContactDisplayLabel::FieldLabel); |
714 | + sortDisplayName.setDirection(Qt::AscendingOrder); |
715 | + sortDisplayName.setCaseSensitivity(Qt::CaseInsensitive); |
716 | + sortDisplayName.setBlankPolicy(QContactSortOrder::BlanksLast); |
717 | + |
718 | + QList<QContactSortOrder> sortOrders; |
719 | + sortOrders << sortTag << sortDisplayName; |
720 | + |
721 | + // check result |
722 | + QList<QContact> contacts = m_manager->contacts(filter, sortOrders); |
723 | + QCOMPARE(contacts.size(), 7); |
724 | + QCOMPARE(contacts[0].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
725 | + QStringLiteral("Aa")); |
726 | + QCOMPARE(contacts[1].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
727 | + QStringLiteral("Ba")); |
728 | + QCOMPARE(contacts[2].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
729 | + QStringLiteral("Bb")); |
730 | + QCOMPARE(contacts[3].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
731 | + QStringLiteral("x")); |
732 | + QCOMPARE(contacts[4].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
733 | + QStringLiteral("*")); |
734 | + QCOMPARE(contacts[5].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
735 | + QStringLiteral("321")); |
736 | + QCOMPARE(contacts[6].detail(QContactDetail::TypeDisplayLabel).value(QContactDisplayLabel::FieldLabel).toString(), |
737 | + QStringLiteral("")); |
738 | + } |
739 | + |
740 | + void testContactDisplayName() |
741 | + { |
742 | + // create a contact "" |
743 | + QContact contact; |
744 | + QContactName name = contact.detail<QContactName>(); |
745 | + name.setFirstName(""); |
746 | + name.setMiddleName(""); |
747 | + name.setLastName(""); |
748 | + contact.saveDetail(&name); |
749 | + bool result = m_manager->saveContact(&contact); |
750 | + QCOMPARE(result, true); |
751 | + |
752 | + // create contact "Aa" |
753 | + contact = QContact(); |
754 | + name = contact.detail<QContactName>(); |
755 | + name.setFirstName("Aa"); |
756 | + contact.saveDetail(&name); |
757 | + result = m_manager->saveContact(&contact); |
758 | + QCOMPARE(result, true); |
759 | + |
760 | + // create contact "" with company "x" |
761 | + contact = QContact(); |
762 | + name = contact.detail<QContactName>(); |
763 | + name.setFirstName(""); |
764 | + name.setMiddleName(""); |
765 | + name.setLastName(""); |
766 | + contact.saveDetail(&name); |
767 | + QContactOrganization org; |
768 | + org.setName("x"); |
769 | + contact.saveDetail(&org); |
770 | + result = m_manager->saveContact(&contact); |
771 | + |
772 | + QCOMPARE(result, true); |
773 | + |
774 | + // check result |
775 | + QContactFilter filter; |
776 | + QList<QContact> contacts = m_manager->contacts(filter); |
777 | + |
778 | + QStringList expectedContacts; |
779 | + expectedContacts << "" |
780 | + << "Aa" |
781 | + << "x"; |
782 | + QCOMPARE(contacts.size(), 3); |
783 | + Q_FOREACH(const QContact &c, contacts) { |
784 | + expectedContacts.removeAll(c.detail<QContactDisplayLabel>().label()); |
785 | + } |
786 | + QCOMPARE(expectedContacts.size(), 0); |
787 | + } |
788 | }; |
789 | |
790 | QTEST_MAIN(QContactsTest) |
791 | |
792 | === modified file 'tests/unittest/sort-clause-test.cpp' |
793 | --- tests/unittest/sort-clause-test.cpp 2013-06-11 20:13:09 +0000 |
794 | +++ tests/unittest/sort-clause-test.cpp 2014-05-05 14:42:08 +0000 |
795 | @@ -113,6 +113,19 @@ |
796 | QCOMPARE(clause.toContactSortOrder().size(), 0); |
797 | } |
798 | |
799 | + void testTagSourtClause() |
800 | + { |
801 | + const QString strClause = QString("TAG ASC"); |
802 | + SortClause clause(strClause); |
803 | + |
804 | + QList<QContactSortOrder> cClauseList; |
805 | + QContactSortOrder sortTag; |
806 | + sortTag.setDetailType(QContactDetail::TypeTag, QContactTag::FieldTag); |
807 | + sortTag.setDirection(Qt::AscendingOrder); |
808 | + sortTag.setCaseSensitivity(Qt::CaseInsensitive); |
809 | + cClauseList << sortTag; |
810 | + QVERIFY(clause.toContactSortOrder() == cClauseList); |
811 | + } |
812 | }; |
813 | |
814 | QTEST_MAIN(SortClauseTest) |
PASSED: Continuous integration, rev:116 jenkins. qa.ubuntu. com/job/ address- book-service- ci/220/ jenkins. qa.ubuntu. com/job/ address- book-service- trusty- amd64-ci/ 127 jenkins. qa.ubuntu. com/job/ address- book-service- trusty- armhf-ci/ 127 jenkins. qa.ubuntu. com/job/ address- book-service- trusty- armhf-ci/ 127/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ address- book-service- trusty- i386-ci/ 128
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/address- book-service- ci/220/ rebuild
http://