From 30c0b28f8744157e00c1ae7804320bb4d88327e0 Mon Sep 17 00:00:00 2001 From: Darius Davis Date: Fri, 9 Feb 2024 09:05:37 +1000 Subject: [PATCH] Qt: Implement "Show in Folder" using DBus. On Linux (and presumably other DBus-using Unix-like OSes), right-clicking on a file on the Welcome page and choosing "Show in Folder" would only ever open the folder, and would not highlight the chosen file. Adding DBus support to function desktop_show_in_folder allows for the file itself to be shown -- subject to support from the user's desktop environment... --- CMakeLists.txt | 8 ++++++++ ui/qt/main.cpp | 7 +++++++ ui/qt/utils/qt_ui_utils.cpp | 41 +++++++++++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71b771ec65..a6b2cb83fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1264,6 +1264,7 @@ if(BUILD_wireshark OR BUILD_logray) Widgets Concurrent Core5Compat + DBus OPTIONAL_COMPONENTS Multimedia ) @@ -1297,6 +1298,10 @@ if(BUILD_wireshark OR BUILD_logray) if(WIN32) list(APPEND QT5_PACKAGELIST Qt5WinExtras) endif() + if(NOT WIN32 AND NOT APPLE) + # DBus is a core component of Qt6, but was an add-on in Qt5. + list(APPEND QT5_OPTIONAL_PACKAGELIST Qt5DBus) + endif() foreach(_qt5_package IN LISTS QT5_PACKAGELIST) find_package(${_qt5_package} REQUIRED ${QT5_FIND_PACKAGE_OPTIONS}) list(APPEND QT5_LIBRARIES ${${_qt5_package}_LIBRARIES}) @@ -1335,6 +1340,9 @@ if(BUILD_wireshark OR BUILD_logray) if(Qt6Multimedia_FOUND OR Qt5Multimedia_FOUND) set(QT_MULTIMEDIA_LIB 1) endif() + if(Qt6DBus_FOUND OR Qt5DBus_FOUND) + set(QT_DBUS_LIB 1) + endif() if(NOT DEFINED MOC_OPTIONS) # Squelch moc verbose "nothing to do" output set(MOC_OPTIONS -nn) diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp index 44e3b7d253..0634e229ca 100644 --- a/ui/qt/main.cpp +++ b/ui/qt/main.cpp @@ -212,6 +212,13 @@ gather_wireshark_qt_compiled_info(feature_list l) #else without_feature(l, "QtMultimedia"); #endif +#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) +#ifdef QT_DBUS_LIB + with_feature(l, "QtDBus"); +#else + without_feature(l, "QtDBus"); +#endif +#endif /* !Q_OS_WIN && !Q_OS_MAC */ const char *update_info = software_update_info(); if (update_info) { diff --git a/ui/qt/utils/qt_ui_utils.cpp b/ui/qt/utils/qt_ui_utils.cpp index 3b42bdf432..ac3ada430c 100644 --- a/ui/qt/utils/qt_ui_utils.cpp +++ b/ui/qt/utils/qt_ui_utils.cpp @@ -23,6 +23,7 @@ #include "ui/ws_ui_util.h" #include +#include #include #include @@ -33,9 +34,14 @@ #include #include #include -#include #include +#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && defined(QT_DBUS_LIB) +#include +#include +#include +#endif + /* * We might want to create our own "wsstring" class with convenience * methods for handling g_malloc()ed strings, GStrings, and a shortcut @@ -246,8 +252,39 @@ void desktop_show_in_folder(const QString file_path) << "tell application \"Finder\" to activate"; QProcess::execute("/usr/bin/osascript", script_args); } +#elif defined(QT_DBUS_LIB) + // First, try the FileManager1 DBus interface's "ShowItems" method. + // https://www.freedesktop.org/wiki/Specifications/file-manager-interface/ + QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.FileManager1"), + QLatin1String("/org/freedesktop/FileManager1"), + QLatin1String("org.freedesktop.FileManager1"), + QLatin1String("ShowItems")); + QStringList uris(QUrl::fromLocalFile(file_path).toString()); + message << uris << QString(); + + message = QDBusConnection::sessionBus().call(message); + success = message.type() == QDBusMessage::ReplyMessage; + + // If that failed, perhaps we are sandboxed. Try using Portal Services. + // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.OpenURI.html + if (!success) { + const int fd = ws_open(QFile::encodeName(file_path), O_CLOEXEC | O_PATH, 0000); + if (fd != -1) { + QDBusUnixFileDescriptor descriptor; + descriptor.giveFileDescriptor(fd); + QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"), + QLatin1String("/org/freedesktop/portal/desktop"), + QLatin1String("org.freedesktop.portal.OpenURI"), + QLatin1String("OpenDirectory")); + message << QString() << QVariant::fromValue(descriptor) << QVariantMap(); + + message = QDBusConnection::sessionBus().call(message); + success = message.type() == QDBusMessage::ReplyMessage; + ws_close(fd); + } + } #else - // Is there a way to highlight the file using xdg-open? + // Any other possibilities to highlight the file before falling back to showing the folder? #endif if (!success) { QFileInfo file_info(file_path);