]> git.saurik.com Git - wxWidgets.git/blame - src/common/fswatchercmn.cpp
Generate text events in generic wxSpinCtrl itself.
[wxWidgets.git] / src / common / fswatchercmn.cpp
CommitLineData
6b8ef0b3 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/common/fswatchercmn.cpp
6b8ef0b3
VZ
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{
f8d37148
VZ
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());
6b8ef0b3 95 return false;
f8d37148 96 }
6b8ef0b3 97
3a2b3701 98 return AddAny(path, events, type);
f8d37148
VZ
99}
100
101bool
3a2b3701
VZ
102wxFileSystemWatcherBase::AddAny(const wxFileName& path,
103 int events,
104 wxFSWPathType type)
f8d37148 105{
6b8ef0b3
VZ
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
f8d37148 114 wxFSWatchInfo watch(canonical, events, type);
6b8ef0b3
VZ
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
b5b1a8e4 162 virtual wxDirTraverseResult OnFile(const wxString& filename)
6b8ef0b3 163 {
b5b1a8e4
VZ
164 wxLogTrace(wxTRACE_FSWATCHER,
165 "--- AddTree adding file '%s' ---", filename);
3a2b3701 166 m_watcher->AddAny(wxFileName::FileName(filename),
b5b1a8e4 167 m_events, wxFSWPath_File);
6b8ef0b3
VZ
168 return wxDIR_CONTINUE;
169 }
170
171 virtual wxDirTraverseResult OnDir(const wxString& dirname)
172 {
b5b1a8e4
VZ
173 wxLogTrace(wxTRACE_FSWATCHER,
174 "--- AddTree adding directory '%s' ---", dirname);
6b8ef0b3 175 // we add as much as possible and ignore errors
3a2b3701 176 m_watcher->AddAny(wxFileName::DirName(dirname),
b5b1a8e4 177 m_events, wxFSWPath_Dir);
6b8ef0b3
VZ
178 return wxDIR_CONTINUE;
179 }
180
181 private:
182 wxFileSystemWatcherBase* m_watcher;
183 int m_events;
184 wxString m_filter;
185 };
186
187 wxDir dir(path.GetFullPath());
188 AddTraverser traverser(this, events);
189 dir.Traverse(traverser, filter);
190
b5b1a8e4
VZ
191 // Add the path itself explicitly as Traverse() doesn't return it.
192 Add(path.GetPathWithSep(), events);
193
6b8ef0b3
VZ
194 return true;
195}
196
197bool wxFileSystemWatcherBase::RemoveTree(const wxFileName& path)
198{
199 if (!path.DirExists())
200 return false;
201
202 // OPT could be optimised if we stored information about relationships
203 // between paths
204 class RemoveTraverser : public wxDirTraverser
205 {
206 public:
207 RemoveTraverser(wxFileSystemWatcherBase* watcher) :
208 m_watcher(watcher)
209 {
210 }
211
212 virtual wxDirTraverseResult OnFile(const wxString& filename)
213 {
214 m_watcher->Remove(wxFileName(filename));
215 return wxDIR_CONTINUE;
216 }
217
218 virtual wxDirTraverseResult OnDir(const wxString& dirname)
219 {
b5b1a8e4 220 m_watcher->Remove(wxFileName::DirName(dirname));
6b8ef0b3
VZ
221 return wxDIR_CONTINUE;
222 }
223
224 private:
225 wxFileSystemWatcherBase* m_watcher;
226 };
227
228 wxDir dir(path.GetFullPath());
229 RemoveTraverser traverser(this);
230 dir.Traverse(traverser);
231
b5b1a8e4
VZ
232 // As in AddTree() above, handle the path itself explicitly.
233 Remove(path);
234
6b8ef0b3
VZ
235 return true;
236}
237
238bool wxFileSystemWatcherBase::RemoveAll()
239{
240 m_service->RemoveAll();
241 m_watches.clear();
242 return true;
243}
244
245int wxFileSystemWatcherBase::GetWatchedPathsCount() const
246{
247 return m_watches.size();
248}
249
250int wxFileSystemWatcherBase::GetWatchedPaths(wxArrayString* paths) const
251{
252 wxCHECK_MSG( paths != NULL, -1, "Null array passed to retrieve paths");
253
254 wxFSWatchInfoMap::const_iterator it = m_watches.begin();
255 for ( ; it != m_watches.end(); ++it)
256 {
257 paths->push_back(it->first);
258 }
259
260 return m_watches.size();
261}
262
263#endif // wxUSE_FSWATCHER