summaryrefslogtreecommitdiffstats
path: root/src/plugins/platformthemes/xdgdesktopportal
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platformthemes/xdgdesktopportal')
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt6
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/main.cpp48
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp198
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h50
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp146
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h42
6 files changed, 222 insertions, 268 deletions
diff --git a/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt b/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt
index 82fb94e31d..6228e83ec7 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt
+++ b/src/plugins/platformthemes/xdgdesktopportal/CMakeLists.txt
@@ -1,4 +1,5 @@
-# Generated from xdgdesktopportal.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## QXdgDesktopPortalThemePlugin Plugin:
@@ -19,6 +20,3 @@ qt_internal_add_plugin(QXdgDesktopPortalThemePlugin
Qt::Gui
Qt::GuiPrivate
)
-
-#### Keys ignored in scope 1:.:.:xdgdesktopportal.pro:<TRUE>:
-# PLUGIN_EXTENDS = "-"
diff --git a/src/plugins/platformthemes/xdgdesktopportal/main.cpp b/src/plugins/platformthemes/xdgdesktopportal/main.cpp
index 64a03d479f..efbc16b3d2 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/main.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/main.cpp
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2017-2018 Red Hat, Inc
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017-2018 Red Hat, Inc
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatformthemeplugin.h>
#include "qxdgdesktopportaltheme.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QXdgDesktopPortalThemePlugin : public QPlatformThemePlugin
{
Q_OBJECT
@@ -54,9 +20,9 @@ public:
QPlatformTheme *QXdgDesktopPortalThemePlugin::create(const QString &key, const QStringList &params)
{
Q_UNUSED(params);
- if (!key.compare(QLatin1String("xdgdesktopportal"), Qt::CaseInsensitive) ||
- !key.compare(QLatin1String("flatpak"), Qt::CaseInsensitive) ||
- !key.compare(QLatin1String("snap"), Qt::CaseInsensitive))
+ if (!key.compare("xdgdesktopportal"_L1, Qt::CaseInsensitive) ||
+ !key.compare("flatpak"_L1, Qt::CaseInsensitive) ||
+ !key.compare("snap"_L1, Qt::CaseInsensitive))
return new QXdgDesktopPortalTheme;
return nullptr;
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
index 85bdd1ab88..1c162be8fc 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
@@ -1,44 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017-2018 Red Hat, Inc
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017-2018 Red Hat, Inc
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qxdgdesktopportalfiledialog_p.h"
+#include <private/qgenericunixservices_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingCall>
@@ -48,6 +16,7 @@
#include <QEventLoop>
#include <QFile>
+#include <QFileInfo>
#include <QMetaType>
#include <QMimeType>
#include <QMimeDatabase>
@@ -57,6 +26,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QDBusArgument &operator <<(QDBusArgument &arg, const QXdgDesktopPortalFileDialog::FilterCondition &filterCondition)
{
arg.beginStructure();
@@ -102,15 +73,12 @@ const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFile
class QXdgDesktopPortalFileDialogPrivate
{
public:
- QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
+ QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
: nativeFileDialog(nativeFileDialog)
+ , fileChooserPortalVersion(fileChooserPortalVersion)
{ }
- WId winId = 0;
- bool directoryMode = false;
- bool modal = false;
- bool multipleFiles = false;
- bool saveFile = false;
+ QEventLoop loop;
QString acceptLabel;
QString directory;
QString title;
@@ -121,19 +89,27 @@ public:
QString selectedMimeTypeFilter;
QString selectedNameFilter;
QStringList selectedFiles;
- QPlatformFileDialogHelper *nativeFileDialog = nullptr;
+ std::unique_ptr<QPlatformFileDialogHelper> nativeFileDialog;
+ uint fileChooserPortalVersion = 0;
+ bool failedToOpen = false;
+ bool directoryMode = false;
+ bool multipleFiles = false;
+ bool saveFile = false;
};
-QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog)
+QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog, uint fileChooserPortalVersion)
: QPlatformFileDialogHelper()
- , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
+ , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog, fileChooserPortalVersion))
{
Q_D(QXdgDesktopPortalFileDialog);
if (d->nativeFileDialog) {
- connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept()));
- connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject()));
+ connect(d->nativeFileDialog.get(), SIGNAL(accept()), this, SIGNAL(accept()));
+ connect(d->nativeFileDialog.get(), SIGNAL(reject()), this, SIGNAL(reject()));
}
+
+ d->loop.connect(this, SIGNAL(accept()), SLOT(quit()));
+ d->loop.connect(this, SIGNAL(reject()), SLOT(quit()));
}
QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
@@ -177,30 +153,34 @@ void QXdgDesktopPortalFileDialog::initializeDialog()
setDirectory(options()->initialDirectory());
}
-void QXdgDesktopPortalFileDialog::openPortal()
+void QXdgDesktopPortalFileDialog::openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
{
Q_D(QXdgDesktopPortalFileDialog);
- QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.portal.FileChooser"),
- d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
- QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId, 16);
-
+ QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
+ "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.FileChooser"_L1,
+ d->saveFile ? "SaveFile"_L1 : "OpenFile"_L1);
QVariantMap options;
if (!d->acceptLabel.isEmpty())
- options.insert(QLatin1String("accept_label"), d->acceptLabel);
-
- options.insert(QLatin1String("modal"), d->modal);
- options.insert(QLatin1String("multiple"), d->multipleFiles);
- options.insert(QLatin1String("directory"), d->directoryMode);
-
- if (d->saveFile) {
- if (!d->directory.isEmpty())
- options.insert(QLatin1String("current_folder"), QFile::encodeName(d->directory).append('\0'));
-
- if (!d->selectedFiles.isEmpty())
- options.insert(QLatin1String("current_file"), QFile::encodeName(d->selectedFiles.first()).append('\0'));
+ options.insert("accept_label"_L1, d->acceptLabel);
+
+ options.insert("modal"_L1, windowModality != Qt::NonModal);
+ options.insert("multiple"_L1, d->multipleFiles);
+ options.insert("directory"_L1, d->directoryMode);
+
+ if (!d->directory.isEmpty())
+ options.insert("current_folder"_L1, QFile::encodeName(d->directory).append('\0'));
+
+ if (d->saveFile && !d->selectedFiles.isEmpty()) {
+ // current_file for the file to be pre-selected, current_name for the file name to be
+ // pre-filled current_file accepts absolute path and requires the file to exist while
+ // current_name accepts just file name
+ QFileInfo selectedFileInfo(d->selectedFiles.constFirst());
+ if (selectedFileInfo.exists())
+ options.insert("current_file"_L1,
+ QFile::encodeName(d->selectedFiles.constFirst()).append('\0'));
+ options.insert("current_name"_L1, selectedFileInfo.fileName());
}
// Insert filters
@@ -233,6 +213,9 @@ void QXdgDesktopPortalFileDialog::openPortal()
filter.name = mimeType.comment();
filter.filterConditions = filterConditions;
+ if (filter.name.isEmpty())
+ filter.name = mimeTypefilter;
+
filterList << filter;
if (!d->selectedMimeTypeFilter.isEmpty() && d->selectedMimeTypeFilter == mimeTypefilter)
@@ -246,7 +229,7 @@ void QXdgDesktopPortalFileDialog::openPortal()
QRegularExpressionMatch match = regexp.match(nameFilter);
if (match.hasMatch()) {
QString userVisibleName = match.captured(1);
- QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), Qt::SkipEmptyParts);
+ QStringList filterStrings = match.captured(2).split(u' ', Qt::SkipEmptyParts);
if (filterStrings.isEmpty()) {
qWarning() << "Filter " << userVisibleName << " is empty and will be ignored.";
@@ -276,32 +259,48 @@ void QXdgDesktopPortalFileDialog::openPortal()
}
if (!filterList.isEmpty())
- options.insert(QLatin1String("filters"), QVariant::fromValue(filterList));
+ options.insert("filters"_L1, QVariant::fromValue(filterList));
if (selectedFilterIndex != -1)
- options.insert(QLatin1String("current_filter"), QVariant::fromValue(filterList[selectedFilterIndex]));
+ options.insert("current_filter"_L1, QVariant::fromValue(filterList[selectedFilterIndex]));
- options.insert(QLatin1String("handle_token"), QStringLiteral("qt%1").arg(QRandomGenerator::global()->generate()));
+ options.insert("handle_token"_L1, QStringLiteral("qt%1").arg(QRandomGenerator::global()->generate()));
// TODO choices a(ssa(ss)s)
// List of serialized combo boxes to add to the file chooser.
- message << parentWindowId << d->title << options;
+ auto unixServices = dynamic_cast<QGenericUnixServices *>(
+ QGuiApplicationPrivate::platformIntegration()->services());
+ if (parent && unixServices)
+ message << unixServices->portalWindowIdentifier(parent);
+ else
+ message << QString();
+
+ message << d->title << options;
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, d, windowFlags, windowModality, parent] (QDBusPendingCallWatcher *watcher) {
QDBusPendingReply<QDBusObjectPath> reply = *watcher;
- if (reply.isError()) {
- Q_EMIT reject();
+ // Any error means the dialog is not shown and we need to fallback
+ d->failedToOpen = reply.isError();
+ if (d->failedToOpen) {
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->show(windowFlags, windowModality, parent);
+ if (d->loop.isRunning())
+ d->nativeFileDialog->exec();
+ } else {
+ Q_EMIT reject();
+ }
} else {
QDBusConnection::sessionBus().connect(nullptr,
reply.value().path(),
- QLatin1String("org.freedesktop.portal.Request"),
- QLatin1String("Response"),
+ "org.freedesktop.portal.Request"_L1,
+ "Response"_L1,
this,
SLOT(gotResponse(uint,QVariantMap)));
}
+ watcher->deleteLater();
});
}
@@ -326,7 +325,7 @@ QUrl QXdgDesktopPortalFileDialog::directory() const
{
Q_D(const QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog())
return d->nativeFileDialog->directory();
return d->directory;
@@ -348,7 +347,7 @@ QList<QUrl> QXdgDesktopPortalFileDialog::selectedFiles() const
{
Q_D(const QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog())
return d->nativeFileDialog->selectedFiles();
QList<QUrl> files;
@@ -403,16 +402,13 @@ void QXdgDesktopPortalFileDialog::exec()
{
Q_D(QXdgDesktopPortalFileDialog);
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) {
+ if (d->nativeFileDialog && useNativeFileDialog()) {
d->nativeFileDialog->exec();
return;
}
// HACK we have to avoid returning until we emit that the dialog was accepted or rejected
- QEventLoop loop;
- loop.connect(this, SIGNAL(accept()), SLOT(quit()));
- loop.connect(this, SIGNAL(reject()), SLOT(quit()));
- loop.exec();
+ d->loop.exec();
}
void QXdgDesktopPortalFileDialog::hide()
@@ -429,13 +425,10 @@ bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowMo
initializeDialog();
- d->modal = windowModality != Qt::NonModal;
- d->winId = parent ? parent->winId() : 0;
-
- if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ if (d->nativeFileDialog && useNativeFileDialog(OpenFallback))
return d->nativeFileDialog->show(windowFlags, windowModality, parent);
- openPortal();
+ openPortal(windowFlags, windowModality, parent);
return true;
}
@@ -445,10 +438,10 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &
Q_D(QXdgDesktopPortalFileDialog);
if (!response) {
- if (results.contains(QLatin1String("uris")))
- d->selectedFiles = results.value(QLatin1String("uris")).toStringList();
+ if (results.contains("uris"_L1))
+ d->selectedFiles = results.value("uris"_L1).toStringList();
- if (results.contains(QLatin1String("current_filter"))) {
+ if (results.contains("current_filter"_L1)) {
const Filter selectedFilter = qdbus_cast<Filter>(results.value(QStringLiteral("current_filter")));
if (!selectedFilter.filterConditions.empty() && selectedFilter.filterConditions[0].type == MimeType) {
// s.a. QXdgDesktopPortalFileDialog::openPortal which basically does the inverse
@@ -465,4 +458,23 @@ void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &
}
}
+bool QXdgDesktopPortalFileDialog::useNativeFileDialog(QXdgDesktopPortalFileDialog::FallbackType fallbackType) const
+{
+ Q_D(const QXdgDesktopPortalFileDialog);
+
+ if (d->failedToOpen && fallbackType != OpenFallback)
+ return true;
+
+ if (d->fileChooserPortalVersion < 3) {
+ if (options()->fileMode() == QFileDialogOptions::Directory)
+ return true;
+ else if (options()->fileMode() == QFileDialogOptions::DirectoryOnly)
+ return true;
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
+
+#include "moc_qxdgdesktopportalfiledialog_p.cpp"
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
index ce1a0720bb..f309307cd6 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017-2018 Red Hat, Inc
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017-2018 Red Hat, Inc
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXDGDESKTOPPORTALFILEDIALOG_P_H
#define QXDGDESKTOPPORTALFILEDIALOG_P_H
@@ -51,6 +15,11 @@ class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
Q_OBJECT
Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
public:
+ enum FallbackType {
+ GenericFallback,
+ OpenFallback
+ };
+
enum ConditionType : uint {
GlobalPattern = 0,
MimeType = 1
@@ -69,7 +38,7 @@ public:
};
typedef QList<Filter> FilterList;
- QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
+ QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr, uint fileChooserPortalVersion = 0);
~QXdgDesktopPortalFileDialog();
bool defaultNameFilterDisables() const override;
@@ -92,7 +61,8 @@ private Q_SLOTS:
private:
void initializeDialog();
- void openPortal();
+ void openPortal(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
+ bool useNativeFileDialog(FallbackType fallbackType = GenericFallback) const;
QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
};
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
index fb324afbd8..355d3e6cc9 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qxdgdesktopportaltheme.h"
#include "qxdgdesktopportalfiledialog_p.h"
@@ -50,14 +14,24 @@
#include <QDBusPendingCall>
#include <QDBusPendingCallWatcher>
#include <QDBusPendingReply>
+#include <QDBusReply>
QT_BEGIN_NAMESPACE
-class QXdgDesktopPortalThemePrivate : public QPlatformThemePrivate
-{
+using namespace Qt::StringLiterals;
+
+class QXdgDesktopPortalThemePrivate : public QObject
+ {
+ Q_OBJECT
public:
+ enum XdgColorschemePref {
+ None,
+ PreferDark,
+ PreferLight
+ };
+
QXdgDesktopPortalThemePrivate()
- : QPlatformThemePrivate()
+ : QObject()
{ }
~QXdgDesktopPortalThemePrivate()
@@ -65,8 +39,44 @@ public:
delete baseTheme;
}
+ /*! \internal
+
+ Converts the given Freedesktop color scheme setting \a colorschemePref to a Qt::ColorScheme value.
+ Specification: https://github.com/flatpak/xdg-desktop-portal/blob/d7a304a00697d7d608821253cd013f3b97ac0fb6/data/org.freedesktop.impl.portal.Settings.xml#L33-L45
+
+ Unfortunately the enum numerical values are not defined identically, so we have to convert them.
+
+ The mapping is as follows:
+
+ Enum Index: Freedesktop definition | Qt definition
+ ----------------------------------- | -------------
+ 0: No preference | 0: Unknown
+ 1: Prefer dark appearance | 2: Dark
+ 2: Prefer light appearance | 1: Light
+ */
+ static Qt::ColorScheme colorSchemeFromXdgPref(const XdgColorschemePref colorschemePref)
+ {
+ switch (colorschemePref) {
+ case PreferDark: return Qt::ColorScheme::Dark;
+ case PreferLight: return Qt::ColorScheme::Light;
+ default: return Qt::ColorScheme::Unknown;
+ }
+ }
+
+public Q_SLOTS:
+ void settingChanged(const QString &group, const QString &key,
+ const QDBusVariant &value)
+ {
+ if (group == "org.freedesktop.appearance"_L1 && key == "color-scheme"_L1) {
+ colorScheme = colorSchemeFromXdgPref(static_cast<XdgColorschemePref>(value.variant().toUInt()));
+ QWindowSystemInterface::handleThemeChange();
+ }
+ }
+
+public:
QPlatformTheme *baseTheme = nullptr;
uint fileChooserPortalVersion = 0;
+ Qt::ColorScheme colorScheme = Qt::ColorScheme::Unknown;
};
QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
@@ -77,7 +87,7 @@ QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
QStringList themeNames;
themeNames += QGuiApplicationPrivate::platform_integration->themeNames();
// 1) Look for a theme plugin.
- for (const QString &themeName : qAsConst(themeNames)) {
+ for (const QString &themeName : std::as_const(themeNames)) {
d->baseTheme = QPlatformThemeFactory::create(themeName, nullptr);
if (d->baseTheme)
break;
@@ -86,7 +96,7 @@ QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
// 2) If no theme plugin was found ask the platform integration to
// create a theme
if (!d->baseTheme) {
- for (const QString &themeName : qAsConst(themeNames)) {
+ for (const QString &themeName : std::as_const(themeNames)) {
d->baseTheme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
if (d->baseTheme)
break;
@@ -99,19 +109,40 @@ QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
d->baseTheme = new QPlatformTheme;
// Get information about portal version
- QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.DBus.Properties"),
- QLatin1String("Get"));
- message << QLatin1String("org.freedesktop.portal.FileChooser") << QLatin1String("version");
+ QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
+ "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.DBus.Properties"_L1,
+ "Get"_L1);
+ message << "org.freedesktop.portal.FileChooser"_L1 << "version"_L1;
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
- QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [d] (QDBusPendingCallWatcher *watcher) {
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [d] (QDBusPendingCallWatcher *watcher) {
QDBusPendingReply<QVariant> reply = *watcher;
if (reply.isValid()) {
d->fileChooserPortalVersion = reply.value().toUInt();
}
+ watcher->deleteLater();
});
+
+ // Get information about system theme preference
+ message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
+ "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.Settings"_L1,
+ "Read"_L1);
+ message << "org.freedesktop.appearance"_L1 << "color-scheme"_L1;
+
+ // this must not be asyncCall() because we have to set appearance now
+ QDBusReply<QVariant> reply = QDBusConnection::sessionBus().call(message);
+ if (reply.isValid()) {
+ const QDBusVariant dbusVariant = qvariant_cast<QDBusVariant>(reply.value());
+ const QXdgDesktopPortalThemePrivate::XdgColorschemePref xdgPref = static_cast<QXdgDesktopPortalThemePrivate::XdgColorschemePref>(dbusVariant.variant().toUInt());
+ d->colorScheme = QXdgDesktopPortalThemePrivate::colorSchemeFromXdgPref(xdgPref);
+ }
+
+ QDBusConnection::sessionBus().connect(
+ "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.Settings"_L1, "SettingChanged"_L1, d_ptr.get(),
+ SLOT(settingChanged(QString, QString, QDBusVariant)));
}
QPlatformMenuItem* QXdgDesktopPortalTheme::createPlatformMenuItem() const
@@ -152,11 +183,12 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
{
Q_D(const QXdgDesktopPortalTheme);
- if (type == FileDialog) {
+ if (type == FileDialog && d->fileChooserPortalVersion) {
// Older versions of FileChooser portal don't support opening directories, therefore we fallback
// to native file dialog opened inside the sandbox to open a directory.
- if (d->fileChooserPortalVersion < 3 && d->baseTheme->usePlatformNativeDialog(type))
- return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
+ if (d->baseTheme->usePlatformNativeDialog(type))
+ return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)),
+ d->fileChooserPortalVersion);
return new QXdgDesktopPortalFileDialog;
}
@@ -190,6 +222,14 @@ QVariant QXdgDesktopPortalTheme::themeHint(ThemeHint hint) const
return d->baseTheme->themeHint(hint);
}
+Qt::ColorScheme QXdgDesktopPortalTheme::colorScheme() const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ if (d->colorScheme == Qt::ColorScheme::Unknown)
+ return d->baseTheme->colorScheme();
+ return d->colorScheme;
+}
+
QPixmap QXdgDesktopPortalTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
{
Q_D(const QXdgDesktopPortalTheme);
@@ -224,3 +264,5 @@ QString QXdgDesktopPortalTheme::standardButtonText(int button) const
}
QT_END_NAMESPACE
+
+#include "qxdgdesktopportaltheme.moc"
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
index d38b3ddda3..1ac04c45e6 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXDGDESKTOPPORTALTHEME_H
#define QXDGDESKTOPPORTALTHEME_H
@@ -70,6 +34,8 @@ public:
QVariant themeHint(ThemeHint hint) const override;
+ Qt::ColorScheme colorScheme() const override;
+
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
QIcon fileIcon(const QFileInfo &fileInfo,
QPlatformTheme::IconOptions iconOptions = { }) const override;