Add a method to find data files in standard directories (such as $PREFIX/share)
[quassel.git] / src / uisupport / iconloader.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-09 by the Quassel Project                          *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
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.                                           *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21 #ifndef HAVE_KDE
22
23 #include <QCoreApplication>
24 #include <QDebug>
25 #include <QDir>
26 #include <QFile>
27
28 #include "iconloader.h"
29 #include "util.h"
30
31 IconLoader IconLoader::_iconLoader;
32 int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 };  // default sizes taken from Oxygen
33
34 IconLoader *IconLoader::global() {
35   // Workaround: the static _iconLoader might be initialized before the resources it needs
36   // This way, first call to global() will init it by setting the theme
37   if(_iconLoader.theme().isEmpty())
38     _iconLoader.setTheme("oxygen");
39   return &_iconLoader;
40 }
41
42 IconLoader::IconLoader(QObject *parent) : QObject(parent) {
43
44   // setTheme("oxygen");
45 }
46
47 IconLoader::~IconLoader() {
48
49 }
50
51 void IconLoader::setTheme(const QString &theme) {
52   _theme = theme;
53   // check which dirs could contain themed icons
54   _themedIconDirNames.clear();
55   _plainIconDirNames.clear();
56   QString path;
57   QStringList dataDirNames = dataDirPaths();
58
59   // System theme in $data/icons/$theme
60   foreach(QString dir, dataDirNames) {
61     path = QString("%1/icons/%2").arg(dir, theme);
62     if(QFile::exists(path))
63       _themedIconDirNames.append(path);
64   }
65   // Resource for system theme :/icons/$theme
66   path = QString(":/icons/%1").arg(theme);
67   if(QFile::exists(path))
68     _themedIconDirNames.append(path);
69
70   // Own icons in $data/apps/quassel/icons/hicolor
71   // Also, plain icon dirs $data/apps/quassel/pics
72   foreach(QString dir, dataDirNames) {
73     path = QString("%1/icons/hicolor").arg(dir);
74     if(QFile::exists(path))
75       _themedIconDirNames.append(path);
76     path = QString("%1/apps/quassel/pics").arg(dir);
77     if(QFile::exists(path))
78       _plainIconDirNames.append(path);
79   }
80
81   // Same for :/icons/hicolor and :/pics
82   path = QString(":/icons/hicolor");
83   if(QFile::exists(path))
84     _themedIconDirNames.append(path);
85
86   path = QString(":/pics");
87   if(QFile::exists(path))
88     _plainIconDirNames.append(path);
89 }
90
91 // TODO: optionally implement cache (speed/memory tradeoff?)
92 QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size) {
93   if(group < 0 || group >= LastGroup) {
94     qWarning() << "Invalid icon group!";
95     return QPixmap();
96   }
97   if(size == 0)
98     size = _groupSize[group];
99
100   QString path = findIconPath(name, size);
101   if(path.isEmpty()) return QPixmap();
102
103   // load the icon
104   return QPixmap(path);
105 }
106
107 QString IconLoader::findIconPath(const QString &name, int size) {
108   QString fname = QString("%1.png").arg(name);  // we only support PNG so far
109   // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size
110   foreach(QString basedir, _themedIconDirNames) {
111     QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size)));
112     if(sizedir.exists()) {
113       // ignore context, i.e. scan all subdirs
114       QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
115       foreach(QString dir, contextdirs) {
116         QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname);
117         if(QFile::exists(path)) return path;
118       }
119     }
120   }
121   // Now check the plain dirs
122   foreach(QString dir, _plainIconDirNames) {
123     QString path = QString("%1/%2").arg(dir, name);
124     if(QFile::exists(path)) return path;
125   }
126
127   qWarning() << "Icon not found:" << name << size;
128   return QString();
129 }
130
131 // Convenience constructors
132
133 QPixmap DesktopIcon(const QString& name, int force_size) {
134   IconLoader *loader = IconLoader::global();
135   return loader->loadIcon(name, IconLoader::Desktop, force_size);
136 }
137
138 QPixmap BarIcon(const QString& name, int force_size) {
139   IconLoader *loader = IconLoader::global();
140   return loader->loadIcon(name, IconLoader::Toolbar, force_size);
141 }
142
143 QPixmap MainBarIcon(const QString& name, int force_size) {
144   IconLoader *loader = IconLoader::global();
145   return loader->loadIcon(name, IconLoader::MainToolbar, force_size);
146 }
147
148 QPixmap SmallIcon(const QString& name, int force_size) {
149   IconLoader *loader = IconLoader::global();
150   return loader->loadIcon(name, IconLoader::Small, force_size);
151 }
152
153 #endif