Search the web with selected text.
[quassel.git] / src / uisupport / iconloader.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2014 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  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 {
37     // Workaround: the static _iconLoader might be initialized before the resources it needs
38     // This way, first call to global() will init it by setting the theme
39     if (_iconLoader.theme().isEmpty())
40         _iconLoader.setTheme("oxygen");
41     return &_iconLoader;
42 }
43
44
45 IconLoader::IconLoader(QObject *parent) : QObject(parent)
46 {
47     // setTheme("oxygen");
48 }
49
50
51 IconLoader::~IconLoader()
52 {
53 }
54
55
56 void IconLoader::setTheme(const QString &theme)
57 {
58     _theme = theme;
59     // check which dirs could contain themed icons
60     _themedIconDirNames.clear();
61     _plainIconDirNames.clear();
62
63     // First, look for a system theme
64     // This is supposed to only work on Unix, though other platforms might set $XDG_DATA_DIRS if they please.
65     QStringList iconDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts);
66     if (!iconDirNames.isEmpty()) {
67         for (int i = 0; i < iconDirNames.count(); i++)
68             iconDirNames[i].append(QString("/icons/"));
69     }
70 #ifdef Q_OS_UNIX
71     else {
72         // Provide a fallback
73         iconDirNames << "/usr/share/icons/";
74     }
75     // Add our prefix too
76     QString appDir = QCoreApplication::applicationDirPath();
77     int binpos = appDir.lastIndexOf("/bin");
78     if (binpos >= 0) {
79         appDir.replace(binpos, 4, "/share");
80         appDir.append("/icons/");
81         if (!iconDirNames.contains(appDir))
82             iconDirNames.append(appDir);
83     }
84 #endif
85
86     // Now look for an icons/ subdir in our data paths
87     foreach(const QString &dir, Quassel::dataDirPaths())
88     iconDirNames << dir + "icons/";
89
90     // Add our resource path too
91     iconDirNames << ":/icons/";
92
93     // Ready do add theme names
94     foreach(const QString &dir, iconDirNames) {
95         QString path = dir + theme + '/';
96         if (QFile::exists(path))
97             _themedIconDirNames << path;
98     }
99     foreach(const QString &dir, iconDirNames) {
100         QString path = dir + "hicolor/";
101         if (QFile::exists(path))
102             _themedIconDirNames << path;
103     }
104
105     // We ship some plain (non-themed) icons in $data/pics
106     foreach(const QString &dir, Quassel::dataDirPaths()) {
107         QString path = dir + "pics/";
108         if (QFile::exists(path))
109             _plainIconDirNames << path;
110     }
111     // And of course, our resource path
112     if (QFile::exists(":/pics"))
113         _plainIconDirNames << ":/pics";
114 }
115
116
117 // TODO: optionally implement cache (speed/memory tradeoff?)
118 QPixmap IconLoader::loadIcon(const QString &name, IconLoader::Group group, int size)
119 {
120     if (group < 0 || group >= LastGroup) {
121         qWarning() << "Invalid icon group!";
122         return QPixmap();
123     }
124     if (size == 0)
125         size = _groupSize[group];
126
127     QString path = findIconPath(name, size);
128     if (path.isEmpty()) return QPixmap();
129
130     // load the icon
131     return QPixmap(path);
132 }
133
134
135 QString IconLoader::findIconPath(const QString &name, int size)
136 {
137     QString fname = QString("%1.png").arg(name); // we only support PNG so far
138     // First, look for a themed icon... we don't do anything fancy here, only exact match for both name and size
139     foreach(QString basedir, _themedIconDirNames) {
140         QDir sizedir(QString("%1/%2x%2").arg(basedir).arg(QString::number(size)));
141         if (sizedir.exists()) {
142             // ignore context, i.e. scan all subdirs
143             QStringList contextdirs = sizedir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
144             foreach(QString dir, contextdirs) {
145                 QString path = QString("%1/%2/%3").arg(sizedir.absolutePath(), dir, fname);
146                 if (QFile::exists(path)) return path;
147             }
148         }
149     }
150     // Now check the plain dirs
151     foreach(QString dir, _plainIconDirNames) {
152         QString path = QString("%1/%2").arg(dir, name);
153         if (QFile::exists(path)) return path;
154     }
155
156     qWarning() << "Icon not found:" << name << size;
157     return QString();
158 }
159
160
161 // Convenience constructors
162
163 QPixmap DesktopIcon(const QString &name, int force_size)
164 {
165     IconLoader *loader = IconLoader::global();
166     return loader->loadIcon(name, IconLoader::Desktop, force_size);
167 }
168
169
170 QPixmap BarIcon(const QString &name, int force_size)
171 {
172     IconLoader *loader = IconLoader::global();
173     return loader->loadIcon(name, IconLoader::Toolbar, force_size);
174 }
175
176
177 QPixmap MainBarIcon(const QString &name, int force_size)
178 {
179     IconLoader *loader = IconLoader::global();
180     return loader->loadIcon(name, IconLoader::MainToolbar, force_size);
181 }
182
183
184 QPixmap SmallIcon(const QString &name, int force_size)
185 {
186     IconLoader *loader = IconLoader::global();
187     return loader->loadIcon(name, IconLoader::Small, force_size);
188 }
189
190
191 #endif