Browse Source

Define and use Outline and TocPrinter classes

Antialize 16 years ago
parent
commit
16a0459973
4 changed files with 178 additions and 122 deletions
  1. 40 0
      src/outline.hh
  2. 93 121
      src/pageconverter.cc
  3. 8 1
      src/pageconverter_p.hh
  4. 37 0
      src/tocprinter.hh

+ 40 - 0
src/outline.hh

@@ -0,0 +1,40 @@
+//-*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-file-style: "stroustrup"; -*-
+// This file is part of wkhtmltopdf.
+//
+// wkhtmltopdf is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// wkhtmltopdf is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with wkhtmltopdf.  If not, see <http://www.gnu.org/licenses/>.
+#ifndef __OUTLINE_HH__
+#define __OUTLINE_HH__
+#include <QWebFrame>
+#ifdef  __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
+#include <QWebElement>
+#include "settings.hh"
+
+class OutlinePrivate;
+
+class Outline {
+public:
+	Outline(const Settings & settings);
+	~Outline();
+	void addWebPage(const QString & name, QWebPrinter & wp, QWebFrame * frame);
+	void fillHeaderFooterParms(int d, int page, QHash<QString, QString> & parms);
+	void fillAnchors(int d, QHash<QString, QWebElement> & anchors);
+	int pageCount();
+	void printOutline(QPrinter * printer);
+	void addOffset(int d);
+private:
+	OutlinePrivate * d;
+};
+
+#endif //__EXTENSIVE_WKHTMLTOPDF_QT_HACK__
+#endif //__OUTLINE_HH__

+ 93 - 121
src/pageconverter.cc

@@ -71,31 +71,6 @@ PageConverterPrivate::PageConverterPrivate(Settings & s, PageConverter & o) :
 	connect(&hfLoader, SIGNAL(loadFinished(bool)), this, SLOT(printPage(bool)));
 }
 
-
-// /*!
-//  * Once loading is finished, we start the printing
-//  * \param ok did the loading finish correctly?
-//  */
-// void PageConverterPrivate::loadFinished(bool ok) {
-// 	//Keep track of the number of pages currently loading
-// 	#warning "This is a race condition"
-// 	loading.deref();
-// 	if (!ok) {
-// 		//It went bad, return with 1
-// 		emit outer.error("Failed loading page");
-//         #warning "FIX ME"
-// 		exit(1);
-// 		return;
-// 	}
-
-// 	  #warning "FIX ME"
-// 	//feedback.nextState("Waiting for redirect");
-// 	if (loading == 0) {
-// 		//Wait a little while for js-redirects, and then print
-// 		QTimer::singleShot(settings.jsredirectwait, this, SLOT(preparePrint()));
-// 	}
-// }
-
 /*!
  * Called when the page is loading, display some progress to the using
  * \param progress the loading progress in percent
@@ -130,14 +105,6 @@ void PageConverterPrivate::beginConvert() {
  * Prepares printing out the document to the pdf file
  */
 void PageConverterPrivate::preparePrint(bool ok) {
-	//If there are still pages loading wait til they are done
-	//if (loading != 0) return;
-	//Give some user feed back
-// 	if (!quiet) {
-// 		fprintf(stderr, "Outputting pages       \r");
-// 		fflush(stdout);
-// 	}
-	
 
 	printer = new QPrinter(settings.resolution);
 	
@@ -242,11 +209,9 @@ void PageConverterPrivate::preparePrint(bool ok) {
 		}
 	}
 
-	headings.clear();
-
 	currentPhase = 2;
 	emit outer.phaseChanged();
-
+	outline = new Outline(settings);
 	//This is the first render face, it is done to calculate:
 	// * The number of pages of each document
 	// * A visual ordering of the header elemnt
@@ -259,46 +224,32 @@ void PageConverterPrivate::preparePrint(bool ok) {
 		painter->save();
 		QWebPrinter wp(pages[d]->mainFrame(), printer, *painter);
 		int count = wp.pageCount();
-		pageCount.push_back(count);
+		//pageCount.push_back(count);
 		actualPages += count;
 		if (settings.cover.isEmpty() || d != 0) {
+			outline->addWebPage("", wp, pages[d]->mainFrame());
 			logicalPages += count;
-			foreach(const QWebElement & e, pages[d]->mainFrame()->findAllElements("h1,h2,h3,h4,h5,h6,h7,h8,h9")) {
-				QPair<int, QRectF> location = wp.elementLocation(e);
-				headings[d][ qMakePair(location.first, qMakePair(location.second.y(), location.second.x()) ) ] = e;
-			}
 		} 
 		painter->restore();
 	}
 
+
 	//Now that we know the ordering of the headers in each document we
 	//can calculate the number of pages in the table of content
 	if (settings.printToc) {
 		int k=pages.size()+1;
 		progressString = QString("Page ")+QString::number(k)+QString(" of ")+QString::number(k);
 		emit outer.progressChanged(100);
-
-//  		TocItem * root = new TocItem();
-// 		for(int d=0; d < pages.size(); ++d) {
-// 			if (cover[0] && d == 0) continue;
-// 			// buildToc(root,pages[d]->mainFrame(),
-//  					 anchors[d], externalLinks[d]
-//  					 ,-1);
-// 		}
-		//tocPages = tocPrinter.countPages(root, &printer, painter);
-		tocPages = 0;
-		actualPages += tocPages;
-		logicalPages += tocPages;
- 		//delete root;
+		
+		tocPrinter = new TocPrinter(outline, printer, *painter);
+		actualPages += tocPrinter->pageCount();
+		logicalPages += tocPrinter->pageCount();
    	}
 	actualPages *= settings.copies;
 	int page=1;
 
 	headers.clear();
 	footers.clear();
-// 	headerFooterLoading =
-// 		(settings.header.htmlUrl.isEmpty()?0:actualPages) +
-// 		(settings.fooher.htmlURl.isEmpty()?0:actualPages);
 	if(!settings.header.htmlUrl.isEmpty() || !settings.footer.htmlUrl.isEmpty()) {
 		for(int d=0; d < pages.size(); ++d) {
 			if (!settings.cover.isEmpty() && d == 0) continue;
@@ -310,11 +261,72 @@ void PageConverterPrivate::preparePrint(bool ok) {
 				++page;
 			}
 		}
+		hfLoader.load();
 	} else 
 		printPage(true);
 #endif
 }
 
+void PageConverterPrivate::beginPage(int & actualPage, bool & first) {
+	progressString = QString("Page ") + QString::number(actualPage) + QString(" of ") + QString::number(actualPages);
+	emit outer.progressChanged(actualPage * 100 / actualPages);
+	if(first)
+		first=false;
+	else
+		printer->newPage();
+	actualPages++;
+}
+
+void PageConverterPrivate::endPage(bool actual, bool hasHeaderFooter) {
+	if(hasHeaderFooter && actual) {
+		//Webkit used all kinds of crasy cordinate transformation, and font setup
+		//We save it here and restore some sane defaults
+		painter->save();
+		painter->resetTransform();
+						
+		int h=printer->height();
+		int w=printer->width();
+						
+		//If needed draw the header line
+		if (settings.header.line) painter->drawLine(0, 0, w, 0);
+		//Guess the height of the header text
+		painter->setFont(QFont(settings.header.fontName, settings.header.fontSize));
+		int dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height();
+		//Draw the header text
+		QRect r=QRect(0, 0-dy, w, h);
+		painter->drawText(r, Qt::AlignTop | Qt::AlignLeft, hfreplace(settings.header.left));
+		painter->drawText(r, Qt::AlignTop | Qt::AlignHCenter, hfreplace(settings.header.center));
+		painter->drawText(r, Qt::AlignTop | Qt::AlignRight, hfreplace(settings.header.right));
+		
+		//IF needed draw the footer line
+		if (settings.footer.line) painter->drawLine(0, h, w, h);
+		//Guess the height of the footer text
+		painter->setFont(QFont(settings.footer.fontName, settings.footer.fontSize));
+		dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height();
+		//Draw the fooder text
+		r=QRect(0,0,w,h+dy);
+		painter->drawText(r, Qt::AlignBottom | Qt::AlignLeft, hfreplace(settings.footer.left));
+		painter->drawText(r, Qt::AlignBottom | Qt::AlignHCenter, hfreplace(settings.footer.center));
+		painter->drawText(r, Qt::AlignBottom | Qt::AlignRight, hfreplace(settings.footer.right));
+		
+		//Restore webkits crasy scaling and font settings
+		painter->restore();
+	}
+// 					painter->save();
+// 					painter->resetTransform();
+// 					painter->drawPicture(0,-208 - 4, picture);
+// 					painter->restore();
+// 					{
+// 						painter->save();
+// 						
+// 						//MThread::msleep(100);
+// 						painter->translate(0,-222);
+// 						QWebPrinter whp(headers[0]->mainFrame(), printer, *painter);
+// 						//painter->translate(0,-whp.elementLocation(headers[0]->mainFrame()->findFirstElement("body")).second.height());
+// 						whp.spoolPage(1);
+// 					}
+
+}
 
 void PageConverterPrivate::printPage(bool ok) {
 	//if (headerFooterLoading != 0 || loading != 0) return;
@@ -362,12 +374,32 @@ void PageConverterPrivate::printPage(bool ok) {
 
 		logicalPage=1;
 		for(int d=0; d < pages.size(); ++d) {
+			//Output the table of content now
+			if(tocPrinter && d == (settings.cover.isEmpty()?0:1)) {
+				painter->save();
+				for(int p=0; p < tocPrinter->pageCount(); ++p) {
+					for(int pc_=0; pc_ < pc; ++pc_) {
+						beginPage(actualPage,first);
+						tocPrinter->spoolPage(p);
+						endPage(true, hasHeaderFooter);
+					}
+					++logicalPage;
+				}
+				painter->restore();
+			}
 			painter->save();
-			
+
+			//output 
 			QWebPrinter wp(pages[d]->mainFrame(), printer, *painter);
 			QString l1=pages[d]->mainFrame()->url().path().split("/").back()+"#";
 			QString l2=pages[d]->mainFrame()->url().toString() + "#";
 
+			if (settings.cover.isEmpty() || d != 0) {
+				int md = d - settings.cover.isEmpty()?0:1;
+				if(tocPrinter) tocPrinter->fillLinks(md, localLinks[md]);
+				outline->fillAnchors(md, anchors[md]);				
+			}
+
 			//Sort anchors and links by page
 			QHash<int, QHash<QString, QWebElement> > myAnchors;
 			QHash<int, QVector< QPair<QWebElement,QString> > > myLocalLinks;
@@ -383,21 +415,11 @@ void PageConverterPrivate::printPage(bool ok) {
 			for(QVector< QPair<QWebElement,QString> >::iterator i=externalLinks[d].begin();
 				i != externalLinks[d].end(); ++i)
 				myExternalLinks[wp.elementLocation(i->first).first].push_back(*i);
-						
+				
 			for(int p=0; p < wp.pageCount(); ++p) {
 				for(int pc_=0; pc_ < pc; ++pc_) {
-
-					progressString = QString("Page ") + QString::number(actualPage) + QString(" of ") + QString::number(actualPages);
-					emit outer.progressChanged(actualPage * 100 / actualPages);
-
-					if(first)
-						first=false;
-					else
-						printer->newPage();
-
-
+					beginPage(actualPage,first);
 					wp.spoolPage(p+1);
-					
 					for(QHash<QString, QWebElement>::iterator i=myAnchors[p+1].begin();
 						i != myAnchors[p+1].end(); ++i) {
 						QRectF r = wp.elementLocation(i.value()).second;
@@ -413,57 +435,7 @@ void PageConverterPrivate::printPage(bool ok) {
 						QRectF r = wp.elementLocation(i->first).second;
 						painter->addHyperlink(r, QUrl(i->second));
 					}
-					++actualPage;
-
-					if(hasHeaderFooter && (settings.cover.isEmpty() || d != 0)) {
-						//Webkit used all kinds of crasy cordinate transformation, and font setup
-						//We save it here and restore some sane defaults
-						painter->save();
-						painter->resetTransform();
-						
-						int h=printer->height();
-						int w=printer->width();
-						
-						//If needed draw the header line
-						if (settings.header.line) painter->drawLine(0, 0, w, 0);
-						//Guess the height of the header text
-						painter->setFont(QFont(settings.header.fontName, settings.header.fontSize));
-						int dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height();
-						//Draw the header text
-						QRect r=QRect(0, 0-dy, w, h);
-						painter->drawText(r, Qt::AlignTop | Qt::AlignLeft, hfreplace(settings.header.left));
-						painter->drawText(r, Qt::AlignTop | Qt::AlignHCenter, hfreplace(settings.header.center));
-						painter->drawText(r, Qt::AlignTop | Qt::AlignRight, hfreplace(settings.header.right));
-						
-						//IF needed draw the footer line
-						if (settings.footer.line) painter->drawLine(0, h, w, h);
-						//Guess the height of the footer text
-						painter->setFont(QFont(settings.footer.fontName, settings.footer.fontSize));
-						dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height();
-						//Draw the fooder text
-						r=QRect(0,0,w,h+dy);
-						painter->drawText(r, Qt::AlignBottom | Qt::AlignLeft, hfreplace(settings.footer.left));
-						painter->drawText(r, Qt::AlignBottom | Qt::AlignHCenter, hfreplace(settings.footer.center));
-						painter->drawText(r, Qt::AlignBottom | Qt::AlignRight, hfreplace(settings.footer.right));
-						
-						//Restore webkits crasy scaling and font settings
-						painter->restore();
-					}
-
-
-// 					painter->save();
-// 					painter->resetTransform();
-// 					painter->drawPicture(0,-208 - 4, picture);
-// 					painter->restore();
-// 					{
-// 						painter->save();
-// 						
-// 						//MThread::msleep(100);
-// 						painter->translate(0,-222);
-// 						QWebPrinter whp(headers[0]->mainFrame(), printer, *painter);
-// 						//painter->translate(0,-whp.elementLocation(headers[0]->mainFrame()->findFirstElement("body")).second.height());
-// 						whp.spoolPage(1);
-// 					}
+					endPage(settings.cover.isEmpty() || d != 0, hasHeaderFooter);
 				}
 				if (settings.cover.isEmpty() || d != 0) ++logicalPage;
 			}

+ 8 - 1
src/pageconverter_p.hh

@@ -28,6 +28,8 @@
 #include "tempfile.hh"
 #include <QWaitCondition>
 #include <QMutex>
+#include "outline.hh"
+#include "tocprinter.hh"
 
 class PageConverterPrivate: public QObject {
 	Q_OBJECT
@@ -57,6 +59,9 @@ private:
 	QList<QWebPage *> pages;
 	QPrinter * printer;
 	QPainter * painter;
+	Outline * outline;
+	TocPrinter * tocPrinter;
+
 	int logicalPages;
 	int logicalPage;
 	int actualPages;
@@ -69,10 +74,12 @@ private:
 	QHash<int, QHash<QString, QWebElement> > anchors;
 	QHash<int, QVector< QPair<QWebElement,QString> > > localLinks;
 	QHash<int, QVector< QPair<QWebElement,QString> > > externalLinks;
-	QHash<int, QMap< QPair<int, QPair<qreal,qreal> >, QWebElement> > headings;
+
 	QList<QWebPage *> headers;
 	QList<QWebPage *> footers;
 
+	void beginPage(int & actualPage, bool & first);
+	void endPage(bool actual, bool hasHeaderFooter);
 	QString hfreplace(const QString & q);
 	QWebPage * loadHeaderFooter(QString url, int d, int page);
 public slots:

+ 37 - 0
src/tocprinter.hh

@@ -0,0 +1,37 @@
+//-*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-file-style: "stroustrup"; -*-
+// This file is part of wkhtmltopdf.
+//
+// wkhtmltopdf is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// wkhtmltopdf is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with wkhtmltopdf.  If not, see <http://www.gnu.org/licenses/>.
+#ifndef __TOCPRINTER_HH__
+#define __TOCPRINTER_HH__
+#include <QWebFrame>
+#ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
+#include "outline.hh"
+#include <QPainter>
+#include <QPrinter>
+
+class TocPrinterPrivate;
+
+class TocPrinter {
+public:
+	TocPrinter(Outline * outline, QPrinter * printer, QPainter & painter);
+	int pageCount();
+	void spoolPage(int page);
+	void fillLinks(int d, QVector<QPair<QWebElement, QString> > & links);
+private:
+	TocPrinterPrivate * tocPrinter;
+};
+
+#endif //__EXTENSIVE_WKHTMLTOPDF_QT_HACK__
+#endif //__TOCPRINTER_HH