Merge lp:~renatofilho/address-book-service/fix-edit into lp:address-book-service

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Bill Filler
Approved revision: no longer in the source branch.
Merged at revision: 36
Proposed branch: lp:~renatofilho/address-book-service/fix-edit
Merge into: lp:address-book-service
Prerequisite: lp:~renatofilho/address-book-service/wait-for-server
Diff against target: 2729 lines (+1310/-735)
11 files modified
common/vcard-parser.cpp (+46/-8)
common/vcard-parser.h (+2/-0)
src/addressbook-adaptor.h (+4/-4)
src/addressbook.cpp (+68/-70)
src/addressbook.h (+8/-3)
src/contacts-map.cpp (+11/-0)
src/contacts-map.h (+1/-0)
src/qindividual.cpp (+1107/-622)
src/qindividual.h (+56/-26)
src/view-adaptor.h (+2/-2)
src/view.cpp (+5/-0)
To merge this branch: bzr merge lp:~renatofilho/address-book-service/fix-edit
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Bill Filler (community) Approve
Review via email: mp+170609@code.launchpad.net

This proposal supersedes a proposal from 2013-06-17.

Commit message

Added support to edit contacts with multiple persona.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Bill Filler (bfiller) wrote :

approved

review: Approve
35. By Renato Araujo Oliveira Filho

Fixed qcontacts plugins to wait for server fully start before request any data.

Approved by PS Jenkins bot, Bill Filler.

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)
36. By Renato Araujo Oliveira Filho

Added support to edit contacts with multiple persona.

Approved by PS Jenkins bot, Bill Filler.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'common/vcard-parser.cpp'
2--- common/vcard-parser.cpp 2013-05-18 01:11:38 +0000
3+++ common/vcard-parser.cpp 2013-06-20 20:58:26 +0000
4@@ -55,7 +55,7 @@
5
6 if (detail.type() == QContactDetail::TypeExtendedDetail) {
7 const QContactExtendedDetail *extendedDetail = static_cast<const QContactExtendedDetail *>(&detail);
8- if (extendedDetail->name() == "CLIENTPIDMAP") {
9+ if (extendedDetail->name() == galera::VCardParser::PidMapFieldName) {
10 QVersitProperty prop;
11 prop.setName(extendedDetail->name());
12 QStringList value;
13@@ -70,11 +70,12 @@
14 }
15
16 if (!detail.detailUri().isEmpty()) {
17- QVersitProperty prop = toBeAdded->takeLast();
18- QMultiHash<QString, QString> params = prop.parameters();
19- params.insert("PID", detail.detailUri());
20- prop.setParameters(params);
21- *toBeAdded << prop;
22+ if (toBeAdded->size() > 0) {
23+ QVersitProperty &prop = toBeAdded->last();
24+ QMultiHash<QString, QString> params = prop.parameters();
25+ params.insert(galera::VCardParser::PidFieldName, detail.detailUri());
26+ prop.setParameters(params);
27+ }
28 }
29 }
30
31@@ -102,16 +103,50 @@
32 Q_UNUSED(document);
33 Q_UNUSED(contact);
34
35- if (!*alreadyProcessed && (property.name() == "CLIENTPIDMAP")) {
36+ if (!*alreadyProcessed && (property.name() == galera::VCardParser::PidMapFieldName)) {
37 QContactExtendedDetail detail;
38 detail.setName(property.name());
39- QStringList value = property.value<QStringList>();
40+ QStringList value = property.value<QString>().split(";");
41 detail.setValue(QContactExtendedDetail::FieldData, value[0]);
42 detail.setValue(QContactExtendedDetail::FieldData + 1, value[1]);
43 *updatedDetails << detail;
44 *alreadyProcessed = true;
45 }
46
47+ QString pid = property.parameters().value(galera::VCardParser::PidFieldName);
48+ if (!pid.isEmpty()) {
49+ QContactDetail &det = updatedDetails->last();
50+ det.setDetailUri(pid);
51+ }
52+
53+ // Remove empty phone and address subtypes
54+ // Remove this after this fix get merged: https://codereview.qt-project.org/#change,59156
55+ if (updatedDetails->size() > 0) {
56+ QContactDetail &det = updatedDetails->last();
57+ switch (det.type()) {
58+ case QContactDetail::TypePhoneNumber:
59+ {
60+ QContactPhoneNumber phone = static_cast<QContactPhoneNumber>(det);
61+ if (phone.subTypes().isEmpty()) {
62+ det.setValue(QContactPhoneNumber::FieldSubTypes, QVariant());
63+ }
64+ break;
65+ }
66+ case QContactDetail::TypeAddress:
67+ {
68+ QContactAddress addr = static_cast<QContactAddress>(det);
69+ if (addr.subTypes().isEmpty()) {
70+ det.setValue(QContactAddress::FieldSubTypes, QVariant());
71+ } else {
72+ QSet<int> subtypes = addr.subTypes().toSet();
73+ det.setValue(QContactAddress::FieldSubTypes, QVariant::fromValue<QList<int> >(subtypes.toList()));
74+ }
75+ break;
76+ }
77+ default:
78+ break;
79+ }
80+ }
81 }
82
83 virtual void documentProcessed(const QVersitDocument& document, QContact* contact)
84@@ -125,6 +160,9 @@
85 namespace galera
86 {
87
88+const QString VCardParser::PidMapFieldName = QString("CLIENTPIDMAP");
89+const QString VCardParser::PidFieldName = QString("PID");
90+
91 QStringList VCardParser::contactToVcard(QList<QtContacts::QContact> contacts)
92 {
93 QStringList result;
94
95=== modified file 'common/vcard-parser.h'
96--- common/vcard-parser.h 2013-05-18 01:11:38 +0000
97+++ common/vcard-parser.h 2013-06-20 20:58:26 +0000
98@@ -29,6 +29,8 @@
99 class VCardParser
100 {
101 public:
102+ static const QString PidMapFieldName;
103+ static const QString PidFieldName;
104
105 static QStringList contactToVcard(QList<QtContacts::QContact> contacts);
106 static QtContacts::QContact vcardToContact(const QString &vcard);
107
108=== modified file 'src/addressbook-adaptor.h'
109--- src/addressbook-adaptor.h 2013-06-20 20:58:26 +0000
110+++ src/addressbook-adaptor.h 2013-06-20 20:58:26 +0000
111@@ -99,13 +99,13 @@
112
113 public Q_SLOTS:
114 SourceList availableSources();
115+ QStringList sortFields();
116+ QDBusObjectPath query(const QString &clause, const QString &sort, const QStringList &sources);
117+ int removeContacts(const QStringList &contactIds, const QDBusMessage &message);
118 QString createContact(const QString &contact, const QString &source, const QDBusMessage &message);
119+ QStringList updateContacts(const QStringList &contacts, const QDBusMessage &message);
120 QString linkContacts(const QStringList &contacts);
121- QDBusObjectPath query(const QString &clause, const QString &sort, const QStringList &sources);
122- int removeContacts(const QStringList &contactIds, const QDBusMessage &message);
123- QStringList sortFields();
124 bool unlinkContacts(const QString &parentId, const QStringList &contactsIds);
125- QStringList updateContacts(const QStringList &contacts, const QDBusMessage &message);
126 bool isReady();
127
128 Q_SIGNALS:
129
130=== modified file 'src/addressbook.cpp'
131--- src/addressbook.cpp 2013-06-20 20:58:26 +0000
132+++ src/addressbook.cpp 2013-06-20 20:58:26 +0000
133@@ -26,7 +26,6 @@
134
135 #include <QtCore/QPair>
136 #include <QtCore/QUuid>
137-#include <QtContacts/QContact>
138
139 using namespace QtContacts;
140
141@@ -240,76 +239,75 @@
142
143 QStringList AddressBook::updateContacts(const QStringList &contacts, const QDBusMessage &message)
144 {
145- UpdateContactsData *data = 0;
146-
147- if (!contacts.isEmpty()) {
148- data = new UpdateContactsData;
149- data->m_contacts = VCardParser::vcardToContact(contacts);
150- data->m_request = contacts;
151- data->m_currentIndex = -1;
152- data->m_addressbook = this;
153- data->m_message = message;
154-
155- }
156- updateContacts("", data);
157+ //TODO: support multiple update contacts calls
158+ Q_ASSERT(m_updateCommandPendingContacts.isEmpty());
159+
160+ qDebug() << "update contacts:" << contacts;
161+ m_updateCommandReplyMessage = message;
162+ m_updateCommandResult = contacts;
163+ m_updateCommandPendingContacts << VCardParser::vcardToContact(contacts);
164+
165+ updateContactsDone(0, QString());
166
167 return QStringList();
168 }
169
170-void AddressBook::updateContacts(const QString &error, void *userData)
171+void AddressBook::updateContactsDone(galera::QIndividual *individual, const QString &error)
172 {
173- qDebug() << Q_FUNC_INFO << userData;
174- UpdateContactsData *data = static_cast<UpdateContactsData*>(userData);
175- QDBusMessage reply;
176-
177- if (data) {
178- if (!error.isEmpty()) {
179- data->m_result << error;
180- } else if (data->m_currentIndex > -1) {
181- data->m_result << data->m_request[data->m_currentIndex];
182- }
183-
184- if (!data->m_contacts.isEmpty()) {
185- QContact newContact = data->m_contacts.takeFirst();
186- data->m_currentIndex++;
187-
188- ContactEntry *entry = data->m_addressbook->m_contacts->value(newContact.detail<QContactGuid>().guid());
189- if (entry) {
190- entry->individual()->update(newContact, updateContacts, userData);
191- } else {
192- updateContacts("Contact not found!", userData);
193- }
194- return;
195- }
196- folks_persona_store_flush(folks_individual_aggregator_get_primary_store(data->m_addressbook->m_individualAggregator), 0, 0);
197- reply = data->m_message.createReply(data->m_result);
198+ Q_UNUSED(individual);
199+ qDebug() << Q_FUNC_INFO;
200+
201+ if (!error.isEmpty()) {
202+ // update the result with the error
203+ m_updateCommandResult[m_updateCommandResult.size() - m_updateCommandPendingContacts.size() - 1] = error;
204+ }
205+
206+ if (!m_updateCommandPendingContacts.isEmpty()) {
207+ QContact newContact = m_updateCommandPendingContacts.takeFirst();
208+ ContactEntry *entry = m_contacts->value(newContact.detail<QContactGuid>().guid());
209+ if (entry) {
210+ entry->individual()->update(newContact, this, "updateContactsDone(galera::QIndividual*, const QString&)"); //));
211+ } else {
212+ updateContactsDone(0, "Contact not found!");
213+ }
214 } else {
215- reply = data->m_message.createReply(QStringList());
216+ folks_persona_store_flush(folks_individual_aggregator_get_primary_store(m_individualAggregator), 0, 0);
217+ QDBusMessage reply = m_updateCommandReplyMessage.createReply(m_updateCommandResult);
218+ QDBusConnection::sessionBus().send(reply);
219+
220+ // clear command data
221+ m_updateCommandResult.clear();
222+ m_updateCommandReplyMessage = QDBusMessage();
223 }
224-
225- QDBusConnection::sessionBus().send(reply);
226- delete data;
227 }
228
229
230 QString AddressBook::removeContact(FolksIndividual *individual)
231 {
232- Q_ASSERT(m_contacts->contains(individual));
233- ContactEntry *ci = m_contacts->take(individual);
234- if (ci) {
235- QString id = QString::fromUtf8(folks_individual_get_id(individual));
236- delete ci;
237- return id;
238+ if (m_contacts->contains(individual)) {
239+ ContactEntry *ci = m_contacts->take(individual);
240+ if (ci) {
241+ QString id = QString::fromUtf8(folks_individual_get_id(individual));
242+ qDebug() << "Remove contact" << id;
243+ delete ci;
244+ return id;
245+ }
246 }
247 return QString();
248 }
249
250 QString AddressBook::addContact(FolksIndividual *individual)
251 {
252- Q_ASSERT(!m_contacts->contains(individual));
253- m_contacts->insert(new ContactEntry(new QIndividual(individual, m_individualAggregator)));
254- //TODO: Notify view
255- return QString::fromUtf8(folks_individual_get_id(individual));
256+ QString id = QString::fromUtf8(folks_individual_get_id(individual));
257+ ContactEntry *entry = m_contacts->value(id);
258+ if (entry) {
259+ entry->individual()->setIndividual(individual);
260+ } else {
261+ m_contacts->insert(new ContactEntry(new QIndividual(individual, m_individualAggregator)));
262+ qDebug() << "Add contact" << folks_individual_get_id(individual);
263+ //TODO: Notify view
264+ }
265+ return id;
266 }
267
268 void AddressBook::individualsChangedCb(FolksIndividualAggregator *individualAggregator,
269@@ -322,28 +320,28 @@
270
271 GeeIterator *iter;
272 GeeSet *removed = gee_multi_map_get_keys(changes);
273- iter = gee_iterable_iterator(GEE_ITERABLE(removed));
274-
275- while(gee_iterator_next(iter)) {
276- FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));
277- if (individual) {
278- QString id = self->removeContact(individual);
279- if(!id.isEmpty()) {
280- removedIds << id;
281- }
282- g_object_unref(individual);
283- }
284- }
285- g_object_unref (iter);
286-
287 GeeCollection *added = gee_multi_map_get_values(changes);
288+
289 iter = gee_iterable_iterator(GEE_ITERABLE(added));
290 while(gee_iterator_next(iter)) {
291 FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));
292 if (individual) {
293- QString id = self->addContact(individual);
294- if(!id.isEmpty()) {
295- addedIds << id;
296+ // add contact to the map
297+ addedIds << self->addContact(individual);
298+ g_object_unref(individual);
299+ }
300+ }
301+ g_object_unref (iter);
302+
303+
304+ iter = gee_iterable_iterator(GEE_ITERABLE(removed));
305+ while(gee_iterator_next(iter)) {
306+ FolksIndividual *individual = FOLKS_INDIVIDUAL(gee_iterator_get(iter));
307+ if (individual) {
308+ QString id = QString::fromUtf8(folks_individual_get_id(individual));
309+ if (!addedIds.contains(id)) {
310+ // delete from contact map
311+ removedIds << self->removeContact(individual);
312 }
313 g_object_unref(individual);
314 }
315
316=== modified file 'src/addressbook.h'
317--- src/addressbook.h 2013-06-20 20:58:26 +0000
318+++ src/addressbook.h 2013-06-20 20:58:26 +0000
319@@ -28,6 +28,8 @@
320
321 #include <QtDBus/QtDBus>
322
323+#include <QtContacts/QContact>
324+
325 #include <folks/folks.h>
326 #include <glib.h>
327 #include <glib-object.h>
328@@ -37,6 +39,7 @@
329 class View;
330 class ContactsMap;
331 class AddressBookAdaptor;
332+class QIndividual;
333
334 class AddressBook: public QObject
335 {
336@@ -60,6 +63,7 @@
337 QString createContact(const QString &contact, const QString &source, const QDBusMessage &message);
338 int removeContacts(const QStringList &contactIds, const QDBusMessage &message);
339 QStringList updateContacts(const QStringList &contacts, const QDBusMessage &message);
340+ void updateContactsDone(galera::QIndividual *individual, const QString &error);
341
342 private Q_SLOTS:
343 void viewClosed();
344@@ -71,14 +75,15 @@
345 bool m_ready;
346 AddressBookAdaptor *m_adaptor;
347
348+ // Update command
349+ QDBusMessage m_updateCommandReplyMessage;
350+ QStringList m_updateCommandResult;
351+ QList<QtContacts::QContact> m_updateCommandPendingContacts;
352
353 void prepareFolks();
354 QString removeContact(FolksIndividual *individual);
355 QString addContact(FolksIndividual *individual);
356
357-
358- static void updateContacts(const QString &error, void *userData);
359-
360 static void individualsChangedCb(FolksIndividualAggregator *individualAggregator,
361 GeeMultiMap *changes,
362 AddressBook *self);
363
364=== modified file 'src/contacts-map.cpp'
365--- src/contacts-map.cpp 2013-06-11 13:00:01 +0000
366+++ src/contacts-map.cpp 2013-06-20 20:58:26 +0000
367@@ -28,6 +28,7 @@
368 ContactEntry::ContactEntry(QIndividual *individual)
369 : m_individual(individual)
370 {
371+ Q_ASSERT(individual);
372 }
373
374 ContactEntry::~ContactEntry()
375@@ -75,6 +76,16 @@
376 return 0;
377 }
378
379+void ContactsMap::remove(const QString &id)
380+{
381+ ContactEntry *entry = m_idToEntry[id];
382+ if (entry) {
383+ m_individualsToEntry.remove(entry->individual()->individual());
384+ m_idToEntry.remove(id);
385+ delete entry;
386+ }
387+}
388+
389 bool ContactsMap::contains(FolksIndividual *individual) const
390 {
391 return m_individualsToEntry.contains(individual);
392
393=== modified file 'src/contacts-map.h'
394--- src/contacts-map.h 2013-06-11 13:00:01 +0000
395+++ src/contacts-map.h 2013-06-20 20:58:26 +0000
396@@ -60,6 +60,7 @@
397 ContactEntry *value(FolksIndividual *individual) const;
398 ContactEntry *value(const QString &id) const;
399 ContactEntry *take(FolksIndividual *individual);
400+ void remove(const QString &id);
401 void insert(ContactEntry *entry);
402 int size() const;
403
404
405=== modified file 'src/qindividual.cpp'
406--- src/qindividual.cpp 2013-06-11 21:49:45 +0000
407+++ src/qindividual.cpp 2013-06-20 20:58:26 +0000
408@@ -53,14 +53,14 @@
409 class UpdateContactData
410 {
411 public:
412- QContactDetail::DetailType m_currentDetailType;
413 QContact m_newContact;
414 galera::QIndividual *m_self;
415- FolksPersona *m_persona;
416-
417- QList<QContactDetail> m_detailsChanged;
418- galera::UpdateDoneCB m_doneCB;
419- void *m_doneData;
420+
421+ QList<QContactDetail> m_details;
422+ QContactDetail m_currentDetail;
423+
424+ QObject *m_object;
425+ QMetaMethod m_slot;
426 };
427
428 #ifdef FOLKS_0_9_0
429@@ -82,9 +82,6 @@
430 namespace galera
431 {
432
433-// TODO: find a better way to link abstract field with details
434-#define FOLKS_DATA_FIELD 10000
435-
436 #ifdef FOLKS_0_9_0
437 #define SET_AFD_NEW() \
438 GEE_SET(gee_hash_set_new(FOLKS_TYPE_ABSTRACT_FIELD_DETAILS, \
439@@ -96,6 +93,16 @@
440 NULL, \
441 NULL))
442
443+ #define SET_PERSONA_NEW() \
444+ GEE_SET(gee_hash_set_new(FOLKS_TYPE_PERSONA, \
445+ (GBoxedCopyFunc) g_object_ref, g_object_unref, \
446+ NULL, \
447+ NULL, \
448+ NULL, \
449+ NULL, \
450+ NULL, \
451+ NULL))
452+
453 #define GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE) \
454 GEE_MULTI_MAP(gee_hash_multi_map_new(G_TYPE_STRING,\
455 (GBoxedCopyFunc) g_strdup, g_free, \
456@@ -120,6 +127,13 @@
457 (GHashFunc) folks_abstract_field_details_hash, \
458 (GEqualFunc) folks_abstract_field_details_equal))
459
460+ #define SET_PERSONA_NEW() \
461+ GEE_SET(gee_hash_set_new(FOLKS_TYPE_PERSONA, \
462+ (GBoxedCopyFunc) g_object_ref, g_object_unref, \
463+ NULL, \
464+ NULL))
465+
466+
467 #define GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE) \
468 GEE_MULTI_MAP(gee_hash_multi_map_new(G_TYPE_STRING, \
469 (GBoxedCopyFunc) g_strdup, \
470@@ -131,16 +145,17 @@
471 (GHashFunc) folks_abstract_field_details_hash, \
472 (GEqualFunc) folks_abstract_field_details_equal));
473
474+
475+
476 #endif
477
478
479 #define PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(\
480- details, key, value, q_type, g_type, member) \
481+ details, cDetails, key, value, q_type, g_type, member) \
482 { \
483- QList<q_type> contactDetails = contact.details<q_type>(); \
484- if(contactDetails.size() > 0) { \
485+ if(cDetails.size() > 0) { \
486 value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT); \
487- Q_FOREACH(const q_type& detail, contact.details<q_type>()) { \
488+ Q_FOREACH(const q_type& detail, cDetails) { \
489 if(!detail.isEmpty()) { \
490 QIndividualUtils::gValueGeeSetAddStringFieldDetails(value, (g_type), \
491 detail.member().toUtf8().data(), \
492@@ -242,10 +257,53 @@
493 return retval;
494 }
495
496+ static FolksAbstractFieldDetails *getDetails(GeeSet *set, const QString &uri)
497+ {
498+ Q_ASSERT(set);
499+
500+ int pos = 0;
501+ int size = 0;
502+ QStringList index = uri.split(".");
503+ gpointer* values = gee_collection_to_array(GEE_COLLECTION(set), &size);
504+
505+ if (size == 0) {
506+ return 0;
507+ } else if (index.count() == 2) {
508+ pos = index[1].toInt() - 1;
509+ Q_ASSERT(pos >= 0);
510+ Q_ASSERT(pos < size);
511+ }
512+ return FOLKS_ABSTRACT_FIELD_DETAILS(values[pos]);
513+ }
514+
515+ static FolksPersona *personaFromUri(const QString &uri, FolksIndividual *individual, FolksPersona *defaultPersona)
516+ {
517+ Q_ASSERT(individual);
518+
519+ if (uri.isEmpty()) {
520+ //TODO
521+ qWarning() << "NO PERSONA";
522+ return defaultPersona;
523+ } else {
524+
525+ GeeSet *personas = folks_individual_get_personas(individual);
526+ QStringList index = uri.split(".");
527+ Q_ASSERT(index.count() >= 1);
528+ int pos = index[0].toInt() - 1;
529+ int size = 0;
530+ gpointer* values = gee_collection_to_array(GEE_COLLECTION(personas), &size);
531+ Q_ASSERT(pos >= 0);
532+ Q_ASSERT(pos < size);
533+
534+ return FOLKS_PERSONA(values[pos]);
535+ }
536+ }
537+
538 }; // class
539
540 QIndividual::QIndividual(FolksIndividual *individual, FolksIndividualAggregator *aggregator)
541 : m_individual(individual),
542+ m_primaryPersona(0),
543 m_aggregator(aggregator)
544 {
545 g_object_ref(m_individual);
546@@ -267,7 +325,6 @@
547 QList<QtContacts::QContactDetail> QIndividual::getClientPidMap() const
548 {
549 QList<QtContacts::QContactDetail> details;
550- /*
551 int index = 1;
552 GeeSet *personas = folks_individual_get_personas(m_individual);
553 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
554@@ -282,16 +339,75 @@
555 }
556
557 g_object_unref(iter);
558- */
559- return details;
560-}
561-
562-
563-QtContacts::QContactDetail QIndividual::getName() const
564-{
565+ return details;
566+}
567+
568+void QIndividual::appendDetailsForPersona(QList<QtContacts::QContactDetail> *list, QtContacts::QContactDetail detail, const QString &personaIndex, bool readOnly) const
569+{
570+ if (!detail.isEmpty()) {
571+ detail.setDetailUri(personaIndex);
572+ if (readOnly) {
573+ QContactManagerEngine::setDetailAccessConstraints(&detail, QContactDetail::ReadOnly);
574+ }
575+ list->append(detail);
576+ }
577+}
578+
579+void QIndividual::appendDetailsForPersona(QList<QtContacts::QContactDetail> *list, QList<QtContacts::QContactDetail> details, const QString &personaIndex, bool readOnly) const
580+{
581+ int subIndex = 1;
582+ Q_FOREACH(QContactDetail detail, details) {
583+ appendDetailsForPersona(list, detail, QString("%1.%2").arg(personaIndex).arg(subIndex), readOnly);
584+ subIndex++;
585+ }
586+}
587+
588+
589+QList<QContactDetail> QIndividual::getDetails() const
590+{
591+ int personaIndex = 1;
592+ QList<QContactDetail> details;
593+ GeeSet *personas = folks_individual_get_personas(m_individual);
594+ GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
595+
596+ while(gee_iterator_next(iter)) {
597+ FolksPersona *persona = FOLKS_PERSONA(gee_iterator_get(iter));
598+
599+ int wsize = 0;
600+ gchar **wproperties = folks_persona_get_writeable_properties(persona, &wsize);
601+ //"gender", "local-ids", "avatar", "postal-addresses", "urls", "phone-numbers", "structured-name",
602+ //"anti-links", "im-addresses", "is-favourite", "birthday", "notes", "roles", "email-addresses",
603+ //"web-service-addresses", "groups", "full-name"
604+ QStringList wPropList;
605+ for(int i=0; i < wsize; i++) {
606+ wPropList << wproperties[i];
607+ }
608+
609+ QString index = QString::number(personaIndex);
610+
611+ appendDetailsForPersona(&details, getPersonaName(persona), index, !wPropList.contains("structured-name"));
612+ appendDetailsForPersona(&details, getPersonaFullName(persona), index, !wPropList.contains("full-name"));
613+ appendDetailsForPersona(&details, getPersonaNickName(persona), index, !wPropList.contains("nickname"));
614+ appendDetailsForPersona(&details, getPersonaBirthday(persona), index, !wPropList.contains("birthday"));
615+ appendDetailsForPersona(&details, getPersonaRoles(persona), index, !wPropList.contains("roles"));
616+ appendDetailsForPersona(&details, getPersonaEmails(persona), index, !wPropList.contains("email-addresses"));
617+ appendDetailsForPersona(&details, getPersonaPhones(persona), index, !wPropList.contains("phone-numbers"));
618+ appendDetailsForPersona(&details, getPersonaAddresses(persona), index, !wPropList.contains("postal-addresses"));
619+ appendDetailsForPersona(&details, getPersonaIms(persona), index, !wPropList.contains("im-addresses"));
620+ appendDetailsForPersona(&details, getPersonaUrls(persona), index, !wPropList.contains("urls"));
621+ personaIndex++;
622+ }
623+ return details;
624+}
625+
626+QContactDetail QIndividual::getPersonaName(FolksPersona *persona) const
627+{
628+ if (!FOLKS_IS_NAME_DETAILS(persona)) {
629+ return QContactDetail();
630+ }
631+
632 QContactName detail;
633- FolksStructuredName *sn = folks_name_details_get_structured_name(FOLKS_NAME_DETAILS(m_individual));
634-
635+ FolksStructuredName *sn = folks_name_details_get_structured_name(FOLKS_NAME_DETAILS(persona));
636 if (sn) {
637 const char *name = folks_structured_name_get_given_name(sn);
638 if (name && strlen(name)) {
639@@ -317,30 +433,42 @@
640 return detail;
641 }
642
643-QtContacts::QContactDetail QIndividual::getFullName() const
644+QtContacts::QContactDetail QIndividual::getPersonaFullName(FolksPersona *persona) const
645 {
646+ if (!FOLKS_IS_NAME_DETAILS(persona)) {
647+ return QContactDetail();
648+ }
649+
650 QContactDisplayLabel detail;
651- const gchar *fullName = folks_name_details_get_full_name(FOLKS_NAME_DETAILS(m_individual));
652+ const gchar *fullName = folks_name_details_get_full_name(FOLKS_NAME_DETAILS(persona));
653 if (fullName && strlen(fullName)) {
654 detail.setLabel(QString::fromUtf8(fullName));
655 }
656 return detail;
657 }
658
659-QtContacts::QContactDetail QIndividual::getNickname() const
660+QtContacts::QContactDetail QIndividual::getPersonaNickName(FolksPersona *persona) const
661 {
662+ if (!FOLKS_IS_NAME_DETAILS(persona)) {
663+ return QContactDetail();
664+ }
665+
666 QContactNickname detail;
667- const gchar* nickname = folks_name_details_get_nickname(FOLKS_NAME_DETAILS(m_individual));
668+ const gchar* nickname = folks_name_details_get_nickname(FOLKS_NAME_DETAILS(persona));
669 if (nickname && strlen(nickname)) {
670 detail.setNickname(QString::fromUtf8(nickname));
671 }
672 return detail;
673 }
674
675-QtContacts::QContactDetail QIndividual::getBirthday() const
676+QtContacts::QContactDetail QIndividual::getPersonaBirthday(FolksPersona *persona) const
677 {
678+ if (!FOLKS_IS_BIRTHDAY_DETAILS(persona)) {
679+ return QContactDetail();
680+ }
681+
682 QContactBirthday detail;
683- GDateTime* datetime = folks_birthday_details_get_birthday(FOLKS_BIRTHDAY_DETAILS(m_individual));
684+ GDateTime* datetime = folks_birthday_details_get_birthday(FOLKS_BIRTHDAY_DETAILS(persona));
685 if (datetime) {
686 QDate date(g_date_time_get_year(datetime), g_date_time_get_month(datetime), g_date_time_get_day_of_month(datetime));
687 QTime time(g_date_time_get_hour(datetime), g_date_time_get_minute(datetime), g_date_time_get_second(datetime));
688@@ -349,16 +477,20 @@
689 return detail;
690 }
691
692-QtContacts::QContactDetail QIndividual::getPhoto() const
693+QtContacts::QContactDetail QIndividual::getPersonaPhoto(FolksPersona *persona) const
694 {
695 // TODO
696 return QContactAvatar();
697 }
698
699-QList<QtContacts::QContactDetail> QIndividual::getRoles() const
700+QList<QtContacts::QContactDetail> QIndividual::getPersonaRoles(FolksPersona *persona) const
701 {
702+ if (!FOLKS_IS_ROLE_DETAILS(persona)) {
703+ return QList<QtContacts::QContactDetail>();
704+ }
705+
706 QList<QtContacts::QContactDetail> details;
707- GeeSet *roles = folks_role_details_get_roles(FOLKS_ROLE_DETAILS(m_individual));
708+ GeeSet *roles = folks_role_details_get_roles(FOLKS_ROLE_DETAILS(persona));
709 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(roles));
710
711 while(gee_iterator_next(iter)) {
712@@ -366,8 +498,15 @@
713 FolksRole *role = FOLKS_ROLE(folks_abstract_field_details_get_value(fd));
714
715 QContactOrganization org;
716- org.setName(QString::fromUtf8(folks_role_get_organisation_name(role)));
717- org.setTitle(QString::fromUtf8(folks_role_get_title(role)));
718+ QString field;
719+ field = QString::fromUtf8(folks_role_get_organisation_name(role));
720+ if (field.isEmpty()) {
721+ org.setName(field);
722+ }
723+ field = QString::fromUtf8(folks_role_get_title(role));
724+ if (!field.isEmpty()) {
725+ org.setTitle(field);
726+ }
727 parseParameters(org, fd);
728
729 g_object_unref(fd);
730@@ -379,10 +518,14 @@
731 return details;
732 }
733
734-QList<QtContacts::QContactDetail> QIndividual::getEmails() const
735+QList<QtContacts::QContactDetail> QIndividual::getPersonaEmails(FolksPersona *persona) const
736 {
737+ if (!FOLKS_IS_EMAIL_DETAILS(persona)) {
738+ return QList<QtContacts::QContactDetail>();
739+ }
740+
741 QList<QtContacts::QContactDetail> details;
742- GeeSet *emails = folks_email_details_get_email_addresses(FOLKS_EMAIL_DETAILS(m_individual));
743+ GeeSet *emails = folks_email_details_get_email_addresses(FOLKS_EMAIL_DETAILS(persona));
744 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(emails));
745
746 while(gee_iterator_next(iter)) {
747@@ -402,10 +545,14 @@
748 return details;
749 }
750
751-QList<QtContacts::QContactDetail> QIndividual::getPhones() const
752+QList<QtContacts::QContactDetail> QIndividual::getPersonaPhones(FolksPersona *persona) const
753 {
754+ if (!FOLKS_IS_PHONE_DETAILS(persona)) {
755+ return QList<QtContacts::QContactDetail>();
756+ }
757+
758 QList<QtContacts::QContactDetail> details;
759- GeeSet *phones = folks_phone_details_get_phone_numbers(FOLKS_PHONE_DETAILS(m_individual));
760+ GeeSet *phones = folks_phone_details_get_phone_numbers(FOLKS_PHONE_DETAILS(persona));
761 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(phones));
762
763 while(gee_iterator_next(iter)) {
764@@ -425,10 +572,14 @@
765 return details;
766 }
767
768-QList<QtContacts::QContactDetail> QIndividual::getAddresses() const
769+QList<QtContacts::QContactDetail> QIndividual::getPersonaAddresses(FolksPersona *persona) const
770 {
771+ if (!FOLKS_IS_POSTAL_ADDRESS_DETAILS(persona)) {
772+ return QList<QtContacts::QContactDetail>();
773+ }
774+
775 QList<QtContacts::QContactDetail> details;
776- GeeSet *addresses = folks_postal_address_details_get_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(m_individual));
777+ GeeSet *addresses = folks_postal_address_details_get_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(persona));
778 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(addresses));
779
780 while(gee_iterator_next(iter)) {
781@@ -476,10 +627,14 @@
782 return details;
783 }
784
785-QList<QtContacts::QContactDetail> QIndividual::getIms() const
786+QList<QtContacts::QContactDetail> QIndividual::getPersonaIms(FolksPersona *persona) const
787 {
788+ if (!FOLKS_IS_IM_DETAILS(persona)) {
789+ return QList<QtContacts::QContactDetail>();
790+ }
791+
792 QList<QtContacts::QContactDetail> details;
793- GeeMultiMap *ims = folks_im_details_get_im_addresses(FOLKS_IM_DETAILS(m_individual));
794+ GeeMultiMap *ims = folks_im_details_get_im_addresses(FOLKS_IM_DETAILS(persona));
795 GeeSet *keys = gee_multi_map_get_keys(ims);
796 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(keys));
797
798@@ -508,16 +663,14 @@
799 return details;
800 }
801
802-QtContacts::QContactDetail QIndividual::getTimeZone() const
803+QList<QtContacts::QContactDetail> QIndividual::getPersonaUrls(FolksPersona *persona) const
804 {
805- //TODO
806- return QContactDetail();
807-}
808+ if (!FOLKS_IS_URL_DETAILS(persona)) {
809+ return QList<QtContacts::QContactDetail>();
810+ }
811
812-QList<QtContacts::QContactDetail> QIndividual::getUrls() const
813-{
814 QList<QtContacts::QContactDetail> details;
815- GeeSet *urls = folks_url_details_get_urls(FOLKS_URL_DETAILS(m_individual));
816+ GeeSet *urls = folks_url_details_get_urls(FOLKS_URL_DETAILS(persona));
817 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(urls));
818
819 while(gee_iterator_next(iter)) {
820@@ -635,519 +788,696 @@
821 {
822 m_contact = QContact();
823 m_contact.appendDetail(getUid());
824- m_contact.appendDetail(getName());
825- m_contact.appendDetail(getFullName());
826- m_contact.appendDetail(getNickname());
827- m_contact.appendDetail(getBirthday());
828- m_contact.appendDetail(getPhoto());
829- m_contact.appendDetail(getTimeZone());
830 Q_FOREACH(QContactDetail detail, getClientPidMap()) {
831 m_contact.appendDetail(detail);
832 }
833- Q_FOREACH(QContactDetail detail, getRoles()) {
834- m_contact.appendDetail(detail);
835- }
836- Q_FOREACH(QContactDetail detail, getEmails()) {
837- m_contact.appendDetail(detail);
838- }
839- Q_FOREACH(QContactDetail detail, getPhones()) {
840- m_contact.appendDetail(detail);
841- }
842- Q_FOREACH(QContactDetail detail, getAddresses()) {
843- m_contact.appendDetail(detail);
844- }
845- Q_FOREACH(QContactDetail detail, getIms()) {
846- m_contact.appendDetail(detail);
847- }
848- Q_FOREACH(QContactDetail detail, getUrls()) {
849- m_contact.appendDetail(detail);
850- }
851+
852+ Q_FOREACH(QContactDetail detail, getDetails()) {
853+ m_contact.appendDetail(detail);
854+ }
855+}
856+
857+void QIndividual::createPersonaForDetail(QList<QtContacts::QContactDetail> cDetails, ParseDetailsFunc parseFunc, void *data) const
858+{
859+ GHashTable *details = g_hash_table_new_full(g_str_hash,
860+ g_str_equal,
861+ NULL,
862+ (GDestroyNotify) QIndividualUtils::gValueSliceFree);
863+
864+ parseFunc(details, cDetails);
865+
866+ folks_individual_aggregator_add_persona_from_details(m_aggregator,
867+ NULL, // we should pass the m_individual here but due a bug on folks lest do a work around
868+ folks_individual_aggregator_get_primary_store(m_aggregator),
869+ details,
870+ (GAsyncReadyCallback) createPersonaDone,
871+ (void*) data);
872+
873+ g_hash_table_destroy(details);
874 }
875
876 void QIndividual::updateFullName(const QtContacts::QContactDetail &detail, void* data)
877 {
878- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
879- QContactDetail originalLabel = m_contact.detail(QContactDetail::TypeDisplayLabel);
880- if (FOLKS_IS_NAME_DETAILS(udata->m_persona) && (originalLabel != detail)) {
881+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
882+ QContactDetail originalLabel = detailFromUri(QContactDetail::TypeDisplayLabel, detail.detailUri());
883+
884+ if (persona == 0) {
885+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseFullNameDetails, data);
886+ } else if (FOLKS_IS_NAME_DETAILS(persona) && (originalLabel != detail)) {
887+ qDebug() << "Full Name diff";
888+ qDebug() << "\t" << originalLabel << "\n\t" << detail;
889+
890 const QContactDisplayLabel *label = static_cast<const QContactDisplayLabel*>(&detail);
891
892- folks_name_details_change_full_name(FOLKS_NAME_DETAILS(udata->m_persona),
893+ folks_name_details_change_full_name(FOLKS_NAME_DETAILS(persona),
894 label->label().toUtf8().data(),
895 (GAsyncReadyCallback) updateDetailsDone,
896 data);
897 } else {
898- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
899+ updateDetailsDone(G_OBJECT(persona), NULL, data);
900 }
901 }
902
903 void QIndividual::updateName(const QtContacts::QContactDetail &detail, void* data)
904 {
905- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
906- QContactDetail originalName = m_contact.detail(QContactDetail::TypeName);
907- if (FOLKS_IS_NAME_DETAILS(udata->m_persona) && (originalName != detail)) {
908+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
909+ QContactDetail originalName = detailFromUri(QContactDetail::TypeName, detail.detailUri());
910+
911+ if (persona == 0) {
912+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseNameDetails, data);
913+ } else if (FOLKS_IS_NAME_DETAILS(persona) && (originalName != detail)) {
914+ qDebug() << "Name diff";
915+ qDebug() << "\t" << originalName << "\n\t" << detail;
916+
917 const QContactName *name = static_cast<const QContactName*>(&detail);
918- FolksStructuredName *sn = folks_name_details_get_structured_name(FOLKS_NAME_DETAILS(m_individual));
919- if (!sn) {
920- sn = folks_structured_name_new(name->lastName().toUtf8().data(),
921- name->firstName().toUtf8().data(),
922- name->middleName().toUtf8().data(),
923- name->prefix().toUtf8().data(),
924- name->suffix().toUtf8().data());
925- } else {
926- folks_structured_name_set_family_name(sn, name->lastName().toUtf8().data());
927- folks_structured_name_set_given_name(sn, name->firstName().toUtf8().data());
928- folks_structured_name_set_additional_names(sn, name->middleName().toUtf8().data());
929- folks_structured_name_set_prefixes(sn, name->prefix().toUtf8().data());
930- folks_structured_name_set_suffixes(sn, name->suffix().toUtf8().data());
931- }
932+ FolksStructuredName *sn;
933+ sn = folks_structured_name_new(name->lastName().toUtf8().data(),
934+ name->firstName().toUtf8().data(),
935+ name->middleName().toUtf8().data(),
936+ name->prefix().toUtf8().data(),
937+ name->suffix().toUtf8().data());
938
939- folks_name_details_change_structured_name(FOLKS_NAME_DETAILS(udata->m_persona),
940+ folks_name_details_change_structured_name(FOLKS_NAME_DETAILS(persona),
941 sn,
942 (GAsyncReadyCallback) updateDetailsDone,
943 data);
944+
945 g_object_unref(sn);
946 } else {
947- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
948+ updateDetailsDone(G_OBJECT(persona), NULL, data);
949 }
950 }
951
952 void QIndividual::updateNickname(const QtContacts::QContactDetail &detail, void* data)
953 {
954- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
955- QContactDetail originalNickname = m_contact.detail(QContactDetail::TypeNickname);
956- if (FOLKS_IS_NAME_DETAILS(udata->m_persona) && (originalNickname != detail)) {
957+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
958+ QContactDetail originalNickname = detailFromUri(QContactDetail::TypeNickname, detail.detailUri());
959+
960+ if (persona == 0) {
961+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseNicknameDetails, data);
962+ } else if (FOLKS_IS_NAME_DETAILS(persona) && (originalNickname != detail)) {
963 const QContactNickname *nickname = static_cast<const QContactNickname*>(&detail);
964- folks_name_details_change_nickname(FOLKS_NAME_DETAILS(udata->m_persona),
965+ folks_name_details_change_nickname(FOLKS_NAME_DETAILS(persona),
966 nickname->nickname().toUtf8().data(),
967 (GAsyncReadyCallback) updateDetailsDone,
968 data);
969 } else {
970- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
971+ updateDetailsDone(G_OBJECT(persona), NULL, data);
972 }
973 }
974
975 void QIndividual::updateBirthday(const QtContacts::QContactDetail &detail, void* data)
976 {
977- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
978- QContactDetail originalBirthday = m_contact.detail(QContactDetail::TypeBirthday);
979- if (FOLKS_IS_BIRTHDAY_DETAILS(udata->m_persona) && (originalBirthday != detail)) {
980+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
981+ QContactDetail originalBirthday = detailFromUri(QContactDetail::TypeBirthday, detail.detailUri());
982+
983+ if (persona == 0) {
984+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseBirthdayDetails, data);
985+ } else if (FOLKS_IS_BIRTHDAY_DETAILS(persona) && (originalBirthday != detail)) {
986 const QContactBirthday *birthday = static_cast<const QContactBirthday*>(&detail);
987+
988 GDateTime *dateTime = NULL;
989 if (!birthday->isEmpty()) {
990 dateTime = g_date_time_new_from_unix_utc(birthday->dateTime().toMSecsSinceEpoch() / 1000);
991 }
992- folks_birthday_details_change_birthday(FOLKS_BIRTHDAY_DETAILS(udata->m_persona),
993+ folks_birthday_details_change_birthday(FOLKS_BIRTHDAY_DETAILS(persona),
994 dateTime,
995 (GAsyncReadyCallback) updateDetailsDone,
996 data);
997 g_date_time_unref(dateTime);
998 } else {
999- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1000+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1001 }
1002 }
1003
1004 void QIndividual::updatePhoto(const QtContacts::QContactDetail &detail, void* data)
1005 {
1006- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1007- QContactDetail originalAvatar = m_contact.detail(QContactDetail::TypeAvatar);
1008- if (FOLKS_IS_AVATAR_DETAILS(udata->m_persona) && (detail != originalAvatar)) {
1009+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1010+ QContactDetail originalAvatar = detailFromUri(QContactDetail::TypeAvatar, detail.detailUri());
1011+
1012+ if (persona == 0) {
1013+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parsePhotoDetails, data);
1014+ } else if (FOLKS_IS_AVATAR_DETAILS(persona) && (detail != originalAvatar)) {
1015 //TODO:
1016 //const QContactAvatar *avatar = static_cast<const QContactAvatar*>(&detail);
1017- folks_avatar_details_change_avatar(FOLKS_AVATAR_DETAILS(udata->m_persona),
1018+ folks_avatar_details_change_avatar(FOLKS_AVATAR_DETAILS(persona),
1019 0,
1020 (GAsyncReadyCallback) updateDetailsDone,
1021 data);
1022 } else {
1023- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1024+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1025 }
1026 }
1027
1028-void QIndividual::updateTimezone(const QtContacts::QContactDetail &detail, void* data)
1029-{
1030- //TODO
1031- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1032- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1033-}
1034-
1035-void QIndividual::updateRoles(QList<QtContacts::QContactDetail> details, void* data)
1036-{
1037- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1038- QList<QContactDetail> originalOrganizations = m_contact.details(QContactDetail::TypeOrganization);
1039-
1040- if (FOLKS_IS_ROLE_DETAILS(udata->m_persona) && !detailListIsEqual(originalOrganizations, details)) {
1041- GeeSet *roleSet = SET_AFD_NEW();
1042- Q_FOREACH(const QContactDetail& detail, details) {
1043- const QContactOrganization *org = static_cast<const QContactOrganization*>(&detail);
1044-
1045- // The role values can not be NULL
1046- const gchar* title = org->title().toUtf8().data();
1047- const gchar* name = org->name().toUtf8().data();
1048- const gchar* roleName = org->role().toUtf8().data();
1049-
1050- FolksRole *role = folks_role_new(title ? title : "", name ? name : "", "");
1051- folks_role_set_role(role, roleName ? roleName : "");
1052-
1053- FolksRoleFieldDetails *fieldDetails = folks_role_field_details_new(role, NULL);
1054- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(fieldDetails), detail);
1055- gee_collection_add(GEE_COLLECTION(roleSet), fieldDetails);
1056-
1057- g_object_unref(role);
1058- g_object_unref(fieldDetails);
1059- }
1060-
1061- folks_role_details_change_roles(FOLKS_ROLE_DETAILS(udata->m_persona),
1062+void QIndividual::updateRole(QtContacts::QContactDetail detail, void* data)
1063+{
1064+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1065+ QContactDetail originalRole = detailFromUri(QContactDetail::TypeOrganization, detail.detailUri());
1066+
1067+ if (!persona) {
1068+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseOrganizationDetails, data);
1069+ } else if (FOLKS_IS_ROLE_DETAILS(persona) && (originalRole != detail)) {
1070+ qDebug() << "Role diff";
1071+ qDebug() << "\t" << originalRole << "\n\t" << detail;
1072+
1073+ FolksRoleFieldDetails *roleDetails = 0;
1074+ const QContactOrganization *cRole = static_cast<const QContactOrganization*>(&detail);
1075+ GeeSet *roleSet = folks_role_details_get_roles(FOLKS_ROLE_DETAILS(persona));
1076+
1077+ if (!roleSet || (gee_collection_get_size(GEE_COLLECTION(roleSet)) == 0)) {
1078+ roleSet = SET_AFD_NEW();
1079+ } else {
1080+ roleDetails = FOLKS_ROLE_FIELD_DETAILS(QIndividualUtils::getDetails(roleSet, detail.detailUri()));
1081+ // this will be unref at the end of the function
1082+ g_object_ref(roleSet);
1083+ g_object_ref(roleDetails);
1084+ }
1085+
1086+ const gchar* title = cRole->title().isEmpty() ? "" : cRole->title().toUtf8().data();
1087+ const gchar* name = cRole->name().isEmpty() ? "" : cRole->name().toUtf8().data();
1088+ const gchar* roleName = cRole->role().isEmpty() ? "" : cRole->role().toUtf8().data();
1089+
1090+ FolksRole *roleValue;
1091+ if (!roleDetails) {
1092+ roleValue = folks_role_new(title, name, "");
1093+ folks_role_set_role(roleValue, roleName);
1094+
1095+ roleDetails = folks_role_field_details_new(roleValue, NULL);
1096+ gee_collection_add(GEE_COLLECTION(roleSet), roleDetails);
1097+ } else {
1098+ roleValue = FOLKS_ROLE(folks_abstract_field_details_get_value(FOLKS_ABSTRACT_FIELD_DETAILS(roleDetails)));
1099+ folks_role_set_organisation_name(roleValue, name);
1100+ folks_role_set_title(roleValue, title);
1101+ folks_role_set_role(roleValue, roleName);
1102+ }
1103+
1104+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(roleDetails), detail);
1105+ folks_role_details_change_roles(FOLKS_ROLE_DETAILS(persona),
1106 roleSet,
1107 (GAsyncReadyCallback) updateDetailsDone,
1108 data);
1109+
1110+ g_object_unref(roleDetails);
1111 g_object_unref(roleSet);
1112+ g_object_unref(roleValue);
1113 } else {
1114- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1115+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1116 }
1117 }
1118
1119-void QIndividual::updateEmails(QList<QtContacts::QContactDetail> details, void* data)
1120+void QIndividual::updateEmail(QtContacts::QContactDetail detail, void* data)
1121 {
1122- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1123- QList<QContactDetail> originalEmails = m_contact.details(QContactDetail::TypeEmailAddress);
1124-
1125- if (FOLKS_IS_EMAIL_DETAILS(udata->m_persona) && !detailListIsEqual(originalEmails, details)) {
1126- GeeSet *emailSet = SET_AFD_NEW();
1127- Q_FOREACH(const QContactDetail& detail, details) {
1128- const QContactEmailAddress *email = static_cast<const QContactEmailAddress*>(&detail);
1129-
1130- if(!email->isEmpty()) {
1131- FolksEmailFieldDetails *emailDetails = folks_email_field_details_new(email->emailAddress().toUtf8().data(), NULL);
1132- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(emailDetails), detail);
1133- gee_collection_add(GEE_COLLECTION(emailSet), emailDetails);
1134- g_object_unref(emailDetails);
1135- }
1136- }
1137- folks_email_details_change_email_addresses(FOLKS_EMAIL_DETAILS(udata->m_persona),
1138+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1139+ QContactDetail originalEmail = detailFromUri(QContactDetail::TypeEmailAddress, detail.detailUri());
1140+
1141+ if (!persona) {
1142+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseEmailDetails, data);
1143+ } else if (FOLKS_IS_EMAIL_DETAILS(persona) && (originalEmail != detail)) {
1144+ qDebug() << "email diff";
1145+ qDebug() << "\t" << originalEmail << "\n\t" << detail;
1146+
1147+ FolksEmailFieldDetails *emailDetails = 0;
1148+ const QContactEmailAddress *email = static_cast<const QContactEmailAddress*>(&detail);
1149+ GeeSet *emailSet = folks_email_details_get_email_addresses(FOLKS_EMAIL_DETAILS(persona));
1150+ if (!emailSet || (gee_collection_get_size(GEE_COLLECTION(emailSet)) == 0)) {
1151+ emailSet = SET_AFD_NEW();
1152+ } else {
1153+ emailDetails = FOLKS_EMAIL_FIELD_DETAILS(QIndividualUtils::getDetails(emailSet, detail.detailUri()));
1154+ // this will be unref at the end of the function
1155+ g_object_ref(emailSet);
1156+ g_object_ref(emailDetails);
1157+ }
1158+
1159+ if (!emailDetails) {
1160+ emailDetails = folks_email_field_details_new(email->emailAddress().toUtf8().data(), NULL);
1161+ gee_collection_add(GEE_COLLECTION(emailSet), emailDetails);
1162+ } else {
1163+ folks_abstract_field_details_set_value(FOLKS_ABSTRACT_FIELD_DETAILS(emailDetails),
1164+ email->emailAddress().toUtf8().data());
1165+ }
1166+
1167+ folks_email_details_change_email_addresses(FOLKS_EMAIL_DETAILS(persona),
1168 emailSet,
1169 (GAsyncReadyCallback) updateDetailsDone,
1170 data);
1171+
1172 g_object_unref(emailSet);
1173+ g_object_unref(emailDetails);
1174 } else {
1175- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1176+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1177 }
1178 }
1179
1180-void QIndividual::updatePhones(QList<QtContacts::QContactDetail> details, void* data)
1181+void QIndividual::updatePhone(QtContacts::QContactDetail detail, void* data)
1182 {
1183- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1184- QList<QContactDetail> originalPhones = m_contact.details(QContactDetail::TypePhoneNumber);
1185-
1186- if (FOLKS_IS_PHONE_DETAILS(udata->m_persona) && !detailListIsEqual(originalPhones, details)) {
1187- GeeSet *phoneSet = SET_AFD_NEW();
1188- Q_FOREACH(const QContactDetail& detail, details) {
1189- const QContactPhoneNumber *phone = static_cast<const QContactPhoneNumber*>(&detail);
1190-
1191- if(!phone->isEmpty()) {
1192- FolksPhoneFieldDetails *phoneDetails = folks_phone_field_details_new(phone->number().toUtf8().data(), NULL);
1193- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(phoneDetails), detail);
1194- gee_collection_add(GEE_COLLECTION(phoneSet), phoneDetails);
1195- g_object_unref(phoneDetails);
1196- }
1197- }
1198- folks_phone_details_change_phone_numbers(FOLKS_PHONE_DETAILS(udata->m_persona),
1199+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1200+ QContactDetail originalPhone = detailFromUri(QContactDetail::TypePhoneNumber, detail.detailUri());
1201+ // if we do not have a persona for this detail we need to create one
1202+ if (!persona) {
1203+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parsePhoneNumbersDetails, data);
1204+ } else if (FOLKS_IS_PHONE_DETAILS(persona) && (originalPhone != detail)) {
1205+ qDebug() << "Phone diff";
1206+ qDebug() << "\t" << originalPhone << "\n\t" << detail;
1207+
1208+ /// Only update the details on the current persona
1209+ FolksPhoneFieldDetails *phoneDetails = 0;
1210+ const QContactPhoneNumber *phone = static_cast<const QContactPhoneNumber*>(&detail);
1211+ GeeSet *phoneSet = folks_phone_details_get_phone_numbers(FOLKS_PHONE_DETAILS(persona));
1212+
1213+ if (!phoneSet || (gee_collection_get_size(GEE_COLLECTION(phoneSet)) == 0)) {
1214+ phoneSet = SET_AFD_NEW();
1215+ } else {
1216+ phoneDetails = FOLKS_PHONE_FIELD_DETAILS(QIndividualUtils::getDetails(phoneSet, detail.detailUri()));
1217+ // this will be unref at the end of the function
1218+ g_object_ref(phoneSet);
1219+ g_object_ref(phoneDetails);
1220+ }
1221+
1222+ if (!phoneDetails) {
1223+ phoneDetails = folks_phone_field_details_new(phone->number().toUtf8().data(), NULL);
1224+ gee_collection_add(GEE_COLLECTION(phoneSet), phoneDetails);
1225+ } else {
1226+ folks_abstract_field_details_set_value(FOLKS_ABSTRACT_FIELD_DETAILS(phoneDetails),
1227+ phone->number().toUtf8().data());
1228+ }
1229+
1230+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(phoneDetails), detail);
1231+ folks_phone_details_change_phone_numbers(FOLKS_PHONE_DETAILS(persona),
1232 phoneSet,
1233 (GAsyncReadyCallback) updateDetailsDone,
1234 data);
1235+ g_object_unref(phoneDetails);
1236 g_object_unref(phoneSet);
1237 } else {
1238- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1239- }
1240-}
1241-
1242-bool QIndividual::detailListIsEqual(QList<QtContacts::QContactDetail> original, QList<QtContacts::QContactDetail> details)
1243-{
1244- if (original.size() != details.size()) {
1245- return false;
1246- }
1247-
1248- Q_FOREACH(const QContactDetail& detail, details) {
1249- if (!original.contains(detail)) {
1250- return false;
1251- }
1252- }
1253-
1254- return true;
1255-}
1256-
1257-void QIndividual::updateAddresses(QList<QtContacts::QContactDetail> details, void* data)
1258-{
1259- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1260- QList<QContactDetail> originalAddress = m_contact.details(QContactDetail::TypeAddress);
1261-
1262- if (FOLKS_IS_POSTAL_ADDRESS_DETAILS(udata->m_persona) && !detailListIsEqual(originalAddress, details)) {
1263- GeeSet *addressSet = SET_AFD_NEW();
1264- Q_FOREACH(const QContactDetail& detail, details) {
1265- const QContactAddress *address = static_cast<const QContactAddress*>(&detail);
1266- if (!address->isEmpty()) {
1267- FolksPostalAddress *postalAddress = folks_postal_address_new(address->postOfficeBox().toUtf8().data(),
1268- NULL,
1269- address->street().toUtf8().data(),
1270- address->locality().toUtf8().data(),
1271- address->region().toUtf8().data(),
1272- address->postcode().toUtf8().data(),
1273- address->country().toUtf8().data(),
1274- NULL,
1275- NULL);
1276- FolksPostalAddressFieldDetails *pafd = folks_postal_address_field_details_new(postalAddress, NULL);
1277-
1278- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(pafd), detail);
1279- gee_collection_add(GEE_COLLECTION(addressSet), pafd);
1280-
1281- g_object_unref(postalAddress);
1282- g_object_unref(pafd);
1283- }
1284- }
1285-
1286- folks_postal_address_details_change_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(udata->m_persona),
1287- addressSet,
1288+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1289+ }
1290+}
1291+
1292+void QIndividual::updateAddress(QtContacts::QContactDetail detail, void* data)
1293+{
1294+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1295+ QContactDetail originalAddress = detailFromUri(QContactDetail::TypeAddress, detail.detailUri());
1296+
1297+ if (!persona) {
1298+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseAddressDetails, data);
1299+ } else if (FOLKS_IS_POSTAL_ADDRESS_DETAILS(persona) && (originalAddress != detail)) {
1300+
1301+
1302+ FolksPostalAddressFieldDetails *addrDetails = 0;
1303+ const QContactAddress *addr = static_cast<const QContactAddress*>(&detail);
1304+ const QContactAddress *addro = static_cast<const QContactAddress*>(&originalAddress);
1305+
1306+ qDebug() << "Adderess diff";
1307+ qDebug() << "\t" << *addro << "subtypes:" << addro->subTypes() << "context" << addro->contexts();
1308+ qDebug() << "\t" << *addr << "subtypes:" << addr->subTypes() << "context" << addr->contexts();
1309+
1310+
1311+ qDebug() << "SubTypes:" << addr->subTypes();
1312+ GeeSet *addrSet = folks_postal_address_details_get_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(persona));
1313+
1314+ if (!addrSet || (gee_collection_get_size(GEE_COLLECTION(addrSet)) == 0)) {
1315+ addrSet = SET_AFD_NEW();
1316+ } else {
1317+ addrDetails = FOLKS_POSTAL_ADDRESS_FIELD_DETAILS(QIndividualUtils::getDetails(addrSet, detail.detailUri()));
1318+ // this will be unref at the end of the function
1319+ g_object_ref(addrSet);
1320+ g_object_ref(addrDetails);
1321+ }
1322+
1323+ FolksPostalAddress *addrValue;
1324+ if (!addrDetails) {
1325+ addrValue = folks_postal_address_new(addr->postOfficeBox().toUtf8().data(),
1326+ NULL,
1327+ addr->street().toUtf8().data(),
1328+ addr->locality().toUtf8().data(),
1329+ addr->region().toUtf8().data(),
1330+ addr->postcode().toUtf8().data(),
1331+ addr->country().toUtf8().data(),
1332+ NULL,
1333+ NULL);
1334+ addrDetails = folks_postal_address_field_details_new(addrValue, NULL);
1335+ gee_collection_add(GEE_COLLECTION(addrSet), addrDetails);
1336+ } else {
1337+ addrValue = FOLKS_POSTAL_ADDRESS(folks_abstract_field_details_get_value(FOLKS_ABSTRACT_FIELD_DETAILS(addrDetails)));
1338+ Q_ASSERT(addrValue);
1339+ folks_postal_address_set_po_box(addrValue, addr->postOfficeBox().toUtf8().data());
1340+ folks_postal_address_set_street(addrValue, addr->street().toUtf8().data());
1341+ folks_postal_address_set_locality(addrValue, addr->locality().toUtf8().data());
1342+ folks_postal_address_set_region(addrValue, addr->region().toUtf8().data());
1343+ folks_postal_address_set_postal_code(addrValue, addr->postcode().toUtf8().data());
1344+ folks_postal_address_set_country(addrValue, addr->country().toUtf8().data());
1345+ }
1346+
1347+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(addrDetails), detail);
1348+ folks_postal_address_details_change_postal_addresses(FOLKS_POSTAL_ADDRESS_DETAILS(persona),
1349+ addrSet,
1350 (GAsyncReadyCallback) updateDetailsDone,
1351 data);
1352- g_object_unref(addressSet);
1353+ g_object_unref(addrDetails);
1354+ g_object_unref(addrSet);
1355+ g_object_unref(addrValue);
1356 } else {
1357- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1358+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1359 }
1360 }
1361
1362-void QIndividual::updateIms(QList<QtContacts::QContactDetail> details, void* data)
1363+void QIndividual::updateIm(QtContacts::QContactDetail detail, void* data)
1364 {
1365- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1366- QList<QContactDetail> originalIms = m_contact.details(QContactDetail::TypeOnlineAccount);
1367-
1368- if (FOLKS_IS_IM_DETAILS(udata->m_persona) && !detailListIsEqual(originalIms, details)) {
1369- GeeMultiMap *imAddressHash = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);
1370- Q_FOREACH(const QContactDetail& detail, details) {
1371- const QContactOnlineAccount *im = static_cast<const QContactOnlineAccount*>(&detail);
1372- if (!im->accountUri().isEmpty()) {
1373- FolksImFieldDetails *imfd = folks_im_field_details_new(im->accountUri().toUtf8().data(), NULL);
1374- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(imfd), detail);
1375- gee_multi_map_set(imAddressHash,
1376- onlineAccountProtocolFromEnum(im->protocol()).toUtf8().data(), imfd);
1377- g_object_unref(imfd);
1378+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1379+ QContactDetail originalIm = detailFromUri(QContactDetail::TypeOnlineAccount, detail.detailUri());
1380+
1381+ if (!persona) {
1382+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseImDetails, data);
1383+ } else if (FOLKS_IS_IM_DETAILS(persona) && (originalIm != detail)) {
1384+ qDebug() << "Im diff";
1385+ qDebug() << "\t" << originalIm << "\n\t" << detail;
1386+
1387+ const QContactOnlineAccount *im = static_cast<const QContactOnlineAccount*>(&detail);
1388+ GeeMultiMap *imSet = folks_im_details_get_im_addresses(FOLKS_IM_DETAILS(persona));
1389+
1390+ if (!imSet || (gee_multi_map_get_size(GEE_MULTI_MAP(imSet)) == 0)) {
1391+ imSet = GEE_MULTI_MAP_AFD_NEW(FOLKS_TYPE_IM_FIELD_DETAILS);
1392+ } else {
1393+ // We can not relay on the index inside of detailUri because online account are stored in a hash
1394+ QContactOnlineAccount oldIm = static_cast<QContactOnlineAccount>(originalIm);
1395+ QString oldProtocolName = onlineAccountProtocolFromEnum(oldIm.protocol());
1396+ GeeCollection *value = gee_multi_map_get(imSet, oldProtocolName.toUtf8().data());
1397+
1398+ // Remove the old one
1399+ if (value) {
1400+ // if there is more than one address only remove the correct one
1401+ if (gee_collection_get_size(value) > 1) {
1402+ gee_collection_remove(value, oldIm.accountUri().toUtf8().data());
1403+ } else {
1404+ // otherwise remove the key
1405+ gee_multi_map_remove_all(imSet, oldProtocolName.toUtf8().data());
1406+ }
1407 }
1408+
1409+ g_object_ref(imSet);
1410 }
1411
1412- folks_im_details_change_im_addresses(FOLKS_IM_DETAILS(udata->m_persona),
1413- imAddressHash,
1414+ // Append the new one
1415+ FolksImFieldDetails *imDetails = folks_im_field_details_new(im->accountUri().toUtf8().data(), NULL);
1416+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(imDetails), detail);
1417+
1418+ gee_multi_map_set(imSet,
1419+ onlineAccountProtocolFromEnum(im->protocol()).toUtf8().data(),
1420+ imDetails);
1421+
1422+ folks_im_details_change_im_addresses(FOLKS_IM_DETAILS(persona),
1423+ imSet,
1424 (GAsyncReadyCallback) updateDetailsDone,
1425 data);
1426- g_object_unref(imAddressHash);
1427+ g_object_unref(imSet);
1428+ g_object_unref(imDetails);
1429 } else {
1430- updateDetailsDone(G_OBJECT(udata->m_persona), NULL, data);
1431+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1432 }
1433 }
1434
1435-void QIndividual::updateUrls(QList<QtContacts::QContactDetail> details, void* data)
1436+void QIndividual::updateUrl(QtContacts::QContactDetail detail, void* data)
1437 {
1438- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1439- QList<QContactDetail> originalUrls = m_contact.details(QContactDetail::TypeUrl);
1440-
1441- if (FOLKS_IS_URL_DETAILS(udata->m_persona) && !detailListIsEqual(originalUrls, details)) {
1442- GeeSet *urlSet = SET_AFD_NEW();
1443- Q_FOREACH(const QContactDetail& detail, details) {
1444- const QContactUrl *url = static_cast<const QContactUrl*>(&detail);
1445-
1446- if(!url->isEmpty()) {
1447- FolksUrlFieldDetails *urlDetails = folks_url_field_details_new(url->url().toUtf8().data(), NULL);
1448- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(urlDetails), detail);
1449- gee_collection_add(GEE_COLLECTION(urlSet), urlDetails);
1450- g_object_unref(urlDetails);
1451- }
1452- }
1453- folks_url_details_change_urls(FOLKS_URL_DETAILS(udata->m_persona),
1454+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1455+ QContactDetail originalUrl = detailFromUri(QContactDetail::TypeUrl, detail.detailUri());
1456+
1457+ if (!persona) {
1458+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseUrlDetails, data);
1459+ } else if (FOLKS_IS_URL_DETAILS(persona) && (originalUrl != detail)) {
1460+ qDebug() << "Url diff";
1461+ qDebug() << "\t" << originalUrl << "\n\t" << detail;
1462+
1463+ FolksUrlFieldDetails *urlDetails = 0;
1464+ const QContactUrl *url = static_cast<const QContactUrl*>(&detail);
1465+ GeeSet *urlSet = folks_url_details_get_urls(FOLKS_URL_DETAILS(persona));
1466+
1467+ if (!urlSet || (gee_collection_get_size(GEE_COLLECTION(urlSet)) == 0)) {
1468+ urlSet = SET_AFD_NEW();
1469+ } else {
1470+ urlDetails = FOLKS_URL_FIELD_DETAILS(QIndividualUtils::getDetails(urlSet, detail.detailUri()));
1471+
1472+ // this will be unref at the end of the function
1473+ g_object_ref(urlSet);
1474+ g_object_ref(urlDetails);
1475+ }
1476+
1477+ if (!urlDetails) {
1478+ urlDetails = folks_url_field_details_new(url->url().toUtf8().data(), NULL);
1479+ gee_collection_add(GEE_COLLECTION(urlSet), urlDetails);
1480+ } else {
1481+ folks_abstract_field_details_set_value(FOLKS_ABSTRACT_FIELD_DETAILS(urlDetails),
1482+ url->url().toUtf8().data());
1483+ }
1484+
1485+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(urlDetails), detail);
1486+ folks_url_details_change_urls(FOLKS_URL_DETAILS(persona),
1487 urlSet,
1488 (GAsyncReadyCallback) updateDetailsDone,
1489 data);
1490+ g_object_unref(urlDetails);
1491 g_object_unref(urlSet);
1492 } else {
1493- updateDetailsDone(G_OBJECT(m_individual), NULL, data);
1494+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1495 }
1496 }
1497
1498-void QIndividual::updateNotes(QList<QtContacts::QContactDetail> details, void* data)
1499+void QIndividual::updateNote(QtContacts::QContactDetail detail, void* data)
1500 {
1501- UpdateContactData *udata = static_cast<UpdateContactData*>(data);
1502- QList<QContactDetail> originalNotes = m_contact.details(QContactDetail::TypeNote);
1503-
1504- if (FOLKS_IS_NOTE_DETAILS(udata->m_persona) && !detailListIsEqual(originalNotes, details)) {
1505- GeeSet *noteSet = SET_AFD_NEW();
1506- Q_FOREACH(const QContactDetail& detail, details) {
1507- const QContactNote *note = static_cast<const QContactNote*>(&detail);
1508-
1509- if(!note->isEmpty()) {
1510- FolksNoteFieldDetails *noteDetails = folks_note_field_details_new(note->note().toUtf8().data(), NULL, 0);
1511-
1512- //TODO: set context
1513- gee_collection_add(GEE_COLLECTION(noteSet), noteDetails);
1514- g_object_unref(noteDetails);
1515- }
1516- }
1517- folks_note_details_change_notes(FOLKS_NOTE_DETAILS(udata->m_persona),
1518+ FolksPersona *persona = QIndividualUtils::personaFromUri(detail.detailUri(), m_individual, primaryPersona());
1519+ QContactDetail originalNote = detailFromUri(QContactDetail::TypeNote, detail.detailUri());
1520+
1521+ if (!persona) {
1522+ createPersonaForDetail(QList<QContactDetail>() << detail, QIndividual::parseNoteDetails, data);
1523+ } else if (FOLKS_IS_URL_DETAILS(persona) && (originalNote != detail)) {
1524+ qDebug() << "Note diff";
1525+ qDebug() << "\t" << originalNote << "\n\t" << detail;
1526+
1527+ FolksNoteFieldDetails *noteDetails = 0;
1528+ const QContactNote *note = static_cast<const QContactNote*>(&detail);
1529+ GeeSet *noteSet = folks_note_details_get_notes(FOLKS_NOTE_DETAILS(persona));
1530+
1531+ if (!noteSet || (gee_collection_get_size(GEE_COLLECTION(noteSet)) == 0)) {
1532+ noteSet = SET_AFD_NEW();
1533+ } else {
1534+ noteDetails = FOLKS_NOTE_FIELD_DETAILS(QIndividualUtils::getDetails(noteSet, detail.detailUri()));
1535+
1536+ // this will be unref at the end of the function
1537+ g_object_ref(noteSet);
1538+ g_object_ref(noteDetails);
1539+ }
1540+
1541+ if (!noteDetails) {
1542+ noteDetails = folks_note_field_details_new(note->note().toUtf8().data(), NULL, 0);
1543+ gee_collection_add(GEE_COLLECTION(noteSet), noteDetails);
1544+ } else {
1545+ folks_abstract_field_details_set_value(FOLKS_ABSTRACT_FIELD_DETAILS(noteDetails),
1546+ note->note().toUtf8().data());
1547+ }
1548+
1549+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(noteDetails), detail);
1550+ folks_note_details_change_notes(FOLKS_NOTE_DETAILS(persona),
1551 noteSet,
1552 (GAsyncReadyCallback) updateDetailsDone,
1553- data);
1554+ data);;
1555+ g_object_unref(noteDetails);
1556 g_object_unref(noteSet);
1557 } else {
1558- updateDetailsDone(G_OBJECT(m_individual), NULL, data);
1559- }
1560-}
1561-
1562+ updateDetailsDone(G_OBJECT(persona), NULL, data);
1563+ }
1564+}
1565+
1566+QString QIndividual::callDetailChangeFinish(QtContacts::QContactDetail::DetailType detailType,
1567+ FolksPersona *persona,
1568+ GAsyncResult *result)
1569+{
1570+ Q_ASSERT(persona);
1571+ Q_ASSERT(result);
1572+
1573+ GError *error = 0;
1574+ switch(detailType) {
1575+ case QContactDetail::TypeAddress:
1576+ folks_postal_address_details_change_postal_addresses_finish(FOLKS_POSTAL_ADDRESS_DETAILS(persona), result, &error);
1577+ break;
1578+ case QContactDetail::TypeAvatar:
1579+ folks_avatar_details_change_avatar_finish(FOLKS_AVATAR_DETAILS(persona), result, &error);
1580+ break;
1581+ case QContactDetail::TypeBirthday:
1582+ folks_birthday_details_change_birthday_finish(FOLKS_BIRTHDAY_DETAILS(persona), result, &error);
1583+ break;
1584+ case QContactDetail::TypeDisplayLabel:
1585+ folks_name_details_change_full_name_finish(FOLKS_NAME_DETAILS(persona), result, &error);
1586+ break;
1587+ case QContactDetail::TypeEmailAddress:
1588+ folks_email_details_change_email_addresses_finish(FOLKS_EMAIL_DETAILS(persona), result, &error);
1589+ break;
1590+ case QContactDetail::TypeName:
1591+ folks_name_details_change_structured_name_finish(FOLKS_NAME_DETAILS(persona), result, &error);
1592+ break;
1593+ case QContactDetail::TypeNickname:
1594+ folks_name_details_change_nickname_finish(FOLKS_NAME_DETAILS(persona), result, &error);
1595+ break;
1596+ case QContactDetail::TypeNote:
1597+ folks_note_details_change_notes_finish(FOLKS_NOTE_DETAILS(persona), result, &error);
1598+ break;
1599+ case QContactDetail::TypeOnlineAccount:
1600+ folks_im_details_change_im_addresses_finish(FOLKS_IM_DETAILS(persona), result, &error);
1601+ break;
1602+ case QContactDetail::TypeOrganization:
1603+ folks_role_details_change_roles_finish(FOLKS_ROLE_DETAILS(persona), result, &error);
1604+ break;
1605+ case QContactDetail::TypePhoneNumber:
1606+ folks_phone_details_change_phone_numbers_finish(FOLKS_PHONE_DETAILS(persona), result, &error);
1607+ break;
1608+ case QContactDetail::TypeUrl:
1609+ folks_url_details_change_urls_finish(FOLKS_URL_DETAILS(persona), result, &error);
1610+ default:
1611+ break;
1612+ }
1613+
1614+ QString errorMessage;
1615+ if (error) {
1616+ errorMessage = QString::fromUtf8(error->message);
1617+ g_error_free(error);
1618+ }
1619+ return errorMessage;
1620+}
1621+
1622+void QIndividual::updateDetailsSendReply(gpointer userdata, const QString &errorMessage)
1623+{
1624+ UpdateContactData *data = static_cast<UpdateContactData*>(userdata);
1625+ data->m_slot.invoke(data->m_object,
1626+ Q_ARG(QIndividual*, data->m_self), Q_ARG(QString, errorMessage));
1627+ delete data;
1628+}
1629+
1630+void QIndividual::updateDetailsSendReply(gpointer userdata, GError *error)
1631+{
1632+ QString errorMessage;
1633+ if (error) {
1634+ errorMessage = QString::fromUtf8(error->message);
1635+ qWarning() << error->message;
1636+ g_error_free(error);
1637+ }
1638+ updateDetailsSendReply(userdata, errorMessage);
1639+}
1640+
1641+
1642+void QIndividual::createPersonaDone(GObject *aggregator, GAsyncResult *result, gpointer userdata)
1643+{
1644+ qDebug() << Q_FUNC_INFO;
1645+ UpdateContactData *data = static_cast<UpdateContactData*>(userdata);
1646+
1647+ // A new persona was create to store the new data
1648+ GError *error = 0;
1649+ FolksPersona *newPersona = folks_individual_aggregator_add_persona_from_details_finish(FOLKS_INDIVIDUAL_AGGREGATOR(aggregator),
1650+ result,
1651+ &error);
1652+ if (error) {
1653+ updateDetailsSendReply(data, error);
1654+ } else {
1655+ // Link the new personas
1656+ GeeSet *personas = folks_individual_get_personas(data->m_self->m_individual);
1657+ GeeSet *newPersonas = SET_PERSONA_NEW();
1658+ gee_collection_add_all(GEE_COLLECTION(newPersonas), GEE_COLLECTION(personas));
1659+ gee_collection_add(GEE_COLLECTION(newPersonas), newPersona);
1660+ data->m_self->m_primaryPersona = newPersona;
1661+ folks_individual_aggregator_link_personas(data->m_self->m_aggregator, newPersonas, updateDetailsDone, userdata);
1662+ }
1663+}
1664
1665 void QIndividual::updateDetailsDone(GObject *detail, GAsyncResult *result, gpointer userdata)
1666 {
1667- GError *error = 0;
1668+ QString errorMessage;
1669 UpdateContactData *data = static_cast<UpdateContactData*>(userdata);
1670-
1671- switch(data->m_currentDetailType) {
1672+ if (result && !data->m_currentDetail.isEmpty()) {
1673+ if (FOLKS_IS_PERSONA(detail)) {
1674+ // This is a normal field update
1675+ errorMessage = QIndividual::callDetailChangeFinish(data->m_currentDetail.type(),
1676+ FOLKS_PERSONA(detail),
1677+ result);
1678+ } else if (FOLKS_IS_INDIVIDUAL_AGGREGATOR(detail)) {
1679+ GError *error = 0;
1680+ folks_individual_aggregator_link_personas_finish(FOLKS_INDIVIDUAL_AGGREGATOR(detail), result, &error);
1681+ if (error) {
1682+ errorMessage = QString::fromUtf8(error->message);
1683+ }
1684+ }
1685+
1686+ if (!errorMessage.isEmpty()) {
1687+ updateDetailsSendReply(data, errorMessage);
1688+ return;
1689+ }
1690+ }
1691+
1692+ if (data->m_details.isEmpty()) {
1693+ updateDetailsSendReply(data, 0);
1694+ return;
1695+ }
1696+
1697+
1698+ data->m_currentDetail = data->m_details.takeFirst();
1699+ switch(data->m_currentDetail.type()) {
1700 case QContactDetail::TypeAddress:
1701- if (result) {
1702- folks_postal_address_details_change_postal_addresses_finish(FOLKS_POSTAL_ADDRESS_DETAILS(data->m_persona), result, &error);
1703- }
1704- if (!error) {
1705- data->m_currentDetailType = QContactDetail::TypeAvatar;
1706- data->m_self->updatePhoto(data->m_newContact.detail(QContactDetail::TypeAvatar), data);
1707- return;
1708- }
1709+ data->m_self->updateAddress(data->m_currentDetail, data);
1710 break;
1711 case QContactDetail::TypeAvatar:
1712- if (result) {
1713- folks_avatar_details_change_avatar_finish(FOLKS_AVATAR_DETAILS(data->m_persona), result, &error);
1714- }
1715- if (!error) {
1716- data->m_currentDetailType = QContactDetail::TypeBirthday;
1717- data->m_self->updateBirthday(data->m_newContact.detail(QContactDetail::TypeBirthday), data);
1718- return;
1719- }
1720+ data->m_self->updatePhoto(data->m_currentDetail, data);
1721 break;
1722 case QContactDetail::TypeBirthday:
1723- if (result) {
1724- folks_birthday_details_change_birthday_finish(FOLKS_BIRTHDAY_DETAILS(data->m_persona), result, &error);
1725- }
1726- if (!error) {
1727- data->m_currentDetailType = QContactDetail::TypeDisplayLabel;
1728- data->m_self->updateFullName(data->m_newContact.detail(QContactDetail::TypeDisplayLabel), data);
1729- return;
1730- }
1731+ data->m_self->updateBirthday(data->m_currentDetail, data);
1732 break;
1733 case QContactDetail::TypeDisplayLabel:
1734- if (result) {
1735- folks_name_details_change_full_name_finish(FOLKS_NAME_DETAILS(data->m_persona), result, &error);
1736- }
1737- if (!error) {
1738- data->m_currentDetailType = QContactDetail::TypeEmailAddress;
1739- data->m_self->updateEmails(data->m_newContact.details(QContactDetail::TypeEmailAddress), data);
1740- return;
1741- }
1742+ data->m_self->updateFullName(data->m_currentDetail, data);
1743 break;
1744-
1745 case QContactDetail::TypeEmailAddress:
1746- if (result) {
1747- folks_email_details_change_email_addresses_finish(FOLKS_EMAIL_DETAILS(data->m_persona), result, &error);
1748- }
1749- if (!error) {
1750- data->m_currentDetailType = QContactDetail::TypeName;
1751- data->m_self->updateName(data->m_newContact.detail(QContactDetail::TypeName), data);
1752- return;
1753- }
1754+ data->m_self->updateEmail(data->m_currentDetail, data);
1755 break;
1756 case QContactDetail::TypeName:
1757- if (result) {
1758- folks_name_details_change_structured_name_finish(FOLKS_NAME_DETAILS(data->m_persona), result, &error);
1759- }
1760- if (!error) {
1761- data->m_currentDetailType = QContactDetail::TypeNickname;
1762- data->m_self->updateNickname(data->m_newContact.detail(QContactDetail::TypeNickname), data);
1763- return;
1764- }
1765+ data->m_self->updateName(data->m_currentDetail, data);
1766 break;
1767 case QContactDetail::TypeNickname:
1768- if (result) {
1769- folks_name_details_change_nickname_finish(FOLKS_NAME_DETAILS(data->m_persona), result, &error);
1770- }
1771- if (!error) {
1772- data->m_currentDetailType = QContactDetail::TypeNote;
1773- data->m_self->updateNotes(data->m_newContact.details(QContactDetail::TypeNote), data);
1774- return;
1775- }
1776+ data->m_self->updateNickname(data->m_currentDetail, data);
1777 break;
1778 case QContactDetail::TypeNote:
1779- if (result) {
1780- folks_note_details_change_notes_finish(FOLKS_NOTE_DETAILS(data->m_persona), result, &error);
1781- }
1782- if (!error) {
1783- data->m_currentDetailType = QContactDetail::TypeOnlineAccount;
1784- data->m_self->updateIms(data->m_newContact.details(QContactDetail::TypeOnlineAccount), data);
1785- return;
1786- }
1787+ data->m_self->updateNote(data->m_currentDetail, data);
1788 break;
1789 case QContactDetail::TypeOnlineAccount:
1790- if (result) {
1791- folks_im_details_change_im_addresses_finish(FOLKS_IM_DETAILS(data->m_persona), result, &error);
1792- }
1793- if (!error) {
1794- data->m_currentDetailType = QContactDetail::TypeOrganization;
1795- data->m_self->updateRoles(data->m_newContact.details(QContactDetail::TypeOrganization), data);
1796- return;
1797- }
1798+ data->m_self->updateIm(data->m_currentDetail, data);
1799 break;
1800 case QContactDetail::TypeOrganization:
1801- if (result) {
1802- folks_role_details_change_roles_finish(FOLKS_ROLE_DETAILS(data->m_persona), result, &error);
1803- }
1804- if (!error) {
1805- data->m_currentDetailType = QContactDetail::TypePhoneNumber;
1806- data->m_self->updatePhones(data->m_newContact.details(QContactDetail::TypePhoneNumber), data);
1807- return;
1808- }
1809+ data->m_self->updateRole(data->m_currentDetail, data);
1810 break;
1811 case QContactDetail::TypePhoneNumber:
1812- if (result) {
1813- folks_phone_details_change_phone_numbers_finish(FOLKS_PHONE_DETAILS(data->m_persona), result, &error);
1814- }
1815- if (!error) {
1816- data->m_currentDetailType = QContactDetail::TypeUrl;
1817- data->m_self->updateUrls(data->m_newContact.details(QContactDetail::TypeUrl), data);
1818- return;
1819- }
1820+ data->m_self->updatePhone(data->m_currentDetail, data);
1821 break;
1822 case QContactDetail::TypeUrl:
1823- if (result) {
1824- folks_url_details_change_urls_finish(FOLKS_URL_DETAILS(data->m_persona), result, &error);
1825- }
1826+ data->m_self->updateUrl(data->m_currentDetail, data);
1827+ break;
1828 default:
1829+ qWarning() << "Update not implemented for" << data->m_currentDetail.type();
1830+ updateDetailsDone(0, 0, data);
1831 break;
1832 }
1833-
1834- QString errorMessage;
1835- if (error) {
1836- errorMessage = QString::fromUtf8(error->message);
1837- g_error_free(error);
1838- }
1839-
1840- qDebug() << "Update done" << errorMessage;
1841- data->m_doneCB(errorMessage, data->m_doneData);
1842- delete data;
1843 }
1844
1845-
1846-bool QIndividual::update(const QtContacts::QContact &newContact, UpdateDoneCB cb, void* userData)
1847+bool QIndividual::update(const QtContacts::QContact &newContact, QObject *object, const QString &slot)
1848 {
1849+ int slotIndex = object->metaObject()->indexOfSlot(QMetaObject::normalizedSignature(slot.toUtf8().data()));
1850+ if (slotIndex == -1) {
1851+ qWarning() << "Invalid slot:" << slot << "for object" << object;
1852+ return false;
1853+ }
1854+
1855 QContact &originalContact = contact();
1856 if (newContact != originalContact) {
1857
1858 UpdateContactData *data = new UpdateContactData;
1859- data->m_currentDetailType = QContactDetail::TypeAddress;
1860+ data->m_details = newContact.details();
1861 data->m_newContact = newContact;
1862 data->m_self = this;
1863- data->m_doneCB = cb;
1864- data->m_doneData = userData;
1865- data->m_persona = primaryPersona();
1866-
1867- updateAddresses(newContact.details(QContactDetail::TypeAddress), data);
1868+ data->m_object = object;
1869+ data->m_slot = object->metaObject()->method(slotIndex);
1870+ updateDetailsDone(0, 0, data);
1871 return true;
1872 } else {
1873 qDebug() << "Contact is equal";
1874@@ -1160,10 +1490,26 @@
1875 return m_individual;
1876 }
1877
1878-bool QIndividual::update(const QString &vcard, UpdateDoneCB cb, void* data)
1879+void QIndividual::setIndividual(FolksIndividual *individual)
1880+{
1881+ if (m_individual != individual) {
1882+ if (m_individual) {
1883+ g_object_unref(m_individual);
1884+ }
1885+ m_individual = individual;
1886+ if (m_individual) {
1887+ g_object_ref(m_individual);
1888+ }
1889+ // initialize qcontact
1890+ m_contact = QContact();
1891+ updateContact();
1892+ }
1893+}
1894+
1895+bool QIndividual::update(const QString &vcard, QObject *object, const QString &slot)
1896 {
1897 QContact contact = VCardParser::vcardToContact(vcard);
1898- return update(contact, cb, data);
1899+ return update(contact, object, slot);
1900 }
1901
1902 QStringList QIndividual::listParameters(FolksAbstractFieldDetails *details)
1903@@ -1362,6 +1708,8 @@
1904 {
1905 static QMap<QString, int> map;
1906
1907+ qDebug() << "PArse paramater:" << parameters;
1908+
1909 // populate the map once
1910 if (map.isEmpty()) {
1911 map["home"] = QContactDetail::ContextHome;
1912@@ -1372,9 +1720,9 @@
1913 QList<int> values;
1914 QStringList accepted;
1915 Q_FOREACH(const QString &param, parameters) {
1916- if (map.contains(param)) {
1917+ if (map.contains(param.toLower())) {
1918 accepted << param;
1919- values << map[param];
1920+ values << map[param.toLower()];
1921 }
1922 }
1923
1924@@ -1382,6 +1730,8 @@
1925 parameters.removeOne(param);
1926 }
1927
1928+ qDebug() << "PArseed paramater (DONE):" << parameters;
1929+
1930 return values;
1931 }
1932
1933@@ -1407,8 +1757,8 @@
1934
1935 QList<int> subTypes;
1936 Q_FOREACH(const QString &param, params) {
1937- if (mapTypes.contains(param)) {
1938- subTypes << mapTypes[param];
1939+ if (mapTypes.contains(param.toLower())) {
1940+ subTypes << mapTypes[param.toLower()];
1941 } else {
1942 qWarning() << "Invalid phone parameter:" << param;
1943 }
1944@@ -1434,8 +1784,8 @@
1945 QList<int> values;
1946
1947 Q_FOREACH(const QString &param, parameters) {
1948- if (map.contains(param)) {
1949- values << map[param];
1950+ if (map.contains(param.toLower())) {
1951+ values << map[param.toLower()];
1952 } else {
1953 qWarning() << "invalid Address subtype" << param;
1954 }
1955@@ -1461,8 +1811,8 @@
1956 QSet<int> values;
1957
1958 Q_FOREACH(const QString &param, parameters) {
1959- if (map.contains(param)) {
1960- values << map[param];
1961+ if (map.contains(param.toLower())) {
1962+ values << map[param.toLower()];
1963 } else {
1964 qWarning() << "invalid IM subtype" << param;
1965 }
1966@@ -1497,8 +1847,8 @@
1967 map["yahoo"] = QContactOnlineAccount::ProtocolYahoo;
1968 }
1969
1970- if (map.contains(protocol)) {
1971- return map[protocol];
1972+ if (map.contains(protocol.toLower())) {
1973+ return map[protocol.toLower()];
1974 } else {
1975 qWarning() << "invalid IM protocol" << protocol;
1976 }
1977@@ -1532,31 +1882,26 @@
1978 return map[QContactOnlineAccount::ProtocolUnknown];
1979 }
1980
1981-GHashTable *QIndividual::parseDetails(const QtContacts::QContact &contact)
1982+GHashTable *QIndividual::parseAddressDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
1983 {
1984- GHashTable *details = g_hash_table_new_full(g_str_hash,
1985- g_str_equal,
1986- NULL,
1987- (GDestroyNotify) QIndividualUtils::gValueSliceFree);
1988- GValue *value;
1989-
1990- /*
1991- * Addresses
1992- */
1993- QList<QContactAddress> addresses = contact.details<QContactAddress>();
1994- if(addresses.size() > 0) {
1995- value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT);
1996- Q_FOREACH(const QContactAddress& address, addresses) {
1997- if(!address.isEmpty()) {
1998+ if(cDetails.size() == 0) {
1999+ return details;
2000+ }
2001+
2002+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT);
2003+
2004+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2005+ if(!detail.isEmpty()) {
2006+ QContactAddress address = static_cast<QContactAddress>(detail);
2007 FolksPostalAddress *postalAddress = folks_postal_address_new(address.postOfficeBox().toUtf8().data(),
2008- NULL, // extension
2009- address.street().toUtf8().data(),
2010- address.locality().toUtf8().data(),
2011- address.region().toUtf8().data(),
2012- address.postcode().toUtf8().data(),
2013- address.country().toUtf8().data(),
2014- NULL, // address format
2015- NULL); //UID
2016+ NULL, // extension
2017+ address.street().toUtf8().data(),
2018+ address.locality().toUtf8().data(),
2019+ address.region().toUtf8().data(),
2020+ address.postcode().toUtf8().data(),
2021+ address.country().toUtf8().data(),
2022+ NULL, // address format
2023+ NULL); //UID
2024
2025 GeeCollection *collection = (GeeCollection*) g_value_get_object(value);
2026 if(collection == NULL) {
2027@@ -1570,188 +1915,318 @@
2028
2029 g_object_unref(pafd);
2030 g_object_unref(postalAddress);
2031- }
2032 }
2033 QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_POSTAL_ADDRESSES, value);
2034 }
2035
2036-
2037- /*
2038- * Avatar
2039- */
2040- QContactAvatar avatar = contact.detail<QContactAvatar>();
2041- if(!avatar.isEmpty()) {
2042- value = QIndividualUtils::gValueSliceNew(G_TYPE_FILE_ICON);
2043- QUrl avatarUri = avatar.imageUrl();
2044- if(!avatarUri.isEmpty()) {
2045- QString formattedUri = avatarUri.toString(QUrl::RemoveUserInfo);
2046- if(!formattedUri.isEmpty()) {
2047- GFile *avatarFile = g_file_new_for_uri(formattedUri.toUtf8().data());
2048- GFileIcon *avatarFileIcon = G_FILE_ICON(g_file_icon_new(avatarFile));
2049- g_value_take_object(value, avatarFileIcon);
2050-
2051- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_AVATAR, value);
2052- g_clear_object((GObject**) &avatarFile);
2053- }
2054- }
2055- }
2056-
2057- /*
2058- * Birthday
2059- */
2060- QContactBirthday birthday = contact.detail<QContactBirthday>();
2061- if(!birthday.isEmpty()) {
2062- value = QIndividualUtils::gValueSliceNew(G_TYPE_DATE_TIME);
2063- GDateTime *dateTime = g_date_time_new_from_unix_utc(birthday.dateTime().toMSecsSinceEpoch() / 1000);
2064- g_value_set_boxed(value, dateTime);
2065-
2066- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_BIRTHDAY, value);
2067- g_date_time_unref(dateTime);
2068- }
2069-
2070- /*
2071- * Email addresses
2072- */
2073- PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(details,
2074+ return details;
2075+}
2076+
2077+GHashTable *QIndividual::parsePhotoDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2078+{
2079+ if(cDetails.size() == 0) {
2080+ return details;
2081+ }
2082+
2083+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2084+ QContactAvatar avatar = static_cast<QContactAvatar>(detail);
2085+ if(!avatar.isEmpty()) {
2086+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_FILE_ICON);
2087+ QUrl avatarUri = avatar.imageUrl();
2088+ if(!avatarUri.isEmpty()) {
2089+ QString formattedUri = avatarUri.toString(QUrl::RemoveUserInfo);
2090+ if(!formattedUri.isEmpty()) {
2091+ GFile *avatarFile = g_file_new_for_uri(formattedUri.toUtf8().data());
2092+ GFileIcon *avatarFileIcon = G_FILE_ICON(g_file_icon_new(avatarFile));
2093+ g_value_take_object(value, avatarFileIcon);
2094+
2095+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_AVATAR, value);
2096+ g_clear_object((GObject**) &avatarFile);
2097+ }
2098+ } else {
2099+ g_object_unref(value);
2100+ }
2101+ }
2102+ }
2103+
2104+ return details;
2105+}
2106+
2107+GHashTable *QIndividual::parseBirthdayDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2108+{
2109+ if(cDetails.size() == 0) {
2110+ return details;
2111+ }
2112+
2113+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2114+ QContactBirthday birthday = static_cast<QContactBirthday>(detail);
2115+ if(!birthday.isEmpty()) {
2116+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_DATE_TIME);
2117+ GDateTime *dateTime = g_date_time_new_from_unix_utc(birthday.dateTime().toMSecsSinceEpoch() / 1000);
2118+ g_value_set_boxed(value, dateTime);
2119+
2120+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_BIRTHDAY, value);
2121+ g_date_time_unref(dateTime);
2122+ }
2123+ }
2124+
2125+ return details;
2126+}
2127+
2128+GHashTable *QIndividual::parseEmailDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2129+{
2130+ if(cDetails.size() == 0) {
2131+ return details;
2132+ }
2133+
2134+ GValue *value;
2135+ PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(details, cDetails,
2136 FOLKS_PERSONA_DETAIL_EMAIL_ADDRESSES, value, QContactEmailAddress,
2137 FOLKS_TYPE_EMAIL_FIELD_DETAILS, emailAddress);
2138-
2139- /*
2140- * Favorite
2141- */
2142- QContactFavorite favorite = contact.detail<QContactFavorite>();
2143- if(!favorite.isEmpty()) {
2144- value = QIndividualUtils::gValueSliceNew(G_TYPE_BOOLEAN);
2145- g_value_set_boolean(value, favorite.isFavorite());
2146-
2147- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_IS_FAVOURITE, value);
2148- }
2149-
2150- /*
2151- * Gender
2152- */
2153- QContactGender gender = contact.detail<QContactGender>();
2154- if(!gender.isEmpty()) {
2155- value = QIndividualUtils::gValueSliceNew(FOLKS_TYPE_GENDER);
2156- FolksGender genderEnum = FOLKS_GENDER_UNSPECIFIED;
2157- if(gender.gender() == QContactGender::GenderMale) {
2158- genderEnum = FOLKS_GENDER_MALE;
2159- } else if(gender.gender() == QContactGender::GenderFemale) {
2160- genderEnum = FOLKS_GENDER_FEMALE;
2161- }
2162- g_value_set_enum(value, genderEnum);
2163-
2164- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_GENDER, value);
2165- }
2166-
2167- /*
2168- * Names
2169- */
2170- QContactName name = contact.detail<QContactName>();
2171- if(!name.isEmpty()) {
2172- value = QIndividualUtils::gValueSliceNew(FOLKS_TYPE_STRUCTURED_NAME);
2173- FolksStructuredName *sn = folks_structured_name_new(name.lastName().toUtf8().data(),
2174- name.firstName().toUtf8().data(),
2175- name.middleName().toUtf8().data(),
2176- name.prefix().toUtf8().data(),
2177- name.suffix().toUtf8().data());
2178- g_value_take_object(value, sn);
2179- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_STRUCTURED_NAME, value);
2180- }
2181-
2182- QContactDisplayLabel displayLabel = contact.detail<QContactDisplayLabel>();
2183- if(!displayLabel.label().isEmpty()) {
2184- value = QIndividualUtils::gValueSliceNew(G_TYPE_STRING);
2185- g_value_set_string(value, displayLabel.label().toUtf8().data());
2186- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_FULL_NAME, value);
2187-
2188- // FIXME: check if those values should all be set to the same thing
2189- value = QIndividualUtils::gValueSliceNew(G_TYPE_STRING);
2190- g_value_set_string(value, displayLabel.label().toUtf8().data());
2191- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_ALIAS, value);
2192- }
2193-
2194- /*
2195- * Notes
2196- */
2197- PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(details,
2198+ return details;
2199+}
2200+
2201+GHashTable *QIndividual::parseFavoriteDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2202+{
2203+ if(cDetails.size() == 0) {
2204+ return details;
2205+ }
2206+
2207+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2208+ QContactFavorite favorite = static_cast<QContactFavorite>(detail);
2209+ if(!favorite.isEmpty()) {
2210+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_BOOLEAN);
2211+ g_value_set_boolean(value, favorite.isFavorite());
2212+
2213+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_IS_FAVOURITE, value);
2214+ }
2215+ }
2216+
2217+ return details;
2218+}
2219+
2220+GHashTable *QIndividual::parseGenderDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2221+{
2222+ if(cDetails.size() == 0) {
2223+ return details;
2224+ }
2225+
2226+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2227+ QContactGender gender = static_cast<QContactDetail>(detail);
2228+ if(!gender.isEmpty()) {
2229+ GValue *value = QIndividualUtils::gValueSliceNew(FOLKS_TYPE_GENDER);
2230+ FolksGender genderEnum = FOLKS_GENDER_UNSPECIFIED;
2231+ if(gender.gender() == QContactGender::GenderMale) {
2232+ genderEnum = FOLKS_GENDER_MALE;
2233+ } else if(gender.gender() == QContactGender::GenderFemale) {
2234+ genderEnum = FOLKS_GENDER_FEMALE;
2235+ }
2236+ g_value_set_enum(value, genderEnum);
2237+
2238+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_GENDER, value);
2239+ }
2240+ }
2241+
2242+ return details;
2243+}
2244+
2245+GHashTable *QIndividual::parseNameDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2246+{
2247+ if(cDetails.size() == 0) {
2248+ return details;
2249+ }
2250+
2251+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2252+ QContactName name = static_cast<QContactName>(detail);
2253+ if(!name.isEmpty()) {
2254+ GValue *value = QIndividualUtils::gValueSliceNew(FOLKS_TYPE_STRUCTURED_NAME);
2255+ FolksStructuredName *sn = folks_structured_name_new(name.lastName().toUtf8().data(),
2256+ name.firstName().toUtf8().data(),
2257+ name.middleName().toUtf8().data(),
2258+ name.prefix().toUtf8().data(),
2259+ name.suffix().toUtf8().data());
2260+ g_value_take_object(value, sn);
2261+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_STRUCTURED_NAME, value);
2262+ }
2263+ }
2264+
2265+ return details;
2266+}
2267+
2268+GHashTable *QIndividual::parseFullNameDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2269+{
2270+ if(cDetails.size() == 0) {
2271+ return details;
2272+ }
2273+
2274+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2275+ QContactDisplayLabel displayLabel = static_cast<QContactDisplayLabel>(detail);
2276+ if(!displayLabel.label().isEmpty()) {
2277+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_STRING);
2278+ g_value_set_string(value, displayLabel.label().toUtf8().data());
2279+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_FULL_NAME, value);
2280+
2281+ // FIXME: check if those values should all be set to the same thing
2282+ value = QIndividualUtils::gValueSliceNew(G_TYPE_STRING);
2283+ g_value_set_string(value, displayLabel.label().toUtf8().data());
2284+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_ALIAS, value);
2285+ }
2286+ }
2287+
2288+ return details;
2289+}
2290+
2291+GHashTable *QIndividual::parseNicknameDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2292+{
2293+ if(cDetails.size() == 0) {
2294+ return details;
2295+ }
2296+
2297+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2298+ QContactNickname nickname = static_cast<QContactNickname>(detail);
2299+ if(!nickname.nickname().isEmpty()) {
2300+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_STRING);
2301+ g_value_set_string(value, nickname.nickname().toUtf8().data());
2302+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_NICKNAME, value);
2303+
2304+ // FIXME: check if those values should all be set to the same thing
2305+ value = QIndividualUtils::gValueSliceNew(G_TYPE_STRING);
2306+ g_value_set_string(value, nickname.nickname().toUtf8().data());
2307+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_ALIAS, value);
2308+ }
2309+ }
2310+
2311+ return details;
2312+}
2313+
2314+GHashTable *QIndividual::parseNoteDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2315+{
2316+ if(cDetails.size() == 0) {
2317+ return details;
2318+ }
2319+
2320+ GValue *value;
2321+ PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(details, cDetails,
2322 FOLKS_PERSONA_DETAIL_NOTES, value, QContactNote,
2323 FOLKS_TYPE_NOTE_FIELD_DETAILS, note);
2324
2325-
2326-
2327- /*
2328- * OnlineAccounts
2329- */
2330- QList<QContactOnlineAccount> accounts = contact.details<QContactOnlineAccount>();
2331- if(!accounts.isEmpty()) {
2332- QMultiMap<QString, QString> providerUidMap;
2333-
2334- Q_FOREACH(const QContactOnlineAccount &account, accounts) {
2335- if (!account.isEmpty()) {
2336- providerUidMap.insert(onlineAccountProtocolFromEnum(account.protocol()), account.accountUri());
2337- }
2338- }
2339-
2340- if(!providerUidMap.isEmpty()) {
2341- //TODO: add account type and subtype
2342- value = QIndividualUtils::asvSetStrNew(providerUidMap);
2343- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_IM_ADDRESSES, value);
2344- }
2345- }
2346-
2347- /*
2348- * Organization
2349- */
2350- QList<QContactOrganization> orgs = contact.details<QContactOrganization>();
2351- if(orgs.size() > 0) {
2352- value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT);
2353- Q_FOREACH(const QContactOrganization& org, orgs) {
2354- if(!org.isEmpty()) {
2355- FolksRole *role = folks_role_new(org.title().toUtf8().data(),
2356- org.name().toUtf8().data(),
2357- NULL);
2358- folks_role_set_role(role, org.role().toUtf8().data());
2359-
2360- GeeCollection *collection = (GeeCollection*) g_value_get_object(value);
2361- if(collection == NULL) {
2362- collection = GEE_COLLECTION(SET_AFD_NEW());
2363- g_value_take_object(value, collection);
2364- }
2365- FolksRoleFieldDetails *rfd = folks_role_field_details_new(role, NULL);
2366- parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(rfd), org);
2367- gee_collection_add(collection, rfd);
2368-
2369- g_object_unref(rfd);
2370- g_object_unref(role);
2371- }
2372- }
2373- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_ROLES, value);
2374- }
2375-
2376- /*
2377- * Phone Numbers
2378- */
2379- QList<QContactPhoneNumber> phones = contact.details<QContactPhoneNumber>();
2380- if (phones.size() > 0) {
2381- value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT);
2382- Q_FOREACH(const QContactPhoneNumber &phone, phones) {
2383- if(!phone.isEmpty()) {
2384- QIndividualUtils::gValueGeeSetAddStringFieldDetails(value,
2385- FOLKS_TYPE_PHONE_FIELD_DETAILS,
2386- phone.number().toUtf8().data(),
2387- phone);
2388- }
2389- }
2390- QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_PHONE_NUMBERS, value);
2391- }
2392-
2393- /*
2394- * URLs
2395- */
2396- PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(details,
2397+ return details;
2398+}
2399+
2400+GHashTable *QIndividual::parseImDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2401+{
2402+ if(cDetails.size() == 0) {
2403+ return details;
2404+ }
2405+
2406+ QMultiMap<QString, QString> providerUidMap;
2407+ Q_FOREACH(const QContactDetail &detail, cDetails) {
2408+ QContactOnlineAccount account = static_cast<QContactOnlineAccount>(detail);
2409+ if (!account.isEmpty()) {
2410+ providerUidMap.insert(onlineAccountProtocolFromEnum(account.protocol()), account.accountUri());
2411+ }
2412+ }
2413+
2414+ if(!providerUidMap.isEmpty()) {
2415+ //TODO: add account type and subtype
2416+ GValue *value = QIndividualUtils::asvSetStrNew(providerUidMap);
2417+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_IM_ADDRESSES, value);
2418+ }
2419+
2420+ return details;
2421+}
2422+
2423+GHashTable *QIndividual::parseOrganizationDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2424+{
2425+ if(cDetails.size() == 0) {
2426+ return details;
2427+ }
2428+
2429+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT);
2430+ Q_FOREACH(const QContactDetail& detail, cDetails) {
2431+ QContactOrganization org = static_cast<QContactOrganization>(detail);
2432+ if(!org.isEmpty()) {
2433+ FolksRole *role = folks_role_new(org.title().toUtf8().data(),
2434+ org.name().toUtf8().data(),
2435+ NULL);
2436+ folks_role_set_role(role, org.role().toUtf8().data());
2437+
2438+ GeeCollection *collection = (GeeCollection*) g_value_get_object(value);
2439+ if(collection == NULL) {
2440+ collection = GEE_COLLECTION(SET_AFD_NEW());
2441+ g_value_take_object(value, collection);
2442+ }
2443+ FolksRoleFieldDetails *rfd = folks_role_field_details_new(role, NULL);
2444+ parseContext(FOLKS_ABSTRACT_FIELD_DETAILS(rfd), org);
2445+ gee_collection_add(collection, rfd);
2446+
2447+ g_object_unref(rfd);
2448+ g_object_unref(role);
2449+ }
2450+ }
2451+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_ROLES, value);
2452+
2453+ return details;
2454+}
2455+
2456+GHashTable *QIndividual::parsePhoneNumbersDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2457+{
2458+ if(cDetails.size() == 0) {
2459+ return details;
2460+ }
2461+
2462+ GValue *value = QIndividualUtils::gValueSliceNew(G_TYPE_OBJECT);
2463+ Q_FOREACH(const QContactDetail &detail, cDetails) {
2464+ QContactPhoneNumber phone = static_cast<QContactPhoneNumber>(detail);
2465+ if(!phone.isEmpty()) {
2466+ QIndividualUtils::gValueGeeSetAddStringFieldDetails(value,
2467+ FOLKS_TYPE_PHONE_FIELD_DETAILS,
2468+ phone.number().toUtf8().data(),
2469+ phone);
2470+ }
2471+ }
2472+ QIndividualUtils::personaDetailsInsert(details, FOLKS_PERSONA_DETAIL_PHONE_NUMBERS, value);
2473+
2474+ return details;
2475+}
2476+
2477+GHashTable *QIndividual::parseUrlDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails)
2478+{
2479+ if(cDetails.size() == 0) {
2480+ return details;
2481+ }
2482+
2483+ GValue *value;
2484+ PERSONA_DETAILS_INSERT_STRING_FIELD_DETAILS(details, cDetails,
2485 FOLKS_PERSONA_DETAIL_URLS, value, QContactUrl,
2486 FOLKS_TYPE_URL_FIELD_DETAILS, url);
2487+
2488+ return details;
2489+}
2490+
2491+
2492+GHashTable *QIndividual::parseDetails(const QtContacts::QContact &contact)
2493+{
2494+ GHashTable *details = g_hash_table_new_full(g_str_hash,
2495+ g_str_equal,
2496+ NULL,
2497+ (GDestroyNotify) QIndividualUtils::gValueSliceFree);
2498+
2499+ parseAddressDetails(details, contact.details(QContactAddress::Type));
2500+ parsePhotoDetails(details, contact.details(QContactAvatar::Type));
2501+ parseBirthdayDetails(details, contact.details(QContactBirthday::Type));
2502+ parseEmailDetails(details, contact.details(QContactEmailAddress::Type));
2503+ parseFavoriteDetails(details, contact.details(QContactFavorite::Type));
2504+ parseGenderDetails(details, contact.details(QContactGender::Type));
2505+ parseNameDetails(details, contact.details(QContactName::Type));
2506+ parseFullNameDetails(details, contact.details(QContactDisplayLabel::Type));
2507+ parseNicknameDetails(details, contact.details(QContactNickname::Type));
2508+ parseNoteDetails(details, contact.details(QContactNote::Type));
2509+ parseImDetails(details, contact.details(QContactOnlineAccount::Type));
2510+ parseOrganizationDetails(details, contact.details(QContactOrganization::Type));
2511+ parsePhoneNumbersDetails(details, contact.details(QContactPhoneNumber::Type));
2512+ parseUrlDetails(details, contact.details(QContactUrl::Type));
2513+
2514 return details;
2515 }
2516
2517@@ -1761,29 +2236,39 @@
2518 {
2519 }
2520
2521-FolksPersona* QIndividual::primaryPersona() const
2522+FolksPersona* QIndividual::primaryPersona()
2523 {
2524- if(m_individual == 0) {
2525- return 0;
2526+ Q_ASSERT(m_individual);
2527+
2528+ if (m_primaryPersona) {
2529+ return m_primaryPersona;
2530 }
2531
2532- FolksPersona *retval = NULL;
2533 GeeSet *personas = folks_individual_get_personas(m_individual);
2534 GeeIterator *iter = gee_iterable_iterator(GEE_ITERABLE(personas));
2535+ FolksPersonaStore *primaryStore = folks_individual_aggregator_get_primary_store(m_aggregator);
2536
2537- while(retval == NULL && gee_iterator_next(iter)) {
2538+ while(m_primaryPersona == NULL && gee_iterator_next(iter)) {
2539 FolksPersona *persona = FOLKS_PERSONA(gee_iterator_get(iter));
2540- FolksPersonaStore *primaryStore = folks_individual_aggregator_get_primary_store(m_aggregator);
2541 if(folks_persona_get_store(persona) == primaryStore) {
2542- retval = persona;
2543- g_object_ref(retval);
2544+ m_primaryPersona = persona;
2545+ g_object_ref (persona);
2546 }
2547-
2548 g_object_unref(persona);
2549 }
2550 g_object_unref (iter);
2551
2552- return retval;
2553+ return m_primaryPersona;
2554+}
2555+
2556+QtContacts::QContactDetail QIndividual::detailFromUri(QtContacts::QContactDetail::DetailType type, const QString &uri) const
2557+{
2558+ Q_FOREACH(QContactDetail detail, m_contact.details(type)) {
2559+ if (detail.detailUri() == uri) {
2560+ return detail;
2561+ }
2562+ }
2563+ return m_contact.detail(type);
2564 }
2565
2566 } //namespace
2567
2568=== modified file 'src/qindividual.h'
2569--- src/qindividual.h 2013-06-11 13:00:01 +0000
2570+++ src/qindividual.h 2013-06-20 20:58:26 +0000
2571@@ -31,7 +31,7 @@
2572
2573 namespace galera
2574 {
2575-typedef void (*UpdateDoneCB)(const QString&, void*);
2576+typedef GHashTable* (ParseDetailsFunc)(GHashTable*, const QList<QtContacts::QContactDetail> &);
2577
2578 typedef QList<QtVersit::QVersitProperty> PropertyList;
2579 class QIndividual
2580@@ -59,40 +59,47 @@
2581
2582 QtContacts::QContact &contact();
2583 QtContacts::QContact copy(Fields fields = QIndividual::All);
2584- bool update(const QString &vcard, UpdateDoneCB cb, void* data);
2585- bool update(const QtContacts::QContact &contact, UpdateDoneCB cb, void* data);
2586+ bool update(const QString &vcard, QObject *object, const QString &slot);
2587+ bool update(const QtContacts::QContact &contact, QObject *object, const QString &slot);
2588 FolksIndividual *individual() const;
2589+ void setIndividual(FolksIndividual *individual);
2590
2591 static GHashTable *parseDetails(const QtContacts::QContact &contact);
2592-
2593 private:
2594 FolksIndividual *m_individual;
2595+ FolksPersona *m_primaryPersona;
2596 FolksIndividualAggregator *m_aggregator;
2597 QtContacts::QContact m_contact;
2598 QMap<QString, QPair<QtContacts::QContactDetail, FolksAbstractFieldDetails*> > m_fieldsMap;
2599- unsigned int m_fieldMapNextKey;
2600+
2601
2602 bool fieldsContains(Fields fields, Field value) const;
2603 QList<QtVersit::QVersitProperty> parseFieldList(const QString &fieldName, GeeSet *values) const;
2604 QMultiHash<QString, QString> parseDetails(FolksAbstractFieldDetails *details) const;
2605 void updateContact();
2606- FolksPersona *primaryPersona() const;
2607+
2608+ FolksPersona *primaryPersona();
2609+ QtContacts::QContactDetail detailFromUri(QtContacts::QContactDetail::DetailType type, const QString &uri) const;
2610
2611 // QContact
2612+ QList<QtContacts::QContactDetail> getDetails() const;
2613+ void appendDetailsForPersona(QList<QtContacts::QContactDetail> *list, QtContacts::QContactDetail detail, const QString &personaIndex, bool readOnly) const;
2614+ void appendDetailsForPersona(QList<QtContacts::QContactDetail> *list, QList<QtContacts::QContactDetail> details, const QString &personaIndex, bool readOnly) const;
2615+
2616 QtContacts::QContactDetail getUid() const;
2617 QList<QtContacts::QContactDetail> getClientPidMap() const;
2618- QtContacts::QContactDetail getName() const;
2619- QtContacts::QContactDetail getFullName() const;
2620- QtContacts::QContactDetail getNickname() const;
2621- QtContacts::QContactDetail getBirthday() const;
2622- QtContacts::QContactDetail getPhoto() const;
2623- QList<QtContacts::QContactDetail> getRoles() const;
2624- QList<QtContacts::QContactDetail> getEmails() const;
2625- QList<QtContacts::QContactDetail> getPhones() const;
2626- QList<QtContacts::QContactDetail> getAddresses() const;
2627- QList<QtContacts::QContactDetail> getIms() const;
2628- QtContacts::QContactDetail getTimeZone() const;
2629- QList<QtContacts::QContactDetail> getUrls() const;
2630+ QtContacts::QContactDetail getPersonaName(FolksPersona *persona) const;
2631+ QtContacts::QContactDetail getPersonaFullName(FolksPersona *persona) const;
2632+ QtContacts::QContactDetail getPersonaNickName(FolksPersona *persona) const;
2633+ QtContacts::QContactDetail getPersonaBirthday(FolksPersona *persona) const;
2634+ QtContacts::QContactDetail getPersonaPhoto(FolksPersona *persona) const;
2635+ //TODO: organization
2636+ QList<QtContacts::QContactDetail> getPersonaRoles(FolksPersona *persona) const;
2637+ QList<QtContacts::QContactDetail> getPersonaEmails(FolksPersona *persona) const;
2638+ QList<QtContacts::QContactDetail> getPersonaPhones(FolksPersona *persona) const;
2639+ QList<QtContacts::QContactDetail> getPersonaAddresses(FolksPersona *persona) const;
2640+ QList<QtContacts::QContactDetail> getPersonaIms(FolksPersona *persona) const;
2641+ QList<QtContacts::QContactDetail> getPersonaUrls(FolksPersona *persona) const;
2642
2643
2644 // update
2645@@ -102,15 +109,38 @@
2646 void updateBirthday(const QtContacts::QContactDetail &detail, void* data);
2647 void updatePhoto(const QtContacts::QContactDetail &detail, void* data);
2648 void updateTimezone(const QtContacts::QContactDetail &detail, void* data);
2649- void updateRoles(QList<QtContacts::QContactDetail> details, void* data);
2650- void updatePhones(QList<QtContacts::QContactDetail> details, void* data);
2651- void updateEmails(QList<QtContacts::QContactDetail> details, void* data);
2652- void updateIms(QList<QtContacts::QContactDetail> details, void* data);
2653- void updateUrls(QList<QtContacts::QContactDetail> details, void* data);
2654- void updateNotes(QList<QtContacts::QContactDetail> details, void* data);
2655- void updateAddresses(QList<QtContacts::QContactDetail> details, void* data);
2656+ void updateRole(QtContacts::QContactDetail detail, void* data);
2657+ void updatePhone(QtContacts::QContactDetail detail, void* data);
2658+ void updateEmail(QtContacts::QContactDetail detail, void* data);
2659+ void updateIm(QtContacts::QContactDetail detail, void* data);
2660+ void updateUrl(QtContacts::QContactDetail details, void* data);
2661+ void updateNote(QtContacts::QContactDetail detail, void* data);
2662+ void updateAddress(QtContacts::QContactDetail detail, void* data);
2663+ void createPersonaForDetail(QList<QtContacts::QContactDetail> detail, ParseDetailsFunc parseFunc, void *data) const;
2664+
2665+ static void createPersonaDone(GObject *detail, GAsyncResult *result, gpointer userdata);
2666 static void updateDetailsDone(GObject *detail, GAsyncResult *result, gpointer userdata);
2667- static bool detailListIsEqual(QList<QtContacts::QContactDetail> original, QList<QtContacts::QContactDetail> details);
2668+ static void updateDetailsSendReply(gpointer userdata, GError *error);
2669+ static void updateDetailsSendReply(gpointer userdata, const QString &errorMessage);
2670+ static QString callDetailChangeFinish(QtContacts::QContactDetail::DetailType type, FolksPersona *persona, GAsyncResult *result);
2671+ //static bool detailListIsEqual(QList<QtContacts::QContactDetail> original, QList<QtContacts::QContactDetail> details);
2672+
2673+ // translate details
2674+ static GHashTable *parseAddressDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2675+ static GHashTable *parsePhotoDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2676+ static GHashTable *parsePhoneNumbersDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2677+ static GHashTable *parseOrganizationDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2678+ static GHashTable *parseImDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2679+ static GHashTable *parseNoteDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2680+ static GHashTable *parseFullNameDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2681+ static GHashTable *parseNicknameDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2682+ static GHashTable *parseNameDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2683+ static GHashTable *parseGenderDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2684+ static GHashTable *parseFavoriteDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2685+ static GHashTable *parseEmailDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2686+ static GHashTable *parseBirthdayDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2687+ static GHashTable *parseUrlDetails(GHashTable *details, const QList<QtContacts::QContactDetail> &cDetails);
2688+
2689
2690 // parse context and parameters
2691 static void parseParameters(QtContacts::QContactDetail &detail, FolksAbstractFieldDetails *fd);
2692
2693=== modified file 'src/view-adaptor.h'
2694--- src/view-adaptor.h 2013-06-13 14:00:42 +0000
2695+++ src/view-adaptor.h 2013-06-20 20:58:26 +0000
2696@@ -45,7 +45,7 @@
2697 " <arg direction=\"out\" type=\"i\" name=\"pos\"/>\n"
2698 " <arg direction=\"out\" type=\"i\" name=\"lenght\"/>\n"
2699 " </signal>\n"
2700-" <signal name=\"contactsCreated\">\n"
2701+" <signal name=\"contactsAdded\">\n"
2702 " <arg direction=\"out\" type=\"i\" name=\"pos\"/>\n"
2703 " <arg direction=\"out\" type=\"i\" name=\"lenght\"/>\n"
2704 " </signal>\n"
2705@@ -81,7 +81,7 @@
2706 void close();
2707
2708 Q_SIGNALS:
2709- void contactsCreated(int pos, int lenght);
2710+ void contactsAdded(int pos, int lenght);
2711 void contactsRemoved(int pos, int lenght);
2712 void contactsUpdated(int pos, int lenght);
2713
2714
2715=== modified file 'src/view.cpp'
2716--- src/view.cpp 2013-06-13 14:35:08 +0000
2717+++ src/view.cpp 2013-06-20 20:58:26 +0000
2718@@ -166,6 +166,11 @@
2719 }
2720
2721 QStringList ret = VCardParser::contactToVcard(contacts);
2722+ qDebug() << "fetch" << ret;
2723+ QList<QContact> cs = VCardParser::vcardToContact(ret);
2724+ QStringList ret2 = VCardParser::contactToVcard(cs);
2725+ qDebug() << "fetch2" << ret2;
2726+
2727 QDBusMessage reply = message.createReply(ret);
2728 QDBusConnection::sessionBus().send(reply);
2729 return ret;

Subscribers

People subscribed via source and target branches