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

Proposed by Renato Araujo Oliveira Filho
Status: Approved
Approved by: Tiago Salem Herrmann
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) Approve
system-apps-ci-bot continuous-integration Approve
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

Added missing file.

234. By Renato Araujo Oliveira Filho

Implement support for PROVIDERS save on IRC accounts.

235. By Renato Araujo Oliveira Filho

Implement support for PROVIDER on online accounts.

TODO: Folks EDS does not support it.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tiago Salem Herrmann (tiagosh) wrote :

just one remark.
looks good otherwise.

review: Needs Fixing
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

> just one remark.
> looks good otherwise.

Fixed

236. By Renato Araujo Oliveira Filho

Removed duplicated check.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

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)
Revision history for this message
Tiago Salem Herrmann (tiagosh) wrote :

looks good. thanks.

review: Approve

Unmerged revisions

236. By Renato Araujo Oliveira Filho

Removed duplicated check.

235. By Renato Araujo Oliveira Filho

Implement support for PROVIDER on online accounts.

TODO: Folks EDS does not support it.

234. By Renato Araujo Oliveira Filho

Implement support for PROVIDERS save on IRC accounts.

233. By Renato Araujo Oliveira Filho

Added missing file.

232. By Renato Araujo Oliveira Filho

Fixed contact creation with IRC field.

231. By Renato Araujo Oliveira Filho

Implement support for saving IRC accounts.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-09-23 12:36:13 +0000
+++ CMakeLists.txt 2017-03-22 11:39:22 +0000
@@ -40,7 +40,7 @@
40else()40else()
41 set(EVOLUTION_API_3_17 "1")41 set(EVOLUTION_API_3_17 "1")
42 set(EVOLUTION_ADDRESSBOOK_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook9")42 set(EVOLUTION_ADDRESSBOOK_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook9")
43 set(EVOLUTION_SOURCE_SERVICE_NAME "org.gnome.evolution.dataserver.Sources4")43 set(EVOLUTION_SOURCE_SERVICE_NAME "org.gnome.evolution.dataserver.Sources5")
44endif()44endif()
4545
46set(CMAKE_INCLUDE_CURRENT_DIR ON)46set(CMAKE_INCLUDE_CURRENT_DIR ON)
4747
=== modified file 'common/vcard-parser.cpp'
--- common/vcard-parser.cpp 2015-11-03 23:54:53 +0000
+++ common/vcard-parser.cpp 2017-03-22 11:39:22 +0000
@@ -34,6 +34,20 @@
34using namespace QtVersit;34using namespace QtVersit;
35using namespace QtContacts;35using namespace QtContacts;
3636
37namespace galera
38{
39
40const QString VCardParser::PidMapFieldName = QStringLiteral("CLIENTPIDMAP");
41const QString VCardParser::PidFieldName = QStringLiteral("PID");
42const QString VCardParser::PrefParamName = QStringLiteral("PREF");
43const QString VCardParser::IrremovableFieldName = QStringLiteral("IRREMOVABLE");
44const QString VCardParser::ReadOnlyFieldName = QStringLiteral("READ-ONLY");
45const QString VCardParser::TagFieldName = QStringLiteral("TAG");
46const QString VCardParser::IrcFieldName = QStringLiteral("X-IRC");
47const QString VCardParser::OnlineAccountProviderParamName = QStringLiteral("PROVIDER");
48
49}
50
37namespace51namespace
38{52{
39 class ContactExporterDetailHandler : public QVersitContactExporterDetailHandlerV253 class ContactExporterDetailHandler : public QVersitContactExporterDetailHandlerV2
@@ -67,10 +81,25 @@
67 }81 }
6882
69 if (detail.type() == QContactDetail::TypeExtendedDetail) {83 if (detail.type() == QContactDetail::TypeExtendedDetail) {
70 QVersitProperty prop;84 // Do not translate X-IRC extended details
71 prop.setName(detail.value(QContactExtendedDetail::FieldName).toString());85 if (detail.value(QContactExtendedDetail::FieldName).toString() != galera::VCardParser::IrcFieldName) {
72 prop.setValue(detail.value(QContactExtendedDetail::FieldData).toString());86 QVersitProperty prop;
73 *toBeAdded << prop;87 prop.setName(detail.value(QContactExtendedDetail::FieldName).toString());
88 prop.setValue(detail.value(QContactExtendedDetail::FieldData).toString());
89 *toBeAdded << prop;
90 }
91 }
92
93 // export IRC online account (This is not exported by QtVersit)
94 if (detail.type() == QContactDetail::TypeOnlineAccount) {
95 QContactOnlineAccount acc = static_cast<QContactOnlineAccount>(detail);
96 if (acc.protocol() == QContactOnlineAccount::ProtocolIrc) {
97 QVersitProperty prop;
98 prop.setName(galera::VCardParser::IrcFieldName);
99 prop.setValue(acc.accountUri());
100 // provider will be added by later accout parse
101 *toBeAdded << prop;
102 }
74 }103 }
75104
76 if (toBeAdded->size() == 0) {105 if (toBeAdded->size() == 0) {
@@ -122,6 +151,15 @@
122 }151 }
123 break;152 break;
124 }153 }
154 case QContactDetail::TypeOnlineAccount:
155 {
156 QContactOnlineAccount account = static_cast<QContactOnlineAccount>(detail);
157 QVersitProperty &prop = toBeAdded->last();
158 QMultiHash<QString, QString> params = prop.parameters();
159 params.insert(galera::VCardParser::OnlineAccountProviderParamName, account.serviceProvider());
160 prop.setParameters(params);
161 break;
162 }
125 default:163 default:
126 break;164 break;
127 }165 }
@@ -170,9 +208,19 @@
170 }208 }
171209
172 if (!*alreadyProcessed && (property.name().startsWith("X-"))) {210 if (!*alreadyProcessed && (property.name().startsWith("X-"))) {
211 // IRC FIELDS
212 if (property.name() == galera::VCardParser::IrcFieldName) {
213 QContactOnlineAccount acc;
214 acc.setProtocol(QContactOnlineAccount::ProtocolIrc);
215 acc.setAccountUri(property.value());
216 acc.setServiceProvider(property.parameters().value(galera::VCardParser::OnlineAccountProviderParamName));
217 *updatedDetails << acc;
218 }
173 QContactExtendedDetail xDet;219 QContactExtendedDetail xDet;
174 xDet.setName(property.name());220 xDet.setName(property.name());
175 xDet.setData(property.value<QString>());221 xDet.setData(property.value<QString>());
222 xDet.setValue(QContactExtendedDetail::FieldData + 1, property.parameters().value(galera::VCardParser::OnlineAccountProviderParamName));
223
176 *updatedDetails << xDet;224 *updatedDetails << xDet;
177 *alreadyProcessed = true;225 *alreadyProcessed = true;
178 }226 }
@@ -181,6 +229,7 @@
181 return;229 return;
182 }230 }
183231
232
184 QString pid = property.parameters().value(galera::VCardParser::PidFieldName);233 QString pid = property.parameters().value(galera::VCardParser::PidFieldName);
185 if (!pid.isEmpty()) {234 if (!pid.isEmpty()) {
186 QContactDetail &det = updatedDetails->last();235 QContactDetail &det = updatedDetails->last();
@@ -230,6 +279,14 @@
230 }279 }
231 break;280 break;
232 }281 }
282 case QContactDetail::TypeOnlineAccount:
283 {
284 // Fill provider for online accounts
285 QString provider = property.parameters().value(galera::VCardParser::OnlineAccountProviderParamName);
286 if (!provider.isEmpty())
287 det.setValue(QContactOnlineAccount::FieldServiceProvider, provider);
288 break;
289 }
233 default:290 default:
234 break;291 break;
235 }292 }
@@ -270,13 +327,6 @@
270namespace galera327namespace galera
271{328{
272329
273const QString VCardParser::PidMapFieldName = QStringLiteral("CLIENTPIDMAP");
274const QString VCardParser::PidFieldName = QStringLiteral("PID");
275const QString VCardParser::PrefParamName = QStringLiteral("PREF");
276const QString VCardParser::IrremovableFieldName = QStringLiteral("IRREMOVABLE");
277const QString VCardParser::ReadOnlyFieldName = QStringLiteral("READ-ONLY");
278const QString VCardParser::TagFieldName = QStringLiteral("TAG");
279
280static QMap<QtContacts::QContactDetail::DetailType, QString> prefferedActions()330static QMap<QtContacts::QContactDetail::DetailType, QString> prefferedActions()
281{331{
282 QMap<QtContacts::QContactDetail::DetailType, QString> values;332 QMap<QtContacts::QContactDetail::DetailType, QString> values;
283333
=== modified file 'common/vcard-parser.h'
--- common/vcard-parser.h 2015-10-28 14:28:11 +0000
+++ common/vcard-parser.h 2017-03-22 11:39:22 +0000
@@ -57,6 +57,8 @@
57 static const QString IrremovableFieldName;57 static const QString IrremovableFieldName;
58 static const QString ReadOnlyFieldName;58 static const QString ReadOnlyFieldName;
59 static const QString TagFieldName;59 static const QString TagFieldName;
60 static const QString IrcFieldName;
61 static const QString OnlineAccountProviderParamName;
60 static const QMap<QtContacts::QContactDetail::DetailType, QString> PreferredActionNames;62 static const QMap<QtContacts::QContactDetail::DetailType, QString> PreferredActionNames;
6163
62 static QtContacts::QContact vcardToContact(const QString &vcard);64 static QtContacts::QContact vcardToContact(const QString &vcard);
6365
=== modified file 'lib/detail-context-parser.cpp'
--- lib/detail-context-parser.cpp 2016-09-20 13:25:21 +0000
+++ lib/detail-context-parser.cpp 2017-03-22 11:39:22 +0000
@@ -218,10 +218,13 @@
218218
219 while (gee_iterator_next (siter)) {219 while (gee_iterator_next (siter)) {
220 char *parameter = (char*) gee_iterator_get(siter);220 char *parameter = (char*) gee_iterator_get(siter);
221 if (QString::fromUtf8(parameter).toUpper() == VCardParser::PrefParamName) {221 const QString parameterName = QString::fromUtf8(parameter).toUpper();
222 if (parameterName == VCardParser::PrefParamName) {
222 params << "pref";223 params << "pref";
223 continue;224 continue;
224 } else if (QString::fromUtf8(parameter) != "type") {225 } else if (parameterName == VCardParser::OnlineAccountProviderParamName) {
226
227 } else if (parameterName != "TYPE") {
225 if (!whiteList.contains(QString::fromUtf8(parameter))) {228 if (!whiteList.contains(QString::fromUtf8(parameter))) {
226 qDebug() << "not supported field details" << parameter;229 qDebug() << "not supported field details" << parameter;
227 // FIXME: check what to do with other parameters230 // FIXME: check what to do with other parameters
@@ -389,7 +392,7 @@
389 Q_FOREACH(const QString &param, parameters) {392 Q_FOREACH(const QString &param, parameters) {
390 if (map.contains(param.toLower())) {393 if (map.contains(param.toLower())) {
391 values << map[param.toLower()];394 values << map[param.toLower()];
392 } else {395 } else {
393 qWarning() << "invalid IM subtype" << param;396 qWarning() << "invalid IM subtype" << param;
394 }397 }
395 }398 }
396399
=== modified file 'lib/gee-utils.cpp'
--- lib/gee-utils.cpp 2013-10-30 19:07:49 +0000
+++ lib/gee-utils.cpp 2017-03-22 11:39:22 +0000
@@ -19,6 +19,7 @@
19#include "gee-utils.h"19#include "gee-utils.h"
2020
21#include <QDebug>21#include <QDebug>
22#include <QPair>
2223
23GValue* GeeUtils::gValueSliceNew(GType type)24GValue* GeeUtils::gValueSliceNew(GType type)
24{25{
@@ -39,7 +40,7 @@
39 g_hash_table_insert(details, (gpointer) folks_persona_store_detail_key(key), value);40 g_hash_table_insert(details, (gpointer) folks_persona_store_detail_key(key), value);
40}41}
4142
42GValue* GeeUtils::asvSetStrNew(QMultiMap<QString, QString> providerUidMap)43GValue* GeeUtils::asvSetStrNew(QMultiMap<QString, QPair<QString, QString> > providerUidMap)
43{44{
44 GeeMultiMap *hashSet = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);45 GeeMultiMap *hashSet = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);
45 GValue *retval = gValueSliceNew (G_TYPE_OBJECT);46 GValue *retval = gValueSliceNew (G_TYPE_OBJECT);
@@ -47,11 +48,16 @@
4748
48 QList<QString> keys = providerUidMap.keys();49 QList<QString> keys = providerUidMap.keys();
49 Q_FOREACH(const QString& key, keys) {50 Q_FOREACH(const QString& key, keys) {
50 QList<QString> values = providerUidMap.values(key);51 Q_FOREACH(const auto &value, providerUidMap.values(key)) {
51 Q_FOREACH(const QString& value, values) {
52 FolksImFieldDetails *imfd;52 FolksImFieldDetails *imfd;
53 const QString &accountUri = value.first;
54 const QString &accountProvider = value.second;
5355
54 imfd = folks_im_field_details_new (value.toUtf8().data(), NULL);56 imfd = folks_im_field_details_new (accountUri.toUtf8().data(), NULL);
57 if (!accountProvider.isEmpty()) {
58 folks_abstract_field_details_add_parameter(FOLKS_ABSTRACT_FIELD_DETAILS(imfd),
59 "PROVIDER", accountProvider.toUtf8().data());
60 }
5561
56 gee_multi_map_set(hashSet,62 gee_multi_map_set(hashSet,
57 key.toUtf8().data(),63 key.toUtf8().data(),
5864
=== modified file 'lib/gee-utils.h'
--- lib/gee-utils.h 2013-10-30 19:07:49 +0000
+++ lib/gee-utils.h 2017-03-22 11:39:22 +0000
@@ -84,7 +84,7 @@
84 static GValue* gValueSliceNew(GType type);84 static GValue* gValueSliceNew(GType type);
85 static void gValueSliceFree(GValue *value);85 static void gValueSliceFree(GValue *value);
86 static void personaDetailsInsert(GHashTable *details, FolksPersonaDetail key, gpointer value);86 static void personaDetailsInsert(GHashTable *details, FolksPersonaDetail key, gpointer value);
87 static GValue* asvSetStrNew(QMultiMap<QString, QString> providerUidMap);87 static GValue* asvSetStrNew(QMultiMap<QString, QPair<QString, QString> > providerUidMap);
88}; // class88}; // class
8989
90#endif90#endif
9191
=== modified file 'lib/qindividual.cpp'
--- lib/qindividual.cpp 2016-05-04 17:56:15 +0000
+++ lib/qindividual.cpp 2017-03-22 11:39:22 +0000
@@ -28,6 +28,7 @@
28#include <libebook/libebook.h>28#include <libebook/libebook.h>
2929
30#include <QtCore/QMutexLocker>30#include <QtCore/QMutexLocker>
31#include <QtCore/QPair>
3132
32#include <QtVersit/QVersitDocument>33#include <QtVersit/QVersitDocument>
33#include <QtVersit/QVersitProperty>34#include <QtVersit/QVersitProperty>
@@ -64,6 +65,7 @@
64#define X_GROUP_ID "X-GROUP-ID"65#define X_GROUP_ID "X-GROUP-ID"
65#define X_DELETED_AT "X-DELETED-AT"66#define X_DELETED_AT "X-DELETED-AT"
66#define X_AVATAR_REV "X-AVATAR-REV"67#define X_AVATAR_REV "X-AVATAR-REV"
68#define X_IRC_ACCOUNT "X-IRC"
6769
68namespace70namespace
69{71{
@@ -100,12 +102,16 @@
100 } else if(g_type == FOLKS_TYPE_WEB_SERVICE_FIELD_DETAILS) {102 } else if(g_type == FOLKS_TYPE_WEB_SERVICE_FIELD_DETAILS) {
101 fieldDetails = FOLKS_ABSTRACT_FIELD_DETAILS (103 fieldDetails = FOLKS_ABSTRACT_FIELD_DETAILS (
102 folks_web_service_field_details_new(v_string, NULL));104 folks_web_service_field_details_new(v_string, NULL));
105 } else if(g_type == FOLKS_TYPE_EXTENDED_FIELD_DETAILS) {
106 fieldDetails = FOLKS_ABSTRACT_FIELD_DETAILS (
107 folks_extended_field_details_new(v_string, NULL));
103 }108 }
104109
105 if (fieldDetails == NULL) {110 if (fieldDetails == NULL) {
106 qWarning() << "Invalid fieldDetails type" << g_type;111 qWarning() << "Invalid fieldDetails type" << g_type;
107 } else {112 } else {
108 galera::DetailContextParser::parseContext(fieldDetails, detail, ispreferred);113 galera::DetailContextParser::parseContext(fieldDetails, detail, ispreferred);
114
109 gee_collection_add(collection, fieldDetails);115 gee_collection_add(collection, fieldDetails);
110116
111 g_object_unref(fieldDetails);117 g_object_unref(fieldDetails);
@@ -151,6 +157,7 @@
151{157{
152bool QIndividual::m_autoLink = false;158bool QIndividual::m_autoLink = false;
153QStringList QIndividual::m_supportedExtendedDetails;159QStringList QIndividual::m_supportedExtendedDetails;
160QList<QContactOnlineAccount::Protocol> QIndividual::m_protocolBlackList;
154161
155QIndividual::QIndividual(FolksIndividual *individual, FolksIndividualAggregator *aggregator)162QIndividual::QIndividual(FolksIndividual *individual, FolksIndividualAggregator *aggregator)
156 : m_individual(0),163 : m_individual(0),
@@ -164,7 +171,8 @@
164 << X_REMOTE_ID171 << X_REMOTE_ID
165 << X_GOOGLE_ETAG172 << X_GOOGLE_ETAG
166 << X_GROUP_ID173 << X_GROUP_ID
167 << X_AVATAR_REV;174 << X_AVATAR_REV
175 << X_IRC_ACCOUNT;
168 }176 }
169 setIndividual(individual);177 setIndividual(individual);
170}178}
@@ -689,6 +697,20 @@
689 int protocolId = DetailContextParser::accountProtocolFromString(qStringFromGChar(key));697 int protocolId = DetailContextParser::accountProtocolFromString(qStringFromGChar(key));
690 account.setProtocol(static_cast<QContactOnlineAccount::Protocol>(protocolId));698 account.setProtocol(static_cast<QContactOnlineAccount::Protocol>(protocolId));
691699
700 // provider
701 GeeCollection *providers = folks_abstract_field_details_get_parameter_values(fd, "PROVIDER");
702 if (providers) {
703 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE (providers));
704 if (iter) {
705 char *provider = (char*) gee_iterator_get(iter);
706 if (strlen(provider) > 0) {
707 account.setServiceProvider(QString::fromUtf8(provider));
708 }
709 g_free(provider);
710 g_object_unref(iter);
711 }
712 }
713
692 bool isPref = false;714 bool isPref = false;
693 DetailContextParser::parseParameters(account, fd, &isPref);715 DetailContextParser::parseParameters(account, fd, &isPref);
694 account.setDetailUri(QString("%1.%2").arg(index).arg(fieldIndex++));716 account.setDetailUri(QString("%1.%2").arg(index).arg(fieldIndex++));
@@ -765,12 +787,24 @@
765 EVCardAttribute *attr = e_vcard_get_attribute(E_VCARD(c), xDetName.toUtf8().constData());787 EVCardAttribute *attr = e_vcard_get_attribute(E_VCARD(c), xDetName.toUtf8().constData());
766 if (attr) {788 if (attr) {
767 GString *attrValue = e_vcard_attribute_get_value_decoded(attr);789 GString *attrValue = e_vcard_attribute_get_value_decoded(attr);
768 QContactExtendedDetail xDet;790
769 xDet.setName(xDetName);791 if (xDetName == X_IRC_ACCOUNT) {
770 xDet.setData(QString::fromUtf8(attrValue->str));792 QContactOnlineAccount acc;
771 xDet.setDetailUri(QString("%1.1").arg(index));793 acc.setProtocol(QContactOnlineAccount::ProtocolIrc);
772 g_string_free(attrValue, true);794 acc.setAccountUri(QString::fromUtf8(attrValue->str));
773 result << xDet;795 GList *param = e_vcard_attribute_get_param(attr, "PROVIDER");
796 if (param)
797 acc.setServiceProvider(QString::fromUtf8(static_cast<gchar*>(param->data)));
798
799 result << acc;
800 } else {
801 QContactExtendedDetail xDet;
802 xDet.setName(xDetName);
803 xDet.setData(QString::fromUtf8(attrValue->str));
804 xDet.setDetailUri(QString("%1.1").arg(index));
805 g_string_free(attrValue, true);
806 result << xDet;
807 }
774 }808 }
775 }809 }
776810
@@ -1559,11 +1593,20 @@
1559 return details;1593 return details;
1560 }1594 }
15611595
1562 QMultiMap<QString, QString> providerUidMap;1596 if (m_protocolBlackList.isEmpty()) {
1597 m_protocolBlackList << QContactOnlineAccount::ProtocolIrc;
1598 }
1599
1600 QMultiMap<QString, QPair<QString,QString> > providerUidMap;
1563 Q_FOREACH(const QContactDetail &detail, cDetails) {1601 Q_FOREACH(const QContactDetail &detail, cDetails) {
1564 QContactOnlineAccount account = static_cast<QContactOnlineAccount>(detail);1602 QContactOnlineAccount account = static_cast<QContactOnlineAccount>(detail);
1603 if (m_protocolBlackList.contains(account.protocol())) {
1604 continue;
1605 }
1606
1565 if (!account.isEmpty()) {1607 if (!account.isEmpty()) {
1566 providerUidMap.insert(DetailContextParser::accountProtocolName(account.protocol()), account.accountUri());1608 providerUidMap.insert(DetailContextParser::accountProtocolName(account.protocol()),
1609 qMakePair(account.accountUri(), account.serviceProvider()));
1567 }1610 }
1568 }1611 }
15691612
@@ -1789,6 +1832,17 @@
1789 }1832 }
17901833
1791 attr = e_vcard_attribute_new("", xd.name().toUtf8().constData());1834 attr = e_vcard_attribute_new("", xd.name().toUtf8().constData());
1835
1836 // Special cases
1837 if (xd.name() == X_IRC_ACCOUNT) {
1838 // IRC - save provider
1839 QString provider = xd.value(QContactExtendedDetail::FieldData + 1).toString();
1840 if (!provider.isEmpty()) {
1841 EVCardAttributeParam * param = e_vcard_attribute_param_new("PROVIDER");
1842 e_vcard_attribute_add_param_with_value(attr, param, provider.toUtf8().constData());
1843 }
1844 }
1845
1792 e_vcard_add_attribute_with_value(E_VCARD(c),1846 e_vcard_add_attribute_with_value(E_VCARD(c),
1793 attr,1847 attr,
1794 xd.data().toString().toUtf8().constData());1848 xd.data().toString().toUtf8().constData());
@@ -1824,6 +1878,11 @@
1824 return m_autoLink;1878 return m_autoLink;
1825}1879}
18261880
1881QList<QContactOnlineAccount::Protocol> QIndividual::protocolBlackList()
1882{
1883 return m_protocolBlackList;
1884}
1885
1827FolksPersona* QIndividual::primaryPersona()1886FolksPersona* QIndividual::primaryPersona()
1828{1887{
1829 if (m_personas.size() > 0) {1888 if (m_personas.size() > 0) {
18301889
=== modified file 'lib/qindividual.h'
--- lib/qindividual.h 2015-09-04 15:01:52 +0000
+++ lib/qindividual.h 2017-03-22 11:39:22 +0000
@@ -29,6 +29,7 @@
2929
30#include <QtContacts/QContact>30#include <QtContacts/QContact>
31#include <QtContacts/QContactDetail>31#include <QtContacts/QContactDetail>
32#include <QtContacts/QContactOnlineAccount>
3233
33#include <folks/folks.h>34#include <folks/folks.h>
3435
@@ -70,6 +71,7 @@
70 // enable or disable auto-link71 // enable or disable auto-link
71 static void enableAutoLink(bool flag);72 static void enableAutoLink(bool flag);
72 static bool autoLinkEnabled();73 static bool autoLinkEnabled();
74 static QList<QtContacts::QContactOnlineAccount::Protocol> protocolBlackList();
7375
74private:76private:
75 FolksIndividual *m_individual;77 FolksIndividual *m_individual;
@@ -86,6 +88,7 @@
86 bool m_visible;88 bool m_visible;
87 static bool m_autoLink;89 static bool m_autoLink;
88 static QStringList m_supportedExtendedDetails;90 static QStringList m_supportedExtendedDetails;
91 static QList<QtContacts::QContactOnlineAccount::Protocol> m_protocolBlackList;
8992
90 QIndividual();93 QIndividual();
91 QIndividual(const QIndividual &);94 QIndividual(const QIndividual &);
@@ -144,10 +147,6 @@
144147
145 static void avatarCacheStoreDone(GObject *source, GAsyncResult *result, gpointer data);148 static void avatarCacheStoreDone(GObject *source, GAsyncResult *result, gpointer data);
146149
147 // create
148 void createPersonaFromDetails(QList<QtContacts::QContactDetail> detail, ParseDetailsFunc parseFunc, void *data) const;
149 static void createPersonaForDetailDone(GObject *detail, GAsyncResult *result, gpointer userdata);
150
151 // translate details150 // translate details
152 static GHashTable *parseFullNameDetails (GHashTable *details,151 static GHashTable *parseFullNameDetails (GHashTable *details,
153 const QList<QtContacts::QContactDetail> &cDetails,152 const QList<QtContacts::QContactDetail> &cDetails,
154153
=== modified file 'lib/update-contact-request.cpp'
--- lib/update-contact-request.cpp 2015-09-24 17:47:49 +0000
+++ lib/update-contact-request.cpp 2017-03-22 11:39:22 +0000
@@ -229,6 +229,7 @@
229 return detailsFromPersona(m_originalContact, type, persona, false, pref);229 return detailsFromPersona(m_originalContact, type, persona, false, pref);
230}230}
231231
232
232QList<QtContacts::QContactDetail> UpdateContactRequest::detailsFromPersona(QtContacts::QContactDetail::DetailType type,233QList<QtContacts::QContactDetail> UpdateContactRequest::detailsFromPersona(QtContacts::QContactDetail::DetailType type,
233 int persona,234 int persona,
234 QtContacts::QContactDetail *pref) const235 QtContacts::QContactDetail *pref) const
@@ -570,6 +571,27 @@
570 m_currentPersonaIndex,571 m_currentPersonaIndex,
571 &prefDetail);572 &prefDetail);
572573
574 // remove blacklisted protocols to avoid try to save it
575 QList<QtContacts::QContactDetail>::iterator i = originalDetails.begin();
576 while (i != originalDetails.end())
577 {
578 if (QIndividual::protocolBlackList().contains(static_cast<QtContacts::QContactOnlineAccount>(*i).protocol())) {
579 originalDetails.erase(i++);
580 } else {
581 ++i;
582 }
583 }
584
585 i = newDetails.begin();
586 while (i != newDetails.end())
587 {
588 if (QIndividual::protocolBlackList().contains(static_cast<QtContacts::QContactOnlineAccount>(*i).protocol())) {
589 newDetails.erase(i++);
590 } else {
591 ++i;
592 }
593 }
594
573 if (m_currentPersona &&595 if (m_currentPersona &&
574 FOLKS_IS_IM_DETAILS(m_currentPersona) &&596 FOLKS_IS_IM_DETAILS(m_currentPersona) &&
575 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {597 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
@@ -585,6 +607,10 @@
585 field = folks_im_field_details_new(accountUri.constData(), NULL);607 field = folks_im_field_details_new(accountUri.constData(), NULL);
586 DetailContextParser::parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(field), account, account == prefDetail);608 DetailContextParser::parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(field), account, account == prefDetail);
587609
610 if (!account.serviceProvider().isEmpty()) {
611 folks_abstract_field_details_add_parameter(FOLKS_ABSTRACT_FIELD_DETAILS(field),
612 "PROVIDER", account.serviceProvider().toUtf8().data());
613 }
588 QString protocolName(DetailContextParser::accountProtocolName(account.protocol()));614 QString protocolName(DetailContextParser::accountProtocolName(account.protocol()));
589 QByteArray protocolNameUtf8 = protocolName.toUtf8();615 QByteArray protocolNameUtf8 = protocolName.toUtf8();
590 gee_multi_map_set(imMap, protocolNameUtf8.constData(), field);616 gee_multi_map_set(imMap, protocolNameUtf8.constData(), field);
@@ -769,6 +795,8 @@
769{795{
770 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeExtendedDetail, m_currentPersonaIndex, 0);796 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeExtendedDetail, m_currentPersonaIndex, 0);
771 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeExtendedDetail, m_currentPersonaIndex, 0);797 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeExtendedDetail, m_currentPersonaIndex, 0);
798
799
772 if (m_currentPersona &&800 if (m_currentPersona &&
773 !isEqual(originalDetails, newDetails)) {801 !isEqual(originalDetails, newDetails)) {
774 qDebug() << "Extended details diff";802 qDebug() << "Extended details diff";
775803
=== modified file 'tests/unittest/CMakeLists.txt'
--- tests/unittest/CMakeLists.txt 2015-09-29 14:15:42 +0000
+++ tests/unittest/CMakeLists.txt 2017-03-22 11:39:22 +0000
@@ -116,6 +116,7 @@
116 declare_eds_test(contact-collection-test)116 declare_eds_test(contact-collection-test)
117 declare_eds_test(contact-timestamp-test)117 declare_eds_test(contact-timestamp-test)
118 declare_eds_test(contact-avatar-test)118 declare_eds_test(contact-avatar-test)
119 declare_eds_test(contact-accounts-test)
119elseif()120elseif()
120 message(STATUS "DBus test runner not found. Some tests will be disabled")121 message(STATUS "DBus test runner not found. Some tests will be disabled")
121endif()122endif()
122123
=== added file 'tests/unittest/contact-accounts-test.cpp'
--- tests/unittest/contact-accounts-test.cpp 1970-01-01 00:00:00 +0000
+++ tests/unittest/contact-accounts-test.cpp 2017-03-22 11:39:22 +0000
@@ -0,0 +1,182 @@
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This file is part of contact-service-app.
5 *
6 * contact-service-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * contact-service-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <QObject>
20#include <QtTest>
21#include <QDebug>
22#include <QtContacts>
23
24#include "config.h"
25#include "common/vcard-parser.h"
26#include "base-eds-test.h"
27
28using namespace QtContacts;
29
30class ContactAccountTest : public QObject, public BaseEDSTest
31{
32 Q_OBJECT
33private:
34
35
36private Q_SLOTS:
37 void initTestCase()
38 {
39 BaseEDSTest::initTestCaseImpl();
40 }
41
42 void cleanupTestCase()
43 {
44 BaseEDSTest::cleanupTestCaseImpl();
45 }
46
47 void init()
48 {
49 BaseEDSTest::initImpl();
50 }
51
52 void cleanup()
53 {
54 QList<QContactId> contacts = m_manager->contactIds();
55 m_manager->removeContacts(contacts);
56 BaseEDSTest::cleanupImpl();
57 }
58
59 void testCreateIrcAccount()
60 {
61 QContact contact = galera::VCardParser::vcardToContact(QString("BEGIN:VCARD\r\n"
62 "VERSION:3.0\r\n"
63 "X-REMOTE-ID:1dd7d51a1518626a\r\n"
64 "N:;Fulano;;;\r\n"
65 "EMAIL:fulano@gmail.com\r\n"
66 "TEL:123456\r\n"
67 "X-IRC;PROVIDER=irc.freenode.net:myIRC\r\n"
68 "CLIENTPIDMAP:56183a5b-5da7-49fe-8cf6-9bfd3633bf6d\r\n"
69 "END:VCARD\r\n"));
70
71 QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
72
73 // create a contact
74 QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>)));
75 bool result = m_manager->saveContact(&contact);
76 QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
77 QCOMPARE(result, true);
78 QTRY_COMPARE(spyContactAdded.count(), 1);
79
80 // query contacts;
81 QContactFilter filter;
82 QList<QContact> contacts = m_manager->contacts(filter);
83 QCOMPARE(contacts.size(), 1);
84
85 QList<QContactOnlineAccount> accs = contacts[0].details<QContactOnlineAccount>();
86 QCOMPARE(accs.size(), 1);
87
88 QContactOnlineAccount acc = accs[0];
89 QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolIrc);
90 QCOMPARE(acc.accountUri(), QStringLiteral("myIRC"));
91 QCOMPARE(acc.serviceProvider(), QStringLiteral("irc.freenode.net"));
92 }
93
94 //TODO: implement support for provider in well-know accounts
95 /*
96 void testCreateSkypeAccount()
97 {
98 QContact contact = galera::VCardParser::vcardToContact(QString("BEGIN:VCARD\r\n"
99 "VERSION:3.0\r\n"
100 "X-REMOTE-ID:1dd7d51a1518626a\r\n"
101 "N:;Fulano;;;\r\n"
102 "EMAIL:fulano@gmail.com\r\n"
103 "TEL:123456\r\n"
104 "X-SKYPE;PROVIDER=skype.net:mySkype\r\n"
105 "CLIENTPIDMAP:56183a5b-5da7-49fe-8cf6-9bfd3633bf6d\r\n"
106 "END:VCARD\r\n"));
107
108 QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
109
110 // create a contact
111 QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>)));
112 bool result = m_manager->saveContact(&contact);
113 QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
114 QCOMPARE(result, true);
115 QTRY_COMPARE(spyContactAdded.count(), 1);
116
117 // query contacts;
118 QContactFilter filter;
119 QList<QContact> contacts = m_manager->contacts(filter);
120 QCOMPARE(contacts.size(), 1);
121
122 QList<QContactOnlineAccount> accs = contacts[0].details<QContactOnlineAccount>();
123 QCOMPARE(accs.size(), 1);
124
125 QContactOnlineAccount acc = accs[0];
126 QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolSkype);
127 QCOMPARE(acc.accountUri(), QStringLiteral("mySkype"));
128 QCOMPARE(acc.serviceProvider(), QStringLiteral("skype.net"));
129 }
130 */
131
132 void testModifyIrcAccount()
133 {
134 QContact contact = galera::VCardParser::vcardToContact(QString("BEGIN:VCARD\r\n"
135 "VERSION:3.0\r\n"
136 "X-REMOTE-ID:1dd7d51a1518626a\r\n"
137 "N:;Fulano;;;\r\n"
138 "EMAIL:fulano@gmail.com\r\n"
139 "TEL:123456\r\n"
140 "X-IRC;PROVIDER=irc.freenode.net:myIRC\r\n"
141 "CLIENTPIDMAP:56183a5b-5da7-49fe-8cf6-9bfd3633bf6d\r\n"
142 "END:VCARD\r\n"));
143
144 QCOMPARE(contact.details<QContactOnlineAccount>().size(), 1);
145
146 // create a contact
147 QSignalSpy spyContactAdded(m_manager, SIGNAL(contactsAdded(QList<QContactId>)));
148 bool result = m_manager->saveContact(&contact);
149 QCOMPARE(result, true);
150 QTRY_COMPARE(spyContactAdded.count(), 1);
151
152 // query contacts;
153 QContactFilter filter;
154 QList<QContact> contacts = m_manager->contacts(filter);
155 QCOMPARE(contacts.size(), 1);
156
157 contact = contacts[0];
158 QList<QContactOnlineAccount> accs = contact.details<QContactOnlineAccount>();
159 QCOMPARE(accs.size(), 1);
160
161 QContactOnlineAccount acc = accs[0];
162 acc.setAccountUri(QStringLiteral("otherIRC"));
163 contact.saveDetail(&acc);
164
165 QSignalSpy spyContactChanged(m_manager, SIGNAL(contactsChanged(QList<QContactId>)));
166 result = m_manager->saveContact(&contact);
167 QCOMPARE(result, true);
168 QTRY_COMPARE(spyContactChanged.count(), 1);
169
170 accs = contact.details<QContactOnlineAccount>();
171 QCOMPARE(accs.size(), 1);
172
173 acc = accs[0];
174 QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolIrc);
175 QCOMPARE(acc.accountUri(), QStringLiteral("otherIRC"));
176 QCOMPARE(acc.serviceProvider(), QStringLiteral("irc.freenode.net"));
177 }
178};
179
180QTEST_MAIN(ContactAccountTest)
181
182#include "contact-accounts-test.moc"
0183
=== modified file 'tests/unittest/vcardparser-test.cpp'
--- tests/unittest/vcardparser-test.cpp 2015-09-29 14:15:42 +0000
+++ tests/unittest/vcardparser-test.cpp 2017-03-22 11:39:22 +0000
@@ -425,6 +425,87 @@
425 QString vcard = VCardParser::contactToVcard(c);425 QString vcard = VCardParser::contactToVcard(c);
426 QVERIFY(vcard.contains("UID:11"));426 QVERIFY(vcard.contains("UID:11"));
427 }427 }
428
429 /*
430 * Test parse a vcard with irc
431 */
432 void testVCardWithIrc()
433 {
434 QString vcard = QStringLiteral("BEGIN:VCARD\r\n"
435 "VERSION:3.0\r\n"
436 "N:Sauro;Dino;da Silva;;\r\n"
437 "X-IRC;PROVIDER=irc.freenode.net:myIRC\r\n"
438 "REV:2015-04-14T21:56:56Z(2300)\r\n"
439 "END:VCARD\r\n");
440 QContact contact = VCardParser::vcardToContact(vcard);
441 QList<QContactOnlineAccount> accs = contact.details<QContactOnlineAccount>();
442 QCOMPARE(accs.size(), 1);
443
444 QContactOnlineAccount acc = accs.at(0);
445 QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolIrc);
446 QCOMPARE(acc.accountUri(), QStringLiteral("myIRC"));
447 QCOMPARE(acc.serviceProvider(), QStringLiteral("irc.freenode.net"));
448
449 QList<QContactExtendedDetail> exs = contact.details<QContactExtendedDetail>();
450 QCOMPARE(exs.size(), 1);
451
452 QContactExtendedDetail ex = exs.at(0);
453 QCOMPARE(ex.name(), QStringLiteral("X-IRC"));
454 QCOMPARE(ex.data().toString(), QStringLiteral("myIRC"));
455 QCOMPARE(ex.value(QContactExtendedDetail::FieldData+1).toString(), QStringLiteral("irc.freenode.net"));
456 }
457
458 void testContactWithIrc()
459 {
460 QContact c = m_contacts[0];
461
462 QContactOnlineAccount acc;
463 acc.setProtocol(QContactOnlineAccount::ProtocolIrc);
464 acc.setAccountUri(QStringLiteral("myIRC"));
465 acc.setServiceProvider(QStringLiteral("irc.freenode.net"));
466 c.saveDetail(&acc);
467
468 QString vcard = VCardParser::contactToVcard(c);
469 QVERIFY(vcard.contains("X-IRC;PROVIDER=irc.freenode.net:myIRC"));
470 }
471
472 /*
473 * Test parse a vcard with an online account
474 */
475 void testVCardWithSkype()
476 {
477 QString vcard = QStringLiteral("BEGIN:VCARD\r\n"
478 "VERSION:3.0\r\n"
479 "N:Sauro;Dino;da Silva;;\r\n"
480 "X-SKYPE;PROVIDER=microsoft.com:mySkype\r\n"
481 "REV:2015-04-14T21:56:56Z(2300)\r\n"
482 "END:VCARD\r\n");
483 QContact contact = VCardParser::vcardToContact(vcard);
484 QList<QContactOnlineAccount> accs = contact.details<QContactOnlineAccount>();
485 QCOMPARE(accs.size(), 1);
486
487 QContactOnlineAccount acc = accs.at(0);
488 QCOMPARE(acc.protocol(), QContactOnlineAccount::ProtocolSkype);
489 QCOMPARE(acc.accountUri(), QStringLiteral("mySkype"));
490 QCOMPARE(acc.serviceProvider(), QStringLiteral("microsoft.com"));
491
492 QList<QContactExtendedDetail> exs = contact.details<QContactExtendedDetail>();
493 QCOMPARE(exs.size(), 0);
494 }
495
496 void testContactWithSkype()
497 {
498 QContact c = m_contacts[0];
499
500 QContactOnlineAccount acc;
501 acc.setProtocol(QContactOnlineAccount::ProtocolSkype);
502 acc.setAccountUri(QStringLiteral("mySkype"));
503 acc.setServiceProvider(QStringLiteral("microsoft.com"));
504 c.saveDetail(&acc);
505
506 QString vcard = VCardParser::contactToVcard(c);
507 QVERIFY(vcard.contains("X-SKYPE;PROVIDER=microsoft.com:mySkype"));
508 }
428};509};
429510
430QTEST_MAIN(VCardParseTest)511QTEST_MAIN(VCardParseTest)

Subscribers

People subscribed via source and target branches