recover export

This commit is contained in:
Le Tan 2019-07-30 21:00:25 +08:00
parent f507475ccd
commit f72d6e6299
12 changed files with 3322 additions and 10 deletions

1505
src/dialog/vexportdialog.cpp Normal file

File diff suppressed because it is too large Load Diff

516
src/dialog/vexportdialog.h Normal file
View File

@ -0,0 +1,516 @@
#ifndef VEXPORTDIALOG_H
#define VEXPORTDIALOG_H
#include <QDialog>
#include <QPageLayout>
#include <QList>
#include <QComboBox>
#include "vconstants.h"
class QLabel;
class VLineEdit;
class QDialogButtonBox;
class QPushButton;
class QGroupBox;
class QPlainTextEdit;
class VNotebook;
class VDirectory;
class VFile;
class VCart;
class VExporter;
class QCheckBox;
class VLineEdit;
class QProgressBar;
enum class ExportSource
{
CurrentNote = 0,
CurrentFolder,
CurrentNotebook,
Cart
};
enum class ExportFormat
{
Markdown = 0,
HTML,
PDF,
OnePDF,
Custom
};
enum class ExportPageNumber
{
None = 0,
Left,
Center,
Right
};
struct ExportHTMLOption
{
ExportHTMLOption()
: m_embedCssStyle(true),
m_completeHTML(true),
m_embedImages(true),
m_mimeHTML(false),
m_outlinePanel(true)
{
}
ExportHTMLOption(bool p_embedCssStyle,
bool p_completeHTML,
bool p_embedImages,
bool p_mimeHTML,
bool p_outlinePanel)
: m_embedCssStyle(p_embedCssStyle),
m_completeHTML(p_completeHTML),
m_embedImages(p_embedImages),
m_mimeHTML(p_mimeHTML),
m_outlinePanel(p_outlinePanel)
{
}
bool m_embedCssStyle;
bool m_completeHTML;
bool m_embedImages;
bool m_mimeHTML;
bool m_outlinePanel;
};
struct ExportPDFOption
{
ExportPDFOption()
: m_layout(NULL),
m_wkhtmltopdf(false),
m_wkEnableBackground(true),
m_enableTableOfContents(false),
m_wkPageNumber(ExportPageNumber::None)
{
}
ExportPDFOption(QPageLayout *p_layout,
bool p_wkhtmltopdf,
const QString &p_wkPath,
bool p_wkEnableBackground,
bool p_enableTableOfContents,
const QString &p_wkTitle,
const QString &p_wkTargetFileName,
ExportPageNumber p_wkPageNumber,
const QString &p_wkExtraArgs)
: m_layout(p_layout),
m_wkhtmltopdf(p_wkhtmltopdf),
m_wkPath(p_wkPath),
m_wkEnableBackground(p_wkEnableBackground),
m_enableTableOfContents(p_enableTableOfContents),
m_wkTitle(p_wkTitle),
m_wkTargetFileName(p_wkTargetFileName),
m_wkPageNumber(p_wkPageNumber),
m_wkExtraArgs(p_wkExtraArgs)
{
}
QPageLayout *m_layout;
bool m_wkhtmltopdf;
QString m_wkPath;
bool m_wkEnableBackground;
bool m_enableTableOfContents;;
QString m_wkTitle;
QString m_wkTargetFileName;
ExportPageNumber m_wkPageNumber;
QString m_wkExtraArgs;
};
struct ExportCustomOption
{
#if defined(Q_OS_WIN)
#define DEFAULT_SEP ";"
#else
#define DEFAULT_SEP ":"
#endif
enum SourceFormat
{
Markdown = 0,
HTML
};
ExportCustomOption()
: m_srcFormat(SourceFormat::Markdown),
m_allInOne(false),
m_pdfLike(false),
m_folderSep(DEFAULT_SEP)
{
}
ExportCustomOption(const QStringList &p_config)
: m_srcFormat(SourceFormat::Markdown),
m_allInOne(false),
m_pdfLike(false),
m_folderSep(DEFAULT_SEP)
{
if (p_config.size() < 3) {
return;
}
if (p_config.at(0).trimmed() != "0") {
m_srcFormat = SourceFormat::HTML;
}
m_outputSuffix = p_config.at(1).trimmed();
m_cmd = p_config.at(2).trimmed();
}
ExportCustomOption(ExportCustomOption::SourceFormat p_srcFormat,
const QString &p_outputSuffix,
const QString &p_cmd,
const QString &p_cssUrl,
const QString &p_codeBlockCssUrl,
bool p_allInOne,
bool p_pdfLike,
const QString &p_folderSep,
const QString &p_targetFileName)
: m_srcFormat(p_srcFormat),
m_outputSuffix(p_outputSuffix),
m_cssUrl(p_cssUrl),
m_codeBlockCssUrl(p_codeBlockCssUrl),
m_allInOne(p_allInOne),
m_pdfLike(p_pdfLike),
m_folderSep(p_folderSep),
m_targetFileName(p_targetFileName)
{
QStringList cmds = p_cmd.split('\n');
if (!cmds.isEmpty()) {
m_cmd = cmds.first();
}
}
QStringList toConfig() const
{
QStringList config;
config << QString::number((int)m_srcFormat);
config << m_outputSuffix;
config << m_cmd;
return config;
}
SourceFormat m_srcFormat;
QString m_outputSuffix;
QString m_cmd;
QString m_cssUrl;
QString m_codeBlockCssUrl;
bool m_allInOne;
bool m_pdfLike;
QString m_folderSep;
QString m_targetFileName;
};
struct ExportOption
{
ExportOption()
: m_source(ExportSource::CurrentNote),
m_format(ExportFormat::Markdown),
m_renderer(MarkdownConverterType::MarkdownIt),
m_processSubfolders(true)
{
}
ExportOption(ExportSource p_source,
ExportFormat p_format,
MarkdownConverterType p_renderer,
const QString &p_renderBg,
const QString &p_renderStyle,
const QString &p_renderCodeBlockStyle,
bool p_processSubfolders,
const ExportPDFOption &p_pdfOpt,
const ExportHTMLOption &p_htmlOpt,
const ExportCustomOption &p_customOpt)
: m_source(p_source),
m_format(p_format),
m_renderer(p_renderer),
m_renderBg(p_renderBg),
m_renderStyle(p_renderStyle),
m_renderCodeBlockStyle(p_renderCodeBlockStyle),
m_processSubfolders(p_processSubfolders),
m_pdfOpt(p_pdfOpt),
m_htmlOpt(p_htmlOpt),
m_customOpt(p_customOpt)
{
}
ExportSource m_source;
ExportFormat m_format;
MarkdownConverterType m_renderer;
// Background name.
QString m_renderBg;
QString m_renderStyle;
QString m_renderCodeBlockStyle;
// Whether process subfolders recursively when source is CurrentFolder.
bool m_processSubfolders;
ExportPDFOption m_pdfOpt;
ExportHTMLOption m_htmlOpt;
ExportCustomOption m_customOpt;
};
class VExportDialog : public QDialog
{
Q_OBJECT
public:
VExportDialog(VNotebook *p_notebook,
VDirectory *p_directory,
VFile *p_file,
VCart *p_cart,
MarkdownConverterType p_renderer,
QWidget *p_parent = nullptr);
private slots:
void startExport();
void handleOutputBrowseBtnClicked();
void handleWkPathBrowseBtnClicked();
void handleInputChanged();
void handleLayoutBtnClicked();
void handleCurrentFormatChanged(int p_index);
void handleCurrentSrcChanged(int p_index);
private:
void setupUI();
QWidget *setupPDFAdvancedSettings();
QWidget *setupHTMLAdvancedSettings();
QWidget *setupGeneralAdvancedSettings();
QWidget *setupCustomAdvancedSettings();
void initUIFields(MarkdownConverterType p_renderer);
QString getOutputDirectory() const;
void appendLogLine(const QString &p_text);
// Return number of files exported.
int doExport(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExport(VDirectory *p_directory,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExport(VNotebook *p_notebook,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExport(VCart *p_cart,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExportMarkdown(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
int doExportPDF(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
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 QString &p_outputFolder,
QString *p_errMsg = NULL);
int doExportCustomAllInOne(const QList<QString> &p_files,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL);
int doExportCustom(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
// Return false if we could not continue.
bool checkUserAction();
void updatePageLayoutLabel();
bool checkWkhtmltopdfExecutable(const QString &p_file);
ExportSource currentSource() const;
ExportFormat currentFormat() const;
int outputAsHTML(const QString &p_outputFolder,
QString *p_errMsg = NULL,
QList<QString> *p_outputFiles = NULL);
// Collect files to be handled.
QList<QString> collectFiles(QString *p_errMsg = NULL);
QComboBox *m_srcCB;
QComboBox *m_formatCB;
QComboBox *m_rendererCB;
QComboBox *m_renderBgCB;
QComboBox *m_renderStyleCB;
QComboBox *m_renderCodeBlockStyleCB;
VLineEdit *m_outputEdit;
QGroupBox *m_basicBox;
QGroupBox *m_settingBox;
QWidget *m_pdfSettings;
QWidget *m_htmlSettings;
QWidget *m_generalSettings;
QWidget *m_customSettings;
QPlainTextEdit *m_consoleEdit;
QDialogButtonBox *m_btnBox;
QPushButton *m_openBtn;
QPushButton *m_exportBtn;
QPushButton *m_copyBtn;
QLabel *m_layoutLabel;
QCheckBox *m_wkhtmltopdfCB;
VLineEdit *m_wkPathEdit;
QPushButton *m_wkPathBrowseBtn;
VLineEdit *m_wkTitleEdit;
VLineEdit *m_wkTargetFileNameEdit;
QCheckBox *m_wkBackgroundCB;
QCheckBox *m_tableOfContentsCB;
QComboBox *m_wkPageNumberCB;
VLineEdit *m_wkExtraArgsEdit;
QCheckBox *m_embedStyleCB;
QCheckBox *m_completeHTMLCB;
QCheckBox *m_embedImagesCB;
QCheckBox *m_mimeHTMLCB;
QCheckBox *m_outlinePanelCB;
QCheckBox *m_subfolderCB;
QComboBox *m_customSrcFormatCB;
VLineEdit *m_customSuffixEdit;
QCheckBox *m_customAllInOneCB;
QCheckBox *m_customPdfLikeCB;
QPlainTextEdit *m_customCmdEdit;
VLineEdit *m_customFolderSepEdit;
VLineEdit *m_customTargetFileNameEdit;
VNotebook *m_notebook;
VDirectory *m_directory;
VFile *m_file;
VCart *m_cart;
QProgressBar *m_proBar;
QPageLayout m_pageLayout;
// Whether we are exporting files.
bool m_inExport;
// Asked to stop exporting by user.
bool m_askedToStop;
// Exporter used to export PDF and HTML.
VExporter *m_exporter;
// Last exproted file path.
QString m_exportedFile;
// Last output folder path.
static QString s_lastOutputFolder;
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

View File

@ -161,7 +161,9 @@ SOURCES += main.cpp\
vwebview.cpp \
websocketclientwrapper.cpp \
websockettransport.cpp \
vmathjaxwebdocument.cpp
vmathjaxwebdocument.cpp \
vexporter.cpp \
dialog/vexportdialog.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@ -307,7 +309,9 @@ HEADERS += vmainwindow.h \
vwebview.h \
websocketclientwrapper.h \
websockettransport.h \
vmathjaxwebdocument.h
vmathjaxwebdocument.h \
vexporter.h \
dialog/vexportdialog.h
RESOURCES += \
vnote.qrc \

View File

@ -664,6 +664,7 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType,
const QString &p_renderBg,
const QString &p_renderStyle,
const QString &p_renderCodeBlockStyle,
quint16 p_port,
bool p_isPDF,
bool p_wkhtmltopdf,
bool p_addToc)
@ -675,7 +676,7 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType,
g_config->getCodeBlockCssStyleUrl(p_renderCodeBlockStyle),
p_isPDF);
return generateHtmlTemplate(templ, p_conType, 0, p_isPDF, p_wkhtmltopdf, p_addToc);
return generateHtmlTemplate(templ, p_conType, p_port, p_isPDF, p_wkhtmltopdf, p_addToc);
}
QString VUtils::generateHtmlTemplate(const QString &p_template,

View File

@ -194,6 +194,7 @@ public:
const QString &p_renderBg,
const QString &p_renderStyle,
const QString &p_renderCodeBlockStyle,
quint16 p_port,
bool p_isPDF,
bool p_wkhtmltopdf = false,
bool p_addToc = false);

View File

@ -18,6 +18,10 @@ enum class FileType { Note, Orphan };
enum class ClipboardOpType { CopyFile, CopyDir, Invalid };
enum WebSocketPort { PreviewHelperPort = 10900,
ExportWebViewPort,
LastSpecialPort };
namespace ClipboardConfig
{
static const QString c_type = "type";

1063
src/vexporter.cpp Normal file

File diff suppressed because it is too large Load Diff

213
src/vexporter.h Normal file
View File

@ -0,0 +1,213 @@
#ifndef VEXPORTER_H
#define VEXPORTER_H
#include <QObject>
#include <QPageLayout>
#include <QUrl>
// #include <QWebEngineDownloadItem>
#include <QStringList>
#include "dialog/vexportdialog.h"
class QWidget;
class VWebView;
class VDocument;
class VExporter : public QObject
{
Q_OBJECT
public:
explicit VExporter(QWidget *p_parent = nullptr);
void prepareExport(const ExportOption &p_opt);
bool exportPDF(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
bool exportHTML(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
bool exportCustom(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
int exportPDFInOne(const QList<QString> &p_htmlFiles,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
int exportCustomInOne(const QList<QString> &p_files,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
void setAskedToStop(bool p_askedToStop);
signals:
// Request to output log.
void outputLog(const QString &p_log);
private slots:
void handleLogicsFinished();
void handleLoadFinished(bool p_ok);
// void handleDownloadRequested(QWebEngineDownloadItem *p_item);
private:
enum class ExportState
{
Idle = 0,
Cancelled,
Busy,
Failed,
Successful
};
enum NoteState
{
NotReady = 0,
WebLogicsReady = 0x1,
WebLoadFinished = 0x2,
Ready = 0x3,
Failed = 0x4
};
void initWebViewer(VFile *p_file, const ExportOption &p_opt);
void clearWebViewer();
void clearNoteState();
bool isNoteStateReady() const;
bool isNoteStateFailed() const;
bool exportViaWebView(VFile *p_file,
const ExportOption &p_opt,
const QString &p_outputFile,
QString *p_errMsg = NULL);
bool exportToPDF(VWebView *p_webViewer,
const QString &p_filePath,
const QPageLayout &p_layout);
bool exportToPDFViaWK(VDocument *p_webDocument,
const ExportPDFOption &p_opt,
const QString &p_filePath,
QString *p_errMsg = NULL);
bool exportToCustom(VDocument *p_webDocument,
const ExportCustomOption &p_opt,
const QString &p_filePath,
QString *p_errMsg = NULL);
bool exportToHTML(VDocument *p_webDocument,
const ExportHTMLOption &p_opt,
const QString &p_filePath);
bool exportToMHTML(VWebView *p_webViewer,
const ExportHTMLOption &p_opt,
const QString &p_filePath);
bool htmlsToPDFViaWK(const QList<QString> &p_htmlFiles,
const QString &p_filePath,
const ExportPDFOption &p_opt,
QString *p_errMsg = NULL);
bool convertFilesViaCustom(const QList<QString> &p_files,
const QString &p_filePath,
const ExportCustomOption &p_opt,
QString *p_errMsg = NULL);
void prepareWKArguments(const ExportPDFOption &p_opt);
int startProcess(const QString &p_program, const QStringList &p_args);
int startProcess(const QString &p_cmd);
// @p_embedImages: embed <img> as data URI.
bool outputToHTMLFile(const QString &p_file,
const QString &p_title,
const QString &p_headContent,
const QString &p_styleContent,
const QString &p_bodyContent,
bool p_embedCssStyle,
bool p_completeHTML,
bool p_embedImages);
// Fix @p_html's resources like url("...") with "file" or "qrc" schema.
// Copy the resource to @p_folder and fix the url string.
static bool fixStyleResources(const QString &p_folder,
QString &p_html);
// Fix @p_html's resources like url("...") with "file" or "qrc" schema.
// Embed the image data in data URIs.
static bool embedStyleResources(QString &p_html);
// Fix @p_html's resources like <img>.
// Copy the resource to @p_folder and fix the url string.
static bool fixBodyResources(const QUrl &p_baseUrl,
const QString &p_folder,
QString &p_html);
// Embed @p_html's resources like <img>.
static bool embedBodyResources(const QUrl &p_baseUrl, QString &p_html);
static QString getResourceRelativePath(const QString &p_file);
QPageLayout m_pageLayout;
// Will be allocated and free for each conversion.
VWebView *m_webViewer;
VDocument *m_webDocument;
// Base URL of VWebView.
QUrl m_baseUrl;
QString m_htmlTemplate;
// Template to hold the export HTML result.
QString m_exportHtmlTemplate;
NoteState m_noteState;
ExportState m_state;
// Download state used for MIME HTML.
// QWebEngineDownloadItem::DownloadState m_downloadState;
// Arguments for wkhtmltopdf.
QStringList m_wkArgs;
bool m_askedToStop;
};
inline void VExporter::clearNoteState()
{
m_noteState = NoteState::NotReady;
}
inline bool VExporter::isNoteStateReady() const
{
return m_noteState == NoteState::Ready;
}
inline bool VExporter::isNoteStateFailed() const
{
return m_noteState & NoteState::Failed;
}
inline void VExporter::setAskedToStop(bool p_askedToStop)
{
m_askedToStop = p_askedToStop;
}
#endif // VEXPORTER_H

View File

@ -50,6 +50,8 @@
#include "vlistue.h"
#include "vtagexplorer.h"
#include "vmdeditor.h"
#include "vexporter.h"
#include "dialog/vexportdialog.h"
extern VConfigManager *g_config;
@ -1050,7 +1052,6 @@ void VMainWindow::initFileMenu()
fileMenu->addSeparator();
/*
m_exportAct = new QAction(tr("E&xport"), this);
m_exportAct->setToolTip(tr("Export notes"));
VUtils::fixTextWithCaptainShortcut(m_exportAct, "Export");
@ -1058,7 +1059,6 @@ void VMainWindow::initFileMenu()
this, &VMainWindow::handleExportAct);
fileMenu->addAction(m_exportAct);
*/
// Print.
m_printAct = new QAction(VIconUtils::menuIcon(":/resources/icons/print.svg"),
@ -3309,6 +3309,13 @@ void VMainWindow::updateEditReadAct(const VEditTab *p_tab)
void VMainWindow::handleExportAct()
{
VExportDialog dialog(m_notebookSelector->currentNotebook(),
m_dirTree->currentDirectory(),
m_curFile,
m_cart,
g_config->getMdConverterType(),
this);
dialog.exec();
}
VNotebook *VMainWindow::getCurrentNotebook() const

View File

@ -9,6 +9,7 @@
#include "vconfigmanager.h"
#include "websocketclientwrapper.h"
#include "websockettransport.h"
#include "vconstants.h"
extern VConfigManager *g_config;
@ -78,7 +79,7 @@ void VMathJaxPreviewHelper::doInit()
emit diagramPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, ba);
});
quint16 port = 20001;
quint16 port = WebSocketPort::PreviewHelperPort;
bindToChannel(port, "content", m_webDoc);
// setHtml() will change focus if it is not disabled.

View File

@ -29,7 +29,6 @@ extern VMainWindow *g_mainWin;
extern VConfigManager *g_config;
const quint16 VMdTab::c_basePort = 10999;
QSet<quint16> VMdTab::s_usedPorts;
VMdTab::VMdTab(VFile *p_file, VEditArea *p_editArea,
@ -1684,7 +1683,7 @@ bool VMdTab::previewExpanded() const
quint16 VMdTab::getNextPort()
{
auto port = c_basePort;
quint16 port = WebSocketPort::LastSpecialPort;
while (s_usedPorts.find(port) != s_usedPorts.end()) {
++port;
}

View File

@ -286,8 +286,6 @@ private:
int m_documentID;
static const quint16 c_basePort;
static QSet<quint16> s_usedPorts;
};