diff options
Diffstat (limited to 'desktop/Settings.qml')
| -rw-r--r-- | desktop/Settings.qml | 149 |
1 files changed, 113 insertions, 36 deletions
diff --git a/desktop/Settings.qml b/desktop/Settings.qml index af41fe4..52ca549 100644 --- a/desktop/Settings.qml +++ b/desktop/Settings.qml @@ -16,7 +16,7 @@ import QtQuick // tiles or floats it like any app. The drawer is the quick area; things set // once and left alone live here. It hosts the pages of the modules that // declare `settings: true`, from the same module list as the drawer, with a -// list of them down the left. +// searchable list of them down the left and an About page as the landing. Scope { id: root @@ -30,6 +30,24 @@ Scope { if (root.modules[i].settings) out.push(root.modules[i]); return out; } + property string query: "" + + // The pages the search keeps, as {mod, hit}: hit is the keyword that + // matched when the label did not, shown under the entry. + readonly property var found: { + const q = root.query.trim().toLowerCase(); + const out = []; + for (const m of root.pages) { + if (q === "" || m.label.toLowerCase().includes(q) || m.name.includes(q)) { + out.push({ mod: m, hit: "" }); + continue; + } + const k = Array.from(m.keywords).find(w => w.toLowerCase().includes(q)); + if (k !== undefined) out.push({ mod: m, hit: k }); + } + return out; + } + // Null is the landing page. readonly property QtObject current: root.pages.find(m => m.name === root.page) ?? null @@ -40,7 +58,7 @@ Scope { if (root.current) root.page = ""; else root.close(); } - function close() { root.open = false; root.page = ""; } + function close() { root.open = false; root.page = ""; root.query = ""; } LazyLoader { active: root.open @@ -57,35 +75,82 @@ Scope { focus: true Keys.onEscapePressed: root.back() + // Search: filters the list below by label and by each + // module's keywords, the settings buried in its page. Enter + // opens the first match; Escape clears, then steps out. + Rectangle { + id: search + anchors { top: parent.top; left: parent.left; margins: 12 } + width: 200 + height: 34 + radius: 8 + color: Theme.surface + + TextInput { + id: searchIn + anchors { fill: parent; leftMargin: 10; rightMargin: 10 } + verticalAlignment: TextInput.AlignVCenter + clip: true + selectByMouse: true + color: Theme.text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + text: root.query + onTextEdited: root.query = text + onAccepted: if (root.found.length) root.page = root.found[0].mod.name + Keys.onEscapePressed: event => { + if (root.query !== "") root.query = ""; + else event.accepted = false; + } + Text { + anchors.verticalCenter: parent.verticalCenter + visible: parent.text === "" + text: "Search settings" + color: Theme.subtext + font: parent.font + } + } + } + ListView { id: side - anchors { top: parent.top; left: parent.left; bottom: parent.bottom; margins: 12 } + anchors { top: search.bottom; left: parent.left; bottom: parent.bottom; margins: 12 } width: 200 spacing: 4 - model: root.pages + model: root.found delegate: Rectangle { id: entry - required property QtObject modelData - readonly property bool selected: root.current === modelData + required property var modelData + readonly property bool selected: root.current === modelData.mod width: side.width - height: 36 + height: modelData.hit ? 46 : 36 radius: 8 color: selected ? Qt.alpha(Theme.accent, 0.22) : area.containsMouse ? Qt.alpha(Theme.text, 0.06) : "transparent" - Row { + Text { + id: entryIcon anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } - spacing: 10 + text: entry.modelData.mod.icon + font { family: Theme.iconFamily; pixelSize: Theme.fontSize } + color: Theme.text + } + Column { + anchors { left: entryIcon.right; leftMargin: 10; right: parent.right; rightMargin: 8 + verticalCenter: parent.verticalCenter } Text { - text: entry.modelData.icon - font { family: Theme.iconFamily; pixelSize: Theme.fontSize } + text: entry.modelData.mod.label + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } color: Theme.text } + // Which buried setting matched, when the label did not. Text { - text: entry.modelData.label - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } - color: Theme.text + visible: entry.modelData.hit !== "" + width: parent.width + elide: Text.ElideRight + text: entry.modelData.hit + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 5 } + color: Theme.subtext } } @@ -94,11 +159,19 @@ Scope { anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: root.page = entry.modelData.name + onClicked: root.page = entry.modelData.mod.name } } } + Text { + anchors { top: search.bottom; left: parent.left; margins: 12; leftMargin: 22 } + visible: root.found.length === 0 + text: "Nothing matches" + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } + color: Theme.subtext + } + Rectangle { id: rule anchors { top: parent.top; bottom: parent.bottom; left: side.right; leftMargin: 12 } @@ -106,37 +179,41 @@ Scope { color: Qt.alpha(Theme.text, 0.12) } - // The landing page: every settings page as a tile, as the - // drawer's grid shows its modules. Where back returns to. - Item { - anchors { top: parent.top; right: parent.right; bottom: parent.bottom; left: rule.right; margins: 16 } + // The landing page, where back returns to: what this shell is. + Column { + anchors { top: parent.top; right: parent.right; left: rule.right; margins: 16 } visible: root.current === null + spacing: 12 Text { - id: landingTitle height: 44 verticalAlignment: Text.AlignVCenter - text: "Settings" + text: "About" font { family: Theme.fontFamily; pixelSize: Theme.fontSize + 2; bold: true } color: Theme.text } - Flow { - id: landing - anchors { top: landingTitle.bottom; topMargin: 12; left: parent.left; right: parent.right } - spacing: 10 - - Repeater { - model: root.pages + Text { + width: Math.min(parent.width, 560) + wrapMode: Text.Wrap + textFormat: Text.PlainText + lineHeight: 1.25 + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } + color: Theme.text + text: "A desktop shell for Hyprland, built on Quickshell.\n\n" + + "SUPER alone opens the drawer, the quick area: notifications, sound, " + + "network, bluetooth, mail, VMs, performance, the clipboard and the " + + "rest of what changes during the day. The island at the top of the " + + "main screen carries the clock, volume, tray, keyboard layout and " + + "calendar, and SUPER+Home opens the assistant.\n\n" + + "This window holds what is set once and left alone. Pick a page on " + + "the left, or search for a setting by name." + } - Tile { - required property QtObject modelData - width: (landing.width - 2 * landing.spacing) / 3 - icon: modelData.icon - label: modelData.label - onClicked: root.page = modelData.name - } - } + Text { + text: "GPLv2. Colours follow the wallpaper through unified-desktop-theme." + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + color: Theme.subtext } } |
