From 71d7e1a6931b5edfa3fd15de5ad82bbca25d1426 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Tue, 23 Sep 2008 00:33:33 +0200 Subject: [PATCH] Add Icon and IconLoader The former is a very thin wrapper around QIcon that will use the latter to locate an icon in the current theme (harcoded to Oxygen for now), either in the file system or in a resource. This will allow us to make icon resources optional, and also to seamlessly integrate with KDE's icon theming later. Note that we don't provide proper theming support now, as IconLoader is _very_ rudimentary for now and assumes Oxygen to be present. --- src/qtui/mainwin.cpp | 2 +- src/qtui/qtuiapplication.cpp | 6 ++ src/uisupport/CMakeLists.txt | 8 ++- src/uisupport/icon.cpp | 26 ++++++++ src/uisupport/icon.h | 38 ++++++++++++ src/uisupport/iconloader.cpp | 112 +++++++++++++++++++++++++++++++++++ src/uisupport/iconloader.h | 105 ++++++++++++++++++++++++++++++++ 7 files changed, 294 insertions(+), 3 deletions(-) create mode 100644 src/uisupport/icon.cpp create mode 100644 src/uisupport/icon.h create mode 100644 src/uisupport/iconloader.cpp create mode 100644 src/uisupport/iconloader.h diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index 88968936..d2363e6f 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -36,6 +36,7 @@ #include "clientbacklogmanager.h" #include "coreinfodlg.h" #include "coreconnectdlg.h" +#include "icon.h" #include "msgprocessorstatuswidget.h" #include "qtuimessageprocessor.h" #include "qtuiapplication.h" @@ -92,7 +93,6 @@ MainWin::MainWin(QWidget *parent) if(style != "") { QApplication::setStyle(style); } - ui.setupUi(this); setWindowTitle("Quassel IRC"); setWindowIcon(offlineTrayIcon); diff --git a/src/qtui/qtuiapplication.cpp b/src/qtui/qtuiapplication.cpp index 7a6f0977..80cc4d40 100644 --- a/src/qtui/qtuiapplication.cpp +++ b/src/qtui/qtuiapplication.cpp @@ -27,6 +27,8 @@ #include "qtui.h" #include "sessionsettings.h" +#include "iconloader.h" + QtUiApplication::QtUiApplication(int &argc, char **argv) : QApplication(argc, argv), Quassel() { setRunMode(Quassel::ClientOnly); @@ -45,6 +47,10 @@ bool QtUiApplication::init() { // QTimer::singleShot(0, gui, SLOT(init())); gui->init(); resumeSessionIfPossible(); + + // DEBUG + QPixmap pix = IconLoader::global()->loadIcon("network-connect", IconLoader::Small); + qDebug() << pix; return true; } return false; diff --git a/src/uisupport/CMakeLists.txt b/src/uisupport/CMakeLists.txt index f60c8cae..19befcac 100644 --- a/src/uisupport/CMakeLists.txt +++ b/src/uisupport/CMakeLists.txt @@ -14,9 +14,11 @@ set(SOURCES clearablelineedit.cpp clickablelabel.cpp colorbutton.cpp - nickviewfilter.cpp + icon.cpp + iconloader.cpp inputline.cpp nickview.cpp + nickviewfilter.cpp settingspage.cpp tabcompleter.cpp uisettings.cpp @@ -32,13 +34,15 @@ set(MOC_HDRS clearablelineedit.h clickablelabel.h colorbutton.h - nickviewfilter.h + iconloader.h inputline.h nickview.h + nickviewfilter.h settingspage.h tabcompleter.h) set(HEADERS + icon.h uisettings.h uistyle.h) diff --git a/src/uisupport/icon.cpp b/src/uisupport/icon.cpp new file mode 100644 index 00000000..729a88b2 --- /dev/null +++ b/src/uisupport/icon.cpp @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel IRC Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "icon.h" +#include "iconloader.h" + +Icon::Icon(const QString &name) : QIcon() { + addPixmap(IconLoader::global()->loadIcon(name, IconLoader::Desktop)); +} diff --git a/src/uisupport/icon.h b/src/uisupport/icon.h new file mode 100644 index 00000000..7ca18448 --- /dev/null +++ b/src/uisupport/icon.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel IRC Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef ICON_H_ +#define ICON_H_ + +#include + +/// A very thin wrapper around QIcon +/** This wrapper class allows us to load an icon by its theme name rather than its full file name. + * The overloaded ctor uses IconLoader to locate an icon with this basename in the current theme + * or in Qt Resources. + */ +class Icon : public QIcon { + + public: + //explicit Icon(); + explicit Icon(const QString &iconName); +}; + +#endif diff --git a/src/uisupport/iconloader.cpp b/src/uisupport/iconloader.cpp new file mode 100644 index 00000000..0fff1e82 --- /dev/null +++ b/src/uisupport/iconloader.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel IRC Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "iconloader.h" + +IconLoader IconLoader::_iconLoader; +int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 }; // default sizes taken from Oxygen + +IconLoader *IconLoader::global() { + return &_iconLoader; +} + +IconLoader::IconLoader(QObject *parent) : QObject(parent) { + + setTheme("oxygen"); +} + +IconLoader::~IconLoader() { + +} + +void IconLoader::setTheme(const QString &theme) { + _theme = theme; + // check which dirs could contain themed icons + _themedIconDirNames.clear(); + _plainIconDirNames.clear(); + QString path; + QStringList dataDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':'); + + // System theme in $data/icons/$theme + foreach(QString dir, dataDirNames) { + path = QString("%1/icons/%2").arg(dir, theme); + if(QFile::exists(path)) + _themedIconDirNames.append(path); + } + // Resource for system theme :/icons/$theme + path = QString(":/icons/%2"); + if(QFile::exists(path)) + _themedIconDirNames.append(path); + + // Own icons in $data/apps/quassel/icons/hicolor and :/icons/hicolor + // Also, plain icon dirs $data/apps/quassel/pics and :/pics + dataDirNames.append(":"); + foreach(QString dir, dataDirNames) { + path = QString("%1/apps/quassel/icons/hicolor"); + if(QFile::exists(path)) + _themedIconDirNames.append(path); + path = QString("%1/apps/quassel/pics"); + if(QFile::exists(path)) + _plainIconDirNames.append(path); + } +} + +// TODO: optionally implement cache (speed/memory tradeoff?) +QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size) { + if(group < 0 || group >= LastGroup) { + qWarning() << "Invalid icon group!"; + return QPixmap(); + } + if(size == 0) + size = _groupSize[group]; + + QString path = findIconPath(name, size); + if(path.isEmpty()) return QPixmap(); + + // load the icon + return QPixmap(path); +} + +QString IconLoader::findIconPath(const QString &name, int size) { + QString fname = QString("%1.png").arg(name); // we only support PNG so far + // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size + foreach(QString basedir, _themedIconDirNames) { + QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size))); + if(sizedir.exists()) { + // ignore context, i.e. scan all subdirs + QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + foreach(QString dir, contextdirs) { + QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname); + if(QFile::exists(path)) return path; + } + } + } + // Now check the plain dirs + foreach(QString dir, _plainIconDirNames) { + QString path = QString("%1/%2").arg(dir, name); + if(QFile::exists(path)) return path; + } + + return QString(); +} diff --git a/src/uisupport/iconloader.h b/src/uisupport/iconloader.h new file mode 100644 index 00000000..165aa9b7 --- /dev/null +++ b/src/uisupport/iconloader.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel IRC Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + *************************************************************************** + * Based in part on KDE's kiconloader.h * + * This declares a subset of that API. * + ***************************************************************************/ + +#ifndef ICONLOADER_H_ +#define ICONLOADER_H_ + +#include + +/// Provides basic facilities to load icons from standard locations or resources +/** This implements a (very) basic subset of KIconLoader's API, such that we can use those classes + * interchangeably in Quassel. + * + * We currently (unless somebody does a more fancy implementation ;-)) assume the Oxygen icon theme + * to be used. In particular, this means that we do assume its directory layout and existing icons to + * be present. Though it should be easy to switch to a different theme name, we don't currently support + * any fallback mechanism if this other theme misses an icon for a given size. Also, we only support PNG. + * + * Since we do support integrating the required part of Oxygen into the binary via Qt Resources, this + * should work for everyone for now. + * + * - $XDG_DATA_DIRS/icons/$theme (in order) + * - :/icons/$theme (fallback in case we use Qt Resources) + * - $XDG_DATA_DIRS/apps/quassel/icons/hicolor (our own unthemed icons) + * - :/icons/hicolor + * - $XDG_DATA_DIRS/apps/quassel/pics + * - :/pics + * + * We don't search for size/context dirs in /pics, i.e. for a given $name, we expect pics/$name.png. + */ +class IconLoader : public QObject { + Q_OBJECT + +public: + enum Group { + NoGroup = -1, ///< No group + Desktop = 0, ///< Desktop icons + Toolbar, ///< Toolbar icons + MainToolbar, ///< Main toolbar icons + Small, ///< Small icons, e.g. for buttons + Panel, ///< Panel icons + Dialog, ///< Icons for use in dialog title etc. + LastGroup + }; + + /// Standard icon sizes + enum StdSizes { + SizeSmall=16, ///< Small icons for menu entries + SizeSmallMedium=22, ///< Slightly larger small icons for toolbars, panels, etc + SizeMedium=32, ///< Medium-sized icons for the desktop + SizeLarge=48, ///< Large icons for the panel + SizeHuge=64, ///< Huge icons for iconviews + SizeEnormous=128 ///< Enormous icons for iconviews + }; + + explicit IconLoader(QObject *parent = 0); + ~IconLoader(); + + static IconLoader *global(); + + /// Load a pixmap for the given name and group + QPixmap loadIcon(const QString& name, IconLoader::Group group, int size = 0); + + inline QString theme() const; + void setTheme(const QString &name); + +private: + QString findIconPath(const QString &name, int size); + + static IconLoader _iconLoader; + QString _theme; + QStringList _themedIconDirNames; + QStringList _plainIconDirNames; + static int _groupSize[]; +}; + +// convenience +QPixmap DesktopIcon(const QString& name, int size = 0); +QPixmap BarIcon(const QString& name, int size = 0); +QPixmap MainbarIcon(const QString& name, int size = 0); +QPixmap SmallIcon(const QString& name, int size = 0); +//QPixmap SmallMediumIcon(const QString &name, int size = 0); // not part of KIconLoader + +QString IconLoader::theme() const { return _theme; } + +#endif -- 2.20.1