diff options
-rw-r--r-- | desktop-widgets/templatelayout.cpp | 141 | ||||
-rw-r--r-- | desktop-widgets/templatelayout.h | 30 |
2 files changed, 94 insertions, 77 deletions
diff --git a/desktop-widgets/templatelayout.cpp b/desktop-widgets/templatelayout.cpp index 9ed5a35cf..89222b8a8 100644 --- a/desktop-widgets/templatelayout.cpp +++ b/desktop-widgets/templatelayout.cpp @@ -106,11 +106,11 @@ QString TemplateLayout::generate() QString htmlContent; - QVariantList diveList; + State state; struct dive *dive; if (in_planner()) { - diveList.append(QVariant::fromValue(DiveObjectHelperGrantlee(&displayed_dive))); + state.dives.append(DiveObjectHelperGrantlee(&displayed_dive)); emit progressUpdated(100.0); } else { int i; @@ -118,7 +118,7 @@ QString TemplateLayout::generate() //TODO check for exporting selected dives only if (!dive->selected && printOptions.print_selected) continue; - diveList.append(QVariant::fromValue(DiveObjectHelperGrantlee(dive))); + state.dives.append(DiveObjectHelperGrantlee(dive)); progress++; emit progressUpdated(lrint(progress * 100.0 / totalWork)); } @@ -126,15 +126,11 @@ QString TemplateLayout::generate() QString templateContents = readTemplate(printOptions.p_template); - QHash<QString, QVariant> options; - options["print_options"] = QVariant::fromValue(printOptions); - options["template_options"] = QVariant::fromValue(templateOptions); - options["dives"] = QVariant::fromValue(diveList); QList<token> tokens = lexer(templateContents); QString buffer; QTextStream out(&buffer); int pos = 0; - parser(tokens, pos, out, options); + parser(tokens, pos, out, state); htmlContent = out.readAll(); return htmlContent; } @@ -142,29 +138,26 @@ QString TemplateLayout::generate() QString TemplateLayout::generateStatistics() { QString htmlContent; - QVariantList years; + + State state; int i = 0; stats_summary_auto_free stats; calculate_stats_summary(&stats, false); while (stats.stats_yearly != NULL && stats.stats_yearly[i].period) { YearInfo year{ &stats.stats_yearly[i] }; - years.append(QVariant::fromValue(year)); + state.years.append(year); i++; } QString templateFile = QString("statistics") + QDir::separator() + printOptions.p_template; QString templateContents = readTemplate(templateFile); - QHash<QString, QVariant> options; - options["print_options"] = QVariant::fromValue(printOptions); - options["template_options"] = QVariant::fromValue(templateOptions); - options["years"] = QVariant::fromValue(years); QList<token> tokens = lexer(templateContents); QString buffer; QTextStream out(&buffer); int pos = 0; - parser(tokens, pos, out, options); + parser(tokens, pos, out, state); htmlContent = out.readAll(); return htmlContent; } @@ -270,7 +263,7 @@ QList<token> TemplateLayout::lexer(QString input) static QRegularExpression var(R"(\{\{\s*(\w+)\.(\w+)\s*(\|\s*(\w+))?\s*\}\})"); // Look for {{ stuff.stuff|stuff }} -QString TemplateLayout::translate(QString s, QHash<QString, QVariant> options) +QString TemplateLayout::translate(QString s, State &state) { QString out; int last = 0; @@ -279,8 +272,8 @@ QString TemplateLayout::translate(QString s, QHash<QString, QVariant> options) QString obname = match.captured(1); QString memname = match.captured(2); out += s.mid(last, match.capturedStart() - last); - QString listname = options.contains("typeof:" + obname) ? options.value("typeof:" + obname).value<QString>() : obname; - QVariant value = getValue(listname, memname, options.value(obname)); + QString listname = state.types.value(obname, obname); + QVariant value = getValue(listname, memname, state); out += value.toString(); last = match.capturedEnd(); match = var.match(s, last); @@ -292,12 +285,31 @@ QString TemplateLayout::translate(QString s, QHash<QString, QVariant> options) static QRegularExpression forloop(R"(\s*(\w+)\s+in\s+(\w+))"); // Look for "VAR in LISTNAME" static QRegularExpression ifstatement(R"(forloop\.counter\|\s*divisibleby\:\s*(\d+))"); // Look for forloop.counter|divisibleby: NUMBER -void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out, QHash<QString, QVariant> options) +template<typename V, typename T> +void TemplateLayout::parser_for(QList<token> tokenList, int &pos, QTextStream &out, State &state, + const V &data, const T *&act) +{ + const T *old = act; + int i = 1; // Loop iterators start at one + int olditerator = state.forloopiterator; + int savepos = pos; + for (const T &item: data) { + act = &item; + state.forloopiterator = i; + pos = savepos; + ++i; + parser(tokenList, pos, out, state); + } + act = old; + state.forloopiterator = olditerator; +} + +void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out, State &state) { while (pos < tokenList.length()) { switch (tokenList[pos].type) { case LITERAL: - out << translate(tokenList[pos].contents, options); + out << translate(tokenList[pos].contents, state); ++pos; break; case BLOCKSTART: @@ -312,32 +324,25 @@ void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out, if (match.hasMatch()) { QString itemname = match.captured(1); QString listname = match.captured(2); - options["typeof:" + itemname] = listname; + state.types[itemname] = listname; QString buffer; QTextStream capture(&buffer); - QVariantList list = options[listname].value<QVariantList>(); - int savepos = pos; - for (int i = 0; i < list.size(); ++i) { - QVariant item = list.at(i); - QVariant olditerator = options["forloopiterator"]; - options[itemname] = item; - options["forloopiterator"] = i + 1; - pos = savepos; - if (listname == "dives") { - options["cylinderObjects"] = QVariant::fromValue(item.value<DiveObjectHelperGrantlee>().cylinderObjects); - options["cylinders"] = QVariant::fromValue(item.value<DiveObjectHelperGrantlee>().cylinders); - } - parser(tokenList, pos, capture, options); - options.remove(itemname); - options.remove("forloopiterator"); - if (listname == "dives") { - options.remove("cylinderObjects"); - options.remove("cylinders"); - } - if (olditerator.isValid()) - options["forloopiterator"] = olditerator; + if (listname == "years") { + parser_for(tokenList, pos, capture, state, state.years, state.currentYear); + } else if (listname == "dives") { + parser_for(tokenList, pos, capture, state, state.dives, state.currentDive); + } else if (listname == "cylinders") { + if (state.currentDive) + parser_for(tokenList, pos, capture, state, state.currentDive->cylinders, state.currentCylinder); + else + qWarning("cylinders loop outside of dive"); + } else if (listname == "cylinderObjects") { + if (state.currentDive) + parser_for(tokenList, pos, capture, state, state.currentDive->cylinderObjects, state.currentCylinderObject); + else + qWarning("cylinderObjects loop outside of dive"); } - options.remove("typeof:" + itemname); + state.types.remove(itemname); out << capture.readAll(); } else { out << "PARSING ERROR: '" << argument << "'"; @@ -353,9 +358,9 @@ void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out, int divisor = match.captured(1).toInt(); QString buffer; QTextStream capture(&buffer); - int counter = options["forloopiterator"].toInt(); - parser(tokenList, pos, capture, options); - if (!(counter % divisor)) + int counter = std::max(0, state.forloopiterator); + parser(tokenList, pos, capture, state); + if (!(counter % divisor)) out << capture.readAll(); } else { out << "PARSING ERROR: '" << argument << "'"; @@ -373,12 +378,11 @@ void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out, } } -QVariant TemplateLayout::getValue(QString list, QString property, QVariant option) +QVariant TemplateLayout::getValue(QString list, QString property, const State &state) { if (list == "template_options") { - template_options object = option.value<template_options>(); if (property == "font") { - switch (object.font_index) { + switch (templateOptions.font_index) { case 0: return "Arial, Helvetica, sans-serif"; case 1: @@ -391,35 +395,36 @@ QVariant TemplateLayout::getValue(QString list, QString property, QVariant optio return "Verdana, Geneva, sans-serif"; } } else if (property == "borderwidth") { - return object.border_width; + return templateOptions.border_width; } else if (property == "font_size") { - return object.font_size / 9.0; + return templateOptions.font_size / 9.0; } else if (property == "line_spacing") { - return object.line_spacing; + return templateOptions.line_spacing; } else if (property == "color1") { - return object.color_palette.color1.name(); + return templateOptions.color_palette.color1.name(); } else if (property == "color2") { - return object.color_palette.color2.name(); + return templateOptions.color_palette.color2.name(); } else if (property == "color3") { - return object.color_palette.color3.name(); + return templateOptions.color_palette.color3.name(); } else if (property == "color4") { - return object.color_palette.color4.name(); + return templateOptions.color_palette.color4.name(); } else if (property == "color5") { - return object.color_palette.color5.name(); + return templateOptions.color_palette.color5.name(); } else if (property == "color6") { - return object.color_palette.color6.name(); + return templateOptions.color_palette.color6.name(); } } else if (list == "print_options") { - print_options object = option.value<print_options>(); if (property == "grayscale") { - if (object.color_selected) { + if (printOptions.color_selected) { return ""; } else { return "-webkit-filter: grayscale(100%)"; } } - } else if (list =="year") { - YearInfo object = option.value<YearInfo>(); + } else if (list =="years") { + if (!state.currentYear) + return QVariant(); + const YearInfo &object = *state.currentYear; if (property == "year") { return object.year->period; } else if (property == "dives") { @@ -451,11 +456,13 @@ QVariant TemplateLayout::getValue(QString list, QString property, QVariant optio return get_volume_string(object.year->max_sac); } } else if (list == "cylinders") { - if (property == "description") { - return option.value<QString>(); + if (state.currentCylinder && property == "description") { + return *state.currentCylinder; } } else if (list == "cylinderObjects") { - CylinderObjectHelper object = option.value<CylinderObjectHelper>(); + if (!state.currentCylinderObject) + return QVariant(); + const CylinderObjectHelper &object = *state.currentCylinderObject; if (property == "description") { return object.description; } else if (property == "size") { @@ -470,7 +477,9 @@ QVariant TemplateLayout::getValue(QString list, QString property, QVariant optio return object.gasMix; } } else if (list == "dives") { - DiveObjectHelperGrantlee object = option.value<DiveObjectHelperGrantlee>(); + if (!state.currentDive) + return QVariant(); + const DiveObjectHelperGrantlee &object = *state.currentDive; if (property == "number") { return object.number; } else if (property == "id") { diff --git a/desktop-widgets/templatelayout.h b/desktop-widgets/templatelayout.h index b59679285..0ed1951b4 100644 --- a/desktop-widgets/templatelayout.h +++ b/desktop-widgets/templatelayout.h @@ -24,6 +24,10 @@ struct token { extern QList<QString> grantlee_templates, grantlee_statistics_templates; +struct YearInfo { + stats_t *year; +}; + class TemplateLayout : public QObject { Q_OBJECT public: @@ -34,23 +38,27 @@ public: static void writeTemplate(QString template_name, QString grantlee_template); private: + struct State { + QList<DiveObjectHelperGrantlee> dives; + QList<YearInfo> years; + QMap<QString, QString> types; + int forloopiterator = -1; + const DiveObjectHelperGrantlee *currentDive = nullptr; + const YearInfo *currentYear = nullptr; + const QString *currentCylinder = nullptr; + const CylinderObjectHelper *currentCylinderObject = nullptr; + }; const print_options &printOptions; const template_options &templateOptions; QList<token> lexer(QString input); - void parser(QList<token> tokenList, int &pos, QTextStream &out, QHash<QString, QVariant> options); - QVariant getValue(QString list, QString property, QVariant option); - QString translate(QString s, QHash<QString, QVariant> options); + void parser(QList<token> tokenList, int &pos, QTextStream &out, State &state); + template<typename V, typename T> + void parser_for(QList<token> tokenList, int &pos, QTextStream &out, State &state, const V &data, const T *&act); + QVariant getValue(QString list, QString property, const State &state); + QString translate(QString s, State &state); signals: void progressUpdated(int value); }; -struct YearInfo { - stats_t *year; -}; - -Q_DECLARE_METATYPE(template_options) -Q_DECLARE_METATYPE(print_options) -Q_DECLARE_METATYPE(YearInfo) - #endif |