From e55b0af00e0593a2287b2bc40b18c9554d86693d Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 8 Sep 2017 21:41:19 +0800 Subject: [PATCH] bug-fix: QTextDocument.clearUndoRedoStacks() will crash in VImagePreviewer --- src/vimagepreviewer.cpp | 31 +++++++-------------------- src/vimagepreviewer.h | 10 ++++++--- src/vmdedit.cpp | 47 +++++++++++++++++++++++++++++++++++++++-- src/vmdedit.h | 8 +++++++ 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/src/vimagepreviewer.cpp b/src/vimagepreviewer.cpp index 069b9489..8da0648f 100644 --- a/src/vimagepreviewer.cpp +++ b/src/vimagepreviewer.cpp @@ -48,6 +48,7 @@ void VImagePreviewer::kickOffPreview(const QVector &p_imageRegio Q_ASSERT(m_imageRegions.isEmpty()); Q_ASSERT(m_previewImages.isEmpty()); Q_ASSERT(m_imageCache.isEmpty()); + emit previewFinished(); return; } @@ -60,6 +61,8 @@ void VImagePreviewer::kickOffPreview(const QVector &p_imageRegio shrinkImageCache(); m_isPreviewing = false; + + emit previewFinished(); } void VImagePreviewer::previewImages() @@ -541,6 +544,7 @@ bool VImagePreviewer::updateImageWidth(QTextImageFormat &p_format) void VImagePreviewer::updatePreviewImageWidth() { if (!m_previewEnabled) { + emit previewWidthUpdated(); return; } @@ -568,6 +572,10 @@ void VImagePreviewer::doUpdatePreviewImageWidth() if (updated) { emit m_edit->statusChanged(); } + + qDebug() << "update preview image width" << updated; + + emit previewWidthUpdated(); } bool VImagePreviewer::updatePreviewImageWidthOfBlock(const QTextBlock &p_block, @@ -631,32 +639,9 @@ void VImagePreviewer::shrinkImageCache() void VImagePreviewer::saveEditStatus(EditStatus &p_status) const { p_status.m_modified = m_edit->isModified(); - p_status.m_undoAvailable = m_document->isUndoAvailable(); - p_status.m_redoAvailable = m_document->isRedoAvailable(); } void VImagePreviewer::restoreEditStatus(const EditStatus &p_status) { - int st = 0; - if (!p_status.m_undoAvailable) { - st |= 1; - } - - if (!p_status.m_redoAvailable) { - st |= 2; - } - - if (st > 0) { - QTextDocument::Stacks stack = QTextDocument::UndoStack; - if (st == 2) { - stack = QTextDocument::RedoStack; - } else if (st == 3) { - stack = QTextDocument::UndoAndRedoStacks; - } - - m_document->clearUndoRedoStacks(stack); - } - - // Clear undo and redo stacks will change the state to modified. m_edit->setModified(p_status.m_modified); } diff --git a/src/vimagepreviewer.h b/src/vimagepreviewer.h index 558e61e5..b17c6b75 100644 --- a/src/vimagepreviewer.h +++ b/src/vimagepreviewer.h @@ -48,6 +48,12 @@ signals: // Request highlighter to update image links. void requestUpdateImageLinks(); + // Emit after finishing previewing. + void previewFinished(); + + // Emit after updating preview width. + void previewWidthUpdated(); + private: struct ImageInfo { @@ -116,13 +122,11 @@ private: struct EditStatus { EditStatus() - : m_modified(false), m_undoAvailable(false), m_redoAvailable(false) + : m_modified(false) { } bool m_modified; - bool m_undoAvailable; - bool m_redoAvailable; }; // Kick off new preview of m_imageRegions. diff --git a/src/vmdedit.cpp b/src/vmdedit.cpp index bafb126b..04ada89b 100644 --- a/src/vmdedit.cpp +++ b/src/vmdedit.cpp @@ -16,13 +16,17 @@ extern VConfigManager *g_config; extern VNote *g_vnote; +const int VMdEdit::c_numberOfAysncJobs = 2; + VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type, QWidget *p_parent) - : VEdit(p_file, p_parent), m_mdHighlighter(NULL) + : VEdit(p_file, p_parent), m_mdHighlighter(NULL), m_freshEdit(true), + m_finishedAsyncJobs(c_numberOfAysncJobs) { V_ASSERT(p_file->getDocType() == DocType::Markdown); setAcceptRichText(false); + m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(), g_config->getCodeBlockStyles(), g_config->getMarkdownHighlightInterval(), @@ -45,6 +49,19 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type, m_imagePreviewer, &VImagePreviewer::imageLinksChanged); connect(m_imagePreviewer, &VImagePreviewer::requestUpdateImageLinks, m_mdHighlighter, &HGMarkdownHighlighter::updateHighlight); + connect(m_imagePreviewer, &VImagePreviewer::previewFinished, + this, [this](){ + if (m_freshEdit) { + finishOneAsyncJob(0); + } + }); + + connect(m_imagePreviewer, &VImagePreviewer::previewWidthUpdated, + this, [this](){ + if (m_freshEdit) { + finishOneAsyncJob(1); + } + }); m_editOps = new VMdEditOperations(this, m_file); @@ -80,11 +97,19 @@ void VMdEdit::beginEdit() initInitImages(); - setReadOnly(false); setModified(false); // Request update outline. generateEditOutline(); + + if (m_freshEdit) { + // Will set to false when all async jobs completed. + setReadOnly(true); + // Disable and clear undo stacks temporary. + setUndoRedoEnabled(false); + } else { + setReadOnly(false); + } } void VMdEdit::endEdit() @@ -634,3 +659,21 @@ bool VMdEdit::jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat) return false; } + +void VMdEdit::finishOneAsyncJob(int p_idx) +{ + Q_ASSERT(m_freshEdit); + if (m_finishedAsyncJobs[p_idx]) { + return; + } + + m_finishedAsyncJobs[p_idx] = true; + if (-1 == m_finishedAsyncJobs.indexOf(false)) { + // All jobs finished. + m_freshEdit = false; + setUndoRedoEnabled(true); + setReadOnly(false); + setModified(false); + emit statusChanged(); + } +} diff --git a/src/vmdedit.h b/src/vmdedit.h index 7fc4920b..0ce63816 100644 --- a/src/vmdedit.h +++ b/src/vmdedit.h @@ -100,6 +100,8 @@ private: bool getPreviewImageRegionOfBlock(const QTextBlock &p_block, QVector &p_regions) const; + void finishOneAsyncJob(int p_idx); + HGMarkdownHighlighter *m_mdHighlighter; VCodeBlockHighlightHelper *m_cbHighlighter; VImagePreviewer *m_imagePreviewer; @@ -111,6 +113,12 @@ private: QVector m_initImages; QVector m_headers; + + bool m_freshEdit; + + QVector m_finishedAsyncJobs; + + static const int c_numberOfAysncJobs; }; #endif // VMDEDIT_H