From a331eee186ed91e49b67a099783c071e6dcbdfee Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 2 Mar 2018 22:37:02 +0800 Subject: [PATCH] export: support exporting notes all in one PDF --- src/dialog/vexportdialog.cpp | 272 ++++++++++++++++++++++++++--------- src/dialog/vexportdialog.h | 55 +++++-- src/vexporter.cpp | 63 +++++--- src/vexporter.h | 13 +- 4 files changed, 309 insertions(+), 94 deletions(-) diff --git a/src/dialog/vexportdialog.cpp b/src/dialog/vexportdialog.cpp index ec107981..ad28cfb9 100644 --- a/src/dialog/vexportdialog.cpp +++ b/src/dialog/vexportdialog.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #ifndef QT_NO_PRINTER #include @@ -196,11 +197,6 @@ QWidget *VExportDialog::setupPDFAdvancedSettings() updatePageLayoutLabel(); - QHBoxLayout *layoutLayout = new QHBoxLayout(); - layoutLayout->addWidget(m_layoutLabel); - layoutLayout->addWidget(layoutBtn); - layoutLayout->addStretch(); - // Use wkhtmltopdf. m_wkhtmltopdfCB = new QCheckBox(tr("Use wkhtmltopdf")); m_wkhtmltopdfCB->setToolTip(tr("Use wkhtmltopdf tool to generate PDF (wkhtmltopdf needed to be installed)")); @@ -222,14 +218,9 @@ QWidget *VExportDialog::setupPDFAdvancedSettings() QDesktopServices::openUrl(QUrl(url)); }); - QHBoxLayout *wkLayout = new QHBoxLayout(); - wkLayout->addWidget(m_wkhtmltopdfCB); - wkLayout->addStretch(); - wkLayout->addWidget(wkBtn); - // wkhtmltopdf Path. m_wkPathEdit = new VLineEdit(); - m_wkPathEdit->setToolTip(tr("Tell VNote where to find wkhtmlpdf tool")); + m_wkPathEdit->setToolTip(tr("Tell VNote where to find wkhtmltopdf tool")); m_wkPathEdit->setEnabled(m_wkhtmltopdfCB->isChecked()); m_wkPathBrowseBtn = new QPushButton(tr("&Browse")); @@ -237,9 +228,18 @@ QWidget *VExportDialog::setupPDFAdvancedSettings() connect(m_wkPathBrowseBtn, &QPushButton::clicked, this, &VExportDialog::handleWkPathBrowseBtnClicked); - QHBoxLayout *wkPathLayout = new QHBoxLayout(); - wkPathLayout->addWidget(m_wkPathEdit); - wkPathLayout->addWidget(m_wkPathBrowseBtn); + m_wkTitleEdit = new VLineEdit(); + m_wkTitleEdit->setPlaceholderText(tr("Use the name of the first source note")); + m_wkTitleEdit->setToolTip(tr("Title of the generated PDF file")); + m_wkTitleEdit->setEnabled(m_wkhtmltopdfCB->isChecked()); + + m_wkTargetFileNameEdit = new VLineEdit(); + m_wkTargetFileNameEdit->setPlaceholderText(tr("Use the name of the first source note")); + m_wkTargetFileNameEdit->setToolTip(tr("Name of the generated PDF file")); + QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), + m_wkTargetFileNameEdit); + m_wkTargetFileNameEdit->setValidator(validator); + m_wkTargetFileNameEdit->setEnabled(m_wkhtmltopdfCB->isChecked()); // wkhtmltopdf enable background. m_wkBackgroundCB = new QCheckBox(tr("Enable background")); @@ -262,14 +262,32 @@ QWidget *VExportDialog::setupPDFAdvancedSettings() m_wkExtraArgsEdit->setPlaceholderText(tr("Use \" to enclose arguments containing space")); m_wkExtraArgsEdit->setEnabled(m_wkhtmltopdfCB->isChecked()); - QFormLayout *advLayout = new QFormLayout(); - advLayout->addRow(tr("Page layout:"), layoutLayout); - advLayout->addRow(wkLayout); - advLayout->addRow(tr("wkhtmltopdf path:"), wkPathLayout); - advLayout->addRow(m_wkBackgroundCB); - advLayout->addRow(m_wkTableOfContentsCB); - advLayout->addRow(tr("Page number:"), m_wkPageNumberCB); - advLayout->addRow(tr("Additional arguments:"), m_wkExtraArgsEdit); + QGridLayout *advLayout = new QGridLayout(); + advLayout->addWidget(new QLabel(tr("Page layout:")), 0, 0); + advLayout->addWidget(m_layoutLabel, 0, 1); + advLayout->addWidget(layoutBtn, 0, 2); + + advLayout->addWidget(m_wkhtmltopdfCB, 1, 1, 1, 2); + advLayout->addWidget(wkBtn, 1, 4, 1, 2); + + advLayout->addWidget(new QLabel(tr("wkhtmltopdf path:")), 2, 0); + advLayout->addWidget(m_wkPathEdit, 2, 1, 1, 4); + advLayout->addWidget(m_wkPathBrowseBtn, 2, 5); + + advLayout->addWidget(new QLabel(tr("Title:")), 3, 0); + advLayout->addWidget(m_wkTitleEdit, 3, 1, 1, 2); + + advLayout->addWidget(new QLabel(tr("Output file name:")), 3, 3); + advLayout->addWidget(m_wkTargetFileNameEdit, 3, 4, 1, 2); + + advLayout->addWidget(m_wkBackgroundCB, 4, 1, 1, 2); + advLayout->addWidget(m_wkTableOfContentsCB, 4, 4, 1, 2); + + advLayout->addWidget(new QLabel(tr("Page number:")), 5, 0); + advLayout->addWidget(m_wkPageNumberCB, 5, 1, 1, 2); + + advLayout->addWidget(new QLabel(tr("Additional global options:")), 6, 0); + advLayout->addWidget(m_wkExtraArgsEdit, 6, 1, 1, 5); advLayout->setContentsMargins(0, 0, 0, 0); @@ -360,6 +378,7 @@ void VExportDialog::initUIFields(MarkdownConverterType p_renderer) m_formatCB->addItem(tr("Markdown"), (int)ExportFormat::Markdown); m_formatCB->addItem(tr("HTML"), (int)ExportFormat::HTML); m_formatCB->addItem(tr("PDF"), (int)ExportFormat::PDF); + m_formatCB->addItem(tr("PDF (All In One)"), (int)ExportFormat::OnePDF); m_formatCB->setCurrentIndex(m_formatCB->findData((int)s_opt.m_format)); // Markdown renderer. @@ -464,8 +483,8 @@ void VExportDialog::startExport() QString outputFolder = QDir::cleanPath(QDir(getOutputDirectory()).absolutePath()); - s_opt = ExportOption((ExportSource)m_srcCB->currentData().toInt(), - (ExportFormat)m_formatCB->currentData().toInt(), + s_opt = ExportOption(currentSource(), + currentFormat(), (MarkdownConverterType)m_rendererCB->currentData().toInt(), m_renderBgCB->currentData().toString(), m_renderStyleCB->currentData().toString(), @@ -476,6 +495,8 @@ void VExportDialog::startExport() QDir::toNativeSeparators(m_wkPathEdit->text()), m_wkBackgroundCB->isChecked(), m_wkTableOfContentsCB->isChecked(), + m_wkTitleEdit->text(), + m_wkTargetFileNameEdit->text(), (ExportPageNumber)m_wkPageNumberCB->currentData().toInt(), m_wkExtraArgsEdit->text()), ExportHTMLOption(m_embedStyleCB->isChecked(), @@ -486,11 +507,16 @@ void VExportDialog::startExport() appendLogLine(tr("Export to %1.").arg(outputFolder)); if (s_opt.m_format == ExportFormat::PDF + || s_opt.m_format == ExportFormat::OnePDF || s_opt.m_format == ExportFormat::HTML) { - m_exporter->prepareExport(s_opt); + if (s_opt.m_format != ExportFormat::OnePDF) { + s_opt.m_pdfOpt.m_wkTitle.clear(); + s_opt.m_pdfOpt.m_wkTargetFileName.clear(); + } - if (s_opt.m_format == ExportFormat::PDF - && s_opt.m_pdfOpt.m_wkhtmltopdf) { + if ((s_opt.m_format == ExportFormat::PDF + && s_opt.m_pdfOpt.m_wkhtmltopdf) + || s_opt.m_format == ExportFormat::OnePDF) { g_config->setWkhtmltopdfPath(s_opt.m_pdfOpt.m_wkPath); g_config->setWkhtmltopdfArgs(s_opt.m_pdfOpt.m_wkExtraArgs); @@ -500,32 +526,77 @@ void VExportDialog::startExport() return; } } + + m_exporter->prepareExport(s_opt); } int ret = 0; QString msg; - switch (s_opt.m_source) { - case ExportSource::CurrentNote: - ret = doExport(m_file, s_opt, outputFolder, &msg); - break; + if (s_opt.m_format == ExportFormat::OnePDF) { + QList files; - case ExportSource::CurrentFolder: - ret = doExport(m_directory, s_opt, outputFolder, &msg); - break; + // Output HTMLs to a tmp folder. + QTemporaryDir tmpDir; + if (!tmpDir.isValid()) { + goto exit; + } - case ExportSource::CurrentNotebook: - ret = doExport(m_notebook, s_opt, outputFolder, &msg); - break; + qDebug() << "output HTMLs to temporary dir" << tmpDir.path(); - case ExportSource::Cart: - ret = doExport(m_cart, s_opt, outputFolder, &msg); - break; + s_opt.m_format = ExportFormat::HTML; + switch (s_opt.m_source) { + case ExportSource::CurrentNote: + ret = doExport(m_file, s_opt, tmpDir.path(), &msg, &files); + break; - default: - break; + case ExportSource::CurrentFolder: + ret = doExport(m_directory, s_opt, tmpDir.path(), &msg, &files); + break; + + case ExportSource::CurrentNotebook: + ret = doExport(m_notebook, s_opt, tmpDir.path(), &msg, &files); + break; + + case ExportSource::Cart: + ret = doExport(m_cart, s_opt, tmpDir.path(), &msg, &files); + break; + + default: + break; + } + + s_opt.m_format = ExportFormat::OnePDF; + + Q_ASSERT(ret == files.size()); + if (!files.isEmpty()) { + ret = doExportPDFAllInOne(files, s_opt, outputFolder, &msg); + } + } else { + switch (s_opt.m_source) { + case ExportSource::CurrentNote: + ret = doExport(m_file, s_opt, outputFolder, &msg); + break; + + case ExportSource::CurrentFolder: + ret = doExport(m_directory, s_opt, outputFolder, &msg); + break; + + case ExportSource::CurrentNotebook: + ret = doExport(m_notebook, s_opt, outputFolder, &msg); + break; + + case ExportSource::Cart: + ret = doExport(m_cart, s_opt, outputFolder, &msg); + break; + + default: + break; + } } +exit: + if (m_askedToStop) { appendLogLine(tr("User cancelled the export. Aborted!")); m_askedToStop = false; @@ -622,24 +693,27 @@ void VExportDialog::appendLogLine(const QString &p_text) int VExportDialog::doExport(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_ASSERT(p_file); appendLogLine(tr("Exporting note %1.").arg(p_file->fetchPath())); int ret = 0; - switch ((int)p_opt.m_format) { - case (int)ExportFormat::Markdown: - ret = doExportMarkdown(p_file, p_opt, p_outputFolder, p_errMsg); + switch (p_opt.m_format) { + case ExportFormat::Markdown: + ret = doExportMarkdown(p_file, p_opt, p_outputFolder, p_errMsg, p_outputFiles); break; - case (int)ExportFormat::PDF: - ret = doExportPDF(p_file, p_opt, p_outputFolder, p_errMsg); + case ExportFormat::PDF: + V_FALLTHROUGH; + case ExportFormat::OnePDF: + ret = doExportPDF(p_file, p_opt, p_outputFolder, p_errMsg, p_outputFiles); break; - case (int)ExportFormat::HTML: - ret = doExportHTML(p_file, p_opt, p_outputFolder, p_errMsg); + case ExportFormat::HTML: + ret = doExportHTML(p_file, p_opt, p_outputFolder, p_errMsg, p_outputFiles); break; default: @@ -652,7 +726,8 @@ int VExportDialog::doExport(VFile *p_file, int VExportDialog::doExport(VDirectory *p_directory, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_ASSERT(p_directory); @@ -678,7 +753,7 @@ int VExportDialog::doExport(VDirectory *p_directory, goto exit; } - ret += doExport(file, p_opt, outputPath, p_errMsg); + ret += doExport(file, p_opt, outputPath, p_errMsg, p_outputFiles); } // Export subfolders. @@ -688,7 +763,7 @@ int VExportDialog::doExport(VDirectory *p_directory, goto exit; } - ret += doExport(dir, p_opt, outputPath, p_errMsg); + ret += doExport(dir, p_opt, outputPath, p_errMsg, p_outputFiles); } } @@ -703,7 +778,8 @@ exit: int VExportDialog::doExport(VNotebook *p_notebook, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_ASSERT(p_notebook); @@ -729,7 +805,7 @@ int VExportDialog::doExport(VNotebook *p_notebook, goto exit; } - ret += doExport(dir, p_opt, outputPath, p_errMsg); + ret += doExport(dir, p_opt, outputPath, p_errMsg, p_outputFiles); } exit: @@ -743,7 +819,8 @@ exit: int VExportDialog::doExport(VCart *p_cart, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_ASSERT(p_cart); @@ -757,7 +834,7 @@ int VExportDialog::doExport(VCart *p_cart, continue; } - ret += doExport(file, p_opt, p_outputFolder, p_errMsg); + ret += doExport(file, p_opt, p_outputFolder, p_errMsg, p_outputFiles); } return ret; @@ -766,7 +843,8 @@ int VExportDialog::doExport(VCart *p_cart, int VExportDialog::doExportMarkdown(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_UNUSED(p_opt); @@ -826,6 +904,10 @@ int VExportDialog::doExportMarkdown(VFile *p_file, } if (ret) { + if (p_outputFiles) { + p_outputFiles->append(destPath); + } + appendLogLine(tr("Note %1 exported to %2.").arg(srcFilePath).arg(outputPath)); } @@ -835,7 +917,8 @@ int VExportDialog::doExportMarkdown(VFile *p_file, int VExportDialog::doExportPDF(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_UNUSED(p_opt); @@ -858,6 +941,10 @@ int VExportDialog::doExportPDF(VFile *p_file, QString outputPath = QDir(p_outputFolder).filePath(name); if (m_exporter->exportPDF(p_file, p_opt, outputPath, p_errMsg)) { + if (p_outputFiles) { + p_outputFiles->append(outputPath); + } + appendLogLine(tr("Note %1 exported to %2.").arg(srcFilePath).arg(outputPath)); return 1; } else { @@ -869,7 +956,8 @@ int VExportDialog::doExportPDF(VFile *p_file, int VExportDialog::doExportHTML(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg) + QString *p_errMsg, + QList *p_outputFiles) { Q_UNUSED(p_opt); @@ -892,6 +980,10 @@ int VExportDialog::doExportHTML(VFile *p_file, QString outputPath = QDir(p_outputFolder).filePath(name); if (m_exporter->exportHTML(p_file, p_opt, outputPath, p_errMsg)) { + if (p_outputFiles) { + p_outputFiles->append(outputPath); + } + appendLogLine(tr("Note %1 exported to %2.").arg(srcFilePath).arg(outputPath)); return 1; } else { @@ -942,17 +1034,26 @@ void VExportDialog::handleCurrentFormatChanged(int p_index) { bool pdfEnabled = false; bool htmlEnabled = false; + bool pdfTitleNameEnabled = false; if (p_index >= 0) { - switch (m_formatCB->currentData().toInt()) { - case (int)ExportFormat::PDF: + switch (currentFormat()) { + case ExportFormat::PDF: pdfEnabled = true; + m_wkhtmltopdfCB->setEnabled(true); break; - case (int)ExportFormat::HTML: + case ExportFormat::HTML: htmlEnabled = true; break; + case ExportFormat::OnePDF: + pdfEnabled = true; + pdfTitleNameEnabled = true; + m_wkhtmltopdfCB->setChecked(true); + m_wkhtmltopdfCB->setEnabled(false); + break; + default: break; } @@ -960,6 +1061,9 @@ void VExportDialog::handleCurrentFormatChanged(int p_index) m_pdfSettings->setVisible(pdfEnabled); m_htmlSettings->setVisible(htmlEnabled); + + m_wkTitleEdit->setEnabled(pdfTitleNameEnabled); + m_wkTargetFileNameEdit->setEnabled(pdfTitleNameEnabled); } void VExportDialog::handleCurrentSrcChanged(int p_index) @@ -967,8 +1071,8 @@ void VExportDialog::handleCurrentSrcChanged(int p_index) bool subfolderEnabled = false; if (p_index >= 0) { - switch (m_srcCB->currentData().toInt()) { - case (int)ExportSource::CurrentFolder: + switch (currentSource()) { + case ExportSource::CurrentFolder: subfolderEnabled = true; break; @@ -979,3 +1083,41 @@ void VExportDialog::handleCurrentSrcChanged(int p_index) m_subfolderCB->setVisible(subfolderEnabled); } + +int VExportDialog::doExportPDFAllInOne(const QList &p_files, + const ExportOption &p_opt, + const QString &p_outputFolder, + QString *p_errMsg) +{ + if (p_files.isEmpty()) { + return 0; + } + + if (!VUtils::makePath(p_outputFolder)) { + LOGERR(tr("Fail to create directory %1.").arg(p_outputFolder)); + return 0; + } + + // Get output file. + const QString suffix = ".pdf"; + QString name = p_opt.m_pdfOpt.m_wkTargetFileName; + if (name.isEmpty()) { + name = VUtils::getFileNameWithSequence(p_outputFolder, + QFileInfo(p_files.first()).completeBaseName() + suffix); + } else if (!name.endsWith(suffix)) { + name += suffix; + } + + QString outputPath = QDir(p_outputFolder).filePath(name); + + qDebug() << "output" << p_files.size() << "HTML files as PDF to" << outputPath; + + int ret = m_exporter->exportPDFInOne(p_files, p_opt, outputPath, p_errMsg); + if (ret > 0) { + appendLogLine(tr("%1 notes exported to %2.").arg(ret).arg(outputPath)); + } else { + appendLogLine(tr("Fail to export %1 notes in one PDF.").arg(p_files.size())); + } + + return ret; +} diff --git a/src/dialog/vexportdialog.h b/src/dialog/vexportdialog.h index c056c424..25bfcb19 100644 --- a/src/dialog/vexportdialog.h +++ b/src/dialog/vexportdialog.h @@ -3,13 +3,14 @@ #include #include +#include +#include #include "vconstants.h" class QLabel; class VLineEdit; class QDialogButtonBox; -class QComboBox; class QPushButton; class QGroupBox; class QPlainTextEdit; @@ -35,7 +36,8 @@ enum class ExportFormat { Markdown = 0, HTML, - PDF + PDF, + OnePDF }; @@ -88,6 +90,8 @@ struct ExportPDFOption const QString &p_wkPath, bool p_wkEnableBackground, bool p_wkEnableTableOfContents, + const QString &p_wkTitle, + const QString &p_wkTargetFileName, ExportPageNumber p_wkPageNumber, const QString &p_wkExtraArgs) : m_layout(p_layout), @@ -95,6 +99,8 @@ struct ExportPDFOption m_wkPath(p_wkPath), m_wkEnableBackground(p_wkEnableBackground), m_wkEnableTableOfContents(p_wkEnableTableOfContents), + m_wkTitle(p_wkTitle), + m_wkTargetFileName(p_wkTargetFileName), m_wkPageNumber(p_wkPageNumber), m_wkExtraArgs(p_wkExtraArgs) { @@ -105,6 +111,8 @@ struct ExportPDFOption QString m_wkPath; bool m_wkEnableBackground; bool m_wkEnableTableOfContents; + QString m_wkTitle; + QString m_wkTargetFileName; ExportPageNumber m_wkPageNumber; QString m_wkExtraArgs; }; @@ -205,37 +213,49 @@ private: int doExport(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); int doExport(VDirectory *p_directory, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); int doExport(VNotebook *p_notebook, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); int doExport(VCart *p_cart, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); int doExportMarkdown(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); int doExportPDF(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); int doExportHTML(VFile *p_file, const ExportOption &p_opt, const QString &p_outputFolder, - QString *p_errMsg = NULL); + QString *p_errMsg = NULL, + QList *p_outputFiles = NULL); + + int doExportPDFAllInOne(const QList &p_files, + const ExportOption &p_opt, + const QString &p_outputFolder, + QString *p_errMsg = NULL); // Return false if we could not continue. bool checkUserAction(); @@ -244,6 +264,10 @@ private: bool checkWkhtmltopdfExecutable(const QString &p_file); + ExportSource currentSource() const; + + ExportFormat currentFormat() const; + QComboBox *m_srcCB; QComboBox *m_formatCB; @@ -284,6 +308,10 @@ private: QPushButton *m_wkPathBrowseBtn; + VLineEdit *m_wkTitleEdit; + + VLineEdit *m_wkTargetFileNameEdit; + QCheckBox *m_wkBackgroundCB; QCheckBox *m_wkTableOfContentsCB; @@ -325,4 +353,13 @@ private: static ExportOption s_opt; }; +inline ExportSource VExportDialog::currentSource() const +{ + return (ExportSource)m_srcCB->currentData().toInt(); +} + +inline ExportFormat VExportDialog::currentFormat() const +{ + return (ExportFormat)m_formatCB->currentData().toInt(); +} #endif // VEXPORTDIALOG_H diff --git a/src/vexporter.cpp b/src/vexporter.cpp index 4b0bd702..0bcb4004 100644 --- a/src/vexporter.cpp +++ b/src/vexporter.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "vconfigmanager.h" #include "vfile.h" @@ -39,7 +40,8 @@ void VExporter::prepareExport(const ExportOption &p_opt) p_opt.m_renderBg, p_opt.m_renderStyle, p_opt.m_renderCodeBlockStyle, - p_opt.m_format == ExportFormat::PDF); + p_opt.m_format == ExportFormat::PDF + || p_opt.m_format == ExportFormat::OnePDF); m_exportHtmlTemplate = VUtils::generateExportHtmlTemplate(p_opt.m_renderBg); @@ -129,6 +131,11 @@ void VExporter::prepareWKArguments(const ExportPDFOption &p_opt) << "--footer-spacing" << QString::number(marginsMM.bottom() / 3, 'f', 2); } + // Title. + if (!p_opt.m_wkTitle.isEmpty()) { + m_wkArgs << "--title" << p_opt.m_wkTitle; + } + // Append additional arguments. if (!p_opt.m_wkExtraArgs.isEmpty()) { m_wkArgs.append(parseCombinedArgString(p_opt.m_wkExtraArgs)); @@ -265,7 +272,15 @@ bool VExporter::exportToPDFViaWK(VDocument *p_webDocument, } Q_ASSERT(!p_filePath.isEmpty()); - QString htmlPath = p_filePath + ".vnote.html"; + + // Save HTML to a temp dir. + QTemporaryDir tmpDir; + if (!tmpDir.isValid()) { + pdfExported = -1; + return; + } + + QString htmlPath = tmpDir.filePath("vnote_tmp.html"); QFile file(htmlPath); if (!file.open(QFile::WriteOnly)) { @@ -296,16 +311,12 @@ bool VExporter::exportToPDFViaWK(VDocument *p_webDocument, file.write(html.toUtf8()); file.close(); - // Convert vis wkhtmltopdf. - if (!htmlToPDFViaWK(htmlPath, p_filePath, p_opt, p_errMsg)) { + // Convert via wkhtmltopdf. + QList files; + files.append(htmlPath); + if (!htmlsToPDFViaWK(files, p_filePath, p_opt, p_errMsg)) { pdfExported = -1; - } - - // Clean up. - VUtils::deleteFile(htmlPath); - VUtils::deleteDirectory(resFolderPath); - - if (pdfExported == 0) { + } else { pdfExported = 1; } }); @@ -369,6 +380,8 @@ bool VExporter::exportViaWebView(VFile *p_file, bool exportRet = false; switch (p_opt.m_format) { case ExportFormat::PDF: + V_FALLTHROUGH; + case ExportFormat::OnePDF: if (p_opt.m_pdfOpt.m_wkhtmltopdf) { exportRet = exportToPDFViaWK(m_webDocument, p_opt.m_pdfOpt, @@ -624,17 +637,23 @@ static QString combineArgs(QStringList &p_args) return str; } -bool VExporter::htmlToPDFViaWK(const QString &p_htmlFile, - const QString &p_filePath, - const ExportPDFOption &p_opt, - QString *p_errMsg) +bool VExporter::htmlsToPDFViaWK(const QList &p_htmlFiles, + const QString &p_filePath, + const ExportPDFOption &p_opt, + QString *p_errMsg) { // Note: system's locale settings (Language for non-Unicode programs) is important to wkhtmltopdf. // Input file could be encoded via QUrl::fromLocalFile(p_htmlFile).toString(QUrl::EncodeUnicode) to // handle non-ASCII path. + QStringList args(m_wkArgs); - args << QDir::toNativeSeparators(p_htmlFile); + + for (auto const & it : p_htmlFiles) { + args << QDir::toNativeSeparators(it); + } + args << QDir::toNativeSeparators(p_filePath); + QString cmd = p_opt.m_wkPath + " " + combineArgs(args); emit outputLog(cmd); int ret = QProcess::execute(p_opt.m_wkPath, args); @@ -654,3 +673,15 @@ bool VExporter::htmlToPDFViaWK(const QString &p_htmlFile, return ret == 0; } + +int VExporter::exportPDFInOne(const QList &p_htmlFiles, + const ExportOption &p_opt, + const QString &p_outputFile, + QString *p_errMsg) +{ + if (!htmlsToPDFViaWK(p_htmlFiles, p_outputFile, p_opt.m_pdfOpt, p_errMsg)) { + return 0; + } + + return p_htmlFiles.size(); +} diff --git a/src/vexporter.h b/src/vexporter.h index 616429bc..d0ecc7f3 100644 --- a/src/vexporter.h +++ b/src/vexporter.h @@ -31,6 +31,11 @@ public: const QString &p_outputFile, QString *p_errMsg = NULL); + int exportPDFInOne(const QList &p_htmlFiles, + const ExportOption &p_opt, + const QString &p_outputFile, + QString *p_errMsg = NULL); + signals: // Request to output log. void outputLog(const QString &p_log); @@ -95,10 +100,10 @@ private: const ExportHTMLOption &p_opt, const QString &p_filePath); - bool htmlToPDFViaWK(const QString &p_htmlFile, - const QString &p_filePath, - const ExportPDFOption &p_opt, - QString *p_errMsg = NULL); + bool htmlsToPDFViaWK(const QList &p_htmlFiles, + const QString &p_filePath, + const ExportPDFOption &p_opt, + QString *p_errMsg = NULL); void prepareWKArguments(const ExportPDFOption &p_opt);