]>
Commit | Line | Data |
---|---|---|
6b8ef0b3 VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: samples/fswatcher/fswatcher.cpp | |
3 | // Purpose: wxFileSystemWatcher sample | |
4 | // Author: Bartosz Bekier | |
5 | // Created: 2009-06-27 | |
6b8ef0b3 VZ |
6 | // Copyright: (c) Bartosz Bekier |
7 | // Licence: wxWindows licence | |
8 | ///////////////////////////////////////////////////////////////////////////// | |
9 | ||
10 | #include "wx/wxprec.h" | |
11 | ||
12 | #ifdef __BORLANDC__ | |
13 | #pragma hdrstop | |
14 | #endif | |
15 | #ifndef WX_PRECOMP | |
16 | #include "wx/wx.h" | |
17 | #endif | |
18 | ||
e7092398 | 19 | #ifndef wxHAS_IMAGES_IN_RESOURCES |
6b8ef0b3 VZ |
20 | #include "../sample.xpm" |
21 | #endif | |
22 | ||
23 | #include "wx/fswatcher.h" | |
24 | #include "wx/listctrl.h" | |
5fc3e6d4 | 25 | #include "wx/cmdline.h" |
6b8ef0b3 VZ |
26 | |
27 | // Define a new frame type: this is going to be our main frame | |
28 | class MyFrame : public wxFrame | |
29 | { | |
30 | public: | |
31 | MyFrame(const wxString& title); | |
32 | virtual ~MyFrame(); | |
33 | ||
f8d37148 VZ |
34 | // Add an entry of the specified type asking the user for the filename if |
35 | // the one passed to this function is empty. | |
36 | void AddEntry(wxFSWPathType type, wxString filename = wxString()); | |
5fc3e6d4 VZ |
37 | |
38 | bool CreateWatcherIfNecessary(); | |
39 | ||
6b8ef0b3 VZ |
40 | private: |
41 | // file system watcher creation | |
6b8ef0b3 VZ |
42 | void CreateWatcher(); |
43 | ||
44 | // event handlers | |
45 | void OnClear(wxCommandEvent& WXUNUSED(event)) { m_evtConsole->Clear(); } | |
46 | void OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(true); } | |
47 | void OnWatch(wxCommandEvent& event); | |
0fccda2c | 48 | void OnFollowLinks(wxCommandEvent& event); |
6b8ef0b3 VZ |
49 | void OnAbout(wxCommandEvent& event); |
50 | ||
51 | void OnAdd(wxCommandEvent& event); | |
f8d37148 | 52 | void OnAddTree(wxCommandEvent& event); |
6b8ef0b3 | 53 | void OnRemove(wxCommandEvent& event); |
0fccda2c | 54 | void OnRemoveUpdateUI(wxUpdateUIEvent& event); |
6b8ef0b3 VZ |
55 | |
56 | void OnFileSystemEvent(wxFileSystemWatcherEvent& event); | |
57 | void LogEvent(const wxFileSystemWatcherEvent& event); | |
58 | ||
59 | wxTextCtrl *m_evtConsole; // events console | |
60 | wxListView *m_filesList; // list of watched paths | |
61 | wxFileSystemWatcher* m_watcher; // file system watcher | |
0fccda2c | 62 | bool m_followLinks; // should symlinks be dereferenced |
6b8ef0b3 | 63 | |
6b8ef0b3 VZ |
64 | const static wxString LOG_FORMAT; // how to format events |
65 | }; | |
66 | ||
67 | const wxString MyFrame::LOG_FORMAT = " %-12s %-36s %-36s"; | |
68 | ||
69 | // Define a new application type, each program should derive a class from wxApp | |
70 | class MyApp : public wxApp | |
71 | { | |
72 | public: | |
73 | // 'Main program' equivalent: the program execution "starts" here | |
74 | virtual bool OnInit() | |
75 | { | |
5fc3e6d4 VZ |
76 | if ( !wxApp::OnInit() ) |
77 | return false; | |
78 | ||
5cd99866 | 79 | wxLog::AddTraceMask("EventSource"); |
6b8ef0b3 VZ |
80 | wxLog::AddTraceMask(wxTRACE_FSWATCHER); |
81 | ||
82 | // create the main application window | |
83 | m_frame = new MyFrame("File System Watcher wxWidgets App"); | |
84 | ||
85 | // If we returned false here, the application would exit immediately. | |
86 | return true; | |
87 | } | |
88 | ||
89 | // create the file system watcher here, because it needs an active loop | |
90 | virtual void OnEventLoopEnter(wxEventLoopBase* WXUNUSED(loop)) | |
91 | { | |
5fc3e6d4 VZ |
92 | if ( m_frame->CreateWatcherIfNecessary() ) |
93 | { | |
94 | if ( !m_dirToWatch.empty() ) | |
f8d37148 | 95 | m_frame->AddEntry(wxFSWPath_Dir, m_dirToWatch); |
5fc3e6d4 VZ |
96 | } |
97 | } | |
98 | ||
99 | virtual void OnInitCmdLine(wxCmdLineParser& parser) | |
100 | { | |
101 | wxApp::OnInitCmdLine(parser); | |
102 | parser.AddParam("directory to watch", | |
103 | wxCMD_LINE_VAL_STRING, | |
104 | wxCMD_LINE_PARAM_OPTIONAL); | |
105 | } | |
106 | ||
107 | virtual bool OnCmdLineParsed(wxCmdLineParser& parser) | |
108 | { | |
109 | if ( !wxApp::OnCmdLineParsed(parser) ) | |
110 | return false; | |
111 | ||
112 | if ( parser.GetParamCount() ) | |
113 | m_dirToWatch = parser.GetParam(); | |
114 | ||
115 | return true; | |
6b8ef0b3 VZ |
116 | } |
117 | ||
118 | private: | |
119 | MyFrame *m_frame; | |
5fc3e6d4 VZ |
120 | |
121 | // The directory to watch if specified on the command line. | |
122 | wxString m_dirToWatch; | |
6b8ef0b3 VZ |
123 | }; |
124 | ||
125 | // Create a new application object: this macro will allow wxWidgets to create | |
126 | // the application object during program execution (it's better than using a | |
127 | // static object for many reasons) and also declares the accessor function | |
128 | // wxGetApp() which will return the reference of the right type (i.e. MyApp and | |
129 | // not wxApp) | |
130 | IMPLEMENT_APP(MyApp) | |
131 | ||
132 | ||
133 | // ============================================================================ | |
134 | // implementation | |
135 | // ============================================================================ | |
136 | ||
137 | // frame constructor | |
138 | MyFrame::MyFrame(const wxString& title) | |
139 | : wxFrame(NULL, wxID_ANY, title), | |
0fccda2c | 140 | m_watcher(NULL), m_followLinks(false) |
6b8ef0b3 VZ |
141 | { |
142 | SetIcon(wxICON(sample)); | |
143 | ||
144 | // IDs for menu and buttons | |
145 | enum | |
146 | { | |
147 | MENU_ID_QUIT = wxID_EXIT, | |
148 | MENU_ID_CLEAR = wxID_CLEAR, | |
149 | MENU_ID_WATCH = 101, | |
0fccda2c | 150 | MENU_ID_DEREFERENCE, |
6b8ef0b3 VZ |
151 | |
152 | BTN_ID_ADD = 200, | |
f8d37148 VZ |
153 | BTN_ID_ADD_TREE, |
154 | BTN_ID_REMOVE | |
6b8ef0b3 VZ |
155 | }; |
156 | ||
157 | // ================================================================ | |
158 | // menu | |
159 | ||
160 | // create a menu bar | |
161 | wxMenu *menuFile = new wxMenu; | |
162 | menuFile->Append(MENU_ID_CLEAR, "&Clear log\tCtrl-L"); | |
163 | menuFile->AppendSeparator(); | |
164 | menuFile->Append(MENU_ID_QUIT, "E&xit\tAlt-X", "Quit this program"); | |
165 | ||
166 | // "Watch" menu | |
167 | wxMenu *menuMon = new wxMenu; | |
168 | wxMenuItem* it = menuMon->AppendCheckItem(MENU_ID_WATCH, "&Watch\tCtrl-W"); | |
169 | // started by default, because file system watcher is started by default | |
170 | it->Check(true); | |
171 | ||
0fccda2c VZ |
172 | #if defined(__UNIX__) |
173 | // Let the user decide whether to dereference symlinks. If he makes the | |
174 | // wrong choice, asserts will occur if the symlink target is also watched | |
175 | it = menuMon->AppendCheckItem(MENU_ID_DEREFERENCE, | |
176 | "&Follow symlinks\tCtrl-F", | |
177 | _("If checked, dereference symlinks") | |
178 | ); | |
179 | it->Check(false); | |
ce7fe42e | 180 | Connect(MENU_ID_DEREFERENCE, wxEVT_MENU, |
0fccda2c VZ |
181 | wxCommandEventHandler(MyFrame::OnFollowLinks)); |
182 | #endif // __UNIX__ | |
183 | ||
6b8ef0b3 VZ |
184 | // the "About" item should be in the help menu |
185 | wxMenu *menuHelp = new wxMenu; | |
2d143b66 | 186 | menuHelp->Append(wxID_ABOUT, "&About\tF1", "Show about dialog"); |
6b8ef0b3 VZ |
187 | |
188 | // now append the freshly created menu to the menu bar... | |
189 | wxMenuBar *menuBar = new wxMenuBar(); | |
190 | menuBar->Append(menuFile, "&File"); | |
191 | menuBar->Append(menuMon, "&Watch"); | |
192 | menuBar->Append(menuHelp, "&Help"); | |
193 | ||
194 | // ... and attach this menu bar to the frame | |
195 | SetMenuBar(menuBar); | |
196 | ||
197 | // ================================================================ | |
198 | // upper panel | |
199 | ||
200 | // panel | |
201 | wxPanel *panel = new wxPanel(this); | |
202 | wxSizer *panelSizer = new wxGridSizer(2); | |
203 | wxBoxSizer *leftSizer = new wxBoxSizer(wxVERTICAL); | |
204 | ||
205 | // label | |
206 | wxStaticText* label = new wxStaticText(panel, wxID_ANY, "Watched paths"); | |
207 | leftSizer->Add(label, wxSizerFlags().Center().Border(wxALL)); | |
208 | ||
209 | // list of files | |
210 | m_filesList = new wxListView(panel, wxID_ANY, wxPoint(-1,-1), | |
211 | wxSize(300,200), wxLC_LIST | wxLC_SINGLE_SEL); | |
212 | leftSizer->Add(m_filesList, wxSizerFlags(1).Expand()); | |
213 | ||
214 | // buttons | |
215 | wxButton* buttonAdd = new wxButton(panel, BTN_ID_ADD, "&Add"); | |
f8d37148 | 216 | wxButton* buttonAddTree = new wxButton(panel, BTN_ID_ADD_TREE, "Add &tree"); |
6b8ef0b3 VZ |
217 | wxButton* buttonRemove = new wxButton(panel, BTN_ID_REMOVE, "&Remove"); |
218 | wxSizer *btnSizer = new wxGridSizer(2); | |
219 | btnSizer->Add(buttonAdd, wxSizerFlags().Center().Border(wxALL)); | |
f8d37148 | 220 | btnSizer->Add(buttonAddTree, wxSizerFlags().Center().Border(wxALL)); |
6b8ef0b3 VZ |
221 | btnSizer->Add(buttonRemove, wxSizerFlags().Center().Border(wxALL)); |
222 | ||
223 | // and put it all together | |
224 | leftSizer->Add(btnSizer, wxSizerFlags(0).Expand()); | |
225 | panelSizer->Add(leftSizer, wxSizerFlags(1).Expand()); | |
226 | panel->SetSizerAndFit(panelSizer); | |
227 | ||
228 | // ================================================================ | |
229 | // lower panel | |
230 | ||
231 | wxTextCtrl *headerText = new wxTextCtrl(this, wxID_ANY, "", | |
232 | wxDefaultPosition, wxDefaultSize, | |
233 | wxTE_READONLY); | |
234 | wxString h = wxString::Format(LOG_FORMAT, "event", "path", "new path"); | |
235 | headerText->SetValue(h); | |
236 | ||
237 | // event console | |
238 | m_evtConsole = new wxTextCtrl(this, wxID_ANY, "", | |
239 | wxDefaultPosition, wxSize(200,200), | |
240 | wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL); | |
241 | ||
242 | // set monospace font to have output in nice columns | |
243 | wxFont font(9, wxFONTFAMILY_TELETYPE, | |
244 | wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); | |
245 | headerText->SetFont(font); | |
246 | m_evtConsole->SetFont(font); | |
247 | ||
248 | // ================================================================ | |
249 | // laying out whole frame | |
250 | ||
251 | wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); | |
252 | sizer->Add(panel, wxSizerFlags(1).Expand()); | |
253 | sizer->Add(headerText, wxSizerFlags().Expand()); | |
254 | sizer->Add(m_evtConsole, wxSizerFlags(1).Expand()); | |
255 | SetSizerAndFit(sizer); | |
256 | ||
257 | // set size and position on screen | |
258 | SetSize(800, 600); | |
259 | CentreOnScreen(); | |
260 | ||
261 | // ================================================================ | |
262 | // event handlers & show | |
263 | ||
264 | // menu | |
ce7fe42e | 265 | Connect(MENU_ID_CLEAR, wxEVT_MENU, |
6b8ef0b3 | 266 | wxCommandEventHandler(MyFrame::OnClear)); |
ce7fe42e | 267 | Connect(MENU_ID_QUIT, wxEVT_MENU, |
6b8ef0b3 | 268 | wxCommandEventHandler(MyFrame::OnQuit)); |
ce7fe42e | 269 | Connect(MENU_ID_WATCH, wxEVT_MENU, |
6b8ef0b3 | 270 | wxCommandEventHandler(MyFrame::OnWatch)); |
ce7fe42e | 271 | Connect(wxID_ABOUT, wxEVT_MENU, |
6b8ef0b3 VZ |
272 | wxCommandEventHandler(MyFrame::OnAbout)); |
273 | ||
274 | // buttons | |
ce7fe42e | 275 | Connect(BTN_ID_ADD, wxEVT_BUTTON, |
6b8ef0b3 | 276 | wxCommandEventHandler(MyFrame::OnAdd)); |
ce7fe42e | 277 | Connect(BTN_ID_ADD_TREE, wxEVT_BUTTON, |
f8d37148 | 278 | wxCommandEventHandler(MyFrame::OnAddTree)); |
ce7fe42e | 279 | Connect(BTN_ID_REMOVE, wxEVT_BUTTON, |
6b8ef0b3 | 280 | wxCommandEventHandler(MyFrame::OnRemove)); |
0fccda2c VZ |
281 | Connect(BTN_ID_REMOVE, wxEVT_UPDATE_UI, |
282 | wxUpdateUIEventHandler(MyFrame::OnRemoveUpdateUI)); | |
6b8ef0b3 VZ |
283 | |
284 | // and show itself (the frames, unlike simple controls, are not shown when | |
285 | // created initially) | |
286 | Show(true); | |
287 | } | |
288 | ||
289 | MyFrame::~MyFrame() | |
290 | { | |
291 | delete m_watcher; | |
292 | } | |
293 | ||
5fc3e6d4 | 294 | bool MyFrame::CreateWatcherIfNecessary() |
6b8ef0b3 VZ |
295 | { |
296 | if (m_watcher) | |
5fc3e6d4 | 297 | return false; |
6b8ef0b3 VZ |
298 | |
299 | CreateWatcher(); | |
300 | Connect(wxEVT_FSWATCHER, | |
301 | wxFileSystemWatcherEventHandler(MyFrame::OnFileSystemEvent)); | |
5fc3e6d4 VZ |
302 | |
303 | return true; | |
6b8ef0b3 VZ |
304 | } |
305 | ||
306 | void MyFrame::CreateWatcher() | |
307 | { | |
308 | wxCHECK_RET(!m_watcher, "Watcher already initialized"); | |
309 | m_watcher = new wxFileSystemWatcher(); | |
310 | m_watcher->SetOwner(this); | |
311 | } | |
312 | ||
313 | // ============================================================================ | |
314 | // event handlers | |
315 | // ============================================================================ | |
316 | ||
317 | void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) | |
318 | { | |
319 | wxMessageBox("Demonstrates the usage of file system watcher, " | |
320 | "the wxWidgets monitoring system notifying you of " | |
321 | "changes done to your files.\n" | |
322 | "(c) 2009 Bartosz Bekier\n", | |
323 | "About wxWidgets File System Watcher Sample", | |
324 | wxOK | wxICON_INFORMATION, this); | |
325 | } | |
326 | ||
327 | void MyFrame::OnWatch(wxCommandEvent& event) | |
328 | { | |
329 | wxLogDebug("%s start=%d", __WXFUNCTION__, event.IsChecked()); | |
330 | ||
331 | if (event.IsChecked()) | |
332 | { | |
333 | wxCHECK_RET(!m_watcher, "Watcher already initialized"); | |
334 | CreateWatcher(); | |
335 | } | |
336 | else | |
337 | { | |
338 | wxCHECK_RET(m_watcher, "Watcher not initialized"); | |
339 | m_filesList->DeleteAllItems(); | |
5276b0a5 | 340 | wxDELETE(m_watcher); |
6b8ef0b3 VZ |
341 | } |
342 | } | |
343 | ||
0fccda2c VZ |
344 | void MyFrame::OnFollowLinks(wxCommandEvent& event) |
345 | { | |
346 | m_followLinks = event.IsChecked(); | |
347 | } | |
348 | ||
6b8ef0b3 VZ |
349 | void MyFrame::OnAdd(wxCommandEvent& WXUNUSED(event)) |
350 | { | |
f8d37148 VZ |
351 | AddEntry(wxFSWPath_Dir); |
352 | } | |
6b8ef0b3 | 353 | |
f8d37148 VZ |
354 | void MyFrame::OnAddTree(wxCommandEvent& WXUNUSED(event)) |
355 | { | |
356 | AddEntry(wxFSWPath_Tree); | |
5fc3e6d4 VZ |
357 | } |
358 | ||
f8d37148 | 359 | void MyFrame::AddEntry(wxFSWPathType type, wxString filename) |
5fc3e6d4 | 360 | { |
f8d37148 VZ |
361 | if ( filename.empty() ) |
362 | { | |
363 | // TODO account for adding the files as well | |
364 | filename = wxDirSelector("Choose a folder to watch", "", | |
365 | wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); | |
366 | if ( filename.empty() ) | |
367 | return; | |
368 | } | |
369 | ||
370 | wxCHECK_RET(m_watcher, "Watcher not initialized"); | |
371 | ||
372 | wxLogDebug("Adding %s: '%s'", | |
373 | filename, | |
374 | type == wxFSWPath_Dir ? "directory" : "directory tree"); | |
6b8ef0b3 | 375 | |
ce2532fb | 376 | wxString prefix; |
f8d37148 | 377 | bool ok = false; |
0fccda2c VZ |
378 | |
379 | // This will tell wxFileSystemWatcher whether to dereference symlinks | |
380 | wxFileName fn = wxFileName::DirName(filename); | |
381 | if (!m_followLinks) | |
382 | { | |
383 | fn.DontFollowLink(); | |
384 | } | |
385 | ||
f8d37148 | 386 | switch ( type ) |
6b8ef0b3 | 387 | { |
f8d37148 | 388 | case wxFSWPath_Dir: |
0fccda2c | 389 | ok = m_watcher->Add(fn); |
ce2532fb | 390 | prefix = "Dir: "; |
f8d37148 VZ |
391 | break; |
392 | ||
393 | case wxFSWPath_Tree: | |
0fccda2c | 394 | ok = m_watcher->AddTree(fn); |
ce2532fb | 395 | prefix = "Tree: "; |
f8d37148 VZ |
396 | break; |
397 | ||
398 | case wxFSWPath_File: | |
399 | case wxFSWPath_None: | |
400 | wxFAIL_MSG( "Unexpected path type." ); | |
6b8ef0b3 | 401 | } |
f8d37148 VZ |
402 | |
403 | if (!ok) | |
6b8ef0b3 | 404 | { |
f8d37148 VZ |
405 | wxLogError("Error adding '%s' to watched paths", filename); |
406 | return; | |
6b8ef0b3 | 407 | } |
f8d37148 | 408 | |
ce2532fb VZ |
409 | // Prepend 'prefix' to the filepath, partly for display |
410 | // but mostly so that OnRemove() can work out the correct way to remove it | |
411 | m_filesList->InsertItem(m_filesList->GetItemCount(), | |
412 | prefix + wxFileName::DirName(filename).GetFullPath()); | |
6b8ef0b3 VZ |
413 | } |
414 | ||
415 | void MyFrame::OnRemove(wxCommandEvent& WXUNUSED(event)) | |
416 | { | |
417 | wxCHECK_RET(m_watcher, "Watcher not initialized"); | |
418 | long idx = m_filesList->GetFirstSelected(); | |
419 | if (idx == -1) | |
420 | return; | |
421 | ||
b62afb79 | 422 | bool ret = false; |
0fccda2c VZ |
423 | wxString path = m_filesList->GetItemText(idx).Mid(6); |
424 | ||
425 | // This will tell wxFileSystemWatcher whether to dereference symlinks | |
426 | wxFileName fn = wxFileName::DirName(path); | |
427 | if (!m_followLinks) | |
428 | { | |
429 | fn.DontFollowLink(); | |
430 | } | |
431 | ||
6b8ef0b3 | 432 | // TODO we know it is a dir, but it doesn't have to be |
0fccda2c | 433 | if (m_filesList->GetItemText(idx).StartsWith("Dir: ")) |
ce2532fb | 434 | { |
0fccda2c | 435 | ret = m_watcher->Remove(fn); |
ce2532fb | 436 | } |
0fccda2c | 437 | else if (m_filesList->GetItemText(idx).StartsWith("Tree: ")) |
ce2532fb | 438 | { |
0fccda2c | 439 | ret = m_watcher->RemoveTree(fn); |
ce2532fb VZ |
440 | } |
441 | else | |
442 | { | |
443 | wxFAIL_MSG("Unexpected item in wxListView."); | |
444 | } | |
445 | ||
446 | if (!ret) | |
6b8ef0b3 VZ |
447 | { |
448 | wxLogError("Error removing '%s' from watched paths", path); | |
449 | } | |
450 | else | |
451 | { | |
452 | m_filesList->DeleteItem(idx); | |
453 | } | |
454 | } | |
455 | ||
0fccda2c VZ |
456 | void MyFrame::OnRemoveUpdateUI(wxUpdateUIEvent& event) |
457 | { | |
458 | event.Enable(m_filesList->GetFirstSelected() != wxNOT_FOUND); | |
459 | } | |
460 | ||
6b8ef0b3 VZ |
461 | void MyFrame::OnFileSystemEvent(wxFileSystemWatcherEvent& event) |
462 | { | |
463 | // TODO remove when code is rock-solid | |
6969b18c | 464 | wxLogTrace(wxTRACE_FSWATCHER, "*** %s ***", event.ToString()); |
6b8ef0b3 | 465 | LogEvent(event); |
0b3ef556 VZ |
466 | |
467 | int type = event.GetChangeType(); | |
468 | if ((type == wxFSW_EVENT_DELETE) || (type == wxFSW_EVENT_RENAME)) | |
469 | { | |
470 | // If path is one of our watched dirs, we need to react to this | |
471 | // otherwise there'll be asserts if later we try to remove it | |
472 | wxString eventpath = event.GetPath().GetFullPath(); | |
473 | bool found(false); | |
474 | for (size_t n = m_filesList->GetItemCount(); n > 0; --n) | |
475 | { | |
476 | wxString path, foo = m_filesList->GetItemText(n-1); | |
477 | if ((!m_filesList->GetItemText(n-1).StartsWith("Dir: ", &path)) && | |
478 | (!m_filesList->GetItemText(n-1).StartsWith("Tree: ", &path))) | |
479 | { | |
480 | wxFAIL_MSG("Unexpected item in wxListView."); | |
481 | } | |
482 | if (path == eventpath) | |
483 | { | |
484 | if (type == wxFSW_EVENT_DELETE) | |
485 | { | |
486 | m_filesList->DeleteItem(n-1); | |
487 | } | |
488 | else | |
489 | { | |
490 | // At least in wxGTK, we'll never get here: renaming the top | |
491 | // watched dir gives IN_MOVE_SELF and no new-name info. | |
492 | // However I'll leave the code in case other platforms do | |
493 | wxString newname = event.GetNewPath().GetFullPath(); | |
494 | if (newname.empty() || | |
495 | newname == event.GetPath().GetFullPath()) | |
496 | { | |
497 | // Just in case either of these are possible... | |
498 | wxLogTrace(wxTRACE_FSWATCHER, | |
499 | "Invalid attempt to rename to %s", newname); | |
500 | return; | |
501 | } | |
502 | wxString prefix = | |
503 | m_filesList->GetItemText(n-1).StartsWith("Dir: ") ? | |
504 | "Dir: " : "Tree: "; | |
505 | m_filesList->SetItemText(n-1, prefix + newname); | |
506 | } | |
507 | found = true; | |
508 | // Don't break: a filepath may have been added more than once | |
509 | } | |
510 | } | |
511 | ||
512 | if (found) | |
513 | { | |
514 | wxString msg = wxString::Format( | |
515 | "Your watched path %s has been deleted or renamed\n", | |
516 | eventpath); | |
517 | m_evtConsole->AppendText(msg); | |
518 | } | |
519 | } | |
6b8ef0b3 VZ |
520 | } |
521 | ||
522 | ||
523 | static wxString GetFSWEventChangeTypeName(int changeType) | |
524 | { | |
525 | switch (changeType) | |
526 | { | |
527 | case wxFSW_EVENT_CREATE: | |
528 | return "CREATE"; | |
529 | case wxFSW_EVENT_DELETE: | |
530 | return "DELETE"; | |
531 | case wxFSW_EVENT_RENAME: | |
532 | return "RENAME"; | |
533 | case wxFSW_EVENT_MODIFY: | |
534 | return "MODIFY"; | |
535 | case wxFSW_EVENT_ACCESS: | |
536 | return "ACCESS"; | |
092e08a8 | 537 | case wxFSW_EVENT_ATTRIB: // Currently this is wxGTK-only |
f31f9900 | 538 | return "ATTRIBUTE"; |
092e08a8 VZ |
539 | #ifdef wxHAS_INOTIFY |
540 | case wxFSW_EVENT_UNMOUNT: // Currently this is wxGTK-only | |
541 | return "UNMOUNT"; | |
542 | #endif | |
1ec4e9c2 VZ |
543 | case wxFSW_EVENT_WARNING: |
544 | return "WARNING"; | |
545 | case wxFSW_EVENT_ERROR: | |
546 | return "ERROR"; | |
6b8ef0b3 VZ |
547 | } |
548 | ||
549 | return "INVALID_TYPE"; | |
550 | } | |
551 | ||
552 | void MyFrame::LogEvent(const wxFileSystemWatcherEvent& event) | |
553 | { | |
554 | wxString entry = wxString::Format(LOG_FORMAT + "\n", | |
555 | GetFSWEventChangeTypeName(event.GetChangeType()), | |
556 | event.GetPath().GetFullPath(), | |
557 | event.GetNewPath().GetFullPath()); | |
558 | m_evtConsole->AppendText(entry); | |
559 | } |