annotate src/fswatcher.h @ 672:88fa1544b407

Merge from branch qt5. There's much more to be done before we can make another release, but clearly it's going to be done using qt5
author Chris Cannam
date Wed, 05 Dec 2018 09:44:10 +0000
parents ae67ea0af696
children
rev   line source
Chris@538 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@538 2
Chris@538 3 /*
Chris@538 4 EasyMercurial
Chris@538 5
Chris@538 6 Based on HgExplorer by Jari Korhonen
Chris@538 7 Copyright (c) 2010 Jari Korhonen
Chris@644 8 Copyright (c) 2013 Chris Cannam
Chris@644 9 Copyright (c) 2013 Queen Mary, University of London
Chris@538 10
Chris@538 11 This program is free software; you can redistribute it and/or
Chris@538 12 modify it under the terms of the GNU General Public License as
Chris@538 13 published by the Free Software Foundation; either version 2 of the
Chris@538 14 License, or (at your option) any later version. See the file
Chris@538 15 COPYING included with this distribution for more information.
Chris@538 16 */
Chris@538 17
Chris@538 18 #ifndef FSWATCHER_H
Chris@538 19 #define FSWATCHER_H
Chris@538 20
Chris@538 21 #include <QObject>
Chris@538 22 #include <QMutex>
Chris@538 23 #include <QString>
Chris@538 24 #include <QSet>
Chris@538 25 #include <QHash>
Chris@538 26 #include <QMap>
Chris@586 27 #include <QDateTime>
Chris@538 28 #include <QStringList>
Chris@584 29
Chris@584 30 #ifndef Q_OS_MAC
Chris@584 31 // We don't use QFileSystemWatcher on OS/X.
Chris@584 32 // See comments at top of fswatcher.cpp for an explanation.
Chris@538 33 #include <QFileSystemWatcher>
Chris@584 34 #endif
Chris@538 35
Chris@538 36 class FsWatcher : public QObject
Chris@538 37 {
Chris@538 38 Q_OBJECT
Chris@538 39
Chris@538 40 public:
Chris@538 41 FsWatcher();
Chris@538 42 virtual ~FsWatcher();
Chris@538 43
Chris@538 44 /**
Chris@539 45 * Set the root path of the work directory to be monitored. This
Chris@539 46 * directory and all its subdirectories (recursively) will be
Chris@539 47 * monitored for changes.
Chris@539 48 *
Chris@541 49 * If this path differs from the currently set work dir path, then
Chris@541 50 * the tracked file paths will also be cleared. Call
Chris@539 51 * setTrackedFilePaths afterwards to ensure non-directory files
Chris@539 52 * are monitored.
Chris@538 53 */
Chris@538 54 void setWorkDirPath(QString path);
Chris@538 55
Chris@538 56 /**
Chris@539 57 * Provide a set of paths for files which should be tracked. These
Chris@542 58 * will be the only non-directory files monitored for changes. The
Chris@542 59 * paths should be relative to the work directory.
Chris@539 60 */
Chris@539 61 void setTrackedFilePaths(QStringList paths);
Chris@539 62
Chris@539 63 /**
Chris@538 64 * Provide a set of prefixes to ignore. Files whose names start
Chris@538 65 * with a prefix in this set will be ignored when they change.
Chris@538 66 */
Chris@538 67 void setIgnoredFilePrefixes(QStringList prefixes);
Chris@538 68
Chris@538 69 /**
Chris@538 70 * Provide a set of suffixes to ignore. Files whose names end
Chris@538 71 * with a suffix in this set will be ignored when they change.
Chris@538 72 */
Chris@538 73 void setIgnoredFileSuffixes(QStringList suffixes);
Chris@538 74
Chris@538 75 /**
Chris@538 76 * Return a token to identify the current caller in subsequent
Chris@538 77 * calls to getChangedPaths(). Only changes that occur after this
Chris@538 78 * has been called can be detected by the caller.
Chris@538 79 */
Chris@538 80 int getNewToken();
Chris@538 81
Chris@538 82 /**
Chris@538 83 * Return a list of all non-ignored file paths that have been
Chris@538 84 * observed to have changed since the last call to getChangedPaths
Chris@538 85 * with the same token.
Chris@538 86 */
Chris@538 87 QSet<QString> getChangedPaths(int token);
Chris@538 88
Chris@538 89 signals:
Chris@538 90 /**
Chris@538 91 * Emitted when something has changed. Use the asynchronous
Chris@538 92 * interface to find out what.
Chris@538 93 */
Chris@538 94 void changed();
Chris@538 95
Chris@585 96 public slots:
Chris@538 97 void fsDirectoryChanged(QString);
Chris@538 98 void fsFileChanged(QString);
Chris@538 99
Chris@538 100 private:
Chris@538 101 // call with lock already held
Chris@584 102 void clearWatchedPaths();
Chris@584 103
Chris@584 104 // call with lock already held
Chris@538 105 void addWorkDirectory(QString path);
Chris@538 106
Chris@538 107 // call with lock already held
Chris@538 108 bool shouldIgnore(QString path);
Chris@538 109
Chris@540 110 // call with lock already held. Returns set of non-ignored files in dir
Chris@540 111 QSet<QString> scanDirectory(QString path);
Chris@540 112
Chris@540 113 // call with lock already held
Chris@540 114 void debugPrint();
Chris@540 115
Chris@538 116 private:
Chris@538 117 /**
Chris@538 118 * A change associates a filename with a counter (the
Chris@538 119 * size_t). Each time a file is changed, its counter is assigned
Chris@538 120 * from m_lastCounter and m_lastCounter is incremented.
Chris@538 121 *
Chris@538 122 * This is not especially efficient -- we often want to find "all
Chris@538 123 * files whose counter is greater than X" which involves a
Chris@538 124 * traversal. Maybe something better later.
Chris@538 125 */
Chris@538 126 QHash<QString, size_t> m_changes;
Chris@538 127
Chris@538 128 /**
Chris@538 129 * Associates a token (the client identifier) with a counter. The
Chris@538 130 * counter represents the value of m_lastCounter at the moment
Chris@538 131 * getChangedPaths last completed for that token. Any files in
Chris@538 132 * m_changes whose counters are larger must have been modified.
Chris@538 133 */
Chris@538 134 QMap<int, size_t> m_tokenMap;
Chris@538 135
Chris@540 136 /**
Chris@540 137 * Associates a directory path with a list of all the files in it
Chris@540 138 * that do not match our ignore patterns. When a directory is
Chris@540 139 * signalled as having changed, then we need to rescan it and
Chris@540 140 * compare against this list before we can determine whether to
Chris@540 141 * notify about the change or not.
Chris@540 142 */
Chris@540 143 QHash<QString, QSet<QString> > m_dirContents;
Chris@540 144
Chris@538 145 QStringList m_ignoredPrefixes;
Chris@538 146 QStringList m_ignoredSuffixes;
Chris@538 147
Chris@538 148 /// Everything in this class is synchronised.
Chris@538 149 QMutex m_mutex;
Chris@538 150
Chris@538 151 QString m_workDirPath;
Chris@538 152 int m_lastToken;
Chris@538 153 size_t m_lastCounter;
Chris@584 154
Chris@584 155 #ifdef Q_OS_MAC
Chris@584 156 void *m_stream;
Chris@586 157 typedef QMap<QString, QDateTime> PathTimeMap;
Chris@586 158 PathTimeMap m_trackedFileUpdates;
Chris@586 159 bool manuallyCheckTrackedFiles();
Chris@584 160 #else
Chris@538 161 QFileSystemWatcher m_watcher;
Chris@584 162 #endif
Chris@538 163 };
Chris@538 164
Chris@538 165 #endif