Don't let the inputline eat application shortcuts
[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 "quassel.h"
30 #include "util.h"
31
32 IconLoader IconLoader::_iconLoader;
33 int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 };  // default sizes taken from Oxygen
34
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");
40   return &_iconLoader;
41 }
42
43 IconLoader::IconLoader(QObject *parent) : QObject(parent) {
44
45   // setTheme("oxygen");
46 }
47
48 IconLoader::~IconLoader() {
49
50 }
51
52 void IconLoader::setTheme(const QString &theme) {
53   _theme = theme;
54   // check which dirs could contain themed icons
55   _themedIconDirNames.clear();
56   _plainIconDirNames.clear();
57
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/"));
64   }
65 #ifdef Q_OS_UNIX
66   else {
67     // Provide a fallback
68     iconDirNames << "/usr/share/icons/";
69   }
70   // Add our prefix too
71   QString appDir = QCoreApplication::applicationDirPath();
72   int binpos = appDir.lastIndexOf("/bin");
73   if(binpos >= 0) {
74     appDir.replace(binpos, 4, "/share");
75     appDir.append("/icons/");
76     if(!iconDirNames.contains(appDir))
77       iconDirNames.append(appDir);
78   }
79 #endif
80
81   // Now look for an icons/ subdir in our data paths
82   foreach(const QString &dir, Quassel::dataDirPaths())
83     iconDirNames << dir + "icons/";
84
85   // Add our resource path too
86   iconDirNames << ":/icons/";
87
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;
93   }
94   foreach(const QString &dir, iconDirNames) {
95     QString path = dir + "hicolor/";
96     if(QFile::exists(path))
97       _themedIconDirNames << path;
98   }
99
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;
105   }
106   // And of course, our resource path
107   if(QFile::exists(":/pics"))
108     _plainIconDirNames << ":/pics";
109
110 }
111
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!";
116     return QPixmap();
117   }
118   if(size == 0)
119     size = _groupSize[group];
120
121   QString path = findIconPath(name, size);
122   if(path.isEmpty()) return QPixmap();
123
124   // load the icon
125   return QPixmap(path);
126 }
127
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;
139       }
140     }
141   }
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;
146   }
147
148   qWarning() << "Icon not found:" << name << size;
149   return QString();
150 }
151
152 // Convenience constructors
153
154 QPixmap DesktopIcon(const QString& name, int force_size) {
155   IconLoader *loader = IconLoader::global();
156   return loader->loadIcon(name, IconLoader::Desktop, force_size);
157 }
158
159 QPixmap BarIcon(const QString& name, int force_size) {
160   IconLoader *loader = IconLoader::global();
161   return loader->loadIcon(name, IconLoader::Toolbar, force_size);
162 }
163
164 QPixmap MainBarIcon(const QString& name, int force_size) {
165   IconLoader *loader = IconLoader::global();
166   return loader->loadIcon(name, IconLoader::MainToolbar, force_size);
167 }
168
169 QPixmap SmallIcon(const QString& name, int force_size) {
170   IconLoader *loader = IconLoader::global();
171   return loader->loadIcon(name, IconLoader::Small, force_size);
172 }
173
174 #endif