diff --git a/patch/qtbase-flatpak-portals-filechooser.patch b/patch/qtbase-flatpak-portals-filechooser.patch index ac4f324..c1731a5 100644 --- a/patch/qtbase-flatpak-portals-filechooser.patch +++ b/patch/qtbase-flatpak-portals-filechooser.patch @@ -1,1026 +1,1026 @@ From 84731fbb2bafe4d92bec6cc60db5115279bc6e38 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 11 Dec 2017 09:53:49 +0100 Subject: Add support for FileChooser flatpak portal Adds support for FileChooser Flatpak portal. To support them we just do specific DBus calls, which are then caught and forwarded by xdg-desktop- portal daemon/service. This is needed for Qt applications running in sandbox. [ChangeLog][Platform Specific Changes][Linux] Added support for flatpak portals. Flatpak is a software utility for software deployment and package management. It provides a sandbox environment in which users can run applications in isolation from the rest of the system. To communicate with the system flatpak uses portals, which are designed to be a bridge between sandboxed applications and desktop/system running on user's computer. Flatpak runs this service (called xdg-desktop-portal) automatically. It exports the portals via DBus and they are visible by default to all applications running under Flatpak. Change-Id: I4de1402434ba7cbcc805eab51c30f84f8ba0c5c5 Reviewed-by: Thiago Macieira diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index b26567a..762e0d3 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -244,6 +245,15 @@ static inline void clearFontUnlocked() QGuiApplicationPrivate::app_font = 0; } +static bool checkRunningUnderFlatpak() +{ +#if QT_CONFIG(dbus) + return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty(); +#else + return false; +#endif // QT_CONFIG(dbus) +} + // Using aggregate initialization instead of ctor so we can have a POD global static #define Q_WINDOW_GEOMETRY_SPECIFICATION_INITIALIZER { Qt::TopLeftCorner, -1, -1, -1, -1 } @@ -1173,16 +1183,21 @@ static void init_platform(const QString &pluginArgument, const QString &platform if (!platformThemeName.isEmpty()) themeNames.append(platformThemeName); - // 2) Ask the platform integration for a list of theme names + // 2) Special case - check whether we are in sandbox to use flatpak platform theme for portals support + if (checkRunningUnderFlatpak()) { + themeNames.append(QStringLiteral("flatpak")); + } + + // 3) Ask the platform integration for a list of theme names themeNames += QGuiApplicationPrivate::platform_integration->themeNames(); - // 3) Look for a theme plugin. + // 4) Look for a theme plugin. for (const QString &themeName : qAsConst(themeNames)) { QGuiApplicationPrivate::platform_theme = QPlatformThemeFactory::create(themeName, platformPluginPath); if (QGuiApplicationPrivate::platform_theme) break; } - // 4) If no theme plugin was found ask the platform integration to + // 5) If no theme plugin was found ask the platform integration to // create a theme if (!QGuiApplicationPrivate::platform_theme) { for (const QString &themeName : qAsConst(themeNames)) { @@ -1193,7 +1208,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform // No error message; not having a theme plugin is allowed. } - // 5) Fall back on the built-in "null" platform theme. + // 6) Fall back on the built-in "null" platform theme. if (!QGuiApplicationPrivate::platform_theme) QGuiApplicationPrivate::platform_theme = new QPlatformTheme; diff --git a/src/plugins/platformthemes/flatpak/flatpak.json b/src/plugins/platformthemes/flatpak/flatpak.json new file mode 100644 index 0000000..71f834f --- /dev/null +++ b/src/plugins/platformthemes/flatpak/flatpak.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "flatpak" ] +} diff --git a/src/plugins/platformthemes/flatpak/flatpak.pro b/src/plugins/platformthemes/flatpak/flatpak.pro new file mode 100644 index 0000000..1e5dbb7 --- /dev/null +++ b/src/plugins/platformthemes/flatpak/flatpak.pro @@ -0,0 +1,17 @@ +TARGET = qflatpak + +PLUGIN_TYPE = platformthemes +PLUGIN_EXTENDS = - +PLUGIN_CLASS_NAME = QFlatpakThemePlugin +load(qt_plugin) + +QT += core-private dbus gui-private theme_support-private + +HEADERS += \ + qflatpaktheme.h \ + qflatpakfiledialog_p.h + +SOURCES += \ + main.cpp \ + qflatpaktheme.cpp \ + qflatpakfiledialog.cpp diff --git a/src/plugins/platformthemes/flatpak/main.cpp b/src/plugins/platformthemes/flatpak/main.cpp new file mode 100644 index 0000000..7888eed --- /dev/null +++ b/src/plugins/platformthemes/flatpak/main.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 +#include "qflatpaktheme.h" + +QT_BEGIN_NAMESPACE + +class QFlatpakThemePlugin : public QPlatformThemePlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "flatpak.json") + +public: + QPlatformTheme *create(const QString &key, const QStringList ¶ms) override; +}; + +QPlatformTheme *QFlatpakThemePlugin::create(const QString &key, const QStringList ¶ms) +{ + Q_UNUSED(params); + if (!key.compare(QLatin1String("flatpak"), Qt::CaseInsensitive)) + return new QFlatpakTheme; + + return nullptr; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp new file mode 100644 index 0000000..1a24015 --- /dev/null +++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp @@ -0,0 +1,352 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qflatpakfiledialog_p.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QDBusArgument &operator <<(QDBusArgument &arg, const QFlatpakFileDialog::FilterCondition &filterCondition) +{ + arg.beginStructure(); + arg << filterCondition.type << filterCondition.pattern; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator >>(const QDBusArgument &arg, QFlatpakFileDialog::FilterCondition &filterCondition) +{ + uint type; + QString filterPattern; + arg.beginStructure(); + arg >> type >> filterPattern; + filterCondition.type = (QFlatpakFileDialog::ConditionType)type; + filterCondition.pattern = filterPattern; + arg.endStructure(); + + return arg; +} + +QDBusArgument &operator <<(QDBusArgument &arg, const QFlatpakFileDialog::Filter filter) +{ + arg.beginStructure(); + arg << filter.name << filter.filterConditions; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator >>(const QDBusArgument &arg, QFlatpakFileDialog::Filter &filter) +{ + QString name; + QFlatpakFileDialog::FilterConditionList filterConditions; + arg.beginStructure(); + arg >> name >> filterConditions; + filter.name = name; + filter.filterConditions = filterConditions; + arg.endStructure(); + + return arg; +} + +class QFlatpakFileDialogPrivate +{ +public: + WId winId = 0; + bool modal = false; + bool multipleFiles = false; + bool saveFile = false; + QString acceptLabel; + QString directory; + QString title; + QStringList nameFilters; + QStringList mimeTypesFilters; + QStringList selectedFiles; +}; + +QFlatpakFileDialog::QFlatpakFileDialog() + : QPlatformFileDialogHelper() + , d_ptr(new QFlatpakFileDialogPrivate) +{ +} + +QFlatpakFileDialog::~QFlatpakFileDialog() +{ +} + +void QFlatpakFileDialog::initializeDialog() +{ + Q_D(QFlatpakFileDialog); + + 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 QFlatpakFileDialog::openPortal() +{ + Q_D(const QFlatpakFileDialog); + + 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(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + 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(QLatin1String(" ")); ++ 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)); + + // 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 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 QFlatpakFileDialog::defaultNameFilterDisables() const +{ + return false; +} + +void QFlatpakFileDialog::setDirectory(const QUrl &directory) +{ + Q_D(QFlatpakFileDialog); + + d->directory = directory.path(); +} + +QUrl QFlatpakFileDialog::directory() const +{ + Q_D(const QFlatpakFileDialog); + + return d->directory; +} + +void QFlatpakFileDialog::selectFile(const QUrl &filename) +{ + Q_D(QFlatpakFileDialog); + + d->selectedFiles << filename.path(); +} + +QList QFlatpakFileDialog::selectedFiles() const +{ + Q_D(const QFlatpakFileDialog); + + QList files; + for (const QString &file : d->selectedFiles) { + files << QUrl(file); + } + return files; +} + +void QFlatpakFileDialog::setFilter() +{ + // TODO +} + +void QFlatpakFileDialog::selectNameFilter(const QString &filter) +{ + Q_UNUSED(filter); + // TODO +} + +QString QFlatpakFileDialog::selectedNameFilter() const +{ + // TODO + return QString(); +} + +void QFlatpakFileDialog::exec() +{ + // 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 QFlatpakFileDialog::hide() +{ +} + +bool QFlatpakFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) +{ + Q_D(QFlatpakFileDialog); + Q_UNUSED(windowFlags); + + initializeDialog(); + + d->modal = windowModality != Qt::NonModal; + d->winId = parent ? parent->winId() : 0; + + openPortal(); + + return true; +} + +void QFlatpakFileDialog::gotResponse(uint response, const QVariantMap &results) +{ + Q_D(QFlatpakFileDialog); + + 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/flatpak/qflatpakfiledialog_p.h b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h new file mode 100644 index 0000000..f3e195f --- /dev/null +++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QFLATPAKFILEDIALOG_P_H +#define QFLATPAKFILEDIALOG_P_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QFlatpakFileDialogPrivate; + +class QFlatpakFileDialog : public QPlatformFileDialogHelper +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QFlatpakFileDialog) +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 FilterConditionList; + + struct Filter { + QString name; // E.g. 'Images' or 'Text + FilterConditionList filterConditions;; // E.g. [(0, '*.ico'), (1, 'image/png')] or [(0, '*.txt')] + }; + typedef QVector FilterList; + + QFlatpakFileDialog(); + ~QFlatpakFileDialog(); + + bool defaultNameFilterDisables() const override; + QUrl directory() const override; + void setDirectory(const QUrl &directory) override; + void selectFile(const QUrl &filename) override; + QList 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 d_ptr; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterCondition); +Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterConditionList); +Q_DECLARE_METATYPE(QFlatpakFileDialog::Filter); +Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterList); + +#endif // QFLATPAKFILEDIALOG_P_H + diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp new file mode 100644 index 0000000..04abd70 --- /dev/null +++ b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** 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 "qflatpaktheme.h" +#include "qflatpakfiledialog_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QFlatpakThemePrivate : public QPlatformThemePrivate +{ +public: + QFlatpakThemePrivate() + : QPlatformThemePrivate() + { } + + ~QFlatpakThemePrivate() + { + delete baseTheme; + } + + QPlatformTheme *baseTheme; +}; + +QFlatpakTheme::QFlatpakTheme() + : d_ptr(new QFlatpakThemePrivate) +{ + Q_D(QFlatpakTheme); + + 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* QFlatpakTheme::createPlatformMenuItem() const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->createPlatformMenuItem(); + + return QPlatformTheme::createPlatformMenuItem(); +} + +QPlatformMenu* QFlatpakTheme::createPlatformMenu() const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->createPlatformMenu(); + + return QPlatformTheme::createPlatformMenu(); +} + +QPlatformMenuBar* QFlatpakTheme::createPlatformMenuBar() const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->createPlatformMenuBar(); + + return QFlatpakTheme::createPlatformMenuBar(); +} + +void QFlatpakTheme::showPlatformMenuBar() +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->showPlatformMenuBar(); + + return QFlatpakTheme::showPlatformMenuBar(); +} + +bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const +{ + Q_D(const QFlatpakTheme); + + if (type == FileDialog) + return true; + + if (d->baseTheme) + return d->baseTheme->usePlatformNativeDialog(type); + + return QFlatpakTheme::usePlatformNativeDialog(type); +} + +QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type) const +{ + Q_D(const QFlatpakTheme); + + if (type == FileDialog) + return new QFlatpakFileDialog; + + if (d->baseTheme) + return d->baseTheme->createPlatformDialogHelper(type); + + return QFlatpakTheme::createPlatformDialogHelper(type); +} + +#ifndef QT_NO_SYSTEMTRAYICON +QPlatformSystemTrayIcon* QFlatpakTheme::createPlatformSystemTrayIcon() const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->createPlatformSystemTrayIcon(); + + return QPlatformTheme::createPlatformSystemTrayIcon(); +} +#endif + +const QPalette *QFlatpakTheme::palette(Palette type) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->palette(type); + + return QPlatformTheme::palette(type); +} + +const QFont* QFlatpakTheme::font(Font type) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->font(type); + + return QPlatformTheme::font(type); +} + +QVariant QFlatpakTheme::themeHint(ThemeHint hint) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->themeHint(hint); + + return QPlatformTheme::themeHint(hint); +} + +QPixmap QFlatpakTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->standardPixmap(sp, size); + + return QPlatformTheme::standardPixmap(sp, size); +} + +QIcon QFlatpakTheme::fileIcon(const QFileInfo &fileInfo, + QPlatformTheme::IconOptions iconOptions) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->fileIcon(fileInfo, iconOptions); + + return QPlatformTheme::fileIcon(fileInfo, iconOptions); +} + +QIconEngine * QFlatpakTheme::createIconEngine(const QString &iconName) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->createIconEngine(iconName); + + return QPlatformTheme::createIconEngine(iconName); +} + +QList QFlatpakTheme::keyBindings(QKeySequence::StandardKey key) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->keyBindings(key); + + return QPlatformTheme::keyBindings(key); +} + +QString QFlatpakTheme::standardButtonText(int button) const +{ + Q_D(const QFlatpakTheme); + + if (d->baseTheme) + return d->baseTheme->standardButtonText(button); + + return QPlatformTheme::standardButtonText(button); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.h b/src/plugins/platformthemes/flatpak/qflatpaktheme.h new file mode 100644 index 0000000..fcaac5b --- /dev/null +++ b/src/plugins/platformthemes/flatpak/qflatpaktheme.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 QFLATPAKTHEME_H +#define QFLATPAKTHEME_H + +#include + +QT_BEGIN_NAMESPACE + +class QFlatpakThemePrivate; + +class QFlatpakTheme : public QPlatformTheme +{ + Q_DECLARE_PRIVATE(QFlatpakTheme) +public: + QFlatpakTheme(); + + 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; + + QIconEngine *createIconEngine(const QString &iconName) const override; + + QList keyBindings(QKeySequence::StandardKey key) const override; + + QString standardButtonText(int button) const override; + +private: + QScopedPointer d_ptr; + Q_DISABLE_COPY(QFlatpakTheme) +}; + +QT_END_NAMESPACE + +#endif // QFLATPAKTHEME_H diff --git a/src/plugins/platformthemes/platformthemes.pro b/src/plugins/platformthemes/platformthemes.pro index 0e2812b..ebf92ba 100644 --- a/src/plugins/platformthemes/platformthemes.pro +++ b/src/plugins/platformthemes/platformthemes.pro @@ -1,4 +1,6 @@ TEMPLATE = subdirs QT_FOR_CONFIG += widgets-private +qtConfig(dbus): SUBDIRS += flatpak + qtHaveModule(widgets):qtConfig(gtk3): SUBDIRS += gtk3