1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qplatformdefs.h"
43 #include "qdir.h"
44 #include "qdir_p.h"
45 #include "qabstractfileengine.h"
46 #ifndef QT_NO_DEBUG_STREAM
47 #include "qdebug.h"
48 #endif
49 #include "qdiriterator.h"
50 #include "qfsfileengine.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
driveSpec(const QString & path)71 static QString driveSpec(const QString &path)
72 {
73 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
74 if (path.size() < 2)
75 return QString();
76 char c = path.at(0).toAscii();
77 if (c < 'a' && c > 'z' && c < 'A' && c > 'Z')
78 return QString();
79 if (path.at(1).toAscii() != ':')
80 return QString();
81 return path.mid(0, 2);
82 #else
83 Q_UNUSED(path);
84 return QString();
85 #endif
86 }
87
88 //************* QDirPrivate
QDirPrivate(const QString & path,const QStringList & nameFilters_,QDir::SortFlags sort_,QDir::Filters filters_)89 QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_, QDir::SortFlags sort_, QDir::Filters filters_)
90 : QSharedData()
91 , nameFilters(nameFilters_)
92 , sort(sort_)
93 , filters(filters_)
94 #ifdef QT3_SUPPORT
95 , filterSepChar(0)
96 , matchAllDirs(false)
97 #endif
98 , fileListsInitialized(false)
99 {
100 setPath(path.isEmpty() ? QString::fromLatin1(".") : path);
101
102 bool empty = nameFilters.isEmpty();
103 if (!empty) {
104 empty = true;
105 for (int i = 0; i < nameFilters.size(); ++i) {
106 if (!nameFilters.at(i).isEmpty()) {
107 empty = false;
108 break;
109 }
110 }
111 }
112 if (empty)
113 nameFilters = QStringList(QString::fromLatin1("*"));
114 }
115
QDirPrivate(const QDirPrivate & copy)116 QDirPrivate::QDirPrivate(const QDirPrivate ©)
117 : QSharedData(copy)
118 , nameFilters(copy.nameFilters)
119 , sort(copy.sort)
120 , filters(copy.filters)
121 #ifdef QT3_SUPPORT
122 , filterSepChar(copy.filterSepChar)
123 , matchAllDirs(copy.matchAllDirs)
124 #endif
125 , fileListsInitialized(false)
126 , dirEntry(copy.dirEntry)
127 , metaData(copy.metaData)
128 {
129 }
130
exists() const131 bool QDirPrivate::exists() const
132 {
133 if (fileEngine.isNull()) {
134 QFileSystemEngine::fillMetaData(dirEntry, metaData,
135 QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); // always stat
136 return metaData.exists() && metaData.isDirectory();
137 }
138 const QAbstractFileEngine::FileFlags info =
139 fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
140 | QAbstractFileEngine::ExistsFlag
141 | QAbstractFileEngine::Refresh);
142 if (!(info & QAbstractFileEngine::DirectoryType))
143 return false;
144 return info & QAbstractFileEngine::ExistsFlag;
145 }
146
147 // static
getFilterSepChar(const QString & nameFilter)148 inline QChar QDirPrivate::getFilterSepChar(const QString &nameFilter)
149 {
150 QChar sep(QLatin1Char(';'));
151 int i = nameFilter.indexOf(sep, 0);
152 if (i == -1 && nameFilter.indexOf(QLatin1Char(' '), 0) != -1)
153 sep = QChar(QLatin1Char(' '));
154 return sep;
155 }
156
157 // static
splitFilters(const QString & nameFilter,QChar sep)158 inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar sep)
159 {
160 if (sep == 0)
161 sep = getFilterSepChar(nameFilter);
162 QStringList ret = nameFilter.split(sep);
163 for (int i = 0; i < ret.count(); ++i)
164 ret[i] = ret[i].trimmed();
165 return ret;
166 }
167
setPath(const QString & path)168 inline void QDirPrivate::setPath(const QString &path)
169 {
170 QString p = QDir::fromNativeSeparators(path);
171 if (p.endsWith(QLatin1Char('/'))
172 && p.length() > 1
173 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
174 && (!(p.length() == 3 && p.at(1).unicode() == ':' && p.at(0).isLetter()))
175 #endif
176 ) {
177 p.truncate(p.length() - 1);
178 }
179
180 dirEntry = QFileSystemEntry(p, QFileSystemEntry::FromInternalPath());
181 metaData.clear();
182 initFileEngine();
183 clearFileLists();
184 absoluteDirEntry = QFileSystemEntry();
185 }
186
clearFileLists()187 inline void QDirPrivate::clearFileLists()
188 {
189 fileListsInitialized = false;
190 files.clear();
191 fileInfos.clear();
192 }
193
resolveAbsoluteEntry() const194 inline void QDirPrivate::resolveAbsoluteEntry() const
195 {
196 if (!absoluteDirEntry.isEmpty() || dirEntry.isEmpty())
197 return;
198
199 QString absoluteName;
200 if (fileEngine.isNull()) {
201 if (!dirEntry.isRelative() && dirEntry.isClean()) {
202 absoluteDirEntry = dirEntry;
203 return;
204 }
205
206 absoluteName = QFileSystemEngine::absoluteName(dirEntry).filePath();
207 } else {
208 absoluteName = fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
209 }
210
211 absoluteDirEntry = QFileSystemEntry(QDir::cleanPath(absoluteName), QFileSystemEntry::FromInternalPath());
212 }
213
214 /* For sorting */
215 struct QDirSortItem
216 {
217 mutable QString filename_cache;
218 mutable QString suffix_cache;
219 QFileInfo item;
220 };
221
222
223 class QDirSortItemComparator
224 {
225 int qt_cmp_si_sort_flags;
226 public:
QDirSortItemComparator(int flags)227 QDirSortItemComparator(int flags) : qt_cmp_si_sort_flags(flags) {}
228 bool operator()(const QDirSortItem &, const QDirSortItem &);
229 };
230
operator ()(const QDirSortItem & n1,const QDirSortItem & n2)231 bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortItem &n2)
232 {
233 const QDirSortItem* f1 = &n1;
234 const QDirSortItem* f2 = &n2;
235
236 if ((qt_cmp_si_sort_flags & QDir::DirsFirst) && (f1->item.isDir() != f2->item.isDir()))
237 return f1->item.isDir();
238 if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir()))
239 return !f1->item.isDir();
240
241 int r = 0;
242 int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask)
243 | (qt_cmp_si_sort_flags & QDir::Type);
244
245 switch (sortBy) {
246 case QDir::Time:
247 r = f1->item.lastModified().secsTo(f2->item.lastModified());
248 break;
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
sortFileList(QDir::SortFlags sort,QFileInfoList & l,QStringList * names,QFileInfoList * infos)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 }
initFileLists(const QDir & dir) const324 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
initFileEngine()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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/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 \o QDir \o QString \o Return Value
463 \row \o current() \o currentPath() \o The application's working directory
464 \row \o home() \o homePath() \o The user's home directory
465 \row \o root() \o rootPath() \o The root directory
466 \row \o temp() \o tempPath() \o 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 doc/src/snippets/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 doc/src/snippets/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 doc/src/snippets/qdir-listfiles/main.cpp 0
514
515 \sa QFileInfo, QFile, QFileDialog, QApplication::applicationDirPath(), {Find Files Example}
516 */
517
518 /*!
519 Constructs a QDir pointing to the given directory \a path. If path
520 is empty the program's working directory, ("."), is used.
521
522 \sa currentPath()
523 */
QDir(const QString & path)524 QDir::QDir(const QString &path) : d_ptr(new QDirPrivate(path))
525 {
526 }
527
528 /*!
529 Constructs a QDir with path \a path, that filters its entries by
530 name using \a nameFilter and by attributes using \a filters. It
531 also sorts the names using \a sort.
532
533 The default \a nameFilter is an empty string, which excludes
534 nothing; the default \a filters is \l AllEntries, which also means
535 exclude nothing. The default \a sort is \l Name | \l IgnoreCase,
536 i.e. sort by name case-insensitively.
537
538 If \a path is an empty string, QDir uses "." (the current
539 directory). If \a nameFilter is an empty string, QDir uses the
540 name filter "*" (all files).
541
542 Note that \a path need not exist.
543
544 \sa exists(), setPath(), setNameFilter(), setFilter(), setSorting()
545 */
QDir(const QString & path,const QString & nameFilter,SortFlags sort,Filters filters)546 QDir::QDir(const QString &path, const QString &nameFilter,
547 SortFlags sort, Filters filters)
548 : d_ptr(new QDirPrivate(path, QDir::nameFiltersFromString(nameFilter), sort, filters))
549 {
550 }
551
552 /*!
553 Constructs a QDir object that is a copy of the QDir object for
554 directory \a dir.
555
556 \sa operator=()
557 */
QDir(const QDir & dir)558 QDir::QDir(const QDir &dir)
559 : d_ptr(dir.d_ptr)
560 {
561 }
562
563 /*!
564 Destroys the QDir object frees up its resources. This has no
565 effect on the underlying directory in the file system.
566 */
~QDir()567 QDir::~QDir()
568 {
569 }
570
571 /*!
572 Sets the path of the directory to \a path. The path is cleaned of
573 redundant ".", ".." and of multiple separators. No check is made
574 to see whether a directory with this path actually exists; but you
575 can check for yourself using exists().
576
577 The path can be either absolute or relative. Absolute paths begin
578 with the directory separator "/" (optionally preceded by a drive
579 specification under Windows). Relative file names begin with a
580 directory name or a file name and specify a path relative to the
581 current directory. An example of an absolute path is the string
582 "/tmp/quartz", a relative path might look like "src/fatlib".
583
584 \sa path(), absolutePath(), exists(), cleanPath(), dirName(),
585 absoluteFilePath(), isRelative(), makeAbsolute()
586 */
setPath(const QString & path)587 void QDir::setPath(const QString &path)
588 {
589 d_ptr->setPath(path);
590 }
591
592 /*!
593 Returns the path. This may contain symbolic links, but never
594 contains redundant ".", ".." or multiple separators.
595
596 The returned path can be either absolute or relative (see
597 setPath()).
598
599 \sa setPath(), absolutePath(), exists(), cleanPath(), dirName(),
600 absoluteFilePath(), toNativeSeparators(), makeAbsolute()
601 */
path() const602 QString QDir::path() const
603 {
604 const QDirPrivate* d = d_ptr.constData();
605 return d->dirEntry.filePath();
606 }
607
608 /*!
609 Returns the absolute path (a path that starts with "/" or with a
610 drive specification), which may contain symbolic links, but never
611 contains redundant ".", ".." or multiple separators.
612
613 \sa setPath(), canonicalPath(), exists(), cleanPath(),
614 dirName(), absoluteFilePath()
615 */
absolutePath() const616 QString QDir::absolutePath() const
617 {
618 const QDirPrivate* d = d_ptr.constData();
619 d->resolveAbsoluteEntry();
620 return d->absoluteDirEntry.filePath();
621 }
622
623 /*!
624 Returns the canonical path, i.e. a path without symbolic links or
625 redundant "." or ".." elements.
626
627 On systems that do not have symbolic links this function will
628 always return the same string that absolutePath() returns. If the
629 canonical path does not exist (normally due to dangling symbolic
630 links) canonicalPath() returns an empty string.
631
632 Example:
633
634 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 6
635
636 \sa path(), absolutePath(), exists(), cleanPath(), dirName(),
637 absoluteFilePath()
638 */
canonicalPath() const639 QString QDir::canonicalPath() const
640 {
641 const QDirPrivate* d = d_ptr.constData();
642 if (d->fileEngine.isNull()) {
643 QFileSystemEntry answer = QFileSystemEngine::canonicalName(d->dirEntry, d->metaData);
644 return answer.filePath();
645 }
646 return d->fileEngine->fileName(QAbstractFileEngine::CanonicalName);
647 }
648
649 /*!
650 Returns the name of the directory; this is \e not the same as the
651 path, e.g. a directory with the name "mail", might have the path
652 "/var/spool/mail". If the directory has no name (e.g. it is the
653 root directory) an empty string is returned.
654
655 No check is made to ensure that a directory with this name
656 actually exists; but see exists().
657
658 \sa path(), filePath(), absolutePath(), absoluteFilePath()
659 */
dirName() const660 QString QDir::dirName() const
661 {
662 const QDirPrivate* d = d_ptr.constData();
663 return d->dirEntry.fileName();
664 }
665
666 /*!
667 Returns the path name of a file in the directory. Does \e not
668 check if the file actually exists in the directory; but see
669 exists(). If the QDir is relative the returned path name will also
670 be relative. Redundant multiple separators or "." and ".."
671 directories in \a fileName are not removed (see cleanPath()).
672
673 \sa dirName() absoluteFilePath(), isRelative(), canonicalPath()
674 */
filePath(const QString & fileName) const675 QString QDir::filePath(const QString &fileName) const
676 {
677 const QDirPrivate* d = d_ptr.constData();
678 if (isAbsolutePath(fileName))
679 return QString(fileName);
680
681 QString ret = d->dirEntry.filePath();
682 if (!fileName.isEmpty()) {
683 if (!ret.isEmpty() && ret[(int)ret.length()-1] != QLatin1Char('/') && fileName[0] != QLatin1Char('/'))
684 ret += QLatin1Char('/');
685 ret += fileName;
686 }
687 return ret;
688 }
689
690 /*!
691 Returns the absolute path name of a file in the directory. Does \e
692 not check if the file actually exists in the directory; but see
693 exists(). Redundant multiple separators or "." and ".."
694 directories in \a fileName are not removed (see cleanPath()).
695
696 \sa relativeFilePath() filePath() canonicalPath()
697 */
absoluteFilePath(const QString & fileName) const698 QString QDir::absoluteFilePath(const QString &fileName) const
699 {
700 const QDirPrivate* d = d_ptr.constData();
701 if (isAbsolutePath(fileName))
702 return fileName;
703
704 d->resolveAbsoluteEntry();
705 if (fileName.isEmpty())
706 return d->absoluteDirEntry.filePath();
707 if (!d->absoluteDirEntry.isRoot())
708 return d->absoluteDirEntry.filePath() % QLatin1Char('/') % fileName;
709 return d->absoluteDirEntry.filePath() % fileName;
710 }
711
712 /*!
713 Returns the path to \a fileName relative to the directory.
714
715 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 7
716
717 \sa absoluteFilePath() filePath() canonicalPath()
718 */
relativeFilePath(const QString & fileName) const719 QString QDir::relativeFilePath(const QString &fileName) const
720 {
721 QString dir = cleanPath(absolutePath());
722 QString file = cleanPath(fileName);
723
724 if (isRelativePath(file) || isRelativePath(dir))
725 return file;
726
727 QString dirDrive = driveSpec(dir);
728 QString fileDrive = driveSpec(file);
729
730 bool fileDriveMissing = false;
731 if (fileDrive.isEmpty()) {
732 fileDrive = dirDrive;
733 fileDriveMissing = true;
734 }
735
736 #ifdef Q_OS_WIN
737 if (fileDrive.toLower() != dirDrive.toLower()
738 || (file.startsWith(QLatin1String("//"))
739 && !dir.startsWith(QLatin1String("//"))))
740 #elif defined(Q_OS_SYMBIAN)
741 if (fileDrive.toLower() != dirDrive.toLower())
742 #else
743 if (fileDrive != dirDrive)
744 #endif
745 return file;
746
747 dir.remove(0, dirDrive.size());
748 if (!fileDriveMissing)
749 file.remove(0, fileDrive.size());
750
751 QString result;
752 QStringList dirElts = dir.split(QLatin1Char('/'), QString::SkipEmptyParts);
753 QStringList fileElts = file.split(QLatin1Char('/'), QString::SkipEmptyParts);
754
755 int i = 0;
756 while (i < dirElts.size() && i < fileElts.size() &&
757 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
758 dirElts.at(i).toLower() == fileElts.at(i).toLower())
759 #else
760 dirElts.at(i) == fileElts.at(i))
761 #endif
762 ++i;
763
764 for (int j = 0; j < dirElts.size() - i; ++j)
765 result += QLatin1String("../");
766
767 for (int j = i; j < fileElts.size(); ++j) {
768 result += fileElts.at(j);
769 if (j < fileElts.size() - 1)
770 result += QLatin1Char('/');
771 }
772
773 return result;
774 }
775
776 #ifndef QT_NO_DEPRECATED
777 /*!
778 \obsolete
779
780 Use QDir::toNativeSeparators() instead.
781 */
convertSeparators(const QString & pathName)782 QString QDir::convertSeparators(const QString &pathName)
783 {
784 return toNativeSeparators(pathName);
785 }
786 #endif
787
788 /*!
789 \since 4.2
790
791 Returns \a pathName with the '/' separators converted to
792 separators that are appropriate for the underlying operating
793 system.
794
795 On Windows, toNativeSeparators("c:/winnt/system32") returns
796 "c:\\winnt\\system32".
797
798 The returned string may be the same as the argument on some
799 operating systems, for example on Unix.
800
801 \sa fromNativeSeparators(), separator()
802 */
toNativeSeparators(const QString & pathName)803 QString QDir::toNativeSeparators(const QString &pathName)
804 {
805 #if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
806 int i = pathName.indexOf(QLatin1Char('/'));
807 if (i != -1) {
808 QString n(pathName);
809
810 QChar * const data = n.data();
811 data[i++] = QLatin1Char('\\');
812
813 for (; i < n.length(); ++i) {
814 if (data[i] == QLatin1Char('/'))
815 data[i] = QLatin1Char('\\');
816 }
817
818 return n;
819 }
820 #endif
821 return pathName;
822 }
823
824 /*!
825 \since 4.2
826
827 Returns \a pathName using '/' as file separator. On Windows,
828 for instance, fromNativeSeparators("\c{c:\\winnt\\system32}") returns
829 "c:/winnt/system32".
830
831 The returned string may be the same as the argument on some
832 operating systems, for example on Unix.
833
834 \sa toNativeSeparators(), separator()
835 */
fromNativeSeparators(const QString & pathName)836 QString QDir::fromNativeSeparators(const QString &pathName)
837 {
838 #if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
839 int i = pathName.indexOf(QLatin1Char('\\'));
840 if (i != -1) {
841 QString n(pathName);
842
843 QChar * const data = n.data();
844 data[i++] = QLatin1Char('/');
845
846 for (; i < n.length(); ++i) {
847 if (data[i] == QLatin1Char('\\'))
848 data[i] = QLatin1Char('/');
849 }
850
851 return n;
852 }
853 #endif
854 return pathName;
855 }
856
857 /*!
858 Changes the QDir's directory to \a dirName.
859
860 Returns true if the new directory exists and is readable;
861 otherwise returns false. Note that the logical cd() operation is
862 not performed if the new directory does not exist.
863
864 Calling cd("..") is equivalent to calling cdUp().
865
866 \sa cdUp(), isReadable(), exists(), path()
867 */
cd(const QString & dirName)868 bool QDir::cd(const QString &dirName)
869 {
870 // Don't detach just yet.
871 const QDirPrivate * const d = d_ptr.constData();
872
873 if (dirName.isEmpty() || dirName == QLatin1String("."))
874 return true;
875 QString newPath;
876 if (isAbsolutePath(dirName)) {
877 newPath = cleanPath(dirName);
878 } else {
879 if (isRoot()) {
880 if (dirName == QLatin1String(".."))
881 return false;
882 newPath = d->dirEntry.filePath();
883 } else {
884 newPath = d->dirEntry.filePath() % QLatin1Char('/');
885 }
886
887 newPath += dirName;
888 if (dirName.indexOf(QLatin1Char('/')) >= 0
889 || dirName == QLatin1String("..")
890 || d->dirEntry.filePath() == QLatin1String(".")) {
891 newPath = cleanPath(newPath);
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 */
cdUp()925 bool QDir::cdUp()
926 {
927 return cd(QString::fromLatin1(".."));
928 }
929
930 /*!
931 Returns the string list set by setNameFilters()
932 */
nameFilters() const933 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 doc/src/snippets/qdir-namefilters/main.cpp 0
951
952 \sa nameFilters(), setFilter()
953 */
setNameFilters(const QStringList & nameFilters)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 */
addResourceSearchPath(const QString & path)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 doc/src/snippets/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 */
setSearchPaths(const QString & prefix,const QStringList & searchPaths)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 */
addSearchPath(const QString & prefix,const QString & path)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 */
searchPaths(const QString & prefix)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 */
filter() const1061 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 DefaultFilter
1105 \omitvalue TypeMask
1106 \omitvalue All
1107 \omitvalue RWEMask
1108 \omitvalue AccessMask
1109 \omitvalue PermissionMask
1110 \omitvalue NoFilter
1111
1112 Functions that use Filter enum values to filter lists of files
1113 and directories will include symbolic links to files and directories
1114 unless you set the NoSymLinks value.
1115
1116 A default constructed QDir will not filter out files based on
1117 their permissions, so entryList() and entryInfoList() will return
1118 all files that are readable, writable, executable, or any
1119 combination of the three. This makes the default easy to write,
1120 and at the same time useful.
1121
1122 For example, setting the \c Readable, \c Writable, and \c Files
1123 flags allows all files to be listed for which the application has read
1124 access, write access or both. If the \c Dirs and \c Drives flags are
1125 also included in this combination then all drives, directories, all
1126 files that the application can read, write, or execute, and symlinks
1127 to such files/directories can be listed.
1128
1129 To retrieve the permissons for a directory, use the
1130 entryInfoList() function to get the associated QFileInfo objects
1131 and then use the QFileInfo::permissons() to obtain the permissions
1132 and ownership for each file.
1133 */
1134
1135 /*!
1136 Sets the filter used by entryList() and entryInfoList() to \a
1137 filters. The filter is used to specify the kind of files that
1138 should be returned by entryList() and entryInfoList(). See
1139 \l{QDir::Filter}.
1140
1141 \sa filter(), setNameFilters()
1142 */
setFilter(Filters filters)1143 void QDir::setFilter(Filters filters)
1144 {
1145 QDirPrivate* d = d_ptr.data();
1146 d->initFileEngine();
1147 d->clearFileLists();
1148
1149 d->filters = filters;
1150 }
1151
1152 /*!
1153 Returns the value set by setSorting()
1154
1155 \sa setSorting() SortFlag
1156 */
sorting() const1157 QDir::SortFlags QDir::sorting() const
1158 {
1159 const QDirPrivate* d = d_ptr.constData();
1160 return d->sort;
1161 }
1162
1163 /*!
1164 \enum QDir::SortFlag
1165
1166 This enum describes the sort options available to QDir, e.g. for
1167 entryList() and entryInfoList(). The sort value is specified by
1168 OR-ing together values from the following list:
1169
1170 \value Name Sort by name.
1171 \value Time Sort by time (modification time).
1172 \value Size Sort by file size.
1173 \value Type Sort by file type (extension).
1174 \value Unsorted Do not sort.
1175 \value NoSort Not sorted by default.
1176
1177 \value DirsFirst Put the directories first, then the files.
1178 \value DirsLast Put the files first, then the directories.
1179 \value Reversed Reverse the sort order.
1180 \value IgnoreCase Sort case-insensitively.
1181 \value LocaleAware Sort items appropriately using the current locale settings.
1182
1183 \omitvalue SortByMask
1184 \omitvalue DefaultSort
1185
1186 You can only specify one of the first four.
1187
1188 If you specify both DirsFirst and Reversed, directories are
1189 still put first, but in reverse order; the files will be listed
1190 after the directories, again in reverse order.
1191 */
1192
1193 /*!
1194 Sets the sort order used by entryList() and entryInfoList().
1195
1196 The \a sort is specified by OR-ing values from the enum
1197 \l{QDir::SortFlag}.
1198
1199 \sa sorting() SortFlag
1200 */
setSorting(SortFlags sort)1201 void QDir::setSorting(SortFlags sort)
1202 {
1203 QDirPrivate* d = d_ptr.data();
1204 d->initFileEngine();
1205 d->clearFileLists();
1206
1207 d->sort = sort;
1208 }
1209
1210 /*!
1211 Returns the total number of directories and files in the directory.
1212
1213 Equivalent to entryList().count().
1214
1215 \sa operator[](), entryList()
1216 */
count() const1217 uint QDir::count() const
1218 {
1219 const QDirPrivate* d = d_ptr.constData();
1220 d->initFileLists(*this);
1221 return d->files.count();
1222 }
1223
1224 /*!
1225 Returns the file name at position \a pos in the list of file
1226 names. Equivalent to entryList().at(index).
1227 \a pos must be a valid index position in the list (i.e., 0 <= pos < count()).
1228
1229 \sa count(), entryList()
1230 */
operator [](int pos) const1231 QString QDir::operator[](int pos) const
1232 {
1233 const QDirPrivate* d = d_ptr.constData();
1234 d->initFileLists(*this);
1235 return d->files[pos];
1236 }
1237
1238 /*!
1239 \overload
1240
1241 Returns a list of the names of all the files and directories in
1242 the directory, ordered according to the name and attribute filters
1243 previously set with setNameFilters() and setFilter(), and sorted according
1244 to the flags set with setSorting().
1245
1246 The attribute filter and sorting specifications can be overridden using the
1247 \a filters and \a sort arguments.
1248
1249 Returns an empty list if the directory is unreadable, does not
1250 exist, or if nothing matches the specification.
1251
1252 \note To list symlinks that point to non existing files, \l System must be
1253 passed to the filter.
1254
1255 \sa entryInfoList(), setNameFilters(), setSorting(), setFilter()
1256 */
entryList(Filters filters,SortFlags sort) const1257 QStringList QDir::entryList(Filters filters, SortFlags sort) const
1258 {
1259 const QDirPrivate* d = d_ptr.constData();
1260 return entryList(d->nameFilters, filters, sort);
1261 }
1262
1263
1264 /*!
1265 \overload
1266
1267 Returns a list of QFileInfo objects for all the files and directories in
1268 the directory, ordered according to the name and attribute filters
1269 previously set with setNameFilters() and setFilter(), and sorted according
1270 to the flags set with setSorting().
1271
1272 The attribute filter and sorting specifications can be overridden using the
1273 \a filters and \a sort arguments.
1274
1275 Returns an empty list if the directory is unreadable, does not
1276 exist, or if nothing matches the specification.
1277
1278 \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
1279 */
entryInfoList(Filters filters,SortFlags sort) const1280 QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const
1281 {
1282 const QDirPrivate* d = d_ptr.constData();
1283 return entryInfoList(d->nameFilters, filters, sort);
1284 }
1285
1286 /*!
1287 Returns a list of the names of all the files and
1288 directories in the directory, ordered according to the name
1289 and attribute filters previously set with setNameFilters()
1290 and setFilter(), and sorted according to the flags set with
1291 setSorting().
1292
1293 The name filter, file attribute filter, and sorting specification
1294 can be overridden using the \a nameFilters, \a filters, and \a sort
1295 arguments.
1296
1297 Returns an empty list if the directory is unreadable, does not
1298 exist, or if nothing matches the specification.
1299
1300 \sa entryInfoList(), setNameFilters(), setSorting(), setFilter()
1301 */
entryList(const QStringList & nameFilters,Filters filters,SortFlags sort) const1302 QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
1303 SortFlags sort) const
1304 {
1305 const QDirPrivate* d = d_ptr.constData();
1306
1307 if (filters == NoFilter)
1308 filters = d->filters;
1309 #ifdef QT3_SUPPORT
1310 if (d->matchAllDirs)
1311 filters |= AllDirs;
1312 #endif
1313 if (sort == NoSort)
1314 sort = d->sort;
1315
1316 if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
1317 d->initFileLists(*this);
1318 return d->files;
1319 }
1320
1321 QFileInfoList l;
1322 QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
1323 while (it.hasNext()) {
1324 it.next();
1325 l.append(it.fileInfo());
1326 }
1327 QStringList ret;
1328 d->sortFileList(sort, l, &ret, 0);
1329 return ret;
1330 }
1331
1332 /*!
1333 Returns a list of QFileInfo objects for all the files and
1334 directories in the directory, ordered according to the name
1335 and attribute filters previously set with setNameFilters()
1336 and setFilter(), and sorted according to the flags set with
1337 setSorting().
1338
1339 The name filter, file attribute filter, and sorting specification
1340 can be overridden using the \a nameFilters, \a filters, and \a sort
1341 arguments.
1342
1343 Returns an empty list if the directory is unreadable, does not
1344 exist, or if nothing matches the specification.
1345
1346 \sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
1347 */
entryInfoList(const QStringList & nameFilters,Filters filters,SortFlags sort) const1348 QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filters,
1349 SortFlags sort) const
1350 {
1351 const QDirPrivate* d = d_ptr.constData();
1352
1353 if (filters == NoFilter)
1354 filters = d->filters;
1355 #ifdef QT3_SUPPORT
1356 if (d->matchAllDirs)
1357 filters |= AllDirs;
1358 #endif
1359 if (sort == NoSort)
1360 sort = d->sort;
1361
1362 if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) {
1363 d->initFileLists(*this);
1364 return d->fileInfos;
1365 }
1366
1367 QFileInfoList l;
1368 QDirIterator it(d->dirEntry.filePath(), nameFilters, filters);
1369 while (it.hasNext()) {
1370 it.next();
1371 l.append(it.fileInfo());
1372 }
1373 QFileInfoList ret;
1374 d->sortFileList(sort, l, 0, &ret);
1375 return ret;
1376 }
1377
1378 /*!
1379 Creates a sub-directory called \a dirName.
1380
1381 Returns true on success; otherwise returns false.
1382
1383 If the directory already exists when this function is called, it will return false.
1384
1385 \sa rmdir()
1386 */
1387 // ### Qt5: behaviour when directory already exists should be made consistent for mkdir and mkpath
mkdir(const QString & dirName) const1388 bool QDir::mkdir(const QString &dirName) const
1389 {
1390 const QDirPrivate* d = d_ptr.constData();
1391
1392 if (dirName.isEmpty()) {
1393 qWarning("QDir::mkdir: Empty or null file name(s)");
1394 return false;
1395 }
1396
1397 QString fn = filePath(dirName);
1398 if (d->fileEngine.isNull())
1399 return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), false);
1400 return d->fileEngine->mkdir(fn, false);
1401 }
1402
1403 /*!
1404 Removes the directory specified by \a dirName.
1405
1406 The directory must be empty for rmdir() to succeed.
1407
1408 Returns true if successful; otherwise returns false.
1409
1410 \sa mkdir()
1411 */
rmdir(const QString & dirName) const1412 bool QDir::rmdir(const QString &dirName) const
1413 {
1414 const QDirPrivate* d = d_ptr.constData();
1415
1416 if (dirName.isEmpty()) {
1417 qWarning("QDir::rmdir: Empty or null file name(s)");
1418 return false;
1419 }
1420
1421 QString fn = filePath(dirName);
1422 if (d->fileEngine.isNull())
1423 return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), false);
1424
1425 return d->fileEngine->rmdir(fn, false);
1426 }
1427
1428 /*!
1429 Creates the directory path \a dirPath.
1430
1431 The function will create all parent directories necessary to
1432 create the directory.
1433
1434 Returns true if successful; otherwise returns false.
1435
1436 If the path already exists when this function is called, it will return true.
1437
1438 \sa rmpath()
1439 */
1440 // ### Qt5: behaviour when directory already exists should be made consistent for mkdir and mkpath
mkpath(const QString & dirPath) const1441 bool QDir::mkpath(const QString &dirPath) const
1442 {
1443 const QDirPrivate* d = d_ptr.constData();
1444
1445 if (dirPath.isEmpty()) {
1446 qWarning("QDir::mkpath: Empty or null file name(s)");
1447 return false;
1448 }
1449
1450 QString fn = filePath(dirPath);
1451 if (d->fileEngine.isNull())
1452 return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), true);
1453 return d->fileEngine->mkdir(fn, true);
1454 }
1455
1456 /*!
1457 Removes the directory path \a dirPath.
1458
1459 The function will remove all parent directories in \a dirPath,
1460 provided that they are empty. This is the opposite of
1461 mkpath(dirPath).
1462
1463 Returns true if successful; otherwise returns false.
1464
1465 \sa mkpath()
1466 */
rmpath(const QString & dirPath) const1467 bool QDir::rmpath(const QString &dirPath) const
1468 {
1469 const QDirPrivate* d = d_ptr.constData();
1470
1471 if (dirPath.isEmpty()) {
1472 qWarning("QDir::rmpath: Empty or null file name(s)");
1473 return false;
1474 }
1475
1476 QString fn = filePath(dirPath);
1477 if (d->fileEngine.isNull())
1478 return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), true);
1479 return d->fileEngine->rmdir(fn, true);
1480 }
1481
1482 /*!
1483 Returns true if the directory is readable \e and we can open files
1484 by name; otherwise returns false.
1485
1486 \warning A false value from this function is not a guarantee that
1487 files in the directory are not accessible.
1488
1489 \sa QFileInfo::isReadable()
1490 */
isReadable() const1491 bool QDir::isReadable() const
1492 {
1493 const QDirPrivate* d = d_ptr.constData();
1494
1495 if (d->fileEngine.isNull()) {
1496 if (!d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission))
1497 QFileSystemEngine::fillMetaData(d->dirEntry, d->metaData, QFileSystemMetaData::UserReadPermission);
1498
1499 return (d->metaData.permissions() & QFile::ReadUser) != 0;
1500 }
1501
1502 const QAbstractFileEngine::FileFlags info =
1503 d->fileEngine->fileFlags(QAbstractFileEngine::DirectoryType
1504 | QAbstractFileEngine::PermsMask);
1505 if (!(info & QAbstractFileEngine::DirectoryType))
1506 return false;
1507 return info & QAbstractFileEngine::ReadUserPerm;
1508 }
1509
1510 /*!
1511 \overload
1512
1513 Returns true if the directory exists; otherwise returns false.
1514 (If a file with the same name is found this function will return false).
1515
1516 The overload of this function that accepts an argument is used to test
1517 for the presence of files and directories within a directory.
1518
1519 \sa QFileInfo::exists(), QFile::exists()
1520 */
exists() const1521 bool QDir::exists() const
1522 {
1523 return d_ptr->exists();
1524 }
1525
1526 /*!
1527 Returns true if the directory is the root directory; otherwise
1528 returns false.
1529
1530 Note: If the directory is a symbolic link to the root directory
1531 this function returns false. If you want to test for this use
1532 canonicalPath(), e.g.
1533
1534 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 9
1535
1536 \sa root(), rootPath()
1537 */
isRoot() const1538 bool QDir::isRoot() const
1539 {
1540 if (d_ptr->fileEngine.isNull())
1541 return d_ptr->dirEntry.isRoot();
1542 return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::RootFlag;
1543 }
1544
1545 /*!
1546 \fn bool QDir::isAbsolute() const
1547
1548 Returns true if the directory's path is absolute; otherwise
1549 returns false. See isAbsolutePath().
1550
1551 \sa isRelative() makeAbsolute() cleanPath()
1552 */
1553
1554 /*!
1555 \fn bool QDir::isAbsolutePath(const QString &)
1556
1557 Returns true if \a path is absolute; returns false if it is
1558 relative.
1559
1560 \sa isAbsolute() isRelativePath() makeAbsolute() cleanPath()
1561 */
1562
1563 /*!
1564 Returns true if the directory path is relative; otherwise returns
1565 false. (Under Unix a path is relative if it does not start with a
1566 "/").
1567
1568 \sa makeAbsolute() isAbsolute() isAbsolutePath() cleanPath()
1569 */
isRelative() const1570 bool QDir::isRelative() const
1571 {
1572 if (d_ptr->fileEngine.isNull())
1573 return d_ptr->dirEntry.isRelative();
1574 return d_ptr->fileEngine->isRelativePath();
1575 }
1576
1577
1578 /*!
1579 Converts the directory path to an absolute path. If it is already
1580 absolute nothing happens. Returns true if the conversion
1581 succeeded; otherwise returns false.
1582
1583 \sa isAbsolute() isAbsolutePath() isRelative() cleanPath()
1584 */
makeAbsolute()1585 bool QDir::makeAbsolute()
1586 {
1587 const QDirPrivate *d = d_ptr.constData();
1588 QScopedPointer<QDirPrivate> dir;
1589 if (!d->fileEngine.isNull()) {
1590 QString absolutePath = d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName);
1591 if (QDir::isRelativePath(absolutePath))
1592 return false;
1593
1594 dir.reset(new QDirPrivate(*d_ptr.constData()));
1595 dir->setPath(absolutePath);
1596 } else { // native FS
1597 d->resolveAbsoluteEntry();
1598 dir.reset(new QDirPrivate(*d_ptr.constData()));
1599 dir->setPath(d->absoluteDirEntry.filePath());
1600 }
1601 d_ptr = dir.take(); // actually detach
1602 return true;
1603 }
1604
1605 /*!
1606 Returns true if directory \a dir and this directory have the same
1607 path and their sort and filter settings are the same; otherwise
1608 returns false.
1609
1610 Example:
1611
1612 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 10
1613 */
operator ==(const QDir & dir) const1614 bool QDir::operator==(const QDir &dir) const
1615 {
1616 const QDirPrivate *d = d_ptr.constData();
1617 const QDirPrivate *other = dir.d_ptr.constData();
1618
1619 if (d == other)
1620 return true;
1621 Qt::CaseSensitivity sensitive;
1622 if (d->fileEngine.isNull() || other->fileEngine.isNull()) {
1623 if (d->fileEngine.data() != other->fileEngine.data()) // one is native, the other is a custom file-engine
1624 return false;
1625
1626 sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
1627 } else {
1628 if (d->fileEngine->caseSensitive() != other->fileEngine->caseSensitive())
1629 return false;
1630 sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
1631 }
1632
1633 if (d->filters == other->filters
1634 && d->sort == other->sort
1635 && d->nameFilters == other->nameFilters) {
1636
1637 // Assume directories are the same if path is the same
1638 if (d->dirEntry.filePath() == other->dirEntry.filePath())
1639 return true;
1640
1641 if (exists()) {
1642 if (!dir.exists())
1643 return false; //can't be equal if only one exists
1644 // Both exist, fallback to expensive canonical path computation
1645 return canonicalPath().compare(dir.canonicalPath(), sensitive) == 0;
1646 } else {
1647 if (dir.exists())
1648 return false; //can't be equal if only one exists
1649 // Neither exists, compare absolute paths rather than canonical (which would be empty strings)
1650 d->resolveAbsoluteEntry();
1651 other->resolveAbsoluteEntry();
1652 return d->absoluteDirEntry.filePath().compare(other->absoluteDirEntry.filePath(), sensitive) == 0;
1653 }
1654 }
1655 return false;
1656 }
1657
1658 /*!
1659 Makes a copy of the \a dir object and assigns it to this QDir
1660 object.
1661 */
operator =(const QDir & dir)1662 QDir &QDir::operator=(const QDir &dir)
1663 {
1664 d_ptr = dir.d_ptr;
1665 return *this;
1666 }
1667
1668 /*!
1669 \overload
1670 \obsolete
1671
1672 Sets the directory path to the given \a path.
1673
1674 Use setPath() instead.
1675 */
operator =(const QString & path)1676 QDir &QDir::operator=(const QString &path)
1677 {
1678 d_ptr->setPath(path);
1679 return *this;
1680 }
1681
1682 /*!
1683 \fn bool QDir::operator!=(const QDir &dir) const
1684
1685 Returns true if directory \a dir and this directory have different
1686 paths or different sort or filter settings; otherwise returns
1687 false.
1688
1689 Example:
1690
1691 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 11
1692 */
1693
1694 /*!
1695 Removes the file, \a fileName.
1696
1697 Returns true if the file is removed successfully; otherwise
1698 returns false.
1699 */
remove(const QString & fileName)1700 bool QDir::remove(const QString &fileName)
1701 {
1702 if (fileName.isEmpty()) {
1703 qWarning("QDir::remove: Empty or null file name");
1704 return false;
1705 }
1706 return QFile::remove(filePath(fileName));
1707 }
1708
1709 /*!
1710 Renames a file or directory from \a oldName to \a newName, and returns
1711 true if successful; otherwise returns false.
1712
1713 On most file systems, rename() fails only if \a oldName does not
1714 exist, if \a newName and \a oldName are not on the same
1715 partition or if a file with the new name already exists.
1716 However, there are also other reasons why rename() can
1717 fail. For example, on at least one file system rename() fails if
1718 \a newName points to an open file.
1719 */
rename(const QString & oldName,const QString & newName)1720 bool QDir::rename(const QString &oldName, const QString &newName)
1721 {
1722 if (oldName.isEmpty() || newName.isEmpty()) {
1723 qWarning("QDir::rename: Empty or null file name(s)");
1724 return false;
1725 }
1726
1727 QFile file(filePath(oldName));
1728 if (!file.exists())
1729 return false;
1730 return file.rename(filePath(newName));
1731 }
1732
1733 /*!
1734 Returns true if the file called \a name exists; otherwise returns
1735 false.
1736
1737 Unless \a name contains an absolute file path, the file name is assumed
1738 to be relative to the directory itself, so this function is typically used
1739 to check for the presence of files within a directory.
1740
1741 \sa QFileInfo::exists(), QFile::exists()
1742 */
exists(const QString & name) const1743 bool QDir::exists(const QString &name) const
1744 {
1745 if (name.isEmpty()) {
1746 qWarning("QDir::exists: Empty or null file name");
1747 return false;
1748 }
1749 return QFile::exists(filePath(name));
1750 }
1751
1752 /*!
1753 Returns a list of the root directories on this system.
1754
1755 On Windows this returns a list of QFileInfo objects containing "C:/",
1756 "D:/", etc. On other operating systems, it returns a list containing
1757 just one root directory (i.e. "/").
1758
1759 \sa root(), rootPath()
1760 */
drives()1761 QFileInfoList QDir::drives()
1762 {
1763 #ifdef QT_NO_FSFILEENGINE
1764 return QFileInfoList();
1765 #else
1766 return QFSFileEngine::drives();
1767 #endif
1768 }
1769
1770 /*!
1771 Returns the native directory separator: "/" under Unix (including
1772 Mac OS X) and "\\" under Windows.
1773
1774 You do not need to use this function to build file paths. If you
1775 always use "/", Qt will translate your paths to conform to the
1776 underlying operating system. If you want to display paths to the
1777 user using their operating system's separator use
1778 toNativeSeparators().
1779 */
separator()1780 QChar QDir::separator()
1781 {
1782 #if defined (Q_FS_FAT) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
1783 return QLatin1Char('\\');
1784 #elif defined(Q_OS_UNIX)
1785 return QLatin1Char('/');
1786 #elif defined (Q_OS_MAC)
1787 return QLatin1Char(':');
1788 #else
1789 return QLatin1Char('/');
1790 #endif
1791 }
1792
1793 /*!
1794 Sets the application's current working directory to \a path.
1795 Returns true if the directory was successfully changed; otherwise
1796 returns false.
1797
1798 \sa current(), currentPath(), home(), root(), temp()
1799 */
setCurrent(const QString & path)1800 bool QDir::setCurrent(const QString &path)
1801 {
1802 return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
1803 }
1804
1805 /*!
1806 \fn QDir QDir::current()
1807
1808 Returns the application's current directory.
1809
1810 The directory is constructed using the absolute path of the current directory,
1811 ensuring that its path() will be the same as its absolutePath().
1812
1813 \sa currentPath(), setCurrent(), home(), root(), temp()
1814 */
1815
1816 /*!
1817 Returns the absolute path of the application's current directory.
1818
1819 \sa current(), setCurrent(), homePath(), rootPath(), tempPath()
1820 */
currentPath()1821 QString QDir::currentPath()
1822 {
1823 return QFileSystemEngine::currentPath().filePath();
1824 }
1825
1826 /*!
1827 \fn QString QDir::currentDirPath()
1828 Returns the absolute path of the application's current directory.
1829
1830 Use currentPath() instead.
1831
1832 \sa currentPath(), setCurrent()
1833 */
1834
1835 /*!
1836 \fn QDir QDir::home()
1837
1838 Returns the user's home directory.
1839
1840 The directory is constructed using the absolute path of the home directory,
1841 ensuring that its path() will be the same as its absolutePath().
1842
1843 See homePath() for details.
1844
1845 \sa drives(), current(), root(), temp()
1846 */
1847
1848 /*!
1849 Returns the absolute path of the user's home directory.
1850
1851 Under Windows this function will return the directory of the
1852 current user's profile. Typically, this is:
1853
1854 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 12
1855
1856 Use the toNativeSeparators() function to convert the separators to
1857 the ones that are appropriate for the underlying operating system.
1858
1859 If the directory of the current user's profile does not exist or
1860 cannot be retrieved, the following alternatives will be checked (in
1861 the given order) until an existing and available path is found:
1862
1863 \list 1
1864 \o The path specified by the \c USERPROFILE environment variable.
1865 \o The path formed by concatenating the \c HOMEDRIVE and \c HOMEPATH
1866 environment variables.
1867 \o The path specified by the \c HOME environment variable.
1868 \o The path returned by the rootPath() function (which uses the \c SystemDrive
1869 environment variable)
1870 \o The \c{C:/} directory.
1871 \endlist
1872
1873 Under non-Windows operating systems the \c HOME environment
1874 variable is used if it exists, otherwise the path returned by the
1875 rootPath().
1876
1877 On Symbian this typically returns "c:/data",
1878 i.e. the same as native PathInfo::PhoneMemoryRootPath().
1879
1880 \sa home(), currentPath(), rootPath(), tempPath()
1881 */
homePath()1882 QString QDir::homePath()
1883 {
1884 return QFileSystemEngine::homePath();
1885 }
1886
1887 /*!
1888 \fn QString QDir::homeDirPath()
1889
1890 Returns the absolute path of the user's home directory.
1891
1892 Use homePath() instead.
1893
1894 \sa homePath()
1895 */
1896
1897 /*!
1898 \fn QDir QDir::temp()
1899
1900 Returns the system's temporary directory.
1901
1902 The directory is constructed using the absolute path of the temporary directory,
1903 ensuring that its path() will be the same as its absolutePath().
1904
1905 See tempPath() for details.
1906
1907 \sa drives(), current(), home(), root()
1908 */
1909
1910 /*!
1911 Returns the absolute path of the system's temporary directory.
1912
1913 On Unix/Linux systems this is the path in the \c TMPDIR environment
1914 variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is
1915 usually the path in the \c TEMP or \c TMP environment
1916 variable. Whether a directory separator is added to the end or
1917 not, depends on the operating system.
1918
1919 \sa temp(), currentPath(), homePath(), rootPath()
1920 */
tempPath()1921 QString QDir::tempPath()
1922 {
1923 return QFileSystemEngine::tempPath();
1924 }
1925
1926 /*!
1927 \fn QDir QDir::root()
1928
1929 Returns the root directory.
1930
1931 The directory is constructed using the absolute path of the root directory,
1932 ensuring that its path() will be the same as its absolutePath().
1933
1934 See rootPath() for details.
1935
1936 \sa drives(), current(), home(), temp()
1937 */
1938
1939 /*!
1940 Returns the absolute path of the root directory.
1941
1942 For Unix operating systems this returns "/". For Windows and Symbian file
1943 systems this normally returns "c:/". I.E. the root of the system drive.
1944
1945 \sa root(), drives(), currentPath(), homePath(), tempPath()
1946 */
rootPath()1947 QString QDir::rootPath()
1948 {
1949 return QFileSystemEngine::rootPath();
1950 }
1951
1952 /*!
1953 \fn QString QDir::rootDirPath()
1954
1955 Returns the absolute path of the root directory.
1956
1957 Use rootPath() instead.
1958
1959 \sa rootPath()
1960 */
1961
1962 #ifndef QT_NO_REGEXP
1963 /*!
1964 \overload
1965
1966 Returns true if the \a fileName matches any of the wildcard (glob)
1967 patterns in the list of \a filters; otherwise returns false. The
1968 matching is case insensitive.
1969
1970 \sa {QRegExp wildcard matching}, QRegExp::exactMatch() entryList() entryInfoList()
1971 */
match(const QStringList & filters,const QString & fileName)1972 bool QDir::match(const QStringList &filters, const QString &fileName)
1973 {
1974 for (QStringList::ConstIterator sit = filters.constBegin(); sit != filters.constEnd(); ++sit) {
1975 QRegExp rx(*sit, Qt::CaseInsensitive, QRegExp::Wildcard);
1976 if (rx.exactMatch(fileName))
1977 return true;
1978 }
1979 return false;
1980 }
1981
1982 /*!
1983 Returns true if the \a fileName matches the wildcard (glob)
1984 pattern \a filter; otherwise returns false. The \a filter may
1985 contain multiple patterns separated by spaces or semicolons.
1986 The matching is case insensitive.
1987
1988 \sa {QRegExp wildcard matching}, QRegExp::exactMatch() entryList() entryInfoList()
1989 */
match(const QString & filter,const QString & fileName)1990 bool QDir::match(const QString &filter, const QString &fileName)
1991 {
1992 return match(nameFiltersFromString(filter), fileName);
1993 }
1994 #endif // QT_NO_REGEXP
1995
1996 /*!
1997 Removes all multiple directory separators "/" and resolves any
1998 "."s or ".."s found in the path, \a path.
1999
2000 Symbolic links are kept. This function does not return the
2001 canonical path, but rather the simplest version of the input.
2002 For example, "./local" becomes "local", "local/../bin" becomes
2003 "bin" and "/local/usr/../bin" becomes "/local/bin".
2004
2005 \sa absolutePath() canonicalPath()
2006 */
cleanPath(const QString & path)2007 QString QDir::cleanPath(const QString &path)
2008 {
2009 if (path.isEmpty())
2010 return path;
2011 QString name = path;
2012 QChar dir_separator = separator();
2013 if (dir_separator != QLatin1Char('/'))
2014 name.replace(dir_separator, QLatin1Char('/'));
2015
2016 int used = 0, levels = 0;
2017 const int len = name.length();
2018 QVarLengthArray<QChar> outVector(len);
2019 QChar *out = outVector.data();
2020
2021 const QChar *p = name.unicode();
2022 for (int i = 0, last = -1, iwrite = 0; i < len; ++i) {
2023 if (p[i] == QLatin1Char('/')) {
2024 while (i+1 < len && p[i+1] == QLatin1Char('/')) {
2025 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths
2026 if (!i)
2027 break;
2028 #endif
2029 i++;
2030 }
2031 bool eaten = false;
2032 if (i+1 < len && p[i+1] == QLatin1Char('.')) {
2033 int dotcount = 1;
2034 if (i+2 < len && p[i+2] == QLatin1Char('.'))
2035 dotcount++;
2036 if (i == len - dotcount - 1) {
2037 if (dotcount == 1) {
2038 break;
2039 } else if (levels) {
2040 if (last == -1) {
2041 for (int i2 = iwrite-1; i2 >= 0; i2--) {
2042 if (out[i2] == QLatin1Char('/')) {
2043 last = i2;
2044 break;
2045 }
2046 }
2047 }
2048 used -= iwrite - last - 1;
2049 break;
2050 }
2051 } else if (p[i+dotcount+1] == QLatin1Char('/')) {
2052 if (dotcount == 2 && levels) {
2053 if (last == -1 || iwrite - last == 1) {
2054 for (int i2 = (last == -1) ? (iwrite-1) : (last-1); i2 >= 0; i2--) {
2055 if (out[i2] == QLatin1Char('/')) {
2056 eaten = true;
2057 last = i2;
2058 break;
2059 }
2060 }
2061 } else {
2062 eaten = true;
2063 }
2064 if (eaten) {
2065 levels--;
2066 used -= iwrite - last;
2067 iwrite = last;
2068 last = -1;
2069 }
2070 } else if (dotcount == 2 && i > 0 && p[i - 1] != QLatin1Char('.')) {
2071 eaten = true;
2072 used -= iwrite - qMax(0, last);
2073 iwrite = qMax(0, last);
2074 last = -1;
2075 ++i;
2076 } else if (dotcount == 1) {
2077 eaten = true;
2078 }
2079 if (eaten)
2080 i += dotcount;
2081 } else {
2082 levels++;
2083 }
2084 } else if (last != -1 && iwrite - last == 1) {
2085 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
2086 eaten = (iwrite > 2);
2087 #else
2088 eaten = true;
2089 #endif
2090 last = -1;
2091 } else if (last != -1 && i == len-1) {
2092 eaten = true;
2093 } else {
2094 levels++;
2095 }
2096 if (!eaten)
2097 last = i - (i - iwrite);
2098 else
2099 continue;
2100 } else if (!i && p[i] == QLatin1Char('.')) {
2101 int dotcount = 1;
2102 if (len >= 1 && p[1] == QLatin1Char('.'))
2103 dotcount++;
2104 if (len >= dotcount && p[dotcount] == QLatin1Char('/')) {
2105 if (dotcount == 1) {
2106 i++;
2107 while (i+1 < len-1 && p[i+1] == QLatin1Char('/'))
2108 i++;
2109 continue;
2110 }
2111 }
2112 }
2113 out[iwrite++] = p[i];
2114 used++;
2115 }
2116
2117 QString ret = (used == len ? name : QString(out, used));
2118 // Strip away last slash except for root directories
2119 if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
2120 #if defined (Q_OS_WIN) || defined (Q_OS_SYMBIAN)
2121 if (!(ret.length() == 3 && ret.at(1) == QLatin1Char(':')))
2122 #endif
2123 ret.chop(1);
2124 }
2125
2126 return ret;
2127 }
2128
2129 /*!
2130 Returns true if \a path is relative; returns false if it is
2131 absolute.
2132
2133 \sa isRelative() isAbsolutePath() makeAbsolute()
2134 */
isRelativePath(const QString & path)2135 bool QDir::isRelativePath(const QString &path)
2136 {
2137 return QFileInfo(path).isRelative();
2138 }
2139
2140 /*!
2141 Refreshes the directory information.
2142 */
refresh() const2143 void QDir::refresh() const
2144 {
2145 QDirPrivate *d = const_cast<QDir*>(this)->d_ptr.data();
2146 d->metaData.clear();
2147 d->initFileEngine();
2148 d->clearFileLists();
2149 }
2150
2151 /*!
2152 \internal
2153
2154 Returns a list of name filters from the given \a nameFilter. (If
2155 there is more than one filter, each pair of filters is separated
2156 by a space or by a semicolon.)
2157 */
nameFiltersFromString(const QString & nameFilter)2158 QStringList QDir::nameFiltersFromString(const QString &nameFilter)
2159 {
2160 return QDirPrivate::splitFilters(nameFilter);
2161 }
2162
2163 /*!
2164 \macro void Q_INIT_RESOURCE(name)
2165 \relates QDir
2166
2167 Initializes the resources specified by the \c .qrc file with the
2168 specified base \a name. Normally, Qt resources are loaded
2169 automatically at startup. The Q_INIT_RESOURCE() macro is
2170 necessary on some platforms for resources stored in a static
2171 library.
2172
2173 For example, if your application's resources are listed in a file
2174 called \c myapp.qrc, you can ensure that the resources are
2175 initialized at startup by adding this line to your \c main()
2176 function:
2177
2178 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 13
2179
2180 If the file name contains characters that cannot be part of a valid C++ function name
2181 (such as '-'), they have to be replaced by the underscore character ('_').
2182
2183 Note: This macro cannot be used in a namespace. It should be called from
2184 main(). If that is not possible, the following workaround can be used
2185 to init the resource \c myapp from the function \c{MyNamespace::myFunction}:
2186
2187 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 14
2188
2189 \sa Q_CLEANUP_RESOURCE(), {The Qt Resource System}
2190 */
2191
2192 /*!
2193 \since 4.1
2194 \macro void Q_CLEANUP_RESOURCE(name)
2195 \relates QDir
2196
2197 Unloads the resources specified by the \c .qrc file with the base
2198 name \a name.
2199
2200 Normally, Qt resources are unloaded automatically when the
2201 application terminates, but if the resources are located in a
2202 plugin that is being unloaded, call Q_CLEANUP_RESOURCE() to force
2203 removal of your resources.
2204
2205 Note: This macro cannot be used in a namespace. Please see the
2206 Q_INIT_RESOURCE documentation for a workaround.
2207
2208 Example:
2209
2210 \snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 15
2211
2212 \sa Q_INIT_RESOURCE(), {The Qt Resource System}
2213 */
2214
2215 #ifdef QT3_SUPPORT
2216
2217 /*!
2218 \fn bool QDir::matchAllDirs() const
2219
2220 Use filter() & AllDirs instead.
2221 */
matchAllDirs() const2222 bool QDir::matchAllDirs() const
2223 {
2224 const QDirPrivate* d = d_ptr.constData();
2225 return d->matchAllDirs;
2226 }
2227
2228
2229 /*!
2230 \fn void QDir::setMatchAllDirs(bool on)
2231
2232 Use setFilter() instead.
2233 */
setMatchAllDirs(bool on)2234 void QDir::setMatchAllDirs(bool on)
2235 {
2236 QDirPrivate* d = d_ptr.data();
2237 d->initFileEngine();
2238 d->clearFileLists();
2239
2240 d->matchAllDirs = on;
2241 }
2242
2243 /*!
2244 Use nameFilters() instead.
2245 */
nameFilter() const2246 QString QDir::nameFilter() const
2247 {
2248 const QDirPrivate* d = d_ptr.constData();
2249 return nameFilters().join(QString(d->filterSepChar));
2250 }
2251
2252 /*!
2253 Use setNameFilters() instead.
2254
2255 The \a nameFilter is a wildcard (globbing) filter that understands
2256 "*" and "?" wildcards. (See \l{QRegExp wildcard matching}.) You may
2257 specify several filter entries, each separated by spaces or by
2258 semicolons.
2259
2260 For example, if you want entryList() and entryInfoList() to list
2261 all files ending with either ".cpp" or ".h", you would use either
2262 dir.setNameFilters("*.cpp *.h") or dir.setNameFilters("*.cpp;*.h").
2263
2264 \oldcode
2265 QString filter = "*.cpp *.cxx *.cc";
2266 dir.setNameFilter(filter);
2267 \newcode
2268 QString filter = "*.cpp *.cxx *.cc";
2269 dir.setNameFilters(filter.split(' '));
2270 \endcode
2271 */
setNameFilter(const QString & nameFilter)2272 void QDir::setNameFilter(const QString &nameFilter)
2273 {
2274 QDirPrivate* d = d_ptr.data();
2275 d->initFileEngine();
2276 d->clearFileLists();
2277
2278 d->filterSepChar = QDirPrivate::getFilterSepChar(nameFilter);
2279 d->nameFilters = QDirPrivate::splitFilters(nameFilter, d->filterSepChar);
2280 }
2281
2282 /*!
2283 \fn QString QDir::absPath() const
2284
2285 Use absolutePath() instead.
2286 */
2287
2288 /*!
2289 \fn QString QDir::absFilePath(const QString &fileName, bool acceptAbsPath) const
2290
2291 Use absoluteFilePath(\a fileName) instead.
2292
2293 The \a acceptAbsPath parameter is ignored.
2294 */
2295
2296 /*!
2297 \fn bool QDir::mkdir(const QString &dirName, bool acceptAbsPath) const
2298
2299 Use mkdir(\a dirName) instead.
2300
2301 The \a acceptAbsPath parameter is ignored.
2302 */
2303
2304 /*!
2305 \fn bool QDir::rmdir(const QString &dirName, bool acceptAbsPath) const
2306
2307 Use rmdir(\a dirName) instead.
2308
2309 The \a acceptAbsPath parameter is ignored.
2310 */
2311
2312 /*!
2313 \fn QStringList QDir::entryList(const QString &nameFilter, Filters filters,
2314 SortFlags sort) const
2315 \overload
2316
2317 Use the overload that takes a name filter string list as first
2318 argument instead of a combination of attribute filter flags.
2319 */
2320
2321 /*!
2322 \fn QFileInfoList QDir::entryInfoList(const QString &nameFilter, Filters filters,
2323 SortFlags sort) const
2324 \overload
2325
2326 Use the overload that takes a name filter string list as first
2327 argument instead of a combination of attribute filter flags.
2328 */
2329
2330 /*!
2331 \fn void QDir::convertToAbs()
2332
2333 Use makeAbsolute() instead.
2334 */
2335
2336 /*!
2337 \fn QString QDir::cleanDirPath(const QString &name)
2338
2339 Use cleanPath() instead.
2340 */
2341
2342 /*!
2343 \typedef QDir::FilterSpec
2344
2345 Use QDir::Filters instead.
2346 */
2347
2348 /*!
2349 \typedef QDir::SortSpec
2350
2351 Use QDir::SortFlags instead.
2352 */
2353 #endif // QT3_SUPPORT
2354
2355 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug debug,QDir::Filters filters)2356 QDebug operator<<(QDebug debug, QDir::Filters filters)
2357 {
2358 QStringList flags;
2359 if (filters == QDir::NoFilter) {
2360 flags << QLatin1String("NoFilter");
2361 } else {
2362 if (filters & QDir::Dirs) flags << QLatin1String("Dirs");
2363 if (filters & QDir::AllDirs) flags << QLatin1String("AllDirs");
2364 if (filters & QDir::Files) flags << QLatin1String("Files");
2365 if (filters & QDir::Drives) flags << QLatin1String("Drives");
2366 if (filters & QDir::NoSymLinks) flags << QLatin1String("NoSymLinks");
2367 if (filters & QDir::NoDotAndDotDot) flags << QLatin1String("NoDotAndDotDot"); // ### Qt5: remove (because NoDotAndDotDot=NoDot|NoDotDot)
2368 if (filters & QDir::NoDot) flags << QLatin1String("NoDot");
2369 if (filters & QDir::NoDotDot) flags << QLatin1String("NoDotDot");
2370 if ((filters & QDir::AllEntries) == QDir::AllEntries) flags << QLatin1String("AllEntries");
2371 if (filters & QDir::Readable) flags << QLatin1String("Readable");
2372 if (filters & QDir::Writable) flags << QLatin1String("Writable");
2373 if (filters & QDir::Executable) flags << QLatin1String("Executable");
2374 if (filters & QDir::Modified) flags << QLatin1String("Modified");
2375 if (filters & QDir::Hidden) flags << QLatin1String("Hidden");
2376 if (filters & QDir::System) flags << QLatin1String("System");
2377 if (filters & QDir::CaseSensitive) flags << QLatin1String("CaseSensitive");
2378 }
2379 debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ')';
2380 return debug;
2381 }
2382
operator <<(QDebug debug,QDir::SortFlags sorting)2383 static QDebug operator<<(QDebug debug, QDir::SortFlags sorting)
2384 {
2385 if (sorting == QDir::NoSort) {
2386 debug << "QDir::SortFlags(NoSort)";
2387 } else {
2388 QString type;
2389 if ((sorting & 3) == QDir::Name) type = QLatin1String("Name");
2390 if ((sorting & 3) == QDir::Time) type = QLatin1String("Time");
2391 if ((sorting & 3) == QDir::Size) type = QLatin1String("Size");
2392 if ((sorting & 3) == QDir::Unsorted) type = QLatin1String("Unsorted");
2393
2394 QStringList flags;
2395 if (sorting & QDir::DirsFirst) flags << QLatin1String("DirsFirst");
2396 if (sorting & QDir::DirsLast) flags << QLatin1String("DirsLast");
2397 if (sorting & QDir::IgnoreCase) flags << QLatin1String("IgnoreCase");
2398 if (sorting & QDir::LocaleAware) flags << QLatin1String("LocaleAware");
2399 if (sorting & QDir::Type) flags << QLatin1String("Type");
2400 debug << "QDir::SortFlags(" << qPrintable(type)
2401 << '|'
2402 << qPrintable(flags.join(QLatin1String("|"))) << ')';
2403 }
2404 return debug;
2405 }
2406
operator <<(QDebug debug,const QDir & dir)2407 QDebug operator<<(QDebug debug, const QDir &dir)
2408 {
2409 debug.maybeSpace() << "QDir(" << dir.path()
2410 << ", nameFilters = {"
2411 << qPrintable(dir.nameFilters().join(QLatin1String(",")))
2412 << "}, "
2413 << dir.sorting()
2414 << ','
2415 << dir.filter()
2416 << ')';
2417 return debug.space();
2418 }
2419 #endif // QT_NO_DEBUG_STREAM
2420
2421 QT_END_NAMESPACE
2422