diff options
author | Tim Jenssen <tim.jenssen@qt.io> | 2024-03-11 18:02:37 +0100 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2024-03-11 17:18:48 +0000 |
commit | e7e9a58e46482142de3028cba2b9f3646542258d (patch) | |
tree | ce1317817015e5e1f765f013a563ffc80eee6763 /src/plugins/texteditor | |
parent | 09b00446b788063f1c821581cfa8a03800e71629 (diff) | |
parent | 3af6f65ebc06ea52001e459c09179680dfa41d1a (diff) |
Merge remote-tracking branch 'origin/13.0' into qds/dev
Change-Id: I8cd3cdf5854299d3017d6c6bfa656fc483a0e20b
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r-- | src/plugins/texteditor/icodestylepreferences.cpp | 11 | ||||
-rw-r--r-- | src/plugins/texteditor/icodestylepreferences.h | 3 | ||||
-rw-r--r-- | src/plugins/texteditor/syntaxhighlighter.cpp | 15 | ||||
-rw-r--r-- | src/plugins/texteditor/syntaxhighlighter.h | 11 | ||||
-rw-r--r-- | src/plugins/texteditor/syntaxhighlighterrunner.cpp | 158 | ||||
-rw-r--r-- | src/plugins/texteditor/syntaxhighlighterrunner.h | 16 | ||||
-rw-r--r-- | src/plugins/texteditor/textdocument.cpp | 16 | ||||
-rw-r--r-- | src/plugins/texteditor/textdocument.h | 2 | ||||
-rw-r--r-- | src/plugins/texteditor/texteditor.cpp | 15 |
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; |