60 lines
1.8 KiB
QML
60 lines
1.8 KiB
QML
import Quickshell
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.components
|
|
import qs.services
|
|
|
|
// Left section, right of the app menu: one icon per pinned desktop entry.
|
|
Item {
|
|
id: root
|
|
|
|
// Resolved from the ids in Config.quickLaunch, in the order given, minus
|
|
// whatever this machine does not have installed.
|
|
//
|
|
// A scan rather than DesktopEntries.byId: the binding then depends on the
|
|
// model itself, so the icons appear when the initial scan finishes and
|
|
// follow an app being installed or removed. A function call would be
|
|
// evaluated once against an empty model and stay that way.
|
|
readonly property var entries: {
|
|
const apps = [...DesktopEntries.applications.values];
|
|
|
|
return Config.quickLaunch.map(id => {
|
|
const wanted = id.replace(/\.desktop$/, "").toLowerCase();
|
|
return apps.find(e => (e.id || "").toLowerCase() === wanted) ?? null;
|
|
}).filter(e => e !== null);
|
|
}
|
|
|
|
visible: root.entries.length > 0
|
|
implicitWidth: row.implicitWidth
|
|
|
|
Row {
|
|
id: row
|
|
|
|
anchors.centerIn: parent
|
|
spacing: Theme.spacing
|
|
|
|
Repeater {
|
|
model: root.entries
|
|
|
|
PanelButton {
|
|
id: button
|
|
|
|
required property var modelData
|
|
|
|
height: root.height - Theme.spacing
|
|
minContentWidth: Theme.iconSize
|
|
|
|
onClicked: AppLauncher.launch(button.modelData)
|
|
|
|
// Content is reparented into the button's holder, so the entry
|
|
// is reached through the button's id rather than `parent`.
|
|
AppIcon {
|
|
icon: button.modelData.icon
|
|
fallbackLabel: button.modelData.name
|
|
size: Theme.iconSize
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|