Merge lp:~renatofilho/address-book-service/create-source into lp:address-book-service

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~renatofilho/address-book-service/create-source
Merge into: lp:address-book-service
Diff against target: 2318 lines (+905/-330)
22 files modified
3rd_party/folks/dummy/lib/dummy-full-persona.vala (+12/-1)
3rd_party/folks/dummy/lib/dummy-persona.vala (+33/-3)
CMakeLists.txt (+1/-0)
debian/changelog (+16/-0)
debian/control (+1/-0)
lib/CMakeLists.txt (+2/-0)
lib/addressbook-adaptor.cpp (+10/-0)
lib/addressbook-adaptor.h (+6/-0)
lib/addressbook.cpp (+175/-72)
lib/addressbook.h (+9/-3)
lib/contacts-map.cpp (+44/-22)
lib/contacts-map.h (+9/-3)
lib/qindividual.cpp (+181/-137)
lib/qindividual.h (+19/-6)
lib/update-contact-request.cpp (+173/-72)
lib/update-contact-request.h (+17/-7)
lib/view.cpp (+3/-1)
tests/unittest/CMakeLists.txt (+3/-0)
tests/unittest/addressbook-test.cpp (+42/-2)
tests/unittest/contact-link-test.cpp (+100/-0)
tests/unittest/dummy-backend.cpp (+36/-1)
tests/unittest/dummy-backend.h (+13/-0)
To merge this branch: bzr merge lp:~renatofilho/address-book-service/create-source
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Ubuntu Phablet Team Pending
Review via email: mp+206826@code.launchpad.net

This proposal has been superseded by a proposal from 2014-02-18.

Commit message

Implemented createSource functionality.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
100. By Renato Araujo Oliveira Filho

Merged parent branch.

101. By Renato Araujo Oliveira Filho

Merged parent branch.

102. By Renato Araujo Oliveira Filho

Merged mainline.

103. By Renato Araujo Oliveira Filho

Attempt to fix power pc build

104. By Renato Araujo Oliveira Filho

Attempt to fix powerpc tests.

105. By Renato Araujo Oliveira Filho

Attempt to fix powerpc tests.

106. By Renato Araujo Oliveira Filho

Moved DirtyContactsNotify class to a individual file and make it a QObject.

107. By Renato Araujo Oliveira Filho

Make sure that the temporary directory is created.

108. By Renato Araujo Oliveira Filho

Make the dummy backend start async in an attempt to fix powerPC tests.

109. By Renato Araujo Oliveira Filho

Added debug messages.

110. By Renato Araujo Oliveira Filho

Skip tests when running on PPC machines.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '3rd_party/folks/dummy/lib/dummy-full-persona.vala'
--- 3rd_party/folks/dummy/lib/dummy-full-persona.vala 2013-12-13 14:24:51 +0000
+++ 3rd_party/folks/dummy/lib/dummy-full-persona.vala 2014-02-18 00:13:04 +0000
@@ -72,6 +72,15 @@
72 PostalAddressDetails,72 PostalAddressDetails,
73 WebServiceDetails73 WebServiceDetails
74{74{
75 private const string[] _default_linkable_properties =
76 {
77 "im-addresses",
78 "email-addresses",
79 "local-ids",
80 "web-service-addresses"
81 };
82
83
75 /**84 /**
76 * Create a new ‘full’ persona.85 * Create a new ‘full’ persona.
77 *86 *
@@ -88,7 +97,8 @@
88 * @since UNRELEASED97 * @since UNRELEASED
89 */98 */
90 public FullPersona (PersonaStore store, string contact_id,99 public FullPersona (PersonaStore store, string contact_id,
91 bool is_user = false, string[] linkable_properties = {})100 bool is_user = false,
101 string[] linkable_properties = {})
92 {102 {
93 base (store, contact_id, is_user, linkable_properties);103 base (store, contact_id, is_user, linkable_properties);
94 }104 }
@@ -104,6 +114,7 @@
104 this._groups_ro = this._groups.read_only_view;114 this._groups_ro = this._groups.read_only_view;
105 this._roles_ro = this._roles.read_only_view;115 this._roles_ro = this._roles.read_only_view;
106 this._anti_links_ro = this._anti_links.read_only_view;116 this._anti_links_ro = this._anti_links.read_only_view;
117 this.update_linkable_properties(FullPersona._default_linkable_properties);
107 }118 }
108119
109 private HashMultiMap<string, WebServiceFieldDetails> _web_service_addresses =120 private HashMultiMap<string, WebServiceFieldDetails> _web_service_addresses =
110121
=== modified file '3rd_party/folks/dummy/lib/dummy-persona.vala'
--- 3rd_party/folks/dummy/lib/dummy-persona.vala 2013-12-13 14:24:51 +0000
+++ 3rd_party/folks/dummy/lib/dummy-persona.vala 2014-02-18 00:13:04 +0000
@@ -53,7 +53,6 @@
53public class FolksDummy.Persona : Folks.Persona53public class FolksDummy.Persona : Folks.Persona
54{54{
55 private string[] _linkable_properties = new string[0];55 private string[] _linkable_properties = new string[0];
56
57 /**56 /**
58 * {@inheritDoc}57 * {@inheritDoc}
59 *58 *
@@ -96,8 +95,8 @@
96 *95 *
97 * @since UNRELEASED96 * @since UNRELEASED
98 */97 */
99 public Persona (PersonaStore store, string contact_id, bool is_user = false,98 public Persona (PersonaStore store, string contact_id,
100 string[] linkable_properties = {})99 bool is_user = false, string[] linkable_properties = {})
101 {100 {
102 var uid = Folks.Persona.build_uid (BACKEND_NAME, store.id, contact_id);101 var uid = Folks.Persona.build_uid (BACKEND_NAME, store.id, contact_id);
103 var iid = store.id + ":" + contact_id;102 var iid = store.id + ":" + contact_id;
@@ -233,6 +232,37 @@
233 }232 }
234 }233 }
235234
235 public void update_linkable_properties (string[] linkable_properties)
236 {
237 var new_linkable_properties = new HashSet<string> ();
238 new_linkable_properties.add_all_array(linkable_properties);
239
240 /* Check for changes. */
241 var changed = false;
242
243
244 if (this._linkable_properties.length != new_linkable_properties.size)
245 {
246 changed = true;
247 }
248 else
249 {
250 foreach (var p in this._linkable_properties)
251 {
252 if (new_linkable_properties.contains (p) == false)
253 {
254 changed = true;
255 break;
256 }
257 }
258 }
259 if (changed == true)
260 {
261 this._linkable_properties = new_linkable_properties.to_array ();
262 this.notify_property ("linkable-properties");
263 }
264 }
265
236 /**266 /**
237 * Delay between property changes and notifications.267 * Delay between property changes and notifications.
238 *268 *
239269
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2013-11-06 14:42:23 +0000
+++ CMakeLists.txt 2014-02-18 00:13:04 +0000
@@ -14,6 +14,7 @@
14pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)14pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
15pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)15pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
16pkg_check_modules(FOLKS REQUIRED folks>=0.9.0)16pkg_check_modules(FOLKS REQUIRED folks>=0.9.0)
17pkg_check_modules(FOLKS_EDS REQUIRED folks-eds)
1718
18if(FOLKS_VERSION VERSION_LESS "0.9.5")19if(FOLKS_VERSION VERSION_LESS "0.9.5")
19 set(FOLKS_VERSION_LESS_THAN_0_9_5 "1")20 set(FOLKS_VERSION_LESS_THAN_0_9_5 "1")
2021
=== modified file 'debian/changelog'
--- debian/changelog 2014-02-13 16:49:03 +0000
+++ debian/changelog 2014-02-18 00:13:04 +0000
@@ -1,3 +1,19 @@
1address-book-service (0.1.1) UNRELEASED; urgency=medium
2
3 * Avoid the persona to get linked automatically during the contact create or
4 edit.
5 * Create test to remove contacts functionality.
6 * Updated dummy backend code.
7 * Created test for add contacts.
8 * Rewrite unit test to work in a server/client way.
9 * Moved static address-book-service-lib to a different directory.
10 * Fork dummy backend from folks tree as a temporary solution before its get
11 release on folks.
12 * Check if query was destroyed on client side before delete it on the server
13 side.
14
15 -- Renato Araujo Oliveira Filho <renato@ubuntu> Fri, 24 Jan 2014 08:04:56 -0300
16
1address-book-service (0.1.0+14.04.20140213-0ubuntu1) trusty; urgency=low17address-book-service (0.1.0+14.04.20140213-0ubuntu1) trusty; urgency=low
218
3 [ Renato Araujo Oliveira Filho ]19 [ Renato Araujo Oliveira Filho ]
420
=== modified file 'debian/control'
--- debian/control 2013-10-30 00:19:00 +0000
+++ debian/control 2014-02-18 00:13:04 +0000
@@ -7,6 +7,7 @@
7 debhelper (>= 9),7 debhelper (>= 9),
8 gobject-introspection (>= 1.31.0-2~),8 gobject-introspection (>= 1.31.0-2~),
9 libfolks-dev,9 libfolks-dev,
10 libfolks-eds-dev,
10 libgee-0.8-dev (>= 0.8.4),11 libgee-0.8-dev (>= 0.8.4),
11 qt5-default,12 qt5-default,
12 qt5-qmake,13 qt5-qmake,
1314
=== modified file 'lib/CMakeLists.txt'
--- lib/CMakeLists.txt 2013-10-30 19:07:49 +0000
+++ lib/CMakeLists.txt 2014-02-18 00:13:04 +0000
@@ -38,6 +38,7 @@
38 ${GLIB_LIBRARIES}38 ${GLIB_LIBRARIES}
39 ${GIO_LIBRARIES}39 ${GIO_LIBRARIES}
40 ${FOLKS_LIBRARIES}40 ${FOLKS_LIBRARIES}
41 ${FOLKS_EDS_LIBRARIES}
41)42)
4243
43qt5_use_modules(${CONTACTS_SERVICE_LIB} Core Contacts DBus Versit)44qt5_use_modules(${CONTACTS_SERVICE_LIB} Core Contacts DBus Versit)
@@ -48,4 +49,5 @@
48 ${GLIB_INCLUDE_DIRS}49 ${GLIB_INCLUDE_DIRS}
49 ${GIO_INCLUDE_DIRS}50 ${GIO_INCLUDE_DIRS}
50 ${FOLKS_INCLUDE_DIRS}51 ${FOLKS_INCLUDE_DIRS}
52 ${FOLKS_EDS_INCLUDE_DIRS}
51)53)
5254
=== modified file 'lib/addressbook-adaptor.cpp'
--- lib/addressbook-adaptor.cpp 2013-11-04 18:34:43 +0000
+++ lib/addressbook-adaptor.cpp 2014-02-18 00:13:04 +0000
@@ -54,6 +54,16 @@
54 return Source();54 return Source();
55}55}
5656
57Source AddressBookAdaptor::createSource(const QString &sourceName, const QDBusMessage &message)
58{
59 message.setDelayedReply(true);
60 QMetaObject::invokeMethod(m_addressBook, "createSource",
61 Qt::QueuedConnection,
62 Q_ARG(const QString&, sourceName),
63 Q_ARG(const QDBusMessage&, message));
64 return Source();
65}
66
57QString AddressBookAdaptor::createContact(const QString &contact, const QString &source, const QDBusMessage &message)67QString AddressBookAdaptor::createContact(const QString &contact, const QString &source, const QDBusMessage &message)
58{68{
59 message.setDelayedReply(true);69 message.setDelayedReply(true);
6070
=== modified file 'lib/addressbook-adaptor.h'
--- lib/addressbook-adaptor.h 2013-11-01 01:10:12 +0000
+++ lib/addressbook-adaptor.h 2014-02-18 00:13:04 +0000
@@ -62,6 +62,11 @@
62" <arg direction=\"out\" type=\"(sb)\"/>\n"62" <arg direction=\"out\" type=\"(sb)\"/>\n"
63" <annotation value=\"Source\" name=\"com.trolltech.QtDBus.QtTypeName.Out0\"/>\n"63" <annotation value=\"Source\" name=\"com.trolltech.QtDBus.QtTypeName.Out0\"/>\n"
64" </method>\n"64" </method>\n"
65" <method name=\"createSource\">\n"
66" <arg direction=\"in\" type=\"s\"/>\n"
67" <arg direction=\"out\" type=\"(sb)\"/>\n"
68" <annotation value=\"Source\" name=\"com.trolltech.QtDBus.QtTypeName.Out0\"/>\n"
69" </method>\n"
65" <method name=\"sortFields\">\n"70" <method name=\"sortFields\">\n"
66" <arg direction=\"out\" type=\"as\"/>\n"71" <arg direction=\"out\" type=\"as\"/>\n"
67" </method>\n"72" </method>\n"
@@ -103,6 +108,7 @@
103public Q_SLOTS:108public Q_SLOTS:
104 SourceList availableSources(const QDBusMessage &message);109 SourceList availableSources(const QDBusMessage &message);
105 Source source(const QDBusMessage &message);110 Source source(const QDBusMessage &message);
111 Source createSource(const QString &sourceName, const QDBusMessage &message);
106 QStringList sortFields();112 QStringList sortFields();
107 QDBusObjectPath query(const QString &clause, const QString &sort, const QStringList &sources);113 QDBusObjectPath query(const QString &clause, const QString &sort, const QStringList &sources);
108 int removeContacts(const QStringList &contactIds, const QDBusMessage &message);114 int removeContacts(const QStringList &contactIds, const QDBusMessage &message);
109115
=== modified file 'lib/addressbook.cpp'
--- lib/addressbook.cpp 2013-11-05 19:26:25 +0000
+++ lib/addressbook.cpp 2014-02-18 00:13:04 +0000
@@ -31,6 +31,8 @@
31#include <signal.h>31#include <signal.h>
32#include <sys/socket.h>32#include <sys/socket.h>
3333
34#include <folks/folks-eds.h>
35
34//this timeout represents how long the server will wait for changes on the contact before notify the client36//this timeout represents how long the server will wait for changes on the contact before notify the client
35#define NOTIFY_CONTACTS_TIMEOUT 50037#define NOTIFY_CONTACTS_TIMEOUT 500
3638
@@ -38,6 +40,14 @@
3840
39namespace41namespace
40{42{
43
44class CreateContactData
45{
46public:
47 QDBusMessage m_message;
48 galera::AddressBook *m_addressbook;
49};
50
41class UpdateContactsData51class UpdateContactsData
42{52{
43public:53public:
@@ -58,6 +68,14 @@
58 int m_sucessCount;68 int m_sucessCount;
59};69};
6070
71class CreateSourceData
72{
73public:
74 QString sourceName;
75 galera::AddressBook *m_addressbook;
76 QDBusMessage m_message;
77};
78
61}79}
6280
63namespace galera81namespace galera
@@ -242,6 +260,37 @@
242 return Source();260 return Source();
243}261}
244262
263Source AddressBook::createSource(const QString &sourceId, const QDBusMessage &message)
264{
265 CreateSourceData *data = new CreateSourceData;
266 data->m_addressbook = this;
267 data->m_message = message;
268 data->sourceName = sourceId;
269 edsf_persona_store_create_address_book(sourceId.toUtf8().data(),
270 (GAsyncReadyCallback) AddressBook::createSourceDone,
271 data);
272 return Source();
273}
274
275void AddressBook::createSourceDone(GObject *source,
276 GAsyncResult *res,
277 void *data)
278{
279 CreateSourceData *cData = static_cast<CreateSourceData*>(data);
280 GError *error = 0;
281 Source src;
282 edsf_persona_store_create_address_book_finish(res, &error);
283 if (error) {
284 qWarning() << "Fail to create source" << error->message;
285 g_error_free(error);
286 } else {
287 src = Source(cData->sourceName, false);
288 }
289 QDBusMessage reply = cData->m_message.createReply(QVariant::fromValue<Source>(src));
290 QDBusConnection::sessionBus().send(reply);
291 delete cData;
292}
293
245void AddressBook::getSource(const QDBusMessage &message, bool onlyTheDefault)294void AddressBook::getSource(const QDBusMessage &message, bool onlyTheDefault)
246{295{
247 FolksBackendStore *backendStore = folks_backend_store_dup();296 FolksBackendStore *backendStore = folks_backend_store_dup();
@@ -338,13 +387,15 @@
338 if (!qcontact.isEmpty()) {387 if (!qcontact.isEmpty()) {
339 GHashTable *details = QIndividual::parseDetails(qcontact);388 GHashTable *details = QIndividual::parseDetails(qcontact);
340 //TOOD: lookup for source and use the correct store389 //TOOD: lookup for source and use the correct store
341 QDBusMessage *cpy = new QDBusMessage(message);390 CreateContactData *data = new CreateContactData;
391 data->m_message = message;
392 data->m_addressbook = this;
342 folks_individual_aggregator_add_persona_from_details(m_individualAggregator,393 folks_individual_aggregator_add_persona_from_details(m_individualAggregator,
343 NULL, //parent394 NULL, //parent
344 folks_individual_aggregator_get_primary_store(m_individualAggregator),395 folks_individual_aggregator_get_primary_store(m_individualAggregator),
345 details,396 details,
346 (GAsyncReadyCallback) createContactDone,397 (GAsyncReadyCallback) createContactDone,
347 (void*) cpy);398 (void*) data);
348 g_hash_table_destroy(details);399 g_hash_table_destroy(details);
349 return "";400 return "";
350 }401 }
@@ -429,6 +480,28 @@
429 }480 }
430}481}
431482
483void AddressBook::addAntiLinksDone(FolksAntiLinkable *antilinkable,
484 GAsyncResult *result,
485 void *data)
486{
487 CreateContactData *createData = static_cast<CreateContactData*>(data);
488 QDBusMessage reply;
489
490 GError *error = 0;
491 folks_anti_linkable_change_anti_links_finish(antilinkable, result, &error);
492 if (error) {
493 qWarning() << "Fail to anti link pesona" << folks_persona_get_display_id(FOLKS_PERSONA(antilinkable)) << error->message;
494 reply = createData->m_message.createErrorReply("Fail to anti link pesona:", error->message);
495 g_error_free(error);
496 } else {
497 FolksIndividual *individual = folks_persona_get_individual(FOLKS_PERSONA(antilinkable));
498 // return the result/contactId to the client
499 reply = createData->m_message.createReply(QString::fromUtf8(folks_individual_get_id(individual)));
500 }
501 QDBusConnection::sessionBus().send(reply);
502 delete createData;
503}
504
432QStringList AddressBook::sortFields()505QStringList AddressBook::sortFields()
433{506{
434 return SortClause::supportedFields();507 return SortClause::supportedFields();
@@ -455,25 +528,26 @@
455 m_updateCommandResult = contacts;528 m_updateCommandResult = contacts;
456 m_updateCommandPendingContacts << VCardParser::vcardToContact(contacts);529 m_updateCommandPendingContacts << VCardParser::vcardToContact(contacts);
457530
458 updateContactsDone(0, QString());531 updateContactsDone("", "");
459
460 return QStringList();532 return QStringList();
461}533}
462534
463void AddressBook::updateContactsDone(galera::QIndividual *individual, const QString &error)535void AddressBook::updateContactsDone(const QString &contactId,
536 const QString &error)
464{537{
465 Q_UNUSED(individual);
466 qDebug() << Q_FUNC_INFO;538 qDebug() << Q_FUNC_INFO;
467
468 int currentContactIndex = m_updateCommandResult.size() - m_updateCommandPendingContacts.size() - 1;539 int currentContactIndex = m_updateCommandResult.size() - m_updateCommandPendingContacts.size() - 1;
469540
470 if (!error.isEmpty()) {541 if (!error.isEmpty()) {
471 // update the result with the error542 // update the result with the error
472 m_updateCommandResult[currentContactIndex] = error;543 m_updateCommandResult[currentContactIndex] = error;
473 } else if (individual){544 } else if (!contactId.isEmpty()){
474 // update the result with the new contact info545 // update the result with the new contact info
475 m_updatedIds << individual->id();546 m_updatedIds << contactId;
476 QStringList newContacts = VCardParser::contactToVcard(QList<QContact>() << individual->contact());547 ContactEntry *entry = m_contacts->value(contactId);
548 Q_ASSERT(entry);
549 QContact contact = entry->individual()->contact();
550 QStringList newContacts = VCardParser::contactToVcard(QList<QContact>() << contact);
477 if (newContacts.length() == 1) {551 if (newContacts.length() == 1) {
478 m_updateCommandResult[currentContactIndex] = newContacts[0];552 m_updateCommandResult[currentContactIndex] = newContacts[0];
479 } else {553 } else {
@@ -485,12 +559,13 @@
485 QContact newContact = m_updateCommandPendingContacts.takeFirst();559 QContact newContact = m_updateCommandPendingContacts.takeFirst();
486 ContactEntry *entry = m_contacts->value(newContact.detail<QContactGuid>().guid());560 ContactEntry *entry = m_contacts->value(newContact.detail<QContactGuid>().guid());
487 if (entry) {561 if (entry) {
488 entry->individual()->update(newContact, this, SLOT(updateContactsDone(galera::QIndividual*,QString)));562 entry->individual()->update(newContact, this,
563 SLOT(updateContactsDone(QString,QString)));
489 } else {564 } else {
490 updateContactsDone(0, "Contact not found!");565 updateContactsDone("", "Contact not found!");
491 }566 }
492 } else {567 } else {
493 folks_persona_store_flush(folks_individual_aggregator_get_primary_store(m_individualAggregator), 0, 0);568
494 QDBusMessage reply = m_updateCommandReplyMessage.createReply(m_updateCommandResult);569 QDBusMessage reply = m_updateCommandReplyMessage.createReply(m_updateCommandResult);
495 QDBusConnection::sessionBus().send(reply);570 QDBusConnection::sessionBus().send(reply);
496571
@@ -504,17 +579,13 @@
504 }579 }
505}580}
506581
507
508QString AddressBook::removeContact(FolksIndividual *individual)582QString AddressBook::removeContact(FolksIndividual *individual)
509{583{
510 if (m_contacts->contains(individual)) {584 QString contactId = QString::fromUtf8(folks_individual_get_id(individual));
511 ContactEntry *ci = m_contacts->take(individual);585 ContactEntry *ci = m_contacts->take(contactId);
512 if (ci) {586 if (ci) {
513 QString id = QString::fromUtf8(folks_individual_get_id(individual));587 delete ci;
514 qDebug() << "Remove contact" << id;588 return contactId;
515 delete ci;
516 return id;
517 }
518 }589 }
519 return QString();590 return QString();
520}591}
@@ -526,7 +597,6 @@
526 if (entry) {597 if (entry) {
527 entry->individual()->setIndividual(individual);598 entry->individual()->setIndividual(individual);
528 } else {599 } else {
529 Q_ASSERT(!m_contacts->contains(individual));
530 QIndividual *i = new QIndividual(individual, m_individualAggregator);600 QIndividual *i = new QIndividual(individual, m_individualAggregator);
531 i->addListener(this, SLOT(individualChanged(QIndividual*)));601 i->addListener(this, SLOT(individualChanged(QIndividual*)));
532 m_contacts->insert(new ContactEntry(i));602 m_contacts->insert(new ContactEntry(i));
@@ -540,51 +610,72 @@
540 AddressBook *self)610 AddressBook *self)
541{611{
542 qDebug() << Q_FUNC_INFO;612 qDebug() << Q_FUNC_INFO;
543 QStringList removedIds;613 Q_UNUSED(individualAggregator);
544 QStringList addedIds;614
545615 QSet<QString> removedIds;
546 GeeIterator *iter;616 QSet<QString> addedIds;
547 GeeSet *removed = gee_multi_map_get_keys(changes);617 QSet<QString> updatedIds;
548 GeeCollection *added = gee_multi_map_get_values(changes);618
549619 GeeSet *keys = gee_multi_map_get_keys(changes);
550 iter = gee_iterable_iterator(GEE_ITERABLE(added));620 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(keys));
551 while(gee_iterator_next(iter)) {621
552 FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));622 while(gee_iterator_next(iter)) {
553 if (individual) {623 FolksIndividual *individualKey = FOLKS_INDIVIDUAL(gee_iterator_get(iter));
554 // add contact to the map624 GeeCollection *values = gee_multi_map_get(changes, individualKey);
555 addedIds << self->addContact(individual);625 GeeIterator *iterV;
556 g_object_unref(individual);626
557 }627 iterV = gee_iterable_iterator(GEE_ITERABLE(values));
558 }628 while(gee_iterator_next(iterV)) {
559 g_object_unref (iter);629 FolksIndividual *individualValue = FOLKS_INDIVIDUAL(gee_iterator_get(iterV));
560630
561631 // contact added
562 iter = gee_iterable_iterator(GEE_ITERABLE(removed));632 if (individualKey == 0) {
563 while(gee_iterator_next(iter)) {633 addedIds << self->addContact(individualValue);
564 FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));634 } else if (individualValue != 0){
565 if (individual) {635 qDebug() << "Link changes";
566 QString id = QString::fromUtf8(folks_individual_get_id(individual));636 QString idValue = QString::fromUtf8(folks_individual_get_id(individualValue));
567 if (!addedIds.contains(id)) {637 if (self->m_contacts->value(idValue)) {
568 // delete from contact map638 updatedIds << self->addContact(individualValue);
569 removedIds << self->removeContact(individual);639 } else {
570 }640 addedIds << self->addContact(individualValue);
571 g_object_unref(individual);641 }
572 }642 }
573 }643
574 g_object_unref (iter);644 if (individualValue) {
575645 g_object_unref(individualValue);
576 //TODO: check for linked and unliked contacts646 }
647 }
648
649 g_object_unref(iterV);
650 g_object_unref(values);
651
652 if (individualKey) {
653 QString id = QString::fromUtf8(folks_individual_get_id(individualKey));
654 if (!addedIds.contains(id) &&
655 !updatedIds.contains(id)) {
656 removedIds << self->removeContact(individualKey);
657 }
658 g_object_unref(individualKey);
659 }
660 }
661
662 g_object_unref(keys);
663
577 if (!removedIds.isEmpty() && self->m_ready) {664 if (!removedIds.isEmpty() && self->m_ready) {
578 Q_EMIT self->m_adaptor->contactsRemoved(removedIds);665 Q_EMIT self->m_adaptor->contactsRemoved(removedIds.toList());
579 }666 }
580667
581 if (!addedIds.isEmpty() && self->m_ready) {668 if (!addedIds.isEmpty() && self->m_ready) {
582 Q_EMIT self->m_adaptor->contactsAdded(addedIds);669 Q_EMIT self->m_adaptor->contactsAdded(addedIds.toList());
583 }670 }
584671
585 g_object_unref(added);672 if (!updatedIds.isEmpty() && self->m_ready) {
586 g_object_unref(removed);673 Q_EMIT self->m_adaptor->contactsUpdated(updatedIds.toList());
674 }
675
587 qDebug() << "Added" << addedIds;676 qDebug() << "Added" << addedIds;
677 qDebug() << "Removed" << removedIds;
678 qDebug() << "Changed" << updatedIds;
588}679}
589680
590void AddressBook::prepareFolksDone(GObject *source,681void AddressBook::prepareFolksDone(GObject *source,
@@ -598,29 +689,41 @@
598689
599void AddressBook::createContactDone(FolksIndividualAggregator *individualAggregator,690void AddressBook::createContactDone(FolksIndividualAggregator *individualAggregator,
600 GAsyncResult *res,691 GAsyncResult *res,
601 QDBusMessage *msg)692 void *data)
602{693{
603 qDebug() << "Create Contact Done" << msg;694 CreateContactData *createData = static_cast<CreateContactData*>(data);
695
604 FolksPersona *persona;696 FolksPersona *persona;
605 GError *error = NULL;697 GError *error = NULL;
606 QDBusMessage reply;698 QDBusMessage reply;
607 persona = folks_individual_aggregator_add_persona_from_details_finish(individualAggregator, res, &error);699 persona = folks_individual_aggregator_add_persona_from_details_finish(individualAggregator, res, &error);
608 if (error != NULL) {700 if (error != NULL) {
609 qWarning() << "Failed to create individual from contact:" << error->message;701 qWarning() << "Failed to create individual from contact:" << error->message;
610 reply = msg->createErrorReply("Failed to create individual from contact", error->message);702 reply = createData->m_message.createErrorReply("Failed to create individual from contact", error->message);
611 g_clear_error(&error);703 g_clear_error(&error);
612 } else if (persona == NULL) {704 } else if (persona == NULL) {
613 qWarning() << "Failed to create individual from contact: Persona already exists";705 qWarning() << "Failed to create individual from contact: Persona already exists";
614 reply = msg->createErrorReply("Failed to create individual from contact", "Contact already exists");706 reply = createData->m_message.createErrorReply("Failed to create individual from contact", "Contact already exists");
707 } else if (QIndividual::autoLinkEnabled()){
708 FolksIndividual *individual = folks_persona_get_individual(persona);
709 reply = createData->m_message.createReply(QString::fromUtf8(folks_individual_get_id(individual)));
615 } else {710 } else {
616 qDebug() << "Persona created:" << persona;711 // avoid the new persona get linked
617 FolksIndividual *individual;712 GeeHashSet *antiLinks = gee_hash_set_new(G_TYPE_STRING,
618 individual = folks_persona_get_individual(persona);713 (GBoxedCopyFunc) g_strdup,
619 reply = msg->createReply(QString::fromUtf8(folks_individual_get_id(individual)));714 g_free,
715 NULL, NULL, NULL, NULL, NULL, NULL);
716 gee_collection_add(GEE_COLLECTION(antiLinks), "*");
717 folks_anti_linkable_change_anti_links(FOLKS_ANTI_LINKABLE(persona),
718 GEE_SET(antiLinks),
719 (GAsyncReadyCallback) addAntiLinksDone,
720 data);
721 g_object_unref(antiLinks);
722 return;
620 }723 }
621 //TODO: use dbus connection724 //TODO: use dbus connection
622 QDBusConnection::sessionBus().send(reply);725 QDBusConnection::sessionBus().send(reply);
623 delete msg;726 delete createData;
624}727}
625728
626void AddressBook::isQuiescentChanged(GObject *source, GParamSpec *param, AddressBook *self)729void AddressBook::isQuiescentChanged(GObject *source, GParamSpec *param, AddressBook *self)
627730
=== modified file 'lib/addressbook.h'
--- lib/addressbook.h 2013-11-01 13:15:51 +0000
+++ lib/addressbook.h 2014-02-18 00:13:04 +0000
@@ -69,10 +69,11 @@
69 void shutdown();69 void shutdown();
70 SourceList availableSources(const QDBusMessage &message);70 SourceList availableSources(const QDBusMessage &message);
71 Source source(const QDBusMessage &message);71 Source source(const QDBusMessage &message);
72 Source createSource(const QString &sourceId, const QDBusMessage &message);
72 QString createContact(const QString &contact, const QString &source, const QDBusMessage &message);73 QString createContact(const QString &contact, const QString &source, const QDBusMessage &message);
73 int removeContacts(const QStringList &contactIds, const QDBusMessage &message);74 int removeContacts(const QStringList &contactIds, const QDBusMessage &message);
74 QStringList updateContacts(const QStringList &contacts, const QDBusMessage &message);75 QStringList updateContacts(const QStringList &contacts, const QDBusMessage &message);
75 void updateContactsDone(galera::QIndividual *individual, const QString &error);76 void updateContactsDone(const QString &contactId, const QString &error);
7677
77private Q_SLOTS:78private Q_SLOTS:
78 void viewClosed();79 void viewClosed();
@@ -139,11 +140,16 @@
139 AddressBook *self);140 AddressBook *self);
140 static void createContactDone(FolksIndividualAggregator *individualAggregator,141 static void createContactDone(FolksIndividualAggregator *individualAggregator,
141 GAsyncResult *res,142 GAsyncResult *res,
142 QDBusMessage *msg);143 void *data);
143 static void removeContactDone(FolksIndividualAggregator *individualAggregator,144 static void removeContactDone(FolksIndividualAggregator *individualAggregator,
144 GAsyncResult *result,145 GAsyncResult *result,
145 void *data);146 void *data);
146147 static void addAntiLinksDone(FolksAntiLinkable *antilinkable,
148 GAsyncResult *result,
149 void *data);
150 static void createSourceDone(GObject *source,
151 GAsyncResult *res,
152 void *data);
147 friend class DirtyContactsNotify;153 friend class DirtyContactsNotify;
148};154};
149155
150156
=== modified file 'lib/contacts-map.cpp'
--- lib/contacts-map.cpp 2013-11-06 18:49:59 +0000
+++ lib/contacts-map.cpp 2014-02-18 00:13:04 +0000
@@ -33,7 +33,7 @@
3333
34ContactEntry::~ContactEntry()34ContactEntry::~ContactEntry()
35{35{
36 delete m_individual;36 delete m_individual;
37}37}
3838
39QIndividual *ContactEntry::individual() const39QIndividual *ContactEntry::individual() const
@@ -52,11 +52,6 @@
52 clear();52 clear();
53}53}
5454
55ContactEntry *ContactsMap::value(FolksIndividual *individual) const
56{
57 return m_individualsToEntry[individual];
58}
59
60ContactEntry *ContactsMap::value(const QString &id) const55ContactEntry *ContactsMap::value(const QString &id) const
61{56{
62 return m_idToEntry[id];57 return m_idToEntry[id];
@@ -64,32 +59,33 @@
6459
65ContactEntry *ContactsMap::take(FolksIndividual *individual)60ContactEntry *ContactsMap::take(FolksIndividual *individual)
66{61{
67 if (m_individualsToEntry.remove(individual)) {62 QString contactId = QString::fromUtf8(folks_individual_get_id(individual));
68 return m_idToEntry.take(folks_individual_get_id(individual));63 return take(contactId);
69 }64}
70 return 0;65
66ContactEntry *ContactsMap::take(const QString &id)
67{
68 QMutexLocker locker(&m_mutex);
69 return m_idToEntry.take(id);
71}70}
7271
73void ContactsMap::remove(const QString &id)72void ContactsMap::remove(const QString &id)
74{73{
75 ContactEntry *entry = m_idToEntry[id];74 QMutexLocker locker(&m_mutex);
75 ContactEntry *entry = m_idToEntry.value(id,0);
76 if (entry) {76 if (entry) {
77 m_individualsToEntry.remove(entry->individual()->individual());
78 m_idToEntry.remove(id);77 m_idToEntry.remove(id);
79 delete entry;78 delete entry;
80 }79 }
81}80}
8281
83bool ContactsMap::contains(FolksIndividual *individual) const
84{
85 return m_individualsToEntry.contains(individual);
86}
87
88void ContactsMap::insert(ContactEntry *entry)82void ContactsMap::insert(ContactEntry *entry)
89{83{
84 QMutexLocker locker(&m_mutex);
90 FolksIndividual *fIndividual = entry->individual()->individual();85 FolksIndividual *fIndividual = entry->individual()->individual();
91 m_idToEntry.insert(folks_individual_get_id(fIndividual), entry);86 if (fIndividual) {
92 m_individualsToEntry.insert(fIndividual, entry);87 m_idToEntry.insert(folks_individual_get_id(fIndividual), entry);
88 }
93}89}
9490
95int ContactsMap::size() const91int ContactsMap::size() const
@@ -99,16 +95,25 @@
9995
100void ContactsMap::clear()96void ContactsMap::clear()
101{97{
98 QMutexLocker locker(&m_mutex);
102 QList<ContactEntry*> entries = m_idToEntry.values();99 QList<ContactEntry*> entries = m_idToEntry.values();
103 m_idToEntry.clear();100 m_idToEntry.clear();
104 m_individualsToEntry.clear();
105
106 qDeleteAll(entries);101 qDeleteAll(entries);
107}102}
108103
104void ContactsMap::lock()
105{
106 m_mutex.lock();
107}
108
109void ContactsMap::unlock()
110{
111 m_mutex.unlock();
112}
113
109QList<ContactEntry*> ContactsMap::values() const114QList<ContactEntry*> ContactsMap::values() const
110{115{
111 return m_individualsToEntry.values();116 return m_idToEntry.values();
112}117}
113118
114ContactEntry *ContactsMap::valueFromVCard(const QString &vcard) const119ContactEntry *ContactsMap::valueFromVCard(const QString &vcard) const
@@ -125,4 +130,21 @@
125 return 0;130 return 0;
126}131}
127132
133bool ContactsMap::contains(FolksIndividual *individual) const
134{
135 QString contactId = QString::fromUtf8(folks_individual_get_id(individual));
136 return contains(contactId);
137}
138
139bool ContactsMap::contains(const QString &id) const
140{
141 return m_idToEntry.contains(id);
142}
143
144ContactEntry *ContactsMap::value(FolksIndividual *individual) const
145{
146 QString contactId = QString::fromUtf8(folks_individual_get_id(individual));
147 return m_idToEntry.value(contactId, 0);
148}
149
128} //namespace150} //namespace
129151
=== modified file 'lib/contacts-map.h'
--- lib/contacts-map.h 2013-11-05 00:25:03 +0000
+++ lib/contacts-map.h 2014-02-18 00:13:04 +0000
@@ -22,6 +22,7 @@
22#include <QtCore/QString>22#include <QtCore/QString>
23#include <QtCore/QStringList>23#include <QtCore/QStringList>
24#include <QtCore/QHash>24#include <QtCore/QHash>
25#include <QtCore/QMutex>
2526
26#include <folks/folks.h>27#include <folks/folks.h>
27#include <glib.h>28#include <glib.h>
@@ -57,20 +58,25 @@
57 ContactEntry *valueFromVCard(const QString &vcard) const;58 ContactEntry *valueFromVCard(const QString &vcard) const;
5859
59 bool contains(FolksIndividual *individual) const;60 bool contains(FolksIndividual *individual) const;
61 bool contains(const QString &id) const;
62
60 ContactEntry *value(FolksIndividual *individual) const;63 ContactEntry *value(FolksIndividual *individual) const;
61 ContactEntry *value(const QString &id) const;64 ContactEntry *value(const QString &id) const;
65
62 ContactEntry *take(FolksIndividual *individual);66 ContactEntry *take(FolksIndividual *individual);
67 ContactEntry *take(const QString &id);
68
63 void remove(const QString &id);69 void remove(const QString &id);
64 void insert(ContactEntry *entry);70 void insert(ContactEntry *entry);
65 int size() const;71 int size() const;
66 void clear();72 void clear();
6773 void lock();
6874 void unlock();
69 QList<ContactEntry*> values() const;75 QList<ContactEntry*> values() const;
7076
71private:77private:
72 QHash<FolksIndividual *, ContactEntry*> m_individualsToEntry;
73 QHash<QString, ContactEntry*> m_idToEntry;78 QHash<QString, ContactEntry*> m_idToEntry;
79 QMutex m_mutex;
74};80};
7581
76} //namespace82} //namespace
7783
=== modified file 'lib/qindividual.cpp'
--- lib/qindividual.cpp 2013-11-05 00:25:03 +0000
+++ lib/qindividual.cpp 2014-02-18 00:13:04 +0000
@@ -118,15 +118,15 @@
118118
119namespace galera119namespace galera
120{120{
121bool QIndividual::m_autoLink = false;
121122
122QIndividual::QIndividual(FolksIndividual *individual, FolksIndividualAggregator *aggregator)123QIndividual::QIndividual(FolksIndividual *individual, FolksIndividualAggregator *aggregator)
123 : m_individual(individual),124 : m_individual(0),
124 m_primaryPersona(0),
125 m_aggregator(aggregator),125 m_aggregator(aggregator),
126 m_contact(0)126 m_contact(0),
127 m_currentUpdate(0)
127{128{
128 g_object_ref(m_individual);129 setIndividual(individual);
129 updateContact();
130}130}
131131
132void QIndividual::notifyUpdate()132void QIndividual::notifyUpdate()
@@ -139,20 +139,20 @@
139139
140QIndividual::~QIndividual()140QIndividual::~QIndividual()
141{141{
142 if (m_contact) {142 if (m_currentUpdate) {
143 delete m_contact;143 m_currentUpdate->disconnect(m_updateConnection);
144 // this will leave the update object to destroy itself
145 // this is necessary because the individual can be destroyed during a update
146 // Eg. If the individual get linked
147 m_currentUpdate->deatach();
148 m_currentUpdate = 0;
144 }149 }
145 Q_ASSERT(m_individual);150 clear();
146 g_object_unref(m_individual);
147}151}
148152
149QString QIndividual::id() const153QString QIndividual::id() const
150{154{
151 if (m_individual) {155 return m_id;
152 return QString::fromUtf8(folks_individual_get_id(m_individual));
153 } else {
154 return "";
155 }
156}156}
157157
158QtContacts::QContactDetail QIndividual::getUid() const158QtContacts::QContactDetail QIndividual::getUid() const
@@ -167,25 +167,17 @@
167167
168QList<QtContacts::QContactDetail> QIndividual::getClientPidMap() const168QList<QtContacts::QContactDetail> QIndividual::getClientPidMap() const
169{169{
170 QList<QtContacts::QContactDetail> details;
171 int index = 1;170 int index = 1;
172 GeeSet *personas = folks_individual_get_personas(m_individual);171 QList<QContactDetail> details;
173 if (!personas) {
174 return details;
175 }
176 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
177172
178 while(gee_iterator_next(iter)) {173 Q_FOREACH(const QString id, m_personas.keys()) {
179 QContactExtendedDetail detail;174 QContactExtendedDetail detail;
180 FolksPersona *persona = FOLKS_PERSONA(gee_iterator_get(iter));175
181 detail.setName("CLIENTPIDMAP");176 detail.setName("CLIENTPIDMAP");
182 detail.setValue(QContactExtendedDetail::FieldData, index++);177 detail.setValue(QContactExtendedDetail::FieldData, index++);
183 detail.setValue(QContactExtendedDetail::FieldData + 1, QString::fromUtf8(folks_persona_get_uid(persona)));178 detail.setValue(QContactExtendedDetail::FieldData + 1, id);
184 details << detail;179 details << detail;
185 g_object_unref(persona);
186 }180 }
187
188 g_object_unref(iter);
189 return details;181 return details;
190}182}
191183
@@ -360,9 +352,13 @@
360 g_free(uri);352 g_free(uri);
361 g_object_unref(cache);353 g_object_unref(cache);
362 }354 }
355 // Avoid to set a empty url
356 if (url.isEmpty()) {
357 return avatar;
358 }
363 avatar.setImageUrl(QUrl(url));359 avatar.setImageUrl(QUrl(url));
360 avatar.setDetailUri(QString("%1.1").arg(index));
364 }361 }
365 avatar.setDetailUri(QString("%1.1").arg(index));
366 return avatar;362 return avatar;
367}363}
368364
@@ -744,40 +740,64 @@
744740
745QtContacts::QContact &QIndividual::contact()741QtContacts::QContact &QIndividual::contact()
746{742{
747 if (!m_contact) {743 if (!m_contact && m_individual) {
744 updatePersonas();
748 updateContact();745 updateContact();
749 }746 }
750 return *m_contact;747 return *m_contact;
751}748}
752749
750void QIndividual::updatePersonas()
751{
752 Q_FOREACH(FolksPersona *p, m_personas.values()) {
753 g_object_unref(p);
754 }
755
756 GeeSet *personas = folks_individual_get_personas(m_individual);
757 if (!personas) {
758 return;
759 }
760
761 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
762 while(gee_iterator_next(iter)) {
763 FolksPersona *persona = FOLKS_PERSONA(gee_iterator_get(iter));
764 g_signal_connect(G_OBJECT(persona), "notify::avatar",
765 (GCallback) QIndividual::folksPersonaChanged,
766 const_cast<QIndividual*>(this));
767
768 m_personas.insert(QString::fromUtf8(folks_persona_get_iid(persona)), persona);
769 }
770
771 g_object_unref(iter);
772}
773
753void QIndividual::updateContact()774void QIndividual::updateContact()
754{775{
755 Q_ASSERT(m_individual);776 // disconnect any previous handler
777 Q_FOREACH(FolksPersona *p, m_notifyConnections.keys()) {
778 Q_FOREACH(int handlerId, m_notifyConnections.value(p)) {
779 g_signal_handler_disconnect(p, handlerId);
780 }
781 m_notifyConnections.remove(p);
782 }
783
784 if (m_contact) {
785 delete m_contact;
786 m_contact = 0;
787 }
756788
757 m_contact = new QContact();789 m_contact = new QContact();
790 if (!m_individual) {
791 return;
792 }
793
758 m_contact->appendDetail(getUid());794 m_contact->appendDetail(getUid());
759 Q_FOREACH(QContactDetail detail, getClientPidMap()) {795 Q_FOREACH(QContactDetail detail, getClientPidMap()) {
760 m_contact->appendDetail(detail);796 m_contact->appendDetail(detail);
761 }797 }
762798
763 int personaIndex = 1;799 int personaIndex = 1;
764 GeeSet *personas = folks_individual_get_personas(m_individual);800 Q_FOREACH(FolksPersona *persona, m_personas.values()) {
765 Q_ASSERT(personas);
766 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
767
768 FolksPersona *persona;
769
770 // disconnect any previous handler
771 Q_FOREACH(gpointer persona, m_notifyConnections.keys()) {
772 Q_FOREACH(int handlerId, m_notifyConnections[persona]) {
773 g_signal_handler_disconnect(persona, handlerId);
774 }
775 }
776
777 m_notifyConnections.clear();
778
779 while(gee_iterator_next(iter)) {
780 persona = FOLKS_PERSONA(gee_iterator_get(iter));
781 Q_ASSERT(FOLKS_IS_PERSONA(persona));801 Q_ASSERT(FOLKS_IS_PERSONA(persona));
782802
783 int wsize = 0;803 int wsize = 0;
@@ -790,25 +810,27 @@
790 wPropList << wproperties[i];810 wPropList << wproperties[i];
791 }811 }
792812
793 appendDetailsForPersona(m_contact,813 // vcard only support one of these details by contact
794 getPersonaName(persona, personaIndex),814 if (personaIndex == 1) {
795 !wPropList.contains("structured-name"));815 appendDetailsForPersona(m_contact,
796 appendDetailsForPersona(m_contact,816 getPersonaName(persona, personaIndex),
797 getPersonaFullName(persona, personaIndex),817 !wPropList.contains("structured-name"));
798 !wPropList.contains("full-name"));818 appendDetailsForPersona(m_contact,
799 appendDetailsForPersona(m_contact,819 getPersonaFullName(persona, personaIndex),
800 getPersonaNickName(persona, personaIndex),820 !wPropList.contains("full-name"));
801 !wPropList.contains("structured-name"));821 appendDetailsForPersona(m_contact,
802 appendDetailsForPersona(m_contact,822 getPersonaNickName(persona, personaIndex),
803 getPersonaBirthday(persona, personaIndex),823 !wPropList.contains("structured-name"));
804 !wPropList.contains("birthday"));824 appendDetailsForPersona(m_contact,
805 appendDetailsForPersona(m_contact,825 getPersonaBirthday(persona, personaIndex),
806 getPersonaPhoto(persona, personaIndex),826 !wPropList.contains("birthday"));
807 !wPropList.contains("avatar"));827 appendDetailsForPersona(m_contact,
808 appendDetailsForPersona(m_contact,828 getPersonaPhoto(persona, personaIndex),
809 getPersonaFavorite(persona, personaIndex),829 !wPropList.contains("avatar"));
810 !wPropList.contains("is-favourite"));830 appendDetailsForPersona(m_contact,
811831 getPersonaFavorite(persona, personaIndex),
832 !wPropList.contains("is-favourite"));
833 }
812834
813 QList<QContactDetail> details;835 QList<QContactDetail> details;
814 QContactDetail prefDetail;836 QContactDetail prefDetail;
@@ -855,33 +877,34 @@
855 !wPropList.contains("urls"));877 !wPropList.contains("urls"));
856 personaIndex++;878 personaIndex++;
857879
880 QList<int> ids = m_notifyConnections.value(persona);
881
858 // for now we are getting updated only about avatar changes882 // for now we are getting updated only about avatar changes
859 int handlerId = g_signal_connect(G_OBJECT(persona), "notify::avatar",883 ids << g_signal_connect(G_OBJECT(persona), "notify::avatar",
860 (GCallback) QIndividual::folksPersonaChanged,884 (GCallback) QIndividual::folksPersonaChanged,
861 const_cast<QIndividual*>(this));885 const_cast<QIndividual*>(this));
862 QList<int> ids = m_notifyConnections[persona];
863 ids << handlerId;
864 m_notifyConnections[persona] = ids;886 m_notifyConnections[persona] = ids;
865
866 g_object_unref(persona);
867 }887 }
868
869 g_object_unref(iter);
870}888}
871889
872bool QIndividual::update(const QtContacts::QContact &newContact, QObject *object, const char *slot)890bool QIndividual::update(const QtContacts::QContact &newContact, QObject *object, const char *slot)
873{891{
874 QContact &originalContact = contact();892 QContact &originalContact = contact();
875 if (newContact != originalContact) {893 if (newContact != originalContact) {
876 UpdateContactRequest *request = new UpdateContactRequest(newContact, this, object, slot);894 // only suppport one update by time
895 Q_ASSERT(m_currentUpdate == 0);
896 m_currentUpdate = new UpdateContactRequest(newContact, this, object, slot);
897 m_updateConnection = QObject::connect(m_currentUpdate,
898 &UpdateContactRequest::done,
899 [this] (const QString &errorMessage) {
877900
878 QObject::connect(request, &UpdateContactRequest::done, [request, this] (const QString &errorMessage) {
879 if (errorMessage.isEmpty()) {901 if (errorMessage.isEmpty()) {
880 this->updateContact();902 this->updateContact();
881 }903 }
882 request->deleteLater();904 m_currentUpdate->deleteLater();
905 m_currentUpdate = 0;
883 });906 });
884 request->start();907 m_currentUpdate->start();
885 return true;908 return true;
886 } else {909 } else {
887 qDebug() << "Contact is equal";910 qDebug() << "Contact is equal";
@@ -895,31 +918,40 @@
895 return update(contact, object, slot);918 return update(contact, object, slot);
896}919}
897920
898
899FolksIndividual *QIndividual::individual() const921FolksIndividual *QIndividual::individual() const
900{922{
901 return m_individual;923 return m_individual;
902}924}
903925
904FolksPersona *QIndividual::getPersona(int index) const926QList<FolksPersona *> QIndividual::personas() const
905{927{
906 int size = 0;928 return m_personas.values();
907 FolksPersona *persona = 0;929}
908 GeeSet *personas = folks_individual_get_personas(m_individual);930
909 gpointer* values = gee_collection_to_array(GEE_COLLECTION(personas), &size);931void QIndividual::clearPersonas()
910932{
911 if ((index > 0) && (index <= size)) {933 Q_FOREACH(FolksPersona *p, m_personas.values()) {
912 persona = FOLKS_PERSONA(values[index - 1]);934 Q_FOREACH(int handlerId, m_notifyConnections.value(p)) {
913 }935 g_signal_handler_disconnect(p, handlerId);
914936 }
915 g_free(values);937 m_notifyConnections.remove(p);
916 return persona;938 g_object_unref(p);
917}939 }
918940 m_personas.clear();
919int QIndividual::personaCount() const941}
920{942
921 GeeSet *personas = folks_individual_get_personas(m_individual);943void QIndividual::clear()
922 return gee_collection_get_size(GEE_COLLECTION(personas));944{
945 clearPersonas();
946 if (m_individual) {
947 g_object_unref(m_individual);
948 m_individual = 0;
949 }
950
951 if (m_contact) {
952 delete m_contact;
953 m_contact = 0;
954 }
923}955}
924956
925void QIndividual::addListener(QObject *object, const char *slot)957void QIndividual::addListener(QObject *object, const char *slot)
@@ -932,27 +964,45 @@
932 }964 }
933}965}
934966
967bool QIndividual::isValid() const
968{
969 return (m_individual != 0);
970}
971
972void QIndividual::flush()
973{
974 // flush the folks persona store
975 folks_persona_store_flush(folks_individual_aggregator_get_primary_store(m_aggregator), 0, 0);
976
977 // cause the contact info to be reload
978 if (m_contact) {
979 delete m_contact;
980 m_contact = 0;
981 }
982}
983
935void QIndividual::setIndividual(FolksIndividual *individual)984void QIndividual::setIndividual(FolksIndividual *individual)
936{985{
937 if (m_individual != individual) {986 if (m_individual != individual) {
938 if (m_individual) {987 clear();
939 g_object_unref(m_individual);988
989 if (individual) {
990 QString newId = QString::fromUtf8(folks_individual_get_id(individual));
991 if (!m_id.isEmpty()) {
992 // we can only update to individual with the same id
993 Q_ASSERT(newId == m_id);
994 } else {
995 m_id = newId;
996 }
940 }997 }
998
941 m_individual = individual;999 m_individual = individual;
942 if (m_individual) {1000 if (m_individual) {
943 g_object_ref(m_individual);1001 g_object_ref(m_individual);
944 }1002 }
945
946 // initialize qcontact
947 if (m_contact) {
948 delete m_contact;
949 m_contact = 0;
950 }
951 updateContact();
952 }1003 }
953}1004}
9541005
955
956GHashTable *QIndividual::parseAddressDetails(GHashTable *details,1006GHashTable *QIndividual::parseAddressDetails(GHashTable *details,
957 const QList<QtContacts::QContactDetail> &cDetails,1007 const QList<QtContacts::QContactDetail> &cDetails,
958 const QtContacts::QContactDetail &prefDetail)1008 const QtContacts::QContactDetail &prefDetail)
@@ -982,13 +1032,15 @@
982 g_value_take_object(value, collection);1032 g_value_take_object(value, collection);
983 }1033 }
9841034
985 FolksPostalAddressFieldDetails *pafd = folks_postal_address_field_details_new(postalAddress, NULL);1035 if (!folks_postal_address_is_empty(postalAddress)) {
986 DetailContextParser::parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(pafd),1036 FolksPostalAddressFieldDetails *pafd = folks_postal_address_field_details_new(postalAddress, NULL);
987 address,1037 DetailContextParser::parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(pafd),
988 detail == prefDetail);1038 address,
989 gee_collection_add(collection, pafd);1039 detail == prefDetail);
1040 gee_collection_add(collection, pafd);
1041 g_object_unref(pafd);
1042 }
9901043
991 g_object_unref(pafd);
992 g_object_unref(postalAddress);1044 g_object_unref(postalAddress);
993 }1045 }
994 GeeUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_POSTAL_ADDRESSES, value);1046 GeeUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_POSTAL_ADDRESSES, value);
@@ -1293,7 +1345,6 @@
1293 return details;1345 return details;
1294}1346}
12951347
1296
1297GHashTable *QIndividual::parseDetails(const QtContacts::QContact &contact)1348GHashTable *QIndividual::parseDetails(const QtContacts::QContact &contact)
1298{1349{
1299 GHashTable *details = g_hash_table_new_full(g_str_hash,1350 GHashTable *details = g_hash_table_new_full(g_str_hash,
@@ -1309,7 +1360,6 @@
1309 parseFullNameDetails(details, contact.details(QContactDisplayLabel::Type));1360 parseFullNameDetails(details, contact.details(QContactDisplayLabel::Type));
1310 parseNicknameDetails(details, contact.details(QContactNickname::Type));1361 parseNicknameDetails(details, contact.details(QContactNickname::Type));
13111362
1312
1313 parseAddressDetails(details,1363 parseAddressDetails(details,
1314 contact.details(QContactAddress::Type),1364 contact.details(QContactAddress::Type),
1315 contact.preferredDetail(VCardParser::PreferredActionNames[QContactAddress::Type]));1365 contact.preferredDetail(VCardParser::PreferredActionNames[QContactAddress::Type]));
@@ -1335,29 +1385,23 @@
1335 return details;1385 return details;
1336}1386}
13371387
1388void QIndividual::enableAutoLink(bool flag)
1389{
1390 m_autoLink = flag;
1391}
1392
1393bool QIndividual::autoLinkEnabled()
1394{
1395 return m_autoLink;
1396}
1397
1338FolksPersona* QIndividual::primaryPersona()1398FolksPersona* QIndividual::primaryPersona()
1339{1399{
1340 Q_ASSERT(m_individual);1400 if (m_personas.size() > 0) {
13411401 return m_personas.begin().value();
1342 if (m_primaryPersona) {1402 } else {
1343 return m_primaryPersona;1403 return 0;
1344 }1404 }
1345
1346 GeeSet *personas = folks_individual_get_personas(m_individual);
1347 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
1348 FolksPersonaStore *primaryStore = folks_individual_aggregator_get_primary_store(m_aggregator);
1349
1350 while(m_primaryPersona == NULL && gee_iterator_next(iter)) {
1351 FolksPersona *persona = FOLKS_PERSONA(gee_iterator_get(iter));
1352 if(folks_persona_get_store(persona) == primaryStore) {
1353 m_primaryPersona = persona;
1354 g_object_ref (persona);
1355 }
1356 g_object_unref(persona);
1357 }
1358 g_object_unref(iter);
1359
1360 return m_primaryPersona;
1361}1405}
13621406
1363QtContacts::QContactDetail QIndividual::detailFromUri(QtContacts::QContactDetail::DetailType type, const QString &uri) const1407QtContacts::QContactDetail QIndividual::detailFromUri(QtContacts::QContactDetail::DetailType type, const QString &uri) const
13641408
=== modified file 'lib/qindividual.h'
--- lib/qindividual.h 2013-10-30 19:07:49 +0000
+++ lib/qindividual.h 2014-02-18 00:13:04 +0000
@@ -33,6 +33,8 @@
33{33{
34typedef GHashTable* (*ParseDetailsFunc)(GHashTable*, const QList<QtContacts::QContactDetail> &);34typedef GHashTable* (*ParseDetailsFunc)(GHashTable*, const QList<QtContacts::QContactDetail> &);
3535
36class UpdateContactRequest;
37
36class QIndividual38class QIndividual
37{39{
38public:40public:
@@ -46,20 +48,28 @@
46 bool update(const QtContacts::QContact &contact, QObject *object, const char *slot);48 bool update(const QtContacts::QContact &contact, QObject *object, const char *slot);
47 void setIndividual(FolksIndividual *individual);49 void setIndividual(FolksIndividual *individual);
48 FolksIndividual *individual() const;50 FolksIndividual *individual() const;
4951 QList<FolksPersona*> personas() const;
50 FolksPersona *getPersona(int index) const;
51 int personaCount() const;
52 void addListener(QObject *object, const char *slot);52 void addListener(QObject *object, const char *slot);
53 bool isValid() const;
54 void flush();
5355
54 static GHashTable *parseDetails(const QtContacts::QContact &contact);56 static GHashTable *parseDetails(const QtContacts::QContact &contact);
57
58 // enable or disable auto-link
59 static void enableAutoLink(bool flag);
60 static bool autoLinkEnabled();
61
55private:62private:
56 FolksIndividual *m_individual;63 FolksIndividual *m_individual;
57 FolksPersona *m_primaryPersona;
58 FolksIndividualAggregator *m_aggregator;64 FolksIndividualAggregator *m_aggregator;
59 QtContacts::QContact *m_contact;65 QtContacts::QContact *m_contact;
60 QMap<QString, QPair<QtContacts::QContactDetail, FolksAbstractFieldDetails*> > m_fieldsMap;66 UpdateContactRequest *m_currentUpdate;
61 QList<QPair<QObject*, QMetaMethod> > m_listeners;67 QList<QPair<QObject*, QMetaMethod> > m_listeners;
62 QMap<gpointer, QList<int> > m_notifyConnections;68 QMap<QString, FolksPersona*> m_personas;
69 QMap<FolksPersona*, QList<int> > m_notifyConnections;
70 QString m_id;
71 QMetaObject::Connection m_updateConnection;
72 static bool m_autoLink;
6373
64 QIndividual();74 QIndividual();
65 QIndividual(const QIndividual &);75 QIndividual(const QIndividual &);
@@ -68,6 +78,9 @@
6878
69 QMultiHash<QString, QString> parseDetails(FolksAbstractFieldDetails *details) const;79 QMultiHash<QString, QString> parseDetails(FolksAbstractFieldDetails *details) const;
70 void updateContact();80 void updateContact();
81 void updatePersonas();
82 void clearPersonas();
83 void clear();
7184
72 FolksPersona *primaryPersona();85 FolksPersona *primaryPersona();
73 QtContacts::QContactDetail detailFromUri(QtContacts::QContactDetail::DetailType type, const QString &uri) const;86 QtContacts::QContactDetail detailFromUri(QtContacts::QContactDetail::DetailType type, const QString &uri) const;
7487
=== modified file 'lib/update-contact-request.cpp'
--- lib/update-contact-request.cpp 2013-10-30 19:07:49 +0000
+++ lib/update-contact-request.cpp 2014-02-18 00:13:04 +0000
@@ -27,19 +27,16 @@
2727
28using namespace QtContacts;28using namespace QtContacts;
2929
30namespace {
31
32
33
34}
35
36namespace galera {30namespace galera {
3731
38UpdateContactRequest::UpdateContactRequest(QtContacts::QContact newContact, QIndividual *parent, QObject *listener, const char *slot)32UpdateContactRequest::UpdateContactRequest(QtContacts::QContact newContact, QIndividual *parent, QObject *listener, const char *slot)
39 : QObject(),33 : QObject(),
34 m_parent(parent),
35 m_object(listener),
36 m_currentPersona(0),
37 m_eventLoop(0),
40 m_newContact(newContact),38 m_newContact(newContact),
41 m_parent(parent),39 m_currentPersonaIndex(0)
42 m_object(listener)
43{40{
44 int slotIndex = listener->metaObject()->indexOfSlot(++slot);41 int slotIndex = listener->metaObject()->indexOfSlot(++slot);
45 if (slotIndex == -1) {42 if (slotIndex == -1) {
@@ -49,18 +46,67 @@
49 }46 }
50}47}
5148
49UpdateContactRequest::~UpdateContactRequest()
50{
51 // check if there is a operation running
52 if (m_currentPersona != 0) {
53 wait();
54 }
55}
56
52void UpdateContactRequest::invokeSlot(const QString &errorMessage)57void UpdateContactRequest::invokeSlot(const QString &errorMessage)
53{58{
54 if (m_slot.isValid()) {59 if (m_slot.isValid() && m_parent) {
55 m_slot.invoke(m_object, Q_ARG(galera::QIndividual*, m_parent), Q_ARG(QString, errorMessage));60 m_slot.invoke(m_object, Q_ARG(QString, m_parent->id()),
56 }61 Q_ARG(QString, errorMessage));
62 } else if (m_parent == 0) {
63 // the object was detached we need to destroy it
64 deleteLater();
65 }
66
67 if (m_eventLoop) {
68 m_eventLoop->quit();
69 }
70
57 Q_EMIT done(errorMessage);71 Q_EMIT done(errorMessage);
58}72}
5973
60void UpdateContactRequest::start()74void UpdateContactRequest::start()
61{75{
62 m_currentDetailType = QContactDetail::TypeAddress;76 m_currentDetailType = QContactDetail::TypeAddress;
63 updatePersona(1);77 m_personas = m_parent->personas();
78 m_originalContact = m_parent->contact();
79 m_currentPersonaIndex = 0;
80 updatePersona();
81}
82
83void UpdateContactRequest::wait()
84{
85 Q_ASSERT(m_eventLoop == 0);
86 QEventLoop eventLoop;
87 m_eventLoop = &eventLoop;
88 eventLoop.exec();
89 m_eventLoop = 0;
90}
91
92void UpdateContactRequest::deatach()
93{
94 m_parent = 0;
95}
96
97bool UpdateContactRequest::isEqual(const QtContacts::QContactDetail &detailA,
98 const QtContacts::QContactDetail &detailB)
99{
100 if (detailA.type() != detailB.type()) {
101 return false;
102 }
103
104 switch(detailA.type()) {
105 case QContactDetail::TypeFavorite:
106 return detailA.value(QContactFavorite::FieldFavorite) == detailB.value(QContactFavorite::FieldFavorite);
107 default:
108 return (detailA == detailB);
109 }
64}110}
65111
66bool UpdateContactRequest::isEqual(QList<QtContacts::QContactDetail> listA,112bool UpdateContactRequest::isEqual(QList<QtContacts::QContactDetail> listA,
@@ -71,7 +117,7 @@
71 }117 }
72118
73 for(int i=0; i < listA.size(); i++) {119 for(int i=0; i < listA.size(); i++) {
74 if (listA[i] != listB[i]) {120 if (!isEqual(listA[i], listB[i])) {
75 return false;121 return false;
76 }122 }
77 }123 }
@@ -116,7 +162,8 @@
116 }162 }
117163
118 Q_FOREACH(QContactDetail det, contact.details(type)) {164 Q_FOREACH(QContactDetail det, contact.details(type)) {
119 if ((includeEmptyPersona && det.detailUri().isEmpty()) || checkPersona(det, persona)) {165 if ((includeEmptyPersona && det.detailUri().isEmpty()) ||
166 checkPersona(det, persona)) {
120 if (!det.isEmpty()) {167 if (!det.isEmpty()) {
121 personaDetails << det;168 personaDetails << det;
122 if (pref && det == globalPref) {169 if (pref && det == globalPref) {
@@ -132,19 +179,19 @@
132 int persona,179 int persona,
133 QtContacts::QContactDetail *pref) const180 QtContacts::QContactDetail *pref) const
134{181{
135 return detailsFromPersona(m_parent->contact(), type, persona, false, pref);182 return detailsFromPersona(m_originalContact, type, persona, false, pref);
136}183}
137184
138QList<QtContacts::QContactDetail> UpdateContactRequest::detailsFromPersona(QtContacts::QContactDetail::DetailType type,185QList<QtContacts::QContactDetail> UpdateContactRequest::detailsFromPersona(QtContacts::QContactDetail::DetailType type,
139 int persona,186 int persona,
140 QtContacts::QContactDetail *pref) const187 QtContacts::QContactDetail *pref) const
141{188{
142 return detailsFromPersona(m_newContact, type, persona, true, pref);189 // only return new details for the first persona, this will avoid to create the details for all personas
190 return detailsFromPersona(m_newContact, type, persona, (persona==1), pref);
143}191}
144192
145void UpdateContactRequest::updateAddress()193void UpdateContactRequest::updateAddress()
146{194{
147 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
148 QContactDetail originalPref;195 QContactDetail originalPref;
149 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeAddress,196 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeAddress,
150 m_currentPersonaIndex,197 m_currentPersonaIndex,
@@ -154,8 +201,8 @@
154 m_currentPersonaIndex,201 m_currentPersonaIndex,
155 &prefDetail);202 &prefDetail);
156203
157 if (persona &&204 if (m_currentPersona &&
158 FOLKS_IS_POSTAL_ADDRESS_DETAILS(persona) &&205 FOLKS_IS_POSTAL_ADDRESS_DETAILS(m_currentPersona) &&
159 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {206 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
160 qDebug() << "Adderess diff";207 qDebug() << "Adderess diff";
161 GeeSet *newSet = SET_AFD_NEW();208 GeeSet *newSet = SET_AFD_NEW();
@@ -188,7 +235,7 @@
188 g_object_unref(pa);235 g_object_unref(pa);
189 }236 }
190237
191 folks_postal_address_details_change_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(persona),238 folks_postal_address_details_change_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(m_currentPersona),
192 newSet,239 newSet,
193 (GAsyncReadyCallback) updateDetailsDone,240 (GAsyncReadyCallback) updateDetailsDone,
194 this);241 this);
@@ -200,12 +247,15 @@
200247
201void UpdateContactRequest::updateAvatar()248void UpdateContactRequest::updateAvatar()
202{249{
203 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
204 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeAvatar, m_currentPersonaIndex, 0);250 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeAvatar, m_currentPersonaIndex, 0);
205 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeAvatar, m_currentPersonaIndex, 0);251 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeAvatar, m_currentPersonaIndex, 0);
206252
207 if (persona && FOLKS_IS_AVATAR_DETAILS(persona) && !isEqual(originalDetails, newDetails)) {253 if (m_currentPersona &&
208 qDebug() << "avatar diff";254 FOLKS_IS_AVATAR_DETAILS(m_currentPersona) &&
255 !isEqual(originalDetails, newDetails)) {
256 qDebug() << "avatar diff:"
257 << "\n\t" << originalDetails.size() << (originalDetails.size() > 0 ? originalDetails[0] : QContactDetail()) << "\n"
258 << "\n\t" << newDetails.size() << (newDetails.size() > 0 ? newDetails[0] : QContactDetail());
209 //Only supports one avatar259 //Only supports one avatar
210 QUrl avatarUri;260 QUrl avatarUri;
211 if (newDetails.count()) {261 if (newDetails.count()) {
@@ -225,7 +275,7 @@
225 }275 }
226 }276 }
227277
228 folks_avatar_details_change_avatar(FOLKS_AVATAR_DETAILS(persona),278 folks_avatar_details_change_avatar(FOLKS_AVATAR_DETAILS(m_currentPersona),
229 G_LOADABLE_ICON(avatarFileIcon),279 G_LOADABLE_ICON(avatarFileIcon),
230 (GAsyncReadyCallback) updateDetailsDone,280 (GAsyncReadyCallback) updateDetailsDone,
231 this);281 this);
@@ -239,11 +289,12 @@
239289
240void UpdateContactRequest::updateBirthday()290void UpdateContactRequest::updateBirthday()
241{291{
242 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
243 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeBirthday, m_currentPersonaIndex, 0);292 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeBirthday, m_currentPersonaIndex, 0);
244 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeBirthday, m_currentPersonaIndex, 0);293 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeBirthday, m_currentPersonaIndex, 0);
245294
246 if (persona && FOLKS_IS_BIRTHDAY_DETAILS(persona) && !isEqual(originalDetails, newDetails)) {295 if (m_currentPersona &&
296 FOLKS_IS_BIRTHDAY_DETAILS(m_currentPersona) &&
297 !isEqual(originalDetails, newDetails)) {
247 qDebug() << "birthday diff";298 qDebug() << "birthday diff";
248 //Only supports one birthday299 //Only supports one birthday
249 QDateTime dateTimeBirthday;300 QDateTime dateTimeBirthday;
@@ -258,7 +309,7 @@
258 if (dateTimeBirthday.isValid()) {309 if (dateTimeBirthday.isValid()) {
259 dateTime = g_date_time_new_from_unix_utc(dateTimeBirthday.toMSecsSinceEpoch() / 1000);310 dateTime = g_date_time_new_from_unix_utc(dateTimeBirthday.toMSecsSinceEpoch() / 1000);
260 }311 }
261 folks_birthday_details_change_birthday(FOLKS_BIRTHDAY_DETAILS(persona),312 folks_birthday_details_change_birthday(FOLKS_BIRTHDAY_DETAILS(m_currentPersona),
262 dateTime,313 dateTime,
263 (GAsyncReadyCallback) updateDetailsDone,314 (GAsyncReadyCallback) updateDetailsDone,
264 this);315 this);
@@ -272,12 +323,15 @@
272323
273void UpdateContactRequest::updateFullName()324void UpdateContactRequest::updateFullName()
274{325{
275 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
276 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeDisplayLabel, m_currentPersonaIndex, 0);326 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeDisplayLabel, m_currentPersonaIndex, 0);
277 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeDisplayLabel, m_currentPersonaIndex, 0);327 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeDisplayLabel, m_currentPersonaIndex, 0);
278328
279 if (persona && FOLKS_IS_NAME_DETAILS(persona) && !isEqual(originalDetails, newDetails)) {329 if (m_currentPersona &&
280 qDebug() << "Full Name diff";330 FOLKS_IS_NAME_DETAILS(m_currentPersona) &&
331 !isEqual(originalDetails, newDetails)) {
332 qDebug() << "Full Name diff:"
333 << "\n\t" << originalDetails.size() << (originalDetails.size() > 0 ? originalDetails[0] : QContactDetail()) << "\n"
334 << "\n\t" << newDetails.size() << (newDetails.size() > 0 ? newDetails[0] : QContactDetail());
281 //Only supports one fullName335 //Only supports one fullName
282 QString fullName;336 QString fullName;
283 if (newDetails.count()) {337 if (newDetails.count()) {
@@ -286,7 +340,7 @@
286 }340 }
287341
288 QByteArray fullNameUtf8 = fullName.toUtf8();342 QByteArray fullNameUtf8 = fullName.toUtf8();
289 folks_name_details_change_full_name(FOLKS_NAME_DETAILS(persona),343 folks_name_details_change_full_name(FOLKS_NAME_DETAILS(m_currentPersona),
290 fullNameUtf8.constData(),344 fullNameUtf8.constData(),
291 (GAsyncReadyCallback) updateDetailsDone,345 (GAsyncReadyCallback) updateDetailsDone,
292 this);346 this);
@@ -297,7 +351,6 @@
297351
298void UpdateContactRequest::updateEmail()352void UpdateContactRequest::updateEmail()
299{353{
300 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
301 QContactDetail originalPref;354 QContactDetail originalPref;
302 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeEmailAddress,355 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeEmailAddress,
303 m_currentPersonaIndex,356 m_currentPersonaIndex,
@@ -308,8 +361,8 @@
308 m_currentPersonaIndex,361 m_currentPersonaIndex,
309 &prefDetail);362 &prefDetail);
310363
311 if (persona &&364 if (m_currentPersona &&
312 FOLKS_IS_EMAIL_DETAILS(persona) &&365 FOLKS_IS_EMAIL_DETAILS(m_currentPersona) &&
313 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {366 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
314 qDebug() << "email diff";367 qDebug() << "email diff";
315 GeeSet *newSet = SET_AFD_NEW();368 GeeSet *newSet = SET_AFD_NEW();
@@ -325,7 +378,7 @@
325 g_object_unref(field);378 g_object_unref(field);
326 }379 }
327380
328 folks_email_details_change_email_addresses(FOLKS_EMAIL_DETAILS(persona),381 folks_email_details_change_email_addresses(FOLKS_EMAIL_DETAILS(m_currentPersona),
329 newSet,382 newSet,
330 (GAsyncReadyCallback) updateDetailsDone,383 (GAsyncReadyCallback) updateDetailsDone,
331 this);384 this);
@@ -337,11 +390,12 @@
337390
338void UpdateContactRequest::updateName()391void UpdateContactRequest::updateName()
339{392{
340 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
341 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeName, m_currentPersonaIndex, 0);393 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeName, m_currentPersonaIndex, 0);
342 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeName, m_currentPersonaIndex, 0);394 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeName, m_currentPersonaIndex, 0);
343395
344 if (persona && FOLKS_IS_NAME_DETAILS(persona) && !isEqual(originalDetails, newDetails)) {396 if (m_currentPersona &&
397 FOLKS_IS_NAME_DETAILS(m_currentPersona) &&
398 !isEqual(originalDetails, newDetails)) {
345 qDebug() << "Name diff";399 qDebug() << "Name diff";
346 //Only supports one fullName400 //Only supports one fullName
347 FolksStructuredName *sn = 0;401 FolksStructuredName *sn = 0;
@@ -360,7 +414,7 @@
360 suffix.constData());414 suffix.constData());
361 }415 }
362416
363 folks_name_details_change_structured_name(FOLKS_NAME_DETAILS(persona),417 folks_name_details_change_structured_name(FOLKS_NAME_DETAILS(m_currentPersona),
364 sn,418 sn,
365 (GAsyncReadyCallback) updateDetailsDone,419 (GAsyncReadyCallback) updateDetailsDone,
366 this);420 this);
@@ -374,11 +428,12 @@
374428
375void UpdateContactRequest::updateNickname()429void UpdateContactRequest::updateNickname()
376{430{
377 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
378 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeNickname, m_currentPersonaIndex, 0);431 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeNickname, m_currentPersonaIndex, 0);
379 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeNickname, m_currentPersonaIndex, 0);432 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeNickname, m_currentPersonaIndex, 0);
380433
381 if (persona && FOLKS_IS_NAME_DETAILS(persona) && !isEqual(originalDetails, newDetails)) {434 if (m_currentPersona &&
435 FOLKS_IS_NAME_DETAILS(m_currentPersona) &&
436 !isEqual(originalDetails, newDetails)) {
382 qDebug() << "Nickname diff";437 qDebug() << "Nickname diff";
383 //Only supports one fullName438 //Only supports one fullName
384 QString nicknameValue;439 QString nicknameValue;
@@ -388,7 +443,7 @@
388 }443 }
389444
390 QByteArray nicknameValueUtf8 = nicknameValue.toUtf8();445 QByteArray nicknameValueUtf8 = nicknameValue.toUtf8();
391 folks_name_details_change_nickname(FOLKS_NAME_DETAILS(persona),446 folks_name_details_change_nickname(FOLKS_NAME_DETAILS(m_currentPersona),
392 nicknameValueUtf8.constData(),447 nicknameValueUtf8.constData(),
393 (GAsyncReadyCallback) updateDetailsDone,448 (GAsyncReadyCallback) updateDetailsDone,
394 this);449 this);
@@ -399,14 +454,13 @@
399454
400void UpdateContactRequest::updateNote()455void UpdateContactRequest::updateNote()
401{456{
402 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
403 QContactDetail originalPref;457 QContactDetail originalPref;
404 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeNote, m_currentPersonaIndex, &originalPref);458 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeNote, m_currentPersonaIndex, &originalPref);
405 QContactDetail prefDetail;459 QContactDetail prefDetail;
406 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeNote, m_currentPersonaIndex, &prefDetail);460 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeNote, m_currentPersonaIndex, &prefDetail);
407461
408 if (persona &&462 if (m_currentPersona &&
409 FOLKS_IS_EMAIL_DETAILS(persona) &&463 FOLKS_IS_EMAIL_DETAILS(m_currentPersona) &&
410 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {464 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
411 qDebug() << "notes diff";465 qDebug() << "notes diff";
412 GeeSet *newSet = SET_AFD_NEW();466 GeeSet *newSet = SET_AFD_NEW();
@@ -422,7 +476,7 @@
422 g_object_unref(field);476 g_object_unref(field);
423 }477 }
424478
425 folks_note_details_change_notes(FOLKS_NOTE_DETAILS(persona),479 folks_note_details_change_notes(FOLKS_NOTE_DETAILS(m_currentPersona),
426 newSet,480 newSet,
427 (GAsyncReadyCallback) updateDetailsDone,481 (GAsyncReadyCallback) updateDetailsDone,
428 this);482 this);
@@ -434,7 +488,6 @@
434488
435void UpdateContactRequest::updateOnlineAccount()489void UpdateContactRequest::updateOnlineAccount()
436{490{
437 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
438 QContactDetail originalPref;491 QContactDetail originalPref;
439 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeOnlineAccount,492 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeOnlineAccount,
440 m_currentPersonaIndex,493 m_currentPersonaIndex,
@@ -444,8 +497,8 @@
444 m_currentPersonaIndex,497 m_currentPersonaIndex,
445 &prefDetail);498 &prefDetail);
446499
447 if (persona &&500 if (m_currentPersona &&
448 FOLKS_IS_IM_DETAILS(persona) &&501 FOLKS_IS_IM_DETAILS(m_currentPersona) &&
449 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {502 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
450 qDebug() << "OnlineAccounts diff";503 qDebug() << "OnlineAccounts diff";
451 GeeMultiMap *imMap = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);504 GeeMultiMap *imMap = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);
@@ -467,7 +520,7 @@
467 }520 }
468 }521 }
469522
470 folks_im_details_change_im_addresses(FOLKS_IM_DETAILS(persona),523 folks_im_details_change_im_addresses(FOLKS_IM_DETAILS(m_currentPersona),
471 imMap,524 imMap,
472 (GAsyncReadyCallback) updateDetailsDone,525 (GAsyncReadyCallback) updateDetailsDone,
473 this);526 this);
@@ -480,7 +533,6 @@
480533
481void UpdateContactRequest::updateOrganization()534void UpdateContactRequest::updateOrganization()
482{535{
483 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
484 QContactDetail originalPref;536 QContactDetail originalPref;
485 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeOrganization,537 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeOrganization,
486 m_currentPersonaIndex,538 m_currentPersonaIndex,
@@ -490,8 +542,8 @@
490 m_currentPersonaIndex,542 m_currentPersonaIndex,
491 &prefDetail);543 &prefDetail);
492544
493 if (persona &&545 if (m_currentPersona &&
494 FOLKS_IS_ROLE_DETAILS(persona) &&546 FOLKS_IS_ROLE_DETAILS(m_currentPersona) &&
495 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {547 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
496 qDebug() << "Organization diff";548 qDebug() << "Organization diff";
497 GeeSet *newSet = SET_AFD_NEW();549 GeeSet *newSet = SET_AFD_NEW();
@@ -515,7 +567,7 @@
515 g_object_unref(roleValue);567 g_object_unref(roleValue);
516 }568 }
517569
518 folks_role_details_change_roles(FOLKS_ROLE_DETAILS(persona),570 folks_role_details_change_roles(FOLKS_ROLE_DETAILS(m_currentPersona),
519 newSet,571 newSet,
520 (GAsyncReadyCallback) updateDetailsDone,572 (GAsyncReadyCallback) updateDetailsDone,
521 this);573 this);
@@ -528,7 +580,6 @@
528580
529void UpdateContactRequest::updatePhone()581void UpdateContactRequest::updatePhone()
530{582{
531 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
532 QContactDetail originalPref;583 QContactDetail originalPref;
533 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypePhoneNumber,584 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypePhoneNumber,
534 m_currentPersonaIndex,585 m_currentPersonaIndex,
@@ -538,10 +589,13 @@
538 m_currentPersonaIndex,589 m_currentPersonaIndex,
539 &prefDetail);590 &prefDetail);
540591
541 if (persona &&592 if (m_currentPersona &&
542 FOLKS_IS_PHONE_DETAILS(persona) &&593 FOLKS_IS_PHONE_DETAILS(m_currentPersona) &&
543 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {594 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
544 qDebug() << "Phone diff";595 qDebug() << "Phone diff:"
596 << "\n\t" << originalDetails.size() << (originalDetails.size() > 0 ? originalDetails[0] : QContactDetail()) << "\n"
597 << "\n\t" << newDetails.size() << (newDetails.size() > 0 ? newDetails[0] : QContactDetail());
598
545 GeeSet *newSet = SET_AFD_NEW();599 GeeSet *newSet = SET_AFD_NEW();
546600
547 Q_FOREACH(QContactDetail newDetail, newDetails) {601 Q_FOREACH(QContactDetail newDetail, newDetails) {
@@ -555,7 +609,7 @@
555 g_object_unref(field);609 g_object_unref(field);
556 }610 }
557611
558 folks_phone_details_change_phone_numbers(FOLKS_PHONE_DETAILS(persona),612 folks_phone_details_change_phone_numbers(FOLKS_PHONE_DETAILS(m_currentPersona),
559 newSet,613 newSet,
560 (GAsyncReadyCallback) updateDetailsDone,614 (GAsyncReadyCallback) updateDetailsDone,
561 this);615 this);
@@ -567,7 +621,6 @@
567621
568void UpdateContactRequest::updateUrl()622void UpdateContactRequest::updateUrl()
569{623{
570 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
571 QContactDetail originalPref;624 QContactDetail originalPref;
572 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeUrl,625 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeUrl,
573 m_currentPersonaIndex,626 m_currentPersonaIndex,
@@ -578,8 +631,8 @@
578 m_currentPersonaIndex,631 m_currentPersonaIndex,
579 &prefDetail);632 &prefDetail);
580633
581 if (persona &&634 if (m_currentPersona &&
582 FOLKS_IS_PHONE_DETAILS(persona) &&635 FOLKS_IS_URL_DETAILS(m_currentPersona) &&
583 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {636 !isEqual(originalDetails, originalPref, newDetails, prefDetail)) {
584 qDebug() << "Url diff";637 qDebug() << "Url diff";
585 GeeSet *newSet = SET_AFD_NEW();638 GeeSet *newSet = SET_AFD_NEW();
@@ -595,7 +648,7 @@
595 g_object_unref(field);648 g_object_unref(field);
596 }649 }
597650
598 folks_url_details_change_urls(FOLKS_URL_DETAILS(persona),651 folks_url_details_change_urls(FOLKS_URL_DETAILS(m_currentPersona),
599 newSet,652 newSet,
600 (GAsyncReadyCallback) updateDetailsDone,653 (GAsyncReadyCallback) updateDetailsDone,
601 this);654 this);
@@ -607,19 +660,23 @@
607660
608void UpdateContactRequest::updateFavorite()661void UpdateContactRequest::updateFavorite()
609{662{
610 FolksPersona *persona = m_parent->getPersona(m_currentPersonaIndex);
611 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeFavorite, m_currentPersonaIndex, 0);663 QList<QContactDetail> originalDetails = originalDetailsFromPersona(QContactDetail::TypeFavorite, m_currentPersonaIndex, 0);
612 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeFavorite, m_currentPersonaIndex, 0);664 QList<QContactDetail> newDetails = detailsFromPersona(QContactDetail::TypeFavorite, m_currentPersonaIndex, 0);
613665
614 if (persona && FOLKS_IS_FAVOURITE_DETAILS(persona) && !isEqual(originalDetails, newDetails)) {666 if (m_currentPersona &&
615 qDebug() << "Favorite diff";667 FOLKS_IS_FAVOURITE_DETAILS(m_currentPersona) &&
668 !isEqual(originalDetails, newDetails)) {
669 qDebug() << "Favorite diff:"
670 << "\n\t" << originalDetails.size() << (originalDetails.size() > 0 ? originalDetails[0] : QContactDetail()) << "\n"
671 << "\n\t" << newDetails.size() << (newDetails.size() > 0 ? newDetails[0] : QContactDetail());
672
616 //Only supports one fullName673 //Only supports one fullName
617 bool isFavorite = false;674 bool isFavorite = false;
618 if (newDetails.count()) {675 if (newDetails.count()) {
619 QContactFavorite favorite = static_cast<QContactFavorite>(newDetails[0]);676 QContactFavorite favorite = static_cast<QContactFavorite>(newDetails[0]);
620 isFavorite = favorite.isFavorite();677 isFavorite = favorite.isFavorite();
621 }678 }
622 folks_favourite_details_change_is_favourite(FOLKS_FAVOURITE_DETAILS(persona),679 folks_favourite_details_change_is_favourite(FOLKS_FAVOURITE_DETAILS(m_currentPersona),
623 isFavorite,680 isFavorite,
624 (GAsyncReadyCallback) updateDetailsDone,681 (GAsyncReadyCallback) updateDetailsDone,
625 this);682 this);
@@ -628,14 +685,44 @@
628 }685 }
629}686}
630687
631void UpdateContactRequest::updatePersona(int index)688void UpdateContactRequest::updatePersona()
632{689{
633 if (index > m_parent->personaCount()) {690 if (m_personas.size() <= m_currentPersonaIndex) {
691 m_currentPersona = 0;
692 if (m_parent) {
693 m_parent->flush();
694 }
634 invokeSlot();695 invokeSlot();
635 } else {696 } else {
636 m_currentPersonaIndex = index;697 m_currentPersona = m_personas[m_currentPersonaIndex];
637 m_currentDetailType = QContactDetail::TypeUndefined;698 m_currentDetailType = QContactDetail::TypeUndefined;
638 updateDetailsDone(0, 0, this);699 m_currentPersonaIndex++;
700
701 if (QIndividual::autoLinkEnabled()) {
702 updateDetailsDone(0, 0, this);
703 } else {
704 // all personas edited by the user will have the auto link disabled
705 GeeSet *antiLinks;
706 antiLinks = GEE_SET(gee_hash_set_new(G_TYPE_STRING,
707 (GBoxedCopyFunc) g_strdup,
708 g_free,
709 NULL, NULL, NULL, NULL, NULL, NULL));
710
711 GeeSet *oldLinks = folks_anti_linkable_get_anti_links(FOLKS_ANTI_LINKABLE(m_currentPersona));
712 if (oldLinks &&
713 gee_collection_contains(GEE_COLLECTION(antiLinks), "*")) {
714 updateDetailsDone(0, 0, this);
715 return;
716 } else if (oldLinks) {
717 gee_collection_add_all(GEE_COLLECTION(antiLinks), GEE_COLLECTION(oldLinks));
718 }
719 gee_collection_add(GEE_COLLECTION(antiLinks), "*");
720
721 folks_anti_linkable_change_anti_links(FOLKS_ANTI_LINKABLE(m_currentPersona),
722 antiLinks,
723 (GAsyncReadyCallback) folksAddAntiLinksDone,
724 this);
725 }
639 }726 }
640}727}
641728
@@ -780,8 +867,9 @@
780 updateDetailsDone(0, 0, self);867 updateDetailsDone(0, 0, self);
781 break;868 break;
782 case QContactDetail::TypeVersion:869 case QContactDetail::TypeVersion:
783 self->m_currentPersonaIndex += 1;870 g_object_unref(self->m_currentPersona);
784 self->updatePersona(self->m_currentPersonaIndex);871 self->m_currentPersona = 0;
872 self->updatePersona();
785 break;873 break;
786 default:874 default:
787 qWarning() << "Update not implemented for" << self->m_currentDetailType;875 qWarning() << "Update not implemented for" << self->m_currentDetailType;
@@ -790,4 +878,17 @@
790 }878 }
791}879}
792880
881void UpdateContactRequest::folksAddAntiLinksDone(FolksAntiLinkable *antilinkable,
882 GAsyncResult *result,
883 UpdateContactRequest *self)
884{
885 GError *error = 0;
886 folks_anti_linkable_change_anti_links_finish(antilinkable, result, &error);
887 if (error) {
888 qWarning() << "Error during the anti link operation:" << error->message;
889 g_error_free(error);
890 }
891 updateDetailsDone(0, 0, self);
793}892}
893
894} // namespace
794895
=== modified file 'lib/update-contact-request.h'
--- lib/update-contact-request.h 2013-10-30 19:07:49 +0000
+++ lib/update-contact-request.h 2014-02-18 00:13:04 +0000
@@ -23,6 +23,7 @@
23#include <QtCore/QString>23#include <QtCore/QString>
24#include <QtCore/QList>24#include <QtCore/QList>
25#include <QtCore/QMetaMethod>25#include <QtCore/QMetaMethod>
26#include <QtCore/QEventLoop>
2627
27#include <QtContacts/QContact>28#include <QtContacts/QContact>
2829
@@ -38,20 +39,26 @@
3839
39public:40public:
40 UpdateContactRequest(QtContacts::QContact newContact, QIndividual *parent, QObject *listener, const char *slot);41 UpdateContactRequest(QtContacts::QContact newContact, QIndividual *parent, QObject *listener, const char *slot);
4142 ~UpdateContactRequest();
42 void start();43 void start();
44 void wait();
45 void deatach();
4346
44Q_SIGNALS:47Q_SIGNALS:
45 void done(const QString &errorMessage);48 void done(const QString &errorMessage);
4649
47private:50private:
51 QIndividual *m_parent;
52 QObject *m_object;
53 FolksPersona *m_currentPersona;
54 QEventLoop *m_eventLoop;
55
56 QList<FolksPersona*> m_personas;
57 QtContacts::QContact m_originalContact;
48 QtContacts::QContact m_newContact;58 QtContacts::QContact m_newContact;
49 int m_currentDetailType;59 int m_currentDetailType;
60 QMetaMethod m_slot;
50 int m_currentPersonaIndex;61 int m_currentPersonaIndex;
51 int m_maxPersona;
52 QIndividual *m_parent;
53 QObject *m_object;
54 QMetaMethod m_slot;
5562
56 void invokeSlot(const QString &errorMessage = QString());63 void invokeSlot(const QString &errorMessage = QString());
5764
@@ -61,6 +68,8 @@
61 const QtContacts::QContactDetail &prefB);68 const QtContacts::QContactDetail &prefB);
62 static bool isEqual(QList<QtContacts::QContactDetail> listA,69 static bool isEqual(QList<QtContacts::QContactDetail> listA,
63 QList<QtContacts::QContactDetail> listB);70 QList<QtContacts::QContactDetail> listB);
71 static bool isEqual(const QtContacts::QContactDetail &detailA,
72 const QtContacts::QContactDetail &detailB);
64 static bool checkPersona(QtContacts::QContactDetail &det, int persona);73 static bool checkPersona(QtContacts::QContactDetail &det, int persona);
65 static QList<QtContacts::QContactDetail> detailsFromPersona(const QtContacts::QContact &contact,74 static QList<QtContacts::QContactDetail> detailsFromPersona(const QtContacts::QContact &contact,
66 QtContacts::QContactDetail::DetailType type,75 QtContacts::QContactDetail::DetailType type,
@@ -74,7 +83,8 @@
74 int persona,83 int persona,
75 QtContacts::QContactDetail *pref) const;84 QtContacts::QContactDetail *pref) const;
7685
77 void updatePersona(int index);86
87 void updatePersona();
78 void updateAddress();88 void updateAddress();
79 void updateAvatar();89 void updateAvatar();
80 void updateBirthday();90 void updateBirthday();
@@ -94,7 +104,7 @@
94 GAsyncResult *result);104 GAsyncResult *result);
95105
96 static void updateDetailsDone(GObject *detail, GAsyncResult *result, gpointer userdata);106 static void updateDetailsDone(GObject *detail, GAsyncResult *result, gpointer userdata);
97107 static void folksAddAntiLinksDone(FolksAntiLinkable *antilinkable, GAsyncResult *result, UpdateContactRequest *self);
98};108};
99109
100}110}
101111
=== modified file 'lib/view.cpp'
--- lib/view.cpp 2013-10-30 19:07:49 +0000
+++ lib/view.cpp 2014-02-18 00:13:04 +0000
@@ -108,11 +108,13 @@
108protected:108protected:
109 void run()109 void run()
110 {110 {
111 m_allContacts->lock();
111 Q_FOREACH(ContactEntry *entry, m_allContacts->values())112 Q_FOREACH(ContactEntry *entry, m_allContacts->values())
112 {113 {
113 m_stoppedLock.lockForRead();114 m_stoppedLock.lockForRead();
114 if (m_stopped) {115 if (m_stopped) {
115 m_stoppedLock.unlock();116 m_stoppedLock.unlock();
117 m_allContacts->unlock();
116 return;118 return;
117 }119 }
118 m_stoppedLock.unlock();120 m_stoppedLock.unlock();
@@ -121,8 +123,8 @@
121 m_contacts << entry;123 m_contacts << entry;
122 }124 }
123 }125 }
124
125 chageSort(m_sortClause);126 chageSort(m_sortClause);
127 m_allContacts->unlock();
126 }128 }
127129
128private:130private:
129131
=== modified file 'tests/unittest/CMakeLists.txt'
--- tests/unittest/CMakeLists.txt 2013-11-01 01:10:12 +0000
+++ tests/unittest/CMakeLists.txt 2014-02-18 00:13:04 +0000
@@ -70,6 +70,9 @@
7070
71 declare_test(addressbook-test True ${BASE_CLIENT_TEST_SRC})71 declare_test(addressbook-test True ${BASE_CLIENT_TEST_SRC})
72 declare_test(service-life-cycle-test True ${BASE_CLIENT_TEST_SRC})72 declare_test(service-life-cycle-test True ${BASE_CLIENT_TEST_SRC})
73 # Disable test until the new folks arrive on jenkins
74 #declare_test(contact-link-test True ${BASE_CLIENT_TEST_SRC})
75
73elseif()76elseif()
74 message(STATUS "DBus test runner not found. Some tests will be disabled")77 message(STATUS "DBus test runner not found. Some tests will be disabled")
75endif()78endif()
7679
=== modified file 'tests/unittest/addressbook-test.cpp'
--- tests/unittest/addressbook-test.cpp 2013-12-13 19:06:57 +0000
+++ tests/unittest/addressbook-test.cpp 2014-02-18 00:13:04 +0000
@@ -111,7 +111,7 @@
111 m_resultBasicVcard = QStringLiteral("BEGIN:VCARD\r\n"111 m_resultBasicVcard = QStringLiteral("BEGIN:VCARD\r\n"
112 "VERSION:3.0\r\n"112 "VERSION:3.0\r\n"
113 "UID:%1\r\n"113 "UID:%1\r\n"
114 "CLIENTPIDMAP:1;dummy:dummy-store:0\r\n"114 "CLIENTPIDMAP:1;dummy:dummy-store:%2\r\n"
115 "N;PID=1.1:Tal;Fulano_;de;;\r\n"115 "N;PID=1.1:Tal;Fulano_;de;;\r\n"
116 "FN;PID=1.1:Fulano_ Tal\r\n"116 "FN;PID=1.1:Fulano_ Tal\r\n"
117 "X-QTPROJECT-FAVORITE;PID=1.1:false;0\r\n"117 "X-QTPROJECT-FAVORITE;PID=1.1:false;0\r\n"
@@ -213,7 +213,7 @@
213213
214 // user returned id to fill the new vcard214 // user returned id to fill the new vcard
215 QString newContactId = reply.value();215 QString newContactId = reply.value();
216 QString newVcard = m_resultBasicVcard.arg(newContactId);216 QString newVcard = m_resultBasicVcard.arg(newContactId).arg(0);
217217
218 // try create a contact with the same id218 // try create a contact with the same id
219 QDBusReply<QString> reply2 = m_serverIface->call("createContact", newVcard, "dummy-store");219 QDBusReply<QString> reply2 = m_serverIface->call("createContact", newVcard, "dummy-store");
@@ -267,6 +267,46 @@
267 QDBusReply<QStringList> replyList = m_dummyIface->call("listContacts");267 QDBusReply<QStringList> replyList = m_dummyIface->call("listContacts");
268 QCOMPARE(replyList.value().count(), 0);268 QCOMPARE(replyList.value().count(), 0);
269 }269 }
270
271 void testUpdateContact()
272 {
273 // create a basic contact
274 QDBusReply<QString> replyAdd = m_serverIface->call("createContact", m_basicVcard, "dummy-store");
275 QString newContactId = replyAdd.value();
276
277 // update the contact phone number
278 QString vcard = m_resultBasicVcard.arg(newContactId).arg(3);
279 vcard = vcard.replace("8888888", "0000000");
280 QList<QtContacts::QContact> contacts = galera::VCardParser::vcardToContact(QStringList() << vcard);
281 QtContacts::QContact contactUpdated = contacts[0];
282
283 // spy 'contactsUpdated' signal
284 QSignalSpy updateContactSpy(m_serverIface, SIGNAL(contactsUpdated(const QStringList &)));
285 QDBusReply<QStringList> replyUpdate = m_serverIface->call("updateContacts", QStringList() << vcard);
286 QStringList result = replyUpdate.value();
287 QCOMPARE(result.size(), 1);
288
289 // check if contact returned by update function contains the new data
290 contacts = galera::VCardParser::vcardToContact(result);
291 QtContacts::QContact contactUpdatedResult = contacts[0];
292 compareContact(contactUpdatedResult, contactUpdated);
293
294 // check if the 'contactsUpdated' signal was fired with the correct args
295 QTRY_COMPARE(updateContactSpy.count(), 1);
296 QList<QVariant> args = updateContactSpy.takeFirst();
297 QCOMPARE(args.count(), 1);
298 QStringList ids = args[0].toStringList();
299 QCOMPARE(ids[0], newContactId);
300
301 // check if the contact was updated into the backend
302 QDBusReply<QStringList> replyList = m_dummyIface->call("listContacts");
303 result = replyList.value();
304 QCOMPARE(result.count(), 1);
305
306 contacts = galera::VCardParser::vcardToContact(result);
307 contactUpdatedResult = contacts[0];
308 compareContact(contactUpdatedResult, contactUpdated);
309 }
270};310};
271311
272QTEST_MAIN(AddressBookTest)312QTEST_MAIN(AddressBookTest)
273313
=== added file 'tests/unittest/contact-link-test.cpp'
--- tests/unittest/contact-link-test.cpp 1970-01-01 00:00:00 +0000
+++ tests/unittest/contact-link-test.cpp 2014-02-18 00:13:04 +0000
@@ -0,0 +1,100 @@
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 "base-client-test.h"
20#include "lib/source.h"
21#include "lib/qindividual.h"
22#include "common/dbus-service-defs.h"
23#include "common/vcard-parser.h"
24
25#include <QObject>
26#include <QtDBus>
27#include <QtTest>
28#include <QDebug>
29#include <QtVersit>
30
31class ContactLinkTest : public BaseClientTest
32{
33 Q_OBJECT
34private:
35 QString m_vcard;
36
37private Q_SLOTS:
38 void initTestCase()
39 {
40 BaseClientTest::initTestCase();
41 m_vcard = QStringLiteral("BEGIN:VCARD\n"
42 "VERSION:3.0\n"
43 "N:tal;fulano_;de;;\n"
44 "EMAIL:email@ubuntu.com\n"
45 "TEL;PID=1.1;TYPE=ISDN:33331410\n"
46 "END:VCARD");
47 }
48
49 void testCreateContactWithSameEmail()
50 {
51 // call create contact
52 QDBusReply<QString> reply = m_serverIface->call("createContact", m_vcard, "dummy-store");
53
54 // check if the returned id is valid
55 QString contactAId = reply.value();
56 QVERIFY(!contactAId.isEmpty());
57
58 QString vcardB = m_vcard.replace("fulano", "contact");
59 reply = m_serverIface->call("createContact", vcardB, "dummy-store");
60
61 // check if the returned id is valid
62 QString contactBId = reply.value();
63 QVERIFY(!contactBId.isEmpty());
64
65 QVERIFY(contactAId != contactBId);
66 }
67
68 void testAppendOtherContactEmail()
69 {
70 // call create contact
71 QDBusReply<QString> reply = m_serverIface->call("createContact", m_vcard, "dummy-store");
72
73 // check if the returned id is valid
74 QString contactAId = reply.value();
75 QVERIFY(!contactAId.isEmpty());
76
77 // add a contact with diff email
78 QString vcardB = m_vcard.replace("fulano", "contact").replace("email","email2");
79 reply = m_serverIface->call("createContact", vcardB, "dummy-store");
80
81 // check if the returned id is valid
82 QString contactBId = reply.value();
83 QVERIFY(!contactBId.isEmpty());
84
85 // udate contactB with same email as contactA
86 vcardB = m_vcard.replace("fulano", "contact");
87 reply = m_serverIface->call("createContact", vcardB, "dummy-store");
88
89 // check if the returned id is valid
90 contactBId = reply.value();
91 QVERIFY(!contactBId.isEmpty());
92
93 // check if id still different
94 QVERIFY(contactAId != contactBId);
95 }
96};
97
98QTEST_MAIN(ContactLinkTest)
99
100#include "contact-link-test.moc"
0101
=== modified file 'tests/unittest/dummy-backend.cpp'
--- tests/unittest/dummy-backend.cpp 2013-12-13 19:57:13 +0000
+++ tests/unittest/dummy-backend.cpp 2014-02-18 00:13:04 +0000
@@ -192,6 +192,24 @@
192 return QString();192 return QString();
193}193}
194194
195void DummyBackendProxy::contactUpdated(const QString &contactId,
196 const QString &errorMsg)
197{
198 m_contactUpdated = true;
199}
200
201QString DummyBackendProxy::updateContact(const QString &contactId,
202 const QtContacts::QContact &qcontact)
203{
204 galera::QIndividual *i = m_contacts.value(contactId);
205 Q_ASSERT(i);
206 ScopedEventLoop loop(&m_eventLoop);
207 m_contactUpdated = false;
208 i->update(qcontact, this, SLOT(contactUpdated(QString,QString)));
209 loop.exec();
210 return i->id();
211}
212
195void DummyBackendProxy::configurePrimaryStore()213void DummyBackendProxy::configurePrimaryStore()
196{214{
197 static const char* writableProperties[] = {215 static const char* writableProperties[] = {
@@ -205,6 +223,7 @@
205 "Dummy personas",223 "Dummy personas",
206 const_cast<char**>(writableProperties), 4);224 const_cast<char**>(writableProperties), 4);
207 folks_dummy_persona_store_set_persona_type(m_primaryPersonaStore, FOLKS_DUMMY_TYPE_FULL_PERSONA);225 folks_dummy_persona_store_set_persona_type(m_primaryPersonaStore, FOLKS_DUMMY_TYPE_FULL_PERSONA);
226 folks_dummy_persona_store_update_trust_level(m_primaryPersonaStore, FOLKS_PERSONA_STORE_TRUST_FULL);
208227
209 GeeHashSet *personaStores = gee_hash_set_new(FOLKS_TYPE_PERSONA_STORE,228 GeeHashSet *personaStores = gee_hash_set_new(FOLKS_TYPE_PERSONA_STORE,
210 (GBoxedCopyFunc) g_object_ref, g_object_unref,229 (GBoxedCopyFunc) g_object_ref, g_object_unref,
@@ -349,9 +368,12 @@
349 GeeMultiMap *changes,368 GeeMultiMap *changes,
350 DummyBackendProxy *self)369 DummyBackendProxy *self)
351{370{
371 Q_UNUSED(individualAggregator);
372
352 GeeIterator *iter;373 GeeIterator *iter;
353 GeeSet *removed = gee_multi_map_get_keys(changes);374 GeeSet *removed = gee_multi_map_get_keys(changes);
354 GeeCollection *added = gee_multi_map_get_values(changes);375 GeeCollection *added = gee_multi_map_get_values(changes);
376 QStringList addedIds;
355377
356 iter = gee_iterable_iterator(GEE_ITERABLE(added));378 iter = gee_iterable_iterator(GEE_ITERABLE(added));
357 while(gee_iterator_next(iter)) {379 while(gee_iterator_next(iter)) {
@@ -359,6 +381,7 @@
359 if (individual) {381 if (individual) {
360 galera::QIndividual *idv = new galera::QIndividual(individual, self->m_aggregator);382 galera::QIndividual *idv = new galera::QIndividual(individual, self->m_aggregator);
361 self->m_contacts.insert(idv->id(), idv);383 self->m_contacts.insert(idv->id(), idv);
384 addedIds << idv->id();
362 g_object_unref(individual);385 g_object_unref(individual);
363 }386 }
364 }387 }
@@ -369,7 +392,7 @@
369 FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));392 FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));
370 if (individual) {393 if (individual) {
371 QString id = QString::fromUtf8(folks_individual_get_id(individual));394 QString id = QString::fromUtf8(folks_individual_get_id(individual));
372 if (self->m_contacts.contains(id)) {395 if (!addedIds.contains(id) && self->m_contacts.contains(id)) {
373 delete self->m_contacts.take(id);396 delete self->m_contacts.take(id);
374 }397 }
375 g_object_unref(individual);398 g_object_unref(individual);
@@ -426,3 +449,15 @@
426 QList<QtContacts::QContact> contacts = galera::VCardParser::vcardToContact(QStringList() << vcard);449 QList<QtContacts::QContact> contacts = galera::VCardParser::vcardToContact(QStringList() << vcard);
427 return m_proxy->createContact(contacts[0]);450 return m_proxy->createContact(contacts[0]);
428}451}
452
453QString DummyBackendAdaptor::updateContact(const QString &contactId, const QString &vcard)
454{
455 QList<QtContacts::QContact> contacts = galera::VCardParser::vcardToContact(QStringList() << vcard);
456 return m_proxy->updateContact(contactId, contacts[0]);
457}
458
459void DummyBackendAdaptor::enableAutoLink(bool flag)
460{
461 galera::QIndividual::enableAutoLink(flag);
462}
463
429464
=== modified file 'tests/unittest/dummy-backend.h'
--- tests/unittest/dummy-backend.h 2013-11-11 14:21:24 +0000
+++ tests/unittest/dummy-backend.h 2014-02-18 00:13:04 +0000
@@ -46,6 +46,7 @@
46 bool isReady() const;46 bool isReady() const;
4747
48 QString createContact(const QtContacts::QContact &qcontact);48 QString createContact(const QtContacts::QContact &qcontact);
49 QString updateContact(const QString &contactId, const QtContacts::QContact &qcontact);
49 QList<QtContacts::QContact> contacts() const;50 QList<QtContacts::QContact> contacts() const;
50 QList<galera::QIndividual*> individuals() const;51 QList<galera::QIndividual*> individuals() const;
5152
@@ -55,6 +56,7 @@
55 void shutdown();56 void shutdown();
56 QStringList listContacts() const;57 QStringList listContacts() const;
57 void reset();58 void reset();
59 void contactUpdated(const QString &contactId, const QString &errorMsg);
5860
59Q_SIGNALS:61Q_SIGNALS:
60 void ready();62 void ready();
@@ -71,6 +73,7 @@
71 bool m_isReady;73 bool m_isReady;
72 int m_individualsChangedDetailedId;74 int m_individualsChangedDetailedId;
73 QHash<QString, galera::QIndividual*> m_contacts;75 QHash<QString, galera::QIndividual*> m_contacts;
76 bool m_contactUpdated;
7477
75 bool registerObject();78 bool registerObject();
76 void initFolks();79 void initFolks();
@@ -108,10 +111,18 @@
108" <arg direction=\"out\" type=\"b\"/>\n"111" <arg direction=\"out\" type=\"b\"/>\n"
109" </method>\n"112" </method>\n"
110" <method name=\"quit\"/>\n"113" <method name=\"quit\"/>\n"
114" <method name=\"enableAutoLink\">\n"
115" <arg direction=\"in\" type=\"b\"/>\n"
116" </method>\n"
111" <method name=\"createContact\">\n"117" <method name=\"createContact\">\n"
112" <arg direction=\"in\" type=\"s\"/>\n"118" <arg direction=\"in\" type=\"s\"/>\n"
113" <arg direction=\"out\" type=\"s\"/>\n"119" <arg direction=\"out\" type=\"s\"/>\n"
114" </method>\n"120" </method>\n"
121" <method name=\"updateContact\">\n"
122" <arg direction=\"in\" type=\"s\"/>\n"
123" <arg direction=\"in\" type=\"s\"/>\n"
124" <arg direction=\"out\" type=\"s\"/>\n"
125" </method>\n"
115" <method name=\"listContacts\">\n"126" <method name=\"listContacts\">\n"
116" <arg direction=\"out\" type=\"as\"/>\n"127" <arg direction=\"out\" type=\"as\"/>\n"
117" </method>\n"128" </method>\n"
@@ -130,6 +141,8 @@
130 void reset();141 void reset();
131 QStringList listContacts();142 QStringList listContacts();
132 QString createContact(const QString &vcard);143 QString createContact(const QString &vcard);
144 QString updateContact(const QString &contactId, const QString &vcard);
145 void enableAutoLink(bool flag);
133146
134Q_SIGNALS:147Q_SIGNALS:
135 void ready();148 void ready();

Subscribers

People subscribed via source and target branches