From 68304272a26c12b7d72fa3d95a732471341e3d15 Mon Sep 17 00:00:00 2001 From: nerix Date: Sun, 3 Nov 2024 19:23:53 +0100 Subject: [PATCH] fix: handle multiline selection starting at trailing space (#5691) --- CHANGELOG.md | 1 + .../layouts/MessageLayoutContainer.cpp | 38 ++++++++++++------- .../layouts/MessageLayoutContainer.hpp | 7 +++- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eea64131..ee859fad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ - Bugfix: Fixed emotes starting with ":" not tab-completing. (#5603) - Bugfix: Fixed 7TV emotes messing with Qt's HTML. (#5677) - Bugfix: Fixed incorrect messages getting replaced visually. (#5683) +- Bugfix: Fixed rendering of multi-line selection that starts at a trailing space. (#5691) - Dev: Update Windows build from Qt 6.5.0 to Qt 6.7.1. (#5420) - Dev: Update vcpkg build Qt from 6.5.0 to 6.7.0, boost from 1.83.0 to 1.85.0, openssl from 3.1.3 to 3.3.0. (#5422) - Dev: Unsingletonize `ISoundController`. (#5462) diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index dbf04fb77..20569a8b8 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -854,6 +854,18 @@ std::optional MessageLayoutContainer::paintSelectionStart( { const auto selectionColor = getTheme()->messages.selection; + auto paintRemainingLines = [&](size_t startIndex) { + for (size_t i = startIndex; i < this->lines_.size(); i++) + { + const auto &line = this->lines_[i]; + auto left = this->elements_[line.startIndex]->getRect().left(); + auto right = this->elements_[line.endIndex - 1]->getRect().right(); + + this->paintSelectionRect(painter, line, left, right, yOffset, + selectionColor); + } + }; + // The selection starts in this message for (size_t lineIndex = 0; lineIndex < this->lines_.size(); lineIndex++) { @@ -874,7 +886,17 @@ std::optional MessageLayoutContainer::paintSelectionStart( auto right = this->elements_[line.endIndex - 1]->getRect().right(); this->paintSelectionRect(painter, line, right, right, yOffset, selectionColor); - return std::nullopt; + + if (selection.selectionMax.messageIndex != messageIndex) + { + // The selection does not end in this message + paintRemainingLines(lineIndex + 1); + + return std::nullopt; + } + + // The selection starts in this line, but ends in some next line or message + return {lineIndex + 1}; } int x = this->elements_[line.startIndex]->getRect().left(); @@ -923,21 +945,9 @@ std::optional MessageLayoutContainer::paintSelectionStart( if (selection.selectionMax.messageIndex != messageIndex) { // The selection does not end in this message - for (size_t lineIndex2 = lineIndex + 1; - lineIndex2 < this->lines_.size(); lineIndex2++) - { - const auto &line2 = this->lines_[lineIndex2]; - auto left = - this->elements_[line2.startIndex]->getRect().left(); - auto right = - this->elements_[line2.endIndex - 1]->getRect().right(); - - this->paintSelectionRect(painter, line2, left, right, - yOffset, selectionColor); - } - this->paintSelectionRect(painter, line, x, r, yOffset, selectionColor); + paintRemainingLines(lineIndex + 1); return std::nullopt; } diff --git a/src/messages/layouts/MessageLayoutContainer.hpp b/src/messages/layouts/MessageLayoutContainer.hpp index 1cd7f6af2..e59e53922 100644 --- a/src/messages/layouts/MessageLayoutContainer.hpp +++ b/src/messages/layouts/MessageLayoutContainer.hpp @@ -283,7 +283,12 @@ private: /** * Paint the selection start * - * Returns a line index if this message should also paint the selection end + * @returns A line index if the selection ends within this message but start + * and end are on different lines. The returned index is the index + * of the first line where the selection starts at the beginning of + * the line. This index should be passed to paintSelectionEnd(). + * If `std::nullopt` is returned, no further call to + * paintSelectionEnd() is necessary. */ std::optional paintSelectionStart(QPainter &painter, size_t messageIndex,