From 13a31fe82845f8b1f4d86919080d3b2a87c4d061 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Mon, 10 Aug 2009 17:15:03 +0200 Subject: Introducing icon theme support Added some static functions to QIcon to support desktop themes based on the freedesktop spec. It is not intended to replace KIcon and the intention is to use it when available to share icon cache between applications. Applications currently using icon themes are Assistant, Designer and the textedit demo. Reviewed-by: ogoffart --- demos/textedit/textedit.cpp | 65 +- doc/src/snippets/code/src_gui_image_qicon.cpp | 9 + src/gui/gui.pro | 1 - src/gui/image/image.pri | 3 + src/gui/image/qicon.cpp | 226 ++++-- src/gui/image/qicon.h | 10 + src/gui/image/qicon_p.h | 138 ++++ src/gui/image/qiconloader.cpp | 599 ++++++++++++++++ src/gui/image/qiconloader_p.h | 185 +++++ src/gui/kernel/qapplication_x11.cpp | 4 +- src/gui/styles/gtksymbols.cpp | 8 +- src/gui/styles/gtksymbols_p.h | 1 + src/gui/styles/qcleanlooksstyle.cpp | 563 +-------------- src/gui/styles/qcleanlooksstyle_p.h | 2 - src/gui/styles/qcommonstyle.cpp | 770 ++++++--------------- src/gui/styles/qcommonstyle_p.h | 13 - src/gui/styles/qgtkstyle.cpp | 96 +-- src/gui/styles/qgtkstyle.h | 4 + .../testtheme/16x16/actions/appointment-new.png | Bin 0 -> 897 bytes .../testtheme/22x22/actions/appointment-new.png | Bin 0 -> 1411 bytes .../testtheme/32x32/actions/appointment-new.png | Bin 0 -> 2399 bytes tests/auto/qicon/icons/testtheme/index.theme | 492 +++++++++++++ .../icons/testtheme/scalable/actions/svg-only.svg | 425 ++++++++++++ .../themeparent/16x16/actions/address-book-new.png | Bin 0 -> 796 bytes .../themeparent/16x16/actions/appointment-new.png | Bin 0 -> 897 bytes .../themeparent/22x22/actions/address-book-new.png | Bin 0 -> 924 bytes .../themeparent/22x22/actions/appointment-new.png | Bin 0 -> 1411 bytes .../themeparent/32x32/actions/address-book-new.png | Bin 0 -> 1897 bytes .../themeparent/32x32/actions/appointment-new.png | Bin 0 -> 2399 bytes tests/auto/qicon/icons/themeparent/index.theme | 492 +++++++++++++ .../scalable/actions/address-book-new.svg | 389 +++++++++++ .../scalable/actions/appointment-new.svg | 425 ++++++++++++ tests/auto/qicon/tst_qicon.cpp | 67 ++ tools/assistant/compat/mainwindow.cpp | 10 + tools/assistant/tools/assistant/mainwindow.cpp | 13 + .../components/buddyeditor/buddyeditor_plugin.cpp | 5 +- .../components/formeditor/formwindowmanager.cpp | 22 +- .../signalsloteditor/signalsloteditor_plugin.cpp | 3 +- .../tabordereditor/tabordereditor_plugin.cpp | 4 +- tools/designer/src/designer/qdesigner_actions.cpp | 7 +- tools/designer/src/lib/shared/actioneditor.cpp | 18 +- tools/designer/src/lib/shared/qtresourceview.cpp | 10 +- 42 files changed, 3784 insertions(+), 1295 deletions(-) create mode 100644 src/gui/image/qicon_p.h create mode 100644 src/gui/image/qiconloader.cpp create mode 100644 src/gui/image/qiconloader_p.h create mode 100644 tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png create mode 100644 tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png create mode 100644 tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png create mode 100644 tests/auto/qicon/icons/testtheme/index.theme create mode 100644 tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg create mode 100644 tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png create mode 100644 tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png create mode 100644 tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png create mode 100644 tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png create mode 100644 tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png create mode 100644 tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png create mode 100644 tests/auto/qicon/icons/themeparent/index.theme create mode 100644 tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg create mode 100644 tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg diff --git a/demos/textedit/textedit.cpp b/demos/textedit/textedit.cpp index d1e12bb..31b419a 100644 --- a/demos/textedit/textedit.cpp +++ b/demos/textedit/textedit.cpp @@ -158,14 +158,16 @@ void TextEdit::setupFileActions() QAction *a; - a = new QAction(QIcon(rsrcPath + "/filenew.png"), tr("&New"), this); + QIcon newIcon = QIcon::fromTheme("document-new", QIcon(rsrcPath + "/filenew.png")); + a = new QAction( newIcon, tr("&New"), this); a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::New); connect(a, SIGNAL(triggered()), this, SLOT(fileNew())); tb->addAction(a); menu->addAction(a); - a = new QAction(QIcon(rsrcPath + "/fileopen.png"), tr("&Open..."), this); + a = new QAction(QIcon::fromTheme("document-open", QIcon(rsrcPath + "/fileopen.png")), + tr("&Open..."), this); a->setShortcut(QKeySequence::Open); connect(a, SIGNAL(triggered()), this, SLOT(fileOpen())); tb->addAction(a); @@ -173,7 +175,8 @@ void TextEdit::setupFileActions() menu->addSeparator(); - actionSave = a = new QAction(QIcon(rsrcPath + "/filesave.png"), tr("&Save"), this); + actionSave = a = new QAction(QIcon::fromTheme("document-save", QIcon(rsrcPath + "/filesave.png")), + tr("&Save"), this); a->setShortcut(QKeySequence::Save); connect(a, SIGNAL(triggered()), this, SLOT(fileSave())); a->setEnabled(false); @@ -187,17 +190,21 @@ void TextEdit::setupFileActions() menu->addSeparator(); #ifndef QT_NO_PRINTER - a = new QAction(QIcon(rsrcPath + "/fileprint.png"), tr("&Print..."), this); + a = new QAction(QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png")), + tr("&Print..."), this); + a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Print); connect(a, SIGNAL(triggered()), this, SLOT(filePrint())); tb->addAction(a); menu->addAction(a); - a = new QAction(QIcon(rsrcPath + "/fileprint.png"), tr("Print Preview..."), this); + a = new QAction(QIcon::fromTheme("fileprint", QIcon(rsrcPath + "/fileprint.png")), + tr("Print Preview..."), this); connect(a, SIGNAL(triggered()), this, SLOT(filePrintPreview())); menu->addAction(a); - a = new QAction(QIcon(rsrcPath + "/exportpdf.png"), tr("&Export PDF..."), this); + a = new QAction(QIcon::fromTheme("exportpdf", QIcon(rsrcPath + "/exportpdf.png")), + tr("&Export PDF..."), this); a->setPriority(QAction::LowPriority); a->setShortcut(Qt::CTRL + Qt::Key_D); connect(a, SIGNAL(triggered()), this, SLOT(filePrintPdf())); @@ -218,32 +225,36 @@ void TextEdit::setupEditActions() QToolBar *tb = new QToolBar(this); tb->setWindowTitle(tr("Edit Actions")); addToolBar(tb); - QMenu *menu = new QMenu(tr("&Edit"), this); menuBar()->addMenu(menu); QAction *a; - a = actionUndo = new QAction(QIcon(rsrcPath + "/editundo.png"), tr("&Undo"), this); + a = actionUndo = new QAction(QIcon::fromTheme("edit-undo", QIcon(rsrcPath + "/editundo.png")), + tr("&Undo"), this); a->setShortcut(QKeySequence::Undo); tb->addAction(a); menu->addAction(a); - a = actionRedo = new QAction(QIcon(rsrcPath + "/editredo.png"), tr("&Redo"), this); + a = actionRedo = new QAction(QIcon::fromTheme("edit-redo", QIcon(rsrcPath + "/editredo.png")), + tr("&Redo"), this); a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Redo); tb->addAction(a); menu->addAction(a); menu->addSeparator(); - a = actionCut = new QAction(QIcon(rsrcPath + "/editcut.png"), tr("Cu&t"), this); + a = actionCut = new QAction(QIcon::fromTheme("edit-cut", QIcon(rsrcPath + "/editcut.png")), + tr("Cu&t"), this); a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Cut); tb->addAction(a); menu->addAction(a); - a = actionCopy = new QAction(QIcon(rsrcPath + "/editcopy.png"), tr("&Copy"), this); + a = actionCopy = new QAction(QIcon::fromTheme("edit-copy", QIcon(rsrcPath + "/editcopy.png")), + tr("&Copy"), this); a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Copy); tb->addAction(a); menu->addAction(a); - a = actionPaste = new QAction(QIcon(rsrcPath + "/editpaste.png"), tr("&Paste"), this); + a = actionPaste = new QAction(QIcon::fromTheme("edit-paste", QIcon(rsrcPath + "/editpaste.png")), + tr("&Paste"), this); a->setPriority(QAction::LowPriority); a->setShortcut(QKeySequence::Paste); tb->addAction(a); @@ -260,10 +271,11 @@ void TextEdit::setupTextActions() QMenu *menu = new QMenu(tr("F&ormat"), this); menuBar()->addMenu(menu); - actionTextBold = new QAction(QIcon(rsrcPath + "/textbold.png"), tr("&Bold"), this); - actionTextBold->setPriority(QAction::LowPriority); + actionTextBold = new QAction(QIcon::fromTheme("format-text-bold", QIcon(rsrcPath + "/textbold.png")), + tr("&Bold"), this); actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B); - QFont bold; + actionTextBold->setPriority(QAction::LowPriority); + QFont bold; bold.setBold(true); actionTextBold->setFont(bold); connect(actionTextBold, SIGNAL(triggered()), this, SLOT(textBold())); @@ -271,7 +283,8 @@ void TextEdit::setupTextActions() menu->addAction(actionTextBold); actionTextBold->setCheckable(true); - actionTextItalic = new QAction(QIcon(rsrcPath + "/textitalic.png"), tr("&Italic"), this); + actionTextItalic = new QAction(QIcon::fromTheme("format-text-italic", QIcon(rsrcPath + "/textitalic.png")), + tr("&Italic"), this); actionTextItalic->setPriority(QAction::LowPriority); actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I); QFont italic; @@ -282,9 +295,10 @@ void TextEdit::setupTextActions() menu->addAction(actionTextItalic); actionTextItalic->setCheckable(true); - actionTextUnderline = new QAction(QIcon(rsrcPath + "/textunder.png"), tr("&Underline"), this); - actionTextUnderline->setPriority(QAction::LowPriority); + actionTextUnderline = new QAction(QIcon::fromTheme("format-text-underline", QIcon(rsrcPath + "/textunder.png")), + tr("&Underline"), this); actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U); + actionTextUnderline->setPriority(QAction::LowPriority); QFont underline; underline.setUnderline(true); actionTextUnderline->setFont(underline); @@ -300,15 +314,16 @@ void TextEdit::setupTextActions() // Make sure the alignLeft is always left of the alignRight if (QApplication::isLeftToRight()) { - actionAlignLeft = new QAction(QIcon(rsrcPath + "/textleft.png"), tr("&Left"), grp); - actionAlignCenter = new QAction(QIcon(rsrcPath + "/textcenter.png"), tr("C&enter"), grp); - actionAlignRight = new QAction(QIcon(rsrcPath + "/textright.png"), tr("&Right"), grp); + actionAlignLeft = new QAction(QIcon::fromTheme("format-justify-left", QIcon(rsrcPath + "/textleft.png")), + tr("&Left"), grp); + actionAlignCenter = new QAction(QIcon::fromTheme("format-justify-center", QIcon(rsrcPath + "/textcenter.png")), tr("C&enter"), grp); + actionAlignRight = new QAction(QIcon::fromTheme("format-justify-right", QIcon(rsrcPath + "/textright.png")), tr("&Right"), grp); } else { - actionAlignRight = new QAction(QIcon(rsrcPath + "/textright.png"), tr("&Right"), grp); - actionAlignCenter = new QAction(QIcon(rsrcPath + "/textcenter.png"), tr("C&enter"), grp); - actionAlignLeft = new QAction(QIcon(rsrcPath + "/textleft.png"), tr("&Left"), grp); + actionAlignRight = new QAction(QIcon::fromTheme("format-justify-right", QIcon(rsrcPath + "/textright.png")), tr("&Right"), grp); + actionAlignCenter = new QAction(QIcon::fromTheme("format-justify-center", QIcon(rsrcPath + "/textcenter.png")), tr("C&enter"), grp); + actionAlignLeft = new QAction(QIcon::fromTheme("format-justify-left", QIcon(rsrcPath + "/textleft.png")), tr("&Left"), grp); } - actionAlignJustify = new QAction(QIcon(rsrcPath + "/textjustify.png"), tr("&Justify"), grp); + actionAlignJustify = new QAction(QIcon::fromTheme("format-justify-fill", QIcon(rsrcPath + "/textjustify.png")), tr("&Justify"), grp); actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); actionAlignLeft->setCheckable(true); diff --git a/doc/src/snippets/code/src_gui_image_qicon.cpp b/doc/src/snippets/code/src_gui_image_qicon.cpp index 2b7c893..455fd84 100644 --- a/doc/src/snippets/code/src_gui_image_qicon.cpp +++ b/doc/src/snippets/code/src_gui_image_qicon.cpp @@ -20,3 +20,12 @@ void MyWidget::drawIcon(QPainter *painter, QPoint pos) painter->drawPixmap(pos, pixmap); } //! [2] + +//! [3] + QIcon undoicon = QIcon::fromTheme("edit-undo"); +//! [3] + +//! [4] + QIcon undoicon = QIcon::fromTheme("edit-undo", QIcon(":/undo.png")); +//! [4] + diff --git a/src/gui/gui.pro b/src/gui/gui.pro index b77bfdc..a49d680 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -46,4 +46,3 @@ contains(DEFINES,QT_EVAL):include($$QT_SOURCE_TREE/src/corelib/eval.pri) QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist DEFINES += Q_INTERNAL_QAPP_SRC - diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index b9c36dc..baf2125 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -6,6 +6,8 @@ HEADERS += \ image/qbitmap.h \ image/qicon.h \ + image/qicon_p.h \ + image/qiconloader_p.h \ image/qiconengine.h \ image/qiconengineplugin.h \ image/qimage.h \ @@ -32,6 +34,7 @@ HEADERS += \ SOURCES += \ image/qbitmap.cpp \ image/qicon.cpp \ + image/qiconloader.cpp \ image/qimage.cpp \ image/qimageiohandler.cpp \ image/qimagereader.cpp \ diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index fa407c7..7a43514 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -40,9 +40,11 @@ ****************************************************************************/ #include "qicon.h" +#include "qicon_p.h" #include "qiconengine.h" #include "qiconengineplugin.h" #include "private/qfactoryloader_p.h" +#include "private/qiconloader_p.h" #include "qapplication.h" #include "qstyleoption.h" #include "qpainter.h" @@ -50,6 +52,7 @@ #include "qstyle.h" #include "qpixmapcache.h" #include "qvariant.h" +#include "qcache.h" #include "qdebug.h" #ifdef Q_WS_MAC @@ -57,6 +60,11 @@ #include #endif +#ifdef Q_WS_X11 +#include "private/qt_x11_p.h" +#include "private/qkde_p.h" +#endif + QT_BEGIN_NAMESPACE /*! @@ -94,73 +102,14 @@ QT_BEGIN_NAMESPACE static QBasicAtomicInt serialNumCounter = Q_BASIC_ATOMIC_INITIALIZER(1); -class QIconPrivate -{ -public: - QIconPrivate(): engine(0), ref(1), serialNum(serialNumCounter.fetchAndAddRelaxed(1)), detach_no(0), engine_version(2), v1RefCount(0) {} - - ~QIconPrivate() { - if (engine_version == 1) { - if (!v1RefCount->deref()) { - delete engine; - delete v1RefCount; - } - } else if (engine_version == 2) { - delete engine; - } - } - - QIconEngine *engine; - - QAtomicInt ref; - int serialNum; - int detach_no; - int engine_version; - - QAtomicInt *v1RefCount; -}; - - -struct QPixmapIconEngineEntry +QIconPrivate::QIconPrivate() + : engine(0), ref(1), + serialNum(serialNumCounter.fetchAndAddRelaxed(1)), + detach_no(0), + engine_version(2), + v1RefCount(0) { - QPixmapIconEngineEntry():mode(QIcon::Normal), state(QIcon::Off){} - QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) - :pixmap(pm), size(pm.size()), mode(m), state(s){} - QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) - :fileName(file), size(sz), mode(m), state(s){} - QPixmap pixmap; - QString fileName; - QSize size; - QIcon::Mode mode; - QIcon::State state; - bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); } -}; - -class QPixmapIconEngine : public QIconEngineV2 { -public: - QPixmapIconEngine(); - QPixmapIconEngine(const QPixmapIconEngine &); - ~QPixmapIconEngine(); - void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state); - QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); - QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly); - QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); - void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state); - void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state); - - // v2 functions - QString key() const; - QIconEngineV2 *clone() const; - bool read(QDataStream &in); - bool write(QDataStream &out) const; - void virtual_hook(int id, void *data); - -private: - QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state); - QVector pixmaps; - - friend QDataStream &operator<<(QDataStream &s, const QIcon &icon); -}; +} QPixmapIconEngine::QPixmapIconEngine() { @@ -918,6 +867,146 @@ QList QIcon::availableSizes(Mode mode, State state) const return engine->availableSizes(mode, state); } +/*! + \since 4.6 + + Sets the search paths for icon themes. + \sa themeSearchPaths(), fromTheme() +*/ +void QIcon::setThemeSearchPaths(const QStringList &paths) +{ + QIconLoader::instance()->setThemeSearchPath(paths); +} + +/*! + \since 4.6 + + Returns the search paths for icon themes. + + The default value will depend on the platform: + + On X11, the search path will use the XDG_DATA_DIRS environment + variable if available. + + On Windows the search path defaults to [Application Directory]/icons + + On Mac the default search path will search in the + [Contents/Resources/icons] part of the application bundle. + + \sa setThemeSearchPaths(), fromName() +*/ +QStringList QIcon::themeSearchPaths() +{ + return QIconLoader::instance()->themeSearchPaths(); +} + +/*! + \since 4.6 + + Sets the current icon theme. + + The name should correspond to a directory name in the + current \ themeSearchPath() containing an index.theme + file describing it's contents.. + +*/ +void QIcon::setThemeName(const QString &path) +{ + QIconLoader::instance()->setThemeName(path); +} + +/*! + \since 4.6 + + Returns the name of the current icon theme. + + On X11, the current icon theme depends on your desktop + settings. On other platforms it is not set by default. + + \sa themeSearchPaths(), themeIcon(), fromTheme(), hasThemeIcon() +*/ +QString QIcon::themeName() +{ + return QIconLoader::instance()->themeName(); +} + +/*! + \since 4.6 + + Returns the QIcon corresponding to \a name in the current + icon theme. If no such icon is found in the current theme + \a fallback is return instead. + + To use an icon theme on Windows or Mac, you will need to + bundle a compliant theme with your application and make sure + it is located in your themeSarchPaths. + + The lastest version of the freedesktop icon specification and naming + spesification can be obtained here: + http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html + http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html + + To fetch an icon from the current icon theme: + + \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 3 + + Or if you want to provide a guaranteed fallback for platforms that + do not support theme icons, you can use the second argument: + + \snippet doc/src/snippets/code/src_gui_image_qicon.cpp 4 + + \note By default, only X11 will support themed icons. In order to + use themed icons on Mac and Windows, you will have to bundle a + compliant theme in one of your themeSearchPaths() and set the + appropriate themeName(). + + \sa themeName(), themeSearchPaths() +*/ +QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) +{ + + static QCache iconCache; + + QIcon icon; + +#ifdef Q_WS_X11 + if (X11->desktopEnvironment == DE_KDE) { + icon = QKde::kdeIcon(name); + if (!icon.isNull()) + return icon; + } +#endif + + if (iconCache.contains(name)) { + icon = *iconCache.object(name); + } else { + QIcon *cachedIcon = new QIcon(new QIconLoaderEngine(name)); + iconCache.insert(name, cachedIcon); + icon = *cachedIcon; + } + + if (icon.availableSizes().isEmpty()) + return fallback; + + return icon; +} + +/*! + \since 4.6 + + Returns true if there is an icon available for a \a name in the current + icon theme, otherwise returns false. + + \sa themeSearchPaths(), fromTheme() +*/ +bool QIcon::hasThemeIcon(const QString &name) +{ + QIcon icon = fromTheme(name); + + return !icon.isNull(); +} + + /***************************************************************************** QIcon stream functions *****************************************************************************/ @@ -989,6 +1078,11 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon) QIconEngineV2 *engine = new QPixmapIconEngine; icon.d->engine = engine; engine->read(s); + } else if (key == QLatin1String("QIconLoaderEngine")) { + icon.d = new QIconPrivate; + QIconEngineV2 *engine = new QIconLoaderEngine(); + icon.d->engine = engine; + engine->read(s); #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) } else if (QIconEngineFactoryInterfaceV2 *factory = qobject_cast(loaderV2()->instance(key))) { if (QIconEngineV2 *engine= factory->create()) { diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index c318e14..2a71717 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -97,6 +97,16 @@ public: QList availableSizes(Mode mode = Normal, State state = Off) const; + static QIcon fromTheme(const QString &name, const QIcon &fallback = QIcon()); + static bool hasThemeIcon(const QString &name); + + static QStringList themeSearchPaths(); + static void setThemeSearchPaths(const QStringList &searchpath); + + static QString themeName(); + static void setThemeName(const QString &path); + + #ifdef QT3_SUPPORT enum Size { Small, Large, Automatic = Small }; static QT3_SUPPORT void setPixmapSize(Size which, const QSize &size); diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h new file mode 100644 index 0000000..ccac4c3 --- /dev/null +++ b/src/gui/image/qicon_p.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QICON_P_H +#define QICON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QIconPrivate +{ +public: + QIconPrivate(); + + ~QIconPrivate() { + if (engine_version == 1) { + if (!v1RefCount->deref()) { + delete engine; + delete v1RefCount; + } + } else if (engine_version == 2) { + delete engine; + } + } + + QIconEngine *engine; + + QAtomicInt ref; + int serialNum; + int detach_no; + int engine_version; + + QAtomicInt *v1RefCount; +}; + + +struct QPixmapIconEngineEntry +{ + QPixmapIconEngineEntry():mode(QIcon::Normal), state(QIcon::Off){} + QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) + :pixmap(pm), size(pm.size()), mode(m), state(s){} + QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off) + :fileName(file), size(sz), mode(m), state(s){} + QPixmap pixmap; + QString fileName; + QSize size; + QIcon::Mode mode; + QIcon::State state; + bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); } +}; + + + +class QPixmapIconEngine : public QIconEngineV2 { +public: + QPixmapIconEngine(); + QPixmapIconEngine(const QPixmapIconEngine &); + ~QPixmapIconEngine(); + void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state); + QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); + QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly); + QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); + void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state); + void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state); + + // v2 functions + QString key() const; + QIconEngineV2 *clone() const; + bool read(QDataStream &in); + bool write(QDataStream &out) const; + void virtual_hook(int id, void *data); + +private: + QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state); + QVector pixmaps; + + friend QDataStream &operator<<(QDataStream &s, const QIcon &icon); + friend class QIconThemeEngine; +}; + +QT_END_NAMESPACE + +#endif // QICON_P_H diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp new file mode 100644 index 0000000..6bf8d3b --- /dev/null +++ b/src/gui/image/qiconloader.cpp @@ -0,0 +1,599 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_WS_MAC +#include +#endif + +#ifdef Q_WS_X11 +#include +#include +#endif + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance) + +static QString systemThemeName() +{ + QString result; +#ifdef Q_WS_X11 + if (X11->desktopEnvironment == DE_GNOME) { + result = QGtk::getGConfString(QLatin1String("/desktop/gnome/interface/icon_theme"), + QLatin1String("gnome")); + } else if (X11->desktopEnvironment == DE_KDE) { + QString kdeDefault = 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"), kdeDefault).toString(); + } +#endif + return result; +} + +static QString fallbackTheme() +{ + QString defaultTheme = systemThemeName(); + if (defaultTheme.isEmpty()) + defaultTheme = QLatin1String("hicolor"); + return defaultTheme; +} + +QIconLoader::QIconLoader() : + m_themeKey(1), m_supportsSvg(false) +{ + m_systemTheme = systemThemeName(); + + QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid, + QLatin1String("/iconengines"), + Qt::CaseInsensitive); + if (iconFactoryLoader.keys().contains(QLatin1String("svg"))) + m_supportsSvg = true; +} + +QIconLoader *QIconLoader::instance() +{ + return iconLoaderInstance(); +} + +// Queries the system theme and invalidates existing +// icons if the theme has changed. +void QIconLoader::updateSystemTheme() +{ + // Only change if this is not explicitly set by the user + if (m_userTheme.isEmpty()) { + QString theme = systemThemeName(); + if (theme != m_systemTheme) { + m_systemTheme = theme; + invalidateKey(); + } + } +} + +void QIconLoader::setThemeName(const QString &themeName) +{ + m_userTheme = themeName; + invalidateKey(); +} + +void QIconLoader::setThemeSearchPath(const QStringList &searchPaths) +{ + m_iconDirs = searchPaths; + themeList.clear(); + invalidateKey(); +} + +QStringList QIconLoader::themeSearchPaths() const +{ + if (m_iconDirs.isEmpty()) { + +#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()) + m_iconDirs.append(dir.path() + + QLatin1String("/icons")); + } + + if (X11->desktopEnvironment == DE_KDE) { + + m_iconDirs << 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()) + m_iconDirs.append(dir.path()); + } + } + + // Add home directory first in search path + QDir homeDir(QDir::homePath() + QLatin1String("/.icons")); + if (homeDir.exists()) + m_iconDirs.prepend(homeDir.path()); + +#elif defined(Q_WS_WIN) + m_iconDirs.append(qApp->applicationDirPath() + + QLatin1String("/icons")); +#elif defined(Q_WS_MAC) + m_iconDirs.append(qApp->applicationDirPath() + + QLatin1String("/../Resources/icons")); +#endif + } + return m_iconDirs; +} + +QIconTheme::QIconTheme(const QString &themeName) + : m_valid(false) +{ + QFile themeIndex; + + QList keyList; + QStringList iconDirs = QIcon::themeSearchPaths(); + for ( int i = 0 ; i < iconDirs.size() ; ++i) { + QDir iconDir(iconDirs[i]); + QString themeDir = iconDir.path() + QLatin1Char('/') + themeName; + themeIndex.setFileName(themeDir + QLatin1String("/index.theme")); + if (themeIndex.exists()) { + m_contentDir = themeDir; + m_valid = true; + break; + } + } + + if (themeIndex.exists()) { + const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat); + QStringListIterator keyIterator(indexReader.allKeys()); + while (keyIterator.hasNext()) { + + const QString key = keyIterator.next(); + if (key.endsWith(QLatin1String("/Size"))) { + // Note the QSettings ini-format does not accept + // slashes in key names, hence we have to cheat + if (int size = indexReader.value(key).toInt()) { + QString directoryKey = key.left(key.size() - 5); + QIconDirInfo dirInfo(directoryKey); + dirInfo.size = size; + QString type = indexReader.value(directoryKey + + QLatin1String("/Type") + ).toString(); + + if (type == QLatin1String("Fixed")) + dirInfo.type = QIconDirInfo::Fixed; + else if (type == QLatin1String("Scalable")) + dirInfo.type = QIconDirInfo::Scalable; + else + dirInfo.type = QIconDirInfo::Threshold; + + dirInfo.threshold = indexReader.value(directoryKey + + QLatin1String("/Threshold"), + 2).toInt(); + + dirInfo.minSize = indexReader.value(directoryKey + + QLatin1String("/MinSize"), + size).toInt(); + + dirInfo.maxSize = indexReader.value(directoryKey + + QLatin1String("/MaxSize"), + size).toInt(); + m_keyList.append(dirInfo); + } + } + } + + // Parent themes provide fallbacks for missing icons + m_parents = indexReader.value( + QLatin1String("Icon Theme/Inherits")).toStringList(); + + // Ensure a default platform fallback for all themes + if (m_parents.isEmpty()) + m_parents.append(fallbackTheme()); + + // Ensure that all themes fall back to hicolor + if (!m_parents.isEmpty()) + m_parents.append(QLatin1String("hicolor")); + } +} + +QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName, + const QString &iconName, + QStringList &visited) const +{ + QThemeIconEntries entries; + Q_ASSERT(!themeName.isEmpty()); + + QPixmap pixmap; + + // Used to protect against potential recursions + visited << themeName; + + QIconTheme theme = themeList.value(themeName); + if (!theme.isValid()) { + theme = QIconTheme(themeName); + if (!theme.isValid()) + theme = fallbackTheme(); + + themeList.insert(themeName, theme); + } + + QString contentDir = theme.contentDir() + QLatin1Char('/'); + QList subDirs = theme.keyList(); + + const QString svgext(QLatin1String(".svg")); + const QString pngext(QLatin1String(".png")); + + // Add all relevant files + for (int i = 0; i < subDirs.size() ; ++i) { + const QIconDirInfo &dirInfo = subDirs.at(i); + QString subdir = dirInfo.path; + QDir currentDir(contentDir + subdir); + + if (dirInfo.type == QIconDirInfo::Scalable && m_supportsSvg && + currentDir.exists(iconName + svgext)) { + ScalableEntry *iconEntry = new ScalableEntry; + iconEntry->dir = dirInfo; + iconEntry->filename = currentDir.filePath(iconName + svgext); + entries.append(iconEntry); + + } else if (currentDir.exists(iconName + pngext)) { + PixmapEntry *iconEntry = new PixmapEntry; + iconEntry->dir = dirInfo; + iconEntry->filename = currentDir.filePath(iconName + pngext); + // Notice we ensure that pixmap entries allways come before + // scalable to preserve search order afterwards + entries.prepend(iconEntry); + } + } + + if (entries.isEmpty()) { + const QStringList parents = theme.parents(); + // Search recursively through inherited themes + for (int i = 0 ; i < parents.size() ; ++i) { + + const QString parentTheme = parents.at(i).trimmed(); + + if (!visited.contains(parentTheme)) // guard against recursion + entries = findIconHelper(parentTheme, iconName, visited); + + if (!entries.isEmpty()) // success + break; + } + } + return entries; +} + +QThemeIconEntries QIconLoader::loadIcon(const QString &name) const +{ + if (!themeName().isEmpty()) { + QStringList visited; + return findIconHelper(themeName(), name, visited); + } + + return QThemeIconEntries(); +} + + +// -------- Icon Loader Engine -------- // + + +QIconLoaderEngine::QIconLoaderEngine(const QString& iconName) + : m_iconName(iconName), m_key(0) +{ +} + +QIconLoaderEngine::~QIconLoaderEngine() +{ + while (!m_entries.isEmpty()) + delete m_entries.takeLast(); + Q_ASSERT(m_entries.size() == 0); +} + +QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other) + : QIconEngineV2(other), + m_iconName(other.m_iconName), + m_key(0) +{ +} + +QIconEngineV2 *QIconLoaderEngine::clone() const +{ + return new QIconLoaderEngine(*this); +} + +bool QIconLoaderEngine::read(QDataStream &in) { + in >> m_iconName; + return true; +} + +bool QIconLoaderEngine::write(QDataStream &out) const +{ + out << m_iconName; + return true; +} + +bool QIconLoaderEngine::hasIcon() const +{ + return !(m_entries.isEmpty()); +} + +// Lazily load the icon +void QIconLoaderEngine::ensureLoaded() +{ + if (!(iconLoaderInstance()->themeKey() == m_key)) { + + while (!m_entries.isEmpty()) + delete m_entries.takeLast(); + + Q_ASSERT(m_entries.size() == 0); + m_entries = iconLoaderInstance()->loadIcon(m_iconName); + m_key = iconLoaderInstance()->themeKey(); + } +} + +void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect, + QIcon::Mode mode, QIcon::State state) +{ + QSize pixmapSize = rect.size(); +#if defined(Q_WS_MAC) + pixmapSize *= qt_mac_get_scalefactor(); +#endif + painter->drawPixmap(rect, pixmap(pixmapSize, mode, state)); +} + +/* + * This algorithm is defined by the freedesktop spec: + * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html + */ +static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize) +{ + if (dir.type == QIconDirInfo::Fixed) { + return dir.size == iconsize; + + } else if (dir.type == QIconDirInfo::Scalable) { + return dir.size <= dir.maxSize && + iconsize >= dir.minSize; + + } else if (dir.type == QIconDirInfo::Threshold) { + return iconsize >= dir.size - dir.threshold && + iconsize <= dir.size + dir.threshold; + } + + Q_ASSERT(1); // Not a valid value + return false; +} + +/* + * This algorithm is defined by the freedesktop spec: + * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html + */ +static int directorySizeDistance(const QIconDirInfo &dir, int iconsize) +{ + if (dir.type == QIconDirInfo::Fixed) { + return qAbs(dir.size - iconsize); + + } else if (dir.type == QIconDirInfo::Scalable) { + if (iconsize < dir.minSize) + return dir.minSize - iconsize; + else if (iconsize > dir.maxSize) + return iconsize - dir.maxSize; + else + return 0; + + } else if (dir.type == QIconDirInfo::Threshold) { + if (iconsize < dir.size - dir.threshold) + return dir.minSize - iconsize; + else if (iconsize > dir.size + dir.threshold) + return iconsize - dir.maxSize; + else return 0; + } + + Q_ASSERT(1); // Not a valid value + return INT_MAX; +} + +QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size) +{ + int iconsize = qMin(size.width(), size.height()); + + // Note that m_entries are sorted so that png-files + // come first + + // Search for exact matches first + for (int i = 0; i < m_entries.count(); ++i) { + QIconLoaderEngineEntry *entry = m_entries.at(i); + if (directoryMatchesSize(entry->dir, iconsize)) { + return entry; + } + } + + // Find the minimum distance icon + int minimalSize = INT_MAX; + QIconLoaderEngineEntry *closestMatch = 0; + for (int i = 0; i < m_entries.count(); ++i) { + QIconLoaderEngineEntry *entry = m_entries.at(i); + int distance = directorySizeDistance(entry->dir, iconsize); + if (distance < minimalSize) { + minimalSize = distance; + closestMatch = entry; + } + } + return closestMatch; +} + +/* + * Returns the actual icon size. For scalable svg's this is equivalent + * to the requested size. Otherwise the closest match is returned. + * + * todo: the spec is a bit fuzzy in this area, but we should probably + * allow scaling down pixmap icons as well. + * + */ +QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode, + QIcon::State state) +{ + ensureLoaded(); + + QIconLoaderEngineEntry *entry = entryForSize(size); + if (entry) { + const QIconDirInfo &dir = entry->dir; + if (dir.type == QIconDirInfo::Scalable) + return size; + else + return QSize(dir.size, dir.size); + } + return QIconEngineV2::actualSize(size, mode, state); +} + +QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + Q_UNUSED(state); + + // Ensure that basePixmap is lazily initialized before generating the + // key, otherwise the cache key is not unique + if (basePixmap.isNull()) + basePixmap.load(filename); + + int actualSize = qMin(size.width(), size.height()); + QString key = QLatin1String("$qt_theme_") + + QString::number(basePixmap.cacheKey(), 16) + + QLatin1Char('_') + + QString::number(mode) + + QLatin1Char('_') + + QString::number(qApp->palette().cacheKey(), 16) + + QLatin1Char('_') + + QString::number(actualSize); + + QPixmap cachedPixmap; + if (QPixmapCache::find(key, &cachedPixmap)) { + return cachedPixmap; + } else { + QStyleOption opt(0); + opt.palette = qApp->palette(); + cachedPixmap = qApp->style()->generatedIconPixmap(mode, basePixmap, &opt); + QPixmapCache::insert(key, cachedPixmap); + } + return cachedPixmap; +} + +QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + if (svgIcon.isNull()) + svgIcon = QIcon(filename); + + // Simply reuse svg icon engine + return svgIcon.pixmap(size, mode, state); +} + +QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode, + QIcon::State state) +{ + ensureLoaded(); + + QIconLoaderEngineEntry *entry = entryForSize(size); + if (entry) + return entry->pixmap(size, mode, state); + + return QPixmap(); +} + +QString QIconLoaderEngine::key() const +{ + return QLatin1String("QIconLoaderEngine"); +} + +void QIconLoaderEngine::virtual_hook(int id, void *data) +{ + ensureLoaded(); + + switch (id) { + case QIconEngineV2::AvailableSizesHook: + { + QIconEngineV2::AvailableSizesArgument &arg + = *reinterpret_cast(data); + const QList directoryKey = iconLoaderInstance()->theme().keyList(); + arg.sizes.clear(); + + // Gets all sizes from the DirectoryInfo entries + for (int i = 0 ; i < m_entries.size() ; ++i) { + int size = m_entries.at(i)->dir.size; + arg.sizes.append(QSize(size, size)); + } + } + break; + default: + QIconEngineV2::virtual_hook(id, data); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h new file mode 100644 index 0000000..707107c --- /dev/null +++ b/src/gui/image/qiconloader_p.h @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDESKTOPICON_P_H +#define QDESKTOPICON_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QIconLoader; + +struct QIconDirInfo +{ + enum Type { Fixed, Scalable, Threshold }; + QIconDirInfo(const QString &_path = QString()) : + path(_path), + size(0), + maxSize(0), + minSize(0), + threshold(0), + type(Threshold) {} + QString path; + short size; + short maxSize; + short minSize; + short threshold; + Type type : 4; +}; + +class QIconLoaderEngineEntry + { +public: + virtual QPixmap pixmap(const QSize &size, + QIcon::Mode mode, + QIcon::State state) = 0; + QString filename; + QIconDirInfo dir; + static int count; +}; + +struct ScalableEntry : public QIconLoaderEngineEntry +{ + QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); + QIcon svgIcon; +}; + +struct PixmapEntry : public QIconLoaderEngineEntry +{ + QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); + QPixmap basePixmap; +}; + +typedef QList QThemeIconEntries; + +class QIconLoaderEngine : public QIconEngineV2 +{ +public: + QIconLoaderEngine(const QString& iconName = QString()); + ~QIconLoaderEngine(); + + void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state); + QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); + QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); + QIconEngineV2 *clone() const; + bool read(QDataStream &in); + bool write(QDataStream &out) const; + +private: + QString key() const; + bool hasIcon() const; + void ensureLoaded(); + void virtual_hook(int id, void *data); + QIconLoaderEngineEntry *entryForSize(const QSize &size); + QIconLoaderEngine(const QIconLoaderEngine &other); + QThemeIconEntries m_entries; + QString m_iconName; + uint m_key; + + friend class QIconLoader; +}; + +class QIconTheme +{ +public: + QIconTheme(const QString &name); + QIconTheme() : m_valid(false) {}; + QStringList parents() { return m_parents; } + QList keyList() { return m_keyList; } + QString contentDir() { return m_contentDir; } + bool isValid() { return m_valid; } + +private: + QString m_contentDir; + QList m_keyList; + QStringList m_parents; + bool m_valid; +}; + +class QIconLoader : public QObject +{ +public: + QIconLoader(); + QThemeIconEntries loadIcon(const QString &iconName) const; + uint themeKey() const { return m_themeKey; } + + QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; } + void setThemeName(const QString &themeName); + QIconTheme theme() { return themeList.value(themeName()); } + void setThemeSearchPath(const QStringList &searchPaths); + QStringList themeSearchPaths() const; + QIconDirInfo dirInfo(int dirindex); + static QIconLoader *instance(); + void updateSystemTheme(); + void invalidateKey() { m_themeKey++; } + +private: + QThemeIconEntries findIconHelper(const QString &themeName, + const QString &iconName, + QStringList &visited) const; + uint m_themeKey; + bool m_supportsSvg; + + mutable QString m_userTheme; + mutable QString m_systemTheme; + mutable QStringList m_iconDirs; + mutable QHash themeList; +}; + +QT_END_NAMESPACE + +#endif // QDESKTOPICON_P_H diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 32e7e3c..221101a 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -78,6 +78,7 @@ #include #include #include +#include #include "qstyle.h" #include "qmetaobject.h" #include "qtimer.h" @@ -1087,7 +1088,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, if (QApplication::desktopSettingsAware()) { // first, read from settings QApplicationPrivate::x11_apply_settings(); - // the call to QApplication::style() below creates the system // palette, which breaks the logic after the RESOURCE_MANAGER // loop... so I have to save this value to be able to use it later @@ -1328,6 +1328,8 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, effects.contains(QLatin1String("animatetoolbox"))); } + + QIconLoader::instance()->updateSystemTheme(); } diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index f947ac1..c8b4fda 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -60,6 +60,7 @@ #include #include +#include #include #include @@ -341,9 +342,9 @@ static bool resolveGConf() typedef int (*x11ErrorHandler)(Display*, XErrorEvent*); -static QString getGConfString(const QString &value) +QString QGtk::getGConfString(const QString &value, const QString &fallback) { - QString retVal; + QString retVal = fallback; if (resolveGConf()) { g_type_init(); GConfClient* client = QGtk::gconf_client_get_default(); @@ -393,7 +394,7 @@ static QString getThemeName() // Fall back to gconf if (themeName.isEmpty() && resolveGConf()) - themeName = getGConfString(QLS("/desktop/gnome/interface/gtk_theme")); + themeName = QGtk::getGConfString(QLS("/desktop/gnome/interface/gtk_theme")); return themeName; } @@ -561,6 +562,7 @@ void QGtkStyleUpdateScheduler::updateTheme() QApplication::sendEvent(widget, &e); } } + QIconLoader::instance()->updateSystemTheme(); } static void add_widget(GtkWidget *widget) diff --git a/src/gui/styles/gtksymbols_p.h b/src/gui/styles/gtksymbols_p.h index 18c6dc5..68e970a 100644 --- a/src/gui/styles/gtksymbols_p.h +++ b/src/gui/styles/gtksymbols_p.h @@ -216,6 +216,7 @@ public: static QString openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); static QStringList openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); + static QString getGConfString(const QString &key, const QString &fallback = QString()); static Ptr_gtk_container_forall gtk_container_forall; static Ptr_gtk_init gtk_init; diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 8f88781..1782e36 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -462,26 +462,6 @@ static const char * const qt_cleanlooks_checkbox_checked[] = { " ", " "}; -#ifdef Q_WS_X11 -extern "C" { - struct GConfClient; - struct GError; - typedef void (*Ptr_g_type_init)(); - typedef GConfClient* (*Ptr_gconf_client_get_default)(); - typedef char* (*Ptr_gconf_client_get_string)(GConfClient*, const char*, GError **); - typedef void (*Ptr_g_object_unref)(void *); - typedef void (*Ptr_g_error_free)(GError *); - typedef void (*Ptr_g_free)(void*); -} - -static Ptr_g_type_init p_g_type_init = 0; -static Ptr_gconf_client_get_default p_gconf_client_get_default = 0; -static Ptr_gconf_client_get_string p_gconf_client_get_string = 0; -static Ptr_g_object_unref p_g_object_unref = 0; -static Ptr_g_error_free p_g_error_free = 0; -static Ptr_g_free p_g_free = 0; -#endif - static void qt_cleanlooks_draw_gradient(QPainter *painter, const QRect &rect, const QColor &gradientStart, const QColor &gradientStop, Direction direction = TopDown, QBrush bgBrush = QBrush()) { @@ -3848,17 +3828,6 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption * void QCleanlooksStyle::polish(QApplication *app) { QWindowsStyle::polish(app); -#ifdef Q_WS_X11 - Q_D(QCleanlooksStyle); - - QString dataDirs = QLatin1String(getenv("XDG_DATA_DIRS")); - - if (dataDirs.isEmpty()) - dataDirs = QLatin1String("/usr/local/share/:/usr/share/"); - - dataDirs.prepend(QDir::homePath() + QLatin1String("/:")); - d->iconDirs = dataDirs.split(QLatin1Char(':')); -#endif } /*! @@ -4376,44 +4345,6 @@ QRect QCleanlooksStyle::subElementRect(SubElement sr, const QStyleOption *opt, c return r; } -void QCleanlooksStylePrivate::lookupIconTheme() const -{ -#ifdef Q_WS_X11 - - if (themeName.isEmpty()) { - //resolve glib and gconf functions - p_g_type_init = (Ptr_g_type_init)QLibrary::resolve(QLatin1String("gobject-2.0"), 0, "g_type_init"); - p_gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLatin1String("gconf-2"), 4, "gconf_client_get_default"); - p_gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLatin1String("gconf-2"), 4, "gconf_client_get_string"); - p_g_object_unref = (Ptr_g_object_unref)QLibrary::resolve(QLatin1String("gobject-2.0"), 0, "g_object_unref"); - p_g_error_free = (Ptr_g_error_free)QLibrary::resolve(QLatin1String("glib-2.0"), 0, "g_error_free"); - p_g_free = (Ptr_g_free)QLibrary::resolve(QLatin1String("glib-2.0"), 0, "g_free"); - - if (p_g_type_init && - p_gconf_client_get_default && - p_gconf_client_get_string && - p_g_object_unref && - p_g_error_free && - p_g_free) { - - p_g_type_init(); - GConfClient* client = p_gconf_client_get_default(); - GError *err = 0; - char *str = p_gconf_client_get_string(client, "/desktop/gnome/interface/icon_theme", &err); - if (!err) { - themeName = QString::fromUtf8(str); - p_g_free(str); - } - p_g_object_unref(client); - if (err) - p_g_error_free (err); - } - if (themeName.isEmpty()) - themeName = QLatin1String("gnome"); - } -#endif -} - /*! \internal */ @@ -4421,165 +4352,6 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { -#ifdef Q_WS_X11 - Q_D(const QCleanlooksStyle); - if (!QApplication::desktopSettingsAware()) - return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); - QIcon icon; - QPixmap pixmap; - QPixmap link; - d->lookupIconTheme(); - switch (standardIcon) { - case SP_DirIcon: { - icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget)); - icon.addPixmap(proxy()->standardPixmap(SP_DirClosedIcon, option, widget), - QIcon::Normal, QIcon::Off); - pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png")); - if (!pixmap.isNull()) - icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); - pixmap = d->findIcon(48, QLatin1String("gnome-fs-directory.png")); - if (!pixmap.isNull()) - icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); - pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory-accept.png")); - if (!pixmap.isNull()) - icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); - pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory-accept.png")); - if (!pixmap.isNull()) - icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); - } - break; - case SP_DirLinkIcon: - { - icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget)); - QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png")); - if (!link.isNull()) { - icon.addPixmap(proxy()->standardPixmap(SP_DirLinkIcon, option, widget)); - pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png")); - if (!pixmap.isNull()) { - QPainter painter(&pixmap); - painter.drawPixmap(8, 8, 8, 8, link); - painter.end(); - icon.addPixmap(pixmap); - } - } - break; - } - case SP_FileIcon: - { - icon = d->createIcon(QLatin1String("unknown.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("gnome-fs-regular.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("stock_new.png")); - break; - } - case SP_DialogCloseButton: - { - icon = d->createIcon(QLatin1String("gtk-close.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("stock-close.png")); - break; - } - case SP_DirHomeIcon: - { - icon = d->createIcon(QLatin1String("folder_home.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("gnome_home.png")); - break; - } - case SP_DriveFDIcon: - { - icon = d->createIcon(QLatin1String("gnome-dev-floppy.png")); - break; - } - case SP_ComputerIcon: - { - icon = d->createIcon(QLatin1String("gnome-fs-client.png")); - break; - } - case SP_DesktopIcon: - { - icon = d->createIcon(QLatin1String("gnome-fs-desktop.png")); - break; - } - case SP_TrashIcon: - { - icon = d->createIcon(QLatin1String("gnome-fs-trash-empty.png")); - break; - } - case SP_DriveCDIcon: - case SP_DriveDVDIcon: - { - icon = d->createIcon(QLatin1String("gnome-dev-cdrom.png")); - break; - } - case SP_DriveHDIcon: - { - icon = d->createIcon(QLatin1String("gnome-dev-harddisk.png")); - break; - } - case SP_ArrowUp: - { - icon = d->createIcon(QLatin1String("stock_up.png")); - break; - } - case SP_ArrowDown: - { - icon = d->createIcon(QLatin1String("stock_down.png")); - break; - } - case SP_ArrowRight: - { - icon = d->createIcon(QLatin1String("stock_right.png")); - break; - } - case SP_ArrowLeft: - { - icon = d->createIcon(QLatin1String("stock_left.png")); - break; - } - case SP_BrowserReload: - { - icon = d->createIcon(QLatin1String("view-refresh.png")); - break; - } - case SP_BrowserStop: - { - pixmap = d->findIcon(24, QLatin1String("stop.png")); - break; - } - case SP_FileLinkIcon: - { - icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget)); - QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png")); - if (!link.isNull()) { - icon.addPixmap(proxy()->standardPixmap(SP_FileLinkIcon,option, widget)); - pixmap = d->findIcon(16, QLatin1String("unknown.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("stock_new.png")); - if (!pixmap.isNull()) { - QPainter painter(&pixmap); - painter.drawPixmap(8, 8, 8, 8, link); - painter.end(); - icon.addPixmap(pixmap); - } - } - break; - } - case SP_ArrowForward: - if (QApplication::layoutDirection() == Qt::RightToLeft) - return standardIconImplementation(SP_ArrowLeft, option, widget); - return standardIconImplementation(SP_ArrowRight, option, widget); - case SP_ArrowBack: - if (QApplication::layoutDirection() == Qt::RightToLeft) - return standardIconImplementation(SP_ArrowRight, option, widget); - return standardIconImplementation(SP_ArrowLeft, option, widget); - default: - icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget)); - } - if (!icon.isNull()) - return icon; -#endif // Q_WS_X11 return QWindowsStyle::standardIconImplementation(standardIcon, option, widget); } @@ -4589,341 +4361,10 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon, QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const { -#ifdef Q_WS_X11 - Q_D(const QCleanlooksStyle); QPixmap pixmap; - if (!QApplication::desktopSettingsAware()) - return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); - d->lookupIconTheme(); + #ifndef QT_NO_IMAGEFORMAT_XPM switch (standardPixmap) { - case SP_MessageBoxInformation: - { - pixmap = d->findIcon(48, QLatin1String("dialog-info.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(48, QLatin1String("stock_dialog-info.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MessageBoxWarning: - { - pixmap = d->findIcon(48, QLatin1String("dialog-warning.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(48, QLatin1String("stock_dialog-warning.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MessageBoxCritical: - { - pixmap = d->findIcon(48, QLatin1String("dialog-error.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(48, QLatin1String("stock_dialog-error.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MessageBoxQuestion: - { - pixmap = d->findIcon(48, QLatin1String("dialog-question.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DirHomeIcon: - { - pixmap = d->findIcon(16, QLatin1String("folder_home.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("gnome_home.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogOpenButton: - case SP_DirOpenIcon: - { - pixmap = d->findIcon(24, QLatin1String("stock_open.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_FileIcon: - { - pixmap = d->findIcon(24, QLatin1String("unknown.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("gnome-fs-regular.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("stock_new.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_FileLinkIcon: - { - pixmap = d->findIcon(24, QLatin1String("emblem-symbolic-link.png")); - if (!pixmap.isNull()) { - QPixmap fileIcon = d->findIcon(24, QLatin1String("unknown.png")); - if (fileIcon.isNull()) - fileIcon = d->findIcon(24, QLatin1String("stock_new.png")); - if (!fileIcon.isNull()) { - QPainter painter(&fileIcon); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.drawPixmap(12, 12, 12, 12, pixmap); - return fileIcon; - } - } - break; - } - case SP_DirClosedIcon: - case SP_DirIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-fs-directory.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DirLinkIcon: - { - pixmap = d->findIcon(24, QLatin1String("emblem-symbolic-link.png")); - if (!pixmap.isNull()) { - QPixmap dirIcon = d->findIcon(24, QLatin1String("gnome-fs-directory.png")); - if (!dirIcon.isNull()) { - QPainter painter(&dirIcon); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.drawPixmap(12, 12, 12, 12, pixmap); - return dirIcon; - } - } - break; - } - case SP_DriveFDIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-dev-floppy.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_ComputerIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-fs-client.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DesktopIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-fs-desktop.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_TrashIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-fs-trash-empty.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DriveCDIcon: - case SP_DriveDVDIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-dev-cdrom.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DriveHDIcon: - { - pixmap = d->findIcon(24, QLatin1String("gnome-dev-harddisk.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_FileDialogToParent: - { - pixmap = d->findIcon(16, QLatin1String("stock_up.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_FileDialogNewFolder: - { - pixmap = d->findIcon(16, QLatin1String("stock_new-dir.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_ArrowUp: - { - pixmap = d->findIcon(16, QLatin1String("stock_up.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_ArrowDown: - { - pixmap = d->findIcon(16, QLatin1String("stock_down.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_ArrowRight: - { - pixmap = d->findIcon(16, QLatin1String("stock_right.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_ArrowLeft: - { - pixmap = d->findIcon(16, QLatin1String("stock_left.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogCloseButton: - { - pixmap = d->findIcon(24, QLatin1String("gtk-close.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("stock-close.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogApplyButton: - { - pixmap = d->findIcon(24, QLatin1String("dialog-apply.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("stock-apply.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogResetButton: - { - pixmap = d->findIcon(24, QLatin1String("gtk-clear.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogHelpButton: - { - pixmap = d->findIcon(24, QLatin1String("gtk-help.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogOkButton: - { - pixmap = d->findIcon(24, QLatin1String("dialog-ok.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("stock-ok.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogCancelButton: - { - pixmap = d->findIcon(24, QLatin1String("dialog-cancel.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("stock-cancel.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(24, QLatin1String("process-stop.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_DialogSaveButton: - { - pixmap = d->findIcon(24, QLatin1String("stock_save.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_BrowserStop: - { - pixmap = d->findIcon(16, QLatin1String("process-stop.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_BrowserReload: - { - pixmap = d->findIcon(16, QLatin1String("view-refresh.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaPlay: - { - pixmap = d->findIcon(24, QLatin1String("media-playback-start.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaPause: - { - pixmap = d->findIcon(24, QLatin1String("media-playback-pause.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaStop: - { - pixmap = d->findIcon(24, QLatin1String("media-playback-stop.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaVolume: - { - pixmap = d->findIcon(16, QLatin1String("audio-volume-medium.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaVolumeMuted: - { - pixmap = d->findIcon(16, QLatin1String("audio-volume-muted.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaSeekForward: - { - pixmap = d->findIcon(24, QLatin1String("media-seek-forward.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaSeekBackward: - { - pixmap = d->findIcon(24, QLatin1String("media-seek-backward.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaSkipForward: - { - pixmap = d->findIcon(24, QLatin1String("media-skip-forward.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_MediaSkipBackward: - { - pixmap = d->findIcon(24, QLatin1String("media-skip-backward.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_TitleBarMenuButton: - case SP_TitleBarShadeButton: - case SP_TitleBarUnshadeButton: - case SP_TitleBarMaxButton: - case SP_TitleBarContextHelpButton: - return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); case SP_TitleBarNormalButton: return QPixmap((const char **)dock_widget_restore_xpm); case SP_TitleBarMinButton: @@ -4936,7 +4377,7 @@ QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QS break; } #endif //QT_NO_IMAGEFORMAT_XPM -#endif //Q_WS_X11 + return QWindowsStyle::standardPixmap(standardPixmap, opt, widget); } diff --git a/src/gui/styles/qcleanlooksstyle_p.h b/src/gui/styles/qcleanlooksstyle_p.h index a26d40d..d325499 100644 --- a/src/gui/styles/qcleanlooksstyle_p.h +++ b/src/gui/styles/qcleanlooksstyle_p.h @@ -71,8 +71,6 @@ public: ~QCleanlooksStylePrivate() { } - - void lookupIconTheme() const; }; QT_END_NAMESPACE diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index c7feb25..3878856 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -840,176 +840,8 @@ static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbut #endif // QT_NO_TOOLBUTTON - #ifdef Q_WS_X11 // These functions are used to parse the X11 freedesktop icon spec -void QCommonStylePrivate::lookupIconTheme() const -{ - if (!themeName.isEmpty()) - return; - - QString dataDirs = QString::fromLocal8Bit(getenv("XDG_DATA_DIRS")); - if (dataDirs.isEmpty()) - dataDirs = QLatin1String("/usr/local/share/:/usr/share/"); - dataDirs += QLatin1Char(':') + QKde::kdeHome() + QLatin1String("/share"); - dataDirs.prepend(QDir::homePath() + QLatin1String("/:")); - QStringList kdeDirs = QString::fromLocal8Bit(getenv("KDEDIRS")).split(QLatin1Char(':'), QString::SkipEmptyParts); - foreach (const QString &dirName, kdeDirs) - dataDirs.append(QLatin1Char(':') + dirName + QLatin1String("/share")); - iconDirs = dataDirs.split(QLatin1Char(':')); - - QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde")); - QDir dir(fileInfo.canonicalFilePath()); - QString kdeDefault = (X11->desktopEnvironment != DE_KDE || X11->desktopVersion >= 4) - ? QString::fromLatin1("oxygen") : QString::fromLatin1("crystalsvg"); - QString defaultTheme = fileInfo.exists() ? dir.dirName() : kdeDefault; - QSettings settings(QKde::kdeHome() + - QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - settings.beginGroup(QLatin1String("Icons")); - themeName = settings.value(QLatin1String("Theme"), defaultTheme).toString(); -} - -QIconTheme QCommonStylePrivate::parseIndexFile(const QString &themeName) const -{ - Q_Q(const QCommonStyle); - QIconTheme theme; - QFile themeIndex; - QStringList parents; - QHash dirList; - - for ( int i = 0 ; i < iconDirs.size() && !themeIndex.exists() ; ++i) { - QString contentDir = QLatin1String(iconDirs[i].startsWith(QDir::homePath()) ? - "/.icons/" : "/icons/"); - themeIndex.setFileName(iconDirs[i] + contentDir + - themeName + QLatin1String("/index.theme")); - } - - if (themeIndex.open(QIODevice::ReadOnly | QIODevice::Text)) { - - QTextStream in(&themeIndex); - - while (!in.atEnd()) { - - QString line = in.readLine(); - - if (line.startsWith(QLatin1String("Inherits="))) { - line = line.right(line.length() - 9); - parents = line.split(QLatin1Char(',')); - } - - if (line.startsWith(QLatin1Char('['))) { - line = line.trimmed(); - line.chop(1); - QString dirName = line.right(line.length() - 1); - if (!in.atEnd()) { - line = in.readLine(); - int size; - if (line.startsWith(QLatin1String("Size="))) { - size = line.right(line.length() - 5).toInt(); - if (size) - dirList.insertMulti(size, dirName); - } - } - } - } - } - - if (q->inherits("QPlastiqueStyle")) { - QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde")); - QDir dir(fileInfo.canonicalFilePath()); - QString defaultKDETheme = dir.exists() ? dir.dirName() : QString::fromLatin1("crystalsvg"); - if (!parents.contains(defaultKDETheme) && themeName != defaultKDETheme) - parents.append(defaultKDETheme); - } else if (parents.isEmpty() && themeName != QLatin1String("hicolor")) { - parents.append(QLatin1String("hicolor")); - } - theme = QIconTheme(dirList, parents); - return theme; -} - -QPixmap QCommonStylePrivate::findIconHelper(int size, - const QString &themeName, - const QString &iconName, - QStringList &visited) const -{ - QPixmap pixmap; - - if (!themeName.isEmpty()) { - - visited << themeName; - QIconTheme theme = themeList.value(themeName); - - if (!theme.isValid()) { - theme = parseIndexFile(themeName); - themeList.insert(themeName, theme); - } - - if (!theme.isValid()) - return QPixmap(); - - QList subDirs = theme.dirList().values(size); - - for ( int i = 0 ; i < iconDirs.size() ; ++i) { - for ( int j = 0 ; j < subDirs.size() ; ++j) { - QString contentDir = (iconDirs[i].startsWith(QDir::homePath())) ? - QLatin1String("/.icons/") : QLatin1String("/icons/"); - QString fileName = iconDirs[i] + contentDir + themeName + QLatin1Char('/') + subDirs[j] + QLatin1Char('/') + iconName; - QFile file(fileName); - if (file.exists()) - pixmap.load(fileName); - if (!pixmap.isNull()) - break; - } - } - - if (pixmap.isNull()) { - QStringList parents = theme.parents(); - //search recursively through inherited themes - for (int i = 0 ; pixmap.isNull() && i < parents.size() ; ++i) { - QString parentTheme = parents[i].trimmed(); - if (!visited.contains(parentTheme)) //guard against endless recursion - pixmap = findIconHelper(size, parentTheme, iconName, visited); - } - } - } - return pixmap; -} - -/*! \internal - find a pixmap with the given size and name from the freedesktop theme. -*/ -QPixmap QCommonStylePrivate::findIcon(int size, const QString &name) const -{ - QIcon icon = QKde::kdeIcon(name); - if (!icon.isNull()) - return icon.pixmap(size); - - QPixmap pixmap; - QString pixmapName = QLatin1String("$qt") + name + QString::number(size); - - if (QPixmapCache::find(pixmapName, pixmap)) - return pixmap; - - if (!themeName.isEmpty()) { - QStringList visited; - pixmap = findIconHelper(size, themeName, name, visited); - } - QPixmapCache::insert(pixmapName, pixmap); - return pixmap; -} -/*! \internal - create an Icon from the freedesktop theme. - */ -QIcon QCommonStylePrivate::createIcon(const QString &name) const -{ - QIcon icon = QKde::kdeIcon(name); - if (icon.isNull()) { - icon.addPixmap(findIcon(16, name)); - icon.addPixmap(findIcon(24, name)); - icon.addPixmap(findIcon(32, name)); - } - return icon; -} /*!internal Checks if you are running KDE and looks up the toolbar @@ -4859,8 +4691,24 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid ret = int(QStyleHelper::dpiScaled(6.)); break; - case PM_TabBarIconSize: case PM_ToolBarIconSize: +#ifdef Q_WS_X11 + if (X11->desktopVersion >= 4) { + static int iconSize = 0; + if (!iconSize) { + QSettings settings(QKde::kdeHome() + + QLatin1String("/share/config/kdeglobals"), + QSettings::IniFormat); + settings.beginGroup(QLatin1String("ToolbarIcons")); + iconSize = settings.value(QLatin1String("Size"), QLatin1String("22")).toInt(); + } + ret = iconSize; + } else +#endif + ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + break; + + case PM_TabBarIconSize: case PM_ListViewIconSize: ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); break; @@ -5371,293 +5219,161 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti Q_UNUSED(widget); Q_UNUSED(sp); #else -#ifdef Q_WS_X11 - Q_D(const QCommonStyle); QPixmap pixmap; - if (QApplication::desktopSettingsAware()) { - d->lookupIconTheme(); + + if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) { switch (sp) { case SP_DirHomeIcon: - { - pixmap = d->findIcon(16, QLatin1String("folder_home.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } + pixmap = QIcon::fromTheme(QLatin1String("user-home")).pixmap(16); + break; case SP_MessageBoxInformation: - { - pixmap = d->findIcon(32, QLatin1String("messagebox_info.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } + pixmap = QIcon::fromTheme(QLatin1String("messagebox_info")).pixmap(16); + break; case SP_MessageBoxWarning: - { - pixmap = d->findIcon(32, QLatin1String("messagebox_warning.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } + pixmap = QIcon::fromTheme(QLatin1String("messagebox_warning")).pixmap(16); + break; case SP_MessageBoxCritical: - { - pixmap = d->findIcon(32, QLatin1String("messagebox_critical.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } + pixmap = QIcon::fromTheme(QLatin1String("messagebox_critical")).pixmap(16); + break; case SP_MessageBoxQuestion: - { - pixmap = d->findIcon(32, QLatin1String("help.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } + pixmap = QIcon::fromTheme(QLatin1String("help")).pixmap(16); + break; case SP_DialogOpenButton: case SP_DirOpenIcon: - { - pixmap = d->findIcon(16, QLatin1String("folder-open.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("folder_open.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } + pixmap = QIcon::fromTheme(QLatin1String("folder-open")).pixmap(16); + break; case SP_FileIcon: - { - pixmap = d->findIcon(16, QLatin1String("text-x-generic.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("empty.png")); - if (!pixmap.isNull()) - return pixmap; - break; - } - case SP_FileLinkIcon: - { - pixmap = d->findIcon(16, QLatin1String("link_overlay.png")); - if (!pixmap.isNull()) { - QPixmap fileIcon = d->findIcon(16, QLatin1String("text-x-generic.png")); - if (fileIcon.isNull()) - fileIcon = d->findIcon(16, QLatin1String("empty.png")); - if (!fileIcon.isNull()) { - QPainter painter(&fileIcon); - painter.drawPixmap(0, 0, 16, 16, pixmap); - return fileIcon; - } - } - break; - } + pixmap = QIcon::fromTheme(QLatin1String("text-x-generic"), + QIcon::fromTheme(QLatin1String("empty"))).pixmap(16); + break; case SP_DirClosedIcon: case SP_DirIcon: - { - pixmap = d->findIcon(16, QLatin1String("folder.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("folder")).pixmap(16); break; - } - case SP_DirLinkIcon: - { - pixmap = d->findIcon(16, QLatin1String("link_overlay.png")); - if (!pixmap.isNull()) { - QPixmap dirIcon = d->findIcon(16, QLatin1String("folder.png")); - if (!dirIcon.isNull()) { - QPainter painter(&dirIcon); - painter.drawPixmap(0, 0, 16, 16, pixmap); - return dirIcon; - } - } - break; - } case SP_DriveFDIcon: - { - pixmap = d->findIcon(16, QLatin1String("media-floppy.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("3floppy_unmount.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-floppy"), + QIcon::fromTheme(QLatin1String("3floppy_unmount"))).pixmap(16); break; - } case SP_ComputerIcon: - { - pixmap = d->findIcon(16, QLatin1String("computer.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("system.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("computer"), + QIcon::fromTheme(QLatin1String("system"))).pixmap(16); break; - } case SP_DesktopIcon: - { - pixmap = d->findIcon(16, QLatin1String("user-desktop.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("desktop.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("user-desktop"), + QIcon::fromTheme(QLatin1String("desktop"))).pixmap(16); break; - } case SP_TrashIcon: - { - pixmap = d->findIcon(16, QLatin1String("user-trash.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("trashcan_empty.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("user-trash"), + QIcon::fromTheme(QLatin1String("trashcan_empty"))).pixmap(16); break; - } case SP_DriveCDIcon: case SP_DriveDVDIcon: - { - pixmap = d->findIcon(16, QLatin1String("media-optical.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("cdrom_unmount.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-optical"), + QIcon::fromTheme(QLatin1String("cdrom_unmount"))).pixmap(16); break; - } case SP_DriveHDIcon: - { - pixmap = d->findIcon(16, QLatin1String("drive-harddisk.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(16, QLatin1String("hdd_unmount.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("drive-harddisk"), + QIcon::fromTheme(QLatin1String("hdd_unmount"))).pixmap(16); break; - } case SP_FileDialogToParent: - { - pixmap = d->findIcon(32, QLatin1String("go-up.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(32, QLatin1String("up.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("go-up"), + QIcon::fromTheme(QLatin1String("up"))).pixmap(16); break; - } case SP_FileDialogNewFolder: - { - pixmap = d->findIcon(16, QLatin1String("folder_new.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("folder_new")).pixmap(16); break; - } case SP_ArrowUp: - { - pixmap = d->findIcon(32, QLatin1String("go-up.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(32, QLatin1String("up.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("go-up"), + QIcon::fromTheme(QLatin1String("up"))).pixmap(16); break; - } case SP_ArrowDown: - { - pixmap = d->findIcon(32, QLatin1String("go-down.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(32, QLatin1String("down.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("go-down"), + QIcon::fromTheme(QLatin1String("down"))).pixmap(16); break; - } case SP_ArrowRight: - { - pixmap = d->findIcon(32, QLatin1String("go-next.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(32, QLatin1String("forward.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("go-next"), + QIcon::fromTheme(QLatin1String("forward"))).pixmap(16); break; - } case SP_ArrowLeft: - { - pixmap = d->findIcon(32, QLatin1String("go-previous.png")); - if (pixmap.isNull()) - pixmap = d->findIcon(32, QLatin1String("back.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("go-previous"), + QIcon::fromTheme(QLatin1String("back"))).pixmap(16); break; - } case SP_FileDialogDetailedView: - { - pixmap = d->findIcon(16, QLatin1String("view_detailed.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("view_detailed")).pixmap(16); break; - } - case SP_FileDialogListView: - { - pixmap = d->findIcon(16, QLatin1String("view_icon.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("view_icon")).pixmap(16); break; - } case SP_BrowserReload: - { - pixmap = d->findIcon(32, QLatin1String("reload.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("reload")).pixmap(16); break; - } case SP_BrowserStop: - { - pixmap = d->findIcon(32, QLatin1String("stop.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(16); break; - } case SP_MediaPlay: - { - pixmap = d->findIcon(16, QLatin1String("player_play.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-playback-start")).pixmap(16); break; - } case SP_MediaPause: - { - pixmap = d->findIcon(16, QLatin1String("player_pause.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-playback-pause")).pixmap(16); break; - } case SP_MediaStop: - { - pixmap = d->findIcon(16, QLatin1String("player_stop.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-playback-stop")).pixmap(16); break; - } case SP_MediaSeekForward: - { - pixmap = d->findIcon(16, QLatin1String("player_fwd.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-seek-forward")).pixmap(16); break; - } case SP_MediaSeekBackward: - { - pixmap = d->findIcon(16, QLatin1String("player_rew.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-seek-backward")).pixmap(16); break; - } case SP_MediaSkipForward: - { - pixmap = d->findIcon(16, QLatin1String("player_end.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16); break; - } case SP_MediaSkipBackward: - { - pixmap = d->findIcon(16, QLatin1String("player_start.png")); - if (!pixmap.isNull()) - return pixmap; + pixmap = QIcon::fromTheme(QLatin1String("media-skip-backward")).pixmap(16); + break; + case SP_DialogResetButton: + pixmap = QIcon::fromTheme(QLatin1String("edit-clear")).pixmap(24); + break; + case SP_DialogHelpButton: + pixmap = QIcon::fromTheme(QLatin1String("help-contents")).pixmap(24); + break; + case SP_DialogCancelButton: + pixmap = QIcon::fromTheme(QLatin1String("process-stop")).pixmap(24); + break; + case SP_DialogSaveButton: + pixmap = QIcon::fromTheme(QLatin1String("document-save")).pixmap(24); break; + case SP_FileLinkIcon: + pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16); + if (!pixmap.isNull()) { + QPixmap fileIcon = QIcon::fromTheme(QLatin1String("text-x-generic")).pixmap(16); + if (fileIcon.isNull()) + fileIcon = QIcon::fromTheme(QLatin1String("empty")).pixmap(16); + if (!fileIcon.isNull()) { + QPainter painter(&fileIcon); + painter.drawPixmap(0, 0, 16, 16, pixmap); + return fileIcon; + } } - + break; + case SP_DirLinkIcon: + pixmap = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")).pixmap(16); + if (!pixmap.isNull()) { + QPixmap dirIcon = QIcon::fromTheme(QLatin1String("folder")).pixmap(16); + if (!dirIcon.isNull()) { + QPainter painter(&dirIcon); + painter.drawPixmap(0, 0, 16, 16, pixmap); + return dirIcon; + } + } + break; default: break; } } -#endif //Q_WS_X11 + + if (!pixmap.isNull()) + return pixmap; #endif //QT_NO_IMAGEFORMAT_PNG switch (sp) { #ifndef QT_NO_IMAGEFORMAT_XPM @@ -5793,254 +5509,178 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons const QWidget *widget) const { QIcon icon; - if (QApplication::desktopSettingsAware()) { -#ifdef Q_WS_X11 - Q_D(const QCommonStyle); - d->lookupIconTheme(); - QPixmap pixmap; + if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) { switch (standardIcon) { case SP_DirHomeIcon: - { - icon = d->createIcon(QLatin1String("folder_home.png")); + icon = QIcon::fromTheme(QLatin1String("user-home")); break; - } case SP_MessageBoxInformation: - { - icon = d->createIcon(QLatin1String("dialog-information.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("messagebox_info.png")); + icon = QIcon::fromTheme(QLatin1String("dialog-information")); break; - } case SP_MessageBoxWarning: - { - icon = d->createIcon(QLatin1String("dialog-warning.png")); - icon = d->createIcon(QLatin1String("dialog-warning.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("messagebox_warning.png")); + icon = QIcon::fromTheme(QLatin1String("dialog-warning")); break; - } case SP_MessageBoxCritical: - { - icon = d->createIcon(QLatin1String("dialog-error.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("messagebox_critical.png")); + icon = QIcon::fromTheme(QLatin1String("dialog-error")); break; - } case SP_MessageBoxQuestion: - { - icon = d->createIcon(QLatin1String("help.png")); + icon = QIcon::fromTheme(QLatin1String("dialog-question")); break; - } case SP_DialogOpenButton: case SP_DirOpenIcon: - { - icon = d->createIcon(QLatin1String("folder-open.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("folder_open.png")); + icon = QIcon::fromTheme(QLatin1String("folder-open")); break; - } case SP_FileIcon: - { - icon = d->createIcon(QLatin1String("text-x-generic.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("empty.png")); + icon = QIcon::fromTheme(QLatin1String("text-x-generic")); break; - } case SP_DirClosedIcon: case SP_DirIcon: - { - icon = d->createIcon(QLatin1String("folder.png")); + icon = QIcon::fromTheme(QLatin1String("folder")); break; - } case SP_DriveFDIcon: - { - icon = d->createIcon(QLatin1String("floppy_unmount.png")); + icon = QIcon::fromTheme(QLatin1String("floppy_unmount")); break; - } case SP_ComputerIcon: - { - icon = d->createIcon(QLatin1String("computer.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("system.png")); + icon = QIcon::fromTheme(QLatin1String("computer"), + QIcon::fromTheme(QLatin1String("system"))); break; - } case SP_DesktopIcon: - { - icon = d->createIcon(QLatin1String("user-desktop.png")); + icon = QIcon::fromTheme(QLatin1String("user-desktop")); break; - } case SP_TrashIcon: - { - icon = d->createIcon(QLatin1String("user-trash.png")); + icon = QIcon::fromTheme(QLatin1String("user-trash")); break; - } case SP_DriveCDIcon: case SP_DriveDVDIcon: - { - icon = d->createIcon(QLatin1String("media-optical.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("cdrom_unmount.png")); + icon = QIcon::fromTheme(QLatin1String("media-optical")); break; - } case SP_DriveHDIcon: - { - icon = d->createIcon(QLatin1String("drive-harddisk.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("hdd_unmount.png")); + icon = QIcon::fromTheme(QLatin1String("drive-harddisk")); break; - } case SP_FileDialogToParent: - { - icon = d->createIcon(QLatin1String("go-up.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("up.png")); + icon = QIcon::fromTheme(QLatin1String("go-up")); break; - } case SP_FileDialogNewFolder: - { - icon = d->createIcon(QLatin1String("folder_new.png")); + icon = QIcon::fromTheme(QLatin1String("folder-new")); break; - } case SP_ArrowUp: - { - icon = d->createIcon(QLatin1String("go-up.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("up.png")); + icon = QIcon::fromTheme(QLatin1String("go-up")); break; - } case SP_ArrowDown: - { - icon = d->createIcon(QLatin1String("go-down.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("down.png")); + icon = QIcon::fromTheme(QLatin1String("go-down")); break; - } case SP_ArrowRight: - { - icon = d->createIcon(QLatin1String("go-next.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("forward.png")); + icon = QIcon::fromTheme(QLatin1String("go-next")); break; - } case SP_ArrowLeft: - { - icon = d->createIcon(QLatin1String("go-previous.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("back.png")); + icon = QIcon::fromTheme(QLatin1String("go-previous")); + break; + case SP_DialogHelpButton: + icon = QIcon::fromTheme(QLatin1String("help-contents")); + break; + case SP_DialogCancelButton: + icon = QIcon::fromTheme(QLatin1String("process-stop")); + break; + case SP_DialogCloseButton: + icon = QIcon::fromTheme(QLatin1String("window-close")); + break; + case SP_DialogApplyButton: + icon = QIcon::fromTheme(QLatin1String("dialog-ok-apply")); + break; + case SP_DialogOkButton: + icon = QIcon::fromTheme(QLatin1String("dialog-ok")); break; - } case SP_FileDialogDetailedView: - { - icon = d->createIcon(QLatin1String("view-list-details.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("view_detailed.png")); + icon = QIcon::fromTheme(QLatin1String("view-list-details")); break; - } case SP_FileDialogListView: - { - icon = d->createIcon(QLatin1String("view-list-icons.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("view_icon.png")); + icon = QIcon::fromTheme(QLatin1String("view-list-icons")); break; - } case SP_BrowserReload: - { - icon = d->createIcon(QLatin1String("view-refresh.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("reload.png")); + icon = QIcon::fromTheme(QLatin1String("view-refresh")); break; - } case SP_BrowserStop: - { - icon = d->createIcon(QLatin1String("process-stop.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("stop.png")); + icon = QIcon::fromTheme(QLatin1String("process-stop")); break; - } case SP_MediaPlay: - { - icon = d->createIcon(QLatin1String("media-playback-start.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_play.png")); + icon = QIcon::fromTheme(QLatin1String("media-playback-start")); break; - } case SP_MediaPause: - { - icon = d->createIcon(QLatin1String("media-playback-pause.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_pause.png")); + icon = QIcon::fromTheme(QLatin1String("media-playback-pause")); break; - } case SP_MediaStop: - { - icon = d->createIcon(QLatin1String("media-playback-stop.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_stop.png")); + icon = QIcon::fromTheme(QLatin1String("media-playback-stop")); break; - } case SP_MediaSeekForward: - { - icon = d->createIcon(QLatin1String("media-skip-forward.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_fwd.png")); + icon = QIcon::fromTheme(QLatin1String("media-seek-forward")); break; - } case SP_MediaSeekBackward: - { - icon = d->createIcon(QLatin1String("media-skip-backward.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_rew.png")); + icon = QIcon::fromTheme(QLatin1String("media-seek-backward")); break; - } case SP_MediaSkipForward: - { - icon = d->createIcon(QLatin1String("media-skip-forward.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_end.png")); + icon = QIcon::fromTheme(QLatin1String("media-skip-forward")); break; - } case SP_MediaSkipBackward: - { - icon = d->createIcon(QLatin1String("media-skip-backward.png")); - if (icon.isNull()) - icon = d->createIcon(QLatin1String("player_start.png")); + icon = QIcon::fromTheme(QLatin1String("media-skip-backward")); break; - } - - case SP_FileLinkIcon: { - icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget)); - QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png")); - if (!pixmap.isNull()) { - QPixmap fileIcon = d->findIcon(32, QLatin1String("text-x-generic.png")); - if (fileIcon.isNull()) - fileIcon = d->findIcon(32, QLatin1String("empty.png")); - if (!fileIcon.isNull()) { - QPainter painter(&fileIcon); - painter.drawPixmap(0, 0, 32, 32, pixmap); - icon.addPixmap(fileIcon); + case SP_MediaVolume: + icon = QIcon::fromTheme(QLatin1String("audio-volume-medium")); + break; + case SP_MediaVolumeMuted: + icon = QIcon::fromTheme(QLatin1String("audio-volume-muted")); + break; + case SP_DialogResetButton: + icon = QIcon::fromTheme(QLatin1String("edit-clear")); + break; + case SP_ArrowForward: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return standardIconImplementation(SP_ArrowLeft, option, widget); + return standardIconImplementation(SP_ArrowRight, option, widget); + case SP_ArrowBack: + if (QApplication::layoutDirection() == Qt::RightToLeft) + return standardIconImplementation(SP_ArrowRight, option, widget); + return standardIconImplementation(SP_ArrowLeft, option, widget); + case SP_FileLinkIcon: + { + QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")); + if (!linkIcon.isNull()) { + QIcon baseIcon = standardIconImplementation(SP_FileIcon, option, widget); + const QList sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off); + for (int i = 0 ; i < sizes.size() ; ++i) { + int size = sizes[i].width(); + QPixmap basePixmap = baseIcon.pixmap(size); + QPixmap linkPixmap = linkIcon.pixmap(size/2); + QPainter painter(&basePixmap); + painter.drawPixmap(size/2, size/2, linkPixmap); + icon.addPixmap(basePixmap); + } } } - } - break; - case SP_DirLinkIcon: { - icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget)); - QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png")); - if (!pixmap.isNull()) { - QPixmap fileIcon = d->findIcon(32, QLatin1String("folder.png")); - if (!fileIcon.isNull()) { - QPainter painter(&fileIcon); - painter.drawPixmap(0, 0, 32, 32, pixmap); - icon.addPixmap(fileIcon); + break; + case SP_DirLinkIcon: + { + QIcon linkIcon = QIcon::fromTheme(QLatin1String("emblem-symbolic-link")); + if (!linkIcon.isNull()) { + QIcon baseIcon = standardIconImplementation(SP_DirIcon, option, widget); + const QList sizes = baseIcon.availableSizes(QIcon::Normal, QIcon::Off); + for (int i = 0 ; i < sizes.size() ; ++i) { + int size = sizes[i].width(); + QPixmap basePixmap = baseIcon.pixmap(size); + QPixmap linkPixmap = linkIcon.pixmap(size/2); + QPainter painter(&basePixmap); + painter.drawPixmap(size/2, size/2, linkPixmap); + icon.addPixmap(basePixmap); + } } - } } break; default: break; } + if (!icon.isNull()) return icon; -#elif defined(Q_WS_MAC) +#if defined(Q_WS_MAC) OSType iconType = 0; switch (standardIcon) { case QStyle::SP_MessageBoxQuestion: @@ -6131,11 +5771,9 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons ReleaseIconRef(overlayIcon); return retIcon; } - -#endif //Q_WS_X11 || Q_WS_MAC +#endif // Q_WS_MAC } - switch (standardIcon) { #ifndef QT_NO_IMAGEFORMAT_PNG case SP_FileDialogNewFolder: diff --git a/src/gui/styles/qcommonstyle_p.h b/src/gui/styles/qcommonstyle_p.h index f2af5b2..cff46e6 100644 --- a/src/gui/styles/qcommonstyle_p.h +++ b/src/gui/styles/qcommonstyle_p.h @@ -122,20 +122,7 @@ public: } #endif mutable QIcon tabBarcloseButtonIcon; - -//icon detection on X11 -#ifdef Q_WS_X11 - void lookupIconTheme() const; int lookupToolButtonStyle() const; - QIcon createIcon(const QString &) const; - QPixmap findIcon(int size, const QString &) const; - QPixmap findIconHelper(int size, const QString &, const QString &, QStringList &visited) const; - QIconTheme parseIndexFile(const QString &themeName) const; - mutable QString themeName; - mutable QStringList iconDirs; - mutable QHash themeList; -#endif - }; QT_END_NAMESPACE diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index 660b4c3..f6d8c88 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -3239,6 +3239,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, return newSize; } + /*! \reimp */ QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, const QWidget *widget) const @@ -3271,65 +3272,80 @@ QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, } break; - case SP_DialogDiscardButton: { + case SP_DialogDiscardButton: return QGtkPainter::getIcon(GTK_STOCK_DELETE); - } - - case SP_DialogOkButton: { + case SP_DialogOkButton: return QGtkPainter::getIcon(GTK_STOCK_OK); - } - - case SP_DialogCancelButton: { + case SP_DialogCancelButton: return QGtkPainter::getIcon(GTK_STOCK_CANCEL); - } - - case SP_DialogYesButton: { + case SP_DialogYesButton: return QGtkPainter::getIcon(GTK_STOCK_YES); - } - - case SP_DialogNoButton: { + case SP_DialogNoButton: return QGtkPainter::getIcon(GTK_STOCK_NO); - } - - case SP_DialogOpenButton: { + case SP_DialogOpenButton: return QGtkPainter::getIcon(GTK_STOCK_OPEN); - } - - case SP_DialogCloseButton: { + case SP_DialogCloseButton: return QGtkPainter::getIcon(GTK_STOCK_CLOSE); - } - - case SP_DialogApplyButton: { + case SP_DialogApplyButton: return QGtkPainter::getIcon(GTK_STOCK_APPLY); - } - - case SP_DialogSaveButton: { + case SP_DialogSaveButton: return QGtkPainter::getIcon(GTK_STOCK_SAVE); - } - - case SP_MessageBoxWarning: { + case SP_MessageBoxWarning: return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); - } - - case SP_MessageBoxQuestion: { + case SP_MessageBoxQuestion: return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); - } - - case SP_MessageBoxInformation: { + case SP_MessageBoxInformation: return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); - } - - case SP_MessageBoxCritical: { + case SP_MessageBoxCritical: return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); - } - default: return QCleanlooksStyle::standardPixmap(sp, option, widget); } + return pixmap; +} - return QPixmap(); +/*! + \internal +*/ +QIcon QGtkStyle::standardIconImplementation(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + if (!QGtk::isThemeAvailable()) + return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget); + switch (standardIcon) { + case SP_DialogDiscardButton: + return QGtkPainter::getIcon(GTK_STOCK_DELETE); + case SP_DialogOkButton: + return QGtkPainter::getIcon(GTK_STOCK_OK); + case SP_DialogCancelButton: + return QGtkPainter::getIcon(GTK_STOCK_CANCEL); + case SP_DialogYesButton: + return QGtkPainter::getIcon(GTK_STOCK_YES); + case SP_DialogNoButton: + return QGtkPainter::getIcon(GTK_STOCK_NO); + case SP_DialogOpenButton: + return QGtkPainter::getIcon(GTK_STOCK_OPEN); + case SP_DialogCloseButton: + return QGtkPainter::getIcon(GTK_STOCK_CLOSE); + case SP_DialogApplyButton: + return QGtkPainter::getIcon(GTK_STOCK_APPLY); + case SP_DialogSaveButton: + return QGtkPainter::getIcon(GTK_STOCK_SAVE); + case SP_MessageBoxWarning: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxQuestion: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxInformation: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); + case SP_MessageBoxCritical: + return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); + default: + return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget); + } } + /*! \reimp */ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { diff --git a/src/gui/styles/qgtkstyle.h b/src/gui/styles/qgtkstyle.h index e12f175..f12de52 100644 --- a/src/gui/styles/qgtkstyle.h +++ b/src/gui/styles/qgtkstyle.h @@ -106,6 +106,10 @@ public: void unpolish(QWidget *widget); void unpolish(QApplication *app); + +protected Q_SLOTS: + QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget = 0) const; }; diff --git a/tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png b/tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png new file mode 100644 index 0000000..18b7c67 Binary files /dev/null and b/tests/auto/qicon/icons/testtheme/16x16/actions/appointment-new.png differ diff --git a/tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png b/tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png new file mode 100644 index 0000000..d676ffd Binary files /dev/null and b/tests/auto/qicon/icons/testtheme/22x22/actions/appointment-new.png differ diff --git a/tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png b/tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png new file mode 100644 index 0000000..85daef3 Binary files /dev/null and b/tests/auto/qicon/icons/testtheme/32x32/actions/appointment-new.png differ diff --git a/tests/auto/qicon/icons/testtheme/index.theme b/tests/auto/qicon/icons/testtheme/index.theme new file mode 100644 index 0000000..e18736a --- /dev/null +++ b/tests/auto/qicon/icons/testtheme/index.theme @@ -0,0 +1,492 @@ +[Icon Theme] +_Name=Test +_Comment=Test Theme +Inherits=crystalsvg, themeparent +Example=x-directory-normal + +# KDE Specific Stuff +DisplayDepth=32 +LinkOverlay=link_overlay +LockOverlay=lock_overlay +ZipOverlay=zip_overlay +DesktopDefault=48 +DesktopSizes=16,22,32,48,64,72,96,128 +ToolbarDefault=22 +ToolbarSizes=16,22,32,48 +MainToolbarDefault=22 +MainToolbarSizes=16,22,32,48 +SmallDefault=16 +SmallSizes=16 +PanelDefault=32 +PanelSizes=16,22,32,48,64,72,96,128 + +# Directory list +Directories=16x16/actions,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/mimetypes,16x16/places,16x16/status,22x22/actions,22x22/apps,22x22/categories,22x22/devices,22x22/emblems,22x22/emotes,22x22/mimetypes,22x22/places,22x22/status,24x24/actions,24x24/apps,24x24/categories,24x24/devices,24x24/emblems,24x24/emotes,24x24/mimetypes,24x24/places,24x24/status,32x32/actions,32x32/apps,32x32/categories,32x32/devices,32x32/emblems,32x32/emotes,32x32/mimetypes,32x32/places,32x32/status,48x48/actions,48x48/apps,48x48/categories,48x48/devices,48x48/emblems,48x48/emotes,48x48/mimetypes,48x48/places,48x48/status,64x64/actions,64x64/apps,64x64/categories,64x64/devices,64x64/emblems,64x64/emotes,64x64/mimetypes,64x64/places,64x64/status,72x72/actions,72x72/apps,72x72/categories,72x72/devices,72x72/emblems,72x72/emotes,72x72/mimetypes,72x72/places,72x72/status,96x96/actions,96x96/apps,96x96/categories,96x96/devices,96x96/emblems,96x96/emotes,96x96/mimetypes,96x96/places,96x96/status,128x128/actions,128x128/apps,128x128/categories,128x128/devices,128x128/emblems,128x128/emotes,128x128/mimetypes,128x128/places,128x128/status,scalable/actions,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/mimetypes,scalable/places,scalable/status + +[16x16/actions] +Size=16 +Context=Actions +Type=Fixed + +[16x16/apps] +Size=16 +Context=Applications +Type=Fixed + +[16x16/categories] +Size=16 +Context=Categories +Type=Fixed + +[16x16/devices] +Size=16 +Context=Devices +Type=Fixed + +[16x16/emblems] +Size=16 +Context=Emblems +Type=Fixed + +[16x16/emotes] +Size=16 +Context=Emotes +Type=Fixed + +[16x16/mimetypes] +Size=16 +Context=MimeTypes +Type=Fixed + +[16x16/places] +Size=16 +Context=Places +Type=Fixed + +[16x16/status] +Size=16 +Context=Status +Type=Fixed + +[22x22/actions] +Size=22 +Context=Actions +Type=Fixed + +[22x22/apps] +Size=22 +Context=Applications +Type=Fixed + +[22x22/categories] +Size=22 +Context=Categories +Type=Fixed + +[22x22/devices] +Size=22 +Context=Devices +Type=Fixed + +[22x22/emblems] +Size=22 +Context=Emblems +Type=Fixed + +[22x22/emotes] +Size=22 +Context=Emotes +Type=Fixed + +[22x22/mimetypes] +Size=22 +Context=MimeTypes +Type=Fixed + +[22x22/places] +Size=22 +Context=Places +Type=Fixed + +[22x22/status] +Size=22 +Context=Status +Type=Fixed + +[24x24/actions] +Size=24 +Context=Actions +Type=Fixed + +[24x24/apps] +Size=24 +Context=Applications +Type=Fixed + +[24x24/categories] +Size=24 +Context=Categories +Type=Fixed + +[24x24/devices] +Size=24 +Context=Devices +Type=Fixed + +[24x24/emblems] +Size=24 +Context=Emblems +Type=Fixed + +[24x24/emotes] +Size=24 +Context=Emotes +Type=Fixed + +[24x24/mimetypes] +Size=24 +Context=MimeTypes +Type=Fixed + +[24x24/places] +Size=24 +Context=Places +Type=Fixed + +[24x24/status] +Size=24 +Context=Status +Type=Fixed + +[32x32/actions] +Size=32 +Context=Actions +Type=Fixed + +[32x32/apps] +Size=32 +Context=Applications +Type=Fixed + +[32x32/categories] +Size=32 +Context=Categories +Type=Fixed + +[32x32/devices] +Size=32 +Context=Devices +Type=Fixed + +[32x32/emblems] +Size=32 +Context=Emblems +Type=Fixed + +[32x32/emotes] +Size=32 +Context=Emotes +Type=Fixed + +[32x32/mimetypes] +Size=32 +Context=MimeTypes +Type=Fixed + +[32x32/places] +Size=32 +Context=Places +Type=Fixed + +[32x32/status] +Size=32 +Context=Status +Type=Fixed + +[48x48/actions] +Size=48 +Context=Actions +Type=Fixed + +[48x48/apps] +Size=48 +Context=Applications +Type=Fixed + +[48x48/categories] +Size=48 +Context=Categories +Type=Fixed + +[48x48/devices] +Size=48 +Context=Devices +Type=Fixed + +[48x48/emblems] +Size=48 +Context=Emblems +Type=Fixed + +[48x48/emotes] +Size=48 +Context=Emotes +Type=Fixed + +[48x48/mimetypes] +Size=48 +Context=MimeTypes +Type=Fixed + +[48x48/places] +Size=48 +Context=Places +Type=Fixed + +[48x48/status] +Size=48 +Context=Status +Type=Fixed + +[64x64/actions] +Size=64 +Context=Actions +Type=Fixed + +[64x64/apps] +Size=64 +Context=Applications +Type=Fixed + +[64x64/categories] +Size=64 +Context=Categories +Type=Fixed + +[64x64/devices] +Size=64 +Context=Devices +Type=Fixed + +[64x64/emblems] +Size=64 +Context=Emblems +Type=Fixed + +[64x64/emotes] +Size=64 +Context=Emotes +Type=Fixed + +[64x64/mimetypes] +Size=64 +Context=MimeTypes +Type=Fixed + +[64x64/places] +Size=64 +Context=Places +Type=Fixed + +[64x64/status] +Size=64 +Context=Status +Type=Fixed + +[72x72/actions] +Size=72 +Context=Actions +Type=Fixed + +[72x72/apps] +Size=72 +Context=Applications +Type=Fixed + +[72x72/categories] +Size=72 +Context=Categories +Type=Fixed + +[72x72/devices] +Size=72 +Context=Devices +Type=Fixed + +[72x72/emblems] +Size=72 +Context=Emblems +Type=Fixed + +[72x72/emotes] +Size=72 +Context=Emotes +Type=Fixed + +[72x72/mimetypes] +Size=72 +Context=MimeTypes +Type=Fixed + +[72x72/places] +Size=72 +Context=Places +Type=Fixed + +[72x72/status] +Size=72 +Context=Status +Type=Fixed + +[96x96/actions] +Size=96 +Context=Actions +Type=Fixed + +[96x96/apps] +Size=96 +Context=Applications +Type=Fixed + +[96x96/categories] +Size=96 +Context=Categories +Type=Fixed + +[96x96/devices] +Size=96 +Context=Devices +Type=Fixed + +[96x96/emblems] +Size=96 +Context=Emblems +Type=Fixed + +[96x96/emotes] +Size=96 +Context=Emotes +Type=Fixed + +[96x96/mimetypes] +Size=96 +Context=MimeTypes +Type=Fixed + +[96x96/places] +Size=96 +Context=Places +Type=Fixed + +[96x96/status] +Size=96 +Context=Status +Type=Fixed + +[128x128/actions] +Size=128 +Context=Actions +Type=Fixed + +[128x128/apps] +Size=128 +Context=Applications +Type=Fixed + +[128x128/categories] +Size=128 +Context=Categories +Type=Fixed + +[128x128/devices] +Size=128 +Context=Devices +Type=Fixed + +[128x128/emblems] +Size=128 +Context=Emblems +Type=Fixed + +[128x128/emotes] +Size=128 +Context=Emotes +Type=Fixed + +[128x128/mimetypes] +Size=128 +Context=MimeTypes +Type=Fixed + +[128x128/places] +Size=128 +Context=Places +Type=Fixed + +[128x128/status] +Size=128 +Context=Status +Type=Fixed + +[scalable/actions] +Size=48 +Context=Actions +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/apps] +Size=48 +Context=Applications +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/categories] +Size=48 +Context=Categories +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/devices] +Size=48 +Context=Devices +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/emblems] +Size=48 +Context=Emblems +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/emotes] +Size=48 +Context=Emotes +Type=Scalable +Minsize=32 +MaxSize=256 + +[scalable/mimetypes] +Size=48 +Context=MimeTypes +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/places] +Size=48 +Context=Places +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/status] +Size=48 +Context=Status +Type=Scalable +MinSize=32 +MaxSize=256 diff --git a/tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg b/tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg new file mode 100644 index 0000000..4cb14f8 --- /dev/null +++ b/tests/auto/qicon/icons/testtheme/scalable/actions/svg-only.svg @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + New Appointment + + + appointment + new + meeting + rvsp + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png b/tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png new file mode 100644 index 0000000..2098cfd Binary files /dev/null and b/tests/auto/qicon/icons/themeparent/16x16/actions/address-book-new.png differ diff --git a/tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png b/tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png new file mode 100644 index 0000000..18b7c67 Binary files /dev/null and b/tests/auto/qicon/icons/themeparent/16x16/actions/appointment-new.png differ diff --git a/tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png b/tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png new file mode 100644 index 0000000..fad446c Binary files /dev/null and b/tests/auto/qicon/icons/themeparent/22x22/actions/address-book-new.png differ diff --git a/tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png b/tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png new file mode 100644 index 0000000..d676ffd Binary files /dev/null and b/tests/auto/qicon/icons/themeparent/22x22/actions/appointment-new.png differ diff --git a/tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png b/tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png new file mode 100644 index 0000000..420139d Binary files /dev/null and b/tests/auto/qicon/icons/themeparent/32x32/actions/address-book-new.png differ diff --git a/tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png b/tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png new file mode 100644 index 0000000..85daef3 Binary files /dev/null and b/tests/auto/qicon/icons/themeparent/32x32/actions/appointment-new.png differ diff --git a/tests/auto/qicon/icons/themeparent/index.theme b/tests/auto/qicon/icons/themeparent/index.theme new file mode 100644 index 0000000..e536a0b --- /dev/null +++ b/tests/auto/qicon/icons/themeparent/index.theme @@ -0,0 +1,492 @@ +[Icon Theme] +_Name=Test +_Comment=Test Theme +Inherits=gnome,crystalsvg +Example=x-directory-normal + +# KDE Specific Stuff +DisplayDepth=32 +LinkOverlay=link_overlay +LockOverlay=lock_overlay +ZipOverlay=zip_overlay +DesktopDefault=48 +DesktopSizes=16,22,32,48,64,72,96,128 +ToolbarDefault=22 +ToolbarSizes=16,22,32,48 +MainToolbarDefault=22 +MainToolbarSizes=16,22,32,48 +SmallDefault=16 +SmallSizes=16 +PanelDefault=32 +PanelSizes=16,22,32,48,64,72,96,128 + +# Directory list +Directories=16x16/actions,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/mimetypes,16x16/places,16x16/status,22x22/actions,22x22/apps,22x22/categories,22x22/devices,22x22/emblems,22x22/emotes,22x22/mimetypes,22x22/places,22x22/status,24x24/actions,24x24/apps,24x24/categories,24x24/devices,24x24/emblems,24x24/emotes,24x24/mimetypes,24x24/places,24x24/status,32x32/actions,32x32/apps,32x32/categories,32x32/devices,32x32/emblems,32x32/emotes,32x32/mimetypes,32x32/places,32x32/status,48x48/actions,48x48/apps,48x48/categories,48x48/devices,48x48/emblems,48x48/emotes,48x48/mimetypes,48x48/places,48x48/status,64x64/actions,64x64/apps,64x64/categories,64x64/devices,64x64/emblems,64x64/emotes,64x64/mimetypes,64x64/places,64x64/status,72x72/actions,72x72/apps,72x72/categories,72x72/devices,72x72/emblems,72x72/emotes,72x72/mimetypes,72x72/places,72x72/status,96x96/actions,96x96/apps,96x96/categories,96x96/devices,96x96/emblems,96x96/emotes,96x96/mimetypes,96x96/places,96x96/status,128x128/actions,128x128/apps,128x128/categories,128x128/devices,128x128/emblems,128x128/emotes,128x128/mimetypes,128x128/places,128x128/status,scalable/actions,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/mimetypes,scalable/places,scalable/status + +[16x16/actions] +Size=16 +Context=Actions +Type=Fixed + +[16x16/apps] +Size=16 +Context=Applications +Type=Fixed + +[16x16/categories] +Size=16 +Context=Categories +Type=Fixed + +[16x16/devices] +Size=16 +Context=Devices +Type=Fixed + +[16x16/emblems] +Size=16 +Context=Emblems +Type=Fixed + +[16x16/emotes] +Size=16 +Context=Emotes +Type=Fixed + +[16x16/mimetypes] +Size=16 +Context=MimeTypes +Type=Fixed + +[16x16/places] +Size=16 +Context=Places +Type=Fixed + +[16x16/status] +Size=16 +Context=Status +Type=Fixed + +[22x22/actions] +Size=22 +Context=Actions +Type=Fixed + +[22x22/apps] +Size=22 +Context=Applications +Type=Fixed + +[22x22/categories] +Size=22 +Context=Categories +Type=Fixed + +[22x22/devices] +Size=22 +Context=Devices +Type=Fixed + +[22x22/emblems] +Size=22 +Context=Emblems +Type=Fixed + +[22x22/emotes] +Size=22 +Context=Emotes +Type=Fixed + +[22x22/mimetypes] +Size=22 +Context=MimeTypes +Type=Fixed + +[22x22/places] +Size=22 +Context=Places +Type=Fixed + +[22x22/status] +Size=22 +Context=Status +Type=Fixed + +[24x24/actions] +Size=24 +Context=Actions +Type=Fixed + +[24x24/apps] +Size=24 +Context=Applications +Type=Fixed + +[24x24/categories] +Size=24 +Context=Categories +Type=Fixed + +[24x24/devices] +Size=24 +Context=Devices +Type=Fixed + +[24x24/emblems] +Size=24 +Context=Emblems +Type=Fixed + +[24x24/emotes] +Size=24 +Context=Emotes +Type=Fixed + +[24x24/mimetypes] +Size=24 +Context=MimeTypes +Type=Fixed + +[24x24/places] +Size=24 +Context=Places +Type=Fixed + +[24x24/status] +Size=24 +Context=Status +Type=Fixed + +[32x32/actions] +Size=32 +Context=Actions +Type=Fixed + +[32x32/apps] +Size=32 +Context=Applications +Type=Fixed + +[32x32/categories] +Size=32 +Context=Categories +Type=Fixed + +[32x32/devices] +Size=32 +Context=Devices +Type=Fixed + +[32x32/emblems] +Size=32 +Context=Emblems +Type=Fixed + +[32x32/emotes] +Size=32 +Context=Emotes +Type=Fixed + +[32x32/mimetypes] +Size=32 +Context=MimeTypes +Type=Fixed + +[32x32/places] +Size=32 +Context=Places +Type=Fixed + +[32x32/status] +Size=32 +Context=Status +Type=Fixed + +[48x48/actions] +Size=48 +Context=Actions +Type=Fixed + +[48x48/apps] +Size=48 +Context=Applications +Type=Fixed + +[48x48/categories] +Size=48 +Context=Categories +Type=Fixed + +[48x48/devices] +Size=48 +Context=Devices +Type=Fixed + +[48x48/emblems] +Size=48 +Context=Emblems +Type=Fixed + +[48x48/emotes] +Size=48 +Context=Emotes +Type=Fixed + +[48x48/mimetypes] +Size=48 +Context=MimeTypes +Type=Fixed + +[48x48/places] +Size=48 +Context=Places +Type=Fixed + +[48x48/status] +Size=48 +Context=Status +Type=Fixed + +[64x64/actions] +Size=64 +Context=Actions +Type=Fixed + +[64x64/apps] +Size=64 +Context=Applications +Type=Fixed + +[64x64/categories] +Size=64 +Context=Categories +Type=Fixed + +[64x64/devices] +Size=64 +Context=Devices +Type=Fixed + +[64x64/emblems] +Size=64 +Context=Emblems +Type=Fixed + +[64x64/emotes] +Size=64 +Context=Emotes +Type=Fixed + +[64x64/mimetypes] +Size=64 +Context=MimeTypes +Type=Fixed + +[64x64/places] +Size=64 +Context=Places +Type=Fixed + +[64x64/status] +Size=64 +Context=Status +Type=Fixed + +[72x72/actions] +Size=72 +Context=Actions +Type=Fixed + +[72x72/apps] +Size=72 +Context=Applications +Type=Fixed + +[72x72/categories] +Size=72 +Context=Categories +Type=Fixed + +[72x72/devices] +Size=72 +Context=Devices +Type=Fixed + +[72x72/emblems] +Size=72 +Context=Emblems +Type=Fixed + +[72x72/emotes] +Size=72 +Context=Emotes +Type=Fixed + +[72x72/mimetypes] +Size=72 +Context=MimeTypes +Type=Fixed + +[72x72/places] +Size=72 +Context=Places +Type=Fixed + +[72x72/status] +Size=72 +Context=Status +Type=Fixed + +[96x96/actions] +Size=96 +Context=Actions +Type=Fixed + +[96x96/apps] +Size=96 +Context=Applications +Type=Fixed + +[96x96/categories] +Size=96 +Context=Categories +Type=Fixed + +[96x96/devices] +Size=96 +Context=Devices +Type=Fixed + +[96x96/emblems] +Size=96 +Context=Emblems +Type=Fixed + +[96x96/emotes] +Size=96 +Context=Emotes +Type=Fixed + +[96x96/mimetypes] +Size=96 +Context=MimeTypes +Type=Fixed + +[96x96/places] +Size=96 +Context=Places +Type=Fixed + +[96x96/status] +Size=96 +Context=Status +Type=Fixed + +[128x128/actions] +Size=128 +Context=Actions +Type=Fixed + +[128x128/apps] +Size=128 +Context=Applications +Type=Fixed + +[128x128/categories] +Size=128 +Context=Categories +Type=Fixed + +[128x128/devices] +Size=128 +Context=Devices +Type=Fixed + +[128x128/emblems] +Size=128 +Context=Emblems +Type=Fixed + +[128x128/emotes] +Size=128 +Context=Emotes +Type=Fixed + +[128x128/mimetypes] +Size=128 +Context=MimeTypes +Type=Fixed + +[128x128/places] +Size=128 +Context=Places +Type=Fixed + +[128x128/status] +Size=128 +Context=Status +Type=Fixed + +[scalable/actions] +Size=48 +Context=Actions +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/apps] +Size=48 +Context=Applications +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/categories] +Size=48 +Context=Categories +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/devices] +Size=48 +Context=Devices +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/emblems] +Size=48 +Context=Emblems +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/emotes] +Size=48 +Context=Emotes +Type=Scalable +Minsize=32 +MaxSize=256 + +[scalable/mimetypes] +Size=48 +Context=MimeTypes +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/places] +Size=48 +Context=Places +Type=Scalable +MinSize=32 +MaxSize=256 + +[scalable/status] +Size=48 +Context=Status +Type=Scalable +MinSize=32 +MaxSize=256 diff --git a/tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg b/tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg new file mode 100644 index 0000000..600a82c --- /dev/null +++ b/tests/auto/qicon/icons/themeparent/scalable/actions/address-book-new.svg @@ -0,0 +1,389 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Addess Book - New + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + address + contact + book + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg b/tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg new file mode 100644 index 0000000..4cb14f8 --- /dev/null +++ b/tests/auto/qicon/icons/themeparent/scalable/actions/appointment-new.svg @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + New Appointment + + + appointment + new + meeting + rvsp + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/qicon/tst_qicon.cpp b/tests/auto/qicon/tst_qicon.cpp index a266c16..545ca09 100644 --- a/tests/auto/qicon/tst_qicon.cpp +++ b/tests/auto/qicon/tst_qicon.cpp @@ -74,6 +74,7 @@ private slots: void availableSizes(); void streamAvailableSizes_data(); void streamAvailableSizes(); + void fromTheme(); void task184901_badCache(); void task223279_inconsistentAddFile(); @@ -605,6 +606,72 @@ void tst_QIcon::task184901_badCache() QVERIFY( icon.pixmap(32, QIcon::Normal).toImage() == icon.pixmap(32, QIcon::Disabled).toImage() ); } +void tst_QIcon::fromTheme() +{ + const QString prefix = QLatin1String(SRCDIR) + QLatin1String("/"); + QString searchPath = prefix + QLatin1String("/icons"); + QIcon::setThemeSearchPaths(QStringList() << searchPath); + QVERIFY(QIcon::themeSearchPaths().size() == 1); + QCOMPARE(searchPath, QIcon::themeSearchPaths()[0]); + + QString themeName("testtheme"); + QIcon::setThemeName(themeName); + QCOMPARE(QIcon::themeName(), themeName); + + // Test normal icon + QIcon appointmentIcon = QIcon::fromTheme("appointment-new"); + QVERIFY(!appointmentIcon.isNull()); + QVERIFY(!appointmentIcon.availableSizes(QIcon::Normal, QIcon::Off).isEmpty()); + QVERIFY(appointmentIcon.availableSizes().contains(QSize(16, 16))); + QVERIFY(appointmentIcon.availableSizes().contains(QSize(32, 32))); + QVERIFY(appointmentIcon.availableSizes().contains(QSize(22, 22))); + + // Test icon from parent theme + QIcon abIcon = QIcon::fromTheme("address-book-new"); + QVERIFY(!abIcon.isNull()); + QVERIFY(QIcon::hasThemeIcon("address-book-new")); + QVERIFY(!abIcon.availableSizes().isEmpty()); + + // Test non existing icon + QIcon noIcon = QIcon::fromTheme("broken-icon"); + QVERIFY(noIcon.isNull()); + QVERIFY(!QIcon::hasThemeIcon("broken-icon")); + + // Test non existing icon with fallback + noIcon = QIcon::fromTheme("broken-icon", abIcon); + QVERIFY(noIcon.cacheKey() == abIcon.cacheKey()); + + // Test svg-only icon + noIcon = QIcon::fromTheme("svg-icon", abIcon); + QVERIFY(!noIcon.availableSizes().isEmpty()); + + QByteArray ba; + // write to QByteArray + { + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + stream << abIcon; + } + + // read from QByteArray + { + QBuffer buffer(&ba); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + QIcon i; + stream >> i; + QCOMPARE(i.isNull(), abIcon.isNull()); + QCOMPARE(i.availableSizes(), abIcon.availableSizes()); + } + + // Make sure setting the theme name clears the state + QIcon::setThemeName(""); + abIcon = QIcon::fromTheme("address-book-new"); + QVERIFY(abIcon.isNull()); +} + + void tst_QIcon::task223279_inconsistentAddFile() { QIcon icon1; diff --git a/tools/assistant/compat/mainwindow.cpp b/tools/assistant/compat/mainwindow.cpp index 670b144..9d308df 100644 --- a/tools/assistant/compat/mainwindow.cpp +++ b/tools/assistant/compat/mainwindow.cpp @@ -140,6 +140,16 @@ MainWindow::MainWindow() ui.actionZoomIn->setIcon(QIcon(MacIconPath + QLatin1String("/zoomin.png"))); ui.actionSyncToc->setIcon(QIcon(MacIconPath + QLatin1String("/synctoc.png"))); ui.actionHelpWhatsThis->setIcon(QIcon(MacIconPath + QLatin1String("/whatsthis.png"))); +#elif defined(Q_WS_X11) + ui.actionGoNext->setIcon(QIcon::fromTheme("go-next" , ui.actionGoNext->icon())); + ui.actionGoPrevious->setIcon(QIcon::fromTheme("go-previous" , ui.actionGoPrevious->icon())); + ui.actionGoHome->setIcon(QIcon::fromTheme("user-home" , ui.actionGoHome->icon())); + ui.actionEditCopy->setIcon(QIcon::fromTheme("edit-copy" , ui.actionEditCopy->icon())); + ui.actionEditFind->setIcon(QIcon::fromTheme("edit-find" , ui.actionEditFind->icon())); + ui.actionFilePrint->setIcon(QIcon::fromTheme("document-print" , ui.actionFilePrint->icon())); + ui.actionZoomOut->setIcon(QIcon::fromTheme("zoom-out" , ui.actionZoomOut->icon())); + ui.actionZoomIn->setIcon(QIcon::fromTheme("zoom-in" , ui.actionZoomIn->icon())); + ui.actionSyncToc->setIcon(QIcon::fromTheme("view-refresh" , ui.actionSyncToc->icon())); #endif } diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index bc73b80..a0d4fbf 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -545,6 +545,19 @@ void MainWindow::setupActions() m_aboutAction = menu->addAction(tr("About..."), this, SLOT(showAboutDialog())); m_aboutAction->setMenuRole(QAction::AboutRole); +#ifdef Q_WS_X11 + m_backAction->setIcon(QIcon::fromTheme("go-previous" , m_backAction->icon())); + m_nextAction->setIcon(QIcon::fromTheme("go-next" , m_nextAction->icon())); + m_zoomInAction->setIcon(QIcon::fromTheme("zoom-in" , m_zoomInAction->icon())); + m_zoomOutAction->setIcon(QIcon::fromTheme("zoom-out" , m_zoomOutAction->icon())); + m_resetZoomAction->setIcon(QIcon::fromTheme("zoom-original" , m_resetZoomAction->icon())); + m_syncAction->setIcon(QIcon::fromTheme("view-refresh" , m_syncAction->icon())); + m_copyAction->setIcon(QIcon::fromTheme("edit-copy" , m_copyAction->icon())); + m_findAction->setIcon(QIcon::fromTheme("edit-find" , m_findAction->icon())); + m_homeAction->setIcon(QIcon::fromTheme("go-home" , m_homeAction->icon())); + m_printAction->setIcon(QIcon::fromTheme("document-print" , m_printAction->icon())); +#endif + QToolBar *navigationBar = addToolBar(tr("Navigation Toolbar")); navigationBar->setObjectName(QLatin1String("NavigationToolBar")); navigationBar->addAction(m_backAction); diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp b/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp index ff0c3c6..cf838a2 100644 --- a/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp +++ b/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp @@ -72,8 +72,9 @@ void BuddyEditorPlugin::initialize(QDesignerFormEditorInterface *core) m_action = new QAction(tr("Edit Buddies"), this); m_action->setObjectName(QLatin1String("__qt_edit_buddies_action")); - m_action->setIcon(QIcon(core->resourceLocation() + QLatin1String("/buddytool.png"))); - m_action->setIcon(QIcon(core->resourceLocation() + QLatin1String("/buddytool.png"))); + QIcon buddyIcon = QIcon::fromTheme("designer-edit-buddy", + QIcon(core->resourceLocation() + QLatin1String("/buddytool.png"))); + m_action->setIcon(buddyIcon); m_action->setEnabled(false); setParent(core); diff --git a/tools/designer/src/components/formeditor/formwindowmanager.cpp b/tools/designer/src/components/formeditor/formwindowmanager.cpp index 993bae9..a2a0a40 100644 --- a/tools/designer/src/components/formeditor/formwindowmanager.cpp +++ b/tools/designer/src/components/formeditor/formwindowmanager.cpp @@ -443,7 +443,8 @@ void FormWindowManager::setupActions() m_actionVerticalLayout->setEnabled(false); connect(m_actionVerticalLayout, SIGNAL(triggered()), this, SLOT(createLayout())); - QAction *actionFormLayout = new QAction(createIconSet(QLatin1String("editform.png")), tr("Lay Out in a &Form Layout"), this); + QIcon formIcon = QIcon::fromTheme("designer-form-layout", createIconSet(QLatin1String("editform.png"))); + QAction *actionFormLayout = new QAction(formIcon, tr("Lay Out in a &Form Layout"), this); actionFormLayout->setObjectName(QLatin1String("__qt_form_layout_action")); actionFormLayout->setShortcut(Qt::CTRL + Qt::Key_6); actionFormLayout->setStatusTip(tr("Lays out the selected widgets in a form layout")); @@ -510,15 +511,30 @@ void FormWindowManager::setupActions() m_actionUndo = m_undoGroup->createUndoAction(this); m_actionUndo->setEnabled(false); - m_actionUndo->setIcon(createIconSet(QLatin1String("undo.png"))); + + m_actionUndo->setIcon(QIcon::fromTheme("edit-undo", createIconSet(QLatin1String("undo.png")))); m_actionRedo = m_undoGroup->createRedoAction(this); m_actionRedo->setEnabled(false); - m_actionRedo->setIcon(createIconSet(QLatin1String("redo.png"))); + m_actionRedo->setIcon(QIcon::fromTheme("edit-redo", createIconSet(QLatin1String("redo.png")))); m_actionShowFormWindowSettingsDialog = new QAction(tr("Form &Settings..."), this); m_actionShowFormWindowSettingsDialog->setObjectName(QLatin1String("__qt_form_settings_action")); connect(m_actionShowFormWindowSettingsDialog, SIGNAL(triggered()), this, SLOT(slotActionShowFormWindowSettingsDialog())); m_actionShowFormWindowSettingsDialog->setEnabled(false); + + + m_actionCopy->setIcon(QIcon::fromTheme("edit-copy", m_actionCopy->icon())); + m_actionCut->setIcon(QIcon::fromTheme("edit-cut", m_actionCut->icon())); + m_actionPaste->setIcon(QIcon::fromTheme("edit-paste", m_actionPaste->icon())); + + // These do not currently exist, but will allow theme authors to fill in the gaps + m_actionBreakLayout->setIcon(QIcon::fromTheme("designer-break-layout", m_actionBreakLayout->icon())); + m_actionGridLayout->setIcon(QIcon::fromTheme("designer-grid-layout", m_actionGridLayout->icon())); + m_actionHorizontalLayout->setIcon(QIcon::fromTheme("designer-horizontal-layout", m_actionHorizontalLayout->icon())); + m_actionVerticalLayout->setIcon(QIcon::fromTheme("designer-vertical-layout", m_actionVerticalLayout->icon())); + m_actionSplitHorizontal->setIcon(QIcon::fromTheme("designer-split-horizontal", m_actionSplitHorizontal->icon())); + m_actionSplitVertical->setIcon(QIcon::fromTheme("designer-split-vertical", m_actionSplitVertical->icon())); + m_actionAdjustSize->setIcon(QIcon::fromTheme("designer-adjust-size", m_actionAdjustSize->icon())); } void FormWindowManager::slotActionCutActivated() diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp index e664ae7..a113041 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp @@ -72,7 +72,8 @@ void SignalSlotEditorPlugin::initialize(QDesignerFormEditorInterface *core) m_action = new QAction(tr("Edit Signals/Slots"), this); m_action->setObjectName(QLatin1String("__qt_edit_signals_slots_action")); m_action->setShortcut(tr("F4")); - QIcon icon(QIcon(core->resourceLocation() + QLatin1String("/signalslottool.png"))); + QIcon icon = QIcon::fromTheme("designer-edit-signals", + QIcon(core->resourceLocation() + QLatin1String("/signalslottool.png"))); m_action->setIcon(icon); m_action->setEnabled(false); diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp b/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp index 9b051c9..ddddd08 100644 --- a/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp +++ b/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp @@ -72,7 +72,9 @@ void TabOrderEditorPlugin::initialize(QDesignerFormEditorInterface *core) m_action = new QAction(tr("Edit Tab Order"), this); m_action->setObjectName(QLatin1String("_qt_edit_tab_order_action")); - m_action->setIcon(QIcon(core->resourceLocation() + QLatin1String("/tabordertool.png"))); + QIcon icon = QIcon::fromTheme("designer-edit-tabs", + QIcon(core->resourceLocation() + QLatin1String("/tabordertool.png"))); + m_action->setIcon(icon); m_action->setEnabled(false); setParent(core); diff --git a/tools/designer/src/designer/qdesigner_actions.cpp b/tools/designer/src/designer/qdesigner_actions.cpp index c671386..567a13e 100644 --- a/tools/designer/src/designer/qdesigner_actions.cpp +++ b/tools/designer/src/designer/qdesigner_actions.cpp @@ -200,6 +200,10 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench) #endif m_previewManager(0) { + m_newFormAction->setIcon(QIcon::fromTheme("document-new", m_newFormAction->icon())); + m_openFormAction->setIcon(QIcon::fromTheme("document-open", m_openFormAction->icon())); + m_saveFormAction->setIcon(QIcon::fromTheme("document-save", m_saveFormAction->icon())); + Q_ASSERT(m_core != 0); qdesigner_internal::QDesignerFormWindowManager *ifwm = qobject_cast(m_core->formWindowManager()); Q_ASSERT(ifwm); @@ -323,7 +327,8 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench) shortcuts.append(QKeySequence(Qt::Key_Escape)); #endif m_editWidgetsAction->setShortcuts(shortcuts); - m_editWidgetsAction->setIcon(QIcon(m_core->resourceLocation() + QLatin1String("/widgettool.png"))); + QIcon fallback(m_core->resourceLocation() + QLatin1String("/widgettool.png")); + m_editWidgetsAction->setIcon(QIcon::fromTheme("designer-edit-widget", fallback)); connect(m_editWidgetsAction, SIGNAL(triggered()), this, SLOT(editWidgetsSlot())); m_editWidgetsAction->setChecked(true); m_editWidgetsAction->setEnabled(false); diff --git a/tools/designer/src/lib/shared/actioneditor.cpp b/tools/designer/src/lib/shared/actioneditor.cpp index 1a236d6..a931b8a 100644 --- a/tools/designer/src/lib/shared/actioneditor.cpp +++ b/tools/designer/src/lib/shared/actioneditor.cpp @@ -147,7 +147,8 @@ ActionEditor::ActionEditor(QDesignerFormEditorInterface *core, QWidget *parent, toolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); l->addWidget(toolbar); // edit actions - m_actionNew->setIcon(createIconSet(QLatin1String("filenew.png"))); + QIcon documentNewIcon = QIcon::fromTheme("document-new", createIconSet(QLatin1String("filenew.png"))); + m_actionNew->setIcon(documentNewIcon); m_actionNew->setEnabled(false); connect(m_actionNew, SIGNAL(triggered()), this, SLOT(slotNewAction())); toolbar->addAction(m_actionNew); @@ -156,15 +157,18 @@ ActionEditor::ActionEditor(QDesignerFormEditorInterface *core, QWidget *parent, m_actionCut->setEnabled(false); connect(m_actionCut, SIGNAL(triggered()), this, SLOT(slotCut())); - m_actionCut->setIcon(createIconSet(QLatin1String("editcut.png"))); + QIcon editCutIcon = QIcon::fromTheme("edit-cut", createIconSet(QLatin1String("editcut.png"))); + m_actionCut->setIcon(editCutIcon); m_actionCopy->setEnabled(false); connect(m_actionCopy, SIGNAL(triggered()), this, SLOT(slotCopy())); - m_actionCopy->setIcon(createIconSet(QLatin1String("editcopy.png"))); + QIcon editCopyIcon = QIcon::fromTheme("edit-copy", createIconSet(QLatin1String("editcopy.png"))); + m_actionCopy->setIcon(editCopyIcon); toolbar->addAction(m_actionCopy); connect(m_actionPaste, SIGNAL(triggered()), this, SLOT(slotPaste())); - m_actionPaste->setIcon(createIconSet(QLatin1String("editpaste.png"))); + QIcon editPasteIcon = QIcon::fromTheme("edit-paste", createIconSet(QLatin1String("editpaste.png"))); + m_actionPaste->setIcon(editPasteIcon); toolbar->addAction(m_actionPaste); m_actionEdit->setEnabled(false); @@ -172,7 +176,8 @@ ActionEditor::ActionEditor(QDesignerFormEditorInterface *core, QWidget *parent, connect(m_actionNavigateToSlot, SIGNAL(triggered()), this, SLOT(navigateToSlotCurrentAction())); - m_actionDelete->setIcon(createIconSet(QLatin1String("editdelete.png"))); + QIcon editDeleteIcon = QIcon::fromTheme("edit-delete", createIconSet(QLatin1String("editdelete.png"))); + m_actionDelete->setIcon(editDeleteIcon); m_actionDelete->setEnabled(false); connect(m_actionDelete, SIGNAL(triggered()), this, SLOT(slotDelete())); toolbar->addAction(m_actionDelete); @@ -243,7 +248,8 @@ QToolButton *ActionEditor::createConfigureMenuButton(const QString &t, QMenu **p { QToolButton *configureButton = new QToolButton; QAction *configureAction = new QAction(t, configureButton); - configureAction->setIcon(createIconSet(QLatin1String("configure.png"))); + QIcon configureIcon = QIcon::fromTheme("document-properties", createIconSet(QLatin1String("configure.png"))); + configureAction->setIcon(configureIcon); QMenu *configureMenu = new QMenu; configureAction->setMenu(configureMenu); configureButton->setDefaultAction(configureAction); diff --git a/tools/designer/src/lib/shared/qtresourceview.cpp b/tools/designer/src/lib/shared/qtresourceview.cpp index 40be3e6..f55f7ae 100644 --- a/tools/designer/src/lib/shared/qtresourceview.cpp +++ b/tools/designer/src/lib/shared/qtresourceview.cpp @@ -582,17 +582,21 @@ QtResourceView::QtResourceView(QDesignerFormEditorInterface *core, QWidget *pare { d_ptr->q_ptr = this; - d_ptr->m_editResourcesAction = new QAction(qdesigner_internal::createIconSet(QLatin1String("edit.png")), tr("Edit Resources..."), this); + QIcon editIcon = QIcon::fromTheme("document-properties", qdesigner_internal::createIconSet(QLatin1String("edit.png"))); + d_ptr->m_editResourcesAction = new QAction(editIcon, tr("Edit Resources..."), this); d_ptr->m_toolBar->addAction(d_ptr->m_editResourcesAction); connect(d_ptr->m_editResourcesAction, SIGNAL(triggered()), this, SLOT(slotEditResources())); d_ptr->m_editResourcesAction->setEnabled(false); - d_ptr->m_reloadResourcesAction = new QAction(qdesigner_internal::createIconSet(QLatin1String("reload.png")), tr("Reload"), this); + QIcon refreshIcon = QIcon::fromTheme("view-refresh", qdesigner_internal::createIconSet(QLatin1String("reload.png"))); + d_ptr->m_reloadResourcesAction = new QAction(refreshIcon, tr("Reload"), this); + d_ptr->m_toolBar->addAction(d_ptr->m_reloadResourcesAction); connect(d_ptr->m_reloadResourcesAction, SIGNAL(triggered()), this, SLOT(slotReloadResources())); d_ptr->m_reloadResourcesAction->setEnabled(false); - d_ptr->m_copyResourcePathAction = new QAction(qdesigner_internal::createIconSet(QLatin1String("editcopy.png")), tr("Copy Path"), this); + QIcon copyIcon = QIcon::fromTheme("edit-copy", qdesigner_internal::createIconSet(QLatin1String("editcopy.png"))); + d_ptr->m_copyResourcePathAction = new QAction(copyIcon, tr("Copy Path"), this); connect(d_ptr->m_copyResourcePathAction, SIGNAL(triggered()), this, SLOT(slotCopyResourcePath())); d_ptr->m_copyResourcePathAction->setEnabled(false); -- cgit v0.12