From 968e74e1ca7cbac832c55906a644db7e5f46d257 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Mon, 13 Aug 2018 20:14:18 +0800 Subject: [PATCH] PreviewManager: refactor layout logics - Bug fix: use cached image name in preview helpers; - Only relayout necessary blocks; --- src/pegmarkdownhighlighter.cpp | 4 -- src/vlivepreviewhelper.cpp | 19 ++++++++- src/vlivepreviewhelper.h | 6 ++- src/vmathjaxinplacepreviewhelper.cpp | 21 ++++++++-- src/vmathjaxinplacepreviewhelper.h | 6 ++- src/vpreviewmanager.cpp | 60 ++++++++++++++++------------ src/vpreviewmanager.h | 18 +++++++-- src/vtextdocumentlayout.cpp | 23 ++++++----- src/vtextedit.cpp | 4 ++ 9 files changed, 108 insertions(+), 53 deletions(-) diff --git a/src/pegmarkdownhighlighter.cpp b/src/pegmarkdownhighlighter.cpp index 40e5a9b1..d9a1afe5 100644 --- a/src/pegmarkdownhighlighter.cpp +++ b/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); diff --git a/src/vlivepreviewhelper.cpp b/src/vlivepreviewhelper.cpp index 978d8df8..4956c5ef 100644 --- a/src/vlivepreviewhelper.cpp +++ b/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 QVectorm_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(); } diff --git a/src/vlivepreviewhelper.h b/src/vlivepreviewhelper.h index 32ae8f89..e3dda5e9 100644 --- a/src/vlivepreviewhelper.h +++ b/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 inplacePreview() const + const QSharedPointer &inplacePreview() const { return m_inplacePreview; } @@ -197,6 +198,7 @@ private: // For in-place preview. QPixmap m_image; + QString m_imageName; }; diff --git a/src/vmathjaxinplacepreviewhelper.cpp b/src/vmathjaxinplacepreviewhelper.cpp index 998abb4b..26ad8aa7 100644 --- a/src/vmathjaxinplacepreviewhelper.cpp +++ b/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 &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(); } diff --git a/src/vmathjaxinplacepreviewhelper.h b/src/vmathjaxinplacepreviewhelper.h index a8efac16..8e0ccb89 100644 --- a/src/vmathjaxinplacepreviewhelper.h +++ b/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 inplacePreview() const + const QSharedPointer &inplacePreview() const { return m_inplacePreview; } @@ -103,6 +104,7 @@ private: TimeStamp m_ts; QPixmap m_image; + QString m_imageName; }; diff --git a/src/vpreviewmanager.cpp b/src/vpreviewmanager.cpp index 1a658aad..9e798950 100644 --- a/src/vpreviewmanager.cpp +++ b/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(i)); - clearBlockObsoletePreviewInfo(ts, static_cast(i)); + clearBlockObsoletePreviewInfo(ts, static_cast(i), affectedBlocks); clearObsoleteImages(ts, static_cast(i)); } + + relayout(affectedBlocks); } void VPreviewManager::previewImages(TS p_timeStamp, const QVector &p_imageRegions) @@ -95,11 +98,15 @@ void VPreviewManager::previewImages(TS p_timeStamp, const QVector 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 &p_imageLinks) + const QVector &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 > &p_images) + const QVector > &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 obsoleteBlocks; const QSet &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 > &p_images) @@ -535,11 +539,15 @@ void VPreviewManager::updateMathjaxBlocks(const QVector &p_blocks) @@ -576,7 +584,7 @@ void VPreviewManager::checkBlocksForObsoletePreview(const QList &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); diff --git a/src/vpreviewmanager.h b/src/vpreviewmanager.h index 5560d109..77b88150 100644 --- a/src/vpreviewmanager.h +++ b/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 &p_imageLinks); + void updateBlockPreviewInfo(TS p_timeStamp, + const QVector &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 > &p_images); + const QVector > &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 diff --git a/src/vtextdocumentlayout.cpp b/src/vtextdocumentlayout.cpp index eb595676..3d2be0af 100644 --- a/src/vtextdocumentlayout.cpp +++ b/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 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 &p_info, diff --git a/src/vtextedit.cpp b/src/vtextedit.cpp index a6c6f473..2b664076 100644 --- a/src/vtextedit.cpp +++ b/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();