1 /***************************************************************************
2 * Copyright (C) 2005-09 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
23 #include <QCoreApplication>
28 #include "iconloader.h"
32 IconLoader IconLoader::_iconLoader;
33 int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 }; // default sizes taken from Oxygen
35 IconLoader *IconLoader::global() {
36 // Workaround: the static _iconLoader might be initialized before the resources it needs
37 // This way, first call to global() will init it by setting the theme
38 if(_iconLoader.theme().isEmpty())
39 _iconLoader.setTheme("oxygen");
43 IconLoader::IconLoader(QObject *parent) : QObject(parent) {
45 // setTheme("oxygen");
48 IconLoader::~IconLoader() {
52 void IconLoader::setTheme(const QString &theme) {
54 // check which dirs could contain themed icons
55 _themedIconDirNames.clear();
56 _plainIconDirNames.clear();
58 // First, look for a system theme
59 // This is supposed to only work on Unix, though other platforms might set $XDG_DATA_DIRS if they please.
60 QStringList iconDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts);
61 if(!iconDirNames.isEmpty()) {
62 for(int i = 0; i < iconDirNames.count(); i++)
63 iconDirNames[i].append(QString("/icons/"));
68 iconDirNames << "/usr/share/icons/";
71 QString appDir = QCoreApplication::applicationDirPath();
72 int binpos = appDir.lastIndexOf("/bin");
74 appDir.replace(binpos, 4, "/share");
75 appDir.append("/icons/");
76 if(!iconDirNames.contains(appDir))
77 iconDirNames.append(appDir);
81 // Now look for an icons/ subdir in our data paths
82 foreach(const QString &dir, Quassel::dataDirPaths())
83 iconDirNames << dir + "icons/";
85 // Add our resource path too
86 iconDirNames << ":/icons/";
88 // Ready do add theme names
89 foreach(const QString &dir, iconDirNames) {
90 QString path = dir + theme + '/';
91 if(QFile::exists(path))
92 _themedIconDirNames << path;
94 foreach(const QString &dir, iconDirNames) {
95 QString path = dir + "hicolor/";
96 if(QFile::exists(path))
97 _themedIconDirNames << path;
100 // We ship some plain (non-themed) icons in $data/pics
101 foreach(const QString &dir, Quassel::dataDirPaths()) {
102 QString path = dir + "pics/";
103 if(QFile::exists(path))
104 _plainIconDirNames << path;
106 // And of course, our resource path
107 if(QFile::exists(":/pics"))
108 _plainIconDirNames << ":/pics";
112 // TODO: optionally implement cache (speed/memory tradeoff?)
113 QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size) {
114 if(group < 0 || group >= LastGroup) {
115 qWarning() << "Invalid icon group!";
119 size = _groupSize[group];
121 QString path = findIconPath(name, size);
122 if(path.isEmpty()) return QPixmap();
125 return QPixmap(path);
128 QString IconLoader::findIconPath(const QString &name, int size) {
129 QString fname = QString("%1.png").arg(name); // we only support PNG so far
130 // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size
131 foreach(QString basedir, _themedIconDirNames) {
132 QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size)));
133 if(sizedir.exists()) {
134 // ignore context, i.e. scan all subdirs
135 QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
136 foreach(QString dir, contextdirs) {
137 QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname);
138 if(QFile::exists(path)) return path;
142 // Now check the plain dirs
143 foreach(QString dir, _plainIconDirNames) {
144 QString path = QString("%1/%2").arg(dir, name);
145 if(QFile::exists(path)) return path;
148 qWarning() << "Icon not found:" << name << size;
152 // Convenience constructors
154 QPixmap DesktopIcon(const QString& name, int force_size) {
155 IconLoader *loader = IconLoader::global();
156 return loader->loadIcon(name, IconLoader::Desktop, force_size);
159 QPixmap BarIcon(const QString& name, int force_size) {
160 IconLoader *loader = IconLoader::global();
161 return loader->loadIcon(name, IconLoader::Toolbar, force_size);
164 QPixmap MainBarIcon(const QString& name, int force_size) {
165 IconLoader *loader = IconLoader::global();
166 return loader->loadIcon(name, IconLoader::MainToolbar, force_size);
169 QPixmap SmallIcon(const QString& name, int force_size) {
170 IconLoader *loader = IconLoader::global();
171 return loader->loadIcon(name, IconLoader::Small, force_size);