source: vendor/trolltech/current/src/tools/qdir.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 38.4 KB
Line 
1/****************************************************************************
2** $Id: qdir.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QDir class
5**
6** Created : 950427
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qplatformdefs.h"
39#include "qdir.h"
40
41#ifndef QT_NO_DIR
42#include <private/qdir_p.h>
43#include "qfileinfo.h"
44#include "qregexp.h"
45#include "qstringlist.h"
46#include "qdeepcopy.h"
47#include <limits.h>
48
49#if defined(Q_FS_FAT) && !defined(Q_OS_UNIX)
50const bool CaseSensitiveFS = FALSE;
51#else
52const bool CaseSensitiveFS = TRUE;
53#endif
54
55
56/*!
57 \class QDir
58 \reentrant
59 \brief The QDir class provides access to directory structures and their contents in a platform-independent way.
60
61 \ingroup io
62 \mainclass
63
64 A QDir is used to manipulate path names, access information
65 regarding paths and files, and manipulate the underlying file
66 system.
67
68 A QDir can point to a file using either a relative or an absolute
69 path. Absolute paths begin with the directory separator "/"
70 (optionally preceded by a drive specification under Windows). If
71 you always use "/" as a directory separator, Qt will translate
72 your paths to conform to the underlying operating system. Relative
73 file names begin with a directory name or a file name and specify
74 a path relative to the current directory.
75
76 The "current" path refers to the application's working directory.
77 A QDir's own path is set and retrieved with setPath() and path().
78
79 An example of an absolute path is the string "/tmp/quartz", a
80 relative path might look like "src/fatlib". You can use the
81 function isRelative() to check if a QDir is using a relative or an
82 absolute file path. Call convertToAbs() to convert a relative QDir
83 to an absolute one. For a simplified path use cleanDirPath(). To
84 obtain a path which has no symbolic links or redundant ".."
85 elements use canonicalPath(). The path can be set with setPath(),
86 and changed with cd() and cdUp().
87
88 QDir provides several static functions, for example, setCurrent()
89 to set the application's working directory and currentDirPath() to
90 retrieve the application's working directory. Access to some
91 common paths is provided with the static functions, current(),
92 home() and root() which return QDir objects or currentDirPath(),
93 homeDirPath() and rootDirPath() which return the path as a string.
94 If you want to know about your application's path use
95 \l{QApplication::applicationDirPath()}.
96
97 The number of entries in a directory is returned by count().
98 Obtain a string list of the names of all the files and directories
99 in a directory with entryList(). If you prefer a list of QFileInfo
100 pointers use entryInfoList(). Both these functions can apply a
101 name filter, an attributes filter (e.g. read-only, files not
102 directories, etc.), and a sort order. The filters and sort may be
103 set with calls to setNameFilter(), setFilter() and setSorting().
104 They may also be specified in the entryList() and
105 entryInfoList()'s arguments.
106
107 Create a new directory with mkdir(), rename a directory with
108 rename() and remove an existing directory with rmdir(). Remove a
109 file with remove(). You can interrogate a directory with exists(),
110 isReadable() and isRoot().
111
112 To get a path with a filename use filePath(), and to get a
113 directory name use dirName(); neither of these functions checks
114 for the existence of the file or directory.
115
116 The list of root directories is provided by drives(); on Unix
117 systems this returns a list containing one root directory, "/"; on
118 Windows the list will usually contain "C:/", and possibly "D:/",
119 etc.
120
121 It is easiest to work with "/" separators in Qt code. If you need
122 to present a path to the user or need a path in a form suitable
123 for a function in the underlying operating system use
124 convertSeparators().
125
126 Examples:
127
128 See if a directory exists.
129 \code
130 QDir d( "example" ); // "./example"
131 if ( !d.exists() )
132 qWarning( "Cannot find the example directory" );
133 \endcode
134
135 Traversing directories and reading a file.
136 \code
137 QDir d = QDir::root(); // "/"
138 if ( !d.cd("tmp") ) { // "/tmp"
139 qWarning( "Cannot find the \"/tmp\" directory" );
140 } else {
141 QFile f( d.filePath("ex1.txt") ); // "/tmp/ex1.txt"
142 if ( !f.open(IO_ReadWrite) )
143 qWarning( "Cannot create the file %s", f.name() );
144 }
145 \endcode
146
147 A program that lists all the files in the current directory
148 (excluding symbolic links), sorted by size, smallest first:
149 \code
150 #include <stdio.h>
151 #include <qdir.h>
152
153 int main( int argc, char **argv )
154 {
155 QDir d;
156 d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );
157 d.setSorting( QDir::Size | QDir::Reversed );
158
159 const QFileInfoList *list = d.entryInfoList();
160 QFileInfoListIterator it( *list );
161 QFileInfo *fi;
162
163 printf( " Bytes Filename\n" );
164 while ( (fi = it.current()) != 0 ) {
165 printf( "%10li %s\n", fi->size(), fi->fileName().latin1() );
166 ++it;
167 }
168 return 0;
169 }
170 \endcode
171
172 \sa QApplication::applicationDirPath()
173*/
174
175/*!
176 Constructs a QDir pointing to the current directory (".").
177
178 \sa currentDirPath()
179*/
180
181QDir::QDir()
182{
183 dPath = QString::fromLatin1(".");
184 init();
185}
186
187/*!
188 Constructs a QDir with path \a path, that filters its entries by
189 name using \a nameFilter and by attributes using \a filterSpec. It
190 also sorts the names using \a sortSpec.
191
192 The default \a nameFilter is an empty string, which excludes
193 nothing; the default \a filterSpec is \c All, which also means
194 exclude nothing. The default \a sortSpec is \c Name|IgnoreCase,
195 i.e. sort by name case-insensitively.
196
197 Example that lists all the files in "/tmp":
198 \code
199 QDir d( "/tmp" );
200 for ( int i = 0; i < d.count(); i++ )
201 printf( "%s\n", d[i] );
202 \endcode
203
204 If \a path is "" or QString::null, QDir uses "." (the current
205 directory). If \a nameFilter is "" or QString::null, QDir uses the
206 name filter "*" (all files).
207
208 Note that \a path need not exist.
209
210 \sa exists(), setPath(), setNameFilter(), setFilter(), setSorting()
211*/
212
213QDir::QDir( const QString &path, const QString &nameFilter,
214 int sortSpec, int filterSpec )
215{
216 init();
217 dPath = cleanDirPath( path );
218 if ( dPath.isEmpty() )
219 dPath = QString::fromLatin1(".");
220 nameFilt = nameFilter;
221 if ( nameFilt.isEmpty() )
222 nameFilt = QString::fromLatin1("*");
223 filtS = (FilterSpec)filterSpec;
224 sortS = (SortSpec)sortSpec;
225}
226
227/*!
228 Constructs a QDir that is a copy of the directory \a d.
229
230 \sa operator=()
231*/
232
233QDir::QDir( const QDir &d )
234{
235 dPath = d.dPath;
236 fList = 0;
237 fiList = 0;
238 nameFilt = d.nameFilt;
239 dirty = TRUE;
240 allDirs = d.allDirs;
241 filtS = d.filtS;
242 sortS = d.sortS;
243}
244
245/*!
246 Refreshes the directory information.
247*/
248void QDir::refresh() const
249{
250 QDir* that = (QDir*) this;
251 that->dirty = TRUE;
252}
253
254void QDir::init()
255{
256 fList = 0;
257 fiList = 0;
258 nameFilt = QString::fromLatin1("*");
259 dirty = TRUE;
260 allDirs = FALSE;
261 filtS = All;
262 sortS = SortSpec(Name | IgnoreCase);
263}
264
265/*!
266 Destroys the QDir frees up its resources.
267*/
268
269QDir::~QDir()
270{
271 delete fList;
272 delete fiList;
273}
274
275
276/*!
277 Sets the path of the directory to \a path. The path is cleaned of
278 redundant ".", ".." and of multiple separators. No check is made
279 to ensure that a directory with this path exists.
280
281 The path can be either absolute or relative. Absolute paths begin
282 with the directory separator "/" (optionally preceded by a drive
283 specification under Windows). Relative file names begin with a
284 directory name or a file name and specify a path relative to the
285 current directory. An example of an absolute path is the string
286 "/tmp/quartz", a relative path might look like "src/fatlib".
287
288 \sa path(), absPath(), exists(), cleanDirPath(), dirName(),
289 absFilePath(), isRelative(), convertToAbs()
290*/
291
292void QDir::setPath( const QString &path )
293{
294 dPath = cleanDirPath( path );
295 if ( dPath.isEmpty() )
296 dPath = QString::fromLatin1(".");
297 dirty = TRUE;
298}
299
300/*!
301 \fn QString QDir::path() const
302
303 Returns the path, this may contain symbolic links, but never
304 contains redundant ".", ".." or multiple separators.
305
306 The returned path can be either absolute or relative (see
307 setPath()).
308
309 \sa setPath(), absPath(), exists(), cleanDirPath(), dirName(),
310 absFilePath(), convertSeparators()
311*/
312
313/*!
314 Returns the absolute path (a path that starts with "/" or with a
315 drive specification), which may contain symbolic links, but never
316 contains redundant ".", ".." or multiple separators.
317
318 \sa setPath(), canonicalPath(), exists(), cleanDirPath(),
319 dirName(), absFilePath()
320*/
321
322QString QDir::absPath() const
323{
324 if ( QDir::isRelativePath(dPath) ) {
325 QString tmp = currentDirPath();
326 if ( tmp.right(1) != QString::fromLatin1("/") )
327 tmp += '/';
328 tmp += dPath;
329 return cleanDirPath( tmp );
330 } else {
331 return cleanDirPath( dPath );
332 }
333}
334
335/*!
336 Returns the name of the directory; this is \e not the same as the
337 path, e.g. a directory with the name "mail", might have the path
338 "/var/spool/mail". If the directory has no name (e.g. it is the
339 root directory) QString::null is returned.
340
341 No check is made to ensure that a directory with this name
342 actually exists.
343
344 \sa path(), absPath(), absFilePath(), exists(), QString::isNull()
345*/
346
347QString QDir::dirName() const
348{
349 int pos = dPath.findRev( '/' );
350 if ( pos == -1 )
351 return dPath;
352 return dPath.right( dPath.length() - pos - 1 );
353}
354
355/*!
356 Returns the path name of a file in the directory. Does \e not
357 check if the file actually exists in the directory. If the QDir is
358 relative the returned path name will also be relative. Redundant
359 multiple separators or "." and ".." directories in \a fileName
360 will not be removed (see cleanDirPath()).
361
362 If \a acceptAbsPath is TRUE a \a fileName starting with a
363 separator "/" will be returned without change. If \a acceptAbsPath
364 is FALSE an absolute path will be prepended to the fileName and
365 the resultant string returned.
366
367 \sa absFilePath(), isRelative(), canonicalPath()
368*/
369
370QString QDir::filePath( const QString &fileName,
371 bool acceptAbsPath ) const
372{
373 if ( acceptAbsPath && !isRelativePath(fileName) )
374 return QString(fileName);
375
376 QString tmp = dPath;
377 if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName &&
378 fileName[0] != '/') )
379 tmp += '/';
380 tmp += fileName;
381 return tmp;
382}
383
384/*!
385 Returns the absolute path name of a file in the directory. Does \e
386 not check if the file actually exists in the directory. Redundant
387 multiple separators or "." and ".." directories in \a fileName
388 will not be removed (see cleanDirPath()).
389
390 If \a acceptAbsPath is TRUE a \a fileName starting with a
391 separator "/" will be returned without change. If \a acceptAbsPath
392 is FALSE an absolute path will be prepended to the fileName and
393 the resultant string returned.
394
395 \sa filePath()
396*/
397
398QString QDir::absFilePath( const QString &fileName,
399 bool acceptAbsPath ) const
400{
401 if ( acceptAbsPath && !isRelativePath( fileName ) )
402 return fileName;
403
404 QString tmp = absPath();
405#ifdef Q_OS_WIN32
406 if ( fileName[0].isLetter() && fileName[1] == ':' ) {
407 int drv = fileName.upper()[0].latin1() - 'A' + 1;
408 if ( _getdrive() != drv ) {
409 QT_WA( {
410 TCHAR buf[PATH_MAX];
411 ::_wgetdcwd( drv, buf, PATH_MAX );
412 tmp.setUnicodeCodes( (ushort*)buf, ::wcslen(buf) );
413 }, {
414 char buf[PATH_MAX];
415 ::_getdcwd( drv, buf, PATH_MAX );
416 tmp = buf;
417 } );
418 if ( !tmp.endsWith("\\") )
419 tmp += "\\";
420 tmp += fileName.right( fileName.length() - 2 );
421 int x;
422 for ( x = 0; x < (int) tmp.length(); x++ ) {
423 if ( tmp[x] == '\\' )
424 tmp[x] = '/';
425 }
426 }
427 } else
428#endif
429 {
430 if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName &&
431 fileName[0] != '/') )
432 tmp += '/';
433 tmp += fileName;
434 }
435 return tmp;
436}
437
438
439/*!
440 Returns \a pathName with the '/' separators converted to
441 separators that are appropriate for the underlying operating
442 system.
443
444 On Windows, convertSeparators("c:/winnt/system32") returns
445 "c:\winnt\system32".
446
447 The returned string may be the same as the argument on some
448 operating systems, for example on Unix.
449*/
450
451QString QDir::convertSeparators( const QString &pathName )
452{
453 QString n( pathName );
454#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX)
455 for ( int i=0; i<(int)n.length(); i++ ) {
456 if ( n[i] == '/' )
457 n[i] = '\\';
458 }
459#elif defined(Q_OS_MAC9)
460 while(n.length() && n[0] == '/' ) n = n.right(n.length()-1);
461 for ( int i=0; i<(int)n.length(); i++ ) {
462 if ( n[i] == '/' )
463 n[i] = ':';
464 }
465 if(n.contains(':') && n.left(1) != ':')
466 n.prepend(':');
467#endif
468 return n;
469}
470
471
472/*!
473 Changes the QDir's directory to \a dirName.
474
475 If \a acceptAbsPath is TRUE a path starting with separator "/"
476 will cause the function to change to the absolute directory. If \a
477 acceptAbsPath is FALSE any number of separators at the beginning
478 of \a dirName will be removed and the function will descend into
479 \a dirName.
480
481 Returns TRUE if the new directory exists and is readable;
482 otherwise returns FALSE. Note that the logical cd() operation is
483 not performed if the new directory does not exist.
484
485 Calling cd( ".." ) is equivalent to calling cdUp().
486
487 \sa cdUp(), isReadable(), exists(), path()
488*/
489
490bool QDir::cd( const QString &dirName, bool acceptAbsPath )
491{
492 if ( dirName.isEmpty() || dirName == QString::fromLatin1(".") )
493 return TRUE;
494 QString old = dPath;
495 if ( acceptAbsPath && !isRelativePath(dirName) ) {
496 dPath = cleanDirPath( dirName );
497 } else {
498 if ( isRoot() ) {
499 if ( dirName == ".." ) {
500 dPath = old;
501 return FALSE;
502 }
503 } else {
504 dPath += '/';
505 }
506
507 dPath += dirName;
508 if ( dirName.find('/') >= 0
509 || old == QString::fromLatin1(".")
510 || dirName == QString::fromLatin1("..") ) {
511 dPath = cleanDirPath( dPath );
512
513 /*
514 If dPath starts with .., we convert it to absolute to
515 avoid infinite looping on
516
517 QDir dir( "." );
518 while ( dir.cdUp() )
519 ;
520 */
521 if ( dPath[0] == QChar('.') && dPath[1] == QChar('.') &&
522 (dPath.length() == 2 || dPath[2] == QChar('/')) )
523 convertToAbs();
524 }
525 }
526 if ( !exists() ) {
527 dPath = old; // regret
528 return FALSE;
529 }
530 dirty = TRUE;
531 return TRUE;
532}
533
534/*!
535 Changes directory by moving one directory up from the QDir's
536 current directory.
537
538 Returns TRUE if the new directory exists and is readable;
539 otherwise returns FALSE. Note that the logical cdUp() operation is
540 not performed if the new directory does not exist.
541
542 \sa cd(), isReadable(), exists(), path()
543*/
544
545bool QDir::cdUp()
546{
547 return cd( QString::fromLatin1("..") );
548}
549
550/*!
551 \fn QString QDir::nameFilter() const
552
553 Returns the string set by setNameFilter()
554*/
555
556/*!
557 Sets the name filter used by entryList() and entryInfoList() to \a
558 nameFilter.
559
560 The \a nameFilter is a wildcard (globbing) filter that understands
561 "*" and "?" wildcards. (See \link qregexp.html#wildcard-matching
562 QRegExp wildcard matching\endlink.) You may specify several filter
563 entries all separated by a single space " " or by a semi-colon
564 ";".
565
566 For example, if you want entryList() and entryInfoList() to list
567 all files ending with either ".cpp" or ".h", you would use either
568 dir.setNameFilter("*.cpp *.h") or dir.setNameFilter("*.cpp;*.h").
569
570 \sa nameFilter(), setFilter()
571*/
572
573void QDir::setNameFilter( const QString &nameFilter )
574{
575 nameFilt = nameFilter;
576 if ( nameFilt.isEmpty() )
577 nameFilt = QString::fromLatin1("*");
578 dirty = TRUE;
579}
580
581/*!
582 \fn QDir::FilterSpec QDir::filter() const
583
584 Returns the value set by setFilter()
585*/
586
587/*!
588 \enum QDir::FilterSpec
589
590 This enum describes the filtering options available to QDir, e.g.
591 for entryList() and entryInfoList(). The filter value is specified
592 by OR-ing together values from the following list:
593
594 \value Dirs List directories only.
595 \value Files List files only.
596 \value Drives List disk drives (ignored under Unix).
597 \value NoSymLinks Do not list symbolic links (ignored by operating
598 systems that don't support symbolic links).
599 \value All List directories, files, drives and symlinks (this does not list
600 broken symlinks unless you specify System).
601 \value TypeMask A mask for the the Dirs, Files, Drives and
602 NoSymLinks flags.
603 \value Readable List files for which the application has read access.
604 \value Writable List files for which the application has write access.
605 \value Executable List files for which the application has execute
606 access. Executables needs to be combined with Dirs or Files.
607 \value RWEMask A mask for the Readable, Writable and Executable flags.
608 \value Modified Only list files that have been modified (ignored
609 under Unix).
610 \value Hidden List hidden files (on Unix, files starting with a .).
611 \value System List system files (on Unix, FIFOs, sockets and
612 device files)
613 \value AccessMask A mask for the Readable, Writable, Executable
614 Modified, Hidden and System flags
615 \value DefaultFilter Internal flag.
616
617 If you do not set any of \c Readable, \c Writable or \c
618 Executable, QDir will set all three of them. This makes the
619 default easy to write and at the same time useful.
620
621 Examples: \c Readable|Writable means list all files for which the
622 application has read access, write access or both. \c Dirs|Drives
623 means list drives, directories, all files that the application can
624 read, write or execute, and also symlinks to such
625 files/directories.
626*/
627
628
629/*!
630 Sets the filter used by entryList() and entryInfoList() to \a
631 filterSpec. The filter is used to specify the kind of files that
632 should be returned by entryList() and entryInfoList(). See
633 \l{QDir::FilterSpec}.
634
635 \sa filter(), setNameFilter()
636*/
637
638void QDir::setFilter( int filterSpec )
639{
640 if ( filtS == (FilterSpec) filterSpec )
641 return;
642 filtS = (FilterSpec) filterSpec;
643 dirty = TRUE;
644}
645
646/*!
647 \fn QDir::SortSpec QDir::sorting() const
648
649 Returns the value set by setSorting()
650
651 \sa setSorting() SortSpec
652*/
653
654/*!
655 \enum QDir::SortSpec
656
657 This enum describes the sort options available to QDir, e.g. for
658 entryList() and entryInfoList(). The sort value is specified by
659 OR-ing together values from the following list:
660
661 \value Name Sort by name.
662 \value Time Sort by time (modification time).
663 \value Size Sort by file size.
664 \value Unsorted Do not sort.
665 \value SortByMask A mask for Name, Time and Size.
666
667 \value DirsFirst Put the directories first, then the files.
668 \value Reversed Reverse the sort order.
669 \value IgnoreCase Sort case-insensitively.
670 \value DefaultSort Internal flag.
671
672 You can only specify one of the first four.
673
674 If you specify both \c DirsFirst and \c Reversed, directories are
675 still put first, but in reverse order; the files will be listed
676 after the directories, again in reverse order.
677*/
678
679// ### Unsorted+DirsFirst ? Unsorted+Reversed?
680
681/*!
682 Sets the sort order used by entryList() and entryInfoList().
683
684 The \a sortSpec is specified by OR-ing values from the enum
685 \l{QDir::SortSpec}.
686
687 \sa sorting() SortSpec
688*/
689
690void QDir::setSorting( int sortSpec )
691{
692 if ( sortS == (SortSpec) sortSpec )
693 return;
694 sortS = (SortSpec) sortSpec;
695 dirty = TRUE;
696}
697
698/*!
699 \fn bool QDir::matchAllDirs() const
700
701 Returns the value set by setMatchAllDirs()
702
703 \sa setMatchAllDirs()
704*/
705
706/*!
707 If \a enable is TRUE then all directories are included (e.g. in
708 entryList()), and the nameFilter() is only applied to the files.
709 If \a enable is FALSE then the nameFilter() is applied to both
710 directories and files.
711
712 \sa matchAllDirs()
713*/
714
715void QDir::setMatchAllDirs( bool enable )
716{
717 if ( (bool)allDirs == enable )
718 return;
719 allDirs = enable;
720 dirty = TRUE;
721}
722
723
724/*!
725 Returns the total number of directories and files that were found.
726
727 Equivalent to entryList().count().
728
729 \sa operator[](), entryList()
730*/
731
732uint QDir::count() const
733{
734 return (uint)entryList().count();
735}
736
737/*!
738 Returns the file name at position \a index in the list of file
739 names. Equivalent to entryList().at(index).
740
741 Returns a QString::null if the \a index is out of range or if the
742 entryList() function failed.
743
744 \sa count(), entryList()
745*/
746
747QString QDir::operator[]( int index ) const
748{
749 entryList();
750 return fList && index >= 0 && index < (int)fList->count() ?
751 (*fList)[index] : QString::null;
752}
753
754
755/*!
756 \obsolete
757 This function is included to easy porting from Qt 1.x to Qt 2.0,
758 it is the same as entryList(), but encodes the filenames as 8-bit
759 strings using QFile::encodedName().
760
761 It is more efficient to use entryList().
762*/
763QStrList QDir::encodedEntryList( int filterSpec, int sortSpec ) const
764{
765 QStrList r;
766 QStringList l = entryList(filterSpec,sortSpec);
767 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
768 r.append( QFile::encodeName(*it) );
769 }
770 return r;
771}
772
773/*!
774 \obsolete
775 \overload
776 This function is included to easy porting from Qt 1.x to Qt 2.0,
777 it is the same as entryList(), but encodes the filenames as 8-bit
778 strings using QFile::encodedName().
779
780 It is more efficient to use entryList().
781*/
782QStrList QDir::encodedEntryList( const QString &nameFilter,
783 int filterSpec,
784 int sortSpec ) const
785{
786 QStrList r;
787 QStringList l = entryList(nameFilter,filterSpec,sortSpec);
788 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
789 r.append( QFile::encodeName(*it) );
790 }
791 return r;
792}
793
794
795
796/*!
797 \overload
798
799 Returns a list of the names of all the files and directories in
800 the directory, ordered in accordance with setSorting() and
801 filtered in accordance with setFilter() and setNameFilter().
802
803 The filter and sorting specifications can be overridden using the
804 \a filterSpec and \a sortSpec arguments.
805
806 Returns an empty list if the directory is unreadable or does not
807 exist.
808
809 \sa entryInfoList(), setNameFilter(), setSorting(), setFilter()
810*/
811
812QStringList QDir::entryList( int filterSpec, int sortSpec ) const
813{
814 if ( !dirty && filterSpec == (int)DefaultFilter &&
815 sortSpec == (int)DefaultSort )
816 return *fList;
817 return entryList( nameFilt, filterSpec, sortSpec );
818}
819
820/*!
821 Returns a list of the names of all the files and directories in
822 the directory, ordered in accordance with setSorting() and
823 filtered in accordance with setFilter() and setNameFilter().
824
825 The filter and sorting specifications can be overridden using the
826 \a nameFilter, \a filterSpec and \a sortSpec arguments.
827
828 Returns an empty list if the directory is unreadable or does not
829 exist.
830
831 \sa entryInfoList(), setNameFilter(), setSorting(), setFilter()
832*/
833
834QStringList QDir::entryList( const QString &nameFilter,
835 int filterSpec, int sortSpec ) const
836{
837 if ( filterSpec == (int)DefaultFilter )
838 filterSpec = filtS;
839 if ( sortSpec == (int)DefaultSort )
840 sortSpec = sortS;
841 QDir *that = (QDir*)this; // mutable function
842 if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) ) {
843 if ( that->fList )
844 return *that->fList;
845 }
846 return QStringList();
847}
848
849/*!
850 \overload
851
852 Returns a list of QFileInfo objects for all the files and
853 directories in the directory, ordered in accordance with
854 setSorting() and filtered in accordance with setFilter() and
855 setNameFilter().
856
857 The filter and sorting specifications can be overridden using the
858 \a filterSpec and \a sortSpec arguments.
859
860 Returns 0 if the directory is unreadable or does not exist.
861
862 The returned pointer is a const pointer to a QFileInfoList. The
863 list is owned by the QDir object and will be reused on the next
864 call to entryInfoList() for the same QDir instance. If you want to
865 keep the entries of the list after a subsequent call to this
866 function you must copy them.
867
868 Note: QFileInfoList is really a QPtrList<QFileInfo>.
869
870 \sa entryList(), setNameFilter(), setSorting(), setFilter()
871*/
872
873const QFileInfoList *QDir::entryInfoList( int filterSpec, int sortSpec ) const
874{
875 if ( !dirty && filterSpec == (int)DefaultFilter &&
876 sortSpec == (int)DefaultSort )
877 return fiList;
878 return entryInfoList( nameFilt, filterSpec, sortSpec );
879}
880
881/*!
882 Returns a list of QFileInfo objects for all the files and
883 directories in the directory, ordered in accordance with
884 setSorting() and filtered in accordance with setFilter() and
885 setNameFilter().
886
887 The filter and sorting specifications can be overridden using the
888 \a nameFilter, \a filterSpec and \a sortSpec arguments.
889
890 Returns 0 if the directory is unreadable or does not exist.
891
892 The returned pointer is a const pointer to a QFileInfoList. The
893 list is owned by the QDir object and will be reused on the next
894 call to entryInfoList() for the same QDir instance. If you want to
895 keep the entries of the list after a subsequent call to this
896 function you must copy them.
897
898 Note: QFileInfoList is really a QPtrList<QFileInfo>.
899
900 \sa entryList(), setNameFilter(), setSorting(), setFilter()
901*/
902
903const QFileInfoList *QDir::entryInfoList( const QString &nameFilter,
904 int filterSpec, int sortSpec ) const
905{
906 if ( filterSpec == (int)DefaultFilter )
907 filterSpec = filtS;
908 if ( sortSpec == (int)DefaultSort )
909 sortSpec = sortS;
910 QDir *that = (QDir*)this; // mutable function
911 if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) )
912 return that->fiList;
913 else
914 return 0;
915}
916
917/*!
918 \overload
919
920 Returns TRUE if the \e directory exists; otherwise returns FALSE.
921 (If a file with the same name is found this function will return
922 FALSE).
923
924 \sa QFileInfo::exists(), QFile::exists()
925*/
926
927bool QDir::exists() const
928{
929 QFileInfo fi( dPath );
930 return fi.exists() && fi.isDir();
931}
932
933/*!
934 Returns TRUE if the directory path is relative to the current
935 directory and returns FALSE if the path is absolute (e.g. under
936 UNIX a path is relative if it does not start with a "/").
937
938 \sa convertToAbs()
939*/
940
941bool QDir::isRelative() const
942{
943 return isRelativePath( dPath );
944}
945
946/*!
947 Converts the directory path to an absolute path. If it is already
948 absolute nothing is done.
949
950 \sa isRelative()
951*/
952
953void QDir::convertToAbs()
954{
955 dPath = absPath();
956}
957
958/*!
959 Makes a copy of QDir \a d and assigns it to this QDir.
960*/
961
962QDir &QDir::operator=( const QDir &d )
963{
964 dPath = d.dPath;
965 delete fList;
966 fList = 0;
967 delete fiList;
968 fiList = 0;
969 nameFilt = d.nameFilt;
970 dirty = TRUE;
971 allDirs = d.allDirs;
972 filtS = d.filtS;
973 sortS = d.sortS;
974 return *this;
975}
976
977/*!
978 \overload
979
980 Sets the directory path to be the given \a path.
981*/
982
983QDir &QDir::operator=( const QString &path )
984{
985 dPath = cleanDirPath( path );
986 dirty = TRUE;
987 return *this;
988}
989
990
991/*!
992 \fn bool QDir::operator!=( const QDir &d ) const
993
994 Returns TRUE if directory \a d and this directory have different
995 paths or different sort or filter settings; otherwise returns
996 FALSE.
997
998 Example:
999 \code
1000 // The current directory is "/usr/local"
1001 QDir d1( "/usr/local/bin" );
1002 QDir d2( "bin" );
1003 if ( d1 != d2 )
1004 qDebug( "They differ" );
1005 \endcode
1006*/
1007
1008/*!
1009 Returns TRUE if directory \a d and this directory have the same
1010 path and their sort and filter settings are the same; otherwise
1011 returns FALSE.
1012
1013 Example:
1014 \code
1015 // The current directory is "/usr/local"
1016 QDir d1( "/usr/local/bin" );
1017 QDir d2( "bin" );
1018 d2.convertToAbs();
1019 if ( d1 == d2 )
1020 qDebug( "They're the same" );
1021 \endcode
1022*/
1023
1024bool QDir::operator==( const QDir &d ) const
1025{
1026 return dPath == d.dPath &&
1027 nameFilt == d.nameFilt &&
1028 allDirs == d.allDirs &&
1029 filtS == d.filtS &&
1030 sortS == d.sortS;
1031}
1032
1033
1034/*!
1035 Removes the file, \a fileName.
1036
1037 If \a acceptAbsPath is TRUE a path starting with separator "/"
1038 will remove the file with the absolute path. If \a acceptAbsPath
1039 is FALSE any number of separators at the beginning of \a fileName
1040 will be removed and the resultant file name will be removed.
1041
1042 Returns TRUE if the file is removed successfully; otherwise
1043 returns FALSE.
1044*/
1045
1046bool QDir::remove( const QString &fileName, bool acceptAbsPath )
1047{
1048 if ( fileName.isEmpty() ) {
1049#if defined(QT_CHECK_NULL)
1050 qWarning( "QDir::remove: Empty or null file name" );
1051#endif
1052 return FALSE;
1053 }
1054 QString p = filePath( fileName, acceptAbsPath );
1055 return QFile::remove( p );
1056}
1057
1058/*!
1059 Checks for the existence of the file \a name.
1060
1061 If \a acceptAbsPath is TRUE a path starting with separator "/"
1062 will check the file with the absolute path. If \a acceptAbsPath is
1063 FALSE any number of separators at the beginning of \a name will be
1064 removed and the resultant file name will be checked.
1065
1066 Returns TRUE if the file exists; otherwise returns FALSE.
1067
1068 \sa QFileInfo::exists(), QFile::exists()
1069*/
1070
1071bool QDir::exists( const QString &name, bool acceptAbsPath ) //### const in 4.0
1072{
1073 if ( name.isEmpty() ) {
1074#if defined(QT_CHECK_NULL)
1075 qWarning( "QDir::exists: Empty or null file name" );
1076#endif
1077 return FALSE;
1078 }
1079 QString tmp = filePath( name, acceptAbsPath );
1080 return QFile::exists( tmp );
1081}
1082
1083/*!
1084 Returns the native directory separator; "/" under UNIX (including
1085 Mac OS X) and "\" under Windows.
1086
1087 You do not need to use this function to build file paths. If you
1088 always use "/", Qt will translate your paths to conform to the
1089 underlying operating system.
1090*/
1091
1092char QDir::separator()
1093{
1094#if defined(Q_OS_UNIX)
1095 return '/';
1096#elif defined (Q_FS_FAT) || defined(Q_WS_WIN)
1097 return '\\';
1098#elif defined (Q_OS_MAC)
1099 return ':';
1100#else
1101 return '/';
1102#endif
1103}
1104
1105/*!
1106 Returns the application's current directory.
1107
1108 Use path() to access a QDir object's path.
1109
1110 \sa currentDirPath(), QDir::QDir()
1111*/
1112
1113QDir QDir::current()
1114{
1115 return QDir( currentDirPath() );
1116}
1117
1118/*!
1119 Returns the home directory.
1120
1121 Under Windows the \c HOME environment variable is used. If this
1122 does not exist the \c USERPROFILE environment variable is used. If
1123 that does not exist the path is formed by concatenating the \c
1124 HOMEDRIVE and \c HOMEPATH environment variables. If they don't
1125 exist the rootDirPath() is used (this uses the \c SystemDrive
1126 environment variable). If none of these exist "C:\" is used.
1127
1128 Under non-Windows operating systems the \c HOME environment
1129 variable is used if it exists, otherwise rootDirPath() is used.
1130
1131 \sa homeDirPath()
1132*/
1133
1134QDir QDir::home()
1135{
1136 return QDir( homeDirPath() );
1137}
1138
1139/*!
1140 Returns the root directory.
1141
1142 \sa rootDirPath() drives()
1143*/
1144
1145QDir QDir::root()
1146{
1147 return QDir( rootDirPath() );
1148}
1149
1150/*!
1151 \fn QString QDir::homeDirPath()
1152
1153 Returns the absolute path of the user's home directory.
1154
1155 \sa home()
1156*/
1157
1158QValueList<QRegExp> qt_makeFilterList( const QString &filter )
1159{
1160 QValueList<QRegExp> regExps;
1161 if ( filter.isEmpty() )
1162 return regExps;
1163
1164 QChar sep( ';' );
1165 int i = filter.find( sep, 0 );
1166 if ( i == -1 && filter.find( ' ', 0 ) != -1 )
1167 sep = QChar( ' ' );
1168
1169 QStringList list = QStringList::split( sep, filter );
1170 QStringList::Iterator it = list.begin();
1171 while ( it != list.end() ) {
1172 regExps << QRegExp( (*it).stripWhiteSpace(), CaseSensitiveFS, TRUE );
1173 ++it;
1174 }
1175 return regExps;
1176}
1177
1178bool qt_matchFilterList( const QValueList<QRegExp>& filters,
1179 const QString &fileName )
1180{
1181 QValueList<QRegExp>::ConstIterator rit = filters.begin();
1182 while ( rit != filters.end() ) {
1183 if ( (*rit).exactMatch(fileName) )
1184 return TRUE;
1185 ++rit;
1186 }
1187 return FALSE;
1188}
1189
1190
1191/*!
1192 \overload
1193
1194 Returns TRUE if the \a fileName matches any of the wildcard (glob)
1195 patterns in the list of \a filters; otherwise returns FALSE.
1196
1197 (See \link qregexp.html#wildcard-matching QRegExp wildcard
1198 matching.\endlink)
1199 \sa QRegExp::match()
1200*/
1201
1202bool QDir::match( const QStringList &filters, const QString &fileName )
1203{
1204 QStringList::ConstIterator sit = filters.begin();
1205 while ( sit != filters.end() ) {
1206 QRegExp rx( *sit, CaseSensitiveFS, TRUE );
1207 if ( rx.exactMatch(fileName) )
1208 return TRUE;
1209 ++sit;
1210 }
1211 return FALSE;
1212}
1213
1214/*!
1215 Returns TRUE if the \a fileName matches the wildcard (glob)
1216 pattern \a filter; otherwise returns FALSE. The \a filter may
1217 contain multiple patterns separated by spaces or semicolons.
1218
1219 (See \link qregexp.html#wildcard-matching QRegExp wildcard
1220 matching.\endlink)
1221 \sa QRegExp::match()
1222*/
1223
1224bool QDir::match( const QString &filter, const QString &fileName )
1225{
1226 return qt_matchFilterList( qt_makeFilterList(filter), fileName );
1227}
1228
1229
1230/*!
1231 Removes all multiple directory separators "/" and resolves any
1232 "."s or ".."s found in the path, \a filePath.
1233
1234 Symbolic links are kept. This function does not return the
1235 canonical path, but rather the simplest version of the input.
1236 For example, "./local" becomes "local", "local/../bin" becomes
1237 "bin" and "/local/usr/../bin" becomes "/local/bin".
1238
1239 \sa absPath() canonicalPath()
1240*/
1241
1242QString QDir::cleanDirPath( const QString &filePath )
1243{
1244 QString name = filePath;
1245 QString newPath;
1246
1247 if ( name.isEmpty() )
1248 return name;
1249
1250 slashify( name );
1251
1252 bool addedSeparator = isRelativePath( name );
1253 if ( addedSeparator )
1254 name.insert( 0, '/' );
1255
1256 int ePos, pos, upLevel;
1257
1258 pos = ePos = name.length();
1259 upLevel = 0;
1260 int len;
1261
1262 while ( pos && (pos = name.findRev('/', pos - 1)) != -1 ) {
1263 len = ePos - pos - 1;
1264 if ( len == 2 && name.at(pos + 1) == '.'
1265 && name.at(pos + 2) == '.' ) {
1266 upLevel++;
1267 } else {
1268 if ( len != 0 && (len != 1 || name.at(pos + 1) != '.') ) {
1269 if ( !upLevel )
1270 newPath = QString::fromLatin1("/")
1271 + name.mid(pos + 1, len) + newPath;
1272 else
1273 upLevel--;
1274 }
1275 }
1276 ePos = pos;
1277 }
1278 if ( addedSeparator ) {
1279 while ( upLevel-- )
1280 newPath.insert( 0, QString::fromLatin1("/..") );
1281 if ( !newPath.isEmpty() )
1282 newPath.remove( (uint)0, (uint)1 );
1283 else
1284 newPath = QString::fromLatin1(".");
1285 } else {
1286 if ( newPath.isEmpty() )
1287 newPath = QString::fromLatin1("/");
1288#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX)
1289 if ( name[0] == '/' ) {
1290 if ( name[1] == '/' ) // "\\machine\x\ ..."
1291 newPath.insert( 0, '/' );
1292 } else {
1293 newPath = name.left(2) + newPath;
1294 }
1295#endif
1296 }
1297 return newPath;
1298}
1299
1300int qt_cmp_si_sortSpec;
1301
1302#if defined(Q_C_CALLBACKS)
1303extern "C" {
1304#endif
1305
1306#ifdef Q_OS_TEMP
1307int __cdecl qt_cmp_si( const void *n1, const void *n2 )
1308#else
1309int qt_cmp_si( const void *n1, const void *n2 )
1310#endif
1311{
1312 if ( !n1 || !n2 )
1313 return 0;
1314
1315 QDirSortItem* f1 = (QDirSortItem*)n1;
1316 QDirSortItem* f2 = (QDirSortItem*)n2;
1317
1318 if ( qt_cmp_si_sortSpec & QDir::DirsFirst )
1319 if ( f1->item->isDir() != f2->item->isDir() )
1320 return f1->item->isDir() ? -1 : 1;
1321
1322 int r = 0;
1323 int sortBy = qt_cmp_si_sortSpec & QDir::SortByMask;
1324
1325 switch ( sortBy ) {
1326 case QDir::Time:
1327 r = f1->item->lastModified().secsTo(f2->item->lastModified());
1328 break;
1329 case QDir::Size:
1330 r = f2->item->size() - f1->item->size();
1331 break;
1332 default:
1333 ;
1334 }
1335
1336 if ( r == 0 && sortBy != QDir::Unsorted ) {
1337 // Still not sorted - sort by name
1338 bool ic = qt_cmp_si_sortSpec & QDir::IgnoreCase;
1339
1340 if ( f1->filename_cache.isNull() )
1341 f1->filename_cache = ic ? f1->item->fileName().lower()
1342 : f1->item->fileName();
1343 if ( f2->filename_cache.isNull() )
1344 f2->filename_cache = ic ? f2->item->fileName().lower()
1345 : f2->item->fileName();
1346
1347 r = f1->filename_cache.compare(f2->filename_cache);
1348 }
1349
1350 if ( r == 0 ) {
1351 // Enforce an order - the order the items appear in the array
1352 r = (char*)n1 - (char*)n2;
1353 }
1354
1355 if ( qt_cmp_si_sortSpec & QDir::Reversed )
1356 return -r;
1357 else
1358 return r;
1359}
1360
1361#if defined(Q_C_CALLBACKS)
1362}
1363#endif
1364
1365/*! \internal
1366 Detaches all internal data.
1367*/
1368void QDir::detach()
1369{
1370 // deepcopy
1371 dPath = QDeepCopy<QString>(dPath);
1372 nameFilt = QDeepCopy<QString>(nameFilt);
1373
1374 if ( fList )
1375 *fList = QDeepCopy<QStringList>( *fList );
1376
1377 if ( fiList ) {
1378 QFileInfoList *newlist = new QFileInfoList( *fiList );
1379 delete fiList;
1380 fiList = newlist;
1381 }
1382}
1383
1384#endif // QT_NO_DIR
Note: See TracBrowser for help on using the repository browser.