File indexing completed on 2025-02-16 04:45:49
0001 /* 0002 This file is part of KAddressBook. 0003 0004 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "grantleecontactformatter.h" 0010 #include "contactgrantleewrapper.h" 0011 0012 #include <KContacts/Addressee> 0013 0014 #include <GrantleeTheme/GrantleeKi18nLocalizer> 0015 #include <GrantleeTheme/GrantleeTheme> 0016 #include <GrantleeTheme/GrantleeThemeEngine> 0017 #include <KTextTemplate/Context> 0018 #include <KTextTemplate/MetaType> 0019 #include <KTextTemplate/TemplateLoader> 0020 0021 #include <Akonadi/Item> 0022 0023 #include <KColorScheme> 0024 0025 #include <KConfigGroup> 0026 #include <KLocalizedString> 0027 #include <KStringHandler> 0028 0029 #include <QLocale> 0030 #include <QMetaProperty> 0031 #include <QSet> 0032 0033 using namespace KAddressBookGrantlee; 0034 0035 KTEXTTEMPLATE_BEGIN_LOOKUP(QUrl) 0036 if (property == QLatin1StringView("scheme")) { 0037 return object.scheme(); 0038 } else if (property == QLatin1StringView("path")) { 0039 return object.path(); 0040 } 0041 KTEXTTEMPLATE_END_LOOKUP 0042 0043 class KAddressBookGrantlee::GrantleeContactFormatterPrivate 0044 { 0045 public: 0046 GrantleeContactFormatterPrivate() 0047 { 0048 KConfig config(QStringLiteral("akonadi_contactrc")); 0049 KConfigGroup group(&config, QStringLiteral("View")); 0050 showQRCode = group.readEntry("QRCodes", true); 0051 mEngine = std::make_unique<GrantleeTheme::Engine>(); 0052 mTemplateLoader = QSharedPointer<KTextTemplate::FileSystemTemplateLoader>(new KTextTemplate::FileSystemTemplateLoader()); 0053 } 0054 0055 ~GrantleeContactFormatterPrivate() 0056 { 0057 mTemplateLoader.clear(); 0058 } 0059 0060 void changeGrantleePath(const QString &path) 0061 { 0062 mTemplateLoader->setTemplateDirs(QStringList() << path); 0063 mEngine->addTemplateLoader(mTemplateLoader); 0064 0065 mSelfcontainedTemplate = mEngine->loadByName(QStringLiteral("contact.html")); 0066 if (mSelfcontainedTemplate->error()) { 0067 mErrorMessage += mSelfcontainedTemplate->errorString() + QStringLiteral("<br>"); 0068 } 0069 0070 mEmbeddableTemplate = mEngine->loadByName(QStringLiteral("contact_embedded.html")); 0071 if (mEmbeddableTemplate->error()) { 0072 mErrorMessage += mEmbeddableTemplate->errorString() + QStringLiteral("<br>"); 0073 } 0074 } 0075 0076 QList<QObject *> mObjects; 0077 std::unique_ptr<GrantleeTheme::Engine> mEngine; 0078 QSharedPointer<KTextTemplate::FileSystemTemplateLoader> mTemplateLoader; 0079 KTextTemplate::Template mSelfcontainedTemplate; 0080 KTextTemplate::Template mEmbeddableTemplate; 0081 QString mErrorMessage; 0082 bool forceDisableQRCode = false; 0083 bool showQRCode = true; 0084 }; 0085 0086 GrantleeContactFormatter::GrantleeContactFormatter() 0087 : d(new GrantleeContactFormatterPrivate) 0088 { 0089 KTextTemplate::registerMetaType<QUrl>(); 0090 } 0091 0092 GrantleeContactFormatter::~GrantleeContactFormatter() = default; 0093 0094 void GrantleeContactFormatter::setAbsoluteThemePath(const QString &path) 0095 { 0096 d->changeGrantleePath(path); 0097 } 0098 0099 void GrantleeContactFormatter::setGrantleeTheme(const GrantleeTheme::Theme &theme) 0100 { 0101 d->changeGrantleePath(theme.absolutePath()); 0102 } 0103 0104 void GrantleeContactFormatter::setForceDisableQRCode(bool b) 0105 { 0106 d->forceDisableQRCode = b; 0107 } 0108 0109 bool GrantleeContactFormatter::forceDisableQRCode() const 0110 { 0111 return d->forceDisableQRCode; 0112 } 0113 0114 void GrantleeContactFormatter::setShowQRCode(bool b) 0115 { 0116 d->showQRCode = b; 0117 } 0118 0119 QString GrantleeContactFormatter::toHtml(HtmlForm form) const 0120 { 0121 if (!d->mErrorMessage.isEmpty()) { 0122 return d->mErrorMessage; 0123 } 0124 0125 KContacts::Addressee rawContact; 0126 const Akonadi::Item localItem = item(); 0127 if (localItem.isValid() && localItem.hasPayload<KContacts::Addressee>()) { 0128 rawContact = localItem.payload<KContacts::Addressee>(); 0129 } else { 0130 rawContact = contact(); 0131 } 0132 0133 if (rawContact.isEmpty()) { 0134 return {}; 0135 } 0136 0137 // Custom fields 0138 QVariantList customFields; 0139 QVariantList customFieldsUrl; 0140 static QSet<QString> blacklistedKeys = {QStringLiteral("CRYPTOPROTOPREF"), 0141 QStringLiteral("OPENPGPFP"), 0142 QStringLiteral("SMIMEFP"), 0143 QStringLiteral("CRYPTOSIGNPREF"), 0144 QStringLiteral("CRYPTOENCRYPTPREF"), 0145 QStringLiteral("Anniversary"), 0146 QStringLiteral("BlogFeed"), 0147 QStringLiteral("Profession"), 0148 QStringLiteral("Office"), 0149 QStringLiteral("ManagersName"), 0150 QStringLiteral("AssistantsName"), 0151 QStringLiteral("SpousesName"), 0152 QStringLiteral("IMAddress"), 0153 QStringLiteral("AddressBook"), 0154 QStringLiteral("MailPreferedFormatting"), 0155 QStringLiteral("MailAllowToRemoteContent"), 0156 QStringLiteral("MAILPREFEREDFORMATTING"), 0157 QStringLiteral("MAILALLOWTOREMOTECONTENT")}; 0158 0159 const auto customs = rawContact.customs(); 0160 for (QString custom : customs) { 0161 if (custom.startsWith(QLatin1StringView("KADDRESSBOOK-"))) { 0162 custom.remove(QStringLiteral("KADDRESSBOOK-X-")); 0163 custom.remove(QStringLiteral("KADDRESSBOOK-")); 0164 0165 int pos = custom.indexOf(QLatin1Char(':')); 0166 QString key = custom.left(pos); 0167 QString value = custom.mid(pos + 1); 0168 0169 if (blacklistedKeys.contains(key)) { 0170 continue; 0171 } 0172 0173 bool addUrl = false; 0174 // check whether it is a custom local field 0175 for (int i = 0; i < customFieldDescriptions().size(); ++i) { 0176 const QVariantMap description = customFieldDescriptions().at(i); 0177 if (description.value(QStringLiteral("key")).toString() == key) { 0178 key = description.value(QStringLiteral("title")).toString(); 0179 const QString descriptionType = description.value(QStringLiteral("type")).toString(); 0180 if (descriptionType == QLatin1StringView("boolean")) { 0181 if (value == QLatin1StringView("true")) { 0182 value = i18nc("Boolean value", "yes"); 0183 } else { 0184 value = i18nc("Boolean value", "no"); 0185 } 0186 } else if (descriptionType == QLatin1StringView("date")) { 0187 const QDate date = QDate::fromString(value, Qt::ISODate); 0188 value = QLocale().toString(date, QLocale::ShortFormat); 0189 } else if (descriptionType == QLatin1StringView("time")) { 0190 const QTime time = QTime::fromString(value, Qt::ISODate); 0191 value = QLocale::system().toString(time, QLocale::ShortFormat); 0192 } else if (descriptionType == QLatin1StringView("datetime")) { 0193 const QDateTime dateTime = QDateTime::fromString(value, Qt::ISODate); 0194 value = QLocale().toString(dateTime, QLocale::ShortFormat); 0195 } else if (descriptionType == QLatin1StringView("url")) { 0196 value = KStringHandler::tagUrls(value.toHtmlEscaped()); 0197 addUrl = true; 0198 } 0199 break; 0200 } 0201 } 0202 QVariantHash customFieldObject; 0203 customFieldObject.insert(QStringLiteral("title"), key); 0204 customFieldObject.insert(QStringLiteral("value"), value); 0205 0206 if (addUrl) { 0207 customFieldsUrl.append(customFieldObject); 0208 } else { 0209 customFields.append(customFieldObject); 0210 } 0211 } 0212 } 0213 0214 QVariantHash colorsObject; 0215 0216 colorsObject.insert(QStringLiteral("linkColor"), KColorScheme(QPalette::Active, KColorScheme::View).foreground().color().name()); 0217 0218 colorsObject.insert(QStringLiteral("textColor"), KColorScheme(QPalette::Active, KColorScheme::View).foreground().color().name()); 0219 0220 colorsObject.insert(QStringLiteral("backgroundColor"), KColorScheme(QPalette::Active, KColorScheme::View).background().color().name()); 0221 0222 QVariantHash mapping; 0223 mapping.insert(QStringLiteral("contact"), QVariant::fromValue(ContactGrantleeWrapper(rawContact))); 0224 mapping.insert(QStringLiteral("colors"), colorsObject); 0225 mapping.insert(QStringLiteral("customFields"), customFields); 0226 mapping.insert(QStringLiteral("customFieldsUrl"), customFieldsUrl); 0227 mapping.insert(QStringLiteral("hasqrcode"), !d->forceDisableQRCode && d->showQRCode); 0228 KTextTemplate::Context context(mapping); 0229 context.setLocalizer(d->mEngine->localizer()); 0230 0231 if (form == SelfcontainedForm) { 0232 return d->mSelfcontainedTemplate->render(&context); 0233 } else if (form == EmbeddableForm) { 0234 return d->mEmbeddableTemplate->render(&context); 0235 } else { 0236 return {}; 0237 } 0238 } 0239 0240 void GrantleeContactFormatter::setApplicationDomain(const QByteArray &domain) 0241 { 0242 d->mEngine->localizer()->setApplicationDomain(domain); 0243 }