blob: afd2c4cd7ded78add5c93185219bc20515b430d6 (
plain)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 | // 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>#if QT_CONFIG(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>#if QT_CONFIG(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>#if QT_CONFIG(dbus)#include <QtDBus/QDBusConnectionInterface>#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 namespaceQt::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(newQGenericUnixThemePrivate()){}const QFont *QGenericUnixTheme::font(Font type)const{Q_D(const QGenericUnixTheme);switch(type) {caseQPlatformTheme::SystemFont:return&d->systemFont;caseQPlatformTheme::FixedFont:return&d->fixedFont;default:returnnullptr;}}#if QT_CONFIG(dbus) QPlatformMenuBar *QGenericUnixTheme::createPlatformMenuBar()const{if(isDBusGlobalMenuAvailable())return newQDBusMenuBar();returnnullptr;}#endif#if QT_CONFIG(dbus) && QT_CONFIG(systemtrayicon) QPlatformSystemTrayIcon *QGenericUnixTheme::createPlatformSystemTrayIcon()const{if(shouldUseDBusTray())return newQDBusTrayIcon();returnnullptr;}#endif QVariant QGenericUnixTheme::themeHint(ThemeHint hint)const{switch(hint) {caseQPlatformTheme::SystemIconFallbackThemeName:returnQVariant(QString(QStringLiteral("hicolor")));caseQPlatformTheme::IconThemeSearchPaths:returnxdgIconThemePaths();caseQPlatformTheme::IconFallbackSearchPaths:returniconFallbackPaths();caseQPlatformTheme::DialogButtonBoxButtonsHaveIcons:returnQVariant(true);caseQPlatformTheme::StyleNames: { QStringList styleNames; styleNames <<QStringLiteral("Fusion") <<QStringLiteral("Windows");returnQVariant(styleNames);}caseQPlatformTheme::KeyboardScheme:returnQVariant(int(X11KeyboardScheme));caseQPlatformTheme::UiEffects:returnQVariant(int(HoverEffect));caseQPlatformTheme::MouseCursorTheme:returnQVariant(mouseCursorTheme());caseQPlatformTheme::MouseCursorSize:returnQVariant(mouseCursorSize());caseQPlatformTheme::PreferFileIconFromTheme:return true;default:break;}returnQPlatformTheme::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 QT_CONFIG(dbus) && QT_CONFIG(settings) && (QT_CONFIG(xcb) || QT_CONFIG(wayland))if(desktopEnvironment =="KDE") { result.push_back(QLatin1StringView(QKdeTheme::name));}else#endifif(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 QT_CONFIG(dbus) && QT_CONFIG(settings) && (QT_CONFIG(xcb) || QT_CONFIG(wayland))if(name ==QLatin1StringView(QKdeTheme::name))returnQKdeTheme::createKdeTheme();#endifif(name ==QLatin1StringView(QGnomeTheme::name))return new QGnomeTheme;returnnullptr;}// Helper to return the icon theme paths from XDG. QStringList QGenericUnixTheme::xdgIconThemePaths(){ QStringList paths;// Add home directory first in search pathconst 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(){constexprint defaultCursorSize =24;static const int xCursorSize =qEnvironmentVariableIntValue("XCURSOR_SIZE");static const int s = xCursorSize >0? xCursorSize : defaultCursorSize;returnQSize(s, s);}#if QT_CONFIG(dbus)static boolcheckDBusGlobalMenuAvailable(){const QDBusConnection connection =QDBusConnection::sessionBus();static const QString registrarService =QStringLiteral("com.canonical.AppMenu.Registrar");if(constauto iface = connection.interface())return iface->isServiceRegistered(registrarService);return false;}boolQGenericUnixTheme::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())returnQIcon();const QString &iconName = mimeType.iconName();if(!iconName.isEmpty()) { 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(dbus) && QT_CONFIG(systemtrayicon)boolQGenericUnixTheme::shouldUseDBusTray(){// There's no other tray implementation to fallback to on non-X11// and QDBusTrayIcon can register the icon on the fly after creationif(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(){returnQIcon::fromTheme(QStringLiteral("inode-directory")).availableSizes();} QT_END_NAMESPACE
|