diff options
Diffstat (limited to 'src/plugins/platformthemes/xdgdesktopportal')
7 files changed, 890 insertions, 0 deletions
diff --git a/src/plugins/platformthemes/xdgdesktopportal/main.cpp b/src/plugins/platformthemes/xdgdesktopportal/main.cpp new file mode 100644 index 0000000000..64a03d479f --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/main.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <qpa/qplatformthemeplugin.h> +#include "qxdgdesktopportaltheme.h" + +QT_BEGIN_NAMESPACE + +class QXdgDesktopPortalThemePlugin : public QPlatformThemePlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "xdgdesktopportal.json") + +public: + QPlatformTheme *create(const QString &key, const QStringList ¶ms) override; +}; + +QPlatformTheme *QXdgDesktopPortalThemePlugin::create(const QString &key, const QStringList ¶ms) +{ + Q_UNUSED(params); + if (!key.compare(QLatin1String("xdgdesktopportal"), Qt::CaseInsensitive) || + !key.compare(QLatin1String("flatpak"), Qt::CaseInsensitive) || + !key.compare(QLatin1String("snap"), Qt::CaseInsensitive)) + return new QXdgDesktopPortalTheme; + + return nullptr; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp new file mode 100644 index 0000000000..cda267d24b --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp @@ -0,0 +1,407 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qxdgdesktopportalfiledialog_p.h" + +#include <QtCore/qeventloop.h> + +#include <QtDBus/QtDBus> +#include <QDBusConnection> +#include <QDBusMessage> +#include <QDBusPendingCall> +#include <QDBusPendingCallWatcher> +#include <QDBusPendingReply> + +#include <QMetaType> +#include <QMimeType> +#include <QMimeDatabase> +#include <QRandomGenerator> +#include <QWindow> + +QT_BEGIN_NAMESPACE + +QDBusArgument &operator <<(QDBusArgument &arg, const QXdgDesktopPortalFileDialog::FilterCondition &filterCondition) +{ + arg.beginStructure(); + arg << filterCondition.type << filterCondition.pattern; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFileDialog::FilterCondition &filterCondition) +{ + uint type; + QString filterPattern; + arg.beginStructure(); + arg >> type >> filterPattern; + filterCondition.type = (QXdgDesktopPortalFileDialog::ConditionType)type; + filterCondition.pattern = filterPattern; + arg.endStructure(); + + return arg; +} + +QDBusArgument &operator <<(QDBusArgument &arg, const QXdgDesktopPortalFileDialog::Filter filter) +{ + arg.beginStructure(); + arg << filter.name << filter.filterConditions; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFileDialog::Filter &filter) +{ + QString name; + QXdgDesktopPortalFileDialog::FilterConditionList filterConditions; + arg.beginStructure(); + arg >> name >> filterConditions; + filter.name = name; + filter.filterConditions = filterConditions; + arg.endStructure(); + + return arg; +} + +class QXdgDesktopPortalFileDialogPrivate +{ +public: + QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog) + : nativeFileDialog(nativeFileDialog) + { } + + WId winId = 0; + bool modal = false; + bool multipleFiles = false; + bool saveFile = false; + QString acceptLabel; + QString directory; + QString title; + QStringList nameFilters; + QStringList mimeTypesFilters; + QStringList selectedFiles; + QPlatformFileDialogHelper *nativeFileDialog = nullptr; +}; + +QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog) + : QPlatformFileDialogHelper() + , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog)) +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) { + connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept())); + connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject())); + } +} + +QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog() +{ +} + +void QXdgDesktopPortalFileDialog::initializeDialog() +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) + d->nativeFileDialog->setOptions(options()); + + if (options()->fileMode() == QFileDialogOptions::ExistingFiles) + d->multipleFiles = true; + + if (options()->isLabelExplicitlySet(QFileDialogOptions::Accept)) + d->acceptLabel = options()->labelText(QFileDialogOptions::Accept); + + if (!options()->windowTitle().isEmpty()) + d->title = options()->windowTitle(); + + if (options()->acceptMode() == QFileDialogOptions::AcceptSave) + d->saveFile = true; + + if (!options()->nameFilters().isEmpty()) + d->nameFilters = options()->nameFilters(); + + if (!options()->mimeTypeFilters().isEmpty()) + d->mimeTypesFilters = options()->mimeTypeFilters(); + + setDirectory(options()->initialDirectory()); +} + +void QXdgDesktopPortalFileDialog::openPortal() +{ + Q_D(const 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); + + 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); + + if (d->saveFile) { + if (!d->directory.isEmpty()) + options.insert(QLatin1String("current_folder"), d->directory.toLatin1()); + + if (!d->selectedFiles.isEmpty()) + options.insert(QLatin1String("current_file"), d->selectedFiles.first().toLatin1()); + } + + // Insert filters + qDBusRegisterMetaType<FilterCondition>(); + qDBusRegisterMetaType<FilterConditionList>(); + qDBusRegisterMetaType<Filter>(); + qDBusRegisterMetaType<FilterList>(); + + FilterList filterList; + + if (!d->mimeTypesFilters.isEmpty()) { + for (const QString &mimeTypefilter : d->mimeTypesFilters) { + QMimeDatabase mimeDatabase; + QMimeType mimeType = mimeDatabase.mimeTypeForName(mimeTypefilter); + + // Creates e.g. (1, "image/png") + FilterCondition filterCondition; + filterCondition.type = MimeType; + filterCondition.pattern = mimeTypefilter; + + // Creates e.g. [((1, "image/png"))] + FilterConditionList filterConditions; + filterConditions << filterCondition; + + // Creates e.g. [("Images", [((1, "image/png"))])] + Filter filter; + filter.name = mimeType.comment(); + filter.filterConditions = filterConditions; + + filterList << filter; + } + } else if (!d->nameFilters.isEmpty()) { + for (const QString &filter : d->nameFilters) { + // Do parsing: + // Supported format is ("Images (*.png *.jpg)") + QRegularExpression regexp(QPlatformFileDialogHelper::filterRegExp); + QRegularExpressionMatch match = regexp.match(filter); + if (match.hasMatch()) { + QString userVisibleName = match.captured(1); + QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), QString::SkipEmptyParts); + + FilterConditionList filterConditions; + for (const QString &filterString : filterStrings) { + FilterCondition filterCondition; + filterCondition.type = GlobalPattern; + filterCondition.pattern = filterString; + filterConditions << filterCondition; + } + + Filter filter; + filter.name = userVisibleName; + filter.filterConditions = filterConditions; + + filterList << filter; + } + } + } + + if (!filterList.isEmpty()) + options.insert(QLatin1String("filters"), QVariant::fromValue(filterList)); + + options.insert(QLatin1String("handle_token"), 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; + + QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) { + QDBusPendingReply<QDBusObjectPath> reply = *watcher; + if (reply.isError()) { + Q_EMIT reject(); + } else { + QDBusConnection::sessionBus().connect(nullptr, + reply.value().path(), + QLatin1String("org.freedesktop.portal.Request"), + QLatin1String("Response"), + this, + SLOT(gotResponse(uint,QVariantMap))); + } + }); +} + +bool QXdgDesktopPortalFileDialog::defaultNameFilterDisables() const +{ + return false; +} + +void QXdgDesktopPortalFileDialog::setDirectory(const QUrl &directory) +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) { + d->nativeFileDialog->setOptions(options()); + d->nativeFileDialog->setDirectory(directory); + } + + d->directory = directory.path(); +} + +QUrl QXdgDesktopPortalFileDialog::directory() const +{ + Q_D(const QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) + return d->nativeFileDialog->directory(); + + return d->directory; +} + +void QXdgDesktopPortalFileDialog::selectFile(const QUrl &filename) +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) { + d->nativeFileDialog->setOptions(options()); + d->nativeFileDialog->selectFile(filename); + } + + d->selectedFiles << filename.path(); +} + +QList<QUrl> QXdgDesktopPortalFileDialog::selectedFiles() const +{ + Q_D(const QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) + return d->nativeFileDialog->selectedFiles(); + + QList<QUrl> files; + for (const QString &file : d->selectedFiles) { + files << QUrl(file); + } + return files; +} + +void QXdgDesktopPortalFileDialog::setFilter() +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) { + d->nativeFileDialog->setOptions(options()); + d->nativeFileDialog->setFilter(); + } +} + +void QXdgDesktopPortalFileDialog::selectNameFilter(const QString &filter) +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) { + d->nativeFileDialog->setOptions(options()); + d->nativeFileDialog->selectNameFilter(filter); + } +} + +QString QXdgDesktopPortalFileDialog::selectedNameFilter() const +{ + // TODO + return QString(); +} + +void QXdgDesktopPortalFileDialog::exec() +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) { + 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(); +} + +void QXdgDesktopPortalFileDialog::hide() +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (d->nativeFileDialog) + d->nativeFileDialog->hide(); +} + +bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) +{ + Q_D(QXdgDesktopPortalFileDialog); + + initializeDialog(); + + d->modal = windowModality != Qt::NonModal; + d->winId = parent ? parent->winId() : 0; + + if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) + return d->nativeFileDialog->show(windowFlags, windowModality, parent); + + openPortal(); + + return true; +} + +void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &results) +{ + Q_D(QXdgDesktopPortalFileDialog); + + if (!response) { + if (results.contains(QLatin1String("uris"))) + d->selectedFiles = results.value(QLatin1String("uris")).toStringList(); + + Q_EMIT accept(); + } else { + Q_EMIT reject(); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h new file mode 100644 index 0000000000..c1f1a2c005 --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#ifndef QXDGDESKTOPPORTALFILEDIALOG_P_H +#define QXDGDESKTOPPORTALFILEDIALOG_P_H + +#include <qpa/qplatformdialoghelper.h> +#include <QVector> + +QT_BEGIN_NAMESPACE + +class QXdgDesktopPortalFileDialogPrivate; + +class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog) +public: + enum ConditionType : uint { + GlobalPattern = 0, + MimeType = 1 + }; + // Filters a(sa(us)) + // Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])] + struct FilterCondition { + ConditionType type; + QString pattern; // E.g. '*ico' or 'image/png' + }; + typedef QVector<FilterCondition> FilterConditionList; + + struct Filter { + QString name; // E.g. 'Images' or 'Text + FilterConditionList filterConditions;; // E.g. [(0, '*.ico'), (1, 'image/png')] or [(0, '*.txt')] + }; + typedef QVector<Filter> FilterList; + + QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr); + ~QXdgDesktopPortalFileDialog(); + + bool defaultNameFilterDisables() const override; + QUrl directory() const override; + void setDirectory(const QUrl &directory) override; + void selectFile(const QUrl &filename) override; + QList<QUrl> selectedFiles() const override; + void setFilter() override; + void selectNameFilter(const QString &filter) override; + QString selectedNameFilter() const override; + + void exec() override; + bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override; + void hide() override; + +private Q_SLOTS: + void gotResponse(uint response, const QVariantMap &results); + +private: + void initializeDialog(); + void openPortal(); + + QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::FilterCondition); +Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::FilterConditionList); +Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::Filter); +Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::FilterList); + +#endif // QXDGDESKTOPPORTALFILEDIALOG_P_H + diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp new file mode 100644 index 0000000000..f07ca3f098 --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qxdgdesktopportaltheme.h" +#include "qxdgdesktopportalfiledialog_p.h" + +#include <private/qguiapplication_p.h> +#include <qpa/qplatformtheme_p.h> +#include <qpa/qplatformthemefactory_p.h> +#include <qpa/qplatformintegration.h> + +QT_BEGIN_NAMESPACE + +class QXdgDesktopPortalThemePrivate : public QPlatformThemePrivate +{ +public: + QXdgDesktopPortalThemePrivate() + : QPlatformThemePrivate() + { } + + ~QXdgDesktopPortalThemePrivate() + { + delete baseTheme; + } + + QPlatformTheme *baseTheme; +}; + +QXdgDesktopPortalTheme::QXdgDesktopPortalTheme() + : d_ptr(new QXdgDesktopPortalThemePrivate) +{ + Q_D(QXdgDesktopPortalTheme); + + QStringList themeNames; + themeNames += QGuiApplicationPrivate::platform_integration->themeNames(); + // 1) Look for a theme plugin. + for (const QString &themeName : qAsConst(themeNames)) { + d->baseTheme = QPlatformThemeFactory::create(themeName, nullptr); + if (d->baseTheme) + break; + } + + // 2) If no theme plugin was found ask the platform integration to + // create a theme + if (!d->baseTheme) { + for (const QString &themeName : qAsConst(themeNames)) { + d->baseTheme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName); + if (d->baseTheme) + break; + } + // No error message; not having a theme plugin is allowed. + } + + // 3) Fall back on the built-in "null" platform theme. + if (!d->baseTheme) + d->baseTheme = new QPlatformTheme; +} + +QPlatformMenuItem* QXdgDesktopPortalTheme::createPlatformMenuItem() const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->createPlatformMenuItem(); +} + +QPlatformMenu* QXdgDesktopPortalTheme::createPlatformMenu() const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->createPlatformMenu(); +} + +QPlatformMenuBar* QXdgDesktopPortalTheme::createPlatformMenuBar() const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->createPlatformMenuBar(); +} + +void QXdgDesktopPortalTheme::showPlatformMenuBar() +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->showPlatformMenuBar(); +} + +bool QXdgDesktopPortalTheme::usePlatformNativeDialog(DialogType type) const +{ + Q_D(const QXdgDesktopPortalTheme); + + if (type == FileDialog) + return true; + + return d->baseTheme->usePlatformNativeDialog(type); +} + +QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(DialogType type) const +{ + Q_D(const QXdgDesktopPortalTheme); + + if (type == FileDialog) { + if (d->baseTheme->usePlatformNativeDialog(type)) + return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type))); + + return new QXdgDesktopPortalFileDialog; + } + + return d->baseTheme->createPlatformDialogHelper(type); +} + +#ifndef QT_NO_SYSTEMTRAYICON +QPlatformSystemTrayIcon* QXdgDesktopPortalTheme::createPlatformSystemTrayIcon() const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->createPlatformSystemTrayIcon(); +} +#endif + +const QPalette *QXdgDesktopPortalTheme::palette(Palette type) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->palette(type); +} + +const QFont* QXdgDesktopPortalTheme::font(Font type) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->font(type); +} + +QVariant QXdgDesktopPortalTheme::themeHint(ThemeHint hint) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->themeHint(hint); +} + +QPixmap QXdgDesktopPortalTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->standardPixmap(sp, size); +} + +QIcon QXdgDesktopPortalTheme::fileIcon(const QFileInfo &fileInfo, + QPlatformTheme::IconOptions iconOptions) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->fileIcon(fileInfo, iconOptions); +} + +QIconEngine * QXdgDesktopPortalTheme::createIconEngine(const QString &iconName) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->createIconEngine(iconName); +} + +QList<QKeySequence> QXdgDesktopPortalTheme::keyBindings(QKeySequence::StandardKey key) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->keyBindings(key); +} + +QString QXdgDesktopPortalTheme::standardButtonText(int button) const +{ + Q_D(const QXdgDesktopPortalTheme); + return d->baseTheme->standardButtonText(button); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h new file mode 100644 index 0000000000..b72e676419 --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QXDGDESKTOPPORTALTHEME_H +#define QXDGDESKTOPPORTALTHEME_H + +#include <qpa/qplatformtheme.h> + +QT_BEGIN_NAMESPACE + +class QXdgDesktopPortalThemePrivate; + +class QXdgDesktopPortalTheme : public QPlatformTheme +{ + Q_DECLARE_PRIVATE(QXdgDesktopPortalTheme) +public: + QXdgDesktopPortalTheme(); + + QPlatformMenuItem *createPlatformMenuItem() const override; + QPlatformMenu *createPlatformMenu() const override; + QPlatformMenuBar *createPlatformMenuBar() const override; + void showPlatformMenuBar() override; + + bool usePlatformNativeDialog(DialogType type) const override; + QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override; + +#ifndef QT_NO_SYSTEMTRAYICON + QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override; +#endif + + const QPalette *palette(Palette type = SystemPalette) const override; + + const QFont *font(Font type = SystemFont) const override; + + QVariant themeHint(ThemeHint hint) const override; + + QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override; + QIcon fileIcon(const QFileInfo &fileInfo, + QPlatformTheme::IconOptions iconOptions = 0) const override; + + QIconEngine *createIconEngine(const QString &iconName) const override; + + QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const override; + + QString standardButtonText(int button) const override; + +private: + QScopedPointer<QXdgDesktopPortalThemePrivate> d_ptr; + Q_DISABLE_COPY(QXdgDesktopPortalTheme) +}; + +QT_END_NAMESPACE + +#endif // QXDGDESKTOPPORTALTHEME_H diff --git a/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json new file mode 100644 index 0000000000..c69062d9a1 --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "xdgdesktopportal", "flatpak", "snap" ] +} diff --git a/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro new file mode 100644 index 0000000000..0a71484cf9 --- /dev/null +++ b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro @@ -0,0 +1,17 @@ +TARGET = qxdgdesktopportal + +PLUGIN_TYPE = platformthemes +PLUGIN_EXTENDS = - +PLUGIN_CLASS_NAME = QXdgDesktopPortalThemePlugin +load(qt_plugin) + +QT += core-private dbus gui-private theme_support-private + +HEADERS += \ + qxdgdesktopportaltheme.h \ + qxdgdesktopportalfiledialog_p.h + +SOURCES += \ + main.cpp \ + qxdgdesktopportaltheme.cpp \ + qxdgdesktopportalfiledialog.cpp |