qtmobility/plugins/contacts/wince/contactconversions.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
   102         LPWSTR newStr = wcsdup(str);
   102         LPWSTR newStr = wcsdup(str);
   103         m_list.push_back(newStr);
   103         m_list.push_back(newStr);
   104         return newStr;
   104         return newStr;
   105     }
   105     }
   106     void clear() {
   106     void clear() {
   107         foreach (LPWSTR str, m_list) {
   107         foreach (const LPWSTR& str, m_list) {
   108             free(str);
   108             free(str);
   109         }
   109         }
   110         m_list.clear();
   110         m_list.clear();
   111     }
   111     }
   112 private:
   112 private:
   190 
   190 
   191 static void processName(const QContactWinCEEngine* /*engine*/, IItem* /*contact*/, const QVariantList& values, QContact& ret)
   191 static void processName(const QContactWinCEEngine* /*engine*/, IItem* /*contact*/, const QVariantList& values, QContact& ret)
   192 {
   192 {
   193     QContactName name;
   193     QContactName name;
   194     setIfNotEmpty(name, QContactName::FieldPrefix, values[0].toString());
   194     setIfNotEmpty(name, QContactName::FieldPrefix, values[0].toString());
   195     setIfNotEmpty(name, QContactName::FieldFirst, values[1].toString());
   195     setIfNotEmpty(name, QContactName::FieldFirstName, values[1].toString());
   196     setIfNotEmpty(name, QContactName::FieldMiddle, values[2].toString());
   196     setIfNotEmpty(name, QContactName::FieldMiddleName, values[2].toString());
   197     setIfNotEmpty(name, QContactName::FieldLast, values[3].toString());
   197     setIfNotEmpty(name, QContactName::FieldLastName, values[3].toString());
   198     setIfNotEmpty(name, QContactName::FieldSuffix, values[4].toString());
   198     setIfNotEmpty(name, QContactName::FieldSuffix, values[4].toString());
   199     setIfNotEmpty(name, QContactName::FieldCustomLabel, values[5].toString());
   199     setIfNotEmpty(name, QContactName::FieldCustomLabel, values[5].toString());
   200     if (!name.isEmpty())
   200     if (!name.isEmpty())
   201         ret.saveDetail(&name);
   201         ret.saveDetail(&name);
   202 }
   202 }
   296     QByteArray data;
   296     QByteArray data;
   297     if (loadAvatarData(contact, &data)) {
   297     if (loadAvatarData(contact, &data)) {
   298         if (!data.isEmpty()) {
   298         if (!data.isEmpty()) {
   299             QPixmap pixmap;
   299             QPixmap pixmap;
   300             pixmap.loadFromData(data, "PNG");
   300             pixmap.loadFromData(data, "PNG");
   301             avatar.setPixmap(pixmap);
   301             //avatar.setPixmap(pixmap);
   302         }
   302         }
   303     }
   303     }
   304 
   304 
   305     if (values[0].toString().isEmpty()) {
   305     if (values[0].toString().isEmpty()) {
   306         if (!data.isEmpty()) {
   306         if (!data.isEmpty()) {
   307             QUrl url(QUrl::fromEncoded(data.toPercentEncoding()));
   307             QUrl url(QUrl::fromEncoded(data.toPercentEncoding()));
   308             url.setScheme("data");
   308             url.setScheme("data");
   309             avatar.setAvatar(url.toString());
   309             avatar.setImageUrl(url.toString());
   310         }
   310         }
   311     } else {
   311     } else {
   312         avatar.setAvatar(values[0].toString());
   312         avatar.setImageUrl(values[0].toString());
   313     }
   313     }
   314 
   314 
   315     setIfNotEmpty(avatar, QContactAvatar::FieldSubType, values[1].toString());
       
   316     
   315     
   317         
   316         
   318     if (!avatar.isEmpty())
   317     if (!avatar.isEmpty())
   319         ret.saveDetail(&avatar);
   318         ret.saveDetail(&avatar);
   320 }
   319 }
   433                     break;
   432                     break;
   434                 case 9: // Home fax
   433                 case 9: // Home fax
   435                     m = meta.at(i);
   434                     m = meta.at(i);
   436                     if (m ==  ' ')
   435                     if (m ==  ' ')
   437                         m = 'H';
   436                         m = 'H';
   438                     number.setSubTypes(QContactPhoneNumber::SubTypeFacsimile);
   437                     number.setSubTypes(QContactPhoneNumber::SubTypeFax);
   439                     break;
   438                     break;
   440                 case 10: // Business fax
   439                 case 10: // Business fax
   441                     m = meta.at(i);
   440                     m = meta.at(i);
   442                     if (m ==  ' ')
   441                     if (m ==  ' ')
   443                         m = 'W';
   442                         m = 'W';
   444                     number.setSubTypes(QContactPhoneNumber::SubTypeFacsimile);
   443                     number.setSubTypes(QContactPhoneNumber::SubTypeFax);
   445                     break;
   444                     break;
   446             }
   445             }
   447 
   446 
   448             if (m == 'H')
   447             if (m == 'H')
   449                 number.setContexts(QContactDetail::ContextHome);
   448                 number.setContexts(QContactDetail::ContextHome);
   606         family.func = processFamily;
   605         family.func = processFamily;
   607         list.append(family);
   606         list.append(family);
   608 
   607 
   609         // Avatar
   608         // Avatar
   610         PoomContactElement avatar;
   609         PoomContactElement avatar;
   611         avatar.poom << avatarMeta << avatarTypeMeta; //PIMPR_PICTURE need to be handled inside the processAvatar() function seperately.
   610         avatar.poom << avatarMeta << avatarTypeMeta; //PIMPR_PICTURE need to be handled inside the processAvatar() function separately.
   612         avatar.func = processAvatar;
   611         avatar.func = processAvatar;
   613         list.append(avatar);
   612         list.append(avatar);
   614 
   613 
   615 
   614 
   616         // XXX Unhandled:
   615         // XXX Unhandled:
   635         //  PIMPR_YOMI_FIRSTNAME
   634         //  PIMPR_YOMI_FIRSTNAME
   636         //  PIMPR_YOMI_LASTNAME
   635         //  PIMPR_YOMI_LASTNAME
   637 
   636 
   638         // Now, build the hash
   637         // Now, build the hash
   639         foreach(const PoomContactElement& e, list) {
   638         foreach(const PoomContactElement& e, list) {
   640             foreach(CEPROPID id, e.poom) {
   639             foreach(const CEPROPID& id, e.poom) {
   641                 ids.append(id);
   640                 ids.append(id);
   642                 hash.insert(id, e);
   641                 hash.insert(id, e);
   643             }
   642             }
   644         }
   643         }
   645     }
   644     }
   654 }
   653 }
   655 
   654 
   656 static bool processQName(const QContactWinCEEngine*, IItem* /*contact*/, const QContactDetail& detail, QVector<CEPROPVAL>& props)
   655 static bool processQName(const QContactWinCEEngine*, IItem* /*contact*/, const QContactDetail& detail, QVector<CEPROPVAL>& props)
   657 {
   656 {
   658     addIfNotEmpty(PIMPR_TITLE, detail.value(QContactName::FieldPrefix), props);
   657     addIfNotEmpty(PIMPR_TITLE, detail.value(QContactName::FieldPrefix), props);
   659     addIfNotEmpty(PIMPR_FIRST_NAME, detail.value(QContactName::FieldFirst), props);
   658     addIfNotEmpty(PIMPR_FIRST_NAME, detail.value(QContactName::FieldFirstName), props);
   660     addIfNotEmpty(PIMPR_MIDDLE_NAME, detail.value(QContactName::FieldMiddle), props);
   659     addIfNotEmpty(PIMPR_MIDDLE_NAME, detail.value(QContactName::FieldMiddleName), props);
   661     addIfNotEmpty(PIMPR_LAST_NAME, detail.value(QContactName::FieldLast), props);
   660     addIfNotEmpty(PIMPR_LAST_NAME, detail.value(QContactName::FieldLastName), props);
   662     addIfNotEmpty(PIMPR_SUFFIX, detail.value(QContactName::FieldSuffix), props);
   661     addIfNotEmpty(PIMPR_SUFFIX, detail.value(QContactName::FieldSuffix), props);
   663     addIfNotEmpty(PIMPR_FILEAS, detail.value(QContactName::FieldCustomLabel), props);
   662     addIfNotEmpty(PIMPR_FILEAS, detail.value(QContactName::FieldCustomLabel), props);
   664     return true;
   663     return true;
   665 }
   664 }
   666 
   665 
   667 static bool processQAvatar(const QContactWinCEEngine* engine, IItem* contact, const QContactDetail& detail, QVector<CEPROPVAL>& props)
   666 static bool processQAvatar(const QContactWinCEEngine* engine, IItem* contact, const QContactDetail& detail, QVector<CEPROPVAL>& props)
   668 {
   667 {
   669     QString avatarData = detail.value(QContactAvatar::FieldAvatar);
   668     Q_UNUSED(engine);
   670     QPixmap avatarPixmap = detail.value<QPixmap>(QContactAvatar::FieldAvatarPixmap);
   669     Q_UNUSED(contact);
   671 
   670     Q_UNUSED(detail);
   672     addIfNotEmpty(engine->metaAvatarType(), detail.value(QContactAvatar::FieldSubType), props);
   671     Q_UNUSED(props);
   673     addIfNotEmpty(engine->metaAvatar(), avatarData, props);
   672     //QString avatarData = detail.value(QContactAvatar::FieldImageUrl);
   674 
   673     //QPixmap avatarPixmap = detail.value<QPixmap>(QContactAvatar::FieldAvatarPixmap);
   675     if (!avatarPixmap.isNull()) {
   674 
   676         QByteArray data;
   675     //FIXME:wince avatar should be processed as thumbnail
   677         QBuffer buffer(&data);
   676     //addIfNotEmpty(engine->metaAvatar(), avatarData, props);
   678         buffer.open(QIODevice::WriteOnly);
   677 
   679         if (!avatarPixmap.save(&buffer, "PNG") || !saveAvatarData(contact, data))
   678     //if (!avatarPixmap.isNull()) {
   680             return false;
   679     //    QByteArray data;
   681     }
   680     //    QBuffer buffer(&data);
       
   681     //    buffer.open(QIODevice::WriteOnly);
       
   682     //    if (!avatarPixmap.save(&buffer, "PNG") || !saveAvatarData(contact, data))
       
   683     //        return false;
       
   684     //}
   682     return true;
   685     return true;
   683 }
   686 }
   684 
   687 
   685 static bool processQFamily(const QContactWinCEEngine*, IItem* /*contact*/, const QContactDetail& detail, QVector<CEPROPVAL>& props)
   688 static bool processQFamily(const QContactWinCEEngine*, IItem* /*contact*/, const QContactDetail& detail, QVector<CEPROPVAL>& props)
   686 {
   689 {
   767         // Map from our attributes to ids
   770         // Map from our attributes to ids
   768         if (number.subTypes().contains(QContactPhoneNumber::SubTypeCar))
   771         if (number.subTypes().contains(QContactPhoneNumber::SubTypeCar))
   769             id = PIMPR_CAR_TELEPHONE_NUMBER;
   772             id = PIMPR_CAR_TELEPHONE_NUMBER;
   770         else if (number.subTypes().contains(QContactPhoneNumber::SubTypeMobile))
   773         else if (number.subTypes().contains(QContactPhoneNumber::SubTypeMobile))
   771             id = PIMPR_MOBILE_TELEPHONE_NUMBER;
   774             id = PIMPR_MOBILE_TELEPHONE_NUMBER;
   772         else if (number.subTypes().contains(QContactPhoneNumber::SubTypeFacsimile)) {
   775         else if (number.subTypes().contains(QContactPhoneNumber::SubTypeFax)) {
   773             if (number.contexts().contains(QContactDetail::ContextHome))
   776             if (number.contexts().contains(QContactDetail::ContextHome))
   774                 id = PIMPR_HOME_FAX_NUMBER;
   777                 id = PIMPR_HOME_FAX_NUMBER;
   775             else if (number.contexts().contains(QContactDetail::ContextWork))
   778             else if (number.contexts().contains(QContactDetail::ContextWork))
   776                 id = PIMPR_BUSINESS_FAX_NUMBER;
   779                 id = PIMPR_BUSINESS_FAX_NUMBER;
   777         } else if (number.subTypes().contains(QContactPhoneNumber::SubTypeVoice)) {
   780         } else if (number.subTypes().contains(QContactPhoneNumber::SubTypeVoice)) {
   838 
   841 
   839     foreach(const QContactEmailAddress& email, emails) {
   842     foreach(const QContactEmailAddress& email, emails) {
   840         CEPROPID id = availableIds.takeFirst();
   843         CEPROPID id = availableIds.takeFirst();
   841         if (id != 0) {
   844         if (id != 0) {
   842             if (email.contexts().contains(QContactDetail::ContextHome))
   845             if (email.contexts().contains(QContactDetail::ContextHome))
   843                 meta += "H";
   846                 meta += 'H';
   844             else if (email.contexts().contains(QContactDetail::ContextWork))
   847             else if (email.contexts().contains(QContactDetail::ContextWork))
   845                 meta += "W";
   848                 meta += 'W';
   846             else
   849             else
   847                 meta += " ";
   850                 meta += ' ';
   848             props.append(convertToCEPropVal(id, email.emailAddress()));
   851             props.append(convertToCEPropVal(id, email.emailAddress()));
   849         } else {
   852         } else {
   850             qDebug() << "Too many email addresses";
   853             qDebug() << "Too many email addresses";
   851             break;
   854             break;
   852         }
   855         }
  1012         HeapFree(GetProcessHeap(), 0, propvals);
  1015         HeapFree(GetProcessHeap(), 0, propvals);
  1013     }
  1016     }
  1014 
  1017 
  1015     // Synthesize the display label.
  1018     // Synthesize the display label.
  1016     QContactManager::Error error;
  1019     QContactManager::Error error;
  1017     QString synth = synthesizedDisplayLabel(ret, error);
  1020     QString synth = synthesizedDisplayLabel(ret, &error);
  1018     ret = setContactDisplayLabel(synth, ret);
  1021     setContactDisplayLabel(&ret, synth);
  1019 
  1022 
  1020     return ret;
  1023     return ret;
  1021 }
  1024 }
  1022 
  1025 
  1023 bool QContactWinCEEngine::convertFromQContact(const QContact& contact, IItem* item, QContactManager::Error &error) const
  1026 bool QContactWinCEEngine::convertFromQContact(const QContact& contact, IItem* item, QContactManager::Error &error) const
  1234 void QContactWinCEEngine::buildHashForContactDetailToPoomPropId() const
  1237 void QContactWinCEEngine::buildHashForContactDetailToPoomPropId() const
  1235 {
  1238 {
  1236     if (hashForContactDetailToPoomPropId.isEmpty()) {
  1239     if (hashForContactDetailToPoomPropId.isEmpty()) {
  1237         //QContactName
  1240         //QContactName
  1238         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldPrefix, PIMPR_TITLE);
  1241         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldPrefix, PIMPR_TITLE);
  1239         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldFirst, PIMPR_FIRST_NAME);
  1242         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldFirstName, PIMPR_FIRST_NAME);
  1240         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldMiddle, PIMPR_MIDDLE_NAME);
  1243         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldMiddleName, PIMPR_MIDDLE_NAME);
  1241         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldLast, PIMPR_LAST_NAME);
  1244         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldLastName, PIMPR_LAST_NAME);
  1242         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldSuffix, PIMPR_SUFFIX);
  1245         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactName, FieldSuffix, PIMPR_SUFFIX);
  1243 
  1246 
  1244         // Display label
  1247         // Display label
  1245         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactDisplayLabel, FieldLabel, PIMPR_FILEAS);
  1248         Q_HASH_CONTACT_DETAIL_TO_POOM_ID(QContactDisplayLabel, FieldLabel, PIMPR_FILEAS);
  1246 
  1249 
  1306 }
  1309 }
  1307 
  1310 
  1308 
  1311 
  1309 /*!
  1312 /*!
  1310  * Convert from the supplied QContactFilter \a filter into a POOM query string.
  1313  * Convert from the supplied QContactFilter \a filter into a POOM query string.
  1311  * Return empty string if any error occured.
  1314  * Return empty string if any error occurred.
  1312  */
  1315  */
  1313 QString QContactWinCEEngine::convertFilterToQueryString(const QContactFilter& filter) const
  1316 QString QContactWinCEEngine::convertFilterToQueryString(const QContactFilter& filter) const
  1314 {
  1317 {
  1315     QString ret;
  1318     QString ret;
  1316     switch(filter.type()) {
  1319     switch(filter.type()) {
  1349                 //XXX Only exact match can be supported?
  1352                 //XXX Only exact match can be supported?
  1350                 if (cdf.matchFlags() == QContactFilter::MatchExactly && cdf.value().isValid()) {
  1353                 if (cdf.matchFlags() == QContactFilter::MatchExactly && cdf.value().isValid()) {
  1351                     QList<CEPROPID> ids = convertToCEPropIds(cdf.detailDefinitionName(), cdf.detailFieldName());
  1354                     QList<CEPROPID> ids = convertToCEPropIds(cdf.detailDefinitionName(), cdf.detailFieldName());
  1352                     if (!ids.isEmpty()) {
  1355                     if (!ids.isEmpty()) {
  1353                         QStringList strList;
  1356                         QStringList strList;
  1354                         foreach (CEPROPID id, ids) {
  1357                         foreach (const CEPROPID& id, ids) {
  1355                             strList << QString("%1 = %2").arg(getPropertyName(id))
  1358                             strList << QString("%1 = %2").arg(getPropertyName(id))
  1356                                                 .arg(convertToCEPropValString(id, cdf.value()));
  1359                                                 .arg(convertToCEPropValString(id, cdf.value()));
  1357                         }
  1360                         }
  1358                         ret = QString("(%1)").arg(strList.join(" OR "));
  1361                         ret = QString("(%1)").arg(strList.join(" OR "));
  1359                     }
  1362                     }
  1373                         const QString maxComp = cdf.rangeFlags() & QContactDetailRangeFilter::IncludeUpper ? "<=" : "<";
  1376                         const QString maxComp = cdf.rangeFlags() & QContactDetailRangeFilter::IncludeUpper ? "<=" : "<";
  1374 
  1377 
  1375                         QString minCompString, maxCompString;
  1378                         QString minCompString, maxCompString;
  1376                         QStringList strList;
  1379                         QStringList strList;
  1377 
  1380 
  1378                         foreach (CEPROPID id, ids) {
  1381                         foreach (const CEPROPID& id, ids) {
  1379                             if (cdf.minValue().isValid()) {
  1382                             if (cdf.minValue().isValid()) {
  1380                                 minCompString = QString("%1 %2 %3").arg(getPropertyName(id))
  1383                                 minCompString = QString("%1 %2 %3").arg(getPropertyName(id))
  1381                                                                    .arg(minComp)
  1384                                                                    .arg(minComp)
  1382                                                                    .arg(convertToCEPropValString(id, cdf.minValue()));
  1385                                                                    .arg(convertToCEPropValString(id, cdf.minValue()));
  1383                             }
  1386                             }
  1566     }
  1569     }
  1567 
  1570 
  1568     return SUCCEEDED(hr);
  1571     return SUCCEEDED(hr);
  1569 }
  1572 }
  1570 
  1573 
  1571 QList<QContactLocalId> QContactWinCEEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const
  1574 QList<QContactLocalId> QContactWinCEEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
  1572 {
  1575 {
  1573     QString query = convertFilterToQueryString(filter);
  1576     QString query = convertFilterToQueryString(filter);
  1574 
  1577 
  1575     if (!query.isEmpty()) {
  1578     if (!query.isEmpty()) {
  1576         error = QContactManager::NoError;
  1579         *error = QContactManager::NoError;
  1577         //Filtering contacts with POOM API
  1580         //Filtering contacts with POOM API
  1578         SimpleComPointer<IPOutlookItemCollection> collection;
  1581         SimpleComPointer<IPOutlookItemCollection> collection;
  1579         HRESULT hr = d->m_collection->Restrict((BSTR)(query.constData()), &collection);
  1582         HRESULT hr = d->m_collection->Restrict((BSTR)(query.constData()), &collection);
  1580 
  1583 
  1581         if (SUCCEEDED(hr)) {
  1584         if (SUCCEEDED(hr)) {
  1588                 //Multi sort orders or native sorting failed, fall back to the generic sorting
  1591                 //Multi sort orders or native sorting failed, fall back to the generic sorting
  1589                 QList<QContact> filteredContacts;
  1592                 QList<QContact> filteredContacts;
  1590                 if (convertP2QContacts(collection, &filteredContacts)) {
  1593                 if (convertP2QContacts(collection, &filteredContacts)) {
  1591                     ids = sortContacts(filteredContacts, sortOrders);
  1594                     ids = sortContacts(filteredContacts, sortOrders);
  1592                 } else {
  1595                 } else {
  1593                     error = QContactManager::UnspecifiedError;
  1596                     *error = QContactManager::UnspecifiedError;
  1594                     qDebug() << "Wince contact manager internal error";
  1597                     qDebug() << "Wince contact manager internal error";
  1595                 }
  1598                 }
  1596             }
  1599             }
  1597             return ids;
  1600             return ids;
  1598         } else {
  1601         } else {
  1602     }
  1605     }
  1603     //Fail back to generic filtering
  1606     //Fail back to generic filtering
  1604     return QContactManagerEngine::contactIds(filter, sortOrders, error);
  1607     return QContactManagerEngine::contactIds(filter, sortOrders, error);
  1605 }
  1608 }
  1606 
  1609 
  1607 QList<QContactLocalId> QContactWinCEEngine::contactIds(const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const
  1610 
  1608 {
       
  1609     QList<QContactLocalId> ids;
       
  1610     error = QContactManager::NoError;
       
  1611     if (sortOrders.isEmpty()) {
       
  1612         ids = d->m_ids;
       
  1613     } else {
       
  1614         SimpleComPointer<IPOutlookItemCollection> newCollection;
       
  1615         HRESULT hr = d->m_collection->Restrict(TEXT("[Oid] <> 0"), &newCollection);
       
  1616 
       
  1617         if (SUCCEEDED(hr)) {
       
  1618             //Try native sorting first...
       
  1619             if (sortOrders.size() == 1 && sortPOOMContacts(newCollection, sortOrders.at(0))) {
       
  1620                 ids = convertP2QIdList(newCollection);
       
  1621                 return ids;
       
  1622             } 
       
  1623         }
       
  1624 
       
  1625         //Multi sort orders or native sorting failed, fall back to the generic sorting
       
  1626         QList<QContact> contacts;
       
  1627         if (convertP2QContacts(d->m_collection, &contacts)) {
       
  1628             ids = sortContacts(contacts, sortOrders);
       
  1629         } else {
       
  1630             error = QContactManager::UnspecifiedError;
       
  1631             qDebug() << "Wince contact manager internal error";
       
  1632         }
       
  1633     }
       
  1634     return ids;
       
  1635 }
       
  1636