Merge lp:~renatofilho/address-book-service/irc-accounts into lp:address-book-service

Proposed by Renato Araujo Oliveira Filho on 2017-02-21
Status: Approved
Approved by: Tiago Salem Herrmann on 2017-03-22
Approved revision: 236
Proposed branch: lp:~renatofilho/address-book-service/irc-accounts
Merge into: lp:address-book-service
Diff against target: 786 lines (+444/-33)
12 files modified
CMakeLists.txt (+1/-1)
common/vcard-parser.cpp (+61/-11)
common/vcard-parser.h (+2/-0)
lib/detail-context-parser.cpp (+6/-3)
lib/gee-utils.cpp (+10/-4)
lib/gee-utils.h (+1/-1)
lib/qindividual.cpp (+68/-9)
lib/qindividual.h (+3/-4)
lib/update-contact-request.cpp (+28/-0)
tests/unittest/CMakeLists.txt (+1/-0)
tests/unittest/contact-accounts-test.cpp (+182/-0)
tests/unittest/vcardparser-test.cpp (+81/-0)
To merge this branch: bzr merge lp:~renatofilho/address-book-service/irc-accounts
Reviewer Review Type Date Requested Status
Tiago Salem Herrmann (community) 2017-02-21 Approve on 2017-03-22
system-apps-ci-bot continuous-integration Approve on 2017-03-22
Review via email: mp+317836@code.launchpad.net

Commit message

Implement support for saving IRC accounts.

To post a comment you must log in.
233. By Renato Araujo Oliveira Filho on 2017-02-21

Added missing file.

234. By Renato Araujo Oliveira Filho on 2017-02-23

Implement support for PROVIDERS save on IRC accounts.

235. By Renato Araujo Oliveira Filho on 2017-02-24

Implement support for PROVIDER on online accounts.

TODO: Folks EDS does not support it.

review: Needs Fixing (continuous-integration)
Tiago Salem Herrmann (tiagosh) wrote :

just one remark.
looks good otherwise.

review: Needs Fixing

> just one remark.
> looks good otherwise.

Fixed

236. By Renato Araujo Oliveira Filho on 2017-03-22

Removed duplicated check.

PASSED: Continuous integration, rev:236
https://jenkins.canonical.com/system-apps/job/lp-address-book-service-ci/2/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build/2336
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/2335
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2157
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=zesty/2157
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=zesty/2157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2157
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=zesty/2157
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=zesty/2157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/2157
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/2157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=zesty/2157
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=zesty/2157/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-address-book-service-ci/2/rebuild

review: Approve (continuous-integration)
Tiago Salem Herrmann (tiagosh) wrote :

looks good. thanks.

review: Approve

Unmerged revisions

236. By Renato Araujo Oliveira Filho on 2017-03-22

Removed duplicated check.

235. By Renato Araujo Oliveira Filho on 2017-02-24

Implement support for PROVIDER on online accounts.

TODO: Folks EDS does not support it.

234. By Renato Araujo Oliveira Filho on 2017-02-23

Implement support for PROVIDERS save on IRC accounts.

233. By Renato Araujo Oliveira Filho on 2017-02-21

Added missing file.

232. By Renato Araujo Oliveira Filho on 2017-02-21

Fixed contact creation with IRC field.

231. By Renato Araujo Oliveira Filho on 2017-02-20

Implement support for saving IRC accounts.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-09-23 12:36:13 +0000
3+++ CMakeLists.txt 2017-03-22 11:39:22 +0000
4@@ -40,7 +40,7 @@
5 else()
6 set(EVOLUTION_API_3_17 "1")
7 set(EVOLUTION_ADDRESSBOOK_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook9")
8- set(EVOLUTION_SOURCE_SERVICE_NAME "org.gnome.evolution.dataserver.Sources4")
9+ set(EVOLUTION_SOURCE_SERVICE_NAME "org.gnome.evolution.dataserver.Sources5")
10 endif()
11
12 set(CMAKE_INCLUDE_CURRENT_DIR ON)
13
14=== modified file 'common/vcard-parser.cpp'
15--- common/vcard-parser.cpp 2015-11-03 23:54:53 +0000
16+++ common/vcard-parser.cpp 2017-03-22 11:39:22 +0000
17@@ -34,6 +34,20 @@
18 using namespace QtVersit;
19 using namespace QtContacts;
20
21+namespace galera
22+{
23+
24+const QString VCardParser::PidMapFieldName = QStringLiteral("CLIENTPIDMAP");
25+const QString VCardParser::PidFieldName = QStringLiteral("PID");
26+const QString VCardParser::PrefParamName = QStringLiteral("PREF");
27+const QString VCardParser::IrremovableFieldName = QStringLiteral("IRREMOVABLE");
28+const QString VCardParser::ReadOnlyFieldName = QStringLiteral("READ-ONLY");
29+const QString VCardParser::TagFieldName = QStringLiteral("TAG");
30+const QString VCardParser::IrcFieldName = QStringLiteral("X-IRC");
31+const QString VCardParser::OnlineAccountProviderParamName = QStringLiteral("PROVIDER");
32+
33+}
34+
35 namespace
36 {
37 class ContactExporterDetailHandler : public QVersitContactExporterDetailHandlerV2
38@@ -67,10 +81,25 @@
39 }
40
41 if (detail.type() == QContactDetail::TypeExtendedDetail) {
42- QVersitProperty prop;
43- prop.setName(detail.value(QContactExtendedDetail::FieldName).toString());
44- prop.setValue(detail.value(QContactExtendedDetail::FieldData).toString());
45- *toBeAdded << prop;
46+ // Do not translate X-IRC extended details
47+ if (detail.value(QContactExtendedDetail::FieldName).toString() != galera::VCardParser::IrcFieldName) {
48+ QVersitProperty prop;
49+ prop.setName(detail.value(QContactExtendedDetail::FieldName).toString());
50+ prop.setValue(detail.value(QContactExtendedDetail::FieldData).toString());
51+ *toBeAdded << prop;
52+ }
53+ }
54+
55+ // export IRC online account (This is not exported by QtVersit)
56+ if (detail.type() == QContactDetail::TypeOnlineAccount) {
57+ QContactOnlineAccount acc = static_cast<QContactOnlineAccount>(detail);
58+ if (acc.protocol() == QContactOnlineAccount::ProtocolIrc) {
59+ QVersitProperty prop;
60+ prop.setName(galera::VCardParser::IrcFieldName);
61+ prop.setValue(acc.accountUri());
62+ // provider will be added by later accout parse
63+ *toBeAdded << prop;
64+ }
65 }
66
67 if (toBeAdded->size() == 0) {
68@@ -122,6 +151,15 @@
69 }
70 break;
71 }
72+ case QContactDetail::TypeOnlineAccount:
73+ {
74+ QContactOnlineAccount account = static_cast<QContactOnlineAccount>(detail);
75+ QVersitProperty &prop = toBeAdded->last();
76+ QMultiHash<QString, QString> params = prop.parameters();
77+ params.insert(galera::VCardParser::OnlineAccountProviderParamName, account.serviceProvider());
78+ prop.setParameters(params);
79+ break;
80+ }
81 default:
82 break;
83 }
84@@ -170,9 +208,19 @@
85 }
86
87 if (!*alreadyProcessed && (property.name().startsWith("X-"))) {
88+ // IRC FIELDS
89+ if (property.name() == galera::VCardParser::IrcFieldName) {
90+ QContactOnlineAccount acc;
91+ acc.setProtocol(QContactOnlineAccount::ProtocolIrc);
92+ acc.setAccountUri(property.value());
93+ acc.setServiceProvider(property.parameters().value(galera::VCardParser::OnlineAccountProviderParamName));
94+ *updatedDetails << acc;
95+ }
96 QContactExtendedDetail xDet;
97 xDet.setName(property.name());
98 xDet.setData(property.value<QString>());
99+ xDet.setValue(QContactExtendedDetail::FieldData + 1, property.parameters().value(galera::VCardParser::OnlineAccountProviderParamName));
100+
101 *updatedDetails << xDet;
102 *alreadyProcessed = true;
103 }
104@@ -181,6 +229,7 @@
105 return;
106 }
107
108+
109 QString pid = property.parameters().value(galera::VCardParser::PidFieldName);
110 if (!pid.isEmpty()) {
111 QContactDetail &det = updatedDetails->last();
112@@ -230,6 +279,14 @@
113 }
114 break;
115 }
116+ case QContactDetail::TypeOnlineAccount:
117+ {
118+ // Fill provider for online accounts
119+ QString provider = property.parameters().value(galera::VCardParser::OnlineAccountProviderParamName);
120+ if (!provider.isEmpty())
121+ det.setValue(QContactOnlineAccount::FieldServiceProvider, provider);
122+ break;
123+ }
124 default:
125 break;
126 }
127@@ -270,13 +327,6 @@
128 namespace galera
129 {
130
131-const QString VCardParser::PidMapFieldName = QStringLiteral("CLIENTPIDMAP");
132-const QString VCardParser::PidFieldName = QStringLiteral("PID");
133-const QString VCardParser::PrefParamName = QStringLiteral("PREF");
134-const QString VCardParser::IrremovableFieldName = QStringLiteral("IRREMOVABLE");
135-const QString VCardParser::ReadOnlyFieldName = QStringLiteral("READ-ONLY");
136-const QString VCardParser::TagFieldName = QStringLiteral("TAG");
137-
138 static QMap<QtContacts::QContactDetail::DetailType, QString> prefferedActions()
139 {
140 QMap<QtContacts::QContactDetail::DetailType, QString> values;
141
142=== modified file 'common/vcard-parser.h'
143--- common/vcard-parser.h 2015-10-28 14:28:11 +0000
144+++ common/vcard-parser.h 2017-03-22 11:39:22 +0000
145@@ -57,6 +57,8 @@
146 static const QString IrremovableFieldName;
147 static const QString ReadOnlyFieldName;
148 static const QString TagFieldName;
149+ static const QString IrcFieldName;
150+ static const QString OnlineAccountProviderParamName;
151 static const QMap<QtContacts::QContactDetail::DetailType, QString> PreferredActionNames;
152
153 static QtContacts::QContact vcardToContact(const QString &vcard);
154
155=== modified file 'lib/detail-context-parser.cpp'
156--- lib/detail-context-parser.cpp 2016-09-20 13:25:21 +0000
157+++ lib/detail-context-parser.cpp 2017-03-22 11:39:22 +0000
158@@ -218,10 +218,13 @@
159
160 while (gee_iterator_next (siter)) {
161 char *parameter = (char*) gee_iterator_get(siter);
162- if (QString::fromUtf8(parameter).toUpper() == VCardParser::PrefParamName) {
163+ const QString parameterName = QString::fromUtf8(parameter).toUpper();
164+ if (parameterName == VCardParser::PrefParamName) {
165 params << "pref";
166 continue;
167- } else if (QString::fromUtf8(parameter) != "type") {
168+ } else if (parameterName == VCardParser::OnlineAccountProviderParamName) {
169+
170+ } else if (parameterName != "TYPE") {
171 if (!whiteList.contains(QString::fromUtf8(parameter))) {
172 qDebug() << "not supported field details" << parameter;
173 // FIXME: check what to do with other parameters
174@@ -389,7 +392,7 @@
175 Q_FOREACH(const QString &param, parameters) {
176 if (map.contains(param.toLower())) {
177 values << map[param.toLower()];
178- } else {
179+ } else {
180 qWarning() << "invalid IM subtype" << param;
181 }
182 }
183
184=== modified file 'lib/gee-utils.cpp'
185--- lib/gee-utils.cpp 2013-10-30 19:07:49 +0000
186+++ lib/gee-utils.cpp 2017-03-22 11:39:22 +0000
187@@ -19,6 +19,7 @@
188 #include "gee-utils.h"
189
190 #include <QDebug>
191+#include <QPair>
192
193 GValue* GeeUtils::gValueSliceNew(GType type)
194 {
195@@ -39,7 +40,7 @@
196 g_hash_table_insert(details, (gpointer) folks_persona_store_detail_key(key), value);
197 }
198
199-GValue* GeeUtils::asvSetStrNew(QMultiMap<QString, QString> providerUidMap)
200+GValue* GeeUtils::asvSetStrNew(QMultiMap<QString, QPair<QString, QString> > providerUidMap)
201 {
202 GeeMultiMap *hashSet = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);
203 GValue *retval = gValueSliceNew (G_TYPE_OBJECT);
204@@ -47,11 +48,16 @@
205
206 QList<QString> keys = providerUidMap.keys();
207 Q_FOREACH(const QString& key, keys) {
208- QList<QString> values = providerUidMap.values(key);
209- Q_FOREACH(const QString& value, values) {
210+ Q_FOREACH(const auto &value, providerUidMap.values(key)) {
211 FolksImFieldDetails *imfd;
212+ const QString &accountUri = value.first;
213+ const QString &accountProvider = value.second;
214
215- imfd = folks_im_field_details_new (value.toUtf8().data(), NULL);
216+ imfd = folks_im_field_details_new (accountUri.toUtf8().data(), NULL);
217+ if (!accountProvider.isEmpty()) {
218+ folks_abstract_field_details_add_parameter(FOLKS_ABSTRACT_FIELD_DETAILS(imfd),
219+ "PROVIDER", accountProvider.toUtf8().data());
220+ }
221
222 gee_multi_map_set(hashSet,
223 key.toUtf8().data(),
224
225=== modified file 'lib/gee-utils.h'
226--- lib/gee-utils.h 2013-10-30 19:07:49 +0000
227+++ lib/gee-utils.h 2017-03-22 11:39:22 +0000
228@@ -84,7 +84,7 @@
229 static GValue* gValueSliceNew(GType type);
230 static void gValueSliceFree(GValue *value);
231 static void personaDetailsInsert(GHashTable *details, FolksPersonaDetail key, gpointer value);
232- static GValue* asvSetStrNew(QMultiMap<QString, QString> providerUidMap);
233+ static GValue* asvSetStrNew(QMultiMap<QString, QPair<QString, QString> > providerUidMap);
234 }; // class
235
236 #endif
237
238=== modified file 'lib/qindividual.cpp'
239--- lib/qindividual.cpp 2016-05-04 17:56:15 +0000
240+++ lib/qindividual.cpp 2017-03-22 11:39:22 +0000
241@@ -28,6 +28,7 @@
242 #include <libebook/libebook.h>
243
244 #include <QtCore/QMutexLocker>
245+#include <QtCore/QPair>
246
247 #include <QtVersit/QVersitDocument>
248 #include <QtVersit/QVersitProperty>
249@@ -64,6 +65,7 @@
250 #define X_GROUP_ID "X-GROUP-ID"
251 #define X_DELETED_AT "X-DELETED-AT"
252 #define X_AVATAR_REV "X-AVATAR-REV"
253+#define X_IRC_ACCOUNT "X-IRC"
254
255 namespace
256 {
257@@ -100,12 +102,16 @@
258 } else if(g_type == FOLKS_TYPE_WEB_SERVICE_FIELD_DETAILS) {
259 fieldDetails = FOLKS_ABSTRACT_FIELD_DETAILS (
260 folks_web_service_field_details_new(v_string, NULL));
261+ } else if(g_type == FOLKS_TYPE_EXTENDED_FIELD_DETAILS) {
262+ fieldDetails = FOLKS_ABSTRACT_FIELD_DETAILS (
263+ folks_extended_field_details_new(v_string, NULL));
264 }
265
266 if (fieldDetails == NULL) {
267 qWarning() << "Invalid fieldDetails type" << g_type;
268 } else {
269 galera::DetailContextParser::parseContext(fieldDetails, detail, ispreferred);
270+
271 gee_collection_add(collection, fieldDetails);
272
273 g_object_unref(fieldDetails);
274@@ -151,6 +157,7 @@
275 {
276 bool QIndividual::m_autoLink = false;
277 QStringList QIndividual::m_supportedExtendedDetails;
278+QList<QContactOnlineAccount::Protocol> QIndividual::m_protocolBlackList;
279
280 QIndividual::QIndividual(FolksIndividual *individual, FolksIndividualAggregator *aggregator)
281 : m_individual(0),
282@@ -164,7 +171,8 @@
283 << X_REMOTE_ID
284 << X_GOOGLE_ETAG
285 << X_GROUP_ID
286- << X_AVATAR_REV;
287+ << X_AVATAR_REV
288+ << X_IRC_ACCOUNT;
289 }
290 setIndividual(individual);
291 }
292@@ -689,6 +697,20 @@
293 int protocolId = DetailContextParser::accountProtocolFromString(qStringFromGChar(key));
294 account.setProtocol(static_cast<QContactOnlineAccount::Protocol>(protocolId));
295
296+ // provider
297+ GeeCollection *providers = folks_abstract_field_details_get_parameter_values(fd, "PROVIDER");
298+ if (providers) {
299+ GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE (providers));
300+ if (iter) {
301+ char *provider = (char*) gee_iterator_get(iter);
302+ if (strlen(provider) > 0) {
303+ account.setServiceProvider(QString::fromUtf8(provider));
304+ }
305+ g_free(provider);
306+ g_object_unref(iter);
307+ }
308+ }
309+
310 bool isPref = false;
311 DetailContextParser::parseParameters(account, fd, &isPref);
312 account.setDetailUri(QString("%1.%2").arg(index).arg(fieldIndex++));
313@@ -765,12 +787,24 @@
314 EVCardAttribute *attr = e_vcard_get_attribute(E_VCARD(c), xDetName.toUtf8().constData());
315 if (attr) {
316 GString *attrValue = e_vcard_attribute_get_value_decoded(attr);
317- QContactExtendedDetail xDet;
318- xDet.setName(xDetName);
319- xDet.setData(QString::fromUtf8(attrValue->str));
320- xDet.setDetailUri(QString("%1.1").arg(index));
321- g_string_free(attrValue, true);
322- result << xDet;
323+
324+ if (xDetName == X_IRC_ACCOUNT) {
325+ QContactOnlineAccount acc;
326+ acc.setProtocol(QContactOnlineAccount::ProtocolIrc);
327+ acc.setAccountUri(QString::fromUtf8(attrValue->str));
328+ GList *param = e_vcard_attribute_get_param(attr, "PROVIDER");
329+ if (param)
330+ acc.setServiceProvider(QString::fromUtf8(static_cast<gchar*>(param->data)));
331+
332+ result << acc;
333+ } else {
334+ QContactExtendedDetail xDet;
335+ xDet.setName(xDetName);
336+ xDet.setData(QString::fromUtf8(attrValue->str));
337+ xDet.setDetailUri(QString("%1.1").arg(index));
338+ g_string_free(attrValue, true);
339+ result << xDet;
340+ }
341 }
342 }
343
344@@ -1559,11 +1593,20 @@
345 return details;
346 }
347
348- QMultiMap<QString, QString> providerUidMap;
349+ if (m_protocolBlackList.isEmpty()) {
350+ m_protocolBlackList << QContactOnlineAccount::ProtocolIrc;
351+ }
352+
353+ QMultiMap<QString, QPair<QString,QString> > providerUidMap;
354 Q_FOREACH(const QContactDetail &detail, cDetails) {
355 QContactOnlineAccount account = static_cast<QContactOnlineAccount>(detail);
356+ if (m_protocolBlackList.contains(account.protocol())) {
357+ continue;
358+ }
359+
360 if (!account.isEmpty()) {
361- providerUidMap.insert(DetailContextParser::accountProtocolName(account.protocol()), account.accountUri());
362+ providerUidMap.insert(DetailContextParser::accountProtocolName(account.protocol()),
363+ qMakePair(account.accountUri(), account.serviceProvider()));
364 }
365 }
366
367@@ -1789,6 +1832,17 @@
368 }
369
370 attr = e_vcard_attribute_new("", xd.name().toUtf8().constData());
371+
372+ // Special cases
373+ if (xd.name() == X_IRC_ACCOUNT) {
374+ // IRC - save provider
375+ QString provider = xd.value(QContactExtendedDetail::FieldData + 1).toString();
376+ if (!provider.isEmpty()) {
377+ EVCardAttributeParam * param = e_vcard_attribute_param_new("PROVIDER");
378+ e_vcard_attribute_add_param_with_value(attr, param, provider.toUtf8().constData());
379+ }
380+ }
381+
382 e_vcard_add_attribute_with_value(E_VCARD(c),
383 attr,
384 xd.data().toString().toUtf8().constData());
385@@ -1824,6 +1878,11 @@
386 return m_autoLink;
387 }
388
389+QList<QContactOnlineAccount::Protocol> QIndividual::protocolBlackList()
390+{
391+ return m_protocolBlackList;
392+}
393+
394 FolksPersona* QIndividual::primaryPersona()
395 {
396 if (m_personas.size() > 0) {
397
398=== modified file 'lib/qindividual.h'
399--- lib/qindividual.h 2015-09-04 15:01:52 +0000
400+++ lib/qindividual.h 2017-03-22 11:39:22 +0000
401@@ -29,6 +29,7 @@
402
403 #include <QtContacts/QContact>
404 #include <QtContacts/QContactDetail>
405+#include <QtContacts/QContactOnlineAccount>
406
407 #include <folks/folks.h>
408
409@@ -70,6 +71,7 @@
410 // enable or disable auto-link
411 static void enableAutoLink(bool flag);
412 static bool autoLinkEnabled();
413+ static QList<QtContacts::QContactOnlineAccount::Protocol> protocolBlackList();
414
415 private:
416 FolksIndividual *m_individual;
417@@ -86,6 +88,7 @@
418 bool m_visible;
419 static bool m_autoLink;
420 static QStringList m_supportedExtendedDetails;
421+ static QList<QtContacts::QContactOnlineAccount::Protocol> m_protocolBlackList;
422
423 QIndividual();
424 QIndividual(const QIndividual &);
425@@ -144,10 +147,6 @@
426
427 static void avatarCacheStoreDone(GObject *source, GAsyncResult *result, gpointer data);
428
429- // create
430- void createPersonaFromDetails(QList<QtContacts::QContactDetail> detail, ParseDetailsFunc parseFunc, void *data) const;
431- static void createPersonaForDetailDone(GObject *detail, GAsyncResult *result, gpointer userdata);
432-
433 // translate details
434 static GHashTable *parseFullNameDetails (GHashTable *details,
435 const QList<QtContacts::QContactDetail> &cDetails,
436
437=== modified file 'lib/update-contact-request.cpp'
438--- lib/update-contact-request.cpp 2015-09-24 17:47:49 +0000
439+++ lib/update-contact-request.cpp 2017-03-22 11:39:22 +0000
440@@ -229,6 +229,7 @@
441 return detailsFromPersona(m_originalContact, type, persona, false, pref);
442 }
443
444+
445 QList<QtContacts::QContactDetail> UpdateContactRequest::detailsFromPersona(QtContacts::QContactDetail::DetailType type,
446 int persona,
447 QtContacts::QContactDetail *pref) const
448@@ -570,6 +571,27 @@
449 m_currentPersonaIndex,
450 &prefDetail);
451
452+ // remove blacklisted protocols to avoid try to save it
453+ QList<QtContacts::QContactDetail>::iterator i = originalDetails.begin();
454+ while (i != originalDetails.end())
455+ {
456+ if (QIndividual::protocolBlackList().contains(static_cast<QtContacts::QContactOnlineAccount>(*i).protocol())) {
457+ originalDetails.erase(i++);
458+ } else {
459+ ++i;
460+ }
461+ }
462+
463+ i = newDetails.begin();
464+ while (i != newDetails.end())
465+ {
466+ if (QIndividual::protocolBlackList().contains(static_cast<QtContacts::QContactOnlineAccount>(*i).protocol())) {
467+ newDetails.erase(i++);
468+ } else {
469+ ++i;
470+ }
471+ }
472+
473 if (m_currentPersona &&
474 FOLKS_IS_IM_DETAILS(m_currentPersona) &&
475 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
476@@ -585,6 +607,10 @@
477 field = folks_im_field_details_new(accountUri.constData(), NULL);
478 DetailContextParser::parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(field), account, account == prefDetail);
479
480+ if (!account.serviceProvider().isEmpty()) {
481+ folks_abstract_field_details_add_parameter(FOLKS_ABSTRACT_FIELD_DETAILS(field),
482+ "PROVIDER", account.serviceProvider().toUtf8().data());
483+ }
484 QString protocolName(DetailContextParser::accountProtocolName(account.protocol()));
485 QByteArray protocolNameUtf8 = protocolName.toUtf8();
486 gee_multi_map_set(imMap, protocolNameUtf8.constData(), field);
487@@ -769,6 +795,8 @@
488 {
489 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeExtendedDetail, m_currentPersonaIndex, 0);
490 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeExtendedDetail, m_currentPersonaIndex, 0);
491+
492+
493 if (m_currentPersona &&
494 !isEqual(originalDetails, newDetails)) {
495 qDebug() << "Extended details diff";
496
497=== modified file 'tests/unittest/CMakeLists.txt'
498--- tests/unittest/CMakeLists.txt 2015-09-29 14:15:42 +0000
499+++ tests/unittest/CMakeLists.txt 2017-03-22 11:39:22 +0000
500@@ -116,6 +116,7 @@
501 declare_eds_test(contact-collection-test)
502 declare_eds_test(contact-timestamp-test)
503 declare_eds_test(contact-avatar-test)
504+ declare_eds_test(contact-accounts-test)
505 elseif()
506 message(STATUS "DBus test runner not found. Some tests will be disabled")
507 endif()
508
509=== added file 'tests/unittest/contact-accounts-test.cpp'
510--- tests/unittest/contact-accounts-test.cpp 1970-01-01 00:00:00 +0000
511+++ tests/unittest/contact-accounts-test.cpp 2017-03-22 11:39:22 +0000
512@@ -0,0 +1,182 @@
513+/*
514+ * Copyright 2013 Canonical Ltd.
515+ *
516+ * This file is part of contact-service-app.
517+ *
518+ * contact-service-app is free software; you can redistribute it and/or modify
519+ * it under the terms of the GNU General Public License as published by
520+ * the Free Software Foundation; version 3.
521+ *
522+ * contact-service-app is distributed in the hope that it will be useful,
523+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
524+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
525+ * GNU General Public License for more details.
526+ *
527+ * You should have received a copy of the GNU General Public License
528+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
529+ */
530+
531+#include <QObject>
532+#include <QtTest>
533+#include <QDebug>
534+#include <QtContacts>
535+
536+#include "config.h"
537+#include "common/vcard-parser.h"
538+#include "base-eds-test.h"
539+
540+using namespace QtContacts;
541+
542+class ContactAccountTest : public QObject, public BaseEDSTest
543+{
544+ Q_OBJECT
545+private:
546+
547+
548+private Q_SLOTS:
549+ void initTestCase()
550+ {
551+ BaseEDSTest::initTestCaseImpl();
552+ }
553+
554+ void cleanupTestCase()
555+ {
556+ BaseEDSTest::cleanupTestCaseImpl();
557+ }
558+
559+ void init()
560+ {
561+ BaseEDSTest::initImpl();
562+ }
563+
564+ void cleanup()
565+ {
566+ QList<QContactId> contacts = m_manager->contactIds();
567+ m_manager->removeContacts(contacts);
568+ BaseEDSTest::cleanupImpl();
569+ }
570+
571+ void testCreateIrcAccount()
572+ {
573+ QContact contact = galera::VCardParser::vcardToContact(QString("BEGIN:VCARD\r\n"
574+ "VERSION:3.0\r\n"
575+ "X-REMOTE-ID:1dd7d51a1518626a\r\n"
576+ "N:;Fulano;;;\r\n"
577+ "EMAIL:fulano@gmail.com\r\n"
578+ "TEL:123456\r\n"
579+ "X-IRC;PROVIDER=irc.freenode.net:myIRC\r\n"
580+ "CLIENTPIDMAP:56183a5b-5da7-49fe-8cf6-9bfd3633bf6d\r\n"
581+ "END:VCARD\r\n"));
582+
583+ QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
584+
585+ // create a contact
586+ QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>)));
587+ bool result = m_manager->saveContact(&contact);
588+ QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
589+ QCOMPARE(result, true);
590+ QTRY_COMPARE(spyContactAdded.count(), 1);
591+
592+ // query contacts;
593+ QContactFilter filter;
594+ QList<QContact> contacts = m_manager->contacts(filter);
595+ QCOMPARE(contacts.size(), 1);
596+
597+ QList<QContactOnlineAccount> accs = contacts[0].details<QContactOnlineAccount>();
598+ QCOMPARE(accs.size(), 1);
599+
600+ QContactOnlineAccount acc = accs[0];
601+ QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolIrc);
602+ QCOMPARE(acc.accountUri(), QStringLiteral("myIRC"));
603+ QCOMPARE(acc.serviceProvider(), QStringLiteral("irc.freenode.net"));
604+ }
605+
606+ //TODO: implement support for provider in well-know accounts
607+ /*
608+ void testCreateSkypeAccount()
609+ {
610+ QContact contact = galera::VCardParser::vcardToContact(QString("BEGIN:VCARD\r\n"
611+ "VERSION:3.0\r\n"
612+ "X-REMOTE-ID:1dd7d51a1518626a\r\n"
613+ "N:;Fulano;;;\r\n"
614+ "EMAIL:fulano@gmail.com\r\n"
615+ "TEL:123456\r\n"
616+ "X-SKYPE;PROVIDER=skype.net:mySkype\r\n"
617+ "CLIENTPIDMAP:56183a5b-5da7-49fe-8cf6-9bfd3633bf6d\r\n"
618+ "END:VCARD\r\n"));
619+
620+ QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
621+
622+ // create a contact
623+ QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>)));
624+ bool result = m_manager->saveContact(&contact);
625+ QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
626+ QCOMPARE(result, true);
627+ QTRY_COMPARE(spyContactAdded.count(), 1);
628+
629+ // query contacts;
630+ QContactFilter filter;
631+ QList<QContact> contacts = m_manager->contacts(filter);
632+ QCOMPARE(contacts.size(), 1);
633+
634+ QList<QContactOnlineAccount> accs = contacts[0].details<QContactOnlineAccount>();
635+ QCOMPARE(accs.size(), 1);
636+
637+ QContactOnlineAccount acc = accs[0];
638+ QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolSkype);
639+ QCOMPARE(acc.accountUri(), QStringLiteral("mySkype"));
640+ QCOMPARE(acc.serviceProvider(), QStringLiteral("skype.net"));
641+ }
642+ */
643+
644+ void testModifyIrcAccount()
645+ {
646+ QContact contact = galera::VCardParser::vcardToContact(QString("BEGIN:VCARD\r\n"
647+ "VERSION:3.0\r\n"
648+ "X-REMOTE-ID:1dd7d51a1518626a\r\n"
649+ "N:;Fulano;;;\r\n"
650+ "EMAIL:fulano@gmail.com\r\n"
651+ "TEL:123456\r\n"
652+ "X-IRC;PROVIDER=irc.freenode.net:myIRC\r\n"
653+ "CLIENTPIDMAP:56183a5b-5da7-49fe-8cf6-9bfd3633bf6d\r\n"
654+ "END:VCARD\r\n"));
655+
656+ QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
657+
658+ // create a contact
659+ QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>)));
660+ bool result = m_manager->saveContact(&contact);
661+ QCOMPARE(result, true);
662+ QTRY_COMPARE(spyContactAdded.count(), 1);
663+
664+ // query contacts;
665+ QContactFilter filter;
666+ QList<QContact> contacts = m_manager->contacts(filter);
667+ QCOMPARE(contacts.size(), 1);
668+
669+ contact = contacts[0];
670+ QList<QContactOnlineAccount> accs = contact.details<QContactOnlineAccount>();
671+ QCOMPARE(accs.size(), 1);
672+
673+ QContactOnlineAccount acc = accs[0];
674+ acc.setAccountUri(QStringLiteral("otherIRC"));
675+ contact.saveDetail(&acc);
676+
677+ QSignalSpy spyContactChanged(m_manager, SIGNAL(contactsChanged(QList<QContactId>)));
678+ result = m_manager->saveContact(&contact);
679+ QCOMPARE(result, true);
680+ QTRY_COMPARE(spyContactChanged.count(), 1);
681+
682+ accs = contact.details<QContactOnlineAccount>();
683+ QCOMPARE(accs.size(), 1);
684+
685+ acc = accs[0];
686+ QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolIrc);
687+ QCOMPARE(acc.accountUri(), QStringLiteral("otherIRC"));
688+ QCOMPARE(acc.serviceProvider(), QStringLiteral("irc.freenode.net"));
689+ }
690+};
691+
692+QTEST_MAIN(ContactAccountTest)
693+
694+#include "contact-accounts-test.moc"
695
696=== modified file 'tests/unittest/vcardparser-test.cpp'
697--- tests/unittest/vcardparser-test.cpp 2015-09-29 14:15:42 +0000
698+++ tests/unittest/vcardparser-test.cpp 2017-03-22 11:39:22 +0000
699@@ -425,6 +425,87 @@
700 QString vcard = VCardParser::contactToVcard(c);
701 QVERIFY(vcard.contains("UID:11"));
702 }
703+
704+ /*
705+ * Test parse a vcard with irc
706+ */
707+ void testVCardWithIrc()
708+ {
709+ QString vcard = QStringLiteral("BEGIN:VCARD\r\n"
710+ "VERSION:3.0\r\n"
711+ "N:Sauro;Dino;da Silva;;\r\n"
712+ "X-IRC;PROVIDER=irc.freenode.net:myIRC\r\n"
713+ "REV:2015-04-14T21:56:56Z(2300)\r\n"
714+ "END:VCARD\r\n");
715+ QContact contact = VCardParser::vcardToContact(vcard);
716+ QList<QContactOnlineAccount> accs = contact.details<QContactOnlineAccount>();
717+ QCOMPARE(accs.size(), 1);
718+
719+ QContactOnlineAccount acc = accs.at(0);
720+ QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolIrc);
721+ QCOMPARE(acc.accountUri(), QStringLiteral("myIRC"));
722+ QCOMPARE(acc.serviceProvider(), QStringLiteral("irc.freenode.net"));
723+
724+ QList<QContactExtendedDetail> exs = contact.details<QContactExtendedDetail>();
725+ QCOMPARE(exs.size(), 1);
726+
727+ QContactExtendedDetail ex = exs.at(0);
728+ QCOMPARE(ex.name(), QStringLiteral("X-IRC"));
729+ QCOMPARE(ex.data().toString(), QStringLiteral("myIRC"));
730+ QCOMPARE(ex.value(QContactExtendedDetail::FieldData+1).toString(), QStringLiteral("irc.freenode.net"));
731+ }
732+
733+ void testContactWithIrc()
734+ {
735+ QContact c = m_contacts[0];
736+
737+ QContactOnlineAccount acc;
738+ acc.setProtocol(QContactOnlineAccount::ProtocolIrc);
739+ acc.setAccountUri(QStringLiteral("myIRC"));
740+ acc.setServiceProvider(QStringLiteral("irc.freenode.net"));
741+ c.saveDetail(&acc);
742+
743+ QString vcard = VCardParser::contactToVcard(c);
744+ QVERIFY(vcard.contains("X-IRC;PROVIDER=irc.freenode.net:myIRC"));
745+ }
746+
747+ /*
748+ * Test parse a vcard with an online account
749+ */
750+ void testVCardWithSkype()
751+ {
752+ QString vcard = QStringLiteral("BEGIN:VCARD\r\n"
753+ "VERSION:3.0\r\n"
754+ "N:Sauro;Dino;da Silva;;\r\n"
755+ "X-SKYPE;PROVIDER=microsoft.com:mySkype\r\n"
756+ "REV:2015-04-14T21:56:56Z(2300)\r\n"
757+ "END:VCARD\r\n");
758+ QContact contact = VCardParser::vcardToContact(vcard);
759+ QList<QContactOnlineAccount> accs = contact.details<QContactOnlineAccount>();
760+ QCOMPARE(accs.size(), 1);
761+
762+ QContactOnlineAccount acc = accs.at(0);
763+ QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolSkype);
764+ QCOMPARE(acc.accountUri(), QStringLiteral("mySkype"));
765+ QCOMPARE(acc.serviceProvider(), QStringLiteral("microsoft.com"));
766+
767+ QList<QContactExtendedDetail> exs = contact.details<QContactExtendedDetail>();
768+ QCOMPARE(exs.size(), 0);
769+ }
770+
771+ void testContactWithSkype()
772+ {
773+ QContact c = m_contacts[0];
774+
775+ QContactOnlineAccount acc;
776+ acc.setProtocol(QContactOnlineAccount::ProtocolSkype);
777+ acc.setAccountUri(QStringLiteral("mySkype"));
778+ acc.setServiceProvider(QStringLiteral("microsoft.com"));
779+ c.saveDetail(&acc);
780+
781+ QString vcard = VCardParser::contactToVcard(c);
782+ QVERIFY(vcard.contains("X-SKYPE;PROVIDER=microsoft.com:mySkype"));
783+ }
784 };
785
786 QTEST_MAIN(VCardParseTest)

Subscribers

People subscribed via source and target branches