Refactor qgeneericunixthemes_p.h/cpp
Header and implementation file of QGenericUnixTheme contained several helper functions and classes. It also contained the implementation of QGnomeTheme and QKdeTheme, both of which are not generic. Split qgenericunixthemes_p.h/cpp up into separate files. Group all helpers as static member functions in QGenericUnixTheme. Inherit QGnomeTheme and QKdeTheme from QGenericUnixTheme. Task-number: QTBUG-132929 Change-Id: Idfa6198a2b7f669edd009dc165375a9b2960fcad Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
This commit is contained in:
parent
3bbc9e29ef
commit
53fb13456f
@ -1042,9 +1042,16 @@ qt_internal_extend_target(Gui CONDITION TARGET Qt::DBus AND UNIX AND (QT_FEATURE
|
||||
Qt::DBus
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Gui CONDITION UNIX AND QT_FEATURE_settings AND QT_FEATURE_dbus AND (QT_FEATURE_xcb OR QT_FEATURE_wayland)
|
||||
SOURCES
|
||||
platform/unix/qkdetheme_p.h platform/unix/qkdetheme.cpp
|
||||
platform/unix/qdbuslistener_p.h platform/unix/qdbuslistener.cpp
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Gui CONDITION UNIX AND (QT_FEATURE_xcb OR NOT MACOS) AND (QT_FEATURE_xcb OR NOT UIKIT)
|
||||
SOURCES
|
||||
platform/unix/qgenericunixthemes.cpp platform/unix/qgenericunixthemes_p.h
|
||||
platform/unix/qgenericunixtheme.cpp platform/unix/qgenericunixtheme_p.h
|
||||
platform/unix/qgnometheme_p.h platform/unix/qgnometheme.cpp
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Gui CONDITION TARGET Qt::DBus AND UNIX AND (QT_FEATURE_xcb OR NOT MACOS) AND (QT_FEATURE_xcb OR NOT UIKIT)
|
||||
|
233
src/gui/platform/unix/qdbuslistener.cpp
Normal file
233
src/gui/platform/unix/qdbuslistener.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright (C) 2025 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 "qdbuslistener_p.h"
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <qpa/qplatformservices.h>
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
using namespace Qt::StringLiterals;
|
||||
Q_STATIC_LOGGING_CATEGORY(lcQpaThemeDBus, "qt.qpa.theme.dbus")
|
||||
|
||||
/*!
|
||||
\internal
|
||||
The QDBusListener class listens to the SettingChanged DBus signal
|
||||
and translates it into combinations of the enums \c Provider and \c Setting.
|
||||
Upon construction, it logs success/failure of the DBus connection.
|
||||
|
||||
The signal settingChanged delivers the normalized setting type and the new value as a string.
|
||||
It is emitted on known setting types only.
|
||||
*/
|
||||
QDBusListener::QDBusListener(const QString &service,
|
||||
const QString &path, const QString &interface, const QString &signal)
|
||||
{
|
||||
init (service, path, interface, signal);
|
||||
}
|
||||
|
||||
QDBusListener::QDBusListener()
|
||||
{
|
||||
const auto service = u""_s;
|
||||
const auto path = u"/org/freedesktop/portal/desktop"_s;
|
||||
const auto interface = u"org.freedesktop.portal.Settings"_s;
|
||||
const auto signal = u"SettingChanged"_s;
|
||||
|
||||
init (service, path, interface, signal);
|
||||
}
|
||||
|
||||
namespace {
|
||||
namespace JsonKeys {
|
||||
constexpr auto dbusLocation() { return "DBusLocation"_L1; }
|
||||
constexpr auto dbusKey() { return "DBusKey"_L1; }
|
||||
constexpr auto provider() { return "Provider"_L1; }
|
||||
constexpr auto setting() { return "Setting"_L1; }
|
||||
constexpr auto dbusSignals() { return "DbusSignals"_L1; }
|
||||
constexpr auto root() { return "Q_L1.qpa.DBusSignals"_L1; }
|
||||
} // namespace JsonKeys
|
||||
}
|
||||
|
||||
|
||||
void QDBusListener::init(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &signal)
|
||||
{
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
const bool dBusRunning = dbus.isConnected();
|
||||
bool dBusSignalConnected = false;
|
||||
#define LOG service << path << interface << signal;
|
||||
|
||||
if (dBusRunning) {
|
||||
populateSignalMap();
|
||||
qRegisterMetaType<QDBusVariant>();
|
||||
dBusSignalConnected = dbus.connect(service, path, interface, signal, this,
|
||||
SLOT(onSettingChanged(QString,QString,QDBusVariant)));
|
||||
}
|
||||
|
||||
if (dBusSignalConnected) {
|
||||
// Connection successful
|
||||
qCDebug(lcQpaThemeDBus) << LOG;
|
||||
} else {
|
||||
if (dBusRunning) {
|
||||
// DBus running, but connection failed
|
||||
qCWarning(lcQpaThemeDBus) << "DBus connection failed:" << LOG;
|
||||
} else {
|
||||
// DBus not running
|
||||
qCWarning(lcQpaThemeDBus) << "Session DBus not running.";
|
||||
}
|
||||
qCWarning(lcQpaThemeDBus) << "Application will not react to setting changes.\n"
|
||||
<< "Check your DBus installation.";
|
||||
}
|
||||
#undef LOG
|
||||
}
|
||||
|
||||
void QDBusListener::loadJson(const QString &fileName)
|
||||
{
|
||||
Q_ASSERT(!fileName.isEmpty());
|
||||
#define CHECK(cond, warning)\
|
||||
if (!cond) {\
|
||||
qCWarning(lcQpaThemeDBus) << fileName << warning << "Falling back to default.";\
|
||||
return;\
|
||||
}
|
||||
|
||||
#define PARSE(var, enumeration, string)\
|
||||
enumeration var;\
|
||||
{\
|
||||
bool success;\
|
||||
const int val = QMetaEnum::fromType<enumeration>().keyToValue(string.toLatin1(), &success);\
|
||||
CHECK(success, "Parse Error: Invalid value" << string << "for" << #var);\
|
||||
var = static_cast<enumeration>(val);\
|
||||
}
|
||||
|
||||
QFile file(fileName);
|
||||
CHECK(file.exists(), fileName << "doesn't exist.");
|
||||
CHECK(file.open(QIODevice::ReadOnly), "could not be opened for reading.");
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||
CHECK((error.error == QJsonParseError::NoError), error.errorString());
|
||||
CHECK(doc.isObject(), "Parse Error: Expected root object" << JsonKeys::root());
|
||||
|
||||
const QJsonObject &root = doc.object();
|
||||
CHECK(root.contains(JsonKeys::root()), "Parse Error: Expectned root object" << JsonKeys::root());
|
||||
CHECK(root[JsonKeys::root()][JsonKeys::dbusSignals()].isArray(), "Parse Error: Expected array" << JsonKeys::dbusSignals());
|
||||
|
||||
const QJsonArray &sigs = root[JsonKeys::root()][JsonKeys::dbusSignals()].toArray();
|
||||
CHECK((sigs.count() > 0), "Parse Error: Found empty array" << JsonKeys::dbusSignals());
|
||||
|
||||
for (auto sig = sigs.constBegin(); sig != sigs.constEnd(); ++sig) {
|
||||
CHECK(sig->isObject(), "Parse Error: Expected object array" << JsonKeys::dbusSignals());
|
||||
const QJsonObject &obj = sig->toObject();
|
||||
CHECK(obj.contains(JsonKeys::dbusLocation()), "Parse Error: Expected key" << JsonKeys::dbusLocation());
|
||||
CHECK(obj.contains(JsonKeys::dbusKey()), "Parse Error: Expected key" << JsonKeys::dbusKey());
|
||||
CHECK(obj.contains(JsonKeys::provider()), "Parse Error: Expected key" << JsonKeys::provider());
|
||||
CHECK(obj.contains(JsonKeys::setting()), "Parse Error: Expected key" << JsonKeys::setting());
|
||||
const QString &location = obj[JsonKeys::dbusLocation()].toString();
|
||||
const QString &key = obj[JsonKeys::dbusKey()].toString();
|
||||
const QString &providerString = obj[JsonKeys::provider()].toString();
|
||||
const QString &settingString = obj[JsonKeys::setting()].toString();
|
||||
PARSE(provider, Provider, providerString);
|
||||
PARSE(setting, Setting, settingString);
|
||||
const DBusKey dkey(location, key);
|
||||
CHECK (!m_signalMap.contains(dkey), "Duplicate key" << location << key);
|
||||
m_signalMap.insert(dkey, ChangeSignal(provider, setting));
|
||||
}
|
||||
#undef PARSE
|
||||
#undef CHECK
|
||||
|
||||
if (m_signalMap.count() > 0)
|
||||
qCInfo(lcQpaThemeDBus) << "Successfully imported" << fileName;
|
||||
else
|
||||
qCWarning(lcQpaThemeDBus) << "No data imported from" << fileName << "falling back to default.";
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
const int count = m_signalMap.count();
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
qCDebug(lcQpaThemeDBus) << "Listening to" << count << "signals:";
|
||||
for (auto it = m_signalMap.constBegin(); it != m_signalMap.constEnd(); ++it) {
|
||||
qDebug() << it.key().key << it.key().location << "mapped to"
|
||||
<< it.value().provider << it.value().setting;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void QDBusListener::saveJson(const QString &fileName) const
|
||||
{
|
||||
Q_ASSERT(!m_signalMap.isEmpty());
|
||||
Q_ASSERT(!fileName.isEmpty());
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qCWarning(lcQpaThemeDBus) << fileName << "could not be opened for writing.";
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonArray sigs;
|
||||
for (auto sig = m_signalMap.constBegin(); sig != m_signalMap.constEnd(); ++sig) {
|
||||
const DBusKey &dkey = sig.key();
|
||||
const ChangeSignal &csig = sig.value();
|
||||
QJsonObject obj;
|
||||
obj[JsonKeys::dbusLocation()] = dkey.location;
|
||||
obj[JsonKeys::dbusKey()] = dkey.key;
|
||||
obj[JsonKeys::provider()] = QLatin1StringView(QMetaEnum::fromType<Provider>()
|
||||
.valueToKey(static_cast<int>(csig.provider)));
|
||||
obj[JsonKeys::setting()] = QLatin1StringView(QMetaEnum::fromType<Setting>()
|
||||
.valueToKey(static_cast<int>(csig.setting)));
|
||||
sigs.append(obj);
|
||||
}
|
||||
QJsonObject obj;
|
||||
obj[JsonKeys::dbusSignals()] = sigs;
|
||||
QJsonObject root;
|
||||
root[JsonKeys::root()] = obj;
|
||||
QJsonDocument doc(root);
|
||||
file.write(doc.toJson());
|
||||
file.close();
|
||||
}
|
||||
|
||||
void QDBusListener::populateSignalMap()
|
||||
{
|
||||
m_signalMap.clear();
|
||||
const QString &loadJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS");
|
||||
if (!loadJsonFile.isEmpty())
|
||||
loadJson(loadJsonFile);
|
||||
if (!m_signalMap.isEmpty())
|
||||
return;
|
||||
|
||||
m_signalMap.insert(DBusKey("org.kde.kdeglobals.KDE"_L1, "widgetStyle"_L1),
|
||||
ChangeSignal(Provider::Kde, Setting::ApplicationStyle));
|
||||
|
||||
m_signalMap.insert(DBusKey("org.kde.kdeglobals.General"_L1, "ColorScheme"_L1),
|
||||
ChangeSignal(Provider::Kde, Setting::Theme));
|
||||
|
||||
m_signalMap.insert(DBusKey("org.gnome.desktop.interface"_L1, "gtk-theme"_L1),
|
||||
ChangeSignal(Provider::Gtk, Setting::Theme));
|
||||
|
||||
m_signalMap.insert(DBusKey("org.freedesktop.appearance"_L1, "color-scheme"_L1),
|
||||
ChangeSignal(Provider::Gnome, Setting::ColorScheme));
|
||||
|
||||
const QString &saveJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS_SAVE");
|
||||
if (!saveJsonFile.isEmpty())
|
||||
saveJson(saveJsonFile);
|
||||
}
|
||||
|
||||
std::optional<QDBusListener::ChangeSignal>
|
||||
QDBusListener::findSignal(const QString &location, const QString &key) const
|
||||
{
|
||||
const DBusKey dkey(location, key);
|
||||
std::optional<QDBusListener::ChangeSignal> ret;
|
||||
if (m_signalMap.contains(dkey))
|
||||
ret.emplace(m_signalMap.value(dkey));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QDBusListener::onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value)
|
||||
{
|
||||
auto sig = findSignal(location, key);
|
||||
if (!sig.has_value())
|
||||
return;
|
||||
|
||||
emit settingChanged(sig.value().provider, sig.value().setting, value.variant().toString());
|
||||
}
|
||||
QT_END_NAMESPACE
|
88
src/gui/platform/unix/qdbuslistener_p.h
Normal file
88
src/gui/platform/unix/qdbuslistener_p.h
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright (C) 2025 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 QDBUSLISTENER_P_H
|
||||
#define QDBUSLISTENER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <qpa/qplatformtheme.h>
|
||||
#include <private/qflatmap_p.h>
|
||||
#include <QDBusVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QDBusListener : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum class Provider {
|
||||
Kde,
|
||||
Gtk,
|
||||
Gnome,
|
||||
};
|
||||
Q_ENUM(Provider)
|
||||
|
||||
enum class Setting {
|
||||
Theme,
|
||||
ApplicationStyle,
|
||||
ColorScheme,
|
||||
};
|
||||
Q_ENUM(Setting)
|
||||
|
||||
QDBusListener();
|
||||
QDBusListener(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &signal);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void settingChanged(QDBusListener::Provider provider,
|
||||
QDBusListener::Setting setting,
|
||||
const QString &value);
|
||||
|
||||
private:
|
||||
struct DBusKey
|
||||
{
|
||||
QString location;
|
||||
QString key;
|
||||
DBusKey(const QString &loc, const QString &k) : location(loc), key(k) {};
|
||||
bool operator<(const DBusKey &other) const
|
||||
{
|
||||
return location + key < other.location + other.key;
|
||||
}
|
||||
};
|
||||
|
||||
struct ChangeSignal
|
||||
{
|
||||
Provider provider;
|
||||
Setting setting;
|
||||
ChangeSignal(Provider p, Setting s) : provider(p), setting(s) {}
|
||||
ChangeSignal() {}
|
||||
};
|
||||
|
||||
QFlatMap <DBusKey, ChangeSignal> m_signalMap;
|
||||
|
||||
void init(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &signal);
|
||||
|
||||
std::optional<ChangeSignal> findSignal(const QString &location, const QString &key) const;
|
||||
void populateSignalMap();
|
||||
void loadJson(const QString &fileName);
|
||||
void saveJson(const QString &fileName) const;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
#endif // QDBUSLISTENER_P_H
|
297
src/gui/platform/unix/qgenericunixtheme.cpp
Normal file
297
src/gui/platform/unix/qgenericunixtheme.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
// Copyright (C) 2022 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 "qgenericunixtheme_p.h"
|
||||
#include "qgnometheme_p.h"
|
||||
|
||||
#include <QPalette>
|
||||
#include <QFont>
|
||||
#include <QGuiApplication>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QLoggingCategory>
|
||||
#include <QVariant>
|
||||
#include <QStandardPaths>
|
||||
#include <QStringList>
|
||||
#if QT_CONFIG(mimetype)
|
||||
#include <QMimeDatabase>
|
||||
#endif
|
||||
#if QT_CONFIG(settings)
|
||||
#include <QSettings>
|
||||
#ifndef QT_NO_DBUS
|
||||
#include "qkdetheme_p.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <qpa/qplatformfontdatabase.h> // lcQpaFonts
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <qpa/qplatformservices.h>
|
||||
#include <qpa/qplatformdialoghelper.h>
|
||||
#include <qpa/qplatformtheme_p.h>
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonParseError>
|
||||
#ifndef QT_NO_SYSTEMTRAYICON
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
#include <private/qdbusmenubar_p.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#ifndef QT_NO_DBUS
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
#endif
|
||||
#if QT_CONFIG(mimetype)
|
||||
#include <QtCore/QMimeDatabase>
|
||||
#include <QtCore/QMimeData>
|
||||
#endif
|
||||
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(qLcTray)
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
const char *QGenericUnixTheme::name = "generic";
|
||||
|
||||
QGenericUnixThemePrivate::QGenericUnixThemePrivate()
|
||||
: QPlatformThemePrivate()
|
||||
, systemFont(QLatin1StringView(QGenericUnixTheme::defaultSystemFontNameC),
|
||||
QGenericUnixTheme::defaultSystemFontSize)
|
||||
, fixedFont(QLatin1StringView(QGenericUnixTheme::defaultFixedFontNameC),
|
||||
systemFont.pointSize())
|
||||
{
|
||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
|
||||
}
|
||||
|
||||
QGenericUnixTheme::QGenericUnixTheme(QGenericUnixThemePrivate *p)
|
||||
: QPlatformTheme(p)
|
||||
{}
|
||||
|
||||
QGenericUnixTheme::QGenericUnixTheme()
|
||||
: QPlatformTheme(new QGenericUnixThemePrivate())
|
||||
{}
|
||||
|
||||
const QFont *QGenericUnixTheme::font(Font type) const
|
||||
{
|
||||
Q_D(const QGenericUnixTheme);
|
||||
switch (type) {
|
||||
case QPlatformTheme::SystemFont:
|
||||
return &d->systemFont;
|
||||
case QPlatformTheme::FixedFont:
|
||||
return &d->fixedFont;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *QGenericUnixTheme::createPlatformMenuBar() const
|
||||
{
|
||||
if (isDBusGlobalMenuAvailable())
|
||||
return new QDBusMenuBar();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *QGenericUnixTheme::createPlatformSystemTrayIcon() const
|
||||
{
|
||||
if (shouldUseDBusTray())
|
||||
return new QDBusTrayIcon();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const
|
||||
{
|
||||
switch (hint) {
|
||||
case QPlatformTheme::SystemIconFallbackThemeName:
|
||||
return QVariant(QString(QStringLiteral("hicolor")));
|
||||
case QPlatformTheme::IconThemeSearchPaths:
|
||||
return xdgIconThemePaths();
|
||||
case QPlatformTheme::IconFallbackSearchPaths:
|
||||
return iconFallbackPaths();
|
||||
case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
|
||||
return QVariant(true);
|
||||
case QPlatformTheme::StyleNames: {
|
||||
QStringList styleNames;
|
||||
styleNames << QStringLiteral("Fusion") << QStringLiteral("Windows");
|
||||
return QVariant(styleNames);
|
||||
}
|
||||
case QPlatformTheme::KeyboardScheme:
|
||||
return QVariant(int(X11KeyboardScheme));
|
||||
case QPlatformTheme::UiEffects:
|
||||
return QVariant(int(HoverEffect));
|
||||
case QPlatformTheme::MouseCursorTheme:
|
||||
return QVariant(mouseCursorTheme());
|
||||
case QPlatformTheme::MouseCursorSize:
|
||||
return QVariant(mouseCursorSize());
|
||||
case QPlatformTheme::PreferFileIconFromTheme:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformTheme::themeHint(hint);
|
||||
}
|
||||
|
||||
QStringList QGenericUnixTheme::themeNames()
|
||||
{
|
||||
QStringList result;
|
||||
if (QGuiApplication::desktopSettingsAware()) {
|
||||
const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment();
|
||||
QList<QByteArray> gtkBasedEnvironments;
|
||||
gtkBasedEnvironments << "GNOME"
|
||||
<< "X-CINNAMON"
|
||||
<< "PANTHEON"
|
||||
<< "UNITY"
|
||||
<< "MATE"
|
||||
<< "XFCE"
|
||||
<< "LXDE";
|
||||
const QList<QByteArray> desktopNames = desktopEnvironment.split(':');
|
||||
for (const QByteArray &desktopName : desktopNames) {
|
||||
if (desktopEnvironment == "KDE") {
|
||||
#if !defined QT_NO_DBUS && QT_CONFIG(settings)
|
||||
result.push_back(QLatin1StringView(QKdeTheme::name));
|
||||
#endif
|
||||
} else if (gtkBasedEnvironments.contains(desktopName)) {
|
||||
// prefer the GTK3 theme implementation with native dialogs etc.
|
||||
result.push_back(QStringLiteral("gtk3"));
|
||||
// fallback to the generic Gnome theme if loading the GTK3 theme fails
|
||||
result.push_back(QLatin1StringView(QGnomeTheme::name));
|
||||
} else {
|
||||
// unknown, but lowercase the name (our standard practice) and
|
||||
// remove any "x-" prefix
|
||||
QString s = QString::fromLatin1(desktopName.toLower());
|
||||
result.push_back(s.startsWith("x-"_L1) ? s.mid(2) : s);
|
||||
}
|
||||
}
|
||||
} // desktopSettingsAware
|
||||
result.append(QLatin1StringView(QGenericUnixTheme::name));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\brief Creates a UNIX theme according to the given theme \a name
|
||||
*/
|
||||
QPlatformTheme *QGenericUnixTheme::createUnixTheme(const QString &name)
|
||||
{
|
||||
if (name == QLatin1StringView(QGenericUnixTheme::name))
|
||||
return new QGenericUnixTheme;
|
||||
#if !defined QT_NO_DBUS && QT_CONFIG(settings)
|
||||
if (name == QLatin1StringView(QKdeTheme::name))
|
||||
return QKdeTheme::createKdeTheme();
|
||||
#endif
|
||||
if (name == QLatin1StringView(QGnomeTheme::name))
|
||||
return new QGnomeTheme;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Helper to return the icon theme paths from XDG.
|
||||
QStringList QGenericUnixTheme::xdgIconThemePaths()
|
||||
{
|
||||
QStringList paths;
|
||||
// Add home directory first in search path
|
||||
const QFileInfo homeIconDir(QDir::homePath() + "/.icons"_L1);
|
||||
if (homeIconDir.isDir())
|
||||
paths.prepend(homeIconDir.absoluteFilePath());
|
||||
|
||||
paths.append(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
|
||||
QStringLiteral("icons"),
|
||||
QStandardPaths::LocateDirectory));
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
QStringList QGenericUnixTheme::iconFallbackPaths()
|
||||
{
|
||||
QStringList paths;
|
||||
const QFileInfo pixmapsIconsDir(QStringLiteral("/usr/share/pixmaps"));
|
||||
if (pixmapsIconsDir.isDir())
|
||||
paths.append(pixmapsIconsDir.absoluteFilePath());
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
QString QGenericUnixTheme::mouseCursorTheme()
|
||||
{
|
||||
static QString themeName = qEnvironmentVariable("XCURSOR_THEME");
|
||||
return themeName;
|
||||
}
|
||||
|
||||
QSize QGenericUnixTheme::mouseCursorSize()
|
||||
{
|
||||
constexpr int defaultCursorSize = 24;
|
||||
static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
|
||||
static const int s = xCursorSize > 0 ? xCursorSize : defaultCursorSize;
|
||||
return QSize(s, s);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
static bool checkDBusGlobalMenuAvailable()
|
||||
{
|
||||
const QDBusConnection connection = QDBusConnection::sessionBus();
|
||||
static const QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar");
|
||||
if (const auto iface = connection.interface())
|
||||
return iface->isServiceRegistered(registrarService);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QGenericUnixTheme::isDBusGlobalMenuAvailable()
|
||||
{
|
||||
static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable();
|
||||
return dbusGlobalMenuAvailable;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(mimetype)
|
||||
QIcon QGenericUnixTheme::xdgFileIcon(const QFileInfo &fileInfo)
|
||||
{
|
||||
QMimeDatabase mimeDatabase;
|
||||
QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo);
|
||||
if (!mimeType.isValid())
|
||||
return QIcon();
|
||||
const QString &iconName = mimeType.iconName();
|
||||
if (!iconName.isEmpty()) {
|
||||
const QIcon icon = QIcon::fromTheme(iconName);
|
||||
if (!icon.isNull())
|
||||
return icon;
|
||||
}
|
||||
const QString &genericIconName = mimeType.genericIconName();
|
||||
return genericIconName.isEmpty() ? QIcon() : QIcon::fromTheme(genericIconName);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
bool QGenericUnixTheme::shouldUseDBusTray()
|
||||
{
|
||||
// There's no other tray implementation to fallback to on non-X11
|
||||
// and QDBusTrayIcon can register the icon on the fly after creation
|
||||
if (QGuiApplication::platformName() != "xcb"_L1)
|
||||
return true;
|
||||
const bool result = QDBusMenuConnection().isWatcherRegistered();
|
||||
qCDebug(qLcTray) << "D-Bus tray available:" << result;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Helper functions for implementing QPlatformTheme::fileIcon() for XDG icon themes.
|
||||
QList<QSize> QGenericUnixTheme::availableXdgFileIconSizes()
|
||||
{
|
||||
return QIcon::fromTheme(QStringLiteral("inode-directory")).availableSizes();
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
85
src/gui/platform/unix/qgenericunixtheme_p.h
Normal file
85
src/gui/platform/unix/qgenericunixtheme_p.h
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2020 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 QGENERICUNIXTHEMES_H
|
||||
#define QGENERICUNIXTHEMES_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <qpa/qplatformtheme.h>
|
||||
#include <qpa/qplatformtheme_p.h>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtGui/QFont>
|
||||
#include <QtCore/private/qglobal_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QGenericUnixTheme;
|
||||
class QGenericUnixThemePrivate : public QPlatformThemePrivate
|
||||
{
|
||||
public:
|
||||
QGenericUnixThemePrivate();
|
||||
const QFont systemFont;
|
||||
QFont fixedFont;
|
||||
};
|
||||
|
||||
class Q_GUI_EXPORT QGenericUnixTheme : public QPlatformTheme
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QGenericUnixTheme)
|
||||
|
||||
protected:
|
||||
QGenericUnixTheme(QGenericUnixThemePrivate *p);
|
||||
|
||||
public:
|
||||
QGenericUnixTheme();
|
||||
|
||||
const QFont *font(Font type) const override;
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *createPlatformMenuBar() const override;
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
|
||||
#endif
|
||||
|
||||
static const char *name;
|
||||
|
||||
// Default system font, corresponding to the value returned by 4.8 for
|
||||
// XRender/FontConfig which we can now assume as default.
|
||||
static constexpr char defaultSystemFontNameC[] = "Sans Serif";
|
||||
static constexpr char defaultFixedFontNameC[] = "monospace";
|
||||
enum { defaultSystemFontSize = 9 };
|
||||
|
||||
// Helpers
|
||||
static QStringList xdgIconThemePaths();
|
||||
static QPlatformTheme *createUnixTheme(const QString &name);
|
||||
static QStringList themeNames();
|
||||
protected:
|
||||
static QStringList iconFallbackPaths();
|
||||
static bool isDBusGlobalMenuAvailable();
|
||||
static QString mouseCursorTheme();
|
||||
static QSize mouseCursorSize();
|
||||
static QList<QSize> availableXdgFileIconSizes();
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
static bool shouldUseDBusTray();
|
||||
#endif
|
||||
#if QT_CONFIG(mimetype)
|
||||
static QIcon xdgFileIcon(const QFileInfo &fileInfo);
|
||||
#endif
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QGENERICUNIXTHEMES_H
|
@ -1,123 +0,0 @@
|
||||
// Copyright (C) 2020 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 QGENERICUNIXTHEMES_H
|
||||
#define QGENERICUNIXTHEMES_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <qpa/qplatformtheme.h>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtGui/QFont>
|
||||
#include <QtCore/private/qglobal_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class ResourceHelper
|
||||
{
|
||||
public:
|
||||
ResourceHelper();
|
||||
~ResourceHelper() { clear(); }
|
||||
|
||||
void clear();
|
||||
|
||||
QPalette *palettes[QPlatformTheme::NPalettes];
|
||||
QFont *fonts[QPlatformTheme::NFonts];
|
||||
};
|
||||
|
||||
class QGenericUnixThemePrivate;
|
||||
|
||||
class Q_GUI_EXPORT QGenericUnixTheme : public QPlatformTheme
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QGenericUnixTheme)
|
||||
public:
|
||||
QGenericUnixTheme();
|
||||
|
||||
static QPlatformTheme *createUnixTheme(const QString &name);
|
||||
static QStringList themeNames();
|
||||
|
||||
const QFont *font(Font type) const override;
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
|
||||
static QStringList xdgIconThemePaths();
|
||||
static QStringList iconFallbackPaths();
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *createPlatformMenuBar() const override;
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
|
||||
#endif
|
||||
|
||||
static const char *name;
|
||||
};
|
||||
|
||||
#if QT_CONFIG(settings)
|
||||
class QKdeThemePrivate;
|
||||
|
||||
class QKdeTheme : public QPlatformTheme
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QKdeTheme)
|
||||
public:
|
||||
QKdeTheme(const QStringList& kdeDirs, int kdeVersion);
|
||||
|
||||
static QPlatformTheme *createKdeTheme();
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
|
||||
QIcon fileIcon(const QFileInfo &fileInfo,
|
||||
QPlatformTheme::IconOptions iconOptions = { }) const override;
|
||||
|
||||
const QPalette *palette(Palette type = SystemPalette) const override;
|
||||
Qt::ColorScheme colorScheme() const override;
|
||||
|
||||
const QFont *font(Font type) const override;
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *createPlatformMenuBar() const override;
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
|
||||
#endif
|
||||
|
||||
static const char *name;
|
||||
};
|
||||
#endif // settings
|
||||
|
||||
class QGnomeThemePrivate;
|
||||
|
||||
class Q_GUI_EXPORT QGnomeTheme : public QPlatformTheme
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QGnomeTheme)
|
||||
public:
|
||||
QGnomeTheme();
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
QIcon fileIcon(const QFileInfo &fileInfo,
|
||||
QPlatformTheme::IconOptions = { }) const override;
|
||||
const QFont *font(Font type) const override;
|
||||
QString standardButtonText(int button) const override;
|
||||
|
||||
virtual QString gtkFontName() const;
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *createPlatformMenuBar() const override;
|
||||
Qt::ColorScheme colorScheme() const override;
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
|
||||
#endif
|
||||
|
||||
static const char *name;
|
||||
};
|
||||
|
||||
QPlatformTheme *qt_createUnixTheme();
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QGENERICUNIXTHEMES_H
|
214
src/gui/platform/unix/qgnometheme.cpp
Normal file
214
src/gui/platform/unix/qgnometheme.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
// Copyright (C) 2025 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 "qgnometheme_p.h"
|
||||
#include <qpa/qplatformdialoghelper.h>
|
||||
#include <qpa/qplatformfontdatabase.h>
|
||||
#ifndef QT_NO_DBUS
|
||||
#include "qdbuslistener_p.h"
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
#include <private/qdbusplatformmenu_p.h>
|
||||
#include <private/qdbusmenubar_p.h>
|
||||
#endif
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QGnomeTheme
|
||||
\brief QGnomeTheme is a theme implementation for the Gnome desktop.
|
||||
\since 5.0
|
||||
\internal
|
||||
\ingroup qpa
|
||||
*/
|
||||
const char *QGnomeTheme::name = "gnome";
|
||||
|
||||
QGnomeThemePrivate::QGnomeThemePrivate()
|
||||
{
|
||||
#ifndef QT_NO_DBUS
|
||||
initDbus();
|
||||
#endif // QT_NO_DBUS
|
||||
}
|
||||
QGnomeThemePrivate::~QGnomeThemePrivate()
|
||||
{
|
||||
if (systemFont)
|
||||
delete systemFont;
|
||||
if (fixedFont)
|
||||
delete fixedFont;
|
||||
}
|
||||
|
||||
void QGnomeThemePrivate::configureFonts(const QString >kFontName) const
|
||||
{
|
||||
Q_ASSERT(!systemFont);
|
||||
const int split = gtkFontName.lastIndexOf(QChar::Space);
|
||||
float size = QStringView{gtkFontName}.mid(split + 1).toFloat();
|
||||
QString fontName = gtkFontName.left(split);
|
||||
|
||||
systemFont = new QFont(fontName, size);
|
||||
fixedFont = new QFont(QLatin1StringView(QGenericUnixTheme::defaultFixedFontNameC), systemFont->pointSize());
|
||||
fixedFont->setStyleHint(QFont::TypeWriter);
|
||||
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
bool QGnomeThemePrivate::initDbus()
|
||||
{
|
||||
dbus.reset(new QDBusListener());
|
||||
Q_ASSERT(dbus);
|
||||
|
||||
// Wrap slot in a lambda to avoid inheriting QGnomeThemePrivate from QObject
|
||||
auto wrapper = [this](QDBusListener::Provider provider,
|
||||
QDBusListener::Setting setting,
|
||||
const QString &value) {
|
||||
if (provider != QDBusListener::Provider::Gnome
|
||||
&& provider != QDBusListener::Provider::Gtk) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (setting == QDBusListener::Setting::Theme)
|
||||
updateColorScheme(value);
|
||||
};
|
||||
|
||||
return QObject::connect(dbus.get(), &QDBusListener::settingChanged, dbus.get(), wrapper);
|
||||
}
|
||||
|
||||
void QGnomeThemePrivate::updateColorScheme(const QString &themeName)
|
||||
{
|
||||
const auto oldColorScheme = m_colorScheme;
|
||||
if (themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive)) {
|
||||
m_colorScheme = Qt::ColorScheme::Light;
|
||||
} else if (themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) {
|
||||
m_colorScheme = Qt::ColorScheme::Dark;
|
||||
} else {
|
||||
m_colorScheme = Qt::ColorScheme::Unknown;
|
||||
}
|
||||
|
||||
if (oldColorScheme != m_colorScheme)
|
||||
QWindowSystemInterface::handleThemeChange();
|
||||
}
|
||||
#endif // QT_NO_DBUS
|
||||
|
||||
QGnomeTheme::QGnomeTheme()
|
||||
: QGenericUnixTheme(new QGnomeThemePrivate())
|
||||
{
|
||||
}
|
||||
|
||||
QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
|
||||
{
|
||||
switch (hint) {
|
||||
case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
|
||||
return QVariant(true);
|
||||
case QPlatformTheme::DialogButtonBoxLayout:
|
||||
return QVariant(QPlatformDialogHelper::GnomeLayout);
|
||||
case QPlatformTheme::SystemIconThemeName:
|
||||
return QVariant(QStringLiteral("Adwaita"));
|
||||
case QPlatformTheme::SystemIconFallbackThemeName:
|
||||
return QVariant(QStringLiteral("gnome"));
|
||||
case QPlatformTheme::IconThemeSearchPaths:
|
||||
return QVariant(xdgIconThemePaths());
|
||||
case QPlatformTheme::IconPixmapSizes:
|
||||
return QVariant::fromValue(availableXdgFileIconSizes());
|
||||
case QPlatformTheme::StyleNames: {
|
||||
QStringList styleNames;
|
||||
styleNames << QStringLiteral("Fusion") << QStringLiteral("windows");
|
||||
return QVariant(styleNames);
|
||||
}
|
||||
case QPlatformTheme::KeyboardScheme:
|
||||
return QVariant(int(GnomeKeyboardScheme));
|
||||
case QPlatformTheme::PasswordMaskCharacter:
|
||||
return QVariant(QChar(0x2022));
|
||||
case QPlatformTheme::UiEffects:
|
||||
return QVariant(int(HoverEffect));
|
||||
case QPlatformTheme::ButtonPressKeys:
|
||||
return QVariant::fromValue(
|
||||
QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
|
||||
case QPlatformTheme::PreselectFirstFileInDirectory:
|
||||
return true;
|
||||
case QPlatformTheme::MouseCursorTheme:
|
||||
return QVariant(mouseCursorTheme());
|
||||
case QPlatformTheme::MouseCursorSize:
|
||||
return QVariant(mouseCursorSize());
|
||||
case QPlatformTheme::PreferFileIconFromTheme:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformTheme::themeHint(hint);
|
||||
}
|
||||
|
||||
QIcon QGnomeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const
|
||||
{
|
||||
#if QT_CONFIG(mimetype)
|
||||
return xdgFileIcon(fileInfo);
|
||||
#else
|
||||
Q_UNUSED(fileInfo);
|
||||
return QIcon();
|
||||
#endif
|
||||
}
|
||||
|
||||
const QFont *QGnomeTheme::font(Font type) const
|
||||
{
|
||||
Q_D(const QGnomeTheme);
|
||||
if (!d->systemFont)
|
||||
d->configureFonts(gtkFontName());
|
||||
switch (type) {
|
||||
case QPlatformTheme::SystemFont:
|
||||
return d->systemFont;
|
||||
case QPlatformTheme::FixedFont:
|
||||
return d->fixedFont;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QString QGnomeTheme::gtkFontName() const
|
||||
{
|
||||
return QStringLiteral("%1 %2").arg(QLatin1StringView(defaultSystemFontNameC))
|
||||
.arg(defaultSystemFontSize);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const
|
||||
{
|
||||
if (isDBusGlobalMenuAvailable())
|
||||
return new QDBusMenuBar();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Qt::ColorScheme QGnomeTheme::colorScheme() const
|
||||
{
|
||||
return d_func()->m_colorScheme;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *QGnomeTheme::createPlatformSystemTrayIcon() const
|
||||
{
|
||||
if (shouldUseDBusTray())
|
||||
return new QDBusTrayIcon();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString QGnomeTheme::standardButtonText(int button) const
|
||||
{
|
||||
switch (button) {
|
||||
case QPlatformDialogHelper::Ok:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&OK");
|
||||
case QPlatformDialogHelper::Save:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&Save");
|
||||
case QPlatformDialogHelper::Cancel:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&Cancel");
|
||||
case QPlatformDialogHelper::Close:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&Close");
|
||||
case QPlatformDialogHelper::Discard:
|
||||
return QCoreApplication::translate("QGnomeTheme", "Close without Saving");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformTheme::standardButtonText(button);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
74
src/gui/platform/unix/qgnometheme_p.h
Normal file
74
src/gui/platform/unix/qgnometheme_p.h
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2025 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 QGNOMETHEME_P_H
|
||||
#define QGNOMETHEME_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qgenericunixtheme_p.h"
|
||||
#include <qpa/qplatformtheme.h>
|
||||
#include <qpa/qplatformtheme_p.h>
|
||||
#include <QtGui/QFont>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QGnomeThemePrivate;
|
||||
#ifndef QT_NO_DBUS
|
||||
class QDBusListener;
|
||||
#endif
|
||||
|
||||
class Q_GUI_EXPORT QGnomeTheme : public QGenericUnixTheme
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QGnomeTheme)
|
||||
public:
|
||||
QGnomeTheme();
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
QIcon fileIcon(const QFileInfo &fileInfo,
|
||||
QPlatformTheme::IconOptions = { }) const override;
|
||||
const QFont *font(Font type) const override;
|
||||
QString standardButtonText(int button) const override;
|
||||
|
||||
virtual QString gtkFontName() const;
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *createPlatformMenuBar() const override;
|
||||
Qt::ColorScheme colorScheme() const override;
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
|
||||
#endif
|
||||
|
||||
static const char *name;
|
||||
};
|
||||
|
||||
class QGnomeThemePrivate : public QGenericUnixThemePrivate
|
||||
{
|
||||
public:
|
||||
QGnomeThemePrivate();
|
||||
~QGnomeThemePrivate();
|
||||
|
||||
void configureFonts(const QString >kFontName) const;
|
||||
|
||||
mutable QFont *systemFont = nullptr;
|
||||
mutable QFont *fixedFont = nullptr;
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
|
||||
private:
|
||||
std::unique_ptr<QDBusListener> dbus;
|
||||
bool initDbus();
|
||||
void updateColorScheme(const QString &themeName);
|
||||
#endif // QT_NO_DBUS
|
||||
};
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
#endif // QGNOMETHEME_P_H
|
@ -1,59 +1,22 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// Copyright (C) 2025 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 "qgenericunixthemes_p.h"
|
||||
|
||||
#include <QPalette>
|
||||
#include <QFont>
|
||||
#include <QGuiApplication>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QLoggingCategory>
|
||||
#include <QVariant>
|
||||
#include <QStandardPaths>
|
||||
#include <QStringList>
|
||||
#if QT_CONFIG(mimetype)
|
||||
#include <QMimeDatabase>
|
||||
#endif
|
||||
#if QT_CONFIG(settings)
|
||||
#include <QSettings>
|
||||
#endif
|
||||
|
||||
#include <qpa/qplatformfontdatabase.h> // lcQpaFonts
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <qpa/qplatformservices.h>
|
||||
#include <qpa/qplatformdialoghelper.h>
|
||||
#include "qkdetheme_p.h"
|
||||
#include <qpa/qplatformtheme_p.h>
|
||||
|
||||
#include <private/qguiapplication_p.h>
|
||||
#ifndef QT_NO_DBUS
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <qpa/qplatformfontdatabase.h>
|
||||
#include <qpa/qplatformdialoghelper.h>
|
||||
#include <QPalette>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include "qdbuslistener_p.h"
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
#include <private/qdbusplatformmenu_p.h>
|
||||
#include <private/qdbusmenubar_p.h>
|
||||
#include <private/qflatmap_p.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonParseError>
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
#include <private/qdbustrayicon_p.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
#ifndef QT_NO_DBUS
|
||||
Q_STATIC_LOGGING_CATEGORY(lcQpaThemeDBus, "qt.qpa.theme.dbus")
|
||||
#endif
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(qLcTray)
|
||||
Q_STATIC_LOGGING_CATEGORY(lcQpaThemeKde, "qt.qpa.theme.kde")
|
||||
|
||||
ResourceHelper::ResourceHelper()
|
||||
{
|
||||
@ -69,477 +32,7 @@ void ResourceHelper::clear()
|
||||
std::fill(fonts, fonts + QPlatformTheme::NFonts, static_cast<QFont *>(nullptr));
|
||||
}
|
||||
|
||||
const char *QGenericUnixTheme::name = "generic";
|
||||
|
||||
// Default system font, corresponding to the value returned by 4.8 for
|
||||
// XRender/FontConfig which we can now assume as default.
|
||||
static const char defaultSystemFontNameC[] = "Sans Serif";
|
||||
static const char defaultFixedFontNameC[] = "monospace";
|
||||
enum { defaultSystemFontSize = 9 };
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
static bool shouldUseDBusTray() {
|
||||
// There's no other tray implementation to fallback to on non-X11
|
||||
// and QDBusTrayIcon can register the icon on the fly after creation
|
||||
if (QGuiApplication::platformName() != "xcb"_L1)
|
||||
return true;
|
||||
const bool result = QDBusMenuConnection().isWatcherRegistered();
|
||||
qCDebug(qLcTray) << "D-Bus tray available:" << result;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static QString mouseCursorTheme()
|
||||
{
|
||||
static QString themeName = qEnvironmentVariable("XCURSOR_THEME");
|
||||
return themeName;
|
||||
}
|
||||
|
||||
static QSize mouseCursorSize()
|
||||
{
|
||||
constexpr int defaultCursorSize = 24;
|
||||
static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
|
||||
static const int s = xCursorSize > 0 ? xCursorSize : defaultCursorSize;
|
||||
return QSize(s, s);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
static bool checkDBusGlobalMenuAvailable()
|
||||
{
|
||||
const QDBusConnection connection = QDBusConnection::sessionBus();
|
||||
static const QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar");
|
||||
if (const auto iface = connection.interface())
|
||||
return iface->isServiceRegistered(registrarService);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isDBusGlobalMenuAvailable()
|
||||
{
|
||||
static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable();
|
||||
return dbusGlobalMenuAvailable;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* The QGenericUnixThemeDBusListener class listens to the SettingChanged DBus signal
|
||||
* and translates it into combinations of the enums \c Provider and \c Setting.
|
||||
* Upon construction, it logs success/failure of the DBus connection.
|
||||
*
|
||||
* The signal settingChanged delivers the normalized setting type and the new value as a string.
|
||||
* It is emitted on known setting types only.
|
||||
*/
|
||||
|
||||
class QGenericUnixThemeDBusListener : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum class Provider {
|
||||
Kde,
|
||||
Gtk,
|
||||
Gnome,
|
||||
};
|
||||
Q_ENUM(Provider)
|
||||
|
||||
enum class Setting {
|
||||
Theme,
|
||||
ApplicationStyle,
|
||||
ColorScheme,
|
||||
};
|
||||
Q_ENUM(Setting)
|
||||
|
||||
QGenericUnixThemeDBusListener();
|
||||
QGenericUnixThemeDBusListener(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &signal);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void settingChanged(QGenericUnixThemeDBusListener::Provider provider,
|
||||
QGenericUnixThemeDBusListener::Setting setting,
|
||||
const QString &value);
|
||||
|
||||
private:
|
||||
struct DBusKey
|
||||
{
|
||||
QString location;
|
||||
QString key;
|
||||
DBusKey(const QString &loc, const QString &k) : location(loc), key(k) {};
|
||||
bool operator<(const DBusKey &other) const
|
||||
{
|
||||
return location + key < other.location + other.key;
|
||||
}
|
||||
};
|
||||
|
||||
struct ChangeSignal
|
||||
{
|
||||
Provider provider;
|
||||
Setting setting;
|
||||
ChangeSignal(Provider p, Setting s) : provider(p), setting(s) {}
|
||||
ChangeSignal() {}
|
||||
};
|
||||
|
||||
QFlatMap <DBusKey, ChangeSignal> m_signalMap;
|
||||
|
||||
void init(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &signal);
|
||||
|
||||
std::optional<ChangeSignal> findSignal(const QString &location, const QString &key) const;
|
||||
void populateSignalMap();
|
||||
void loadJson(const QString &fileName);
|
||||
void saveJson(const QString &fileName) const;
|
||||
};
|
||||
|
||||
namespace {
|
||||
namespace JsonKeys {
|
||||
constexpr auto dbusLocation() { return "DBusLocation"_L1; }
|
||||
constexpr auto dbusKey() { return "DBusKey"_L1; }
|
||||
constexpr auto provider() { return "Provider"_L1; }
|
||||
constexpr auto setting() { return "Setting"_L1; }
|
||||
constexpr auto dbusSignals() { return "DbusSignals"_L1; }
|
||||
constexpr auto root() { return "Qt.qpa.DBusSignals"_L1; }
|
||||
} // namespace JsonKeys
|
||||
}
|
||||
|
||||
QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener(const QString &service,
|
||||
const QString &path, const QString &interface, const QString &signal)
|
||||
{
|
||||
init (service, path, interface, signal);
|
||||
}
|
||||
|
||||
QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener()
|
||||
{
|
||||
const auto service = u""_s;
|
||||
const auto path = u"/org/freedesktop/portal/desktop"_s;
|
||||
const auto interface = u"org.freedesktop.portal.Settings"_s;
|
||||
const auto signal = u"SettingChanged"_s;
|
||||
|
||||
init (service, path, interface, signal);
|
||||
}
|
||||
|
||||
void QGenericUnixThemeDBusListener::init(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &signal)
|
||||
{
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
const bool dBusRunning = dbus.isConnected();
|
||||
bool dBusSignalConnected = false;
|
||||
#define LOG service << path << interface << signal;
|
||||
|
||||
if (dBusRunning) {
|
||||
populateSignalMap();
|
||||
qRegisterMetaType<QDBusVariant>();
|
||||
dBusSignalConnected = dbus.connect(service, path, interface, signal, this,
|
||||
SLOT(onSettingChanged(QString,QString,QDBusVariant)));
|
||||
}
|
||||
|
||||
if (dBusSignalConnected) {
|
||||
// Connection successful
|
||||
qCDebug(lcQpaThemeDBus) << LOG;
|
||||
} else {
|
||||
if (dBusRunning) {
|
||||
// DBus running, but connection failed
|
||||
qCWarning(lcQpaThemeDBus) << "DBus connection failed:" << LOG;
|
||||
} else {
|
||||
// DBus not running
|
||||
qCWarning(lcQpaThemeDBus) << "Session DBus not running.";
|
||||
}
|
||||
qCWarning(lcQpaThemeDBus) << "Application will not react to setting changes.\n"
|
||||
<< "Check your DBus installation.";
|
||||
}
|
||||
#undef LOG
|
||||
}
|
||||
|
||||
void QGenericUnixThemeDBusListener::loadJson(const QString &fileName)
|
||||
{
|
||||
Q_ASSERT(!fileName.isEmpty());
|
||||
#define CHECK(cond, warning)\
|
||||
if (!cond) {\
|
||||
qCWarning(lcQpaThemeDBus) << fileName << warning << "Falling back to default.";\
|
||||
return;\
|
||||
}
|
||||
|
||||
#define PARSE(var, enumeration, string)\
|
||||
enumeration var;\
|
||||
{\
|
||||
bool success;\
|
||||
const int val = QMetaEnum::fromType<enumeration>().keyToValue(string.toLatin1(), &success);\
|
||||
CHECK(success, "Parse Error: Invalid value" << string << "for" << #var);\
|
||||
var = static_cast<enumeration>(val);\
|
||||
}
|
||||
|
||||
QFile file(fileName);
|
||||
CHECK(file.exists(), fileName << "doesn't exist.");
|
||||
CHECK(file.open(QIODevice::ReadOnly), "could not be opened for reading.");
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||
CHECK((error.error == QJsonParseError::NoError), error.errorString());
|
||||
CHECK(doc.isObject(), "Parse Error: Expected root object" << JsonKeys::root());
|
||||
|
||||
const QJsonObject &root = doc.object();
|
||||
CHECK(root.contains(JsonKeys::root()), "Parse Error: Expected root object" << JsonKeys::root());
|
||||
CHECK(root[JsonKeys::root()][JsonKeys::dbusSignals()].isArray(), "Parse Error: Expected array" << JsonKeys::dbusSignals());
|
||||
|
||||
const QJsonArray &sigs = root[JsonKeys::root()][JsonKeys::dbusSignals()].toArray();
|
||||
CHECK((sigs.count() > 0), "Parse Error: Found empty array" << JsonKeys::dbusSignals());
|
||||
|
||||
for (auto sig = sigs.constBegin(); sig != sigs.constEnd(); ++sig) {
|
||||
CHECK(sig->isObject(), "Parse Error: Expected object array" << JsonKeys::dbusSignals());
|
||||
const QJsonObject &obj = sig->toObject();
|
||||
CHECK(obj.contains(JsonKeys::dbusLocation()), "Parse Error: Expected key" << JsonKeys::dbusLocation());
|
||||
CHECK(obj.contains(JsonKeys::dbusKey()), "Parse Error: Expected key" << JsonKeys::dbusKey());
|
||||
CHECK(obj.contains(JsonKeys::provider()), "Parse Error: Expected key" << JsonKeys::provider());
|
||||
CHECK(obj.contains(JsonKeys::setting()), "Parse Error: Expected key" << JsonKeys::setting());
|
||||
const QString &location = obj[JsonKeys::dbusLocation()].toString();
|
||||
const QString &key = obj[JsonKeys::dbusKey()].toString();
|
||||
const QString &providerString = obj[JsonKeys::provider()].toString();
|
||||
const QString &settingString = obj[JsonKeys::setting()].toString();
|
||||
PARSE(provider, Provider, providerString);
|
||||
PARSE(setting, Setting, settingString);
|
||||
const DBusKey dkey(location, key);
|
||||
CHECK (!m_signalMap.contains(dkey), "Duplicate key" << location << key);
|
||||
m_signalMap.insert(dkey, ChangeSignal(provider, setting));
|
||||
}
|
||||
#undef PARSE
|
||||
#undef CHECK
|
||||
|
||||
if (m_signalMap.count() > 0)
|
||||
qCInfo(lcQpaThemeDBus) << "Successfully imported" << fileName;
|
||||
else
|
||||
qCWarning(lcQpaThemeDBus) << "No data imported from" << fileName << "falling back to default.";
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
const int count = m_signalMap.count();
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
qCDebug(lcQpaThemeDBus) << "Listening to" << count << "signals:";
|
||||
for (auto it = m_signalMap.constBegin(); it != m_signalMap.constEnd(); ++it) {
|
||||
qDebug() << it.key().key << it.key().location << "mapped to"
|
||||
<< it.value().provider << it.value().setting;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void QGenericUnixThemeDBusListener::saveJson(const QString &fileName) const
|
||||
{
|
||||
Q_ASSERT(!m_signalMap.isEmpty());
|
||||
Q_ASSERT(!fileName.isEmpty());
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qCWarning(lcQpaThemeDBus) << fileName << "could not be opened for writing.";
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonArray sigs;
|
||||
for (auto sig = m_signalMap.constBegin(); sig != m_signalMap.constEnd(); ++sig) {
|
||||
const DBusKey &dkey = sig.key();
|
||||
const ChangeSignal &csig = sig.value();
|
||||
QJsonObject obj;
|
||||
obj[JsonKeys::dbusLocation()] = dkey.location;
|
||||
obj[JsonKeys::dbusKey()] = dkey.key;
|
||||
obj[JsonKeys::provider()] = QLatin1StringView(QMetaEnum::fromType<Provider>()
|
||||
.valueToKey(static_cast<int>(csig.provider)));
|
||||
obj[JsonKeys::setting()] = QLatin1StringView(QMetaEnum::fromType<Setting>()
|
||||
.valueToKey(static_cast<int>(csig.setting)));
|
||||
sigs.append(obj);
|
||||
}
|
||||
QJsonObject obj;
|
||||
obj[JsonKeys::dbusSignals()] = sigs;
|
||||
QJsonObject root;
|
||||
root[JsonKeys::root()] = obj;
|
||||
QJsonDocument doc(root);
|
||||
file.write(doc.toJson());
|
||||
file.close();
|
||||
}
|
||||
|
||||
void QGenericUnixThemeDBusListener::populateSignalMap()
|
||||
{
|
||||
m_signalMap.clear();
|
||||
const QString &loadJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS");
|
||||
if (!loadJsonFile.isEmpty())
|
||||
loadJson(loadJsonFile);
|
||||
if (!m_signalMap.isEmpty())
|
||||
return;
|
||||
|
||||
m_signalMap.insert(DBusKey("org.kde.kdeglobals.KDE"_L1, "widgetStyle"_L1),
|
||||
ChangeSignal(Provider::Kde, Setting::ApplicationStyle));
|
||||
|
||||
m_signalMap.insert(DBusKey("org.kde.kdeglobals.General"_L1, "ColorScheme"_L1),
|
||||
ChangeSignal(Provider::Kde, Setting::Theme));
|
||||
|
||||
m_signalMap.insert(DBusKey("org.gnome.desktop.interface"_L1, "gtk-theme"_L1),
|
||||
ChangeSignal(Provider::Gtk, Setting::Theme));
|
||||
|
||||
m_signalMap.insert(DBusKey("org.freedesktop.appearance"_L1, "color-scheme"_L1),
|
||||
ChangeSignal(Provider::Gnome, Setting::ColorScheme));
|
||||
|
||||
const QString &saveJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS_SAVE");
|
||||
if (!saveJsonFile.isEmpty())
|
||||
saveJson(saveJsonFile);
|
||||
}
|
||||
|
||||
std::optional<QGenericUnixThemeDBusListener::ChangeSignal>
|
||||
QGenericUnixThemeDBusListener::findSignal(const QString &location, const QString &key) const
|
||||
{
|
||||
const DBusKey dkey(location, key);
|
||||
std::optional<QGenericUnixThemeDBusListener::ChangeSignal> ret;
|
||||
if (m_signalMap.contains(dkey))
|
||||
ret.emplace(m_signalMap.value(dkey));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QGenericUnixThemeDBusListener::onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value)
|
||||
{
|
||||
auto sig = findSignal(location, key);
|
||||
if (!sig.has_value())
|
||||
return;
|
||||
|
||||
emit settingChanged(sig.value().provider, sig.value().setting, value.variant().toString());
|
||||
}
|
||||
|
||||
#endif //QT_NO_DBUS
|
||||
|
||||
class QGenericUnixThemePrivate : public QPlatformThemePrivate
|
||||
{
|
||||
public:
|
||||
QGenericUnixThemePrivate()
|
||||
: QPlatformThemePrivate()
|
||||
, systemFont(QLatin1StringView(defaultSystemFontNameC), defaultSystemFontSize)
|
||||
, fixedFont(QLatin1StringView(defaultFixedFontNameC), systemFont.pointSize())
|
||||
{
|
||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
|
||||
}
|
||||
|
||||
const QFont systemFont;
|
||||
QFont fixedFont;
|
||||
};
|
||||
|
||||
QGenericUnixTheme::QGenericUnixTheme()
|
||||
: QPlatformTheme(new QGenericUnixThemePrivate())
|
||||
{
|
||||
}
|
||||
|
||||
const QFont *QGenericUnixTheme::font(Font type) const
|
||||
{
|
||||
Q_D(const QGenericUnixTheme);
|
||||
switch (type) {
|
||||
case QPlatformTheme::SystemFont:
|
||||
return &d->systemFont;
|
||||
case QPlatformTheme::FixedFont:
|
||||
return &d->fixedFont;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to return the icon theme paths from XDG.
|
||||
QStringList QGenericUnixTheme::xdgIconThemePaths()
|
||||
{
|
||||
QStringList paths;
|
||||
// Add home directory first in search path
|
||||
const QFileInfo homeIconDir(QDir::homePath() + "/.icons"_L1);
|
||||
if (homeIconDir.isDir())
|
||||
paths.prepend(homeIconDir.absoluteFilePath());
|
||||
|
||||
paths.append(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
|
||||
QStringLiteral("icons"),
|
||||
QStandardPaths::LocateDirectory));
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
QStringList QGenericUnixTheme::iconFallbackPaths()
|
||||
{
|
||||
QStringList paths;
|
||||
const QFileInfo pixmapsIconsDir(QStringLiteral("/usr/share/pixmaps"));
|
||||
if (pixmapsIconsDir.isDir())
|
||||
paths.append(pixmapsIconsDir.absoluteFilePath());
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *QGenericUnixTheme::createPlatformMenuBar() const
|
||||
{
|
||||
if (isDBusGlobalMenuAvailable())
|
||||
return new QDBusMenuBar();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *QGenericUnixTheme::createPlatformSystemTrayIcon() const
|
||||
{
|
||||
if (shouldUseDBusTray())
|
||||
return new QDBusTrayIcon();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const
|
||||
{
|
||||
switch (hint) {
|
||||
case QPlatformTheme::SystemIconFallbackThemeName:
|
||||
return QVariant(QString(QStringLiteral("hicolor")));
|
||||
case QPlatformTheme::IconThemeSearchPaths:
|
||||
return xdgIconThemePaths();
|
||||
case QPlatformTheme::IconFallbackSearchPaths:
|
||||
return iconFallbackPaths();
|
||||
case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
|
||||
return QVariant(true);
|
||||
case QPlatformTheme::StyleNames: {
|
||||
QStringList styleNames;
|
||||
styleNames << QStringLiteral("Fusion") << QStringLiteral("Windows");
|
||||
return QVariant(styleNames);
|
||||
}
|
||||
case QPlatformTheme::KeyboardScheme:
|
||||
return QVariant(int(X11KeyboardScheme));
|
||||
case QPlatformTheme::UiEffects:
|
||||
return QVariant(int(HoverEffect));
|
||||
case QPlatformTheme::MouseCursorTheme:
|
||||
return QVariant(mouseCursorTheme());
|
||||
case QPlatformTheme::MouseCursorSize:
|
||||
return QVariant(mouseCursorSize());
|
||||
case QPlatformTheme::PreferFileIconFromTheme:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformTheme::themeHint(hint);
|
||||
}
|
||||
|
||||
// Helper functions for implementing QPlatformTheme::fileIcon() for XDG icon themes.
|
||||
static QList<QSize> availableXdgFileIconSizes()
|
||||
{
|
||||
return QIcon::fromTheme(QStringLiteral("inode-directory")).availableSizes();
|
||||
}
|
||||
|
||||
#if QT_CONFIG(mimetype)
|
||||
static QIcon xdgFileIcon(const QFileInfo &fileInfo)
|
||||
{
|
||||
QMimeDatabase mimeDatabase;
|
||||
QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo);
|
||||
if (!mimeType.isValid())
|
||||
return QIcon();
|
||||
const QString &iconName = mimeType.iconName();
|
||||
if (!iconName.isEmpty()) {
|
||||
const QIcon icon = QIcon::fromTheme(iconName);
|
||||
if (!icon.isNull())
|
||||
return icon;
|
||||
}
|
||||
const QString &genericIconName = mimeType.genericIconName();
|
||||
return genericIconName.isEmpty() ? QIcon() : QIcon::fromTheme(genericIconName);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(settings)
|
||||
class QKdeThemePrivate : public QPlatformThemePrivate
|
||||
class QKdeThemePrivate : public QGenericUnixThemePrivate
|
||||
{
|
||||
|
||||
public:
|
||||
@ -624,31 +117,31 @@ public:
|
||||
private:
|
||||
mutable QHash<QString, QSettings *> kdeSettings;
|
||||
#ifndef QT_NO_DBUS
|
||||
std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
|
||||
std::unique_ptr<QDBusListener> dbus;
|
||||
bool initDbus();
|
||||
void settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
|
||||
QGenericUnixThemeDBusListener::Setting setting,
|
||||
void settingChangedHandler(QDBusListener::Provider provider,
|
||||
QDBusListener::Setting setting,
|
||||
const QString &value);
|
||||
#endif // QT_NO_DBUS
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
void QKdeThemePrivate::settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
|
||||
QGenericUnixThemeDBusListener::Setting setting,
|
||||
void QKdeThemePrivate::settingChangedHandler(QDBusListener::Provider provider,
|
||||
QDBusListener::Setting setting,
|
||||
const QString &value)
|
||||
{
|
||||
if (provider != QGenericUnixThemeDBusListener::Provider::Kde)
|
||||
if (provider != QDBusListener::Provider::Kde)
|
||||
return;
|
||||
|
||||
switch (setting) {
|
||||
case QGenericUnixThemeDBusListener::Setting::ColorScheme:
|
||||
qCDebug(lcQpaThemeDBus) << "KDE color theme changed to:" << value;
|
||||
case QDBusListener::Setting::ColorScheme:
|
||||
qCDebug(lcQpaThemeKde) << "KDE color theme changed to:" << value;
|
||||
break;
|
||||
case QGenericUnixThemeDBusListener::Setting::Theme:
|
||||
qCDebug(lcQpaThemeDBus) << "KDE global theme changed to:" << value;
|
||||
case QDBusListener::Setting::Theme:
|
||||
qCDebug(lcQpaThemeKde) << "KDE global theme changed to:" << value;
|
||||
break;
|
||||
case QGenericUnixThemeDBusListener::Setting::ApplicationStyle:
|
||||
qCDebug(lcQpaThemeDBus) << "KDE application style changed to:" << value;
|
||||
case QDBusListener::Setting::ApplicationStyle:
|
||||
qCDebug(lcQpaThemeKde) << "KDE application style changed to:" << value;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -657,17 +150,17 @@ void QKdeThemePrivate::settingChangedHandler(QGenericUnixThemeDBusListener::Prov
|
||||
|
||||
bool QKdeThemePrivate::initDbus()
|
||||
{
|
||||
dbus.reset(new QGenericUnixThemeDBusListener());
|
||||
dbus.reset(new QDBusListener());
|
||||
Q_ASSERT(dbus);
|
||||
|
||||
// Wrap slot in a lambda to avoid inheriting QKdeThemePrivate from QObject
|
||||
auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
|
||||
QGenericUnixThemeDBusListener::Setting setting,
|
||||
auto wrapper = [this](QDBusListener::Provider provider,
|
||||
QDBusListener::Setting setting,
|
||||
const QString &value) {
|
||||
settingChangedHandler(provider, setting, value);
|
||||
};
|
||||
|
||||
return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, dbus.get(), wrapper);
|
||||
return QObject::connect(dbus.get(), &QDBusListener::settingChanged, dbus.get(), wrapper);
|
||||
}
|
||||
#endif // QT_NO_DBUS
|
||||
|
||||
@ -909,12 +402,14 @@ void QKdeThemePrivate::refresh()
|
||||
if (QFont *systemFont = kdeFont(readKdeSetting(KdeSetting::Font)))
|
||||
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
|
||||
else
|
||||
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1StringView(defaultSystemFontNameC), defaultSystemFontSize);
|
||||
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1StringView(QGenericUnixTheme::defaultSystemFontNameC),
|
||||
QGenericUnixTheme::defaultSystemFontSize);
|
||||
|
||||
if (QFont *fixedFont = kdeFont(readKdeSetting(KdeSetting::Fixed))) {
|
||||
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
|
||||
} else {
|
||||
fixedFont = new QFont(QLatin1StringView(defaultFixedFontNameC), defaultSystemFontSize);
|
||||
fixedFont = new QFont(QLatin1StringView(QGenericUnixTheme::defaultFixedFontNameC),
|
||||
QGenericUnixTheme::defaultSystemFontSize);
|
||||
fixedFont->setStyleHint(QFont::TypeWriter);
|
||||
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
|
||||
}
|
||||
@ -1043,7 +538,7 @@ void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeV
|
||||
const char *QKdeTheme::name = "kde";
|
||||
|
||||
QKdeTheme::QKdeTheme(const QStringList& kdeDirs, int kdeVersion)
|
||||
: QPlatformTheme(new QKdeThemePrivate(kdeDirs,kdeVersion))
|
||||
: QGenericUnixTheme(new QKdeThemePrivate(kdeDirs, kdeVersion))
|
||||
{
|
||||
d_func()->refresh();
|
||||
}
|
||||
@ -1276,278 +771,4 @@ QPlatformSystemTrayIcon *QKdeTheme::createPlatformSystemTrayIcon() const
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // settings
|
||||
|
||||
/*!
|
||||
\class QGnomeTheme
|
||||
\brief QGnomeTheme is a theme implementation for the Gnome desktop.
|
||||
\since 5.0
|
||||
\internal
|
||||
\ingroup qpa
|
||||
*/
|
||||
|
||||
const char *QGnomeTheme::name = "gnome";
|
||||
|
||||
class QGnomeThemePrivate : public QPlatformThemePrivate
|
||||
{
|
||||
public:
|
||||
QGnomeThemePrivate();
|
||||
~QGnomeThemePrivate();
|
||||
|
||||
void configureFonts(const QString >kFontName) const
|
||||
{
|
||||
Q_ASSERT(!systemFont);
|
||||
const int split = gtkFontName.lastIndexOf(QChar::Space);
|
||||
float size = QStringView{gtkFontName}.mid(split + 1).toFloat();
|
||||
QString fontName = gtkFontName.left(split);
|
||||
|
||||
systemFont = new QFont(fontName, size);
|
||||
fixedFont = new QFont(QLatin1StringView(defaultFixedFontNameC), systemFont->pointSize());
|
||||
fixedFont->setStyleHint(QFont::TypeWriter);
|
||||
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
|
||||
}
|
||||
|
||||
mutable QFont *systemFont = nullptr;
|
||||
mutable QFont *fixedFont = nullptr;
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
|
||||
private:
|
||||
std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
|
||||
bool initDbus();
|
||||
void updateColorScheme(const QString &themeName);
|
||||
#endif // QT_NO_DBUS
|
||||
};
|
||||
|
||||
QGnomeThemePrivate::QGnomeThemePrivate()
|
||||
{
|
||||
#ifndef QT_NO_DBUS
|
||||
initDbus();
|
||||
#endif // QT_NO_DBUS
|
||||
}
|
||||
QGnomeThemePrivate::~QGnomeThemePrivate()
|
||||
{
|
||||
if (systemFont)
|
||||
delete systemFont;
|
||||
if (fixedFont)
|
||||
delete fixedFont;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
bool QGnomeThemePrivate::initDbus()
|
||||
{
|
||||
dbus.reset(new QGenericUnixThemeDBusListener());
|
||||
Q_ASSERT(dbus);
|
||||
|
||||
// Wrap slot in a lambda to avoid inheriting QGnomeThemePrivate from QObject
|
||||
auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
|
||||
QGenericUnixThemeDBusListener::Setting setting,
|
||||
const QString &value) {
|
||||
if (provider != QGenericUnixThemeDBusListener::Provider::Gnome
|
||||
&& provider != QGenericUnixThemeDBusListener::Provider::Gtk) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (setting == QGenericUnixThemeDBusListener::Setting::Theme)
|
||||
updateColorScheme(value);
|
||||
};
|
||||
|
||||
return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, dbus.get(), wrapper);
|
||||
}
|
||||
|
||||
void QGnomeThemePrivate::updateColorScheme(const QString &themeName)
|
||||
{
|
||||
const auto oldColorScheme = m_colorScheme;
|
||||
if (themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive)) {
|
||||
m_colorScheme = Qt::ColorScheme::Light;
|
||||
} else if (themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) {
|
||||
m_colorScheme = Qt::ColorScheme::Dark;
|
||||
} else {
|
||||
m_colorScheme = Qt::ColorScheme::Unknown;
|
||||
}
|
||||
|
||||
if (oldColorScheme != m_colorScheme)
|
||||
QWindowSystemInterface::handleThemeChange();
|
||||
}
|
||||
#endif // QT_NO_DBUS
|
||||
|
||||
QGnomeTheme::QGnomeTheme()
|
||||
: QPlatformTheme(new QGnomeThemePrivate())
|
||||
{
|
||||
}
|
||||
|
||||
QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
|
||||
{
|
||||
switch (hint) {
|
||||
case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
|
||||
return QVariant(true);
|
||||
case QPlatformTheme::DialogButtonBoxLayout:
|
||||
return QVariant(QPlatformDialogHelper::GnomeLayout);
|
||||
case QPlatformTheme::SystemIconThemeName:
|
||||
return QVariant(QStringLiteral("Adwaita"));
|
||||
case QPlatformTheme::SystemIconFallbackThemeName:
|
||||
return QVariant(QStringLiteral("gnome"));
|
||||
case QPlatformTheme::IconThemeSearchPaths:
|
||||
return QVariant(QGenericUnixTheme::xdgIconThemePaths());
|
||||
case QPlatformTheme::IconPixmapSizes:
|
||||
return QVariant::fromValue(availableXdgFileIconSizes());
|
||||
case QPlatformTheme::StyleNames: {
|
||||
QStringList styleNames;
|
||||
styleNames << QStringLiteral("Fusion") << QStringLiteral("windows");
|
||||
return QVariant(styleNames);
|
||||
}
|
||||
case QPlatformTheme::KeyboardScheme:
|
||||
return QVariant(int(GnomeKeyboardScheme));
|
||||
case QPlatformTheme::PasswordMaskCharacter:
|
||||
return QVariant(QChar(0x2022));
|
||||
case QPlatformTheme::UiEffects:
|
||||
return QVariant(int(HoverEffect));
|
||||
case QPlatformTheme::ButtonPressKeys:
|
||||
return QVariant::fromValue(
|
||||
QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
|
||||
case QPlatformTheme::PreselectFirstFileInDirectory:
|
||||
return true;
|
||||
case QPlatformTheme::MouseCursorTheme:
|
||||
return QVariant(mouseCursorTheme());
|
||||
case QPlatformTheme::MouseCursorSize:
|
||||
return QVariant(mouseCursorSize());
|
||||
case QPlatformTheme::PreferFileIconFromTheme:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformTheme::themeHint(hint);
|
||||
}
|
||||
|
||||
QIcon QGnomeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const
|
||||
{
|
||||
#if QT_CONFIG(mimetype)
|
||||
return xdgFileIcon(fileInfo);
|
||||
#else
|
||||
Q_UNUSED(fileInfo);
|
||||
return QIcon();
|
||||
#endif
|
||||
}
|
||||
|
||||
const QFont *QGnomeTheme::font(Font type) const
|
||||
{
|
||||
Q_D(const QGnomeTheme);
|
||||
if (!d->systemFont)
|
||||
d->configureFonts(gtkFontName());
|
||||
switch (type) {
|
||||
case QPlatformTheme::SystemFont:
|
||||
return d->systemFont;
|
||||
case QPlatformTheme::FixedFont:
|
||||
return d->fixedFont;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QString QGnomeTheme::gtkFontName() const
|
||||
{
|
||||
return QStringLiteral("%1 %2").arg(QLatin1StringView(defaultSystemFontNameC)).arg(defaultSystemFontSize);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const
|
||||
{
|
||||
if (isDBusGlobalMenuAvailable())
|
||||
return new QDBusMenuBar();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Qt::ColorScheme QGnomeTheme::colorScheme() const
|
||||
{
|
||||
return d_func()->m_colorScheme;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *QGnomeTheme::createPlatformSystemTrayIcon() const
|
||||
{
|
||||
if (shouldUseDBusTray())
|
||||
return new QDBusTrayIcon();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString QGnomeTheme::standardButtonText(int button) const
|
||||
{
|
||||
switch (button) {
|
||||
case QPlatformDialogHelper::Ok:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&OK");
|
||||
case QPlatformDialogHelper::Save:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&Save");
|
||||
case QPlatformDialogHelper::Cancel:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&Cancel");
|
||||
case QPlatformDialogHelper::Close:
|
||||
return QCoreApplication::translate("QGnomeTheme", "&Close");
|
||||
case QPlatformDialogHelper::Discard:
|
||||
return QCoreApplication::translate("QGnomeTheme", "Close without Saving");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformTheme::standardButtonText(button);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Creates a UNIX theme according to the detected desktop environment.
|
||||
*/
|
||||
|
||||
QPlatformTheme *QGenericUnixTheme::createUnixTheme(const QString &name)
|
||||
{
|
||||
if (name == QLatin1StringView(QGenericUnixTheme::name))
|
||||
return new QGenericUnixTheme;
|
||||
#if QT_CONFIG(settings)
|
||||
if (name == QLatin1StringView(QKdeTheme::name))
|
||||
if (QPlatformTheme *kdeTheme = QKdeTheme::createKdeTheme())
|
||||
return kdeTheme;
|
||||
#endif
|
||||
if (name == QLatin1StringView(QGnomeTheme::name))
|
||||
return new QGnomeTheme;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QStringList QGenericUnixTheme::themeNames()
|
||||
{
|
||||
QStringList result;
|
||||
if (QGuiApplication::desktopSettingsAware()) {
|
||||
const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment();
|
||||
QList<QByteArray> gtkBasedEnvironments;
|
||||
gtkBasedEnvironments << "GNOME"
|
||||
<< "X-CINNAMON"
|
||||
<< "PANTHEON"
|
||||
<< "UNITY"
|
||||
<< "MATE"
|
||||
<< "XFCE"
|
||||
<< "LXDE";
|
||||
const QList<QByteArray> desktopNames = desktopEnvironment.split(':');
|
||||
for (const QByteArray &desktopName : desktopNames) {
|
||||
if (desktopEnvironment == "KDE") {
|
||||
#if QT_CONFIG(settings)
|
||||
result.push_back(QLatin1StringView(QKdeTheme::name));
|
||||
#endif
|
||||
} else if (gtkBasedEnvironments.contains(desktopName)) {
|
||||
// prefer the GTK3 theme implementation with native dialogs etc.
|
||||
result.push_back(QStringLiteral("gtk3"));
|
||||
// fallback to the generic Gnome theme if loading the GTK3 theme fails
|
||||
result.push_back(QLatin1StringView(QGnomeTheme::name));
|
||||
} else {
|
||||
// unknown, but lowercase the name (our standard practice) and
|
||||
// remove any "x-" prefix
|
||||
QString s = QString::fromLatin1(desktopName.toLower());
|
||||
result.push_back(s.startsWith("x-"_L1) ? s.mid(2) : s);
|
||||
}
|
||||
}
|
||||
} // desktopSettingsAware
|
||||
result.append(QLatin1StringView(QGenericUnixTheme::name));
|
||||
return result;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
#include "qgenericunixthemes.moc"
|
||||
#endif // QT_NO_DBUS
|
68
src/gui/platform/unix/qkdetheme_p.h
Normal file
68
src/gui/platform/unix/qkdetheme_p.h
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2025 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 QKDETHEME_P_H
|
||||
#define QKDETHEME_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qgenericunixtheme_p.h"
|
||||
#include <qpa/qplatformtheme.h>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtGui/QFont>
|
||||
#include <QtCore/private/qglobal_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class ResourceHelper
|
||||
{
|
||||
public:
|
||||
ResourceHelper();
|
||||
~ResourceHelper() { clear(); }
|
||||
|
||||
void clear();
|
||||
|
||||
QPalette *palettes[QPlatformTheme::NPalettes];
|
||||
QFont *fonts[QPlatformTheme::NFonts];
|
||||
};
|
||||
|
||||
class QKdeThemePrivate;
|
||||
class Q_GUI_EXPORT QKdeTheme : public QGenericUnixTheme
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QKdeTheme)
|
||||
public:
|
||||
QKdeTheme(const QStringList& kdeDirs, int kdeVersion);
|
||||
|
||||
static QPlatformTheme *createKdeTheme();
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
|
||||
QIcon fileIcon(const QFileInfo &fileInfo,
|
||||
QPlatformTheme::IconOptions iconOptions = { }) const override;
|
||||
|
||||
const QPalette *palette(Palette type = SystemPalette) const override;
|
||||
Qt::ColorScheme colorScheme() const override;
|
||||
//void requestColorScheme(Qt::ColorScheme scheme) override;
|
||||
|
||||
const QFont *font(Font type) const override;
|
||||
#ifndef QT_NO_DBUS
|
||||
QPlatformMenuBar *createPlatformMenuBar() const override;
|
||||
#endif
|
||||
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
|
||||
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
|
||||
#endif
|
||||
|
||||
static const char *name;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
#endif // QKDETHEME_P_H
|
@ -32,7 +32,7 @@
|
||||
#endif
|
||||
|
||||
#include <QtGui/private/qgenericunixfontdatabase_p.h>
|
||||
#include <QtGui/private/qgenericunixthemes_p.h>
|
||||
#include <QtGui/private/qgenericunixtheme_p.h>
|
||||
#include <QtGui/private/qgenericunixeventdispatcher_p.h>
|
||||
#include <QtFbSupport/private/qfbvthandler_p.h>
|
||||
#ifndef QT_NO_OPENGL
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <QtGui/private/qwindow_p.h>
|
||||
#include <QtGui/private/qgenericunixeventdispatcher_p.h>
|
||||
#include <QtGui/private/qgenericunixfontdatabase_p.h>
|
||||
#include <QtGui/private/qgenericunixthemes_p.h>
|
||||
#include <QtGui/private/qgenericunixtheme_p.h>
|
||||
#include <qpa/qplatformservices.h>
|
||||
|
||||
#include <QtFbSupport/private/qfbvthandler_p.h>
|
||||
|
@ -43,7 +43,8 @@
|
||||
#endif
|
||||
|
||||
#include <qpa/qplatforminputcontextfactory_p.h>
|
||||
#include <private/qgenericunixthemes_p.h>
|
||||
#include <private/qgenericunixtheme_p.h>
|
||||
#include <private/qkdetheme_p.h>
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
|
||||
#include <QtGui/QOpenGLContext>
|
||||
|
@ -5,7 +5,7 @@
|
||||
#define QGTK3THEME_H
|
||||
|
||||
#include <private/qtguiglobal_p.h>
|
||||
#include <private/qgenericunixthemes_p.h>
|
||||
#include <private/qgnometheme_p.h>
|
||||
#include "qgtk3storage_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
Loading…
x
Reference in New Issue
Block a user