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
110 lines
3.8 KiB
QML
110 lines
3.8 KiB
QML
// A free-text setting, bound to a schema key by name.
|
|
//
|
|
// TextEntryRow { setting: "keyboardOptions"; placeholder: "compose:ralt" }
|
|
//
|
|
// For the settings whose value is a short string with too many legal values to
|
|
// enumerate -- XKB layouts and options, chiefly. Label, explanation, and
|
|
// validation all come from PreferenceSchema, so a row cannot drift from the
|
|
// setting it edits.
|
|
//
|
|
// Rejected input is shown as rejected rather than silently dropped or quietly
|
|
// sanitised. Several of these strings are serialized into an hl.config payload,
|
|
// where stripping an unexpected character would turn a typo into a different
|
|
// working setting -- so the schema's pattern decides, the field turns red when
|
|
// it fails, and nothing is committed until it passes.
|
|
//
|
|
// Committed on Enter or when focus leaves, not per keystroke: half a layout
|
|
// name is a valid string that means something else, and each commit is a round
|
|
// trip to the compositor.
|
|
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.services
|
|
|
|
SettingRow {
|
|
id: root
|
|
|
|
required property string setting
|
|
property string placeholder: ""
|
|
|
|
readonly property var spec: PreferenceSchema.spec(root.setting)
|
|
readonly property string stored: String(DesktopPreferences.get(root.setting) ?? "")
|
|
|
|
// Empty is always allowed to be typed through, even where the pattern
|
|
// forbids it, so a field can be cleared on the way to a new value.
|
|
readonly property bool valid: input.text === ""
|
|
|| !root.spec?.pattern
|
|
|| new RegExp(root.spec.pattern).test(input.text)
|
|
|
|
label: root.spec ? root.spec.label : root.setting
|
|
detail: root.spec ? root.spec.detail : ""
|
|
controlWidth: 210
|
|
|
|
function commit(): void {
|
|
if (!root.valid || input.text === root.stored)
|
|
return;
|
|
SystemSettings.commitPreference(root.setting, input.text);
|
|
}
|
|
|
|
function revert(): void {
|
|
input.text = root.stored;
|
|
}
|
|
|
|
// Follows the store when the value changes elsewhere -- a reset, a restored
|
|
// backup -- but never while the field has focus, which would overwrite what
|
|
// is being typed.
|
|
onStoredChanged: if (!input.activeFocus) input.text = root.stored
|
|
|
|
Rectangle {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: root.controlWidth
|
|
height: 30
|
|
radius: 8
|
|
color: Theme.alpha(Theme.fg, 0.05)
|
|
border.width: 1
|
|
border.color: !root.valid
|
|
? Theme.danger
|
|
: (input.activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.12))
|
|
|
|
TextInput {
|
|
id: input
|
|
|
|
anchors.fill: parent
|
|
anchors.leftMargin: 10
|
|
anchors.rightMargin: 10
|
|
verticalAlignment: TextInput.AlignVCenter
|
|
clip: true
|
|
|
|
text: root.stored
|
|
color: root.valid ? Theme.fg : Theme.danger
|
|
font.family: Theme.fontMono
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
selectByMouse: true
|
|
selectionColor: Theme.alpha(Theme.accent, 0.35)
|
|
|
|
onAccepted: root.commit()
|
|
|
|
// Commit, then show what is actually stored. If the compositor
|
|
// refused the value, the field snaps back to the value in effect
|
|
// rather than displaying a setting that was never applied; if it
|
|
// accepted, onStoredChanged brings the field back up to date the
|
|
// moment the write lands.
|
|
onActiveFocusChanged: if (!activeFocus) { root.commit(); root.revert(); }
|
|
|
|
Keys.onEscapePressed: {
|
|
root.revert();
|
|
input.focus = false;
|
|
}
|
|
|
|
Text {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: input.text === "" && !input.activeFocus
|
|
text: root.placeholder
|
|
color: Theme.fgMuted
|
|
font: input.font
|
|
}
|
|
}
|
|
}
|
|
}
|