diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml new file mode 100644 index 0000000..31ada32 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml @@ -0,0 +1,256 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + property var selectedItem: null + property var controller: null + property bool expanded: false + property int selectedActionIndex: 0 + + function getPluginContextMenuActions() { + if (selectedItem?.type !== "plugin" || !selectedItem?.pluginId) + return []; + var instance = PluginService.pluginInstances[selectedItem.pluginId]; + if (!instance) + return []; + if (typeof instance.getContextMenuActions !== "function") + return []; + var actions = instance.getContextMenuActions(selectedItem.data); + if (!Array.isArray(actions)) + return []; + return actions; + } + + readonly property var actions: { + var result = []; + if (selectedItem?.primaryAction) { + result.push(selectedItem.primaryAction); + } + + switch (selectedItem?.type) { + case "plugin": + var pluginActions = getPluginContextMenuActions(); + for (var i = 0; i < pluginActions.length; i++) { + var act = pluginActions[i]; + result.push({ + name: act.text || act.name || "", + icon: act.icon || "play_arrow", + action: "plugin_action", + pluginAction: act.action + }); + } + break; + case "plugin_browse": + if (selectedItem?.actions) { + for (var i = 0; i < selectedItem.actions.length; i++) { + result.push(selectedItem.actions[i]); + } + } + break; + case "app": + if (selectedItem?.isCore) + break; + if (SessionService.nvidiaCommand) { + result.push({ + name: I18n.tr("Launch on dGPU"), + icon: "memory", + action: "launch_dgpu" + }); + } + if (selectedItem?.actions) { + for (var i = 0; i < selectedItem.actions.length; i++) { + result.push(selectedItem.actions[i]); + } + } + break; + } + return result; + } + + readonly property bool hasActions: { + switch (selectedItem?.type) { + case "app": + return !selectedItem?.isCore; + case "plugin": + return getPluginContextMenuActions().length > 0; + case "plugin_browse": + return selectedItem?.actions?.length > 0; + default: + return actions.length > 1; + } + } + + width: parent?.width ?? 200 + height: expanded && hasActions ? 52 : 0 + color: Theme.surfaceContainerHigh + radius: Theme.cornerRadius + + clip: true + + Behavior on height { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + + Rectangle { + anchors.top: parent.top + width: parent.width + height: 1 + color: Theme.outlineMedium + } + + Item { + anchors.fill: parent + anchors.margins: Theme.spacingS + + Flickable { + id: actionsFlickable + anchors.left: parent.left + anchors.right: tabHint.left + anchors.rightMargin: Theme.spacingS + anchors.verticalCenter: parent.verticalCenter + height: parent.height + contentWidth: actionsRow.width + contentHeight: height + clip: true + boundsBehavior: Flickable.StopAtBounds + flickableDirection: Flickable.HorizontalFlick + + Row { + id: actionsRow + height: parent.height + spacing: Theme.spacingS + + Repeater { + model: root.actions + + Rectangle { + id: actionButton + + required property var modelData + required property int index + + width: actionContent.implicitWidth + Theme.spacingM * 2 + height: actionsRow.height + radius: Theme.cornerRadius + color: index === root.selectedActionIndex ? Theme.primaryHover : actionArea.containsMouse ? Theme.surfaceHover : "transparent" + + Row { + id: actionContent + anchors.centerIn: parent + spacing: Theme.spacingXS + + DankIcon { + anchors.verticalCenter: parent.verticalCenter + name: actionButton.modelData?.icon ?? "play_arrow" + size: 16 + color: actionButton.index === root.selectedActionIndex ? Theme.primary : Theme.surfaceText + } + + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: actionButton.modelData?.name ?? "" + font.pixelSize: Theme.fontSizeSmall + font.weight: Font.Medium + color: actionButton.index === root.selectedActionIndex ? Theme.primary : Theme.surfaceText + } + } + + MouseArea { + id: actionArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (root.controller && root.selectedItem) { + root.controller.executeAction(root.selectedItem, actionButton.modelData); + } + } + onEntered: root.selectedActionIndex = actionButton.index + } + } + } + } + } + + StyledText { + id: tabHint + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + visible: root.hasActions + text: "Tab" + font.pixelSize: Theme.fontSizeSmall - 2 + color: Theme.outlineButton + } + } + + function toggle() { + expanded = !expanded; + selectedActionIndex = 0; + } + + function show() { + expanded = true; + selectedActionIndex = actions.length > 1 ? 1 : 0; + } + + function hide() { + expanded = false; + selectedActionIndex = 0; + } + + function cycleAction(reverse = false) { + if (actions.length > 0) { + if (! reverse) + selectedActionIndex = (selectedActionIndex + 1) % actions.length; + else + selectedActionIndex = (selectedActionIndex - 1) % actions.length; + ensureSelectedVisible(); + } + } + + function ensureSelectedVisible() { + if (selectedActionIndex < 0 || !actionsRow.children || selectedActionIndex >= actionsRow.children.length) + return; + var buttonX = 0; + for (var i = 0; i < selectedActionIndex; i++) { + var child = actionsRow.children[i]; + if (child) + buttonX += child.width + actionsRow.spacing; + } + + var button = actionsRow.children[selectedActionIndex]; + if (!button) + return; + var buttonRight = buttonX + button.width; + var viewLeft = actionsFlickable.contentX; + var viewRight = viewLeft + actionsFlickable.width; + + if (buttonX < viewLeft) { + actionsFlickable.contentX = Math.max(0, buttonX - Theme.spacingS); + } else if (buttonRight > viewRight) { + actionsFlickable.contentX = Math.min(actionsFlickable.contentWidth - actionsFlickable.width, buttonRight - actionsFlickable.width + Theme.spacingS); + } + } + + function executeSelectedAction() { + if (!controller || !selectedItem || selectedActionIndex >= actions.length) + return; + var action = actions[selectedActionIndex]; + if (action.action === "plugin_action" && typeof action.pluginAction === "function") { + action.pluginAction(); + controller.performSearch(); + controller.itemExecuted(); + } else { + controller.executeAction(selectedItem, action); + } + } +} |