fix(settings): make the Font row actually change the font

It shipped doing nothing. Measured on the built binary: picking a face
persisted the pref and changed ZERO of 600600 pixels in the settings
label column. The row was a control that lied.

Two measurements say why, and both were run against this Qt build rather
than reasoned about:

  - `ApplicationWindow.font.family` propagates through Qt Quick CONTROLS
    only. In a standalone scene with a family set on the window, a
    `Label` resolved to it and a sibling `Text` stayed on the
    APPLICATION font. This tree is 1082 plain `Text` items against 13
    that name a family, so the app's typeface IS the application font.
  - The application font is read when an item is CONSTRUCTED. Driving
    PySide6 against the same Qt, `QGuiApplication::setFont` updated
    `QGuiApplication::font()` and left an already-built `Text` on its old
    family.

Together those close the door on changing it live, so the ordering in
main() is the feature: FontPreload.qml registers the bundled faces (a
family does not exist until its file is loaded, and `load()` returns
with its FontLoaders already in the database), the application font is
set from the persisted choice, and only then does Main.qml build the UI.
Swap any two of those and the setting silently does nothing again.

The row now says "(requires restart)", the same wording Interface size
two rows above already uses, in all eight catalogues.

"System" resolves to "" and takes no branch, so anyone who never opens
the row gets exactly the font this app rendered before — verified by
capturing the window on both settings: 0 log lines and an untouched
frame for System, 27065 changed pixels for Montserrat.

NOT ADDRESSED, and worth its own decision: those 1082 Text items have
never used the bundled Inter either. `Main.qml` has always named it, but
that only ever reached the Controls, so the app renders in whatever Qt
picks. Making "System" mean Inter is a one-line change and a visible
one, so it is left alone here.

cc
This commit is contained in:
vicrodh committed 2026-08-22 01:31:42 -06:00
1 parent bbe9f25689
commit cf07f10a59
7 files changed
+143 -46

No files matched your search

+10 -28
View File
@@ -179,36 +179,18 @@ ApplicationWindow {
// own loader into every row it renders in.
FontLoader { id: lineSeed; source: "assets/fonts/LINESeedJP-Regular.ttf" }
// ── Settings > Appearance > Typography & Language > Font ───────────────
// The app-wide typeface. Every Text in the tree that does not name a
// family of its own inherits THIS one, which is why the setting lives on
// the ApplicationWindow and applies live with no restart.
// Settings > Appearance > Typography & Language > Font — the CONTROLS half.
//
// The catalog is settings_qt::APP_FONT_VALUES and the index rides
// `QbzShell.appFontIndex` — a property of its own rather than a read out
// of settingsJson, so the root window does not parse the whole settings
// document to find one integer.
// The app's own text does not come from here: a plain `Text` takes the
// APPLICATION font at construction, which main() sets before this document
// is even loaded (see qml/FontPreload.qml for the measurements). What this
// line still owns is Qt Quick Controls, which follow ApplicationWindow.font
// and would otherwise sit on Inter while every label around them moved.
//
// LAZY, exactly like the lyrics panel's own picker
// (shell/LyricsLinesView.qml:66-80): a family nobody selected is never
// loaded, and a family that has not FINISHED loading falls back to Inter
// rather than rendering the app in a wrong face for a frame.
FontLoader { id: appMontserrat; source: QbzShell.appFontIndex === 2 ? "assets/fonts/Montserrat-VariableFont_wght.ttf" : "" }
FontLoader { id: appNoto; source: QbzShell.appFontIndex === 3 ? "assets/fonts/NotoSans-VariableFont_wdth,wght.ttf" : "" }
FontLoader { id: appSource; source: QbzShell.appFontIndex === 4 ? "assets/fonts/SourceSans3-VariableFont_wght.ttf" : "" }
readonly property string appFontFamily: {
if (QbzShell.appFontIndex === 1)
return lineSeed.status === FontLoader.Ready ? lineSeed.name : ""
if (QbzShell.appFontIndex === 2)
return appMontserrat.status === FontLoader.Ready ? appMontserrat.name : ""
if (QbzShell.appFontIndex === 3)
return appNoto.status === FontLoader.Ready ? appNoto.name : ""
if (QbzShell.appFontIndex === 4)
return appSource.status === FontLoader.Ready ? appSource.name : ""
return ""
}
font.family: window.appFontFamily !== ""
? window.appFontFamily
// "" = System, i.e. leave Qt's own choice alone, which is what this app
// rendered before the setting existed.
font.family: QbzShell.appFontFamily !== ""
? QbzShell.appFontFamily
: (interRegular.status === FontLoader.Ready ? interRegular.name : "Sans Serif")
// Phase 23: every domain singleton boots (registers its Qt-thread