Browse Source

bug-fix: QTextDocument.clearUndoRedoStacks() will crash in VImagePreviewer

Le Tan 8 years ago
parent
commit
e55b0af00e
4 changed files with 68 additions and 28 deletions
  1. 8 23
      src/vimagepreviewer.cpp
  2. 7 3
      src/vimagepreviewer.h
  3. 45 2
      src/vmdedit.cpp
  4. 8 0
      src/vmdedit.h

+ 8 - 23
src/vimagepreviewer.cpp

@@ -48,6 +48,7 @@ void VImagePreviewer::kickOffPreview(const QVector<VElementRegion> &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<VElementRegion> &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);
 }

+ 7 - 3
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.

+ 45 - 2
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();
+    }
+}

+ 8 - 0
src/vmdedit.h

@@ -100,6 +100,8 @@ private:
     bool getPreviewImageRegionOfBlock(const QTextBlock &p_block,
                                       QVector<Region> &p_regions) const;
 
+    void finishOneAsyncJob(int p_idx);
+
     HGMarkdownHighlighter *m_mdHighlighter;
     VCodeBlockHighlightHelper *m_cbHighlighter;
     VImagePreviewer *m_imagePreviewer;
@@ -111,6 +113,12 @@ private:
     QVector<ImageLink> m_initImages;
 
     QVector<VHeader> m_headers;
+
+    bool m_freshEdit;
+
+    QVector<bool> m_finishedAsyncJobs;
+
+    static const int c_numberOfAysncJobs;
 };
 
 #endif // VMDEDIT_H