diff --git a/Makefile b/Makefile index 7bf43d0..6b27836 100644 --- a/Makefile +++ b/Makefile @@ -142,13 +142,11 @@ kf5-install: /usr/lib/x86_64-linux-gnu/qt5/qml/org/ollie/private/ install -m644 plasmoid/plugin/qmldir \ /usr/lib/x86_64-linux-gnu/qt5/qml/org/ollie/private/ - # Plasmoid package - cp -a plasmoid /tmp/ollie-plasmoid-kf5 - cp plasmoid/metadata-kf5.json /tmp/ollie-plasmoid-kf5/metadata.json - cp plasmoid/contents/ui/main-kf5.qml /tmp/ollie-plasmoid-kf5/contents/ui/main.qml - kpackagetool5 -t Plasma/Applet -u /tmp/ollie-plasmoid-kf5/ 2>/dev/null || \ - kpackagetool5 -t Plasma/Applet -i /tmp/ollie-plasmoid-kf5/ - $(RM) -r /tmp/ollie-plasmoid-kf5 + # Plasmoid package (direct install — kpackagetool5 -u doesn't overwrite) + mkdir -p /usr/share/plasma/plasmoids/org.ollie.plasmoid/contents/ui + cp plasmoid/metadata-kf5.json /usr/share/plasma/plasmoids/org.ollie.plasmoid/metadata.json + cp plasmoid/contents/ui/main-kf5.qml /usr/share/plasma/plasmoids/org.ollie.plasmoid/contents/ui/main.qml + rm -f /usr/share/plasma/plasmoids/org.ollie.plasmoid/contents/ui/main-kf5.qml # Dolphin service menus + helper scripts mkdir -p ~/.local/share/kio/servicemenus rm -f ~/.local/share/kio/servicemenus/ollie-actions.desktop diff --git a/plasmoid/plugin/olliedbusclient.cpp b/plasmoid/plugin/olliedbusclient.cpp index 7d9b70e..ea3b65f 100644 --- a/plasmoid/plugin/olliedbusclient.cpp +++ b/plasmoid/plugin/olliedbusclient.cpp @@ -233,6 +233,30 @@ void OllieDBusClient::createSessionWithDialog() { // Use xdg-desktop-portal FileChooser — plasmashell is QGuiApplication, // so QFileDialog (QtWidgets) cannot be used. + // + // We use handle_token to make the request object path predictable, then + // connect to the Response signal BEFORE making the call. This avoids a + // race where the portal fires Response before we subscribe to the signal. + static int handleSeq = 0; + QString handleToken = QString("ollie_folder_%1").arg(++handleSeq); + + // Predict the request object path: /org/freedesktop/portal/desktop/request// + QString sender = QDBusConnection::sessionBus().baseService(); + sender.replace('.', '_'); + if (sender.startsWith(':')) + sender = sender.mid(1); + QString requestPath = QString("/org/freedesktop/portal/desktop/request/%1/%2") + .arg(sender, handleToken); + + // Connect to Response BEFORE making the call to avoid race + QDBusConnection::sessionBus().connect( + "org.freedesktop.portal.Desktop", + requestPath, + "org.freedesktop.portal.Request", + "Response", + this, + SLOT(onPortalFolderResponse(uint,QVariantMap))); + QDBusMessage msg = QDBusMessage::createMethodCall( "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", @@ -244,25 +268,25 @@ void OllieDBusClient::createSessionWithDialog() QVariantMap options; options["directory"] = true; options["modal"] = true; + options["handle_token"] = handleToken; msg << parentWindow << title << options; QDBusPendingCall pending = QDBusConnection::sessionBus().asyncCall(msg); auto *watcher = new QDBusPendingCallWatcher(pending, this); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *w) { + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, requestPath](QDBusPendingCallWatcher *w) { w->deleteLater(); QDBusPendingReply reply = *w; - if (reply.isError()) return; - - // Connect to the Response signal on the request object - QString requestPath = reply.value().path(); - QDBusConnection::sessionBus().connect( - "org.freedesktop.portal.Desktop", - requestPath, - "org.freedesktop.portal.Request", - "Response", - this, - SLOT(onPortalFolderResponse(uint,QVariantMap))); + if (reply.isError()) { + // Clean up the signal connection on failure + QDBusConnection::sessionBus().disconnect( + "org.freedesktop.portal.Desktop", + requestPath, + "org.freedesktop.portal.Request", + "Response", + this, + SLOT(onPortalFolderResponse(uint,QVariantMap))); + } }); }