export: support exporting notes all in one PDF

This commit is contained in:
Le Tan 2018-03-02 22:37:02 +08:00
parent 2bb2910fec
commit a331eee186
4 changed files with 309 additions and 94 deletions

View File

@ -3,6 +3,7 @@
#include <QtWidgets> #include <QtWidgets>
#include <QCoreApplication> #include <QCoreApplication>
#include <QProcess> #include <QProcess>
#include <QTemporaryDir>
#ifndef QT_NO_PRINTER #ifndef QT_NO_PRINTER
#include <QPrinter> #include <QPrinter>
@ -196,11 +197,6 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
updatePageLayoutLabel(); updatePageLayoutLabel();
QHBoxLayout *layoutLayout = new QHBoxLayout();
layoutLayout->addWidget(m_layoutLabel);
layoutLayout->addWidget(layoutBtn);
layoutLayout->addStretch();
// Use wkhtmltopdf. // Use wkhtmltopdf.
m_wkhtmltopdfCB = new QCheckBox(tr("Use wkhtmltopdf")); m_wkhtmltopdfCB = new QCheckBox(tr("Use wkhtmltopdf"));
m_wkhtmltopdfCB->setToolTip(tr("Use wkhtmltopdf tool to generate PDF (wkhtmltopdf needed to be installed)")); 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)); QDesktopServices::openUrl(QUrl(url));
}); });
QHBoxLayout *wkLayout = new QHBoxLayout();
wkLayout->addWidget(m_wkhtmltopdfCB);
wkLayout->addStretch();
wkLayout->addWidget(wkBtn);
// wkhtmltopdf Path. // wkhtmltopdf Path.
m_wkPathEdit = new VLineEdit(); 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_wkPathEdit->setEnabled(m_wkhtmltopdfCB->isChecked());
m_wkPathBrowseBtn = new QPushButton(tr("&Browse")); m_wkPathBrowseBtn = new QPushButton(tr("&Browse"));
@ -237,9 +228,18 @@ QWidget *VExportDialog::setupPDFAdvancedSettings()
connect(m_wkPathBrowseBtn, &QPushButton::clicked, connect(m_wkPathBrowseBtn, &QPushButton::clicked,
this, &VExportDialog::handleWkPathBrowseBtnClicked); this, &VExportDialog::handleWkPathBrowseBtnClicked);
QHBoxLayout *wkPathLayout = new QHBoxLayout(); m_wkTitleEdit = new VLineEdit();
wkPathLayout->addWidget(m_wkPathEdit); m_wkTitleEdit->setPlaceholderText(tr("Use the name of the first source note"));
wkPathLayout->addWidget(m_wkPathBrowseBtn); 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. // wkhtmltopdf enable background.
m_wkBackgroundCB = new QCheckBox(tr("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->setPlaceholderText(tr("Use \" to enclose arguments containing space"));
m_wkExtraArgsEdit->setEnabled(m_wkhtmltopdfCB->isChecked()); m_wkExtraArgsEdit->setEnabled(m_wkhtmltopdfCB->isChecked());
QFormLayout *advLayout = new QFormLayout(); QGridLayout *advLayout = new QGridLayout();
advLayout->addRow(tr("Page layout:"), layoutLayout); advLayout->addWidget(new QLabel(tr("Page layout:")), 0, 0);
advLayout->addRow(wkLayout); advLayout->addWidget(m_layoutLabel, 0, 1);
advLayout->addRow(tr("wkhtmltopdf path:"), wkPathLayout); advLayout->addWidget(layoutBtn, 0, 2);
advLayout->addRow(m_wkBackgroundCB);
advLayout->addRow(m_wkTableOfContentsCB); advLayout->addWidget(m_wkhtmltopdfCB, 1, 1, 1, 2);
advLayout->addRow(tr("Page number:"), m_wkPageNumberCB); advLayout->addWidget(wkBtn, 1, 4, 1, 2);
advLayout->addRow(tr("Additional arguments:"), m_wkExtraArgsEdit);
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); 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("Markdown"), (int)ExportFormat::Markdown);
m_formatCB->addItem(tr("HTML"), (int)ExportFormat::HTML); m_formatCB->addItem(tr("HTML"), (int)ExportFormat::HTML);
m_formatCB->addItem(tr("PDF"), (int)ExportFormat::PDF); 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)); m_formatCB->setCurrentIndex(m_formatCB->findData((int)s_opt.m_format));
// Markdown renderer. // Markdown renderer.
@ -464,8 +483,8 @@ void VExportDialog::startExport()
QString outputFolder = QDir::cleanPath(QDir(getOutputDirectory()).absolutePath()); QString outputFolder = QDir::cleanPath(QDir(getOutputDirectory()).absolutePath());
s_opt = ExportOption((ExportSource)m_srcCB->currentData().toInt(), s_opt = ExportOption(currentSource(),
(ExportFormat)m_formatCB->currentData().toInt(), currentFormat(),
(MarkdownConverterType)m_rendererCB->currentData().toInt(), (MarkdownConverterType)m_rendererCB->currentData().toInt(),
m_renderBgCB->currentData().toString(), m_renderBgCB->currentData().toString(),
m_renderStyleCB->currentData().toString(), m_renderStyleCB->currentData().toString(),
@ -476,6 +495,8 @@ void VExportDialog::startExport()
QDir::toNativeSeparators(m_wkPathEdit->text()), QDir::toNativeSeparators(m_wkPathEdit->text()),
m_wkBackgroundCB->isChecked(), m_wkBackgroundCB->isChecked(),
m_wkTableOfContentsCB->isChecked(), m_wkTableOfContentsCB->isChecked(),
m_wkTitleEdit->text(),
m_wkTargetFileNameEdit->text(),
(ExportPageNumber)m_wkPageNumberCB->currentData().toInt(), (ExportPageNumber)m_wkPageNumberCB->currentData().toInt(),
m_wkExtraArgsEdit->text()), m_wkExtraArgsEdit->text()),
ExportHTMLOption(m_embedStyleCB->isChecked(), ExportHTMLOption(m_embedStyleCB->isChecked(),
@ -486,11 +507,16 @@ void VExportDialog::startExport()
appendLogLine(tr("Export to %1.").arg(outputFolder)); appendLogLine(tr("Export to %1.").arg(outputFolder));
if (s_opt.m_format == ExportFormat::PDF if (s_opt.m_format == ExportFormat::PDF
|| s_opt.m_format == ExportFormat::OnePDF
|| s_opt.m_format == ExportFormat::HTML) { || 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 if ((s_opt.m_format == ExportFormat::PDF
&& s_opt.m_pdfOpt.m_wkhtmltopdf) { && s_opt.m_pdfOpt.m_wkhtmltopdf)
|| s_opt.m_format == ExportFormat::OnePDF) {
g_config->setWkhtmltopdfPath(s_opt.m_pdfOpt.m_wkPath); g_config->setWkhtmltopdfPath(s_opt.m_pdfOpt.m_wkPath);
g_config->setWkhtmltopdfArgs(s_opt.m_pdfOpt.m_wkExtraArgs); g_config->setWkhtmltopdfArgs(s_opt.m_pdfOpt.m_wkExtraArgs);
@ -500,11 +526,53 @@ void VExportDialog::startExport()
return; return;
} }
} }
m_exporter->prepareExport(s_opt);
} }
int ret = 0; int ret = 0;
QString msg; QString msg;
if (s_opt.m_format == ExportFormat::OnePDF) {
QList<QString> files;
// Output HTMLs to a tmp folder.
QTemporaryDir tmpDir;
if (!tmpDir.isValid()) {
goto exit;
}
qDebug() << "output HTMLs to temporary dir" << tmpDir.path();
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;
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) { switch (s_opt.m_source) {
case ExportSource::CurrentNote: case ExportSource::CurrentNote:
ret = doExport(m_file, s_opt, outputFolder, &msg); ret = doExport(m_file, s_opt, outputFolder, &msg);
@ -525,6 +593,9 @@ void VExportDialog::startExport()
default: default:
break; break;
} }
}
exit:
if (m_askedToStop) { if (m_askedToStop) {
appendLogLine(tr("User cancelled the export. Aborted!")); appendLogLine(tr("User cancelled the export. Aborted!"));
@ -622,24 +693,27 @@ void VExportDialog::appendLogLine(const QString &p_text)
int VExportDialog::doExport(VFile *p_file, int VExportDialog::doExport(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_ASSERT(p_file); Q_ASSERT(p_file);
appendLogLine(tr("Exporting note %1.").arg(p_file->fetchPath())); appendLogLine(tr("Exporting note %1.").arg(p_file->fetchPath()));
int ret = 0; int ret = 0;
switch ((int)p_opt.m_format) { switch (p_opt.m_format) {
case (int)ExportFormat::Markdown: case ExportFormat::Markdown:
ret = doExportMarkdown(p_file, p_opt, p_outputFolder, p_errMsg); ret = doExportMarkdown(p_file, p_opt, p_outputFolder, p_errMsg, p_outputFiles);
break; break;
case (int)ExportFormat::PDF: case ExportFormat::PDF:
ret = doExportPDF(p_file, p_opt, p_outputFolder, p_errMsg); V_FALLTHROUGH;
case ExportFormat::OnePDF:
ret = doExportPDF(p_file, p_opt, p_outputFolder, p_errMsg, p_outputFiles);
break; break;
case (int)ExportFormat::HTML: case ExportFormat::HTML:
ret = doExportHTML(p_file, p_opt, p_outputFolder, p_errMsg); ret = doExportHTML(p_file, p_opt, p_outputFolder, p_errMsg, p_outputFiles);
break; break;
default: default:
@ -652,7 +726,8 @@ int VExportDialog::doExport(VFile *p_file,
int VExportDialog::doExport(VDirectory *p_directory, int VExportDialog::doExport(VDirectory *p_directory,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_ASSERT(p_directory); Q_ASSERT(p_directory);
@ -678,7 +753,7 @@ int VExportDialog::doExport(VDirectory *p_directory,
goto exit; goto exit;
} }
ret += doExport(file, p_opt, outputPath, p_errMsg); ret += doExport(file, p_opt, outputPath, p_errMsg, p_outputFiles);
} }
// Export subfolders. // Export subfolders.
@ -688,7 +763,7 @@ int VExportDialog::doExport(VDirectory *p_directory,
goto exit; 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, int VExportDialog::doExport(VNotebook *p_notebook,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_ASSERT(p_notebook); Q_ASSERT(p_notebook);
@ -729,7 +805,7 @@ int VExportDialog::doExport(VNotebook *p_notebook,
goto exit; goto exit;
} }
ret += doExport(dir, p_opt, outputPath, p_errMsg); ret += doExport(dir, p_opt, outputPath, p_errMsg, p_outputFiles);
} }
exit: exit:
@ -743,7 +819,8 @@ exit:
int VExportDialog::doExport(VCart *p_cart, int VExportDialog::doExport(VCart *p_cart,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_ASSERT(p_cart); Q_ASSERT(p_cart);
@ -757,7 +834,7 @@ int VExportDialog::doExport(VCart *p_cart,
continue; continue;
} }
ret += doExport(file, p_opt, p_outputFolder, p_errMsg); ret += doExport(file, p_opt, p_outputFolder, p_errMsg, p_outputFiles);
} }
return ret; return ret;
@ -766,7 +843,8 @@ int VExportDialog::doExport(VCart *p_cart,
int VExportDialog::doExportMarkdown(VFile *p_file, int VExportDialog::doExportMarkdown(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_UNUSED(p_opt); Q_UNUSED(p_opt);
@ -826,6 +904,10 @@ int VExportDialog::doExportMarkdown(VFile *p_file,
} }
if (ret) { if (ret) {
if (p_outputFiles) {
p_outputFiles->append(destPath);
}
appendLogLine(tr("Note %1 exported to %2.").arg(srcFilePath).arg(outputPath)); 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, int VExportDialog::doExportPDF(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_UNUSED(p_opt); Q_UNUSED(p_opt);
@ -858,6 +941,10 @@ int VExportDialog::doExportPDF(VFile *p_file,
QString outputPath = QDir(p_outputFolder).filePath(name); QString outputPath = QDir(p_outputFolder).filePath(name);
if (m_exporter->exportPDF(p_file, p_opt, outputPath, p_errMsg)) { 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)); appendLogLine(tr("Note %1 exported to %2.").arg(srcFilePath).arg(outputPath));
return 1; return 1;
} else { } else {
@ -869,7 +956,8 @@ int VExportDialog::doExportPDF(VFile *p_file,
int VExportDialog::doExportHTML(VFile *p_file, int VExportDialog::doExportHTML(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg) QString *p_errMsg,
QList<QString> *p_outputFiles)
{ {
Q_UNUSED(p_opt); Q_UNUSED(p_opt);
@ -892,6 +980,10 @@ int VExportDialog::doExportHTML(VFile *p_file,
QString outputPath = QDir(p_outputFolder).filePath(name); QString outputPath = QDir(p_outputFolder).filePath(name);
if (m_exporter->exportHTML(p_file, p_opt, outputPath, p_errMsg)) { 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)); appendLogLine(tr("Note %1 exported to %2.").arg(srcFilePath).arg(outputPath));
return 1; return 1;
} else { } else {
@ -942,17 +1034,26 @@ void VExportDialog::handleCurrentFormatChanged(int p_index)
{ {
bool pdfEnabled = false; bool pdfEnabled = false;
bool htmlEnabled = false; bool htmlEnabled = false;
bool pdfTitleNameEnabled = false;
if (p_index >= 0) { if (p_index >= 0) {
switch (m_formatCB->currentData().toInt()) { switch (currentFormat()) {
case (int)ExportFormat::PDF: case ExportFormat::PDF:
pdfEnabled = true; pdfEnabled = true;
m_wkhtmltopdfCB->setEnabled(true);
break; break;
case (int)ExportFormat::HTML: case ExportFormat::HTML:
htmlEnabled = true; htmlEnabled = true;
break; break;
case ExportFormat::OnePDF:
pdfEnabled = true;
pdfTitleNameEnabled = true;
m_wkhtmltopdfCB->setChecked(true);
m_wkhtmltopdfCB->setEnabled(false);
break;
default: default:
break; break;
} }
@ -960,6 +1061,9 @@ void VExportDialog::handleCurrentFormatChanged(int p_index)
m_pdfSettings->setVisible(pdfEnabled); m_pdfSettings->setVisible(pdfEnabled);
m_htmlSettings->setVisible(htmlEnabled); m_htmlSettings->setVisible(htmlEnabled);
m_wkTitleEdit->setEnabled(pdfTitleNameEnabled);
m_wkTargetFileNameEdit->setEnabled(pdfTitleNameEnabled);
} }
void VExportDialog::handleCurrentSrcChanged(int p_index) void VExportDialog::handleCurrentSrcChanged(int p_index)
@ -967,8 +1071,8 @@ void VExportDialog::handleCurrentSrcChanged(int p_index)
bool subfolderEnabled = false; bool subfolderEnabled = false;
if (p_index >= 0) { if (p_index >= 0) {
switch (m_srcCB->currentData().toInt()) { switch (currentSource()) {
case (int)ExportSource::CurrentFolder: case ExportSource::CurrentFolder:
subfolderEnabled = true; subfolderEnabled = true;
break; break;
@ -979,3 +1083,41 @@ void VExportDialog::handleCurrentSrcChanged(int p_index)
m_subfolderCB->setVisible(subfolderEnabled); m_subfolderCB->setVisible(subfolderEnabled);
} }
int VExportDialog::doExportPDFAllInOne(const QList<QString> &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;
}

View File

@ -3,13 +3,14 @@
#include <QDialog> #include <QDialog>
#include <QPageLayout> #include <QPageLayout>
#include <QList>
#include <QComboBox>
#include "vconstants.h" #include "vconstants.h"
class QLabel; class QLabel;
class VLineEdit; class VLineEdit;
class QDialogButtonBox; class QDialogButtonBox;
class QComboBox;
class QPushButton; class QPushButton;
class QGroupBox; class QGroupBox;
class QPlainTextEdit; class QPlainTextEdit;
@ -35,7 +36,8 @@ enum class ExportFormat
{ {
Markdown = 0, Markdown = 0,
HTML, HTML,
PDF PDF,
OnePDF
}; };
@ -88,6 +90,8 @@ struct ExportPDFOption
const QString &p_wkPath, const QString &p_wkPath,
bool p_wkEnableBackground, bool p_wkEnableBackground,
bool p_wkEnableTableOfContents, bool p_wkEnableTableOfContents,
const QString &p_wkTitle,
const QString &p_wkTargetFileName,
ExportPageNumber p_wkPageNumber, ExportPageNumber p_wkPageNumber,
const QString &p_wkExtraArgs) const QString &p_wkExtraArgs)
: m_layout(p_layout), : m_layout(p_layout),
@ -95,6 +99,8 @@ struct ExportPDFOption
m_wkPath(p_wkPath), m_wkPath(p_wkPath),
m_wkEnableBackground(p_wkEnableBackground), m_wkEnableBackground(p_wkEnableBackground),
m_wkEnableTableOfContents(p_wkEnableTableOfContents), m_wkEnableTableOfContents(p_wkEnableTableOfContents),
m_wkTitle(p_wkTitle),
m_wkTargetFileName(p_wkTargetFileName),
m_wkPageNumber(p_wkPageNumber), m_wkPageNumber(p_wkPageNumber),
m_wkExtraArgs(p_wkExtraArgs) m_wkExtraArgs(p_wkExtraArgs)
{ {
@ -105,6 +111,8 @@ struct ExportPDFOption
QString m_wkPath; QString m_wkPath;
bool m_wkEnableBackground; bool m_wkEnableBackground;
bool m_wkEnableTableOfContents; bool m_wkEnableTableOfContents;
QString m_wkTitle;
QString m_wkTargetFileName;
ExportPageNumber m_wkPageNumber; ExportPageNumber m_wkPageNumber;
QString m_wkExtraArgs; QString m_wkExtraArgs;
}; };
@ -205,34 +213,46 @@ private:
int doExport(VFile *p_file, int doExport(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExport(VDirectory *p_directory, int doExport(VDirectory *p_directory,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExport(VNotebook *p_notebook, int doExport(VNotebook *p_notebook,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExport(VCart *p_cart, int doExport(VCart *p_cart,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExportMarkdown(VFile *p_file, int doExportMarkdown(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExportPDF(VFile *p_file, int doExportPDF(VFile *p_file,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExportHTML(VFile *p_file, int doExportHTML(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExportPDFAllInOne(const QList<QString> &p_files,
const ExportOption &p_opt, const ExportOption &p_opt,
const QString &p_outputFolder, const QString &p_outputFolder,
QString *p_errMsg = NULL); QString *p_errMsg = NULL);
@ -244,6 +264,10 @@ private:
bool checkWkhtmltopdfExecutable(const QString &p_file); bool checkWkhtmltopdfExecutable(const QString &p_file);
ExportSource currentSource() const;
ExportFormat currentFormat() const;
QComboBox *m_srcCB; QComboBox *m_srcCB;
QComboBox *m_formatCB; QComboBox *m_formatCB;
@ -284,6 +308,10 @@ private:
QPushButton *m_wkPathBrowseBtn; QPushButton *m_wkPathBrowseBtn;
VLineEdit *m_wkTitleEdit;
VLineEdit *m_wkTargetFileNameEdit;
QCheckBox *m_wkBackgroundCB; QCheckBox *m_wkBackgroundCB;
QCheckBox *m_wkTableOfContentsCB; QCheckBox *m_wkTableOfContentsCB;
@ -325,4 +353,13 @@ private:
static ExportOption s_opt; 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 #endif // VEXPORTDIALOG_H

View File

@ -6,6 +6,7 @@
#include <QWebEngineProfile> #include <QWebEngineProfile>
#include <QRegExp> #include <QRegExp>
#include <QProcess> #include <QProcess>
#include <QTemporaryDir>
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "vfile.h" #include "vfile.h"
@ -39,7 +40,8 @@ void VExporter::prepareExport(const ExportOption &p_opt)
p_opt.m_renderBg, p_opt.m_renderBg,
p_opt.m_renderStyle, p_opt.m_renderStyle,
p_opt.m_renderCodeBlockStyle, 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); 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); << "--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. // Append additional arguments.
if (!p_opt.m_wkExtraArgs.isEmpty()) { if (!p_opt.m_wkExtraArgs.isEmpty()) {
m_wkArgs.append(parseCombinedArgString(p_opt.m_wkExtraArgs)); m_wkArgs.append(parseCombinedArgString(p_opt.m_wkExtraArgs));
@ -265,7 +272,15 @@ bool VExporter::exportToPDFViaWK(VDocument *p_webDocument,
} }
Q_ASSERT(!p_filePath.isEmpty()); 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); QFile file(htmlPath);
if (!file.open(QFile::WriteOnly)) { if (!file.open(QFile::WriteOnly)) {
@ -296,16 +311,12 @@ bool VExporter::exportToPDFViaWK(VDocument *p_webDocument,
file.write(html.toUtf8()); file.write(html.toUtf8());
file.close(); file.close();
// Convert vis wkhtmltopdf. // Convert via wkhtmltopdf.
if (!htmlToPDFViaWK(htmlPath, p_filePath, p_opt, p_errMsg)) { QList<QString> files;
files.append(htmlPath);
if (!htmlsToPDFViaWK(files, p_filePath, p_opt, p_errMsg)) {
pdfExported = -1; pdfExported = -1;
} } else {
// Clean up.
VUtils::deleteFile(htmlPath);
VUtils::deleteDirectory(resFolderPath);
if (pdfExported == 0) {
pdfExported = 1; pdfExported = 1;
} }
}); });
@ -369,6 +380,8 @@ bool VExporter::exportViaWebView(VFile *p_file,
bool exportRet = false; bool exportRet = false;
switch (p_opt.m_format) { switch (p_opt.m_format) {
case ExportFormat::PDF: case ExportFormat::PDF:
V_FALLTHROUGH;
case ExportFormat::OnePDF:
if (p_opt.m_pdfOpt.m_wkhtmltopdf) { if (p_opt.m_pdfOpt.m_wkhtmltopdf) {
exportRet = exportToPDFViaWK(m_webDocument, exportRet = exportToPDFViaWK(m_webDocument,
p_opt.m_pdfOpt, p_opt.m_pdfOpt,
@ -624,7 +637,7 @@ static QString combineArgs(QStringList &p_args)
return str; return str;
} }
bool VExporter::htmlToPDFViaWK(const QString &p_htmlFile, bool VExporter::htmlsToPDFViaWK(const QList<QString> &p_htmlFiles,
const QString &p_filePath, const QString &p_filePath,
const ExportPDFOption &p_opt, const ExportPDFOption &p_opt,
QString *p_errMsg) QString *p_errMsg)
@ -632,9 +645,15 @@ bool VExporter::htmlToPDFViaWK(const QString &p_htmlFile,
// Note: system's locale settings (Language for non-Unicode programs) is important to wkhtmltopdf. // 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 // Input file could be encoded via QUrl::fromLocalFile(p_htmlFile).toString(QUrl::EncodeUnicode) to
// handle non-ASCII path. // handle non-ASCII path.
QStringList args(m_wkArgs); QStringList args(m_wkArgs);
args << QDir::toNativeSeparators(p_htmlFile);
for (auto const & it : p_htmlFiles) {
args << QDir::toNativeSeparators(it);
}
args << QDir::toNativeSeparators(p_filePath); args << QDir::toNativeSeparators(p_filePath);
QString cmd = p_opt.m_wkPath + " " + combineArgs(args); QString cmd = p_opt.m_wkPath + " " + combineArgs(args);
emit outputLog(cmd); emit outputLog(cmd);
int ret = QProcess::execute(p_opt.m_wkPath, args); int ret = QProcess::execute(p_opt.m_wkPath, args);
@ -654,3 +673,15 @@ bool VExporter::htmlToPDFViaWK(const QString &p_htmlFile,
return ret == 0; return ret == 0;
} }
int VExporter::exportPDFInOne(const QList<QString> &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();
}

View File

@ -31,6 +31,11 @@ public:
const QString &p_outputFile, const QString &p_outputFile,
QString *p_errMsg = NULL); QString *p_errMsg = NULL);
int exportPDFInOne(const QList<QString> &p_htmlFiles,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
signals: signals:
// Request to output log. // Request to output log.
void outputLog(const QString &p_log); void outputLog(const QString &p_log);
@ -95,7 +100,7 @@ private:
const ExportHTMLOption &p_opt, const ExportHTMLOption &p_opt,
const QString &p_filePath); const QString &p_filePath);
bool htmlToPDFViaWK(const QString &p_htmlFile, bool htmlsToPDFViaWK(const QList<QString> &p_htmlFiles,
const QString &p_filePath, const QString &p_filePath,
const ExportPDFOption &p_opt, const ExportPDFOption &p_opt,
QString *p_errMsg = NULL); QString *p_errMsg = NULL);