Speed up sorting of dir entries when sorted by date
[profile/ivi/qtbase.git] / src / corelib / io / qdir.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qplatformdefs.h"
43 #include "qdir.h"
44 #include "qdir_p.h"
45 #include "qabstractfileengine_p.h"
46 #include "qfsfileengine_p.h"
47 #ifndef QT_NO_DEBUG_STREAM
48 #include "qdebug.h"
49 #endif
50 #include "qdiriterator.h"
51 #include "qdatetime.h"
52 #include "qstring.h"
53 #include "qregexp.h"
54 #include "qvector.h"
55 #include "qalgorithms.h"
56 #include "qvarlengtharray.h"
57 #include "qfilesystementry_p.h"
58 #include "qfilesystemmetadata_p.h"
59 #include "qfilesystemengine_p.h"
60 #include <qstringbuilder.h>
61
62 #ifdef QT_BUILD_CORE_LIB
63 #  include "qresource.h"
64 #  include "private/qcoreglobaldata_p.h"
65 #endif
66
67 #include <stdlib.h>
68
69 QT_BEGIN_NAMESPACE
70
71 #if defined(Q_OS_WIN)
72 static QString driveSpec(const QString &path)
73 {
74     if (path.size() < 2)
75         return QString();
76     char c = path.at(0).toLatin1();
77     if (c < 'a' && c > 'z' && c < 'A' && c > 'Z')
78         return QString();
79     if (path.at(1).toLatin1() != ':')
80         return QString();
81     return path.mid(0, 2);
82 }
83 #endif
84
85 //************* QDirPrivate
86 QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_, QDir::SortFlags sort_, QDir::Filters filters_)
87     : QSharedData()
88     , nameFilters(nameFilters_)
89     , sort(sort_)
90     , filters(filters_)
91     , fileListsInitialized(false)
92 {
93     setPath(path.isEmpty() ? QString::fromLatin1(".") : path);
94
95     bool empty = nameFilters.isEmpty();
96     if (!empty) {
97         empty = true;
98         for (int i = 0; i < nameFilters.size(); ++i) {
99             if (!nameFilters.at(i).isEmpty()) {
100                 empty = false;
101                 break;
102             }
103         }
104     }
105     if (empty)
106         nameFilters = QStringList(QString::fromLatin1("*"));
107 }
108
109 QDirPrivate::QDirPrivate(const QDirPrivate &copy)
110     : QSharedData(copy)
111     , nameFilters(copy.nameFilters)
112     , sort(copy.sort)
113     , filters(copy.filters)
114     , fileListsInitialized(false)
115     , dirEntry(copy.dirEntry)
116     , metaData(copy.metaData)
117 {
118 }
119
120 bool QDirPrivate::exists() const
121 {
122     if (fileEngine.isNull()) {
123         QFileSystemEngine::fillMetaData(dirEntry, metaData,
124                 QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); // always stat
125         return metaData.exists() && metaData.isDirectory();
126     }
127     const QAbstractFileEngine::FileFlags info =
128         fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
129                                        | QAbstractFileEngine::ExistsFlag
130                                        | QAbstractFileEngine::Refresh);
131     if (!(info & QAbstractFileEngine::DirectoryType))
132         return false;
133     return info & QAbstractFileEngine::ExistsFlag;
134 }
135
136 // static
137 inline QChar QDirPrivate::getFilterSepChar(const QString &nameFilter)
138 {
139     QChar sep(QLatin1Char(';'));
140     int i = nameFilter.indexOf(sep, 0);
141     if (i == -1 && nameFilter.indexOf(QLatin1Char(' '), 0) != -1)
142         sep = QChar(QLatin1Char(' '));
143     return sep;
144 }
145
146 // static
147 inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar sep)
148 {
149     if (sep == 0)
150         sep = getFilterSepChar(nameFilter);
151     QStringList ret = nameFilter.split(sep);
152     for (int i = 0; i < ret.count(); ++i)
153         ret[i] = ret[i].trimmed();
154     return ret;
155 }
156
157 inline void QDirPrivate::setPath(const QString &path)
158 {
159     QString p = QDir::fromNativeSeparators(path);
160     if (p.endsWith(QLatin1Char('/'))
161             && p.length() > 1
162 #if defined(Q_OS_WIN)
163         && (!(p.length() == 3 && p.at(1).unicode() == ':' && p.at(0).isLetter()))
164 #endif
165     ) {
166             p.truncate(p.length() - 1);
167     }
168
169     dirEntry = QFileSystemEntry(p, QFileSystemEntry::FromInternalPath());
170     metaData.clear();
171     initFileEngine();
172     clearFileLists();
173     absoluteDirEntry = QFileSystemEntry();
174 }
175
176 inline void QDirPrivate::clearFileLists()
177 {
178     fileListsInitialized = false;
179     files.clear();
180     fileInfos.clear();
181 }
182
183 inline void QDirPrivate::resolveAbsoluteEntry() const
184 {
185     if (!absoluteDirEntry.isEmpty() || dirEntry.isEmpty())
186         return;
187
188     QString absoluteName;
189     if (fileEngine.isNull()) {
190         if (!dirEntry.isRelative() && dirEntry.isClean()) {
191             absoluteDirEntry = dirEntry;
192             return;
193         }
194
195         absoluteName = QFileSystemEngine::absoluteName(dirEntry).filePath();
196     } else {
197         absoluteName = fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
198     }
199
200     absoluteDirEntry = QFileSystemEntry(QDir::cleanPath(absoluteName), QFileSystemEntry::FromInternalPath());
201 }
202
203 /* For sorting */
204 struct QDirSortItem
205 {
206     mutable QString filename_cache;
207     mutable QString suffix_cache;
208     QFileInfo item;
209 };
210
211
212 class QDirSortItemComparator
213 {
214     int qt_cmp_si_sort_flags;
215 public:
216     QDirSortItemComparator(int flags) : qt_cmp_si_sort_flags(flags) {}
217     bool operator()(const QDirSortItem &, const QDirSortItem &);
218 };
219
220 bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortItem &n2)
221 {
222     const QDirSortItem* f1 = &n1;
223     const QDirSortItem* f2 = &n2;
224
225     if ((qt_cmp_si_sort_flags & QDir::DirsFirst) && (f1->item.isDir() != f2->item.isDir()))
226         return f1->item.isDir();
227     if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir()))
228         return !f1->item.isDir();
229
230     int r = 0;
231     int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask)
232                  | (qt_cmp_si_sort_flags & QDir::Type);
233
234     switch (sortBy) {
235       case QDir::Time: {
236         QDateTime firstModified = f1->item.lastModified();
237         QDateTime secondModified = f2->item.lastModified();
238
239         // QDateTime by default will do all sorts of conversions on these to
240         // find timezones, which is incredibly expensive. As we aren't
241         // presenting these to the user, we don't care (at all) about the
242         // local timezone, so force them to UTC to avoid that conversion.
243         firstModified.setTimeSpec(Qt::UTC);
244         secondModified.setTimeSpec(Qt::UTC);
245
246         r = firstModified.secsTo(secondModified);
247         break;
248       }
249       case QDir::Size:
250           r = int(qBound<qint64>(-1, f2->item.size() - f1->item.size(), 1));
251         break;
252       case QDir::Type:
253       {
254         bool ic = qt_cmp_si_sort_flags & QDir::IgnoreCase;
255
256         if (f1->suffix_cache.isNull())
257             f1->suffix_cache = ic ? f1->item.suffix().toLower()
258                                : f1->item.suffix();
259         if (f2->suffix_cache.isNull())
260             f2->suffix_cache = ic ? f2->item.suffix().toLower()
261                                : f2->item.suffix();
262
263         r = qt_cmp_si_sort_flags & QDir::LocaleAware
264             ? f1->suffix_cache.localeAwareCompare(f2->suffix_cache)
265             : f1->suffix_cache.compare(f2->suffix_cache);
266       }
267         break;
268       default:
269         ;
270     }
271
272     if (r == 0 && sortBy != QDir::Unsorted) {
273         // Still not sorted - sort by name
274         bool ic = qt_cmp_si_sort_flags & QDir::IgnoreCase;
275
276         if (f1->filename_cache.isNull())
277             f1->filename_cache = ic ? f1->item.fileName().toLower()
278                                     : f1->item.fileName();
279         if (f2->filename_cache.isNull())
280             f2->filename_cache = ic ? f2->item.fileName().toLower()
281                                     : f2->item.fileName();
282
283         r = qt_cmp_si_sort_flags & QDir::LocaleAware
284             ? f1->filename_cache.localeAwareCompare(f2->filename_cache)
285             : f1->filename_cache.compare(f2->filename_cache);
286     }
287     if (r == 0) // Enforce an order - the order the items appear in the array
288         r = (&n1) - (&n2);
289     if (qt_cmp_si_sort_flags & QDir::Reversed)
290         return r > 0;
291     return r < 0;
292 }
293
294 inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QFileInfoList &l,
295                                       QStringList *names, QFileInfoList *infos)
296 {
297     // names and infos are always empty lists or 0 here
298     int n = l.size();
299     if (n > 0) {
300         if (n == 1 || (sort & QDir::SortByMask) == QDir::Unsorted) {
301             if (infos)
302                 *infos = l;
303             if (names) {
304                 for (int i = 0; i < n; ++i)
305                     names->append(l.at(i).fileName());
306             }
307         } else {
308             QScopedArrayPointer<QDirSortItem> si(new QDirSortItem[n]);
309             for (int i = 0; i < n; ++i)
310                 si[i].item = l.at(i);
311             qSort(si.data(), si.data() + n, QDirSortItemComparator(sort));
312             // put them back in the list(s)
313             if (infos) {
314                 for (int i = 0; i < n; ++i)
315                     infos->append(si[i].item);
316             }
317             if (names) {
318                 for (int i = 0; i < n; ++i)
319                     names->append(si[i].item.fileName());
320             }
321         }
322     }
323 }
324 inline void QDirPrivate::initFileLists(const QDir &dir) const
325 {
326     if (!fileListsInitialized) {
327         QFileInfoList l;
328         QDirIterator it(dir);
329         while (it.hasNext()) {
330             it.next();
331             l.append(it.fileInfo());
332         }
333         sortFileList(sort, l, &files, &fileInfos);
334         fileListsInitialized = true;
335     }
336 }
337
338 inline void QDirPrivate::initFileEngine()
339 {
340     fileEngine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData));
341 }
342
343 /*!
344     \class QDir
345     \brief The QDir class provides access to directory structures and their contents.
346
347     \ingroup io
348     \ingroup shared
349     \reentrant
350
351
352     A QDir is used to manipulate path names, access information
353     regarding paths and files, and manipulate the underlying file
354     system. It can also be used to access Qt's \l{resource system}.
355
356     Qt uses "/" as a universal directory separator in the same way
357     that "/" is used as a path separator in URLs. If you always use
358     "/" as a directory separator, Qt will translate your paths to
359     conform to the underlying operating system.
360
361     A QDir can point to a file using either a relative or an absolute
362     path. Absolute paths begin with the directory separator
363     (optionally preceded by a drive specification under Windows).
364     Relative file names begin with a directory name or a file name and
365     specify a path relative to the current directory.
366
367     Examples of absolute paths:
368
369     \snippet code/src_corelib_io_qdir.cpp 0
370
371     On Windows, the second example above will be translated to
372     \c{C:\Documents and Settings} when used to access files.
373
374     Examples of relative paths:
375
376     \snippet code/src_corelib_io_qdir.cpp 1
377
378     You can use the isRelative() or isAbsolute() functions to check if
379     a QDir is using a relative or an absolute file path. Call
380     makeAbsolute() to convert a relative QDir to an absolute one.
381
382     \section1 Navigation and Directory Operations
383
384     A directory's path can be obtained with the path() function, and
385     a new path set with the setPath() function. The absolute path to
386     a directory is found by calling absolutePath().
387
388     The name of a directory is found using the dirName() function. This
389     typically returns the last element in the absolute path that specifies
390     the location of the directory. However, it can also return "." if
391     the QDir represents the current directory.
392
393     \snippet code/src_corelib_io_qdir.cpp 2
394
395     The path for a directory can also be changed with the cd() and cdUp()
396     functions, both of which operate like familiar shell commands.
397     When cd() is called with the name of an existing directory, the QDir
398     object changes directory so that it represents that directory instead.
399     The cdUp() function changes the directory of the QDir object so that
400     it refers to its parent directory; i.e. cd("..") is equivalent to
401     cdUp().
402
403     Directories can be created with mkdir(), renamed with rename(), and
404     removed with rmdir().
405
406     You can test for the presence of a directory with a given name by
407     using exists(), and the properties of a directory can be tested with
408     isReadable(), isAbsolute(), isRelative(), and isRoot().
409
410     The refresh() function re-reads the directory's data from disk.
411
412     \section1 Files and Directory Contents
413
414     Directories contain a number of entries, representing files,
415     directories, and symbolic links. The number of entries in a
416     directory is returned by count().
417     A string list of the names of all the entries in a directory can be
418     obtained with entryList(). If you need information about each
419     entry, use entryInfoList() to obtain a list of QFileInfo objects.
420
421     Paths to files and directories within a directory can be
422     constructed using filePath() and absoluteFilePath().
423     The filePath() function returns a path to the specified file
424     or directory relative to the path of the QDir object;
425     absoluteFilePath() returns an absolute path to the specified
426     file or directory. Neither of these functions checks for the
427     existence of files or directory; they only construct paths.
428
429     \snippet code/src_corelib_io_qdir.cpp 3
430
431     Files can be removed by using the remove() function. Directories
432     cannot be removed in the same way as files; use rmdir() to remove
433     them instead.
434
435     It is possible to reduce the number of entries returned by
436     entryList() and entryInfoList() by applying filters to a QDir object.
437     You can apply a name filter to specify a pattern with wildcards that
438     file names need to match, an attribute filter that selects properties
439     of entries and can distinguish between files and directories, and a
440     sort order.
441
442     Name filters are lists of strings that are passed to setNameFilters().
443     Attribute filters consist of a bitwise OR combination of Filters, and
444     these are specified when calling setFilter().
445     The sort order is specified using setSorting() with a bitwise OR
446     combination of SortFlags.
447
448     You can test to see if a filename matches a filter using the match()
449     function.
450
451     Filter and sort order flags may also be specified when calling
452     entryList() and entryInfoList() in order to override previously defined
453     behavior.
454
455     \section1 The Current Directory and Other Special Paths
456
457     Access to some common directories is provided with a number of static
458     functions that return QDir objects. There are also corresponding functions
459     for these that return strings:
460
461     \table
462     \header \li QDir      \li QString         \li Return Value
463     \row    \li current() \li currentPath()   \li The application's working directory
464     \row    \li home()    \li homePath()      \li The user's home directory
465     \row    \li root()    \li rootPath()      \li The root directory
466     \row    \li temp()    \li tempPath()      \li The system's temporary directory
467     \endtable
468
469     The setCurrent() static function can also be used to set the application's
470     working directory.
471
472     If you want to find the directory containing the application's executable,
473     see \l{QCoreApplication::applicationDirPath()}.
474
475     The drives() static function provides a list of root directories for each
476     device that contains a filing system. On Unix systems this returns a list
477     containing a single root directory "/"; on Windows the list will usually
478     contain \c{C:/}, and possibly other drive letters such as \c{D:/}, depending
479     on the configuration of the user's system.
480
481     \section1 Path Manipulation and Strings
482
483     Paths containing "." elements that reference the current directory at that
484     point in the path, ".." elements that reference the parent directory, and
485     symbolic links can be reduced to a canonical form using the canonicalPath()
486     function.
487
488     Paths can also be simplified by using cleanPath() to remove redundant "/"
489     and ".." elements.
490
491     It is sometimes necessary to be able to show a path in the native
492     representation for the user's platform. The static toNativeSeparators()
493     function returns a copy of the specified path in which each directory
494     separator is replaced by the appropriate separator for the underlying
495     operating system.
496
497     \section1 Examples
498
499     Check if a directory exists:
500
501     \snippet code/src_corelib_io_qdir.cpp 4
502
503     (We could also use the static convenience function
504     QFile::exists().)
505
506     Traversing directories and reading a file:
507
508     \snippet code/src_corelib_io_qdir.cpp 5
509
510     A program that lists all the files in the current directory
511     (excluding symbolic links), sorted by size, smallest first:
512
513     \snippet qdir-listfiles/main.cpp 0
514
515     \sa QFileInfo, QFile, QFileDialog, QCoreApplication::applicationDirPath(), {Find Files Example}
516 */
517
518 /*!
519     \internal
520 */
521 QDir::QDir(QDirPrivate &p) : d_ptr(&p)
522 {
523 }
524
525 /*!
526     Constructs a QDir pointing to the given directory \a path. If path
527     is empty the program's working directory, ("."), is used.
528
529     \sa currentPath()
530 */
531 QDir::QDir(const QString &path) : d_ptr(new QDirPrivate(path))
532 {
533 }
534
535 /*!
536     Constructs a QDir with path \a path, that filters its entries by
537     name using \a nameFilter and by attributes using \a filters. It
538     also sorts the names using \a sort.
539
540     The default \a nameFilter is an empty string, which excludes
541     nothing; the default \a filters is \l AllEntries, which also means
542     exclude nothing. The default \a sort is \l Name | \l IgnoreCase,
543     i.e. sort by name case-insensitively.
544
545     If \a path is an empty string, QDir uses "." (the current
546     directory). If \a nameFilter is an empty string, QDir uses the
547     name filter "*" (all files).
548
549     Note that \a path need not exist.
550
551     \sa exists(), setPath(), setNameFilters(), setFilter(), setSorting()
552 */
553 QDir::QDir(const QString &path, const QString &nameFilter,
554            SortFlags sort, Filters filters)
555     : d_ptr(new QDirPrivate(path, QDir::nameFiltersFromString(nameFilter), sort, filters))
556 {
557 }
558
559 /*!
560     Constructs a QDir object that is a copy of the QDir object for
561     directory \a dir.
562
563     \sa operator=()
564 */
565 QDir::QDir(const QDir &dir)
566     : d_ptr(dir.d_ptr)
567 {
568 }
569
570 /*!
571     Destroys the QDir object frees up its resources. This has no
572     effect on the underlying directory in the file system.
573 */
574 QDir::~QDir()
575 {
576 }
577
578 /*!
579     Sets the path of the directory to \a path. The path is cleaned of
580     redundant ".", ".." and of multiple separators. No check is made
581     to see whether a directory with this path actually exists; but you
582     can check for yourself using exists().
583
584     The path can be either absolute or relative. Absolute paths begin
585     with the directory separator "/" (optionally preceded by a drive
586     specification under Windows). Relative file names begin with a
587     directory name or a file name and specify a path relative to the
588     current directory. An example of an absolute path is the string
589     "/tmp/quartz", a relative path might look like "src/fatlib".
590
591     \sa path(), absolutePath(), exists(), cleanPath(), dirName(),
592       absoluteFilePath(), isRelative(), makeAbsolute()
593 */
594 void QDir::setPath(const QString &path)
595 {
596     d_ptr->setPath(path);
597 }
598
599 /*!
600     Returns the path. This may contain symbolic links, but never
601     contains redundant ".", ".." or multiple separators.
602
603     The returned path can be either absolute or relative (see
604     setPath()).
605
606     \sa setPath(), absolutePath(), exists(), cleanPath(), dirName(),
607     absoluteFilePath(), toNativeSeparators(), makeAbsolute()
608 */
609 QString QDir::path() const
610 {
611     const QDirPrivate* d = d_ptr.constData();
612     return d->dirEntry.filePath();
613 }
614
615 /*!
616     Returns the absolute path (a path that starts with "/" or with a
617     drive specification), which may contain symbolic links, but never
618     contains redundant ".", ".." or multiple separators.
619
620     \sa setPath(), canonicalPath(), exists(), cleanPath(),
621     dirName(), absoluteFilePath()
622 */
623 QString QDir::absolutePath() const
624 {
625     const QDirPrivate* d = d_ptr.constData();
626     d->resolveAbsoluteEntry();
627     return d->absoluteDirEntry.filePath();
628 }
629
630 /*!
631     Returns the canonical path, i.e. a path without symbolic links or
632     redundant "." or ".." elements.
633
634     On systems that do not have symbolic links this function will
635     always return the same string that absolutePath() returns. If the
636     canonical path does not exist (normally due to dangling symbolic
637     links) canonicalPath() returns an empty string.
638
639     Example:
640
641     \snippet code/src_corelib_io_qdir.cpp 6
642
643     \sa path(), absolutePath(), exists(), cleanPath(), dirName(),
644         absoluteFilePath()
645 */
646 QString QDir::canonicalPath() const
647 {
648     const QDirPrivate* d = d_ptr.constData();
649     if (d->fileEngine.isNull()) {
650         QFileSystemEntry answer = QFileSystemEngine::canonicalName(d->dirEntry, d->metaData);
651         return answer.filePath();
652     }
653     return d->fileEngine->fileName(QAbstractFileEngine::CanonicalName);
654 }
655
656 /*!
657     Returns the name of the directory; this is \e not the same as the
658     path, e.g. a directory with the name "mail", might have the path
659     "/var/spool/mail". If the directory has no name (e.g. it is the
660     root directory) an empty string is returned.
661
662     No check is made to ensure that a directory with this name
663     actually exists; but see exists().
664
665     \sa path(), filePath(), absolutePath(), absoluteFilePath()
666 */
667 QString QDir::dirName() const
668 {
669     const QDirPrivate* d = d_ptr.constData();
670     return d->dirEntry.fileName();
671 }
672
673 /*!
674     Returns the path name of a file in the directory. Does \e not
675     check if the file actually exists in the directory; but see
676     exists(). If the QDir is relative the returned path name will also
677     be relative. Redundant multiple separators or "." and ".."
678     directories in \a fileName are not removed (see cleanPath()).
679
680     \sa dirName(), absoluteFilePath(), isRelative(), canonicalPath()
681 */
682 QString QDir::filePath(const QString &fileName) const
683 {
684     const QDirPrivate* d = d_ptr.constData();
685     if (isAbsolutePath(fileName))
686         return QString(fileName);
687
688     QString ret = d->dirEntry.filePath();
689     if (!fileName.isEmpty()) {
690         if (!ret.isEmpty() && ret[(int)ret.length()-1] != QLatin1Char('/') && fileName[0] != QLatin1Char('/'))
691             ret += QLatin1Char('/');
692         ret += fileName;
693     }
694     return ret;
695 }
696
697 /*!
698     Returns the absolute path name of a file in the directory. Does \e
699     not check if the file actually exists in the directory; but see
700     exists(). Redundant multiple separators or "." and ".."
701     directories in \a fileName are not removed (see cleanPath()).
702
703     \sa relativeFilePath(), filePath(), canonicalPath()
704 */
705 QString QDir::absoluteFilePath(const QString &fileName) const
706 {
707     const QDirPrivate* d = d_ptr.constData();
708     if (isAbsolutePath(fileName))
709         return fileName;
710
711     d->resolveAbsoluteEntry();
712     if (fileName.isEmpty())
713         return d->absoluteDirEntry.filePath();
714     if (!d->absoluteDirEntry.isRoot())
715         return d->absoluteDirEntry.filePath() % QLatin1Char('/') % fileName;
716     return d->absoluteDirEntry.filePath() % fileName;
717 }
718
719 /*!
720     Returns the path to \a fileName relative to the directory.
721
722     \snippet code/src_corelib_io_qdir.cpp 7
723
724     \sa absoluteFilePath(), filePath(), canonicalPath()
725 */
726 QString QDir::relativeFilePath(const QString &fileName) const
727 {
728     QString dir = cleanPath(absolutePath());
729     QString file = cleanPath(fileName);
730
731     if (isRelativePath(file) || isRelativePath(dir))
732         return file;
733
734 #ifdef Q_OS_WIN
735     QString dirDrive = driveSpec(dir);
736     QString fileDrive = driveSpec(file);
737
738     bool fileDriveMissing = false;
739     if (fileDrive.isEmpty()) {
740         fileDrive = dirDrive;
741         fileDriveMissing = true;
742     }
743
744     if (fileDrive.toLower() != dirDrive.toLower()
745         || (file.startsWith(QLatin1String("//"))
746         && !dir.startsWith(QLatin1String("//"))))
747         return file;
748
749     dir.remove(0, dirDrive.size());
750     if (!fileDriveMissing)
751         file.remove(0, fileDrive.size());
752 #endif
753
754     QString result;
755     QStringList dirElts = dir.split(QLatin1Char('/'), QString::SkipEmptyParts);
756     QStringList fileElts = file.split(QLatin1Char('/'), QString::SkipEmptyParts);
757
758     int i = 0;
759     while (i < dirElts.size() && i < fileElts.size() &&
760 #if defined(Q_OS_WIN)
761            dirElts.at(i).toLower() == fileElts.at(i).toLower())
762 #else
763            dirElts.at(i) == fileElts.at(i))
764 #endif
765         ++i;
766
767     for (int j = 0; j < dirElts.size() - i; ++j)
768         result += QLatin1String("../");
769
770     for (int j = i; j < fileElts.size(); ++j) {
771         result += fileElts.at(j);
772         if (j < fileElts.size() - 1)
773             result += QLatin1Char('/');
774     }
775
776     return result;
777 }
778
779 /*!
780     \since 4.2
781
782     Returns \a pathName with the '/' separators converted to
783     separators that are appropriate for the underlying operating
784     system.
785
786     On Windows, toNativeSeparators("c:/winnt/system32") returns
787     "c:\\winnt\\system32".
788
789     The returned string may be the same as the argument on some
790     operating systems, for example on Unix.
791
792     \sa fromNativeSeparators(), separator()
793 */
794 QString QDir::toNativeSeparators(const QString &pathName)
795 {
796 #if defined(Q_OS_WIN)
797     int i = pathName.indexOf(QLatin1Char('/'));
798     if (i != -1) {
799         QString n(pathName);
800
801         QChar * const data = n.data();
802         data[i++] = QLatin1Char('\\');
803
804         for (; i < n.length(); ++i) {
805             if (data[i] == QLatin1Char('/'))
806                 data[i] = QLatin1Char('\\');
807         }
808
809         return n;
810     }
811 #endif
812     return pathName;
813 }
814
815 /*!
816     \since 4.2
817
818     Returns \a pathName using '/' as file separator. On Windows,
819     for instance, fromNativeSeparators("\c{c:\\winnt\\system32}") returns
820     "c:/winnt/system32".
821
822     The returned string may be the same as the argument on some
823     operating systems, for example on Unix.
824
825     \sa toNativeSeparators(), separator()
826 */
827 QString QDir::fromNativeSeparators(const QString &pathName)
828 {
829 #if defined(Q_OS_WIN)
830     int i = pathName.indexOf(QLatin1Char('\\'));
831     if (i != -1) {
832         QString n(pathName);
833
834         QChar * const data = n.data();
835         data[i++] = QLatin1Char('/');
836
837         for (; i < n.length(); ++i) {
838             if (data[i] == QLatin1Char('\\'))
839                 data[i] = QLatin1Char('/');
840         }
841
842         return n;
843     }
844 #endif
845     return pathName;
846 }
847
848 /*!
849     Changes the QDir's directory to \a dirName.
850
851     Returns true if the new directory exists and is readable;
852     otherwise returns false. Note that the logical cd() operation is
853     not performed if the new directory does not exist.
854
855     Calling cd("..") is equivalent to calling cdUp().
856
857     \sa cdUp(), isReadable(), exists(), path()
858 */
859 bool QDir::cd(const QString &dirName)
860 {
861     // Don't detach just yet.
862     const QDirPrivate * const d = d_ptr.constData();
863
864     if (dirName.isEmpty() || dirName == QLatin1String("."))
865         return true;
866     QString newPath;
867     if (isAbsolutePath(dirName)) {
868         newPath = cleanPath(dirName);
869     } else {
870         if (isRoot())
871             newPath = d->dirEntry.filePath();
872         else
873             newPath = d->dirEntry.filePath() % QLatin1Char('/');
874         newPath += dirName;
875         if (dirName.indexOf(QLatin1Char('/')) >= 0
876             || dirName == QLatin1String("..")
877             || d->dirEntry.filePath() == QLatin1String(".")) {
878             newPath = cleanPath(newPath);
879 #if defined (Q_OS_UNIX)
880             //After cleanPath() if path is "/.." or starts with "/../" it means trying to cd above root.
881             if (newPath.startsWith(QLatin1String("/../")) || newPath == QLatin1String("/.."))
882 #else
883             /*
884               cleanPath() already took care of replacing '\' with '/'.
885               We can't use startsWith here because the letter of the drive is unknown.
886               After cleanPath() if path is "[A-Z]:/.." or starts with "[A-Z]:/../" it means trying to cd above root.
887              */
888
889             if (newPath.midRef(1, 4) == QLatin1String(":/..") && (newPath.length() == 5 || newPath.at(5) == QLatin1Char('/')))
890 #endif
891                 return false;
892             /*
893               If newPath starts with .., we convert it to absolute to
894               avoid infinite looping on
895
896                   QDir dir(".");
897                   while (dir.cdUp())
898                       ;
899             */
900             if (newPath.startsWith(QLatin1String(".."))) {
901                 newPath = QFileInfo(newPath).absoluteFilePath();
902             }
903         }
904     }
905
906     QScopedPointer<QDirPrivate> dir(new QDirPrivate(*d_ptr.constData()));
907     dir->setPath(newPath);
908     if (!dir->exists())
909         return false;
910
911     d_ptr = dir.take();
912     return true;
913 }
914
915 /*!
916     Changes directory by moving one directory up from the QDir's
917     current directory.
918
919     Returns true if the new directory exists and is readable;
920     otherwise returns false. Note that the logical cdUp() operation is
921     not performed if the new directory does not exist.
922
923     \sa cd(), isReadable(), exists(), path()
924 */
925 bool QDir::cdUp()
926 {
927     return cd(QString::fromLatin1(".."));
928 }
929
930 /*!
931     Returns the string list set by setNameFilters()
932 */
933 QStringList QDir::nameFilters() const
934 {
935     const QDirPrivate* d = d_ptr.constData();
936     return d->nameFilters;
937 }
938
939 /*!
940     Sets the name filters used by entryList() and entryInfoList() to the
941     list of filters specified by \a nameFilters.
942
943     Each name filter is a wildcard (globbing) filter that understands
944     \c{*} and \c{?} wildcards. (See \l{QRegExp wildcard matching}.)
945
946     For example, the following code sets three name filters on a QDir
947     to ensure that only files with extensions typically used for C++
948     source files are listed:
949
950     \snippet qdir-namefilters/main.cpp 0
951
952     \sa nameFilters(), setFilter()
953 */
954 void QDir::setNameFilters(const QStringList &nameFilters)
955 {
956     QDirPrivate* d = d_ptr.data();
957     d->initFileEngine();
958     d->clearFileLists();
959
960     d->nameFilters = nameFilters;
961 }
962
963 /*!
964     \obsolete
965
966     Use QDir::addSearchPath() with a prefix instead.
967
968     Adds \a path to the search paths searched in to find resources
969     that are not specified with an absolute path. The default search
970     path is to search only in the root (\c{:/}).
971
972     \sa {The Qt Resource System}
973 */
974 void QDir::addResourceSearchPath(const QString &path)
975 {
976 #ifdef QT_BUILD_CORE_LIB
977     QResource::addSearchPath(path);
978 #else
979     Q_UNUSED(path)
980 #endif
981 }
982
983 #ifdef QT_BUILD_CORE_LIB
984 /*!
985     \since 4.3
986
987     Sets or replaces Qt's search paths for file names with the prefix \a prefix
988     to \a searchPaths.
989
990     To specify a prefix for a file name, prepend the prefix followed by a single
991     colon (e.g., "images:undo.png", "xmldocs:books.xml"). \a prefix can only
992     contain letters or numbers (e.g., it cannot contain a colon, nor a slash).
993
994     Qt uses this search path to locate files with a known prefix. The search
995     path entries are tested in order, starting with the first entry.
996
997     \snippet code/src_corelib_io_qdir.cpp 8
998
999     File name prefix must be at least 2 characters long to avoid conflicts with
1000     Windows drive letters.
1001
1002     Search paths may contain paths to \l{The Qt Resource System}.
1003 */
1004 void QDir::setSearchPaths(const QString &prefix, const QStringList &searchPaths)
1005 {
1006     if (prefix.length() < 2) {
1007         qWarning("QDir::setSearchPaths: Prefix must be longer than 1 character");
1008         return;
1009     }
1010
1011     for (int i = 0; i < prefix.count(); ++i) {
1012         if (!prefix.at(i).isLetterOrNumber()) {
1013             qWarning("QDir::setSearchPaths: Prefix can only contain letters or numbers");
1014             return;
1015         }
1016     }
1017
1018     QWriteLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
1019     QMap<QString, QStringList> &paths = QCoreGlobalData::instance()->dirSearchPaths;
1020     if (searchPaths.isEmpty()) {
1021         paths.remove(prefix);
1022     } else {
1023         paths.insert(prefix, searchPaths);
1024     }
1025 }
1026
1027 /*!
1028     \since 4.3
1029
1030     Adds \a path to the search path for \a prefix.
1031
1032     \sa setSearchPaths()
1033 */
1034 void QDir::addSearchPath(const QString &prefix, const QString &path)
1035 {
1036     if (path.isEmpty())
1037         return;
1038
1039     QWriteLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
1040     QCoreGlobalData::instance()->dirSearchPaths[prefix] += path;
1041 }
1042
1043 /*!
1044     \since 4.3
1045
1046     Returns the search paths for \a prefix.
1047
1048     \sa setSearchPaths(), addSearchPath()
1049 */
1050 QStringList QDir::searchPaths(const QString &prefix)
1051 {
1052     QReadLocker lock(&QCoreGlobalData::instance()->dirSearchPathsLock);
1053     return QCoreGlobalData::instance()->dirSearchPaths.value(prefix);
1054 }
1055
1056 #endif // QT_BUILD_CORE_LIB
1057
1058 /*!
1059     Returns the value set by setFilter()
1060 */
1061 QDir::Filters QDir::filter() const
1062 {
1063     const QDirPrivate* d = d_ptr.constData();
1064     return d->filters;
1065 }
1066
1067 /*!
1068     \enum QDir::Filter
1069
1070     This enum describes the filtering options available to QDir; e.g.
1071     for entryList() and entryInfoList(). The filter value is specified
1072     by combining values from the following list using the bitwise OR
1073     operator:
1074
1075     \value Dirs    List directories that match the filters.
1076     \value AllDirs  List all directories; i.e. don't apply the filters
1077                     to directory names.
1078     \value Files   List files.
1079     \value Drives  List disk drives (ignored under Unix).
1080     \value NoSymLinks  Do not list symbolic links (ignored by operating
1081                        systems that don't support symbolic links).
1082     \value NoDotAndDotDot Do not list the special entries "." and "..".
1083     \value NoDot       Do not list the special entry ".".
1084     \value NoDotDot    Do not list the special entry "..".
1085     \value AllEntries  List directories, files, drives and symlinks (this does not list
1086                 broken symlinks unless you specify System).
1087     \value Readable    List files for which the application has read
1088                        access. The Readable value needs to be combined
1089                        with Dirs or Files.
1090     \value Writable    List files for which the application has write
1091                        access. The Writable value needs to be combined
1092                        with Dirs or Files.
1093     \value Executable  List files for which the application has
1094                        execute access. The Executable value needs to be
1095                        combined with Dirs or Files.
1096     \value Modified  Only list files that have been modified (ignored
1097                      on Unix).
1098     \value Hidden  List hidden files (on Unix, files starting with a ".").
1099     \value System  List system files (on Unix, FIFOs, sockets and
1100                    device files are included; on Windows, \c {.lnk}
1101                    files are included)
1102     \value CaseSensitive  The filter should be case sensitive.
1103
1104     \omitvalue TypeMask
1105     \omitvalue AccessMask
1106     \omitvalue PermissionMask
1107     \omitvalue NoFilter
1108
1109     Functions that use Filter enum values to filter lists of files
1110     and directories will include symbolic links to files and directories
1111     unless you set the NoSymLinks value.
1112
1113     A default constructed QDir will not filter out files based on
1114     their permissions, so entryList() and entryInfoList() will return
1115     all files that are readable, writable, executable, or any
1116     combination of the three.  This makes the default easy to write,
1117     and at the same time useful.
1118
1119     For example, setting the \c Readable, \c Writable, and \c Files
1120     flags allows all files to be listed for which the application has read
1121     access, write access or both. If the \c Dirs and \c Drives flags are
1122     also included in this combination then all drives, directories, all
1123     files that the application can read, write, or execute, and symlinks
1124     to such files/directories can be listed.
1125
1126     To retrieve the permissons for a directory, use the
1127     entryInfoList() function to get the associated QFileInfo objects
1128     and then use the QFileInfo::permissons() to obtain the permissions
1129     and ownership for each file.
1130 */
1131
1132 /*!
1133     Sets the filter used by entryList() and entryInfoList() to \a
1134     filters. The filter is used to specify the kind of files that
1135     should be returned by entryList() and entryInfoList(). See
1136     \l{QDir::Filter}.
1137
1138     \sa filter(), setNameFilters()
1139 */
1140 void QDir::setFilter(Filters filters)
1141 {
1142     QDirPrivate* d = d_ptr.data();
1143     d->initFileEngine();
1144     d->clearFileLists();
1145
1146     d->filters = filters;
1147 }
1148
1149 /*!
1150     Returns the value set by setSorting()
1151
1152     \sa setSorting(), SortFlag
1153 */
1154 QDir::SortFlags QDir::sorting() const
1155 {
1156     const QDirPrivate* d = d_ptr.constData();
1157     return d->sort;
1158 }
1159
1160 /*!
1161     \enum QDir::SortFlag
1162
1163     This enum describes the sort options available to QDir, e.g. for
1164     entryList() and entryInfoList(). The sort value is specified by
1165     OR-ing together values from the following list:
1166
1167     \value Name  Sort by name.
1168     \value Time  Sort by time (modification time).
1169     \value Size  Sort by file size.
1170     \value Type  Sort by file type (extension).
1171     \value Unsorted  Do not sort.
1172     \value NoSort Not sorted by default.
1173
1174     \value DirsFirst  Put the directories first, then the files.
1175     \value DirsLast Put the files first, then the directories.
1176     \value Reversed  Reverse the sort order.
1177     \value IgnoreCase  Sort case-insensitively.
1178     \value LocaleAware Sort items appropriately using the current locale settings.
1179
1180     \omitvalue SortByMask
1181
1182     You can only specify one of the first four.
1183
1184     If you specify both DirsFirst and Reversed, directories are
1185     still put first, but in reverse order; the files will be listed
1186     after the directories, again in reverse order.
1187 */
1188
1189 /*!
1190     Sets the sort order used by entryList() and entryInfoList().
1191
1192     The \a sort is specified by OR-ing values from the enum
1193     \l{QDir::SortFlag}.
1194
1195     \sa sorting(), SortFlag
1196 */
1197 void QDir::setSorting(SortFlags sort)
1198 {
1199     QDirPrivate* d = d_ptr.data();
1200     d->initFileEngine();
1201     d->clearFileLists();
1202
1203     d->sort = sort;
1204 }
1205
1206 /*!
1207     Returns the total number of directories and files in the directory.
1208
1209     Equivalent to entryList().count().
1210
1211     \sa operator[](), entryList()
1212 */
1213 uint QDir::count() const
1214 {
1215     const QDirPrivate* d = d_ptr.constData();
1216     d->initFileLists(*this);
1217     return d->files.count();
1218 }
1219
1220 /*!
1221     Returns the file name at position \a pos in the list of file
1222     names. Equivalent to entryList().at(index).
1223     \a pos must be a valid index position in the list (i.e., 0 <= pos < count()).
1224
1225     \sa count(), entryList()
1226 */
1227 QString QDir::operator[](int pos) const
1228 {
1229     const QDirPrivate* d = d_ptr.constData();
1230     d->initFileLists(*this);
1231     return d->files[pos];
1232 }
1233
1234 /*!
1235     \overload
1236
1237     Returns a list of the names of all the files and directories in
1238     the directory, ordered according to the name and attribute filters
1239     previously set with setNameFilters() and setFilter(), and sorted according
1240     to the flags set with setSorting().
1241
1242     The attribute filter and sorting specifications can be overridden using the
1243     \a filters and \a sort arguments.
1244
1245     Returns an empty list if the directory is unreadable, does not
1246     exist, or if nothing matches the specification.
1247
1248     \note To list symlinks that point to non existing files, \l System must be
1249      passed to the filter.
1250
1251     \sa entryInfoList(), setNameFilters(), setSorting(), setFilter()
1252 */
1253 QStringList QDir::entryList(Filters filters, SortFlags sort) const
1254 {
1255     const QDirPrivate* d = d_ptr.constData();
1256     return entryList(d->nameFilters, filters, sort);
1257 }
1258
1259
1260 /*!
1261     \overload
1262
1263     Returns a list of QFileInfo objects for all the files and directories in
1264     the directory, ordered according to the name and attribute filters
1265     previously set with setNameFilters() and setFilter(), and sorted according
1266     to the flags set with setSorting().
1267
1268     The attribute filter and sorting specifications can be overridden using the
1269     \a filters and \a sort arguments.
1270
1271     Returns an empty list if the directory is unreadable, does not
1272     exist, or if nothing matches the specification.
1273
1274     \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
1275 */
1276 QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const
1277 {
1278     const QDirPrivate* d = d_ptr.constData();
1279     return entryInfoList(d->nameFilters, filters, sort);
1280 }
1281
1282 /*!
1283     Returns a list of the names of all the files and
1284     directories in the directory, ordered according to the name
1285     and attribute filters previously set with setNameFilters()
1286     and setFilter(), and sorted according to the flags set with
1287     setSorting().
1288
1289     The name filter, file attribute filter, and sorting specification
1290     can be overridden using the \a nameFilters, \a filters, and \a sort
1291     arguments.
1292
1293     Returns an empty list if the directory is unreadable, does not
1294     exist, or if nothing matches the specification.
1295
1296     \sa entryInfoList(), setNameFilters(), setSorting(), setFilter()
1297 */
1298 QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
1299                             SortFlags sort) const
1300 {
1301     const QDirPrivate* d = d_ptr.constData();
1302
1303     if (filters == NoFilter)
1304         filters = d->filters;
1305     if (sort == NoSort)
1306         sort = d->sort;
1307
1308     if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
1309         d->initFileLists(*this);
1310         return d->files;
1311     }
1312
1313     QFileInfoList l;
1314     QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
1315     while (it.hasNext()) {
1316         it.next();
1317         l.append(it.fileInfo());
1318     }
1319     QStringList ret;
1320     d->sortFileList(sort, l, &ret, 0);
1321     return ret;
1322 }
1323
1324 /*!
1325     Returns a list of QFileInfo objects for all the files and
1326     directories in the directory, ordered according to the name
1327     and attribute filters previously set with setNameFilters()
1328     and setFilter(), and sorted according to the flags set with
1329     setSorting().
1330
1331     The name filter, file attribute filter, and sorting specification
1332     can be overridden using the \a nameFilters, \a filters, and \a sort
1333     arguments.
1334
1335     Returns an empty list if the directory is unreadable, does not
1336     exist, or if nothing matches the specification.
1337
1338     \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
1339 */
1340 QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filters,
1341                                   SortFlags sort) const
1342 {
1343     const QDirPrivate* d = d_ptr.constData();
1344
1345     if (filters == NoFilter)
1346         filters = d->filters;
1347     if (sort == NoSort)
1348         sort = d->sort;
1349
1350     if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
1351         d->initFileLists(*this);
1352         return d->fileInfos;
1353     }
1354
1355     QFileInfoList l;
1356     QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
1357     while (it.hasNext()) {
1358         it.next();
1359         l.append(it.fileInfo());
1360     }
1361     QFileInfoList ret;
1362     d->sortFileList(sort, l, 0, &ret);
1363     return ret;
1364 }
1365
1366 /*!
1367     Creates a sub-directory called \a dirName.
1368
1369     Returns true on success; otherwise returns false.
1370
1371     If the directory already exists when this function is called, it will return false.
1372
1373     \sa rmdir()
1374 */
1375 bool QDir::mkdir(const QString &dirName) const
1376 {
1377     const QDirPrivate* d = d_ptr.constData();
1378
1379     if (dirName.isEmpty()) {
1380         qWarning("QDir::mkdir: Empty or null file name(s)");
1381         return false;
1382     }
1383
1384     QString fn = filePath(dirName);
1385     if (d->fileEngine.isNull())
1386         return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), false);
1387     return d->fileEngine->mkdir(fn, false);
1388 }
1389
1390 /*!
1391     Removes the directory specified by \a dirName.
1392
1393     The directory must be empty for rmdir() to succeed.
1394
1395     Returns true if successful; otherwise returns false.
1396
1397     \sa mkdir()
1398 */
1399 bool QDir::rmdir(const QString &dirName) const
1400 {
1401     const QDirPrivate* d = d_ptr.constData();
1402
1403     if (dirName.isEmpty()) {
1404         qWarning("QDir::rmdir: Empty or null file name(s)");
1405         return false;
1406     }
1407
1408     QString fn = filePath(dirName);
1409     if (d->fileEngine.isNull())
1410         return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), false);
1411
1412     return d->fileEngine->rmdir(fn, false);
1413 }
1414
1415 /*!
1416     Creates the directory path \a dirPath.
1417
1418     The function will create all parent directories necessary to
1419     create the directory.
1420
1421     Returns true if successful; otherwise returns false.
1422
1423     If the path already exists when this function is called, it will return true.
1424
1425     \sa rmpath()
1426 */
1427 bool QDir::mkpath(const QString &dirPath) const
1428 {
1429     const QDirPrivate* d = d_ptr.constData();
1430
1431     if (dirPath.isEmpty()) {
1432         qWarning("QDir::mkpath: Empty or null file name(s)");
1433         return false;
1434     }
1435
1436     QString fn = filePath(dirPath);
1437     if (d->fileEngine.isNull())
1438         return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), true);
1439     return d->fileEngine->mkdir(fn, true);
1440 }
1441
1442 /*!
1443     Removes the directory path \a dirPath.
1444
1445     The function will remove all parent directories in \a dirPath,
1446     provided that they are empty. This is the opposite of
1447     mkpath(dirPath).
1448
1449     Returns true if successful; otherwise returns false.
1450
1451     \sa mkpath()
1452 */
1453 bool QDir::rmpath(const QString &dirPath) const
1454 {
1455     const QDirPrivate* d = d_ptr.constData();
1456
1457     if (dirPath.isEmpty()) {
1458         qWarning("QDir::rmpath: Empty or null file name(s)");
1459         return false;
1460     }
1461
1462     QString fn = filePath(dirPath);
1463     if (d->fileEngine.isNull())
1464         return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), true);
1465     return d->fileEngine->rmdir(fn, true);
1466 }
1467
1468 /*!
1469     \since 5.0
1470     Removes the directory, including all its contents.
1471
1472     Returns true if successful, otherwise false.
1473
1474     If a file or directory cannot be removed, removeRecursively() keeps going
1475     and attempts to delete as many files and sub-directories as possible,
1476     then returns false.
1477
1478     If the directory was already removed, the method returns true
1479     (expected result already reached).
1480
1481     Note: this function is meant for removing a small application-internal
1482     directory (such as a temporary directory), but not user-visible
1483     directories. For user-visible operations, it is rather recommended
1484     to report errors more precisely to the user, to offer solutions
1485     in case of errors, to show progress during the deletion since it
1486     could take several minutes, etc.
1487 */
1488 bool QDir::removeRecursively()
1489 {
1490     if (!d_ptr->exists())
1491         return true;
1492
1493     bool success = true;
1494     const QString dirPath = path();
1495     // not empty -- we must empty it first
1496     QDirIterator di(dirPath, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
1497     while (di.hasNext()) {
1498         di.next();
1499         const QFileInfo& fi = di.fileInfo();
1500         bool ok;
1501         if (fi.isDir() && !fi.isSymLink())
1502             ok = QDir(di.filePath()).removeRecursively(); // recursive
1503         else
1504             ok = QFile::remove(di.filePath());
1505         if (!ok)
1506             success = false;
1507     }
1508
1509     if (success)
1510         success = rmdir(absolutePath());
1511
1512     return success;
1513 }
1514
1515 /*!
1516     Returns true if the directory is readable \e and we can open files
1517     by name; otherwise returns false.
1518
1519     \warning A false value from this function is not a guarantee that
1520     files in the directory are not accessible.
1521
1522     \sa QFileInfo::isReadable()
1523 */
1524 bool QDir::isReadable() const
1525 {
1526     const QDirPrivate* d = d_ptr.constData();
1527
1528     if (d->fileEngine.isNull()) {
1529         if (!d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission))
1530             QFileSystemEngine::fillMetaData(d->dirEntry, d->metaData, QFileSystemMetaData::UserReadPermission);
1531
1532         return (d->metaData.permissions() & QFile::ReadUser) != 0;
1533     }
1534
1535     const QAbstractFileEngine::FileFlags info =
1536         d->fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
1537                                        | QAbstractFileEngine::PermsMask);
1538     if (!(info & QAbstractFileEngine::DirectoryType))
1539         return false;
1540     return info & QAbstractFileEngine::ReadUserPerm;
1541 }
1542
1543 /*!
1544     \overload
1545
1546     Returns true if the directory exists; otherwise returns false.
1547     (If a file with the same name is found this function will return false).
1548
1549     The overload of this function that accepts an argument is used to test
1550     for the presence of files and directories within a directory.
1551
1552     \sa QFileInfo::exists(), QFile::exists()
1553 */
1554 bool QDir::exists() const
1555 {
1556     return d_ptr->exists();
1557 }
1558
1559 /*!
1560     Returns true if the directory is the root directory; otherwise
1561     returns false.
1562
1563     Note: If the directory is a symbolic link to the root directory
1564     this function returns false. If you want to test for this use
1565     canonicalPath(), e.g.
1566
1567     \snippet code/src_corelib_io_qdir.cpp 9
1568
1569     \sa root(), rootPath()
1570 */
1571 bool QDir::isRoot() const
1572 {
1573     if (d_ptr->fileEngine.isNull())
1574         return d_ptr->dirEntry.isRoot();
1575     return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::RootFlag;
1576 }
1577
1578 /*!
1579     \fn bool QDir::isAbsolute() const
1580
1581     Returns true if the directory's path is absolute; otherwise
1582     returns false. See isAbsolutePath().
1583
1584     \sa isRelative(), makeAbsolute(), cleanPath()
1585 */
1586
1587 /*!
1588    \fn bool QDir::isAbsolutePath(const QString &)
1589
1590     Returns true if \a path is absolute; returns false if it is
1591     relative.
1592
1593     \sa isAbsolute(), isRelativePath(), makeAbsolute(), cleanPath()
1594 */
1595
1596 /*!
1597     Returns true if the directory path is relative; otherwise returns
1598     false. (Under Unix a path is relative if it does not start with a
1599     "/").
1600
1601     \sa makeAbsolute(), isAbsolute(), isAbsolutePath(), cleanPath()
1602 */
1603 bool QDir::isRelative() const
1604 {
1605     if (d_ptr->fileEngine.isNull())
1606         return d_ptr->dirEntry.isRelative();
1607     return d_ptr->fileEngine->isRelativePath();
1608 }
1609
1610
1611 /*!
1612     Converts the directory path to an absolute path. If it is already
1613     absolute nothing happens. Returns true if the conversion
1614     succeeded; otherwise returns false.
1615
1616     \sa isAbsolute(), isAbsolutePath(), isRelative(), cleanPath()
1617 */
1618 bool QDir::makeAbsolute()
1619 {
1620     const QDirPrivate *d = d_ptr.constData();
1621     QScopedPointer<QDirPrivate> dir;
1622     if (!d->fileEngine.isNull()) {
1623         QString absolutePath = d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
1624         if (QDir::isRelativePath(absolutePath))
1625             return false;
1626
1627         dir.reset(new QDirPrivate(*d_ptr.constData()));
1628         dir->setPath(absolutePath);
1629     } else { // native FS
1630         d->resolveAbsoluteEntry();
1631         dir.reset(new QDirPrivate(*d_ptr.constData()));
1632         dir->setPath(d->absoluteDirEntry.filePath());
1633     }
1634     d_ptr = dir.take(); // actually detach
1635     return true;
1636 }
1637
1638 /*!
1639     Returns true if directory \a dir and this directory have the same
1640     path and their sort and filter settings are the same; otherwise
1641     returns false.
1642
1643     Example:
1644
1645     \snippet code/src_corelib_io_qdir.cpp 10
1646 */
1647 bool QDir::operator==(const QDir &dir) const
1648 {
1649     const QDirPrivate *d = d_ptr.constData();
1650     const QDirPrivate *other = dir.d_ptr.constData();
1651
1652     if (d == other)
1653         return true;
1654     Qt::CaseSensitivity sensitive;
1655     if (d->fileEngine.isNull() || other->fileEngine.isNull()) {
1656         if (d->fileEngine.data() != other->fileEngine.data()) // one is native, the other is a custom file-engine
1657             return false;
1658
1659         sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
1660     } else {
1661         if (d->fileEngine->caseSensitive() != other->fileEngine->caseSensitive())
1662             return false;
1663         sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
1664     }
1665
1666     if (d->filters == other->filters
1667        && d->sort == other->sort
1668        && d->nameFilters == other->nameFilters) {
1669
1670         // Assume directories are the same if path is the same
1671         if (d->dirEntry.filePath() == other->dirEntry.filePath())
1672             return true;
1673
1674         if (exists()) {
1675             if (!dir.exists())
1676                 return false; //can't be equal if only one exists
1677             // Both exist, fallback to expensive canonical path computation
1678             return canonicalPath().compare(dir.canonicalPath(), sensitive) == 0;
1679         } else {
1680             if (dir.exists())
1681                 return false; //can't be equal if only one exists
1682             // Neither exists, compare absolute paths rather than canonical (which would be empty strings)
1683             d->resolveAbsoluteEntry();
1684             other->resolveAbsoluteEntry();
1685             return d->absoluteDirEntry.filePath().compare(other->absoluteDirEntry.filePath(), sensitive) == 0;
1686         }
1687     }
1688     return false;
1689 }
1690
1691 /*!
1692     Makes a copy of the \a dir object and assigns it to this QDir
1693     object.
1694 */
1695 QDir &QDir::operator=(const QDir &dir)
1696 {
1697     d_ptr = dir.d_ptr;
1698     return *this;
1699 }
1700
1701 /*!
1702     \overload
1703     \obsolete
1704
1705     Sets the directory path to the given \a path.
1706
1707     Use setPath() instead.
1708 */
1709 QDir &QDir::operator=(const QString &path)
1710 {
1711     d_ptr->setPath(path);
1712     return *this;
1713 }
1714
1715 /*!
1716     \fn void QDir::swap(QDir &other)
1717     \since 5.0
1718
1719     Swaps this QDir instance with \a other. This function is very fast
1720     and never fails.
1721 */
1722
1723 /*!
1724     \fn bool QDir::operator!=(const QDir &dir) const
1725
1726     Returns true if directory \a dir and this directory have different
1727     paths or different sort or filter settings; otherwise returns
1728     false.
1729
1730     Example:
1731
1732     \snippet code/src_corelib_io_qdir.cpp 11
1733 */
1734
1735 /*!
1736     Removes the file, \a fileName.
1737
1738     Returns true if the file is removed successfully; otherwise
1739     returns false.
1740 */
1741 bool QDir::remove(const QString &fileName)
1742 {
1743     if (fileName.isEmpty()) {
1744         qWarning("QDir::remove: Empty or null file name");
1745         return false;
1746     }
1747     return QFile::remove(filePath(fileName));
1748 }
1749
1750 /*!
1751     Renames a file or directory from \a oldName to \a newName, and returns
1752     true if successful; otherwise returns false.
1753
1754     On most file systems, rename() fails only if \a oldName does not
1755     exist, or if a file with the new name already exists.
1756     However, there are also other reasons why rename() can
1757     fail. For example, on at least one file system rename() fails if
1758     \a newName points to an open file.
1759
1760     If \a oldName is a file (not a directory) that can't be renamed
1761     right away, Qt will try to copy \a oldName to \a newName and remove
1762     \a oldName.
1763
1764     \sa QFile::rename()
1765 */
1766 bool QDir::rename(const QString &oldName, const QString &newName)
1767 {
1768     if (oldName.isEmpty() || newName.isEmpty()) {
1769         qWarning("QDir::rename: Empty or null file name(s)");
1770         return false;
1771     }
1772
1773     QFile file(filePath(oldName));
1774     if (!file.exists())
1775         return false;
1776     return file.rename(filePath(newName));
1777 }
1778
1779 /*!
1780     Returns true if the file called \a name exists; otherwise returns
1781     false.
1782
1783     Unless \a name contains an absolute file path, the file name is assumed
1784     to be relative to the directory itself, so this function is typically used
1785     to check for the presence of files within a directory.
1786
1787     \sa QFileInfo::exists(), QFile::exists()
1788 */
1789 bool QDir::exists(const QString &name) const
1790 {
1791     if (name.isEmpty()) {
1792         qWarning("QDir::exists: Empty or null file name");
1793         return false;
1794     }
1795     return QFile::exists(filePath(name));
1796 }
1797
1798 /*!
1799     Returns a list of the root directories on this system.
1800
1801     On Windows this returns a list of QFileInfo objects containing "C:/",
1802     "D:/", etc. On other operating systems, it returns a list containing
1803     just one root directory (i.e. "/").
1804
1805     \sa root(), rootPath()
1806 */
1807 QFileInfoList QDir::drives()
1808 {
1809 #ifdef QT_NO_FSFILEENGINE
1810     return QFileInfoList();
1811 #else
1812     return QFSFileEngine::drives();
1813 #endif
1814 }
1815
1816 /*!
1817     Returns the native directory separator: "/" under Unix (including
1818     Mac OS X) and "\\" under Windows.
1819
1820     You do not need to use this function to build file paths. If you
1821     always use "/", Qt will translate your paths to conform to the
1822     underlying operating system. If you want to display paths to the
1823     user using their operating system's separator use
1824     toNativeSeparators().
1825 */
1826 QChar QDir::separator()
1827 {
1828 #if defined(Q_OS_WIN)
1829     return QLatin1Char('\\');
1830 #else
1831     return QLatin1Char('/');
1832 #endif
1833 }
1834
1835 /*!
1836     Sets the application's current working directory to \a path.
1837     Returns true if the directory was successfully changed; otherwise
1838     returns false.
1839
1840     \sa current(), currentPath(), home(), root(), temp()
1841 */
1842 bool QDir::setCurrent(const QString &path)
1843 {
1844     return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
1845 }
1846
1847 /*!
1848     \fn QDir QDir::current()
1849
1850     Returns the application's current directory.
1851
1852     The directory is constructed using the absolute path of the current directory,
1853     ensuring that its path() will be the same as its absolutePath().
1854
1855     \sa currentPath(), setCurrent(), home(), root(), temp()
1856 */
1857
1858 /*!
1859     Returns the absolute path of the application's current directory.
1860
1861     \sa current(), setCurrent(), homePath(), rootPath(), tempPath()
1862 */
1863 QString QDir::currentPath()
1864 {
1865     return QFileSystemEngine::currentPath().filePath();
1866 }
1867
1868 /*!
1869     \fn QDir QDir::home()
1870
1871     Returns the user's home directory.
1872
1873     The directory is constructed using the absolute path of the home directory,
1874     ensuring that its path() will be the same as its absolutePath().
1875
1876     See homePath() for details.
1877
1878     \sa drives(), current(), root(), temp()
1879 */
1880
1881 /*!
1882     Returns the absolute path of the user's home directory.
1883
1884     Under Windows this function will return the directory of the
1885     current user's profile. Typically, this is:
1886
1887     \snippet code/src_corelib_io_qdir.cpp 12
1888
1889     Use the toNativeSeparators() function to convert the separators to
1890     the ones that are appropriate for the underlying operating system.
1891
1892     If the directory of the current user's profile does not exist or
1893     cannot be retrieved, the following alternatives will be checked (in
1894     the given order) until an existing and available path is found:
1895
1896     \list 1
1897     \li The path specified by the \c USERPROFILE environment variable.
1898     \li The path formed by concatenating the \c HOMEDRIVE and \c HOMEPATH
1899     environment variables.
1900     \li The path specified by the \c HOME environment variable.
1901     \li The path returned by the rootPath() function (which uses the \c SystemDrive
1902     environment variable)
1903     \li  The \c{C:/} directory.
1904     \endlist
1905
1906     Under non-Windows operating systems the \c HOME environment
1907     variable is used if it exists, otherwise the path returned by the
1908     rootPath().
1909
1910     \sa home(), currentPath(), rootPath(), tempPath()
1911 */
1912 QString QDir::homePath()
1913 {
1914     return QFileSystemEngine::homePath();
1915 }
1916
1917 /*!
1918     \fn QDir QDir::temp()
1919
1920     Returns the system's temporary directory.
1921
1922     The directory is constructed using the absolute path of the temporary directory,
1923     ensuring that its path() will be the same as its absolutePath().
1924
1925     See tempPath() for details.
1926
1927     \sa drives(), current(), home(), root()
1928 */
1929
1930 /*!
1931     Returns the absolute path of the system's temporary directory.
1932
1933     On Unix/Linux systems this is the path in the \c TMPDIR environment
1934     variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is
1935     usually the path in the \c TEMP or \c TMP environment
1936     variable. Whether a directory separator is added to the end or
1937     not, depends on the operating system.
1938
1939     \sa temp(), currentPath(), homePath(), rootPath()
1940 */
1941 QString QDir::tempPath()
1942 {
1943     return QFileSystemEngine::tempPath();
1944 }
1945
1946 /*!
1947     \fn QDir QDir::root()
1948
1949     Returns the root directory.
1950
1951     The directory is constructed using the absolute path of the root directory,
1952     ensuring that its path() will be the same as its absolutePath().
1953
1954     See rootPath() for details.
1955
1956     \sa drives(), current(), home(), temp()
1957 */
1958
1959 /*!
1960     Returns the absolute path of the root directory.
1961
1962     For Unix operating systems this returns "/". For Windows file
1963     systems this normally returns "c:/".
1964
1965     \sa root(), drives(), currentPath(), homePath(), tempPath()
1966 */
1967 QString QDir::rootPath()
1968 {
1969     return QFileSystemEngine::rootPath();
1970 }
1971
1972 #ifndef QT_NO_REGEXP
1973 /*!
1974     \overload
1975
1976     Returns true if the \a fileName matches any of the wildcard (glob)
1977     patterns in the list of \a filters; otherwise returns false. The
1978     matching is case insensitive.
1979
1980     \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList()
1981 */
1982 bool QDir::match(const QStringList &filters, const QString &fileName)
1983 {
1984     for (QStringList::ConstIterator sit = filters.constBegin(); sit != filters.constEnd(); ++sit) {
1985         QRegExp rx(*sit, Qt::CaseInsensitive, QRegExp::Wildcard);
1986         if (rx.exactMatch(fileName))
1987             return true;
1988     }
1989     return false;
1990 }
1991
1992 /*!
1993     Returns true if the \a fileName matches the wildcard (glob)
1994     pattern \a filter; otherwise returns false. The \a filter may
1995     contain multiple patterns separated by spaces or semicolons.
1996     The matching is case insensitive.
1997
1998     \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList()
1999 */
2000 bool QDir::match(const QString &filter, const QString &fileName)
2001 {
2002     return match(nameFiltersFromString(filter), fileName);
2003 }
2004 #endif // QT_NO_REGEXP
2005
2006 /*!
2007     Removes all multiple directory separators "/" and resolves any
2008     "."s or ".."s found in the path, \a path.
2009
2010     Symbolic links are kept. This function does not return the
2011     canonical path, but rather the simplest version of the input.
2012     For example, "./local" becomes "local", "local/../bin" becomes
2013     "bin" and "/local/usr/../bin" becomes "/local/bin".
2014
2015     \sa absolutePath(), canonicalPath()
2016 */
2017 QString QDir::cleanPath(const QString &path)
2018 {
2019     if (path.isEmpty())
2020         return path;
2021     QString name = path;
2022     QChar dir_separator = separator();
2023     if (dir_separator != QLatin1Char('/'))
2024        name.replace(dir_separator, QLatin1Char('/'));
2025
2026     int used = 0, levels = 0;
2027     const int len = name.length();
2028     QVarLengthArray<QChar> outVector(len);
2029     QChar *out = outVector.data();
2030
2031     const QChar *p = name.unicode();
2032     for (int i = 0, last = -1, iwrite = 0; i < len; ++i) {
2033         if (p[i] == QLatin1Char('/')) {
2034             while (i+1 < len && p[i+1] == QLatin1Char('/')) {
2035 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
2036                 if (!i)
2037                     break;
2038 #endif
2039                 i++;
2040             }
2041             bool eaten = false;
2042             if (i+1 < len && p[i+1] == QLatin1Char('.')) {
2043                 int dotcount = 1;
2044                 if (i+2 < len && p[i+2] == QLatin1Char('.'))
2045                     dotcount++;
2046                 if (i == len - dotcount - 1) {
2047                     if (dotcount == 1) {
2048                         break;
2049                     } else if (levels) {
2050                         if (last == -1) {
2051                             for (int i2 = iwrite-1; i2 >= 0; i2--) {
2052                                 if (out[i2] == QLatin1Char('/')) {
2053                                     last = i2;
2054                                     break;
2055                                 }
2056                             }
2057                         }
2058                         used -= iwrite - last - 1;
2059                         break;
2060                     }
2061                 } else if (p[i+dotcount+1] == QLatin1Char('/')) {
2062                     if (dotcount == 2 && levels) {
2063                         if (last == -1 || iwrite - last == 1) {
2064                             for (int i2 = (last == -1) ? (iwrite-1) : (last-1); i2 >= 0; i2--) {
2065                                 if (out[i2] == QLatin1Char('/')) {
2066                                     eaten = true;
2067                                     last = i2;
2068                                     break;
2069                                 }
2070                             }
2071                         } else {
2072                             eaten = true;
2073                         }
2074                         if (eaten) {
2075                             levels--;
2076                             used -= iwrite - last;
2077                             iwrite = last;
2078                             last = -1;
2079                         }
2080                     } else if (dotcount == 2 && i > 0 && p[i - 1] != QLatin1Char('.')) {
2081                         eaten = true;
2082                         used -= iwrite - qMax(0, last);
2083                         iwrite = qMax(0, last);
2084                         last = -1;
2085                         ++i;
2086                     } else if (dotcount == 1) {
2087                         eaten = true;
2088                     }
2089                     if (eaten)
2090                         i += dotcount;
2091                 } else {
2092                     levels++;
2093                 }
2094             } else if (last != -1 && iwrite - last == 1) {
2095 #if defined(Q_OS_WIN)
2096                 eaten = (iwrite > 2);
2097 #else
2098                 eaten = true;
2099 #endif
2100                 last = -1;
2101             } else if (last != -1 && i == len-1) {
2102                 eaten = true;
2103             } else {
2104                 levels++;
2105             }
2106             if (!eaten)
2107                 last = i - (i - iwrite);
2108             else
2109                 continue;
2110         } else if (!i && p[i] == QLatin1Char('.')) {
2111             int dotcount = 1;
2112             if (len >= 1 && p[1] == QLatin1Char('.'))
2113                 dotcount++;
2114             if (len >= dotcount && p[dotcount] == QLatin1Char('/')) {
2115                 if (dotcount == 1) {
2116                     i++;
2117                     while (i+1 < len-1 && p[i+1] == QLatin1Char('/'))
2118                         i++;
2119                     continue;
2120                 }
2121             }
2122         }
2123         out[iwrite++] = p[i];
2124         used++;
2125     }
2126
2127     QString ret = (used == len ? name : QString(out, used));
2128     // Strip away last slash except for root directories
2129     if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
2130 #if defined (Q_OS_WIN)
2131         if (!(ret.length() == 3 && ret.at(1) == QLatin1Char(':')))
2132 #endif
2133             ret.chop(1);
2134     }
2135
2136     return ret;
2137 }
2138
2139 /*!
2140     Returns true if \a path is relative; returns false if it is
2141     absolute.
2142
2143     \sa isRelative(), isAbsolutePath(), makeAbsolute()
2144 */
2145 bool QDir::isRelativePath(const QString &path)
2146 {
2147     return QFileInfo(path).isRelative();
2148 }
2149
2150 /*!
2151     Refreshes the directory information.
2152 */
2153 void QDir::refresh() const
2154 {
2155     QDirPrivate *d = const_cast<QDir*>(this)->d_ptr.data();
2156     d->metaData.clear();
2157     d->initFileEngine();
2158     d->clearFileLists();
2159 }
2160
2161 /*!
2162     \internal
2163 */
2164 QDirPrivate* QDir::d_func()
2165 {
2166     return d_ptr.data();
2167 }
2168
2169 /*!
2170     \internal
2171
2172     Returns a list of name filters from the given \a nameFilter. (If
2173     there is more than one filter, each pair of filters is separated
2174     by a space or by a semicolon.)
2175 */
2176 QStringList QDir::nameFiltersFromString(const QString &nameFilter)
2177 {
2178     return QDirPrivate::splitFilters(nameFilter);
2179 }
2180
2181 /*!
2182     \macro void Q_INIT_RESOURCE(name)
2183     \relates QDir
2184
2185     Initializes the resources specified by the \c .qrc file with the
2186     specified base \a name. Normally, Qt resources are loaded
2187     automatically at startup. The Q_INIT_RESOURCE() macro is
2188     necessary on some platforms for resources stored in a static
2189     library.
2190
2191     For example, if your application's resources are listed in a file
2192     called \c myapp.qrc, you can ensure that the resources are
2193     initialized at startup by adding this line to your \c main()
2194     function:
2195
2196     \snippet code/src_corelib_io_qdir.cpp 13
2197
2198     If the file name contains characters that cannot be part of a valid C++ function name
2199     (such as '-'), they have to be replaced by the underscore character ('_').
2200
2201     Note: This macro cannot be used in a namespace. It should be called from
2202     main(). If that is not possible, the following workaround can be used
2203     to init the resource \c myapp from the function \c{MyNamespace::myFunction}:
2204
2205     \snippet code/src_corelib_io_qdir.cpp 14
2206
2207     \sa Q_CLEANUP_RESOURCE(), {The Qt Resource System}
2208 */
2209
2210 /*!
2211     \since 4.1
2212     \macro void Q_CLEANUP_RESOURCE(name)
2213     \relates QDir
2214
2215     Unloads the resources specified by the \c .qrc file with the base
2216     name \a name.
2217
2218     Normally, Qt resources are unloaded automatically when the
2219     application terminates, but if the resources are located in a
2220     plugin that is being unloaded, call Q_CLEANUP_RESOURCE() to force
2221     removal of your resources.
2222
2223     Note: This macro cannot be used in a namespace. Please see the
2224     Q_INIT_RESOURCE documentation for a workaround.
2225
2226     Example:
2227
2228     \snippet code/src_corelib_io_qdir.cpp 15
2229
2230     \sa Q_INIT_RESOURCE(), {The Qt Resource System}
2231 */
2232
2233
2234 #ifndef QT_NO_DEBUG_STREAM
2235 QDebug operator<<(QDebug debug, QDir::Filters filters)
2236 {
2237     QStringList flags;
2238     if (filters == QDir::NoFilter) {
2239         flags << QLatin1String("NoFilter");
2240     } else {
2241         if (filters & QDir::Dirs) flags << QLatin1String("Dirs");
2242         if (filters & QDir::AllDirs) flags << QLatin1String("AllDirs");
2243         if (filters & QDir::Files) flags << QLatin1String("Files");
2244         if (filters & QDir::Drives) flags << QLatin1String("Drives");
2245         if (filters & QDir::NoSymLinks) flags << QLatin1String("NoSymLinks");
2246         if (filters & QDir::NoDot) flags << QLatin1String("NoDot");
2247         if (filters & QDir::NoDotDot) flags << QLatin1String("NoDotDot");
2248         if ((filters & QDir::AllEntries) == QDir::AllEntries) flags << QLatin1String("AllEntries");
2249         if (filters & QDir::Readable) flags << QLatin1String("Readable");
2250         if (filters & QDir::Writable) flags << QLatin1String("Writable");
2251         if (filters & QDir::Executable) flags << QLatin1String("Executable");
2252         if (filters & QDir::Modified) flags << QLatin1String("Modified");
2253         if (filters & QDir::Hidden) flags << QLatin1String("Hidden");
2254         if (filters & QDir::System) flags << QLatin1String("System");
2255         if (filters & QDir::CaseSensitive) flags << QLatin1String("CaseSensitive");
2256     }
2257     debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ')';
2258     return debug;
2259 }
2260
2261 static QDebug operator<<(QDebug debug, QDir::SortFlags sorting)
2262 {
2263     if (sorting == QDir::NoSort) {
2264         debug << "QDir::SortFlags(NoSort)";
2265     } else {
2266         QString type;
2267         if ((sorting & 3) == QDir::Name) type = QLatin1String("Name");
2268         if ((sorting & 3) == QDir::Time) type = QLatin1String("Time");
2269         if ((sorting & 3) == QDir::Size) type = QLatin1String("Size");
2270         if ((sorting & 3) == QDir::Unsorted) type = QLatin1String("Unsorted");
2271
2272         QStringList flags;
2273         if (sorting & QDir::DirsFirst) flags << QLatin1String("DirsFirst");
2274         if (sorting & QDir::DirsLast) flags << QLatin1String("DirsLast");
2275         if (sorting & QDir::IgnoreCase) flags << QLatin1String("IgnoreCase");
2276         if (sorting & QDir::LocaleAware) flags << QLatin1String("LocaleAware");
2277         if (sorting & QDir::Type) flags << QLatin1String("Type");
2278         debug << "QDir::SortFlags(" << qPrintable(type)
2279               << '|'
2280               << qPrintable(flags.join(QLatin1String("|"))) << ')';
2281     }
2282     return debug;
2283 }
2284
2285 QDebug operator<<(QDebug debug, const QDir &dir)
2286 {
2287     debug.maybeSpace() << "QDir(" << dir.path()
2288                        << ", nameFilters = {"
2289                        << qPrintable(dir.nameFilters().join(QLatin1String(",")))
2290                        << "}, "
2291                        << dir.sorting()
2292                        << ','
2293                        << dir.filter()
2294                        << ')';
2295     return debug.space();
2296 }
2297 #endif // QT_NO_DEBUG_STREAM
2298
2299 QT_END_NAMESPACE