diff options
Diffstat (limited to 'src/carddelegate.cpp')
| -rw-r--r-- | src/carddelegate.cpp | 85 |
1 files changed, 76 insertions, 9 deletions
diff --git a/src/carddelegate.cpp b/src/carddelegate.cpp index d7d06aa..4e27e6e 100644 --- a/src/carddelegate.cpp +++ b/src/carddelegate.cpp @@ -20,6 +20,7 @@ #include "cardlayout.h" #include "marks.h" +#include "tagchip.h" #include "threadlistmodel.h" #include <QApplication> @@ -31,6 +32,12 @@ namespace { +/// How much of a full-size chip's padding a SIBLING chip keeps. +/// +/// Matched to CardLayout::siblingFont()'s own scale, so the chip shrinks as a +/// whole rather than keeping full-size margins around smaller letters. +constexpr qreal kSiblingPaddingScale = 0.70; + CardLayout::Input inputFor(const QModelIndex &index) { CardLayout::Input in; @@ -58,6 +65,39 @@ QRect CardDelegate::expanderRectFor(const QStyleOptionViewItem &option, .expanderRect; } +QSize CardDelegate::chipSize(const QFontMetrics &metrics, const QString &text, + bool own) +{ + // The padding shrinks with the font for a sibling chip. Left fixed it is + // 18px around roughly 30px of text, so the chip stays wide while its + // letters shrink and the tier reads as "same chip, smaller text". + return own ? TagChip::sizeFor(metrics, text) + : TagChip::sizeFor(metrics, text, kSiblingPaddingScale); +} + +QColor CardDelegate::mutedChipColour(const QColor &chipColour) +{ + if (!chipColour.isValid()) + return chipColour; + + // Saturation only, and NOT a blend toward the background. The accent bar + // above records what blending toward Base costs: on a dark theme it lands + // on the background and the thing disappears. A chip is worse, because its + // fill also has to carry legible text on top of it. + // + // Hue is untouched, so a muted `signed` is still recognisably the same + // colour as a full-size `signed` elsewhere in the list. Lightness is + // untouched too, which is what keeps TagColors::textColourOn() picking the + // same text colour: draining saturation alone moves the fill toward grey + // without moving it toward either black or white, so contrast is preserved + // by construction rather than by hoping. + constexpr float kSaturationScale = 0.45f; + + float h = 0, s = 0, l = 0, a = 0; + chipColour.getHslF(&h, &s, &l, &a); + return QColor::fromHslF(h, s * kSaturationScale, l, a); +} + QColor CardDelegate::accentLineColour(const QColor &accountColour) { if (!accountColour.isValid()) @@ -304,20 +344,47 @@ void CardDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, : ThreadListModel::PillColoursRole) .toList(); - const QFont chipFont = CardLayout::smallFont(chrome.font); - const QFontMetrics chipMetrics(chipFont); + // A thread card draws its own tags at full size and the rest of the + // conversation's smaller and muted (item 111). The count is where the two + // tiers meet; a message row has no such split and reports its whole list. + // + // Shown rather than dropped, at the user's request: a card sits above a + // conversation, so what its siblings carry is worth seeing, just not at + // the same weight. Before the row has been opened everything is in the own + // tier, so a chip SHRINKS when the split becomes known and none vanishes. + const int ownCount = + isMessage ? tags.size() + : index.data(ThreadListModel::PillOwnCountRole).toInt(); + + const QFont ownFont = CardLayout::smallFont(chrome.font); + const QFont siblingFont = CardLayout::siblingFont(chrome.font); + const QFontMetrics ownMetrics(ownFont); + const QFontMetrics siblingMetrics(siblingFont); + painter->save(); - painter->setFont(chipFont); int x = card.tagRect.left(); for (int i = 0; i < tags.size(); ++i) { - const QSize size = TagChip::sizeFor(chipMetrics, tags.at(i)); + const bool own = i < ownCount; + const QFontMetrics &metrics = own ? ownMetrics : siblingMetrics; + + const QSize size = chipSize(metrics, tags.at(i), own); if (x + size.width() > card.tagRect.right()) break; // Out of room; a clipped chip reads as a rendering fault. - const QColor colour = i < colours.size() - ? colours.at(i).value<QColor>() - : QColor(0x55, 0x55, 0x5f); - TagChip::paint(painter, QRect(QPoint(x, card.tagRect.top()), size), - tags.at(i), colour); + + QColor colour = i < colours.size() ? colours.at(i).value<QColor>() + : QColor(0x55, 0x55, 0x5f); + if (!own) + colour = mutedChipColour(colour); + + // Bottom-aligned, so a smaller chip sits on the same baseline as its + // neighbours rather than floating in the middle of the row. Top + // alignment would step the tier down and read as a layout fault. + const int top = card.tagRect.top() + + (ownMetrics.height() - metrics.height()); + + painter->setFont(own ? ownFont : siblingFont); + TagChip::paint(painter, QRect(QPoint(x, top), size), tags.at(i), + colour); x += size.width() + TagChip::kSpacing; } painter->restore(); |
