Verified Commit 3113e628 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖

Move libkf5kaddressbookgrantlee to Akonadi-Contacts

This repo contain all the contact displaying stuff anyway, so it makes
sense that the Grantlee viewer is present here as well rather than
being in some other library.
parent bbede6f0
Pipeline #33957 failed with stage
in 68 minutes and 34 seconds
cmake_minimum_required(VERSION 3.5)
set(PIM_VERSION "5.15.40")
set(PIM_VERSION "5.15.41")
project(Akonadi-Contact VERSION ${PIM_VERSION})
......@@ -29,6 +29,9 @@ include(ECMQtDeclareLoggingCategory)
set(AKONADI_CONTACTS_VERSION ${PIM_VERSION})
set(KMIMELIB_VERSION "5.15.40")
set(AKONADI_VERSION "5.15.40")
set(LIBKLEO_LIB_VERSION "5.15.40")
set(GRANTLEETHEME_LIB_VERSION "5.15.40")
set(GRANTLEE_LIB_VERSION "5.2")
set(QT_REQUIRED_VERSION "5.13.0")
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Widgets Test)
......@@ -49,12 +52,15 @@ find_package(KF5Contacts ${KF5_MIN_VERSION} CONFIG REQUIRED)
find_package(KF5Mime ${KMIMELIB_VERSION} CONFIG REQUIRED)
find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED)
find_package(KF5Libkleo ${LIBKLEO_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5GrantleeTheme ${GRANTLEETHEME_LIB_VERSION} CONFIG REQUIRED)
find_package(Grantlee5 ${GRANTLEE_LIB_VERSION} CONFIG REQUIRED)
########### Targets ###########
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050f00)
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050e00)
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054A00)
add_definitions(-DQT_NO_FOREACH)
......
......@@ -65,12 +65,21 @@ set(akonadicontact_recipientpicker_SRCS
recipientspicker/recipientspickerwidget.cpp
)
set(akonadicontact_grantlee_SRCS
grantlee/contactgrantleewrapper.cpp
grantlee/grantleecontactformatter.cpp
grantlee/grantleecontactgroupformatter.cpp
grantlee/grantleeprint.cpp
grantlee/grantleecontactviewer.cpp
)
set(akonadicontact_LIB_SRC
${akonadicontact_recipientpicker_SRCS}
${akonadicontact_customfieldseditor_SRCS}
${akonadicontact_attributes_SRCS}
${akonadicontact_job_SRCS}
${akonadicontact_grantlee_SRCS}
abstractcontactformatter.cpp
abstractcontactgroupformatter.cpp
collectionfiltermodel.cpp
......@@ -114,14 +123,8 @@ ecm_qt_declare_logging_category(akonadicontact_LIB_SRC HEADER akonadi_contact_de
EXPORT AKONADICONTACTS
)
set(akonadicontact_LIB_SRC
${akonadicontact_LIB_SRC}
)
ki18n_wrap_ui(akonadicontact_LIB_SRC contactgroupeditor.ui)
add_library(KF5AkonadiContact ${akonadicontact_LIB_SRC})
generate_export_header(KF5AkonadiContact BASE_NAME akonadi-contact)
......@@ -138,6 +141,7 @@ target_link_libraries(KF5AkonadiContact
KF5::Contacts
KF5::AkonadiWidgets
Qt5::Widgets
KF5::GrantleeTheme
PRIVATE
KF5::ConfigCore
KF5::ConfigWidgets
......@@ -152,6 +156,8 @@ target_link_libraries(KF5AkonadiContact
KF5::XmlGui
KF5::ContactEditor
KF5::Prison
Grantlee5::Templates
KF5::Libkleo
)
......@@ -228,10 +234,24 @@ ecm_generate_headers(AkonadiContact_CamelCase_HEADERS
PREFIX Akonadi/Contact
)
ecm_generate_headers(AkonadiContactGrantlee_CamelCase_HEADERS
HEADER_NAMES
ContactGrantleeWrapper
GrantleeContactFormatter
GrantleeContactGroupFormatter
GrantleePrint
GrantleeContactViewer
REQUIRED_HEADERS AkonadiContactGrantlee_HEADERS
RELATIVE grantlee
PREFIX Akonadi/Contact
)
install( FILES
${AkonadiContact_CamelCase_HEADERS}
${AkonadiContactJob_CamelCase_HEADERS}
${AkonadiContactRecipients_CamelCase_HEADERS}
${AkonadiContactGrantlee_CamelCase_HEADERS}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/Akonadi/Contact COMPONENT Devel
)
......@@ -239,6 +259,7 @@ install( FILES
${AkonadiContact_HEADERS}
${AkonadiContactJob_HEADERS}
${AkonadiContactRecipients_HEADERS}
${AkonadiContactGrantlee_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/akonadi-contact_export.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/akonadi/contact COMPONENT Devel
)
......
include(ECMMarkAsTest)
include(ECMAddTests)
find_package(Qt5Test CONFIG REQUIRED)
......@@ -18,3 +19,7 @@ endmacro()
########### next target ###############
add_akonadi_contact_demo(contactmetadataattributetest.cpp)
ecm_add_test(grantleeprinttest.cpp
LINK_LIBRARIES KF5::AkonadiContact Qt5::Test KF5::Contacts
)
/*
SPDX-FileCopyrightText: 2015-2020 Laurent Montel <montel@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "grantleeprinttest.h"
#include "grantlee/grantleeprint.h"
#include <QTest>
GrantleePrintTest::GrantleePrintTest(QObject *parent)
: QObject(parent)
{
}
GrantleePrintTest::~GrantleePrintTest()
{
}
void GrantleePrintTest::shouldReturnEmptyStringWhenNotContentAndNoContacts()
{
KAddressBookGrantlee::GrantleePrint grantleePrint;
KContacts::Addressee::List lst;
QVERIFY(grantleePrint.contactsToHtml(lst).isEmpty());
}
void GrantleePrintTest::shouldReturnEmptyStringWhenAddContentWithoutContacts()
{
KAddressBookGrantlee::GrantleePrint grantleePrint;
grantleePrint.setTemplateContent(QStringLiteral("foo"));
KContacts::Addressee::List lst;
QVERIFY(grantleePrint.contactsToHtml(lst).isEmpty());
}
void GrantleePrintTest::shouldReturnStringWhenAddContentAndContacts()
{
KAddressBookGrantlee::GrantleePrint grantleePrint;
grantleePrint.setTemplateContent(QStringLiteral("foo"));
KContacts::Addressee::List lst;
KContacts::Addressee address;
address.setName(QStringLiteral("foo1"));
address.insertEmail(QStringLiteral("foo@kde.org"), true);
lst << address;
QCOMPARE(grantleePrint.contactsToHtml(lst), QStringLiteral("foo"));
}
void GrantleePrintTest::shouldReturnEmails()
{
KAddressBookGrantlee::GrantleePrint grantleePrint;
KContacts::Addressee::List lst;
KContacts::Addressee address;
address.setName(QStringLiteral("foo1"));
address.insertEmail(QStringLiteral("foo@kde.org"), true);
lst << address;
grantleePrint.setTemplateContent(QStringLiteral("{% if contacts %}{% for contact in contacts %}{% if contact.name %}{{ contact.name }}{% endif %}{% endfor %}{% endif %}"));
QCOMPARE(grantleePrint.contactsToHtml(lst), QStringLiteral("foo1"));
}
void GrantleePrintTest::shouldDisplayContactInfo_data()
{
QTest::addColumn<QString>("variable");
QTest::addColumn<QString>("result");
QTest::newRow("name") << QStringLiteral("name") << QStringLiteral("foo1");
QTest::newRow("organization") << QStringLiteral("organization") << QStringLiteral("kde");
QTest::newRow("note") << QStringLiteral("note") << QStringLiteral("foo-note");
QTest::newRow("title") << QStringLiteral("title") << QStringLiteral("foo-title");
QTest::newRow("nickName") << QStringLiteral("nickName") << QStringLiteral("foo-nickname");
QTest::newRow("familyName") << QStringLiteral("familyName") << QStringLiteral("foo-familyname");
QTest::newRow("role") << QStringLiteral("role") << QStringLiteral("foo-role");
QTest::newRow("suffix") << QStringLiteral("suffix") << QStringLiteral("foo-suffix");
QTest::newRow("prefix") << QStringLiteral("prefix") << QStringLiteral("foo-prefix");
QTest::newRow("department") << QStringLiteral("department") << QStringLiteral("foo-department");
QTest::newRow("office") << QStringLiteral("office") << QStringLiteral("foo-office");
QTest::newRow("profesion") << QStringLiteral("profession") << QStringLiteral("foo-profession");
QTest::newRow("manager") << QStringLiteral("managersName") << QStringLiteral("foo-managersname");
QTest::newRow("assistant") << QStringLiteral("assistantsName") << QStringLiteral("foo-assistantsname");
QTest::newRow("spouse") << QStringLiteral("spousesName") << QStringLiteral("foo-spousesname");
QTest::newRow("givenname") << QStringLiteral("givenName") << QStringLiteral("foo-givenname");
QTest::newRow("additionalname") << QStringLiteral("additionalName") << QStringLiteral("foo-additionalname");
}
void GrantleePrintTest::shouldDisplayContactInfo()
{
QFETCH(QString, variable);
QFETCH(QString, result);
KAddressBookGrantlee::GrantleePrint grantleePrint;
KContacts::Addressee::List lst;
KContacts::Addressee address;
address.setGivenName(QStringLiteral("foo-givenname"));
address.setAdditionalName(QStringLiteral("foo-additionalname"));
address.setName(QStringLiteral("foo1"));
address.insertEmail(QStringLiteral("foo@kde.org"), true);
address.setOrganization(QStringLiteral("kde"));
address.insertLang(KContacts::Lang(QStringLiteral("fr")));
address.setNote(QStringLiteral("foo-note"));
address.setTitle(QStringLiteral("foo-title"));
address.setNickName(QStringLiteral("foo-nickname"));
address.setFamilyName(QStringLiteral("foo-familyname"));
address.setRole(QStringLiteral("foo-role"));
address.setSuffix(QStringLiteral("foo-suffix"));
address.setPrefix(QStringLiteral("foo-prefix"));
address.setDepartment(QStringLiteral("foo-department"));
address.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-Office"), QStringLiteral("foo-office"));
address.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-Profession"), QStringLiteral("foo-profession"));
address.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-Office"), QStringLiteral("foo-office"));
address.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-ManagersName"), QStringLiteral("foo-managersname"));
address.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-AssistantsName"), QStringLiteral("foo-assistantsname"));
address.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-SpousesName"), QStringLiteral("foo-spousesname"));
lst << address;
grantleePrint.setTemplateContent(QStringLiteral("{% if contacts %}{% for contact in contacts %}{% if contact.%1 %}{{ contact.%1 }}{% endif %}{% endfor %}{% endif %}").arg(variable));
QCOMPARE(grantleePrint.contactsToHtml(lst), result);
}
QTEST_MAIN(GrantleePrintTest)
/*
SPDX-FileCopyrightText: 2015-2020 Laurent Montel <montel@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef GRANTLEEPRINTTEST_H
#define GRANTLEEPRINTTEST_H
#include <QObject>
class GrantleePrintTest : public QObject
{
Q_OBJECT
public:
explicit GrantleePrintTest(QObject *parent = nullptr);
~GrantleePrintTest();
private Q_SLOTS:
void shouldReturnEmptyStringWhenNotContentAndNoContacts();
void shouldReturnEmptyStringWhenAddContentWithoutContacts();
void shouldReturnStringWhenAddContentAndContacts();
void shouldReturnEmails();
void shouldDisplayContactInfo_data();
void shouldDisplayContactInfo();
};
#endif // GRANTLEEPRINTTEST_H
/*
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "contactgrantleewrapper.h"
#include <Libkleo/Enum>
#include <KLocalizedString>
#include <QBuffer>
#include <QImage>
#include <QLocale>
using namespace KAddressBookGrantlee;
static_assert(sizeof(KContacts::Addressee) == sizeof(KAddressBookGrantlee::ContactGrantleeWrapper), "Grantlee wrapper must not have member variables to prevent slicing issues");
ContactGrantleeWrapper::ContactGrantleeWrapper() = default;
ContactGrantleeWrapper::ContactGrantleeWrapper(const KContacts::Addressee& addr)
: KContacts::Addressee(addr)
{
}
QString ContactGrantleeWrapper::addressBookLabel() const
{
return i18n("Address Book");
}
QString ContactGrantleeWrapper::anniversaryLabel() const
{
return i18n("Anniversary");
}
QString ContactGrantleeWrapper::assistantLabel() const
{
return i18n("Assistant's Name");
}
QString ContactGrantleeWrapper::managerLabel() const
{
return i18n("Manager's Name");
}
QString ContactGrantleeWrapper::officeLabel() const
{
return i18n("Office");
}
QString ContactGrantleeWrapper::professionLabel() const
{
return i18n("Profession");
}
QString ContactGrantleeWrapper::spouseLabel() const
{
return i18n("Partner's Name");
}
QString ContactGrantleeWrapper::addressBookName() const
{
return custom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("AddressBook"));
}
int ContactGrantleeWrapper::age() const
{
QDate now = QDate::currentDate();
int age = now.year() - birthday().date().year();
if (birthday().date() > now.addYears(-age)) {
age--;
}
return age;
}
QString ContactGrantleeWrapper::cryptoPreference() const
{
return Kleo::encryptionPreferenceToLabel(Kleo::stringToEncryptionPreference(custom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("CRYPTOENCRYPTPREF"))));
}
QString ContactGrantleeWrapper::signaturePreference() const
{
return Kleo::signingPreferenceToLabel(Kleo::stringToSigningPreference(custom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("CRYPTOSIGNPREF"))));
}
static QString imgToDataUrl(const QImage &image)
{
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
return QStringLiteral("data:image/%1;base64,%2").arg(QStringLiteral("PNG"), QString::fromLatin1(ba.toBase64()));
}
QString ContactGrantleeWrapper::logoImgElement() const
{
if (logo().isEmpty()) {
return {};
}
return QStringLiteral("<img src=\"%1\" width=\"%2\" height=\"%3\"> &nbsp;").arg(imgToDataUrl(logo().data()), QString::number(60), QString::number(60));
}
QString ContactGrantleeWrapper::photoImgElement() const
{
if (photo().isEmpty()) {
return {};
}
return QStringLiteral("<img src=\"%1\" width=\"%2\" height=\"%3\"> &nbsp;").arg(imgToDataUrl(photo().data()), QString::number(60), QString::number(60));
}
QString ContactGrantleeWrapper::formattedBirthday() const
{
return QLocale().toString(birthday().date());
}
QString ContactGrantleeWrapper::formattedAnniversary() const
{
return QLocale().toString(anniversary());
}
#include "moc_contactgrantleewrapper.cpp"
/*
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef AKONADICONTACTS_CONTACTGRANTLEEWRAPPER_H
#define AKONADICONTACTS_CONTACTGRANTLEEWRAPPER_H
#include <KContacts/Addressee>
namespace KAddressBookGrantlee {
/**
* Additional properties for the KContacts::Addressee Grantlee model.
*/
class ContactGrantleeWrapper : public KContacts::Addressee
{
Q_GADGET
// ### those probably should eventually become i18n calls in the template itself
Q_PROPERTY(QString addressBookLabel READ addressBookLabel)
Q_PROPERTY(QString anniversaryLabel READ anniversaryLabel)
Q_PROPERTY(QString assistantLabel READ assistantLabel)
Q_PROPERTY(QString birthdayLabel READ birthdayLabel)
Q_PROPERTY(QString departmentLabel READ departmentLabel)
Q_PROPERTY(QString noteLabel READ noteLabel)
Q_PROPERTY(QString managerLabel READ managerLabel)
Q_PROPERTY(QString officeLabel READ officeLabel)
Q_PROPERTY(QString professionLabel READ professionLabel)
Q_PROPERTY(QString spouseLabel READ spouseLabel)
Q_PROPERTY(QString addressBookName READ addressBookName)
Q_PROPERTY(int age READ age)
Q_PROPERTY(QString cryptoPreference READ cryptoPreference)
Q_PROPERTY(QString signaturePreference READ signaturePreference)
// ### this shouldn't be returning assembled HTML, that's a job for Grantlee
Q_PROPERTY(QString photo READ photoImgElement)
Q_PROPERTY(QString logo READ logoImgElement)
// ### those two would be unnecessary if we had a proper way for formatting dates in Grantlee
Q_PROPERTY(QString formattedBirthday READ formattedBirthday)
Q_PROPERTY(QString formattedAnniversary READ formattedAnniversary)
public:
ContactGrantleeWrapper();
ContactGrantleeWrapper(const KContacts::Addressee &addr);
private:
QString addressBookLabel() const;
QString anniversaryLabel() const;
QString assistantLabel() const;
QString managerLabel() const;
QString officeLabel() const;
QString professionLabel() const;
QString spouseLabel() const;
QString addressBookName() const;
int age() const;
QString cryptoPreference() const;
QString signaturePreference() const;
QString photoImgElement() const;
QString logoImgElement() const;
QString formattedBirthday() const;
QString formattedAnniversary() const;
QVariantList imAddresses() const;
};
}
Q_DECLARE_METATYPE(KAddressBookGrantlee::ContactGrantleeWrapper)
#endif // KADDRESSBOOKGRANTLEE_CONTACTGRANTLEEWRAPPER_H
/*
This file is part of KAddressBook.
SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "grantleecontactformatter.h"
#include "contactgrantleewrapper.h"
#include <KContacts/Addressee>
#include <GrantleeTheme/GrantleeThemeEngine>
#include <GrantleeTheme/GrantleeKi18nLocalizer>
#include <GrantleeTheme/GrantleeTheme>
#include <grantlee/context.h>
#include <grantlee/metatype.h>
#include <grantlee/templateloader.h>
#include <AkonadiCore/Item>
#include <KColorScheme>
#include <KStringHandler>
#include <KConfigGroup>
#include <KLocalizedString>
#include <QLocale>
#include <QMetaProperty>
#include <QRegularExpression>
#include <QSet>
using namespace KAddressBookGrantlee;
// Grantlee has no Q_GADGET support yet
#define GRANTLEE_MAKE_GADGET(Class) \
GRANTLEE_BEGIN_LOOKUP(Class) \
const auto idx = Class::staticMetaObject.indexOfProperty(property.toUtf8().constData()); \
if (idx < 0) { \
return {};} \
const auto mp = Class::staticMetaObject.property(idx); \
return mp.readOnGadget(&object); \
GRANTLEE_END_LOOKUP
GRANTLEE_MAKE_GADGET(KContacts::Address)
GRANTLEE_MAKE_GADGET(KContacts::Email)
GRANTLEE_MAKE_GADGET(KContacts::Impp)
GRANTLEE_MAKE_GADGET(KContacts::PhoneNumber)
GRANTLEE_MAKE_GADGET(KContacts::ResourceLocatorUrl)
GRANTLEE_MAKE_GADGET(KAddressBookGrantlee::ContactGrantleeWrapper)
GRANTLEE_BEGIN_LOOKUP(QUrl)
if (property == QLatin1String("scheme")) {
return object.scheme();
} else if (property == QLatin1String("path")) {
return object.path();
}
GRANTLEE_END_LOOKUP
class Q_DECL_HIDDEN GrantleeContactFormatter::Private
{
public:
Private()
{
KConfig config(QStringLiteral("akonadi_contactrc"));
KConfigGroup group(&config, QStringLiteral("View"));
showQRCode = group.readEntry("QRCodes", true);
mEngine.reset(new GrantleeTheme::Engine);
mTemplateLoader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader());
}
~Private()
{
mTemplateLoader.clear();
}
void changeGrantleePath(const QString &path)
{
mTemplateLoader->setTemplateDirs(QStringList() << path);
mEngine->addTemplateLoader(mTemplateLoader);
mSelfcontainedTemplate = mEngine->loadByName(QStringLiteral("contact.html"));
if (mSelfcontainedTemplate->error()) {
mErrorMessage += mSelfcontainedTemplate->errorString() + QStringLiteral("<br>");
}
mEmbeddableTemplate = mEngine->loadByName(QStringLiteral("contact_embedded.html"));
if (mEmbeddableTemplate->error()) {
mErrorMessage += mEmbeddableTemplate->errorString() + QStringLiteral("<br>");
}
}
QVector<QObject *> mObjects;
std::unique_ptr<GrantleeTheme::Engine> mEngine;
QSharedPointer<Grantlee::FileSystemTemplateLoader> mTemplateLoader;
Grantlee::Template mSelfcontainedTemplate;
Grantlee::Template mEmbeddableTemplate;
QString mErrorMessage;
bool forceDisableQRCode = false;
bool showQRCode = true;
};
GrantleeContactFormatter::GrantleeContactFormatter()
: d(new Private)
{
Grantlee::registerMetaType<KContacts::Address>();
Grantlee::registerMetaType<KContacts::Email>();
Grantlee::registerMetaType<KContacts::Impp>();
Grantlee::registerMetaType<KContacts::PhoneNumber>();
Grantlee::registerMetaType<KContacts::ResourceLocatorUrl>();
<