diff --git a/quickshell/Modals/DLauncherV2/AppEditView.qml b/quickshell/Modals/DLauncherV2/AppEditView.qml index 6c97929a8..646c888b2 100644 --- a/quickshell/Modals/DLauncherV2/AppEditView.qml +++ b/quickshell/Modals/DLauncherV2/AppEditView.qml @@ -11,6 +11,8 @@ FocusScope { signal closeRequested + implicitHeight: headerRow.height + editFieldsColumn.height + buttonsRow.height + Theme.outlineWidth + Theme.spacingM * 3 + function loadOverride() { var existing = SessionData.getAppOverride(editAppId); editNameField.text = existing?.name || ""; @@ -62,6 +64,7 @@ FocusScope { spacing: Theme.spacingM Row { + id: headerRow width: parent.width spacing: Theme.spacingM diff --git a/quickshell/Modals/DLauncherV2/LauncherContextMenu.qml b/quickshell/Modals/DLauncherV2/LauncherContextMenu.qml index cc6b6f2b7..a15239395 100644 --- a/quickshell/Modals/DLauncherV2/LauncherContextMenu.qml +++ b/quickshell/Modals/DLauncherV2/LauncherContextMenu.qml @@ -11,7 +11,6 @@ DContextMenu { property var controller: null property var searchField: null property var parentHandler: null - property bool allowEditActions: true property string pinDockId: "" readonly property bool isCoreApp: item?.type === "app" && !!item?.isCore @@ -65,13 +64,12 @@ DContextMenu { text: I18n.tr("Hide App"), action: hideCurrentApp }); - if (allowEditActions) - items.push({ - type: "item", - icon: "edit", - text: I18n.tr("Edit App"), - action: editCurrentApp - }); + items.push({ + type: "item", + icon: "edit", + text: I18n.tr("Edit App"), + action: editCurrentApp + }); } if (item?.actions?.length > 0) { items.push({ diff --git a/quickshell/Modals/DLauncherV2/SpotlightLauncherContent.qml b/quickshell/Modals/DLauncherV2/SpotlightLauncherContent.qml index 986a96e28..50c583392 100644 --- a/quickshell/Modals/DLauncherV2/SpotlightLauncherContent.qml +++ b/quickshell/Modals/DLauncherV2/SpotlightLauncherContent.qml @@ -24,6 +24,10 @@ FocusScope { property real maxResultsHeight: 0 property real resultsInset: LauncherMetrics.spotlightInset + property bool editMode: false + property var editingApp: null + property string editAppId: "" + readonly property bool _hasQuery: root.showResultsWithoutQuery || searchInput.text.length > 0 || root.controller.searchMode === "dmenu" readonly property real _searchBarH: LauncherMetrics.pillHeight readonly property real _searchAreaH: _searchBarH @@ -38,8 +42,10 @@ FocusScope { readonly property real _resultsH: _hasQuery ? Math.min(_resultsContentH, _maxResultsH) : 0 readonly property int _resizeDuration: Theme.expressiveDurations.expressiveFastSpatial readonly property real _frameClipRadius: Math.max(0, (parentModal?.frameBottomRadius ?? 0) - resultsInset) + readonly property real _editAvailableH: maxResultsHeight > 0 ? maxResultsHeight + _searchAreaH : Math.max(LauncherMetrics.maxResultsHeight, (parentModal?.screenHeight ?? Theme.mediumBreakpoint) - (parentModal?.modalY ?? 0) - Theme.spacingL) + readonly property real _editH: Math.min(editLoader.implicitHeight, _editAvailableH) - implicitHeight: _searchAreaH + mesgRow.height + resultsContainer.height + actionPanel.height + implicitHeight: editMode ? _editH + Theme.spacingM * 2 : _searchAreaH + mesgRow.height + resultsContainer.height + actionPanel.height property bool _animateResize: false @@ -68,9 +74,29 @@ FocusScope { function closeTransientUi() { transientSurfaceTracker?.closeAll?.(); actionPanel.hide(); + root._clearEditState(); root.enabled = true; } + function _clearEditState() { + editMode = false; + editingApp = null; + editAppId = ""; + } + + function openEditMode(app) { + if (!app) + return; + editingApp = app; + editAppId = app.id || app.execString || app.exec || ""; + editMode = true; + } + + function closeEditMode() { + root._clearEditState(); + Qt.callLater(root._focusSearch); + } + function _focusSearch() { searchInput.forceActiveFocus(); searchInput.cursorPosition = searchInput.text.length; @@ -84,6 +110,14 @@ FocusScope { } function _handleKey(event) { + if (root.editMode) { + if (event.key === Qt.Key_Escape) { + root.closeEditMode(); + event.accepted = true; + } + return; + } + const hasCtrl = event.modifiers & Qt.ControlModifier; const hasAlt = event.modifiers & Qt.AltModifier; @@ -274,8 +308,9 @@ FocusScope { controller: root.controller searchField: searchInput parentHandler: root - allowEditActions: false transientSurfaceTracker: root.transientSurfaceTracker + + onEditAppRequested: app => root.openEditMode(app) } Connections { @@ -326,6 +361,7 @@ FocusScope { anchors.left: parent.left anchors.right: parent.right height: root._searchAreaH + visible: !root.editMode LauncherSearchField { id: searchInput @@ -372,7 +408,7 @@ FocusScope { anchors.leftMargin: root.resultsInset anchors.rightMargin: root.resultsInset height: _visible ? mesgText.implicitHeight + Theme.spacingS * 2 : 0 - visible: _visible + visible: _visible && !root.editMode StyledText { id: mesgText @@ -394,7 +430,7 @@ FocusScope { height: Theme.outlineWidth z: 1 color: Theme.outlineVariant - visible: root._hasQuery && !(Theme.focusRingWidth > 0 && searchInput.getActiveFocus()) + visible: !root.editMode && root._hasQuery && !(Theme.focusRingWidth > 0 && searchInput.getActiveFocus()) } ClippingRectangle { @@ -408,6 +444,7 @@ FocusScope { bottomLeftRadius: actionPanel.height > 0 ? 0 : root._frameClipRadius bottomRightRadius: bottomLeftRadius height: root._resultsH + visible: !root.editMode Behavior on height { enabled: root._animateResize @@ -442,6 +479,28 @@ FocusScope { anchors.right: parent.right selectedItem: root.controller.selectedItem controller: root.controller + visible: !root.editMode + } + + Loader { + id: editLoader + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: Theme.spacingM + height: root.editMode ? root._editH : 0 + active: root.editMode + visible: active + focus: root.editMode + + sourceComponent: AppEditView { + focus: true + editingApp: root.editingApp + editAppId: root.editAppId + onCloseRequested: root.closeEditMode() + } + + onLoaded: item.loadOverride() } function _cycleCategory(reverse) {