source: trunk/src/tools/qdir.cpp@ 138

Last change on this file since 138 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 39.2 KB
Line 
1/****************************************************************************
2** $Id: qdir.cpp 8 2005-11-16 19:36:46Z 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 and OS/2). 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 or OS/2 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 and OS/2). 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#if defined(Q_OS_WIN32) || defined(Q_OS_OS2)
406 if ( fileName[0].isLetter() && fileName[1] == ':' ) {
407#if defined(Q_OS_OS2)
408#if defined(Q_CC_GNU)
409 char drv = fileName.upper()[0].latin1();
410 if ( _getdrive() != drv ) {
411 char buf[PATH_MAX];
412 _getcwd1( buf, drv );
413#else
414 int drv = fileName.upper()[0].latin1() - 'A' + 1;
415 if ( _getdrive() != drv ) {
416 char buf[PATH_MAX];
417 _getdcwd( drv, buf, PATH_MAX );
418#endif
419 tmp = buf;
420#else
421 int drv = fileName.upper()[0].latin1() - 'A' + 1;
422 if ( _getdrive() != drv ) {
423 QT_WA( {
424 TCHAR buf[PATH_MAX];
425 ::_wgetdcwd( drv, buf, PATH_MAX );
426 tmp.setUnicodeCodes( (ushort*)buf, ::wcslen(buf) );
427 }, {
428 char buf[PATH_MAX];
429 ::_getdcwd( drv, buf, PATH_MAX );
430 tmp = buf;
431 } );
432#endif
433 if ( !tmp.endsWith("\\") )
434 tmp += "\\";
435 tmp += fileName.right( fileName.length() - 2 );
436 int x;
437 for ( x = 0; x < (int) tmp.length(); x++ ) {
438 if ( tmp[x] == '\\' )
439 tmp[x] = '/';
440 }
441 }
442 } else
443#endif
444 {
445 if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName &&
446 fileName[0] != '/') )
447 tmp += '/';
448 tmp += fileName;
449 }
450 return tmp;
451}
452
453
454/*!
455 Returns \a pathName with the '/' separators converted to
456 separators that are appropriate for the underlying operating
457 system.
458
459 On Windows, convertSeparators("c:/winnt/system32") returns
460 "c:\winnt\system32".
461
462 On OS/2, convertSeparators("c:/os2/system") returns
463 "c:\os2\system".
464
465 The returned string may be the same as the argument on some
466 operating systems, for example on Unix.
467*/
468
469QString QDir::convertSeparators( const QString &pathName )
470{
471 QString n( pathName );
472#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX)
473 for ( int i=0; i<(int)n.length(); i++ ) {
474 if ( n[i] == '/' )
475 n[i] = '\\';
476 }
477#elif defined(Q_OS_MAC9)
478 while(n.length() && n[0] == '/' ) n = n.right(n.length()-1);
479 for ( int i=0; i<(int)n.length(); i++ ) {
480 if ( n[i] == '/' )
481 n[i] = ':';
482 }
483 if(n.contains(':') && n.left(1) != ':')
484 n.prepend(':');
485#endif
486 return n;
487}
488
489
490/*!
491 Changes the QDir's directory to \a dirName.
492
493 If \a acceptAbsPath is TRUE a path starting with separator "/"
494 will cause the function to change to the absolute directory. If \a
495 acceptAbsPath is FALSE any number of separators at the beginning
496 of \a dirName will be removed and the function will descend into
497 \a dirName.
498
499 Returns TRUE if the new directory exists and is readable;
500 otherwise returns FALSE. Note that the logical cd() operation is
501 not performed if the new directory does not exist.
502
503 Calling cd( ".." ) is equivalent to calling cdUp().
504
505 \sa cdUp(), isReadable(), exists(), path()
506*/
507
508bool QDir::cd( const QString &dirName, bool acceptAbsPath )
509{
510 if ( dirName.isEmpty() || dirName == QString::fromLatin1(".") )
511 return TRUE;
512 QString old = dPath;
513 if ( acceptAbsPath && !isRelativePath(dirName) ) {
514 dPath = cleanDirPath( dirName );
515 } else {
516 if ( isRoot() ) {
517 if ( dirName == ".." ) {
518 dPath = old;
519 return FALSE;
520 }
521 } else {
522 dPath += '/';
523 }
524
525 dPath += dirName;
526 if ( dirName.find('/') >= 0
527 || old == QString::fromLatin1(".")
528 || dirName == QString::fromLatin1("..") ) {
529 dPath = cleanDirPath( dPath );
530
531 /*
532 If dPath starts with .., we convert it to absolute to
533 avoid infinite looping on
534
535 QDir dir( "." );
536 while ( dir.cdUp() )
537 ;
538 */
539 if ( dPath[0] == QChar('.') && dPath[1] == QChar('.') &&
540 (dPath.length() == 2 || dPath[2] == QChar('/')) )
541 convertToAbs();
542 }
543 }
544 if ( !exists() ) {
545 dPath = old; // regret
546 return FALSE;
547 }
548 dirty = TRUE;
549 return TRUE;
550}
551
552/*!
553 Changes directory by moving one directory up from the QDir's
554 current directory.
555
556 Returns TRUE if the new directory exists and is readable;
557 otherwise returns FALSE. Note that the logical cdUp() operation is
558 not performed if the new directory does not exist.
559
560 \sa cd(), isReadable(), exists(), path()
561*/
562
563bool QDir::cdUp()
564{
565 return cd( QString::fromLatin1("..") );
566}
567
568/*!
569 \fn QString QDir::nameFilter() const
570
571 Returns the string set by setNameFilter()
572*/
573
574/*!
575 Sets the name filter used by entryList() and entryInfoList() to \a
576 nameFilter.
577
578 The \a nameFilter is a wildcard (globbing) filter that understands
579 "*" and "?" wildcards. (See \link qregexp.html#wildcard-matching
580 QRegExp wildcard matching\endlink.) You may specify several filter
581 entries all separated by a single space " " or by a semi-colon
582 ";".
583
584 For example, if you want entryList() and entryInfoList() to list
585 all files ending with either ".cpp" or ".h", you would use either
586 dir.setNameFilter("*.cpp *.h") or dir.setNameFilter("*.cpp;*.h").
587
588 \sa nameFilter(), setFilter()
589*/
590
591void QDir::setNameFilter( const QString &nameFilter )
592{
593 nameFilt = nameFilter;
594 if ( nameFilt.isEmpty() )
595 nameFilt = QString::fromLatin1("*");
596 dirty = TRUE;
597}
598
599/*!
600 \fn QDir::FilterSpec QDir::filter() const
601
602 Returns the value set by setFilter()
603*/
604
605/*!
606 \enum QDir::FilterSpec
607
608 This enum describes the filtering options available to QDir, e.g.
609 for entryList() and entryInfoList(). The filter value is specified
610 by OR-ing together values from the following list:
611
612 \value Dirs List directories only.
613 \value Files List files only.
614 \value Drives List disk drives (ignored under Unix).
615 \value NoSymLinks Do not list symbolic links (ignored by operating
616 systems that don't support symbolic links).
617 \value All List directories, files, drives and symlinks (this does not list
618 broken symlinks unless you specify System).
619 \value TypeMask A mask for the the Dirs, Files, Drives and
620 NoSymLinks flags.
621 \value Readable List files for which the application has read access.
622 \value Writable List files for which the application has write access.
623 \value Executable List files for which the application has execute
624 access. Executables needs to be combined with Dirs or Files.
625 \value RWEMask A mask for the Readable, Writable and Executable flags.
626 \value Modified Only list files that have been modified (ignored
627 under Unix).
628 \value Hidden List hidden files (on Unix, files starting with a .).
629 \value System List system files (on Unix, FIFOs, sockets and
630 device files)
631 \value AccessMask A mask for the Readable, Writable, Executable
632 Modified, Hidden and System flags
633 \value DefaultFilter Internal flag.
634
635 If you do not set any of \c Readable, \c Writable or \c
636 Executable, QDir will set all three of them. This makes the
637 default easy to write and at the same time useful.
638
639 Examples: \c Readable|Writable means list all files for which the
640 application has read access, write access or both. \c Dirs|Drives
641 means list drives, directories, all files that the application can
642 read, write or execute, and also symlinks to such
643 files/directories.
644*/
645
646
647/*!
648 Sets the filter used by entryList() and entryInfoList() to \a
649 filterSpec. The filter is used to specify the kind of files that
650 should be returned by entryList() and entryInfoList(). See
651 \l{QDir::FilterSpec}.
652
653 \sa filter(), setNameFilter()
654*/
655
656void QDir::setFilter( int filterSpec )
657{
658 if ( filtS == (FilterSpec) filterSpec )
659 return;
660 filtS = (FilterSpec) filterSpec;
661 dirty = TRUE;
662}
663
664/*!
665 \fn QDir::SortSpec QDir::sorting() const
666
667 Returns the value set by setSorting()
668
669 \sa setSorting() SortSpec
670*/
671
672/*!
673 \enum QDir::SortSpec
674
675 This enum describes the sort options available to QDir, e.g. for
676 entryList() and entryInfoList(). The sort value is specified by
677 OR-ing together values from the following list:
678
679 \value Name Sort by name.
680 \value Time Sort by time (modification time).
681 \value Size Sort by file size.
682 \value Unsorted Do not sort.
683 \value SortByMask A mask for Name, Time and Size.
684
685 \value DirsFirst Put the directories first, then the files.
686 \value Reversed Reverse the sort order.
687 \value IgnoreCase Sort case-insensitively.
688 \value DefaultSort Internal flag.
689
690 You can only specify one of the first four.
691
692 If you specify both \c DirsFirst and \c Reversed, directories are
693 still put first, but in reverse order; the files will be listed
694 after the directories, again in reverse order.
695*/
696
697// ### Unsorted+DirsFirst ? Unsorted+Reversed?
698
699/*!
700 Sets the sort order used by entryList() and entryInfoList().
701
702 The \a sortSpec is specified by OR-ing values from the enum
703 \l{QDir::SortSpec}.
704
705 \sa sorting() SortSpec
706*/
707
708void QDir::setSorting( int sortSpec )
709{
710 if ( sortS == (SortSpec) sortSpec )
711 return;
712 sortS = (SortSpec) sortSpec;
713 dirty = TRUE;
714}
715
716/*!
717 \fn bool QDir::matchAllDirs() const
718
719 Returns the value set by setMatchAllDirs()
720
721 \sa setMatchAllDirs()
722*/
723
724/*!
725 If \a enable is TRUE then all directories are included (e.g. in
726 entryList()), and the nameFilter() is only applied to the files.
727 If \a enable is FALSE then the nameFilter() is applied to both
728 directories and files.
729
730 \sa matchAllDirs()
731*/
732
733void QDir::setMatchAllDirs( bool enable )
734{
735 if ( (bool)allDirs == enable )
736 return;
737 allDirs = enable;
738 dirty = TRUE;
739}
740
741
742/*!
743 Returns the total number of directories and files that were found.
744
745 Equivalent to entryList().count().
746
747 \sa operator[](), entryList()
748*/
749
750uint QDir::count() const
751{
752 return (uint)entryList().count();
753}
754
755/*!
756 Returns the file name at position \a index in the list of file
757 names. Equivalent to entryList().at(index).
758
759 Returns a QString::null if the \a index is out of range or if the
760 entryList() function failed.
761
762 \sa count(), entryList()
763*/
764
765QString QDir::operator[]( int index ) const
766{
767 entryList();
768 return fList && index >= 0 && index < (int)fList->count() ?
769 (*fList)[index] : QString::null;
770}
771
772
773/*!
774 \obsolete
775 This function is included to easy porting from Qt 1.x to Qt 2.0,
776 it is the same as entryList(), but encodes the filenames as 8-bit
777 strings using QFile::encodedName().
778
779 It is more efficient to use entryList().
780*/
781QStrList QDir::encodedEntryList( int filterSpec, int sortSpec ) const
782{
783 QStrList r;
784 QStringList l = entryList(filterSpec,sortSpec);
785 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
786 r.append( QFile::encodeName(*it) );
787 }
788 return r;
789}
790
791/*!
792 \obsolete
793 \overload
794 This function is included to easy porting from Qt 1.x to Qt 2.0,
795 it is the same as entryList(), but encodes the filenames as 8-bit
796 strings using QFile::encodedName().
797
798 It is more efficient to use entryList().
799*/
800QStrList QDir::encodedEntryList( const QString &nameFilter,
801 int filterSpec,
802 int sortSpec ) const
803{
804 QStrList r;
805 QStringList l = entryList(nameFilter,filterSpec,sortSpec);
806 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
807 r.append( QFile::encodeName(*it) );
808 }
809 return r;
810}
811
812
813
814/*!
815 \overload
816
817 Returns a list of the names of all the files and directories in
818 the directory, ordered in accordance with setSorting() and
819 filtered in accordance with setFilter() and setNameFilter().
820
821 The filter and sorting specifications can be overridden using the
822 \a filterSpec and \a sortSpec arguments.
823
824 Returns an empty list if the directory is unreadable or does not
825 exist.
826
827 \sa entryInfoList(), setNameFilter(), setSorting(), setFilter()
828*/
829
830QStringList QDir::entryList( int filterSpec, int sortSpec ) const
831{
832 if ( !dirty && filterSpec == (int)DefaultFilter &&
833 sortSpec == (int)DefaultSort )
834 return *fList;
835 return entryList( nameFilt, filterSpec, sortSpec );
836}
837
838/*!
839 Returns a list of the names of all the files and directories in
840 the directory, ordered in accordance with setSorting() and
841 filtered in accordance with setFilter() and setNameFilter().
842
843 The filter and sorting specifications can be overridden using the
844 \a nameFilter, \a filterSpec and \a sortSpec arguments.
845
846 Returns an empty list if the directory is unreadable or does not
847 exist.
848
849 \sa entryInfoList(), setNameFilter(), setSorting(), setFilter()
850*/
851
852QStringList QDir::entryList( const QString &nameFilter,
853 int filterSpec, int sortSpec ) const
854{
855 if ( filterSpec == (int)DefaultFilter )
856 filterSpec = filtS;
857 if ( sortSpec == (int)DefaultSort )
858 sortSpec = sortS;
859 QDir *that = (QDir*)this; // mutable function
860 if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) ) {
861 if ( that->fList )
862 return *that->fList;
863 }
864 return QStringList();
865}
866
867/*!
868 \overload
869
870 Returns a list of QFileInfo objects for all the files and
871 directories in the directory, ordered in accordance with
872 setSorting() and filtered in accordance with setFilter() and
873 setNameFilter().
874
875 The filter and sorting specifications can be overridden using the
876 \a filterSpec and \a sortSpec arguments.
877
878 Returns 0 if the directory is unreadable or does not exist.
879
880 The returned pointer is a const pointer to a QFileInfoList. The
881 list is owned by the QDir object and will be reused on the next
882 call to entryInfoList() for the same QDir instance. If you want to
883 keep the entries of the list after a subsequent call to this
884 function you must copy them.
885
886 Note: QFileInfoList is really a QPtrList<QFileInfo>.
887
888 \sa entryList(), setNameFilter(), setSorting(), setFilter()
889*/
890
891const QFileInfoList *QDir::entryInfoList( int filterSpec, int sortSpec ) const
892{
893 if ( !dirty && filterSpec == (int)DefaultFilter &&
894 sortSpec == (int)DefaultSort )
895 return fiList;
896 return entryInfoList( nameFilt, filterSpec, sortSpec );
897}
898
899/*!
900 Returns a list of QFileInfo objects for all the files and
901 directories in the directory, ordered in accordance with
902 setSorting() and filtered in accordance with setFilter() and
903 setNameFilter().
904
905 The filter and sorting specifications can be overridden using the
906 \a nameFilter, \a filterSpec and \a sortSpec arguments.
907
908 Returns 0 if the directory is unreadable or does not exist.
909
910 The returned pointer is a const pointer to a QFileInfoList. The
911 list is owned by the QDir object and will be reused on the next
912 call to entryInfoList() for the same QDir instance. If you want to
913 keep the entries of the list after a subsequent call to this
914 function you must copy them.
915
916 Note: QFileInfoList is really a QPtrList<QFileInfo>.
917
918 \sa entryList(), setNameFilter(), setSorting(), setFilter()
919*/
920
921const QFileInfoList *QDir::entryInfoList( const QString &nameFilter,
922 int filterSpec, int sortSpec ) const
923{
924 if ( filterSpec == (int)DefaultFilter )
925 filterSpec = filtS;
926 if ( sortSpec == (int)DefaultSort )
927 sortSpec = sortS;
928 QDir *that = (QDir*)this; // mutable function
929 if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) )
930 return that->fiList;
931 else
932 return 0;
933}
934
935/*!
936 \overload
937
938 Returns TRUE if the \e directory exists; otherwise returns FALSE.
939 (If a file with the same name is found this function will return
940 FALSE).
941
942 \sa QFileInfo::exists(), QFile::exists()
943*/
944
945bool QDir::exists() const
946{
947 QFileInfo fi( dPath );
948 return fi.exists() && fi.isDir();
949}
950
951/*!
952 Returns TRUE if the directory path is relative to the current
953 directory and returns FALSE if the path is absolute (e.g. under
954 UNIX a path is relative if it does not start with a "/").
955
956 \sa convertToAbs()
957*/
958
959bool QDir::isRelative() const
960{
961 return isRelativePath( dPath );
962}
963
964/*!
965 Converts the directory path to an absolute path. If it is already
966 absolute nothing is done.
967
968 \sa isRelative()
969*/
970
971void QDir::convertToAbs()
972{
973 dPath = absPath();
974}
975
976/*!
977 Makes a copy of QDir \a d and assigns it to this QDir.
978*/
979
980QDir &QDir::operator=( const QDir &d )
981{
982 dPath = d.dPath;
983 delete fList;
984 fList = 0;
985 delete fiList;
986 fiList = 0;
987 nameFilt = d.nameFilt;
988 dirty = TRUE;
989 allDirs = d.allDirs;
990 filtS = d.filtS;
991 sortS = d.sortS;
992 return *this;
993}
994
995/*!
996 \overload
997
998 Sets the directory path to be the given \a path.
999*/
1000
1001QDir &QDir::operator=( const QString &path )
1002{
1003 dPath = cleanDirPath( path );
1004 dirty = TRUE;
1005 return *this;
1006}
1007
1008
1009/*!
1010 \fn bool QDir::operator!=( const QDir &d ) const
1011
1012 Returns TRUE if directory \a d and this directory have different
1013 paths or different sort or filter settings; otherwise returns
1014 FALSE.
1015
1016 Example:
1017 \code
1018 // The current directory is "/usr/local"
1019 QDir d1( "/usr/local/bin" );
1020 QDir d2( "bin" );
1021 if ( d1 != d2 )
1022 qDebug( "They differ" );
1023 \endcode
1024*/
1025
1026/*!
1027 Returns TRUE if directory \a d and this directory have the same
1028 path and their sort and filter settings are the same; otherwise
1029 returns FALSE.
1030
1031 Example:
1032 \code
1033 // The current directory is "/usr/local"
1034 QDir d1( "/usr/local/bin" );
1035 QDir d2( "bin" );
1036 d2.convertToAbs();
1037 if ( d1 == d2 )
1038 qDebug( "They're the same" );
1039 \endcode
1040*/
1041
1042bool QDir::operator==( const QDir &d ) const
1043{
1044 return dPath == d.dPath &&
1045 nameFilt == d.nameFilt &&
1046 allDirs == d.allDirs &&
1047 filtS == d.filtS &&
1048 sortS == d.sortS;
1049}
1050
1051
1052/*!
1053 Removes the file, \a fileName.
1054
1055 If \a acceptAbsPath is TRUE a path starting with separator "/"
1056 will remove the file with the absolute path. If \a acceptAbsPath
1057 is FALSE any number of separators at the beginning of \a fileName
1058 will be removed and the resultant file name will be removed.
1059
1060 Returns TRUE if the file is removed successfully; otherwise
1061 returns FALSE.
1062*/
1063
1064bool QDir::remove( const QString &fileName, bool acceptAbsPath )
1065{
1066 if ( fileName.isEmpty() ) {
1067#if defined(QT_CHECK_NULL)
1068 qWarning( "QDir::remove: Empty or null file name" );
1069#endif
1070 return FALSE;
1071 }
1072 QString p = filePath( fileName, acceptAbsPath );
1073 return QFile::remove( p );
1074}
1075
1076/*!
1077 Checks for the existence of the file \a name.
1078
1079 If \a acceptAbsPath is TRUE a path starting with separator "/"
1080 will check the file with the absolute path. If \a acceptAbsPath is
1081 FALSE any number of separators at the beginning of \a name will be
1082 removed and the resultant file name will be checked.
1083
1084 Returns TRUE if the file exists; otherwise returns FALSE.
1085
1086 \sa QFileInfo::exists(), QFile::exists()
1087*/
1088
1089bool QDir::exists( const QString &name, bool acceptAbsPath ) //### const in 4.0
1090{
1091 if ( name.isEmpty() ) {
1092#if defined(QT_CHECK_NULL)
1093 qWarning( "QDir::exists: Empty or null file name" );
1094#endif
1095 return FALSE;
1096 }
1097 QString tmp = filePath( name, acceptAbsPath );
1098 return QFile::exists( tmp );
1099}
1100
1101/*!
1102 Returns the native directory separator; "/" under UNIX (including
1103 Mac OS X) and "\" under Windows and OS/2.
1104
1105 You do not need to use this function to build file paths. If you
1106 always use "/", Qt will translate your paths to conform to the
1107 underlying operating system.
1108*/
1109
1110char QDir::separator()
1111{
1112#if defined(Q_OS_UNIX)
1113 return '/';
1114#elif defined (Q_FS_FAT) || defined(Q_WS_WIN)
1115 return '\\';
1116#elif defined (Q_OS_MAC)
1117 return ':';
1118#else
1119 return '/';
1120#endif
1121}
1122
1123/*!
1124 Returns the application's current directory.
1125
1126 Use path() to access a QDir object's path.
1127
1128 \sa currentDirPath(), QDir::QDir()
1129*/
1130
1131QDir QDir::current()
1132{
1133 return QDir( currentDirPath() );
1134}
1135
1136/*!
1137 Returns the home directory.
1138
1139 Under Windows the \c HOME environment variable is used. If this
1140 does not exist the \c USERPROFILE environment variable is used. If
1141 that does not exist the path is formed by concatenating the \c
1142 HOMEDRIVE and \c HOMEPATH environment variables. If they don't
1143 exist the rootDirPath() is used (this uses the \c SystemDrive
1144 environment variable). If none of these exist "C:\" is used.
1145
1146 Under OS/2 the \c HOME environment variable is also used. If it
1147 does not exist the path is formed by concatenating the \c
1148 HOMEDRIVE and \c HOMEPATH environment variables. If they don't
1149 exist the rootDirPath() is used (which always returns "x:/" where \c x
1150 is the system boot drive letter).
1151
1152 Under non-Windows operating systems the \c HOME environment
1153 variable is used if it exists, otherwise rootDirPath() is used.
1154
1155 \sa homeDirPath()
1156*/
1157
1158QDir QDir::home()
1159{
1160 return QDir( homeDirPath() );
1161}
1162
1163/*!
1164 Returns the root directory.
1165
1166 \sa rootDirPath() drives()
1167*/
1168
1169QDir QDir::root()
1170{
1171 return QDir( rootDirPath() );
1172}
1173
1174/*!
1175 \fn QString QDir::homeDirPath()
1176
1177 Returns the absolute path of the user's home directory.
1178
1179 \sa home()
1180*/
1181
1182QValueList<QRegExp> qt_makeFilterList( const QString &filter )
1183{
1184 QValueList<QRegExp> regExps;
1185 if ( filter.isEmpty() )
1186 return regExps;
1187
1188 QChar sep( ';' );
1189 int i = filter.find( sep, 0 );
1190 if ( i == -1 && filter.find( ' ', 0 ) != -1 )
1191 sep = QChar( ' ' );
1192
1193 QStringList list = QStringList::split( sep, filter );
1194 QStringList::Iterator it = list.begin();
1195 while ( it != list.end() ) {
1196 regExps << QRegExp( (*it).stripWhiteSpace(), CaseSensitiveFS, TRUE );
1197 ++it;
1198 }
1199 return regExps;
1200}
1201
1202bool qt_matchFilterList( const QValueList<QRegExp>& filters,
1203 const QString &fileName )
1204{
1205 QValueList<QRegExp>::ConstIterator rit = filters.begin();
1206 while ( rit != filters.end() ) {
1207 if ( (*rit).exactMatch(fileName) )
1208 return TRUE;
1209 ++rit;
1210 }
1211 return FALSE;
1212}
1213
1214
1215/*!
1216 \overload
1217
1218 Returns TRUE if the \a fileName matches any of the wildcard (glob)
1219 patterns in the list of \a filters; otherwise returns FALSE.
1220
1221 (See \link qregexp.html#wildcard-matching QRegExp wildcard
1222 matching.\endlink)
1223 \sa QRegExp::match()
1224*/
1225
1226bool QDir::match( const QStringList &filters, const QString &fileName )
1227{
1228 QStringList::ConstIterator sit = filters.begin();
1229 while ( sit != filters.end() ) {
1230 QRegExp rx( *sit, CaseSensitiveFS, TRUE );
1231 if ( rx.exactMatch(fileName) )
1232 return TRUE;
1233 ++sit;
1234 }
1235 return FALSE;
1236}
1237
1238/*!
1239 Returns TRUE if the \a fileName matches the wildcard (glob)
1240 pattern \a filter; otherwise returns FALSE. The \a filter may
1241 contain multiple patterns separated by spaces or semicolons.
1242
1243 (See \link qregexp.html#wildcard-matching QRegExp wildcard
1244 matching.\endlink)
1245 \sa QRegExp::match()
1246*/
1247
1248bool QDir::match( const QString &filter, const QString &fileName )
1249{
1250 return qt_matchFilterList( qt_makeFilterList(filter), fileName );
1251}
1252
1253
1254/*!
1255 Removes all multiple directory separators "/" and resolves any
1256 "."s or ".."s found in the path, \a filePath.
1257
1258 Symbolic links are kept. This function does not return the
1259 canonical path, but rather the simplest version of the input.
1260 For example, "./local" becomes "local", "local/../bin" becomes
1261 "bin" and "/local/usr/../bin" becomes "/local/bin".
1262
1263 \sa absPath() canonicalPath()
1264*/
1265
1266QString QDir::cleanDirPath( const QString &filePath )
1267{
1268 QString name = filePath;
1269 QString newPath;
1270
1271 if ( name.isEmpty() )
1272 return name;
1273
1274 slashify( name );
1275
1276 bool addedSeparator = isRelativePath( name );
1277 if ( addedSeparator )
1278 name.insert( 0, '/' );
1279
1280 int ePos, pos, upLevel;
1281
1282 pos = ePos = name.length();
1283 upLevel = 0;
1284 int len;
1285
1286 while ( pos && (pos = name.findRev('/', pos - 1)) != -1 ) {
1287 len = ePos - pos - 1;
1288 if ( len == 2 && name.at(pos + 1) == '.'
1289 && name.at(pos + 2) == '.' ) {
1290 upLevel++;
1291 } else {
1292 if ( len != 0 && (len != 1 || name.at(pos + 1) != '.') ) {
1293 if ( !upLevel )
1294 newPath = QString::fromLatin1("/")
1295 + name.mid(pos + 1, len) + newPath;
1296 else
1297 upLevel--;
1298 }
1299 }
1300 ePos = pos;
1301 }
1302 if ( addedSeparator ) {
1303 while ( upLevel-- )
1304 newPath.insert( 0, QString::fromLatin1("/..") );
1305 if ( !newPath.isEmpty() )
1306 newPath.remove( (uint)0, (uint)1 );
1307 else
1308 newPath = QString::fromLatin1(".");
1309 } else {
1310 if ( newPath.isEmpty() )
1311 newPath = QString::fromLatin1("/");
1312#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX)
1313 if ( name[0] == '/' ) {
1314 if ( name[1] == '/' ) // "\\machine\x\ ..."
1315 newPath.insert( 0, '/' );
1316 } else {
1317 newPath = name.left(2) + newPath;
1318 }
1319#endif
1320 }
1321 return newPath;
1322}
1323
1324int qt_cmp_si_sortSpec;
1325
1326#if defined(Q_C_CALLBACKS)
1327extern "C" {
1328#endif
1329
1330#ifdef Q_OS_TEMP
1331int __cdecl qt_cmp_si( const void *n1, const void *n2 )
1332#else
1333int qt_cmp_si( const void *n1, const void *n2 )
1334#endif
1335{
1336 if ( !n1 || !n2 )
1337 return 0;
1338
1339 QDirSortItem* f1 = (QDirSortItem*)n1;
1340 QDirSortItem* f2 = (QDirSortItem*)n2;
1341
1342 if ( qt_cmp_si_sortSpec & QDir::DirsFirst )
1343 if ( f1->item->isDir() != f2->item->isDir() )
1344 return f1->item->isDir() ? -1 : 1;
1345
1346 int r = 0;
1347 int sortBy = qt_cmp_si_sortSpec & QDir::SortByMask;
1348
1349 switch ( sortBy ) {
1350 case QDir::Time:
1351 r = f1->item->lastModified().secsTo(f2->item->lastModified());
1352 break;
1353 case QDir::Size:
1354 r = f2->item->size() - f1->item->size();
1355 break;
1356 default:
1357 ;
1358 }
1359
1360 if ( r == 0 && sortBy != QDir::Unsorted ) {
1361 // Still not sorted - sort by name
1362 bool ic = qt_cmp_si_sortSpec & QDir::IgnoreCase;
1363
1364 if ( f1->filename_cache.isNull() )
1365 f1->filename_cache = ic ? f1->item->fileName().lower()
1366 : f1->item->fileName();
1367 if ( f2->filename_cache.isNull() )
1368 f2->filename_cache = ic ? f2->item->fileName().lower()
1369 : f2->item->fileName();
1370
1371 r = f1->filename_cache.compare(f2->filename_cache);
1372 }
1373
1374 if ( r == 0 ) {
1375 // Enforce an order - the order the items appear in the array
1376 r = (char*)n1 - (char*)n2;
1377 }
1378
1379 if ( qt_cmp_si_sortSpec & QDir::Reversed )
1380 return -r;
1381 else
1382 return r;
1383}
1384
1385#if defined(Q_C_CALLBACKS)
1386}
1387#endif
1388
1389/*! \internal
1390 Detaches all internal data.
1391*/
1392void QDir::detach()
1393{
1394 // deepcopy
1395 dPath = QDeepCopy<QString>(dPath);
1396 nameFilt = QDeepCopy<QString>(nameFilt);
1397
1398 if ( fList )
1399 *fList = QDeepCopy<QStringList>( *fList );
1400
1401 if ( fiList ) {
1402 QFileInfoList *newlist = new QFileInfoList( *fiList );
1403 delete fiList;
1404 fiList = newlist;
1405 }
1406}
1407
1408#endif // QT_NO_DIR
Note: See TracBrowser for help on using the repository browser.