~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/corelib/io/qresource.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the core module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include <qset.h>
 
30
#include <qhash.h>
 
31
#include <qlocale.h>
 
32
#include <qglobal.h>
 
33
#include <qdatetime.h>
 
34
#include <qbytearray.h>
 
35
#include <qstringlist.h>
 
36
#include <qvector.h>
 
37
#include <private/qfileengine_p.h>
 
38
 
 
39
#include "qresource_p.h"
 
40
 
 
41
//resource glue
 
42
class QResource
 
43
{
 
44
    enum Flags
 
45
    {
 
46
        Compressed = 0x01,
 
47
        Directory = 0x02
 
48
    };
 
49
    const uchar *tree, *names, *payloads;
 
50
    int findNode(const QString &path) const;
 
51
    inline int findOffset(int node) const { return node * 14; } //sizeof each tree element
 
52
    inline int hash(int offset) const;
 
53
    inline QString name(int offset) const;
 
54
public:
 
55
    inline QResource(): tree(0), names(0), payloads(0) {}
 
56
    inline QResource(const uchar *t, const uchar *n, const uchar *d)
 
57
        : tree(t), names(n), payloads(d) {}
 
58
    bool isContainer(const QString &path) const;
 
59
    bool exists(const QString &path) const;
 
60
    QByteArray data(const QString &path) const;
 
61
    QStringList children(const QString &path) const;
 
62
    inline bool operator==(const QResource &other) const
 
63
    { return tree == other.tree && names == other.names && payloads == other.payloads; }
 
64
    inline bool operator!=(const QResource &other) const
 
65
    { return !operator==(other); }
 
66
};
 
67
 
 
68
Q_DECLARE_TYPEINFO(QResource, Q_MOVABLE_TYPE);
 
69
 
 
70
inline int QResource::hash(int node) const
 
71
{
 
72
    if(!node) //root
 
73
        return 0;
 
74
    const int offset = findOffset(node);
 
75
    int name_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
76
                      (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
77
    name_offset += 2; //jump past name length
 
78
    return (names[name_offset+0] << 24) + (names[name_offset+1] << 16) +
 
79
           (names[name_offset+2] << 8) + (names[name_offset+3] << 0);
 
80
}
 
81
inline QString QResource::name(int node) const
 
82
{
 
83
    if(!node) // root
 
84
        return QString();
 
85
    const int offset = findOffset(node);
 
86
 
 
87
    QString ret;
 
88
    int name_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
89
                      (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
90
    const short name_length = (names[name_offset+0] << 8) +
 
91
                              (names[name_offset+1] << 0);
 
92
    name_offset += 2;
 
93
    name_offset += 4; //jump past hash
 
94
    for(int i = 0; i < name_length*2; i+=2)
 
95
        ret += QChar(names[name_offset+i+1], names[name_offset+i]);
 
96
    return ret;
 
97
}
 
98
int QResource::findNode(const QString &path) const
 
99
{
 
100
    if(path == QLatin1String("/"))
 
101
        return 0;
 
102
 
 
103
    //the root node is always first
 
104
    int child_count = (tree[6] << 24) + (tree[7] << 16) +
 
105
                      (tree[8] << 8) + (tree[9] << 0);
 
106
    int child       = (tree[10] << 24) + (tree[11] << 16) +
 
107
                      (tree[12] << 8) + (tree[13] << 0);
 
108
 
 
109
    //now iterate up the tree
 
110
    int node = -1;
 
111
    QLocale locale;
 
112
    QStringList segments = path.split('/', QString::SkipEmptyParts);
 
113
    for(int i = 0; child_count && i < segments.size(); ++i) {
 
114
        const QString &segment = segments[i];
 
115
        const int h = qHash(segment);
 
116
 
 
117
        //do the binary search for the hash
 
118
        int l = 0, r = child_count-1;
 
119
        int sub_node = (l+r+1)/2;
 
120
        while(r != l) {
 
121
            const int sub_node_hash = hash(child+sub_node);
 
122
            if(h == sub_node_hash)
 
123
                break;
 
124
            else if(h < sub_node_hash)
 
125
                r = sub_node - 1;
 
126
            else
 
127
                l = sub_node;
 
128
            sub_node = (l + r + 1) / 2;
 
129
        }
 
130
        sub_node += child;
 
131
 
 
132
        //now do the "harder" compares
 
133
        bool found = false;
 
134
        if(hash(sub_node) == h) {
 
135
            while(sub_node > child && hash(sub_node-1) == h) //backup for collisions
 
136
                --sub_node;
 
137
            for(; sub_node < child+child_count && hash(sub_node) == h; ++sub_node) { //here we go...
 
138
                if(name(sub_node) == segment) {
 
139
                    found = true;
 
140
                    int offset = findOffset(sub_node) + 4; //jump past name
 
141
 
 
142
                    const short flags = (tree[offset+0] << 8) +
 
143
                                        (tree[offset+1] << 0);
 
144
                    offset += 2;
 
145
 
 
146
                    if(i == segments.size()-1) {
 
147
                        if(!(flags & Directory)) {
 
148
                            const short country = (tree[offset+0] << 8) +
 
149
                                                  (tree[offset+1] << 0);
 
150
                            offset += 2;
 
151
 
 
152
                            const short language = (tree[offset+0] << 8) +
 
153
                                                   (tree[offset+1] << 0);
 
154
                            offset += 2;
 
155
 
 
156
                            if(country == locale.country() && language == locale.language())
 
157
                                return sub_node;
 
158
                            else if((country == QLocale::AnyCountry && language == locale.language()) ||
 
159
                                    (country == QLocale::AnyCountry && language == QLocale::C && node == -1))
 
160
                                node = sub_node;
 
161
                            continue;
 
162
                        } else {
 
163
                            return sub_node;
 
164
                        }
 
165
                    }
 
166
 
 
167
                    if(!(flags & Directory))
 
168
                        return -1;
 
169
 
 
170
                    child_count = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
171
                                  (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
172
                    offset += 4;
 
173
                    child = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
174
                            (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
175
                    break;
 
176
                }
 
177
            }
 
178
        }
 
179
        if(!found)
 
180
            break;
 
181
    }
 
182
    return node;
 
183
}
 
184
bool QResource::isContainer(const QString &path) const
 
185
{
 
186
    int node = findNode(path);
 
187
    if(node == -1)
 
188
        return false;
 
189
    const int offset = findOffset(node) + 4; //jump past name
 
190
    const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0);
 
191
    return flags & Directory;
 
192
}
 
193
bool QResource::exists(const QString &path) const
 
194
{
 
195
    return findNode(path) != -1;
 
196
}
 
197
QByteArray QResource::data(const QString &path) const
 
198
{
 
199
    const int node = findNode(path);
 
200
    if(node == -1)
 
201
        return QByteArray();
 
202
    int offset = findOffset(node) + 4; //jump past name
 
203
 
 
204
    const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0);
 
205
    offset += 2;
 
206
 
 
207
    offset += 4; //jump past locale
 
208
 
 
209
    QByteArray ret;
 
210
    if(!(flags & Directory)) {
 
211
        const int data_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
212
                                (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
213
        const uint data_length = (payloads[data_offset+0] << 24) + (payloads[data_offset+1] << 16) +
 
214
                                 (payloads[data_offset+2] << 8) + (payloads[data_offset+3] << 0);
 
215
        const uchar *data = payloads+data_offset+4;
 
216
        if(flags & Compressed)
 
217
            ret = qUncompress(data, data_length);
 
218
        else
 
219
            ret = QByteArray((char*)data, data_length);
 
220
    }
 
221
    return ret;
 
222
}
 
223
QStringList QResource::children(const QString &path) const
 
224
{
 
225
    int node = findNode(path);
 
226
    if(node == -1)
 
227
        return QStringList();
 
228
    int offset = findOffset(node) + 4; //jump past name
 
229
 
 
230
    const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0);
 
231
    offset += 2;
 
232
 
 
233
    QStringList ret;
 
234
    if(flags & Directory) {
 
235
        const int child_count = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
236
                                (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
237
        offset += 4;
 
238
        const int child_off = (tree[offset+0] << 24) + (tree[offset+1] << 16) +
 
239
                              (tree[offset+2] << 8) + (tree[offset+3] << 0);
 
240
        for(int i = child_off; i < child_off+child_count; ++i)
 
241
            ret << name(i);
 
242
    }
 
243
    return ret;
 
244
}
 
245
 
 
246
Q_GLOBAL_STATIC(QStringList, qt_resource_search_paths)
 
247
bool qt_resource_add_search_path(const QString &path)
 
248
{
 
249
    if(path[0] != QLatin1Char('/')) {
 
250
        qWarning("QDir::addResourceSearchPath: Search paths must be absolute (start with /) [%s]",
 
251
                 path.toLocal8Bit().data());
 
252
        return false;
 
253
    }
 
254
    qt_resource_search_paths()->prepend(path);
 
255
    return true;
 
256
}
 
257
 
 
258
typedef QVector<QResource> ResourceList;
 
259
Q_GLOBAL_STATIC(ResourceList, resourceList)
 
260
 
 
261
class QResourceInfo
 
262
{
 
263
    QString file, searchFile;
 
264
    ResourceList related;
 
265
    uint container : 1;
 
266
 
 
267
    mutable uint hasData : 1;
 
268
    mutable QByteArray mData;
 
269
 
 
270
    mutable uint hasChildren : 1;
 
271
    mutable QStringList mChildren;
 
272
 
 
273
    inline void clear() {
 
274
        searchFile.clear();
 
275
        file.clear();
 
276
        hasData = hasChildren = 0;
 
277
        container = 0;
 
278
        related.clear();
 
279
    }
 
280
    bool loadResource(const QString &);
 
281
public:
 
282
    QResourceInfo() { clear(); }
 
283
    QResourceInfo(const QString &f) { setFileName(f); }
 
284
 
 
285
    void setFileName(const QString &f);
 
286
    QString fileName() const { return file; }
 
287
    QString searchFileName() const { return searchFile; }
 
288
 
 
289
    bool exists() const { return !related.isEmpty(); }
 
290
    bool isContainer() const { return container; }
 
291
    QByteArray data() const;
 
292
    QStringList children() const;
 
293
};
 
294
bool
 
295
QResourceInfo::loadResource(const QString &path)
 
296
{
 
297
    const ResourceList *list = resourceList();
 
298
    for(int i = 0; i < list->size(); ++i) {
 
299
        QResource res = list->at(i);
 
300
        if(res.exists(path)) {
 
301
            if(related.isEmpty())
 
302
                container = res.isContainer(path);
 
303
            else if(res.isContainer(path) != container)
 
304
                qWarning("Resource [%s] has both data and children!", file.toLatin1().constData());
 
305
            related.append(res);
 
306
        }
 
307
    }
 
308
    return !related.isEmpty();
 
309
}
 
310
void
 
311
QResourceInfo::setFileName(const QString &f)
 
312
{
 
313
    if(file == f)
 
314
        return;
 
315
    clear();
 
316
    file = f;
 
317
    if(file == QLatin1String(":"))
 
318
        file += "/";
 
319
    searchFile = file;
 
320
 
 
321
    QString path = file;
 
322
    if(path.startsWith(QLatin1String(":")))
 
323
        path = path.mid(1);
 
324
    if(path[0] == QLatin1Char('/')) {
 
325
        loadResource(path);
 
326
        return;
 
327
    } else {
 
328
        QStringList searchPaths = *qt_resource_search_paths();
 
329
        searchPaths << QLatin1String("");
 
330
        for(int i = 0; i < searchPaths.size(); ++i) {
 
331
            const QString searchPath(searchPaths.at(i) + "/" + path);
 
332
            if(loadResource(searchPath)) {
 
333
                searchFile = ":" + searchPath;
 
334
                break;
 
335
            }
 
336
        }
 
337
    }
 
338
}
 
339
QByteArray QResourceInfo::data() const
 
340
{
 
341
    if(container || related.isEmpty())
 
342
        return QByteArray();
 
343
 
 
344
    if(!hasData) {
 
345
        hasData = true;
 
346
        QString path = searchFile;
 
347
        if(path.startsWith(":"))
 
348
            path = path.mid(1);
 
349
        mData = related.at(0).data(path);
 
350
    }
 
351
    return mData;
 
352
}
 
353
 
 
354
QStringList QResourceInfo::children() const
 
355
{
 
356
    if(!container || related.isEmpty())
 
357
        return QStringList();
 
358
 
 
359
    if(!hasChildren) {
 
360
        hasChildren = true;
 
361
        QString path = searchFile;
 
362
        if(path.startsWith(":"))
 
363
            path = path.mid(1);
 
364
        QSet<QString> kids;
 
365
        for(int i = 0; i < related.size(); ++i) {
 
366
            QStringList related_children = related.at(i).children(path);
 
367
            for(int kid = 0; kid < related_children.size(); ++kid) {
 
368
                QString k = related_children.at(kid);
 
369
                if(!kids.contains(k)) {
 
370
                    mChildren += k;
 
371
                    kids.insert(k);
 
372
                }
 
373
            }
 
374
        }
 
375
    }
 
376
    return mChildren;
 
377
}
 
378
 
 
379
Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
 
380
                                         const unsigned char *name, const unsigned char *data)
 
381
{
 
382
    if(version == 0x01) {
 
383
        QResource res(tree, name, data);
 
384
        if (!resourceList()->contains(res))
 
385
            resourceList()->append(res);
 
386
        return true;
 
387
    }
 
388
    return false;
 
389
}
 
390
 
 
391
//file type handler
 
392
class QResourceFileEngineHandler : public QFileEngineHandler
 
393
{
 
394
public:
 
395
    QResourceFileEngineHandler() { }
 
396
    ~QResourceFileEngineHandler() { }
 
397
    QFileEngine *createFileEngine(const QString &path);
 
398
};
 
399
QFileEngine *QResourceFileEngineHandler::createFileEngine(const QString &path)
 
400
{
 
401
    if (path.size() > 0 && path.startsWith(QLatin1String(":")))
 
402
        return new QResourceFileEngine(path);
 
403
    return 0;
 
404
}
 
405
 
 
406
//resource engine
 
407
class QResourceFileEnginePrivate : public QFileEnginePrivate
 
408
{
 
409
protected:
 
410
    Q_DECLARE_PUBLIC(QResourceFileEngine)
 
411
private:
 
412
    qint64 offset;
 
413
    QResourceInfo resource;
 
414
protected:
 
415
    QResourceFileEnginePrivate() : offset(0) { }
 
416
};
 
417
 
 
418
bool QResourceFileEngine::mkdir(const QString &, bool) const
 
419
{
 
420
    return false;
 
421
}
 
422
 
 
423
bool QResourceFileEngine::rmdir(const QString &, bool) const
 
424
{
 
425
    return false;
 
426
}
 
427
 
 
428
bool QResourceFileEngine::setSize(qint64)
 
429
{
 
430
    return false;
 
431
}
 
432
 
 
433
QStringList QResourceFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
 
434
{
 
435
    Q_D(const QResourceFileEngine);
 
436
 
 
437
    const bool doDirs     = (filters & QDir::Dirs) != 0;
 
438
    const bool doFiles    = (filters & QDir::Files) != 0;
 
439
    const bool doReadable = (filters & QDir::Readable) != 0;
 
440
 
 
441
    QStringList ret;
 
442
    if((!doDirs && !doFiles) || ((filters & QDir::PermissionMask) && !doReadable))
 
443
        return ret;
 
444
    if(!d->resource.exists() || !d->resource.isContainer())
 
445
        return ret; // cannot read the "directory"
 
446
 
 
447
    QStringList entries = d->resource.children();
 
448
    for(int i = 0; i < entries.size(); i++) {
 
449
        QResourceInfo entry(d->resource.fileName() + "/" + entries[i]);
 
450
#ifndef QT_NO_REGEXP
 
451
        if(!(filters & QDir::AllDirs && entry.isContainer())) {
 
452
            bool matched = false;
 
453
            for(QStringList::ConstIterator sit = filterNames.begin(); sit != filterNames.end(); ++sit) {
 
454
                QRegExp rx(*sit,
 
455
                           (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
 
456
                           QRegExp::Wildcard);
 
457
                if (rx.exactMatch(entries[i])) {
 
458
                    matched = true;
 
459
                    break;
 
460
                }
 
461
            }
 
462
            if(!matched)
 
463
                continue;
 
464
        }
 
465
#endif
 
466
        if  ((doDirs && entry.isContainer()) ||
 
467
             (doFiles && !entry.isContainer()))
 
468
            ret.append(entries[i]);
 
469
    }
 
470
    return ret;
 
471
}
 
472
 
 
473
bool QResourceFileEngine::caseSensitive() const
 
474
{
 
475
    return true;
 
476
}
 
477
 
 
478
QResourceFileEngine::QResourceFileEngine(const QString &file) :
 
479
    QFileEngine(*new QResourceFileEnginePrivate)
 
480
{
 
481
    Q_D(QResourceFileEngine);
 
482
    d->resource.setFileName(file);
 
483
}
 
484
 
 
485
QResourceFileEngine::~QResourceFileEngine()
 
486
{
 
487
}
 
488
 
 
489
void QResourceFileEngine::setFileName(const QString &file)
 
490
{
 
491
    Q_D(QResourceFileEngine);
 
492
    d->resource.setFileName(file);
 
493
}
 
494
 
 
495
bool QResourceFileEngine::open(int flags)
 
496
{
 
497
    Q_D(QResourceFileEngine);
 
498
    if (d->resource.fileName().isEmpty()) {
 
499
        qWarning("QFSFileEngine::open: No file name specified");
 
500
        return false;
 
501
    }
 
502
    if(flags & QIODevice::WriteOnly)
 
503
        return false;
 
504
    if(!d->resource.exists())
 
505
       return false;
 
506
    return true;
 
507
}
 
508
 
 
509
bool QResourceFileEngine::close()
 
510
{
 
511
    Q_D(QResourceFileEngine);
 
512
    d->offset = 0;
 
513
    return true;
 
514
}
 
515
 
 
516
void QResourceFileEngine::flush()
 
517
{
 
518
 
 
519
}
 
520
 
 
521
qint64 QResourceFileEngine::read(char *data, qint64 len)
 
522
{
 
523
    Q_D(QResourceFileEngine);
 
524
    if(len > d->resource.data().size()-d->offset)
 
525
        len = d->resource.data().size()-d->offset;
 
526
    if(len <= 0)
 
527
        return 0;
 
528
    memcpy(data, d->resource.data().constData()+d->offset, len);
 
529
    d->offset += len;
 
530
    return len;
 
531
}
 
532
 
 
533
qint64 QResourceFileEngine::write(const char *, qint64)
 
534
{
 
535
    return -1;
 
536
}
 
537
 
 
538
int QResourceFileEngine::ungetch(int)
 
539
{
 
540
    return -1;
 
541
}
 
542
 
 
543
bool QResourceFileEngine::remove()
 
544
{
 
545
    return false;
 
546
}
 
547
 
 
548
bool QResourceFileEngine::copy(const QString &)
 
549
{
 
550
    return false;
 
551
}
 
552
 
 
553
bool QResourceFileEngine::rename(const QString &)
 
554
{
 
555
    return false;
 
556
}
 
557
 
 
558
bool QResourceFileEngine::link(const QString &)
 
559
{
 
560
    return false;
 
561
}
 
562
 
 
563
qint64 QResourceFileEngine::size() const
 
564
{
 
565
    Q_D(const QResourceFileEngine);
 
566
    if(!d->resource.exists())
 
567
        return 0;
 
568
    return d->resource.data().size();
 
569
}
 
570
 
 
571
qint64 QResourceFileEngine::at() const
 
572
{
 
573
    Q_D(const QResourceFileEngine);
 
574
    return d->offset;
 
575
}
 
576
 
 
577
bool QResourceFileEngine::atEnd() const
 
578
{
 
579
    Q_D(const QResourceFileEngine);
 
580
    if(!d->resource.exists())
 
581
        return true;
 
582
    return d->offset == d->resource.data().size();
 
583
}
 
584
 
 
585
bool QResourceFileEngine::seek(qint64 pos)
 
586
{
 
587
    Q_D(QResourceFileEngine);
 
588
    if(!d->resource.exists())
 
589
        return false;
 
590
 
 
591
    if(d->offset > d->resource.data().size())
 
592
        return false;
 
593
    d->offset = pos;
 
594
    return true;
 
595
}
 
596
 
 
597
bool QResourceFileEngine::isSequential() const
 
598
{
 
599
    return false;
 
600
}
 
601
 
 
602
QFileEngine::FileFlags QResourceFileEngine::fileFlags(QFileEngine::FileFlags type) const
 
603
{
 
604
    Q_D(const QResourceFileEngine);
 
605
    QFileEngine::FileFlags ret = 0;
 
606
    if(!d->resource.exists())
 
607
        return ret;
 
608
    if(type & PermsMask)
 
609
        ret |= QFileEngine::FileFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm);
 
610
    if(type & TypesMask) {
 
611
        if(d->resource.isContainer())
 
612
            ret |= DirectoryType;
 
613
        else
 
614
            ret |= FileType;
 
615
    }
 
616
    if(type & FlagsMask) {
 
617
        ret |= ExistsFlag;
 
618
        if(d->resource.fileName() == QLatin1String(":/"))
 
619
            ret |= RootFlag;
 
620
    }
 
621
    return ret;
 
622
}
 
623
 
 
624
bool QResourceFileEngine::chmod(uint)
 
625
{
 
626
    return false;
 
627
}
 
628
 
 
629
QString QResourceFileEngine::fileName(FileName file) const
 
630
{
 
631
    Q_D(const QResourceFileEngine);
 
632
    if(file == BaseName) {
 
633
        int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/'));
 
634
        if (slash == -1)
 
635
            return d->resource.fileName();
 
636
        return d->resource.fileName().mid(slash + 1);
 
637
    } else if(file == PathName || file == AbsolutePathName) {
 
638
        const int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/'));
 
639
        if (slash != -1)
 
640
            return d->resource.fileName().left(slash);
 
641
    } else if(file == CanonicalName || file == CanonicalPathName) {
 
642
        const QString canonicalPath = d->resource.searchFileName();
 
643
        if(file == CanonicalPathName) {
 
644
            const int slash = canonicalPath.lastIndexOf(QLatin1Char('/'));
 
645
            if (slash != -1)
 
646
                return canonicalPath.left(slash);
 
647
        }
 
648
        return canonicalPath;
 
649
    }
 
650
    return d->resource.fileName();
 
651
}
 
652
 
 
653
bool QResourceFileEngine::isRelativePath() const
 
654
{
 
655
    return false;
 
656
}
 
657
 
 
658
uint QResourceFileEngine::ownerId(FileOwner) const
 
659
{
 
660
    static const uint nobodyID = (uint) -2;
 
661
    return nobodyID;
 
662
}
 
663
 
 
664
QString QResourceFileEngine::owner(FileOwner) const
 
665
{
 
666
    return QString();
 
667
}
 
668
 
 
669
QDateTime QResourceFileEngine::fileTime(FileTime) const
 
670
{
 
671
    return QDateTime();
 
672
}
 
673
 
 
674
QFileEngine::Type QResourceFileEngine::type() const
 
675
{
 
676
    return QFileEngine::Resource;
 
677
}
 
678
 
 
679
//Initialization and cleanup
 
680
Q_GLOBAL_STATIC(QResourceFileEngineHandler, resource_file_handler)
 
681
 
 
682
static int qt_force_resource_init() { resource_file_handler(); return 1; }
 
683
Q_CORE_EXPORT void qInitResourceIO() { resource_file_handler(); }
 
684
static int qt_forced_resource_init = qt_force_resource_init();
 
685
Q_CONSTRUCTOR_FUNCTION(qt_force_resource_init)
 
686