| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the plugins of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | 
| 21 | ** packaging of this file. Please review the following information to | 
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | 
| 24 | ** | 
| 25 | ** GNU General Public License Usage | 
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | 
| 28 | ** Public license version 3 or any later version approved by the KDE Free | 
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | 
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | 
| 31 | ** included in the packaging of this file. Please review the following | 
| 32 | ** information to ensure the GNU General Public License requirements will | 
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | 
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | 
| 35 | ** | 
| 36 | ** $QT_END_LICENSE$ | 
| 37 | ** | 
| 38 | ****************************************************************************/ | 
| 39 |  | 
| 40 | #include "qgenericunixthemes_p.h" | 
| 41 |  | 
| 42 | #include "qpa/qplatformtheme_p.h" | 
| 43 |  | 
| 44 | #include <QtGui/QPalette> | 
| 45 | #include <QtGui/QFont> | 
| 46 | #include <QtGui/QGuiApplication> | 
| 47 | #include <QtCore/QDir> | 
| 48 | #include <QtCore/QFileInfo> | 
| 49 | #include <QtCore/QFile> | 
| 50 | #include <QtCore/QDebug> | 
| 51 | #include <QtCore/QHash> | 
| 52 | #if QT_CONFIG(mimetype) | 
| 53 | #include <QtCore/QMimeDatabase> | 
| 54 | #endif | 
| 55 | #include <QtCore/QLoggingCategory> | 
| 56 | #if QT_CONFIG(settings) | 
| 57 | #include <QtCore/QSettings> | 
| 58 | #endif | 
| 59 | #include <QtCore/QVariant> | 
| 60 | #include <QtCore/QStandardPaths> | 
| 61 | #include <QtCore/QStringList> | 
| 62 | #include <private/qguiapplication_p.h> | 
| 63 | #include <qpa/qplatformintegration.h> | 
| 64 | #include <qpa/qplatformservices.h> | 
| 65 | #include <qpa/qplatformdialoghelper.h> | 
| 66 | #ifndef QT_NO_DBUS | 
| 67 | #include "qdbusplatformmenu_p.h" | 
| 68 | #include "qdbusmenubar_p.h" | 
| 69 | #endif | 
| 70 | #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) | 
| 71 | #include "qdbustrayicon_p.h" | 
| 72 | #endif | 
| 73 |  | 
| 74 | #include <algorithm> | 
| 75 |  | 
| 76 | QT_BEGIN_NAMESPACE | 
| 77 |  | 
| 78 | Q_DECLARE_LOGGING_CATEGORY(qLcTray) | 
| 79 | Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts" ) | 
| 80 |  | 
| 81 | ResourceHelper::ResourceHelper() | 
| 82 | { | 
| 83 |     std::fill(first: palettes, last: palettes + QPlatformTheme::NPalettes, value: static_cast<QPalette *>(0)); | 
| 84 |     std::fill(first: fonts, last: fonts + QPlatformTheme::NFonts, value: static_cast<QFont *>(0)); | 
| 85 | } | 
| 86 |  | 
| 87 | void ResourceHelper::clear() | 
| 88 | { | 
| 89 |     qDeleteAll(begin: palettes, end: palettes + QPlatformTheme::NPalettes); | 
| 90 |     qDeleteAll(begin: fonts, end: fonts + QPlatformTheme::NFonts); | 
| 91 |     std::fill(first: palettes, last: palettes + QPlatformTheme::NPalettes, value: static_cast<QPalette *>(0)); | 
| 92 |     std::fill(first: fonts, last: fonts + QPlatformTheme::NFonts, value: static_cast<QFont *>(0)); | 
| 93 | } | 
| 94 |  | 
| 95 | const char *QGenericUnixTheme::name = "generic" ; | 
| 96 |  | 
| 97 | // Default system font, corresponding to the value returned by 4.8 for | 
| 98 | // XRender/FontConfig which we can now assume as default. | 
| 99 | static const char defaultSystemFontNameC[] = "Sans Serif" ; | 
| 100 | static const char defaultFixedFontNameC[] = "monospace" ; | 
| 101 | enum { defaultSystemFontSize = 9 }; | 
| 102 |  | 
| 103 | #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) | 
| 104 | static bool isDBusTrayAvailable() { | 
| 105 |     static bool dbusTrayAvailable = false; | 
| 106 |     static bool dbusTrayAvailableKnown = false; | 
| 107 |     if (!dbusTrayAvailableKnown) { | 
| 108 |         QDBusMenuConnection conn; | 
| 109 |         if (conn.isStatusNotifierHostRegistered()) | 
| 110 |             dbusTrayAvailable = true; | 
| 111 |         dbusTrayAvailableKnown = true; | 
| 112 |         qCDebug(qLcTray) << "D-Bus tray available:"  << dbusTrayAvailable; | 
| 113 |     } | 
| 114 |     return dbusTrayAvailable; | 
| 115 | } | 
| 116 | #endif | 
| 117 |  | 
| 118 | #ifndef QT_NO_DBUS | 
| 119 | static bool () | 
| 120 | { | 
| 121 |     const QDBusConnection connection = QDBusConnection::sessionBus(); | 
| 122 |     static const QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar" ); | 
| 123 |     if (const auto iface = connection.interface()) | 
| 124 |         return iface->isServiceRegistered(serviceName: registrarService); | 
| 125 |     return false; | 
| 126 | } | 
| 127 |  | 
| 128 | static bool () | 
| 129 | { | 
| 130 |     static bool  = checkDBusGlobalMenuAvailable(); | 
| 131 |     return dbusGlobalMenuAvailable; | 
| 132 | } | 
| 133 | #endif | 
| 134 |  | 
| 135 | class QGenericUnixThemePrivate : public QPlatformThemePrivate | 
| 136 | { | 
| 137 | public: | 
| 138 |     QGenericUnixThemePrivate() | 
| 139 |         : QPlatformThemePrivate() | 
| 140 |         , systemFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize) | 
| 141 |         , fixedFont(QLatin1String(defaultFixedFontNameC), systemFont.pointSize()) | 
| 142 |     { | 
| 143 |         fixedFont.setStyleHint(QFont::TypeWriter); | 
| 144 |         qCDebug(lcQpaFonts) << "default fonts: system"  << systemFont << "fixed"  << fixedFont; | 
| 145 |     } | 
| 146 |  | 
| 147 |     const QFont systemFont; | 
| 148 |     QFont fixedFont; | 
| 149 | }; | 
| 150 |  | 
| 151 | QGenericUnixTheme::QGenericUnixTheme() | 
| 152 |     : QPlatformTheme(new QGenericUnixThemePrivate()) | 
| 153 | { | 
| 154 | } | 
| 155 |  | 
| 156 | const QFont *QGenericUnixTheme::font(Font type) const | 
| 157 | { | 
| 158 |     Q_D(const QGenericUnixTheme); | 
| 159 |     switch (type) { | 
| 160 |     case QPlatformTheme::SystemFont: | 
| 161 |         return &d->systemFont; | 
| 162 |     case QPlatformTheme::FixedFont: | 
| 163 |         return &d->fixedFont; | 
| 164 |     default: | 
| 165 |         return 0; | 
| 166 |     } | 
| 167 | } | 
| 168 |  | 
| 169 | // Helper to return the icon theme paths from XDG. | 
| 170 | QStringList QGenericUnixTheme::xdgIconThemePaths() | 
| 171 | { | 
| 172 |     QStringList paths; | 
| 173 |     // Add home directory first in search path | 
| 174 |     const QFileInfo homeIconDir(QDir::homePath() + QLatin1String("/.icons" )); | 
| 175 |     if (homeIconDir.isDir()) | 
| 176 |         paths.prepend(t: homeIconDir.absoluteFilePath()); | 
| 177 |  | 
| 178 |     paths.append(t: QStandardPaths::locateAll(type: QStandardPaths::GenericDataLocation, | 
| 179 |                                            QStringLiteral("icons" ), | 
| 180 |                                            options: QStandardPaths::LocateDirectory)); | 
| 181 |  | 
| 182 |     return paths; | 
| 183 | } | 
| 184 |  | 
| 185 | QStringList QGenericUnixTheme::iconFallbackPaths() | 
| 186 | { | 
| 187 |     QStringList paths; | 
| 188 |     const QFileInfo pixmapsIconsDir(QStringLiteral("/usr/share/pixmaps" )); | 
| 189 |     if (pixmapsIconsDir.isDir()) | 
| 190 |         paths.append(t: pixmapsIconsDir.absoluteFilePath()); | 
| 191 |  | 
| 192 |     return paths; | 
| 193 | } | 
| 194 |  | 
| 195 | #ifndef QT_NO_DBUS | 
| 196 | QPlatformMenuBar *QGenericUnixTheme::() const | 
| 197 | { | 
| 198 |     if (isDBusGlobalMenuAvailable()) | 
| 199 |         return new QDBusMenuBar(); | 
| 200 |     return nullptr; | 
| 201 | } | 
| 202 | #endif | 
| 203 |  | 
| 204 | #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) | 
| 205 | QPlatformSystemTrayIcon *QGenericUnixTheme::createPlatformSystemTrayIcon() const | 
| 206 | { | 
| 207 |     if (isDBusTrayAvailable()) | 
| 208 |         return new QDBusTrayIcon(); | 
| 209 |     return nullptr; | 
| 210 | } | 
| 211 | #endif | 
| 212 |  | 
| 213 | QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const | 
| 214 | { | 
| 215 |     switch (hint) { | 
| 216 |     case QPlatformTheme::SystemIconFallbackThemeName: | 
| 217 |         return QVariant(QString(QStringLiteral("hicolor" ))); | 
| 218 |     case QPlatformTheme::IconThemeSearchPaths: | 
| 219 |         return xdgIconThemePaths(); | 
| 220 |     case QPlatformTheme::IconFallbackSearchPaths: | 
| 221 |         return iconFallbackPaths(); | 
| 222 |     case QPlatformTheme::DialogButtonBoxButtonsHaveIcons: | 
| 223 |         return QVariant(true); | 
| 224 |     case QPlatformTheme::StyleNames: { | 
| 225 |         QStringList styleNames; | 
| 226 |         styleNames << QStringLiteral("Fusion" ) << QStringLiteral("Windows" ); | 
| 227 |         return QVariant(styleNames); | 
| 228 |     } | 
| 229 |     case QPlatformTheme::KeyboardScheme: | 
| 230 |         return QVariant(int(X11KeyboardScheme)); | 
| 231 |     case QPlatformTheme::UiEffects: | 
| 232 |         return QVariant(int(HoverEffect)); | 
| 233 |     default: | 
| 234 |         break; | 
| 235 |     } | 
| 236 |     return QPlatformTheme::themeHint(hint); | 
| 237 | } | 
| 238 |  | 
| 239 | // Helper functions for implementing QPlatformTheme::fileIcon() for XDG icon themes. | 
| 240 | static QList<QSize> availableXdgFileIconSizes() | 
| 241 | { | 
| 242 |     return QIcon::fromTheme(QStringLiteral("inode-directory" )).availableSizes(); | 
| 243 | } | 
| 244 |  | 
| 245 | #if QT_CONFIG(mimetype) | 
| 246 | static QIcon xdgFileIcon(const QFileInfo &fileInfo) | 
| 247 | { | 
| 248 |     QMimeDatabase mimeDatabase; | 
| 249 |     QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo); | 
| 250 |     if (!mimeType.isValid()) | 
| 251 |         return QIcon(); | 
| 252 |     const QString &iconName = mimeType.iconName(); | 
| 253 |     if (!iconName.isEmpty()) { | 
| 254 |         const QIcon icon = QIcon::fromTheme(name: iconName); | 
| 255 |         if (!icon.isNull()) | 
| 256 |             return icon; | 
| 257 |     } | 
| 258 |     const QString &genericIconName = mimeType.genericIconName(); | 
| 259 |     return genericIconName.isEmpty() ? QIcon() : QIcon::fromTheme(name: genericIconName); | 
| 260 | } | 
| 261 | #endif | 
| 262 |  | 
| 263 | #if QT_CONFIG(settings) | 
| 264 | class QKdeThemePrivate : public QPlatformThemePrivate | 
| 265 | { | 
| 266 | public: | 
| 267 |     QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion) | 
| 268 |         : kdeDirs(kdeDirs) | 
| 269 |         , kdeVersion(kdeVersion) | 
| 270 |     { } | 
| 271 |  | 
| 272 |     static QString kdeGlobals(const QString &kdeDir, int kdeVersion) | 
| 273 |     { | 
| 274 |         if (kdeVersion > 4) | 
| 275 |             return kdeDir + QLatin1String("/kdeglobals" ); | 
| 276 |         return kdeDir + QLatin1String("/share/config/kdeglobals" ); | 
| 277 |     } | 
| 278 |  | 
| 279 |     void refresh(); | 
| 280 |     static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings); | 
| 281 |     static void readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal); | 
| 282 |     static QFont *kdeFont(const QVariant &fontValue); | 
| 283 |     static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs); | 
| 284 |  | 
| 285 |     const QStringList kdeDirs; | 
| 286 |     const int kdeVersion; | 
| 287 |  | 
| 288 |     ResourceHelper resources; | 
| 289 |     QString iconThemeName; | 
| 290 |     QString iconFallbackThemeName; | 
| 291 |     QStringList styleNames; | 
| 292 |     int toolButtonStyle = Qt::ToolButtonTextBesideIcon; | 
| 293 |     int toolBarIconSize = 0; | 
| 294 |     bool singleClick = true; | 
| 295 |     bool showIconsOnPushButtons = true; | 
| 296 |     int wheelScrollLines = 3; | 
| 297 |     int doubleClickInterval = 400; | 
| 298 |     int startDragDist = 10; | 
| 299 |     int startDragTime = 500; | 
| 300 |     int cursorBlinkRate = 1000; | 
| 301 | }; | 
| 302 |  | 
| 303 | void QKdeThemePrivate::refresh() | 
| 304 | { | 
| 305 |     resources.clear(); | 
| 306 |  | 
| 307 |     toolButtonStyle = Qt::ToolButtonTextBesideIcon; | 
| 308 |     toolBarIconSize = 0; | 
| 309 |     styleNames.clear(); | 
| 310 |     if (kdeVersion >= 5) | 
| 311 |         styleNames << QStringLiteral("breeze" ); | 
| 312 |     styleNames << QStringLiteral("Oxygen" ) << QStringLiteral("fusion" ) << QStringLiteral("windows" ); | 
| 313 |     if (kdeVersion >= 5) | 
| 314 |         iconFallbackThemeName = iconThemeName = QStringLiteral("breeze" ); | 
| 315 |     else | 
| 316 |         iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen" ); | 
| 317 |  | 
| 318 |     QHash<QString, QSettings*> kdeSettings; | 
| 319 |  | 
| 320 |     QPalette systemPalette = QPalette(); | 
| 321 |     readKdeSystemPalette(kdeDirs, kdeVersion, kdeSettings, pal: &systemPalette); | 
| 322 |     resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette); | 
| 323 |     //## TODO tooltip color | 
| 324 |  | 
| 325 |     const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle" ), kdeDirs, kdeVersion, kdeSettings); | 
| 326 |     if (styleValue.isValid()) { | 
| 327 |         const QString style = styleValue.toString(); | 
| 328 |         if (style != styleNames.front()) | 
| 329 |             styleNames.push_front(t: style); | 
| 330 |     } | 
| 331 |  | 
| 332 |     const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick" ), kdeDirs, kdeVersion, kdeSettings); | 
| 333 |     if (singleClickValue.isValid()) | 
| 334 |         singleClick = singleClickValue.toBool(); | 
| 335 |  | 
| 336 |     const QVariant showIconsOnPushButtonsValue = readKdeSetting(QStringLiteral("KDE/ShowIconsOnPushButtons" ), kdeDirs, kdeVersion, kdeSettings); | 
| 337 |     if (showIconsOnPushButtonsValue.isValid()) | 
| 338 |         showIconsOnPushButtons = showIconsOnPushButtonsValue.toBool(); | 
| 339 |  | 
| 340 |     const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme" ), kdeDirs, kdeVersion, kdeSettings); | 
| 341 |     if (themeValue.isValid()) | 
| 342 |         iconThemeName = themeValue.toString(); | 
| 343 |  | 
| 344 |     const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size" ), kdeDirs, kdeVersion, kdeSettings); | 
| 345 |     if (toolBarIconSizeValue.isValid()) | 
| 346 |         toolBarIconSize = toolBarIconSizeValue.toInt(); | 
| 347 |  | 
| 348 |     const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle" ), kdeDirs, kdeVersion, kdeSettings); | 
| 349 |     if (toolbarStyleValue.isValid()) { | 
| 350 |         const QString toolBarStyle = toolbarStyleValue.toString(); | 
| 351 |         if (toolBarStyle == QLatin1String("TextBesideIcon" )) | 
| 352 |             toolButtonStyle =  Qt::ToolButtonTextBesideIcon; | 
| 353 |         else if (toolBarStyle == QLatin1String("TextOnly" )) | 
| 354 |             toolButtonStyle = Qt::ToolButtonTextOnly; | 
| 355 |         else if (toolBarStyle == QLatin1String("TextUnderIcon" )) | 
| 356 |             toolButtonStyle = Qt::ToolButtonTextUnderIcon; | 
| 357 |     } | 
| 358 |  | 
| 359 |     const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines" ), kdeDirs, kdeVersion, kdeSettings); | 
| 360 |     if (wheelScrollLinesValue.isValid()) | 
| 361 |         wheelScrollLines = wheelScrollLinesValue.toInt(); | 
| 362 |  | 
| 363 |     const QVariant doubleClickIntervalValue = readKdeSetting(QStringLiteral("KDE/DoubleClickInterval" ), kdeDirs, kdeVersion, kdeSettings); | 
| 364 |     if (doubleClickIntervalValue.isValid()) | 
| 365 |         doubleClickInterval = doubleClickIntervalValue.toInt(); | 
| 366 |  | 
| 367 |     const QVariant startDragDistValue = readKdeSetting(QStringLiteral("KDE/StartDragDist" ), kdeDirs, kdeVersion, kdeSettings); | 
| 368 |     if (startDragDistValue.isValid()) | 
| 369 |         startDragDist = startDragDistValue.toInt(); | 
| 370 |  | 
| 371 |     const QVariant startDragTimeValue = readKdeSetting(QStringLiteral("KDE/StartDragTime" ), kdeDirs, kdeVersion, kdeSettings); | 
| 372 |     if (startDragTimeValue.isValid()) | 
| 373 |         startDragTime = startDragTimeValue.toInt(); | 
| 374 |  | 
| 375 |     const QVariant cursorBlinkRateValue = readKdeSetting(QStringLiteral("KDE/CursorBlinkRate" ), kdeDirs, kdeVersion, kdeSettings); | 
| 376 |     if (cursorBlinkRateValue.isValid()) { | 
| 377 |         cursorBlinkRate = cursorBlinkRateValue.toInt(); | 
| 378 |         cursorBlinkRate = cursorBlinkRate > 0 ? qBound(min: 200, val: cursorBlinkRate, max: 2000) : 0; | 
| 379 |     } | 
| 380 |  | 
| 381 |     // Read system font, ignore 'smallestReadableFont' | 
| 382 |     if (QFont *systemFont = kdeFont(fontValue: readKdeSetting(QStringLiteral("font" ), kdeDirs, kdeVersion, kdeSettings))) | 
| 383 |         resources.fonts[QPlatformTheme::SystemFont] = systemFont; | 
| 384 |     else | 
| 385 |         resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); | 
| 386 |  | 
| 387 |     if (QFont *fixedFont = kdeFont(fontValue: readKdeSetting(QStringLiteral("fixed" ), kdeDirs, kdeVersion, kdeSettings))) { | 
| 388 |         resources.fonts[QPlatformTheme::FixedFont] = fixedFont; | 
| 389 |     } else { | 
| 390 |         fixedFont = new QFont(QLatin1String(defaultFixedFontNameC), defaultSystemFontSize); | 
| 391 |         fixedFont->setStyleHint(QFont::TypeWriter); | 
| 392 |         resources.fonts[QPlatformTheme::FixedFont] = fixedFont; | 
| 393 |     } | 
| 394 |  | 
| 395 |     if (QFont * = kdeFont(fontValue: readKdeSetting(QStringLiteral("menuFont" ), kdeDirs, kdeVersion, kdeSettings))) { | 
| 396 |         resources.fonts[QPlatformTheme::MenuFont] = menuFont; | 
| 397 |         resources.fonts[QPlatformTheme::MenuBarFont] = new QFont(*menuFont); | 
| 398 |     } | 
| 399 |  | 
| 400 |     if (QFont *toolBarFont = kdeFont(fontValue: readKdeSetting(QStringLiteral("toolBarFont" ), kdeDirs, kdeVersion, kdeSettings))) | 
| 401 |         resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont; | 
| 402 |  | 
| 403 |     qCDebug(lcQpaFonts) << "default fonts: system"  << resources.fonts[QPlatformTheme::SystemFont] | 
| 404 |                         << "fixed"  << resources.fonts[QPlatformTheme::FixedFont]; | 
| 405 |     qDeleteAll(c: kdeSettings); | 
| 406 | } | 
| 407 |  | 
| 408 | QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings) | 
| 409 | { | 
| 410 |     for (const QString &kdeDir : kdeDirs) { | 
| 411 |         QSettings *settings = kdeSettings.value(akey: kdeDir); | 
| 412 |         if (!settings) { | 
| 413 |             const QString kdeGlobalsPath = kdeGlobals(kdeDir, kdeVersion); | 
| 414 |             if (QFileInfo(kdeGlobalsPath).isReadable()) { | 
| 415 |                 settings = new QSettings(kdeGlobalsPath, QSettings::IniFormat); | 
| 416 |                 kdeSettings.insert(akey: kdeDir, avalue: settings); | 
| 417 |             } | 
| 418 |         } | 
| 419 |         if (settings) { | 
| 420 |             const QVariant value = settings->value(key); | 
| 421 |             if (value.isValid()) | 
| 422 |                 return value; | 
| 423 |         } | 
| 424 |     } | 
| 425 |     return QVariant(); | 
| 426 | } | 
| 427 |  | 
| 428 | // Reads the color from the KDE configuration, and store it in the | 
| 429 | // palette with the given color role if found. | 
| 430 | static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVariant &value) | 
| 431 | { | 
| 432 |     if (!value.isValid()) | 
| 433 |         return false; | 
| 434 |     const QStringList values = value.toStringList(); | 
| 435 |     if (values.size() != 3) | 
| 436 |         return false; | 
| 437 |     pal->setBrush(acr: role, abrush: QColor(values.at(i: 0).toInt(), values.at(i: 1).toInt(), values.at(i: 2).toInt())); | 
| 438 |     return true; | 
| 439 | } | 
| 440 |  | 
| 441 | void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal) | 
| 442 | { | 
| 443 |     if (!kdeColor(pal, role: QPalette::Button, value: readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal" ), kdeDirs, kdeVersion, kdeSettings))) { | 
| 444 |         // kcolorscheme.cpp: SetDefaultColors | 
| 445 |         const QColor defaultWindowBackground(214, 210, 208); | 
| 446 |         const QColor defaultButtonBackground(223, 220, 217); | 
| 447 |         *pal = QPalette(defaultButtonBackground, defaultWindowBackground); | 
| 448 |         return; | 
| 449 |     } | 
| 450 |  | 
| 451 |     kdeColor(pal, role: QPalette::Window, value: readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 452 |     kdeColor(pal, role: QPalette::Text, value: readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 453 |     kdeColor(pal, role: QPalette::WindowText, value: readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 454 |     kdeColor(pal, role: QPalette::Base, value: readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 455 |     kdeColor(pal, role: QPalette::Highlight, value: readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 456 |     kdeColor(pal, role: QPalette::HighlightedText, value: readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 457 |     kdeColor(pal, role: QPalette::AlternateBase, value: readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 458 |     kdeColor(pal, role: QPalette::ButtonText, value: readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 459 |     kdeColor(pal, role: QPalette::Link, value: readKdeSetting(QStringLiteral("Colors:View/ForegroundLink" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 460 |     kdeColor(pal, role: QPalette::LinkVisited, value: readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 461 |     kdeColor(pal, role: QPalette::ToolTipBase, value: readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 462 |     kdeColor(pal, role: QPalette::ToolTipText, value: readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal" ), kdeDirs, kdeVersion, kdeSettings)); | 
| 463 |  | 
| 464 |     // The above code sets _all_ color roles to "normal" colors. In KDE, the disabled | 
| 465 |     // color roles are calculated by applying various effects described in kdeglobals. | 
| 466 |     // We use a bit simpler approach here, similar logic than in qt_palette_from_color(). | 
| 467 |     const QColor button = pal->color(cr: QPalette::Button); | 
| 468 |     int h, s, v; | 
| 469 |     button.getHsv(h: &h, s: &s, v: &v); | 
| 470 |  | 
| 471 |     const QBrush whiteBrush = QBrush(Qt::white); | 
| 472 |     const QBrush buttonBrush = QBrush(button); | 
| 473 |     const QBrush buttonBrushDark = QBrush(button.darker(f: v > 128 ? 200 : 50)); | 
| 474 |     const QBrush buttonBrushDark150 = QBrush(button.darker(f: v > 128 ? 150 : 75)); | 
| 475 |     const QBrush buttonBrushLight150 = QBrush(button.lighter(f: v > 128 ? 150 : 75)); | 
| 476 |     const QBrush buttonBrushLight = QBrush(button.lighter(f: v > 128 ? 200 : 50)); | 
| 477 |  | 
| 478 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::WindowText, brush: buttonBrushDark); | 
| 479 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::ButtonText, brush: buttonBrushDark); | 
| 480 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::Button, brush: buttonBrush); | 
| 481 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::Text, brush: buttonBrushDark); | 
| 482 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::BrightText, brush: whiteBrush); | 
| 483 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::Base, brush: buttonBrush); | 
| 484 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::Window, brush: buttonBrush); | 
| 485 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::Highlight, brush: buttonBrushDark150); | 
| 486 |     pal->setBrush(cg: QPalette::Disabled, cr: QPalette::HighlightedText, brush: buttonBrushLight150); | 
| 487 |  | 
| 488 |     // set calculated colors for all groups | 
| 489 |     pal->setBrush(acr: QPalette::Light, abrush: buttonBrushLight); | 
| 490 |     pal->setBrush(acr: QPalette::Midlight, abrush: buttonBrushLight150); | 
| 491 |     pal->setBrush(acr: QPalette::Mid, abrush: buttonBrushDark150); | 
| 492 |     pal->setBrush(acr: QPalette::Dark, abrush: buttonBrushDark); | 
| 493 | } | 
| 494 |  | 
| 495 | /*! | 
| 496 |     \class QKdeTheme | 
| 497 |     \brief QKdeTheme is a theme implementation for the KDE desktop (version 4 or higher). | 
| 498 |     \since 5.0 | 
| 499 |     \internal | 
| 500 |     \ingroup qpa | 
| 501 | */ | 
| 502 |  | 
| 503 | const char *QKdeTheme::name = "kde" ; | 
| 504 |  | 
| 505 | QKdeTheme::QKdeTheme(const QStringList& kdeDirs, int kdeVersion) | 
| 506 |     : QPlatformTheme(new QKdeThemePrivate(kdeDirs,kdeVersion)) | 
| 507 | { | 
| 508 |     d_func()->refresh(); | 
| 509 | } | 
| 510 |  | 
| 511 | QFont *QKdeThemePrivate::kdeFont(const QVariant &fontValue) | 
| 512 | { | 
| 513 |     if (fontValue.isValid()) { | 
| 514 |         // Read font value: Might be a QStringList as KDE stores fonts without quotes. | 
| 515 |         // Also retrieve the family for the constructor since we cannot use the | 
| 516 |         // default constructor of QFont, which accesses QGuiApplication::systemFont() | 
| 517 |         // causing recursion. | 
| 518 |         QString fontDescription; | 
| 519 |         QString fontFamily; | 
| 520 |         if (fontValue.userType() == QMetaType::QStringList) { | 
| 521 |             const QStringList list = fontValue.toStringList(); | 
| 522 |             if (!list.isEmpty()) { | 
| 523 |                 fontFamily = list.first(); | 
| 524 |                 fontDescription = list.join(sep: QLatin1Char(',')); | 
| 525 |             } | 
| 526 |         } else { | 
| 527 |             fontDescription = fontFamily = fontValue.toString(); | 
| 528 |         } | 
| 529 |         if (!fontDescription.isEmpty()) { | 
| 530 |             QFont font(fontFamily); | 
| 531 |             if (font.fromString(fontDescription)) | 
| 532 |                 return new QFont(font); | 
| 533 |         } | 
| 534 |     } | 
| 535 |     return 0; | 
| 536 | } | 
| 537 |  | 
| 538 |  | 
| 539 | QStringList QKdeThemePrivate::kdeIconThemeSearchPaths(const QStringList &kdeDirs) | 
| 540 | { | 
| 541 |     QStringList paths = QGenericUnixTheme::xdgIconThemePaths(); | 
| 542 |     const QString iconPath = QStringLiteral("/share/icons" ); | 
| 543 |     for (const QString &candidate : kdeDirs) { | 
| 544 |         const QFileInfo fi(candidate + iconPath); | 
| 545 |         if (fi.isDir()) | 
| 546 |             paths.append(t: fi.absoluteFilePath()); | 
| 547 |     } | 
| 548 |     return paths; | 
| 549 | } | 
| 550 |  | 
| 551 | QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const | 
| 552 | { | 
| 553 |     Q_D(const QKdeTheme); | 
| 554 |     switch (hint) { | 
| 555 |     case QPlatformTheme::UseFullScreenForPopupMenu: | 
| 556 |         return QVariant(true); | 
| 557 |     case QPlatformTheme::DialogButtonBoxButtonsHaveIcons: | 
| 558 |         return QVariant(d->showIconsOnPushButtons); | 
| 559 |     case QPlatformTheme::DialogButtonBoxLayout: | 
| 560 |         return QVariant(QPlatformDialogHelper::KdeLayout); | 
| 561 |     case QPlatformTheme::ToolButtonStyle: | 
| 562 |         return QVariant(d->toolButtonStyle); | 
| 563 |     case QPlatformTheme::ToolBarIconSize: | 
| 564 |         return QVariant(d->toolBarIconSize); | 
| 565 |     case QPlatformTheme::SystemIconThemeName: | 
| 566 |         return QVariant(d->iconThemeName); | 
| 567 |     case QPlatformTheme::SystemIconFallbackThemeName: | 
| 568 |         return QVariant(d->iconFallbackThemeName); | 
| 569 |     case QPlatformTheme::IconThemeSearchPaths: | 
| 570 |         return QVariant(d->kdeIconThemeSearchPaths(kdeDirs: d->kdeDirs)); | 
| 571 |     case QPlatformTheme::IconPixmapSizes: | 
| 572 |         return QVariant::fromValue(value: availableXdgFileIconSizes()); | 
| 573 |     case QPlatformTheme::StyleNames: | 
| 574 |         return QVariant(d->styleNames); | 
| 575 |     case QPlatformTheme::KeyboardScheme: | 
| 576 |         return QVariant(int(KdeKeyboardScheme)); | 
| 577 |     case QPlatformTheme::ItemViewActivateItemOnSingleClick: | 
| 578 |         return QVariant(d->singleClick); | 
| 579 |     case QPlatformTheme::WheelScrollLines: | 
| 580 |         return QVariant(d->wheelScrollLines); | 
| 581 |     case QPlatformTheme::MouseDoubleClickInterval: | 
| 582 |         return QVariant(d->doubleClickInterval); | 
| 583 |     case QPlatformTheme::StartDragTime: | 
| 584 |         return QVariant(d->startDragTime); | 
| 585 |     case QPlatformTheme::StartDragDistance: | 
| 586 |         return QVariant(d->startDragDist); | 
| 587 |     case QPlatformTheme::CursorFlashTime: | 
| 588 |         return QVariant(d->cursorBlinkRate); | 
| 589 |     case QPlatformTheme::UiEffects: | 
| 590 |         return QVariant(int(HoverEffect)); | 
| 591 |     default: | 
| 592 |         break; | 
| 593 |     } | 
| 594 |     return QPlatformTheme::themeHint(hint); | 
| 595 | } | 
| 596 |  | 
| 597 | QIcon QKdeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const | 
| 598 | { | 
| 599 | #if QT_CONFIG(mimetype) | 
| 600 |     return xdgFileIcon(fileInfo); | 
| 601 | #else | 
| 602 |     Q_UNUSED(fileInfo); | 
| 603 |     return QIcon(); | 
| 604 | #endif | 
| 605 | } | 
| 606 |  | 
| 607 | const QPalette *QKdeTheme::palette(Palette type) const | 
| 608 | { | 
| 609 |     Q_D(const QKdeTheme); | 
| 610 |     return d->resources.palettes[type]; | 
| 611 | } | 
| 612 |  | 
| 613 | const QFont *QKdeTheme::font(Font type) const | 
| 614 | { | 
| 615 |     Q_D(const QKdeTheme); | 
| 616 |     return d->resources.fonts[type]; | 
| 617 | } | 
| 618 |  | 
| 619 | QPlatformTheme *QKdeTheme::createKdeTheme() | 
| 620 | { | 
| 621 |     const QByteArray kdeVersionBA = qgetenv(varName: "KDE_SESSION_VERSION" ); | 
| 622 |     const int kdeVersion = kdeVersionBA.toInt(); | 
| 623 |     if (kdeVersion < 4) | 
| 624 |         return 0; | 
| 625 |  | 
| 626 |     if (kdeVersion > 4) | 
| 627 |         // Plasma 5 follows XDG spec | 
| 628 |         // but uses the same config file format: | 
| 629 |         return new QKdeTheme(QStandardPaths::standardLocations(type: QStandardPaths::GenericConfigLocation), kdeVersion); | 
| 630 |  | 
| 631 |     // Determine KDE prefixes in the following priority order: | 
| 632 |     // - KDEHOME and KDEDIRS environment variables | 
| 633 |     // - ~/.kde(<version>) | 
| 634 |     // - read prefixes from /etc/kde<version>rc | 
| 635 |     // - fallback to /etc/kde<version> | 
| 636 |  | 
| 637 |     QStringList kdeDirs; | 
| 638 |     const QString kdeHomePathVar = QFile::decodeName(localFileName: qgetenv(varName: "KDEHOME" )); | 
| 639 |     if (!kdeHomePathVar.isEmpty()) | 
| 640 |         kdeDirs += kdeHomePathVar; | 
| 641 |  | 
| 642 |     const QString kdeDirsVar = QFile::decodeName(localFileName: qgetenv(varName: "KDEDIRS" )); | 
| 643 |     if (!kdeDirsVar.isEmpty()) | 
| 644 |         kdeDirs += kdeDirsVar.split(sep: QLatin1Char(':'), behavior: Qt::SkipEmptyParts); | 
| 645 |  | 
| 646 |     const QString kdeVersionHomePath = QDir::homePath() + QLatin1String("/.kde" ) + QLatin1String(kdeVersionBA); | 
| 647 |     if (QFileInfo(kdeVersionHomePath).isDir()) | 
| 648 |         kdeDirs += kdeVersionHomePath; | 
| 649 |  | 
| 650 |     const QString kdeHomePath = QDir::homePath() + QLatin1String("/.kde" ); | 
| 651 |     if (QFileInfo(kdeHomePath).isDir()) | 
| 652 |         kdeDirs += kdeHomePath; | 
| 653 |  | 
| 654 |     const QString kdeRcPath = QLatin1String("/etc/kde" ) + QLatin1String(kdeVersionBA) + QLatin1String("rc" ); | 
| 655 |     if (QFileInfo(kdeRcPath).isReadable()) { | 
| 656 |         QSettings kdeSettings(kdeRcPath, QSettings::IniFormat); | 
| 657 |         kdeSettings.beginGroup(QStringLiteral("Directories-default" )); | 
| 658 |         kdeDirs += kdeSettings.value(QStringLiteral("prefixes" )).toStringList(); | 
| 659 |     } | 
| 660 |  | 
| 661 |     const QString kdeVersionPrefix = QLatin1String("/etc/kde" ) + QLatin1String(kdeVersionBA); | 
| 662 |     if (QFileInfo(kdeVersionPrefix).isDir()) | 
| 663 |         kdeDirs += kdeVersionPrefix; | 
| 664 |  | 
| 665 |     kdeDirs.removeDuplicates(); | 
| 666 |     if (kdeDirs.isEmpty()) { | 
| 667 |         qWarning(msg: "Unable to determine KDE dirs" ); | 
| 668 |         return 0; | 
| 669 |     } | 
| 670 |  | 
| 671 |     return new QKdeTheme(kdeDirs, kdeVersion); | 
| 672 | } | 
| 673 |  | 
| 674 | #ifndef QT_NO_DBUS | 
| 675 | QPlatformMenuBar *QKdeTheme::() const | 
| 676 | { | 
| 677 |     if (isDBusGlobalMenuAvailable()) | 
| 678 |         return new QDBusMenuBar(); | 
| 679 |     return nullptr; | 
| 680 | } | 
| 681 | #endif | 
| 682 |  | 
| 683 | #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) | 
| 684 | QPlatformSystemTrayIcon *QKdeTheme::createPlatformSystemTrayIcon() const | 
| 685 | { | 
| 686 |     if (isDBusTrayAvailable()) | 
| 687 |         return new QDBusTrayIcon(); | 
| 688 |     return nullptr; | 
| 689 | } | 
| 690 | #endif | 
| 691 |  | 
| 692 | #endif // settings | 
| 693 |  | 
| 694 | /*! | 
| 695 |     \class QGnomeTheme | 
| 696 |     \brief QGnomeTheme is a theme implementation for the Gnome desktop. | 
| 697 |     \since 5.0 | 
| 698 |     \internal | 
| 699 |     \ingroup qpa | 
| 700 | */ | 
| 701 |  | 
| 702 | const char *QGnomeTheme::name = "gnome" ; | 
| 703 |  | 
| 704 | class QGnomeThemePrivate : public QPlatformThemePrivate | 
| 705 | { | 
| 706 | public: | 
| 707 |     QGnomeThemePrivate() : systemFont(nullptr), fixedFont(nullptr) {} | 
| 708 |     ~QGnomeThemePrivate() { delete systemFont; delete fixedFont; } | 
| 709 |  | 
| 710 |     void configureFonts(const QString >kFontName) const | 
| 711 |     { | 
| 712 |         Q_ASSERT(!systemFont); | 
| 713 |         const int split = gtkFontName.lastIndexOf(c: QChar::Space); | 
| 714 |         float size = gtkFontName.midRef(position: split + 1).toFloat(); | 
| 715 |         QString fontName = gtkFontName.left(n: split); | 
| 716 |  | 
| 717 |         systemFont = new QFont(fontName, size); | 
| 718 |         fixedFont = new QFont(QLatin1String(defaultFixedFontNameC), systemFont->pointSize()); | 
| 719 |         fixedFont->setStyleHint(QFont::TypeWriter); | 
| 720 |         qCDebug(lcQpaFonts) << "default fonts: system"  << systemFont << "fixed"  << fixedFont; | 
| 721 |     } | 
| 722 |  | 
| 723 |     mutable QFont *systemFont; | 
| 724 |     mutable QFont *fixedFont; | 
| 725 | }; | 
| 726 |  | 
| 727 | QGnomeTheme::QGnomeTheme() | 
| 728 |     : QPlatformTheme(new QGnomeThemePrivate()) | 
| 729 | { | 
| 730 | } | 
| 731 |  | 
| 732 | QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const | 
| 733 | { | 
| 734 |     switch (hint) { | 
| 735 |     case QPlatformTheme::DialogButtonBoxButtonsHaveIcons: | 
| 736 |         return QVariant(true); | 
| 737 |     case QPlatformTheme::DialogButtonBoxLayout: | 
| 738 |         return QVariant(QPlatformDialogHelper::GnomeLayout); | 
| 739 |     case QPlatformTheme::SystemIconThemeName: | 
| 740 |         return QVariant(QStringLiteral("Adwaita" )); | 
| 741 |     case QPlatformTheme::SystemIconFallbackThemeName: | 
| 742 |         return QVariant(QStringLiteral("gnome" )); | 
| 743 |     case QPlatformTheme::IconThemeSearchPaths: | 
| 744 |         return QVariant(QGenericUnixTheme::xdgIconThemePaths()); | 
| 745 |     case QPlatformTheme::IconPixmapSizes: | 
| 746 |         return QVariant::fromValue(value: availableXdgFileIconSizes()); | 
| 747 |     case QPlatformTheme::StyleNames: { | 
| 748 |         QStringList styleNames; | 
| 749 |         styleNames << QStringLiteral("fusion" ) << QStringLiteral("windows" ); | 
| 750 |         return QVariant(styleNames); | 
| 751 |     } | 
| 752 |     case QPlatformTheme::KeyboardScheme: | 
| 753 |         return QVariant(int(GnomeKeyboardScheme)); | 
| 754 |     case QPlatformTheme::PasswordMaskCharacter: | 
| 755 |         return QVariant(QChar(0x2022)); | 
| 756 |     case QPlatformTheme::UiEffects: | 
| 757 |         return QVariant(int(HoverEffect)); | 
| 758 |     default: | 
| 759 |         break; | 
| 760 |     } | 
| 761 |     return QPlatformTheme::themeHint(hint); | 
| 762 | } | 
| 763 |  | 
| 764 | QIcon QGnomeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const | 
| 765 | { | 
| 766 | #if QT_CONFIG(mimetype) | 
| 767 |     return xdgFileIcon(fileInfo); | 
| 768 | #else | 
| 769 |     Q_UNUSED(fileInfo); | 
| 770 |     return QIcon(); | 
| 771 | #endif | 
| 772 | } | 
| 773 |  | 
| 774 | const QFont *QGnomeTheme::font(Font type) const | 
| 775 | { | 
| 776 |     Q_D(const QGnomeTheme); | 
| 777 |     if (!d->systemFont) | 
| 778 |         d->configureFonts(gtkFontName: gtkFontName()); | 
| 779 |     switch (type) { | 
| 780 |     case QPlatformTheme::SystemFont: | 
| 781 |         return d->systemFont; | 
| 782 |     case QPlatformTheme::FixedFont: | 
| 783 |         return d->fixedFont; | 
| 784 |     default: | 
| 785 |         return 0; | 
| 786 |     } | 
| 787 | } | 
| 788 |  | 
| 789 | QString QGnomeTheme::gtkFontName() const | 
| 790 | { | 
| 791 |     return QStringLiteral("%1 %2" ).arg(a: QLatin1String(defaultSystemFontNameC)).arg(a: defaultSystemFontSize); | 
| 792 | } | 
| 793 |  | 
| 794 | #ifndef QT_NO_DBUS | 
| 795 | QPlatformMenuBar *QGnomeTheme::() const | 
| 796 | { | 
| 797 |     if (isDBusGlobalMenuAvailable()) | 
| 798 |         return new QDBusMenuBar(); | 
| 799 |     return nullptr; | 
| 800 | } | 
| 801 | #endif | 
| 802 |  | 
| 803 | #if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON) | 
| 804 | QPlatformSystemTrayIcon *QGnomeTheme::createPlatformSystemTrayIcon() const | 
| 805 | { | 
| 806 |     if (isDBusTrayAvailable()) | 
| 807 |         return new QDBusTrayIcon(); | 
| 808 |     return nullptr; | 
| 809 | } | 
| 810 | #endif | 
| 811 |  | 
| 812 | QString QGnomeTheme::standardButtonText(int button) const | 
| 813 | { | 
| 814 |     switch (button) { | 
| 815 |     case QPlatformDialogHelper::Ok: | 
| 816 |         return QCoreApplication::translate(context: "QGnomeTheme" , key: "&OK" ); | 
| 817 |     case QPlatformDialogHelper::Save: | 
| 818 |         return QCoreApplication::translate(context: "QGnomeTheme" , key: "&Save" ); | 
| 819 |     case QPlatformDialogHelper::Cancel: | 
| 820 |         return QCoreApplication::translate(context: "QGnomeTheme" , key: "&Cancel" ); | 
| 821 |     case QPlatformDialogHelper::Close: | 
| 822 |         return QCoreApplication::translate(context: "QGnomeTheme" , key: "&Close" ); | 
| 823 |     case QPlatformDialogHelper::Discard: | 
| 824 |         return QCoreApplication::translate(context: "QGnomeTheme" , key: "Close without Saving" ); | 
| 825 |     default: | 
| 826 |         break; | 
| 827 |     } | 
| 828 |     return QPlatformTheme::standardButtonText(button); | 
| 829 | } | 
| 830 |  | 
| 831 | /*! | 
| 832 |     \brief Creates a UNIX theme according to the detected desktop environment. | 
| 833 | */ | 
| 834 |  | 
| 835 | QPlatformTheme *QGenericUnixTheme::createUnixTheme(const QString &name) | 
| 836 | { | 
| 837 |     if (name == QLatin1String(QGenericUnixTheme::name)) | 
| 838 |         return new QGenericUnixTheme; | 
| 839 | #if QT_CONFIG(settings) | 
| 840 |     if (name == QLatin1String(QKdeTheme::name)) | 
| 841 |         if (QPlatformTheme *kdeTheme = QKdeTheme::createKdeTheme()) | 
| 842 |             return kdeTheme; | 
| 843 | #endif | 
| 844 |     if (name == QLatin1String(QGnomeTheme::name)) | 
| 845 |         return new QGnomeTheme; | 
| 846 |     return nullptr; | 
| 847 | } | 
| 848 |  | 
| 849 | QStringList QGenericUnixTheme::themeNames() | 
| 850 | { | 
| 851 |     QStringList result; | 
| 852 |     if (QGuiApplication::desktopSettingsAware()) { | 
| 853 |         const QByteArray desktopEnvironment = QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment(); | 
| 854 |         QList<QByteArray> gtkBasedEnvironments; | 
| 855 |         gtkBasedEnvironments << "GNOME"  | 
| 856 |                              << "X-CINNAMON"  | 
| 857 |                              << "UNITY"  | 
| 858 |                              << "MATE"  | 
| 859 |                              << "XFCE"  | 
| 860 |                              << "LXDE" ; | 
| 861 |         const QList<QByteArray> desktopNames = desktopEnvironment.split(sep: ':'); | 
| 862 |         for (const QByteArray &desktopName : desktopNames) { | 
| 863 |             if (desktopEnvironment == "KDE" ) { | 
| 864 | #if QT_CONFIG(settings) | 
| 865 |                 result.push_back(t: QLatin1String(QKdeTheme::name)); | 
| 866 | #endif | 
| 867 |             } else if (gtkBasedEnvironments.contains(t: desktopName)) { | 
| 868 |                 // prefer the GTK3 theme implementation with native dialogs etc. | 
| 869 |                 result.push_back(QStringLiteral("gtk3" )); | 
| 870 |                 // fallback to the generic Gnome theme if loading the GTK3 theme fails | 
| 871 |                 result.push_back(t: QLatin1String(QGnomeTheme::name)); | 
| 872 |             } else { | 
| 873 |                 // unknown, but lowercase the name (our standard practice) and | 
| 874 |                 // remove any "x-" prefix | 
| 875 |                 QString s = QString::fromLatin1(str: desktopName.toLower()); | 
| 876 |                 result.push_back(t: s.startsWith(s: QLatin1String("x-" )) ? s.mid(position: 2) : s); | 
| 877 |             } | 
| 878 |         } | 
| 879 |     } // desktopSettingsAware | 
| 880 |     result.append(t: QLatin1String(QGenericUnixTheme::name)); | 
| 881 |     return result; | 
| 882 | } | 
| 883 |  | 
| 884 | QT_END_NAMESPACE | 
| 885 |  |