Add support for choosing directories via xdg-desktop-portal

This commit is contained in:
Ilya Fedin 2020-06-01 21:53:11 +04:00 committed by John Preston
parent 9fd62d3892
commit c776f81dc7
3 changed files with 51 additions and 9 deletions

View File

@ -127,13 +127,14 @@ using Type = ::FileDialog::internal::Type;
bool NativeSupported(Type type = Type::ReadFile) { bool NativeSupported(Type type = Type::ReadFile) {
// use gtk file dialog on gtk-based desktop environments // use gtk file dialog on gtk-based desktop environments
// or if QT_QPA_PLATFORMTHEME=(gtk2|gtk3) // or if QT_QPA_PLATFORMTHEME=(gtk2|gtk3)
// or if portals is used and operation is not to open folder // or if portals is used and operation is to open folder
// (it isn't supported by portals yet) // and portal doesn't support folder choosing
return Platform::UseGtkFileDialog() return Platform::UseGtkFileDialog()
&& (Platform::DesktopEnvironment::IsGtkBased() && (Platform::DesktopEnvironment::IsGtkBased()
|| Platform::IsGtkIntegrationForced() || Platform::IsGtkIntegrationForced()
|| Platform::UseXDGDesktopPortal()) || Platform::UseXDGDesktopPortal())
&& (!Platform::UseXDGDesktopPortal() || type == Type::ReadFolder) && (!Platform::UseXDGDesktopPortal()
|| (type == Type::ReadFolder && !Platform::CanOpenDirectoryWithPortal()))
&& Platform::internal::GdkHelperLoaded() && Platform::internal::GdkHelperLoaded()
&& (Libs::gtk_widget_hide_on_delete != nullptr) && (Libs::gtk_widget_hide_on_delete != nullptr)
&& (Libs::gtk_clipboard_store != nullptr) && (Libs::gtk_clipboard_store != nullptr)

View File

@ -51,6 +51,10 @@ constexpr auto kDesktopFile = ":/misc/telegramdesktop.desktop"_cs;
constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs; constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs;
constexpr auto kIconName = "telegram"_cs; constexpr auto kIconName = "telegram"_cs;
constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
void PortalAutostart(bool autostart, bool silent = false) { void PortalAutostart(bool autostart, bool silent = false) {
QVariantMap options; QVariantMap options;
@ -63,8 +67,8 @@ void PortalAutostart(bool autostart, bool silent = false) {
options["dbus-activatable"] = false; options["dbus-activatable"] = false;
auto message = QDBusMessage::createMethodCall( auto message = QDBusMessage::createMethodCall(
qsl("org.freedesktop.portal.Desktop"), kXDGDesktopPortalService.utf16(),
qsl("/org/freedesktop/portal/desktop"), kXDGDesktopPortalObjectPath.utf16(),
qsl("org.freedesktop.portal.Background"), qsl("org.freedesktop.portal.Background"),
qsl("RequestBackground")); qsl("RequestBackground"));
@ -84,6 +88,34 @@ void PortalAutostart(bool autostart, bool silent = false) {
} }
} }
} }
uint FileChooserPortalVersion() {
static const auto Result = [&]() -> uint {
auto message = QDBusMessage::createMethodCall(
kXDGDesktopPortalService.utf16(),
kXDGDesktopPortalObjectPath.utf16(),
kPropertiesInterface.utf16(),
qsl("Get"));
message.setArguments({
qsl("org.freedesktop.portal.FileChooser"),
qsl("version")
});
const QDBusReply<uint> reply = QDBusConnection::sessionBus().call(message);
if (reply.isValid()) {
return reply.value();
} else {
LOG(("Error getting FileChooser portal version: %1")
.arg(reply.error().message()));
}
return 0;
}();
return Result;
}
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
bool RunShellCommand(const QByteArray &command) { bool RunShellCommand(const QByteArray &command) {
@ -296,8 +328,8 @@ bool IsQtPluginsBundled() {
bool IsXDGDesktopPortalPresent() { bool IsXDGDesktopPortalPresent() {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
static const auto Result = QDBusInterface( static const auto Result = QDBusInterface(
"org.freedesktop.portal.Desktop", kXDGDesktopPortalService.utf16(),
"/org/freedesktop/portal/desktop").isValid(); kXDGDesktopPortalObjectPath.utf16()).isValid();
return Result; return Result;
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
@ -320,6 +352,14 @@ bool UseXDGDesktopPortal() {
return Result; return Result;
} }
bool CanOpenDirectoryWithPortal() {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED) && !defined TDESKTOP_DISABLE_DBUS_INTEGRATION
return FileChooserPortalVersion() >= 3;
#else // (Qt >= 5.15 || DESKTOP_APP_QT_PATCHED) && !TDESKTOP_DISABLE_DBUS_INTEGRATION
return false;
#endif // (Qt < 5.15 && !DESKTOP_APP_QT_PATCHED) || TDESKTOP_DISABLE_DBUS_INTEGRATION
}
QString ProcessNameByPID(const QString &pid) { QString ProcessNameByPID(const QString &pid) {
constexpr auto kMaxPath = 1024; constexpr auto kMaxPath = 1024;
char result[kMaxPath] = { 0 }; char result[kMaxPath] = { 0 };
@ -682,10 +722,10 @@ void start() {
if (IsXDGDesktopPortalPresent()) { if (IsXDGDesktopPortalPresent()) {
LOG(("XDG Desktop Portal is present!")); LOG(("XDG Desktop Portal is present!"));
if (UseXDGDesktopPortal()) { if (UseXDGDesktopPortal()) {
LOG(("Usage of XDG Desktop Portal is enabled.")); LOG(("Using XDG Desktop Portal."));
qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal"); qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal");
} else { } else {
LOG(("Usage of XDG Desktop Portal is disabled.")); LOG(("Not using XDG Desktop Portal."));
} }
} else { } else {
LOG(("XDG Desktop Portal is not present :(")); LOG(("XDG Desktop Portal is not present :("));

View File

@ -30,6 +30,7 @@ bool IsQtPluginsBundled();
bool IsXDGDesktopPortalPresent(); bool IsXDGDesktopPortalPresent();
bool UseXDGDesktopPortal(); bool UseXDGDesktopPortal();
bool CanOpenDirectoryWithPortal();
QString ProcessNameByPID(const QString &pid); QString ProcessNameByPID(const QString &pid);
QString RealExecutablePath(int argc, char *argv[]); QString RealExecutablePath(int argc, char *argv[]);