浏览代码

PreviewManager: refactor layout logics

- Bug fix: use cached image name in preview helpers;
- Only relayout necessary blocks;
Le Tan 7 年之前
父节点
当前提交
968e74e1ca

+ 0 - 4
src/pegmarkdownhighlighter.cpp

@@ -913,10 +913,6 @@ bool PegMarkdownHighlighter::rehighlightBlockRange(int p_first, int p_last)
             }
         }
 
-        if (!needHL && !data->getPreviews().isEmpty()) {
-            needHL = true;
-        }
-
         if (needHL) {
             highlighted = true;
             rehighlightBlock(block);

+ 17 - 2
src/vlivepreviewhelper.cpp

@@ -42,6 +42,7 @@ CodeBlockPreviewInfo::CodeBlockPreviewInfo(const VCodeBlock &p_cb)
 void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
                                                 const QTextDocument *p_doc,
                                                 const QPixmap &p_image,
+                                                const QString &p_imageName,
                                                 const QString &p_background)
 {
     QTextBlock block = p_doc->findBlockByNumber(m_codeBlock.m_endBlock);
@@ -54,7 +55,12 @@ void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
         preview->m_blockNumber = m_codeBlock.m_endBlock;
         preview->m_padding = VPreviewManager::calculateBlockMargin(block,
                                                                    p_editor->tabStopWidthW());
-        preview->m_name = QString::number(getImageIndex());
+        if (!p_imageName.isEmpty()) {
+            preview->m_name = p_imageName;
+        } else {
+            preview->m_name = QString::number(getImageIndex());
+        }
+
         preview->m_background = p_background;
         preview->m_isBlock = true;
 
@@ -178,6 +184,7 @@ void VLivePreviewHelper::updateCodeBlocks(TimeStamp p_timeStamp, const QVector<V
             m_codeBlocks[idx].updateInplacePreview(m_editor,
                                                    m_doc,
                                                    entry->m_image,
+                                                   entry->m_imageName,
                                                    background);
         }
 
@@ -383,7 +390,11 @@ void VLivePreviewHelper::localAsyncResultReady(int p_id,
     m_cache.insert(text, entry);
 
     cb.setImageData(p_format, p_result);
-    cb.updateInplacePreview(m_editor, m_doc, entry->m_image, background);
+    cb.updateInplacePreview(m_editor, m_doc, entry->m_image, QString(), background);
+
+    if (cb.inplacePreview()) {
+        entry->m_imageName = cb.inplacePreview()->m_name;
+    }
 
     if (livePreview) {
         if (idx != m_cbIndex) {
@@ -495,6 +506,10 @@ void VLivePreviewHelper::mathjaxPreviewResultReady(int p_identitifer,
 
     cb.updateInplacePreview(m_editor, m_doc, entry->m_image);
 
+    if (cb.inplacePreview()) {
+        entry->m_imageName = cb.inplacePreview()->m_name;
+    }
+
     updateInplacePreview();
 }
 

+ 4 - 2
src/vlivepreviewhelper.h

@@ -24,13 +24,14 @@ public:
     void updateInplacePreview(const VEditor *p_editor,
                               const QTextDocument *p_doc,
                               const QPixmap &p_image,
+                              const QString &p_imageName,
                               const QString &p_background);
 
     void updateInplacePreview(const VEditor *p_editor,
                               const QTextDocument *p_doc,
                               const QPixmap &p_image)
     {
-        updateInplacePreview(p_editor, p_doc, p_image, QString());
+        updateInplacePreview(p_editor, p_doc, p_image, QString(), QString());
     }
 
     VCodeBlock &codeBlock()
@@ -69,7 +70,7 @@ public:
         m_imgData = p_data;
     }
 
-    const QSharedPointer<VImageToPreview> inplacePreview() const
+    const QSharedPointer<VImageToPreview> &inplacePreview() const
     {
         return m_inplacePreview;
     }
@@ -197,6 +198,7 @@ private:
 
         // For in-place preview.
         QPixmap m_image;
+        QString m_imageName;
     };
 
 

+ 17 - 4
src/vmathjaxinplacepreviewhelper.cpp

@@ -21,7 +21,8 @@ MathjaxBlockPreviewInfo::MathjaxBlockPreviewInfo(const VMathjaxBlock &p_mb)
 
 void MathjaxBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
                                                    const QTextDocument *p_doc,
-                                                   const QPixmap &p_image)
+                                                   const QPixmap &p_image,
+                                                   const QString &p_imageName)
 {
     QTextBlock block = p_doc->findBlockByNumber(m_mathjaxBlock.m_blockNumber);
     if (block.isValid()) {
@@ -33,7 +34,12 @@ void MathjaxBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
         preview->m_blockNumber = m_mathjaxBlock.m_blockNumber;
         preview->m_padding = VPreviewManager::calculateBlockMargin(block,
                                                                    p_editor->tabStopWidthW());
-        preview->m_name = QString::number(getImageIndex());
+        if (!p_imageName.isEmpty()) {
+            preview->m_name = p_imageName;
+        } else {
+            preview->m_name = QString::number(getImageIndex());
+        }
+
         preview->m_isBlock = m_mathjaxBlock.m_previewedAsBlock;
 
         preview->m_image = p_image;
@@ -105,7 +111,10 @@ void VMathJaxInplacePreviewHelper::updateMathjaxBlocks(const QVector<VMathjaxBlo
             QSharedPointer<MathjaxImageCacheEntry> &entry = it.value();
             entry->m_ts = m_timeStamp;
             cached = true;
-            m_mathjaxBlocks.last().updateInplacePreview(m_editor, m_doc, entry->m_image);
+            m_mathjaxBlocks.last().updateInplacePreview(m_editor,
+                                                        m_doc,
+                                                        entry->m_image,
+                                                        entry->m_imageName);
         }
 
         if (!cached || !m_mathjaxBlocks.last().inplacePreviewReady()) {
@@ -198,7 +207,11 @@ void VMathJaxInplacePreviewHelper::mathjaxPreviewResultReady(int p_identitifer,
                                                                             p_data,
                                                                             p_format));
     m_cache.insert(mb.mathjaxBlock().m_text, entry);
-    mb.updateInplacePreview(m_editor, m_doc, entry->m_image);
+    mb.updateInplacePreview(m_editor, m_doc, entry->m_image, QString());
+
+    if (mb.inplacePreview()) {
+        entry->m_imageName = mb.inplacePreview()->m_name;
+    }
 
     updateInplacePreview();
 }

+ 4 - 2
src/vmathjaxinplacepreviewhelper.h

@@ -21,7 +21,8 @@ public:
 
     void updateInplacePreview(const VEditor *p_editor,
                               const QTextDocument *p_doc,
-                              const QPixmap &p_image);
+                              const QPixmap &p_image,
+                              const QString &p_imageName);
 
     VMathjaxBlock &mathjaxBlock()
     {
@@ -38,7 +39,7 @@ public:
         return !m_inplacePreview.isNull();
     }
 
-    const QSharedPointer<VImageToPreview> inplacePreview() const
+    const QSharedPointer<VImageToPreview> &inplacePreview() const
     {
         return m_inplacePreview;
     }
@@ -103,6 +104,7 @@ private:
 
         TimeStamp m_ts;
         QPixmap m_image;
+        QString m_imageName;
     };
 
 

+ 35 - 25
src/vpreviewmanager.cpp

@@ -83,11 +83,14 @@ void VPreviewManager::setPreviewEnabled(bool p_enabled)
 
 void VPreviewManager::clearPreview()
 {
+    OrderedIntSet affectedBlocks;
     for (int i = 0; i < (int)PreviewSource::MaxNumberOfSources; ++i) {
         TS ts = ++timeStamp(static_cast<PreviewSource>(i));
-        clearBlockObsoletePreviewInfo(ts, static_cast<PreviewSource>(i));
+        clearBlockObsoletePreviewInfo(ts, static_cast<PreviewSource>(i), affectedBlocks);
         clearObsoleteImages(ts, static_cast<PreviewSource>(i));
     }
+
+    relayout(affectedBlocks);
 }
 
 void VPreviewManager::previewImages(TS p_timeStamp, const QVector<VElementRegion> &p_imageRegions)
@@ -95,11 +98,15 @@ void VPreviewManager::previewImages(TS p_timeStamp, const QVector<VElementRegion
     QVector<ImageLinkInfo> imageLinks;
     fetchImageLinksFromRegions(p_imageRegions, imageLinks);
 
-    updateBlockPreviewInfo(p_timeStamp, imageLinks);
+    OrderedIntSet affectedBlocks;
 
-    clearBlockObsoletePreviewInfo(p_timeStamp, PreviewSource::ImageLink);
+    updateBlockPreviewInfo(p_timeStamp, imageLinks, affectedBlocks);
+
+    clearBlockObsoletePreviewInfo(p_timeStamp, PreviewSource::ImageLink, affectedBlocks);
 
     clearObsoleteImages(p_timeStamp, PreviewSource::ImageLink);
+
+    relayout(affectedBlocks);
 }
 
 // Returns true if p_text[p_start, p_end) is all spaces.
@@ -367,9 +374,9 @@ int VPreviewManager::calculateBlockMargin(const QTextBlock &p_block, int p_tabSt
 }
 
 void VPreviewManager::updateBlockPreviewInfo(TS p_timeStamp,
-                                             const QVector<ImageLinkInfo> &p_imageLinks)
+                                             const QVector<ImageLinkInfo> &p_imageLinks,
+                                             OrderedIntSet &p_affectedBlocks)
 {
-    OrderedIntSet affectedBlocks;
     for (auto const & link : p_imageLinks) {
         QTextBlock block = m_document->findBlockByNumber(link.m_blockNumber);
         if (!block.isValid()) {
@@ -399,19 +406,17 @@ void VPreviewManager::updateBlockPreviewInfo(TS p_timeStamp,
         imageCache(PreviewSource::ImageLink).insert(name, p_timeStamp);
         if (!tsUpdated) {
             // No need to relayout the block if only timestamp is updated.
-            affectedBlocks.insert(link.m_blockNumber, QMapDummyValue());
+            p_affectedBlocks.insert(link.m_blockNumber, QMapDummyValue());
             m_highlighter->addPossiblePreviewBlock(link.m_blockNumber);
         }
     }
-
-    relayoutEditor(affectedBlocks);
 }
 
 void VPreviewManager::updateBlockPreviewInfo(TS p_timeStamp,
                                              PreviewSource p_source,
-                                             const QVector<QSharedPointer<VImageToPreview> > &p_images)
+                                             const QVector<QSharedPointer<VImageToPreview> > &p_images,
+                                             OrderedIntSet &p_affectedBlocks)
 {
-    OrderedIntSet affectedBlocks;
     for (auto const & img : p_images) {
         if (img.isNull()) {
             continue;
@@ -445,13 +450,10 @@ void VPreviewManager::updateBlockPreviewInfo(TS p_timeStamp,
         imageCache(p_source).insert(name, p_timeStamp);
         if (!tsUpdated) {
             // No need to relayout the block if only timestamp is updated.
-            affectedBlocks.insert(img->m_blockNumber, QMapDummyValue());
+            p_affectedBlocks.insert(img->m_blockNumber, QMapDummyValue());
             m_highlighter->addPossiblePreviewBlock(img->m_blockNumber);
         }
     }
-
-    // Relayout these blocks since they may not have been changed.
-    relayoutEditor(affectedBlocks);
 }
 
 void VPreviewManager::clearObsoleteImages(long long p_timeStamp, PreviewSource p_source)
@@ -469,9 +471,9 @@ void VPreviewManager::clearObsoleteImages(long long p_timeStamp, PreviewSource p
 }
 
 void VPreviewManager::clearBlockObsoletePreviewInfo(long long p_timeStamp,
-                                                    PreviewSource p_source)
+                                                    PreviewSource p_source,
+                                                    OrderedIntSet &p_affectedBlocks)
 {
-    OrderedIntSet affectedBlocks;
     QVector<int> obsoleteBlocks;
     const QSet<int> &blocks = m_highlighter->getPossiblePreviewBlocks();
     for (auto i : blocks) {
@@ -487,7 +489,7 @@ void VPreviewManager::clearBlockObsoletePreviewInfo(long long p_timeStamp,
         }
 
         if (blockData->clearObsoletePreview(p_timeStamp, p_source)) {
-            affectedBlocks.insert(i, QMapDummyValue());
+            p_affectedBlocks.insert(i, QMapDummyValue());
         }
 
         if (blockData->getPreviews().isEmpty()) {
@@ -496,8 +498,6 @@ void VPreviewManager::clearBlockObsoletePreviewInfo(long long p_timeStamp,
     }
 
     m_highlighter->clearPossiblePreviewBlocks(obsoleteBlocks);
-
-    m_editor->relayout(affectedBlocks);
 }
 
 void VPreviewManager::refreshPreview()
@@ -520,11 +520,15 @@ void VPreviewManager::updateCodeBlocks(const QVector<QSharedPointer<VImageToPrev
 
     TS ts = ++timeStamp(PreviewSource::CodeBlock);
 
-    updateBlockPreviewInfo(ts, PreviewSource::CodeBlock, p_images);
+    OrderedIntSet affectedBlocks;
 
-    clearBlockObsoletePreviewInfo(ts, PreviewSource::CodeBlock);
+    updateBlockPreviewInfo(ts, PreviewSource::CodeBlock, p_images, affectedBlocks);
+
+    clearBlockObsoletePreviewInfo(ts, PreviewSource::CodeBlock, affectedBlocks);
 
     clearObsoleteImages(ts, PreviewSource::CodeBlock);
+
+    relayout(affectedBlocks);
 }
 
 void VPreviewManager::updateMathjaxBlocks(const QVector<QSharedPointer<VImageToPreview> > &p_images)
@@ -535,11 +539,15 @@ void VPreviewManager::updateMathjaxBlocks(const QVector<QSharedPointer<VImageToP
 
     TS ts = ++timeStamp(PreviewSource::MathjaxBlock);
 
-    updateBlockPreviewInfo(ts, PreviewSource::MathjaxBlock, p_images);
+    OrderedIntSet affectedBlocks;
+
+    updateBlockPreviewInfo(ts, PreviewSource::MathjaxBlock, p_images, affectedBlocks);
 
-    clearBlockObsoletePreviewInfo(ts, PreviewSource::MathjaxBlock);
+    clearBlockObsoletePreviewInfo(ts, PreviewSource::MathjaxBlock, affectedBlocks);
 
     clearObsoleteImages(ts, PreviewSource::MathjaxBlock);
+
+    relayout(affectedBlocks);
 }
 
 void VPreviewManager::checkBlocksForObsoletePreview(const QList<int> &p_blocks)
@@ -576,7 +584,7 @@ void VPreviewManager::checkBlocksForObsoletePreview(const QList<int> &p_blocks)
         }
     }
 
-    m_editor->relayout(affectedBlocks);
+    relayout(affectedBlocks);
 }
 
 void VPreviewManager::relayoutEditor(const OrderedIntSet &p_blocks)
@@ -594,7 +602,9 @@ void VPreviewManager::relayoutEditor(const OrderedIntSet &p_blocks)
     OrderedIntSet after;
     int afterFirst = m_editor->firstVisibleBlockNumber();
     for (int i = afterFirst; i < first; ++i) {
-        after.insert(i, QMapDummyValue());
+        if (!bs.contains(i)) {
+            after.insert(i, QMapDummyValue());
+        }
     }
 
     m_editor->relayout(after);

+ 15 - 3
src/vpreviewmanager.h

@@ -187,12 +187,15 @@ private:
     void fetchImageInfoToPreview(const QString &p_text, ImageLinkInfo &p_info);
 
     // Update the preview info of related blocks according to @p_imageLinks.
-    void updateBlockPreviewInfo(TS p_timeStamp, const QVector<ImageLinkInfo> &p_imageLinks);
+    void updateBlockPreviewInfo(TS p_timeStamp,
+                                const QVector<ImageLinkInfo> &p_imageLinks,
+                                OrderedIntSet &p_affectedBlocks);
 
     // Update the preview info of related blocks according to @p_images.
     void updateBlockPreviewInfo(TS p_timeStamp,
                                 PreviewSource p_source,
-                                const QVector<QSharedPointer<VImageToPreview> > &p_images);
+                                const QVector<QSharedPointer<VImageToPreview> > &p_images,
+                                OrderedIntSet &p_affectedBlocks);
 
     // Get the name of the image in the resource manager.
     // Will add the image to the resource manager if not exists.
@@ -205,12 +208,16 @@ private:
 
     void clearObsoleteImages(long long p_timeStamp, PreviewSource p_source);
 
-    void clearBlockObsoletePreviewInfo(long long p_timeStamp, PreviewSource p_source);
+    void clearBlockObsoletePreviewInfo(long long p_timeStamp,
+                                       PreviewSource p_source,
+                                       OrderedIntSet &p_affectedBlocks);
 
     TS &timeStamp(PreviewSource p_source);
 
     void relayoutEditor(const OrderedIntSet &p_blocks);
 
+    void relayout(const OrderedIntSet &p_blocks);
+
     VMdEditor *m_editor;
 
     QTextDocument *m_document;
@@ -247,4 +254,9 @@ inline bool VPreviewManager::isPreviewEnabled() const
 {
     return m_previewEnabled;
 }
+
+inline void VPreviewManager::relayout(const OrderedIntSet &p_blocks)
+{
+    m_editor->relayout(p_blocks);
+}
 #endif // VPREVIEWMANAGER_H

+ 12 - 11
src/vtextdocumentlayout.cpp

@@ -730,7 +730,7 @@ void VTextDocumentLayout::finishBlockLayout(const QTextBlock &p_block,
 
 void VTextDocumentLayout::updateDocumentSize()
 {
-    QTextBlock block = document()->lastBlock(); 
+    QTextBlock block = document()->lastBlock();
     const BlockLayoutInfo *info = VTextBlockData::layoutInfo(block);
     if (!info->hasOffset()) {
         if (info->isNull()) {
@@ -959,7 +959,7 @@ void VTextDocumentLayout::relayout()
         block = block.next();
     }
 
-    updateOffsetBefore(doc->lastBlock());
+    updateOffset(doc->firstBlock());
 
     updateDocumentSize();
 
@@ -975,28 +975,29 @@ void VTextDocumentLayout::relayout(const OrderedIntSet &p_blocks)
     QTextDocument *doc = document();
 
     // Need to relayout and update blocks in ascending order.
-    QVector<QTextBlock> blocks;
-    blocks.reserve(p_blocks.size());
+    QTextBlock startBlock;
     for (auto bn = p_blocks.keyBegin(); bn != p_blocks.keyEnd(); ++bn) {
         QTextBlock block = doc->findBlockByNumber(*bn);
         if (block.isValid()) {
-            blocks.append(block);
+            if (!startBlock.isValid()) {
+                startBlock = block;
+            }
+
             clearBlockLayout(block);
             layoutBlock(block);
         }
     }
 
-    if (blocks.isEmpty()) {
+    if (!startBlock.isValid()) {
         return;
     }
 
-    updateOffset(blocks.last());
-
-    for (auto const & blk : blocks) {
-        emit updateBlock(blk);
-    }
+    updateOffset(startBlock);
 
     updateDocumentSize();
+
+    qreal offset = VTextBlockData::layoutInfo(startBlock)->m_offset;
+    emit update(QRectF(0., offset, 1000000000., 1000000000.));
 }
 
 qreal VTextDocumentLayout::fetchInlineImagesForOneLine(const QVector<VPreviewInfo *> &p_info,

+ 4 - 0
src/vtextedit.cpp

@@ -323,6 +323,10 @@ void VTextEdit::clearBlockImages()
 
 void VTextEdit::relayout(const OrderedIntSet &p_blocks)
 {
+    if (p_blocks.isEmpty()) {
+        return;
+    }
+
     getLayout()->relayout(p_blocks);
 
     updateLineNumberArea();