[graphics/koko] src: Show cut files with opacity

Oliver Beard <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 45b8e1364fd31b5a30480c1e5992397d398e611c by Oliver Beard.
Committed on 30/07/2026 at 22:13.
Pushed by olib into branch 'master'.

Show cut files with opacity

Add a class, `CutFileHelper` that the gallery instantiates to know if urls are cut via the clipboard mime type `application/x-kde-cutselection` with data `1`.

A delegate can check whether its url exists in the helper, and show itself with opacity to indicate cutting.

M  +1    -0    src/CMakeLists.txt
A  +43   -0    src/cutfilehelper.cpp     [License: LGPL(v2.1+)]
A  +30   -0    src/cutfilehelper.h     [License: LGPL(v2.1+)]
M  +4    -0    src/qml/gallery/GalleryDelegate.qml
M  +5    -0    src/qml/gallery/GalleryPage.qml

https://invent.kde.org/graphics/koko/-/commit/45b8e1364fd31b5a30480c1e5992397d398e611c

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fe199d90..6703fa0d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -32,6 +32,7 @@ qt_add_library(koko_static STATIC
     printerhelper.cpp
     filedialoghelper.cpp
     resizehelper.cpp
+    cutfilehelper.cpp
 )
 
 kconfig_target_kcfg_file(koko_static
diff --git a/src/cutfilehelper.cpp b/src/cutfilehelper.cpp
new file mode 100644
index 00000000..d296ea06
--- /dev/null
+++ b/src/cutfilehelper.cpp
@@ -0,0 +1,43 @@
+/*
+    SPDX-FileCopyrightText: 2026 Oliver Beard <[email protected]>
+    SPDX-License-Identifier: LGPL-2.1-or-later
+*/
+
+#include <QClipboard>
+#include <QGuiApplication>
+#include <QMimeData>
+#include <QUrl>
+
+#include "cutfilehelper.h"
+
+CutFileHelper::CutFileHelper(QObject *parent)
+    : QObject(parent)
+{
+    QClipboard *clipboard = QGuiApplication::clipboard();
+    connect(clipboard, &QClipboard::dataChanged, this, &CutFileHelper::refresh);
+
+    refresh();
+}
+
+QList<QUrl> CutFileHelper::urls() const
+{
+    return m_urls;
+}
+
+void CutFileHelper::refresh()
+{
+    const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData();
+
+    QList<QUrl> urls;
+
+    if (mimeData) {
+        static const QString cutSelectionMime = QLatin1String("application/x-kde-cutselection");
+
+        if (mimeData->hasFormat(cutSelectionMime) && mimeData->data(cutSelectionMime).trimmed() == "1") {
+            urls = mimeData->urls();
+        }
+    }
+
+    m_urls = std::move(urls);
+    Q_EMIT urlsChanged();
+}
diff --git a/src/cutfilehelper.h b/src/cutfilehelper.h
new file mode 100644
index 00000000..a5896037
--- /dev/null
+++ b/src/cutfilehelper.h
@@ -0,0 +1,30 @@
+/*
+    SPDX-FileCopyrightText: 2026 Oliver Beard <[email protected]>
+    SPDX-License-Identifier: LGPL-2.1-or-later
+*/
+
+#pragma once
+
+#include <QObject>
+#include <qqmlregistration.h>
+
+class CutFileHelper : public QObject
+{
+    Q_OBJECT
+    QML_ELEMENT
+
+    Q_PROPERTY(QList<QUrl> urls READ urls NOTIFY urlsChanged FINAL)
+
+public:
+    explicit CutFileHelper(QObject *parent = nullptr);
+
+    [[nodiscard]] QList<QUrl> urls() const;
+
+Q_SIGNALS:
+    void urlsChanged();
+
+private:
+    void refresh();
+
+    QList<QUrl> m_urls;
+};
diff --git a/src/qml/gallery/GalleryDelegate.qml b/src/qml/gallery/GalleryDelegate.qml
index 659c26d4..dbe3b0cf 100644
--- a/src/qml/gallery/GalleryDelegate.qml
+++ b/src/qml/gallery/GalleryDelegate.qml
@@ -24,6 +24,8 @@ Controls.ItemDelegate {
     required property bool selected
     required property url url
 
+    required property bool isCut
+
     required property bool selectionMode
 
     property alias thumbnailPriority: image.priority
@@ -93,6 +95,8 @@ Controls.ItemDelegate {
                 }
             }
 
+            opacity: root.isCut ? 0.6 : 1
+
             fileItem: root.fileItem
         }
 
diff --git a/src/qml/gallery/GalleryPage.qml b/src/qml/gallery/GalleryPage.qml
index 2eba37a9..382095a7 100644
--- a/src/qml/gallery/GalleryPage.qml
+++ b/src/qml/gallery/GalleryPage.qml
@@ -635,6 +635,10 @@ Kirigami.ScrollablePage {
         model: gallerySortFilterProxyModel
     }
 
+    Koko.CutFileHelper {
+        id: cutFileHelper
+    }
+
     bottomPadding: inlineStatusBar.effectiveHeight
 
     GridView {
@@ -756,6 +760,7 @@ Kirigami.ScrollablePage {
 
             highlighted: gridView.currentIndex == index
             selected: selectionModel.selectedIndexes.includes(gridView.model.index(index, 0)) || (delegateDropAreaLoader.item?.containsDrag ?? false)
+            isCut: cutFileHelper.urls.some(cutUrl => cutUrl.toString() === url.toString())
             selectionMode: page.selectionMode
 
             TapHandler {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.