diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2015-08-23 07:38:11 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2015-08-23 07:38:11 -0700 |
commit | 2f540b56a8e42c8a0722dec3676297024f31eb74 (patch) | |
tree | d5c34830520481fccef873a3cbc5b9f60aae8d07 | |
parent | fbce8a0378f5ebcd36dbc08b3b5771ccf5cad830 (diff) | |
parent | cc864794753eb586e89470d87196e13568cb9031 (diff) | |
download | subsurface-2f540b56a8e42c8a0722dec3676297024f31eb74.tar.gz |
Merge branch 'custom-print' of github.com:neolit123/subsurface
-rw-r--r-- | Documentation/images/PrintDiveLog.jpg | bin | 35196 -> 33884 bytes | |||
-rw-r--r-- | Documentation/images/Printpreview.jpg | bin | 23664 -> 30041 bytes | |||
-rw-r--r-- | Documentation/user-manual.txt | 172 | ||||
-rw-r--r-- | printer.cpp | 111 | ||||
-rw-r--r-- | printer.h | 1 | ||||
-rw-r--r-- | printing_templates/Six Dives.html | 17 | ||||
-rw-r--r-- | printing_templates/statistics/Default.html | 97 | ||||
-rw-r--r-- | qt-ui/printdialog.cpp | 20 | ||||
-rw-r--r-- | qt-ui/printoptions.cpp | 63 | ||||
-rw-r--r-- | qt-ui/printoptions.h | 1 | ||||
-rw-r--r-- | qt-ui/templateedit.cpp | 7 | ||||
-rw-r--r-- | templatelayout.cpp | 69 | ||||
-rw-r--r-- | templatelayout.h | 54 |
13 files changed, 479 insertions, 133 deletions
diff --git a/Documentation/images/PrintDiveLog.jpg b/Documentation/images/PrintDiveLog.jpg Binary files differindex 7a485c4ff..8ff972dd7 100644 --- a/Documentation/images/PrintDiveLog.jpg +++ b/Documentation/images/PrintDiveLog.jpg diff --git a/Documentation/images/Printpreview.jpg b/Documentation/images/Printpreview.jpg Binary files differindex ab5db7fa5..7297d80cc 100644 --- a/Documentation/images/Printpreview.jpg +++ b/Documentation/images/Printpreview.jpg diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 815bb9b2a..943d2268d 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -2711,8 +2711,9 @@ process could be used for the Cloud-based storage of dive logs. [[S_PrintDivelog]] == Printing a dive log -_Subsurface_ provides a simple interface to print a whole dive log or only a -few selected dives, including dive profiles and other contextual information. +_Subsurface_ provides a simple interface to print a whole dive log or only a few selected dives. + Pre-installed templates or a custom written template can be used to choose where the data will + be fitted into the page. Before printing, two decisions are required: @@ -2727,15 +2728,10 @@ below). image::images/PrintDiveLog.jpg["FIGURE: Print dialogue",align="center"] -Under _Print type_ users need to select one of three options: +Under _Print type_ users need to select one of two options: -- Print the complete Dive List: to do this, _Table Print_ should be selected. -- Print the selected dives (dive profiles and all other information) at 6 - dives per printed page: to do this, users should select _6 dives per page_. -- Print the selected dives (dive profiles and all other information) at 2 - dives per printed page: to do this, users should select _2 dives per page_. -- Print the selected dives (dive profiles and all other information) at 1 - dive per printed page: to do this, users should select _1 dive per page_. +- _Dive list_ print: print dives from the list with profiles and other information. +- _Statistics_ print: print yearly statistics of the dives. Under _Print options_ users need to select: @@ -2744,12 +2740,20 @@ Under _Print options_ users need to select: selected dives_. - Printing in colour, achieved by checking the box with _Print in colour_. -The _Ordering_ affects the layout of the page (or part of it) for each dive. -The dive profile could be printed at the top of each dive, with the textual -information underneath, or it could be printed with the textual information at -the top with the dive profile underneath. Users should select the appropriate option in the -print dialogue. See the image below which has a layout with -text below the dive profile. +Under _Template_ users can select: + +- A template to be used as the page layout. + +- _Delete_ a template from the template list +- _Import_ a new template to the template list +- _Export_ a template from the template list +- _Edit_ a template (choose colors, fonts, font-type) + +When editing a template the following options are available: + +- _Style_: edit font type, size, choose color palette; this will not affect the template HTML code +- _Template_: edit the template HTML code; by saving, the "Custom" template in the template list will be replaced +- _Colors_: edit the current color palette; the new color palette will overwrite the "Custom" color palette Users can _Preview_ the printed page by selecting the _Preview_ button on the dialogue. After preview, changes to the options in the print dialogue can be @@ -2767,6 +2771,11 @@ the output for one particular page. image::images/Printpreview.jpg["FIGURE: Print preview page",align="center"] +=== Write a custom printing template (advanced) + +Writing a custom template is an effective way to produce highly customized printouts. Subsurface uses HTML templates with Grantlee as the printing backend. + +See <<_appendix_f_write_a_custom_printing_template ,APPENDIX F>> for information on how to write your own template. [[S_Configure]] == Configuring a dive computer @@ -4137,3 +4146,134 @@ If you have downloaded your dives to different dive logging software before they were overwritten, there is a high change that Subsurface can import these. However, if the logs are only on your dive computer, they cannot be salvaged after being over written by new dives. + +== APPENDIX F: Write a custom printing template + +_Subsurface_ provides a customizable printing support which is based on templates that are transformed by the _Grantlee_ +backend to correct _HTML_ syntax, The _HTML_ output is then rendered by _Subsurface_. + +To write a custom template the following elements must exist so that the template will be correctly handled and rendered. + +=== Main dive loop +_Subsurface_ exports a dive list called (*dives*) to the _Grantlee_ backend. It is possible to iterate over the list as follows: + +.template.html +.... + {% for dive in dives %} + <h1> {{ dive.number }} </h1> + {% endfor %} +.... + +.output.html +.... + <h1> 1 </h1> + <h1> 2 </h1> + <h1> 3 </h1> +.... + +Additional information about _Grantlee_ can be found http://www.grantlee.org/apidox/for_themers.html[here] + +=== Grantlee exported variables +Only a subset of the dive data is exported: +|==================== +|*Name*|*Description* +|number| (*int*) dive number +|id| (*int*) unique dive ID, should be used to fetch the dive profile +|date| (*string*) data of the dive +|time| (*string*) time of the dive +|location| (*string*) location of the dive +|duration| (*string*) duration of the dive +|depth| (*string*) depth of the dive +|divemaster| (*string*) divemaster data +|buddy| (*string*) buddy data +|airTemp| (*string*) air temperature of dive +|waterTemp| (*string*) water temperature of dive +|notes| (*string*) dive notes +|rating| (*int*) dive rating ranges from 0 to 5 +|sac| (*string*) sac value +|tags| (*string*) all dive tags concatenate together +|gas| (*string*) used gas cylinder +|===================== + +_Subsurface_ also exports *template_options* data. This data must be used as _CSS_ values to provide a dynamically +editable template. The exported data is shown in the following table: +|==================== +|*Name*|*Description* +|font| (*string*) font family +|borderwidth| (*int*) border-width value dynamically calculated as 0.1% of the page width with minimum value of 1px +|font_size| (*double*) size of fonts in vw, ranges between 1.0 and 2.0 +|line_spacing| (*double*) distance between text lines, ranges between 1.0 and 3.0 +|color1| (*string*) background color +|color2| (*string*) primary table cell color +|color3| (*string*) secondary table cell color +|color4| (*string*) primary text color +|color5| (*string*) secondary text color +|color6| (*string*) border colors +|===================== + +.template.html +.... + border-width: {{ template_options.borderwidth }}px; +.... + +.output.html +.... + border-width: 3px; +.... + +Another variable that _Subsurface_ exports is *print_options*. This variable contains a single member: +|===================== +|*Name*|*Description* +|grayscale | Use _CSS_ filters to convert the page into grayscale (should be added to body style to enable printing grayscale prints) +|===================== + + +.template.html +.... + body { + {{ print_options.grayscale }}; + } +.... + +.output.html +.... + body { + -webkit-filter: grayscale(100%); + } +.... + +=== Defined CSS selectors + +As the dive profile is placed after rendering, _Subsurface_ uses a special _CSS_ selectors to do some searches +in the HTML output. The _CSS_ selectors in the following table should be added. + +|==================== +|*Selector*|*Type*|*Description* +|dive_{{ dive.id }} | id | is used to fetch the relevant dive profile +|diveProfile | class | each div that will contain a dive profile should have this class selector in addition to the dive_{{ dive.id }} id selector +|dontbreak | class | prevents the div with this class to be divided into two pages, this can be used +in flow layout templates only (when data-numberofdives = 0) +|===================== + +IMPORTANT: Rendering dive profiles is not supported for flow layout templates (when data-numberofdives = 0). + +=== Special attributes + +There are two ways of rendering- either rendering a specific number of dives in each page or make _Subsurface_ try to +fit as much dives as possible into one page (_flow_ rendering). + +The *data-numberofdives* data attribute is added to the body tag to set the rendering mode + +- render 6 dives per page: + +.... + <body data-numberofdives = 6> +.... + +- render as much dives as possible: + +.... + <body data-numberofdives = 0> +.... + +IMPORTANT: All CSS units should be in relative lengths only, to support printing on any page size. diff --git a/printer.cpp b/printer.cpp index b0caa0815..f0197d446 100644 --- a/printer.cpp +++ b/printer.cpp @@ -59,6 +59,11 @@ void Printer::putProfileImage(QRect profilePlaceholder, QRect viewPort, QPainter void Printer::flowRender() { + // add extra padding at the bottom to pages with height not divisible by view port + int paddingBottom = pageSize.height() - (webView->page()->mainFrame()->contentsSize().height() % pageSize.height()); + QString styleString = QString::fromUtf8("padding-bottom: ") + QString::number(paddingBottom) + "px;"; + webView->page()->mainFrame()->findFirstElement("body").setAttribute("style", styleString); + // render the Qwebview QPainter painter; QRect viewPort(0, 0, 0, 0); @@ -90,7 +95,14 @@ void Printer::flowRender() // rendering progress is 4/5 of total work emit(progessUpdated((end * 80.0 / fullPageResolution) + done)); - static_cast<QPrinter*>(paintDevice)->newPage(); + + // add new pages only in print mode, while previewing we don't add new pages + if (printMode == Printer::PRINT) + static_cast<QPrinter*>(paintDevice)->newPage(); + else { + painter.end(); + return; + } start = dontbreakElement.geometry().y(); } } @@ -187,6 +199,7 @@ void Printer::print() return; } + QPrinter *printerPtr; printerPtr = static_cast<QPrinter*>(paintDevice); @@ -194,18 +207,17 @@ void Printer::print() connect(&t, SIGNAL(progressUpdated(int)), this, SLOT(templateProgessUpdated(int))); dpi = printerPtr->resolution(); //rendering resolution = selected paper size in inchs * printer dpi -#if QT_VERSION >= 0x050300 - pageSize.setHeight(printerPtr->pageLayout().paintRectPixels(dpi).height()); - pageSize.setWidth(printerPtr->pageLayout().paintRectPixels(dpi).width()); -#else - pageSize.setHeight(printerPtr->pageRect(QPrinter::Inch).height() * dpi); - pageSize.setWidth(printerPtr->pageRect(QPrinter::Inch).width() * dpi); -#endif + pageSize.setHeight(qCeil(printerPtr->pageRect(QPrinter::Inch).height() * dpi)); + pageSize.setWidth(qCeil(printerPtr->pageRect(QPrinter::Inch).width() * dpi)); webView->page()->setViewportSize(pageSize); webView->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); // export border width with at least 1 pixel templateOptions->border_width = std::max(1, pageSize.width() / 1000); - webView->setHtml(t.generate()); + if (printOptions->type == print_options::DIVELIST) { + webView->setHtml(t.generate()); + } else if (printOptions->type == print_options::STATISTICS ) { + webView->setHtml(t.generateStatistics()); + } if (printOptions->color_selected && printerPtr->colorMode()) { printerPtr->setColorMode(QPrinter::Color); } else { @@ -223,71 +235,13 @@ void Printer::print() } int Pages; if (divesPerPage == 0) { - // add extra padding at the bottom to pages with height not divisible by view port - int paddingBottom = pageSize.height() - (webView->page()->mainFrame()->contentsSize().height() % pageSize.height()); - QString styleString = QString::fromUtf8("padding-bottom: ") + QString::number(paddingBottom) + "px;"; - webView->page()->mainFrame()->findFirstElement("body").setAttribute("style", styleString); flowRender(); } else { - Pages = ceil(getTotalWork(printOptions) / (float)divesPerPage); + Pages = qCeil(getTotalWork(printOptions) / (float)divesPerPage); render(Pages); } } -void Printer::print_statistics() -{ - QPrinter *printerPtr; - printerPtr = static_cast<QPrinter*>(paintDevice); - stats_t total_stats; - - total_stats.selection_size = 0; - total_stats.total_time.seconds = 0; - - QString html; - html += "<table border=1>"; - html += "<tr>"; - html += "<td>Year</td>"; - html += "<td>Dives</td>"; - html += "<td>Total Time</td>"; - html += "<td>Avg Time</td>"; - html += "<td>Shortest Time</td>"; - html += "<td>Longest Time</td>"; - html += "<td>Avg Depth</td>"; - html += "<td>Min Depth</td>"; - html += "<td>Max Depth</td>"; - html += "<td>Avg SAC</td>"; - html += "<td>Min SAC</td>"; - html += "<td>Max SAC</td>"; - html += "<td>Min Temp</td>"; - html += "<td>Max Temp</td>"; - html += "</tr>"; - int i = 0; - while (stats_yearly != NULL && stats_yearly[i].period) { - html += "<tr>"; - html += "<td>" + QString::number(stats_yearly[i].period) + "</td>"; - html += "<td>" + QString::number(stats_yearly[i].selection_size) + "</td>"; - html += "<td>" + QString::fromUtf8(get_time_string(stats_yearly[i].total_time.seconds, 0)) + "</td>"; - html += "<td>" + QString::fromUtf8(get_minutes(stats_yearly[i].total_time.seconds / stats_yearly[i].selection_size)) + "</td>"; - html += "<td>" + QString::fromUtf8(get_minutes(stats_yearly[i].shortest_time.seconds)) + "</td>"; - html += "<td>" + QString::fromUtf8(get_minutes(stats_yearly[i].longest_time.seconds)) + "</td>"; - html += "<td>" + get_depth_string(stats_yearly[i].avg_depth) + "</td>"; - html += "<td>" + get_depth_string(stats_yearly[i].min_depth) + "</td>"; - html += "<td>" + get_depth_string(stats_yearly[i].max_depth) + "</td>"; - html += "<td>" + get_volume_string(stats_yearly[i].avg_sac) + "</td>"; - html += "<td>" + get_volume_string(stats_yearly[i].min_sac) + "</td>"; - html += "<td>" + get_volume_string(stats_yearly[i].max_sac) + "</td>"; - html += "<td>" + QString::number(stats_yearly[i].min_temp == 0 ? 0 : get_temp_units(stats_yearly[i].min_temp, NULL)) + "</td>"; - html += "<td>" + QString::number(stats_yearly[i].max_temp == 0 ? 0 : get_temp_units(stats_yearly[i].max_temp, NULL)) + "</td>"; - html += "</tr>"; - total_stats.selection_size += stats_yearly[i].selection_size; - total_stats.total_time.seconds += stats_yearly[i].total_time.seconds; - i++; - } - html += "</table>"; - webView->setHtml(html); - webView->print(printerPtr); -} - void Printer::previewOnePage() { if (printMode == PREVIEW) { @@ -296,9 +250,24 @@ void Printer::previewOnePage() pageSize.setHeight(paintDevice->height()); pageSize.setWidth(paintDevice->width()); webView->page()->setViewportSize(pageSize); - webView->setHtml(t.generate()); + // initialize the border settings + templateOptions->border_width = std::max(1, pageSize.width() / 1000); + if (printOptions->type == print_options::DIVELIST) { + webView->setHtml(t.generate()); + } else if (printOptions->type == print_options::STATISTICS ) { + webView->setHtml(t.generateStatistics()); + } - // render only one page - render(1); + bool ok; + int divesPerPage = webView->page()->mainFrame()->findFirstElement("body").attribute("data-numberofdives").toInt(&ok); + if (!ok) { + divesPerPage = 1; // print each dive in a single page if the attribute is missing or malformed + //TODO: show warning + } + if (divesPerPage == 0) { + flowRender(); + } else { + render(1); + } } } @@ -39,7 +39,6 @@ public: Printer(QPaintDevice *paintDevice, print_options *printOptions, template_options *templateOptions, PrintMode printMode); ~Printer(); void print(); - void print_statistics(); void previewOnePage(); signals: diff --git a/printing_templates/Six Dives.html b/printing_templates/Six Dives.html index 3f2c7b95e..9d4d1341e 100644 --- a/printing_templates/Six Dives.html +++ b/printing_templates/Six Dives.html @@ -40,11 +40,11 @@ .mainContainer { width: 50%; - height: 33.333333%; + height: 33.333%; margin-left: 0%; margin-right: 0%; - margin-top: 0; - margin-bottom: 0; + margin-top: 0%; + margin-bottom: 0%; overflow: hidden; page-break-inside: avoid; float: left; @@ -111,12 +111,20 @@ text-overflow: ellipsis; line-height: {{ template_options.line_spacing }}; } + + #sixdivespack { + width: 100%; + height: 100%; + } </style> </head> <body data-numberofdives = 6> <div id="body_div"> {% block main_rows %} {% for dive in dives %} + {% if forloop.counter|divisibleby:6 %} + <div id = "sixdivespack"> + {% endif %} <div class="mainContainer"> <div class="innerContainer"> <div class="diveDetails"> @@ -173,6 +181,9 @@ </div> </div> </div> + {% if forloop.counter|divisibleby:6 %} + </div> + {% endif %} {% endfor %} {% endblock %} <div id="footer"> diff --git a/printing_templates/statistics/Default.html b/printing_templates/statistics/Default.html new file mode 100644 index 000000000..4ec02766a --- /dev/null +++ b/printing_templates/statistics/Default.html @@ -0,0 +1,97 @@ +<html> +<head> + <style> + body { + {{ print_options.grayscale }}; + padding: 0; + margin: 0; + font-size: {{ template_options.font_size }}vw; + line-height: {{ template_options.line_spacing }}; + font-family: {{ template_options.font }}; + } + + h1 { + float: left; + font-size: {{ template_options.font_size }}vw; + } + + th { + font-size: {{ template_options.font_size }}vw; + page-break-inside: avoid; + -webkit-column-break-inside: avoid; + padding-top: 1vh; + padding-bottom: 1vh; + -webkit-box-sizing: border-box; + box-sizing: border-box; + border-width: {{ template_options.borderwidth }}px; + border-style:solid; + border-color: {{ template_options.color6 }}; + } + + #body_div { + background-color: {{ template_options.color1 }}; + } + + .mainContainer { + width: 99%; + height: 100%; + margin-left: 0.5%; + margin-right: 0.5%; + margin-top: 0%; + margin-bottom: 0%; + overflow: hidden; + border-width: 0; + page-break-inside: avoid; + } + + .table_class { + overflow: hidden; + width: 100%; + margin: 0%; + } + + </style> +</head> +<body data-numberofdives = 0> +<div id="body_div"> +<table class="table_class"> + <tr style="background-color: {{ template_options.color2 }}; color: {{ template_options.color4 }}"> + <td>Year</td> + <td>Dives</td> + <td>Total Time</td> + <td>Avg Time</td> + <td>Shortest Time</td> + <td>Longest Time</td> + <td>Avg Depth</td> + <td>Min Depth</td> + <td>Max Depth</td> + <td>Avg SAC</td> + <td>Min SAC</td> + <td>Max SAC</td> + <td>Min Temp</td> + <td>Max Temp</td> + </tr> +{% block main_rows %} + {% for year in years %} + <tr class="dontbreak" style="background-color: {{ template_options.color3 }}; color: {{ template_options.color5 }};"> + <td> {{ year.year }} </td> + <td> {{ year.dives }} </td> + <td> {{ year.total_time }} </td> + <td> {{ year.avg_time }} </td> + <td> {{ year.shortest_time }} </td> + <td> {{ year.longest_time }} </td> + <td> {{ year.avg_depth }} </td> + <td> {{ year.min_depth }} </td> + <td> {{ year.max_depth }} </td> + <td> {{ year.avg_sac }} </td> + <td> {{ year.min_sac }} </td> + <td> {{ year.max_sac }} </td> + <td> {{ year.min_temp }} </td> + <td> {{ year.max_temp }} </td> + </tr> + {% endfor %} +{% endblock %} +</table> +</div> +</body> +</html> diff --git a/qt-ui/printdialog.cpp b/qt-ui/printdialog.cpp index 002f9b9f4..cf08062d2 100644 --- a/qt-ui/printdialog.cpp +++ b/qt-ui/printdialog.cpp @@ -178,15 +178,8 @@ void PrintDialog::printClicked(void) { QPrintDialog printDialog(&qprinter, this); if (printDialog.exec() == QDialog::Accepted) { - switch (printOptions.type) { - case print_options::DIVELIST: - connect(printer, SIGNAL(progessUpdated(int)), progressBar, SLOT(setValue(int))); - printer->print(); - break; - case print_options::STATISTICS: - printer->print_statistics(); - break; - } + connect(printer, SIGNAL(progessUpdated(int)), progressBar, SLOT(setValue(int))); + printer->print(); close(); } } @@ -194,14 +187,7 @@ void PrintDialog::printClicked(void) void PrintDialog::onPaintRequested(QPrinter *printerPtr) { connect(printer, SIGNAL(progessUpdated(int)), progressBar, SLOT(setValue(int))); - switch (printOptions.type) { - case print_options::DIVELIST: - printer->print(); - break; - case print_options::STATISTICS: - printer->print_statistics(); - break; - } + printer->print(); progressBar->setValue(0); disconnect(printer, SIGNAL(progessUpdated(int)), progressBar, SLOT(setValue(int))); } diff --git a/qt-ui/printoptions.cpp b/qt-ui/printoptions.cpp index 419098cf8..cb944f9d7 100644 --- a/qt-ui/printoptions.cpp +++ b/qt-ui/printoptions.cpp @@ -31,21 +31,7 @@ void PrintOptions::setup() break; } - // insert existing templates in the UI and select the current template - qSort(grantlee_templates); - int current_index = 0, index = 0; - for (QList<QString>::iterator i = grantlee_templates.begin(); i != grantlee_templates.end(); ++i) { - if ((*i).compare(printOptions->p_template) == 0) { - current_index = index; - break; - } - index++; - } - ui.printTemplate->clear(); - for (QList<QString>::iterator i = grantlee_templates.begin(); i != grantlee_templates.end(); ++i) { - ui.printTemplate->addItem((*i).split('.')[0], QVariant::fromValue(*i)); - } - ui.printTemplate->setCurrentIndex(current_index); + setupTemplates(); // general print option checkboxes if (printOptions->color_selected) @@ -63,6 +49,43 @@ void PrintOptions::setup() hasSetupSlots = true; } +void PrintOptions::setupTemplates() +{ + if (printOptions->type == print_options::DIVELIST) { + // insert dive list templates in the UI and select the current template + qSort(grantlee_templates); + int current_index = 0, index = 0; + for (QList<QString>::iterator i = grantlee_templates.begin(); i != grantlee_templates.end(); ++i) { + if ((*i).compare(printOptions->p_template) == 0) { + current_index = index; + break; + } + index++; + } + ui.printTemplate->clear(); + for (QList<QString>::iterator i = grantlee_templates.begin(); i != grantlee_templates.end(); ++i) { + ui.printTemplate->addItem((*i).split('.')[0], QVariant::fromValue(*i)); + } + ui.printTemplate->setCurrentIndex(current_index); + } else if (printOptions->type == print_options::STATISTICS) { + // insert statistics templates in the UI and select the current template + qSort(grantlee_statistics_templates); + int current_index = 0, index = 0; + for (QList<QString>::iterator i = grantlee_statistics_templates.begin(); i != grantlee_statistics_templates.end(); ++i) { + if ((*i).compare(printOptions->p_template) == 0) { + current_index = index; + break; + } + index++; + } + ui.printTemplate->clear(); + for (QList<QString>::iterator i = grantlee_statistics_templates.begin(); i != grantlee_statistics_templates.end(); ++i) { + ui.printTemplate->addItem((*i).split('.')[0], QVariant::fromValue(*i)); + } + ui.printTemplate->setCurrentIndex(current_index); + } +} + // print type radio buttons void PrintOptions::on_radioDiveListPrint_toggled(bool check) { @@ -70,15 +93,14 @@ void PrintOptions::on_radioDiveListPrint_toggled(bool check) printOptions->type = print_options::DIVELIST; // print options - ui.printInColor->setEnabled(true); ui.printSelected->setEnabled(true); // print template ui.deleteButton->setEnabled(true); - ui.editButton->setEnabled(true); ui.exportButton->setEnabled(true); ui.importButton->setEnabled(true); - ui.printTemplate->setEnabled(true); + + setupTemplates(); } } @@ -88,15 +110,14 @@ void PrintOptions::on_radioStatisticsPrint_toggled(bool check) printOptions->type = print_options::STATISTICS; // print options - ui.printInColor->setEnabled(false); ui.printSelected->setEnabled(false); // print template ui.deleteButton->setEnabled(false); - ui.editButton->setEnabled(false); ui.exportButton->setEnabled(false); ui.importButton->setEnabled(false); - ui.printTemplate->setEnabled(false); + + setupTemplates(); } } diff --git a/qt-ui/printoptions.h b/qt-ui/printoptions.h index 6d7ffffee..9c50b10f3 100644 --- a/qt-ui/printoptions.h +++ b/qt-ui/printoptions.h @@ -70,6 +70,7 @@ private: struct print_options *printOptions; struct template_options *templateOptions; bool hasSetupSlots; + void setupTemplates(); private slots: diff --git a/qt-ui/templateedit.cpp b/qt-ui/templateedit.cpp index e4e6453ac..b50338090 100644 --- a/qt-ui/templateedit.cpp +++ b/qt-ui/templateedit.cpp @@ -35,6 +35,9 @@ TemplateEdit::TemplateEdit(QWidget *parent, struct print_options *printOptions, ui->plainTextEdit->setPlainText(grantlee_template); editingCustomColors = false; + if (printOptions->type == print_options::STATISTICS) { + ui->plainTextEdit->setEnabled(false); + } updatePreview(); } @@ -125,8 +128,8 @@ void TemplateEdit::saveSettings() if (msgBox.exec() == QMessageBox::Save) { memcpy(templateOptions, &newTemplateOptions, sizeof(struct template_options)); if (grantlee_template.compare(ui->plainTextEdit->toPlainText())) { - printOptions->p_template = "custom.html"; - TemplateLayout::writeTemplate("custom.html", ui->plainTextEdit->toPlainText()); + printOptions->p_template = "Custom.html"; + TemplateLayout::writeTemplate("Custom.html", ui->plainTextEdit->toPlainText()); } if (templateOptions->color_palette_index == CUSTOM) { custom_colors = templateOptions->color_palette; diff --git a/templatelayout.cpp b/templatelayout.cpp index b0098fbd9..c52968f09 100644 --- a/templatelayout.cpp +++ b/templatelayout.cpp @@ -4,7 +4,7 @@ #include "helpers.h" #include "display.h" -QList<QString> grantlee_templates; +QList<QString> grantlee_templates, grantlee_statistics_templates; int getTotalWork(print_options *printOptions) { @@ -24,6 +24,7 @@ int getTotalWork(print_options *printOptions) void find_all_templates() { grantlee_templates.clear(); + grantlee_statistics_templates.clear(); QDir dir(getSubsurfaceDataPath("printing_templates")); QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot); foreach (QFileInfo finfo, list) { @@ -32,6 +33,15 @@ void find_all_templates() grantlee_templates.append(finfo.fileName()); } } + // find statistics templates + dir.setPath(getSubsurfaceDataPath("printing_templates") + QDir::separator() + "statistics"); + list = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot); + foreach (QFileInfo finfo, list) { + QString filename = finfo.fileName(); + if (filename.at(filename.size() - 1) != '~') { + grantlee_statistics_templates.append(finfo.fileName()); + } + } } TemplateLayout::TemplateLayout(print_options *PrintOptions, template_options *templateOptions) : @@ -98,6 +108,53 @@ QString TemplateLayout::generate() return htmlContent; } +QString TemplateLayout::generateStatistics() +{ + QString htmlContent; + m_engine = new Grantlee::Engine(this); + + QSharedPointer<Grantlee::FileSystemTemplateLoader> m_templateLoader = + QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader()); + m_templateLoader->setTemplateDirs(QStringList() << getSubsurfaceDataPath("printing_templates/statistics")); + m_engine->addTemplateLoader(m_templateLoader); + + Grantlee::registerMetaType<YearInfo>(); + Grantlee::registerMetaType<template_options>(); + Grantlee::registerMetaType<print_options>(); + + QVariantHash mapping; + QVariantList years; + + int i = 0; + while (stats_yearly != NULL && stats_yearly[i].period) { + YearInfo year(stats_yearly[i]); + years.append(QVariant::fromValue(year)); + i++; + } + + mapping.insert("years", years); + mapping.insert("template_options", QVariant::fromValue(*templateOptions)); + mapping.insert("print_options", QVariant::fromValue(*PrintOptions)); + + Grantlee::Context c(mapping); + + Grantlee::Template t = m_engine->loadByName(PrintOptions->p_template); + if (!t || t->error()) { + qDebug() << "Can't load template"; + return htmlContent; + } + + htmlContent = t->render(&c); + + if (t->error()) { + qDebug() << "Can't render template"; + return htmlContent; + } + + emit progressUpdated(100); + return htmlContent; +} + QString TemplateLayout::readTemplate(QString template_name) { QFile qfile(getSubsurfaceDataPath("printing_templates") + QDir::separator() + template_name); @@ -306,3 +363,13 @@ void Dive::put_sac() m_sac = QString::number(value, 'f', decimal).append(unit); } } + +YearInfo::YearInfo() +{ + +} + +YearInfo::~YearInfo() +{ + +} diff --git a/templatelayout.h b/templatelayout.h index 41a3cbfa9..d9fa29295 100644 --- a/templatelayout.h +++ b/templatelayout.h @@ -4,11 +4,13 @@ #include <grantlee_templates.h> #include "mainwindow.h" #include "printoptions.h" +#include "statistics.h" +#include "helpers.h" int getTotalWork(print_options *printOptions); void find_all_templates(); -extern QList<QString> grantlee_templates; +extern QList<QString> grantlee_templates, grantlee_statistics_templates; class TemplateLayout : public QObject { Q_OBJECT @@ -16,6 +18,7 @@ public: TemplateLayout(print_options *PrintOptions, template_options *templateOptions); ~TemplateLayout(); QString generate(); + QString generateStatistics(); static QString readTemplate(QString template_name); static void writeTemplate(QString template_name, QString grantlee_template); @@ -98,9 +101,22 @@ public: QString sac() const; }; +class YearInfo { +public: + stats_t *year; + YearInfo(stats_t& year) + :year(&year) + { + + } + YearInfo(); + ~YearInfo(); +}; + Q_DECLARE_METATYPE(Dive) Q_DECLARE_METATYPE(template_options) Q_DECLARE_METATYPE(print_options) +Q_DECLARE_METATYPE(YearInfo) GRANTLEE_BEGIN_LOOKUP(Dive) if (property == "number") @@ -182,4 +198,40 @@ if (property == "grayscale") { } GRANTLEE_END_LOOKUP +GRANTLEE_BEGIN_LOOKUP(YearInfo) +if (property == "year") { + return object.year->period; +} else if (property == "dives") { + return object.year->selection_size; +} else if (property == "min_temp") { + const char *unit; + double temp = get_temp_units(object.year->min_temp, &unit); + return object.year->min_temp == 0 ? "0" : QString::number(temp, 'g', 2) + unit; +} else if (property == "max_temp") { + const char *unit; + double temp = get_temp_units(object.year->max_temp, &unit); + return object.year->max_temp == 0 ? "0" : QString::number(temp, 'g', 2) + unit; +} else if (property == "total_time") { + return get_time_string(object.year->total_time.seconds, 0); +} 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); +} +GRANTLEE_END_LOOKUP + #endif |