From 515c40f8576baa237754e24470fbcf2c94a64a2b Mon Sep 17 00:00:00 2001 From: nerix Date: Sat, 9 Sep 2023 14:09:25 +0200 Subject: [PATCH] Use `QFontMetrics::elidedText` over manual implementation (#4807) --- CHANGELOG.md | 1 + src/messages/MessageElement.cpp | 40 ++++--------------- .../layouts/MessageLayoutContainer.cpp | 11 +++-- .../layouts/MessageLayoutContainer.hpp | 1 + 4 files changed, 17 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9febd055efe..9a994b377e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unversioned +- Bugfix: Fixed a performance issue when displaying replies to certain messages. (#4807) - Bugfix: Fixed a data race when disconnecting from Twitch PubSub. (#4771) - Bugfix: Fixed `/shoutout` command not working with usernames starting with @'s (e.g. `/shoutout @forsen`). (#4800) - Dev: Fixed UTF16 encoding of `modes` file for the installer. (#4791) diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 8f6dd2ccdd0..f69d0b785be 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -674,42 +674,16 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container, auto &parsedWord = parsedWords[0]; if (parsedWord.type() == typeid(QString)) { - int nextWidth = - metrics.horizontalAdvance(currentText + word.text); - - // see if the text fits in the current line - if (container.fitsInLine(nextWidth)) + if (!currentText.isEmpty()) { - currentText += (word.text + " "); + currentText += ' '; } - else + currentText += word.text; + QString prev = currentText; // only increments the ref-count + currentText = metrics.elidedText(currentText, Qt::ElideRight, + container.remainingWidth()); + if (currentText != prev) { - // word overflows, try minimum truncation - bool cutSuccess = false; - for (size_t cut = 1; cut < word.text.length(); ++cut) - { - // Cut off n characters and append the ellipsis. - // Try removing characters one by one until the word fits. - QString truncatedWord = - word.text.chopped(cut) + ellipsis; - int newSize = metrics.horizontalAdvance(currentText + - truncatedWord); - if (container.fitsInLine(newSize)) - { - currentText += (truncatedWord); - - cutSuccess = true; - break; - } - } - - if (!cutSuccess) - { - // We weren't able to show any part of the current word, so - // just append the ellipsis. - currentText += ellipsis; - } - break; } } diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index 0081759703a..f4f832f1efd 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -424,11 +424,16 @@ bool MessageLayoutContainer::atStartOfLine() bool MessageLayoutContainer::fitsInLine(int _width) { - return this->currentX_ + _width <= - (this->width_ - int(this->margin.left * this->scale_) - + return _width <= this->remainingWidth(); +} + +int MessageLayoutContainer::remainingWidth() const +{ + return (this->width_ - int(this->margin.left * this->scale_) - int(this->margin.right * this->scale_) - (this->line_ + 1 == MAX_UNCOLLAPSED_LINES ? this->dotdotdotWidth_ - : 0)); + : 0)) - + this->currentX_; } void MessageLayoutContainer::end() diff --git a/src/messages/layouts/MessageLayoutContainer.hpp b/src/messages/layouts/MessageLayoutContainer.hpp index a6daebb2878..5f4bc2228ff 100644 --- a/src/messages/layouts/MessageLayoutContainer.hpp +++ b/src/messages/layouts/MessageLayoutContainer.hpp @@ -66,6 +66,7 @@ struct MessageLayoutContainer { void breakLine(); bool atStartOfLine(); bool fitsInLine(int width_); + int remainingWidth() const; // this method is called when a message has an RTL word // we need to reorder the words to be shown properly // however we don't we to reorder non-text elements like badges, timestamps, username