diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme index e5b312ed159..7cd5888e15e 100644 --- a/share/qtcreator/themes/dark.creatortheme +++ b/share/qtcreator/themes/dark.creatortheme @@ -432,6 +432,7 @@ VcsBase_FileUnmerged_TextColor=ffff4040 Bookmarks_TextMarkColor=ff8080ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ff888888 TextEditor_CurrentLine_ScrollBarColor=ffffffff ProjectExplorer_TaskError_TextMarkColor=error diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme index 241502d1e53..d47e0df1a68 100644 --- a/share/qtcreator/themes/default.creatortheme +++ b/share/qtcreator/themes/default.creatortheme @@ -424,6 +424,7 @@ VcsBase_FileUnmerged_TextColor=ffee0000 Bookmarks_TextMarkColor=ffa0a0ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ffcccccc TextEditor_CurrentLine_ScrollBarColor=ff404040 ProjectExplorer_TaskError_TextMarkColor=error diff --git a/share/qtcreator/themes/design-light.creatortheme b/share/qtcreator/themes/design-light.creatortheme index 5c9a0c6277a..9e1e86d3188 100644 --- a/share/qtcreator/themes/design-light.creatortheme +++ b/share/qtcreator/themes/design-light.creatortheme @@ -437,6 +437,7 @@ VcsBase_FileUnmerged_TextColor=ffee0000 Bookmarks_TextMarkColor=ffa0a0ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ffcccccc TextEditor_CurrentLine_ScrollBarColor=ff404040 ProjectExplorer_TaskError_TextMarkColor=error diff --git a/share/qtcreator/themes/design.creatortheme b/share/qtcreator/themes/design.creatortheme index 6abbcc5de49..cc2499c6e72 100644 --- a/share/qtcreator/themes/design.creatortheme +++ b/share/qtcreator/themes/design.creatortheme @@ -440,6 +440,7 @@ VcsBase_FileUnmerged_TextColor=ffff4040 Bookmarks_TextMarkColor=ff8080ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ff888888 TextEditor_CurrentLine_ScrollBarColor=ffffffff ProjectExplorer_TaskError_TextMarkColor=error diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme index d015c149f0b..b384c8f7baf 100644 --- a/share/qtcreator/themes/flat-dark.creatortheme +++ b/share/qtcreator/themes/flat-dark.creatortheme @@ -436,6 +436,7 @@ VcsBase_FileUnmerged_TextColor=ffff4040 Bookmarks_TextMarkColor=ff8080ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ff888888 TextEditor_CurrentLine_ScrollBarColor=ffffffff ProjectExplorer_TaskError_TextMarkColor=error diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme index 21ded057ece..1afd27f2888 100644 --- a/share/qtcreator/themes/flat-light.creatortheme +++ b/share/qtcreator/themes/flat-light.creatortheme @@ -433,6 +433,7 @@ VcsBase_FileUnmerged_TextColor=ffee0000 Bookmarks_TextMarkColor=ffa0a0ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ffcccccc TextEditor_CurrentLine_ScrollBarColor=ff404040 ProjectExplorer_TaskError_TextMarkColor=error diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme index 6dc677d9ff3..e1bda7b18a3 100644 --- a/share/qtcreator/themes/flat.creatortheme +++ b/share/qtcreator/themes/flat.creatortheme @@ -431,6 +431,7 @@ VcsBase_FileUnmerged_TextColor=ffee0000 Bookmarks_TextMarkColor=ffa0a0ff TextEditor_SearchResult_ScrollBarColor=ff00c000 +TextEditor_Selection_ScrollBarColor=ffcccccc TextEditor_CurrentLine_ScrollBarColor=ff404040 ProjectExplorer_TaskError_TextMarkColor=error diff --git a/src/libs/utils/textutils.cpp b/src/libs/utils/textutils.cpp index f8ada6cca68..31fd1b84640 100644 --- a/src/libs/utils/textutils.cpp +++ b/src/libs/utils/textutils.cpp @@ -15,6 +15,17 @@ bool Position::operator==(const Position &other) const return line == other.line && column == other.column; } +int Position::positionInDocument(QTextDocument *doc) const +{ + if (!isValid()) + return -1; + QTC_ASSERT(doc, return -1); + QTextBlock block = doc->findBlockByNumber(line - 1); + if (!block.isValid()) + return -1; + return block.position() + column; +} + /*! Returns the text position of a \a fileName and sets the \a postfixPos if it can find a positional postfix. @@ -107,6 +118,14 @@ bool Range::operator==(const Range &other) const return begin == other.begin && end == other.end; } +QTextCursor Range::toTextCursor(QTextDocument *doc) const +{ + QTextCursor cursor(doc); + cursor.setPosition(begin.positionInDocument(doc)); + cursor.setPosition(end.positionInDocument(doc), QTextCursor::KeepAnchor); + return cursor; +} + bool convertPosition(const QTextDocument *document, int pos, int *line, int *column) { QTextBlock block = document->findBlock(pos); diff --git a/src/libs/utils/textutils.h b/src/libs/utils/textutils.h index d21ca20d4d9..b96a84eec32 100644 --- a/src/libs/utils/textutils.h +++ b/src/libs/utils/textutils.h @@ -30,6 +30,8 @@ public: bool isValid() const { return line > 0 && column >= 0; } + int positionInDocument(QTextDocument *doc) const; + static Position fromFileName(QStringView fileName, int &postfixPos); static Position fromPositionInDocument(const QTextDocument *document, int pos); static Position fromCursor(const QTextCursor &cursor); @@ -49,6 +51,8 @@ public: bool operator==(const Range &other) const; bool operator!=(const Range &other) const { return !(operator==(other)); } + + QTextCursor toTextCursor(QTextDocument *doc) const; }; // line is 1-based, column is 0-based diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h index 0dbdb61fbe4..c7bf0a5f3af 100644 --- a/src/libs/utils/theme/theme.h +++ b/src/libs/utils/theme/theme.h @@ -259,6 +259,7 @@ public: /* TextEditor Plugin */ TextEditor_SearchResult_ScrollBarColor, + TextEditor_Selection_ScrollBarColor, TextEditor_CurrentLine_ScrollBarColor, /* Debugger Plugin */ diff --git a/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp index 47a857b26af..adaceda64d2 100644 --- a/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp +++ b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp @@ -4,6 +4,7 @@ #include "highlightscrollbarcontroller.h" #include +#include #include #include #include @@ -12,6 +13,8 @@ using namespace Utils; +static Q_LOGGING_CATEGORY(LOG, "qtc.utils.highlightscrollbar", QtWarningMsg) + namespace Core { /*! @@ -403,6 +406,7 @@ void HighlightScrollBarController::addHighlight(Highlight highlight) if (!m_overlay) return; + qCDebug(LOG) << "addHighlight" << highlight.category.toString() << highlight.position; m_highlights[highlight.category] << highlight; m_overlay->scheduleUpdate(); } @@ -412,6 +416,7 @@ void HighlightScrollBarController::removeHighlights(Id category) if (!m_overlay) return; + qCDebug(LOG) << "removeHighlights" << category.toString(); m_highlights.remove(category); m_overlay->scheduleUpdate(); } @@ -421,6 +426,7 @@ void HighlightScrollBarController::removeAllHighlights() if (!m_overlay) return; + qCDebug(LOG) << "removeAllHighlights"; m_highlights.clear(); m_overlay->scheduleUpdate(); } diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp index 5cd8e86c151..fac753b5943 100644 --- a/src/plugins/texteditor/displaysettings.cpp +++ b/src/plugins/texteditor/displaysettings.cpp @@ -37,6 +37,7 @@ const char animateWithinFileTimeMaxKey[] = "AnimateWithinFileTimeMax"; const char displayAnnotationsKey[] = "DisplayAnnotations"; const char annotationAlignmentKey[] = "AnnotationAlignment"; const char minimalAnnotationContentKey[] = "MinimalAnnotationContent"; +const char highlightSelectionKey[] = "HighlightSelection"; const char groupPostfix[] = "textDisplaySettings"; void DisplaySettings::toSettings(QtcSettings *s) const @@ -61,6 +62,7 @@ void DisplaySettings::toSettings(QtcSettings *s) const s->setValue(animateNavigationWithinFileKey, m_animateNavigationWithinFile); s->setValue(displayAnnotationsKey, m_displayAnnotations); s->setValue(annotationAlignmentKey, static_cast(m_annotationAlignment)); + s->setValue(highlightSelectionKey, m_highlightSelection); s->endGroup(); } @@ -92,6 +94,7 @@ void DisplaySettings::fromSettings(QtcSettings *s) s->value(annotationAlignmentKey, static_cast(m_annotationAlignment)).toInt()); m_minimalAnnotationContent = s->value(minimalAnnotationContentKey, m_minimalAnnotationContent).toInt(); + m_highlightSelection = s->value(highlightSelectionKey, m_highlightSelection).toBool(); s->endGroup(); } @@ -119,6 +122,7 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const && m_displayAnnotations == ds.m_displayAnnotations && m_annotationAlignment == ds.m_annotationAlignment && m_minimalAnnotationContent == ds.m_minimalAnnotationContent + && m_highlightSelection == ds.m_highlightSelection ; } diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h index 1c8a27f037d..bb42a9ac935 100644 --- a/src/plugins/texteditor/displaysettings.h +++ b/src/plugins/texteditor/displaysettings.h @@ -52,6 +52,7 @@ public: bool m_displayFileLineEnding = true; bool m_scrollBarHighlights = true; bool m_animateNavigationWithinFile = false; + bool m_highlightSelection = true; int m_animateWithinFileTimeMax = 333; // read only setting bool m_displayAnnotations = true; AnnotationAlignment m_annotationAlignment = AnnotationAlignment::RightSide; diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp index 2449618bf05..e46c5b7c5b4 100644 --- a/src/plugins/texteditor/displaysettingspage.cpp +++ b/src/plugins/texteditor/displaysettingspage.cpp @@ -98,6 +98,10 @@ public: visualizeWhitespace = new QCheckBox(Tr::tr("&Visualize whitespace")); visualizeWhitespace->setToolTip(Tr::tr("Shows tabs and spaces.")); + highlightSelection = new QCheckBox(Tr::tr("&Highlight Selection")); + highlightSelection->setToolTip(Tr::tr("Adds a colored background and a marker to the " + "scrollbar to occurrences of the selected text.")); + leftAligned = new QRadioButton(Tr::tr("Next to editor content")); atMargin = new QRadioButton(Tr::tr("Next to right margin")); rightAligned = new QRadioButton(Tr::tr("Aligned at right side")); @@ -143,6 +147,7 @@ public: autoFoldFirstComment, scrollBarHighlights, animateNavigationWithinFile, + highlightSelection, }, Column { highlightCurrentLine, @@ -195,6 +200,7 @@ public: QCheckBox *openLinksInNextSplit; QCheckBox *highlightMatchingParentheses; QCheckBox *visualizeWhitespace; + QCheckBox *highlightSelection; QGroupBox *displayAnnotations; QRadioButton *leftAligned; QRadioButton *atMargin; @@ -238,6 +244,7 @@ void DisplaySettingsWidget::settingsFromUI(DisplaySettings &displaySettings, displaySettings.m_scrollBarHighlights = scrollBarHighlights->isChecked(); displaySettings.m_animateNavigationWithinFile = animateNavigationWithinFile->isChecked(); displaySettings.m_displayAnnotations = displayAnnotations->isChecked(); + displaySettings.m_highlightSelection = highlightSelection->isChecked(); if (leftAligned->isChecked()) displaySettings.m_annotationAlignment = AnnotationAlignment::NextToContent; else if (atMargin->isChecked()) @@ -276,6 +283,7 @@ void DisplaySettingsWidget::settingsToUI() scrollBarHighlights->setChecked(displaySettings.m_scrollBarHighlights); animateNavigationWithinFile->setChecked(displaySettings.m_animateNavigationWithinFile); displayAnnotations->setChecked(displaySettings.m_displayAnnotations); + highlightSelection->setChecked(displaySettings.m_highlightSelection); switch (displaySettings.m_annotationAlignment) { case AnnotationAlignment::NextToContent: leftAligned->setChecked(true); break; case AnnotationAlignment::NextToMargin: atMargin->setChecked(true); break; diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 3556a08caa0..2a133673afd 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -79,6 +79,13 @@ public: IAssistProvider *m_quickFixProvider = nullptr; QScopedPointer m_indenter; QScopedPointer m_formatter; + struct PlainTextCache + { + int revision = -1; + QString plainText; + }; + + PlainTextCache m_plainTextCache; int m_autoSaveRevision = -1; bool m_silentReload = false; @@ -305,7 +312,11 @@ QString TextDocument::convertToPlainText(const QString &rawText) QString TextDocument::plainText() const { - return convertToPlainText(d->m_document.toRawText()); + if (d->m_plainTextCache.revision != d->m_document.revision()) { + d->m_plainTextCache.plainText = convertToPlainText(d->m_document.toRawText()); + d->m_plainTextCache.revision = d->m_document.revision(); + } + return d->m_plainTextCache.plainText; } QString TextDocument::textAt(int pos, int length) const diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 70265e14a47..a667e29fbaa 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -605,6 +605,7 @@ public: void paintRightMarginLine(const PaintEventData &data, QPainter &painter) const; void paintBlockHighlight(const PaintEventData &data, QPainter &painter) const; void paintSearchResultOverlay(const PaintEventData &data, QPainter &painter) const; + void paintSelectionOverlay(const PaintEventData &data, QPainter &painter) const; void paintIfDefedOutBlocks(const PaintEventData &data, QPainter &painter) const; void paintFindScope(const PaintEventData &data, QPainter &painter) const; void paintCurrentLineHighlight(const PaintEventData &data, QPainter &painter) const; @@ -690,6 +691,7 @@ public: int length; }; void addSearchResultsToScrollBar(const QVector &results); + void addSelectionHighlightToScrollBar(const QVector &selections); void adjustScrollBarRanges(); void setFindScope(const MultiTextCursor &scope); @@ -766,6 +768,7 @@ public: TextEditorOverlay *m_overlay = nullptr; SnippetOverlay *m_snippetOverlay = nullptr; TextEditorOverlay *m_searchResultOverlay = nullptr; + TextEditorOverlay *m_selectionHighlightOverlay = nullptr; bool snippetCheckCursor(const QTextCursor &cursor); void snippetTabOrBacktab(bool forward); @@ -811,6 +814,7 @@ public: QString m_findText; FindFlags m_findFlags; void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const; + void highlightSelection(const QTextBlock &block) const; QTimer m_delayedUpdateTimer; void setExtraSelections(Utils::Id kind, const QList &selections); @@ -871,7 +875,9 @@ public: CommentDefinition m_commentDefinition; QFuture m_searchFuture; + QFuture m_selectionHighlightFuture; QVector m_searchResults; + QVector m_selectionResults; QTimer m_scrollBarUpdateTimer; HighlightScrollBarController *m_highlightScrollBarController = nullptr; bool m_scrollBarUpdateScheduled = false; @@ -995,6 +1001,7 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent) , m_overlay(new TextEditorOverlay(q)) , m_snippetOverlay(new SnippetOverlay(q)) , m_searchResultOverlay(new TextEditorOverlay(q)) + , m_selectionHighlightOverlay(new TextEditorOverlay(q)) , m_refactorOverlay(new RefactorOverlay(q)) , m_marksVisible(false) , m_codeFoldingVisible(false) @@ -1010,6 +1017,7 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent) , m_clipboardAssistProvider(new ClipboardAssistProvider) , m_autoCompleter(new AutoCompleter) { + m_selectionHighlightOverlay->show(); auto aggregate = new Aggregation::Aggregate; m_find = new TextEditorWidgetFind(q); connect(m_find, &BaseTextFind::highlightAllRequested, @@ -1139,6 +1147,8 @@ TextEditorWidgetPrivate::~TextEditorWidgetPrivate() delete m_highlightScrollBarController; if (m_searchFuture.isRunning()) m_searchFuture.cancel(); + if (m_selectionHighlightFuture.isRunning()) + m_selectionHighlightFuture.cancel(); } static QFrame *createSeparator(const QString &styleSheet) @@ -3346,10 +3356,12 @@ void TextEditorWidgetPrivate::documentAboutToBeReloaded() m_overlay->clear(); m_snippetOverlay->clear(); m_searchResultOverlay->clear(); + m_selectionHighlightOverlay->clear(); m_refactorOverlay->clear(); // clear search results m_searchResults.clear(); + m_selectionResults.clear(); } void TextEditorWidgetPrivate::documentReloadFinished(bool success) @@ -4070,6 +4082,35 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, co } } +void TextEditorWidgetPrivate::highlightSelection(const QTextBlock &block) const +{ + if (!m_displaySettings.m_highlightSelection || m_cursors.hasMultipleCursors()) + return; + const QString selection = m_cursors.selectedText(); + if (selection.trimmed().isEmpty()) + return; + + const int blockPosition = block.position(); + + QString text = block.text(); + text.replace(QChar::Nbsp, QLatin1Char(' ')); + const int l = selection.length(); + + 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; + if (!Utils::contains(m_selectionHighlightOverlay->selections(), + [&](const OverlaySelection &selection) { + return selection.m_cursor_begin.position() == start + && selection.m_cursor_end.position() == end; + })) { + m_selectionHighlightOverlay->addOverlaySelection(start, end, {}, {}); + } + } +} + void TextEditorWidgetPrivate::startCursorFlashTimer() { const int flashTime = QApplication::cursorFlashTime(); @@ -4108,6 +4149,44 @@ void TextEditorWidgetPrivate::updateCursorSelections() selections << QTextEdit::ExtraSelection{cursor, selectionFormat}; } q->setExtraSelections(TextEditorWidget::CursorSelection, selections); + + m_selectionHighlightOverlay->clear(); + + if (m_selectionHighlightFuture.isRunning()) + m_selectionHighlightFuture.cancel(); + + m_selectionResults.clear(); + if (!m_highlightScrollBarController) + return; + m_highlightScrollBarController->removeHighlights(Constants::SCROLL_BAR_SELECTION); + + if (!m_displaySettings.m_highlightSelection || m_cursors.hasMultipleCursors()) + return; + + const QString txt = m_cursors.selectedText(); + if (txt.trimmed().isEmpty()) + return; + + m_selectionHighlightFuture = Utils::asyncRun(Utils::searchInContents, + txt, + FindFlags{}, + m_document->filePath(), + m_document->plainText()); + + Utils::onResultReady(m_selectionHighlightFuture, + this, + [this](const SearchResultItems &resultList) { + QList results; + for (const SearchResultItem &item : resultList) { + int start = item.mainRange().begin.positionInDocument( + m_document->document()); + int end = item.mainRange().end.positionInDocument( + m_document->document()); + results << SearchResult{start, end - start}; + } + m_selectionResults = results; + addSelectionHighlightToScrollBar(results); + }); } void TextEditorWidgetPrivate::moveCursor(QTextCursor::MoveOperation operation, @@ -4489,6 +4568,40 @@ void TextEditorWidgetPrivate::paintSearchResultOverlay(const PaintEventData &dat data.eventRect); } +void TextEditorWidgetPrivate::paintSelectionOverlay(const PaintEventData &data, + QPainter &painter) const +{ + if (m_cursors.hasMultipleCursors()) + return; + const QString expr = m_cursors.selectedText(); + if (expr.isEmpty()) + return; + + const int margin = 5; + QTextBlock block = data.block; + QPointF offset = data.offset; + while (block.isValid()) { + QRectF blockBoundingRect = q->blockBoundingRect(block).translated(offset); + + if (blockBoundingRect.bottom() >= data.eventRect.top() - margin + && blockBoundingRect.top() <= data.eventRect.bottom() + margin) { + highlightSelection(block); + } + offset.ry() += blockBoundingRect.height(); + + if (offset.y() > data.viewportRect.height() + margin) + break; + + block = TextEditor::nextVisibleBlock(block, data.doc); + } + + QColor selection = m_document->fontSettings().toTextCharFormat(C_SELECTION).background().color(); + const QColor text = m_document->fontSettings().toTextCharFormat(C_TEXT).background().color(); + selection.setAlphaF(StyleHelper::luminance(text) > 0.5 ? 0.25 : 0.5); + + m_selectionHighlightOverlay->fill(&painter, selection, data.eventRect); +} + void TextEditorWidgetPrivate::paintIfDefedOutBlocks(const PaintEventData &data, QPainter &painter) const { @@ -5076,6 +5189,8 @@ void TextEditorWidget::paintEvent(QPaintEvent *e) d->paintFindScope(data, painter); // paint search results on top of the find scope d->paintSearchResultOverlay(data, painter); + // paint selection highlights + d->paintSelectionOverlay(data, painter); } while (data.block.isValid()) { @@ -6947,6 +7062,33 @@ void TextEditorWidgetPrivate::addSearchResultsToScrollBar(const QVector &selections) +{ + if (!m_highlightScrollBarController) + return; + for (const SearchResult &result : selections) { + const QTextBlock &block = q->document()->findBlock(result.start); + if (block.isValid() && block.isVisible()) { + if (q->lineWrapMode() == QPlainTextEdit::WidgetWidth) { + const int firstLine = block.layout()->lineForTextPosition(result.start - block.position()).lineNumber(); + const int lastLine = block.layout()->lineForTextPosition(result.start - block.position() + result.length).lineNumber(); + for (int line = firstLine; line <= lastLine; ++line) { + m_highlightScrollBarController->addHighlight( + {Constants::SCROLL_BAR_SELECTION, block.firstLineNumber() + line, + Theme::TextEditor_Selection_ScrollBarColor, Highlight::NormalPriority}); + } + } else { + m_highlightScrollBarController->addHighlight( + {Constants::SCROLL_BAR_SELECTION, + block.blockNumber(), + Theme::TextEditor_Selection_ScrollBarColor, + Highlight::NormalPriority}); + } + } + } +} + Highlight markToHighlight(TextMark *mark, int lineNumber) { return Highlight(mark->category().id, @@ -6968,6 +7110,9 @@ void TextEditorWidgetPrivate::updateHighlightScrollBarNow() // update search results addSearchResultsToScrollBar(m_searchResults); + // update search selection + addSelectionHighlightToScrollBar(m_selectionResults); + // update text marks const TextMarks marks = m_document->marks(); for (TextMark *mark : marks) { @@ -7900,6 +8045,7 @@ void TextEditorWidget::setDisplaySettings(const DisplaySettings &ds) d->updateFileLineEndingVisible(); d->updateHighlights(); d->setupScrollBar(); + d->updateCursorSelections(); viewport()->update(); extraArea()->update(); } diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 4cac6a9dd7f..262ce6a5c45 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -216,6 +216,7 @@ const char JUMP_TO_FILE_UNDER_CURSOR[] = "TextEditor.JumpToFileUnderCursor"; const char JUMP_TO_FILE_UNDER_CURSOR_IN_NEXT_SPLIT[] = "TextEditor.JumpToFileUnderCursorInNextSplit"; const char SCROLL_BAR_SEARCH_RESULT[] = "TextEditor.ScrollBarSearchResult"; +const char SCROLL_BAR_SELECTION[] = "TextEditor.ScrollBarSelection"; const char SCROLL_BAR_CURRENT_LINE[] = "TextEditor.ScrollBarCurrentLine"; const TEXTEDITOR_EXPORT char *nameForStyle(TextStyle style); diff --git a/src/plugins/texteditor/texteditoroverlay.cpp b/src/plugins/texteditor/texteditoroverlay.cpp index c5155008926..ab2e9f1279c 100644 --- a/src/plugins/texteditor/texteditoroverlay.cpp +++ b/src/plugins/texteditor/texteditoroverlay.cpp @@ -82,10 +82,13 @@ void TextEditorOverlay::addOverlaySelection(int begin, int end, if (m_selections.isEmpty()) m_firstSelectionOriginalBegin = begin; - else if (begin < m_firstSelectionOriginalBegin) - qWarning() << "overlay selections not in order"; - m_selections.append(selection); + const auto it = std::find_if(m_selections.cbegin(), + m_selections.cend(), + [&](const OverlaySelection &selection) { + return begin > selection.m_cursor_begin.position(); + }); + m_selections.insert(it, selection); update(); }