aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/texteditor
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2024-03-11 18:02:37 +0100
committerTim Jenssen <tim.jenssen@qt.io>2024-03-11 17:18:48 +0000
commite7e9a58e46482142de3028cba2b9f3646542258d (patch)
treece1317817015e5e1f765f013a563ffc80eee6763 /src/plugins/texteditor
parent09b00446b788063f1c821581cfa8a03800e71629 (diff)
parent3af6f65ebc06ea52001e459c09179680dfa41d1a (diff)
Merge remote-tracking branch 'origin/13.0' into qds/dev
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r--src/plugins/texteditor/icodestylepreferences.cpp11
-rw-r--r--src/plugins/texteditor/icodestylepreferences.h3
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.cpp15
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.h11
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.cpp158
-rw-r--r--src/plugins/texteditor/syntaxhighlighterrunner.h16
-rw-r--r--src/plugins/texteditor/textdocument.cpp16
-rw-r--r--src/plugins/texteditor/textdocument.h2
-rw-r--r--src/plugins/texteditor/texteditor.cpp15
9 files changed, 200 insertions, 47 deletions
diff --git a/src/plugins/texteditor/icodestylepreferences.cpp b/src/plugins/texteditor/icodestylepreferences.cpp
index 82a478e697..8eae1c4be7 100644
--- a/src/plugins/texteditor/icodestylepreferences.cpp
+++ b/src/plugins/texteditor/icodestylepreferences.cpp
@@ -25,6 +25,7 @@ public:
bool m_readOnly = false;
bool m_temporarilyReadOnly = false;
bool m_isAdditionalTabVisible = false;
+ bool m_isAdditionalTabExist = false;
Key m_settingsSuffix;
};
@@ -92,6 +93,16 @@ void ICodeStylePreferences::setIsAdditionalTabVisible(bool on)
d->m_isAdditionalTabVisible = on;
}
+bool ICodeStylePreferences::additionalTabExist() const
+{
+ return d->m_isAdditionalTabExist;
+}
+
+void ICodeStylePreferences::setAdditionalTabExist(bool on)
+{
+ d->m_isAdditionalTabExist = on;
+}
+
void ICodeStylePreferences::setTabSettings(const TabSettings &settings)
{
if (d->m_tabSettings == settings)
diff --git a/src/plugins/texteditor/icodestylepreferences.h b/src/plugins/texteditor/icodestylepreferences.h
index 451ac669cc..aab34d3dc2 100644
--- a/src/plugins/texteditor/icodestylepreferences.h
+++ b/src/plugins/texteditor/icodestylepreferences.h
@@ -44,6 +44,9 @@ public:
bool isAdditionalTabVisible() const;
void setIsAdditionalTabVisible(bool on);
+ bool additionalTabExist() const;
+ void setAdditionalTabExist(bool on);
+
void setTabSettings(const TabSettings &settings);
TabSettings tabSettings() const;
TabSettings currentTabSettings() const;
diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp
index 34f4b1c777..f7db190852 100644
--- a/src/plugins/texteditor/syntaxhighlighter.cpp
+++ b/src/plugins/texteditor/syntaxhighlighter.cpp
@@ -206,8 +206,11 @@ void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int ch
vecRes << resStart;
while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
- if (QThread::currentThread()->isInterruptionRequested())
- break;
+ if (QThread::currentThread()->isInterruptionRequested() || q->isInterrupted()) {
+ inReformatBlocks = false;
+ emit q->resultsReady({});
+ return;
+ }
const int stateBeforeHighlight = block.userState();
@@ -767,9 +770,7 @@ void SyntaxHighlighter::setExtraFormats(const QTextBlock &block,
res.m_formatRanges = block.layout()->formats();
res.fillByBlock(block);
res.m_state = SyntaxHighlighter::State::Extras;
- SyntaxHighlighter::Result resDone;
- resDone.m_state = SyntaxHighlighter::State::Done;
- emit resultsReady({res, resDone});
+ emit resultsReady({std::move(res)});
document()->markContentsDirty(block.position(), blockLength - 1);
d->inReformatBlocks = wasInReformatBlocks;
@@ -796,9 +797,7 @@ void SyntaxHighlighter::clearExtraFormats(const QTextBlock &block)
res.m_formatRanges = block.layout()->formats();
res.fillByBlock(block);
res.m_state = SyntaxHighlighter::State::Extras;
- SyntaxHighlighter::Result resDone;
- resDone.m_state = SyntaxHighlighter::State::Done;
- emit resultsReady({res, resDone});
+ emit resultsReady({std::move(res)});
document()->markContentsDirty(block.position(), blockLength - 1);
d->inReformatBlocks = wasInReformatBlocks;
diff --git a/src/plugins/texteditor/syntaxhighlighter.h b/src/plugins/texteditor/syntaxhighlighter.h
index 533c628b9c..6b07d333f3 100644
--- a/src/plugins/texteditor/syntaxhighlighter.h
+++ b/src/plugins/texteditor/syntaxhighlighter.h
@@ -56,15 +56,15 @@ public:
enum State {
Start,
InProgress,
- Extras,
- Done
+ Done,
+ Extras
};
struct Result
{
void fillByBlock(const QTextBlock &block)
{
- m_blockNumber = block.position();
+ m_blockNumber = block.blockNumber();
m_userState = block.userState();
TextBlockUserData *userDate = TextDocumentLayout::textUserData(block);
@@ -117,6 +117,8 @@ public:
State m_state = InProgress;
};
+ void setInterrupted(bool interrupted) { m_interrupted = interrupted; }
+ bool isInterrupted() { return m_interrupted; }
void setExtraFormats(const QTextBlock &block, const QList<QTextLayout::FormatRange> &formats);
virtual void setLanguageFeaturesFlags(unsigned int /*flags*/) {}; // needed for CppHighlighting
virtual void setEnabled(bool /*enabled*/) {}; // needed for DiffAndLogHighlighter
@@ -126,6 +128,7 @@ public slots:
virtual void rehighlight();
void rehighlightBlock(const QTextBlock &block);
void clearExtraFormats(const QTextBlock &block);
+ void reformatBlocks(int from, int charsRemoved, int charsAdded);
void clearAllExtraFormats();
protected:
@@ -165,10 +168,10 @@ signals:
private:
void setTextFormatCategories(const QList<std::pair<int, TextStyle>> &categories);
- void reformatBlocks(int from, int charsRemoved, int charsAdded);
void delayedRehighlight();
QScopedPointer<SyntaxHighlighterPrivate> d_ptr;
+ std::atomic<bool> m_interrupted = false;
#ifdef WITH_TESTS
friend class tst_highlighter;
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.cpp b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
index 228b866849..874f8254ab 100644
--- a/src/plugins/texteditor/syntaxhighlighterrunner.cpp
+++ b/src/plugins/texteditor/syntaxhighlighterrunner.cpp
@@ -35,11 +35,11 @@ public:
if (async) {
m_document = new QTextDocument(this);
m_document->setDocumentLayout(new TextDocumentLayout(m_document));
- m_highlighter->setParent(m_document);
} else {
m_document = document;
}
+ m_highlighter->setParent(m_document);
m_highlighter->setDocument(m_document);
connect(m_highlighter,
@@ -66,45 +66,104 @@ public:
void setExtraFormats(const QMap<int, QList<QTextLayout::FormatRange>> &formatMap)
{
+ QTC_ASSERT(m_highlighter, return);
for (auto it = formatMap.cbegin(); it != formatMap.cend(); ++it)
m_highlighter->setExtraFormats(m_document->findBlockByNumber(it.key()), it.value());
}
void clearExtraFormats(const QList<int> &blockNumbers)
{
+ QTC_ASSERT(m_highlighter, return);
for (auto it = blockNumbers.cbegin(); it != blockNumbers.cend(); ++it)
m_highlighter->clearExtraFormats(m_document->findBlockByNumber(*it));
}
- void clearAllExtraFormats() { m_highlighter->clearAllExtraFormats(); }
+ void clearAllExtraFormats()
+ {
+ QTC_ASSERT(m_highlighter, return);
+ m_highlighter->clearAllExtraFormats();
+ }
void setFontSettings(const TextEditor::FontSettings &fontSettings)
{
+ QTC_ASSERT(m_highlighter, return);
m_highlighter->setFontSettings(fontSettings);
- rehighlight();
}
void setDefinitionName(const QString &name)
{
- return m_highlighter->setDefinitionName(name);
+ QTC_ASSERT(m_highlighter, return);
+ m_highlighter->setDefinitionName(name);
}
void setLanguageFeaturesFlags(unsigned int flags)
{
+ QTC_ASSERT(m_highlighter, return);
m_highlighter->setLanguageFeaturesFlags(flags);
}
- void setEnabled(bool enabled) { m_highlighter->setEnabled(enabled); }
+ void setEnabled(bool enabled)
+ {
+ QTC_ASSERT(m_highlighter, return);
+ m_highlighter->setEnabled(enabled);
+ }
- void rehighlight() { m_highlighter->rehighlight(); }
+ void rehighlight()
+ {
+ QTC_ASSERT(m_highlighter, return);
+ m_highlighter->rehighlight();
+ }
- SyntaxHighlighter *m_highlighter = nullptr;
+ void reformatBlocks(int from, int charsRemoved, int charsAdded)
+ {
+ QTC_ASSERT(m_highlighter, return);
+ m_highlighter->reformatBlocks(from, charsRemoved, charsAdded);
+ }
+
+ void setInterrupted(bool interrupted)
+ {
+ QTC_ASSERT(m_highlighter, return);
+ m_highlighter->setInterrupted(interrupted);
+ }
+
+ QPointer<SyntaxHighlighter> m_highlighter = nullptr;
QTextDocument *m_document = nullptr;
+
signals:
void resultsReady(const QList<SyntaxHighlighter::Result> &result);
};
+void SyntaxHighlighterRunner::HighlightingStatus::notInterrupted(int from,
+ int charsRemoved,
+ int charsAdded)
+{
+ m_from = from;
+ m_addedChars = charsAdded;
+ m_removedChars = charsRemoved;
+ m_current = from;
+ m_newFrom = from + m_addedChars;
+ m_interruptionRequested = false;
+}
+
+void SyntaxHighlighterRunner::HighlightingStatus::interrupted(int from,
+ int charsRemoved,
+ int charsAdded)
+{
+ m_newFrom = std::min(m_newFrom, from);
+ m_newFrom = std::min(m_current, m_newFrom);
+ m_removedChars += charsRemoved;
+ m_addedChars += charsAdded;
+ m_interruptionRequested = true;
+}
+
+void SyntaxHighlighterRunner::HighlightingStatus::applyNewFrom()
+{
+ m_from = m_newFrom;
+ m_current = m_newFrom;
+ m_interruptionRequested = false;
+}
+
SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
QTextDocument *document,
bool async)
@@ -124,8 +183,8 @@ SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
this,
&SyntaxHighlighterRunner::applyFormatRanges);
- changeDocument(0, 0, document->characterCount());
- connect(document,
+ changeDocument(0, 0, m_document->characterCount());
+ connect(m_document,
&QTextDocument::contentsChange,
this,
&SyntaxHighlighterRunner::changeDocument);
@@ -136,10 +195,15 @@ SyntaxHighlighterRunner::SyntaxHighlighterRunner(SyntaxHighlighter *highlighter,
&SyntaxHighlighterRunnerPrivate::resultsReady,
this,
[this](const QList<SyntaxHighlighter::Result> &result) {
+ if (result.size() == 1
+ && result.at(0).m_state == SyntaxHighlighter::State::Extras)
+ return;
+
auto done = std::find_if(result.cbegin(),
result.cend(),
[](const SyntaxHighlighter::Result &res) {
- return res.m_state == SyntaxHighlighter::State::Done;
+ return res.m_state
+ == SyntaxHighlighter::State::Done;
});
if (done != result.cend()) {
m_syntaxInfoUpdated = SyntaxHighlighter::State::Done;
@@ -158,7 +222,6 @@ SyntaxHighlighterRunner::~SyntaxHighlighterRunner()
m_thread->quit();
m_thread->wait();
} else {
- delete d->m_highlighter;
delete d;
}
}
@@ -168,6 +231,34 @@ void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::R
if (m_document == nullptr)
return;
+ if (m_highlightingStatus.m_interruptionRequested) {
+ d->setInterrupted(false);
+ m_highlightingStatus.applyNewFrom();
+ reformatBlocks(m_highlightingStatus.m_newFrom,
+ m_highlightingStatus.m_removedChars,
+ m_highlightingStatus.m_addedChars);
+ return;
+ }
+
+ auto processResult = [this](SyntaxHighlighter::Result result, QTextBlock docBlock) {
+ if (!docBlock.isValid())
+ return;
+
+ result.copyToBlock(docBlock);
+ m_highlightingStatus.m_current = docBlock.position() + docBlock.length() - 1;
+
+ if (result.m_formatRanges != docBlock.layout()->formats()) {
+ docBlock.layout()->setFormats(result.m_formatRanges);
+ m_document->markContentsDirty(docBlock.position(), docBlock.length());
+ }
+ };
+
+ if (results.size() == 1 && results.at(0).m_state == SyntaxHighlighter::State::Extras) {
+ QTextBlock docBlock = m_document->findBlockByNumber(results.at(0).m_blockNumber);
+ processResult(results.at(0), docBlock);
+ return;
+ }
+
for (const SyntaxHighlighter::Result &result : results) {
m_syntaxInfoUpdated = result.m_state;
if (m_syntaxInfoUpdated == SyntaxHighlighter::State::Start) {
@@ -180,25 +271,18 @@ void SyntaxHighlighterRunner::applyFormatRanges(const QList<SyntaxHighlighter::R
return;
}
- QTextBlock docBlock = m_document->findBlock(result.m_blockNumber);
- if (!docBlock.isValid())
- return;
-
- result.copyToBlock(docBlock);
-
- if (result.m_formatRanges != docBlock.layout()->formats()) {
- docBlock.layout()->setFormats(result.m_formatRanges);
- m_document->markContentsDirty(docBlock.position(), docBlock.length());
- }
- if (m_syntaxInfoUpdated != SyntaxHighlighter::State::Extras)
- m_foldValidator.process(docBlock);
+ QTextBlock docBlock = m_document->findBlockByNumber(result.m_blockNumber);
+ processResult(result, docBlock);
+ m_foldValidator.process(docBlock);
}
}
void SyntaxHighlighterRunner::changeDocument(int from, int charsRemoved, int charsAdded)
{
QTC_ASSERT(m_document, return);
+ SyntaxHighlighter::State prevSyntaxInfoUpdated = m_syntaxInfoUpdated;
m_syntaxInfoUpdated = SyntaxHighlighter::State::InProgress;
+
QMap<int, BlockPreeditData> blocksPreedit;
QTextBlock block = m_document->findBlock(from);
const QTextBlock endBlock = m_document->findBlock(from + charsAdded);
@@ -213,6 +297,14 @@ void SyntaxHighlighterRunner::changeDocument(int from, int charsRemoved, int cha
QMetaObject::invokeMethod(d, [this, from, charsRemoved, text, blocksPreedit] {
d->changeDocument(from, charsRemoved, text, blocksPreedit);
});
+
+ if (prevSyntaxInfoUpdated == SyntaxHighlighter::State::InProgress) {
+ m_highlightingStatus.interrupted(from, charsRemoved, charsAdded);
+ d->setInterrupted(true);
+ } else {
+ m_highlightingStatus.notInterrupted(from, charsRemoved, charsAdded);
+ d->setInterrupted(false);
+ }
}
bool SyntaxHighlighterRunner::useGenericHighlighter() const
@@ -239,6 +331,7 @@ void SyntaxHighlighterRunner::clearAllExtraFormats()
void SyntaxHighlighterRunner::setFontSettings(const TextEditor::FontSettings &fontSettings)
{
QMetaObject::invokeMethod(d, [this, fontSettings] { d->setFontSettings(fontSettings); });
+ rehighlight();
}
void SyntaxHighlighterRunner::setLanguageFeaturesFlags(unsigned int flags)
@@ -253,7 +346,24 @@ void SyntaxHighlighterRunner::setEnabled(bool enabled)
void SyntaxHighlighterRunner::rehighlight()
{
- QMetaObject::invokeMethod(d, [this] { d->rehighlight(); });
+ if (m_syntaxInfoUpdated == SyntaxHighlighter::State::InProgress) {
+ m_highlightingStatus.interrupted(0, 0, m_document->characterCount());
+ d->setInterrupted(true);
+ } else {
+ m_highlightingStatus.notInterrupted(0, 0, m_document->characterCount());
+ d->setInterrupted(false);
+ QMetaObject::invokeMethod(d, [this] { d->rehighlight(); });
+ }
+}
+
+
+void SyntaxHighlighterRunner::reformatBlocks(int from, int charsRemoved, int charsAdded)
+{
+ QMetaObject::invokeMethod(
+ d,
+ [this, from, charsRemoved, charsAdded] {
+ d->reformatBlocks(from, charsRemoved, charsAdded);
+ });
}
QString SyntaxHighlighterRunner::definitionName()
diff --git a/src/plugins/texteditor/syntaxhighlighterrunner.h b/src/plugins/texteditor/syntaxhighlighterrunner.h
index 5540bd666a..16b7c1535c 100644
--- a/src/plugins/texteditor/syntaxhighlighterrunner.h
+++ b/src/plugins/texteditor/syntaxhighlighterrunner.h
@@ -34,6 +34,7 @@ public:
void setLanguageFeaturesFlags(unsigned int flags);
void setEnabled(bool enabled);
void rehighlight();
+ void reformatBlocks(int from, int charsRemoved, int charsAdded);
QString definitionName();
void setDefinitionName(const QString &name);
@@ -53,6 +54,21 @@ private:
SyntaxHighlighterRunnerPrivate *d;
QPointer<QTextDocument> m_document = nullptr;
SyntaxHighlighter::State m_syntaxInfoUpdated = SyntaxHighlighter::State::Done;
+
+ struct HighlightingStatus
+ {
+ int m_from = 0;
+ int m_addedChars = 0;
+ int m_current = 0;
+ int m_removedChars = 0;
+ int m_newFrom = 0;
+ bool m_interruptionRequested = false;
+
+ void notInterrupted(int from, int charsRemoved, int charsAdded);
+ void interrupted(int from, int charsRemoved, int charsAdded);
+ void applyNewFrom();
+ } m_highlightingStatus;
+
bool m_useGenericHighlighter = false;
QString m_definitionName;
std::optional<QThread> m_thread;
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index cb421f2bf7..2636ad46e2 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -914,19 +914,23 @@ bool TextDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type
void TextDocument::resetSyntaxHighlighter(const std::function<SyntaxHighlighter *()> &creator,
bool threaded)
{
- if (d->m_highlighterRunner)
- delete d->m_highlighterRunner;
+ delete d->m_highlighterRunner;
- static const bool envValue
- = qtcEnvironmentVariable("QTC_USE_THREADED_HIGHLIGHTER", "TRUE").toUpper()
- == QLatin1String("TRUE");
+ static const std::optional<bool> envValue = []() -> std::optional<bool> {
+ const QString key("QTC_USE_THREADED_HIGHLIGHTER");
+ if (qtcEnvironmentVariableIsSet(key)) {
+ const QString value = qtcEnvironmentVariable(key).toUpper();
+ return value != "FALSE" && value != "0";
+ }
+ return {};
+ }();
SyntaxHighlighter *highlighter = creator();
highlighter->setFontSettings(TextEditorSettings::fontSettings());
highlighter->setMimeType(mimeType());
d->m_highlighterRunner = new SyntaxHighlighterRunner(highlighter,
document(),
- threaded && envValue);
+ envValue.value_or(threaded));
}
void TextDocument::cleanWhitespace(const QTextCursor &cursor)
diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h
index ad3fe262e2..5879d9e9ec 100644
--- a/src/plugins/texteditor/textdocument.h
+++ b/src/plugins/texteditor/textdocument.h
@@ -127,7 +127,7 @@ public:
QTextDocument *document() const;
using SyntaxHighLighterCreator = std::function<SyntaxHighlighter *()>;
- void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator, bool threaded = true);
+ void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator, bool threaded = false);
SyntaxHighlighterRunner *syntaxHighlighterRunner() const;
bool reload(QString *errorString, QTextCodec *codec);
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 054e65193f..3256ee91b7 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -4154,10 +4154,17 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, co
l = match.capturedLength();
if (l == 0)
break;
- if ((m_findFlags & FindWholeWords)
- && ((idx && text.at(idx-1).isLetterOrNumber())
- || (idx + l < text.length() && text.at(idx + l).isLetterOrNumber())))
- continue;
+ if (m_findFlags & FindWholeWords) {
+ auto posAtWordSeparator = [](const QString &text, int idx) {
+ if (idx < 0 || idx >= text.length())
+ return false;
+ const QChar c = text.at(idx);
+ return !c.isLetterOrNumber() && c != QLatin1Char('_');
+ };
+ if (!posAtWordSeparator(text, idx - 1) || !posAtWordSeparator(text, idx + l))
+ continue;
+ }
+
const int start = blockPosition + idx;
const int end = start + l;