aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Schulz <[email protected]>2025-06-02 12:58:51 +0200
committerDavid Schulz <[email protected]>2025-06-02 13:49:58 +0000
commit1e4f53d39918b549f4c492a46a5943d466b3e643 (patch)
treed054a591c1fe366eb95e234f8476fa091ef4f5a3
parent4af4b98f583ac160c40c3c91ef5b02f3722dcdfb (diff)
Editor: optimize highlighting selected textv17.0.0-rc1
Use the same boundary check as in highlightSearchResults to avoid adding highlights outside of the visible area of the viewport. Fixes: QTCREATORBUG-33002 Change-Id: If48fb9cee7f881cccf9bb95a5aaa5427f323ed80 Reviewed-by: Eike Ziller <[email protected]>
-rw-r--r--src/plugins/texteditor/texteditor.cpp39
1 files changed, 36 insertions, 3 deletions
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 4a1a0a0742d..6c9ef0c82cd 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -977,7 +977,7 @@ public:
QString m_findText;
FindFlags m_findFlags;
void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const;
- void highlightSelection(const QTextBlock &block) const;
+ void highlightSelection(const QTextBlock &block, const PaintEventData &data) const;
QTimer m_delayedUpdateTimer;
void setExtraSelections(Utils::Id kind, const QList<QTextEdit::ExtraSelection> &selections);
@@ -5175,7 +5175,7 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, co
}
}
-void TextEditorWidgetPrivate::highlightSelection(const QTextBlock &block) const
+void TextEditorWidgetPrivate::highlightSelection(const QTextBlock &block, const PaintEventData &data) const
{
if (!m_displaySettings.m_highlightSelection || m_cursors.hasMultipleCursors())
return;
@@ -5189,11 +5189,44 @@ void TextEditorWidgetPrivate::highlightSelection(const QTextBlock &block) const
text.replace(QChar::Nbsp, QLatin1Char(' '));
const int l = selection.length();
+ const int left = data.viewportRect.left() - int(data.offset.x());
+ const int right = data.viewportRect.right() - int(data.offset.x());
+ const int top = data.viewportRect.top() - int(data.offset.y());
+ const int bottom = data.viewportRect.bottom() - int(data.offset.y());
+
for (int idx = text.indexOf(selection, 0, Qt::CaseInsensitive);
idx >= 0;
idx = text.indexOf(selection, idx + 1, Qt::CaseInsensitive)) {
const int start = blockPosition + idx;
const int end = start + l;
+
+ // check if the result is inside the visible area for long blocks
+ const QTextLine &startLine = block.layout()->lineForTextPosition(idx);
+ const QTextLine &endLine = block.layout()->lineForTextPosition(idx + l);
+
+ if (startLine.isValid() && endLine.isValid()
+ && startLine.lineNumber() == endLine.lineNumber()) {
+ const int lineY = int(endLine.y() + q->blockBoundingGeometry(block).y());
+ if (startLine.cursorToX(idx) > right) { // result is behind the visible area
+ if (endLine.lineNumber() >= block.lineCount() - 1)
+ break; // this is the last line in the block, nothing more to add
+
+ // skip to the start of the next line
+ idx = block.layout()->lineAt(endLine.lineNumber() + 1).textStart();
+ continue;
+ } else if (endLine.cursorToX(idx + l, QTextLine::Trailing) < left) { // result is in front of the visible area skip it
+ continue;
+ } else if (lineY + endLine.height() < top) {
+ if (endLine.lineNumber() >= block.lineCount() - 1)
+ break; // this is the last line in the block, nothing more to add
+ // before visible area, skip to the start of the next line
+ idx = block.layout()->lineAt(endLine.lineNumber() + 1).textStart();
+ continue;
+ } else if (lineY > bottom) {
+ break; // under the visible area, nothing more to add
+ }
+ }
+
if (!Utils::contains(m_selectionHighlightOverlay->selections(),
[&](const OverlaySelection &selection) {
return selection.m_cursor_begin.position() == start
@@ -5679,7 +5712,7 @@ void TextEditorWidgetPrivate::paintSelectionOverlay(const PaintEventData &data,
if (blockBoundingRect.bottom() >= data.eventRect.top() - margin
&& blockBoundingRect.top() <= data.eventRect.bottom() + margin) {
- highlightSelection(block);
+ highlightSelection(block, data);
}
offset.ry() += blockBoundingRect.height();