2
* Copyright (c) 2015 Boudewijn Rempt <boud@valdyas.org>
3
* Copyright (c) 2015 Friedrich W. H. Kossebau <kossebau@kde.org>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library 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 GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
#include "KoResourcePaths.h"
22
#include <QGlobalStatic>
23
#include <QStringList>
25
#include <QStandardPaths>
33
static const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
35
static const Qt::CaseSensitivity cs = Qt::CaseSensitive;
38
class KoResourcePathsImpl
41
static QStandardPaths::StandardLocation mapTypeToQStandardPaths(const QString &type)
44
type == QLatin1String("data") ? QStandardPaths::GenericDataLocation :
45
type == QLatin1String("config") ? QStandardPaths::GenericConfigLocation :
46
type == QLatin1String("cache") ? QStandardPaths::CacheLocation :
47
type == QLatin1String("tmp") ? QStandardPaths::TempLocation :
48
type == QLatin1String("appdata") ? QStandardPaths::DataLocation :
49
type == QLatin1String("locale") ? QStandardPaths::GenericDataLocation :
50
/* default */ QStandardPaths::GenericDataLocation;
53
KoResourcePathsImpl();
54
~KoResourcePathsImpl();
56
void addResourceTypeInternal(const QString &type, const QString &basetype,
57
const QString &relativeName, bool priority);
59
void addResourceDirInternal(const QString &type, const QString &absdir, bool priority);
61
QString findResourceInternal(const QString &type, const QString &fileName);
63
QStringList findDirsInternal(const QString &type, const QString &relDir);
65
QStringList findAllResourcesInternal(const QString &type,
66
const QString &filter = QString(),
67
KoResourcePaths::SearchOptions options = KoResourcePaths::NoSearchOptions) const;
69
QStringList resourceDirsInternal(const QString &type);
71
QString saveLocationInternal(const QString &type, const QString &suffix = QString(), bool create = true);
73
QString locateLocalInternal(const QString &type, const QString &filename, bool createDir = false);
76
QHash<QString, QStringList> m_absolutes; // For each resource type, the list of absolute paths, from most local (most priority) to most global
77
QHash<QString, QStringList> m_relatives; // Same with relative paths
80
KoResourcePathsImpl::KoResourcePathsImpl()
84
KoResourcePathsImpl::~KoResourcePathsImpl()
89
void KoResourcePathsImpl::addResourceTypeInternal(const QString &type, const QString &basetype,
90
const QString &relativename,
93
if (relativename.isEmpty()) return;
95
QString copy = relativename;
97
Q_ASSERT(basetype == "data");
99
if (!copy.endsWith(QLatin1Char('/'))) {
100
copy += QLatin1Char('/');
103
QStringList &rels = m_relatives[type]; // find or insert
105
if (!rels.contains(copy, cs)) {
113
//qDebug() << "addResourceType: type" << type << "basetype" << basetype << "relativename" << relativename << "priority" << priority << m_relatives[type];
116
void KoResourcePathsImpl::addResourceDirInternal(const QString &type, const QString &absdir, bool priority)
118
if (absdir.isEmpty() || type.isEmpty()) return;
120
// find or insert entry in the map
121
QString copy = absdir;
122
if (!copy.endsWith(QLatin1Char('/'))) {
123
copy += QLatin1Char('/');
126
QStringList &paths = m_absolutes[type];
127
if (!paths.contains(copy, cs)) {
135
//qDebug() << "addResourceDir: type" << type << "absdir" << absdir << "priority" << priority << m_absolutes[type];
138
QString KoResourcePathsImpl::findResourceInternal(const QString &type, const QString &fileName)
140
const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
141
QString resource = QStandardPaths::locate(location, fileName, QStandardPaths::LocateFile);
142
if (resource.isEmpty()) {
143
foreach(const QString &relative, m_relatives.value(type)) {
144
resource = QStandardPaths::locate(location, relative + fileName, QStandardPaths::LocateFile);
145
if (!resource.isEmpty()) {
150
if (resource.isEmpty()) {
151
foreach(const QString &absolute, m_absolutes.value(type)) {
152
const QString filePath = absolute + fileName;
153
if (QFileInfo::exists(filePath)) {
159
//Q_ASSERT(!resource.isEmpty());
160
//qDebug() << "findResource: type" << type << "filename" << fileName << "resource" << resource;
164
QStringList KoResourcePathsImpl::findDirsInternal(const QString &type, const QString &relDir)
166
const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
168
QStringList dirs = QStandardPaths::locateAll(location, relDir, QStandardPaths::LocateDirectory);
170
foreach(const QString &relative, m_relatives.value(type)) {
171
dirs << QStandardPaths::locateAll(location, relative + relDir, QStandardPaths::LocateDirectory);
174
foreach(const QString &absolute, m_absolutes.value(type)) {
175
const QString dirPath = absolute + relDir;
176
if (QDir(dirPath).exists()) {
181
//Q_ASSERT(!dirs.isEmpty());
182
//qDebug() << "findDirs: type" << type << "relDir" << relDir<< "resource" << dirs;
187
QStringList filesInDir(const QString &startdir, const QString & filter, bool noduplicates, bool recursive)
189
//qDebug() << "filesInDir: startdir" << startdir << "filter" << filter << "noduplicates" << noduplicates << "recursive" << recursive;
192
// First the entries in this path
193
QStringList nameFilters;
194
nameFilters << filter;
195
const QStringList fileNames = QDir(startdir).entryList(nameFilters, QDir::Files | QDir::CaseSensitive, QDir::Name);
196
//qDebug() << "\tFound:" << fileNames.size() << ":" << fileNames;
197
Q_FOREACH (const QString &fileName, fileNames) {
198
QString file = startdir + '/' + fileName;
202
// And then everything underneath, if recursive is specified
204
const QStringList entries = QDir(startdir).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
205
Q_FOREACH (const QString &subdir, entries) {
206
//qDebug() << "\tGoing to look in subdir" << subdir << "of" << startdir;
207
result << filesInDir(startdir + '/' + subdir, filter, noduplicates, recursive);
213
QStringList KoResourcePathsImpl::findAllResourcesInternal(const QString &type,
214
const QString &_filter,
215
KoResourcePaths::SearchOptions options) const
217
//qDebug() << "=====================================================";
219
bool noDuplicates = options & KoResourcePaths::NoDuplicates;
220
bool recursive = options & KoResourcePaths::Recursive;
222
//qDebug() << "findAllResources: type" << type << "filter" << _filter << "no dups" << noDuplicates << "recursive" << recursive;
224
const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
226
const QStringList relatives = m_relatives.value(type);
227
QString filter = _filter;
230
// In cases where the filter is like "color-schemes/*.colors" instead of "*.kpp", used with unregistgered resource types
231
if (filter.indexOf('*') > 0) {
232
prefix = filter.split('*').first();
233
filter = '*' + filter.split('*')[1];
234
//qDebug() << "Split up alias" << relatives << "filter" << filter;
237
QStringList resources;
238
if (relatives.isEmpty()) {
239
resources << QStandardPaths::locateAll(location, prefix + filter, QStandardPaths::LocateFile);
242
////qDebug() << "\tresources from qstandardpaths:" << resources.size();
245
foreach(const QString &relative, relatives) {
246
//qDebug() << "\t\relative:" << relative;
247
const QStringList dirs = QStandardPaths::locateAll(location, relative + prefix, QStandardPaths::LocateDirectory);
248
QSet<QString> s = QSet<QString>::fromList(dirs);
250
//qDebug() << "\t\tdirs:" << dirs;
251
Q_FOREACH (const QString &dir, s) {
252
resources << filesInDir(dir, filter, noDuplicates, recursive);
256
foreach(const QString &absolute, m_absolutes.value(type)) {
257
const QString dir = absolute + prefix;
258
if (QDir(dir).exists()) {
259
resources << filesInDir(dir, filter, noDuplicates, recursive);
264
QSet<QString> s = QSet<QString>::fromList(resources);
265
resources = s.toList();
268
//qDebug() << "\tresources also from aliases:" << resources.size();
269
//qDebug() << "=====================================================";
271
//Q_ASSERT(!resources.isEmpty());
276
QStringList KoResourcePathsImpl::resourceDirsInternal(const QString &type)
278
//return KGlobal::dirs()->resourceDirs(type.toLatin1());
279
QStringList resourceDirs;
281
const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
282
foreach(const QString &relative, m_relatives.value(type)) {
283
resourceDirs << QStandardPaths::locateAll(location, relative, QStandardPaths::LocateDirectory);
285
foreach(const QString &absolute, m_absolutes.value(type)) {
286
if (QDir(absolute).exists()) {
287
resourceDirs << absolute;
290
//qDebug() << "resourceDirs: type" << type << resourceDirs;
295
QString KoResourcePathsImpl::saveLocationInternal(const QString &type, const QString &suffix, bool create)
297
QString path = QStandardPaths::writableLocation(mapTypeToQStandardPaths(type)) + '/' + suffix;
299
if (!d.exists() && create) {
302
//qDebug() << "saveLocation: type" << type << "suffix" << suffix << "create" << create << "path" << path;
307
QString KoResourcePathsImpl::locateLocalInternal(const QString &type, const QString &filename, bool createDir)
309
QString path = saveLocationInternal(type, "", createDir);
310
//qDebug() << "locateLocal: type" << type << "filename" << filename << "CreateDir" << createDir << "path" << path;
311
return path + '/' + filename;
314
Q_GLOBAL_STATIC(KoResourcePathsImpl, s_instance);
317
void KoResourcePaths::addResourceType(const char *type, const char *basetype,
318
const QString &relativeName, bool priority)
320
s_instance->addResourceTypeInternal(QString::fromLatin1(type), QString::fromLatin1(basetype), relativeName, priority);
323
void KoResourcePaths::addResourceDir(const char *type, const QString &dir, bool priority)
325
s_instance->addResourceDirInternal(QString::fromLatin1(type), dir, priority);
328
QString KoResourcePaths::findResource(const char *type, const QString &fileName)
330
return s_instance->findResourceInternal(QString::fromLatin1(type), fileName);
333
QStringList KoResourcePaths::findDirs(const char *type, const QString &reldir)
335
return s_instance->findDirsInternal(QString::fromLatin1(type), reldir);
338
QStringList KoResourcePaths::findAllResources(const char *type,
339
const QString &filter,
340
SearchOptions options)
342
return s_instance->findAllResourcesInternal(QString::fromLatin1(type), filter, options);
345
QStringList KoResourcePaths::resourceDirs(const char *type)
347
return s_instance->resourceDirsInternal(QString::fromLatin1(type));
350
QString KoResourcePaths::saveLocation(const char *type, const QString &suffix, bool create)
352
return s_instance->saveLocationInternal(QString::fromLatin1(type), suffix, create);
355
QString KoResourcePaths::locate(const char *type, const QString &filename)
357
return s_instance->findResourceInternal(QString::fromLatin1(type), filename);
360
QString KoResourcePaths::locateLocal(const char *type, const QString &filename, bool createDir)
362
return s_instance->locateLocalInternal(QString::fromLatin1(type), filename, createDir);