mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
export: support MHTML format
This commit is contained in:
parent
28765bf4bb
commit
bccc0b28db
@ -215,9 +215,20 @@ QWidget *VExportDialog::setupHTMLAdvancedSettings()
|
|||||||
"the original page"));
|
"the original page"));
|
||||||
m_completeHTMLCB->setChecked(true);
|
m_completeHTMLCB->setChecked(true);
|
||||||
|
|
||||||
|
// Mime HTML.
|
||||||
|
m_mimeHTMLCB = new QCheckBox(tr("MIME HTML"), this);
|
||||||
|
m_mimeHTMLCB->setToolTip(tr("Export as a complete web page in MIME HTML format"));
|
||||||
|
connect(m_mimeHTMLCB, &QCheckBox::stateChanged,
|
||||||
|
this, [this](int p_state) {
|
||||||
|
bool checked = p_state == Qt::Checked;
|
||||||
|
m_embedStyleCB->setEnabled(!checked);
|
||||||
|
m_completeHTMLCB->setEnabled(!checked);
|
||||||
|
});
|
||||||
|
|
||||||
QFormLayout *advLayout = new QFormLayout();
|
QFormLayout *advLayout = new QFormLayout();
|
||||||
advLayout->addRow(m_embedStyleCB);
|
advLayout->addRow(m_embedStyleCB);
|
||||||
advLayout->addRow(m_completeHTMLCB);
|
advLayout->addRow(m_completeHTMLCB);
|
||||||
|
advLayout->addRow(m_mimeHTMLCB);
|
||||||
|
|
||||||
advLayout->setContentsMargins(0, 0, 0, 0);
|
advLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
@ -311,8 +322,9 @@ void VExportDialog::startExport()
|
|||||||
m_renderStyleCB->currentData().toString(),
|
m_renderStyleCB->currentData().toString(),
|
||||||
m_renderCodeBlockStyleCB->currentData().toString(),
|
m_renderCodeBlockStyleCB->currentData().toString(),
|
||||||
&m_pageLayout,
|
&m_pageLayout,
|
||||||
m_embedStyleCB->isChecked(),
|
ExportHTMLOption(m_embedStyleCB->isChecked(),
|
||||||
m_completeHTMLCB->isChecked());
|
m_completeHTMLCB->isChecked(),
|
||||||
|
m_mimeHTMLCB->isChecked()));
|
||||||
|
|
||||||
s_lastExportFormat = opt.m_format;
|
s_lastExportFormat = opt.m_format;
|
||||||
|
|
||||||
@ -683,7 +695,7 @@ int VExportDialog::doExportHTML(VFile *p_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get output file.
|
// Get output file.
|
||||||
QString suffix = ".html";
|
QString suffix = p_opt.m_htmlOpt.m_mimeHTML ? ".mht" : ".html";
|
||||||
QString name = VUtils::getFileNameWithSequence(p_outputFolder,
|
QString name = VUtils::getFileNameWithSequence(p_outputFolder,
|
||||||
QFileInfo(p_file->getName()).completeBaseName() + suffix);
|
QFileInfo(p_file->getName()).completeBaseName() + suffix);
|
||||||
QString outputPath = QDir(p_outputFolder).filePath(name);
|
QString outputPath = QDir(p_outputFolder).filePath(name);
|
||||||
|
@ -38,6 +38,23 @@ enum class ExportFormat
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ExportHTMLOption
|
||||||
|
{
|
||||||
|
ExportHTMLOption(bool p_embedCssStyle,
|
||||||
|
bool p_completeHTML,
|
||||||
|
bool p_mimeHTML)
|
||||||
|
: m_embedCssStyle(p_embedCssStyle),
|
||||||
|
m_completeHTML(p_completeHTML),
|
||||||
|
m_mimeHTML(p_mimeHTML)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_embedCssStyle;
|
||||||
|
bool m_completeHTML;
|
||||||
|
bool m_mimeHTML;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ExportOption
|
struct ExportOption
|
||||||
{
|
{
|
||||||
ExportOption(ExportSource p_source,
|
ExportOption(ExportSource p_source,
|
||||||
@ -47,8 +64,7 @@ struct ExportOption
|
|||||||
const QString &p_renderStyle,
|
const QString &p_renderStyle,
|
||||||
const QString &p_renderCodeBlockStyle,
|
const QString &p_renderCodeBlockStyle,
|
||||||
QPageLayout *p_layout,
|
QPageLayout *p_layout,
|
||||||
bool p_embedCssStyle,
|
const ExportHTMLOption &p_htmlOpt)
|
||||||
bool p_completeHTML)
|
|
||||||
: m_source(p_source),
|
: m_source(p_source),
|
||||||
m_format(p_format),
|
m_format(p_format),
|
||||||
m_renderer(p_renderer),
|
m_renderer(p_renderer),
|
||||||
@ -56,8 +72,7 @@ struct ExportOption
|
|||||||
m_renderStyle(p_renderStyle),
|
m_renderStyle(p_renderStyle),
|
||||||
m_renderCodeBlockStyle(p_renderCodeBlockStyle),
|
m_renderCodeBlockStyle(p_renderCodeBlockStyle),
|
||||||
m_layout(p_layout),
|
m_layout(p_layout),
|
||||||
m_embedCssStyle(p_embedCssStyle),
|
m_htmlOpt(p_htmlOpt)
|
||||||
m_completeHTML(p_completeHTML)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +87,7 @@ struct ExportOption
|
|||||||
QString m_renderCodeBlockStyle;
|
QString m_renderCodeBlockStyle;
|
||||||
QPageLayout *m_layout;
|
QPageLayout *m_layout;
|
||||||
|
|
||||||
bool m_embedCssStyle;
|
ExportHTMLOption m_htmlOpt;
|
||||||
bool m_completeHTML;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -191,6 +205,8 @@ private:
|
|||||||
|
|
||||||
QCheckBox *m_completeHTMLCB;;
|
QCheckBox *m_completeHTMLCB;;
|
||||||
|
|
||||||
|
QCheckBox *m_mimeHTMLCB;
|
||||||
|
|
||||||
VNotebook *m_notebook;
|
VNotebook *m_notebook;
|
||||||
|
|
||||||
VDirectory *m_directory;
|
VDirectory *m_directory;
|
||||||
|
@ -7,7 +7,7 @@ mdhl_file=v_moonlight.mdhl
|
|||||||
css_file=v_moonlight.css
|
css_file=v_moonlight.css
|
||||||
codeblock_css_file=v_moonlight_codeblock.css
|
codeblock_css_file=v_moonlight_codeblock.css
|
||||||
mermaid_css_file=v_moonlight_mermaid.css
|
mermaid_css_file=v_moonlight_mermaid.css
|
||||||
version=4
|
version=5
|
||||||
|
|
||||||
; This mapping will be used to translate colors when the content of HTML is copied
|
; This mapping will be used to translate colors when the content of HTML is copied
|
||||||
; without background. You could just specify the foreground colors mapping here.
|
; without background. You could just specify the foreground colors mapping here.
|
||||||
@ -329,6 +329,7 @@ editwindow_corner_icon_fg=@master_bg
|
|||||||
editwindow_corner_icon_inactive_fg=@icon_fg
|
editwindow_corner_icon_inactive_fg=@icon_fg
|
||||||
|
|
||||||
; CheckBox.
|
; CheckBox.
|
||||||
|
checkbox_disabled_fg=@disabled_fg
|
||||||
checkbox_indicator_hover_bg=@hover_bg
|
checkbox_indicator_hover_bg=@hover_bg
|
||||||
checkbox_indicator_pressed_bg=@pressed_bg
|
checkbox_indicator_pressed_bg=@pressed_bg
|
||||||
|
|
||||||
|
@ -1114,6 +1114,10 @@ QCheckBox {
|
|||||||
spacing: 5px;
|
spacing: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCheckBox:disabled {
|
||||||
|
color: @checkbox_disabled_fg;
|
||||||
|
}
|
||||||
|
|
||||||
QCheckBox::indicator {
|
QCheckBox::indicator {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
@ -7,7 +7,7 @@ mdhl_file=v_pure.mdhl
|
|||||||
css_file=v_pure.css
|
css_file=v_pure.css
|
||||||
codeblock_css_file=v_pure_codeblock.css
|
codeblock_css_file=v_pure_codeblock.css
|
||||||
mermaid_css_file=v_pure_mermaid.css
|
mermaid_css_file=v_pure_mermaid.css
|
||||||
version=4
|
version=5
|
||||||
|
|
||||||
[phony]
|
[phony]
|
||||||
; Abstract color attributes.
|
; Abstract color attributes.
|
||||||
@ -322,6 +322,7 @@ editwindow_corner_icon_fg=@master_bg
|
|||||||
editwindow_corner_icon_inactive_fg=#D3D3D3
|
editwindow_corner_icon_inactive_fg=#D3D3D3
|
||||||
|
|
||||||
; CheckBox.
|
; CheckBox.
|
||||||
|
checkbox_disabled_fg=@disabled_fg
|
||||||
checkbox_indicator_hover_bg=@hover_bg
|
checkbox_indicator_hover_bg=@hover_bg
|
||||||
checkbox_indicator_pressed_bg=@pressed_bg
|
checkbox_indicator_pressed_bg=@pressed_bg
|
||||||
|
|
||||||
|
@ -1117,6 +1117,10 @@ QCheckBox {
|
|||||||
spacing: 5px;
|
spacing: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCheckBox:disabled {
|
||||||
|
color: @checkbox_disabled_fg;
|
||||||
|
}
|
||||||
|
|
||||||
QCheckBox::indicator {
|
QCheckBox::indicator {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
@ -7,7 +7,7 @@ mdhl_file=v_white.mdhl
|
|||||||
css_file=v_white.css
|
css_file=v_white.css
|
||||||
codeblock_css_file=v_white_codeblock.css
|
codeblock_css_file=v_white_codeblock.css
|
||||||
mermaid_css_file=v_white_mermaid.css
|
mermaid_css_file=v_white_mermaid.css
|
||||||
version=4
|
version=5
|
||||||
|
|
||||||
[phony]
|
[phony]
|
||||||
; Abstract color attributes.
|
; Abstract color attributes.
|
||||||
@ -287,6 +287,7 @@ editwindow_corner_icon_fg=@icon_fg
|
|||||||
editwindow_corner_icon_inactive_fg=#808080
|
editwindow_corner_icon_inactive_fg=#808080
|
||||||
|
|
||||||
; CheckBox.
|
; CheckBox.
|
||||||
|
checkbox_disabled_fg=@disabled_fg
|
||||||
checkbox_indicator_hover_bg=@hover_bg
|
checkbox_indicator_hover_bg=@hover_bg
|
||||||
checkbox_indicator_pressed_bg=@pressed_bg
|
checkbox_indicator_pressed_bg=@pressed_bg
|
||||||
|
|
||||||
|
@ -1003,6 +1003,10 @@ QCheckBox {
|
|||||||
spacing: 5px;
|
spacing: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCheckBox:disabled {
|
||||||
|
color: @checkbox_disabled_fg;
|
||||||
|
}
|
||||||
|
|
||||||
QCheckBox::indicator {
|
QCheckBox::indicator {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QWebChannel>
|
#include <QWebChannel>
|
||||||
|
#include <QWebEngineProfile>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
@ -64,9 +65,10 @@ void VExporter::initWebViewer(VFile *p_file, const ExportOption &p_opt)
|
|||||||
|
|
||||||
VPreviewPage *page = new VPreviewPage(m_webViewer);
|
VPreviewPage *page = new VPreviewPage(m_webViewer);
|
||||||
m_webViewer->setPage(page);
|
m_webViewer->setPage(page);
|
||||||
|
|
||||||
connect(page, &VPreviewPage::loadFinished,
|
connect(page, &VPreviewPage::loadFinished,
|
||||||
this, &VExporter::handleLoadFinished);
|
this, &VExporter::handleLoadFinished);
|
||||||
|
connect(page->profile(), &QWebEngineProfile::downloadRequested,
|
||||||
|
this, &VExporter::handleDownloadRequested);
|
||||||
|
|
||||||
m_webDocument = new VDocument(p_file, m_webViewer);
|
m_webDocument = new VDocument(p_file, m_webViewer);
|
||||||
connect(m_webDocument, &VDocument::logicsFinished,
|
connect(m_webDocument, &VDocument::logicsFinished,
|
||||||
@ -199,11 +201,16 @@ bool VExporter::exportViaWebView(VFile *p_file,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ExportFormat::HTML:
|
case ExportFormat::HTML:
|
||||||
exportRet = exportToHTML(m_webViewer,
|
if (p_opt.m_htmlOpt.m_mimeHTML) {
|
||||||
m_webDocument,
|
exportRet = exportToMHTML(m_webViewer,
|
||||||
p_opt.m_embedCssStyle,
|
p_opt.m_htmlOpt,
|
||||||
p_opt.m_completeHTML,
|
p_outputFile);
|
||||||
p_outputFile);
|
} else {
|
||||||
|
exportRet = exportToHTML(m_webDocument,
|
||||||
|
p_opt.m_htmlOpt,
|
||||||
|
p_outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -236,13 +243,10 @@ exit:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VExporter::exportToHTML(VWebView *p_webViewer,
|
bool VExporter::exportToHTML(VDocument *p_webDocument,
|
||||||
VDocument *p_webDocument,
|
const ExportHTMLOption &p_opt,
|
||||||
bool p_embedCssStyle,
|
|
||||||
bool p_completeHTML,
|
|
||||||
const QString &p_filePath)
|
const QString &p_filePath)
|
||||||
{
|
{
|
||||||
Q_UNUSED(p_webViewer);
|
|
||||||
int htmlExported = 0;
|
int htmlExported = 0;
|
||||||
|
|
||||||
connect(p_webDocument, &VDocument::htmlContentFinished,
|
connect(p_webDocument, &VDocument::htmlContentFinished,
|
||||||
@ -269,7 +273,7 @@ bool VExporter::exportToHTML(VWebView *p_webViewer,
|
|||||||
qDebug() << "HTML files folder" << resFolderPath;
|
qDebug() << "HTML files folder" << resFolderPath;
|
||||||
|
|
||||||
QString html(m_exportHtmlTemplate);
|
QString html(m_exportHtmlTemplate);
|
||||||
if (!p_styleContent.isEmpty() && p_embedCssStyle) {
|
if (!p_styleContent.isEmpty() && p_opt.m_embedCssStyle) {
|
||||||
QString content(p_styleContent);
|
QString content(p_styleContent);
|
||||||
fixStyleResources(resFolderPath, content);
|
fixStyleResources(resFolderPath, content);
|
||||||
html.replace(HtmlHolder::c_styleHolder, content);
|
html.replace(HtmlHolder::c_styleHolder, content);
|
||||||
@ -279,7 +283,7 @@ bool VExporter::exportToHTML(VWebView *p_webViewer,
|
|||||||
html.replace(HtmlHolder::c_headHolder, p_headContent);
|
html.replace(HtmlHolder::c_headHolder, p_headContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_completeHTML) {
|
if (p_opt.m_completeHTML) {
|
||||||
QString content(p_bodyContent);
|
QString content(p_bodyContent);
|
||||||
fixBodyResources(m_baseUrl, resFolderPath, content);
|
fixBodyResources(m_baseUrl, resFolderPath, content);
|
||||||
html.replace(HtmlHolder::c_bodyHolder, content);
|
html.replace(HtmlHolder::c_bodyHolder, content);
|
||||||
@ -389,3 +393,29 @@ QString VExporter::getResourceRelativePath(const QString &p_file)
|
|||||||
Q_ASSERT(idx > 0 && idx2 < idx);
|
Q_ASSERT(idx > 0 && idx2 < idx);
|
||||||
return "." + p_file.mid(idx2);
|
return "." + p_file.mid(idx2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VExporter::exportToMHTML(VWebView *p_webViewer,
|
||||||
|
const ExportHTMLOption &p_opt,
|
||||||
|
const QString &p_filePath)
|
||||||
|
{
|
||||||
|
m_downloadState = QWebEngineDownloadItem::DownloadRequested;
|
||||||
|
|
||||||
|
p_webViewer->page()->save(p_filePath, QWebEngineDownloadItem::MimeHtmlSaveFormat);
|
||||||
|
|
||||||
|
while (m_downloadState == QWebEngineDownloadItem::DownloadRequested
|
||||||
|
|| m_downloadState == QWebEngineDownloadItem::DownloadInProgress) {
|
||||||
|
VUtils::sleepWait(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_downloadState == QWebEngineDownloadItem::DownloadCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VExporter::handleDownloadRequested(QWebEngineDownloadItem *p_item)
|
||||||
|
{
|
||||||
|
if (p_item->savePageFormat() == QWebEngineDownloadItem::MimeHtmlSaveFormat) {
|
||||||
|
connect(p_item, &QWebEngineDownloadItem::stateChanged,
|
||||||
|
this, [this](QWebEngineDownloadItem::DownloadState p_state) {
|
||||||
|
m_downloadState = p_state;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPageLayout>
|
#include <QPageLayout>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QWebEngineDownloadItem>
|
||||||
|
|
||||||
#include "dialog/vexportdialog.h"
|
#include "dialog/vexportdialog.h"
|
||||||
|
|
||||||
@ -33,6 +34,8 @@ private slots:
|
|||||||
|
|
||||||
void handleLoadFinished(bool p_ok);
|
void handleLoadFinished(bool p_ok);
|
||||||
|
|
||||||
|
void handleDownloadRequested(QWebEngineDownloadItem *p_item);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ExportState
|
enum class ExportState
|
||||||
{
|
{
|
||||||
@ -73,12 +76,15 @@ private:
|
|||||||
const QString &p_filePath,
|
const QString &p_filePath,
|
||||||
const QPageLayout &p_layout);
|
const QPageLayout &p_layout);
|
||||||
|
|
||||||
bool exportToHTML(VWebView *p_webViewer,
|
bool exportToHTML(VDocument *p_webDocument,
|
||||||
VDocument *p_webDocument,
|
const ExportHTMLOption &p_opt,
|
||||||
bool p_embedCssStyle,
|
|
||||||
bool p_completeHTML,
|
|
||||||
const QString &p_filePath);
|
const QString &p_filePath);
|
||||||
|
|
||||||
|
bool exportToMHTML(VWebView *p_webViewer,
|
||||||
|
const ExportHTMLOption &p_opt,
|
||||||
|
const QString &p_filePath);
|
||||||
|
|
||||||
|
|
||||||
// Fix @p_html's resources like url("...") with "file" or "qrc" schema.
|
// Fix @p_html's resources like url("...") with "file" or "qrc" schema.
|
||||||
// Copy the resource to @p_folder and fix the url string.
|
// Copy the resource to @p_folder and fix the url string.
|
||||||
static bool fixStyleResources(const QString &p_folder,
|
static bool fixStyleResources(const QString &p_folder,
|
||||||
@ -110,6 +116,9 @@ private:
|
|||||||
NoteState m_noteState;
|
NoteState m_noteState;
|
||||||
|
|
||||||
ExportState m_state;
|
ExportState m_state;
|
||||||
|
|
||||||
|
// Download state used for MIME HTML.
|
||||||
|
QWebEngineDownloadItem::DownloadState m_downloadState;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void VExporter::clearNoteState()
|
inline void VExporter::clearNoteState()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user