Commit e70e43e8 authored by Volker Krause's avatar Volker Krause

Render ticket barcodes if present

Requires a bit of refactoring in how we expose data to Grantlee. As that
can't easily do array or map lookups we need to interleave reservation and
state data already on the outside.
parent dbe08903
......@@ -47,5 +47,6 @@ target_link_libraries(messageviewer_bodypartformatter_semantic
KF5::I18n
Grantlee5::Templates
Qt5::DBus
KF5::Prison
)
install(TARGETS messageviewer_bodypartformatter_semantic DESTINATION ${KDE_INSTALL_PLUGINDIR}/messageviewer/bodypartformatter)
......@@ -156,6 +156,7 @@ class Ticket
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QVariant, ticketedSeat)
SEMANTIC_PROPERTY(QString, ticketToken)
};
class Reservation
......
......@@ -48,6 +48,20 @@ QVector<QVariant> SemanticMemento::data() const
void SemanticMemento::setData(const QVector<QVariant> &data)
{
m_data = data;
m_expanded.resize(data.size());
}
QVector<bool> SemanticMemento::expanded() const
{
return m_expanded;
}
void SemanticMemento::toggleExpanded(int index)
{
if (index >= m_expanded.size()) {
return;
}
m_expanded[index] = !m_expanded.at(index);
}
bool SemanticMemento::hasStructuredData() const
......
......@@ -44,11 +44,15 @@ public:
QVector<QVariant> data() const;
void setData(const QVector<QVariant> &data);
QVector<bool> expanded() const;
void toggleExpanded(int index);
bool hasStructuredData() const;
void setStructuredDataFound(bool f);
private:
QVector<QVariant> m_data;
QVector<bool> m_expanded;
QSet<KMime::ContentIndex> m_parsedParts;
bool m_foundStructuredData = false;
};
......
......@@ -19,15 +19,19 @@
#include "semanticrenderer.h"
#include "datatypes.h"
#include "jsonlddocument.h"
#include "semanticmemento.h"
#include "semantic_debug.h"
#include <MessageViewer/MessagePartRendererManager>
#include <MessageViewer/IconNameCache>
#include <MessageViewer/HtmlWriter>
#include <MessageViewer/MessagePartRendererManager>
#include <grantlee/metatype.h>
#include <grantlee/template.h>
#include <prison/Prison>
#include <QGuiApplication>
#include <QMetaProperty>
#include <QPalette>
......@@ -79,7 +83,6 @@ bool SemanticRenderer::render(const MimeTreeParser::MessagePartPtr &msgPart, Mes
return false;
}
qCDebug(SEMANTIC_LOG) << "========================================= Semantic Rendering";
const auto node = mpList->subParts().at(0)->content();
const auto nodeHelper = msgPart->nodeHelper();
if (!nodeHelper || !node) {
......@@ -91,14 +94,46 @@ bool SemanticRenderer::render(const MimeTreeParser::MessagePartPtr &msgPart, Mes
return false;
}
const auto dir = nodeHelper->createTempDir(QStringLiteral("semantic"));
auto c = MessageViewer::MessagePartRendererManager::self()->createContext();
c.insert(QStringLiteral("data"), QVariant::fromValue(memento->data()));
const auto pal = qGuiApp->palette();
QVariantMap style;
style.insert(QStringLiteral("frameColor"), pal.link().color().name());
style.insert(QStringLiteral("expandIcon"), MessageViewer::IconNameCache::instance()->iconPathFromLocal(QStringLiteral("quoteexpand.png")));
style.insert(QStringLiteral("collapseIcon"), MessageViewer::IconNameCache::instance()->iconPathFromLocal(QStringLiteral("quotecollapse.png")));
c.insert(QStringLiteral("style"), style);
// Grantlee can't do indexed map/array lookups, so we need to interleave this here already
QVariantList elems;
elems.reserve(memento->data().size());
for (int i = 0; i < memento->data().size(); ++i) {
const auto res = memento->data().at(i);
QVariantMap data;
data.insert(QStringLiteral("reservation"), res);
QVariantMap state;
state.insert(QStringLiteral("expanded"), memento->expanded().at(i));
data.insert(QStringLiteral("state"), state);
// generate ticket barcodes
const auto ticket = JsonLdDocument::readProperty(res, "reservedTicket");
const auto ticketToken = JsonLdDocument::readProperty(ticket, "ticketToken").toString();
if (ticketToken.startsWith(QLatin1String("azteccode:"), Qt::CaseInsensitive)) {
std::unique_ptr<Prison::AbstractBarcode> barcode(Prison::createBarcode(Prison::Aztec));
barcode->setData(ticketToken.mid(10));
barcode->toImage(barcode->minimumSize()); // minimumSize is only available after we rendered once...
const auto img = barcode->toImage(barcode->minimumSize());
const auto fileName = dir + QStringLiteral("/ticketToken") + QString::number(i) + QStringLiteral(".png");
img.save(fileName);
data.insert(QStringLiteral("ticketToken"), fileName);
nodeHelper->addTempFile(fileName);
}
elems.push_back(data);
}
c.insert(QStringLiteral("data"), elems);
auto t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral(":/org.kde.messageviewer/semantic/semantic.html"));
Grantlee::OutputStream s(htmlWriter->stream());
t->render(&s, &c);
......
......@@ -46,8 +46,20 @@
bool SemanticUrlHandler::handleClick(MessageViewer::Viewer *viewerInstance, MimeTreeParser::Interface::BodyPart *part, const QString &path) const
{
Q_UNUSED(viewerInstance);
Q_UNUSED(part);
return path == QLatin1String("semanticAction");
if (path == QLatin1String("semanticAction")) {
return true;
}
if (path.startsWith(QLatin1String("semanticExpand?"))) {
auto idx = path.midRef(15).toInt();
auto m = memento(part);
m->toggleExpanded(idx);
const auto nodeHelper = part->nodeHelper();
emit nodeHelper->update(MimeTreeParser::Delayed);
return true;
}
return false;
}
static void addGoToMapAction(QMenu *menu, const QVariant &place)
......
......@@ -2,7 +2,8 @@
<div style="position: absolute; top: 4px; right: 4px;">
<a href="x-kmail:/bodypart/0//semanticAction">{% icon "view-calendar" small _("Add reservation to calendar.") %}</a>
</div>
{% for item in data %}
{% for elem in data %}
{% with elem.reservation as item %}
{% if item.className == "FlightReservation" %}
{% include ":/org.kde.messageviewer/semantic/flightreservation.html" %}
{% elif item.className == "LodgingReservation" %}
......@@ -14,5 +15,6 @@
{% if not forloop.last %}
<hr/>
{% endif %}
{% endwith %}
{% endfor %}
</div>
......@@ -23,6 +23,15 @@
</tr>
<tr><td colspan="3">
<div style="float:left">
{% if elem.ticketToken %}
<a href="x-kmail:/bodypart/0//semanticExpand?{{ forloop.counter0 }}">
{% if elem.state.expanded %}
<img src="{{ style.collapseIcon }}" style="margin-right: 4px;"/>
{% else %}
<img src="{{ style.expandIcon }}" style="margin-right: 4px;"/>
{% endif %}
</a>
{% endif %}
{% if item.reservedTicket.ticketedSeat.seatSection %}
{% i18n "Coach: %1" item.reservedTicket.ticketedSeat.seatSection %}
{% endif %}
......@@ -50,3 +59,11 @@
</td></tr>
</table>
{% if elem.state.expanded %}
<div style="text-align:center;">
<div style="background-color: #ffffff; display: inline-block; padding: 4px;">
<img src="{{ elem.ticketToken }}"/>
</div>
</div>
{% endif %}
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