瀏覽代碼

Initial support for html toc

Jakob Truelsen 15 年之前
父節點
當前提交
ca3a86f9de
共有 8 個文件被更改,包括 142 次插入62 次删除
  1. 1 1
      src/arguments.cc
  2. 6 0
      src/outline.cc
  3. 4 0
      src/outline.hh
  4. 108 52
      src/pageconverter.cc
  5. 1 1
      src/pageconverter.hh
  6. 12 2
      src/pageconverter_p.hh
  7. 3 2
      src/settings.cc
  8. 7 4
      src/tocstylesheet.cc

+ 1 - 1
src/arguments.cc

@@ -365,7 +365,7 @@ struct DefaultTocFunc {
 		QFile file;
 		file.open(0, QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
 		QTextStream stream(&file);
-		wkhtmltopdf::dumbDefaultTOCStyleSheet(stream);
+		wkhtmltopdf::dumpDefaultTOCStyleSheet(stream);
 		exit(0);
 	}
 };

+ 6 - 0
src/outline.cc

@@ -173,6 +173,12 @@ void Outline::addWebPage(const QString & name, QWebPrinter & wp, QWebFrame * fra
 }
 
 
+void Outline::addEmptyWebPage() {
+	OutlineItem * root = new OutlineItem();
+	d->documentOutlines.push_back(root);
+	d->pageCount += 1;
+}
+
 void OutlinePrivate::buildHFCache(OutlineItem * i, int level) {
 	if (level >= hfCache.size()) return;
 	foreach (OutlineItem * j, i->children) {

+ 4 - 0
src/outline.hh

@@ -29,7 +29,11 @@ class Outline {
 public:
 	Outline(const settings::Global & settings);
 	~Outline();
+	void addEmptyWebPage();
+	void replaceWebPage(int d, const QString & name, QWebPrinter & wp, QWebFrame * frame, const settings::Page & ps);
 	void addWebPage(const QString & name, QWebPrinter & wp, QWebFrame * frame, const settings::Page & ps);
+
+
 	void fillHeaderFooterParms(int page, QHash<QString, QString> & parms, const settings::Page & ps);
 	void fillAnchors(int d, QHash<QString, QWebElement> & anchors);
 	int pageCount();

+ 108 - 52
src/pageconverter.cc

@@ -67,7 +67,7 @@ PageConverterPrivate::PageConverterPrivate(Global & s, PageConverter & o) :
 	settings(s), pageLoader(s),
 	outer(o), printer(0), painter(0)
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
-	, hfLoader(s), outline(0), tocPrinter(0)
+	, hfLoader(s), tocLoader(s), outline(0), tocPrinter(0)
 #endif
 {
 		
@@ -83,15 +83,20 @@ PageConverterPrivate::PageConverterPrivate(Global & s, PageConverter & o) :
 	phaseDescriptions.push_back("Done");
 
 	connect(&pageLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int)));
-	connect(&pageLoader, SIGNAL(loadFinished(bool)), this, SLOT(preparePrint(bool)));
+	connect(&pageLoader, SIGNAL(loadFinished(bool)), this, SLOT(pagesLoaded(bool)));
 	connect(&pageLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString)));
 	connect(&pageLoader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString)));
 
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__	
 	connect(&hfLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int)));
-	connect(&hfLoader, SIGNAL(loadFinished(bool)), this, SLOT(printPage(bool)));
+	connect(&hfLoader, SIGNAL(loadFinished(bool)), this, SLOT(headersLoaded(bool)));
 	connect(&hfLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString)));
 	connect(&hfLoader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString)));
+
+	connect(&tocLoader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int)));
+	connect(&tocLoader, SIGNAL(loadFinished(bool)), this, SLOT(tocLoaded(bool)));
+	connect(&tocLoader, SIGNAL(error(QString)), this, SLOT(forwardError(QString)));
+	connect(&tocLoader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString)));
 #endif
 }
 
@@ -117,6 +122,29 @@ void PageConverterPrivate::loadProgress(int progress) {
 	emit outer.progressChanged(progress);
 }
 
+void PageConverterPrivate::updateWebSettings(QWebSettings * ws, const settings::Page & s) const {
+#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
+}
 
 void PageConverterPrivate::beginConvert() {
 	clearResources();
@@ -148,31 +176,11 @@ void PageConverterPrivate::beginConvert() {
 			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);
+		if (!s.isTableOfContent) {
+			o.page = pageLoader.addResource(s.page, s);
+			PageObject::webPageToObject[o.page] = &o;
+			updateWebSettings(o.page->settings(), s);
 		}
-		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
 	}
 
 	
@@ -191,15 +199,17 @@ void PageConverterPrivate::fail() {
 	qApp->exit(0); // quit qt's event handling
 }
 
+
+
 /*!
  * Prepares printing out the document to the pdf file
  */
-void PageConverterPrivate::preparePrint(bool ok) {
+void PageConverterPrivate::pagesLoaded(bool ok) {
 	if (!ok) {
 		fail(); 
 		return;
 	}
-
+	
 	lout = settings.out;
 	if (settings.out == "-") {
 #ifndef Q_OS_WIN32
@@ -253,9 +263,11 @@ void PageConverterPrivate::preparePrint(bool ok) {
 
 #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
 	//If you do not have the hacks you get this crappy solution
-
 	printer->setCollateCopies(settings.copies);
 	printer->setCollateCopies(settings.collate);
+	
+	printPage();
+	
 	printPage(true);
 #else
 	printer->printEngine()->setProperty(QPrintEngine::PKK_UseCompression, settings.useCompression);
@@ -263,8 +275,9 @@ void PageConverterPrivate::preparePrint(bool ok) {
 	painter = new QPainter();
 	
 	QString title = settings.documentTitle;
-	if (title == "") 
-		title = objects[0].page->mainFrame()->title();
+	//if (title == "") 
+	//	title = objects[0].page->mainFrame()->title();
+	qDebug() << "FIX ME";
 	printer->setDocName(title);
 	if (!painter->begin(printer)) {
 		emit outer.error("Unable to write to destination");
@@ -277,12 +290,15 @@ void PageConverterPrivate::preparePrint(bool ok) {
 	emit outer.phaseChanged();
 	
 	QHash<QString, int> urlToDoc;
-	for(int d=0; d < objects.size(); ++d) 
+	for(int d=0; d < objects.size(); ++d) {
+		if (objects[d].settings.isTableOfContent) continue;
 		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());
+		if (objects[d].settings.isTableOfContent) continue;
 		findLinks(objects[d].page->mainFrame(), objects[d].localLinks, objects[d].externalLinks);
 	}
 
@@ -295,6 +311,13 @@ void PageConverterPrivate::preparePrint(bool ok) {
 	// * The location and page number of each header
 	pageCount = 0;
 	for(int d=0; d < objects.size(); ++d) {
+		if (objects[d].settings.isTableOfContent) {
+			objects[d].pageCount = 1;
+			pageCount += 1;
+			outline->addEmptyWebPage();
+			continue;
+		}
+		
 		int tot = objects.size();
 		progressString = QString("Object ")+QString::number(d+1)+QString(" of ")+QString::number(tot);
 		emit outer.progressChanged((d+1)*100 / tot);
@@ -308,24 +331,14 @@ void PageConverterPrivate::preparePrint(bool ok) {
 		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 = 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);
 	
+	loadTocs();
+#endif
+}
+
+void PageConverterPrivate::loadHeaders() {
+#ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
 	currentPhase = 3;
 	emit outer.phaseChanged();
 	bool hf=false;
@@ -351,7 +364,39 @@ void PageConverterPrivate::preparePrint(bool ok) {
 	if (hf)
 		hfLoader.load();
 	else 
-		printPage(true);
+		printDocument();
+#endif	
+}
+
+TempFile tocFile;
+TempFile tocStyleFile;
+
+void PageConverterPrivate::loadTocs() {
+#ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
+	bool toc=false;
+	qDebug() << "a";
+	for(int d=0; d < objects.size(); ++d) {
+		PageObject & obj = objects[d];
+		settings::Page & ps = obj.settings;
+		if (!ps.isTableOfContent) continue;
+		QString style = "toc.xsl"; //tocStyleFile.create(".xsl");
+		StreamDumper styleDump(style);
+		dumpDefaultTOCStyleSheet(styleDump.stream);
+		
+		QString path = "toc.xml"; //tocFile.create(".xml");
+		StreamDumper sd(path);
+		outline->dump(sd.stream, style);
+
+				
+		obj.page = tocLoader.addResource(path, ps);
+		PageObject::webPageToObject[obj.page] = &obj;
+		updateWebSettings(obj.page->settings(), ps);
+		toc= true;
+	}
+	if (toc) 
+		tocLoader.load();
+	else
+		loadHeaders();
 #endif
 }
 
@@ -496,12 +541,23 @@ void PageConverterPrivate::endPage(PageObject & object, bool hasHeaderFooter, in
 }
 #endif
 
+void PageConverterPrivate::tocLoaded(bool ok) {
+	if (!ok) {
+		fail();
+		return;
+	}
+	loadHeaders();
+}
 
-void PageConverterPrivate::printPage(bool ok) {
+void PageConverterPrivate::headersLoaded(bool ok) {
 	if (!ok) {
 		fail();
 		return;
 	}
+	printDocument();
+}
+
+void PageConverterPrivate::printDocument() {
 
 #ifndef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
 	currentPhase = 1;

+ 1 - 1
src/pageconverter.hh

@@ -20,7 +20,7 @@
 #include <QObject>
 namespace wkhtmltopdf {
 
-void dumbDefaultTOCStyleSheet(QTextStream & stream);
+void dumpDefaultTOCStyleSheet(QTextStream & stream);
 
 class PageConverterPrivate;
 class PageConverter: public QObject {

+ 12 - 2
src/pageconverter_p.hh

@@ -98,6 +98,7 @@ private:
 
 #ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
 	MultiPageLoader hfLoader;
+	MultiPageLoader tocLoader;
 
 	QHash<QString, PageObject *> urlToPageObj;
 
@@ -111,11 +112,20 @@ private:
 	QWebPage * loadHeaderFooter(QString url, const QHash<QString, QString> & parms, const settings::Page & ps);
 #endif
 
+	void loadTocs();
+	void loadHeaders();
+	void updateWebSettings(QWebSettings * ws, const settings::Page & s) const;
+
 	void fail();
 public slots:
 	void loadProgress(int progress);
-	void preparePrint(bool ok);
-	void printPage(bool ok);
+	void pagesLoaded(bool ok);
+	void tocLoaded(bool ok);
+	void headersLoaded(bool ok);
+	
+	
+	void printDocument();
+
 	void beginConvert();
 	void cancel();
 	bool convert();

+ 3 - 2
src/settings.cc

@@ -279,7 +279,8 @@ Page::Page():
 	ignoreLoadErrors(false),
 	enablePlugins(false),
 	includeInOutline(true),
-	pagesCount(true)
- {}
+	pagesCount(true),
+	isTableOfContent(false),
+	tocXsl("") {};
 }
 }

+ 7 - 4
src/tocstylesheet.cc

@@ -19,12 +19,15 @@
 
 namespace wkhtmltopdf {
 
-void dumbDefaultTOCStyleSheet(QTextStream & stream) {
+void dumpDefaultTOCStyleSheet(QTextStream & stream) {
     stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl
 		   << "<xsl:stylesheet version=\"1.0\"" << endl
-		   << "	        xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"" << endl
+		   << "	               xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"" << endl
 		   << "                xmlns:outline=\"http://code.google.com/p/wkhtmltopdf/outline\"" << endl
 		   << "                xmlns=\"http://www.w3.org/1999/xhtml\">" << endl
+		   << "  <xsl:output doctype-public=\"-//W3C//DTD XHTML 1.0 Strict//EN\"" << endl
+	       << "              doctype-system=\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"" << endl
+		   << "              indent=\"yes\" />\"" << endl
 		   << "  <xsl:template match=\"outline:outline\">" << endl
 		   << "    <html>" << endl
 		   << "      <head>" << endl
@@ -49,8 +52,8 @@ void dumbDefaultTOCStyleSheet(QTextStream & stream) {
 		   << "        </style>" << endl
 		   << "      </head>" << endl
 		   << "      <body>" << endl
-		   << "        <h1><xsl:value-of select=\"@title\" /></h1>" << endl
-		   << "        <ul><xsl:apply-templates select=\"outline:item\"/></ul>" << endl
+		   << "        <h1><xsl:value-of select=\"@title\" > </xsl:value-of> </h1>" << endl
+		   << "        <ul><xsl:apply-templates select=\"outline:item/outline:item\"/></ul>" << endl
 		   << "      </body>" << endl
 		   << "    </html>" << endl
 		   << "  </xsl:template>" << endl