[utilities/keepsecret] src: Fix selection highlighting, right-click panel behavior

Roshani Kumari <[email protected]> Tue, 4 Aug 2026 13:48:02 +0000 (UTC)
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit bc9046cdfca6cedf38398b602f40601f792854c3 by Roshani Kumari.
Committed on 04/08/2026 at 13:39.
Pushed by roshani into branch 'master'.

Fix selection highlighting, right-click panel behavior

M  +38   -16   src/qml/CollectionContentsPage.qml
M  +23   -0    src/secretitemproxy.cpp
M  +1    -0    src/secretitemproxy.h

https://invent.kde.org/utilities/keepsecret/-/commit/bc9046cdfca6cedf38398b602f40601f792854c3

diff --git a/src/qml/CollectionContentsPage.qml b/src/qml/CollectionContentsPage.qml
index 95df111..dd166d3 100644
--- a/src/qml/CollectionContentsPage.qml
+++ b/src/qml/CollectionContentsPage.qml
@@ -114,23 +114,45 @@ Kirigami.ScrollablePage {
                     : (view.currentIndex !== -1 ? [view.currentIndex] : [])
                 if (indices.length === 0) return
 
+                const singleLabel = indices.length === 1
+                    ? view.model.data(view.model.index(indices[0], 0), Qt.DisplayRole)
+                    : ""
+
                 showDeleteDialog(
                     indices.length > 1 ? i18nc("@title:window", "Delete Secrets") : i18nc("@title:window", "Delete Secret"),
                     indices.length > 1
                         ? i18nc("@label", "Are you sure you want to delete %1 items?", indices.length)
-                        : i18nc("@label", "Are you sure you want to delete this item?"),
+                        : i18nc("@label", "Are you sure you want to delete the item “%1”?", singleLabel),
                     i18nc("@action:check", "I understand that the item(s) will be permanently deleted"),
                     () => {
-                        const paths = indices
-                            .map(idx => view.model.mapToSource(view.model.index(idx, 0)))
-                            .map(sourceIndex => App.collectionModel.dbusPathAt(sourceIndex.row))
-                            .filter(p => p)
-                        paths.forEach(dbusPath => {
-                            App.secretItemForContextMenu.loadItem(App.collectionModel.collectionPath, dbusPath)
+                        const sourceRows = indices
+                            .map(idx => view.model.mapToSource(view.model.index(idx, 0)).row)
+                            .sort((a, b) => b - a)
+
+                        let i = 0
+                        function handler(oldOps, newOps) {
+                            if ((oldOps & StateTracker.ItemDeleting) && !(newOps & StateTracker.ItemDeleting)) {
+                                deleteNext()
+                            }
+                        }
+                        function deleteNext() {
+                            if (i >= sourceRows.length) {
+                                App.stateTracker.operationsChanged.disconnect(handler)
+                                page.selectedIndices = []
+                                page.selectedCount = 0
+                                return
+                            }
+                            const dbusPath = App.collectionModel.dbusPathAt(sourceRows[i])
+                            i++
+                            if (!dbusPath) {
+                                deleteNext()
+                                return
+                            }
+                            App.secretItemForContextMenu.loadItemForDelete(App.collectionModel.collectionPath, dbusPath)
                             App.secretItemForContextMenu.deleteItem()
-                        })
-                        page.selectedIndices = []
-                        page.selectedCount = 0
+                        }
+                        App.stateTracker.operationsChanged.connect(handler)
+                        deleteNext()
                     }
                 );
             }
@@ -343,15 +365,15 @@ Kirigami.ScrollablePage {
             width: view.width
             leftPadding: Kirigami.Units.iconSizes.smallMedium + Kirigami.Units.largeSpacing * 2
             text: model.display
-            highlighted: view.currentIndex == index || page.selectedIndices.indexOf(index) !== -1
+            highlighted: page.selectedIndices.indexOf(index) !== -1
 
             TapHandler {
                 acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
                 acceptedModifiers: Qt.NoModifier
                 onTapped: {
                     if (contextMenu.visible) return
-                    page.selectedIndices = []
-                    page.selectedCount = 0
+                    page.selectedIndices = [index]
+                    page.selectedCount = 1
                     page.lastSelectedIndex = index
                     view.currentIndex = index
                     App.secretItem.loadItem(App.collectionModel.collectionPath, model.dbusPath)
@@ -413,6 +435,7 @@ Kirigami.ScrollablePage {
                                 page.selectedIndices = [index]
                                 page.selectedCount = 1
                                 page.lastSelectedIndex = index
+                                view.currentIndex = index
                                 App.secretItem.close()
                             }
                         } else {
@@ -420,7 +443,6 @@ Kirigami.ScrollablePage {
                             page.selectedCount = 0
                             view.currentIndex = index
                             page.lastSelectedIndex = index
-                            App.secretItem.close()
                         }
                         contextMenu.model = model
                         contextMenu.popup(delegate)
@@ -440,8 +462,8 @@ Kirigami.ScrollablePage {
             Keys.onPressed: (event) => {
                 if (contextMenu.visible) return
                 if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
-                    page.selectedIndices = []
-                    page.selectedCount = 0
+                    page.selectedIndices = [index]
+                    page.selectedCount = 1
                     view.currentIndex = index
                     App.secretItem.loadItem(App.collectionModel.collectionPath, model.dbusPath)
                     view.forceActiveFocus()
diff --git a/src/secretitemproxy.cpp b/src/secretitemproxy.cpp
index b462f46..7e99f6c 100644
--- a/src/secretitemproxy.cpp
+++ b/src/secretitemproxy.cpp
@@ -430,6 +430,29 @@ void SecretItemProxy::loadItem(const QString &collectionPath, const QString &ite
     Q_EMIT attributesChanged(m_attributes);
 }
 
+void SecretItemProxy::loadItemForDelete(const QString &collectionPath, const QString &itemPath)
+{
+    if (collectionPath.isEmpty() || itemPath.isEmpty()) {
+        return;
+    }
+
+    m_dbusPath = itemPath;
+    m_collectionPath = collectionPath;
+
+    if (!StateTracker::instance()->isServiceConnected()) {
+        return;
+    }
+
+    bool ok;
+    m_secretItem = m_secretServiceClient->retrieveItem(itemPath, collectionPath, &ok);
+
+    if (ok) {
+        StateTracker::instance()->clearError();
+    } else {
+        StateTracker::instance()->setError(StateTracker::ItemLoadError, QStringLiteral("Failed to load the secret item"));
+    }
+}
+
 static void onItemUnlockFinished(GObject *source, GAsyncResult *result, gpointer inst)
 {
     Q_UNUSED(inst);
diff --git a/src/secretitemproxy.h b/src/secretitemproxy.h
index 5d7c37e..26c9f53 100644
--- a/src/secretitemproxy.h
+++ b/src/secretitemproxy.h
@@ -66,6 +66,7 @@ public:
                                 const QString &server,
                                 const QString &collectionPath);
     Q_INVOKABLE void loadItem(const QString &collectionPath, const QString &itemPath);
+    Q_INVOKABLE void loadItemForDelete(const QString &collectionPath, const QString &itemPath);
     Q_INVOKABLE void unlock();
     Q_INVOKABLE void save();
     Q_INVOKABLE void revert();