Browse Source

Commit a lot of changes to the page converter relating to per page arguments

Jakob Truelsen 15 years ago
parent
commit
c8878d7539
2 changed files with 257 additions and 229 deletions
  1. 209 213
      src/pageconverter.cc
  2. 48 16
      src/pageconverter_p.hh

+ 209 - 213
src/pageconverter.cc

@@ -30,6 +30,12 @@
 #include <io.h>
 #include <fcntl.h>
 #endif
+
+using namespace wkhtmltopdf;
+using namespace wkhtmltopdf::settings;
+
+QMap<QWebPage *, PageObject *> PageObject::webPageToObject;
+
  
 /*!
   \file pageconverter.hh
@@ -46,7 +52,7 @@ bool looksLikeHtmlAndNotAUrl(QString str) {
 	return s.count('<') > 0 || s.count('<') > 0;
 }
 
-PageConverterPrivate::PageConverterPrivate(Settings & s, PageConverter & o) :
+PageConverterPrivate::PageConverterPrivate(Global & s, PageConverter & o) :
 	settings(s), pageLoader(s),
 	outer(o), printer(0), painter(0)
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
@@ -59,34 +65,12 @@ PageConverterPrivate::PageConverterPrivate(Settings & s, PageConverter & o) :
 	phaseDescriptions.push_back("Resolving links");
 	phaseDescriptions.push_back("Counting pages");
 	phaseDescriptions.push_back("Loading headers and footers");
-	if (!settings.defaultEncoding.isEmpty())
-		QWebSettings::globalSettings()->setDefaultTextEncoding(settings.defaultEncoding);
-	if (!settings.enableIntelligentShrinking) {
-		QWebSettings::globalSettings()->setPrintingMaximumShrinkFactor(1.0);
-		QWebSettings::globalSettings()->setPrintingMinimumShrinkFactor(1.0);
-	}
-	QWebSettings::globalSettings()->setPrintingMediaType(settings.printMediaType?"print":"screen");
 #else
 	phaseDescriptions.push_back("Loading page");
 #endif
 	phaseDescriptions.push_back("Printing pages");
 	phaseDescriptions.push_back("Done");
 
-	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavaEnabled, settings.enablePlugins);
-	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, settings.enableJavascript);
-	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, false);
-	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, false);
-
-	QWebSettings::globalSettings()->setFontSize(QWebSettings::MinimumFontSize, s.minimumFontSize);
-
-#if QT_VERSION >= 0x040500
-	//Newer vertions of QT have even more settings to change
-	QWebSettings::globalSettings()->setAttribute(QWebSettings::PrintElementBackgrounds, settings.background);
-	QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, settings.enablePlugins);
-	if (!settings.userStyleSheet.isEmpty())
-		QWebSettings::globalSettings()->setUserStyleSheetUrl(MultiPageLoader::guessUrlFromString(settings.userStyleSheet));
-#endif
-
 	connect(&pageLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int)));
 	connect(&pageLoader, SIGNAL(loadFinished(bool)), this, SLOT(preparePrint(bool)));
 	connect(&pageLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString)));
@@ -128,32 +112,58 @@ void PageConverterPrivate::beginConvert() {
 	error=false;
 	progressString = "0%";
 	currentPhase=0;
-
-  	if (!settings.cover.isEmpty())
-		settings.in.push_front(settings.cover);
-
-	if (!settings.header.htmlUrl.isEmpty() && looksLikeHtmlAndNotAUrl(settings.header.htmlUrl)) {
-		emit outer.error("--header-html should be a URL and not a string containing HTML code.");
-		fail();
-		return;
-	}
-
-	if (!settings.footer.htmlUrl.isEmpty() && looksLikeHtmlAndNotAUrl(settings.footer.htmlUrl)) {
-		emit outer.error("--header-html should be a URL and not a string containing HTML code.");
-		fail();
-		return;
-	}
 	
 #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__	
-	if (settings.in.size() > 1) {
+	if (pages.size() > 1) {
 		emit outer.error("This version of wkhtmltopdf is build against an unpatched version of QT, and does not support more then one input document.");
 		fail();
 		return;
 	}
 #endif
-	
-	foreach(QString url, settings.in)
-		pages.push_back(pageLoader.addResource(url));
+
+	for (QList<PageObject>::iterator i=objects.begin(); i != objects.end(); ++i) {
+		PageObject & o=*i;
+		settings::Page & s = o.settings;		
+		
+		if (!s.header.htmlUrl.isEmpty() && looksLikeHtmlAndNotAUrl(s.header.htmlUrl)) {
+			emit outer.error("--header-html should be a URL and not a string containing HTML code.");
+			fail();
+			return;
+		}
+
+		if (!s.footer.htmlUrl.isEmpty() && looksLikeHtmlAndNotAUrl(s.footer.htmlUrl)) {
+			emit outer.error("--header-html should be a URL and not a string containing HTML code.");
+			fail();
+			return;
+		}
+
+		o.page = pageLoader.addResource(s.page, s);
+		PageObject::webPageToObject[o.page] = &o;
+		QWebSettings * ws = o.page->settings();
+
+#ifdef  __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
+		if (!s.defaultEncoding.isEmpty())
+			ws->setDefaultTextEncoding(s.defaultEncoding);
+		if (!s.enableIntelligentShrinking) {
+			ws->setPrintingMaximumShrinkFactor(1.0);
+			ws->setPrintingMinimumShrinkFactor(1.0);
+		}
+		ws->setPrintingMediaType(s.printMediaType?"print":"screen");
+#endif
+		ws->setAttribute(QWebSettings::JavaEnabled, s.enablePlugins);
+		ws->setAttribute(QWebSettings::JavascriptEnabled, s.enableJavascript);
+		ws->setAttribute(QWebSettings::JavascriptCanOpenWindows, false);
+		ws->setAttribute(QWebSettings::JavascriptCanAccessClipboard, false);
+		ws->setFontSize(QWebSettings::MinimumFontSize, s.minimumFontSize);
+#if QT_VERSION >= 0x040500
+		//Newer vertions of QT have even more settings to change
+		ws->setAttribute(QWebSettings::PrintElementBackgrounds, s.background);
+		ws->setAttribute(QWebSettings::PluginsEnabled, s.enablePlugins);
+		if (!s.userStyleSheet.isEmpty())
+			ws->setUserStyleSheetUrl(MultiPageLoader::guessUrlFromString(s.userStyleSheet));
+#endif
+	}
+
 	
 	emit outer.phaseChanged();
 	loadProgress(0);
@@ -172,30 +182,35 @@ void PageConverterPrivate::fail() {
 
 
 void PageConverterPrivate::findLinks(QWebFrame * frame, QVector<QPair<QWebElement, QString> > & local, QVector<QPair<QWebElement, QString> > & external) {
-	if (!settings.useLocalLinks && !settings.useExternalLinks) return;
+	bool ulocal=true, uexternal=true;
+	if (PageObject::webPageToObject.contains(frame->page())) {
+		ulocal = PageObject::webPageToObject[frame->page()]->settings.useLocalLinks;
+		uexternal  = PageObject::webPageToObject[frame->page()]->settings.useExternalLinks;
+	}
+	if (!ulocal && !uexternal) return;
 	foreach (const QWebElement & elm, frame->findAllElements("a")) {
 		QUrl href=QUrl(elm.attribute("href"));
 		if (href.isEmpty()) continue;
 		href=frame->url().resolved(href);
-		if (urlToDoc.contains(href.toString(QUrl::RemoveFragment))) {
-			if (settings.useLocalLinks) {
-				int t = urlToDoc[href.toString(QUrl::RemoveFragment)];
+		if (urlToPageObj.contains(href.toString(QUrl::RemoveFragment))) {
+			if (ulocal) {
+				PageObject * p = urlToPageObj[href.toString(QUrl::RemoveFragment)];
 				QWebElement e;
 				if (!href.hasFragment()) 
-					e = pages[t]->mainFrame()->findFirstElement("body");
+					e = p->page->mainFrame()->findFirstElement("body");
 				else {
-					e = pages[t]->mainFrame()->findFirstElement("a[name=\""+href.fragment()+"\"]");
+					e = p->page->mainFrame()->findFirstElement("a[name=\""+href.fragment()+"\"]");
 					if(e.isNull()) 
-						e = pages[t]->mainFrame()->findFirstElement("*[id=\""+href.fragment()+"\"]");
+						e = p->page->mainFrame()->findFirstElement("*[id=\""+href.fragment()+"\"]");
 				}
 				if (e.isNull())
 					qDebug() << "Unable to find target for local link " << href; 
 				else {
-					anchors[t][href.toString()] = e;
+					p->anchors[href.toString()] = e;
 					local.push_back( qMakePair(elm, href.toString()) );
 				}
 			}
-		} else if (settings.useExternalLinks)
+		} else if (uexternal)
 			external.push_back( qMakePair(elm, href.toString() ) );
 	}
 }
@@ -273,7 +288,7 @@ void PageConverterPrivate::preparePrint(bool ok) {
 	
 	QString title = settings.documentTitle;
 	if (title == "") 
-		title = pages[0]->mainFrame()->title();
+		title = objects[0].page->mainFrame()->title();
 	printer->setDocName(title);
 	if (!painter->begin(printer)) {
 		emit outer.error("Unable to write to destination");
@@ -281,24 +296,18 @@ void PageConverterPrivate::preparePrint(bool ok) {
 		return;
 	}
 	
-	logicalPages = 0;
-	actualPages = 0;
-	tocPages = 0;
-	
 	//Find and resolve all local links
-	if(settings.useLocalLinks || settings.useExternalLinks) {
-		currentPhase = 1;
-		emit outer.phaseChanged();
-		
-		QHash<QString, int> urlToDoc;
-		for(int d=0; d < pages.size(); ++d) 
-			urlToDoc[ pages[d]->mainFrame()->url().toString(QUrl::RemoveFragment) ]  = d;
-		
-		for(int d=0; d < pages.size(); ++d) {
-			progressString = QString("Page ")+QString::number(d+1)+QString(" of ")+QString::number(pages.size());
-			emit outer.progressChanged((d+1)*100 / pages.size());
-			findLinks(pages[d]->mainFrame(), localLinks[d], externalLinks[d]);
-		}
+	currentPhase = 1;
+	emit outer.phaseChanged();
+	
+	QHash<QString, int> urlToDoc;
+	for(int d=0; d < objects.size(); ++d) 
+		urlToPageObj[ objects[d].page->mainFrame()->url().toString(QUrl::RemoveFragment) ] = &objects[d];
+	
+	for(int d=0; d < objects.size(); ++d) {
+		progressString = QString("Object ")+QString::number(d+1)+QString(" of ")+QString::number(objects.size());
+		emit outer.progressChanged((d+1)*100 / objects.size());
+		findLinks(objects[d].page->mainFrame(), objects[d].localLinks, objects[d].externalLinks);
 	}
 
 	currentPhase = 2;
@@ -308,85 +317,88 @@ void PageConverterPrivate::preparePrint(bool ok) {
 	// * The number of pages of each document
 	// * A visual ordering of the header element
 	// * The location and page number of each header
-	for(int d=0; d < pages.size(); ++d) {
-		int tot = pages.size()+(settings.printToc?1:0);
-		progressString = QString("Page ")+QString::number(d+1)+QString(" of ")+QString::number(tot);
+	pageCount = 0;
+	for(int d=0; d < objects.size(); ++d) {
+		int tot = objects.size();
+		progressString = QString("Object ")+QString::number(d+1)+QString(" of ")+QString::number(tot);
 		emit outer.progressChanged((d+1)*100 / tot);
 
 		painter->save();
-		QWebPrinter wp(pages[d]->mainFrame(), printer, *painter);
-		int count = wp.pageCount();
-		//pageCount.push_back(count);
-		actualPages += count;
-		if (settings.cover.isEmpty() || d != 0) {
-			outline->addWebPage("", wp, pages[d]->mainFrame());
-			logicalPages += count;
-		} 
+		QWebPrinter wp(objects[d].page->mainFrame(), printer, *painter);
+		objects[d].pageCount = objects[d].settings.pagesCount? wp.pageCount(): 0;
+		pageCount += objects[d].pageCount;
+		
+		outline->addWebPage("", wp, objects[d].page->mainFrame(), objects[d].settings );
 		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
-	tocPrinter = NULL;
-	if (settings.printToc) {
-		int k=pages.size()+1;
-		progressString = QString("Page ")+QString::number(k)+QString(" of ")+QString::number(k);
-		emit outer.progressChanged(100);
+	// tocPrinter = NULL;
+	// if (settings.printToc) {
+	// 	int k=pages.size()+1;
+	// 	progressString = QString("Page ")+QString::number(k)+QString(" of ")+QString::number(k);
+	// 	emit outer.progressChanged(100);
 		
-		tocPrinter = new TocPrinter(outline, printer, *painter);
-		actualPages += tocPrinter->pageCount();
-		logicalPages += tocPrinter->pageCount();
-   	}
-	actualPages *= settings.copies;
-	int page=1;
-
-	headers.clear();
-	footers.clear();
-	if(!settings.header.htmlUrl.isEmpty() || !settings.footer.htmlUrl.isEmpty()) {
-		QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, true);
-		currentPhase = 3;
-		emit outer.phaseChanged();
-		for(int p=0; p < outline->pageCount(); ++p) {
-			QHash<QString, QString> parms;
-			fillParms(parms, page);
-			
-			if(!settings.header.htmlUrl.isEmpty())
-				headers.push_back(loadHeaderFooter(settings.header.htmlUrl, parms) );
-			if(!settings.footer.htmlUrl.isEmpty())
-				footers.push_back(loadHeaderFooter(settings.footer.htmlUrl, parms) );
-			++page;
+	// 	tocPrinter = new TocPrinter(outline, printer, *painter);
+	// 	actualPages += tocPrinter->pageCount();
+	// 	logicalPages += tocPrinter->pageCount();
+   	// }
+	actualPages = pageCount * settings.copies;
+
+	
+	//if(!settings.header.htmlUrl.isEmpty() || !settings.footer.htmlUrl.isEmpty()) {
+	//	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, true);
+	
+	currentPhase = 3;
+	emit outer.phaseChanged();
+	bool hf=false;
+
+	int pageNumber=1;
+	for(int d=0; d < objects.size(); ++d) {
+		PageObject & obj = objects[d];
+		settings::Page & ps = obj.settings;
+		QHash<QString, QString> parms;
+	 	fillParms(parms, pageNumber, ps);
+
+		for (int op=0; op < obj.pageCount; ++op) {
+			if(!ps.header.htmlUrl.isEmpty())
+				obj.headers.push_back(loadHeaderFooter(ps.header.htmlUrl, parms, ps) );
+			if(!ps.footer.htmlUrl.isEmpty())
+				obj.footers.push_back(loadHeaderFooter(ps.footer.htmlUrl, parms, ps) );
+			if (ps.pagesCount) ++pageNumber;
 		}
+	}
+
+
+	if (hf)
 		hfLoader.load();
-	} else 
+	else 
 		printPage(true);
 #endif
 }
 
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
-void PageConverterPrivate::fillParms(QHash<QString, QString> & parms, int page) {
-	outline->fillHeaderFooterParms(page, parms);
+void PageConverterPrivate::fillParms(QHash<QString, QString> & parms, int page, const settings::Page & ps) {
+	outline->fillHeaderFooterParms(page, parms, ps);
 	QDateTime t(QDateTime::currentDateTime());
 	parms["time"] = t.time().toString(Qt::SystemLocaleShortDate);
 	parms["date"] = t.date().toString(Qt::SystemLocaleShortDate);
 }
 
-void PageConverterPrivate::beginPage(int & actualPage, bool & first) {
+void PageConverterPrivate::beginPage(int actualPage) {
 	progressString = QString("Page ") + QString::number(actualPage) + QString(" of ") + QString::number(actualPages);
 	emit outer.progressChanged(actualPage * 100 / actualPages);
-	if(first)
-		first=false;
-	else
+	if (actualPage != 1)
 		printer->newPage();
-	actualPage++;
 }
 
-void PageConverterPrivate::endPage(bool actual, bool hasHeaderFooter) {
+void PageConverterPrivate::endPage(PageObject & object, bool hasHeaderFooter, int objectPage, int pageNumber) {
 	typedef QPair<QWebElement, QString> p_t;		
-		
-	if(hasHeaderFooter && actual) {
+	settings::Page & s = object.settings;
+	if(hasHeaderFooter) {
 		QHash<QString, QString> parms;
-		fillParms(parms, logicalPage);
+		fillParms(parms, pageNumber, s);
 
 		//Webkit used all kinds of crazy coordinate transformation, and font setup
 		//We save it here and restore some sane defaults
@@ -396,75 +408,75 @@ void PageConverterPrivate::endPage(bool actual, bool hasHeaderFooter) {
 		int h=printer->height();
 		int w=printer->width();
 						
-		double spacing = settings.header.spacing * printer->height() / printer->heightMM();
+		double spacing = s.header.spacing * printer->height() / printer->heightMM();
 		//If needed draw the header line
-		if (settings.header.line) painter->drawLine(0, -spacing, w, -spacing);
+		if (s.header.line) painter->drawLine(0, -spacing, w, -spacing);
 		//Guess the height of the header text
-		painter->setFont(QFont(settings.header.fontName, settings.header.fontSize));
+		painter->setFont(QFont(s.header.fontName, s.header.fontSize));
 		int dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height();
 		//Draw the header text
 		QRect r=QRect(0, 0-dy-spacing, w, h);
-		painter->drawText(r, Qt::AlignTop | Qt::AlignLeft, hfreplace(settings.header.left, parms));
-		painter->drawText(r, Qt::AlignTop | Qt::AlignHCenter, hfreplace(settings.header.center, parms));
-		painter->drawText(r, Qt::AlignTop | Qt::AlignRight, hfreplace(settings.header.right, parms));
+		painter->drawText(r, Qt::AlignTop | Qt::AlignLeft, hfreplace(s.header.left, parms));
+		painter->drawText(r, Qt::AlignTop | Qt::AlignHCenter, hfreplace(s.header.center, parms));
+		painter->drawText(r, Qt::AlignTop | Qt::AlignRight, hfreplace(s.header.right, parms));
 		
-		spacing = settings.footer.spacing * printer->height() / printer->heightMM();
+		spacing = s.footer.spacing * printer->height() / printer->heightMM();
 		//IF needed draw the footer line
-		if (settings.footer.line) painter->drawLine(0, h + spacing, w, h + spacing);
+		if (s.footer.line) painter->drawLine(0, h + spacing, w, h + spacing);
 		//Guess the height of the footer text
-		painter->setFont(QFont(settings.footer.fontName, settings.footer.fontSize));
+		painter->setFont(QFont(s.footer.fontName, s.footer.fontSize));
 		dy = painter->boundingRect(0, 0, w, h, Qt::AlignTop, "M").height();
 		//Draw the footer text
 		r=QRect(0,0,w,h+dy+ spacing);
-		painter->drawText(r, Qt::AlignBottom | Qt::AlignLeft, hfreplace(settings.footer.left, parms));
-		painter->drawText(r, Qt::AlignBottom | Qt::AlignHCenter, hfreplace(settings.footer.center, parms));
-		painter->drawText(r, Qt::AlignBottom | Qt::AlignRight, hfreplace(settings.footer.right, parms));
+		painter->drawText(r, Qt::AlignBottom | Qt::AlignLeft, hfreplace(s.footer.left, parms));
+		painter->drawText(r, Qt::AlignBottom | Qt::AlignHCenter, hfreplace(s.footer.center, parms));
+		painter->drawText(r, Qt::AlignBottom | Qt::AlignRight, hfreplace(s.footer.right, parms));
 		
 		//Restore Webkit's crazy scaling and font settings
 		painter->restore();
 	}
 
-	if(actual && logicalPage <= headers.size()) {
+	if (!object.headers.empty()) {
+		QWebPage * header = object.headers[objectPage];
 		painter->save();
 		painter->resetTransform();
-		double spacing = settings.header.spacing * printer->height() / printer->heightMM();
+		double spacing = s.header.spacing * printer->height() / printer->heightMM();
 		painter->translate(0, -spacing);
-		QWebPrinter wp(headers[logicalPage-1]->mainFrame(), printer, *painter);
-		painter->translate(0,-wp.elementLocation(headers[logicalPage-1]->mainFrame()->findFirstElement("body")).second.height());
+		QWebPrinter wp(header->mainFrame(), printer, *painter);
+		painter->translate(0,-wp.elementLocation(header->mainFrame()->findFirstElement("body")).second.height());
 
 		QVector<p_t> local;
 		QVector<p_t> external;
-		findLinks(headers[logicalPage-1]->mainFrame(), local, external);
+		findLinks(header->mainFrame(), local, external);
 		foreach(const p_t & p, local) {
 			QRectF r = wp.elementLocation(p.first).second;
 			painter->addLink(r, p.second);
 		}
 		foreach(const p_t & p, external) {
 			QRectF r = wp.elementLocation(p.first).second;
-			qDebug() << p.second;
 			painter->addHyperlink(r, QUrl(p.second));
 		}
 		wp.spoolPage(1);
 		painter->restore();
- 	}
+}
 
-	if(actual && logicalPage <= footers.size()) {
+	if (!object.footers.empty()) {
+		QWebPage * footer = object.footers[objectPage];
 		painter->save();
 		painter->resetTransform();
-		double spacing = settings.footer.spacing * printer->height() / printer->heightMM();
+		double spacing = s.footer.spacing * printer->height() / printer->heightMM();
 		painter->translate(0, printer->height()+ spacing);
-		QWebPrinter wp(footers[logicalPage-1]->mainFrame(), printer, *painter);
+		QWebPrinter wp(footer->mainFrame(), printer, *painter);
 		
 		QVector<p_t> local;
 		QVector<p_t> external;
-		findLinks(footers[logicalPage-1]->mainFrame(), local, external);
+		findLinks(footer->mainFrame(), local, external);
 		foreach(const p_t & p, local) {
 			QRectF r = wp.elementLocation(p.first).second;
 			painter->addLink(r, p.second);
 		}
 		foreach(const p_t & p, external) {
 			QRectF r = wp.elementLocation(p.first).second;
-			qDebug() << p.second;
 			painter->addHyperlink(r, QUrl(p.second));
 		}
 		wp.spoolPage(1);
@@ -488,80 +500,67 @@ void PageConverterPrivate::printPage(bool ok) {
 	progressString = "";
 	emit outer.progressChanged(-1);
 #else
- 	bool first=true;
  	int actualPage=1;
+		
  	int cc=settings.collate?settings.copies:1;
  	int pc=settings.collate?1:settings.copies;
-	
-	bool hasHeaderFooter = 
-		settings.header.line || settings.footer.line ||
-		!settings.header.left.isEmpty() || !settings.footer.left.isEmpty() ||
-		!settings.header.center.isEmpty() || !settings.footer.center.isEmpty() ||
-		!settings.header.right.isEmpty() || !settings.footer.right.isEmpty();
 
 	currentPhase = 4;
 	emit outer.phaseChanged();
 
 	progressString = "Preparing";
 	emit outer.progressChanged(0);
-			
+
 	for(int cc_=0; cc_ < cc; ++cc_) {
-		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();
+		int pageNumber=1;
+		for(int d=0; d < objects.size(); ++d) {
+			PageObject & obj = objects[d];
+			const settings::Page & ps = obj.settings;
+			bool hasHeaderFooter = ps.header.line || ps.footer.line ||
+				!ps.header.left.isEmpty() || !ps.footer.left.isEmpty() ||
+				!ps.header.center.isEmpty() || !ps.footer.center.isEmpty() ||
+				!ps.header.right.isEmpty() || !ps.footer.right.isEmpty();
 
+			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) {
-				//The toc printer adds an extra TOC document to the beginning of the outline
-				//Using a cover does not add anything to cover
-				int delta = (tocPrinter?1:0) - (settings.cover.isEmpty()?0:1);
-				if(tocPrinter) tocPrinter->fillLinks(d+delta, localLinks[d]);
-				outline->fillAnchors(d+delta, anchors[d]);				
-			}
+			QWebPrinter wp(obj.page->mainFrame(), printer, *painter);
+			QString l1=obj.page->mainFrame()->url().path().split("/").back()+"#";
+			QString l2=obj.page->mainFrame()->url().toString() + "#";
+
+			// if (settings.cover.isEmpty() || d != 0) {
+			// 	//The toc printer adds an extra TOC document to the beginning of the outline
+			// 	//Using a cover does not add anything to cover
+			// 	int delta = (tocPrinter?1:0) - (settings.cover.isEmpty()?0:1);
+			// 	if(tocPrinter) tocPrinter->fillLinks(d+delta, localLinks[d]);
+			outline->fillAnchors(d, obj.anchors);				
+			// }
 
 			//Sort anchors and links by page
 			QHash<int, QHash<QString, QWebElement> > myAnchors;
 			QHash<int, QVector< QPair<QWebElement,QString> > > myLocalLinks;
 			QHash<int, QVector< QPair<QWebElement,QString> > > myExternalLinks;
-			for(QHash<QString, QWebElement>::iterator i=anchors[d].begin();
-				i != anchors[d].end(); ++i)
+			for(QHash<QString, QWebElement>::iterator i=obj.anchors.begin();
+				i != obj.anchors.end(); ++i)
 				myAnchors[ wp.elementLocation(i.value()).first][i.key()] = i.value();
 
-			for(QVector< QPair<QWebElement,QString> >::iterator i=localLinks[d].begin();
-				i != localLinks[d].end(); ++i)
+			for(QVector< QPair<QWebElement,QString> >::iterator i=obj.localLinks.begin();
+				i != obj.localLinks.end(); ++i)
 				myLocalLinks[wp.elementLocation(i->first).first].push_back(*i);
 
-			for(QVector< QPair<QWebElement,QString> >::iterator i=externalLinks[d].begin();
-				i != externalLinks[d].end(); ++i)
+			for(QVector< QPair<QWebElement,QString> >::iterator i=obj.externalLinks.begin();
+				i != obj.externalLinks.end(); ++i)
 				myExternalLinks[wp.elementLocation(i->first).first].push_back(*i);
 
 			QHash<int, QVector<QWebElement> > myFormElements;
-			if (settings.produceForms) {
-				foreach(const QWebElement & elm,pages[d]->mainFrame()->findAllElements("input")) 
+			if (ps.produceForms) {
+				foreach(const QWebElement & elm, obj.page->mainFrame()->findAllElements("input")) 
 					myFormElements[wp.elementLocation(elm).first].push_back(elm);
-				foreach(const QWebElement & elm,pages[d]->mainFrame()->findAllElements("textarea")) 
+				foreach(const QWebElement & elm, obj.page->mainFrame()->findAllElements("textarea")) 
 					myFormElements[wp.elementLocation(elm).first].push_back(elm);
 			}
 			for(int p=0; p < wp.pageCount(); ++p) {
 				for(int pc_=0; pc_ < pc; ++pc_) {
-					beginPage(actualPage,first);
+					beginPage(actualPage);
 					wp.spoolPage(p+1);
 
 					foreach(const QWebElement & elm, myFormElements[p+1]) {
@@ -602,9 +601,10 @@ void PageConverterPrivate::printPage(bool ok) {
 						QRectF r = wp.elementLocation(i->first).second;
 						painter->addHyperlink(r, QUrl(i->second));
 					}
-					endPage(settings.cover.isEmpty() || d != 0, hasHeaderFooter);
+					endPage(obj, hasHeaderFooter, p, pageNumber);
+					actualPage++;
 				}
-				if (settings.cover.isEmpty() || d != 0) ++logicalPage;
+				if (ps.pagesCount) ++pageNumber;
 			}
 			painter->restore();
 		}
@@ -641,13 +641,14 @@ void PageConverterPrivate::printPage(bool ok) {
 }
 
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
-QWebPage * PageConverterPrivate::loadHeaderFooter(QString url, const QHash<QString, QString> & parms) {
+QWebPage * PageConverterPrivate::loadHeaderFooter(QString url, const QHash<QString, QString> & parms, const settings::Page & ps) {
 	QUrl u = MultiPageLoader::guessUrlFromString(url);
 
 	for(QHash<QString, QString>::const_iterator i=parms.begin(); i != parms.end(); ++i)
 		u.addQueryItem(i.key(), i.value());
-	
-	return hfLoader.addResource(u);
+
+	return hfLoader.addResource(u, ps);
+
 }
 
 /*!
@@ -681,24 +682,19 @@ void PageConverterPrivate::clearResources() {
 		delete outline;
 	outline = NULL;
 
-	if (tocPrinter)
-		delete tocPrinter;
+	//if (tocPrinter)
+	//	delete tocPrinter;
 	tocPrinter = NULL;
-	anchors.clear();
-	localLinks.clear();
-	externalLinks.clear();
-
-	foreach (QWebPage * page, headers)
-		delete page;
-	headers.clear();
+	
+	//foreach (QWebPage * page, headers)
+	//	delete page;
+	//headers.clear();
 
-	foreach (QWebPage * page, footers)
-		delete page;
-	footers.clear();
+	//foreach (QWebPage * page, footers)
+	//	delete page;
+	//footers.clear();
 #endif
-	foreach(QWebPage * page, pages)
-		delete page;
-	pages.clear();
+
 	if (printer) 
 		delete printer;
 	printer = NULL;
@@ -722,7 +718,7 @@ void PageConverterPrivate::cancel() {
   \brief Create a page converter object based on the supplied settings
   \param settings Settings for the conversion
 */
-PageConverter::PageConverter(Settings & settings):
+PageConverter::PageConverter(settings::Global & settings):
 	d(new PageConverterPrivate(settings, *this)) {
 }
 
@@ -775,8 +771,8 @@ int PageConverter::httpErrorCode() {
   \brief add a resource we want to convert
   \param url The url of the object we want to convert
 */
-void PageConverter::addResource(const QString & url) {
-	d->settings.in.push_back(url);
+void PageConverter::addResource(const settings::Page & page) {
+	d->objects.push_back( PageObject(page) );
 }
 
 /*!
@@ -804,7 +800,7 @@ void PageConverter::cancel() {
 /*!
   \brief Returns the settings object associated with the page converter
 */
-const Settings & PageConverter::settings() const {
+const settings::Global & PageConverter::globalSettings() const {
 	return d->settings;
 }
 

+ 48 - 16
src/pageconverter_p.hh

@@ -29,20 +29,48 @@
 #include <QWaitCondition>
 #include <QWebPage>
 #include <qnetworkreply.h>
+#include "settings.hh"
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
 #include <QWebElement>
 #endif
 
+namespace wkhtmltopdf {
+
+class PageObject {
+public:
+	static QMap<QWebPage *, PageObject *> webPageToObject;
+	
+	settings::Page settings;
+	QWebPage * page;
+
+	QHash<QString, QWebElement> anchors;
+	QVector< QPair<QWebElement,QString> > localLinks;
+	QVector< QPair<QWebElement,QString> > externalLinks;
+
+	int firstPageNumber;
+	QList<QWebPage *> headers;
+	QList<QWebPage *> footers;
+	int pageCount;
+
+	PageObject(const settings::Page & set): settings(set), page(0) {};
+
+	~PageObject() {
+		if (page) webPageToObject.remove(page);
+	}
+	
+};
+
 class PageConverterPrivate: public QObject {
 	Q_OBJECT
 public:
-	PageConverterPrivate(Settings & s, PageConverter & o);
+	PageConverterPrivate(settings::Global & s, PageConverter & o);
 	~PageConverterPrivate();
 	void copyFile(QFile & src, QFile & dst);
 
 	QList<QString> phaseDescriptions;
 	int currentPhase;
-	Settings & settings;
+	
+	settings::Global & settings;
 
 	MultiPageLoader pageLoader;
 	QString progressString;
@@ -51,35 +79,36 @@ private:
 	void clearResources();
 	TempFile tempOut;
 	bool error;
-	QList<QWebPage *> pages;
+
+
+	QList<PageObject> objects;
+
 	QPrinter * printer;
 	QPainter * painter;
 	QString lout;
-	int logicalPages;
-	int logicalPage;
+
+	//int logicalPages;
+	//int logicalPage;
 	int actualPages;
-	
+	int pageCount;
+
 	int tocPages;
 
 	bool convertionDone;
 
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
 	MultiPageLoader hfLoader;
-	QHash<int, QHash<QString, QWebElement> > anchors;
-	QHash<int, QVector< QPair<QWebElement,QString> > > localLinks;
-	QHash<int, QVector< QPair<QWebElement,QString> > > externalLinks;
 
-	QHash<QString, int> urlToDoc;
-	QList<QWebPage *> headers;
-	QList<QWebPage *> footers;
+	QHash<QString, PageObject *> urlToPageObj;
+
 	Outline * outline;
 	TocPrinter * tocPrinter;
 	void findLinks(QWebFrame * frame, QVector<QPair<QWebElement, QString> > & local, QVector<QPair<QWebElement, QString> > & external);
-	void beginPage(int & actualPage, bool & first);
-	void endPage(bool actual, bool hasHeaderFooter);
-	void fillParms(QHash<QString, QString> & parms, int page);
+	void beginPage(int actualPage);
+	void endPage(PageObject & object, bool hasHeaderFooter, int objectPage,  int pageNumber);
+	void fillParms(QHash<QString, QString> & parms, int page, const settings::Page & ps);
 	QString hfreplace(const QString & q, const QHash<QString, QString> & parms);
-	QWebPage * loadHeaderFooter(QString url, const QHash<QString, QString> & parms);
+	QWebPage * loadHeaderFooter(QString url, const QHash<QString, QString> & parms, const settings::Page & ps);
 #endif
 
 	void fail();
@@ -92,6 +121,9 @@ public slots:
 	bool convert();
 	void forwardError(QString error);
 	void forwardWarning(QString warning);
+
+	friend class PageConverter;
 };
 
+}
 #endif //__TEXTUALFEEDBACK_P_HH__