Mercurial > hg > easyhg
diff src/fswatcher.cpp @ 540:fc2df97920e8 fswatcher
Introduce FsWatcher into main window (though it isn't fully rigged up yet)
author | Chris Cannam |
---|---|
date | Mon, 13 Feb 2012 17:29:06 +0000 |
parents | 3935a7e621ca |
children | 0a16db274f2c |
line wrap: on
line diff
--- a/src/fswatcher.cpp Fri Feb 10 21:49:27 2012 +0000 +++ b/src/fswatcher.cpp Mon Feb 13 17:29:06 2012 +0000 @@ -16,12 +16,15 @@ */ #include "fswatcher.h" +#include "debug.h" #include <QMutexLocker> #include <QDir> #include <deque> +#define DEBUG_FSWATCHER 1 + /* * Watching the filesystem is trickier than it seems at first glance. * @@ -36,9 +39,12 @@ * to test properties of the filesystem. So we need to know to ignore * those files; unfortunately, when watching a directory (which is how * we find out about the creation of new files) we are notified only - * that the directory has changed -- we aren't told what changed. So - * we need to rescan the directory merely to find out whether to - * ignore the change or not. + * that the directory has changed -- we aren't told what changed. + * + * This means that, when a directory changes, we need to rescan the + * directory to learn whether the set of files in it _excluding_ files + * matching our ignore patterns differs from the previous scan, and + * ignore the change if it doesn't. */ FsWatcher::FsWatcher() : @@ -63,6 +69,7 @@ m_watcher.removePaths(m_watcher.files()); m_workDirPath = path; addWorkDirectory(path); + debugPrint(); } void @@ -73,6 +80,7 @@ foreach (QString path, paths) { m_watcher.addPath(path); } + debugPrint(); } void @@ -94,6 +102,7 @@ pending.pop_front(); if (!alreadyWatched.contains(path)) { m_watcher.addPath(path); + m_dirContents[path] = scanDirectory(path); } QDir d(path); @@ -153,22 +162,80 @@ { { QMutexLocker locker(&m_mutex); + if (shouldIgnore(path)) return; - size_t counter = ++m_lastCounter; - m_changes[path] = counter; + + QSet<QString> files = scanDirectory(path); + if (files == m_dirContents[path]) { +#ifdef DEBUG_FSWATCHER + std::cerr << "FsWatcher: Directory " << path << " has changed, but not in a way that we are monitoring" << std::endl; +#endif + return; + } + else m_dirContents[path] = files; + + size_t counter = ++m_lastCounter; + m_changes[path] = counter; } + emit changed(); } void FsWatcher::fsFileChanged(QString path) { - QMutexLocker locker(&m_mutex); + { + QMutexLocker locker(&m_mutex); + + // We don't check whether the file matches an ignore pattern, + // because we are only notified for file changes if we are + // watching the file explicitly, i.e. the file is in the + // tracked file paths list. So we never want to ignore them + + size_t counter = ++m_lastCounter; + m_changes[path] = counter; + } + + emit changed(); } bool FsWatcher::shouldIgnore(QString path) { - + QFileInfo fi(path); + QString fn(fi.fileName()); + foreach (QString pfx, m_ignoredPrefixes) { + if (fn.startsWith(pfx)) return true; + } + foreach (QString sfx, m_ignoredSuffixes) { + if (fn.endsWith(sfx)) return true; + } + return false; } +QSet<QString> +FsWatcher::scanDirectory(QString path) +{ + QSet<QString> files; + QDir d(path); + if (d.exists()) { + d.setFilter(QDir::Files | QDir::NoDotAndDotDot | + QDir::Readable | QDir::NoSymLinks); + foreach (QString entry, d.entryList()) { + if (entry.startsWith('.')) continue; + if (shouldIgnore(entry)) continue; + files.insert(entry); + } + } + return files; +} + +void +FsWatcher::debugPrint() +{ +#ifdef DEBUG_FSWATCHER + std::cerr << "FsWatcher: Now watching " << m_watcher.directories().size() + << " directories and " << m_watcher.files().size() + << " files" << std::endl; +#endif +}