aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor
diff options
context:
space:
mode:
authorArtem Sokolovskii <artem.sokolovskii@qt.io>2024-02-23 17:37:03 +0100
committerArtem Sokolovskii <artem.sokolovskii@qt.io>2024-02-28 11:53:02 +0000
commit95a5f010962ab642a3dbd9d6f8f96f3b2e917b79 (patch)
tree58ff7479b932d891180148d73f01e760d5665787 /src/plugins/texteditor
parent3f785928319716c76cc4eb23eebb0dc8c60a7429 (diff)
TextEditor: Fix folding for async syntax highlighter
- Made restoreState, ensureBlockIsUnfolded, fold, unfold and unfoldAll functions to be called only after highlighting is done - Improved management of foldValidator in async case - Removed optimizations in cpphighlighter and glshighlighter. The highlighters are async now and optimization is not necessary. In these optimizations in the function highlightBlock the highlighting changes not only for currentBlock but and for several next. Which is contradict with the function name. Change-Id: Ib413e6b982eb39d52f36c3066ff0fa8c28fbe231 Reviewed-by: David Schulz <david.schulz@qt.io>
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.cpp18
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.h36
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.cpp13
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.h1
-rw-r--r--src/plugins/texteditor/texteditor.cpp39
-rw-r--r--src/plugins/texteditor/texteditor.h1
6 files changed, 81 insertions, 27 deletions
diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp
index 0ed00af389..34f4b1c777 100644
--- a/src/plugins/texteditor/syntaxhighlighter.cpp
+++ b/src/plugins/texteditor/syntaxhighlighter.cpp
@@ -81,6 +81,10 @@ void SyntaxHighlighter::delayedRehighlight()
if (!d->rehighlightPending)
return;
d->rehighlightPending = false;
+
+ if (document()->isEmpty())
+ return;
+
rehighlight();
}
@@ -197,6 +201,10 @@ void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int ch
QList<SyntaxHighlighter::Result> vecRes;
+ SyntaxHighlighter::Result resStart;
+ resStart.m_state = SyntaxHighlighter::State::Start;
+ vecRes << resStart;
+
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
if (QThread::currentThread()->isInterruptionRequested())
break;
@@ -758,7 +766,10 @@ void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
SyntaxHighlighter::Result res;
res.m_formatRanges = block.layout()->formats();
res.fillByBlock(block);
- emit resultsReady({res});
+ res.m_state = SyntaxHighlighter::State::Extras;
+ SyntaxHighlighter::Result resDone;
+ resDone.m_state = SyntaxHighlighter::State::Done;
+ emit resultsReady({res, resDone});
document()->markContentsDirty(block.position(), blockLength - 1);
d->inReformatBlocks = wasInReformatBlocks;
@@ -784,7 +795,10 @@ void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
SyntaxHighlighter::Result res;
res.m_formatRanges = block.layout()->formats();
res.fillByBlock(block);
- emit resultsReady({res});
+ res.m_state = SyntaxHighlighter::State::Extras;
+ SyntaxHighlighter::Result resDone;
+ resDone.m_state = SyntaxHighlighter::State::Done;
+ emit resultsReady({res, resDone});
document()->markContentsDirty(block.position(), blockLength - 1);
d->inReformatBlocks = wasInReformatBlocks;
diff --git a/src/plugins/texteditor/syntaxhighlighter.h b/src/plugins/texteditor/syntaxhighlighter.h
index 94cee8a65e..533c628b9c 100644
--- a/src/plugins/texteditor/syntaxhighlighter.h
+++ b/src/plugins/texteditor/syntaxhighlighter.h
@@ -53,8 +53,10 @@ public:
virtual void setFontSettings(const TextEditor::FontSettings &fontSettings);
TextEditor::FontSettings fontSettings() const;
- enum State {
+ enum State {
+ Start,
InProgress,
+ Extras,
Done
};
@@ -71,7 +73,6 @@ public:
m_hasBlockUserData = true;
m_foldingIndent = userDate->foldingIndent();
- m_folded = userDate->folded();
m_ifdefedOut = userDate->ifdefedOut();
m_foldingStartIncluded = userDate->foldingStartIncluded();
m_foldingEndIncluded = userDate->foldingEndIncluded();
@@ -83,28 +84,27 @@ public:
{
block.setUserState(m_userState);
- if (m_hasBlockUserData) {
- TextBlockUserData *data = TextDocumentLayout::userData(block);
- data->setExpectedRawStringSuffix(m_expectedRawStringSuffix);
- data->setFolded(m_folded);
- data->setFoldingIndent(m_foldingIndent);
- data->setFoldingStartIncluded(m_foldingStartIncluded);
- data->setFoldingEndIncluded(m_foldingEndIncluded);
-
- if (m_ifdefedOut)
- data->setIfdefedOut();
- else
- data->clearIfdefedOut();
-
- data->setParentheses(m_parentheses);
- }
+ if (!m_hasBlockUserData)
+ return;
+
+ TextBlockUserData *data = TextDocumentLayout::userData(block);
+ data->setExpectedRawStringSuffix(m_expectedRawStringSuffix);
+ data->setFoldingIndent(m_foldingIndent);
+ data->setFoldingStartIncluded(m_foldingStartIncluded);
+ data->setFoldingEndIncluded(m_foldingEndIncluded);
+
+ if (m_ifdefedOut)
+ data->setIfdefedOut();
+ else
+ data->clearIfdefedOut();
+
+ data->setParentheses(m_parentheses);
}
int m_blockNumber;
bool m_hasBlockUserData = false;
int m_foldingIndent : 16;
- uint m_folded : 1;
uint m_ifdefedOut : 1;
uint m_foldingStartIncluded : 1;
uint m_foldingEndIncluded : 1;
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.cpp b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
index bf53d90561..228b866849 100644
--- a/src/plugins/texteditor/syntaxhighlighterrunner.cpp
+++ b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
@@ -100,7 +100,6 @@ public:
SyntaxHighlighter *m_highlighter = nullptr;
QTextDocument *m_document = nullptr;
-
signals:
void resultsReady(const QList<SyntaxHighlighter::Result> &result);
@@ -130,6 +129,8 @@ SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
&QTextDocument::contentsChange,
this,
&SyntaxHighlighterRunner::changeDocument);
+
+ m_foldValidator.setup(qobject_cast<TextDocumentLayout *>(document->documentLayout()));
} else {
connect(d,
&SyntaxHighlighterRunnerPrivate::resultsReady,
@@ -169,7 +170,12 @@ void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::R
for (const SyntaxHighlighter::Result &result : results) {
m_syntaxInfoUpdated = result.m_state;
+ if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Start) {
+ m_foldValidator.reset();
+ continue;
+ }
if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Done) {
+ m_foldValidator.finalize();
emit highlightingFinished();
return;
}
@@ -181,12 +187,11 @@ void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::R
result.copyToBlock(docBlock);
if (result.m_formatRanges != docBlock.layout()->formats()) {
- TextDocumentLayout::FoldValidator foldValidator;
- foldValidator.setup(qobject_cast<TextDocumentLayout *>(m_document->documentLayout()));
docBlock.layout()->setFormats(result.m_formatRanges);
m_document->markContentsDirty(docBlock.position(), docBlock.length());
- foldValidator.process(docBlock);
}
+ if (m_syntaxInfoUpdated != SyntaxHighlighter::State::Extras)
+ m_foldValidator.process(docBlock);
}
}
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.h b/src/plugins/texteditor/syntaxhighlighterrunner.h
index ccb292ea08..5540bd666a 100644
--- a/src/plugins/texteditor/syntaxhighlighterrunner.h
+++ b/src/plugins/texteditor/syntaxhighlighterrunner.h
@@ -56,6 +56,7 @@ private:
bool m_useGenericHighlighter = false;
QString m_definitionName;
std::optional<QThread> m_thread;
+ TextDocumentLayout::FoldValidator m_foldValidator;
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 70239b286e..4817c61dd7 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -3492,13 +3492,35 @@ QByteArray TextEditorWidget::saveState() const
return state;
}
+bool TextEditorWidget::singleShotAfterHighlightingDone(std::function<void()> &&f)
+{
+ if (d->m_document->syntaxHighlighterRunner()
+ && !d->m_document->syntaxHighlighterRunner()->syntaxInfoUpdated()) {
+ connect(d->m_document->syntaxHighlighterRunner(),
+ &SyntaxHighlighterRunner::highlightingFinished,
+ this,
+ [f = std::move(f)] { f(); }, Qt::SingleShotConnection);
+ return true;
+ }
+
+ return false;
+}
+
void TextEditorWidget::restoreState(const QByteArray &state)
{
- if (state.isEmpty()) {
+ if (singleShotAfterHighlightingDone([this, state] { restoreState(state); }))
+ return;
+
+ const auto callFoldLicenseHeader = [this] {
if (d->m_displaySettings.m_autoFoldFirstComment)
d->foldLicenseHeader();
+ };
+
+ if (state.isEmpty()) {
+ callFoldLicenseHeader();
return;
}
+
int version;
int vval;
int hval;
@@ -3530,8 +3552,7 @@ void TextEditorWidget::restoreState(const QByteArray &state)
documentLayout->emitDocumentSizeChanged();
}
} else {
- if (d->m_displaySettings.m_autoFoldFirstComment)
- d->foldLicenseHeader();
+ callFoldLicenseHeader();
}
d->m_lastCursorChangeWasInteresting = false; // avoid adding last position to history
@@ -6642,6 +6663,9 @@ void TextEditorWidget::ensureCursorVisible()
void TextEditorWidget::ensureBlockIsUnfolded(QTextBlock block)
{
+ if (singleShotAfterHighlightingDone([this, block] { ensureBlockIsUnfolded(block); }))
+ return;
+
if (!block.isVisible()) {
auto documentLayout = qobject_cast<TextDocumentLayout*>(document()->documentLayout());
QTC_ASSERT(documentLayout, return);
@@ -8215,6 +8239,9 @@ void TextEditorWidget::foldCurrentBlock()
void TextEditorWidget::fold(const QTextBlock &block)
{
+ if (singleShotAfterHighlightingDone([this, block] { fold(block); }))
+ return;
+
QTextDocument *doc = document();
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
@@ -8235,6 +8262,9 @@ void TextEditorWidget::fold(const QTextBlock &block)
void TextEditorWidget::unfold(const QTextBlock &block)
{
+ if (singleShotAfterHighlightingDone([this, block] { unfold(block); }))
+ return;
+
QTextDocument *doc = document();
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
@@ -8254,6 +8284,9 @@ void TextEditorWidget::unfoldCurrentBlock()
void TextEditorWidget::unfoldAll()
{
+ if (singleShotAfterHighlightingDone([this] { unfoldAll(); }))
+ return;
+
QTextDocument *doc = document();
auto documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 33b8cb84f0..85344a8dbd 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -645,6 +645,7 @@ private:
friend class Internal::TextEditorOverlay;
friend class RefactorOverlay;
+ bool singleShotAfterHighlightingDone(std::function<void()> &&f);
void updateVisualWrapColumn();
};