void CntVersitPrefPlugin::propertyProcessed( const QVersitDocument& document, const QVersitProperty& property, const QContact& contact, bool* alreadyProcessed, QList<QContactDetail>* updatedDetails) { Q_UNUSED(document); Q_UNUSED(contact); if (*alreadyProcessed && !updatedDetails->isEmpty()) { QStringList typeParameters = property.parameters().values(QLatin1String("TYPE")); if (typeParameters.contains(QLatin1String("PREF"), Qt::CaseInsensitive)) { if ((mDetailMappings.value(property.name()) == QContactPhoneNumber::DefinitionName) || (mDetailMappings.value(property.name()) == QContactEmailAddress::DefinitionName) || (mDetailMappings.value(property.name()) == QContactOnlineAccount::DefinitionName) || (mDetailMappings.value(property.name()) == QContactUrl::DefinitionName)) { // This method is called before the corresponding detail gets imported to QContact. // setPreferredDetail() cannot be called here -> detail is stored and will be set // preferred after whole versit document is processed mPrefDetailList.append(updatedDetails->last()); } } } }
/*! * Encodes the \a property and writes it to the device. */ void QVCard30Writer::encodeVersitProperty(const QVersitProperty& property) { QVersitProperty modifiedProperty(property); QString name = mPropertyNameMappings.value(property.name(),property.name()); modifiedProperty.setName(name); encodeGroupsAndName(modifiedProperty); QVariant variant(modifiedProperty.variantValue()); if (variant.type() == QVariant::ByteArray) { modifiedProperty.insertParameter(QLatin1String("ENCODING"), QLatin1String("b")); } encodeParameters(modifiedProperty.parameters()); writeString(QLatin1String(":")); QString renderedValue; QByteArray renderedBytes; if (variant.canConvert<QVersitDocument>()) { QVersitDocument embeddedDocument = variant.value<QVersitDocument>(); QByteArray data; QBuffer buffer(&data); buffer.open(QIODevice::WriteOnly); QVCard30Writer subWriter(mType); subWriter.setCodec(mCodec); subWriter.setDevice(&buffer); subWriter.encodeVersitDocument(embeddedDocument); QString documentString(mCodec->toUnicode(data)); backSlashEscape(&documentString); renderedValue = documentString; } else if (variant.type() == QVariant::String) { renderedValue = variant.toString(); if (property.valueType() != QVersitProperty::PreformattedType) { backSlashEscape(&renderedValue); } } else if (variant.type() == QVariant::StringList) { // We need to backslash escape and concatenate the values in the list QStringList values = property.variantValue().toStringList(); QString separator; if (property.valueType() == QVersitProperty::CompoundType) { separator = QLatin1String(";"); } else { if (property.valueType() != QVersitProperty::ListType) { qWarning("Variant value is a QStringList but the property's value type is neither " "CompoundType or ListType"); } // Assume it's a ListType separator = QLatin1String(","); } bool first = true; foreach (QString value, values) { if (!(value.isEmpty() && property.valueType() == QVersitProperty::ListType)) { if (!first) { renderedValue += separator; } backSlashEscape(&value); renderedValue += value; first = false; } } } else if (variant.type() == QVariant::ByteArray) {
void SeasidePropertyHandler::propertyProcessed(const QVersitDocument &, const QVersitProperty &property, const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails) { if (property.name().toLower() == QLatin1String("photo")) { processPhoto(property, alreadyProcessed, updatedDetails); } else if (property.name().toLower() == QLatin1String("x-nemomobile-onlineaccount-demo")) { processOnlineAccount(property, alreadyProcessed, updatedDetails); } }
foreach(const QVersitProperty& expectedProperty, expectedProperties) { QList<QVersitProperty> actualProperties = findPropertiesByName(subDocuments.first(), expectedProperty.name()); if (!actualProperties.contains(expectedProperty)) { qDebug() << "Actual:" << actualProperties; qDebug() << "Expected to find:" << expectedProperty; QVERIFY(false); } }
/*! * Encodes the groups and name in the \a property and writes it to the device */ void QVersitDocumentWriter::encodeGroupsAndName(const QVersitProperty& property) { QStringList groups = property.groups(); if (!groups.isEmpty()) { writeString(groups.join(QStringLiteral("."))); writeString(QStringLiteral(".")); } writeString(property.name()); }
/*! Returns the hash value for \a key. */ uint qHash(const QVersitProperty &key) { uint hash = QT_PREPEND_NAMESPACE(qHash)(key.name()) + QT_PREPEND_NAMESPACE(qHash)(key.value()); foreach (const QString& group, key.groups()) { hash += QT_PREPEND_NAMESPACE(qHash)(group); } QHash<QString,QString>::const_iterator it = key.parameters().constBegin(); QHash<QString,QString>::const_iterator end = key.parameters().constEnd(); while (it != end) { hash += QT_PREPEND_NAMESPACE(qHash)(it.key()) + QT_PREPEND_NAMESPACE(qHash)(it.value()); ++it; } return hash; }
/*! Called for each processed versit property from QVersitContactImporter during contact import. */ void CntVersitMyCardPlugin::propertyProcessed( const QVersitDocument& document, const QVersitProperty& property, const QContact& contact, bool* alreadyProcessed, QList<QContactDetail>* updatedDetails) { Q_UNUSED(document); Q_UNUSED(contact); Q_UNUSED(updatedDetails); Q_UNUSED(contact); Q_UNUSED(alreadyProcessed); if (property.name() == QLatin1String("X-SELF")) { mIsMyCard = true; } }
bool QVCardRestoreHandler::propertyProcessed( const QVersitProperty& property, QList<QContactDetail>* updatedDetails) { bool success = false; QString group; if (!property.groups().isEmpty()) group = property.groups().first(); if (property.name() == PropertyName) { if (property.groups().size() != 1) return false; QMultiHash<QString, QString> parameters = property.parameters(); QContactDetail::DetailType detailType = QContactDetail::DetailType(parameters.value(DetailTypeParameter).toUInt()); QString fieldName = parameters.value(FieldParameter); // Find a detail previously seen with the same definitionName, which was generated from // a property from the same group QContactDetail detail(detailType); foreach (const QContactDetail& previousDetail, mDetailGroupMap.detailsInGroup(group)) { if (previousDetail.type() == detailType) { detail = previousDetail; } } // If not found, it's a new empty detail with the definitionName set. detail.setValue(fieldName.toInt(), deserializeValue(property)); // Replace the equivalent detail in updatedDetails with the new one QMutableListIterator<QContactDetail> it(*updatedDetails); while (it.hasNext()) { if (it.next().key() == detail.key()) { it.remove(); break; } } updatedDetails->append(detail); success = true; } if (!group.isEmpty()) { // Keep track of which details were generated from which Versit groups foreach (const QContactDetail& detail, *updatedDetails) { mDetailGroupMap.insert(group, detail); } }
QDebug operator<<(QDebug dbg, const QVersitProperty& property) { QStringList groups = property.groups(); QString name = property.name(); QMultiHash<QString,QString> parameters = property.parameters(); dbg.nospace() << "QVersitProperty("; foreach (const QString& group, groups) { dbg.nospace() << group << '.'; } dbg.nospace() << name; QHash<QString,QString>::const_iterator it; for (it = parameters.constBegin(); it != parameters.constEnd(); ++it) { dbg.nospace() << ';' << it.key() << '=' << it.value(); } if (property.valueType() == QVersitProperty::VersitDocumentType) dbg.nospace() << ':' << property.value<QVersitDocument>(); else dbg.nospace() << ':' << property.variantValue(); dbg.nospace() << ')'; return dbg.maybeSpace(); }
void CntVersitFavoritePlugin::propertyProcessed( const QVersitDocument& document, const QVersitProperty& property, const QContact& contact, bool* alreadyProcessed, QList<QContactDetail>* updatedDetails) { Q_UNUSED(document); Q_UNUSED(contact); Q_UNUSED(alreadyProcessed); Q_UNUSED(updatedDetails); if (property.name().contains(QLatin1String("X-FAVORITE"), Qt::CaseInsensitive)) { // This method is called before the corresponding detail gets imported to QContact. // Detail is saved after whole versit document is processed. QContactFavorite favorite; favorite.setFavorite(true); favorite.setIndex(property.value().toInt()); mFavoriteDetailList.append(favorite); } }
void SeasidePhotoHandler::propertyProcessed(const QVersitDocument &, const QVersitProperty &property, const QContact &, bool *alreadyProcessed, QList<QContactDetail> * updatedDetails) { // if the property is a PHOTO property, store the data to disk // and then create an avatar detail which points to it. if (property.name().toLower() != QLatin1String("photo")) return; #ifndef QT_VERSION_5 // The Qt4 / QtMobility version has QContactThumbnail support. // We need to remove any such thumbnail detail from the output, // as some backends (such as qtcontacts-sqlite) do not support // that detail type. for (int i = 0; i < updatedDetails->size(); ++i) { if (updatedDetails->at(i).definitionName() == QContactThumbnail::DefinitionName) { updatedDetails->removeAt(i); --i; } } #endif // The data might be either a URL, a file path, or encoded image data // It's hard to tell what the content is, because versit removes the encoding // information in the process of decoding the data... // Try to interpret the data as a URL QString path(property.variantValue().toString()); QUrl url(path); if (url.isValid()) { // Treat remote URL as a true URL, and reference it in the avatar if (!url.scheme().isEmpty() && !url.isLocalFile()) { QContactAvatar newAvatar; newAvatar.setImageUrl(url); updatedDetails->append(newAvatar); // we have successfully processed this PHOTO property. *alreadyProcessed = true; return; } } if (!url.isValid()) { // See if we can resolve the data as a local file path url = QUrl::fromLocalFile(path); } QByteArray photoData; if (url.isValid()) { // Try to read the data from the referenced file const QString filePath(url.path()); if (QFile::exists(filePath)) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Unable to process photo data as file:" << path; return; } else { photoData = file.readAll(); } } } if (photoData.isEmpty()) { // Try to interpret the encoded property data as the image photoData = property.variantValue().toByteArray(); if (photoData.isEmpty()) { qWarning() << "Failed to extract avatar data from vCard PHOTO property"; return; } } QImage img; bool loaded = img.loadFromData(photoData); if (!loaded) { qWarning() << "Failed to load avatar image from vCard PHOTO data"; return; } // We will save the avatar image to disk in the system's data location // Since we're importing user data, it should not require privileged access const QString subdirectory(QString::fromLatin1(".local/share/system/Contacts/avatars")); const QString photoDirPath(QDir::home().filePath(subdirectory)); // create the photo file dir if it doesn't exist. QDir photoDir; if (!photoDir.mkpath(photoDirPath)) { qWarning() << "Failed to create avatar image directory when loading avatar image from vCard PHOTO data"; return; } // construct the filename of the new avatar image. QString photoFilePath = QString::fromLatin1(QCryptographicHash::hash(photoData, QCryptographicHash::Md5).toHex()); photoFilePath = photoDirPath + QDir::separator() + photoFilePath + QString::fromLatin1(".jpg"); // save the file to disk bool saved = img.save(photoFilePath); if (!saved) { qWarning() << "Failed to save avatar image from vCard PHOTO data to" << photoFilePath; return; } qWarning() << "Successfully saved avatar image from vCard PHOTO data to" << photoFilePath; // save the avatar detail - TODO: mark the avatar as "owned by the contact" (remove on delete) QContactAvatar newAvatar; newAvatar.setImageUrl(QUrl::fromLocalFile(photoFilePath)); updatedDetails->append(newAvatar); // we have successfully processed this PHOTO property. *alreadyProcessed = true; }