]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/fswatchercmn.cpp
Initial work on virtual file system support for the WebKitGTK+ backend. It now suppor...
[wxWidgets.git] / src / common / fswatchercmn.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/fswatchercmn.cpp
3// Purpose: wxMswFileSystemWatcher
4// Author: Bartosz Bekier
5// Created: 2009-05-26
6// RCS-ID: $Id$
7// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#if wxUSE_FSWATCHER
19
20#include "wx/fswatcher.h"
21#include "wx/private/fswatcher.h"
22
23// ============================================================================
24// helpers
25// ============================================================================
26
27wxDEFINE_EVENT(wxEVT_FSWATCHER, wxFileSystemWatcherEvent);
28
29static wxString GetFSWEventChangeTypeName(int type)
30{
31 switch (type)
32 {
33 case wxFSW_EVENT_CREATE:
34 return "CREATE";
35 case wxFSW_EVENT_DELETE:
36 return "DELETE";
37 case wxFSW_EVENT_RENAME:
38 return "RENAME";
39 case wxFSW_EVENT_MODIFY:
40 return "MODIFY";
41 case wxFSW_EVENT_ACCESS:
42 return "ACCESS";
43 }
44
45 // should never be reached!
46 wxFAIL_MSG("Unknown change type");
47 return "INVALID_TYPE";
48}
49
50
51// ============================================================================
52// wxFileSystemWatcherEvent implementation
53// ============================================================================
54
55wxString wxFileSystemWatcherEvent::ToString() const
56{
57 return wxString::Format("FSW_EVT type=%d (%s) path='%s'", m_changeType,
58 GetFSWEventChangeTypeName(m_changeType), GetPath().GetFullPath());
59}
60
61
62// ============================================================================
63// wxFileSystemWatcherEvent implementation
64// ============================================================================
65
66wxFileSystemWatcherBase::wxFileSystemWatcherBase() :
67 m_service(0), m_owner(this)
68{
69}
70
71wxFileSystemWatcherBase::~wxFileSystemWatcherBase()
72{
73 RemoveAll();
74 if (m_service)
75 {
76 delete m_service;
77 }
78}
79
80bool wxFileSystemWatcherBase::Add(const wxFileName& path, int events)
81{
82 wxFSWPathType type = wxFSWPath_None;
83 if ( path.FileExists() )
84 {
85 type = wxFSWPath_File;
86 }
87 else if ( path.DirExists() )
88 {
89 type = wxFSWPath_Dir;
90 }
91 else
92 {
93 wxLogError(_("Can't monitor non-existent path \"%s\" for changes."),
94 path.GetFullPath());
95 return false;
96 }
97
98 return DoAdd(path, events, type);
99}
100
101bool
102wxFileSystemWatcherBase::DoAdd(const wxFileName& path,
103 int events,
104 wxFSWPathType type)
105{
106 wxString canonical = GetCanonicalPath(path);
107 if (canonical.IsEmpty())
108 return false;
109
110 wxCHECK_MSG(m_watches.find(canonical) == m_watches.end(), false,
111 wxString::Format("Path '%s' is already watched", canonical));
112
113 // adding a path in a platform specific way
114 wxFSWatchInfo watch(canonical, events, type);
115 if ( !m_service->Add(watch) )
116 return false;
117
118 // on success, add path to our 'watch-list'
119 wxFSWatchInfoMap::value_type val(canonical, watch);
120 return m_watches.insert(val).second;
121}
122
123bool wxFileSystemWatcherBase::Remove(const wxFileName& path)
124{
125 // args validation & consistency checks
126 wxString canonical = GetCanonicalPath(path);
127 if (canonical.IsEmpty())
128 return false;
129
130 wxFSWatchInfoMap::iterator it = m_watches.find(canonical);
131 wxCHECK_MSG(it != m_watches.end(), false,
132 wxString::Format("Path '%s' is not watched", canonical));
133
134 // remove from watch-list
135 wxFSWatchInfo watch = it->second;
136 m_watches.erase(it);
137
138 // remove in a platform specific way
139 return m_service->Remove(watch);
140}
141
142bool wxFileSystemWatcherBase::AddTree(const wxFileName& path, int events,
143 const wxString& filter)
144{
145 if (!path.DirExists())
146 return false;
147
148 // OPT could be optimised if we stored information about relationships
149 // between paths
150 class AddTraverser : public wxDirTraverser
151 {
152 public:
153 AddTraverser(wxFileSystemWatcherBase* watcher, int events) :
154 m_watcher(watcher), m_events(events)
155 {
156 }
157
158 // CHECK we choose which files to delegate to Add(), maybe we should pass
159 // all of them to Add() and let it choose? this is useful when adding a
160 // file to a dir that is already watched, then not only should we know
161 // about that, but Add() should also behave well then
162 virtual wxDirTraverseResult OnFile(const wxString& WXUNUSED(filename))
163 {
164 return wxDIR_CONTINUE;
165 }
166
167 virtual wxDirTraverseResult OnDir(const wxString& dirname)
168 {
169 wxLogTrace(wxTRACE_FSWATCHER, "--- AddTree adding '%s' ---",
170 dirname);
171 // we add as much as possible and ignore errors
172 m_watcher->Add(wxFileName(dirname), m_events);
173 return wxDIR_CONTINUE;
174 }
175
176 private:
177 wxFileSystemWatcherBase* m_watcher;
178 int m_events;
179 wxString m_filter;
180 };
181
182 wxDir dir(path.GetFullPath());
183 AddTraverser traverser(this, events);
184 dir.Traverse(traverser, filter);
185
186 return true;
187}
188
189bool wxFileSystemWatcherBase::RemoveTree(const wxFileName& path)
190{
191 if (!path.DirExists())
192 return false;
193
194 // OPT could be optimised if we stored information about relationships
195 // between paths
196 class RemoveTraverser : public wxDirTraverser
197 {
198 public:
199 RemoveTraverser(wxFileSystemWatcherBase* watcher) :
200 m_watcher(watcher)
201 {
202 }
203
204 virtual wxDirTraverseResult OnFile(const wxString& filename)
205 {
206 m_watcher->Remove(wxFileName(filename));
207 return wxDIR_CONTINUE;
208 }
209
210 virtual wxDirTraverseResult OnDir(const wxString& dirname)
211 {
212 m_watcher->RemoveTree(wxFileName(dirname));
213 return wxDIR_CONTINUE;
214 }
215
216 private:
217 wxFileSystemWatcherBase* m_watcher;
218 };
219
220 wxDir dir(path.GetFullPath());
221 RemoveTraverser traverser(this);
222 dir.Traverse(traverser);
223
224 return true;
225}
226
227bool wxFileSystemWatcherBase::RemoveAll()
228{
229 m_service->RemoveAll();
230 m_watches.clear();
231 return true;
232}
233
234int wxFileSystemWatcherBase::GetWatchedPathsCount() const
235{
236 return m_watches.size();
237}
238
239int wxFileSystemWatcherBase::GetWatchedPaths(wxArrayString* paths) const
240{
241 wxCHECK_MSG( paths != NULL, -1, "Null array passed to retrieve paths");
242
243 wxFSWatchInfoMap::const_iterator it = m_watches.begin();
244 for ( ; it != m_watches.end(); ++it)
245 {
246 paths->push_back(it->first);
247 }
248
249 return m_watches.size();
250}
251
252#endif // wxUSE_FSWATCHER