File indexing completed on 2024-05-19 05:11:23

0001 /*
0002     SPDX-FileCopyrightText: 2007 Till Adam <adam@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "akonadi_serializer_addressee.h"
0008 
0009 #include <Akonadi/AbstractDifferencesReporter>
0010 #include <Akonadi/Item>
0011 
0012 #include "serializer_debug.h"
0013 #include <KContacts/Addressee>
0014 #include <KLocalizedString>
0015 #include <QIODevice>
0016 
0017 using namespace Akonadi;
0018 
0019 //// ItemSerializerPlugin interface
0020 
0021 // FIXME: these values map to Akonadi::ContactParts::Standard and
0022 // Akonadi::ContactParts::Lookup from AkonadiContact library. We don't use those
0023 // symbols here, because AkonadiContact library links to Qt5WebEngine, which when
0024 // loaded tries to initialize OpenGL. When this plugin gets loaded by Akonadi
0025 // from KRunner, it happens in a non-GUI thread, leading to a crash in Qt5WebEngine.
0026 #define CONTACTPART_STANDARD "CONTACT_STANDARD"
0027 #define CONTACTPART_LOOKUP "CONTACT_LOOKUP"
0028 
0029 bool SerializerPluginAddressee::deserialize(Item &item, const QByteArray &label, QIODevice &data, int version)
0030 {
0031     Q_UNUSED(version)
0032 
0033     KContacts::Addressee addr;
0034     if (label == Item::FullPayload) {
0035         addr = m_converter.parseVCard(data.readAll());
0036     } else if (label == CONTACTPART_STANDARD) {
0037         addr = m_converter.parseVCard(data.readAll());
0038 
0039         // remove pictures and sound
0040         addr.setPhoto(KContacts::Picture());
0041         addr.setLogo(KContacts::Picture());
0042         addr.setSound(KContacts::Sound());
0043     } else if (label == CONTACTPART_LOOKUP) {
0044         const KContacts::Addressee temp = m_converter.parseVCard(data.readAll());
0045 
0046         // copy only uid, name and email addresses
0047         addr.setUid(temp.uid());
0048         addr.setPrefix(temp.prefix());
0049         addr.setGivenName(temp.givenName());
0050         addr.setAdditionalName(temp.additionalName());
0051         addr.setFamilyName(temp.familyName());
0052         addr.setSuffix(temp.suffix());
0053         addr.setEmails(temp.emails());
0054     } else {
0055         return false;
0056     }
0057 
0058     if (!addr.isEmpty()) {
0059         item.setPayload<KContacts::Addressee>(addr);
0060     } else {
0061         qCWarning(AKONADI_SERIALIZER_CONTACT_LOG) << "Empty addressee object!";
0062     }
0063 
0064     return true;
0065 }
0066 
0067 void SerializerPluginAddressee::serialize(const Item &item, const QByteArray &label, QIODevice &data, int &version)
0068 {
0069     Q_UNUSED(version)
0070 
0071     if (label != Item::FullPayload && label != CONTACTPART_STANDARD && label != CONTACTPART_LOOKUP) {
0072         return;
0073     }
0074 
0075     if (!item.hasPayload<KContacts::Addressee>()) {
0076         return;
0077     }
0078 
0079     KContacts::Addressee addr;
0080     KContacts::Addressee temp;
0081 
0082     temp = item.payload<KContacts::Addressee>();
0083 
0084     if (label == Item::FullPayload) {
0085         addr = temp;
0086     } else if (label == CONTACTPART_STANDARD) {
0087         addr = temp;
0088 
0089         // remove pictures and sound
0090         addr.setPhoto(KContacts::Picture());
0091         addr.setLogo(KContacts::Picture());
0092         addr.setSound(KContacts::Sound());
0093     } else if (label == CONTACTPART_LOOKUP) {
0094         // copy only uid, name and email addresses
0095         addr.setUid(temp.uid());
0096         addr.setPrefix(temp.prefix());
0097         addr.setGivenName(temp.givenName());
0098         addr.setAdditionalName(temp.additionalName());
0099         addr.setFamilyName(temp.familyName());
0100         addr.setSuffix(temp.suffix());
0101         addr.setEmails(temp.emails());
0102     }
0103 
0104     data.write(m_converter.createVCard(addr));
0105 }
0106 
0107 //// DifferencesAlgorithmInterface interface
0108 
0109 static bool compareString(const QString &left, const QString &right)
0110 {
0111     if (left.isEmpty() && right.isEmpty()) {
0112         return true;
0113     } else {
0114         return left == right;
0115     }
0116 }
0117 
0118 static QString toString(const KContacts::PhoneNumber &phoneNumber)
0119 {
0120     return phoneNumber.number();
0121 }
0122 
0123 static QString toString(const KContacts::Address &address)
0124 {
0125     return address.toString();
0126 }
0127 
0128 static QString toString(const QString &value)
0129 {
0130     return value;
0131 }
0132 
0133 template<class T>
0134 static void compareList(Akonadi::AbstractDifferencesReporter *reporter, const QString &id, const QList<T> &left, const QList<T> &right)
0135 {
0136     for (int i = 0; i < left.count(); ++i) {
0137         if (!right.contains(left[i])) {
0138             reporter->addProperty(AbstractDifferencesReporter::AdditionalLeftMode, id, toString(left[i]), QString());
0139         }
0140     }
0141 
0142     for (int i = 0; i < right.count(); ++i) {
0143         if (!left.contains(right[i])) {
0144             reporter->addProperty(AbstractDifferencesReporter::AdditionalRightMode, id, QString(), toString(right[i]));
0145         }
0146     }
0147 }
0148 
0149 template<class T>
0150 static void compareVector(Akonadi::AbstractDifferencesReporter *reporter, const QString &id, const QList<T> &left, const QList<T> &right)
0151 {
0152     for (int i = 0; i < left.count(); ++i) {
0153         if (!right.contains(left[i])) {
0154             reporter->addProperty(AbstractDifferencesReporter::AdditionalLeftMode, id, toString(left[i]), QString());
0155         }
0156     }
0157 
0158     for (int i = 0; i < right.count(); ++i) {
0159         if (!left.contains(right[i])) {
0160             reporter->addProperty(AbstractDifferencesReporter::AdditionalRightMode, id, QString(), toString(right[i]));
0161         }
0162     }
0163 }
0164 
0165 void SerializerPluginAddressee::compare(Akonadi::AbstractDifferencesReporter *reporter, const Akonadi::Item &leftItem, const Akonadi::Item &rightItem)
0166 {
0167     Q_ASSERT(reporter);
0168     Q_ASSERT(leftItem.hasPayload<KContacts::Addressee>());
0169     Q_ASSERT(rightItem.hasPayload<KContacts::Addressee>());
0170 
0171     reporter->setLeftPropertyValueTitle(i18n("Changed Contact"));
0172     reporter->setRightPropertyValueTitle(i18n("Conflicting Contact"));
0173 
0174     const auto leftContact = leftItem.payload<KContacts::Addressee>();
0175     const auto rightContact = rightItem.payload<KContacts::Addressee>();
0176 
0177     if (!compareString(leftContact.uid(), rightContact.uid())) {
0178         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::uidLabel(), leftContact.uid(), rightContact.uid());
0179     }
0180 
0181     if (!compareString(leftContact.name(), rightContact.name())) {
0182         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::nameLabel(), leftContact.name(), rightContact.name());
0183     }
0184 
0185     if (!compareString(leftContact.formattedName(), rightContact.formattedName())) {
0186         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0187                               KContacts::Addressee::formattedNameLabel(),
0188                               leftContact.formattedName(),
0189                               rightContact.formattedName());
0190     }
0191 
0192     if (!compareString(leftContact.familyName(), rightContact.familyName())) {
0193         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0194                               KContacts::Addressee::familyNameLabel(),
0195                               leftContact.familyName(),
0196                               rightContact.familyName());
0197     }
0198 
0199     if (!compareString(leftContact.givenName(), rightContact.givenName())) {
0200         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0201                               KContacts::Addressee::givenNameLabel(),
0202                               leftContact.givenName(),
0203                               rightContact.givenName());
0204     }
0205 
0206     if (!compareString(leftContact.additionalName(), rightContact.additionalName())) {
0207         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0208                               KContacts::Addressee::additionalNameLabel(),
0209                               leftContact.additionalName(),
0210                               rightContact.additionalName());
0211     }
0212 
0213     if (!compareString(leftContact.prefix(), rightContact.prefix())) {
0214         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::prefixLabel(), leftContact.prefix(), rightContact.prefix());
0215     }
0216 
0217     if (!compareString(leftContact.suffix(), rightContact.suffix())) {
0218         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::suffixLabel(), leftContact.suffix(), rightContact.suffix());
0219     }
0220 
0221     if (!compareString(leftContact.nickName(), rightContact.nickName())) {
0222         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0223                               KContacts::Addressee::nickNameLabel(),
0224                               leftContact.nickName(),
0225                               rightContact.nickName());
0226     }
0227 
0228     if (leftContact.birthday() != rightContact.birthday()) {
0229         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0230                               KContacts::Addressee::birthdayLabel(),
0231                               leftContact.birthday().toString(),
0232                               rightContact.birthday().toString());
0233     }
0234 
0235     if (!compareString(leftContact.mailer(), rightContact.mailer())) {
0236         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::mailerLabel(), leftContact.mailer(), rightContact.mailer());
0237     }
0238 
0239     if (leftContact.timeZone() != rightContact.timeZone()) {
0240         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0241                               KContacts::Addressee::timeZoneLabel(),
0242                               leftContact.timeZone().toString(),
0243                               rightContact.timeZone().toString());
0244     }
0245 
0246     if (leftContact.geo() != rightContact.geo()) {
0247         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0248                               KContacts::Addressee::geoLabel(),
0249                               leftContact.geo().toString(),
0250                               rightContact.geo().toString());
0251     }
0252 
0253     if (!compareString(leftContact.title(), rightContact.title())) {
0254         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::titleLabel(), leftContact.title(), rightContact.title());
0255     }
0256 
0257     if (!compareString(leftContact.role(), rightContact.role())) {
0258         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::roleLabel(), leftContact.role(), rightContact.role());
0259     }
0260 
0261     if (!compareString(leftContact.organization(), rightContact.organization())) {
0262         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0263                               KContacts::Addressee::organizationLabel(),
0264                               leftContact.organization(),
0265                               rightContact.organization());
0266     }
0267 
0268     if (!compareString(leftContact.note(), rightContact.note())) {
0269         reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KContacts::Addressee::noteLabel(), leftContact.note(), rightContact.note());
0270     }
0271 
0272     if (!compareString(leftContact.productId(), rightContact.productId())) {
0273         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0274                               KContacts::Addressee::productIdLabel(),
0275                               leftContact.productId(),
0276                               rightContact.productId());
0277     }
0278 
0279     if (!compareString(leftContact.sortString(), rightContact.sortString())) {
0280         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0281                               KContacts::Addressee::sortStringLabel(),
0282                               leftContact.sortString(),
0283                               rightContact.sortString());
0284     }
0285 
0286     if (leftContact.secrecy() != rightContact.secrecy()) {
0287         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0288                               KContacts::Addressee::secrecyLabel(),
0289                               leftContact.secrecy().toString(),
0290                               rightContact.secrecy().toString());
0291     }
0292 
0293     if (leftContact.url() != rightContact.url()) {
0294         reporter->addProperty(AbstractDifferencesReporter::ConflictMode,
0295                               KContacts::Addressee::urlLabel(),
0296                               leftContact.url().url().toDisplayString(),
0297                               rightContact.url().url().toDisplayString());
0298     }
0299 
0300     compareList(reporter, i18n("Emails"), leftContact.emails(), rightContact.emails());
0301     compareVector(reporter, i18n("Phone Numbers"), leftContact.phoneNumbers(), rightContact.phoneNumbers());
0302     compareVector(reporter, i18n("Addresses"), leftContact.addresses(), rightContact.addresses());
0303 
0304     // TODO: logo/photo/custom entries
0305 }
0306 
0307 //// GidExtractorInterface
0308 
0309 QString SerializerPluginAddressee::extractGid(const Item &item) const
0310 {
0311     if (!item.hasPayload<KContacts::Addressee>()) {
0312         return {};
0313     }
0314     return item.payload<KContacts::Addressee>().uid();
0315 }
0316 
0317 #include "moc_akonadi_serializer_addressee.cpp"