1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00
Files
DankMaterialShell/quickshell/Modals/Spotlight/SpotlightContextMenuContent.qml

293 lines
10 KiB
QML

import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
property var currentApp: null
property var appLauncher: null
property int selectedMenuIndex: 0
property bool keyboardNavigation: false
signal hideRequested()
readonly property var desktopEntry: (currentApp && !currentApp.isPlugin && appLauncher && appLauncher._uniqueApps && currentApp.appIndex >= 0 && currentApp.appIndex < appLauncher._uniqueApps.length) ? appLauncher._uniqueApps[currentApp.appIndex] : null
readonly property var menuItems: {
const items = [];
const appId = desktopEntry ? (desktopEntry.id || desktopEntry.execString || "") : "";
const isPinned = SessionData.isPinnedApp(appId);
items.push({
type: "item",
icon: isPinned ? "keep_off" : "push_pin",
text: isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock"),
action: togglePin
});
if (desktopEntry && desktopEntry.actions) {
items.push({
type: "separator"
});
for (let i = 0; i < desktopEntry.actions.length; i++) {
const act = desktopEntry.actions[i];
items.push({
type: "item",
text: act.name || "",
action: () => launchAction(act)
});
}
}
items.push({
type: "separator",
hidden: !desktopEntry || !desktopEntry.actions || desktopEntry.actions.length === 0
});
items.push({
type: "item",
icon: "launch",
text: I18n.tr("Launch"),
action: launchCurrentApp
});
if (SessionService.nvidiaCommand) {
items.push({
type: "separator"
});
items.push({
type: "item",
icon: "memory",
text: I18n.tr("Launch on dGPU"),
action: launchWithNvidia
});
}
return items;
}
readonly property int visibleItemCount: {
let count = 0;
for (let i = 0; i < menuItems.length; i++) {
if (menuItems[i].type === "item" && !menuItems[i].hidden) {
count++;
}
}
return count;
}
function selectNext() {
if (visibleItemCount > 0) {
selectedMenuIndex = (selectedMenuIndex + 1) % visibleItemCount;
}
}
function selectPrevious() {
if (visibleItemCount > 0) {
selectedMenuIndex = (selectedMenuIndex - 1 + visibleItemCount) % visibleItemCount;
}
}
function togglePin() {
if (!desktopEntry)
return;
const appId = desktopEntry.id || desktopEntry.execString || "";
if (SessionData.isPinnedApp(appId))
SessionData.removePinnedApp(appId);
else
SessionData.addPinnedApp(appId);
hideRequested();
}
function launchCurrentApp() {
if (currentApp && appLauncher)
appLauncher.launchApp(currentApp);
hideRequested();
}
function launchWithNvidia() {
if (desktopEntry) {
SessionService.launchDesktopEntry(desktopEntry, true);
if (appLauncher && currentApp) {
appLauncher.appLaunched(currentApp);
}
}
hideRequested();
}
function launchAction(action) {
if (desktopEntry) {
SessionService.launchDesktopAction(desktopEntry, action);
if (appLauncher && currentApp) {
appLauncher.appLaunched(currentApp);
}
}
hideRequested();
}
function activateSelected() {
let itemIndex = 0;
for (let i = 0; i < menuItems.length; i++) {
if (menuItems[i].type === "item" && !menuItems[i].hidden) {
if (itemIndex === selectedMenuIndex) {
menuItems[i].action();
return;
}
itemIndex++;
}
}
}
property alias keyboardHandler: keyboardHandler
implicitWidth: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
implicitHeight: menuColumn.implicitHeight + Theme.spacingS * 2
width: implicitWidth
height: implicitHeight
Rectangle {
id: menuContainer
anchors.fill: parent
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
Rectangle {
anchors.fill: parent
anchors.topMargin: 4
anchors.leftMargin: 2
anchors.rightMargin: -2
anchors.bottomMargin: -4
radius: parent.radius
color: Qt.rgba(0, 0, 0, 0.15)
z: -1
}
Item {
id: keyboardHandler
anchors.fill: parent
focus: keyboardNavigation
Keys.onPressed: event => {
if (event.key === Qt.Key_Down) {
selectNext();
event.accepted = true;
} else if (event.key === Qt.Key_Up) {
selectPrevious();
event.accepted = true;
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
activateSelected();
event.accepted = true;
} else if (event.key === Qt.Key_Escape) {
hideRequested();
event.accepted = true;
}
}
Column {
id: menuColumn
anchors.fill: parent
anchors.margins: Theme.spacingS
spacing: 1
Repeater {
model: menuItems
Item {
width: parent.width
height: modelData.type === "separator" ? 5 : 32
visible: !modelData.hidden
property int itemIndex: {
let count = 0;
for (let i = 0; i < index; i++) {
if (menuItems[i].type === "item" && !menuItems[i].hidden) {
count++;
}
}
return count;
}
Rectangle {
visible: modelData.type === "separator"
width: parent.width - Theme.spacingS * 2
height: parent.height
anchors.horizontalCenter: parent.horizontalCenter
color: "transparent"
Rectangle {
anchors.centerIn: parent
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
}
Rectangle {
visible: modelData.type === "item"
width: parent.width
height: parent.height
radius: Theme.cornerRadius
color: {
if (keyboardNavigation && selectedMenuIndex === itemIndex) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2);
}
return mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent";
}
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
Item {
width: Theme.iconSize - 2
height: Theme.iconSize - 2
anchors.verticalCenter: parent.verticalCenter
DankIcon {
visible: modelData.icon !== undefined && modelData.icon !== ""
name: modelData.icon || ""
size: Theme.iconSize - 2
color: Theme.surfaceText
opacity: 0.7
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
text: modelData.text || ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
width: parent.width - (Theme.iconSize - 2) - Theme.spacingS
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: {
keyboardNavigation = false;
selectedMenuIndex = itemIndex;
}
onClicked: modelData.action()
}
}
}
}
}
}
}
}