~ubuntu-branches/debian/sid/calligraplan/sid

« back to all changes in this revision

Viewing changes to src/libs/widgets/KoResourcePaths.cpp

  • Committer: Package Import Robot
  • Author(s): Pino Toscano
  • Date: 2018-02-01 18:20:19 UTC
  • Revision ID: package-import@ubuntu.com-20180201182019-1qo7qaim5wejm5k9
Tags: upstream-3.1.0
ImportĀ upstreamĀ versionĀ 3.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2015 Boudewijn Rempt <boud@valdyas.org>
 
3
 * Copyright (c) 2015 Friedrich W. H. Kossebau <kossebau@kde.org>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 */
 
19
 
 
20
#include "KoResourcePaths.h"
 
21
 
 
22
#include <QGlobalStatic>
 
23
#include <QStringList>
 
24
#include <QHash>
 
25
#include <QStandardPaths>
 
26
#include <QDir>
 
27
#include <QFileInfo>
 
28
#include <QDebug>
 
29
#include <QSet>
 
30
 
 
31
 
 
32
#ifdef Q_OS_WIN
 
33
static const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
 
34
#else
 
35
static const Qt::CaseSensitivity cs = Qt::CaseSensitive;
 
36
#endif
 
37
 
 
38
class KoResourcePathsImpl
 
39
{
 
40
public:
 
41
    static QStandardPaths::StandardLocation mapTypeToQStandardPaths(const QString &type)
 
42
    {
 
43
        return
 
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;
 
51
    }
 
52
 
 
53
    KoResourcePathsImpl();
 
54
    ~KoResourcePathsImpl();
 
55
 
 
56
    void addResourceTypeInternal(const QString &type, const QString &basetype,
 
57
                                 const QString &relativeName, bool priority);
 
58
 
 
59
    void addResourceDirInternal(const QString &type, const QString &absdir, bool priority);
 
60
 
 
61
    QString findResourceInternal(const QString &type, const QString &fileName);
 
62
 
 
63
    QStringList findDirsInternal(const QString &type, const QString &relDir);
 
64
 
 
65
    QStringList findAllResourcesInternal(const QString &type,
 
66
                                         const QString &filter = QString(),
 
67
                                         KoResourcePaths::SearchOptions options = KoResourcePaths::NoSearchOptions) const;
 
68
 
 
69
    QStringList resourceDirsInternal(const QString &type);
 
70
 
 
71
    QString saveLocationInternal(const QString &type, const QString &suffix = QString(), bool create = true);
 
72
 
 
73
    QString locateLocalInternal(const QString &type, const QString &filename, bool createDir = false);
 
74
 
 
75
private:
 
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
 
78
};
 
79
 
 
80
KoResourcePathsImpl::KoResourcePathsImpl()
 
81
{
 
82
}
 
83
 
 
84
KoResourcePathsImpl::~KoResourcePathsImpl()
 
85
{
 
86
}
 
87
 
 
88
 
 
89
void KoResourcePathsImpl::addResourceTypeInternal(const QString &type, const QString &basetype,
 
90
                                                  const QString &relativename,
 
91
                                                  bool priority)
 
92
{
 
93
    if (relativename.isEmpty()) return;
 
94
 
 
95
    QString copy = relativename;
 
96
 
 
97
    Q_ASSERT(basetype == "data");
 
98
 
 
99
    if (!copy.endsWith(QLatin1Char('/'))) {
 
100
        copy += QLatin1Char('/');
 
101
    }
 
102
 
 
103
    QStringList &rels = m_relatives[type]; // find or insert
 
104
 
 
105
    if (!rels.contains(copy, cs)) {
 
106
        if (priority) {
 
107
            rels.prepend(copy);
 
108
        } else {
 
109
            rels.append(copy);
 
110
        }
 
111
    }
 
112
 
 
113
    //qDebug() << "addResourceType: type" << type << "basetype" << basetype << "relativename" << relativename << "priority" << priority << m_relatives[type];
 
114
}
 
115
 
 
116
void KoResourcePathsImpl::addResourceDirInternal(const QString &type, const QString &absdir, bool priority)
 
117
{
 
118
    if (absdir.isEmpty() || type.isEmpty()) return;
 
119
 
 
120
    // find or insert entry in the map
 
121
    QString copy = absdir;
 
122
    if (!copy.endsWith(QLatin1Char('/'))) {
 
123
        copy += QLatin1Char('/');
 
124
    }
 
125
 
 
126
    QStringList &paths = m_absolutes[type];
 
127
    if (!paths.contains(copy, cs)) {
 
128
        if (priority) {
 
129
            paths.prepend(copy);
 
130
        } else {
 
131
            paths.append(copy);
 
132
        }
 
133
    }
 
134
 
 
135
    //qDebug() << "addResourceDir: type" << type << "absdir" << absdir << "priority" << priority << m_absolutes[type];
 
136
}
 
137
 
 
138
QString KoResourcePathsImpl::findResourceInternal(const QString &type, const QString &fileName)
 
139
{
 
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()) {
 
146
                break;
 
147
            }
 
148
        }
 
149
    }
 
150
    if (resource.isEmpty()) {
 
151
        foreach(const QString &absolute, m_absolutes.value(type)) {
 
152
            const QString filePath = absolute + fileName;
 
153
            if (QFileInfo::exists(filePath)) {
 
154
                resource = filePath;
 
155
                break;
 
156
            }
 
157
        }
 
158
    }
 
159
    //Q_ASSERT(!resource.isEmpty());
 
160
    //qDebug() << "findResource: type" << type << "filename" << fileName << "resource" << resource;
 
161
    return resource;
 
162
}
 
163
 
 
164
QStringList KoResourcePathsImpl::findDirsInternal(const QString &type, const QString &relDir)
 
165
{
 
166
    const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
 
167
 
 
168
    QStringList dirs = QStandardPaths::locateAll(location, relDir, QStandardPaths::LocateDirectory);
 
169
 
 
170
    foreach(const QString &relative, m_relatives.value(type)) {
 
171
        dirs << QStandardPaths::locateAll(location, relative + relDir, QStandardPaths::LocateDirectory);
 
172
    }
 
173
 
 
174
    foreach(const QString &absolute, m_absolutes.value(type)) {
 
175
        const QString dirPath = absolute + relDir;
 
176
        if (QDir(dirPath).exists()) {
 
177
            dirs << dirPath;
 
178
        }
 
179
    }
 
180
 
 
181
    //Q_ASSERT(!dirs.isEmpty());
 
182
    //qDebug() << "findDirs: type" << type << "relDir" << relDir<< "resource" << dirs;
 
183
    return dirs;
 
184
}
 
185
 
 
186
 
 
187
QStringList filesInDir(const QString &startdir, const QString & filter, bool noduplicates, bool recursive)
 
188
{
 
189
    //qDebug() << "filesInDir: startdir" << startdir << "filter" << filter << "noduplicates" << noduplicates << "recursive" << recursive;
 
190
    QStringList result;
 
191
 
 
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;
 
199
        result << file;
 
200
    }
 
201
 
 
202
    // And then everything underneath, if recursive is specified
 
203
    if (recursive) {
 
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);
 
208
        }
 
209
    }
 
210
    return result;
 
211
}
 
212
 
 
213
QStringList KoResourcePathsImpl::findAllResourcesInternal(const QString &type,
 
214
                                                          const QString &_filter,
 
215
                                                          KoResourcePaths::SearchOptions options) const
 
216
{
 
217
    //qDebug() << "=====================================================";
 
218
 
 
219
    bool noDuplicates = options & KoResourcePaths::NoDuplicates;
 
220
    bool recursive = options & KoResourcePaths::Recursive;
 
221
 
 
222
    //qDebug() << "findAllResources: type" << type << "filter" << _filter << "no dups" << noDuplicates << "recursive" << recursive;
 
223
 
 
224
    const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
 
225
 
 
226
    const QStringList relatives = m_relatives.value(type);
 
227
    QString filter = _filter;
 
228
    QString prefix;
 
229
 
 
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;
 
235
    }
 
236
 
 
237
    QStringList resources;
 
238
    if (relatives.isEmpty()) {
 
239
        resources << QStandardPaths::locateAll(location, prefix + filter, QStandardPaths::LocateFile);
 
240
    }
 
241
 
 
242
    ////qDebug() << "\tresources from qstandardpaths:" << resources.size();
 
243
 
 
244
 
 
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);
 
249
 
 
250
        //qDebug() << "\t\tdirs:" << dirs;
 
251
        Q_FOREACH (const QString &dir, s) {
 
252
            resources << filesInDir(dir, filter, noDuplicates, recursive);
 
253
        }
 
254
    }
 
255
 
 
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);
 
260
        }
 
261
    }
 
262
 
 
263
    if (noDuplicates) {
 
264
        QSet<QString> s = QSet<QString>::fromList(resources);
 
265
        resources = s.toList();
 
266
    }
 
267
 
 
268
    //qDebug() << "\tresources also from aliases:" << resources.size();
 
269
    //qDebug() << "=====================================================";
 
270
 
 
271
    //Q_ASSERT(!resources.isEmpty());
 
272
 
 
273
    return resources;
 
274
}
 
275
 
 
276
QStringList KoResourcePathsImpl::resourceDirsInternal(const QString &type)
 
277
{
 
278
    //return KGlobal::dirs()->resourceDirs(type.toLatin1());
 
279
    QStringList resourceDirs;
 
280
 
 
281
    const QStandardPaths::StandardLocation location = mapTypeToQStandardPaths(type);
 
282
    foreach(const QString &relative, m_relatives.value(type)) {
 
283
        resourceDirs << QStandardPaths::locateAll(location, relative, QStandardPaths::LocateDirectory);
 
284
    }
 
285
    foreach(const QString &absolute, m_absolutes.value(type)) {
 
286
        if (QDir(absolute).exists()) {
 
287
            resourceDirs << absolute;
 
288
        }
 
289
    }
 
290
    //qDebug() << "resourceDirs: type" << type << resourceDirs;
 
291
 
 
292
    return resourceDirs;
 
293
}
 
294
 
 
295
QString KoResourcePathsImpl::saveLocationInternal(const QString &type, const QString &suffix, bool create)
 
296
{
 
297
    QString path = QStandardPaths::writableLocation(mapTypeToQStandardPaths(type)) + '/' + suffix;
 
298
    QDir d(path);
 
299
    if (!d.exists() && create) {
 
300
        d.mkpath(path);
 
301
    }
 
302
    //qDebug() << "saveLocation: type" << type << "suffix" << suffix << "create" << create << "path" << path;
 
303
 
 
304
    return path;
 
305
}
 
306
 
 
307
QString KoResourcePathsImpl::locateLocalInternal(const QString &type, const QString &filename, bool createDir)
 
308
{
 
309
    QString path = saveLocationInternal(type, "", createDir);
 
310
    //qDebug() << "locateLocal: type" << type << "filename" << filename << "CreateDir" << createDir << "path" << path;
 
311
    return path + '/' + filename;
 
312
}
 
313
 
 
314
Q_GLOBAL_STATIC(KoResourcePathsImpl, s_instance);
 
315
 
 
316
 
 
317
void KoResourcePaths::addResourceType(const char *type, const char *basetype,
 
318
                                      const QString &relativeName, bool priority)
 
319
{
 
320
    s_instance->addResourceTypeInternal(QString::fromLatin1(type), QString::fromLatin1(basetype), relativeName, priority);
 
321
}
 
322
 
 
323
void KoResourcePaths::addResourceDir(const char *type, const QString &dir, bool priority)
 
324
{
 
325
    s_instance->addResourceDirInternal(QString::fromLatin1(type), dir, priority);
 
326
}
 
327
 
 
328
QString KoResourcePaths::findResource(const char *type, const QString &fileName)
 
329
{
 
330
    return s_instance->findResourceInternal(QString::fromLatin1(type), fileName);
 
331
}
 
332
 
 
333
QStringList KoResourcePaths::findDirs(const char *type, const QString &reldir)
 
334
{
 
335
    return s_instance->findDirsInternal(QString::fromLatin1(type), reldir);
 
336
}
 
337
 
 
338
QStringList KoResourcePaths::findAllResources(const char *type,
 
339
                                              const QString &filter,
 
340
                                              SearchOptions options)
 
341
{
 
342
    return s_instance->findAllResourcesInternal(QString::fromLatin1(type), filter, options);
 
343
}
 
344
 
 
345
QStringList KoResourcePaths::resourceDirs(const char *type)
 
346
{
 
347
    return s_instance->resourceDirsInternal(QString::fromLatin1(type));
 
348
}
 
349
 
 
350
QString KoResourcePaths::saveLocation(const char *type, const QString &suffix, bool create)
 
351
{
 
352
    return s_instance->saveLocationInternal(QString::fromLatin1(type), suffix, create);
 
353
}
 
354
 
 
355
QString KoResourcePaths::locate(const char *type, const QString &filename)
 
356
{
 
357
    return s_instance->findResourceInternal(QString::fromLatin1(type), filename);
 
358
}
 
359
 
 
360
QString KoResourcePaths::locateLocal(const char *type, const QString &filename, bool createDir)
 
361
{
 
362
    return s_instance->locateLocalInternal(QString::fromLatin1(type), filename, createDir);
 
363
}