qtmobility/plugins/contacts/qtcontacts-tracker/qcontacttrackerbackend.cpp
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
child 15 1f895d8a5b2b
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qcontacttrackerbackend_p.h"
       
    43 
       
    44 #include <QtTracker/Tracker>
       
    45 #include <QtTracker/ontologies/nco.h>
       
    46 #include <QtTracker/ontologies/nie.h>
       
    47 #include <QtTracker/ontologies/nao.h>
       
    48 #include <QRegExp>
       
    49 #include <QDir>
       
    50 #include <QFile>
       
    51 #include <QSet>
       
    52 #include <QList>
       
    53 
       
    54 #include "qtcontacts.h"
       
    55 
       
    56 #include "trackerchangelistener.h"
       
    57 #include "qtrackercontactsaverequest.h"
       
    58 #include <qtrackerrelationshipfetchrequest.h>
       
    59 #include <qtrackerrelationshipsaverequest.h>
       
    60 #include <qtrackercontactidfetchrequest.h>
       
    61 
       
    62 
       
    63 QContactManagerEngine* ContactTrackerFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
       
    64 {
       
    65     Q_UNUSED(error);
       
    66     QString version = QLatin1String(VERSION_INFO);
       
    67     return new QContactTrackerEngine(managerName(), version.toInt(), parameters);
       
    68 }
       
    69 
       
    70 QString ContactTrackerFactory::managerName() const
       
    71 {
       
    72     return QString("tracker");
       
    73 }
       
    74 Q_EXPORT_PLUGIN2(qtcontacts_tracker, ContactTrackerFactory);
       
    75 
       
    76 QContactTrackerEngine::QContactTrackerEngine(const QString& engineName, int engineVersion, const QMap<QString, QString>& parameters)
       
    77     : d(new QContactTrackerEngineData),
       
    78     contactArchiveFile("removed"),
       
    79     contactArchiveDir(QDir::homePath()+"/.contacts")
       
    80 {
       
    81     Q_UNUSED(parameters);
       
    82     d->m_engineName = engineName;
       
    83     d->m_engineVersion = engineVersion;
       
    84     connectToSignals();
       
    85 }
       
    86 
       
    87 QContactTrackerEngine::QContactTrackerEngine(const QMap<QString, QString>& parameters)
       
    88     : d(new QContactTrackerEngineData),
       
    89     contactArchiveFile("removed"),
       
    90     contactArchiveDir(QDir::homePath()+"/.contacts")
       
    91 {
       
    92     Q_UNUSED(parameters);
       
    93     connectToSignals();
       
    94 }
       
    95 
       
    96 QContactTrackerEngine::QContactTrackerEngine(const QContactTrackerEngine& other)
       
    97     : QContactManagerEngine(), d(other.d)
       
    98 {
       
    99     Q_UNUSED(other);
       
   100     connectToSignals();
       
   101 }
       
   102 
       
   103 void QContactTrackerEngine::connectToSignals()
       
   104 {
       
   105     TrackerChangeListener *listener = new TrackerChangeListener(this, this);
       
   106     connect(listener, SIGNAL(contactsAdded(const QList<QContactLocalId>&)), SIGNAL(contactsAdded(const QList<QContactLocalId>&)));
       
   107     connect(listener, SIGNAL(contactsChanged(const QList<QContactLocalId>&)), SIGNAL(contactsChanged(const QList<QContactLocalId>&)));
       
   108     connect(listener, SIGNAL(contactsRemoved(const QList<QContactLocalId>&)), SIGNAL(contactsRemoved(const QList<QContactLocalId>&)));
       
   109 }
       
   110 
       
   111 QContactTrackerEngine& QContactTrackerEngine::operator=(const QContactTrackerEngine& other)
       
   112 {
       
   113     d = other.d;
       
   114     return *this;
       
   115 }
       
   116 
       
   117 QContactTrackerEngine::~QContactTrackerEngine()
       
   118 {
       
   119 }
       
   120 
       
   121 QContactManagerEngine* QContactTrackerEngine::clone()
       
   122 {
       
   123     // this engine allows sharing - so we increase the reference count.
       
   124     d->m_refCount.ref();
       
   125     return this;
       
   126 }
       
   127 
       
   128 void QContactTrackerEngine::deref()
       
   129 {
       
   130     if (!d->m_refCount.deref())
       
   131         delete this;
       
   132 }
       
   133 
       
   134 QList<QContactLocalId> QContactTrackerEngine::contactIds(const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
       
   135 {
       
   136     return contactIds(QContactFilter(), sortOrders, error);
       
   137 }
       
   138 
       
   139 QList<QContactLocalId> QContactTrackerEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
       
   140 {
       
   141     QContactLocalIdFetchRequest request;
       
   142     request.setFilter(filter);
       
   143     request.setSorting(sortOrders);
       
   144 
       
   145     QContactTrackerEngine engine(*this);
       
   146     engine.startRequest(&request);
       
   147     // 10 seconds should be enough
       
   148     engine.waitForRequestFinished(&request, 10000);
       
   149     if(!request.isFinished()) {
       
   150         *error = QContactManager::UnspecifiedError;
       
   151     }
       
   152     else {
       
   153         // leave the code for now while not all other code is fixed
       
   154         *error = request.error();
       
   155     }
       
   156     return request.ids();
       
   157 }
       
   158 
       
   159 QList<QContact> QContactTrackerEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
       
   160 {
       
   161     // the rest of the code is for internal usage, unit tests etc.
       
   162     QContactFetchRequest request;
       
   163     request.setFetchHint(fetchHint);
       
   164     request.setFilter(filter);
       
   165     request.setSorting(sortOrders);
       
   166 
       
   167     QContactTrackerEngine engine(*this);
       
   168     engine.startRequest(&request);
       
   169     // 10 seconds should be enough
       
   170     engine.waitForRequestFinished(&request, 10000);
       
   171 
       
   172     if( !request.isFinished()) {
       
   173         *error = QContactManager::UnspecifiedError;
       
   174     }
       
   175     else {
       
   176         // leave the code for now while not all other code is fixed
       
   177         *error = request.error();
       
   178     }
       
   179     return request.contacts();
       
   180 }
       
   181 
       
   182 QContact QContactTrackerEngine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
       
   183 {
       
   184     // plan to keep this warning for a while - as message to customers using the API
       
   185     qWarning() << "QContactManager::contact()" << "api is blocking on dbus roundtrip while accessing tracker. Please, consider using asynchronous API QContactFetchRequest and not fetching contacts by id \n"
       
   186             "- reading 100 ids and 100 contact by ids is ~100 times slower then reading 100 contacts at once with QContactFetchRequest.";
       
   187     return contact_impl(contactId, fetchHint, error);
       
   188 }
       
   189 
       
   190 QContactLocalId QContactTrackerEngine::selfContactId(QContactManager::Error* error) const
       
   191 {
       
   192     *error = QContactManager::NoError;
       
   193     return QContactLocalId(0xFFFFFFFF);
       
   194 }
       
   195 
       
   196 // used in tests, removed warning while decided if to provide sync api. Until then customers are advised to use async
       
   197 QContact QContactTrackerEngine::contact_impl(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error ) const
       
   198 {
       
   199     QContactLocalIdFilter idlist;
       
   200     QList<QContactLocalId> ids; ids << contactId;
       
   201     idlist.setIds(ids);
       
   202     QContactFetchRequest request;
       
   203     QStringList definitionNames = fetchHint.detailDefinitionsHint();
       
   204     if (fetchHint.detailDefinitionsHint().isEmpty())
       
   205     {
       
   206         definitionNames << QContactAvatar::DefinitionName
       
   207                 << QContactBirthday::DefinitionName
       
   208                 << QContactAddress::DefinitionName
       
   209                 << QContactEmailAddress::DefinitionName
       
   210                 << QContactDisplayLabel::DefinitionName
       
   211                 << QContactGender::DefinitionName
       
   212                 << QContactAnniversary::DefinitionName
       
   213                 << QContactName::DefinitionName
       
   214                 << QContactOnlineAccount::DefinitionName
       
   215                 << QContactOrganization::DefinitionName
       
   216                 << QContactPhoneNumber::DefinitionName
       
   217                 << QContactOnlineAccount::DefinitionName
       
   218                 << QContactUrl::DefinitionName;
       
   219     }
       
   220 
       
   221     QContactFetchHint modifiedHint;
       
   222     modifiedHint.setDetailDefinitionsHint(definitionNames);
       
   223     request.setFetchHint(modifiedHint);
       
   224     request.setFilter(idlist);
       
   225 
       
   226     QContactTrackerEngine engine(*this);
       
   227     engine.startRequest(&request);
       
   228     // 10 seconds should be enough
       
   229     engine.waitForRequestFinished(&request, 10000);
       
   230 
       
   231     if( !request.isFinished()) {
       
   232         *error = QContactManager::UnspecifiedError;
       
   233         return QContact();
       
   234     }
       
   235     else if(request.contacts().size() == 0)
       
   236     {
       
   237         *error = QContactManager::DoesNotExistError;
       
   238         return QContact();
       
   239     }
       
   240     else {
       
   241         // leave the code for now while not all other code is fixed
       
   242         *error = request.error();
       
   243         return request.contacts()[0];
       
   244     }
       
   245 
       
   246 }
       
   247 
       
   248 bool QContactTrackerEngine::waitForRequestFinished(QContactAbstractRequest* req, int msecs)
       
   249 {
       
   250     Q_ASSERT(req);
       
   251     if(!req->isActive())
       
   252     {
       
   253         return req->isFinished(); // might be already finished
       
   254     }
       
   255     QTime t;
       
   256     t.start();
       
   257     while(t.elapsed() < msecs || msecs == 0) // 0 for infinite
       
   258     {
       
   259         usleep(10000);
       
   260         QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
       
   261         if(req->isFinished())
       
   262             return true;
       
   263     }
       
   264     qDebug() << Q_FUNC_INFO <<"Status Finished" << req->isFinished();
       
   265     return req->isFinished();
       
   266 
       
   267 }
       
   268 
       
   269 bool QContactTrackerEngine::saveContact( QContact* contact, QContactManager::Error* error)
       
   270 {
       
   271     // Signal emitted from TrackerChangeListener
       
   272     QContactSaveRequest request;
       
   273     QList<QContact> contacts(QList<QContact>()<<*contact);
       
   274     request.setContacts(contacts);
       
   275     QContactTrackerEngine engine(*this);
       
   276     engine.startRequest(&request);
       
   277     // 10 seconds should be enough
       
   278     engine.waitForRequestFinished(&request, 10000);
       
   279     *error = request.error();
       
   280     Q_ASSERT(request.contacts().size() == 1);
       
   281     *contact = request.contacts()[0];
       
   282 
       
   283     if( request.isFinished() && *error == QContactManager::NoError)
       
   284         return true;
       
   285     else
       
   286         return false;
       
   287 }
       
   288 
       
   289 bool QContactTrackerEngine::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
       
   290 {
       
   291     *error = QContactManager::NoError;
       
   292 
       
   293     // TODO: Do with LiveNodes when they support strict querying.
       
   294     RDFVariable RDFContact = RDFVariable::fromType<nco::PersonContact>();
       
   295     RDFContact.property<nco::contactUID>() = LiteralValue(QString::number(contactId));
       
   296     RDFSelect query;
       
   297 
       
   298     query.addColumn("contact_uri", RDFContact);
       
   299     LiveNodes ncoContacts = ::tracker()->modelQuery(query);
       
   300     if(ncoContacts->rowCount() == 0) {
       
   301         *error = QContactManager::DoesNotExistError;
       
   302         return false;
       
   303     }
       
   304 
       
   305 
       
   306     Live< nco::PersonContact> ncoContact = ncoContacts->liveNode(0);
       
   307     LiveNodes contactMediums = ncoContact->getHasContactMediums();
       
   308     foreach(Live<nco::ContactMedium> media, contactMediums) {
       
   309         media->remove();
       
   310     }
       
   311     ncoContact->remove();
       
   312 
       
   313     //Temporary workaround to get removed- signal
       
   314     QList<QContactLocalId> removed;
       
   315     removed << contactId;
       
   316     emit contactsRemoved(removed);
       
   317 
       
   318     return true;
       
   319 }
       
   320 
       
   321 bool QContactTrackerEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
   322 {
       
   323     // @todo: Handle errors per saved contact.
       
   324     Q_UNUSED(errorMap)
       
   325 
       
   326     *error = QContactManager::NoError;
       
   327 
       
   328     if(contacts == 0) {
       
   329         *error = QContactManager::BadArgumentError;
       
   330         return false;
       
   331     }
       
   332 
       
   333     // Signal emitted from TrackerChangeListener
       
   334     QContactSaveRequest request;
       
   335     QList<QContact> contactList;
       
   336     for (int i = 0; i < contacts->size(); ++i) {
       
   337         contactList.append(contacts->at(i));
       
   338     }
       
   339     request.setContacts(contactList);
       
   340     QContactTrackerEngine engine(*this);
       
   341     engine.startRequest(&request);
       
   342     /// @todo what should be the delay
       
   343     engine.waitForRequestFinished(&request, 1000*contacts->size());
       
   344     /// @todo what should we do in case request.isFinished() == false
       
   345     if (request.isFinished() == false) {
       
   346         qWarning() << "QContactTrackerEngine::saveContacts:" << "request not finished";
       
   347     }
       
   348     *error = request.error();
       
   349     for (int i = 0; i < contacts->size(); ++i) {
       
   350         (*contacts)[i] = request.contacts().at(i);
       
   351     }
       
   352 
       
   353     // Returns false if we have any errors - true if everything went ok.
       
   354     return (request.errorMap().isEmpty() && *error == QContactManager::NoError);
       
   355 }
       
   356 
       
   357 bool QContactTrackerEngine::removeContacts(const QList<QContactLocalId>& contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
   358 {
       
   359     // Cannot report errors - giving up.
       
   360     if(!errorMap) {
       
   361         *error = QContactManager::BadArgumentError;
       
   362         return false;
       
   363     }
       
   364 
       
   365     // let's clear the error hash so there is nothing old haunting us.
       
   366     errorMap->clear();
       
   367 
       
   368     for (int i = 0; i < contactIds.count(); i++) {
       
   369         QContactManager::Error lastError;
       
   370         removeContact(contactIds.at(i), &lastError);
       
   371         if (lastError != QContactManager::NoError) {
       
   372             errorMap->insert(i, lastError);
       
   373         }
       
   374     }
       
   375 
       
   376     // Returns true if no errors were encountered - false if there was errors.
       
   377     // emit signals removed as they are fired from QContactManager
       
   378     return (errorMap->isEmpty());
       
   379 }
       
   380 
       
   381 QMap<QString, QContactDetailDefinition> QContactTrackerEngine::detailDefinitions(const QString& contactType,
       
   382                                                                                  QContactManager::Error* error) const
       
   383 {
       
   384     if (contactType != QContactType::TypeContact) {
       
   385         *error = QContactManager::InvalidContactTypeError;
       
   386         return QMap<QString, QContactDetailDefinition>();
       
   387     }
       
   388 
       
   389     // lazy initialisation of schema definitions.
       
   390     if (d->m_definitions.isEmpty()) {
       
   391         // none in the list?  get the schema definitions, and modify them to match our capabilities.
       
   392         d->m_definitions = QContactManagerEngine::schemaDefinitions().value(QContactType::TypeContact);
       
   393 
       
   394         // modification: name is unique
       
   395         QContactDetailDefinition nameDef = d->m_definitions.value(QContactName::DefinitionName);
       
   396         nameDef.setUnique(true);
       
   397         d->m_definitions.insert(QContactName::DefinitionName, nameDef);
       
   398 
       
   399         // modification: avatar is unique.
       
   400         QContactDetailDefinition avatarDef = d->m_definitions.value(QContactAvatar::DefinitionName);
       
   401         avatarDef.setUnique(true);
       
   402         d->m_definitions.insert(QContactAvatar::DefinitionName, avatarDef);
       
   403 
       
   404         // modification: url is unique.
       
   405         {
       
   406             const QContactDetailDefinition urlDef = d->m_definitions.value(
       
   407                     QContactUrl::DefinitionName);
       
   408             QContactDetailDefinition newUrlDef;
       
   409 
       
   410             QMap<QString, QContactDetailFieldDefinition> urlFieldNames = urlDef.fields();
       
   411             QMap<QString, QContactDetailFieldDefinition> &fields(urlFieldNames);
       
   412             QContactDetailFieldDefinition f;
       
   413 
       
   414             f.setDataType(QVariant::String);
       
   415             QVariantList subTypes;
       
   416             // removing social networking url
       
   417             subTypes << QString(QLatin1String(QContactUrl::SubTypeFavourite));
       
   418             subTypes << QString(QLatin1String(QContactUrl::SubTypeHomePage));
       
   419             f.setAllowableValues(subTypes);
       
   420             fields.insert(QContactUrl::FieldSubType, f);
       
   421             newUrlDef.setFields(fields);
       
   422             newUrlDef.setUnique(true);
       
   423             newUrlDef.setName(QContactUrl::DefinitionName);
       
   424             d->m_definitions.insert(QContactUrl::DefinitionName, newUrlDef);
       
   425         }
       
   426 
       
   427         // QContactOnlineAccount custom fields
       
   428         {
       
   429             const QContactDetailDefinition accDef = d->m_definitions.value(QContactOnlineAccount::DefinitionName);
       
   430             QContactDetailDefinition newAccountDefinition;
       
   431 
       
   432             QMap<QString, QContactDetailFieldDefinition> accountFieldName = accDef.fields();
       
   433             QMap<QString, QContactDetailFieldDefinition> &fields(accountFieldName);
       
   434             QContactDetailFieldDefinition f;
       
   435 
       
   436             f.setDataType(QVariant::String);
       
   437             fields.insert("Account", f);
       
   438             fields.insert("AccountPath", f);
       
   439             newAccountDefinition.setFields(fields);
       
   440             newAccountDefinition.setName(QContactOnlineAccount::DefinitionName);
       
   441             d->m_definitions.insert(QContactOnlineAccount::DefinitionName, newAccountDefinition);
       
   442         }
       
   443     }
       
   444 
       
   445     *error = QContactManager::NoError;
       
   446     return d->m_definitions;
       
   447 }
       
   448 
       
   449 /*!
       
   450  * \reimp
       
   451  */
       
   452 bool QContactTrackerEngine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const
       
   453 {
       
   454     if (!supportedContactTypes().contains(contactType)) {
       
   455         return false;
       
   456     }
       
   457 
       
   458     switch (feature) {
       
   459         case QContactManager::Groups:
       
   460         case QContactManager::ActionPreferences:
       
   461         case QContactManager::Relationships:
       
   462         case QContactManager::SelfContact:
       
   463             return true;
       
   464         case QContactManager::ArbitraryRelationshipTypes:
       
   465             return true;
       
   466         case QContactManager::MutableDefinitions:
       
   467             return true;
       
   468         case QContactManager::ChangeLogs:
       
   469             return true;
       
   470         default:
       
   471             return false;
       
   472     }
       
   473 }
       
   474 
       
   475 
       
   476 /*!
       
   477  * \reimp
       
   478  */
       
   479 /*!
       
   480  * Definition identifiers which are natively (fast) filterable
       
   481  * on the default backend store managed by the manager from which the capabilities object was accessed
       
   482  */
       
   483 bool QContactTrackerEngine::isFilterSupported(const QContactFilter& filter) const
       
   484 {
       
   485     switch (filter.type()) {
       
   486         case QContactFilter::InvalidFilter:
       
   487         case QContactFilter::DefaultFilter:
       
   488         case QContactFilter::LocalIdFilter:
       
   489         case QContactFilter::ContactDetailFilter:
       
   490         case QContactFilter::ContactDetailRangeFilter:
       
   491         case QContactFilter::ActionFilter:
       
   492         case QContactFilter::ChangeLogFilter:
       
   493         case QContactFilter::RelationshipFilter:
       
   494 
       
   495 // not yet done
       
   496 //        case QContactFilter::IntersectionFilter:
       
   497 //        case QContactFilter::UnionFilter:
       
   498             return true;
       
   499         default:
       
   500             return false;
       
   501     }
       
   502 }
       
   503 
       
   504 /*!
       
   505  * Returns the list of data types supported by the Tracker engine
       
   506  */
       
   507 QList<QVariant::Type> QContactTrackerEngine::supportedDataTypes() const
       
   508 {
       
   509     // TODO: Check supported datatypes for Tracker backend.
       
   510     QList<QVariant::Type> st;
       
   511     st.append(QVariant::String);
       
   512     st.append(QVariant::Date);
       
   513     st.append(QVariant::DateTime);
       
   514     return st;
       
   515 }
       
   516 
       
   517 /*!
       
   518  * Returns the name of the Tracker engine
       
   519  */
       
   520 QString QContactTrackerEngine::managerName() const
       
   521 {
       
   522     return d->m_engineName;
       
   523 }
       
   524 
       
   525 /*!
       
   526  * Returns the manager version of this engine
       
   527  */
       
   528 int QContactTrackerEngine::managerVersion() const
       
   529 {
       
   530     return d->m_engineVersion;
       
   531 }
       
   532 
       
   533 RDFVariable QContactTrackerEngine::contactDetail2Rdf(const RDFVariable& rdfContact, const QString& definitionName,
       
   534                                                       const QString& fieldName) const
       
   535 {
       
   536     if (definitionName == QContactName::DefinitionName) {
       
   537         if (fieldName == QContactName::FieldFirstName) {
       
   538             return rdfContact.property<nco::nameGiven>();
       
   539         }
       
   540         else if (fieldName == QContactName::FieldLastName) {
       
   541             return rdfContact.property<nco::nameFamily>();
       
   542         }
       
   543         else if (fieldName == QContactName::FieldMiddleName) {
       
   544             return rdfContact.property<nco::nameAdditional>();
       
   545         }
       
   546         else if (fieldName == QContactName::FieldPrefix) {
       
   547             return rdfContact.property<nco::nameHonorificPrefix>();
       
   548         }
       
   549         else if (fieldName == QContactName::FieldSuffix) {
       
   550             return rdfContact.property<nco::nameHonorificSuffix>();
       
   551         }
       
   552         else if (fieldName == QContactNickname::FieldNickname) {
       
   553             return rdfContact.property<nco::nickname>();
       
   554         }
       
   555     }
       
   556     return RDFVariable();
       
   557 }
       
   558 
       
   559 /*! \reimp */
       
   560 void QContactTrackerEngine::requestDestroyed(QContactAbstractRequest* req)
       
   561 {
       
   562     if( d->m_requests.contains(req) )
       
   563     {
       
   564         QTrackerContactAsyncRequest *request = d->m_requests.take(req);
       
   565         delete request;
       
   566     }
       
   567 }
       
   568 
       
   569 /*! \reimp */
       
   570 bool QContactTrackerEngine::startRequest(QContactAbstractRequest* req)
       
   571 {
       
   572     QTrackerContactAsyncRequest *request = 0;
       
   573     switch (req->type())
       
   574     {
       
   575         case QContactAbstractRequest::ContactLocalIdFetchRequest:
       
   576             request = new QTrackerContactIdFetchRequest(req, this);
       
   577             break;
       
   578         case QContactAbstractRequest::ContactFetchRequest:
       
   579             request = new QTrackerContactFetchRequest(req, this);
       
   580             break;
       
   581         case QContactAbstractRequest::ContactSaveRequest:
       
   582             request = new QTrackerContactSaveRequest(req, this);
       
   583             break;
       
   584         case QContactAbstractRequest::RelationshipFetchRequest:
       
   585             request = new QTrackerRelationshipFetchRequest(req, this);
       
   586             break;
       
   587         case QContactAbstractRequest::RelationshipSaveRequest:
       
   588             request = new QTrackerRelationshipSaveRequest(req, this);
       
   589             break;
       
   590         default:
       
   591             return false;
       
   592     }
       
   593     d->m_requests[req] = request;
       
   594     return true;
       
   595 }
       
   596 
       
   597 /*! \reimp */
       
   598 QString QContactTrackerEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const
       
   599 {
       
   600     QString label = QContactManagerEngine::synthesizedDisplayLabel(contact, error);
       
   601     if (label.isEmpty())
       
   602         label = contact.detail<QContactNickname>().nickname();
       
   603     //XXX TODO: FIXME - take the nickname from the presence field associated with the online account
       
   604     //if(label.isEmpty())
       
   605     //    label = contact.detail<QContactOnlineAccount>().nickname();
       
   606 
       
   607     qDebug() << Q_FUNC_INFO << label;
       
   608     return label;
       
   609 }