Merge lp:~renatofilho/address-book-service/missing-features into lp:address-book-service

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~renatofilho/address-book-service/missing-features
Merge into: lp:address-book-service
Diff against target: 2761 lines (+1311/-742)
14 files modified
common/sort-clause.cpp (+7/-1)
common/sort-clause.h (+3/-1)
common/vcard-parser.cpp (+29/-8)
common/vcard-parser.h (+2/-0)
src/addressbook-adaptor.cpp (+6/-2)
src/addressbook-adaptor.h (+5/-5)
src/addressbook.cpp (+116/-81)
src/addressbook.h (+13/-4)
src/contacts-map.cpp (+11/-0)
src/contacts-map.h (+1/-0)
src/qindividual.cpp (+1050/-610)
src/qindividual.h (+56/-26)
src/view-adaptor.h (+2/-2)
src/view.cpp (+10/-2)
To merge this branch: bzr merge lp:~renatofilho/address-book-service/missing-features
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Ubuntu Phablet Team Pending
Review via email: mp+170183@code.launchpad.net

This proposal has been superseded by a proposal from 2013-06-20.

Commit message

Implemented AddressBook::availableSources.
Implemented support to change sort clause in the view.
Implemented AddressBook::sortFields.

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

Unmerged revisions

Preview Diff

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

Subscribers

People subscribed via source and target branches