optimize VImagePreviewer by flags

This commit is contained in:
Le Tan 2017-09-08 21:41:46 +08:00
parent e55b0af00e
commit 07e8f27776
5 changed files with 77 additions and 27 deletions

View File

@ -80,7 +80,7 @@ HGMarkdownHighlighter::~HGMarkdownHighlighter()
}
}
void HGMarkdownHighlighter::updateBlockUserData(const QString &p_text)
void HGMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &p_text)
{
VTextBlockData *blockData = dynamic_cast<VTextBlockData *>(currentBlockUserData());
if (!blockData) {
@ -88,7 +88,33 @@ void HGMarkdownHighlighter::updateBlockUserData(const QString &p_text)
setCurrentBlockUserData(blockData);
}
blockData->setContainsPreviewImage(p_text.contains(QChar::ObjectReplacementCharacter));
bool contains = p_text.contains(QChar::ObjectReplacementCharacter);
blockData->setContainsPreviewImage(contains);
auto curIt = m_potentialPreviewBlocks.find(p_blockNum);
if (curIt == m_potentialPreviewBlocks.end()) {
if (contains) {
m_potentialPreviewBlocks.insert(p_blockNum, true);
}
} else {
if (!contains) {
m_potentialPreviewBlocks.erase(curIt);
}
}
// Delete elements beyond current block count.
int blocks = document->blockCount();
if (!m_potentialPreviewBlocks.isEmpty()) {
auto it = m_potentialPreviewBlocks.end();
do {
--it;
if (it.key() >= blocks) {
it = m_potentialPreviewBlocks.erase(it);
} else {
break;
}
} while (it != m_potentialPreviewBlocks.begin());
}
}
void HGMarkdownHighlighter::highlightBlock(const QString &text)
@ -107,7 +133,7 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
// We can use other highlighting methods to complement it.
// Set current block's user data.
updateBlockUserData(text);
updateBlockUserData(blockNum, text);
// If it is a block inside HTML comment, just skip it.
if (isBlockInsideCommentRegion(currentBlock())) {

View File

@ -4,7 +4,7 @@
#include <QTextCharFormat>
#include <QSyntaxHighlighter>
#include <QAtomicInt>
#include <QSet>
#include <QMap>
#include <QString>
#include <QHash>
@ -118,9 +118,12 @@ public:
int waitInterval,
QTextDocument *parent = 0);
~HGMarkdownHighlighter();
// Request to update highlihgt (re-parse and re-highlight)
void setCodeBlockHighlights(const QVector<HLUnitPos> &p_units);
const QMap<int, bool> &getPotentialPreviewBlocks() const;
signals:
void highlightCompleted();
@ -160,6 +163,11 @@ private:
int m_numOfCodeBlockHighlightsToRecv;
// If the ith block contains preview, then the set contains i.
// If the set contains i, the ith block may contain preview.
// We just use the key.
QMap<int, bool> m_potentialPreviewBlocks;
// All HTML comment regions.
QVector<VElementRegion> m_commentRegions;
@ -210,7 +218,12 @@ private:
void highlightChanged();
// Set the user data of currentBlock().
void updateBlockUserData(const QString &p_text);
void updateBlockUserData(int p_blockNum, const QString &p_text);
};
inline const QMap<int, bool> &HGMarkdownHighlighter::getPotentialPreviewBlocks() const
{
return m_potentialPreviewBlocks;
}
#endif

View File

@ -20,10 +20,10 @@ extern VConfigManager *g_config;
const int VImagePreviewer::c_minImageWidth = 100;
VImagePreviewer::VImagePreviewer(VMdEdit *p_edit)
VImagePreviewer::VImagePreviewer(VMdEdit *p_edit, const HGMarkdownHighlighter *p_highlighter)
: QObject(p_edit), m_edit(p_edit), m_document(p_edit->document()),
m_file(p_edit->getFile()), m_imageWidth(c_minImageWidth),
m_timeStamp(0), m_previewIndex(0),
m_file(p_edit->getFile()), m_highlighter(p_highlighter),
m_imageWidth(c_minImageWidth), m_timeStamp(0), m_previewIndex(0),
m_previewEnabled(g_config->getEnablePreviewImages()), m_isPreviewing(false)
{
m_updateTimer = new QTimer(this);
@ -152,19 +152,28 @@ void VImagePreviewer::clearObsoletePreviewImages(QTextCursor &p_cursor)
}
}
bool hasObsolete = false;
QTextBlock block = m_document->begin();
// Clean block data and delete obsolete preview.
while (block.isValid()) {
if (!VTextBlockData::containsPreviewImage(block)) {
block = block.next();
bool hasObsolete = false;
int blockCount = m_document->blockCount();
// Must copy it.
QMap<int, bool> potentialBlocks = m_highlighter->getPotentialPreviewBlocks();
// From back to front.
if (!potentialBlocks.isEmpty()) {
auto it = potentialBlocks.end();
do {
--it;
int blockNum = it.key();
if (blockNum >= blockCount) {
continue;
} else {
QTextBlock nextBlock = block.next();
}
QTextBlock block = m_document->findBlockByNumber(blockNum);
if (block.isValid()
&& VTextBlockData::containsPreviewImage(block)) {
// Notice the short circuit.
hasObsolete = clearObsoletePreviewImagesOfBlock(block, p_cursor) || hasObsolete;
block = nextBlock;
}
} while (it != potentialBlocks.begin());
}
if (hasObsolete) {
@ -246,11 +255,11 @@ bool VImagePreviewer::clearObsoletePreviewImagesOfBlock(QTextBlock &p_block,
return hasObsolete;
}
// Returns true if p_text[p_start, p_end) is all spaces.
static bool isAllSpaces(const QString &p_text, int p_start, int p_end)
// Returns true if p_text[p_start, p_end) is all spaces or QChar::ObjectReplacementCharacter.
static bool isAllSpacesOrObject(const QString &p_text, int p_start, int p_end)
{
for (int i = p_start; i < p_end && i < p_text.size(); ++i) {
if (!p_text[i].isSpace()) {
if (!p_text[i].isSpace() && p_text[i] != QChar::ObjectReplacementCharacter) {
return false;
}
}
@ -281,9 +290,9 @@ void VImagePreviewer::fetchImageLinksFromRegions(QVector<ImageLinkInfo> &p_image
Q_ASSERT(reg.m_endPos <= blockEnd);
ImageLinkInfo info(reg.m_startPos, reg.m_endPos);
if ((reg.m_startPos == blockStart
|| isAllSpaces(text, 0, reg.m_startPos - blockStart))
|| isAllSpacesOrObject(text, 0, reg.m_startPos - blockStart))
&& (reg.m_endPos == blockEnd
|| isAllSpaces(text, reg.m_endPos - blockStart, blockEnd - blockStart))) {
|| isAllSpacesOrObject(text, reg.m_endPos - blockStart, blockEnd - blockStart))) {
// Image block.
info.m_isBlock = true;
info.m_linkUrl = fetchImagePathToPreview(text);

View File

@ -17,7 +17,7 @@ class VImagePreviewer : public QObject
{
Q_OBJECT
public:
explicit VImagePreviewer(VMdEdit *p_edit);
explicit VImagePreviewer(VMdEdit *p_edit, const HGMarkdownHighlighter *p_highlighter);
// Whether @p_block is an image previewed block.
// The image previewed block is a block containing only the special character
@ -202,6 +202,8 @@ private:
QTextDocument *m_document;
VFile *m_file;
const HGMarkdownHighlighter *m_highlighter;
// Map from image full path to QUrl identifier in the QTextDocument's cache.
QHash<QString, ImageInfo> m_imageCache;

View File

@ -44,7 +44,7 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
m_cbHighlighter = new VCodeBlockHighlightHelper(m_mdHighlighter, p_vdoc,
p_type);
m_imagePreviewer = new VImagePreviewer(this);
m_imagePreviewer = new VImagePreviewer(this, m_mdHighlighter);
connect(m_mdHighlighter, &HGMarkdownHighlighter::imageLinksUpdated,
m_imagePreviewer, &VImagePreviewer::imageLinksChanged);
connect(m_imagePreviewer, &VImagePreviewer::requestUpdateImageLinks,