Change {DECLARE,IMPLEMENT}_*CLASS and {DECLARE,BEGIN,END}_EVENT_TABLE
occurrences to use the wx-prefixed version of the macros.
		
	
		
			
				
	
	
		
			584 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			584 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/////////////////////////////////////////////////////////////////////////////
 | 
						|
// 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() wxOVERRIDE
 | 
						|
    {
 | 
						|
        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)) wxOVERRIDE
 | 
						|
    {
 | 
						|
        if ( m_frame->CreateWatcherIfNecessary() )
 | 
						|
        {
 | 
						|
            if ( !m_dirToWatch.empty() )
 | 
						|
                m_frame->AddEntry(wxFSWPath_Dir, m_dirToWatch);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    virtual void OnInitCmdLine(wxCmdLineParser& parser) wxOVERRIDE
 | 
						|
    {
 | 
						|
        wxApp::OnInitCmdLine(parser);
 | 
						|
        parser.AddParam("directory to watch",
 | 
						|
                        wxCMD_LINE_VAL_STRING,
 | 
						|
                        wxCMD_LINE_PARAM_OPTIONAL);
 | 
						|
    }
 | 
						|
 | 
						|
    virtual bool OnCmdLineParsed(wxCmdLineParser& parser) wxOVERRIDE
 | 
						|
    {
 | 
						|
        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)
 | 
						|
wxIMPLEMENT_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);
 | 
						|
}
 |