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