| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 | 
							- /////////////////////////////////////////////////////////////////////////////
 
- // Name:        samples/fswatcher/fswatcher.cpp
 
- // Purpose:     wxFileSystemWatcher sample
 
- // Author:      Bartosz Bekier
 
- // Created:     2009-06-27
 
- // Copyright:   (c) Bartosz Bekier
 
- // Licence:     wxWindows licence
 
- /////////////////////////////////////////////////////////////////////////////
 
- #include "wx/wxprec.h"
 
- #ifdef __BORLANDC__
 
-     #pragma hdrstop
 
- #endif
 
- #ifndef WX_PRECOMP
 
-     #include "wx/wx.h"
 
- #endif
 
- #ifndef wxHAS_IMAGES_IN_RESOURCES
 
-     #include "../sample.xpm"
 
- #endif
 
- #include "wx/fswatcher.h"
 
- #include "wx/listctrl.h"
 
- #include "wx/cmdline.h"
 
- // Define a new frame type: this is going to be our main frame
 
- class MyFrame : public wxFrame
 
- {
 
- public:
 
-     MyFrame(const wxString& title);
 
-     virtual ~MyFrame();
 
-     // Add an entry of the specified type asking the user for the filename if
 
-     // the one passed to this function is empty.
 
-     void AddEntry(wxFSWPathType type, wxString filename = wxString());
 
-     bool CreateWatcherIfNecessary();
 
- private:
 
-     // file system watcher creation
 
-     void CreateWatcher();
 
-     // event handlers
 
-     void OnClear(wxCommandEvent& WXUNUSED(event)) { m_evtConsole->Clear(); }
 
-     void OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(true); }
 
-     void OnWatch(wxCommandEvent& event);
 
-     void OnFollowLinks(wxCommandEvent& event);
 
-     void OnAbout(wxCommandEvent& event);
 
-     void OnAdd(wxCommandEvent& event);
 
-     void OnAddTree(wxCommandEvent& event);
 
-     void OnRemove(wxCommandEvent& event);
 
-     void OnRemoveAll(wxCommandEvent& WXUNUSED(event));
 
-     void OnRemoveUpdateUI(wxUpdateUIEvent& event);
 
-     void OnRemoveAllUpdateUI(wxUpdateUIEvent& event);
 
-     void OnFileSystemEvent(wxFileSystemWatcherEvent& event);
 
-     void LogEvent(const wxFileSystemWatcherEvent& event);
 
-     wxTextCtrl *m_evtConsole;         // events console
 
-     wxListView *m_filesList;          // list of watched paths
 
-     wxFileSystemWatcher* m_watcher;   // file system watcher
 
-     bool m_followLinks;               // should symlinks be dereferenced
 
-     const static wxString LOG_FORMAT; // how to format events
 
- };
 
- const wxString MyFrame::LOG_FORMAT = " %-12s %-36s    %-36s";
 
- // Define a new application type, each program should derive a class from wxApp
 
- class MyApp : public wxApp
 
- {
 
- public:
 
-     // 'Main program' equivalent: the program execution "starts" here
 
-     virtual bool OnInit()
 
-     {
 
-         if ( !wxApp::OnInit() )
 
-             return false;
 
-         wxLog::AddTraceMask("EventSource");
 
-         wxLog::AddTraceMask(wxTRACE_FSWATCHER);
 
-         // create the main application window
 
-         m_frame = new MyFrame("File System Watcher wxWidgets App");
 
-         // If we returned false here, the application would exit immediately.
 
-         return true;
 
-     }
 
-     // create the file system watcher here, because it needs an active loop
 
-     virtual void OnEventLoopEnter(wxEventLoopBase* WXUNUSED(loop))
 
-     {
 
-         if ( m_frame->CreateWatcherIfNecessary() )
 
-         {
 
-             if ( !m_dirToWatch.empty() )
 
-                 m_frame->AddEntry(wxFSWPath_Dir, m_dirToWatch);
 
-         }
 
-     }
 
-     virtual void OnInitCmdLine(wxCmdLineParser& parser)
 
-     {
 
-         wxApp::OnInitCmdLine(parser);
 
-         parser.AddParam("directory to watch",
 
-                         wxCMD_LINE_VAL_STRING,
 
-                         wxCMD_LINE_PARAM_OPTIONAL);
 
-     }
 
-     virtual bool OnCmdLineParsed(wxCmdLineParser& parser)
 
-     {
 
-         if ( !wxApp::OnCmdLineParsed(parser) )
 
-             return false;
 
-         if ( parser.GetParamCount() )
 
-             m_dirToWatch = parser.GetParam();
 
-         return true;
 
-     }
 
- private:
 
-     MyFrame *m_frame;
 
-     // The directory to watch if specified on the command line.
 
-     wxString m_dirToWatch;
 
- };
 
- // Create a new application object: this macro will allow wxWidgets to create
 
- // the application object during program execution (it's better than using a
 
- // static object for many reasons) and also declares the accessor function
 
- // wxGetApp() which will return the reference of the right type (i.e. MyApp and
 
- // not wxApp)
 
- IMPLEMENT_APP(MyApp)
 
- // ============================================================================
 
- // implementation
 
- // ============================================================================
 
- // frame constructor
 
- MyFrame::MyFrame(const wxString& title)
 
-     : wxFrame(NULL, wxID_ANY, title),
 
-       m_watcher(NULL), m_followLinks(false)
 
- {
 
-     SetIcon(wxICON(sample));
 
-     // IDs for menu and buttons
 
-     enum
 
-     {
 
-         MENU_ID_QUIT = wxID_EXIT,
 
-         MENU_ID_CLEAR = wxID_CLEAR,
 
-         MENU_ID_WATCH = 101,
 
-         MENU_ID_DEREFERENCE,
 
-         BTN_ID_ADD = 200,
 
-         BTN_ID_ADD_TREE,
 
-         BTN_ID_REMOVE,
 
-         BTN_ID_REMOVE_ALL
 
-     };
 
-     // ================================================================
 
-     // menu
 
-     // create a menu bar
 
-     wxMenu *menuFile = new wxMenu;
 
-     menuFile->Append(MENU_ID_CLEAR, "&Clear log\tCtrl-L");
 
-     menuFile->AppendSeparator();
 
-     menuFile->Append(MENU_ID_QUIT, "E&xit\tAlt-X", "Quit this program");
 
-     // "Watch" menu
 
-     wxMenu *menuMon = new wxMenu;
 
-     wxMenuItem* it = menuMon->AppendCheckItem(MENU_ID_WATCH, "&Watch\tCtrl-W");
 
-     // started by default, because file system watcher is started by default
 
-     it->Check(true);
 
- #if defined(__UNIX__)
 
-     // Let the user decide whether to dereference symlinks. If he makes the
 
-     // wrong choice, asserts will occur if the symlink target is also watched
 
-     it = menuMon->AppendCheckItem(MENU_ID_DEREFERENCE,
 
-                                   "&Follow symlinks\tCtrl-F",
 
-                                   _("If checked, dereference symlinks")
 
-                                  );
 
-     it->Check(false);
 
-     Connect(MENU_ID_DEREFERENCE, wxEVT_MENU,
 
-             wxCommandEventHandler(MyFrame::OnFollowLinks));
 
- #endif // __UNIX__
 
-     // the "About" item should be in the help menu
 
-     wxMenu *menuHelp = new wxMenu;
 
-     menuHelp->Append(wxID_ABOUT, "&About\tF1", "Show about dialog");
 
-     // now append the freshly created menu to the menu bar...
 
-     wxMenuBar *menuBar = new wxMenuBar();
 
-     menuBar->Append(menuFile, "&File");
 
-     menuBar->Append(menuMon, "&Watch");
 
-     menuBar->Append(menuHelp, "&Help");
 
-     // ... and attach this menu bar to the frame
 
-     SetMenuBar(menuBar);
 
-     // ================================================================
 
-     // upper panel
 
-     // panel
 
-     wxPanel *panel = new wxPanel(this);
 
-     wxSizer *panelSizer = new wxGridSizer(2);
 
-     wxBoxSizer *leftSizer = new wxBoxSizer(wxVERTICAL);
 
-     // label
 
-     wxStaticText* label = new wxStaticText(panel, wxID_ANY, "Watched paths");
 
-     leftSizer->Add(label, wxSizerFlags().Center().Border(wxALL));
 
-     // list of files
 
-     m_filesList = new wxListView(panel, wxID_ANY, wxPoint(-1,-1),
 
-                                  wxSize(300,200), wxLC_LIST | wxLC_SINGLE_SEL);
 
-     leftSizer->Add(m_filesList, wxSizerFlags(1).Expand());
 
-     // buttons
 
-     wxButton* buttonAdd = new wxButton(panel, BTN_ID_ADD, "&Add");
 
-     wxButton* buttonAddTree = new wxButton(panel, BTN_ID_ADD_TREE, "Add &tree");
 
-     wxButton* buttonRemove = new wxButton(panel, BTN_ID_REMOVE, "&Remove");
 
-     wxButton* buttonRemoveAll = new wxButton(panel, BTN_ID_REMOVE_ALL, "Remove a&ll");
 
-     wxSizer *btnSizer = new wxGridSizer(2);
 
-     btnSizer->Add(buttonAdd, wxSizerFlags().Center().Border(wxALL));
 
-     btnSizer->Add(buttonAddTree, wxSizerFlags().Center().Border(wxALL));
 
-     btnSizer->Add(buttonRemove, wxSizerFlags().Center().Border(wxALL));
 
-     btnSizer->Add(buttonRemoveAll, wxSizerFlags().Center().Border(wxALL));
 
-     // and put it all together
 
-     leftSizer->Add(btnSizer, wxSizerFlags(0).Expand());
 
-     panelSizer->Add(leftSizer, wxSizerFlags(1).Expand());
 
-     panel->SetSizerAndFit(panelSizer);
 
-     // ================================================================
 
-     // lower panel
 
-     wxTextCtrl *headerText = new wxTextCtrl(this, wxID_ANY, "",
 
-                                             wxDefaultPosition, wxDefaultSize,
 
-                                             wxTE_READONLY);
 
-     wxString h = wxString::Format(LOG_FORMAT, "event", "path", "new path");
 
-     headerText->SetValue(h);
 
-     // event console
 
-     m_evtConsole = new wxTextCtrl(this, wxID_ANY, "",
 
-                                wxDefaultPosition, wxSize(200,200),
 
-                                wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL);
 
-     // set monospace font to have output in nice columns
 
-     wxFont font(9, wxFONTFAMILY_TELETYPE,
 
-                 wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
 
-     headerText->SetFont(font);
 
-     m_evtConsole->SetFont(font);
 
-     // ================================================================
 
-     // laying out whole frame
 
-     wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
 
-     sizer->Add(panel, wxSizerFlags(1).Expand());
 
-     sizer->Add(headerText, wxSizerFlags().Expand());
 
-     sizer->Add(m_evtConsole, wxSizerFlags(1).Expand());
 
-     SetSizerAndFit(sizer);
 
-     // set size and position on screen
 
-     SetSize(800, 600);
 
-     CentreOnScreen();
 
-     // ================================================================
 
-     // event handlers & show
 
-     // menu
 
-     Connect(MENU_ID_CLEAR, wxEVT_MENU,
 
-             wxCommandEventHandler(MyFrame::OnClear));
 
-     Connect(MENU_ID_QUIT, wxEVT_MENU,
 
-             wxCommandEventHandler(MyFrame::OnQuit));
 
-     Connect(MENU_ID_WATCH, wxEVT_MENU,
 
-             wxCommandEventHandler(MyFrame::OnWatch));
 
-     Connect(wxID_ABOUT, wxEVT_MENU,
 
-             wxCommandEventHandler(MyFrame::OnAbout));
 
-     // buttons
 
-     Connect(BTN_ID_ADD, wxEVT_BUTTON,
 
-             wxCommandEventHandler(MyFrame::OnAdd));
 
-     Connect(BTN_ID_ADD_TREE, wxEVT_BUTTON,
 
-             wxCommandEventHandler(MyFrame::OnAddTree));
 
-     Connect(BTN_ID_REMOVE, wxEVT_BUTTON,
 
-             wxCommandEventHandler(MyFrame::OnRemove));
 
-     Connect(BTN_ID_REMOVE, wxEVT_UPDATE_UI,
 
-             wxUpdateUIEventHandler(MyFrame::OnRemoveUpdateUI));
 
-     Connect(BTN_ID_REMOVE_ALL, wxEVT_BUTTON,
 
-             wxCommandEventHandler(MyFrame::OnRemoveAll));
 
-     Connect(BTN_ID_REMOVE_ALL, wxEVT_UPDATE_UI,
 
-             wxUpdateUIEventHandler(MyFrame::OnRemoveAllUpdateUI));
 
-     // and show itself (the frames, unlike simple controls, are not shown when
 
-     // created initially)
 
-     Show(true);
 
- }
 
- MyFrame::~MyFrame()
 
- {
 
-     delete m_watcher;
 
- }
 
- bool MyFrame::CreateWatcherIfNecessary()
 
- {
 
-     if (m_watcher)
 
-         return false;
 
-     CreateWatcher();
 
-     Connect(wxEVT_FSWATCHER,
 
-             wxFileSystemWatcherEventHandler(MyFrame::OnFileSystemEvent));
 
-     return true;
 
- }
 
- void MyFrame::CreateWatcher()
 
- {
 
-     wxCHECK_RET(!m_watcher, "Watcher already initialized");
 
-     m_watcher = new wxFileSystemWatcher();
 
-     m_watcher->SetOwner(this);
 
- }
 
- // ============================================================================
 
- // event handlers
 
- // ============================================================================
 
- void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxMessageBox("Demonstrates the usage of file system watcher, "
 
-                  "the wxWidgets monitoring system notifying you of "
 
-                  "changes done to your files.\n"
 
-                  "(c) 2009 Bartosz Bekier\n",
 
-                  "About wxWidgets File System Watcher Sample",
 
-                  wxOK | wxICON_INFORMATION, this);
 
- }
 
- void MyFrame::OnWatch(wxCommandEvent& event)
 
- {
 
-     wxLogDebug("%s start=%d", __WXFUNCTION__, event.IsChecked());
 
-     if (event.IsChecked())
 
-     {
 
-         wxCHECK_RET(!m_watcher, "Watcher already initialized");
 
-         CreateWatcher();
 
-     }
 
-     else
 
-     {
 
-         wxCHECK_RET(m_watcher, "Watcher not initialized");
 
-         m_filesList->DeleteAllItems();
 
-         wxDELETE(m_watcher);
 
-     }
 
- }
 
- void MyFrame::OnFollowLinks(wxCommandEvent& event)
 
- {
 
-     m_followLinks = event.IsChecked();
 
- }
 
- void MyFrame::OnAdd(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     AddEntry(wxFSWPath_Dir);
 
- }
 
- void MyFrame::OnAddTree(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     AddEntry(wxFSWPath_Tree);
 
- }
 
- void MyFrame::AddEntry(wxFSWPathType type, wxString filename)
 
- {
 
-     if ( filename.empty() )
 
-     {
 
-         // TODO account for adding the files as well
 
-         filename = wxDirSelector("Choose a folder to watch", "",
 
-                                  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
 
-         if ( filename.empty() )
 
-             return;
 
-     }
 
-     wxCHECK_RET(m_watcher, "Watcher not initialized");
 
-     wxLogDebug("Adding %s: '%s'",
 
-                filename,
 
-                type == wxFSWPath_Dir ? "directory" : "directory tree");
 
-     wxString prefix;
 
-     bool ok = false;
 
-     // This will tell wxFileSystemWatcher whether to dereference symlinks
 
-     wxFileName fn = wxFileName::DirName(filename);
 
-     if (!m_followLinks)
 
-     {
 
-         fn.DontFollowLink();
 
-     }
 
-     switch ( type )
 
-     {
 
-         case wxFSWPath_Dir:
 
-             ok = m_watcher->Add(fn);
 
-             prefix = "Dir:  ";
 
-             break;
 
-         case wxFSWPath_Tree:
 
-             ok = m_watcher->AddTree(fn);
 
-             prefix = "Tree: ";
 
-             break;
 
-         case wxFSWPath_File:
 
-         case wxFSWPath_None:
 
-             wxFAIL_MSG( "Unexpected path type." );
 
-     }
 
-     if (!ok)
 
-     {
 
-         wxLogError("Error adding '%s' to watched paths", filename);
 
-         return;
 
-     }
 
-     // Prepend 'prefix' to the filepath, partly for display
 
-     // but mostly so that OnRemove() can work out the correct way to remove it
 
-     m_filesList->InsertItem(m_filesList->GetItemCount(),
 
-                             prefix + wxFileName::DirName(filename).GetFullPath());
 
- }
 
- void MyFrame::OnRemove(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     wxCHECK_RET(m_watcher, "Watcher not initialized");
 
-     long idx = m_filesList->GetFirstSelected();
 
-     if (idx == -1)
 
-         return;
 
-     bool ret = false;
 
-     wxString path = m_filesList->GetItemText(idx).Mid(6);
 
-     // This will tell wxFileSystemWatcher whether to dereference symlinks
 
-     wxFileName fn = wxFileName::DirName(path);
 
-     if (!m_followLinks)
 
-     {
 
-         fn.DontFollowLink();
 
-     }
 
-     // TODO we know it is a dir, but it doesn't have to be
 
-     if (m_filesList->GetItemText(idx).StartsWith("Dir:  "))
 
-     {
 
-         ret = m_watcher->Remove(fn);
 
-     }
 
-     else if (m_filesList->GetItemText(idx).StartsWith("Tree: "))
 
-     {
 
-         ret = m_watcher->RemoveTree(fn);
 
-     }
 
-     else
 
-     {
 
-         wxFAIL_MSG("Unexpected item in wxListView.");
 
-     }
 
-     if (!ret)
 
-     {
 
-         wxLogError("Error removing '%s' from watched paths", path);
 
-     }
 
-     else
 
-     {
 
-         m_filesList->DeleteItem(idx);
 
-     }
 
- }
 
- void MyFrame::OnRemoveAll(wxCommandEvent& WXUNUSED(event))
 
- {
 
-     if ( !m_watcher->RemoveAll() )
 
-     {
 
-         wxLogError("Error removing all paths from watched paths");
 
-     }
 
-     m_filesList->DeleteAllItems();
 
- }
 
- void MyFrame::OnRemoveUpdateUI(wxUpdateUIEvent& event)
 
- {
 
-     event.Enable(m_filesList->GetFirstSelected() != wxNOT_FOUND);
 
- }
 
- void MyFrame::OnRemoveAllUpdateUI(wxUpdateUIEvent& event)
 
- {
 
-     event.Enable( m_filesList->GetItemCount() != 0 );
 
- }
 
- void MyFrame::OnFileSystemEvent(wxFileSystemWatcherEvent& event)
 
- {
 
-     // TODO remove when code is rock-solid
 
-     wxLogTrace(wxTRACE_FSWATCHER, "*** %s ***", event.ToString());
 
-     LogEvent(event);
 
-     int type = event.GetChangeType();
 
-     if ((type == wxFSW_EVENT_DELETE) || (type == wxFSW_EVENT_RENAME))
 
-     {
 
-         // If path is one of our watched dirs, we need to react to this
 
-         // otherwise there'll be asserts if later we try to remove it
 
-         wxString eventpath = event.GetPath().GetFullPath();
 
-         bool found(false);
 
-         for (size_t n = m_filesList->GetItemCount(); n > 0; --n)
 
-         {
 
-             wxString path, foo = m_filesList->GetItemText(n-1);
 
-             if ((!m_filesList->GetItemText(n-1).StartsWith("Dir:  ", &path)) &&
 
-                 (!m_filesList->GetItemText(n-1).StartsWith("Tree: ", &path)))
 
-             {
 
-                 wxFAIL_MSG("Unexpected item in wxListView.");
 
-             }
 
-             if (path == eventpath)
 
-             {
 
-                 if (type == wxFSW_EVENT_DELETE)
 
-                 {
 
-                     m_filesList->DeleteItem(n-1);
 
-                 }
 
-                 else
 
-                 {
 
-                     // At least in wxGTK, we'll never get here: renaming the top
 
-                     // watched dir gives IN_MOVE_SELF and no new-name info.
 
-                     // However I'll leave the code in case other platforms do
 
-                     wxString newname = event.GetNewPath().GetFullPath();
 
-                     if (newname.empty() ||
 
-                         newname == event.GetPath().GetFullPath())
 
-                     {
 
-                         // Just in case either of these are possible...
 
-                         wxLogTrace(wxTRACE_FSWATCHER,
 
-                                    "Invalid attempt to rename to %s", newname);
 
-                         return;
 
-                     }
 
-                     wxString prefix =
 
-                         m_filesList->GetItemText(n-1).StartsWith("Dir:  ") ?
 
-                                       "Dir:  " : "Tree: ";
 
-                     m_filesList->SetItemText(n-1, prefix + newname);
 
-                 }
 
-                 found = true;
 
-                 // Don't break: a filepath may have been added more than once
 
-             }
 
-         }
 
-         if (found)
 
-         {
 
-             wxString msg = wxString::Format(
 
-                            "Your watched path %s has been deleted or renamed\n",
 
-                            eventpath);
 
-             m_evtConsole->AppendText(msg);
 
-         }
 
-     }
 
- }
 
- static wxString GetFSWEventChangeTypeName(int changeType)
 
- {
 
-     switch (changeType)
 
-     {
 
-     case wxFSW_EVENT_CREATE:
 
-         return "CREATE";
 
-     case wxFSW_EVENT_DELETE:
 
-         return "DELETE";
 
-     case wxFSW_EVENT_RENAME:
 
-         return "RENAME";
 
-     case wxFSW_EVENT_MODIFY:
 
-         return "MODIFY";
 
-     case wxFSW_EVENT_ACCESS:
 
-         return "ACCESS";
 
-     case wxFSW_EVENT_ATTRIB:  // Currently this is wxGTK-only
 
-         return "ATTRIBUTE";
 
- #ifdef wxHAS_INOTIFY
 
-     case wxFSW_EVENT_UNMOUNT: // Currently this is wxGTK-only
 
-         return "UNMOUNT";
 
- #endif
 
-     case wxFSW_EVENT_WARNING:
 
-         return "WARNING";
 
-     case wxFSW_EVENT_ERROR:
 
-         return "ERROR";
 
-     }
 
-     return "INVALID_TYPE";
 
- }
 
- void MyFrame::LogEvent(const wxFileSystemWatcherEvent& event)
 
- {
 
-     wxString entry = wxString::Format(LOG_FORMAT + "\n",
 
-                             GetFSWEventChangeTypeName(event.GetChangeType()),
 
-                             event.GetPath().GetFullPath(),
 
-                             event.GetNewPath().GetFullPath());
 
-     m_evtConsole->AppendText(entry);
 
- }
 
 
  |