1 /*
2 * theme.cpp - base class for any theme
3 * Copyright (C) 2010 Justin Karneges, Michail Pishchagin, Rion (Sergey Ilinyh)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
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 library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "theme.h"
22
23 #include <QFileInfo>
24 #include <QDir>
25 #include <QDirIterator>
26 #include <QStringList>
27
28 #ifndef NO_Theme_ZIP
29 #define Theme_ZIP
30 #endif
31
32 #ifdef Theme_ZIP
33 # include "zip/zip.h"
34 #endif
35
36 #ifndef HAVE_QT5
37 # define QLatin1Literal QLatin1String
38 #endif
39
40 #include "psithemeprovider.h"
41 #include "theme_p.h"
42
43
44
45
46 //--------------------------------------
47 // Theme
48 //--------------------------------------
Theme()49 Theme::Theme()
50 {
51
52 }
53
Theme(ThemePrivate * priv)54 Theme::Theme(ThemePrivate *priv) :
55 d(priv)
56 {
57
58 }
59
Theme(const Theme & other)60 Theme::Theme(const Theme &other) :
61 d(other.d)
62 {
63
64 }
65
operator =(const Theme & other)66 Theme &Theme::operator=(const Theme &other)
67 {
68 d = other.d;
69 return *this;
70 }
71
~Theme()72 Theme::~Theme()
73 {
74
75 }
76
isValid() const77 bool Theme::isValid() const
78 {
79 return d;
80 }
81
state() const82 Theme::State Theme::state() const
83 {
84 if (!d) {
85 return Invalid;
86 }
87 return d->state;
88 }
89
exists()90 bool Theme::exists()
91 {
92 return d && d->exists();
93 }
94
load()95 bool Theme::load()
96 {
97 if (!d) {
98 return false;
99 }
100 return d->load();
101 }
102
load(std::function<void (bool)> loadCallback)103 bool Theme::load(std::function<void (bool)> loadCallback)
104 {
105 return d->load(loadCallback);
106 }
107
hasPreview() const108 bool Theme::hasPreview() const
109 {
110 return d->hasPreview();
111 }
112
previewWidget()113 QWidget* Theme::previewWidget()
114 {
115 return d->previewWidget();
116 }
117
isCompressed(const QFileInfo & fi)118 bool Theme::isCompressed(const QFileInfo &fi)
119 {
120 QString sfx = fi.suffix();
121 return fi.isDir() && (sfx == QLatin1Literal("jisp") ||
122 sfx == QLatin1Literal("zip") ||
123 sfx == QLatin1Literal("theme"));
124 }
125
isCompressed() const126 bool Theme::isCompressed() const
127 {
128 return isCompressed(QFileInfo(d->filepath));
129 }
130
loadData(const QString & fileName,const QString & themePath,bool caseInsensetive)131 QByteArray Theme::loadData(const QString &fileName, const QString &themePath, bool caseInsensetive)
132 {
133 QByteArray ba;
134 //qDebug("loading %s from %s", qPrintable(fileName), qPrintable(dir));
135 QFileInfo fi(themePath);
136 if ( fi.isDir() ) {
137 QFile file(themePath + '/' + fileName);
138 if (caseInsensetive && !file.exists()) {
139 QDir d(themePath);
140 foreach (const QString &name, fileName.toLower().split('/')) {
141 if (name.isEmpty()) { // force relative path and drop double slahses
142 continue;
143 }
144 QDirIterator di(d);
145 QFileInfo fi;
146 bool found = false;
147 while (di.hasNext()) {
148 di.next();
149 if (di.fileName().compare(name, Qt::CaseInsensitive) == 0) {
150 found = true;
151 fi = di.fileInfo();
152 break;
153 }
154 }
155 if (!found) {
156 qDebug("%s Not found: %s/%s", __FUNCTION__, qPrintable(d.path()), qPrintable(name));
157 return ba;
158 }
159 if (fi.isFile()) {
160 file.setFileName(fi.filePath());
161 break;
162 }
163 d.cd(fi.fileName()); // so that was directory. go into.
164 }
165 }
166 //qDebug("read data from %s", qPrintable(file.fileName()));
167 if (!file.open(QIODevice::ReadOnly)) {
168 qDebug("%s Failed to open: %s", __FUNCTION__, qPrintable(file.fileName()));
169 return ba;
170 }
171
172 ba = file.readAll();
173 }
174 #ifdef Theme_ZIP
175 else if ( fi.suffix() == "jisp" || fi.suffix() == "zip" || fi.suffix() == "theme" ) {
176 UnZip z(themePath);
177 if ( !z.open() )
178 return ba;
179 if (caseInsensetive) {
180 z.setCaseSensitivity(UnZip::CS_Insensitive);
181 }
182
183 QString n = fi.completeBaseName() + '/' + fileName;
184 if ( !z.readFile(n, &ba) ) {
185 n = "/" + fileName;
186 z.readFile(n, &ba);
187 }
188 }
189 #endif
190
191 return ba;
192 }
193
loadData(const QString & fileName) const194 QByteArray Theme::loadData(const QString &fileName) const
195 {
196 return d->loadData(fileName);
197 }
198
resourceLoader() const199 Theme::ResourceLoader *Theme::resourceLoader() const
200 {
201 return d->resourceLoader();
202 }
203
id() const204 const QString Theme::id() const
205 {
206 return d? d->id : QString();
207 }
208
setId(const QString & id)209 void Theme::setId(const QString &id)
210 {
211 d->id = id;
212 }
213
name() const214 const QString &Theme::name() const
215 {
216 return d->name;
217 }
218
setName(const QString & name)219 void Theme::setName(const QString &name)
220 {
221 d->name = name;
222 }
223
version() const224 const QString &Theme::version() const
225 {
226 return d->version;
227 }
228
description() const229 const QString &Theme::description() const
230 {
231 return d->description;
232 }
233
234 /**
235 * Returns the Theme authors list.
236 */
authors() const237 const QStringList &Theme::authors() const
238 {
239 return d->authors;
240 }
241
242 /**
243 * Returns the Theme creation date.
244 */
creation() const245 const QString &Theme::creation() const
246 {
247 return d->creation;
248 }
249
homeUrl() const250 const QString &Theme::homeUrl() const
251 {
252 return d->homeUrl;
253 }
254
themeProvider() const255 PsiThemeProvider *Theme::themeProvider() const
256 {
257 return d->provider;
258 }
259
260 /**
261 * Returns directory (or .zip/.jisp archive) name from which Theme was loaded.
262 */
filePath() const263 const QString &Theme::filePath() const
264 {
265 return d->filepath;
266 }
267
268 /**
269 * Sets the Theme directory (.zip archive) name.
270 */
setFilePath(const QString & f)271 void Theme::setFilePath(const QString &f)
272 {
273 d->filepath = f;
274 }
275
276 /**
277 * Returns additional Theme information.
278 * \sa setInfo()
279 */
info() const280 const QHash<QString, QString> Theme::info() const
281 {
282 return d->info;
283 }
284
285 /**
286 * Sets additional Theme information.
287 * \sa info()
288 */
setInfo(const QHash<QString,QString> & i)289 void Theme::setInfo(const QHash<QString, QString> &i)
290 {
291 d->info = i;
292 }
293
setCaseInsensitiveFS(bool state)294 void Theme::setCaseInsensitiveFS(bool state)
295 {
296 d->caseInsensitiveFS = state;
297 }
298
caseInsensitiveFS() const299 bool Theme::caseInsensitiveFS() const
300 {
301 return d->caseInsensitiveFS;
302 }
303
304 /**
305 * Title suitable to display in options dialog
306 */
title() const307 QString Theme::title() const
308 {
309 return d->name.isEmpty()? d->id : d->name;
310 }
311
setState(Theme::State state)312 void Theme::setState(Theme::State state)
313 {
314 d->state = state;
315 }
316
~ResourceLoader()317 Theme::ResourceLoader::~ResourceLoader()
318 {
319
320 }
321