Seconds per clock, and type that scales with the bar height

Seconds move from one bar-wide switch to a per-clock setting. A clock's own
`showSeconds` wins, the top-level one is the default for clocks with no
opinion, and the centre clock gets `local.showSeconds` since it has no entry in
`clocks[]`. An explicit false on a clock beats a true default, so the check is
for the property's presence rather than its truthiness.

The tick rate follows what is actually displayed: `anyShowsSeconds()` decides
between a per-second and a per-minute SystemClock, so a bar showing no seconds
does not wake the shell sixty times as often to redraw an identical minute.

`barSize` is now editable from the popup, and everything drawn on the bar is
sized against the theme's own bar height rather than pinned to the theme's
12px type. A taller bar carries proportionally larger text, gaps and rule; at
the theme's own height the scale is exactly 1, so nothing moves. Heights are
clamped to 12-120 rather than rejected, so a value the editor can produce can
never be one the config layer silently discards.

Fixes a latent bug this surfaced: updateRow() rebuilt a draft row from a fixed
pair of fields, so editing a clock's label would have thrown away its own
seconds setting. It now copies every key the row had.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MhxtL7WzL5XmuTd8GHbcTY
This commit is contained in:
Harvey
2026-09-04 18:02:36 +02:00
co-authored by Claude Opus 5
parent b5f4569233
commit 8364fe2141
6 changed files with 249 additions and 29 deletions
+26 -13
View File
@@ -33,15 +33,28 @@ Item {
// stay the same weight when the theme or font size changes.
readonly property int barSize: config && config.barSize > 0 ? config.barSize : Style.bar.sizeHorizontal
// Everything drawn on the bar is sized against the theme's own bar height,
// so a taller bar carries proportionally larger type and gaps rather than
// the theme's 26px-sized text marooned in the middle of it. At the default
// height this is exactly 1, which leaves the theme's own tokens untouched.
readonly property real barScale: Style.bar.sizeHorizontal > 0
? barSize / Style.bar.sizeHorizontal
: 1
function scaled(px) { return Math.max(1, Math.round(px * root.barScale)) }
readonly property int timeFontSize: scaled(Style.font.body)
readonly property int labelFontSize: scaled(Style.font.caption)
readonly property color background: Color.bar.background
readonly property color foreground: Color.bar.text
readonly property color muted: Color.muted
readonly property color accent: Color.accent
readonly property color urgent: Color.urgent
readonly property int edgePadding: Style.space(12)
readonly property int clockGap: Style.space(16)
readonly property int labelGap: Style.space(6)
readonly property int edgePadding: scaled(Style.space(12))
readonly property int clockGap: scaled(Style.space(16))
readonly property int labelGap: scaled(Style.space(6))
Config { id: configFile }
@@ -50,12 +63,12 @@ Item {
zones: Model.zonesToProbe(root.config)
}
// Minute precision is all the display needs; seconds are opt-in because
// ticking every second wakes the whole shell sixty times as often for a
// readout nobody reads that closely.
// Seconds are opt-in per clock, so the tick only drops to per-second when
// something on the bar is actually displaying them — otherwise this wakes
// the whole shell sixty times as often to redraw an identical minute.
SystemClock {
id: clock
precision: root.config && root.config.showSeconds ? SystemClock.Seconds : SystemClock.Minutes
precision: Model.anyShowsSeconds(root.config) ? SystemClock.Seconds : SystemClock.Minutes
onDateChanged: {
root.nowMs = date.getTime()
// Offsets only move at a transition, and transitions land on the hour.
@@ -117,7 +130,7 @@ Item {
// step down the scale — present for identification, not competing with
// the time for the glance.
font.family: Style.font.family
font.pixelSize: Style.font.caption
font.pixelSize: root.labelFontSize
// Held back from the time it captions, but only once: a dimmed clock is
// already carrying the muted tint, and compounding the two put its label
// under the legibility floor.
@@ -129,7 +142,7 @@ Item {
text: entry.clock.time
color: entry.tint
font.family: Style.font.family
font.pixelSize: Style.font.body
font.pixelSize: root.timeFontSize
}
Text {
@@ -142,7 +155,7 @@ Item {
text: entry.clock.marker
color: entry.tint
font.family: Style.font.family
font.pixelSize: Style.font.caption
font.pixelSize: root.labelFontSize
opacity: 0.7
}
}
@@ -184,7 +197,7 @@ Item {
// that cannot be overlapped by a long list of clocks.
Rectangle {
anchors { top: parent.top; left: parent.left; right: parent.right }
height: configFile.parseError !== "" ? 2 : 1
height: configFile.parseError !== "" ? root.scaled(2) : Math.max(1, root.scaled(1))
color: configFile.parseError !== "" ? root.urgent : root.foreground
opacity: configFile.parseError !== "" ? 0.9 : 0.12
}
@@ -215,7 +228,7 @@ Item {
text: root.bar.center.time
color: root.accent
font.family: Style.font.family
font.pixelSize: Style.font.body
font.pixelSize: root.timeFontSize
font.bold: true
}
@@ -228,7 +241,7 @@ Item {
text: "config error"
color: root.urgent
font.family: Style.font.family
font.pixelSize: Style.font.caption
font.pixelSize: root.labelFontSize
}
}