Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Meego:Tablet
buteo-sync-plugin-google
buteo-sync-plugins-0.5.6.57-update-specific-det...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File buteo-sync-plugins-0.5.6.57-update-specific-details.patch of Package buteo-sync-plugin-google
From a19fcad777ccdc6f33e1c020e3c96b47c9d2dbc0 Mon Sep 17 00:00:00 2001 From: Zhu, Yongsheng <yongsheng.zhu@intel.com> Date: Tue, 30 Nov 2010 03:38:13 -0500 Subject: [PATCH] Google contact: only update fields Google supports We only update those fields Google supports. Otherwise, just keep them unchanged to avoid data loss. The temporary solution is to use 'partial save' of qtcontacts. We never update fields Google never touches when doing sync with it. Copy code from http://qt.gitorious.org/qt-mobility/contacts/ blobs/master/src/contacts/qcontactmanagerengine.cpp under LGPLv2.1. --- storageplugins/hcontacts/ContactsBackend.cpp | 185 +++++++++++++++++++++++++- storageplugins/hcontacts/ContactsBackend.h | 4 + 2 files changed, 187 insertions(+), 2 deletions(-) diff --git a/storageplugins/hcontacts/ContactsBackend.cpp b/storageplugins/hcontacts/ContactsBackend.cpp index 8916eaf..5c43fc0 100644 --- a/storageplugins/hcontacts/ContactsBackend.cpp +++ b/storageplugins/hcontacts/ContactsBackend.cpp @@ -30,6 +30,18 @@ #include <QContactLocalIdFilter> #include <QContactSyncTarget> #include <QContactDetailFilter> +#include <QContactAddress> +#include <QContactBirthday> +#include <QContactEmailAddress> +#include <QContactDisplayLabel> +#include <QContactName> +#include <QContactNote> +#include <QContactOrganization> +#include <QContactPhoneNumber> +#include <QContactThumbnail> +#include <QContactUrl> +#include <QContactGender> +#include <QContactOnlineAccount> #include <QBuffer> #include <QSet> @@ -167,7 +179,7 @@ bool ContactsBackend::addContacts( const QStringList& aContactDataList, i->saveDetail(&syncTarget); } - bool retVal = iMgr->saveContacts(&contactList, &errorMap); + bool retVal = saveContacts(&contactList, &errorMap); if (!retVal) { @@ -265,7 +277,7 @@ QMap<int,ContactsStatus> ContactsBackend::modifyContacts( LOG_DEBUG("Replacing item's ID " << qContactList.at(i).localId()); } - if(iMgr->saveContacts(&qContactList , &errors)) { + if(saveContacts(&qContactList , &errors)) { LOG_DEBUG("Batch Modification of Contacts Succeeded"); } else { @@ -664,3 +676,172 @@ QContactFilter ContactsBackend::getSyncTargetFilter() const { // return the union return detailFilterButeoSyncTarget | detailFilterDefaultSyncTarget; } + +bool ContactsBackend::saveContacts( QList<QContact> *contactList, + QMap<int, QContactManager::Error> *errorMap ) +{ + struct DefinitionFieldPair { + QString definitionName; + QString fieldName; + }; + + static DefinitionFieldPair googleFields[] = { + {QContactAddress::DefinitionName, ""}, // ADR + {QContactBirthday::DefinitionName, QContactBirthday::FieldBirthday}, // BDAY + {QContactEmailAddress::DefinitionName, QContactEmailAddress::FieldEmailAddress}, // EMAIL + {QContactDisplayLabel::DefinitionName, ""}, //FN + {QContactName::DefinitionName, ""}, //N + + {QContactNote::DefinitionName, QContactNote::FieldNote}, //NOTE + {QContactTimestamp::DefinitionName, ""}, //REV + {QContactPhoneNumber::DefinitionName, QContactPhoneNumber::FieldNumber}, //TEL + {QContactPhoneNumber::DefinitionName, QContactPhoneNumber::SubTypeAssistant}, //X-ASSISTANT-TEL + {QContactThumbnail::DefinitionName, ""}, //PHOTO + + {QContactUrl::DefinitionName, QContactUrl::FieldUrl}, //URL + {QContactGender::DefinitionName, QContactGender::FieldGender}, //X-GENDER + {QContactOnlineAccount::DefinitionName, QContactOnlineAccount::SubTypeSip}, //X-SIP + + // separator + {"", ""}, + + // below are stored in one detail in contact, different from above ones + {QContactOrganization::DefinitionName, QContactOrganization::FieldName}, //ORG + {QContactOrganization::DefinitionName, QContactOrganization::FieldTitle}, //TITLE + {QContactOrganization::DefinitionName, QContactOrganization::FieldAssistantName} //X-ASSITANT + }; + + // Partial contact save. + // Basically + + // Need to: + // 1) fetch existing contacts + // 2) strip out fields of details in definitionMask for existing contacts + // 3) copy the details from the passed in list for existing contacts + // 4) for any new contacts, copy the masked details to a blank contact + // 5) save the modified ones + // 6) update the id of any new contacts + // 7) transfer any errors from saving to errorMap + + QList<QContactLocalId> existingContactIds; + + // Error conditions: + // 1) bad id passed in (can't fetch) + // 2) bad fetch (can't save partial update) + // 3) bad save error + // all of which needs to be returned in the error map + + QHash<int, int> existingIdMap; // contacts index to existingContacts index + + // Try to figure out which of our arguments are new contacts + QList<QContactLocalId> localIds = iMgr->contactIds(); + for(int i = 0; i < contactList->count(); i++) { + // don't check manager uri here for they can't match + // See if there's a contactId that's not from this manager + const QContact c = contactList->at(i); + if ( c.localId() != 0 && localIds.indexOf(c.localId()) >= 0 ) { + existingIdMap.insert(i, existingContactIds.count()); + existingContactIds.append(c.localId()); + } + } + + // Now fetch the existing contacts + QList<QContact> existingContacts; + getContacts(existingContactIds, existingContacts); + + // Prepare the list to save + QList<QContact> contactsToSave; + QList<int> savedToOriginalMap; // contactsToSave index to contacts index + + for (int i = 0; i < contactList->count(); i++) { + // See if this is an existing contact or a new one + const int fetchedIdx = existingIdMap.value(i, -1); + QContact contactToSave; + const QContact& c = contactList->at(i); + + bool removeField = false; + unsigned int j = 0; + if (fetchedIdx >= 0) { + // Existing contact we should have fetched + contactToSave = existingContacts.at(fetchedIdx); + + // remove existing details with definitions + for ( ; j < sizeof(googleFields) / sizeof(googleFields[0]); j++) { + if ( googleFields[j].definitionName.isEmpty() ) { + removeField = true; + continue; + } + QList<QContactDetail> details = contactToSave.details(googleFields[j].definitionName); + foreach(QContactDetail detail, details) { + if ( removeField ) { + // only remove related fields otherwise other fields might be removed + // for example, 'ROLE', 'ORG', 'TITLE', and 'X-ASSITANT' are stored in + // one detail. If removing the detail, 'ROLE' will be lost. + contactToSave.removeDetail(&detail); + detail.removeValue(googleFields[j].fieldName); + contactToSave.saveDetail(&detail); + } else if ( googleFields[j].fieldName.isEmpty() + || detail.hasValue(googleFields[j].fieldName) ) { + // only remove specific field instead of a total detail. Because many fields + // are merged into one detail + contactToSave.removeDetail(&detail); + } + } + } + } + + // Now copy in the details from the arguments + + // Perhaps this could do this directly rather than through saveDetail + // but that would duplicate the checks for display label etc + //foreach (const QString& name, definitions) { + removeField = false; + for (j = 0; j < sizeof(googleFields) / sizeof(googleFields[0]); j++) { + if ( googleFields[j].definitionName.isEmpty() ) { + removeField = true; + continue; + } + QList<QContactDetail> details = c.details(googleFields[j].definitionName); + foreach(QContactDetail detail, details) { + if ( removeField ) { + QList<QContactDetail> detailsSave = contactToSave.details(googleFields[j].definitionName); + if ( detailsSave.isEmpty() ) { + contactToSave.saveDetail(&detail); + } else { + QContactDetail detailSave = detailsSave.at(0); + detailSave.setValue(googleFields[j].fieldName, detail.value(googleFields[j].fieldName) ); + contactToSave.saveDetail(&detailSave); + } + } else if ( googleFields[j].fieldName.isEmpty() || + detail.hasValue(googleFields[j].fieldName) ) { + contactToSave.saveDetail(&detail); + } + } + } + + savedToOriginalMap.append(i); + contactsToSave.append(contactToSave); + } + + // Now save them + QMap<int, QContactManager::Error> saveErrors; + iMgr->saveContacts(&contactsToSave, &saveErrors); + + // Now update the passed in arguments, where necessary + + // Update IDs of the contacts list + for (int i = 0; i < contactsToSave.count(); i++) { + (*contactList)[savedToOriginalMap[i]].setId(contactsToSave[i].id()); + } + // Populate the errorMap with the errorMap of the attempted save + QMap<int, QContactManager::Error>::iterator it(saveErrors.begin()); + while (it != saveErrors.end()) { + if (it.value() != QContactManager::NoError) { + errorMap->insert(savedToOriginalMap[it.key()], it.value()); + } + it++; + } + + return errorMap->isEmpty(); +} + diff --git a/storageplugins/hcontacts/ContactsBackend.h b/storageplugins/hcontacts/ContactsBackend.h index ce3b34f..a0fb59d 100644 --- a/storageplugins/hcontacts/ContactsBackend.h +++ b/storageplugins/hcontacts/ContactsBackend.h @@ -224,6 +224,10 @@ private: // functions */ QContactFilter getSyncTargetFilter() const; + // temporary solution to save contacts, update specific fields + bool saveContacts( QList<QContact> *contactList, + QMap<int, QContactManager::Error> *errorMap ); + private: // data // if there is more than one Manager we need to have a list of Managers -- 1.7.2.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor