1 /*
2    SPDX-FileCopyrightText: 2016-2021 Laurent Montel <montel@kde.org>
3 
4    SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "messagepartrenderermanager.h"
8 #include "messageviewer_debug.h"
9 #include <GrantleeTheme/GrantleeKi18nLocalizer>
10 #include <GrantleeTheme/GrantleeThemeEngine>
11 #include <KIconLoader>
12 #include <QStandardPaths>
13 
14 #include <gpgme++/decryptionresult.h>
15 #include <gpgme++/key.h>
16 #include <gpgme++/verificationresult.h>
17 
18 #include <QGpgME/Protocol>
19 
20 #include <grantlee/context.h>
21 #include <grantlee/engine.h>
22 #include <grantlee/metatype.h>
23 #include <grantlee/templateloader.h>
24 
25 #include <QGuiApplication>
26 Q_DECLARE_METATYPE(GpgME::DecryptionResult::Recipient)
27 Q_DECLARE_METATYPE(const QGpgME::Protocol *)
28 Q_DECLARE_METATYPE(GpgME::Key)
29 
30 // Read-only introspection of GpgME::DecryptionResult::Recipient object.
31 GRANTLEE_BEGIN_LOOKUP(GpgME::DecryptionResult::Recipient)
32 if (property == QLatin1String("keyID")) {
33     return QString::fromLatin1(object.keyID());
34 }
35 GRANTLEE_END_LOOKUP
36 // Read-only introspection of QGpgME::Protocol object.
37 namespace Grantlee
38 {
lookUp(const QGpgME::Protocol * const object,const QString & property)39 template<> inline QVariant TypeAccessor<const QGpgME::Protocol *>::lookUp(const QGpgME::Protocol *const object, const QString &property)
40 {
41     if (property == QLatin1String("name")) {
42         return object->name();
43     } else if (property == QLatin1String("displayName")) {
44         return object->displayName();
45     }
46     return QVariant();
47 }
48 }
49 
50 // Read-only introspection of std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key> object.
51 namespace Grantlee
52 {
53 template<>
54 inline QVariant
lookUp(std::pair<GpgME::DecryptionResult::Recipient,GpgME::Key> const & object,const QString & property)55 TypeAccessor<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key> &>::lookUp(std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key> const &object,
56                                                                                   const QString &property)
57 {
58     if (property == QLatin1String("keyID")) {
59         return QString::fromLatin1(object.first.keyID());
60     }
61     if (property == QLatin1String("id")) {
62         return QString::fromUtf8(object.second.userID(0).id());
63     }
64     if (property == QLatin1String("mainID")) {
65         return QString::fromLatin1(object.second.keyID());
66     }
67     return QVariant();
68 }
69 }
70 
71 namespace MessageViewer
72 {
73 class GlobalContext : public QObject
74 {
75     Q_OBJECT
76     Q_PROPERTY(QString dir READ layoutDirection CONSTANT)
77     Q_PROPERTY(int iconSize READ iconSize CONSTANT)
78 public:
GlobalContext(QObject * parent)79     explicit GlobalContext(QObject *parent)
80         : QObject(parent)
81     {
82     }
83 
layoutDirection() const84     QString layoutDirection() const
85     {
86         return QGuiApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr");
87     }
88 
iconSize() const89     int iconSize() const
90     {
91         return KIconLoader::global()->currentSize(KIconLoader::Desktop);
92     }
93 };
94 }
95 
96 using namespace MessageViewer;
97 
MessagePartRendererManager(QObject * parent)98 MessagePartRendererManager::MessagePartRendererManager(QObject *parent)
99     : QObject(parent)
100     , m_globalContext(new GlobalContext(this))
101 {
102     initializeRenderer();
103 }
104 
~MessagePartRendererManager()105 MessagePartRendererManager::~MessagePartRendererManager()
106 {
107     delete m_engine;
108 }
109 
self()110 MessagePartRendererManager *MessagePartRendererManager::self()
111 {
112     static MessagePartRendererManager s_self;
113     return &s_self;
114 }
115 
initializeRenderer()116 void MessagePartRendererManager::initializeRenderer()
117 {
118     Grantlee::registerMetaType<GpgME::DecryptionResult::Recipient>();
119     Grantlee::registerMetaType<const QGpgME::Protocol *>();
120     Grantlee::registerMetaType<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key>>();
121     m_engine = new GrantleeTheme::Engine;
122     const auto libraryPaths = QCoreApplication::libraryPaths();
123     for (const auto &p : libraryPaths) {
124         m_engine->addPluginPath(p + QStringLiteral("/messageviewer"));
125     }
126     m_engine->addDefaultLibrary(QStringLiteral("messageviewer_grantlee_extension"));
127     m_engine->localizer()->setApplicationDomain(QByteArrayLiteral("libmessageviewer"));
128 
129     auto loader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader());
130     loader->setTemplateDirs({QStringLiteral(":/")});
131     m_engine->addTemplateLoader(loader);
132 }
133 
loadByName(const QString & name)134 Grantlee::Template MessagePartRendererManager::loadByName(const QString &name)
135 {
136     Grantlee::Template t = m_engine->loadByName(name);
137     if (t->error()) {
138         qCWarning(MESSAGEVIEWER_LOG) << t->errorString() << ". Searched in subdir mimetreeparser/themes/default in these locations"
139                                      << QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
140     }
141     return t;
142 }
143 
createContext()144 Grantlee::Context MessagePartRendererManager::createContext()
145 {
146     Grantlee::Context c;
147 
148     // careful, m_engine->localizer() is actually a factory function!
149     auto localizer = m_engine->localizer();
150     localizer->setApplicationDomain(QByteArrayLiteral("libmessageviewer"));
151     c.setLocalizer(localizer);
152 
153     c.insert(QStringLiteral("global"), m_globalContext);
154     return c;
155 }
156 
157 #include "messagepartrenderermanager.moc"
158