Orb/Doxygen/qtools/qdir.cpp
changeset 3 d8fccb2cd802
parent 0 42188c7ea2d9
equal deleted inserted replaced
2:932c358ece3e 3:d8fccb2cd802
       
     1 /****************************************************************************
       
     2 ** 
       
     3 **
       
     4 ** Implementation of QDir class
       
     5 **
       
     6 ** Created : 950427
       
     7 **
       
     8 ** Copyright (C) 1992-2000 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 "qglobal.h"
       
    39 
       
    40 #include "qdir.h"
       
    41 
       
    42 #ifndef QT_NO_DIR
       
    43 #include "qfileinfo.h"
       
    44 #include "qfiledefs_p.h"
       
    45 #include "qregexp.h"
       
    46 #include "qstringlist.h"
       
    47 #include <stdlib.h>
       
    48 #include <ctype.h>
       
    49 
       
    50 // NOT REVISED
       
    51 /*!
       
    52   \class QDir qdir.h
       
    53   \brief Traverses directory structures and contents in a
       
    54 	    platform-independent way.
       
    55 
       
    56   \ingroup io
       
    57 
       
    58   A QDir can point to a file using either a relative or an absolute file
       
    59   path. Absolute file paths begin with the directory separator ('/') or a
       
    60   drive specification (not applicable to UNIX).	 Relative file names begin
       
    61   with a directory name or a file name and specify a path relative to the
       
    62   current directory.
       
    63 
       
    64   An example of an absolute path is the string "/tmp/quartz", a relative
       
    65   path might look like "src/fatlib". You can use the function isRelative()
       
    66   to check if a QDir is using a relative or an absolute file path. You can
       
    67   call the function convertToAbs() to convert a relative QDir to an
       
    68   absolute one.
       
    69 
       
    70   The directory "example" under the current directory is checked for existence
       
    71   in the example below:
       
    72 
       
    73   \code
       
    74     QDir d( "example" );			// "./example"
       
    75     if ( !d.exists() )
       
    76 	qWarning( "Cannot find the example directory" );
       
    77   \endcode
       
    78 
       
    79   If you always use '/' as a directory separator, Qt will translate your
       
    80   paths to conform to the underlying operating system.
       
    81 
       
    82   cd() and cdUp() can be used to navigate the directory tree. Note that the
       
    83   logical cd and cdUp operations are not performed if the new directory does
       
    84   not exist.
       
    85 
       
    86   Example:
       
    87   \code
       
    88     QDir d = QDir::root();			// "/"
       
    89     if ( !d.cd("tmp") ) {			// "/tmp"
       
    90 	qWarning( "Cannot find the \"/tmp\" directory" );
       
    91     } else {
       
    92 	QFile f( d.filePath("ex1.txt") );	// "/tmp/ex1.txt"
       
    93 	if ( !f.open(IO_ReadWrite) )
       
    94 	    qWarning( "Cannot create the file %s", f.name() );
       
    95     }
       
    96   \endcode
       
    97 
       
    98   To read the contents of a directory you can use the entryList() and
       
    99   entryInfoList() functions.
       
   100 
       
   101   Example:
       
   102   \code
       
   103     #include <stdio.h>
       
   104     #include <qdir.h>
       
   105 
       
   106     //
       
   107     // This program scans the current directory and lists all files
       
   108     // that are not symbolic links, sorted by size with the smallest files
       
   109     // first.
       
   110     //
       
   111 
       
   112     int main( int argc, char **argv )
       
   113     {
       
   114 	QDir d;
       
   115 	d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );
       
   116 	d.setSorting( QDir::Size | QDir::Reversed );
       
   117 
       
   118 	const QFileInfoList *list = d.entryInfoList();
       
   119 	QFileInfoListIterator it( *list );	// create list iterator
       
   120 	QFileInfo *fi;				// pointer for traversing
       
   121 
       
   122 	printf( "     BYTES FILENAME\n" );	// print header
       
   123 	while ( (fi=it.current()) ) {		// for each file...
       
   124 	    printf( "%10li %s\n", fi->size(), fi->fileName().data() );
       
   125 	    ++it;				// goto next list element
       
   126 	}
       
   127     }
       
   128   \endcode
       
   129 */
       
   130 
       
   131 
       
   132 /*!
       
   133   Constructs a QDir pointing to the current directory.
       
   134   \sa currentDirPath()
       
   135 */
       
   136 
       
   137 QDir::QDir()
       
   138 {
       
   139     dPath = QString::fromLatin1(".");
       
   140     init();
       
   141 }
       
   142 
       
   143 /*!
       
   144   Constructs a QDir.
       
   145 
       
   146   \arg \e path is the directory.
       
   147   \arg \e nameFilter is the file name filter.
       
   148   \arg \e sortSpec is the sort specification, which describes how to
       
   149   sort the files in the directory.
       
   150   \arg \e filterSpec is the filter specification, which describes how
       
   151   to filter the files in the directory.
       
   152 
       
   153   Most of these arguments (except \e path) have optional values.
       
   154 
       
   155   Example:
       
   156   \code
       
   157     // lists all files in /tmp
       
   158 
       
   159     QDir d( "/tmp" );
       
   160     for ( int i=0; i<d.count(); i++ )
       
   161 	printf( "%s\n", d[i] );
       
   162   \endcode
       
   163 
       
   164   If \e path is "" or null, the directory is set to "." (the current
       
   165   directory).  If \e nameFilter is "" or null, it is set to "*" (all
       
   166   files).
       
   167 
       
   168   No check is made to ensure that the directory exists.
       
   169 
       
   170   \sa exists(), setPath(), setNameFilter(), setFilter(), setSorting()
       
   171 */
       
   172 
       
   173 QDir::QDir( const QString &path, const QString &nameFilter,
       
   174 	    int sortSpec, int filterSpec )
       
   175 {
       
   176     init();
       
   177     dPath = cleanDirPath( path );
       
   178     if ( dPath.isEmpty() )
       
   179 	dPath = QString::fromLatin1(".");
       
   180     nameFilt = nameFilter;
       
   181     if ( nameFilt.isEmpty() )
       
   182 	nameFilt = QString::fromLatin1("*");
       
   183     filtS = (FilterSpec)filterSpec;
       
   184     sortS = (SortSpec)sortSpec;
       
   185 }
       
   186 
       
   187 /*!
       
   188   Constructs a QDir that is a copy of the given directory.
       
   189   \sa operator=()
       
   190 */
       
   191 
       
   192 QDir::QDir( const QDir &d )
       
   193 {
       
   194     dPath = d.dPath;
       
   195     fList = 0;
       
   196     fiList = 0;
       
   197     nameFilt = d.nameFilt;
       
   198     dirty = TRUE;
       
   199     allDirs = d.allDirs;
       
   200     filtS = d.filtS;
       
   201     sortS = d.sortS;
       
   202 }
       
   203 
       
   204 
       
   205 void QDir::init()
       
   206 {
       
   207     fList = 0;
       
   208     fiList = 0;
       
   209     nameFilt = QString::fromLatin1("*");
       
   210     dirty = TRUE;
       
   211     allDirs = FALSE;
       
   212     filtS = All;
       
   213     sortS = SortSpec(Name | IgnoreCase);
       
   214 }
       
   215 
       
   216 /*!
       
   217   Destructs the QDir and cleans up.
       
   218 */
       
   219 
       
   220 QDir::~QDir()
       
   221 {
       
   222     if ( fList )
       
   223        delete fList;
       
   224     if ( fiList )
       
   225        delete fiList;
       
   226 }
       
   227 
       
   228 
       
   229 /*!
       
   230   Sets the path of the directory. The path is cleaned of redundant ".", ".."
       
   231   and multiple separators. No check is made to ensure that a directory
       
   232   with this path exists.
       
   233 
       
   234   The path can be either absolute or relative. Absolute paths begin with the
       
   235   directory separator ('/') or a drive specification (not
       
   236   applicable to UNIX).
       
   237   Relative file names begin with a directory name or a file name and specify
       
   238   a path relative to the current directory. An example of
       
   239   an absolute path is the string "/tmp/quartz", a relative path might look like
       
   240   "src/fatlib". You can use the function isRelative() to check if a QDir
       
   241   is using a relative or an absolute file path. You can call the function
       
   242   convertToAbs() to convert a relative QDir to an absolute one.
       
   243 
       
   244   \sa path(), absPath(), exists(), cleanDirPath(), dirName(),
       
   245       absFilePath(), isRelative(), convertToAbs()
       
   246 */
       
   247 
       
   248 void QDir::setPath( const QString &path )
       
   249 {
       
   250     dPath = cleanDirPath( path );
       
   251     if ( dPath.isEmpty() )
       
   252 	dPath = QString::fromLatin1(".");
       
   253     dirty = TRUE;
       
   254 }
       
   255 
       
   256 /*!
       
   257   \fn  QString QDir::path() const
       
   258   Returns the path, this may contain symbolic links, but never contains
       
   259   redundant ".", ".." or multiple separators.
       
   260 
       
   261   The returned path can be either absolute or relative (see setPath()).
       
   262 
       
   263   \sa setPath(), absPath(), exists(), cleanDirPath(), dirName(),
       
   264   absFilePath(), convertSeparators()
       
   265 */
       
   266 
       
   267 /*!
       
   268   Returns the absolute (a path that starts with '/') path, which may
       
   269   contain symbolic links, but never contains redundant ".", ".." or
       
   270   multiple separators.
       
   271 
       
   272   \sa setPath(), canonicalPath(), exists(),  cleanDirPath(), dirName(),
       
   273   absFilePath()
       
   274 */
       
   275 
       
   276 QString QDir::absPath() const
       
   277 {
       
   278     if ( QDir::isRelativePath(dPath) ) {
       
   279 	QString tmp = currentDirPath();
       
   280 	if ( tmp.right(1) != QString::fromLatin1("/") )
       
   281 	    tmp += '/';
       
   282 	tmp += dPath;
       
   283 	return cleanDirPath( tmp );
       
   284     } else {
       
   285 	return cleanDirPath( dPath );
       
   286     }
       
   287 }
       
   288 
       
   289 /*!
       
   290   Returns the name of the directory, this is NOT the same as the path, e.g.
       
   291   a directory with the name "mail", might have the path "/var/spool/mail".
       
   292   If the directory has no name (e.g. the root directory) a null string is
       
   293   returned.
       
   294 
       
   295   No check is made to ensure that a directory with this name actually exists.
       
   296 
       
   297   \sa path(), absPath(), absFilePath(), exists(), QString::isNull()
       
   298 */
       
   299 
       
   300 QString QDir::dirName() const
       
   301 {
       
   302     int pos = dPath.findRev( '/' );
       
   303     if ( pos == -1  )
       
   304 	return dPath;
       
   305     return dPath.right( dPath.length() - pos - 1 );
       
   306 }
       
   307 
       
   308 /*!
       
   309   Returns the path name of a file in the directory. Does NOT check if
       
   310   the file actually exists in the directory. If the QDir is relative
       
   311   the returned path name will also be relative. Redundant multiple separators
       
   312   or "." and ".." directories in \e fileName will not be removed (see
       
   313   cleanDirPath()).
       
   314 
       
   315   If \e acceptAbsPath is TRUE a \e fileName starting with a separator
       
   316   ('/') will be returned without change.
       
   317   If \e acceptAbsPath is FALSE an absolute path will be appended to
       
   318   the directory path.
       
   319 
       
   320   \sa absFilePath(), isRelative(), canonicalPath()
       
   321 */
       
   322 
       
   323 QString QDir::filePath( const QString &fileName,
       
   324 			bool acceptAbsPath ) const
       
   325 {
       
   326     if ( acceptAbsPath && !isRelativePath(fileName) )
       
   327 	return QString(fileName);
       
   328 
       
   329     QString tmp = dPath;
       
   330     if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName &&
       
   331 			   fileName[0] != '/') )
       
   332 	tmp += '/';
       
   333     tmp += fileName;
       
   334     return tmp;
       
   335 }
       
   336 
       
   337 /*!
       
   338   Returns the absolute path name of a file in the directory. Does NOT check if
       
   339   the file actually exists in the directory. Redundant multiple separators
       
   340   or "." and ".." directories in \e fileName will NOT be removed (see
       
   341   cleanDirPath()).
       
   342 
       
   343   If \e acceptAbsPath is TRUE a \e fileName starting with a separator
       
   344   ('/') will be returned without change.
       
   345   if \e acceptAbsPath is FALSE an absolute path will be appended to
       
   346   the directory path.
       
   347 
       
   348   \sa filePath()
       
   349 */
       
   350 
       
   351 QString QDir::absFilePath( const QString &fileName,
       
   352 			   bool acceptAbsPath ) const
       
   353 {
       
   354     if ( acceptAbsPath && !isRelativePath( fileName ) )
       
   355 	return fileName;
       
   356 
       
   357     QString tmp = absPath();
       
   358     if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName &&
       
   359 			   fileName[0] != '/') )
       
   360 	tmp += '/';
       
   361     tmp += fileName;
       
   362     return tmp;
       
   363 }
       
   364 
       
   365 
       
   366 /*!
       
   367   Converts the '/' separators in \a pathName to system native
       
   368   separators.  Returns the translated string.
       
   369 
       
   370   On Windows, convertSeparators("c:/winnt/system32") returns
       
   371   "c:\winnt\system32".
       
   372 
       
   373   No conversion is done on UNIX.
       
   374 */
       
   375 
       
   376 QString QDir::convertSeparators( const QString &pathName )
       
   377 {
       
   378     QString n( pathName );
       
   379 #if defined(_OS_FATFS_) || defined(_OS_OS2EMX_)
       
   380     for ( int i=0; i<(int)n.length(); i++ ) {
       
   381 	if ( n[i] == '/' )
       
   382 	    n[i] = '\\';
       
   383     }
       
   384 #endif
       
   385     return n;
       
   386 }
       
   387 
       
   388 
       
   389 /*!
       
   390   Changes directory by descending into the given directory. Returns
       
   391   TRUE if the new directory exists and is readable. Note that the logical
       
   392   cd operation is NOT performed if the new directory does not exist.
       
   393 
       
   394   If \e acceptAbsPath is TRUE a path starting with a separator ('/')
       
   395   will cd to the absolute directory, if \e acceptAbsPath is FALSE
       
   396   any number of separators at the beginning of \e dirName will be removed.
       
   397 
       
   398   Example:
       
   399   \code
       
   400   QDir d = QDir::home();  // now points to home directory
       
   401   if ( !d.cd("c++") ) {	  // now points to "c++" under home directory if OK
       
   402       QFileInfo fi( d, "c++" );
       
   403       if ( fi.exists() ) {
       
   404 	  if ( fi.isDir() )
       
   405 	      qWarning( "Cannot cd into \"%s\".", (char*)d.absFilePath("c++") );
       
   406 	  else
       
   407 	      qWarning( "Cannot create directory \"%s\"\n"
       
   408 		       "A file named \"c++\" already exists in \"%s\"",
       
   409 		       (const char *)d.absFilePath("c++"),
       
   410 		       (const char *)d.path() );
       
   411 	  return;
       
   412       } else {
       
   413 	  qWarning( "Creating directory \"%s\"",
       
   414 		   (const char *) d.absFilePath("c++") );
       
   415 	  if ( !d.mkdir( "c++" ) ) {
       
   416 	      qWarning("Could not create directory \"%s\"",
       
   417 		      (const char *)d.absFilePath("c++") );
       
   418 	      return;
       
   419 	  }
       
   420       }
       
   421   }
       
   422   \endcode
       
   423 
       
   424   Calling cd( ".." ) is equivalent to calling cdUp().
       
   425 
       
   426   \sa cdUp(), isReadable(), exists(), path()
       
   427 */
       
   428 
       
   429 bool QDir::cd( const QString &dirName, bool acceptAbsPath )
       
   430 {
       
   431     if ( dirName.isEmpty() || dirName==QString::fromLatin1(".") )
       
   432 	return TRUE;
       
   433     QString old = dPath;
       
   434     if ( acceptAbsPath && !isRelativePath(dirName) ) {
       
   435 	dPath = cleanDirPath( dirName );
       
   436     } else {
       
   437 	if ( !isRoot() )
       
   438 	    dPath += '/';
       
   439 	dPath += dirName;
       
   440 	if ( dirName.find('/') >= 0
       
   441 		|| old == QString::fromLatin1(".")
       
   442 		|| dirName == QString::fromLatin1("..") )
       
   443 	    dPath = cleanDirPath( dPath );
       
   444     }
       
   445     if ( !exists() ) {
       
   446 	dPath = old;			// regret
       
   447 	return FALSE;
       
   448     }
       
   449     dirty = TRUE;
       
   450     return TRUE;
       
   451 }
       
   452 
       
   453 /*!
       
   454   Changes directory by moving one directory up the path followed to arrive
       
   455   at the current directory.
       
   456 
       
   457   Returns TRUE if the new directory exists and is readable. Note that the
       
   458   logical cdUp() operation is not performed if the new directory does not
       
   459   exist.
       
   460 
       
   461   \sa cd(), isReadable(), exists(), path()
       
   462 */
       
   463 
       
   464 bool QDir::cdUp()
       
   465 {
       
   466     return cd( QString::fromLatin1("..") );
       
   467 }
       
   468 
       
   469 /*!
       
   470   \fn QString QDir::nameFilter() const
       
   471   Returns the string set by setNameFilter()
       
   472 */
       
   473 
       
   474 /*!
       
   475   Sets the name filter used by entryList() and entryInfoList().
       
   476 
       
   477   The name filter is a wildcarding filter that understands "*" and "?"
       
   478   wildcards, You may specify several filter entries separated by a " " or a ";". If
       
   479   you want entryList() and entryInfoList() to list all files ending with
       
   480   ".cpp" and all files ending with ".h", you simply call
       
   481   dir.setNameFilter("*.cpp *.h") or dir.setNameFilter("*.cpp;*.h")
       
   482 
       
   483   \sa nameFilter(), setFilter()
       
   484 */
       
   485 
       
   486 void QDir::setNameFilter( const QString &nameFilter )
       
   487 {
       
   488     nameFilt = nameFilter;
       
   489     if ( nameFilt.isEmpty() )
       
   490 	nameFilt = QString::fromLatin1("*");
       
   491     dirty = TRUE;
       
   492 }
       
   493 
       
   494 /*!
       
   495   \fn QDir::FilterSpec QDir::filter() const
       
   496   Returns the value set by setFilter()
       
   497 */
       
   498 
       
   499 /*! \enum QDir::FilterSpec
       
   500 
       
   501   This enum describes how QDir is to select what entries in a
       
   502   directory to return.  The filter value is specified by or-ing
       
   503   together values from the following list: <ul>
       
   504 
       
   505   <li> \c Dirs - List directories only
       
   506   <li> \c Files - List files only
       
   507 
       
   508   <li> \c  Drives - List disk drives (does nothing under unix)
       
   509   <li> \c  NoSymLinks - Do not list symbolic links (where they exist)
       
   510   <li> \c  Readable - List files for which the application has read access.
       
   511   <li> \c  Writable - List files for which the application has write access.
       
   512   <li> \c  Executable - List files for which the application has execute access
       
   513   <li> \c  Modified - Only list files that have been modified (does nothing
       
   514   under unix)
       
   515   <li> \c  Hidden - List hidden files (on unix, files starting with a .)
       
   516   <li> \c  System - List system files (does nothing under unix)
       
   517   </ul>
       
   518 
       
   519   If you do not set any of \c Readable, \c Writable or \c Executable,
       
   520   QDir will set all three of them.  This makes the default easy to
       
   521   write and at the same time useful.
       
   522 
       
   523   Examples: \c Readable|Writable means list all files for which the
       
   524   application has read access, write access or both.  \c Dirs|Drives
       
   525   means list drives, directories, all files that the application can
       
   526   read, write or execute, and also symlinks to such files/directories.
       
   527 */
       
   528 
       
   529 
       
   530 /*!
       
   531   Sets the filter used by entryList() and entryInfoList(). The filter is used
       
   532   to specify the kind of files that should be returned by entryList() and
       
   533   entryInfoList().
       
   534 
       
   535   \sa filter(), setNameFilter()
       
   536 */
       
   537 
       
   538 void QDir::setFilter( int filterSpec )
       
   539 {
       
   540     if ( filtS == (FilterSpec) filterSpec )
       
   541 	return;
       
   542     filtS = (FilterSpec) filterSpec;
       
   543     dirty = TRUE;
       
   544 }
       
   545 
       
   546 /*!
       
   547   \fn QDir::SortSpec QDir::sorting() const
       
   548 
       
   549   Returns the value set by setSorting()
       
   550 
       
   551   \sa setSorting()
       
   552 */
       
   553 
       
   554 /*! \enum QDir::SortSpec
       
   555 
       
   556   This enum describes how QDir is to sort entries in a directory when
       
   557   it returns a list of them.  The sort value is specified by or-ing
       
   558   together values from the following list: <ul>
       
   559 
       
   560   <li> \c Name - sort by name
       
   561   <li> \c Time - sort by time (modification time)
       
   562   <li> \c Size - sort by file size
       
   563   <li> \c Unsorted - do not sort
       
   564 
       
   565   <li> \c DirsFirst - put all directories first in the list
       
   566   <li> \c Reversed - reverse the sort order
       
   567   <li> \c IgnoreCase - sort case-insensitively
       
   568 
       
   569   </ul>
       
   570 
       
   571   You can only specify one of the first four.  If you specify both \c
       
   572   DirsFirst and \c Reversed, directories are still put first but the
       
   573   list is otherwise reversed.
       
   574 */
       
   575 
       
   576 // ### Unsorted+DirsFirst ? Unsorted+Reversed?
       
   577 
       
   578 /*!
       
   579   Sets the sorting order used by entryList() and entryInfoList().
       
   580 
       
   581   The \e sortSpec is specified by or-ing values from the enum
       
   582   SortSpec. The different values are:
       
   583 
       
   584   One of these:
       
   585   <dl compact>
       
   586   <dt>Name<dd> Sort by name (alphabetical order).
       
   587   <dt>Time<dd> Sort by time (most recent first).
       
   588   <dt>Size<dd> Sort by size (largest first).
       
   589   <dt>Unsorted<dd> Use the operating system order (UNIX does NOT sort
       
   590   alphabetically).
       
   591 
       
   592   ORed with zero or more of these:
       
   593 
       
   594   <dt>DirsFirst<dd> Always put directory names first.
       
   595   <dt>Reversed<dd> Reverse sort order.
       
   596   <dt>IgnoreCase<dd> Ignore case when sorting by name.
       
   597   </dl>
       
   598 */
       
   599 
       
   600 void QDir::setSorting( int sortSpec )
       
   601 {
       
   602     if ( sortS == (SortSpec) sortSpec )
       
   603 	return;
       
   604     sortS = (SortSpec) sortSpec;
       
   605     dirty = TRUE;
       
   606 }
       
   607 
       
   608 /*!
       
   609   \fn bool QDir::matchAllDirs() const
       
   610   Returns the value set by setMatchAllDirs()
       
   611 
       
   612   \sa setMatchAllDirs()
       
   613 */
       
   614 
       
   615 /*!
       
   616   If \e enable is TRUE, all directories will be listed (even if they do not
       
   617   match the filter or the name filter), otherwise only matched directories
       
   618   will be listed.
       
   619 
       
   620   \bug Currently, directories that do not match the filter will not be
       
   621   included (the name filter will be ignored as expected).
       
   622 
       
   623   \sa matchAllDirs()
       
   624 */
       
   625 
       
   626 void QDir::setMatchAllDirs( bool enable )
       
   627 {
       
   628     if ( (bool)allDirs == enable )
       
   629 	return;
       
   630     allDirs = enable;
       
   631     dirty = TRUE;
       
   632 }
       
   633 
       
   634 
       
   635 /*!
       
   636   Returns the number of files that was found.
       
   637   Equivalent to entryList().count().
       
   638   \sa operator[](), entryList()
       
   639 */
       
   640 
       
   641 uint QDir::count() const
       
   642 {
       
   643     return entryList().count();
       
   644 }
       
   645 
       
   646 /*!
       
   647   Returns the file name at position \e index in the list of found file
       
   648   names.
       
   649   Equivalent to entryList().at(index).
       
   650 
       
   651   Returns null if the \e index is out of range or if the entryList()
       
   652   function failed.
       
   653 
       
   654   \sa count(), entryList()
       
   655 */
       
   656 
       
   657 QString QDir::operator[]( int index ) const
       
   658 {
       
   659     entryList();
       
   660     return fList && index >= 0 && index < (int)fList->count() ?
       
   661 	(*fList)[index] : QString::null;
       
   662 }
       
   663 
       
   664 
       
   665 /*!
       
   666   This function is included to easy porting from Qt 1.x to Qt 2.0,
       
   667   it is the same as entryList(), but encodes the filenames as 8-bit
       
   668   strings using QFile::encodedName().
       
   669 
       
   670   It is more efficient to use entryList().
       
   671 */
       
   672 QStrList QDir::encodedEntryList( int filterSpec, int sortSpec ) const
       
   673 {
       
   674     QStrList r;
       
   675     QStringList l = entryList(filterSpec,sortSpec);
       
   676     for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
       
   677 	r.append( QFile::encodeName(*it) );
       
   678     }
       
   679     return r;
       
   680 }
       
   681 
       
   682 /*!
       
   683   This function is included to easy porting from Qt 1.x to Qt 2.0,
       
   684   it is the same as entryList(), but encodes the filenames as 8-bit
       
   685   strings using QFile::encodedName().
       
   686 
       
   687   It is more efficient to use entryList().
       
   688 */
       
   689 QStrList QDir::encodedEntryList( const QString &nameFilter,
       
   690 			   int filterSpec,
       
   691 			   int sortSpec ) const
       
   692 {
       
   693     QStrList r;
       
   694     QStringList l = entryList(nameFilter,filterSpec,sortSpec);
       
   695     for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
       
   696 	r.append( QFile::encodeName(*it) );
       
   697     }
       
   698     return r;
       
   699 }
       
   700 
       
   701 
       
   702 
       
   703 /*!
       
   704   Returns a list of the names of all files and directories in the directory
       
   705   indicated by the setSorting(), setFilter() and setNameFilter()
       
   706   specifications.
       
   707 
       
   708   The the filter and sorting specifications can be overridden using the
       
   709   \e filterSpec and \e sortSpec arguments.
       
   710 
       
   711   Returns an empty list if the directory is unreadable or does not exist.
       
   712 
       
   713   \sa entryInfoList(), setNameFilter(), setSorting(), setFilter(),
       
   714 	encodedEntryList()
       
   715 */
       
   716 
       
   717 QStringList QDir::entryList( int filterSpec, int sortSpec ) const
       
   718 {
       
   719     if ( !dirty && filterSpec == (int)DefaultFilter &&
       
   720 		   sortSpec   == (int)DefaultSort )
       
   721 	return *fList;
       
   722     return entryList( nameFilt, filterSpec, sortSpec );
       
   723 }
       
   724 
       
   725 /*!
       
   726   Returns a list of the names of all files and directories in the directory
       
   727   indicated by the setSorting(), setFilter() and setNameFilter()
       
   728   specifications.
       
   729 
       
   730   The the filter and sorting specifications can be overridden using the
       
   731   \e nameFilter, \e filterSpec and \e sortSpec arguments.
       
   732 
       
   733   Returns and empty list if the directory is unreadable or does not exist.
       
   734 
       
   735   \sa entryInfoList(), setNameFilter(), setSorting(), setFilter(),
       
   736 	encodedEntryList()
       
   737 */
       
   738 
       
   739 QStringList QDir::entryList( const QString &nameFilter,
       
   740 				 int filterSpec, int sortSpec ) const
       
   741 {
       
   742     if ( filterSpec == (int)DefaultFilter )
       
   743 	filterSpec = filtS;
       
   744     if ( sortSpec == (int)DefaultSort )
       
   745 	sortSpec = sortS;
       
   746     QDir *that = (QDir*)this;			// mutable function
       
   747     if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) )
       
   748 	return *that->fList;
       
   749     else
       
   750 	return QStringList();
       
   751 }
       
   752 
       
   753 /*!
       
   754   Returns a list of QFileInfo objects for all files and directories in
       
   755   the directory pointed to using the setSorting(), setFilter() and
       
   756   setNameFilter() specifications.
       
   757 
       
   758   The the filter and sorting specifications can be overridden using the
       
   759   \e filterSpec and \e sortSpec arguments.
       
   760 
       
   761   Returns 0 if the directory is unreadable or does not exist.
       
   762 
       
   763   The returned pointer is a const pointer to a QFileInfoList. The list is
       
   764   owned by the QDir object and will be reused on the next call to
       
   765   entryInfoList() for the same QDir instance. If you want to keep the
       
   766   entries of the list after a subsequent call to this function you will
       
   767   need to copy them.
       
   768 
       
   769   \sa entryList(), setNameFilter(), setSorting(), setFilter()
       
   770 */
       
   771 
       
   772 const QFileInfoList *QDir::entryInfoList( int filterSpec, int sortSpec ) const
       
   773 {
       
   774     if ( !dirty && filterSpec == (int)DefaultFilter &&
       
   775 		   sortSpec   == (int)DefaultSort )
       
   776 	return fiList;
       
   777     return entryInfoList( nameFilt, filterSpec, sortSpec );
       
   778 }
       
   779 
       
   780 /*!
       
   781   Returns a list of QFileInfo objects for all files and directories in
       
   782   the directory pointed to using the setSorting(), setFilter() and
       
   783   setNameFilter() specifications.
       
   784 
       
   785   The the filter and sorting specifications can be overridden using the
       
   786   \e nameFilter, \e filterSpec and \e sortSpec arguments.
       
   787 
       
   788   Returns 0 if the directory is unreadable or does not exist.
       
   789 
       
   790   The returned pointer is a const pointer to a QFileInfoList. The list is
       
   791   owned by the QDir object and will be reused on the next call to
       
   792   entryInfoList() for the same QDir instance. If you want to keep the
       
   793   entries of the list after a subsequent call to this function you will
       
   794   need to copy them.
       
   795 
       
   796   \sa entryList(), setNameFilter(), setSorting(), setFilter()
       
   797 */
       
   798 
       
   799 const QFileInfoList *QDir::entryInfoList( const QString &nameFilter,
       
   800 					  int filterSpec, int sortSpec ) const
       
   801 {
       
   802     if ( filterSpec == (int)DefaultFilter )
       
   803 	filterSpec = filtS;
       
   804     if ( sortSpec == (int)DefaultSort )
       
   805 	sortSpec = sortS;
       
   806     QDir *that = (QDir*)this;			// mutable function
       
   807     if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) )
       
   808 	return that->fiList;
       
   809     else
       
   810 	return 0;
       
   811 }
       
   812 
       
   813 /*!
       
   814   Returns TRUE if the directory exists. (If a file with the same
       
   815   name is found this function will of course return FALSE).
       
   816 
       
   817   \sa QFileInfo::exists(), QFile::exists()
       
   818 */
       
   819 
       
   820 bool QDir::exists() const
       
   821 {
       
   822     QFileInfo fi( dPath );
       
   823     return fi.exists() && fi.isDir();
       
   824 }
       
   825 
       
   826 /*!
       
   827   Returns TRUE if the directory path is relative to the current directory,
       
   828   FALSE if the path is absolute (e.g. under UNIX a path is relative if it
       
   829   does not start with a '/').
       
   830 
       
   831   According to Einstein this function should always return TRUE.
       
   832 
       
   833   \sa convertToAbs()
       
   834 */
       
   835 
       
   836 bool QDir::isRelative() const
       
   837 {
       
   838     return isRelativePath( dPath );
       
   839 }
       
   840 
       
   841 /*!
       
   842   Converts the directory path to an absolute path. If it is already
       
   843   absolute nothing is done.
       
   844 
       
   845   \sa isRelative()
       
   846 */
       
   847 
       
   848 void QDir::convertToAbs()
       
   849 {
       
   850     dPath = absPath();
       
   851 }
       
   852 
       
   853 /*!
       
   854   Makes a copy of d and assigns it to this QDir.
       
   855 */
       
   856 
       
   857 QDir &QDir::operator=( const QDir &d )
       
   858 {
       
   859     dPath    = d.dPath;
       
   860     delete fList;
       
   861     fList    = 0;
       
   862     delete fiList;
       
   863     fiList   = 0;
       
   864     nameFilt = d.nameFilt;
       
   865     dirty    = TRUE;
       
   866     allDirs  = d.allDirs;
       
   867     filtS    = d.filtS;
       
   868     sortS    = d.sortS;
       
   869     return *this;
       
   870 }
       
   871 
       
   872 /*!
       
   873   Sets the directory path to be the given path.
       
   874 */
       
   875 
       
   876 QDir &QDir::operator=( const QString &path )
       
   877 {
       
   878     dPath = cleanDirPath( path );
       
   879     dirty = TRUE;
       
   880     return *this;
       
   881 }
       
   882 
       
   883 
       
   884 /*!
       
   885   \fn bool QDir::operator!=( const QDir &d ) const
       
   886   Returns TRUE if the \e d and this dir have different path or
       
   887   different sort/filter settings, otherwise FALSE.
       
   888 */
       
   889 
       
   890 /*!
       
   891   Returns TRUE if the \e d and this dir have the same path and all sort
       
   892   and filter settings are equal, otherwise FALSE.
       
   893 */
       
   894 
       
   895 bool QDir::operator==( const QDir &d ) const
       
   896 {
       
   897     return dPath    == d.dPath &&
       
   898 	   nameFilt == d.nameFilt &&
       
   899 	   allDirs  == d.allDirs &&
       
   900 	   filtS    == d.filtS &&
       
   901 	   sortS    == d.sortS;
       
   902 }
       
   903 
       
   904 
       
   905 /*!
       
   906   Removes a file.
       
   907 
       
   908   If \e acceptAbsPath is TRUE a path starting with a separator ('/')
       
   909   will remove the file with the absolute path, if \e acceptAbsPath is FALSE
       
   910   any number of separators at the beginning of \e fileName will be removed.
       
   911 
       
   912   Returns TRUE if successful, otherwise FALSE.
       
   913 */
       
   914 
       
   915 bool QDir::remove( const QString &fileName, bool acceptAbsPath )
       
   916 {
       
   917     if ( fileName.isEmpty() ) {
       
   918 #if defined(CHECK_NULL)
       
   919 	qWarning( "QDir::remove: Empty or null file name" );
       
   920 #endif
       
   921 	return FALSE;
       
   922     }
       
   923     QString p = filePath( fileName, acceptAbsPath );
       
   924     return QFile::remove( p );
       
   925 }
       
   926 
       
   927 /*!
       
   928   Checks for existence of a file.
       
   929 
       
   930   If \e acceptAbsPaths is TRUE a path starting with a separator ('/')
       
   931   will check the file with the absolute path, if \e acceptAbsPath is FALSE
       
   932   any number of separators at the beginning of \e name will be removed.
       
   933 
       
   934   Returns TRUE if the file exists, otherwise FALSE.
       
   935 
       
   936   \sa QFileInfo::exists(), QFile::exists()
       
   937 */
       
   938 
       
   939 bool QDir::exists( const QString &name, bool acceptAbsPath )
       
   940 {
       
   941     if ( name.isEmpty() ) {
       
   942 #if defined(CHECK_NULL)
       
   943 	qWarning( "QDir::exists: Empty or null file name" );
       
   944 #endif
       
   945 	return FALSE;
       
   946     }
       
   947     QString tmp = filePath( name, acceptAbsPath );
       
   948     return QFile::exists( tmp );
       
   949 }
       
   950 
       
   951 /*!
       
   952   Returns the native directory separator; '/' under UNIX and '\' under
       
   953   MS-DOS, Windows NT and OS/2.
       
   954 
       
   955   You do not need to use this function to build file paths. If you always
       
   956   use '/', Qt will translate your paths to conform to the underlying
       
   957   operating system.
       
   958 */
       
   959 
       
   960 char QDir::separator()
       
   961 {
       
   962 #if defined(_OS_UNIX_)
       
   963     return '/';
       
   964 #elif defined (_OS_FATFS_)
       
   965     return '\\';
       
   966 #elif defined (_OS_MAC_)
       
   967     return ':';
       
   968 #else
       
   969     return '/';
       
   970 #endif
       
   971 }
       
   972 
       
   973 /*!
       
   974   Returns the current directory.
       
   975   \sa currentDirPath(), QDir::QDir()
       
   976 */
       
   977 
       
   978 QDir QDir::current()
       
   979 {
       
   980     return QDir( currentDirPath() );
       
   981 }
       
   982 
       
   983 /*!
       
   984   Returns the home directory.
       
   985   \sa homeDirPath()
       
   986 */
       
   987 
       
   988 QDir QDir::home()
       
   989 {
       
   990     return QDir( homeDirPath() );
       
   991 }
       
   992 
       
   993 /*!
       
   994   Returns the root directory.
       
   995   \sa rootDirPath() drives()
       
   996 */
       
   997 
       
   998 QDir QDir::root()
       
   999 {
       
  1000     return QDir( rootDirPath() );
       
  1001 }
       
  1002 
       
  1003 /*!
       
  1004   \fn QString QDir::homeDirPath()
       
  1005 
       
  1006   Returns the absolute path for the user's home directory,
       
  1007   \sa home()
       
  1008 */
       
  1009 
       
  1010 QStringList qt_makeFilterList( const QString &filter )
       
  1011 {
       
  1012     if ( filter.isEmpty() )
       
  1013 	return QStringList();
       
  1014 
       
  1015     QChar sep( ';' );
       
  1016     int i = filter.find( sep, 0 );
       
  1017     if ( i == -1 && filter.find( ' ', 0 ) != -1 )
       
  1018 	sep = QChar( ' ' );
       
  1019 
       
  1020     QStringList lst = QStringList::split( sep, filter );
       
  1021     QStringList lst2;
       
  1022     QStringList::Iterator it = lst.begin();
       
  1023 
       
  1024     for ( ; it != lst.end(); ++it ) {
       
  1025 	QString s = *it;
       
  1026 	lst2 << s.stripWhiteSpace();
       
  1027     }
       
  1028     return lst2;
       
  1029 }
       
  1030 
       
  1031 /*!
       
  1032   Returns TRUE if the \e fileName matches one of the wildcards in the list \e filters.
       
  1033   \sa QRegExp
       
  1034 */
       
  1035 
       
  1036 bool QDir::match( const QStringList &filters, const QString &fileName )
       
  1037 {
       
  1038     QStringList::ConstIterator sit = filters.begin();
       
  1039     bool matched = FALSE;
       
  1040     for ( ; sit != filters.end(); ++sit ) {
       
  1041 	QRegExp regexp( *sit, FALSE, TRUE );
       
  1042 	if ( regexp.match( fileName ) != -1 ) {
       
  1043 	    matched = TRUE;
       
  1044 	    break;
       
  1045 	}
       
  1046     }
       
  1047 
       
  1048     return matched;
       
  1049 }
       
  1050 
       
  1051 /*!
       
  1052   Returns TRUE if the \e fileName matches the wildcard \e filter.
       
  1053   \a Filter may also contain multiple wildcards separated by spaces or
       
  1054   semicolons.
       
  1055   \sa QRegExp
       
  1056 */
       
  1057 
       
  1058 bool QDir::match( const QString &filter, const QString &fileName )
       
  1059 {
       
  1060     QStringList lst = qt_makeFilterList( filter );
       
  1061     return match( lst, fileName );
       
  1062 }
       
  1063 
       
  1064 
       
  1065 /*!
       
  1066   Removes all multiple directory separators ('/') and resolves
       
  1067   any "." or ".." found in the path.
       
  1068 
       
  1069   Symbolic links are kept.  This function does not return the
       
  1070   canonical path, but rather the most simplified version of the input.
       
  1071   "../stuff" becomes "stuff", "stuff/../nonsense" becomes "nonsense"
       
  1072   and "\\stuff\\more\\..\\nonsense" becomes "\\stuff\\nonsense".
       
  1073 
       
  1074   \sa absPath() canonicalPath()
       
  1075 */
       
  1076 
       
  1077 QString QDir::cleanDirPath( const QString &filePath )
       
  1078 {
       
  1079     QString name = filePath;
       
  1080     QString newPath;
       
  1081 
       
  1082     if ( name.isEmpty() )
       
  1083 	return name;
       
  1084 
       
  1085     slashify( name );
       
  1086 
       
  1087     bool addedSeparator;
       
  1088     if ( isRelativePath(name) ) {
       
  1089 	addedSeparator = TRUE;
       
  1090 	name.insert( 0, '/' );
       
  1091     } else {
       
  1092 	addedSeparator = FALSE;
       
  1093     }
       
  1094 
       
  1095     int ePos, pos, upLevel;
       
  1096 
       
  1097     pos = ePos = name.length();
       
  1098     upLevel = 0;
       
  1099     int len;
       
  1100 
       
  1101     while ( pos && (pos = name.findRev('/',--pos)) != -1 ) {
       
  1102 	len = ePos - pos - 1;
       
  1103 	if ( len == 2 && name.at(pos + 1) == '.'
       
  1104 		      && name.at(pos + 2) == '.' ) {
       
  1105 	    upLevel++;
       
  1106 	} else {
       
  1107 	    if ( len != 0 && (len != 1 || name.at(pos + 1) != '.') ) {
       
  1108 		if ( !upLevel )
       
  1109 		    newPath = QString::fromLatin1("/")
       
  1110 			+ name.mid(pos + 1, len) + newPath;
       
  1111 		else
       
  1112 		    upLevel--;
       
  1113 	    }
       
  1114 	}
       
  1115 	ePos = pos;
       
  1116     }
       
  1117     if ( addedSeparator ) {
       
  1118 	while ( upLevel-- )
       
  1119 	    newPath.insert( 0, QString::fromLatin1("/..") );
       
  1120 	if ( !newPath.isEmpty() )
       
  1121 	    newPath.remove( 0, 1 );
       
  1122 	else
       
  1123 	    newPath = QString::fromLatin1(".");
       
  1124     } else {
       
  1125 	if ( newPath.isEmpty() )
       
  1126 	    newPath = QString::fromLatin1("/");
       
  1127 #if defined(_OS_FATFS_) || defined(_OS_OS2EMX_)
       
  1128 	if ( name[0] == '/' ) {
       
  1129 	    if ( name[1] == '/' )		// "\\machine\x\ ..."
       
  1130 		newPath.insert( 0, '/' );
       
  1131 	} else {
       
  1132 	    newPath = name.left(2) + newPath;
       
  1133 	}
       
  1134 #endif
       
  1135     }
       
  1136     return newPath;
       
  1137 }
       
  1138 
       
  1139 int qt_cmp_si_sortSpec;
       
  1140 
       
  1141 #if defined(Q_C_CALLBACKS)
       
  1142 extern "C" {
       
  1143 #endif
       
  1144 
       
  1145 int qt_cmp_si( const void *n1, const void *n2 )
       
  1146 {
       
  1147     if ( !n1 || !n2 )
       
  1148 	return 0;
       
  1149 
       
  1150     QDirSortItem* f1 = (QDirSortItem*)n1;
       
  1151     QDirSortItem* f2 = (QDirSortItem*)n2;
       
  1152 
       
  1153     if ( qt_cmp_si_sortSpec & QDir::DirsFirst )
       
  1154 	if ( f1->item->isDir() != f2->item->isDir() )
       
  1155 	    return f1->item->isDir() ? -1 : 1;
       
  1156 
       
  1157     int r = 0;
       
  1158     int sortBy = qt_cmp_si_sortSpec & QDir::SortByMask;
       
  1159 
       
  1160     switch ( sortBy ) {
       
  1161       case QDir::Time:
       
  1162 	r = f1->item->lastModified().secsTo(f2->item->lastModified());
       
  1163 	break;
       
  1164       case QDir::Size:
       
  1165 	r = f2->item->size() - f1->item->size();
       
  1166 	break;
       
  1167       default:
       
  1168 	;
       
  1169     }
       
  1170 
       
  1171     if ( r == 0 && sortBy != QDir::Unsorted ) {
       
  1172 	// Still not sorted - sort by name
       
  1173 	bool ic = qt_cmp_si_sortSpec & QDir::IgnoreCase;
       
  1174 
       
  1175 	if ( f1->filename_cache.isNull() )
       
  1176 	    f1->filename_cache = ic ? f1->item->fileName().lower()
       
  1177 				    : f1->item->fileName();
       
  1178 	if ( f2->filename_cache.isNull() )
       
  1179 	    f2->filename_cache = ic ? f2->item->fileName().lower()
       
  1180 				    : f2->item->fileName();
       
  1181 
       
  1182 	r = f1->filename_cache.compare(f2->filename_cache);
       
  1183     }
       
  1184 
       
  1185     if ( r == 0 ) {
       
  1186 	// Enforce an order - the order the items appear in the array
       
  1187 	r = (char*)n1 - (char*)n2;
       
  1188     }
       
  1189 
       
  1190     if ( qt_cmp_si_sortSpec & QDir::Reversed )
       
  1191 	return -r;
       
  1192     else
       
  1193 	return r;
       
  1194 }
       
  1195 
       
  1196 #if defined(Q_C_CALLBACKS)
       
  1197 }
       
  1198 #endif
       
  1199 
       
  1200 #endif // QT_NO_DIR