Add palette() and further hints to QtGui/QPlatformTheme.

- Move palette() from deprecated QtWidgets/QGuiPlatformPlugin
  to  QtGui/QPlatformTheme, Make it return a const * since
  QPalette does not have isNull().
- Initialize QGuiApplication::palette() and
  QApplication::systemPalette() from it.
- Do not initialize QPalette from QGuiApplication::palette()
  unless app_pal is non-null (default to Qt::black if it is 0).
  This avoids initialization order crashes/recursions in the
  QPA plugin. Streamline initialization function.
- Remove styleName(), systemIconThemeName() and iconSearchPaths()
  from QGuiPlatformPlugin and re-add them as
  QPlatformTheme::themeHint().
- Remove styleHint() from QGuiPlatformPlugin, add it to
  QPlatformTheme::themeHint().
- Add UNIX themes with factory function (Generic,
  KDE, Gnome), taking it from Qt 4.8 code (stripping the
  KDE 3 code).
- Implement Windows palettes.

Task-number: QTBUG-24204

Change-Id: Ie27ec035df4f84c42deaffc4816b2e53ce705462
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
This commit is contained in:
Friedemann Kleint 2012-02-10 17:17:36 +01:00 committed by Qt by Nokia
parent 71bad3e818
commit 4cf0deef73
31 changed files with 849 additions and 239 deletions

View File

@ -48,6 +48,7 @@
#include "qplatformfontdatabase_qpa.h"
#include "qplatformwindow_qpa.h"
#include "qplatformnativeinterface_qpa.h"
#include "qplatformtheme_qpa.h"
#include <QtCore/QAbstractEventDispatcher>
#include <QtCore/private/qcoreapplication_p.h>
@ -1382,6 +1383,9 @@ QClipboard * QGuiApplication::clipboard()
*/
QPalette QGuiApplication::palette()
{
if (!QGuiApplicationPrivate::app_pal)
if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette())
QGuiApplicationPrivate::app_pal = new QPalette(*themePalette);
if (!QGuiApplicationPrivate::app_pal)
QGuiApplicationPrivate::app_pal = new QPalette(Qt::black);
return *QGuiApplicationPrivate::app_pal;

View File

@ -41,6 +41,7 @@
#include "qpalette.h"
#include "qguiapplication.h"
#include "qguiapplication_p.h"
#include "qdatastream.h"
#include "qvariant.h"
#include "qdebug.h"
@ -64,6 +65,29 @@ static QColor qt_mix_colors(QColor a, QColor b)
(a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
}
static void qt_palette_from_color(QPalette &pal, const QColor &button)
{
int h, s, v;
button.getHsv(&h, &s, &v);
// inactive and active are the same..
const QBrush baseBrush = QBrush(v > 128 ? Qt::white : Qt::black);
const QBrush foregroundBrush = QBrush(v > 128 ? Qt::black : Qt::white);
const QBrush buttonBrush = QBrush(button);
const QBrush buttonBrushDark = QBrush(button.darker());
const QBrush buttonBrushDark150 = QBrush(button.darker(150));
const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
const QBrush whiteBrush = QBrush(Qt::white);
pal.setColorGroup(QPalette::Active, foregroundBrush, buttonBrush, buttonBrushLight150,
buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
baseBrush, buttonBrush);
pal.setColorGroup(QPalette::Inactive, foregroundBrush, buttonBrush, buttonBrushLight150,
buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
baseBrush, buttonBrush);
pal.setColorGroup(QPalette::Disabled, buttonBrushDark, buttonBrush, buttonBrushLight150,
buttonBrushDark, buttonBrushDark150, buttonBrushDark,
whiteBrush, buttonBrush, buttonBrush);
}
/*!
\fn const QColor &QPalette::color(ColorRole role) const
@ -488,40 +512,20 @@ static QColor qt_mix_colors(QColor a, QColor b)
\sa QApplication::setPalette(), QApplication::palette()
*/
QPalette::QPalette()
: d(QGuiApplication::palette().d),
current_group(Active),
resolve_mask(0)
: d(0), current_group(Active), resolve_mask(0)
{
d->ref.ref();
}
static void qt_palette_from_color(QPalette &pal, const QColor & button)
{
QColor bg = button,
btn = button,
fg, base;
int h, s, v;
bg.getHsv(&h, &s, &v);
if(v > 128) {
fg = Qt::black;
base = Qt::white;
// Initialize to application palette if present, else default to black.
// This makes it possible to instantiate QPalette outside QGuiApplication,
// for example in the platform plugins.
if (QGuiApplicationPrivate::app_pal) {
d = QGuiApplicationPrivate::app_pal->d;
d->ref.ref();
} else {
fg = Qt::white;
base = Qt::black;
init();
qt_palette_from_color(*this, Qt::black);
}
//inactive and active are the same..
pal.setColorGroup(QPalette::Active, QBrush(fg), QBrush(btn), QBrush(btn.lighter(150)),
QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(fg), QBrush(Qt::white),
QBrush(base), QBrush(bg));
pal.setColorGroup(QPalette::Inactive, QBrush(fg), QBrush(btn), QBrush(btn.lighter(150)),
QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(fg), QBrush(Qt::white),
QBrush(base), QBrush(bg));
pal.setColorGroup(QPalette::Disabled, QBrush(btn.darker()), QBrush(btn), QBrush(btn.lighter(150)),
QBrush(btn.darker()), QBrush(btn.darker(150)), QBrush(btn.darker()),
QBrush(Qt::white), QBrush(bg), QBrush(bg));
}
/*!
Constructs a palette from the \a button color. The other colors are
automatically calculated, based on this color. \c Window will be

View File

@ -42,6 +42,8 @@
#include "qplatformtheme_qpa.h"
#include <QtCore/QVariant>
#include <QtCore/QStringList>
#include <qpalette.h>
QT_BEGIN_NAMESPACE
@ -68,6 +70,21 @@ QT_BEGIN_NAMESPACE
\value MaximumScrollBarDragDistance (int) Determines the value returned by
QStyle::pixelMetric(PM_MaximumDragDistance)
\value ToolButtonStyle (int) A value representing a Qt::ToolButtonStyle.
\value ToolBarIconSize Icon size for tool bars.
\value SystemIconThemeName (QString) Name of the icon theme.
\value SystemIconFallbackThemeName (QString) Name of the fallback icon theme.
\value IconThemeSearchPaths (QStringList) Search paths for icons.
\value ItemViewActivateItemOnSingleClick (bool) Activate items by single click.
\value StyleNames (QStringList) A list of preferred style names.
\sa themeHint(), QStyle::pixelMetric()
*/
@ -95,9 +112,28 @@ QPlatformDialogHelper *QPlatformTheme::createPlatformDialogHelper(DialogType typ
return 0;
}
const QPalette *QPlatformTheme::palette(Palette type) const
{
Q_UNUSED(type)
return 0;
}
QVariant QPlatformTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
case QPlatformTheme::ItemViewActivateItemOnSingleClick:
return QVariant(false);
case QPlatformTheme::ToolButtonStyle:
return QVariant(int(Qt::ToolButtonIconOnly));
case QPlatformTheme::ToolBarIconSize:
return QVariant(int(0));
case QPlatformTheme::SystemIconThemeName:
case QPlatformTheme::SystemIconFallbackThemeName:
return QVariant(QString());
case QPlatformTheme::IconThemeSearchPaths:
return QVariant(QStringList());
case QPlatformTheme::StyleNames:
return QVariant(QStringList());
case TextCursorWidth:
return QVariant(1);
case DropShadow:

View File

@ -48,13 +48,13 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QMenu;
class QMenuBar;
class QPlatformMenu;
class QPlatformMenuBar;
class QPlatformDialogHelper;
class QVariant;
class QPalette;
class Q_GUI_EXPORT QPlatformTheme
{
@ -62,7 +62,14 @@ public:
enum ThemeHint {
TextCursorWidth,
DropShadow,
MaximumScrollBarDragDistance
MaximumScrollBarDragDistance,
ToolButtonStyle,
ToolBarIconSize,
ItemViewActivateItemOnSingleClick,
SystemIconThemeName,
SystemIconFallbackThemeName,
IconThemeSearchPaths,
StyleNames
};
enum DialogType {
@ -71,12 +78,20 @@ public:
FontDialog
};
enum Palette {
SystemPalette,
ToolTipPalette,
NPalettes
};
virtual QPlatformMenu *createPlatformMenu(QMenu *menu = 0) const;
virtual QPlatformMenuBar *createPlatformMenuBar(QMenuBar *menuBar = 0) const;
virtual bool usePlatformNativeDialog(DialogType type) const;
virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
virtual const QPalette *palette(Palette type = SystemPalette) const;
virtual QVariant themeHint(ThemeHint hint) const;
};

View File

@ -35,3 +35,4 @@ include(glxconvenience/glxconvenience.pri)
include(inputcontext/inputcontext.pri)
include(udev/udev.pri)
include(services/services.pri)
include(themes/themes.pri)

View File

@ -122,9 +122,10 @@ static inline bool launch(const QString &launcher, const QUrl &url)
return ok;
}
QGenericUnixServices::QGenericUnixServices() :
m_desktopEnvironment(detectDesktopEnvironment())
QGenericUnixServices::DesktopEnvironment QGenericUnixServices::desktopEnvironment()
{
static const DesktopEnvironment result = detectDesktopEnvironment();
return result;
}
bool QGenericUnixServices::openUrl(const QUrl &url)
@ -132,7 +133,7 @@ bool QGenericUnixServices::openUrl(const QUrl &url)
if (url.scheme() == QStringLiteral("mailto"))
return openDocument(url);
if (m_webBrowser.isEmpty() && !detectWebBrowser(m_desktopEnvironment, true, &m_webBrowser)) {
if (m_webBrowser.isEmpty() && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) {
qWarning("%s: Unable to detect a web browser to launch '%s'", Q_FUNC_INFO, qPrintable(url.toString()));
return false;
}
@ -141,7 +142,7 @@ bool QGenericUnixServices::openUrl(const QUrl &url)
bool QGenericUnixServices::openDocument(const QUrl &url)
{
if (m_documentLauncher.isEmpty() && !detectWebBrowser(m_desktopEnvironment, false, &m_documentLauncher)) {
if (m_documentLauncher.isEmpty() && !detectWebBrowser(desktopEnvironment(), false, &m_documentLauncher)) {
qWarning("%s: Unable to detect a launcher for '%s'", Q_FUNC_INFO, qPrintable(url.toString()));
return false;
}

View File

@ -58,13 +58,14 @@ public:
DE_GNOME
};
QGenericUnixServices();
QGenericUnixServices() {}
static DesktopEnvironment desktopEnvironment();
virtual bool openUrl(const QUrl &url);
virtual bool openDocument(const QUrl &url);
private:
const DesktopEnvironment m_desktopEnvironment;
QString m_webBrowser;
QString m_documentLauncher;
};

View File

@ -0,0 +1,2 @@
HEADERS += $$PWD/qgenericunixthemes_p.h
SOURCES += $$PWD/qgenericunixthemes.cpp

View File

@ -0,0 +1,325 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgenericunixthemes_p.h"
#include "../../services/genericunix/qgenericunixservices_p.h"
#include <QtGui/QPalette>
#include <QtGui/QGuiApplication>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFile>
#include <QtCore/QDebug>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
/*!
\class QGenericX11ThemeQKdeTheme
\brief QGenericX11Theme is a generic theme implementation for X11.
\since 5.0
\internal
\ingroup qpa
*/
// 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() + QStringLiteral("/.icons"));
if (homeIconDir.isDir())
paths.prepend(homeIconDir.absoluteFilePath());
QString xdgDirString = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
if (xdgDirString.isEmpty())
xdgDirString = QLatin1String("/usr/local/share/:/usr/share/");
foreach (const QString &xdgDir, xdgDirString.split(QLatin1Char(':'))) {
const QFileInfo xdgIconsDir(xdgDir + QStringLiteral("/icons"));
if (xdgIconsDir.isDir())
paths.append(xdgIconsDir.absoluteFilePath());
}
return paths;
}
QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
case QPlatformTheme::SystemIconFallbackThemeName:
return QVariant(QString(QStringLiteral("hicolor")));
case QPlatformTheme::IconThemeSearchPaths:
return xdgIconThemePaths();
case QPlatformTheme::StyleNames: {
QStringList styleNames;
styleNames << QStringLiteral("Plastique") << QStringLiteral("Windows");
return QVariant(styleNames);
}
break;
default:
break;
}
return QPlatformTheme::themeHint(hint);
}
// Reads the color from the KDE configuration, and store it in the
// palette with the given color role if found.
static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role,
const QSettings &kdeSettings, const QString &key)
{
const QVariant value = kdeSettings.value(key);
if (!value.isValid())
return false;
const QStringList values = value.toStringList();
if (values.size() != 3)
return false;
pal->setBrush(role, QColor(values.at(0).toInt(), values.at(1).toInt(), values.at(2).toInt()));
return true;
}
// Reads the KDE system palette
static inline bool readKdeSystemPalette(const QSettings &kdeSettings, QPalette *pal)
{
// Setup KDE palette
return kdeColor(pal, QPalette::Button, kdeSettings, QStringLiteral("Colors:Button/BackgroundNormal"))
|| kdeColor(pal, QPalette::Window, kdeSettings, QStringLiteral("Colors:Window/BackgroundNormal"))
|| kdeColor(pal, QPalette::Text, kdeSettings, QStringLiteral("Colors:View/ForegroundNormal"))
|| kdeColor(pal, QPalette::WindowText, kdeSettings, QStringLiteral("Colors:Window/ForegroundNormal"))
|| kdeColor(pal, QPalette::Base, kdeSettings, QStringLiteral("Colors:View/BackgroundNormal"))
|| kdeColor(pal, QPalette::Highlight, kdeSettings, QStringLiteral("Colors:Selection/BackgroundNormal"))
|| kdeColor(pal, QPalette::HighlightedText, kdeSettings, QStringLiteral("Colors:Selection/ForegroundNormal"))
|| kdeColor(pal, QPalette::AlternateBase, kdeSettings, QStringLiteral("Colors:View/BackgroundAlternate"))
|| kdeColor(pal, QPalette::ButtonText, kdeSettings, QStringLiteral("Colors:Button/ForegroundNormal"))
|| kdeColor(pal, QPalette::Link, kdeSettings, QStringLiteral("Colors:View/ForegroundLink"))
|| kdeColor(pal, QPalette::LinkVisited, kdeSettings, QStringLiteral("Colors:View/ForegroundVisited"));
}
/*!
\class QKdeTheme
\brief QKdeTheme is a theme implementation for the KDE desktop (version 4 or higher).
\since 5.0
\internal
\ingroup qpa
*/
QKdeTheme::QKdeTheme(const QString &kdeHome, int kdeVersion) :
m_kdeHome(kdeHome), m_kdeVersion(kdeVersion),
m_toolButtonStyle(Qt::ToolButtonTextBesideIcon), m_toolBarIconSize(0)
{
qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
refresh();
}
void QKdeTheme::clearPalettes()
{
qDeleteAll(m_palettes, m_palettes + NPalettes);
qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
}
void QKdeTheme::refresh()
{
clearPalettes();
m_toolButtonStyle = Qt::ToolButtonTextBesideIcon;
m_toolBarIconSize = 0;
m_styleNames.clear();
m_styleNames << QStringLiteral("Oxygen") << QStringLiteral("plastique") << QStringLiteral("windows");
m_iconFallbackThemeName = m_iconThemeName = QStringLiteral("oxygen");
// Read settings file.
const QString settingsFile = globalSettingsFile();
if (!QFileInfo(settingsFile).isReadable())
return;
const QSettings kdeSettings(settingsFile, QSettings::IniFormat);
QPalette systemPalette;
if (readKdeSystemPalette(kdeSettings, &systemPalette))
m_palettes[SystemPalette] = new QPalette(systemPalette);
//## TODO tooltip color
const QVariant styleValue = kdeSettings.value(QStringLiteral("widgetStyle"));
if (styleValue.isValid()) {
const QString style = styleValue.toString();
if (style != m_styleNames.front())
m_styleNames.push_front(style);
}
const QVariant themeValue = kdeSettings.value(QStringLiteral("Icons/Theme"));
if (themeValue.isValid())
m_iconThemeName = themeValue.toString();
const QVariant toolBarIconSizeValue = kdeSettings.value(QStringLiteral("ToolbarIcons/Size"));
if (toolBarIconSizeValue.isValid())
m_toolBarIconSize = toolBarIconSizeValue.toInt();
const QVariant toolbarStyleValue = kdeSettings.value(QStringLiteral("ToolButtonStyle"));
if (toolbarStyleValue.isValid()) {
const QString toolBarStyle = toolbarStyleValue.toString();
if (toolBarStyle == QStringLiteral("TextBesideIcon"))
m_toolButtonStyle = Qt::ToolButtonTextBesideIcon;
else if (toolBarStyle == QStringLiteral("TextOnly"))
m_toolButtonStyle = Qt::ToolButtonTextOnly;
else if (toolBarStyle == QStringLiteral("TextUnderIcon"))
m_toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
}
QString QKdeTheme::globalSettingsFile() const
{
return m_kdeHome + QStringLiteral("/share/config/kdeglobals");
}
static QStringList kdeIconThemeSearchPaths(const QString &kdeHome)
{
QStringList candidates = QStringList(kdeHome);
const QString kdeDirs = QFile::decodeName(qgetenv("KDEDIRS"));
if (!kdeDirs.isEmpty())
candidates.append(kdeDirs.split(QLatin1Char(':')));
QStringList paths = QGenericUnixTheme::xdgIconThemePaths();
const QString iconPath = QStringLiteral("/share/icons");
foreach (const QString &candidate, candidates) {
const QFileInfo fi(candidate + iconPath);
if (fi.isDir())
paths.append(fi.absoluteFilePath());
}
return paths;
}
QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
{
switch (hint) {
case QPlatformTheme::ToolButtonStyle:
return QVariant(m_toolButtonStyle);
case QPlatformTheme::ToolBarIconSize:
return QVariant(m_toolBarIconSize);
case QPlatformTheme::SystemIconThemeName:
return QVariant(m_iconThemeName);
case QPlatformTheme::SystemIconFallbackThemeName:
return QVariant(m_iconFallbackThemeName);
case QPlatformTheme::IconThemeSearchPaths:
return QVariant(kdeIconThemeSearchPaths(m_kdeHome));
case QPlatformTheme::StyleNames:
return QVariant(m_styleNames);
default:
break;
}
return QPlatformTheme::themeHint(hint);
}
QPlatformTheme *QKdeTheme::createKdeTheme()
{
// Check for version >= 4 and determine home folder from environment,
// defaulting to ~/.kde<version>, ~/.kde
const QByteArray kdeVersionBA = qgetenv("KDE_SESSION_VERSION");
const int kdeVersion = kdeVersionBA.toInt();
if (kdeVersion < 4)
return 0;
const QString kdeHomePathVar = QString::fromLocal8Bit(qgetenv("KDEHOME"));
if (!kdeHomePathVar.isEmpty())
return new QKdeTheme(kdeHomePathVar, kdeVersion);
const QString kdeVersionHomePath = QDir::homePath() + QStringLiteral("/.kde") + QLatin1String(kdeVersionBA);
if (QFileInfo(kdeVersionHomePath).isDir())
return new QKdeTheme(kdeVersionHomePath, kdeVersion);
const QString kdeHomePath = QDir::homePath() + QStringLiteral("/.kde");
if (QFileInfo(kdeHomePath).isDir())
return new QKdeTheme(kdeHomePath, kdeVersion);
qWarning("%s: Unable to determine KDEHOME", Q_FUNC_INFO);
return 0;
}
/*!
\class QGnomeTheme
\brief QGnomeTheme is a theme implementation for the Gnome desktop.
\since 5.0
\internal
\ingroup qpa
*/
QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
{
switch (hint) {
case QPlatformTheme::SystemIconThemeName:
case QPlatformTheme::SystemIconFallbackThemeName:
return QVariant(QString(QStringLiteral("gnome")));
case QPlatformTheme::IconThemeSearchPaths:
return QVariant(QGenericUnixTheme::xdgIconThemePaths());
case QPlatformTheme::StyleNames: {
QStringList styleNames;
styleNames << QStringLiteral("GTK+") << QStringLiteral("cleanlooks") << QStringLiteral("windows");
return QVariant(styleNames);
}
default:
break;
}
return QPlatformTheme::themeHint(hint);
}
/*!
\brief Creates a UNIX theme according to the detected desktop environment.
*/
QPlatformTheme *QGenericUnixTheme::createUnixTheme()
{
QPlatformTheme *result = 0;
if (QGuiApplication::desktopSettingsAware()) {
switch (QGenericUnixServices::desktopEnvironment()) {
case QGenericUnixServices::DE_UNKNOWN:
break;
case QGenericUnixServices::DE_KDE:
result = QKdeTheme::createKdeTheme();
break;
case QGenericUnixServices::DE_GNOME:
result = new QGnomeTheme;
break;
}
}
if (!result)
result = new QGenericUnixTheme;
return result;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGENERICUNIXTHEMES_H
#define QGENERICUNIXTHEMES_H
#include <QtGui/QPlatformTheme>
#include <QtCore/QString>
#include <QtCore/QStringList>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QGenericUnixTheme : public QPlatformTheme
{
public:
QGenericUnixTheme() {}
static QPlatformTheme *createUnixTheme();
virtual QVariant themeHint(ThemeHint hint) const;
static QStringList xdgIconThemePaths();
};
class QKdeTheme : public QPlatformTheme
{
QKdeTheme(const QString &kdeHome, int kdeVersion);
public:
~QKdeTheme() { clearPalettes(); }
static QPlatformTheme *createKdeTheme();
virtual QVariant themeHint(ThemeHint hint) const;
virtual const QPalette *palette(Palette type = SystemPalette) const
{ return m_palettes[type]; }
private:
QString globalSettingsFile() const;
void clearPalettes();
void refresh();
const QString m_kdeHome;
const int m_kdeVersion;
QPalette *m_palettes[NPalettes];
QString m_iconThemeName;
QString m_iconFallbackThemeName;
QStringList m_styleNames;
int m_toolButtonStyle;
int m_toolBarIconSize;
};
class QGnomeTheme : public QPlatformTheme
{
public:
QGnomeTheme() {}
virtual QVariant themeHint(ThemeHint hint) const;
private:
};
QPlatformTheme *qt_createUnixTheme();
QT_END_NAMESPACE
QT_END_HEADER
#endif // QGENERICUNIXTHEMES_H

View File

@ -0,0 +1,3 @@
unix:!mac {
include($$PWD/genericunix/genericunix.pri)
}

View File

@ -59,6 +59,8 @@ public:
bool usePlatformNativeDialog(DialogType dialogType) const;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const;
QVariant themeHint(ThemeHint hint) const;
};
QT_END_NAMESPACE

View File

@ -102,4 +102,16 @@ QPlatformDialogHelper * QCocoaTheme::createPlatformDialogHelper(DialogType dialo
}
}
QVariant QCocoaTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
case QPlatformTheme::StyleNames:
return QStringList() << QLatin1Literal("macintosh");
break;
default:
return QPlatformTheme::themeHint(hint);
break;
}
}
QT_END_NAMESPACE

View File

@ -45,6 +45,10 @@
#include <QtCore/QtGlobal> // get compiler define
#include <QtCore/qt_windows.h>
#ifndef WM_THEMECHANGED
# define WM_THEMECHANGED 0x031A
#endif
/* Complement the definitions and declarations missing
* when using MinGW or older Windows SDKs. */

View File

@ -60,7 +60,8 @@ enum
KeyDownEventFlag = 0x200000,
TouchEventFlag = 0x400000,
ClipboardEventFlag = 0x800000,
ApplicationEventFlag = 0x1000000
ApplicationEventFlag = 0x1000000,
ThemingEventFlag = 0x2000000
};
enum WindowsEventType // Simplify event types
@ -97,6 +98,7 @@ enum WindowsEventType // Simplify event types
InputMethodOpenCandidateWindowEvent = InputMethodEventFlag + 4,
InputMethodCloseCandidateWindowEvent = InputMethodEventFlag + 5,
InputMethodRequest = InputMethodEventFlag + 6,
ThemeChanged = ThemingEventFlag + 1,
DisplayChangedEvent = 437,
UnknownEvent = 542
};
@ -178,6 +180,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::FocusOutEvent;
case WM_DISPLAYCHANGE:
return QtWindows::DisplayChangedEvent;
case WM_THEMECHANGED:
return QtWindows::ThemeChanged;
default:
break;
}

View File

@ -49,6 +49,7 @@
#include "qwindowsinputcontext.h"
#include "qwindowsaccessibility.h"
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
#include <QtGui/QWindow>
#include <QtGui/QWindowSystemInterface>
@ -78,6 +79,7 @@ int QWindowsContext::verboseGL = 0;
int QWindowsContext::verboseOLE = 0;
int QWindowsContext::verboseInputMethods = 0;
int QWindowsContext::verboseDialogs = 0;
int QWindowsContext::verboseTheming = 0;
// Get verbosity of components from "foo:2,bar:3"
static inline int componentVerbose(const char *v, const char *keyWord)
@ -284,6 +286,7 @@ QWindowsContext::QWindowsContext() :
QWindowsContext::verboseOLE = componentVerbose(v, "ole");
QWindowsContext::verboseInputMethods = componentVerbose(v, "im");
QWindowsContext::verboseDialogs = componentVerbose(v, "dialogs");
QWindowsContext::verboseTheming = componentVerbose(v, "theming");
}
}
@ -784,6 +787,9 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::CloseEvent:
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
return true;
case QtWindows::ThemeChanged: // ### fixme: Compress these events?
QWindowsTheme::instance()->windowsThemeChanged(platformWindow->window());
return true;
default:
break;
}

View File

@ -121,6 +121,7 @@ public:
static int verboseOLE;
static int verboseInputMethods;
static int verboseDialogs;
static int verboseTheming;
explicit QWindowsContext();
~QWindowsContext();

View File

@ -43,6 +43,7 @@
#include "qwindowscontext.h"
#include "qwindowswindow.h"
#include "qwindowstheme.h" // Color conversion helpers
#include <QtWidgets/QColorDialog>
#include <QtWidgets/QFontDialog>
@ -1268,12 +1269,6 @@ QWindowsNativeColorDialog::QWindowsNativeColorDialog(const SharedPointerColor &c
qFill(m_customColors, m_customColors + 16, COLORREF(0));
}
static inline COLORREF qColorToCOLORREF(const QColor &color)
{ return RGB(color.red(), color.green(), color.blue()); }
static inline QColor COLORREFToQColor(COLORREF cr)
{ return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr)); }
void QWindowsNativeColorDialog::exec(HWND owner)
{
typedef BOOL (WINAPI *ChooseColorWType)(LPCHOOSECOLORW);

View File

@ -203,7 +203,8 @@ messageDebugEntries[] = {
{WM_IME_ENDCOMPOSITION, "WM_IME_ENDCOMPOSITION"},
{WM_IME_NOTIFY, "WM_IME_NOTIFY"},
{WM_IME_REQUEST, "WM_IME_REQUEST"},
{WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE"}
{WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE"},
{WM_THEMECHANGED , "WM_THEMECHANGED"}
};
static inline const MessageDebugEntry *messageDebugEntry(UINT msg)

View File

@ -42,12 +42,126 @@
#include "qwindowstheme.h"
#include "qwindowsdialoghelpers.h"
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
#include "qt_windows.h"
#include <QtCore/QVariant>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QSysInfo>
#include <QtGui/QPalette>
#include <QtGui/QGuiApplication>
QT_BEGIN_NAMESPACE
static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
{
str.setIntegerBase(16);
str.setFieldWidth(2);
str.setPadChar(QLatin1Char('0'));
str << " rgb: #" << c.red() << c.green() << c.blue();
str.setIntegerBase(10);
str.setFieldWidth(0);
return str;
}
static inline QString paletteToString(const QPalette &palette)
{
QString result;
QTextStream str(&result);
str << "text=" << palette.color(QPalette::WindowText)
<< " background=" << palette.color(QPalette::Window);
return result;
}
static inline QColor mixColors(const QColor &c1, const QColor &c2)
{
return QColor ((c1.red() + c2.red()) / 2,
(c1.green() + c2.green()) / 2,
(c1.blue() + c2.blue()) / 2);
}
static inline QColor getSysColor(int index)
{
return qColorToCOLORREF(GetSysColor(index));
}
static inline QPalette systemPalette()
{
QPalette result;
result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT));
result.setColor(QPalette::Button, getSysColor(COLOR_BTNFACE));
result.setColor(QPalette::Light, getSysColor(COLOR_BTNHIGHLIGHT));
result.setColor(QPalette::Dark, getSysColor(COLOR_BTNSHADOW));
result.setColor(QPalette::Mid, result.button().color().darker(150));
result.setColor(QPalette::Text, getSysColor(COLOR_WINDOWTEXT));
result.setColor(QPalette::BrightText, getSysColor(COLOR_BTNHIGHLIGHT));
result.setColor(QPalette::Base, getSysColor(COLOR_WINDOW));
result.setColor(QPalette::Window, getSysColor(COLOR_BTNFACE));
result.setColor(QPalette::ButtonText, getSysColor(COLOR_BTNTEXT));
result.setColor(QPalette::Midlight, getSysColor(COLOR_3DLIGHT));
result.setColor(QPalette::Shadow, getSysColor(COLOR_3DDKSHADOW));
result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT));
result.setColor(QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT));
result.setColor(QPalette::Link, Qt::blue);
result.setColor(QPalette::LinkVisited, Qt::magenta);
result.setColor(QPalette::Inactive, QPalette::Button, result.button().color());
result.setColor(QPalette::Inactive, QPalette::Window, result.background().color());
result.setColor(QPalette::Inactive, QPalette::Light, result.light().color());
result.setColor(QPalette::Inactive, QPalette::Dark, result.dark().color());
if (result.midlight() == result.button())
result.setColor(QPalette::Midlight, result.button().color().lighter(110));
if (result.background() != result.base()) {
result.setColor(QPalette::Inactive, QPalette::Highlight, result.color(QPalette::Inactive, QPalette::Window));
result.setColor(QPalette::Inactive, QPalette::HighlightedText, result.color(QPalette::Inactive, QPalette::Text));
}
const QColor disabled =
mixColors(result.foreground().color(), result.button().color());
result.setColorGroup(QPalette::Disabled, result.foreground(), result.button(),
result.light(), result.dark(), result.mid(),
result.text(), result.brightText(), result.base(),
result.background());
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
result.setColor(QPalette::Disabled, QPalette::Highlight,
getSysColor(COLOR_HIGHLIGHT));
result.setColor(QPalette::Disabled, QPalette::HighlightedText,
getSysColor(COLOR_HIGHLIGHTTEXT));
result.setColor(QPalette::Disabled, QPalette::Base,
result.background().color());
return result;
}
QPalette toolTipPalette(const QPalette &systemPalette)
{
QPalette result(systemPalette);
const QColor tipBgColor(getSysColor(COLOR_INFOBK));
const QColor tipTextColor(getSysColor(COLOR_INFOTEXT));
result.setColor(QPalette::All, QPalette::Button, tipBgColor);
result.setColor(QPalette::All, QPalette::Window, tipBgColor);
result.setColor(QPalette::All, QPalette::Text, tipTextColor);
result.setColor(QPalette::All, QPalette::WindowText, tipTextColor);
result.setColor(QPalette::All, QPalette::ButtonText, tipTextColor);
result.setColor(QPalette::All, QPalette::Button, tipBgColor);
result.setColor(QPalette::All, QPalette::Window, tipBgColor);
result.setColor(QPalette::All, QPalette::Text, tipTextColor);
result.setColor(QPalette::All, QPalette::WindowText, tipTextColor);
result.setColor(QPalette::All, QPalette::ButtonText, tipTextColor);
const QColor disabled =
mixColors(result.foreground().color(), result.button().color());
result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
result.setColor(QPalette::Disabled, QPalette::Text, disabled);
result.setColor(QPalette::Disabled, QPalette::Base, Qt::white);
result.setColor(QPalette::Disabled, QPalette::BrightText, Qt::white);
return result;
}
static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
{
BOOL result;
@ -66,11 +180,53 @@ static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue)
QWindowsTheme::QWindowsTheme()
{
qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
refresh();
}
QWindowsTheme::~QWindowsTheme()
{
clearPalettes();
}
void QWindowsTheme::clearPalettes()
{
qDeleteAll(m_palettes, m_palettes + NPalettes);
qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
}
QWindowsTheme *QWindowsTheme::instance()
{
return static_cast<QWindowsTheme *>(QWindowsIntegration::instance()->platformTheme());
}
static inline QStringList iconThemeSearchPaths()
{
const QFileInfo appDir(QCoreApplication::applicationDirPath() + QStringLiteral("/icons"));
return appDir.isDir() ? QStringList(appDir.absoluteFilePath()) : QStringList();
}
static inline QStringList styleNames()
{
QStringList result;
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
result.append(QStringLiteral("WindowsVista"));
if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP)
result.append(QStringLiteral("WindowsXP"));
result.append(QStringLiteral("Windows"));
return result;
}
QVariant QWindowsTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
case SystemIconThemeName:
break;
case IconThemeSearchPaths:
return QVariant(iconThemeSearchPaths());
break;
case StyleNames:
return QVariant(styleNames());
case TextCursorWidth:
return QVariant(int(dWordSystemParametersInfo(SPI_GETCARETWIDTH, 1u)));
case DropShadow:
@ -81,6 +237,19 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
return QVariant();
}
void QWindowsTheme::refresh()
{
clearPalettes();
if (QGuiApplication::desktopSettingsAware()) {
m_palettes[SystemPalette] = new QPalette(systemPalette());
m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
if (QWindowsContext::verboseTheming)
qDebug() << __FUNCTION__ << '\n'
<< " system=" << paletteToString(*m_palettes[SystemPalette])
<< " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]);
}
}
bool QWindowsTheme::usePlatformNativeDialog(DialogType type) const
{
return QWindowsDialogs::useHelper(type);
@ -91,4 +260,10 @@ QPlatformDialogHelper *QWindowsTheme::createPlatformDialogHelper(DialogType type
return QWindowsDialogs::createHelper(type);
}
void QWindowsTheme::windowsThemeChanged(QWindow * /* window */)
{
refresh();
// QWindowSystemInterface::handleThemeChange(window);
}
QT_END_NAMESPACE

View File

@ -43,19 +43,43 @@
#define QWINDOWSTHEME_H
#include <QtGui/QPlatformTheme>
#include <QtGui/QColor>
#include "qtwindows_additional.h"
QT_BEGIN_NAMESPACE
class QWindow;
class QWindowsTheme : public QPlatformTheme
{
public:
QWindowsTheme();
~QWindowsTheme();
static QWindowsTheme *instance();
virtual bool usePlatformNativeDialog(DialogType type) const;
virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
virtual QVariant themeHint(ThemeHint) const;
virtual const QPalette *palette(Palette type = SystemPalette) const
{ return m_palettes[type]; }
void windowsThemeChanged(QWindow *window);
private:
void refresh();
void clearPalettes();
QPalette *m_palettes[NPalettes];
};
static inline COLORREF qColorToCOLORREF(const QColor &color)
{ return RGB(color.red(), color.green(), color.blue()); }
static inline QColor COLORREFToQColor(COLORREF cr)
{ return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr)); }
QT_END_NAMESPACE
#endif // QWINDOWSTHEME_H

View File

@ -70,6 +70,7 @@
#endif
#include <private/qplatforminputcontextfactory_qpa_p.h>
#include <private/qgenericunixthemes_p.h>
#include <qplatforminputcontext_qpa.h>
#if defined(XCB_USE_GLX)
@ -87,7 +88,8 @@ QT_BEGIN_NAMESPACE
QXcbIntegration::QXcbIntegration(const QStringList &parameters)
: m_eventDispatcher(createUnixEventDispatcher()),
m_services(new QGenericUnixServices)
m_services(new QGenericUnixServices),
m_theme(QGenericUnixTheme::createUnixTheme())
{
QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher);
@ -278,4 +280,9 @@ QPlatformServices *QXcbIntegration::services() const
return m_services.data();
}
QPlatformTheme *QXcbIntegration::platformTheme() const
{
return m_theme.data();
}
QT_END_NAMESPACE

View File

@ -85,6 +85,8 @@ public:
QPlatformServices *services() const;
QPlatformTheme *platformTheme() const;
private:
QList<QXcbConnection *> m_connections;
@ -101,6 +103,7 @@ private:
#endif
QScopedPointer<QPlatformServices> m_services;
QScopedPointer<QPlatformTheme> m_theme;
};
QT_END_NAMESPACE

View File

@ -62,6 +62,7 @@
#include "qvariant.h"
#include "qwidget.h"
#include "private/qdnd_p.h"
#include "private/qguiapplication_p.h"
#include "qcolormap.h"
#include "qdebug.h"
#include "private/qstylesheetstyle_p.h"
@ -71,6 +72,7 @@
#include <QtWidgets/qgraphicsproxywidget.h>
#include <QtGui/qstylehints.h>
#include <QtGui/qinputmethod.h>
#include <QtGui/qplatformtheme_qpa.h>
#include "private/qkeymapper_p.h"
@ -1297,6 +1299,9 @@ QStyle *QApplication::style()
// take ownership of the style
QApplicationPrivate::app_style->setParent(qApp);
if (!QApplicationPrivate::sys_pal)
if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette())
QApplicationPrivate::setSystemPalette(*themePalette);
if (!QApplicationPrivate::sys_pal)
QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
if (QApplicationPrivate::set_pal) // repolish set palette with the new style
@ -1850,7 +1855,15 @@ void QApplicationPrivate::setSystemFont(const QFont &font)
*/
QString QApplicationPrivate::desktopStyleKey()
{
return qt_guiPlatformPlugin()->styleName();
// The platform theme might return a style that is not available, find
// first valid one.
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QStringList availableKeys = QStyleFactory::keys();
foreach (const QString &style, theme->themeHint(QPlatformTheme::StyleNames).toStringList())
if (availableKeys.contains(style, Qt::CaseInsensitive))
return style;
}
return QString();
}
/*!

View File

@ -41,6 +41,7 @@
#include "qapplication_p.h"
#include "qcolormap.h"
#include "qpalette.h"
#include "qpixmapcache.h"
#ifndef QT_NO_CURSOR
#include "private/qcursor_p.h"
@ -53,8 +54,9 @@
#include "qgenericpluginfactory_qpa.h"
#include "private/qplatformintegrationfactory_qpa_p.h"
#include <qdesktopwidget.h>
#include <QPlatformCursor>
#include <QPlatformTheme>
#include <qdebug.h>
#include <QWindowSystemInterface>
#include "private/qwindowsysteminterface_qpa_p.h"
@ -62,6 +64,7 @@
#include "qdesktopwidget_qpa_p.h"
#include "qwidgetwindow_qpa_p.h"
#include "qtooltip.h"
#ifdef Q_OS_WIN
# include <QtCore/qt_windows.h> // for qt_win_display_dc()
@ -393,6 +396,8 @@ void qt_init(QApplicationPrivate *priv, int type)
qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QColormap::initialize();
if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
QToolTip::setPalette(*toolTipPalette);
qApp->setObjectName(appName);
}

View File

@ -125,169 +125,10 @@ QGuiPlatformPlugin *qt_guiPlatformPlugin()
QGuiPlatformPlugin::QGuiPlatformPlugin(QObject *parent) : QObject(parent) {}
QGuiPlatformPlugin::~QGuiPlatformPlugin() {}
/* return the string key to be used by default the application */
QString QGuiPlatformPlugin::styleName()
{
#if defined(Q_WS_WIN) && defined(Q_OS_WINCE)
if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
return QLatin1String("WindowsMobile");
else
return QLatin1String("WindowsCE");
#elif defined(Q_OS_WIN)
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
return QLatin1String("WindowsVista");
else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
return QLatin1String("WindowsXP");
else
return QLatin1String("Windows"); // default styles for Windows
#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
return QLatin1String("CDE"); // default style for X11 on Solaris
#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
return QLatin1String("SGI"); // default style for X11 on IRIX
#elif defined(Q_OS_MAC)
return QLatin1String("Macintosh"); // default style for all Mac's
#elif defined(Q_WS_X11)
QString stylename;
switch(X11->desktopEnvironment) {
case DE_KDE:
stylename = QKde::kdeStyle();
break;
case DE_GNOME: {
QStringList availableStyles = QStyleFactory::keys();
// Set QGtkStyle for GNOME if available
QString gtkStyleKey = QString::fromLatin1("GTK+");
if (availableStyles.contains(gtkStyleKey)) {
stylename = gtkStyleKey;
break;
}
if (X11->use_xrender)
stylename = QLatin1String("cleanlooks");
else
stylename = QLatin1String("windows");
break;
}
case DE_CDE:
stylename = QLatin1String("cde");
break;
default:
// Don't do anything
break;
}
return stylename;
#else
return QLatin1String("Plastique"); // default style for X11 and small devices
#endif
}
/* return an additional default palette (only work on X11) */
QPalette QGuiPlatformPlugin::palette()
{
#ifdef Q_WS_X11
if (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE)
return QKde::kdePalette();
#endif
return QPalette();
}
/* the default icon theme name for QIcon::fromTheme. */
QString QGuiPlatformPlugin::systemIconThemeName()
{
QString result;
#ifdef Q_WS_X11
if (X11->desktopEnvironment == DE_GNOME) {
result = QString::fromLatin1("gnome");
#ifndef QT_NO_STYLE_GTK
result = QGtkStylePrivate::getGConfString(QLatin1String("/desktop/gnome/interface/icon_theme"), result);
#endif
} else if (X11->desktopEnvironment == DE_KDE) {
result = X11->desktopVersion >= 4 ? QString::fromLatin1("oxygen") : QString::fromLatin1("crystalsvg");
QSettings settings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
settings.beginGroup(QLatin1String("Icons"));
result = settings.value(QLatin1String("Theme"), result).toString();
}
#endif
return result;
}
QStringList QGuiPlatformPlugin::iconThemeSearchPaths()
{
QStringList paths;
#if defined(Q_WS_X11)
QString xdgDirString = QFile::decodeName(getenv("XDG_DATA_DIRS"));
if (xdgDirString.isEmpty())
xdgDirString = QLatin1String("/usr/local/share/:/usr/share/");
QStringList xdgDirs = xdgDirString.split(QLatin1Char(':'));
for (int i = 0 ; i < xdgDirs.size() ; ++i) {
QDir dir(xdgDirs[i]);
if (dir.exists())
paths.append(dir.path() + QLatin1String("/icons"));
}
if (X11->desktopEnvironment == DE_KDE) {
paths << QLatin1Char(':') + QKde::kdeHome() + QLatin1String("/share/icons");
QStringList kdeDirs = QFile::decodeName(getenv("KDEDIRS")).split(QLatin1Char(':'));
for (int i = 0 ; i< kdeDirs.count() ; ++i) {
QDir dir(QLatin1Char(':') + kdeDirs.at(i) + QLatin1String("/share/icons"));
if (dir.exists())
paths.append(dir.path());
}
}
// Add home directory first in search path
QDir homeDir(QDir::homePath() + QLatin1String("/.icons"));
if (homeDir.exists())
paths.prepend(homeDir.path());
#endif
#if defined(Q_WS_WIN)
paths.append(qApp->applicationDirPath() + QLatin1String("/icons"));
#elif defined(Q_WS_MAC)
paths.append(qApp->applicationDirPath() + QLatin1String("/../Resources/icons"));
#endif
return paths;
}
/* backend for QFileIconProvider, null icon means default */
QIcon QGuiPlatformPlugin::fileSystemIcon(const QFileInfo &)
{
return QIcon();
}
/* Like QStyle::styleHint */
int QGuiPlatformPlugin::platformHint(PlatformHint hint)
{
int ret = 0;
switch(hint)
{
case PH_ToolButtonStyle:
ret = Qt::ToolButtonIconOnly;
#ifdef Q_WS_X11
if (X11->desktopEnvironment == DE_KDE && X11->desktopVersion >= 4
&& QApplication::desktopSettingsAware()) {
ret = QKde::kdeToolButtonStyle();
}
#endif
break;
case PH_ToolBarIconSize:
#ifdef Q_WS_X11
if (X11->desktopEnvironment == DE_KDE && X11->desktopVersion >= 4
&& QApplication::desktopSettingsAware()) {
ret = QKde::kdeToolBarIconSize();
}
#endif
//by default keep ret = 0 so QCommonStyle will use the style default
break;
default:
break;
}
return ret;
}
QT_END_NAMESPACE

View File

@ -87,14 +87,7 @@ class Q_WIDGETS_EXPORT QGuiPlatformPlugin : public QObject, public QGuiPlatformP
virtual QStringList keys() const { return QStringList(QStringLiteral("default")); }
virtual QString styleName();
virtual QPalette palette();
virtual QString systemIconThemeName();
virtual QStringList iconThemeSearchPaths();
virtual QIcon fileSystemIcon(const QFileInfo &);
enum PlatformHint { PH_ToolButtonStyle, PH_ToolBarIconSize, PH_ItemView_ActivateItemOnSingleClick };
virtual int platformHint(PlatformHint hint);
};
//internal

View File

@ -53,7 +53,6 @@
#include "qvariant.h"
#include "qcache.h"
#include "qdebug.h"
#include "private/qguiplatformplugin_p.h"
#include "qapplication.h"
#ifdef Q_WS_MAC

View File

@ -43,11 +43,12 @@
#include <private/qguiapplication_p.h>
#include <private/qicon_p.h>
#include <private/qguiplatformplugin_p.h>
#include <private/qguiapplication_p.h>
#include <QtWidgets/QApplication>
#include <QtWidgets/QIconEnginePlugin>
#include <QtGui/QPixmapCache>
#include <QtGui/QPlatformTheme>
#include <QtWidgets/QIconEngine>
#include <QtWidgets/QStyleOption>
#include <QtCore/QList>
@ -73,17 +74,11 @@ Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
/* Theme to use in last resort, if the theme does not have the icon, neither the parents */
static QString fallbackTheme()
{
#ifdef Q_WS_X11
if (X11->desktopEnvironment == DE_GNOME) {
return QLatin1String("gnome");
} else if (X11->desktopEnvironment == DE_KDE) {
return X11->desktopVersion >= 4
? QString::fromLatin1("oxygen")
: QString::fromLatin1("crystalsvg");
} else {
return QLatin1String("hicolor");
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconThemeName);
if (themeHint.isValid())
return themeHint.toString();
}
#endif
return QString();
}
@ -94,6 +89,27 @@ QIconLoader::QIconLoader() :
// We lazily initialize the loader to make static icons
// work. Though we do not officially support this.
static inline QString systemThemeName()
{
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconThemeName);
if (themeHint.isValid())
return themeHint.toString();
}
return QString();
}
static inline QStringList systemIconSearchPaths()
{
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QVariant themeHint = theme->themeHint(QPlatformTheme::IconThemeSearchPaths);
if (themeHint.isValid())
return themeHint.toStringList();
}
return QStringList();
}
void QIconLoader::ensureInitialized()
{
if (!m_initialized) {
@ -101,7 +117,8 @@ void QIconLoader::ensureInitialized()
Q_ASSERT(qApp);
m_systemTheme = qt_guiPlatformPlugin()->systemIconThemeName();
m_systemTheme = systemThemeName();
if (m_systemTheme.isEmpty())
m_systemTheme = fallbackTheme();
#ifndef QT_NO_LIBRARY
@ -125,7 +142,7 @@ void QIconLoader::updateSystemTheme()
{
// Only change if this is not explicitly set by the user
if (m_userTheme.isEmpty()) {
QString theme = qt_guiPlatformPlugin()->systemIconThemeName();
QString theme = systemThemeName();
if (theme.isEmpty())
theme = fallbackTheme();
if (theme != m_systemTheme) {
@ -151,7 +168,7 @@ void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
QStringList QIconLoader::themeSearchPaths() const
{
if (m_iconDirs.isEmpty()) {
m_iconDirs = qt_guiPlatformPlugin()->iconThemeSearchPaths();
m_iconDirs = systemIconSearchPaths();
// Always add resource directory as search path
m_iconDirs.append(QLatin1String(":/icons"));
}
@ -221,8 +238,11 @@ QIconTheme::QIconTheme(const QString &themeName)
QLatin1String("Icon Theme/Inherits")).toStringList();
// Ensure a default platform fallback for all themes
if (m_parents.isEmpty())
m_parents.append(fallbackTheme());
if (m_parents.isEmpty()) {
const QString fallback = fallbackTheme();
if (!fallback.isEmpty())
m_parents.append(fallback);
}
// Ensure that all themes fall back to hicolor
if (!m_parents.contains(QLatin1String("hicolor")))

View File

@ -45,6 +45,7 @@
#include <qfile.h>
#include <qapplication.h>
#include <private/qguiapplication_p.h>
#include <qplatformtheme_qpa.h>
#include <qbitmap.h>
#include <qcache.h>
#include <qdockwidget.h>
@ -75,7 +76,6 @@
#include <qsettings.h>
#include <qvariant.h>
#include <qpixmapcache.h>
#include <private/qguiplatformplugin_p.h>
#include <limits.h>
@ -4509,9 +4509,11 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
break;
case PM_ToolBarIconSize:
ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ToolBarIconSize);
if (!ret)
ret = int(QStyleHelper::dpiScaled(24.));
ret = 0;
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
ret = theme->themeHint(QPlatformTheme::ToolBarIconSize).toInt();
if (ret <= 0)
ret = int(QStyleHelper::dpiScaled(24.));
break;
case PM_TabBarIconSize:
@ -4903,9 +4905,10 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
break;
case SH_ItemView_ActivateItemOnSingleClick:
ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ItemView_ActivateItemOnSingleClick);
ret = 0;
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
ret = theme->themeHint(QPlatformTheme::ToolButtonStyle).toBool() ? 1 : 0;
break;
case SH_TitleBar_ModifyNotification:
ret = true;
break;
@ -4997,7 +5000,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = true;
break;
case SH_ToolButtonStyle:
ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ToolButtonStyle);
ret = 0;
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
ret = theme->themeHint(QPlatformTheme::ToolButtonStyle).toInt();
break;
case SH_RequestSoftwareInputPanel:
ret = RSIP_OnMouseClickAndAlreadyFocused;

View File

@ -411,8 +411,10 @@ void tst_QMessageBox::staticSourceCompat()
if (qobject_cast<QMacStyle *>(qApp->style()))
expectedButton = int(QMessageBox::No);
#elif !defined(QT_NO_STYLE_CLEANLOOKS)
if (qobject_cast<QCleanlooksStyle *>(qApp->style()))
if (qobject_cast<QCleanlooksStyle *>(qApp->style())) {
QEXPECT_FAIL("", "Special handling of QMessageBox::information buttons for Cleanlooks not implemented yet, QTBUG-24315", Continue);
expectedButton = int(QMessageBox::No);
}
#endif
QCOMPARE(ret, expectedButton);
QCOMPARE(keyToSend, -1);