Hello all, As we are approaching gsoc community bonding period so I thought that a small prototype may be the best way to discuss my thoughts with the community. I sent a group of patches with a very small but full working prototype.
- I added Grantlee library to subsurface code base (thanks for the cmake build environment it made my life much easier as I don't know qmake at all) - I create a simple Grantlee template that prints two dives per page. - the TemplateLayout class iterates the selected dives and interface with Grantlee backend. - QWebview and QPainter are used to render the html file living in a QTemporaryFile object. - finally I added the "print using templates" option in the print dialog. Note: I tested this on Linux only, so there may be problems on other platforms. also many exceptions still need to be handled this is only a fast prototype for discussion. So you may test this and tell me what do you think? -- regards, Gehad
From d274d487dd500d50788517fd42787937c18398cd Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Wed, 15 Apr 2015 21:00:19 +0200 Subject: [PATCH 1/9] Create two dives per page grantlee template Signed-off-by: Gehad elrobey <[email protected]> --- printing_templates/base.html | 86 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 printing_templates/base.html diff --git a/printing_templates/base.html b/printing_templates/base.html new file mode 100644 index 0000000..b38cb19 --- /dev/null +++ b/printing_templates/base.html @@ -0,0 +1,86 @@ +<html> +<head> +<style> +body { + background-color:white; + padding:0px; + margin:0px; +} + +h1 { + font-size: 0.9cm; + float:left; +} + +.class1{ + width:96%; + height:50%; + margin-left:2%; + margin-right:2%; + margin-top:0; + margin-bottom:0; + overflow:hidden; + border-width:0px; + page-break-inside: avoid; +} + +.table_class{ + overflow:hidden; + max-width:44%; + min-width:44%; + box-shadow: 5px 5px 5px #888888; +} + +.g{ + background-color:#CfC7C5; + overflow:hidden; +} + +</style> +</head> + +<body> +{% block main_rows %} + {% for dive in dives %} + <div class="class1"> + <div style="height:85%;border-style:solid;padding:0.5%;margin-top:1%;margin-bottom:1%;overflow: hidden;"> + <div style="width:52%;float:left;"> + <table class="table_class" border="1" style="margin:1.5%;float:left;"> + <tr> + <td class="g"><h1> Dive No. </h1></td><td><h1> {{ dive.number }} </h1></td> + </tr> + <tr> + <td class="g"><h1> Date </h1></td><td><h1> {{ dive.date }} </h1></td> + </tr> + <tr> + <td class="g"><h1> Location </h1></td><td><h1>{{ dive.location }}</h1></td> + </tr> + <tr> + <td class="g"><h1> Max depth </h1></td><td><h1> {{ dive.depth }} </h1></td> + </tr> + <tr> + <td class="g"><h1> Duration </h1></td><td><h1> {{ dive.duration }} </h1></td> + </tr> + <tr> + <td class="g"><h1> Dive Master </h1></td><td><h1>{{ dive.divemaster }}</h1></td> + </tr> + </table> + <table class="table_class" border="1" style="margin:1.5%;width:47%;float:left;"> + <tr> + <td class="g"><h1> Notes </h1></td> + </tr> + <tr> + <td><h1>-</h1></td> + </tr> + </table> + </div> + <div class="diveprofile" style="width:40%;height:50%;margin:1.5%;float:right;border-style:solid;padding:3mm;"> + <h1>Dive profile area</h1> + </div> + </div> + </div> + {% endfor %} +{% endblock %} +</body> + +</html> -- 1.9.1
From 74b123112b68c929a949a2201ed10539451cce50 Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Sun, 12 Apr 2015 19:19:26 +0200 Subject: [PATCH 2/9] Add Printer class that holds the rendering logic. Render Html pages into a QWebView then print it using QPainter. the Printer::print() is called that prepare the HTML file to be rendered by the QWebView. Printer::render() will do the rendering task. Signed-off-by: Gehad elrobey <[email protected]> --- CMakeLists.txt | 1 + printer.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ printer.h | 21 +++++++++++++++ qt-ui/mainwindow.cpp | 3 +++ subsurface.pro | 6 +++-- 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 printer.cpp create mode 100644 printer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f6d713..4d42987 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ SET(SUBSURFACE_CORE_LIB_SRCS configuredivecomputer.cpp configuredivecomputerthreads.cpp divesitehelpers.cpp + printer.cpp ${PLATFORM_SRC} ) diff --git a/printer.cpp b/printer.cpp new file mode 100644 index 0000000..d861057 --- /dev/null +++ b/printer.cpp @@ -0,0 +1,72 @@ +#include "printer.h" + +#include <QPrintDialog> +#include <QPrinter> +#include <QtWebKitWidgets> +#include <QUrl> +#include <QPrintDialog> +#include <QWebElement> +#include <QWebElementCollection> + +#define A4_300DPI_WIDTH 2480 +#define A4_300DPI_HIGHT 3508 + +QWebView *webView; + +void Printer::putFrame(QRect box, QRect viewPort, QPainter *painter) +{ + if(!viewPort.contains(box)) + return; + + int x = box.x() - viewPort.x(); + int y = box.y() - viewPort.y(); + int x1 = box.width() + x; + int y1 = box.height() + y; + + QRect rec(x, y, box.width(), box.height()); + painter->fillRect(x, y, box.width(), box.height(), QColor("#CfC7C5")); + painter->drawText(rec, Qt::AlignCenter, "Profile Area"); +} + +void Printer::render(bool ok) +{ + QPrinter printer; + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName("/home/dive.pdf"); + printer.setFullPage(true); + printer.setOrientation(QPrinter::Portrait); + printer.setPaperSize(QPrinter::A4); + printer.setPrintRange(QPrinter::AllPages); + printer.setResolution(300); + + QPainter painter; + + QSize size(A4_300DPI_WIDTH, A4_300DPI_HIGHT); + painter.begin(&printer); + painter.setRenderHint(QPainter::Antialiasing); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + + webView->page()->setViewportSize(size); + + int Pages = ceil( (float) webView->page()->mainFrame()->contentsSize().rheight() / A4_300DPI_HIGHT); + for (int i =0; i < Pages;i++) { + QRect viewPort(0, A4_300DPI_HIGHT*i, A4_300DPI_WIDTH, A4_300DPI_HIGHT); + webView->page()->mainFrame()->render(&painter, QWebFrame::ContentsLayer); + webView->page()->mainFrame()->scroll(0, A4_300DPI_HIGHT); + QWebElementCollection collection = webView->page()->mainFrame()->findAllElements(".diveprofile"); + foreach (QWebElement paraElement, collection) { + putFrame(paraElement.geometry(),viewPort, &painter); + } + if (i < Pages -1) + printer.newPage(); + } + painter.end(); +} + +void Printer::print() +{ + QUrl qurl("file:///tmp/dives.html"); + webView = new QWebView(); + webView->load(qurl); + connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(render(bool))); +} diff --git a/printer.h b/printer.h new file mode 100644 index 0000000..4c0bc70 --- /dev/null +++ b/printer.h @@ -0,0 +1,21 @@ +#ifndef PRINTER_H +#define PRINTER_H +#include "QDebug" +#include <QPainter> + +class Printer : public QObject +{ + Q_OBJECT +public: + Printer() { + + } + void print(); +private: + void putFrame(QRect box, QRect viewPort, QPainter *painter); +private +slots: + void render(bool ok); +}; + +#endif //PRINTER_H diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index e22f340..8cf1ec3 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -28,6 +28,7 @@ #ifndef NO_PRINTING #include <QPrintDialog> #include "printdialog.h" +#include "printer.h" #endif #include "divelogimportdialog.h" #include "divelogexportdialog.h" @@ -431,6 +432,8 @@ void MainWindow::updateLastUsedDir(const QString &dir) void MainWindow::on_actionPrint_triggered() { #ifndef NO_PRINTING + Printer *p = new Printer(); + p->print(); PrintDialog dlg(this); dlg.exec(); diff --git a/subsurface.pro b/subsurface.pro index bec7d65..4dda8b8 100644 --- a/subsurface.pro +++ b/subsurface.pro @@ -113,7 +113,8 @@ HEADERS = \ qt-ui/diveshareexportdialog.h \ qt-ui/filtermodels.h \ qt-ui/undocommands.h \ - qt-ui/notificationwidget.h + qt-ui/notificationwidget.h \ + printer.h android: HEADERS -= \ qt-ui/usermanual.h \ @@ -214,7 +215,8 @@ SOURCES = \ qt-ui/filtermodels.cpp \ qt-ui/undocommands.cpp \ qt-ui/notificationwidget.cpp \ - ostctools.c + ostctools.c \ + printer.cpp android: SOURCES += android.cpp else: win32: SOURCES += windows.c -- 1.9.1
From 465acc71beb2aee5e097289c58688e24c1946e3c Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Sun, 12 Apr 2015 19:55:08 +0200 Subject: [PATCH 3/9] Integration with subsurface printing dialog Add option for experimental printing using templates in the existing printing dialog. Signed-off-by: Gehad elrobey <[email protected]> --- display.h | 3 ++- qt-ui/mainwindow.cpp | 3 --- qt-ui/printlayout.cpp | 5 +++++ qt-ui/printoptions.cpp | 9 ++++++++ qt-ui/printoptions.h | 1 + qt-ui/printoptions.ui | 59 ++++++++++++++++++++++++++++---------------------- 6 files changed, 50 insertions(+), 30 deletions(-) diff --git a/display.h b/display.h index f010144..1946f1f 100644 --- a/display.h +++ b/display.h @@ -40,7 +40,8 @@ struct print_options { PRETTY, TABLE, TWOPERPAGE, - ONEPERPAGE + ONEPERPAGE, + TEMPLATEBASED } type; bool print_selected; bool color_selected; diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 8cf1ec3..e22f340 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -28,7 +28,6 @@ #ifndef NO_PRINTING #include <QPrintDialog> #include "printdialog.h" -#include "printer.h" #endif #include "divelogimportdialog.h" #include "divelogexportdialog.h" @@ -432,8 +431,6 @@ void MainWindow::updateLastUsedDir(const QString &dir) void MainWindow::on_actionPrint_triggered() { #ifndef NO_PRINTING - Printer *p = new Printer(); - p->print(); PrintDialog dlg(this); dlg.exec(); diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp index 4be5fef..bc0e463 100644 --- a/qt-ui/printlayout.cpp +++ b/qt-ui/printlayout.cpp @@ -11,6 +11,7 @@ #include "modeldelegates.h" #include "models.h" #include "profile/profilewidget2.h" +#include "printer.h" PrintLayout::PrintLayout(PrintDialog *dialogPtr, QPrinter *printerPtr, struct print_options *optionsPtr) { @@ -81,6 +82,10 @@ void PrintLayout::print() case print_options::TABLE: printTable(); break; + case print_options::TEMPLATEBASED: + Printer *p = new Printer(); + p->print(); + break; } } diff --git a/qt-ui/printoptions.cpp b/qt-ui/printoptions.cpp index d3e148c..dbdcba1 100644 --- a/qt-ui/printoptions.cpp +++ b/qt-ui/printoptions.cpp @@ -29,6 +29,9 @@ void PrintOptions::setup(struct print_options *printOpt) case print_options::TABLE: ui.radioTablePrint->setChecked(true); break; + case print_options::TEMPLATEBASED: + ui.radioTemplateBased->setChecked(true); + break; } // general print option checkboxes if (printOptions->color_selected) @@ -49,6 +52,7 @@ void PrintOptions::setup(struct print_options *printOpt) connect(ui.radioTwoDives, SIGNAL(clicked(bool)), this, SLOT(radioTwoDivesClicked(bool))); connect(ui.radioOneDive, SIGNAL(clicked(bool)), this, SLOT(radioOneDiveClicked(bool))); connect(ui.radioTablePrint, SIGNAL(clicked(bool)), this, SLOT(radioTablePrintClicked(bool))); + connect(ui.radioTemplateBased, SIGNAL(clicked(bool)), this, SLOT(radioTemplateBasedClicked(bool))); connect(ui.printInColor, SIGNAL(clicked(bool)), this, SLOT(printInColorClicked(bool))); connect(ui.printSelected, SIGNAL(clicked(bool)), this, SLOT(printSelectedClicked(bool))); @@ -79,6 +83,11 @@ void PrintOptions::radioTablePrintClicked(bool check) printOptions->type = print_options::TABLE; } +void PrintOptions::radioTemplateBasedClicked(bool check) +{ + printOptions->type = print_options::TEMPLATEBASED; +} + // general print option checkboxes void PrintOptions::printInColorClicked(bool check) { diff --git a/qt-ui/printoptions.h b/qt-ui/printoptions.h index 658e7ec..a439313 100644 --- a/qt-ui/printoptions.h +++ b/qt-ui/printoptions.h @@ -24,6 +24,7 @@ slots: void radioTwoDivesClicked(bool check); void radioOneDiveClicked(bool check); void radioTablePrintClicked(bool check); + void radioTemplateBasedClicked(bool check); void printInColorClicked(bool check); void printSelectedClicked(bool check); void notesOnTopClicked(bool check); diff --git a/qt-ui/printoptions.ui b/qt-ui/printoptions.ui index 59a48b9..d26a51b 100644 --- a/qt-ui/printoptions.ui +++ b/qt-ui/printoptions.ui @@ -29,8 +29,8 @@ <string>Print type</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0" colspan="2"> - <widget class="QRadioButton" name="radioSixDives"> + <item row="4" column="0" colspan="2"> + <widget class="QRadioButton" name="radioTwoDives"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -38,15 +38,12 @@ </sizepolicy> </property> <property name="text"> - <string>&6 dives per page</string> - </property> - <property name="checked"> - <bool>true</bool> + <string>&2 dives per page</string> </property> </widget> </item> - <item row="2" column="0"> - <widget class="QRadioButton" name="radioOneDive"> + <item row="1" column="2"> + <widget class="QRadioButton" name="radioTablePrint"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -54,12 +51,25 @@ </sizepolicy> </property> <property name="text"> - <string>&1 dive per page</string> + <string>&Table print</string> </property> </widget> </item> - <item row="3" column="0" colspan="2"> - <widget class="QRadioButton" name="radioTwoDives"> + <item row="3" column="2" rowspan="2"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QRadioButton" name="radioSixDives"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -67,12 +77,15 @@ </sizepolicy> </property> <property name="text"> - <string>&2 dives per page</string> + <string>&6 dives per page</string> + </property> + <property name="checked"> + <bool>true</bool> </property> </widget> </item> - <item row="0" column="2"> - <widget class="QRadioButton" name="radioTablePrint"> + <item row="3" column="0"> + <widget class="QRadioButton" name="radioOneDive"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -80,22 +93,16 @@ </sizepolicy> </property> <property name="text"> - <string>&Table print</string> + <string>&1 dive per page</string> </property> </widget> </item> - <item row="2" column="2" rowspan="2"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> + <item row="5" column="0" colspan="3"> + <widget class="QRadioButton" name="radioTemplateBased"> + <property name="text"> + <string>Template based print (experimental)</string> </property> - </spacer> + </widget> </item> </layout> </widget> -- 1.9.1
From 9fccceab8a13aa57d01be392f59a2478edae5ea6 Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Mon, 13 Apr 2015 00:32:08 +0200 Subject: [PATCH 4/9] Use the existing QPrinter in printer.cpp Pass the existing QPrinter object to the printer class, the QPrinter object is changed to be dynamically allocated as it is used by async function Printer::render() that runs after printlayout.cpp is closed. The QPrinter object needs to be freed correctely. Signed-off-by: Gehad elrobey <[email protected]> --- printer.cpp | 14 +++----------- printer.h | 11 ++++++++++- qt-ui/printdialog.cpp | 21 +++++++++++---------- qt-ui/printdialog.h | 2 +- qt-ui/printlayout.cpp | 2 +- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/printer.cpp b/printer.cpp index d861057..6674ac3 100644 --- a/printer.cpp +++ b/printer.cpp @@ -30,19 +30,10 @@ void Printer::putFrame(QRect box, QRect viewPort, QPainter *painter) void Printer::render(bool ok) { - QPrinter printer; - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setOutputFileName("/home/dive.pdf"); - printer.setFullPage(true); - printer.setOrientation(QPrinter::Portrait); - printer.setPaperSize(QPrinter::A4); - printer.setPrintRange(QPrinter::AllPages); - printer.setResolution(300); - QPainter painter; QSize size(A4_300DPI_WIDTH, A4_300DPI_HIGHT); - painter.begin(&printer); + painter.begin(printer); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); @@ -58,9 +49,10 @@ void Printer::render(bool ok) putFrame(paraElement.geometry(),viewPort, &painter); } if (i < Pages -1) - printer.newPage(); + printer->newPage(); } painter.end(); + delete printer; } void Printer::print() diff --git a/printer.h b/printer.h index 4c0bc70..0f3e582 100644 --- a/printer.h +++ b/printer.h @@ -2,16 +2,25 @@ #define PRINTER_H #include "QDebug" #include <QPainter> +#include <QPrinter> class Printer : public QObject { Q_OBJECT public: - Printer() { + Printer(QPrinter *printer) { + this->printer = printer; + //override these settings + printer->setFullPage(true); + printer->setOrientation(QPrinter::Portrait); + printer->setPaperSize(QPrinter::A4); + printer->setPrintRange(QPrinter::AllPages); + printer->setResolution(300); } void print(); private: + QPrinter *printer; void putFrame(QRect box, QRect viewPort, QPainter *painter); private slots: diff --git a/qt-ui/printdialog.cpp b/qt-ui/printdialog.cpp index fbf71c4..c3f6db0 100644 --- a/qt-ui/printdialog.cpp +++ b/qt-ui/printdialog.cpp @@ -17,6 +17,7 @@ PrintDialog::PrintDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { + printer = new QPrinter(); // check if the options were previously stored in the settings; if not use some defaults. QSettings s; bool stored = s.childGroups().contains(SETTINGS_GROUP); @@ -38,16 +39,16 @@ PrintDialog::PrintDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f printOptions.margins[1] = s.value("margin_top").toInt(); printOptions.margins[2] = s.value("margin_right").toInt(); printOptions.margins[3] = s.value("margin_bottom").toInt(); - printer.setOrientation((QPrinter::Orientation)printOptions.landscape); + printer->setOrientation((QPrinter::Orientation)printOptions.landscape); #if QT_VERSION >= 0x050300 QMarginsF margins; margins.setLeft(printOptions.margins[0]); margins.setTop(printOptions.margins[1]); margins.setRight(printOptions.margins[2]); margins.setBottom(printOptions.margins[3]); - printer.setPageMargins(margins, QPageLayout::Millimeter); + printer->setPageMargins(margins, QPageLayout::Millimeter); #else - printer.setPageMargins( + printer->setPageMargins( printOptions.margins[0], printOptions.margins[1], printOptions.margins[2], @@ -58,7 +59,7 @@ PrintDialog::PrintDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f } // create a print layout and pass the printer and options - printLayout = new PrintLayout(this, &printer, &printOptions); + printLayout = new PrintLayout(this, printer, &printOptions); // create a print options object and pass our options struct optionsWidget = new PrintOptions(this, &printOptions); @@ -116,16 +117,16 @@ void PrintDialog::onFinished() s.setValue("color_selected", printOptions.color_selected); s.setValue("notes_up", printOptions.notes_up); #if QT_VERSION >= 0x050300 - s.setValue("landscape", (bool)printer.pageLayout().orientation()); - QMarginsF margins = printer.pageLayout().margins(QPageLayout::Millimeter); + s.setValue("landscape", (bool)printer->pageLayout().orientation()); + QMarginsF margins = printer->pageLayout().margins(QPageLayout::Millimeter); s.setValue("margin_left", margins.left()); s.setValue("margin_top", margins.top()); s.setValue("margin_right", margins.right()); s.setValue("margin_bottom", margins.bottom()); #else - s.setValue("landscape", (bool)printer.orientation()); + s.setValue("landscape", (bool)printer->orientation()); qreal left, top, right, bottom; - printer.getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter); + printer->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter); s.setValue("margin_left", (int)left); s.setValue("margin_top", (int)top); s.setValue("margin_right", (int)right); @@ -135,7 +136,7 @@ void PrintDialog::onFinished() void PrintDialog::previewClicked(void) { - QPrintPreviewDialog previewDialog(&printer, this, Qt::Window + QPrintPreviewDialog previewDialog(printer, this, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowTitleHint); @@ -145,7 +146,7 @@ void PrintDialog::previewClicked(void) void PrintDialog::printClicked(void) { - QPrintDialog printDialog(&printer, this); + QPrintDialog printDialog(printer, this); if (printDialog.exec() == QDialog::Accepted){ printLayout->print(); close(); diff --git a/qt-ui/printdialog.h b/qt-ui/printdialog.h index b42102d..5ed56f3 100644 --- a/qt-ui/printdialog.h +++ b/qt-ui/printdialog.h @@ -20,7 +20,7 @@ private: PrintOptions *optionsWidget; PrintLayout *printLayout; QProgressBar *progressBar; - QPrinter printer; + QPrinter *printer; struct print_options printOptions; private diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp index bc0e463..8d1965f 100644 --- a/qt-ui/printlayout.cpp +++ b/qt-ui/printlayout.cpp @@ -83,7 +83,7 @@ void PrintLayout::print() printTable(); break; case print_options::TEMPLATEBASED: - Printer *p = new Printer(); + Printer *p = new Printer(printer); p->print(); break; } -- 1.9.1
From 73c01f71b161e49c53722481bb16c6ec9e9d746b Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Mon, 13 Apr 2015 00:56:21 +0200 Subject: [PATCH 5/9] CMAKE: Require Grantlee library -find Grantlee package -configure grantlee_paths.h -install the printing_templates directory Include Grantlee package Signed-off-by: Gehad elrobey <[email protected]> --- CMakeLists.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d42987..8749d3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,10 +54,22 @@ IF(NOT (insource OR insourcedir)) add_custom_target(link_marble_data ALL COMMAND rm -f marbledata && ln -s ${${PROJECT_NAME}_SOURCE_DIR}/marbledata ${${PROJECT_NAME}_BINARY_DIR}/marbledata) ENDIF() +#setup Grantlee + +find_package(Grantlee5) + +get_property(Grantlee_PLUGIN_DIR TARGET Grantlee5::defaulttags PROPERTY LOCATION) +GET_FILENAME_COMPONENT(Grantlee_PLUGIN_DIR ${Grantlee_PLUGIN_DIR} PATH) +GET_FILENAME_COMPONENT(Grantlee_PLUGIN_DIR ${Grantlee_PLUGIN_DIR} PATH) +GET_FILENAME_COMPONENT(Grantlee_PLUGIN_DIR ${Grantlee_PLUGIN_DIR} PATH) + +configure_file(grantlee_paths.h.cmake ${PROJECT_BINARY_DIR}/grantlee_paths.h) + + #configure Qt. FIND_PACKAGE(Qt5 REQUIRED COMPONENTS Core Concurrent Widgets Network WebKitWidgets PrintSupport Svg Test LinguistTools) -SET(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::WebKitWidgets Qt5::PrintSupport Qt5::Svg) +SET(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::WebKitWidgets Qt5::PrintSupport Qt5::Svg Grantlee5::Templates) SET(QT_TEST_LIBRARIES ${QT_LIBRARIES} Qt5::Test) # Generate the ssrf-config.h every 'make' @@ -387,6 +399,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") install(DIRECTORY Documentation/images DESTINATION ${RESOURCEDIR}/share/Documentation) install(FILES ${DOCFILES} DESTINATION ${RESOURCEDIR}/share/Documentation) install(DIRECTORY theme DESTINATION ${RESOURCEDIR}) + install(DIRECTORY printing_templates DESTINATION ${RESOURCEDIR}) install(FILES ${TRANSLATIONS} DESTINATION ${RESOURCEDIR}/translations) install(FILES ${QTTRANSLATIONS} DESTINATION ${RESOURCEDIR}/translations) install(FILES ${CMAKE_SOURCE_DIR}/gpl-2.0.txt DESTINATION ${RESOURCEDIR}) @@ -407,6 +420,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") install(DIRECTORY Documentation/images DESTINATION ${WINDOWSSTAGING}/Documentation) install(FILES ${DOCFILES} DESTINATION ${WINDOWSSTAGING}/Documentation) install(DIRECTORY theme DESTINATION ${WINDOWSSTAGING}) + install(DIRECTORY printing_templates DESTINATION ${WINDOWSSTAGING}) install(FILES ${TRANSLATIONS} DESTINATION ${WINDOWSSTAGING}/translations) install(FILES ${QTTRANSLATIONS} DESTINATION ${WINDOWSSTAGING}/translations) install(FILES ${CMAKE_SOURCE_DIR}/gpl-2.0.txt ${CMAKE_SOURCE_DIR}/packaging/windows/subsurface.ico DESTINATION ${WINDOWSSTAGING}) @@ -493,6 +507,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") install(DIRECTORY Documentation/images DESTINATION share/subsurface/Documentation) install(FILES ${DOCFILES} DESTINATION share/subsurface/Documentation) install(DIRECTORY theme DESTINATION share/subsurface) + install(DIRECTORY printing_templates DESTINATION share/subsurface) install(FILES ${TRANSLATIONS} DESTINATION share/subsurface/translations) install(TARGETS ${SUBSURFACE_TARGET} DESTINATION bin) IF(DEFINED LIBMARBLEDEVEL) -- 1.9.1
From cb901cc6dcace5dee06923dc8ed52aa2286252af Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Tue, 14 Apr 2015 15:15:37 +0200 Subject: [PATCH 6/9] Add TemplateLayout class This is the main class to hold Grantlee engine logic. TemplateLayout::generate() loads QT5Grantlee and initialize the templates then returns a QTemporaryFile that contains the rendered HTML by Grantlee library. Also the class holds Dive class which holds the logic that passes the data to the templates. A better way to interface the data with Grantlee can be found instead of copying the data into the memory. Signed-off-by: Gehad elrobey <[email protected]> --- CMakeLists.txt | 1 + printer.cpp | 33 +++++++------------ printer.h | 8 ++--- templatelayout.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ templatelayout.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 195 insertions(+), 26 deletions(-) create mode 100644 templatelayout.cpp create mode 100644 templatelayout.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8749d3f..6b9cf54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,6 +208,7 @@ SET(SUBSURFACE_CORE_LIB_SRCS configuredivecomputerthreads.cpp divesitehelpers.cpp printer.cpp + templatelayout.cpp ${PLATFORM_SRC} ) diff --git a/printer.cpp b/printer.cpp index 6674ac3..5e60712 100644 --- a/printer.cpp +++ b/printer.cpp @@ -1,7 +1,8 @@ #include "printer.h" +#include "templatelayout.h" #include <QPrintDialog> -#include <QPrinter> +#include <QPainter> #include <QtWebKitWidgets> #include <QUrl> #include <QPrintDialog> @@ -13,23 +14,13 @@ QWebView *webView; -void Printer::putFrame(QRect box, QRect viewPort, QPainter *painter) +void Printer::render(bool ok) { - if(!viewPort.contains(box)) + if (!ok) { + //handle the error return; + } - int x = box.x() - viewPort.x(); - int y = box.y() - viewPort.y(); - int x1 = box.width() + x; - int y1 = box.height() + y; - - QRect rec(x, y, box.width(), box.height()); - painter->fillRect(x, y, box.width(), box.height(), QColor("#CfC7C5")); - painter->drawText(rec, Qt::AlignCenter, "Profile Area"); -} - -void Printer::render(bool ok) -{ QPainter painter; QSize size(A4_300DPI_WIDTH, A4_300DPI_HIGHT); @@ -44,21 +35,19 @@ void Printer::render(bool ok) QRect viewPort(0, A4_300DPI_HIGHT*i, A4_300DPI_WIDTH, A4_300DPI_HIGHT); webView->page()->mainFrame()->render(&painter, QWebFrame::ContentsLayer); webView->page()->mainFrame()->scroll(0, A4_300DPI_HIGHT); - QWebElementCollection collection = webView->page()->mainFrame()->findAllElements(".diveprofile"); - foreach (QWebElement paraElement, collection) { - putFrame(paraElement.geometry(),viewPort, &painter); - } if (i < Pages -1) printer->newPage(); } painter.end(); - delete printer; + + //TODO delete the printer object } void Printer::print() { - QUrl qurl("file:///tmp/dives.html"); + TemplateLayout *t = new TemplateLayout(); webView = new QWebView(); - webView->load(qurl); + webView->load(t->generate()); connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(render(bool))); + delete t; } diff --git a/printer.h b/printer.h index 0f3e582..583fb35 100644 --- a/printer.h +++ b/printer.h @@ -1,7 +1,6 @@ #ifndef PRINTER_H #define PRINTER_H -#include "QDebug" -#include <QPainter> + #include <QPrinter> class Printer : public QObject @@ -11,17 +10,18 @@ public: Printer(QPrinter *printer) { this->printer = printer; - //override these settings + //override these settings for now. printer->setFullPage(true); printer->setOrientation(QPrinter::Portrait); printer->setPaperSize(QPrinter::A4); printer->setPrintRange(QPrinter::AllPages); printer->setResolution(300); } + ~Printer(){ } void print(); private: QPrinter *printer; - void putFrame(QRect box, QRect viewPort, QPainter *painter); + private slots: void render(bool ok); diff --git a/templatelayout.cpp b/templatelayout.cpp new file mode 100644 index 0000000..e01c896 --- /dev/null +++ b/templatelayout.cpp @@ -0,0 +1,93 @@ +#include <string> + +#include "templatelayout.h" +#include "grantlee_paths.h" +#include "helpers.h" + +QTemporaryFile *TemplateLayout::generate() +{ + QTemporaryFile *file; + m_engine = new Grantlee::Engine(this); + + QSharedPointer<Grantlee::FileSystemTemplateLoader> m_templateLoader = + QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader()); + m_templateLoader->setTemplateDirs(QStringList() << getSubsurfaceDataPath("printing_templates")); + m_engine->setPluginPaths( QStringList() << GRANTLEE_PLUGIN_PATH ); + m_engine->addTemplateLoader(m_templateLoader); + + QVariantHash mapping; + QVariantList diveList; + + struct dive *dive; + int i; + QObject *d; + for_each_dive (i, dive) { + //TODO check for exporting selected dives only + if (!dive->selected) + continue; + d = new Dive(dive, this); + diveList.append(QVariant::fromValue(d)); + } + + mapping.insert("dives", diveList); + + Grantlee::Context c(mapping); + + Grantlee::Template t = m_engine->loadByName("base.html"); + if (!t || t->error()) { + qDebug() << "Can't to load template"; + return file; + } + + file = new QTemporaryFile(QDir::tempPath() + QDir::separator() + "subsurface_XXXXXX.html"); + if (!file->open()){ + qDebug() << "Can't write here."; + return file; + } + + QString content = t->render(&c); + + if (t->error()) { + qDebug() << "Can't render template"; + return file; + } + file->write(content.toLocal8Bit()); + file->close(); + return file; +} + +void Dive::put_divemaster() +{ + if (!dive->divemaster) + m_divemaster = ""; + else + m_divemaster = dive->divemaster; +} + +void Dive::put_time() +{ + struct tm tm; + utc_mkdate(dive->when, &tm); + char b[100]; + sprintf(b, "%04u-%02u-%02u", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + m_date = QString::fromUtf8(b); +} + +void Dive::put_location() +{ + m_location = QString::fromUtf8(get_dive_location(dive)); +} + +void Dive::put_depth() +{ + char b[100]; + sprintf(b, "%0.2f m", dive->dc.maxdepth.mm/1000.0); + m_depth = QString::fromUtf8(b); +} + +void Dive::put_duration() +{ + char b[100]; + sprintf(b, "%u:%02u min", FRACTION(dive->dc.duration.seconds, 60)); + m_duration = QString::fromUtf8(b); +} diff --git a/templatelayout.h b/templatelayout.h new file mode 100644 index 0000000..55205e4 --- /dev/null +++ b/templatelayout.h @@ -0,0 +1,86 @@ +#ifndef TEMPLATELAYOUT +#define TEMPLATELAYOUT + +#include <QUrl> +#include <QTemporaryFile> + +#include <grantlee_templates.h> +#include "mainwindow.h" + +class TemplateLayout : public QObject { + Q_OBJECT +public: + TemplateLayout() {}; + ~TemplateLayout(){ + delete m_engine; + }; + QTemporaryFile *generate(); +private: + Grantlee::Engine *m_engine; +}; + +//I think I am wasting time copying the object into memory. +//May be there is a better way to genrate the objects. +class Dive : public QObject { + Q_OBJECT + Q_PROPERTY(int number READ number) + Q_PROPERTY(QString divemaster READ divemaster) + Q_PROPERTY(QString date READ date) + Q_PROPERTY(QString location READ location) + Q_PROPERTY(QString depth READ depth) + Q_PROPERTY(QString duration READ duration) + +private: + QString m_divemaster; + QString m_date; + QString m_location; + QString m_depth; + QString m_duration; + int m_number; + struct dive *dive; + void put_divemaster(); + void put_time(); + void put_location(); + void put_depth(); + void put_duration(); + +public: + Dive(struct dive *dive, QObject *parent = 0) + : QObject(parent), dive(dive) + { + m_number = dive->number; + put_divemaster(); + put_time(); + put_location(); + put_depth(); + put_duration(); + } + ~Dive(){ } + + QString divemaster() + { + return m_divemaster; + } + QString date() + { + return m_date; + } + QString location() + { + return m_location; + } + QString depth() + { + return m_depth; + } + QString duration() + { + return m_duration; + } + int number() + { + return m_number; + } +}; + +#endif -- 1.9.1
From 462b2205e44025437e959e112278155288447d9a Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Wed, 15 Apr 2015 20:58:46 +0200 Subject: [PATCH 7/9] Handle QTemporaryFile generated by template. Signed-off-by: Gehad elrobey <[email protected]> --- printer.cpp | 15 ++++++++++----- printer.h | 10 ++++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/printer.cpp b/printer.cpp index 5e60712..88445c8 100644 --- a/printer.cpp +++ b/printer.cpp @@ -4,6 +4,7 @@ #include <QPrintDialog> #include <QPainter> #include <QtWebKitWidgets> +#include <QTemporaryFile> #include <QUrl> #include <QPrintDialog> #include <QWebElement> @@ -12,17 +13,15 @@ #define A4_300DPI_WIDTH 2480 #define A4_300DPI_HIGHT 3508 -QWebView *webView; - void Printer::render(bool ok) { if (!ok) { //handle the error + qDebug() << "Error rendering the page"; return; } QPainter painter; - QSize size(A4_300DPI_WIDTH, A4_300DPI_HIGHT); painter.begin(printer); painter.setRenderHint(QPainter::Antialiasing); @@ -41,13 +40,19 @@ void Printer::render(bool ok) painter.end(); //TODO delete the printer object + // a Signal must be emited here + delete tempFile; } void Printer::print() { TemplateLayout *t = new TemplateLayout(); webView = new QWebView(); - webView->load(t->generate()); - connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(render(bool))); + tempFile = t->generate(); + if (tempFile) { + QUrl url("file:///" + tempFile->fileName()); + webView->load(url); + connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(render(bool))); + } delete t; } diff --git a/printer.h b/printer.h index 583fb35..2df26e5 100644 --- a/printer.h +++ b/printer.h @@ -2,10 +2,18 @@ #define PRINTER_H #include <QPrinter> +#include <QTemporaryFile> +#include <QWebView> class Printer : public QObject { Q_OBJECT + +private: + QPrinter *printer; + QTemporaryFile *tempFile; + QWebView *webView; + public: Printer(QPrinter *printer) { this->printer = printer; @@ -19,8 +27,6 @@ public: } ~Printer(){ } void print(); -private: - QPrinter *printer; private slots: -- 1.9.1
From 412928c10e53b98b77d504ea0aee9ddfdb291dcf Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Wed, 15 Apr 2015 20:59:51 +0200 Subject: [PATCH 8/9] Add dyanmic paths to Grantlee plugins Signed-off-by: Gehad elrobey <[email protected]> --- grantlee_paths.h.cmake | 1 + 1 file changed, 1 insertion(+) create mode 100644 grantlee_paths.h.cmake diff --git a/grantlee_paths.h.cmake b/grantlee_paths.h.cmake new file mode 100644 index 0000000..00006d2 --- /dev/null +++ b/grantlee_paths.h.cmake @@ -0,0 +1 @@ +#define GRANTLEE_PLUGIN_PATH "@Grantlee_PLUGIN_DIR@" -- 1.9.1
From e631a263d04bda5476cb4699935ecb93cd835c40 Mon Sep 17 00:00:00 2001 From: Gehad elrobey <[email protected]> Date: Wed, 15 Apr 2015 21:11:53 +0200 Subject: [PATCH 9/9] Organize Imports Signed-off-by: Gehad elrobey <[email protected]> --- printer.cpp | 7 +------ templatelayout.h | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/printer.cpp b/printer.cpp index 88445c8..7907a56 100644 --- a/printer.cpp +++ b/printer.cpp @@ -1,14 +1,9 @@ #include "printer.h" #include "templatelayout.h" -#include <QPrintDialog> -#include <QPainter> #include <QtWebKitWidgets> -#include <QTemporaryFile> +#include <QPainter> #include <QUrl> -#include <QPrintDialog> -#include <QWebElement> -#include <QWebElementCollection> #define A4_300DPI_WIDTH 2480 #define A4_300DPI_HIGHT 3508 diff --git a/templatelayout.h b/templatelayout.h index 55205e4..7e8c2ce 100644 --- a/templatelayout.h +++ b/templatelayout.h @@ -1,8 +1,8 @@ #ifndef TEMPLATELAYOUT #define TEMPLATELAYOUT -#include <QUrl> #include <QTemporaryFile> +#include <QUrl> #include <grantlee_templates.h> #include "mainwindow.h" -- 1.9.1
_______________________________________________ subsurface mailing list [email protected] http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface
