On 04/19/2015 10:43 PM, Lubomir I. Ivanov wrote:
> On 16 April 2015 at 01:14, Gehad Elrobey <gehadelro...@gmail.com> wrote:
>> 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?
> 
> 
> hello Gehad,
> 
> here are some generic comments on the patches (+ some more important
> structural ones!).
> i won't be able to provide more until i'm able to build; for some
> reason that UIC error still pops out (the one i explained in the the
> previous email).
> 

Lubomir,

I have attached a new series of cleaner patches, and I have considered
your remarks.

> --------------------
> 0001
> 
> it won't be a bad idea to use the same/similar coding style across all
> formats, being HTML, XML, CSS, JS.
> this includes whitespace indentation of realtabs, spaces after ":" in
> class properties, etc.
> 

Fixed in the attached patches.

> --------------------
> 0002
> this patch should be split into more...
> 
> diff --git a/printer.cpp b/printer.cpp
> 
> for the Printer class, have you considered our plans to use the same
> backend for the facebook share?
> 

I plan to add a new constructor to the Printer class with other paint
devices, also different options can be set for each rendering device.

> +#define A4_300DPI_WIDTH 2480
> +#define A4_300DPI_HIGHT 3508
> 
> i don't think we need to hardcode A4 or any other page sizes in the
> render related class files. the class files should be able to render
> to any size.
> what the printer setup (user setup) returns is of importance and what
> we are interested in.
> 

I am going to add TemplateEdit class that will handle the user setup and
extra printing settings which I didn't implement yet, so these values
exist in this prototype only.

> +QWebView *webView;
> 
> global variables are not really desired, that should be a member of some 
> class.
> 
> + int Pages = ceil( (float)
> webView->page()->mainFrame()->contentsSize().rheight() /
> A4_300DPI_HIGHT);
> + for (int i =0; i < Pages;i++) {
> 
> coding style in the for() loop.
> 
> +void Printer::print()
> +{
> + QUrl qurl("file:///tmp/dives.html");
> 
> there is no such path on Windows. we should avoid temporary files and
> load the HTML from memory.
> 
> diff --git a/printer.h b/printer.h
> ....
> +public:
> + Printer() {
> +
> + }
> 
> we should not have definitions in the header even if the constructor
> is empty. this is code for the .cpp file.
> 
> +private:
> + void putFrame(QRect box, QRect viewPort, QPainter *painter);
> +private
> +slots:
> + void render(bool ok);
> 
> coding style!  accessors groups should be separated by new lines,
> ideally. the extra "private before "slots:" is redundant.
> 
> diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.c
> ...
> + Printer *p = new Printer();
> + p->print();
>   PrintDialog dlg(this);
> 
> i don't like the fact that MainWindow is aware of the existence of the
> Printer class. it should only know of PrintDialog, where an instance
> of Printer should be maintained (if that is the structure we keep on
> using. please see bellow).
> 

Fixed in the attached patches

> --------------------
> 0004
> 
> diff --git a/printer.cpp b/printer.cpp
> 
> - 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);
> -
> 
> using an existing instance should have been the case in the first
> place. this patch removes code which was previously added in the
> series. it would be best to rebase the series.
> 
> in the train of though for using existing render targets (e.g.
> QPrinter) i'm sure we can use QPaintDevice pointers as the rendering
> class should not care if said target is a QPrinter or a QPixmap (for
> the facebook) share. my point here is that the Printer class (or
> DivePrinter, or PrintLayout) should be a class which renders dives on
> surface / render target and only cares about it's dimensions. ideally,
> Printer should not be aware if the render target is a QPrinter.

as I mentioned above I think social network sharing and prints will be
handled slightly different so we can add different constructors for the
printer class with special flags so a social network printer is passed a
QPixmap while paper printer is passed a QPrinter.

> i'm pretty sure the diagram in your proposal followed logic which was similar.
> 
> --------------------
> 0005
> 
> the cmake setup for Granlee is a bit of an issue. i need to be able to
> test this on my end if i want to mentor this GSOC project in the first
> place. :-(
> i may have to add the option GRANTLEE_FROM_PKGCONFIG. please have a
> look at some of my recent patches that are now in master, so that you
> can understand what i mean.
> 
> +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)
> 
> why add the same line multiple times? is this something weird that
> cmake requires?

I removed these lines as apparently we don't need any Grantlee Plug-ins now.

> SET(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network
> Qt5::WebKitWidgets Qt5::PrintSupport Qt5::Svg Grantlee5::Templates)
> 
> we don't have Marble (another Qt lib) in this list. why add Grantlee here?
> wouldn't it be better to keep this list for Qt built-in libraries only?
> 

Fixed in the attached patches

> diff --git a/templatelayout.cpp b/templatelayout.cpp
> ...
> 
> ah, i see. so this is the class that will provide the Grantlee related work.
> i can't comment much on that ATM, but i do understand the need for a
> Grantlee specific class. i think of it the following way - ideally
> only a *single* class in the Subsurface code base should be aware that
> we are using Grantlee.
> 

templatLayout is the only class that will need to call Grantlee.

> -------
> 0008
> 
> diff --git a/grantlee_paths.h.cmake b/grantlee_paths.h.cmake
> +#define GRANTLEE_PLUGIN_PATH "@Grantlee_PLUGIN_DIR@"
> 
> i don't understand how this work, Grantlee wise. can you please
> explain in detail?

This passes Grantlee plugin dir path dynamically to the Grantlee engine,
I removed it from the attached patches, as we don't need grantlee
plugins in the meantime.

> 
> that's all for now.
> please ask any questions that you may have or make sure to point any
> of my comments that you don't agree with.
> 

Thanks for your detailed review.


-- 
regards,
Gehad elrobey


From 02789db44509305093bb918145e0c5cbadce6bba Mon Sep 17 00:00:00 2001
From: Gehad elrobey <gehadelro...@gmail.com>
Date: Wed, 15 Apr 2015 21:00:19 +0200
Subject: [PATCH 1/5] Create two dives per page grantlee template

Signed-off-by: Gehad elrobey <gehadelro...@gmail.com>
---
 printing_templates/base.html | 143 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 143 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..f7f5beb
--- /dev/null
+++ b/printing_templates/base.html
@@ -0,0 +1,143 @@
+<html>
+<head>
+	<style>
+		body
+		{
+			background-color : white;
+			padding : 0px;
+			margin : 0px;
+		}
+
+		h1
+		{
+			font-size : 0.9cm;
+			float : left;
+		}
+
+		.mainContainer
+		{
+			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;
+		}
+
+		.innerContainer
+		{
+			height : 85%;
+			border-style : solid;
+			padding : 0.5%;
+			margin-top : 1%;
+			margin-bottom : 1%;
+			overflow : hidden;
+		}
+
+		.table_class
+		{
+			overflow : hidden;
+			max-width : 44%;
+			min-width : 44%;
+			box-shadow : 5px 5px 5px #888888;
+			margin : 1.5%;
+			float : left;
+		}
+
+		.textArea
+		{
+			background-color:#CfC7C5;
+			overflow:hidden;
+		}
+
+		.diveProfile
+		{
+			width : 40%;
+			height : 50%;
+			margin : 1.5%;
+			float : right;
+			border-style : solid;
+			padding : 3mm;
+		}
+	</style>
+</head>
+<body>
+{% block main_rows %}
+	{% for dive in dives %}
+		<div class = "mainContainer">
+			<div class = "innerContainer">
+				<div style = "width:52%;float:left;">
+					<table class = "table_class" border = "1">
+						<tr>
+							<td class = "textArea">
+								<h1> Dive No. </h1>
+							</td>
+							<td>
+								<h1> {{ dive.number }} </h1>
+							</td>
+						</tr>
+						<tr>
+							<td class = "textArea">
+								<h1> Date </h1>
+							</td>
+								<td><h1> {{ dive.date }} </h1>
+							</td>
+						</tr>
+						<tr>
+							<td class = "textArea">
+								<h1> Location </h1>
+							</td>
+							<td>
+								<h1> {{ dive.location }} </h1>
+							</td>
+						</tr>
+						<tr>
+							<td class = "textArea">
+								<h1> Max depth </h1>
+							</td>
+							<td>
+								<h1> {{ dive.depth }} </h1>
+							</td>
+						</tr>
+						<tr>
+							<td class = "textArea">
+								<h1> Duration </h1>
+							</td>
+							<td>
+								<h1> {{ dive.duration }} </h1>
+							</td>
+						</tr>
+						<tr>
+							<td class = "textArea">
+								<h1> Dive Master </h1>
+							</td>
+							<td>
+								<h1> {{ dive.divemaster }} </h1>
+							</td>
+						</tr>
+					</table>
+					<table class = "table_class" border = "1">
+						<tr>
+							<td class = "textArea">
+								<h1> Notes </h1>
+							</td>
+						</tr>
+						<tr>
+							<td>
+								<h1>-</h1>
+							</td>
+						</tr>
+					</table>
+				</div>
+				<div class = "diveProfile">
+					<h1> Dive profile area </h1>
+				</div>
+			</div>
+		</div>
+	{% endfor %}
+{% endblock %}
+</body>
+</html>
-- 
1.9.1


From 584de7b94ff7a364b92d2207d28ac6cb29eab62d Mon Sep 17 00:00:00 2001
From: Gehad elrobey <gehadelro...@gmail.com>
Date: Tue, 21 Apr 2015 17:15:40 +0200
Subject: [PATCH 2/5] CMAKE: Require Grantlee library

-find Grantlee package
-install the printing_templates directory

Signed-off-by: Gehad elrobey <gehadelro...@gmail.com>
---
 CMakeLists.txt | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a961292..80d6106 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,7 +67,12 @@ if(NO_MARBLE)
 	set(MARBLE_LIBRARIES "")
 endif()
 
-set(SUBSURFACE_LINK_LIBRARIES ${SUBSURFACE_LINK_LIBRARIES} ${LIBDIVECOMPUTER_LIBRARIES} ${LIBGIT2_LIBRARIES} -lusb-1.0)
+# setup Grantlee
+
+find_package(Grantlee5)
+set(GRANTLEE_LIBRARIES Grantlee5::Templates)
+
+set(SUBSURFACE_LINK_LIBRARIES ${SUBSURFACE_LINK_LIBRARIES} ${LIBDIVECOMPUTER_LIBRARIES} ${LIBGIT2_LIBRARIES} ${GRANTLEE_LIBRARIES} -lusb-1.0)
 
 # handle out of tree build correctly
 
@@ -427,6 +432,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})
@@ -447,6 +453,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})
@@ -535,6 +542,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 dfb3824c686245b4cea6d2f06b24efc1fd4f6261 Mon Sep 17 00:00:00 2001
From: Gehad elrobey <gehadelro...@gmail.com>
Date: Tue, 21 Apr 2015 17:23:13 +0200
Subject: [PATCH 3/5] Add TemplateLayout class

This is the main class to hold Grantlee engine logic.
TemplateLayout::generate() loads QT5Grantlee and initialize the
templates then returns a QString 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 <gehadelro...@gmail.com>
---
 CMakeLists.txt     |  1 +
 subsurface.pro     |  2 ++
 templatelayout.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 templatelayout.h   | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 177 insertions(+)
 create mode 100644 templatelayout.cpp
 create mode 100644 templatelayout.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 80d6106..3616346 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -229,6 +229,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
 	configuredivecomputer.cpp
 	configuredivecomputerthreads.cpp
 	divesitehelpers.cpp
+	templatelayout.cpp
 	${PLATFORM_SRC}
 )
 
diff --git a/subsurface.pro b/subsurface.pro
index bec7d65..4936219 100644
--- a/subsurface.pro
+++ b/subsurface.pro
@@ -51,6 +51,7 @@ HEADERS = \
 	qthelper.h \
 	units.h \
 	divecomputer.h \
+	templatelayout.h \
 	qt-ui/about.h \
 	qt-ui/completionmodels.h \
 	qt-ui/divecomputermanagementdialog.h \
@@ -144,6 +145,7 @@ SOURCES =  \
 	profile.c \
 	gaspressures.c \
 	divecomputer.cpp \
+	templatelayout.cpp \
 	worldmap-save.c \
 	save-html.c \
 	qt-gui.cpp \
diff --git a/templatelayout.cpp b/templatelayout.cpp
new file mode 100644
index 0000000..40a2e39
--- /dev/null
+++ b/templatelayout.cpp
@@ -0,0 +1,93 @@
+#include <string>
+
+#include "templatelayout.h"
+#include "helpers.h"
+
+TemplateLayout::TemplateLayout()
+{
+}
+
+TemplateLayout::~TemplateLayout()
+{
+	delete m_engine;
+};
+
+QString TemplateLayout::generate()
+{
+	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"));
+	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 load template";
+		return htmlContent;
+	}
+
+	htmlContent = t->render(&c);
+
+	if (t->error()) {
+		qDebug() << "Can't render template";
+		return htmlContent;
+	}
+
+	return htmlContent;
+}
+
+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..f9c37d9
--- /dev/null
+++ b/templatelayout.h
@@ -0,0 +1,81 @@
+#ifndef TEMPLATELAYOUT_H
+#define TEMPLATELAYOUT_H
+
+#include <grantlee_templates.h>
+#include "mainwindow.h"
+
+class TemplateLayout : public QObject {
+	Q_OBJECT
+public:
+	TemplateLayout();
+	~TemplateLayout();
+	QString 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();
+	}
+
+	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 9868fa35d3b4c75e6f1b813e3ff3b8330532ba53 Mon Sep 17 00:00:00 2001
From: Gehad elrobey <gehadelro...@gmail.com>
Date: Tue, 21 Apr 2015 18:05:20 +0200
Subject: [PATCH 4/5] 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 <gehadelro...@gmail.com>
---
 CMakeLists.txt |  1 +
 printer.cpp    | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 printer.h      | 20 ++++++++++++++++++++
 subsurface.pro |  2 ++
 4 files changed, 72 insertions(+)
 create mode 100644 printer.cpp
 create mode 100644 printer.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3616346..7d1c112 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -230,6 +230,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
 	configuredivecomputerthreads.cpp
 	divesitehelpers.cpp
 	templatelayout.cpp
+	printer.cpp
 	${PLATFORM_SRC}
 )
 
diff --git a/printer.cpp b/printer.cpp
new file mode 100644
index 0000000..dda07e0
--- /dev/null
+++ b/printer.cpp
@@ -0,0 +1,49 @@
+#include "printer.h"
+#include "templatelayout.h"
+
+#include <QtWebKitWidgets>
+#include <QPainter>
+
+#define A4_300DPI_WIDTH 2480
+#define A4_300DPI_HIGHT 3508
+
+Printer::Printer(QPrinter *printer)
+{
+	this->printer = printer;
+
+	//override these settings for now.
+	printer->setFullPage(true);
+	printer->setOrientation(QPrinter::Portrait);
+	printer->setPaperSize(QPrinter::A4);
+	printer->setPrintRange(QPrinter::AllPages);
+	printer->setResolution(300);
+}
+
+void Printer::render()
+{
+	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);
+		if (i < Pages - 1)
+			printer->newPage();
+	}
+	painter.end();
+}
+
+void Printer::print()
+{
+	TemplateLayout t;
+	webView = new QWebView();
+	webView->setHtml(t.generate());
+	render();
+}
diff --git a/printer.h b/printer.h
new file mode 100644
index 0000000..3b574d1
--- /dev/null
+++ b/printer.h
@@ -0,0 +1,20 @@
+#ifndef PRINTER_H
+#define PRINTER_H
+
+#include <QPrinter>
+#include <QWebView>
+
+class Printer : public QObject {
+	Q_OBJECT
+
+private:
+	QPrinter *printer;
+	QWebView *webView;
+	void render();
+
+public:
+	Printer(QPrinter *printer);
+	void print();
+};
+
+#endif //PRINTER_H
diff --git a/subsurface.pro b/subsurface.pro
index 4936219..999c2ef 100644
--- a/subsurface.pro
+++ b/subsurface.pro
@@ -52,6 +52,7 @@ HEADERS = \
 	units.h \
 	divecomputer.h \
 	templatelayout.h \
+	printer.h \
 	qt-ui/about.h \
 	qt-ui/completionmodels.h \
 	qt-ui/divecomputermanagementdialog.h \
@@ -146,6 +147,7 @@ SOURCES =  \
 	gaspressures.c \
 	divecomputer.cpp \
 	templatelayout.cpp \
+	printer.cpp \
 	worldmap-save.c \
 	save-html.c \
 	qt-gui.cpp \
-- 
1.9.1


From 08e677af4ea1db73d135c66afd9035a282c06a19 Mon Sep 17 00:00:00 2001
From: Gehad elrobey <gehadelro...@gmail.com>
Date: Tue, 21 Apr 2015 19:17:54 +0200
Subject: [PATCH 5/5] Integration with subsurface printing dialog

Add option for custom printing using templates in the existing
printing dialog.

Signed-off-by: Gehad elrobey <gehadelro...@gmail.com>
---
 display.h              |  3 ++-
 qt-ui/printlayout.cpp  |  5 +++++
 qt-ui/printoptions.cpp |  9 ++++++++
 qt-ui/printoptions.h   |  1 +
 qt-ui/printoptions.ui  | 59 ++++++++++++++++++++++++++++----------------------
 5 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/display.h b/display.h
index f010144..6a3ba8f 100644
--- a/display.h
+++ b/display.h
@@ -40,7 +40,8 @@ struct print_options {
 		PRETTY,
 		TABLE,
 		TWOPERPAGE,
-		ONEPERPAGE
+		ONEPERPAGE,
+		CUSTOM
 	} type;
 	bool print_selected;
 	bool color_selected;
diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp
index 4be5fef..4520786 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::CUSTOM:
+		Printer p(printer);
+		p.print();
+		break;
 	}
 }
 
diff --git a/qt-ui/printoptions.cpp b/qt-ui/printoptions.cpp
index d3e148c..c46c9b1 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::CUSTOM:
+		ui.radioCustomPrint->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.radioCustomPrint, SIGNAL(clicked(bool)), this, SLOT(radioCustomPrintClicked(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::radioCustomPrintClicked(bool check)
+{
+	printOptions->type = print_options::CUSTOM;
+}
+
 // general print option checkboxes
 void PrintOptions::printInColorClicked(bool check)
 {
diff --git a/qt-ui/printoptions.h b/qt-ui/printoptions.h
index 658e7ec..a65848b 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 radioCustomPrintClicked(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..1b98b83 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>&amp;6 dives per page</string>
-        </property>
-        <property name="checked">
-         <bool>true</bool>
+         <string>&amp;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>&amp;1 dive per page</string>
+         <string>&amp;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>&amp;2 dives per page</string>
+         <string>&amp;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>&amp;Table print</string>
+         <string>&amp;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="radioCustomPrint">
+        <property name="text">
+         <string>Custom print (experimental)</string>
         </property>
-       </spacer>
+       </widget>
       </item>
      </layout>
     </widget>
-- 
1.9.1


_______________________________________________
subsurface mailing list
subsurface@subsurface-divelog.org
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to