diff options
Diffstat (limited to 'desktop/modules/deckit/DeckItWindowsPage.qml')
| -rw-r--r-- | desktop/modules/deckit/DeckItWindowsPage.qml | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/desktop/modules/deckit/DeckItWindowsPage.qml b/desktop/modules/deckit/DeckItWindowsPage.qml new file mode 100644 index 0000000..c7cd11c --- /dev/null +++ b/desktop/modules/deckit/DeckItWindowsPage.qml @@ -0,0 +1,151 @@ +// Copyright (C) 2026 Danilo M. <danix@danix.xyz> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +import Quickshell +import QtQuick +import "../.." +import "../qtmaildir" + +// deck-it's Windows page: the launcher buttons and the workspaces shown. +Column { + id: col + spacing: 6 + readonly property var st: DeckIt.store + function def(section, key) { return col.st.fallback(section, key); } + + // The launcher list, in button order. + readonly property var apps: col.st.value("launch", "apps") ?? [] + property string query: "" + // Installed apps not yet listed, for the picker. Terminal apps are left + // out, as the Autostart page does: gtk-launch would need a terminal for them. + readonly property var candidates: { + const q = col.query.trim().toLowerCase(); + return DesktopEntries.applications.values + .filter(a => !a.noDisplay && !a.runInTerminal && a.execString && !col.apps.includes(a.id) + && (q === "" || a.name.toLowerCase().includes(q) || a.id.toLowerCase().includes(q))) + .sort((a, b) => a.name.localeCompare(b.name)) + .slice(0, 8); + } + function setApps(list) { col.st.put("launch", "apps", list); } + + Small { visible: DeckIt.defaultsError !== ""; color: Theme.red; text: DeckIt.defaultsError } + + Heading { objectName: "launch/apps"; text: "Launchers" } + Small { text: "Buttons on the Windows tab, in this order. Each runs its app through gtk-launch." } + Repeater { + model: col.apps + delegate: Item { + id: row + required property string modelData + required property int index + readonly property var entry: DesktopEntries.byId(row.modelData) + width: col.width + height: 34 + Image { + id: appIcon + anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter } + width: 20; height: 20 + sourceSize: Qt.size(20, 20) + source: row.entry ? Quickshell.iconPath(row.entry.icon, true) : "" + } + Text { + anchors { left: appIcon.right; leftMargin: 10; right: up.left; rightMargin: 8; verticalCenter: parent.verticalCenter } + elide: Text.ElideRight + text: row.entry ? row.entry.name + " " + row.modelData : row.modelData + " not installed" + color: row.entry ? Theme.text : Theme.red + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } + } + Button { + id: up + anchors { right: del.left; rightMargin: 6; verticalCenter: parent.verticalCenter } + text: "Up" + enabled: row.index > 0 + onClicked: { + const a = col.apps.slice(); + a.splice(row.index - 1, 0, a.splice(row.index, 1)[0]); + col.setApps(a); + } + } + Button { + id: del + anchors { right: parent.right; verticalCenter: parent.verticalCenter } + text: "Remove" + danger: true + onClicked: col.setApps(col.apps.filter(a => a !== row.modelData)) + } + } + } + Rectangle { + width: col.width + height: 34 + radius: 8 + color: Theme.surface + TextInput { + id: search + activeFocusOnTab: true + 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 } + onTextEdited: col.query = text + Text { + anchors.verticalCenter: parent.verticalCenter + visible: parent.text === "" + text: "add an app: search installed apps" + color: Theme.subtext + font: parent.font + } + } + } + Repeater { + model: col.candidates + delegate: Rectangle { + id: app + required property var modelData + width: col.width + height: 32 + radius: 8 + color: appArea.containsMouse ? Qt.alpha(Theme.text, 0.06) : "transparent" + Image { + id: candIcon + anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter } + width: 20; height: 20 + sourceSize: Qt.size(20, 20) + source: Quickshell.iconPath(app.modelData.icon, true) + } + Text { + anchors { left: candIcon.right; leftMargin: 10; right: parent.right; rightMargin: 8; verticalCenter: parent.verticalCenter } + elide: Text.ElideRight + text: app.modelData.name + " " + app.modelData.id + color: Theme.text + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } + } + MouseArea { + id: appArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + col.setApps(col.apps.concat([app.modelData.id])); + col.query = ""; + search.text = ""; + } + } + } + } + + Heading { text: "Workspaces" } + Setting { store: col.st; section: "windows"; key: "workspaces"; label: "Workspaces" + placeholder: col.st.placeholder("windows", "workspaces") + hint: "Numbers on the Windows tab, separated by spaces, shown even when empty." } +} |
