/* * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs * Copyright (C) 2026 Danilo M. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "tagchip.h" #include #include #include #include "tagcolors.h" #include "threadlistmodel.h" namespace TagChip { QSize sizeFor(const QFontMetrics &metrics, const QString &text) { return sizeFor(metrics, text, 1.0); } QSize sizeFor(const QFontMetrics &metrics, const QString &text, qreal scale) { // Floored at 2 a side: the corner radius is half the chip's height, so the // leftmost and rightmost pixels of the fill are curve rather than usable // width, and text set flush against it touches the round end. const int padX = qMax(2, qRound(kPaddingX * scale)); const int padY = qMax(0, qRound(kPaddingY * scale)); return QSize(metrics.horizontalAdvance(text) + padX * 2, metrics.height() + padY * 2); } void paint(QPainter *painter, const QRect &rect, const QString &text, const QColor &background) { painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); painter->setBrush(background); // Radius from the chip's own height rather than the fixed kRadius: a 3px // corner on a 17px chip reads as a slightly-softened rectangle, which is // hard to tell from the square cells of the columns behind it. Half the // height gives fully rounded ends, so a chip reads as an object sitting on // the row instead of as another compartment of it. const qreal radius = rect.height() / 2.0; painter->drawRoundedRect(rect, radius, radius); painter->setPen(TagColors::textColourOn(background)); painter->drawText(rect, Qt::AlignCenter, text); painter->restore(); } } // namespace TagChip void RowStyleDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const { QStyledItemDelegate::initStyleOption(option, index); // Qt resolves Qt::ForegroundRole into the palette's Text roles, and its // own painting then prefers those over HighlightedText: a model that // supplies a foreground wins even on a selected row. // // That is wrong for the read/unread dimming. A read thread's colour is // blended against the UNSELECTED background, so over the selection // highlight it lands as grey on purple, near unreadable. The highlight // already says "this row", so the dimming can yield to it while selected. // // Doomed threads are unaffected in practice: their fill is drawn beneath // the selection and their white is a contrast requirement, which // HighlightedText also satisfies. if (option->state & QStyle::State_Selected) { const QColor highlighted = option->palette.color(QPalette::HighlightedText); option->palette.setColor(QPalette::Text, highlighted); option->palette.setColor(QPalette::WindowText, highlighted); } // One line, elided. A card draws its own text through CardDelegate, but // this still governs whatever Qt draws for the item itself, and a wrapped // string would run past the card's own three lines. option->features &= ~QStyleOptionViewItem::WrapText; option->textElideMode = Qt::ElideRight; }