colour -> color, behaviour -> behavior, centre -> center, favourite -> favorite, and about twenty other pairs, applied consistently across comments, docs, error/UI copy, and a handful of QML identifiers that used the British spelling as their actual name: SystemSettings' serialiseValue/serialiseTable/normaliseGradient, Displays' normaliseModes, Wallpaper's normalisePolicy, SettingsBackup's serialiseHomeState, DateTime's ntpSynchronised property, Clipboard's _normalise helper, and ShortcutCapture's cancelled signal (with its onCancelled handler in ShortcutsPage.qml). Every call site and the two tests that assert on the literal source text (settings-ownership and settings-backup-live contracts) were updated in lockstep. Left untouched: config/dot/espanso/match/packages/misspell-en/ is a vendored third-party autocorrect dictionary -- its entries are typo corrections, not our prose, and rewriting them would fight the package's own purpose (and any future re-sync from upstream). The already-American `favorites` property (Home page pinned accessories) was never actually misspelled -- only nearby comments and error strings said "favourites" -- so no data migration was needed there. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
221 lines
8.0 KiB
QML
221 lines
8.0 KiB
QML
// A miniature of the real desktop that redraws as you change Appearance.
|
|
//
|
|
// The point is that "outer gaps 24" and "radius 9" mean nothing as numbers. This
|
|
// shows two tiled windows at the settings currently in effect: the focused one
|
|
// wearing the prism border and its glow, the unfocused one carrying the
|
|
// inactive-opacity setting, both inside real gaps at a real corner radius.
|
|
//
|
|
// Geometry is scaled by the ratio between this preview's width and the actual
|
|
// monitor's, so proportions are honest rather than decorative -- a 10px gap on
|
|
// a 4500px display genuinely is almost invisible, and the preview says so.
|
|
//
|
|
// Everything here is driven by bindings on DesktopPreferences, so the preview
|
|
// shows what is actually stored and applied. It has no state of its own and
|
|
// nothing animates while idle.
|
|
|
|
import QtQuick
|
|
import QtQuick.Effects
|
|
import qs.config
|
|
import qs.services
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
implicitHeight: 232
|
|
radius: Theme.cardRadius
|
|
clip: true
|
|
border.width: 1
|
|
border.color: Theme.alpha(Theme.fg, 0.09)
|
|
|
|
// Falls back to a sane width if the monitor has not been read yet, so the
|
|
// preview is never wrong by a factor of ten on first paint.
|
|
readonly property real monitorWidth: SystemSettings.monitorWidth > 0 ? SystemSettings.monitorWidth : 3000
|
|
readonly property real scale: width > 0 ? width / root.monitorWidth : 0.25
|
|
|
|
readonly property int gapsIn: DesktopPreferences.get("gapsIn")
|
|
readonly property int gapsOut: DesktopPreferences.get("gapsOut")
|
|
readonly property int borderSize: DesktopPreferences.get("borderSize")
|
|
readonly property int rounding: DesktopPreferences.get("windowRounding")
|
|
readonly property real inactiveOpacity: DesktopPreferences.get("inactiveOpacity")
|
|
readonly property bool shadowOn: DesktopPreferences.get("shadowEnabled")
|
|
readonly property int shadowRange: DesktopPreferences.get("shadowRange")
|
|
readonly property bool glowOn: DesktopPreferences.get("glowEnabled")
|
|
readonly property int glowRange: DesktopPreferences.get("glowRange")
|
|
|
|
// Scaled geometry, floored so a small-but-nonzero setting stays visible
|
|
// rather than rounding away to nothing.
|
|
function px(value: real): real {
|
|
return value <= 0 ? 0 : Math.max(1, value * root.scale);
|
|
}
|
|
|
|
// Stands in for the wallpaper. Static: an animated gradient here would
|
|
// repaint forever behind a settings page.
|
|
// Follows the color scheme. A preview that stays dark while the shell
|
|
// around it is light does not read as "your desktop" -- it reads as a
|
|
// screenshot of someone else's.
|
|
gradient: Gradient {
|
|
orientation: Gradient.Vertical
|
|
GradientStop { position: 0.0; color: Theme.dark ? "#2b3050" : "#b9c0dd" }
|
|
GradientStop { position: 1.0; color: Theme.dark ? "#241f33" : "#cbbcd4" }
|
|
}
|
|
|
|
// The bar, so the preview reads as this desktop and not a generic one.
|
|
Rectangle {
|
|
id: miniBar
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: 20
|
|
color: Theme.alpha(Theme.bgDark, 0.4)
|
|
border.width: 0
|
|
|
|
Row {
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 9
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 4
|
|
|
|
Repeater {
|
|
model: 3
|
|
Rectangle {
|
|
required property int index
|
|
width: index === 0 ? 12 : 5
|
|
height: 5
|
|
radius: 2.5
|
|
border.width: 0
|
|
color: index === 0 ? Theme.accent : Theme.alpha(Theme.fg, 0.3)
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
}
|
|
}
|
|
}
|
|
|
|
// The real bar carries a clock here, not a name. Standing in with the
|
|
// actual time keeps the preview a picture of this desktop rather than
|
|
// a picture of a product.
|
|
Text {
|
|
anchors.centerIn: parent
|
|
text: Qt.formatTime(new Date(), "h:mm")
|
|
color: Theme.alpha(Theme.fg, 0.45)
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: 9
|
|
}
|
|
}
|
|
|
|
Row {
|
|
id: tiles
|
|
anchors.top: miniBar.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
anchors.margins: root.px(root.gapsOut)
|
|
spacing: root.px(root.gapsIn) * 2
|
|
|
|
MiniWindow {
|
|
width: (tiles.width - tiles.spacing) / 2
|
|
height: tiles.height
|
|
focused: true
|
|
}
|
|
|
|
MiniWindow {
|
|
width: (tiles.width - tiles.spacing) / 2
|
|
height: tiles.height
|
|
focused: false
|
|
}
|
|
}
|
|
|
|
component MiniWindow: Item {
|
|
id: win
|
|
|
|
required property bool focused
|
|
|
|
// The gradient border is drawn as a filled rounded rect with the window
|
|
// body inset on top of it: QML's Rectangle border takes a color, not a
|
|
// gradient, and the prism border is the whole signature here.
|
|
Rectangle {
|
|
id: frame
|
|
anchors.fill: parent
|
|
radius: root.px(root.rounding)
|
|
border.width: 0
|
|
visible: win.focused && root.borderSize > 0
|
|
|
|
gradient: Gradient {
|
|
orientation: Gradient.Horizontal
|
|
GradientStop { position: 0.0; color: Theme.accent }
|
|
GradientStop { position: 1.0; color: Theme.accentSecondary }
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: body
|
|
anchors.fill: parent
|
|
anchors.margins: win.focused ? root.px(root.borderSize) : 0
|
|
radius: Math.max(0, root.px(root.rounding) - (win.focused ? root.px(root.borderSize) : 0))
|
|
color: Theme.alpha(Theme.bgDark, 0.92)
|
|
opacity: win.focused ? 1.0 : root.inactiveOpacity
|
|
border.width: win.focused ? 0 : 1
|
|
border.color: Theme.alpha(Theme.gutter, 0.6)
|
|
clip: true
|
|
|
|
Rectangle {
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: 13
|
|
color: Theme.alpha(Theme.fg, 0.05)
|
|
border.width: 0
|
|
}
|
|
|
|
Column {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.topMargin: 22
|
|
anchors.margins: 10
|
|
spacing: 5
|
|
|
|
Repeater {
|
|
model: [1.0, 0.74, 0.52]
|
|
Rectangle {
|
|
required property real modelData
|
|
width: parent.width * modelData
|
|
height: 4
|
|
radius: 2
|
|
border.width: 0
|
|
color: Theme.alpha(Theme.fg, win.focused ? 0.2 : 0.13)
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
anchors.left: parent.left
|
|
anchors.bottom: parent.bottom
|
|
anchors.margins: 8
|
|
text: win.focused ? "focused" : "unfocused"
|
|
color: Theme.fgMuted
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: 9
|
|
}
|
|
}
|
|
|
|
// Shadow and glow both come from MultiEffect. Only the focused window
|
|
// gets the glow, matching looks.lua where glow.color_inactive is fully
|
|
// transparent.
|
|
MultiEffect {
|
|
anchors.fill: body
|
|
source: body
|
|
visible: root.shadowOn || (win.focused && root.glowOn)
|
|
z: -1
|
|
|
|
shadowEnabled: true
|
|
shadowColor: win.focused && root.glowOn
|
|
? Theme.alpha(Theme.accent, 0.5)
|
|
: Theme.alpha(Theme.dark ? "#15161e" : "#6172b0", Theme.dark ? 0.85 : 0.45)
|
|
shadowBlur: win.focused && root.glowOn
|
|
? Math.min(1.0, root.px(root.glowRange) / 12)
|
|
: Math.min(1.0, root.px(root.shadowRange) / 24)
|
|
shadowVerticalOffset: win.focused && root.glowOn ? 0 : root.px(4)
|
|
shadowHorizontalOffset: 0
|
|
}
|
|
}
|
|
}
|