Pārlūkot izejas kodu

Exporter: support AllInOne in PDF format

Le Tan 4 gadi atpakaļ
vecāks
revīzija
e017c0f475

+ 7 - 1
src/export/exportdata.cpp

@@ -14,6 +14,7 @@ QJsonObject ExportHtmlOption::toJson() const
     obj["embed_images"] = m_embedImages;
     obj["embed_images"] = m_embedImages;
     obj["use_mime_html_format"] = m_useMimeHtmlFormat;
     obj["use_mime_html_format"] = m_useMimeHtmlFormat;
     obj["add_outline_panel"] = m_addOutlinePanel;
     obj["add_outline_panel"] = m_addOutlinePanel;
+    obj["scrollable"] = m_scrollable;
     return obj;
     return obj;
 }
 }
 
 
@@ -28,6 +29,7 @@ void ExportHtmlOption::fromJson(const QJsonObject &p_obj)
     m_embedImages = p_obj["embed_images"].toBool();
     m_embedImages = p_obj["embed_images"].toBool();
     m_useMimeHtmlFormat = p_obj["use_mime_html_format"].toBool();
     m_useMimeHtmlFormat = p_obj["use_mime_html_format"].toBool();
     m_addOutlinePanel = p_obj["add_outline_panel"].toBool();
     m_addOutlinePanel = p_obj["add_outline_panel"].toBool();
+    m_scrollable = p_obj["scrollable"].toBool(true);
 }
 }
 
 
 bool ExportHtmlOption::operator==(const ExportHtmlOption &p_other) const
 bool ExportHtmlOption::operator==(const ExportHtmlOption &p_other) const
@@ -36,7 +38,8 @@ bool ExportHtmlOption::operator==(const ExportHtmlOption &p_other) const
            && m_completePage == p_other.m_completePage
            && m_completePage == p_other.m_completePage
            && m_embedImages == p_other.m_embedImages
            && m_embedImages == p_other.m_embedImages
            && m_useMimeHtmlFormat == p_other.m_useMimeHtmlFormat
            && m_useMimeHtmlFormat == p_other.m_useMimeHtmlFormat
-           && m_addOutlinePanel == p_other.m_addOutlinePanel;
+           && m_addOutlinePanel == p_other.m_addOutlinePanel
+           && m_scrollable == p_other.m_scrollable;
 }
 }
 
 
 ExportPdfOption::ExportPdfOption()
 ExportPdfOption::ExportPdfOption()
@@ -52,6 +55,7 @@ QJsonObject ExportPdfOption::toJson() const
     QJsonObject obj;
     QJsonObject obj;
     obj["add_table_of_contents"] = m_addTableOfContents;
     obj["add_table_of_contents"] = m_addTableOfContents;
     obj["use_wkhtmltopdf"] = m_useWkhtmltopdf;
     obj["use_wkhtmltopdf"] = m_useWkhtmltopdf;
+    obj["all_in_one"] = m_allInOne;
     obj["wkhtmltopdf_exe_path"] = m_wkhtmltopdfExePath;
     obj["wkhtmltopdf_exe_path"] = m_wkhtmltopdfExePath;
     obj["wkhtmltopdf_args"] = m_wkhtmltopdfArgs;
     obj["wkhtmltopdf_args"] = m_wkhtmltopdfArgs;
     return obj;
     return obj;
@@ -65,6 +69,7 @@ void ExportPdfOption::fromJson(const QJsonObject &p_obj)
 
 
     m_addTableOfContents = p_obj["add_table_of_contents"].toBool();
     m_addTableOfContents = p_obj["add_table_of_contents"].toBool();
     m_useWkhtmltopdf = p_obj["use_wkhtmltopdf"].toBool();
     m_useWkhtmltopdf = p_obj["use_wkhtmltopdf"].toBool();
+    m_allInOne = p_obj["all_in_one"].toBool();
     m_wkhtmltopdfExePath = p_obj["wkhtmltopdf_exe_path"].toString();
     m_wkhtmltopdfExePath = p_obj["wkhtmltopdf_exe_path"].toString();
     m_wkhtmltopdfArgs = p_obj["wkhtmltopdf_args"].toString();
     m_wkhtmltopdfArgs = p_obj["wkhtmltopdf_args"].toString();
 }
 }
@@ -73,6 +78,7 @@ bool ExportPdfOption::operator==(const ExportPdfOption &p_other) const
 {
 {
     return m_addTableOfContents == p_other.m_addTableOfContents
     return m_addTableOfContents == p_other.m_addTableOfContents
            && m_useWkhtmltopdf == p_other.m_useWkhtmltopdf
            && m_useWkhtmltopdf == p_other.m_useWkhtmltopdf
+           && m_allInOne == p_other.m_allInOne
            && m_wkhtmltopdfExePath == p_other.m_wkhtmltopdfExePath
            && m_wkhtmltopdfExePath == p_other.m_wkhtmltopdfExePath
            && m_wkhtmltopdfArgs == p_other.m_wkhtmltopdfArgs;
            && m_wkhtmltopdfArgs == p_other.m_wkhtmltopdfArgs;
 }
 }

+ 7 - 1
src/export/exportdata.h

@@ -40,6 +40,9 @@ namespace vnotex
 
 
         // Whether add outline panel.
         // Whether add outline panel.
         bool m_addOutlinePanel = true;
         bool m_addOutlinePanel = true;
+
+        // When exporting to PDF or custom format, we may need to export to HTML first without scrollable.
+        bool m_scrollable = true;
     };
     };
 
 
     struct ExportPdfOption
     struct ExportPdfOption
@@ -53,11 +56,14 @@ namespace vnotex
 
 
         QSharedPointer<QPageLayout> m_layout;
         QSharedPointer<QPageLayout> m_layout;
 
 
-        // Add TOC at the front to complement the missing of outline.
+        // Add TOC at the front.
         bool m_addTableOfContents = false;
         bool m_addTableOfContents = false;
 
 
         bool m_useWkhtmltopdf = false;
         bool m_useWkhtmltopdf = false;
 
 
+        // Valid only when wkhtmltopdf is used.
+        bool m_allInOne = false;
+
         QString m_wkhtmltopdfExePath;
         QString m_wkhtmltopdfExePath;
 
 
         QString m_wkhtmltopdfArgs;
         QString m_wkhtmltopdfArgs;

+ 147 - 14
src/export/exporter.cpp

@@ -1,6 +1,7 @@
 #include "exporter.h"
 #include "exporter.h"
 
 
 #include <QWidget>
 #include <QWidget>
+#include <QTemporaryDir>
 
 
 #include <notebook/notebook.h>
 #include <notebook/notebook.h>
 #include <notebook/node.h>
 #include <notebook/node.h>
@@ -31,7 +32,7 @@ QString Exporter::doExport(const ExportOption &p_option, Buffer *p_buffer)
 
 
     // Make sure output folder exists.
     // Make sure output folder exists.
     if (!QDir().mkpath(p_option.m_outputDir)) {
     if (!QDir().mkpath(p_option.m_outputDir)) {
-        emit logRequested(tr("Failed to create output folder %1.").arg(p_option.m_outputDir));
+        emit logRequested(tr("Failed to create output folder (%1).").arg(p_option.m_outputDir));
         return outputFile;
         return outputFile;
     }
     }
 
 
@@ -42,6 +43,17 @@ QString Exporter::doExport(const ExportOption &p_option, Buffer *p_buffer)
     return outputFile;
     return outputFile;
 }
 }
 
 
+static QString makeOutputFolder(const QString &p_outputDir, const QString &p_folderName)
+{
+    const auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_folderName);
+    const auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name);
+    if (!QDir().mkpath(outputFolder)) {
+        return QString();
+    }
+
+    return outputFolder;
+}
+
 QString Exporter::doExportMarkdown(const ExportOption &p_option, const QString &p_outputDir, const File *p_file)
 QString Exporter::doExportMarkdown(const ExportOption &p_option, const QString &p_outputDir, const File *p_file)
 {
 {
     QString outputFile;
     QString outputFile;
@@ -51,11 +63,11 @@ QString Exporter::doExportMarkdown(const ExportOption &p_option, const QString &
     }
     }
 
 
     // Export it to a folder with the same name.
     // Export it to a folder with the same name.
-    auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_file->getName(), "");
-    auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name);
+    const auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_file->getName(), "");
+    const auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name);
     QDir outDir(outputFolder);
     QDir outDir(outputFolder);
     if (!outDir.mkpath(outputFolder)) {
     if (!outDir.mkpath(outputFolder)) {
-        emit logRequested(tr("Failed to create output folder %1.").arg(outputFolder));
+        emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir));
         return outputFile;
         return outputFile;
     }
     }
 
 
@@ -113,11 +125,102 @@ QString Exporter::doExport(const ExportOption &p_option, Node *p_note)
     return outputFile;
     return outputFile;
 }
 }
 
 
+QString Exporter::doExportAllInOne(const ExportOption &p_option, Node *p_folder)
+{
+    // Make path.
+    const auto outputFolder = makeOutputFolder(p_option.m_outputDir, p_folder->getName());
+    if (outputFolder.isEmpty()) {
+        emit logRequested(tr("Failed to create output folder under (%1).").arg(p_option.m_outputDir));
+        return QString();
+    }
+
+    // Export to HTML to a tmp dir first.
+    QTemporaryDir tmpDir;
+    if (!tmpDir.isValid()) {
+        emit logRequested(tr("Failed to create temporary dir to hold HTML files."));
+        return QString();
+    }
+
+    auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path()));
+
+    auto htmlFiles = doExport(tmpOption, tmpDir.path(), p_folder);
+    if (htmlFiles.isEmpty()) {
+        return QString();
+    }
+
+    if (checkAskedToStop()) {
+        return QString();
+    }
+
+    cleanUpWebViewExporter();
+
+    auto fileName = FileUtils::generateFileNameWithSequence(outputFolder,
+                                                            tr("all_in_one_export"),
+                                                            "pdf");
+    auto destFilePath = PathUtils::concatenateFilePath(outputFolder, fileName);
+    if (getWebViewExporter(p_option)->htmlToPdfViaWkhtmltopdf(p_option.m_pdfOption, htmlFiles, destFilePath)) {
+        emit logRequested(tr("Exported to (%1).").arg(destFilePath));
+        return destFilePath;
+    }
+
+    return QString();
+}
+
+QString Exporter::doExportAllInOne(const ExportOption &p_option, Notebook *p_notebook)
+{
+    // Make path.
+    const auto outputFolder = makeOutputFolder(p_option.m_outputDir, tr("notebook_%1").arg(p_notebook->getName()));
+    if (outputFolder.isEmpty()) {
+        emit logRequested(tr("Failed to create output folder under (%1).").arg(p_option.m_outputDir));
+        return QString();
+    }
+
+    // Export to HTML to a tmp dir first.
+    QTemporaryDir tmpDir;
+    if (!tmpDir.isValid()) {
+        emit logRequested(tr("Failed to create temporary dir to hold HTML files."));
+        return QString();
+    }
+
+    auto tmpOption(getExportOptionForIntermediateHtml(p_option, tmpDir.path()));
+
+    auto htmlFiles = doExportNotebook(tmpOption, tmpDir.path(), p_notebook);
+    if (htmlFiles.isEmpty()) {
+        return QString();
+    }
+
+    if (checkAskedToStop()) {
+        return QString();
+    }
+
+    cleanUpWebViewExporter();
+
+    auto fileName = FileUtils::generateFileNameWithSequence(outputFolder,
+                                                            tr("all_in_one_export"),
+                                                            "pdf");
+    auto destFilePath = PathUtils::concatenateFilePath(outputFolder, fileName);
+    if (getWebViewExporter(p_option)->htmlToPdfViaWkhtmltopdf(p_option.m_pdfOption, htmlFiles, destFilePath)) {
+        emit logRequested(tr("Exported to (%1).").arg(destFilePath));
+        return destFilePath;
+    }
+
+    return QString();
+}
+
 QStringList Exporter::doExportFolder(const ExportOption &p_option, Node *p_folder)
 QStringList Exporter::doExportFolder(const ExportOption &p_option, Node *p_folder)
 {
 {
     m_askedToStop = false;
     m_askedToStop = false;
 
 
-    auto outputFiles = doExport(p_option, p_option.m_outputDir, p_folder);
+    QStringList outputFiles;
+
+    if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_useWkhtmltopdf && p_option.m_pdfOption.m_allInOne) {
+        auto file = doExportAllInOne(p_option, p_folder);
+        if (!file.isEmpty()) {
+            outputFiles << file;
+        }
+    } else {
+        outputFiles = doExport(p_option, p_option.m_outputDir, p_folder);
+    }
 
 
     cleanUp();
     cleanUp();
 
 
@@ -131,10 +234,9 @@ QStringList Exporter::doExport(const ExportOption &p_option, const QString &p_ou
     QStringList outputFiles;
     QStringList outputFiles;
 
 
     // Make path.
     // Make path.
-    auto name = FileUtils::generateFileNameWithSequence(p_outputDir, p_folder->getName());
-    auto outputFolder = PathUtils::concatenateFilePath(p_outputDir, name);
-    if (!QDir().mkpath(outputFolder)) {
-        emit logRequested(tr("Failed to create output folder %1.").arg(outputFolder));
+    const auto outputFolder = makeOutputFolder(p_outputDir, p_folder->getName());
+    if (outputFolder.isEmpty()) {
+        emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir));
         return outputFiles;
         return outputFiles;
     }
     }
 
 
@@ -200,12 +302,30 @@ QStringList Exporter::doExport(const ExportOption &p_option, Notebook *p_noteboo
 
 
     QStringList outputFiles;
     QStringList outputFiles;
 
 
+    if (p_option.m_targetFormat == ExportFormat::PDF && p_option.m_pdfOption.m_useWkhtmltopdf && p_option.m_pdfOption.m_allInOne) {
+        auto file = doExportAllInOne(p_option, p_notebook);
+        if (!file.isEmpty()) {
+            outputFiles << file;
+        }
+    } else {
+        outputFiles = doExportNotebook(p_option, p_option.m_outputDir, p_notebook);
+    }
+
+    cleanUp();
+
+    return outputFiles;
+}
+
+QStringList Exporter::doExportNotebook(const ExportOption &p_option, const QString &p_outputDir, Notebook *p_notebook)
+{
+    m_askedToStop = false;
+
+    QStringList outputFiles;
+
     // Make path.
     // Make path.
-    auto name = FileUtils::generateFileNameWithSequence(p_option.m_outputDir,
-                                                        tr("notebook_%1").arg(p_notebook->getName()));
-    auto outputFolder = PathUtils::concatenateFilePath(p_option.m_outputDir, name);
-    if (!QDir().mkpath(outputFolder)) {
-        emit logRequested(tr("Failed to create output folder %1.").arg(outputFolder));
+    const auto outputFolder = makeOutputFolder(p_outputDir, tr("notebook_%1").arg(p_notebook->getName()));
+    if (outputFolder.isEmpty()) {
+        emit logRequested(tr("Failed to create output folder under (%1).").arg(p_outputDir));
         return outputFiles;
         return outputFiles;
     }
     }
 
 
@@ -333,3 +453,16 @@ QString Exporter::doExportPdf(const ExportOption &p_option, const QString &p_out
     }
     }
     return outputFile;
     return outputFile;
 }
 }
+
+ExportOption Exporter::getExportOptionForIntermediateHtml(const ExportOption &p_option, const QString &p_outputDir)
+{
+    ExportOption tmpOption(p_option);
+    tmpOption.m_targetFormat = ExportFormat::HTML;
+    tmpOption.m_htmlOption.m_embedStyles = true;
+    tmpOption.m_htmlOption.m_completePage = true;
+    tmpOption.m_htmlOption.m_embedImages = false;
+    tmpOption.m_htmlOption.m_scrollable = false;
+    tmpOption.m_outputDir = p_outputDir;
+
+    return tmpOption;
+}

+ 8 - 0
src/export/exporter.h

@@ -50,6 +50,10 @@ namespace vnotex
 
 
         QString doExportPdf(const ExportOption &p_option, const QString &p_outputDir, const File *p_file);
         QString doExportPdf(const ExportOption &p_option, const QString &p_outputDir, const File *p_file);
 
 
+        QString doExportAllInOne(const ExportOption &p_option, Node *p_folder);
+
+        QString doExportAllInOne(const ExportOption &p_option, Notebook *p_notebook);
+
         void exportAttachments(Node *p_node,
         void exportAttachments(Node *p_node,
                                const QString &p_srcFilePath,
                                const QString &p_srcFilePath,
                                const QString &p_outputFolder,
                                const QString &p_outputFolder,
@@ -63,6 +67,10 @@ namespace vnotex
 
 
         bool checkAskedToStop() const;
         bool checkAskedToStop() const;
 
 
+        QStringList doExportNotebook(const ExportOption &p_option, const QString &p_outputDir, Notebook *p_notebook);
+
+        static ExportOption getExportOptionForIntermediateHtml(const ExportOption &p_option, const QString &p_outputDir);
+
         // Managed by QObject.
         // Managed by QObject.
         WebViewExporter *m_webViewExporter = nullptr;
         WebViewExporter *m_webViewExporter = nullptr;
 
 

+ 8 - 3
src/export/webviewexporter.cpp

@@ -263,7 +263,12 @@ void WebViewExporter::prepare(const ExportOption &p_option)
                 });
                 });
     }
     }
 
 
-    const bool scrollable = p_option.m_targetFormat != ExportFormat::PDF;
+    bool scrollable = true;
+    if (p_option.m_targetFormat == ExportFormat::PDF
+        || (p_option.m_targetFormat == ExportFormat::HTML && !p_option.m_htmlOption.m_scrollable)) {
+        scrollable = false;
+    }
+
     const auto &config = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
     const auto &config = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
     bool useWkhtmltopdf = false;
     bool useWkhtmltopdf = false;
     QSize pageBodySize(1024, 768);
     QSize pageBodySize(1024, 768);
@@ -524,7 +529,7 @@ bool WebViewExporter::doExportWkhtmltopdf(const ExportPdfOption &p_pdfOption, co
                 }
                 }
 
 
                 // Convert HTML to PDF via wkhtmltopdf.
                 // Convert HTML to PDF via wkhtmltopdf.
-                if (doWkhtmltopdf(p_pdfOption, QStringList() << tmpHtmlFile, p_outputFile)) {
+                if (htmlToPdfViaWkhtmltopdf(p_pdfOption, QStringList() << tmpHtmlFile, p_outputFile)) {
                     state = ExportState::Finished;
                     state = ExportState::Finished;
                 } else {
                 } else {
                     state = ExportState::Failed;
                     state = ExportState::Failed;
@@ -544,7 +549,7 @@ bool WebViewExporter::doExportWkhtmltopdf(const ExportPdfOption &p_pdfOption, co
     return state == ExportState::Finished;
     return state == ExportState::Finished;
 }
 }
 
 
-bool WebViewExporter::doWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, const QString &p_outputFile)
+bool WebViewExporter::htmlToPdfViaWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, const QString &p_outputFile)
 {
 {
     // 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

+ 2 - 2
src/export/webviewexporter.h

@@ -41,6 +41,8 @@ namespace vnotex
 
 
         void stop();
         void stop();
 
 
+        bool htmlToPdfViaWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, const QString &p_outputFile);
+
     signals:
     signals:
         void logRequested(const QString &p_log);
         void logRequested(const QString &p_log);
 
 
@@ -82,8 +84,6 @@ namespace vnotex
 
 
         QSize pageLayoutSize(const QPageLayout &p_layout) const;
         QSize pageLayoutSize(const QPageLayout &p_layout) const;
 
 
-        bool doWkhtmltopdf(const ExportPdfOption &p_pdfOption, const QStringList &p_htmlFiles, const QString &p_outputFile);
-
         void prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOption);
         void prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOption);
 
 
         bool startProcess(const QString &p_program, const QStringList &p_args);
         bool startProcess(const QString &p_program, const QStringList &p_args);

+ 20 - 3
src/widgets/dialogs/exportdialog.cpp

@@ -476,8 +476,13 @@ Exporter *ExportDialog::getExporter()
 
 
 void ExportDialog::updateProgress(int p_val, int p_maximum)
 void ExportDialog::updateProgress(int p_val, int p_maximum)
 {
 {
-    m_progressBar->setMaximum(p_maximum);
-    m_progressBar->setValue(p_val);
+    if (p_maximum < m_progressBar->value()) {
+        m_progressBar->setValue(p_val);
+        m_progressBar->setMaximum(p_maximum);
+    } else {
+        m_progressBar->setMaximum(p_maximum);
+        m_progressBar->setValue(p_val);
+    }
 }
 }
 
 
 QWidget *ExportDialog::getHtmlAdvancedSettings()
 QWidget *ExportDialog::getHtmlAdvancedSettings()
@@ -619,7 +624,7 @@ QWidget *ExportDialog::getPdfAdvancedSettings()
         {
         {
             auto useLayout = new QHBoxLayout();
             auto useLayout = new QHBoxLayout();
 
 
-            m_useWkhtmltopdfCheckBox = WidgetsFactory::createCheckBox(tr("Use wkhtmltopdf"), widget);
+            m_useWkhtmltopdfCheckBox = WidgetsFactory::createCheckBox(tr("Use wkhtmltopdf (outline supported)"), widget);
             useLayout->addWidget(m_useWkhtmltopdfCheckBox);
             useLayout->addWidget(m_useWkhtmltopdfCheckBox);
 
 
             auto downloadBtn = new QPushButton(tr("Download"), widget);
             auto downloadBtn = new QPushButton(tr("Download"), widget);
@@ -632,6 +637,16 @@ QWidget *ExportDialog::getPdfAdvancedSettings()
             layout->addRow(useLayout);
             layout->addRow(useLayout);
         }
         }
 
 
+        {
+            m_allInOneCheckBox = WidgetsFactory::createCheckBox(tr("All In One"), widget);
+            m_allInOneCheckBox->setToolTip(tr("Export all source files into one file"));
+            connect(m_useWkhtmltopdfCheckBox, &QCheckBox::stateChanged,
+                    this, [this](int p_state) {
+                        m_allInOneCheckBox->setEnabled(p_state == Qt::Checked);
+                    });
+            layout->addRow(m_allInOneCheckBox);
+        }
+
         {
         {
             auto pathLayout = new QHBoxLayout();
             auto pathLayout = new QHBoxLayout();
 
 
@@ -676,6 +691,7 @@ void ExportDialog::restoreFields(const ExportPdfOption &p_option)
 
 
     m_addTableOfContentsCheckBox->setChecked(p_option.m_addTableOfContents);
     m_addTableOfContentsCheckBox->setChecked(p_option.m_addTableOfContents);
     m_useWkhtmltopdfCheckBox->setChecked(p_option.m_useWkhtmltopdf);
     m_useWkhtmltopdfCheckBox->setChecked(p_option.m_useWkhtmltopdf);
+    m_allInOneCheckBox->setChecked(p_option.m_allInOne);
     m_wkhtmltopdfExePathLineEdit->setText(p_option.m_wkhtmltopdfExePath);
     m_wkhtmltopdfExePathLineEdit->setText(p_option.m_wkhtmltopdfExePath);
     m_wkhtmltopdfArgsLineEdit->setText(p_option.m_wkhtmltopdfArgs);
     m_wkhtmltopdfArgsLineEdit->setText(p_option.m_wkhtmltopdfArgs);
 }
 }
@@ -685,6 +701,7 @@ void ExportDialog::saveFields(ExportPdfOption &p_option)
     p_option.m_layout = m_pageLayout;
     p_option.m_layout = m_pageLayout;
     p_option.m_addTableOfContents = m_addTableOfContentsCheckBox->isChecked();
     p_option.m_addTableOfContents = m_addTableOfContentsCheckBox->isChecked();
     p_option.m_useWkhtmltopdf = m_useWkhtmltopdfCheckBox->isChecked();
     p_option.m_useWkhtmltopdf = m_useWkhtmltopdfCheckBox->isChecked();
+    p_option.m_allInOne = m_allInOneCheckBox->isChecked();
     p_option.m_wkhtmltopdfExePath = m_wkhtmltopdfExePathLineEdit->text();
     p_option.m_wkhtmltopdfExePath = m_wkhtmltopdfExePathLineEdit->text();
     p_option.m_wkhtmltopdfArgs = m_wkhtmltopdfArgsLineEdit->text();
     p_option.m_wkhtmltopdfArgs = m_wkhtmltopdfArgsLineEdit->text();
 }
 }

+ 2 - 0
src/widgets/dialogs/exportdialog.h

@@ -162,6 +162,8 @@ namespace vnotex
 
 
         QCheckBox *m_useWkhtmltopdfCheckBox = nullptr;
         QCheckBox *m_useWkhtmltopdfCheckBox = nullptr;
 
 
+        QCheckBox *m_allInOneCheckBox = nullptr;
+
         QLineEdit *m_wkhtmltopdfExePathLineEdit = nullptr;
         QLineEdit *m_wkhtmltopdfExePathLineEdit = nullptr;
 
 
         QLineEdit *m_wkhtmltopdfArgsLineEdit = nullptr;
         QLineEdit *m_wkhtmltopdfArgsLineEdit = nullptr;

+ 1 - 1
src/widgets/editors/graphhelper.h

@@ -90,7 +90,7 @@ namespace vnotex
         vte::LruCache<QString, CacheItem> m_cache;
         vte::LruCache<QString, CacheItem> m_cache;
 
 
         // Whether @m_program is valid.
         // Whether @m_program is valid.
-        bool m_programValid = true;
+        bool m_programValid = false;
     };
     };
 }
 }
 
 

+ 11 - 11
src/widgets/editors/graphvizhelper.cpp

@@ -5,26 +5,26 @@
 
 
 #include <utils/processutils.h>
 #include <utils/processutils.h>
 #include <utils/pathutils.h>
 #include <utils/pathutils.h>
+#include <core/configmgr.h>
+#include <core/editorconfig.h>
+#include <core/markdowneditorconfig.h>
 
 
 using namespace vnotex;
 using namespace vnotex;
 
 
-void GraphvizHelper::init(const QString &p_graphvizFile)
+GraphvizHelper &GraphvizHelper::getInst()
 {
 {
-    if (m_initialized) {
-        return;
+    static bool initialized = false;
+    static GraphvizHelper inst;
+    if (!initialized) {
+        initialized = true;
+        const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
+        inst.update(markdownEditorConfig.getGraphvizExe());
     }
     }
-
-    m_initialized = true;
-
-    update(p_graphvizFile);
+    return inst;
 }
 }
 
 
 void GraphvizHelper::update(const QString &p_graphvizFile)
 void GraphvizHelper::update(const QString &p_graphvizFile)
 {
 {
-    if (!m_initialized) {
-        return;
-    }
-
     prepareProgramAndArgs(p_graphvizFile, m_program, m_args);
     prepareProgramAndArgs(p_graphvizFile, m_program, m_args);
 
 
     checkValidProgram();
     checkValidProgram();

+ 1 - 9
src/widgets/editors/graphvizhelper.h

@@ -8,15 +8,9 @@ namespace vnotex
     class GraphvizHelper : public GraphHelper
     class GraphvizHelper : public GraphHelper
     {
     {
     public:
     public:
-        void init(const QString &p_graphvizFile);
-
         void update(const QString &p_graphvizFile);
         void update(const QString &p_graphvizFile);
 
 
-        static GraphvizHelper &getInst()
-        {
-            static GraphvizHelper inst;
-            return inst;
-        }
+        static GraphvizHelper &getInst();
 
 
         static QPair<bool, QString> testGraphviz(const QString &p_graphvizFile);
         static QPair<bool, QString> testGraphviz(const QString &p_graphvizFile);
 
 
@@ -28,8 +22,6 @@ namespace vnotex
         static void prepareProgramAndArgs(const QString &p_graphvizFile,
         static void prepareProgramAndArgs(const QString &p_graphvizFile,
                                           QString &p_program,
                                           QString &p_program,
                                           QStringList &p_args);
                                           QStringList &p_args);
-
-        bool m_initialized = false;
     };
     };
 }
 }
 
 

+ 13 - 13
src/widgets/editors/plantumlhelper.cpp

@@ -5,30 +5,30 @@
 
 
 #include <utils/processutils.h>
 #include <utils/processutils.h>
 #include <utils/pathutils.h>
 #include <utils/pathutils.h>
+#include <core/configmgr.h>
+#include <core/editorconfig.h>
+#include <core/markdowneditorconfig.h>
 
 
 using namespace vnotex;
 using namespace vnotex;
 
 
-void PlantUmlHelper::init(const QString &p_plantUmlJarFile,
-                          const QString &p_graphvizFile,
-                          const QString &p_overriddenCommand)
+PlantUmlHelper &PlantUmlHelper::getInst()
 {
 {
-    if (m_initialized) {
-        return;
+    static bool initialized = false;
+    static PlantUmlHelper inst;
+    if (!initialized) {
+        initialized = true;
+        const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
+        inst.update(markdownEditorConfig.getPlantUmlJar(),
+                    markdownEditorConfig.getGraphvizExe(),
+                    markdownEditorConfig.getPlantUmlCommand());
     }
     }
-
-    m_initialized = true;
-
-    update(p_plantUmlJarFile, p_graphvizFile, p_overriddenCommand);
+    return inst;
 }
 }
 
 
 void PlantUmlHelper::update(const QString &p_plantUmlJarFile,
 void PlantUmlHelper::update(const QString &p_plantUmlJarFile,
                             const QString &p_graphvizFile,
                             const QString &p_graphvizFile,
                             const QString &p_overriddenCommand)
                             const QString &p_overriddenCommand)
 {
 {
-    if (!m_initialized) {
-        return;
-    }
-
     m_overriddenCommand = p_overriddenCommand;
     m_overriddenCommand = p_overriddenCommand;
     if (m_overriddenCommand.isEmpty()) {
     if (m_overriddenCommand.isEmpty()) {
         prepareProgramAndArgs(p_plantUmlJarFile, p_graphvizFile, m_program, m_args);
         prepareProgramAndArgs(p_plantUmlJarFile, p_graphvizFile, m_program, m_args);

+ 1 - 11
src/widgets/editors/plantumlhelper.h

@@ -8,19 +8,11 @@ namespace vnotex
     class PlantUmlHelper : public GraphHelper
     class PlantUmlHelper : public GraphHelper
     {
     {
     public:
     public:
-        void init(const QString &p_plantUmlJarFile,
-                  const QString &p_graphvizFile,
-                  const QString &p_overriddenCommand);
-
         void update(const QString &p_plantUmlJarFile,
         void update(const QString &p_plantUmlJarFile,
                     const QString &p_graphvizFile,
                     const QString &p_graphvizFile,
                     const QString &p_overriddenCommand);
                     const QString &p_overriddenCommand);
 
 
-        static PlantUmlHelper &getInst()
-        {
-            static PlantUmlHelper inst;
-            return inst;
-        }
+        static PlantUmlHelper &getInst();
 
 
         static QPair<bool, QString> testPlantUml(const QString &p_plantUmlJarFile);
         static QPair<bool, QString> testPlantUml(const QString &p_plantUmlJarFile);
 
 
@@ -33,8 +25,6 @@ namespace vnotex
                                           const QString &p_graphvizFile,
                                           const QString &p_graphvizFile,
                                           QString &p_program,
                                           QString &p_program,
                                           QStringList &p_args);
                                           QStringList &p_args);
-
-        bool m_initialized = false;
     };
     };
 }
 }
 
 

+ 0 - 5
src/widgets/markdownviewwindow.cpp

@@ -1060,11 +1060,6 @@ void MarkdownViewWindow::setupPreviewHelper()
 
 
     const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
     const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
     updatePreviewHelperFromConfig(markdownEditorConfig);
     updatePreviewHelperFromConfig(markdownEditorConfig);
-
-    PlantUmlHelper::getInst().init(markdownEditorConfig.getPlantUmlJar(),
-                                   markdownEditorConfig.getGraphvizExe(),
-                                   markdownEditorConfig.getPlantUmlCommand());
-    GraphvizHelper::getInst().init(markdownEditorConfig.getGraphvizExe());
 }
 }
 
 
 void MarkdownViewWindow::updatePreviewHelperFromConfig(const MarkdownEditorConfig &p_config)
 void MarkdownViewWindow::updatePreviewHelperFromConfig(const MarkdownEditorConfig &p_config)

+ 2 - 5
src/widgets/toolbarhelper.cpp

@@ -148,7 +148,7 @@ QToolBar *ToolBarHelper::setupFileToolBar(MainWindow *p_win, QToolBar *p_toolBar
 
 
     // Import and export.
     // Import and export.
     {
     {
-        auto act = tb->addAction(generateIcon("import_export_menu.svg"), MainWindow::tr("Import And Export"));
+        auto act = tb->addAction(generateIcon("import_export_menu.svg"), MainWindow::tr("Import/Export"));
 
 
         auto btn = dynamic_cast<QToolButton *>(tb->widgetForAction(act));
         auto btn = dynamic_cast<QToolButton *>(tb->widgetForAction(act));
         Q_ASSERT(btn);
         Q_ASSERT(btn);
@@ -223,13 +223,12 @@ QToolBar *ToolBarHelper::setupQuickAccessToolBar(MainWindow *p_win, QToolBar *p_
     // Quick Access.
     // Quick Access.
     {
     {
         auto toolBtn = WidgetsFactory::createToolButton(tb);
         auto toolBtn = WidgetsFactory::createToolButton(tb);
-        toolBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
 
 
         auto btnMenu = WidgetsFactory::createMenu(tb);
         auto btnMenu = WidgetsFactory::createMenu(tb);
         toolBtn->setMenu(btnMenu);
         toolBtn->setMenu(btnMenu);
 
 
         // Quick Acces.
         // Quick Acces.
-        auto quickAccessAct = new QAction(generateIcon("quick_access_menu.svg"), MainWindow::tr("Quick Access"), toolBtn);
+        auto quickAccessAct = btnMenu->addAction(generateIcon("quick_access_menu.svg"), MainWindow::tr("Quick Access"));
         MainWindow::connect(quickAccessAct, &QAction::triggered,
         MainWindow::connect(quickAccessAct, &QAction::triggered,
                             p_win, [p_win]() {
                             p_win, [p_win]() {
                                 const auto &quickAccess = ConfigMgr::getInst().getSessionConfig().getQuickAccessFiles();
                                 const auto &quickAccess = ConfigMgr::getInst().getSessionConfig().getQuickAccessFiles();
@@ -250,8 +249,6 @@ QToolBar *ToolBarHelper::setupQuickAccessToolBar(MainWindow *p_win, QToolBar *p_
                                        coreConfig.getShortcut(CoreConfig::Shortcut::QuickAccess));
                                        coreConfig.getShortcut(CoreConfig::Shortcut::QuickAccess));
 
 
         toolBtn->setDefaultAction(quickAccessAct);
         toolBtn->setDefaultAction(quickAccessAct);
-        // To hide the shortcut text shown in button.
-        toolBtn->setText(MainWindow::tr("Quick Access"));
 
 
         MainWindow::connect(btnMenu, &QMenu::aboutToShow,
         MainWindow::connect(btnMenu, &QMenu::aboutToShow,
                             btnMenu, [btnMenu]() {
                             btnMenu, [btnMenu]() {