bool wxFileSystemWatcherBase::AddTree(const wxFileName& path, int events, const wxString& filespec) { if (!path.DirExists()) return false; // OPT could be optimised if we stored information about relationships // between paths class AddTraverser : public wxDirTraverser { public: AddTraverser(wxFileSystemWatcherBase* watcher, int events, const wxString& filespec) : m_watcher(watcher), m_events(events), m_filespec(filespec) { } virtual wxDirTraverseResult OnFile(const wxString& WXUNUSED(filename)) { // There is no need to watch individual files as we watch the // parent directory which will notify us about any changes in them. return wxDIR_CONTINUE; } virtual wxDirTraverseResult OnDir(const wxString& dirname) { if ( m_watcher->AddAny(wxFileName::DirName(dirname), m_events, wxFSWPath_Tree, m_filespec) ) { wxLogTrace(wxTRACE_FSWATCHER, "--- AddTree adding directory '%s' ---", dirname); } return wxDIR_CONTINUE; } private: wxFileSystemWatcherBase* m_watcher; int m_events; wxString m_filespec; }; wxDir dir(path.GetFullPath()); // Prevent asserts or infinite loops in trees containing symlinks int flags = wxDIR_DIRS; if ( !path.ShouldFollowLink() ) { flags |= wxDIR_NO_FOLLOW; } AddTraverser traverser(this, events, filespec); dir.Traverse(traverser, filespec, flags); // Add the path itself explicitly as Traverse() doesn't return it. AddAny(path.GetPathWithSep(), events, wxFSWPath_Tree, filespec); return true; }
bool wxFileSystemWatcherBase::RemoveTree(const wxFileName& path) { if (!path.DirExists()) return false; // OPT could be optimised if we stored information about relationships // between paths class RemoveTraverser : public wxDirTraverser { public: RemoveTraverser(wxFileSystemWatcherBase* watcher, const wxString& filespec) : m_watcher(watcher), m_filespec(filespec) { } virtual wxDirTraverseResult OnFile(const wxString& WXUNUSED(filename)) { // We never watch the individual files when watching the tree, so // nothing to do here. return wxDIR_CONTINUE; } virtual wxDirTraverseResult OnDir(const wxString& dirname) { m_watcher->Remove(wxFileName::DirName(dirname)); return wxDIR_CONTINUE; } private: wxFileSystemWatcherBase* m_watcher; wxString m_filespec; }; // If AddTree() used a filespec, we must use the same one wxString canonical = GetCanonicalPath(path); wxFSWatchInfoMap::iterator it = m_watches.find(canonical); wxCHECK_MSG( it != m_watches.end(), false, wxString::Format("Path '%s' is not watched", canonical) ); wxFSWatchInfo watch = it->second; const wxString filespec = watch.GetFilespec(); #if defined(__WINDOWS__) // When there's no filespec, the wxMSW AddTree() would have set a watch // on only the passed 'path'. We must therefore remove only this if (filespec.empty()) { return Remove(path); } // Otherwise fall through to the generic implementation #endif // __WINDOWS__ wxDir dir(path.GetFullPath()); // AddTree() might have used the wxDIR_NO_FOLLOW to prevent asserts or // infinite loops in trees containing symlinks. We need to do the same // or we'll try to remove unwatched items. Let's hope the caller used // the same ShouldFollowLink() setting as in AddTree()... int flags = wxDIR_DIRS; if ( !path.ShouldFollowLink() ) { flags |= wxDIR_NO_FOLLOW; } RemoveTraverser traverser(this, filespec); dir.Traverse(traverser, filespec, flags); // As in AddTree() above, handle the path itself explicitly. Remove(path); return true; }