mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-19 14:25:27 +00:00
printing: remove objects QVariant map
An artifact from the old grantlee code: the whole parser state was kept in an untyped QVariant map. One case was particularly bizarre: the options were a class member and yet added to the weird map. Replace this by a strongly typed state structure. Ultimately, this will allow us to replace the "dive object helper". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
0cbb448740
commit
f42a70586b
2 changed files with 94 additions and 77 deletions
|
@ -106,11 +106,11 @@ QString TemplateLayout::generate()
|
||||||
|
|
||||||
QString htmlContent;
|
QString htmlContent;
|
||||||
|
|
||||||
QVariantList diveList;
|
State state;
|
||||||
|
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
if (in_planner()) {
|
if (in_planner()) {
|
||||||
diveList.append(QVariant::fromValue(DiveObjectHelperGrantlee(&displayed_dive)));
|
state.dives.append(DiveObjectHelperGrantlee(&displayed_dive));
|
||||||
emit progressUpdated(100.0);
|
emit progressUpdated(100.0);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
|
@ -118,7 +118,7 @@ QString TemplateLayout::generate()
|
||||||
//TODO check for exporting selected dives only
|
//TODO check for exporting selected dives only
|
||||||
if (!dive->selected && printOptions.print_selected)
|
if (!dive->selected && printOptions.print_selected)
|
||||||
continue;
|
continue;
|
||||||
diveList.append(QVariant::fromValue(DiveObjectHelperGrantlee(dive)));
|
state.dives.append(DiveObjectHelperGrantlee(dive));
|
||||||
progress++;
|
progress++;
|
||||||
emit progressUpdated(lrint(progress * 100.0 / totalWork));
|
emit progressUpdated(lrint(progress * 100.0 / totalWork));
|
||||||
}
|
}
|
||||||
|
@ -126,15 +126,11 @@ QString TemplateLayout::generate()
|
||||||
|
|
||||||
QString templateContents = readTemplate(printOptions.p_template);
|
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);
|
QList<token> tokens = lexer(templateContents);
|
||||||
QString buffer;
|
QString buffer;
|
||||||
QTextStream out(&buffer);
|
QTextStream out(&buffer);
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
parser(tokens, pos, out, options);
|
parser(tokens, pos, out, state);
|
||||||
htmlContent = out.readAll();
|
htmlContent = out.readAll();
|
||||||
return htmlContent;
|
return htmlContent;
|
||||||
}
|
}
|
||||||
|
@ -142,29 +138,26 @@ QString TemplateLayout::generate()
|
||||||
QString TemplateLayout::generateStatistics()
|
QString TemplateLayout::generateStatistics()
|
||||||
{
|
{
|
||||||
QString htmlContent;
|
QString htmlContent;
|
||||||
QVariantList years;
|
|
||||||
|
State state;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
stats_summary_auto_free stats;
|
stats_summary_auto_free stats;
|
||||||
calculate_stats_summary(&stats, false);
|
calculate_stats_summary(&stats, false);
|
||||||
while (stats.stats_yearly != NULL && stats.stats_yearly[i].period) {
|
while (stats.stats_yearly != NULL && stats.stats_yearly[i].period) {
|
||||||
YearInfo year{ &stats.stats_yearly[i] };
|
YearInfo year{ &stats.stats_yearly[i] };
|
||||||
years.append(QVariant::fromValue(year));
|
state.years.append(year);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString templateFile = QString("statistics") + QDir::separator() + printOptions.p_template;
|
QString templateFile = QString("statistics") + QDir::separator() + printOptions.p_template;
|
||||||
QString templateContents = readTemplate(templateFile);
|
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);
|
QList<token> tokens = lexer(templateContents);
|
||||||
QString buffer;
|
QString buffer;
|
||||||
QTextStream out(&buffer);
|
QTextStream out(&buffer);
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
parser(tokens, pos, out, options);
|
parser(tokens, pos, out, state);
|
||||||
htmlContent = out.readAll();
|
htmlContent = out.readAll();
|
||||||
return htmlContent;
|
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 }}
|
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;
|
QString out;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
|
@ -279,8 +272,8 @@ QString TemplateLayout::translate(QString s, QHash<QString, QVariant> options)
|
||||||
QString obname = match.captured(1);
|
QString obname = match.captured(1);
|
||||||
QString memname = match.captured(2);
|
QString memname = match.captured(2);
|
||||||
out += s.mid(last, match.capturedStart() - last);
|
out += s.mid(last, match.capturedStart() - last);
|
||||||
QString listname = options.contains("typeof:" + obname) ? options.value("typeof:" + obname).value<QString>() : obname;
|
QString listname = state.types.value(obname, obname);
|
||||||
QVariant value = getValue(listname, memname, options.value(obname));
|
QVariant value = getValue(listname, memname, state);
|
||||||
out += value.toString();
|
out += value.toString();
|
||||||
last = match.capturedEnd();
|
last = match.capturedEnd();
|
||||||
match = var.match(s, last);
|
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 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
|
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()) {
|
while (pos < tokenList.length()) {
|
||||||
switch (tokenList[pos].type) {
|
switch (tokenList[pos].type) {
|
||||||
case LITERAL:
|
case LITERAL:
|
||||||
out << translate(tokenList[pos].contents, options);
|
out << translate(tokenList[pos].contents, state);
|
||||||
++pos;
|
++pos;
|
||||||
break;
|
break;
|
||||||
case BLOCKSTART:
|
case BLOCKSTART:
|
||||||
|
@ -312,32 +324,25 @@ void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out,
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
QString itemname = match.captured(1);
|
QString itemname = match.captured(1);
|
||||||
QString listname = match.captured(2);
|
QString listname = match.captured(2);
|
||||||
options["typeof:" + itemname] = listname;
|
state.types[itemname] = listname;
|
||||||
QString buffer;
|
QString buffer;
|
||||||
QTextStream capture(&buffer);
|
QTextStream capture(&buffer);
|
||||||
QVariantList list = options[listname].value<QVariantList>();
|
if (listname == "years") {
|
||||||
int savepos = pos;
|
parser_for(tokenList, pos, capture, state, state.years, state.currentYear);
|
||||||
for (int i = 0; i < list.size(); ++i) {
|
} else if (listname == "dives") {
|
||||||
QVariant item = list.at(i);
|
parser_for(tokenList, pos, capture, state, state.dives, state.currentDive);
|
||||||
QVariant olditerator = options["forloopiterator"];
|
} else if (listname == "cylinders") {
|
||||||
options[itemname] = item;
|
if (state.currentDive)
|
||||||
options["forloopiterator"] = i + 1;
|
parser_for(tokenList, pos, capture, state, state.currentDive->cylinders, state.currentCylinder);
|
||||||
pos = savepos;
|
else
|
||||||
if (listname == "dives") {
|
qWarning("cylinders loop outside of dive");
|
||||||
options["cylinderObjects"] = QVariant::fromValue(item.value<DiveObjectHelperGrantlee>().cylinderObjects);
|
} else if (listname == "cylinderObjects") {
|
||||||
options["cylinders"] = QVariant::fromValue(item.value<DiveObjectHelperGrantlee>().cylinders);
|
if (state.currentDive)
|
||||||
}
|
parser_for(tokenList, pos, capture, state, state.currentDive->cylinderObjects, state.currentCylinderObject);
|
||||||
parser(tokenList, pos, capture, options);
|
else
|
||||||
options.remove(itemname);
|
qWarning("cylinderObjects loop outside of dive");
|
||||||
options.remove("forloopiterator");
|
|
||||||
if (listname == "dives") {
|
|
||||||
options.remove("cylinderObjects");
|
|
||||||
options.remove("cylinders");
|
|
||||||
}
|
|
||||||
if (olditerator.isValid())
|
|
||||||
options["forloopiterator"] = olditerator;
|
|
||||||
}
|
}
|
||||||
options.remove("typeof:" + itemname);
|
state.types.remove(itemname);
|
||||||
out << capture.readAll();
|
out << capture.readAll();
|
||||||
} else {
|
} else {
|
||||||
out << "PARSING ERROR: '" << argument << "'";
|
out << "PARSING ERROR: '" << argument << "'";
|
||||||
|
@ -353,9 +358,9 @@ void TemplateLayout::parser(QList<token> tokenList, int &pos, QTextStream &out,
|
||||||
int divisor = match.captured(1).toInt();
|
int divisor = match.captured(1).toInt();
|
||||||
QString buffer;
|
QString buffer;
|
||||||
QTextStream capture(&buffer);
|
QTextStream capture(&buffer);
|
||||||
int counter = options["forloopiterator"].toInt();
|
int counter = std::max(0, state.forloopiterator);
|
||||||
parser(tokenList, pos, capture, options);
|
parser(tokenList, pos, capture, state);
|
||||||
if (!(counter % divisor))
|
if (!(counter % divisor))
|
||||||
out << capture.readAll();
|
out << capture.readAll();
|
||||||
} else {
|
} else {
|
||||||
out << "PARSING ERROR: '" << argument << "'";
|
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") {
|
if (list == "template_options") {
|
||||||
template_options object = option.value<template_options>();
|
|
||||||
if (property == "font") {
|
if (property == "font") {
|
||||||
switch (object.font_index) {
|
switch (templateOptions.font_index) {
|
||||||
case 0:
|
case 0:
|
||||||
return "Arial, Helvetica, sans-serif";
|
return "Arial, Helvetica, sans-serif";
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -391,35 +395,36 @@ QVariant TemplateLayout::getValue(QString list, QString property, QVariant optio
|
||||||
return "Verdana, Geneva, sans-serif";
|
return "Verdana, Geneva, sans-serif";
|
||||||
}
|
}
|
||||||
} else if (property == "borderwidth") {
|
} else if (property == "borderwidth") {
|
||||||
return object.border_width;
|
return templateOptions.border_width;
|
||||||
} else if (property == "font_size") {
|
} else if (property == "font_size") {
|
||||||
return object.font_size / 9.0;
|
return templateOptions.font_size / 9.0;
|
||||||
} else if (property == "line_spacing") {
|
} else if (property == "line_spacing") {
|
||||||
return object.line_spacing;
|
return templateOptions.line_spacing;
|
||||||
} else if (property == "color1") {
|
} else if (property == "color1") {
|
||||||
return object.color_palette.color1.name();
|
return templateOptions.color_palette.color1.name();
|
||||||
} else if (property == "color2") {
|
} else if (property == "color2") {
|
||||||
return object.color_palette.color2.name();
|
return templateOptions.color_palette.color2.name();
|
||||||
} else if (property == "color3") {
|
} else if (property == "color3") {
|
||||||
return object.color_palette.color3.name();
|
return templateOptions.color_palette.color3.name();
|
||||||
} else if (property == "color4") {
|
} else if (property == "color4") {
|
||||||
return object.color_palette.color4.name();
|
return templateOptions.color_palette.color4.name();
|
||||||
} else if (property == "color5") {
|
} else if (property == "color5") {
|
||||||
return object.color_palette.color5.name();
|
return templateOptions.color_palette.color5.name();
|
||||||
} else if (property == "color6") {
|
} else if (property == "color6") {
|
||||||
return object.color_palette.color6.name();
|
return templateOptions.color_palette.color6.name();
|
||||||
}
|
}
|
||||||
} else if (list == "print_options") {
|
} else if (list == "print_options") {
|
||||||
print_options object = option.value<print_options>();
|
|
||||||
if (property == "grayscale") {
|
if (property == "grayscale") {
|
||||||
if (object.color_selected) {
|
if (printOptions.color_selected) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
return "-webkit-filter: grayscale(100%)";
|
return "-webkit-filter: grayscale(100%)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (list =="year") {
|
} else if (list =="years") {
|
||||||
YearInfo object = option.value<YearInfo>();
|
if (!state.currentYear)
|
||||||
|
return QVariant();
|
||||||
|
const YearInfo &object = *state.currentYear;
|
||||||
if (property == "year") {
|
if (property == "year") {
|
||||||
return object.year->period;
|
return object.year->period;
|
||||||
} else if (property == "dives") {
|
} 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);
|
return get_volume_string(object.year->max_sac);
|
||||||
}
|
}
|
||||||
} else if (list == "cylinders") {
|
} else if (list == "cylinders") {
|
||||||
if (property == "description") {
|
if (state.currentCylinder && property == "description") {
|
||||||
return option.value<QString>();
|
return *state.currentCylinder;
|
||||||
}
|
}
|
||||||
} else if (list == "cylinderObjects") {
|
} else if (list == "cylinderObjects") {
|
||||||
CylinderObjectHelper object = option.value<CylinderObjectHelper>();
|
if (!state.currentCylinderObject)
|
||||||
|
return QVariant();
|
||||||
|
const CylinderObjectHelper &object = *state.currentCylinderObject;
|
||||||
if (property == "description") {
|
if (property == "description") {
|
||||||
return object.description;
|
return object.description;
|
||||||
} else if (property == "size") {
|
} else if (property == "size") {
|
||||||
|
@ -470,7 +477,9 @@ QVariant TemplateLayout::getValue(QString list, QString property, QVariant optio
|
||||||
return object.gasMix;
|
return object.gasMix;
|
||||||
}
|
}
|
||||||
} else if (list == "dives") {
|
} else if (list == "dives") {
|
||||||
DiveObjectHelperGrantlee object = option.value<DiveObjectHelperGrantlee>();
|
if (!state.currentDive)
|
||||||
|
return QVariant();
|
||||||
|
const DiveObjectHelperGrantlee &object = *state.currentDive;
|
||||||
if (property == "number") {
|
if (property == "number") {
|
||||||
return object.number;
|
return object.number;
|
||||||
} else if (property == "id") {
|
} else if (property == "id") {
|
||||||
|
|
|
@ -24,6 +24,10 @@ struct token {
|
||||||
|
|
||||||
extern QList<QString> grantlee_templates, grantlee_statistics_templates;
|
extern QList<QString> grantlee_templates, grantlee_statistics_templates;
|
||||||
|
|
||||||
|
struct YearInfo {
|
||||||
|
stats_t *year;
|
||||||
|
};
|
||||||
|
|
||||||
class TemplateLayout : public QObject {
|
class TemplateLayout : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -34,23 +38,27 @@ public:
|
||||||
static void writeTemplate(QString template_name, QString grantlee_template);
|
static void writeTemplate(QString template_name, QString grantlee_template);
|
||||||
|
|
||||||
private:
|
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 print_options &printOptions;
|
||||||
const template_options &templateOptions;
|
const template_options &templateOptions;
|
||||||
QList<token> lexer(QString input);
|
QList<token> lexer(QString input);
|
||||||
void parser(QList<token> tokenList, int &pos, QTextStream &out, QHash<QString, QVariant> options);
|
void parser(QList<token> tokenList, int &pos, QTextStream &out, State &state);
|
||||||
QVariant getValue(QString list, QString property, QVariant option);
|
template<typename V, typename T>
|
||||||
QString translate(QString s, QHash<QString, QVariant> options);
|
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:
|
signals:
|
||||||
void progressUpdated(int value);
|
void progressUpdated(int value);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct YearInfo {
|
|
||||||
stats_t *year;
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(template_options)
|
|
||||||
Q_DECLARE_METATYPE(print_options)
|
|
||||||
Q_DECLARE_METATYPE(YearInfo)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue