From facb3660177f554e06b4b53ec15ef3b69b4eaeaa Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 29 Jan 2012 17:39:28 +0000 Subject: [PATCH] Remove subdirectory watches after a directory is removed from the library. Otherwise subdirectories that changed after the directory was removed would be re-scanned and re-added. --- src/core/filesystemwatcherinterface.h | 1 + src/core/macfslistener.h | 1 + src/core/macfslistener.mm | 6 +++++ src/core/qtfslistener.cpp | 4 ++++ src/core/qtfslistener.h | 1 + src/library/directory.h | 12 ++++++---- src/library/librarywatcher.cpp | 32 +++++++++++++++------------ src/library/librarywatcher.h | 11 +++------ 8 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/core/filesystemwatcherinterface.h b/src/core/filesystemwatcherinterface.h index 3c260d784..f451f2644 100644 --- a/src/core/filesystemwatcherinterface.h +++ b/src/core/filesystemwatcherinterface.h @@ -26,6 +26,7 @@ class FileSystemWatcherInterface : public QObject { FileSystemWatcherInterface(QObject* parent = 0); virtual void Init() {} virtual void AddPath(const QString& path) = 0; + virtual void RemovePath(const QString& path) = 0; virtual void Clear() = 0; static FileSystemWatcherInterface* Create(QObject* parent = 0); diff --git a/src/core/macfslistener.h b/src/core/macfslistener.h index 7d98ebae1..155cd1bae 100644 --- a/src/core/macfslistener.h +++ b/src/core/macfslistener.h @@ -32,6 +32,7 @@ class MacFSListener : public FileSystemWatcherInterface { explicit MacFSListener(QObject* parent = 0); void Init(); void AddPath(const QString& path); + void RemovePath(const QString& path); void Clear(); signals: diff --git a/src/core/macfslistener.mm b/src/core/macfslistener.mm index 1fa315fb5..d33a4f30a 100644 --- a/src/core/macfslistener.mm +++ b/src/core/macfslistener.mm @@ -59,6 +59,12 @@ void MacFSListener::AddPath(const QString& path) { UpdateStream(); } +void MacFSListener::RemovePath(const QString& path) { + Q_ASSERT(run_loop_); + paths_.remove(path); + UpdateStream(); +} + void MacFSListener::Clear() { paths_.clear(); UpdateStream(); diff --git a/src/core/qtfslistener.cpp b/src/core/qtfslistener.cpp index af1356bda..9a94a0c32 100644 --- a/src/core/qtfslistener.cpp +++ b/src/core/qtfslistener.cpp @@ -30,6 +30,10 @@ void QtFSListener::AddPath(const QString& path) { watcher_.addPath(path); } +void QtFSListener::RemovePath(const QString& path) { + watcher_.removePath(path); +} + void QtFSListener::Clear() { watcher_.removePaths(watcher_.directories()); watcher_.removePaths(watcher_.files()); diff --git a/src/core/qtfslistener.h b/src/core/qtfslistener.h index fcb8d9a69..dd84ca5c6 100644 --- a/src/core/qtfslistener.h +++ b/src/core/qtfslistener.h @@ -27,6 +27,7 @@ class QtFSListener : public FileSystemWatcherInterface { public: QtFSListener(QObject* parent); virtual void AddPath(const QString& path); + virtual void RemovePath(const QString& path); virtual void Clear(); private: diff --git a/src/library/directory.h b/src/library/directory.h index d49b828be..9af610d36 100644 --- a/src/library/directory.h +++ b/src/library/directory.h @@ -27,13 +27,17 @@ class QSqlQuery; struct Directory { Directory() : id(-1) {} + bool operator ==(const Directory& other) const { + return path == other.path && id == other.id; + } + QString path; int id; }; -Q_DECLARE_METATYPE(Directory); +Q_DECLARE_METATYPE(Directory) typedef QList DirectoryList; -Q_DECLARE_METATYPE(DirectoryList); +Q_DECLARE_METATYPE(DirectoryList) struct Subdirectory { @@ -43,9 +47,9 @@ struct Subdirectory { QString path; uint mtime; }; -Q_DECLARE_METATYPE(Subdirectory); +Q_DECLARE_METATYPE(Subdirectory) typedef QList SubdirectoryList; -Q_DECLARE_METATYPE(SubdirectoryList); +Q_DECLARE_METATYPE(SubdirectoryList) #endif // DIRECTORY_H diff --git a/src/library/librarywatcher.cpp b/src/library/librarywatcher.cpp index e104daca8..83d7507ab 100644 --- a/src/library/librarywatcher.cpp +++ b/src/library/librarywatcher.cpp @@ -184,9 +184,7 @@ SubdirectoryList LibraryWatcher::ScanTransaction::GetAllSubdirs() { } void LibraryWatcher::AddDirectory(const Directory& dir, const SubdirectoryList& subdirs) { - DirData data; - data.dir = dir; - watched_dirs_[dir.id] = data; + watched_dirs_[dir.id] = dir; if (subdirs.isEmpty()) { // This is a new directory that we've never seen before. @@ -208,7 +206,7 @@ void LibraryWatcher::AddDirectory(const Directory& dir, const SubdirectoryList& ScanSubdirectory(subdir.path, subdir, &transaction); if (monitor_) - AddWatch(data, subdir.path); + AddWatch(dir, subdir.path); } } @@ -223,8 +221,8 @@ void LibraryWatcher::ScanSubdirectory( // Do not scan symlinked dirs that are already in collection if (path_info.isSymLink()) { QString real_path = path_info.symLinkTarget(); - foreach (const DirData& dir_data, watched_dirs_) { - if (real_path.startsWith(dir_data.dir.path)) { + foreach (const Directory& dir, watched_dirs_) { + if (real_path.startsWith(dir.path)) { t->AddToProgress(1); return; } @@ -550,7 +548,7 @@ uint LibraryWatcher::GetMtimeForCue(const QString& cue_path) { : 0; } -void LibraryWatcher::AddWatch(const DirData& dir, const QString& path) { +void LibraryWatcher::AddWatch(const Directory& dir, const QString& path) { if (!QFile::exists(path)) return; @@ -563,6 +561,12 @@ void LibraryWatcher::AddWatch(const DirData& dir, const QString& path) { void LibraryWatcher::RemoveDirectory(const Directory& dir) { rescan_queue_.remove(dir.id); watched_dirs_.remove(dir.id); + + // Stop watching the directory's subdirectories + foreach (const QString& subdir_path, subdir_mapping_.keys(dir)) { + fs_watcher_->RemovePath(subdir_path); + subdir_mapping_.remove(subdir_path); + } } bool LibraryWatcher::FindSongByPath(const SongList& list, const QString& path, Song* out) { @@ -578,11 +582,11 @@ bool LibraryWatcher::FindSongByPath(const SongList& list, const QString& path, S void LibraryWatcher::DirectoryChanged(const QString &subdir) { // Find what dir it was in - QHash::const_iterator it = subdir_mapping_.constFind(subdir); + QHash::const_iterator it = subdir_mapping_.constFind(subdir); if (it == subdir_mapping_.constEnd()) { return; } - Directory dir = it->dir; + Directory dir = *it; qLog(Debug) << "Subdir" << subdir << "changed under directory" << dir.path << "id" << dir.id; @@ -702,10 +706,10 @@ void LibraryWatcher::ReloadSettings() { fs_watcher_->Clear(); } else if (monitor_ && !was_monitoring_before) { // Add all directories to all QFileSystemWatchers again - foreach (const DirData& data, watched_dirs_.values()) { - SubdirectoryList subdirs = backend_->SubdirsInDirectory(data.dir.id); + foreach (const Directory& dir, watched_dirs_.values()) { + SubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id); foreach (const Subdirectory& subdir, subdirs) { - AddWatch(data, subdir.path); + AddWatch(dir, subdir.path); } } } @@ -739,8 +743,8 @@ void LibraryWatcher::FullScanNow() { } void LibraryWatcher::PerformScan(bool incremental, bool ignore_mtimes) { - foreach (const DirData& data, watched_dirs_.values()) { - ScanTransaction transaction(this, data.dir.id, + foreach (const Directory& dir, watched_dirs_.values()) { + ScanTransaction transaction(this, dir.id, incremental, ignore_mtimes); SubdirectoryList subdirs(transaction.GetAllSubdirs()); transaction.AddToProgressMax(subdirs.count()); diff --git a/src/library/librarywatcher.h b/src/library/librarywatcher.h index 5fe943ef1..09b205742 100644 --- a/src/library/librarywatcher.h +++ b/src/library/librarywatcher.h @@ -140,18 +140,13 @@ class LibraryWatcher : public QObject { ScanTransaction* t, bool force_noincremental = false); private: - // One of these gets stored for each Directory we're watching - struct DirData { - Directory dir; - }; - static bool FindSongByPath(const SongList& list, const QString& path, Song* out); inline static QString NoExtensionPart( const QString &fileName ); inline static QString ExtensionPart( const QString &fileName ); inline static QString DirectoryPart( const QString &fileName ); QString PickBestImage(const QStringList& images); QString ImageForSong(const QString& path, QMap& album_art); - void AddWatch(const DirData& dir, const QString& path); + void AddWatch(const Directory& dir, const QString& path); uint GetMtimeForCue(const QString& cue_path); void PerformScan(bool incremental, bool ignore_mtimes); @@ -181,7 +176,7 @@ class LibraryWatcher : public QObject { QString device_name_; FileSystemWatcherInterface* fs_watcher_; - QHash subdir_mapping_; + QHash subdir_mapping_; /* A list of words use to try to identify the (likely) best image * found in an directory to use as cover artwork. @@ -194,7 +189,7 @@ class LibraryWatcher : public QObject { bool scan_on_startup_; bool monitor_; - QMap watched_dirs_; + QMap watched_dirs_; QTimer* rescan_timer_; QMap rescan_queue_; // dir id -> list of subdirs to be scanned bool rescan_paused_;