PreviewManager: refactor layout logics

- Bug fix: use cached image name in preview helpers;
- Only relayout necessary blocks;
This commit is contained in:
Le Tan 2018-08-13 20:14:18 +08:00
parent be5e34cc85
commit 968e74e1ca
9 changed files with 108 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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