summaryrefslogtreecommitdiffstats
path: root/src/cardlayout.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-11 10:56:40 +0200
committerDanilo M. <danix@danix.xyz>2026-08-11 10:56:40 +0200
commit00c029a819eca601e9ac58e5c236d667505ac566 (patch)
tree52513f0f57129b95e1533863f82be00f5eff404b /src/cardlayout.cpp
parenta8844303aeb9295a6f94408cd809e521483a8b9a (diff)
downloadqtmaildir-00c029a819eca601e9ac58e5c236d667505ac566.tar.gz
qtmaildir-00c029a819eca601e9ac58e5c236d667505ac566.zip
feat(config): let the date format on a card be configured
Adds [general] date_format, a QDateTime pattern for the date a thread card shows. Absent or empty means the system locale's short format, which is what every other application on the desktop uses and stays the default. The format reaches the LAYOUT, not only the painter. CardLayout::compute() reserves the date's width from widestDateSample(), so a pattern that arrived only at the drawText call would be elided into a rect sized for the old format, which is the clipping the bold-font fault already produced once. It rides on CardLayout::Input and defaults to an empty string, leaving every existing call site unchanged. Confirmed by mutation: making the width ignore the format fails the test. widestDateSample() memoised its result in a static, which would have sized every format after the first from whichever arrived first. It is a plain call now, costing one QLocale lookup per row, the same as formatting the date. Validation rejects only a pattern whose output is CONSTANT, found by formatting two different instants and comparing. QDateTime::toString() treats nearly every letter as a field, so "banana" formats as "bpmnpmnpm" and "hello" as "22ello": nonsense, but they vary with the instant, and a check claiming to find "no date field" cannot reject them. What harms the user is the pattern that prints the same text on every card, and that is what is refused, with the value named in the message. The model supplies the pattern through DateFormatRole for the same reason it supplies the tag colours: it is the one object here holding config, and a delegate reading config itself would be a second source of truth. Backlog item 62.
Diffstat (limited to 'src/cardlayout.cpp')
-rw-r--r--src/cardlayout.cpp31
1 files changed, 19 insertions, 12 deletions
diff --git a/src/cardlayout.cpp b/src/cardlayout.cpp
index f542df0..d60bff9 100644
--- a/src/cardlayout.cpp
+++ b/src/cardlayout.cpp
@@ -21,12 +21,16 @@
#include <QFontMetrics>
#include <QLocale>
-QString CardLayout::formatDate(const QDateTime &date)
+QString CardLayout::formatDate(const QDateTime &date, const QString &format)
{
- // The system locale's own short format, not a hardcoded pattern: an
- // Italian desktop writes 10/08/2025, not 2025-08-10, and a mail client
- // that disagrees with every other application on screen is simply wrong.
- return QLocale::system().toString(date, QLocale::ShortFormat);
+ // The system locale's own short format by default, not a hardcoded
+ // pattern: an Italian desktop writes 10/08/2025, not 2025-08-10, and a mail
+ // client that disagrees with every other application on screen is simply
+ // wrong. [general] date_format overrides it for a user who wants one
+ // specific shape regardless of the locale.
+ if (format.isEmpty())
+ return QLocale::system().toString(date, QLocale::ShortFormat);
+ return QLocale::system().toString(date, format);
}
QString CardLayout::expanderLabel(int replyCount, bool expanded)
@@ -45,17 +49,19 @@ QString CardLayout::expanderLabel(int replyCount, bool expanded)
return QStringLiteral("%1 %2 %3").arg(glyph).arg(replyCount).arg(word);
}
-QString CardLayout::widestDateSample()
+QString CardLayout::widestDateSample(const QString &format)
{
// A real date run through the same formatter, with the wide digits and a
// two-digit day and month, so the reserved width matches what is drawn
// whatever the locale's pattern turns out to be. Guessing a pattern here
// would reintroduce the clipping this exists to prevent.
- static const QString sample = [] {
- const QDateTime wide(QDate(2028, 12, 28), QTime(22, 58));
- return formatDate(wide);
- }();
- return sample;
+ //
+ // Not cached in a static any more: the sample depends on the format, and a
+ // single static computed for whichever format arrived first would reserve
+ // the system format's width for a custom pattern. The formatter is one
+ // QLocale call per row, which is the same cost the date itself already pays.
+ const QDateTime wide(QDate(2028, 12, 28), QTime(22, 58));
+ return formatDate(wide, format);
}
QFont CardLayout::smallFont(const QFont &cardFont)
@@ -145,7 +151,8 @@ CardLayout CardLayout::compute(const Input &input, const QRect &rect,
QFont dateFont = font;
dateFont.setBold(true);
const int dateWidth =
- QFontMetrics(dateFont).horizontalAdvance(widestDateSample());
+ QFontMetrics(dateFont).horizontalAdvance(
+ widestDateSample(input.dateFormat));
out.dateRect = QRect(right - dateWidth, lineOneTop, dateWidth,
metrics.height());
out.senderRect = QRect(out.contentLeft, lineOneTop,