Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 599a2275 authored by Volker Krause's avatar Volker Krause

Add a Grantlee callback tag for nesting templates

Summary:
This allows us to write continuously to one single stream rather than
buffering the nested content first.

So far only used for encapsulated messages, all other usages have yet to
be ported.

Reviewers: knauss

Reviewed By: knauss

Subscribers: #kde_pim

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D8126
parent 30776ba7
add_definitions( -DQT_NO_CAST_FROM_ASCII )
add_definitions( -DQT_NO_CAST_TO_ASCII )
add_definitions(-DTRANSLATION_DOMAIN=\"libmessageviewer\")
add_subdirectory(messagepartthemes/grantlee)
# KCFG files:
# The main messageviewer.kcfg is configured by CMake and put in the build directory.
......
......@@ -56,9 +56,14 @@
#include <grantlee/templateloader.h>
#include <grantlee/template.h>
#include <functional>
using namespace MimeTreeParser;
using namespace MessageViewer;
typedef std::function<void(Grantlee::OutputStream *stream)> GrantleeCallback;
Q_DECLARE_METATYPE(GrantleeCallback)
Q_DECLARE_METATYPE(GpgME::DecryptionResult::Recipient)
Q_DECLARE_METATYPE(const QGpgME::Protocol *)
......@@ -373,9 +378,8 @@ void DefaultRendererPrivate::render(const EncapsulatedRfc822MessagePart::Ptr &mp
if (!mp->hasSubParts()) {
return;
}
Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral(
":/encapsulatedrfc822messagepart.html"));
Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext();
Grantlee::Template t = MessagePartRendererManager::self()->loadByName(QStringLiteral(":/encapsulatedrfc822messagepart.html"));
Grantlee::Context c = MessagePartRendererManager::self()->createContext();
QObject block;
c.insert(QStringLiteral("block"), &block);
......@@ -383,11 +387,9 @@ void DefaultRendererPrivate::render(const EncapsulatedRfc822MessagePart::Ptr &mp
mp->mOtp->nodeHelper()->asHREF(mp->mMessage.data(), QStringLiteral("body")));
c.insert(QStringLiteral("msgHeader"), mp->source()->createMessageHeader(mp->mMessage.data()));
{
auto _htmlWriter = QSharedPointer<CacheHtmlWriter>(new CacheHtmlWriter(htmlWriter));
renderSubParts(mp, _htmlWriter.data());
c.insert(QStringLiteral("content"), _htmlWriter->html());
}
c.insert(QStringLiteral("content"), QVariant::fromValue<GrantleeCallback>([this, mp, htmlWriter](Grantlee::OutputStream*) {
renderSubParts(mp, htmlWriter);
}));
HTMLBlock::Ptr aBlock;
if (mp->isAttachment()) {
......@@ -455,22 +457,17 @@ void DefaultRendererPrivate::renderEncrypted(const EncryptedMessagePart::Ptr &mp
QObject block;
if (node || mp->hasSubParts()) {
auto _htmlWriter = QSharedPointer<CacheHtmlWriter>(new CacheHtmlWriter(mOldWriter));
{
c.insert(QStringLiteral("content"), QVariant::fromValue<GrantleeCallback>([this, mp, htmlWriter](Grantlee::OutputStream*) {
HTMLBlock::Ptr rBlock;
if (node && mp->isRoot()) {
rBlock = HTMLBlock::Ptr(new RootBlock(_htmlWriter.data()));
if (mp->content() && mp->isRoot()) {
rBlock = HTMLBlock::Ptr(new RootBlock(htmlWriter));
}
renderSubParts(mp, _htmlWriter.data());
}
c.insert(QStringLiteral("content"), _htmlWriter->html());
renderSubParts(mp, htmlWriter);
}));
} else if (!metaData.inProgress) {
CacheHtmlWriter nestedWriter(htmlWriter);
if (renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, &nestedWriter)) {
c.insert(QStringLiteral("content"), nestedWriter.html());
} else {
c.insert(QStringLiteral("content"), QString());
}
c.insert(QStringLiteral("content"), QVariant::fromValue<GrantleeCallback>([this, mp, htmlWriter](Grantlee::OutputStream*) {
renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, htmlWriter);
}));
}
c.insert(QStringLiteral("cryptoProto"), QVariant::fromValue(mp->mCryptoProto));
......@@ -508,22 +505,17 @@ void DefaultRendererPrivate::renderSigned(const SignedMessagePart::Ptr &mp, Html
QObject block;
if (node) {
auto _htmlWriter = QSharedPointer<CacheHtmlWriter>(new CacheHtmlWriter(htmlWriter));
{
c.insert(QStringLiteral("content"), QVariant::fromValue<GrantleeCallback>([this, mp, htmlWriter](Grantlee::OutputStream*) {
HTMLBlock::Ptr rBlock;
if (mp->isRoot()) {
rBlock = HTMLBlock::Ptr(new RootBlock(_htmlWriter.data()));
rBlock = HTMLBlock::Ptr(new RootBlock(htmlWriter));
}
renderSubParts(mp, _htmlWriter.data());
}
c.insert(QStringLiteral("content"), _htmlWriter->html());
renderSubParts(mp, htmlWriter);
}));
} else if (!metaData.inProgress) {
CacheHtmlWriter nestedWriter(htmlWriter);
if (renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, &nestedWriter)) {
c.insert(QStringLiteral("content"), nestedWriter.html());
} else {
c.insert(QStringLiteral("content"), QString());
}
c.insert(QStringLiteral("content"), QVariant::fromValue<GrantleeCallback>([this, mp, htmlWriter](Grantlee::OutputStream*) {
renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, htmlWriter);
}));
}
c.insert(QStringLiteral("cryptoProto"), QVariant::fromValue(cryptoProto));
......
......@@ -105,6 +105,9 @@ void MessagePartRendererManager::initializeRenderer()
Grantlee::registerMetaType<GpgME::DecryptionResult::Recipient>();
Grantlee::registerMetaType<const QGpgME::Protocol *>();
m_engine = new GrantleeTheme::Engine;
foreach (const auto &p, QCoreApplication::libraryPaths())
m_engine->addPluginPath(p + QStringLiteral("/messageviewer"));
m_engine->addDefaultLibrary(QStringLiteral("messageviewer_grantlee_extension"));
m_engine->localizer()->setApplicationDomain(QByteArrayLiteral("libmessageviewer"));
auto loader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(
......
......@@ -11,7 +11,7 @@
<tr class="rfc822B">
<td>
{{msgHeader|safe}}
{{content|safe}}
{% callback content %}
</td>
</tr>
<tr class="rfc822H">
......
......@@ -26,7 +26,7 @@
<tr class="encrB">
<td>
{% if block.isDecryptable %}
{{content|safe}}
{% callback content %}
{% else %}
<div style="font-size:x-large; text-align:center; padding:20pt;">
{% if block.noSecKey %}
......
......@@ -160,7 +160,7 @@
</td>
</tr>
<tr class="{{block.signClass}}B">
<td>{{content|safe}}</td>
<td>{% callback content %}</td>
</tr>
<tr class="{{block.signClass}}H">
<td dir="{{global.dir}}">{% i18n "End of signed message" %}</td>
......
add_library(messageviewer_grantlee_extension MODULE grantleeextension.cpp)
target_link_libraries(messageviewer_grantlee_extension Grantlee5::Templates)
install(TARGETS messageviewer_grantlee_extension DESTINATION ${KDE_INSTALL_PLUGINDIR}/messageviewer/grantlee/5.0)
/*
Copyright (c) 2017 Volker Krause <vkrause@kde.org>
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 "grantleeextension.h"
#include <grantlee/exception.h>
#include <grantlee/parser.h>
#include <QDebug>
#include <functional>
using namespace MessageViewer;
typedef std::function<void(Grantlee::OutputStream *stream)> GrantleeCallback;
Q_DECLARE_METATYPE(GrantleeCallback)
CallbackTag::CallbackTag(const QString &name, QObject* parent)
: Grantlee::Node(parent)
, m_name(name)
{
}
void CallbackTag::render(Grantlee::OutputStream *stream, Grantlee::Context *context) const
{
auto cb = context->lookup(m_name).value<GrantleeCallback>();
if (cb)
cb(stream);
}
Grantlee::Node* CallbackTagFactory::getNode(const QString &tagContent, Grantlee::Parser *parser) const
{
auto expr = tagContent.split(QLatin1Char(' '), QString::SkipEmptyParts);
if (expr.size() != 2) {
return nullptr;
}
return new CallbackTag(expr.at(1), parser);
}
GrantleeTagLibrary::GrantleeTagLibrary(QObject* parent)
: QObject(parent)
{
}
QHash<QString, Grantlee::AbstractNodeFactory*> GrantleeTagLibrary::nodeFactories(const QString &name)
{
Q_UNUSED(name);
QHash<QString, Grantlee::AbstractNodeFactory*> nodeFactories;
nodeFactories.insert(QStringLiteral("callback"), new CallbackTagFactory());
return nodeFactories;
}
/*
Copyright (c) 2017 Volker Krause <vkrause@kde.org>
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.
*/
#ifndef MESSAGEVIEWER_GRANTLEEEXTENSION_H
#define MESSAGEVIEWER_GRANTLEEEXTENSION_H
#include <grantlee/node.h>
#include <grantlee/taglibraryinterface.h>
#include <QObject>
namespace MessageViewer {
class CallbackTag : public Grantlee::Node
{
Q_OBJECT
public:
explicit CallbackTag(const QString &name, QObject *parent = nullptr);
void render(Grantlee::OutputStream *stream, Grantlee::Context *context) const override;
private:
QString m_name;
};
class CallbackTagFactory : public Grantlee::AbstractNodeFactory
{
Q_OBJECT
public:
Grantlee::Node *getNode(const QString &tagContent, Grantlee::Parser *parser) const override;
};
class GrantleeTagLibrary : public QObject, public Grantlee::TagLibraryInterface
{
Q_OBJECT
Q_INTERFACES(Grantlee::TagLibraryInterface)
Q_PLUGIN_METADATA(IID "org.grantlee.TagLibraryInterface")
public:
explicit GrantleeTagLibrary(QObject *parent = nullptr);
QHash<QString, Grantlee::AbstractNodeFactory*> nodeFactories(const QString &name) override;
};
}
#endif // MESSAGEVIEWER_GRANTLEEEXTENSION_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment