diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b4d2fa..5d07d6a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unversioned -- Minor: Added user notes to the user info dialog (when clicking a username). (#6122) +- Minor: Added user notes to the user info dialog (when clicking a username). (#6122, #6318) - Minor: Added cached emotes fallback when fetching from a provider fails. (#6125, #6229) - Minor: Add an option for the reduced opacity of message history. (#6121) - Minor: Make paused chat indicator more visible, and fix its zoom behavior. (#6123) diff --git a/src/widgets/Label.cpp b/src/widgets/Label.cpp index e1fc8fbc..561129ca 100644 --- a/src/widgets/Label.cpp +++ b/src/widgets/Label.cpp @@ -33,6 +33,11 @@ void Label::setText(const QString &text) if (this->text_ != text) { this->text_ = text; + if (this->shouldElide_) + { + this->updateElidedText(this->getFontMetrics(), + this->getInnerWidth()); + } this->updateSize(); this->update(); } @@ -54,14 +59,9 @@ void Label::setCentered(bool centered) this->updateSize(); } -bool Label::getHasOffset() const +void Label::setHasPadding(bool hasPadding) { - return this->hasOffset_; -} - -void Label::setHasOffset(bool hasOffset) -{ - this->hasOffset_ = hasOffset; + this->hasPadding_ = hasPadding; this->updateSize(); } @@ -76,42 +76,59 @@ void Label::setWordWrap(bool wrap) this->update(); } +void Label::setShouldElide(bool shouldElide) +{ + this->shouldElide_ = shouldElide; + this->updateSize(); + this->update(); +} + void Label::setFontStyle(FontStyle style) { this->fontStyle_ = style; this->updateSize(); } -void Label::scaleChangedEvent(float scale) +void Label::scaleChangedEvent(float /*scale*/) { this->updateSize(); } QSize Label::sizeHint() const { - return this->preferedSize_; + return this->sizeHint_; } QSize Label::minimumSizeHint() const { - return this->preferedSize_; + return this->minimumSizeHint_; } -void Label::paintEvent(QPaintEvent *) +void Label::paintEvent(QPaintEvent * /*event*/) { QPainter painter(this); - auto metrics = getApp()->getFonts()->getFontMetrics(this->getFontStyle(), - this->scale()); + auto metrics = this->getFontMetrics(); + painter.setFont( getApp()->getFonts()->getFont(this->getFontStyle(), this->scale())); - int offset = this->getOffset(); + int padding = this->getPadding(); // draw text - QRect textRect(offset, 0, this->width() - offset - offset, this->height()); + QRect textRect(this->getPadding(), 0, + static_cast(this->getInnerWidth()), this->height()); - int width = static_cast(metrics.horizontalAdvance(this->text_)); + auto text = [this] { + if (this->shouldElide_) + { + return this->elidedText_; + } + + return this->text_; + }(); + + int width = static_cast(metrics.horizontalAdvance(text)); Qt::Alignment alignment = !this->centered_ || width > textRect.width() ? Qt::AlignLeft | Qt::AlignVCenter : Qt::AlignCenter; @@ -127,7 +144,7 @@ void Label::paintEvent(QPaintEvent *) { option.setWrapMode(QTextOption::NoWrap); } - painter.drawText(textRect, this->text_, option); + painter.drawText(textRect, text, option); #if 0 painter.setPen(QColor(255, 0, 0)); @@ -135,22 +152,77 @@ void Label::paintEvent(QPaintEvent *) #endif } +void Label::resizeEvent(QResizeEvent *event) +{ + if (this->shouldElide_) + { + auto metrics = this->getFontMetrics(); + if (this->updateElidedText(metrics, this->getInnerWidth())) + { + this->update(); + } + } + + BaseWidget::resizeEvent(event); +} + +QFontMetricsF Label::getFontMetrics() const +{ + return getApp()->getFonts()->getFontMetrics(this->fontStyle_, + this->scale()); +} + +qreal Label::getInnerWidth() const +{ + return this->width() - (2 * this->getPadding()); +} + void Label::updateSize() { - auto metrics = - getApp()->getFonts()->getFontMetrics(this->fontStyle_, this->scale()); + auto metrics = this->getFontMetrics(); - auto width = - metrics.horizontalAdvance(this->text_) + (2 * this->getOffset()); - auto height = metrics.height(); - this->preferedSize_ = QSizeF(width, height).toSize(); + if (this->shouldElide_) + { + auto height = metrics.height(); + this->updateElidedText(metrics, this->getInnerWidth()); + this->sizeHint_ = QSizeF(-1, height).toSize(); + this->minimumSizeHint_ = this->sizeHint_; + } + else + { + auto width = + metrics.horizontalAdvance(this->text_) + (2 * this->getPadding()); + auto height = metrics.height(); + this->sizeHint_ = QSizeF(width, height).toSize(); + this->minimumSizeHint_ = this->sizeHint_; + } this->updateGeometry(); } -int Label::getOffset() +int Label::getPadding() const { - return this->hasOffset_ ? int(8 * this->scale()) : 0; + if (this->hasPadding_) + { + return static_cast(8 * this->scale()); + } + + return 0; +} + +bool Label::updateElidedText(const QFontMetricsF &fontMetrics, qreal width) +{ + assert(this->shouldElide_ == true); + auto elidedText = fontMetrics.elidedText( + this->text_, Qt::TextElideMode::ElideRight, width); + + if (elidedText != this->elidedText_) + { + this->elidedText_ = elidedText; + return true; + } + + return false; } } // namespace chatterino diff --git a/src/widgets/Label.hpp b/src/widgets/Label.hpp index f3a7c845..3359dfde 100644 --- a/src/widgets/Label.hpp +++ b/src/widgets/Label.hpp @@ -5,6 +5,8 @@ #include +class QFontMetricsF; + namespace chatterino { class Label : public BaseWidget @@ -24,29 +26,51 @@ public: bool getCentered() const; void setCentered(bool centered); - bool getHasOffset() const; - void setHasOffset(bool hasOffset); + /// Enable or disable horizontal padding + void setHasPadding(bool hasPadding); bool getWordWrap() const; void setWordWrap(bool wrap); + /// Sets whether the text should elide if there's not enough room to + /// render the current text. + void setShouldElide(bool shouldElide); + protected: void scaleChangedEvent(float scale_) override; void paintEvent(QPaintEvent *) override; + void resizeEvent(QResizeEvent *event) override; QSize sizeHint() const override; QSize minimumSizeHint() const override; private: void updateSize(); - int getOffset(); + + /// Returns the horizontal padding, or 0 if hasPadding_ is false + int getPadding() const; + + /// Returns the current font style's font metric based on the current scale. + QFontMetricsF getFontMetrics() const; + + /// Returns the width of this content without padding + qreal getInnerWidth() const; + + /// Calculate the new elided text based on text_ + /// + /// Return true if the elided text changed + bool updateElidedText(const QFontMetricsF &fontMetrics, qreal width); QString text_; FontStyle fontStyle_; - QSize preferedSize_; + QSize sizeHint_; + QSize minimumSizeHint_; bool centered_ = false; - bool hasOffset_ = true; + bool hasPadding_ = true; bool wordWrap_ = false; + bool shouldElide_ = false; + /// The text, but elided. Only set if shouldElide_ is true + QString elidedText_; pajlada::Signals::SignalHolder connections_; }; diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index 903a8a74..c5bc193f 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -56,7 +56,6 @@ constexpr QStringView TEXT_UNAVAILABLE = u"(not available)"; constexpr QStringView TEXT_PRONOUNS = u"Pronouns: %1"; constexpr QStringView TEXT_UNSPECIFIED = u"(unspecified)"; constexpr QStringView TEXT_LOADING = u"(loading...)"; -constexpr qsizetype NOTES_PREVIEW_LENGTH = 80; using namespace chatterino; @@ -490,6 +489,7 @@ UserInfoPopup::UserInfoPopup(bool closeAutomatically, Split *split) auto notesPreview = layout.emplace