src/corelib/io/qfilesystemwatcher.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qfilesystemwatcher.h"
       
    43 #include "qfilesystemwatcher_p.h"
       
    44 
       
    45 #ifndef QT_NO_FILESYSTEMWATCHER
       
    46 
       
    47 #include <qdatetime.h>
       
    48 #include <qdebug.h>
       
    49 #include <qdir.h>
       
    50 #include <qfileinfo.h>
       
    51 #include <qmutex.h>
       
    52 #include <qset.h>
       
    53 #include <qtimer.h>
       
    54 
       
    55 #if defined(Q_OS_WIN)
       
    56 #  include "qfilesystemwatcher_win_p.h"
       
    57 #elif defined(Q_OS_LINUX)
       
    58 #  include "qfilesystemwatcher_inotify_p.h"
       
    59 #  include "qfilesystemwatcher_dnotify_p.h"
       
    60 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
       
    61 #  if (defined Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
       
    62 #  include "qfilesystemwatcher_fsevents_p.h"
       
    63 #  endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
       
    64 #  include "qfilesystemwatcher_kqueue_p.h"
       
    65 #elif defined(Q_OS_SYMBIAN)
       
    66 #  include "qfilesystemwatcher_symbian_p.h"
       
    67 #endif
       
    68 
       
    69 QT_BEGIN_NAMESPACE
       
    70 
       
    71 enum { PollingInterval = 1000 };
       
    72 
       
    73 class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
       
    74 {
       
    75     Q_OBJECT
       
    76 
       
    77     class FileInfo
       
    78     {
       
    79         uint ownerId;
       
    80         uint groupId;
       
    81         QFile::Permissions permissions;
       
    82         QDateTime lastModified;
       
    83         QStringList entries;
       
    84 
       
    85     public:
       
    86         FileInfo(const QFileInfo &fileInfo)
       
    87             : ownerId(fileInfo.ownerId()),
       
    88               groupId(fileInfo.groupId()),
       
    89               permissions(fileInfo.permissions()),
       
    90               lastModified(fileInfo.lastModified())
       
    91         { 
       
    92             if (fileInfo.isDir()) {
       
    93                 entries = fileInfo.absoluteDir().entryList(QDir::AllEntries);
       
    94             }
       
    95         }
       
    96         FileInfo &operator=(const QFileInfo &fileInfo)
       
    97         {
       
    98             *this = FileInfo(fileInfo);
       
    99             return *this;
       
   100         }
       
   101 
       
   102         bool operator!=(const QFileInfo &fileInfo) const
       
   103         {
       
   104             if (fileInfo.isDir() && entries != fileInfo.absoluteDir().entryList(QDir::AllEntries))
       
   105                 return true;
       
   106             return (ownerId != fileInfo.ownerId()
       
   107                     || groupId != fileInfo.groupId()
       
   108                     || permissions != fileInfo.permissions()
       
   109                     || lastModified != fileInfo.lastModified());
       
   110         }
       
   111     };
       
   112 
       
   113     mutable QMutex mutex;
       
   114     QHash<QString, FileInfo> files, directories;
       
   115 
       
   116 public:
       
   117     QPollingFileSystemWatcherEngine();
       
   118 
       
   119     void run();
       
   120 
       
   121     QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
       
   122     QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
       
   123 
       
   124     void stop();
       
   125 
       
   126 private Q_SLOTS:
       
   127     void timeout();
       
   128 };
       
   129 
       
   130 QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine()
       
   131 {
       
   132 #ifndef QT_NO_THREAD
       
   133     moveToThread(this);
       
   134 #endif
       
   135 }
       
   136 
       
   137 void QPollingFileSystemWatcherEngine::run()
       
   138 {
       
   139     QTimer timer;
       
   140     connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
       
   141     timer.start(PollingInterval);
       
   142     (void) exec();
       
   143 }
       
   144 
       
   145 QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
       
   146                                                       QStringList *files,
       
   147                                                       QStringList *directories)
       
   148 {
       
   149     QMutexLocker locker(&mutex);
       
   150     QStringList p = paths;
       
   151     QMutableListIterator<QString> it(p);
       
   152     while (it.hasNext()) {
       
   153         QString path = it.next();
       
   154         QFileInfo fi(path);
       
   155         if (!fi.exists())
       
   156             continue;
       
   157         if (fi.isDir()) {
       
   158             if (!directories->contains(path))
       
   159                 directories->append(path);
       
   160             if (!path.endsWith(QLatin1Char('/')))
       
   161                 fi = QFileInfo(path + QLatin1Char('/'));
       
   162             this->directories.insert(path, fi);
       
   163         } else {
       
   164             if (!files->contains(path))
       
   165                 files->append(path);
       
   166             this->files.insert(path, fi);
       
   167         }
       
   168         it.remove();
       
   169     }
       
   170     start();
       
   171     return p;
       
   172 }
       
   173 
       
   174 QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &paths,
       
   175                                                          QStringList *files,
       
   176                                                          QStringList *directories)
       
   177 {
       
   178     QMutexLocker locker(&mutex);
       
   179     QStringList p = paths;
       
   180     QMutableListIterator<QString> it(p);
       
   181     while (it.hasNext()) {
       
   182         QString path = it.next();
       
   183         if (this->directories.remove(path)) {
       
   184             directories->removeAll(path);
       
   185             it.remove();
       
   186         } else if (this->files.remove(path)) {
       
   187             files->removeAll(path);
       
   188             it.remove();
       
   189         }
       
   190     }
       
   191     if (this->files.isEmpty() && this->directories.isEmpty()) {
       
   192         locker.unlock();
       
   193         stop();
       
   194         wait();
       
   195     }
       
   196     return p;
       
   197 }
       
   198 
       
   199 void QPollingFileSystemWatcherEngine::stop()
       
   200 {
       
   201     QMetaObject::invokeMethod(this, "quit");
       
   202 }
       
   203 
       
   204 void QPollingFileSystemWatcherEngine::timeout()
       
   205 {
       
   206     QMutexLocker locker(&mutex);
       
   207     QMutableHashIterator<QString, FileInfo> fit(files);
       
   208     while (fit.hasNext()) {
       
   209         QHash<QString, FileInfo>::iterator x = fit.next();
       
   210         QString path = x.key();
       
   211         QFileInfo fi(path);
       
   212         if (!fi.exists()) {
       
   213             fit.remove();
       
   214             emit fileChanged(path, true);
       
   215         } else if (x.value() != fi) {
       
   216             x.value() = fi;
       
   217             emit fileChanged(path, false);
       
   218         }
       
   219     }
       
   220     QMutableHashIterator<QString, FileInfo> dit(directories);
       
   221     while (dit.hasNext()) {
       
   222         QHash<QString, FileInfo>::iterator x = dit.next();
       
   223         QString path = x.key();
       
   224         QFileInfo fi(path);
       
   225         if (!path.endsWith(QLatin1Char('/')))
       
   226             fi = QFileInfo(path + QLatin1Char('/'));
       
   227         if (!fi.exists()) {
       
   228             dit.remove();
       
   229             emit directoryChanged(path, true);
       
   230         } else if (x.value() != fi) {
       
   231             x.value() = fi;
       
   232             emit directoryChanged(path, false);
       
   233         }
       
   234         
       
   235     }
       
   236 }
       
   237 
       
   238 
       
   239 
       
   240 
       
   241 QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine()
       
   242 {
       
   243 #if defined(Q_OS_WIN)
       
   244     return new QWindowsFileSystemWatcherEngine;
       
   245 #elif defined(Q_OS_LINUX)
       
   246     QFileSystemWatcherEngine *eng = QInotifyFileSystemWatcherEngine::create();
       
   247     if(!eng)
       
   248         eng = QDnotifyFileSystemWatcherEngine::create();
       
   249     return eng;
       
   250 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
       
   251 #  if 0 && (defined Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
       
   252     if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
       
   253         return QFSEventsFileSystemWatcherEngine::create();
       
   254     else
       
   255 #  endif
       
   256         return QKqueueFileSystemWatcherEngine::create();
       
   257 #elif defined(Q_OS_SYMBIAN)
       
   258     return new QSymbianFileSystemWatcherEngine;
       
   259 #else
       
   260     return 0;
       
   261 #endif
       
   262 }
       
   263 
       
   264 QFileSystemWatcherPrivate::QFileSystemWatcherPrivate()
       
   265     : native(0), poller(0), forced(0)
       
   266 {
       
   267 }
       
   268 
       
   269 void QFileSystemWatcherPrivate::init()
       
   270 {
       
   271     Q_Q(QFileSystemWatcher);
       
   272     native = createNativeEngine();
       
   273     if (native) {
       
   274         QObject::connect(native,
       
   275                          SIGNAL(fileChanged(QString,bool)),
       
   276                          q,
       
   277                          SLOT(_q_fileChanged(QString,bool)));
       
   278         QObject::connect(native,
       
   279                          SIGNAL(directoryChanged(QString,bool)),
       
   280                          q,
       
   281                          SLOT(_q_directoryChanged(QString,bool)));
       
   282     }
       
   283 }
       
   284 
       
   285 void QFileSystemWatcherPrivate::initForcedEngine(const QString &forceName)
       
   286 {
       
   287     if(forced)
       
   288         return;
       
   289 
       
   290     Q_Q(QFileSystemWatcher);
       
   291 
       
   292 #if defined(Q_OS_LINUX)
       
   293     if(forceName == QLatin1String("inotify")) {
       
   294         forced = QInotifyFileSystemWatcherEngine::create();
       
   295     } else if(forceName == QLatin1String("dnotify")) {
       
   296         forced = QDnotifyFileSystemWatcherEngine::create();
       
   297     }
       
   298 #else
       
   299     Q_UNUSED(forceName);
       
   300 #endif
       
   301 
       
   302     if(forced) {
       
   303         QObject::connect(forced,
       
   304                          SIGNAL(fileChanged(QString,bool)),
       
   305                          q,
       
   306                          SLOT(_q_fileChanged(QString,bool)));
       
   307         QObject::connect(forced,
       
   308                          SIGNAL(directoryChanged(QString,bool)),
       
   309                          q,
       
   310                          SLOT(_q_directoryChanged(QString,bool)));
       
   311     }
       
   312 }
       
   313 
       
   314 void QFileSystemWatcherPrivate::initPollerEngine()
       
   315 {
       
   316     if(poller)
       
   317         return;
       
   318 
       
   319     Q_Q(QFileSystemWatcher);
       
   320     poller = new QPollingFileSystemWatcherEngine; // that was a mouthful
       
   321     QObject::connect(poller,
       
   322                      SIGNAL(fileChanged(QString,bool)),
       
   323                      q,
       
   324                      SLOT(_q_fileChanged(QString,bool)));
       
   325     QObject::connect(poller,
       
   326                      SIGNAL(directoryChanged(QString,bool)),
       
   327                      q,
       
   328                      SLOT(_q_directoryChanged(QString,bool)));
       
   329 }
       
   330 
       
   331 void QFileSystemWatcherPrivate::_q_fileChanged(const QString &path, bool removed)
       
   332 {
       
   333     Q_Q(QFileSystemWatcher);
       
   334     if (!files.contains(path)) {
       
   335         // the path was removed after a change was detected, but before we delivered the signal
       
   336         return;
       
   337     }
       
   338     if (removed)
       
   339         files.removeAll(path);
       
   340     emit q->fileChanged(path);
       
   341 }
       
   342 
       
   343 void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool removed)
       
   344 {
       
   345     Q_Q(QFileSystemWatcher);
       
   346     if (!directories.contains(path)) {
       
   347         // perhaps the path was removed after a change was detected, but before we delivered the signal
       
   348         return;
       
   349     }
       
   350     if (removed)
       
   351         directories.removeAll(path);
       
   352     emit q->directoryChanged(path);
       
   353 }
       
   354 
       
   355 
       
   356 
       
   357 /*!
       
   358     \class QFileSystemWatcher
       
   359     \brief The QFileSystemWatcher class provides an interface for monitoring files and directories for modifications.
       
   360     \ingroup io
       
   361     \since 4.2
       
   362     \reentrant
       
   363 
       
   364     QFileSystemWatcher monitors the file system for changes to files
       
   365     and directories by watching a list of specified paths.
       
   366 
       
   367     Call addPath() to watch a particular file or directory. Multiple
       
   368     paths can be added using the addPaths() function. Existing paths can
       
   369     be removed by using the removePath() and removePaths() functions.
       
   370 
       
   371     QFileSystemWatcher examines each path added to it. Files that have
       
   372     been added to the QFileSystemWatcher can be accessed using the
       
   373     files() function, and directories using the directories() function.
       
   374 
       
   375     The fileChanged() signal is emitted when a file has been modified,
       
   376     renamed or removed from disk. Similarly, the directoryChanged()
       
   377     signal is emitted when a directory or its contents is modified or
       
   378     removed.  Note that QFileSystemWatcher stops monitoring files once
       
   379     they have been renamed or removed from disk, and directories once
       
   380     they have been removed from disk.
       
   381 
       
   382     \note On systems running a Linux kernel without inotify support,
       
   383     file systems that contain watched paths cannot be unmounted.
       
   384 
       
   385     \note Windows CE does not support directory monitoring by
       
   386     default as this depends on the file system driver installed.
       
   387 
       
   388     \note The act of monitoring files and directories for
       
   389     modifications consumes system resources. This implies there is a
       
   390     limit to the number of files and directories your process can
       
   391     monitor simultaneously. On Mac OS X 10.4 and all BSD variants, for
       
   392     example, an open file descriptor is required for each monitored
       
   393     file. Some system limits the number of open file descriptors to 256
       
   394     by default. This means that addPath() and addPaths() will fail if
       
   395     your process tries to add more than 256 files or directories to
       
   396     the file system monitor. Also note that your process may have
       
   397     other file descriptors open in addition to the ones for files
       
   398     being monitored, and these other open descriptors also count in
       
   399     the total. Mac OS X 10.5 and up use a different backend and do not
       
   400     suffer from this issue.
       
   401 
       
   402 
       
   403     \sa QFile, QDir
       
   404 */
       
   405 
       
   406 
       
   407 /*!
       
   408     Constructs a new file system watcher object with the given \a parent.
       
   409 */
       
   410 QFileSystemWatcher::QFileSystemWatcher(QObject *parent)
       
   411     : QObject(*new QFileSystemWatcherPrivate, parent)
       
   412 {
       
   413     d_func()->init();
       
   414 }
       
   415 
       
   416 /*!
       
   417     Constructs a new file system watcher object with the given \a parent
       
   418     which monitors the specified \a paths list.
       
   419 */
       
   420 QFileSystemWatcher::QFileSystemWatcher(const QStringList &paths, QObject *parent)
       
   421     : QObject(*new QFileSystemWatcherPrivate, parent)
       
   422 {
       
   423     d_func()->init();
       
   424     addPaths(paths);
       
   425 }
       
   426 
       
   427 /*!
       
   428     Destroys the file system watcher.
       
   429 */
       
   430 QFileSystemWatcher::~QFileSystemWatcher()
       
   431 {
       
   432     Q_D(QFileSystemWatcher);
       
   433     if (d->native) {
       
   434         d->native->stop();
       
   435         d->native->wait();
       
   436         delete d->native;
       
   437         d->native = 0;
       
   438     }
       
   439     if (d->poller) {
       
   440         d->poller->stop();
       
   441         d->poller->wait();
       
   442         delete d->poller;
       
   443         d->poller = 0;
       
   444     }
       
   445     if (d->forced) {
       
   446         d->forced->stop();
       
   447         d->forced->wait();
       
   448         delete d->forced;
       
   449         d->forced = 0;
       
   450     }
       
   451 }
       
   452 
       
   453 /*!
       
   454     Adds \a path to the file system watcher if \a path exists. The
       
   455     path is not added if it does not exist, or if it is already being
       
   456     monitored by the file system watcher.
       
   457 
       
   458     If \a path specifies a directory, the directoryChanged() signal
       
   459     will be emitted when \a path is modified or removed from disk;
       
   460     otherwise the fileChanged() signal is emitted when \a path is
       
   461     modified, renamed or removed.
       
   462 
       
   463     \note There is a system dependent limit to the number of files and
       
   464     directories that can be monitored simultaneously. If this limit
       
   465     has been reached, \a path will not be added to the file system
       
   466     watcher, and a warning message will be printed to \e{stderr}.
       
   467 
       
   468     \sa addPaths(), removePath()
       
   469 */
       
   470 void QFileSystemWatcher::addPath(const QString &path)
       
   471 {
       
   472     if (path.isEmpty()) {
       
   473         qWarning("QFileSystemWatcher::addPath: path is empty");
       
   474         return;
       
   475     }
       
   476     addPaths(QStringList(path));
       
   477 }
       
   478 
       
   479 /*!
       
   480     Adds each path in \a paths to the file system watcher. Paths are
       
   481     not added if they not exist, or if they are already being
       
   482     monitored by the file system watcher.
       
   483 
       
   484     If a path specifies a directory, the directoryChanged() signal
       
   485     will be emitted when the path is modified or removed from disk;
       
   486     otherwise the fileChanged() signal is emitted when the path is
       
   487     modified, renamed, or removed.
       
   488 
       
   489     \note There is a system dependent limit to the number of files and
       
   490     directories that can be monitored simultaneously. If this limit
       
   491     has been reached, the excess \a paths will not be added to the
       
   492     file system watcher, and a warning message will be printed to
       
   493     \e{stderr} for each path that could not be added.
       
   494 
       
   495     \sa addPath(), removePaths()
       
   496 */
       
   497 void QFileSystemWatcher::addPaths(const QStringList &paths)
       
   498 {
       
   499     Q_D(QFileSystemWatcher);
       
   500     if (paths.isEmpty()) {
       
   501         qWarning("QFileSystemWatcher::addPaths: list is empty");
       
   502         return;
       
   503     }
       
   504 
       
   505     QStringList p = paths;
       
   506     QFileSystemWatcherEngine *engine = 0;
       
   507 
       
   508     if(!objectName().startsWith(QLatin1String("_qt_autotest_force_engine_"))) {
       
   509         // Normal runtime case - search intelligently for best engine
       
   510         if(d->native) {
       
   511             engine = d->native;
       
   512         } else {
       
   513             d_func()->initPollerEngine();
       
   514             engine = d->poller;
       
   515         }
       
   516 
       
   517     } else {
       
   518         // Autotest override case - use the explicitly selected engine only
       
   519         QString forceName = objectName().mid(26);
       
   520         if(forceName == QLatin1String("poller")) {
       
   521             qDebug() << "QFileSystemWatcher: skipping native engine, using only polling engine";
       
   522             d_func()->initPollerEngine();
       
   523             engine = d->poller;
       
   524         } else if(forceName == QLatin1String("native")) {
       
   525             qDebug() << "QFileSystemWatcher: skipping polling engine, using only native engine";
       
   526             engine = d->native;
       
   527         } else {
       
   528             qDebug() << "QFileSystemWatcher: skipping polling and native engine, using only explicit" << forceName << "engine";
       
   529             d_func()->initForcedEngine(forceName);
       
   530             engine = d->forced;
       
   531         }
       
   532     }
       
   533 
       
   534     if(engine)
       
   535         p = engine->addPaths(p, &d->files, &d->directories);
       
   536 
       
   537     if (!p.isEmpty())
       
   538         qWarning("QFileSystemWatcher: failed to add paths: %s",
       
   539                  qPrintable(p.join(QLatin1String(", "))));
       
   540 }
       
   541 
       
   542 /*!
       
   543     Removes the specified \a path from the file system watcher.
       
   544 
       
   545     \sa removePaths(), addPath()
       
   546 */
       
   547 void QFileSystemWatcher::removePath(const QString &path)
       
   548 {
       
   549     if (path.isEmpty()) {
       
   550         qWarning("QFileSystemWatcher::removePath: path is empty");
       
   551         return;
       
   552     }
       
   553     removePaths(QStringList(path));
       
   554 }
       
   555 
       
   556 /*!
       
   557     Removes the specified \a paths from the file system watcher.
       
   558 
       
   559     \sa removePath(), addPaths()
       
   560 */
       
   561 void QFileSystemWatcher::removePaths(const QStringList &paths)
       
   562 {
       
   563     if (paths.isEmpty()) {
       
   564         qWarning("QFileSystemWatcher::removePaths: list is empty");
       
   565         return;
       
   566     }
       
   567     Q_D(QFileSystemWatcher);
       
   568     QStringList p = paths;
       
   569     if (d->native)
       
   570         p = d->native->removePaths(p, &d->files, &d->directories);
       
   571     if (d->poller)
       
   572         p = d->poller->removePaths(p, &d->files, &d->directories);
       
   573     if (d->forced)
       
   574         p = d->forced->removePaths(p, &d->files, &d->directories);
       
   575 }
       
   576 
       
   577 /*!
       
   578     \fn void QFileSystemWatcher::fileChanged(const QString &path)
       
   579 
       
   580     This signal is emitted when the file at the specified \a path is
       
   581     modified, renamed or removed from disk.
       
   582 
       
   583     \sa directoryChanged()
       
   584 */
       
   585 
       
   586 /*!
       
   587     \fn void QFileSystemWatcher::directoryChanged(const QString &path)
       
   588 
       
   589     This signal is emitted when the directory at a specified \a path,
       
   590     is modified (e.g., when a file is added, modified or deleted) or
       
   591     removed from disk. Note that if there are several changes during a
       
   592     short period of time, some of the changes might not emit this
       
   593     signal. However, the last change in the sequence of changes will
       
   594     always generate this signal.
       
   595 
       
   596     \sa fileChanged()
       
   597 */
       
   598 
       
   599 /*!
       
   600     \fn QStringList QFileSystemWatcher::directories() const
       
   601 
       
   602     Returns a list of paths to directories that are being watched.
       
   603 
       
   604     \sa files()
       
   605 */
       
   606 
       
   607 /*!
       
   608     \fn QStringList QFileSystemWatcher::files() const
       
   609 
       
   610     Returns a list of paths to files that are being watched.
       
   611 
       
   612     \sa directories()
       
   613 */
       
   614 
       
   615 QStringList QFileSystemWatcher::directories() const
       
   616 {
       
   617     Q_D(const QFileSystemWatcher);
       
   618     return d->directories;
       
   619 }
       
   620 
       
   621 QStringList QFileSystemWatcher::files() const
       
   622 {
       
   623     Q_D(const QFileSystemWatcher);
       
   624     return d->files;
       
   625 }
       
   626 
       
   627 QT_END_NAMESPACE
       
   628 
       
   629 #include "moc_qfilesystemwatcher.cpp"
       
   630 
       
   631 #include "qfilesystemwatcher.moc"
       
   632 
       
   633 #endif // QT_NO_FILESYSTEMWATCHER
       
   634