bugfix: wait for images loaded before exporting PDF

This commit is contained in:
Le Tan 2017-05-23 19:22:49 +08:00
parent 1370272424
commit 5b4984f59a
9 changed files with 93 additions and 49 deletions

View File

@ -54,13 +54,13 @@ var updateHtml = function(html) {
// MathJax may be not loaded for now. // MathJax may be not loaded for now.
if (VEnableMathjax && (typeof MathJax != "undefined")) { if (VEnableMathjax && (typeof MathJax != "undefined")) {
try { try {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLoading]); MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLogics]);
} catch (err) { } catch (err) {
content.setLog("err: " + err); content.setLog("err: " + err);
finishLoading(); finishLogics();
} }
} else { } else {
finishLoading(); finishLogics();
} }
}; };

View File

@ -174,13 +174,13 @@ var updateText = function(text) {
// finishLoading logic. // finishLoading logic.
if (VEnableMathjax) { if (VEnableMathjax) {
try { try {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLoading]); MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLogics]);
} catch (err) { } catch (err) {
content.setLog("err: " + err); content.setLog("err: " + err);
finishLoading(); finishLogics();
} }
} else { } else {
finishLoading(); finishLogics();
} }
}; };

View File

@ -309,7 +309,7 @@ var insertImageCaption = function() {
} }
// The renderer specific code should call this function once thay have finished // The renderer specific code should call this function once thay have finished
// loading the page. // markdown-specifi handle logics, such as Mermaid, MathJax.
var finishLoading = function() { var finishLogics = function() {
content.finishLoading(); content.finishLogics();
}; };

View File

@ -132,13 +132,13 @@ var updateText = function(text) {
// finishLoading logic. // finishLoading logic.
if (VEnableMathjax) { if (VEnableMathjax) {
try { try {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLoading]); MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLogics]);
} catch (err) { } catch (err) {
content.setLog("err: " + err); content.setLog("err: " + err);
finishLoading(); finishLogics();
} }
} else { } else {
finishLoading(); finishLogics();
} }
}; };

View File

@ -156,13 +156,13 @@ var updateText = function(text) {
// finishLoading logic. // finishLoading logic.
if (VEnableMathjax) { if (VEnableMathjax) {
try { try {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLoading]); MathJax.Hub.Queue(["Typeset", MathJax.Hub, placeholder, finishLogics]);
} catch (err) { } catch (err) {
content.setLog("err: " + err); content.setLog("err: " + err);
finishLoading(); finishLogics();
} }
} else { } else {
finishLoading(); finishLogics();
} }
}; };

View File

@ -82,8 +82,8 @@ void VDocument::setFile(const VFile *p_file)
m_file = p_file; m_file = p_file;
} }
void VDocument::finishLoading() void VDocument::finishLogics()
{ {
qDebug() << "Web side finished loading"; qDebug() << "Web side finished logics";
emit loadFinished(); emit logicsFinished();
} }

View File

@ -35,8 +35,9 @@ public slots:
void highlightTextCB(const QString &p_html, int p_id, int p_timeStamp); void highlightTextCB(const QString &p_html, int p_id, int p_timeStamp);
void noticeReadyToHighlightText(); void noticeReadyToHighlightText();
// Page is finished loading. // Web-side handle logics (MathJax etc.) is finished.
void finishLoading(); // But the page may not finish loading, such as images.
void finishLogics();
signals: signals:
void textChanged(const QString &text); void textChanged(const QString &text);
@ -49,7 +50,7 @@ signals:
void requestHighlightText(const QString &p_text, int p_id, int p_timeStamp); void requestHighlightText(const QString &p_text, int p_id, int p_timeStamp);
void textHighlighted(const QString &p_html, int p_id, int p_timeStamp); void textHighlighted(const QString &p_html, int p_id, int p_timeStamp);
void readyToHighlightText(); void readyToHighlightText();
void loadFinished(); void logicsFinished();
private: private:
QString m_toc; QString m_toc;

View File

@ -29,7 +29,7 @@ QString VExporter::s_defaultPathDir = QDir::homePath();
VExporter::VExporter(MarkdownConverterType p_mdType, QWidget *p_parent) VExporter::VExporter(MarkdownConverterType p_mdType, QWidget *p_parent)
: QDialog(p_parent), m_document(NULL, this), m_mdType(p_mdType), : QDialog(p_parent), m_document(NULL, this), m_mdType(p_mdType),
m_file(NULL), m_type(ExportType::PDF), m_source(ExportSource::Invalid), m_file(NULL), m_type(ExportType::PDF), m_source(ExportSource::Invalid),
m_webReady(false), m_state(ExportState::Idle), m_noteState(NoteState::NotReady), m_state(ExportState::Idle),
m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0))) m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0)))
{ {
setupUI(); setupUI();
@ -190,12 +190,15 @@ void VExporter::setupMarkdownViewer()
VPreviewPage *page = new VPreviewPage(this); VPreviewPage *page = new VPreviewPage(this);
m_webViewer->setPage(page); m_webViewer->setPage(page);
connect(page, &VPreviewPage::loadFinished,
this, &VExporter::handleLoadFinished);
QWebChannel *channel = new QWebChannel(this); QWebChannel *channel = new QWebChannel(this);
channel->registerObject(QStringLiteral("content"), &m_document); channel->registerObject(QStringLiteral("content"), &m_document);
page->setWebChannel(channel); page->setWebChannel(channel);
connect(&m_document, &VDocument::loadFinished, connect(&m_document, &VDocument::logicsFinished,
this, &VExporter::readyToExport); this, &VExporter::handleLogicsFinished);
QString jsFile, extraFile; QString jsFile, extraFile;
switch (m_mdType) { switch (m_mdType) {
@ -273,10 +276,37 @@ void VExporter::updateWebViewer(VFile *p_file)
m_webViewer->setHtml(m_htmlTemplate, p_file->getBaseUrl()); m_webViewer->setHtml(m_htmlTemplate, p_file->getBaseUrl());
} }
void VExporter::readyToExport() void VExporter::handleLogicsFinished()
{ {
Q_ASSERT(!m_webReady); Q_ASSERT(!(m_noteState & NoteState::WebLogicsReady));
m_webReady = true; m_noteState = NoteState(m_noteState | NoteState::WebLogicsReady);
}
void VExporter::handleLoadFinished(bool p_ok)
{
qDebug() << "Web load finished" << p_ok;
Q_ASSERT(!(m_noteState & NoteState::WebLoadFinished));
m_noteState = NoteState(m_noteState | NoteState::WebLoadFinished);
if (!p_ok) {
m_noteState = NoteState(m_noteState | NoteState::Failed);
}
}
void VExporter::clearNoteState()
{
m_noteState = NoteState::NotReady;
}
bool VExporter::isNoteStateReady() const
{
return m_noteState == NoteState::Ready;
}
bool VExporter::isNoteStateFailed() const
{
return m_noteState & NoteState::Failed;
} }
void VExporter::startExport() void VExporter::startExport()
@ -292,7 +322,7 @@ void VExporter::startExport()
goto exit; goto exit;
} }
m_webReady = false; clearNoteState();
updateWebViewer(m_file); updateWebViewer(m_file);
// Update progress info. // Update progress info.
@ -303,13 +333,13 @@ void VExporter::startExport()
m_proLabel->show(); m_proLabel->show();
m_proBar->show(); m_proBar->show();
while (!m_webReady) { while (!isNoteStateReady()) {
VUtils::sleepWait(100); VUtils::sleepWait(100);
if (m_proBar->value() < 70) { if (m_proBar->value() < 70) {
m_proBar->setValue(m_proBar->value() + 1); m_proBar->setValue(m_proBar->value() + 1);
} }
if (m_state == ExportState::Cancelled) { if (m_state == ExportState::Cancelled || isNoteStateFailed()) {
goto exit; goto exit;
} }
} }
@ -327,7 +357,7 @@ void VExporter::startExport()
m_proBar->setValue(100); m_proBar->setValue(100);
m_webReady = false; clearNoteState();
if (!isOpened) { if (!isOpened) {
m_file->close(); m_file->close();

View File

@ -21,21 +21,6 @@ enum class ExportType
HTML HTML
}; };
enum class ExportSource
{
Note = 0,
Directory,
Notebook,
Invalid
};
enum class ExportState
{
Idle = 0,
Cancelled,
Busy
};
class VExporter : public QDialog class VExporter : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -49,8 +34,34 @@ private slots:
void handleLayoutBtnClicked(); void handleLayoutBtnClicked();
void startExport(); void startExport();
void cancelExport(); void cancelExport();
void handleLogicsFinished();
void handleLoadFinished(bool p_ok);
private: private:
enum class ExportSource
{
Note = 0,
Directory,
Notebook,
Invalid
};
enum class ExportState
{
Idle = 0,
Cancelled,
Busy
};
enum NoteState
{
NotReady = 0,
WebLogicsReady = 0x1,
WebLoadFinished = 0x2,
Ready = 0x3,
Failed = 0x4
};
void setupUI(); void setupUI();
// Init m_webViewer, m_document, and m_htmlTemplate. // Init m_webViewer, m_document, and m_htmlTemplate.
@ -64,12 +75,14 @@ private:
void updateWebViewer(VFile *p_file); void updateWebViewer(VFile *p_file);
void readyToExport();
void enableUserInput(bool p_enabled); void enableUserInput(bool p_enabled);
void exportToPDF(VWebView *p_webViewer, const QString &p_filePath, const QPageLayout &p_layout); void exportToPDF(VWebView *p_webViewer, const QString &p_filePath, const QPageLayout &p_layout);
void clearNoteState();
bool isNoteStateReady() const;
bool isNoteStateFailed() const;
VWebView *m_webViewer; VWebView *m_webViewer;
VDocument m_document; VDocument m_document;
MarkdownConverterType m_mdType; MarkdownConverterType m_mdType;
@ -77,7 +90,7 @@ private:
VFile *m_file; VFile *m_file;
ExportType m_type; ExportType m_type;
ExportSource m_source; ExportSource m_source;
bool m_webReady; NoteState m_noteState;
ExportState m_state; ExportState m_state;