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.

This commit is contained in:
David Sansome 2012-01-29 17:39:28 +00:00
parent b4e1cef2c2
commit facb366017
8 changed files with 42 additions and 26 deletions

View File

@ -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);

View File

@ -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:

View File

@ -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();

View File

@ -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());

View File

@ -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:

View File

@ -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<Directory> 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<Subdirectory> SubdirectoryList;
Q_DECLARE_METATYPE(SubdirectoryList);
Q_DECLARE_METATYPE(SubdirectoryList)
#endif // DIRECTORY_H

View File

@ -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<QString, DirData>::const_iterator it = subdir_mapping_.constFind(subdir);
QHash<QString, Directory>::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());

View File

@ -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<QString, QStringList>& 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<QString, DirData> subdir_mapping_;
QHash<QString, Directory> 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<int, DirData> watched_dirs_;
QMap<int, Directory> watched_dirs_;
QTimer* rescan_timer_;
QMap<int, QStringList> rescan_queue_; // dir id -> list of subdirs to be scanned
bool rescan_paused_;