Mercurial > hg > easyhg
view src/fswatcher.h @ 587:4ed384ea7f39 fswatcher
comment only
author | Chris Cannam |
---|---|
date | Wed, 14 Mar 2012 12:00:20 +0000 |
parents | 687d9e700e81 |
children | ae67ea0af696 |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* EasyMercurial Based on HgExplorer by Jari Korhonen Copyright (c) 2010 Jari Korhonen Copyright (c) 2012 Chris Cannam Copyright (c) 2012 Queen Mary, University of London This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #ifndef FSWATCHER_H #define FSWATCHER_H #include <QObject> #include <QMutex> #include <QString> #include <QSet> #include <QHash> #include <QMap> #include <QDateTime> #include <QStringList> #ifndef Q_OS_MAC // We don't use QFileSystemWatcher on OS/X. // See comments at top of fswatcher.cpp for an explanation. #include <QFileSystemWatcher> #endif class FsWatcher : public QObject { Q_OBJECT public: FsWatcher(); virtual ~FsWatcher(); /** * Set the root path of the work directory to be monitored. This * directory and all its subdirectories (recursively) will be * monitored for changes. * * If this path differs from the currently set work dir path, then * the tracked file paths will also be cleared. Call * setTrackedFilePaths afterwards to ensure non-directory files * are monitored. */ void setWorkDirPath(QString path); /** * Provide a set of paths for files which should be tracked. These * will be the only non-directory files monitored for changes. The * paths should be relative to the work directory. */ void setTrackedFilePaths(QStringList paths); /** * Provide a set of prefixes to ignore. Files whose names start * with a prefix in this set will be ignored when they change. */ void setIgnoredFilePrefixes(QStringList prefixes); /** * Provide a set of suffixes to ignore. Files whose names end * with a suffix in this set will be ignored when they change. */ void setIgnoredFileSuffixes(QStringList suffixes); /** * Return a token to identify the current caller in subsequent * calls to getChangedPaths(). Only changes that occur after this * has been called can be detected by the caller. */ int getNewToken(); /** * Return a list of all non-ignored file paths that have been * observed to have changed since the last call to getChangedPaths * with the same token. */ QSet<QString> getChangedPaths(int token); signals: /** * Emitted when something has changed. Use the asynchronous * interface to find out what. */ void changed(); public slots: void fsDirectoryChanged(QString); void fsFileChanged(QString); private: // call with lock already held void clearWatchedPaths(); // call with lock already held void addWorkDirectory(QString path); // call with lock already held bool shouldIgnore(QString path); // call with lock already held. Returns set of non-ignored files in dir QSet<QString> scanDirectory(QString path); // call with lock already held void debugPrint(); private: /** * A change associates a filename with a counter (the * size_t). Each time a file is changed, its counter is assigned * from m_lastCounter and m_lastCounter is incremented. * * This is not especially efficient -- we often want to find "all * files whose counter is greater than X" which involves a * traversal. Maybe something better later. */ QHash<QString, size_t> m_changes; /** * Associates a token (the client identifier) with a counter. The * counter represents the value of m_lastCounter at the moment * getChangedPaths last completed for that token. Any files in * m_changes whose counters are larger must have been modified. */ QMap<int, size_t> m_tokenMap; /** * Associates a directory path with a list of all the files in it * that do not match our ignore patterns. When a directory is * signalled as having changed, then we need to rescan it and * compare against this list before we can determine whether to * notify about the change or not. */ QHash<QString, QSet<QString> > m_dirContents; QStringList m_ignoredPrefixes; QStringList m_ignoredSuffixes; /// Everything in this class is synchronised. QMutex m_mutex; QString m_workDirPath; int m_lastToken; size_t m_lastCounter; #ifdef Q_OS_MAC void *m_stream; typedef QMap<QString, QDateTime> PathTimeMap; PathTimeMap m_trackedFileUpdates; bool manuallyCheckTrackedFiles(); #else QFileSystemWatcher m_watcher; #endif }; #endif