diff --git a/src/akonadi-contacts/standardcontactformatter.cpp b/src/akonadi-contacts/standardcontactformatter.cpp index 5a00652a..4f5917ce 100644 --- a/src/akonadi-contacts/standardcontactformatter.cpp +++ b/src/akonadi-contacts/standardcontactformatter.cpp @@ -1,381 +1,381 @@ /* This file is part of Akonadi Contact. Copyright (c) 2010 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "standardcontactformatter.h" #include #include #include #include #include #include #include #include #include using namespace Akonadi; class Q_DECL_HIDDEN StandardContactFormatter::Private { public: Private() : displayQRcode(true) { } bool displayQRcode; }; StandardContactFormatter::StandardContactFormatter() : d(new Private()) { } StandardContactFormatter::~StandardContactFormatter() { delete d; } static int contactAge(const QDate &date) { QDate now = QDate::currentDate(); int age = now.year() - date.year(); if (date > now.addYears(-age)) { age--; } return age; } QString StandardContactFormatter::toHtml(HtmlForm form) const { KContacts::Addressee rawContact; const Akonadi::Item localItem = item(); if (localItem.isValid() && localItem.hasPayload()) { rawContact = localItem.payload(); } else { rawContact = contact(); } if (rawContact.isEmpty()) { return QString(); } // We'll be building a table to display the vCard in. // Each row of the table will be built using one of these strings for its HTML. // single data item: // %1 is the item name // %2 is the item value QString rowFmtStr1 = QStringLiteral( "" "%1\n" "%2\n" "\n" ); // data item plus additional icon(s): // %1 is the item name // %2 is the item value // %3 is the icon(s), each as a HTML tag QString rowFmtStr2 = QStringLiteral( "" "%1\n" "%2\n" "%3\n" "\n" ); // Build the table's rows here QString dynamicPart; // Birthday const QDate date = rawContact.birthday().date(); const int years = contactAge(date); if (date.isValid()) { dynamicPart += rowFmtStr1 .arg(KContacts::Addressee::birthdayLabel()) .arg(QLocale().toString(date) +QLatin1String("  ") + i18np("(One year old)", "(%1 years old)", years)); } // Phone Numbers int counter = 0; for (const KContacts::PhoneNumber &number : rawContact.phoneNumbers()) { QString dispLabel = number.typeLabel().replace(QLatin1Char(' '), QStringLiteral(" ")); QString dispValue = QStringLiteral("%2").arg(counter).arg(number.number().toHtmlEscaped()); if (number.type() & KContacts::PhoneNumber::Cell) { QString dispIcon = QStringLiteral("") .arg(counter) .arg(i18nc("@info:tooltip", "Send SMS")); dynamicPart += rowFmtStr2 .arg(dispLabel) .arg(dispValue) .arg(dispIcon); } else { dynamicPart += rowFmtStr1 .arg(dispLabel) .arg(dispValue); } ++counter; } // EMails for (const QString &email : rawContact.emails()) { const QString type = i18nc("a contact's email address", "Email"); const QString fullEmail = QString::fromLatin1(QUrl::toPercentEncoding(rawContact.fullEmail(email))); dynamicPart += rowFmtStr1.arg(type) .arg(QStringLiteral("%2") .arg(fullEmail, email)); } // Homepage if (rawContact.url().isValid()) { QString url = rawContact.url().url().url(); if (!url.startsWith(QLatin1String("http://")) && !url.startsWith(QLatin1String("https://"))) { url = QLatin1String("http://") + url; } url = KStringHandler::tagUrls(url.toHtmlEscaped()); dynamicPart += rowFmtStr1.arg(i18n("Homepage")).arg(url); } // Blog Feed const QString blog = rawContact.custom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("BlogFeed")); if (!blog.isEmpty()) { dynamicPart += rowFmtStr1.arg(i18n("Blog Feed")).arg(KStringHandler::tagUrls(blog.toHtmlEscaped())); } // Addresses counter = 0; for (const KContacts::Address &address : rawContact.addresses()) { QString formattedAddress; if (address.label().isEmpty()) { formattedAddress = address.formattedAddress().trimmed().toHtmlEscaped(); } else { formattedAddress = address.label().toHtmlEscaped(); } formattedAddress.replace(QRegularExpression(QStringLiteral("\n+")), QStringLiteral("
")); const QString url = QStringLiteral("\"%2\"/") .arg(counter) .arg(i18nc("@info:tooltip", "Show address on map")); counter++; dynamicPart += rowFmtStr2 .arg(KContacts::Address::typeLabel(address.type())) .arg(formattedAddress) .arg(url); } // Note QString notes; if (!rawContact.note().isEmpty()) { notes = rowFmtStr1.arg(i18n("Notes")).arg(rawContact.note().toHtmlEscaped().replace(QLatin1Char('\n'), QLatin1String("
"))); } // Custom Data QString customData; static QMap titleMap; if (titleMap.isEmpty()) { titleMap.insert(QStringLiteral("Department"), i18n("Department")); titleMap.insert(QStringLiteral("Profession"), i18n("Profession")); titleMap.insert(QStringLiteral("AssistantsName"), i18n("Assistant's Name")); titleMap.insert(QStringLiteral("ManagersName"), i18n("Manager's Name")); titleMap.insert(QStringLiteral("SpousesName"), i18nc("Wife/Husband/...", "Partner's Name")); titleMap.insert(QStringLiteral("Office"), i18n("Office")); titleMap.insert(QStringLiteral("IMAddress"), i18n("IM Address")); titleMap.insert(QStringLiteral("Anniversary"), i18n("Anniversary")); titleMap.insert(QStringLiteral("AddressBook"), i18n("Address Book")); const QMap tmpTitleMap = titleMap; QMap::const_iterator iterator = tmpTitleMap.constBegin(); - while (iterator != titleMap.constEnd()) { + while (iterator != tmpTitleMap.constEnd()) { titleMap.insert(iterator.key().toUpper(), iterator.value()); ++iterator; } } static QSet blacklistedKeys; if (blacklistedKeys.isEmpty()) { blacklistedKeys.insert(QStringLiteral("CRYPTOPROTOPREF")); blacklistedKeys.insert(QStringLiteral("OPENPGPFP")); blacklistedKeys.insert(QStringLiteral("SMIMEFP")); blacklistedKeys.insert(QStringLiteral("CRYPTOSIGNPREF")); blacklistedKeys.insert(QStringLiteral("CRYPTOENCRYPTPREF")); blacklistedKeys.insert(QStringLiteral("MailPreferedFormatting")); blacklistedKeys.insert(QStringLiteral("MailAllowToRemoteContent")); blacklistedKeys.insert(QStringLiteral("MAILPREFEREDFORMATTING")); blacklistedKeys.insert(QStringLiteral("MAILALLOWTOREMOTECONTENT")); } if (!rawContact.customs().empty()) { const QStringList customs = rawContact.customs(); for (QString custom : customs) { if (custom.startsWith(QLatin1String("KADDRESSBOOK-"))) { custom.remove(QStringLiteral("KADDRESSBOOK-X-")); custom.remove(QStringLiteral("KADDRESSBOOK-")); int pos = custom.indexOf(QLatin1Char(':')); QString key = custom.left(pos); QString value = custom.mid(pos + 1); // convert anniversary correctly if (key == QLatin1String("Anniversary") || key == QLatin1String("ANNIVERSARY")) { const QDateTime dateTime = QDateTime::fromString(value, Qt::ISODate); value = QLocale().toString(dateTime.date()); } else if (key == QLatin1String("BlogFeed") || key == QLatin1String("BLOGFEED")) { // blog is handled separated continue; } else if (blacklistedKeys.contains(key)) { continue; } // check whether we have a mapping for the title const QMap::ConstIterator keyIt = titleMap.constFind(key); bool needToEscape = true; if (keyIt != titleMap.constEnd()) { key = keyIt.value(); } else { // check whether it is a custom local field for (const QVariantMap &description : customFieldDescriptions()) { if (description.value(QStringLiteral("key")).toString() == key) { key = description.value(QStringLiteral("title")).toString(); const QString descriptionType = description.value(QStringLiteral("type")).toString(); if (descriptionType == QLatin1String("boolean")) { if (value == QLatin1String("true")) { value = i18nc("Boolean value", "yes"); } else { value = i18nc("Boolean value", "no"); } } else if (descriptionType == QLatin1String("date")) { const QDate date = QDate::fromString(value, Qt::ISODate); value = QLocale().toString(date, QLocale::ShortFormat); } else if (descriptionType == QLatin1String("time")) { const QTime time = QTime::fromString(value, Qt::ISODate); value = QLocale().toString(time); } else if (descriptionType == QLatin1String("datetime")) { const QDateTime dateTime = QDateTime::fromString(value, Qt::ISODate); value = QLocale().toString(dateTime, QLocale::ShortFormat); } else if (descriptionType == QLatin1String("url")) { value = KStringHandler::tagUrls(value.toHtmlEscaped()); needToEscape = false; } break; } } } if (needToEscape) { value = value.toHtmlEscaped(); } customData += rowFmtStr1.arg(key).arg(value); } } } // Assemble all parts QString role = rawContact.title(); if (role.isEmpty()) { role = rawContact.role(); } if (role.isEmpty()) { role = rawContact.custom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-Profession")); } QString strAddr = QStringLiteral( "
" "" "" "" "" // name "" "" "" // role "" "" "" // organization "") .arg(QStringLiteral("contact_photo")) .arg(rawContact.realName().toHtmlEscaped()) .arg(role.toHtmlEscaped()) .arg(rawContact.organization().toHtmlEscaped()); strAddr.append(dynamicPart); strAddr.append(notes); strAddr.append(customData); strAddr.append(QLatin1String("
" "" // image "%2
%3
%4
")); if (d->displayQRcode) { KConfig config(QStringLiteral("akonadi_contactrc")); KConfigGroup group(&config, QStringLiteral("View")); if (group.readEntry("QRCodes", true)) { strAddr.append(QString::fromLatin1( "

" "" "

" ) .arg(QStringLiteral("qrcode"))); } } strAddr.append(QLatin1String("
\n")); if (form == EmbeddableForm) { return strAddr; } const QString document = QStringLiteral( "" "" " " "" "" // text and background color "%3" // contact part "" "") .arg(KColorScheme(QPalette::Active, KColorScheme::View).foreground().color().name()) .arg(KColorScheme(QPalette::Active, KColorScheme::View).background().color().name()) .arg(strAddr); return document; } void StandardContactFormatter::setDisplayQRCode(bool show) { d->displayQRcode = show; } bool StandardContactFormatter::displayQRCode() const { return d->displayQRcode; }