diff options
Diffstat (limited to 'desktop-widgets/templatelayout.cpp')
-rw-r--r-- | desktop-widgets/templatelayout.cpp | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/desktop-widgets/templatelayout.cpp b/desktop-widgets/templatelayout.cpp index 633d4569c..b9cd5545e 100644 --- a/desktop-widgets/templatelayout.cpp +++ b/desktop-widgets/templatelayout.cpp @@ -161,6 +161,19 @@ QString TemplateLayout::generate() /* don't use the Grantlee loader API */ 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); + htmlContent = out.readAll(); + return htmlContent; + QString preprocessed = preprocessTemplate(templateContents); /* create the template from QString; is this thing allocating memory? */ @@ -215,6 +228,21 @@ QString TemplateLayout::generateStatistics() qDebug() << "Can't load template"; return htmlContent; } + 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); + htmlContent = out.readAll(); + return htmlContent; + htmlContent = t->render(&c); @@ -246,3 +274,351 @@ void TemplateLayout::writeTemplate(QString template_name, QString grantlee_templ qfile.close(); } } + +struct token stringToken(QString s) +{ + struct token newtoken; + newtoken.type = LITERAL; + newtoken.contents = s; + return newtoken; +} + +static QRegularExpression keywordFor(R"(\bfor\b)"); +static QRegularExpression keywordEndfor(R"(\bendfor\b)"); +static QRegularExpression keywordBlock(R"(\bblock\b)"); +static QRegularExpression keywordEndblock(R"(\bendblock\b)"); +static QRegularExpression keywordIf(R"(\bif\b)"); +static QRegularExpression keywordEndif(R"(\bendif\b)"); + +struct token operatorToken(QString s) +{ + struct token newtoken; + + QRegularExpressionMatch match = keywordFor.match(s); + if (match.hasMatch()) { + newtoken.type = FORSTART; + newtoken.contents = s.mid(match.capturedEnd()); + return newtoken; + } + match = keywordEndfor.match(s); + if (match.hasMatch()) { + newtoken.type = FORSTOP; + newtoken.contents = ""; + return newtoken; + } + match = keywordBlock.match(s); + if (match.hasMatch()) { + newtoken.type = BLOCKSTART; + newtoken.contents = s.mid(match.capturedEnd()); + return newtoken; + } + match = keywordEndblock.match(s); + if (match.hasMatch()) { + newtoken.type = BLOCKSTOP; + newtoken.contents = ""; + return newtoken; + } + match = keywordIf.match(s); + if (match.hasMatch()) { + newtoken.type = IFSTART; + newtoken.contents = s.mid(match.capturedEnd()); + return newtoken; + } + match = keywordEndif.match(s); + if (match.hasMatch()) { + newtoken.type = IFSTOP; + newtoken.contents = ""; + return newtoken; + } + + newtoken.type = PARSERERROR; + newtoken.contents = ""; + return newtoken; +} + +static QRegularExpression op(R"(\{%([\w\s\.\|\:]+)%\})"); // Look for {% stuff %} + +QList<token> TemplateLayout::lexer(QString input) +{ + QList<token> tokenList; + + int last = 0; + QRegularExpressionMatch match = op.match(input); + while (match.hasMatch()) { + tokenList << stringToken(input.mid(last, match.capturedStart() - last)); + tokenList << operatorToken(match.captured(1)); + last = match.capturedEnd(); + match = op.match(input, last); + } + tokenList << stringToken(input.mid(last)); + return tokenList; +} + +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 out; + int last = 0; + QRegularExpressionMatch match = var.match(s); + while (match.hasMatch()) { + QString obname = match.captured(1); + QString memname = match.captured(2); + out += s.mid(last, match.capturedStart() - last); + QVariant value = getValue(obname, memname, options.value(obname)); + out += value.toString(); + last = match.capturedEnd(); + match = var.match(s, last); + } + out += s.mid(last); + return out; +} + +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) +{ + while (pos < tokenList.length()) { + switch (tokenList[pos].type) { + case LITERAL: + out << translate(tokenList[pos].contents, options); + ++pos; + break; + case BLOCKSTART: + case BLOCKSTOP: + ++pos; + break; + case FORSTART: + { + QString argument = tokenList[pos].contents; + ++pos; + QRegularExpressionMatch match = forloop.match(argument); + if (match.hasMatch()) { + QString itemname = match.captured(1); + QString listname = match.captured(2); + 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["cylinders"] = QVariant::fromValue(item.value<DiveObjectHelperGrantlee>().cylinderList()); + parser(tokenList, pos, capture, options); + options.remove(itemname); + options.remove("forloopiterator"); + if (listname == "dives") + options.remove("cylinders"); + if (olditerator.isValid()) + options["forloopiterator"] = olditerator; + } + out << capture.readAll(); + } else { + out << "PARSING ERROR: '" << argument << "'"; + } + } + break; + case IFSTART: + { + QString argument = tokenList[pos].contents; + ++pos; + QRegularExpressionMatch match = ifstatement.match(argument); + if (match.hasMatch()) { + int divisor = match.captured(1).toInt(); + QString buffer; + QTextStream capture(&buffer); + int counter = options["forloopiterator"].toInt(); + parser(tokenList, pos, capture, options); + if (!(counter % divisor)) + out << capture.readAll(); + } else { + out << "PARSING ERROR: '" << argument << "'"; + } + } + break; + case FORSTOP: + case IFSTOP: + ++pos; + return; + case PARSERERROR: + out << "PARSING ERROR"; + ++pos; + } + } +} + +QVariant TemplateLayout::getValue(QString list, QString property, QVariant option) +{ + if (list == "template_options") { + template_options object = option.value<template_options>(); + if (property == "font") { + switch (object.font_index) { + case 0: + return "Arial, Helvetica, sans-serif"; + case 1: + return "Impact, Charcoal, sans-serif"; + case 2: + return "Georgia, serif"; + case 3: + return "Courier, monospace"; + case 4: + return "Verdana, Geneva, sans-serif"; + } + } else if (property == "borderwidth") { + return object.border_width; + } else if (property == "font_size") { + return object.font_size / 9.0; + } else if (property == "line_spacing") { + return object.line_spacing; + } else if (property == "color1") { + return object.color_palette.color1.name(); + } else if (property == "color2") { + return object.color_palette.color2.name(); + } else if (property == "color3") { + return object.color_palette.color3.name(); + } else if (property == "color4") { + return object.color_palette.color4.name(); + } else if (property == "color5") { + return object.color_palette.color5.name(); + } else if (property == "color6") { + return object.color_palette.color6.name(); + } + } else if (list == "print_options") { + print_options object = option.value<print_options>(); + if (property == "grayscale") { + if (object.color_selected) { + return ""; + } else { + return "-webkit-filter: grayscale(100%)"; + } + } + } else if (list =="year") { + YearInfo object = option.value<YearInfo>(); + if (property == "year") { + return object.year->period; + } else if (property == "dives") { + return object.year->selection_size; + } else if (property == "min_temp") { + return object.year->min_temp.mkelvin == 0 ? "0" : get_temperature_string(object.year->min_temp, true); + } else if (property == "max_temp") { + return object.year->max_temp.mkelvin == 0 ? "0" : get_temperature_string(object.year->max_temp, true); + } else if (property == "total_time") { + return get_dive_duration_string(object.year->total_time.seconds, gettextFromC::tr("h"), + gettextFromC::tr("min"), gettextFromC::tr("sec"), " "); + } else if (property == "avg_time") { + return get_minutes(object.year->total_time.seconds / object.year->selection_size); + } else if (property == "shortest_time") { + return get_minutes(object.year->shortest_time.seconds); + } else if (property == "longest_time") { + return get_minutes(object.year->longest_time.seconds); + } else if (property == "avg_depth") { + return get_depth_string(object.year->avg_depth); + } else if (property == "min_depth") { + return get_depth_string(object.year->min_depth); + } else if (property == "max_depth") { + return get_depth_string(object.year->max_depth); + } else if (property == "avg_sac") { + return get_volume_string(object.year->avg_sac); + } else if (property == "min_sac") { + return get_volume_string(object.year->min_sac); + } else if (property == "max_sac") { + return get_volume_string(object.year->max_sac); + } + } else if (list == "cylinder") { + CylinderObjectHelper object = option.value<CylinderObjectHelper>(); + if (property == "description") { + return object.description; + } else if (property == "size") { + return object.size; + } else if (property == "workingPressure") { + return object.workingPressure; + } else if (property == "startPressure") { + return object.startPressure; + } else if (property == "endPressure") { + return object.endPressure; + } else if (property == "gasMix") { + return object.gasMix; + } + } else if (list == "dive") { + DiveObjectHelperGrantlee object = option.value<DiveObjectHelperGrantlee>(); + if (property == "number") { + return object.number; + } else if (property == "id") { + return object.id; + } else if (property == "rating") { + return object.rating; + } else if (property == "visibility") { + return object.visibility; + } else if (property == "date") { + return object.date(); + } else if (property == "time") { + return object.time(); + } else if (property == "timestamp") { + return QVariant::fromValue(object.timestamp); + } else if (property == "location") { + return object.location; + } else if (property == "gps") { + return object.gps; + } else if (property == "gps_decimal") { + return object.gps_decimal; + } else if (property == "dive_site") { + return object.dive_site; + } else if (property == "duration") { + return object.duration; + } else if (property == "noDive") { + return object.noDive; + } else if (property == "depth") { + return object.depth; + } else if (property == "divemaster") { + return object.divemaster; + } else if (property == "buddy") { + return object.buddy; + } else if (property == "airTemp") { + return object.airTemp; + } else if (property == "waterTemp") { + return object.waterTemp; + } else if (property == "notes") { + return object.notes; + } else if (property == "tags") { + return object.tags; + } else if (property == "gas") { + return object.gas; + } else if (property == "sac") { + return object.sac; + } else if (property == "weightList") { + return object.weightList; + } else if (property == "weights") { + return object.weights; + } else if (property == "singleWeight") { + return object.singleWeight; + } else if (property == "suit") { + return object.suit; + } else if (property == "cylinderList") { + return object.cylinderList(); + } else if (property == "cylinders") { + return object.cylinders; + } else if (property == "cylinderObjects") { + return QVariant::fromValue(object.cylinderObjects); + } else if (property == "maxcns") { + return object.maxcns; + } else if (property == "otu") { + return object.otu; + } else if (property == "sumWeight") { + return object.sumWeight; + } else if (property == "getCylinder") { + return object.getCylinder; + } else if (property == "startPressure") { + return object.startPressure; + } else if (property == "endPressure") { + return object.endPressure; + } else if (property == "firstGas") { + return object.firstGas; + } + } + return QVariant(); +} |