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
32IconLoader IconLoader::_iconLoader;
33int IconLoader::_groupSize[] = { 48, 22, 22, 16, 32, 22 }; // default sizes taken from Oxygen
34
35IconLoader *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
45IconLoader::IconLoader(QObject *parent) : QObject(parent)
46{
47 // setTheme("oxygen");
48}
49
50
51IconLoader::~IconLoader()
52{
53}
54
55
56void 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?)
118QPixmap 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
135QString 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
163QPixmap 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
170QPixmap 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
177QPixmap 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
184QPixmap 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
192