Pārlūkot izejas kodu

Partly fix issue 366: allow for custum SVG for checkboxes and radio buttons

Antialize 15 gadi atpakaļ
vecāks
revīzija
a2141b031a

+ 1 - 1
common.pri

@@ -43,4 +43,4 @@ win32 {
     CONFIG += console
 }
 
-QT += webkit network xmlpatterns
+QT += webkit network xmlpatterns svg

+ 8 - 1
include/wkhtmltox/converter.hh

@@ -24,8 +24,9 @@
 #endif
 
 #include <QObject>
-
+#include <wkhtmltox/loadsettings.hh>
 #include <wkhtmltox/dllbegin.inc>
+
 namespace wkhtmltopdf {
 
 class DLL_LOCAL ConverterPrivate;
@@ -46,11 +47,17 @@ signals:
     void phaseChanged();
     void progressChanged(int progress);
     void finished(bool ok);
+
+	void checkboxSvgChanged(const QString & path);
+	void checkboxCheckedSvgChanged(const QString & path);
+	void radiobuttonSvgChanged(const QString & path);
+	void radiobuttonCheckedSvgChanged(const QString & path);
 public slots:
     void beginConvertion();
 	bool convert();
 	void cancel();
 protected:
+	void emitCheckboxSvgs(const settings::LoadPage & ls);
 	virtual ConverterPrivate & priv() = 0;
 	friend class ConverterPrivate;
 };

+ 8 - 2
include/wkhtmltox/dllbegin.inc

@@ -37,10 +37,16 @@
   #endif
 #endif
 
+#if defined _WIN32
+#define CALLTYPE __stdcall
+#else
+#define CALLTYPE
+#endif
+
 #ifdef __cplusplus
-  #define CAPI extern "C" DLL_PUBLIC
+  #define CAPI extern "C" DLL_PUBLIC CALLTYPE
 #else
-  #define CAPI DLL_PUBLIC
+  #define CAPI DLL_PUBLIC CALLTYPE
 #endif
 
 #endif /*__WKHTMLTOPDF_DLLBEGIN__*/

+ 1 - 0
include/wkhtmltox/dllend.inc

@@ -23,5 +23,6 @@
 #undef DLL_PUBLIC
 #undef DLL_LOCAL
 #undef CAPI
+#undef CALLTYPE
 
 #endif /*__WKHTMLTOPDF_DLLBEGIN__*/

+ 5 - 0
include/wkhtmltox/loadsettings.hh

@@ -110,6 +110,11 @@ struct DLL_PUBLIC LoadPage {
 
 	//! Additional javascript to run on a page once it has loaded
 	QList< QString > runScript;
+
+	QString checkboxSvg;
+	QString checkboxCheckedSvg;
+	QString radiobuttonSvg;
+	QString radiobuttonCheckedSvg;
 };
 
 DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);

+ 10 - 0
include/wkhtmltox/utilities.hh

@@ -30,6 +30,7 @@
 #include <QImageWriter>
 #include <QPainter>
 #include <QStyleOption>
+#include <QSvgRenderer>
 #include <QUrl>
 
 #include <wkhtmltox/dllbegin.inc>
@@ -43,8 +44,17 @@ public:
 	MyLooksStyle();
 	void drawPrimitive( PrimitiveElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget = 0 ) const;
 	bool weAreDrawingForms;
+
+	static QSvgRenderer * checkbox;
+	static QSvgRenderer * checkbox_checked;
+	static QSvgRenderer * radiobutton;
+	static QSvgRenderer * radiobutton_checked;
 public slots:
 	void producingForms(bool f);
+	void setCheckboxSvg(const QString & path);
+	void setCheckboxCheckedSvg(const QString & path);
+	void setRadioButtonSvg(const QString & path);
+	void setRadioButtonCheckedSvg(const QString & path);
 };
 
 DLL_PUBLIC int handleError(bool success, int errorCode);

+ 7 - 2
src/image/wkhtmltoimage.cc

@@ -43,11 +43,16 @@ int main(int argc, char** argv) {
 #endif
 #endif
 	QApplication a(argc, argv, use_graphics);
-	a.setStyle(new MyLooksStyle());
+	MyLooksStyle * style = new MyLooksStyle();
+	a.setStyle(style);
 
 	//Create the actual page converter to convert the pages
 	wkhtmltopdf::ImageConverter converter(settings);
-
+	QObject::connect(&converter, SIGNAL(checkboxSvgChanged(const QString &)), style, SLOT(setCheckboxSvg(const QString &)));
+	QObject::connect(&converter, SIGNAL(checkboxCheckedSvgChanged(const QString &)), style, SLOT(setCheckboxCheckedSvg(const QString &)));
+	QObject::connect(&converter, SIGNAL(radiobuttonSvgChanged(const QString &)), style, SLOT(setRadioButtonSvg(const QString &)));
+	QObject::connect(&converter, SIGNAL(radiobuttonCheckedSvgChanged(const QString &)), style, SLOT(setRadioButtonCheckedSvg(const QString &)));
+	
 	wkhtmltopdf::ProgressFeedback feedback(settings.quiet, converter);
 	bool success = converter.convert();
 	return handleError(success, converter.httpErrorCode());

+ 6 - 0
src/lib/converter.cc

@@ -154,5 +154,11 @@ void Converter::cancel() {
 	priv().cancel();
 }
 
+void Converter::emitCheckboxSvgs(const settings::LoadPage & ls) {
+	emit checkboxSvgChanged(ls.checkboxSvg);
+	emit checkboxCheckedSvgChanged(ls.checkboxCheckedSvg);
+	emit radiobuttonSvgChanged(ls.radiobuttonSvg);
+	emit radiobuttonCheckedSvgChanged(ls.radiobuttonCheckedSvg);
+}
 
 }

+ 8 - 1
src/lib/converter.hh

@@ -27,8 +27,9 @@
 #endif
 
 #include <QObject>
-
+#include <wkhtmltox/loadsettings.hh>
 #include <wkhtmltox/dllbegin.inc>
+
 namespace wkhtmltopdf {
 
 class DLL_LOCAL ConverterPrivate;
@@ -49,11 +50,17 @@ signals:
     void phaseChanged();
     void progressChanged(int progress);
     void finished(bool ok);
+
+	void checkboxSvgChanged(const QString & path);
+	void checkboxCheckedSvgChanged(const QString & path);
+	void radiobuttonSvgChanged(const QString & path);
+	void radiobuttonCheckedSvgChanged(const QString & path);
 public slots:
     void beginConvertion();
 	bool convert();
 	void cancel();
 protected:
+	void emitCheckboxSvgs(const settings::LoadPage & ls);
 	virtual ConverterPrivate & priv() = 0;
 	friend class ConverterPrivate;
 };

+ 3 - 1
src/lib/imageconverter.cc

@@ -45,6 +45,7 @@ ImageConverterPrivate::ImageConverterPrivate(ImageConverter & o, wkhtmltopdf::se
 	settings(s),
 	loader(s.loadGlobal),
 	out(o) {
+	out.emitCheckboxSvgs(s.loadPage);
 	if (data) inputData = *data;
 
 	phaseDescriptions.push_back("Loading page");
@@ -148,6 +149,7 @@ void ImageConverterPrivate::pagesLoaded(bool ok) {
 	} if (settings.out != "-" ) {
 		file.setFileName(settings.out);
 		openOk = file.open(QIODevice::WriteOnly);
+		qDebug() << "HERE" << endl;
 	} else {
 		openOk = file.open(stdout, QIODevice::WriteOnly);
 	}
@@ -166,7 +168,7 @@ void ImageConverterPrivate::pagesLoaded(bool ok) {
 		emit out.error("Will not output an empty image");
 		fail();
 	}
-
+		
 	if (settings.fmt != "svg") {
 		image = QImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
 		painter.begin(&image);

+ 0 - 3
src/lib/lib.pri

@@ -32,9 +32,6 @@ HEADERS += ../lib/pdfconverter_p.hh
 SOURCES += ../lib/pdfsettings.cc ../lib/pdfconverter.cc \
            ../lib/outline.cc ../lib/tocstylesheet.cc
 
-#Image
-QT += svg
-
 PUBLIC_HEADERS += ../lib/imageconverter.hh ../lib/imagesettings.hh
 HEADERS += ../lib/imageconverter_p.hh
 SOURCES += ../lib/imagesettings.cc ../lib/imageconverter.cc

+ 5 - 0
src/lib/loadsettings.hh

@@ -113,6 +113,11 @@ struct DLL_PUBLIC LoadPage {
 
 	//! Additional javascript to run on a page once it has loaded
 	QList< QString > runScript;
+
+	QString checkboxSvg;
+	QString checkboxCheckedSvg;
+	QString radiobuttonSvg;
+	QString radiobuttonCheckedSvg;
 };
 
 DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);

+ 2 - 1
src/lib/pdfconverter.cc

@@ -667,7 +667,8 @@ void PdfConverterPrivate::printDocument() {
 				foreach (const QWebElement & elm, obj.page->mainFrame()->findAllElements("textarea"))
 					myFormElements[wp.elementLocation(elm).first].push_back(elm);
 			}
-			emit out.producingForms( obj.settings.produceForms);
+			emit out.producingForms(obj.settings.produceForms);
+			out.emitCheckboxSvgs(obj.settings.load);
 			for (int p=0; p < wp.pageCount(); ++p) {
 				for (int pc_=0; pc_ < pc; ++pc_) {
 					beginPage(actualPage);

+ 4 - 0
src/lib/reflect.cc

@@ -71,6 +71,10 @@ ReflectImpl<LoadPage>::ReflectImpl(LoadPage & c) {
 	WKHTMLTOPDF_REFLECT(loadErrorHandling);
 	WKHTMLTOPDF_REFLECT(proxy);
 	WKHTMLTOPDF_REFLECT(runScript);
+	WKHTMLTOPDF_REFLECT(checkboxSvg);
+	WKHTMLTOPDF_REFLECT(checkboxCheckedSvg);
+	WKHTMLTOPDF_REFLECT(radiobuttonSvg);
+	WKHTMLTOPDF_REFLECT(radiobuttonCheckedSvg);
 }
 
 ReflectImpl<Web>::ReflectImpl(Web & c) {

+ 30 - 73
src/lib/utilities.cc

@@ -34,77 +34,22 @@ Q_IMPORT_PLUGIN(qtiff)
 Q_IMPORT_PLUGIN(qmng)
 #endif
 
-MyLooksStyle::MyLooksStyle(): weAreDrawingForms(false) {
-	if (checkbox == 0)
-		checkbox = new QSvgRenderer(QByteArray(
-"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
-"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
-"     version=\"1.1\" baseProfile=\"full\" width=\"12px\" height=\"12px\" viewBox=\"0 0 12px 12px\">\n"
-"  <rect x=\"0\" y=\"0\" width=\"1\" height=\"12\" fill=\"#808080\" />\n"
-"  <rect x=\"1\" y=\"0\" width=\"11\" height=\"1\" fill=\"#808080\" />\n"
-"  <rect x=\"1\" y=\"11\" width=\"11\" height=\"1\" fill=\"#d4d0c8\" />\n"
-"  <rect x=\"11\" y=\"1\" width=\"1\" height=\"11\" fill=\"#d4d0c8\" />\n"
-"  <rect x=\"1\" y=\"1\" width=\"1\" height=\"10\" fill=\"#404040\" />\n"
-"  <rect x=\"2\" y=\"1\" width=\"9\" height=\"1\" fill=\"#404040\" />\n"
-"  <rect x=\"2\" y=\"10\" width=\"9\" height=\"1\" fill=\"white\" />\n"
-"  <rect x=\"10\" y=\"2\" width=\"1\" height=\"9\" fill=\"white\" />\n"
-"  <rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" fill=\"white\" />\n"
-"</svg>\n"));
-	if (checkbox_checked == 0)
-		checkbox_checked = new QSvgRenderer(QByteArray(
-"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
-"<svg xmlns=\"http://www.w3.org/2000/svg\"\n"
-"     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
-"     version=\"1.1\" baseProfile=\"full\" width=\"12px\" height=\"12px\" viewBox=\"0 0 12px 12px\">\n"
-"  <rect x=\"0\" y=\"0\" width=\"1\" height=\"12\" fill=\"#808080\" />\n"
-"  <rect x=\"1\" y=\"0\" width=\"11\" height=\"1\" fill=\"#808080\" />\n"
-"  <rect x=\"1\" y=\"11\" width=\"11\" height=\"1\" fill=\"#d4d0c8\" />\n"
-"  <rect x=\"11\" y=\"1\" width=\"1\" height=\"11\" fill=\"#d4d0c8\" />\n"
-"  <rect x=\"1\" y=\"1\" width=\"1\" height=\"10\" fill=\"#404040\" />\n"
-"  <rect x=\"2\" y=\"1\" width=\"9\" height=\"1\" fill=\"#404040\" />\n"
-"  <rect x=\"2\" y=\"10\" width=\"9\" height=\"1\" fill=\"white\" />\n"
-"  <rect x=\"10\" y=\"2\" width=\"1\" height=\"9\" fill=\"white\" />\n"
-"  <rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" fill=\"white\" />\n"
-"  <path d=\"M 3 5.5 L 3 8 L 5.5 10.5 L 10 5.5 L 10 2.5 L 5.5 7.5\" fill=\"black\" />\n"
-"</svg>\n"));
-	if (radiobutton == 0)
-		radiobutton = new QSvgRenderer(QByteArray(
-"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
-"<svg xmlns=\"http://www.w3.org/2000/svg\"\n"
-"     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
-"     version=\"1.1\" baseProfile=\"full\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11px 11px\">\n"
-"  <clipPath id=\"upleftclip\"><path d=\"M 11 0 L 0 0 L 0 11\"/></clipPath>\n"
-"  <clipPath id=\"downrightclip\"><path d=\"M 11 0 L 11 11 L 0 11\"/></clipPath>\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"5.5\" fill=\"#808080\" clip-path=\"url(#upleftclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"5.5\" fill=\"white\" clip-path=\"url(#downrightclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"4.5\" fill=\"#404040\" clip-path=\"url(#upleftclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"4.5\" fill=\"#d4d0c8\" clip-path=\"url(#downrightclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"3.5\" fill=\"white\"/>\n"
-"</svg>\n"));
-	if (radiobutton_checked == 0)
-		radiobutton_checked = new QSvgRenderer(QByteArray(
-"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
-"<svg xmlns=\"http://www.w3.org/2000/svg\"\n"
-"     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
-"     version=\"1.1\" baseProfile=\"full\" width=\"11px\" height=\"11px\" viewBox=\"0 0 11px 11px\">\n"
-"  <clipPath id=\"upleftclip\"><path d=\"M 11 0 L 0 0 L 0 11\"/></clipPath>\n"
-"  <clipPath id=\"downrightclip\"><path d=\"M 11 0 L 11 11 L 0 11\"/></clipPath>\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"5.5\" fill=\"#808080\" clip-path=\"url(#upleftclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"5.5\" fill=\"white\" clip-path=\"url(#downrightclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"4.5\" fill=\"#404040\" clip-path=\"url(#upleftclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"4.5\" fill=\"#d4d0c8\" clip-path=\"url(#downrightclip)\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"3.5\" fill=\"white\" />\n"
-"  <circle cx=\"5.5\" cy=\"5.5\" r=\"1.5\" fill=\"black\" />\n"
-"</svg>\n"));
+void loadSvg(QSvgRenderer * & ptr, const QString & path) {
+	delete ptr;
+	ptr = new QSvgRenderer(path);
+	if (ptr->isValid()) return;
+	delete ptr;
+	ptr = 0;
 }
 
-void MyLooksStyle::producingForms(bool f) {
-	weAreDrawingForms=f;
-}
+void MyLooksStyle::setCheckboxSvg(const QString & path) {loadSvg(checkbox, path);}
+void MyLooksStyle::setCheckboxCheckedSvg(const QString & path) {loadSvg(checkbox_checked, path);}
+void MyLooksStyle::setRadioButtonSvg(const QString & path) {loadSvg(radiobutton, path);}
+void MyLooksStyle::setRadioButtonCheckedSvg(const QString & path) {loadSvg(radiobutton_checked, path);}
+
+MyLooksStyle::MyLooksStyle(): weAreDrawingForms(false) {}
+
+void MyLooksStyle::producingForms(bool f) {weAreDrawingForms=f;}
 
 void MyLooksStyle::drawPrimitive( PrimitiveElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget) const {
 	painter->setBrush(Qt::white);
@@ -115,16 +60,28 @@ void MyLooksStyle::drawPrimitive( PrimitiveElement element, const QStyleOption *
 	if (element == QStyle::PE_PanelLineEdit) {
 		painter->drawRect(r);
 	} else if (element == QStyle::PE_IndicatorCheckBox) {
-		if (weAreDrawingForms)
+		if (weAreDrawingForms || ((option->state & QStyle::State_On)? !checkbox_checked: !checkbox)) { 
 			painter->drawRect(r);
-		else if (option->state & QStyle::State_On)
+			if (!weAreDrawingForms && (option->state & QStyle::State_On)) {
+				r.translate(int(r.width()*0.075), int(r.width()*0.075));
+				painter->drawLine(r.topLeft(), r.bottomRight());
+				painter->drawLine(r.topRight(), r.bottomLeft());
+			}
+		} else if (option->state & QStyle::State_On)
 			checkbox_checked->render(painter, r);
 		else
 			checkbox->render(painter, r);
 	} else if (element == QStyle::PE_IndicatorRadioButton) {
-		if (weAreDrawingForms)
+		if (weAreDrawingForms || ((option->state & QStyle::State_On)? !radiobutton_checked: !radiobutton)) {
 			painter->drawEllipse(r);
-		else if (option->state & QStyle::State_On)
+			if (!weAreDrawingForms && (option->state & QStyle::State_On)) {
+				r.translate(int(r.width()*0.20), int(r.width()*0.20));
+				r.setWidth(int(r.width()*0.70));
+				r.setHeight(int(r.height()*0.70));
+				painter->setBrush(Qt::black);
+				painter->drawEllipse(r);
+			}
+		} else if (option->state & QStyle::State_On)
 			radiobutton_checked->render(painter, r);
 		else
 			radiobutton->render(painter, r);

+ 4 - 0
src/lib/utilities.hh

@@ -54,6 +54,10 @@ public:
 	static QSvgRenderer * radiobutton_checked;
 public slots:
 	void producingForms(bool f);
+	void setCheckboxSvg(const QString & path);
+	void setCheckboxCheckedSvg(const QString & path);
+	void setRadioButtonSvg(const QString & path);
+	void setRadioButtonCheckedSvg(const QString & path);
 };
 
 DLL_PUBLIC int handleError(bool success, int errorCode);

+ 5 - 0
src/pdf/wkhtmltopdf.cc

@@ -169,6 +169,11 @@ int main(int argc, char * argv[]) {
 	//Create the actual page converter to convert the pages
 	PdfConverter converter(globalSettings);
 	QObject::connect(&converter, SIGNAL(producingForms(bool)), style, SLOT(producingForms(bool)));
+	QObject::connect(&converter, SIGNAL(checkboxSvgChanged(const QString &)), style, SLOT(setCheckboxSvg(const QString &)));
+	QObject::connect(&converter, SIGNAL(checkboxCheckedSvgChanged(const QString &)), style, SLOT(setCheckboxCheckedSvg(const QString &)));
+	QObject::connect(&converter, SIGNAL(radiobuttonSvgChanged(const QString &)), style, SLOT(setRadioButtonSvg(const QString &)));
+	QObject::connect(&converter, SIGNAL(radiobuttonCheckedSvgChanged(const QString &)), style, SLOT(setRadioButtonCheckedSvg(const QString &)));
+
 	ProgressFeedback feedback(globalSettings.quiet, converter);
 	foreach (const PdfObject & object, objectSettings)
 		converter.addResource(object);

+ 4 - 0
src/shared/commonarguments.cc

@@ -226,4 +226,8 @@ void CommandLineParserBase::addPageLoadArgs(LoadPage & s) {
 #endif
 	addarg("run-script", 0, "Run this additional javascript after the page is done loading (repeatable)", new StringListSetter(s.runScript, "js"));
 
+	addarg("checkbox-svg", 0, "Use this SVG file when rendering unchecked checkboxes", new QStrSetter(s.checkboxSvg, "path", ""));
+	addarg("checkbox-checked-svg", 0, "Use this SVG file when rendering checked checkboxes", new QStrSetter(s.checkboxCheckedSvg, "path" ,""));
+	addarg("radiobutton-svg", 0, "Use this SVG file when rendering unchecked radiobuttons", new QStrSetter(s.radiobuttonSvg, "path", ""));
+	addarg("radiobutton-checked-svg", 0, "Use this SVG file when rendering checked radiobuttons", new QStrSetter(s.radiobuttonCheckedSvg, "path", ""));
 }