Commit 6f72aaec authored by jean-pierre charras's avatar jean-pierre charras

Kicad: files watcher: fix Linux specific issues

parent 45b01a5c
...@@ -31,12 +31,6 @@ ...@@ -31,12 +31,6 @@
#include <fctsys.h> #include <fctsys.h>
#include <appl_wxstruct.h> #include <appl_wxstruct.h>
#ifdef USE_SPLASH_IMAGE
#define SPLASH_IMAGE logo_kicad.png
#include "wx/splash.h"
#include "wx/mediactrl.h"
#endif
#include <kicad.h> #include <kicad.h>
#include <tree_project_frame.h> #include <tree_project_frame.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
...@@ -45,12 +39,6 @@ ...@@ -45,12 +39,6 @@
const wxString g_KicadPrjFilenameExtension( wxT( ".pro" ) ); const wxString g_KicadPrjFilenameExtension( wxT( ".pro" ) );
/* Import functions */
char* GetFileName( char* FullPathName );
void ShowLogo( char* FonteFileName );
/* Local functions */
/************************************/ /************************************/
/* Called to initialize the program */ /* Called to initialize the program */
/************************************/ /************************************/
...@@ -113,7 +101,8 @@ bool EDA_APP::OnInit() ...@@ -113,7 +101,8 @@ bool EDA_APP::OnInit()
wxFileName namelessProject( wxGetCwd(), NAMELESS_PROJECT, ProjectFileExtension ); wxFileName namelessProject( wxGetCwd(), NAMELESS_PROJECT, ProjectFileExtension );
frame = new KICAD_MANAGER_FRAME( NULL, wxT( "KiCad" ), frame = new KICAD_MANAGER_FRAME( NULL, wxT( "KiCad" ),
wxPoint( 30, 20 ), wxSize( 600, 400 ) ); wxDefaultPosition, wxDefaultSize );
SetTopWindow( frame );
if( argc > 1 ) if( argc > 1 )
{ {
...@@ -141,38 +130,6 @@ bool EDA_APP::OnInit() ...@@ -141,38 +130,6 @@ bool EDA_APP::OnInit()
frame->OnLoadProject( cmd ); frame->OnLoadProject( cmd );
} }
wxString title = GetTitle() + wxT( " " ) + GetBuildVersion() +
wxT( " " ) + frame->m_ProjectFileName.GetFullPath();
if( !namelessProject.IsDirWritable() )
title += _( " [Read Only]" );
frame->SetTitle( title );
frame->ReCreateMenuBar();
frame->RecreateBaseHToolbar();
frame->m_LeftWin->ReCreateTreePrj();
SetTopWindow( frame );
/* Splash screen logo */
#ifdef USE_SPLASH_IMAGE
wxBitmap bmp;
wxString binDir = GetTraits()->GetStandardPaths().GetExecutablePath() +
wxFileName::GetPathSeparator();
if( bmp.LoadFile( binDir + _T( "logokicad.png" ), wxBITMAP_TYPE_PNG ) )
{
wxSplashScreen* splash = new wxSplashScreen( splash_screen,
wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT,
3000,
frame,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
wxSIMPLE_BORDER | wxSTAY_ON_TOP );
}
#endif /* USE_SPLASH_IMAGE */
frame->Show( true ); frame->Show( true );
frame->Raise(); frame->Raise();
......
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
#include <wxstruct.h> #include <wxstruct.h>
#include <appl_wxstruct.h> #include <appl_wxstruct.h>
// With a recent wxWidget, we can use the wxFileSystemWatcherEvent
// to monitor files add/remove/rename in tree project
#if wxCHECK_VERSION( 2, 9, 4 )
#define KICAD_USE_FILES_WATCHER
#endif
extern const wxString g_KicadPrjFilenameExtension; extern const wxString g_KicadPrjFilenameExtension;
class RIGHT_KM_FRAME; class RIGHT_KM_FRAME;
...@@ -77,7 +83,8 @@ enum id_kicad_frm { ...@@ -77,7 +83,8 @@ enum id_kicad_frm {
ID_SELECT_PREFERED_PDF_BROWSER, ID_SELECT_PREFERED_PDF_BROWSER,
ID_SELECT_DEFAULT_PDF_BROWSER, ID_SELECT_DEFAULT_PDF_BROWSER,
ID_SAVE_AND_ZIP_FILES, ID_SAVE_AND_ZIP_FILES,
ID_READ_ZIP_ARCHIVE ID_READ_ZIP_ARCHIVE,
ID_INIT_WATCHED_PATHS
}; };
...@@ -175,6 +182,15 @@ public: KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title, ...@@ -175,6 +182,15 @@ public: KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title,
*/ */
void SaveSettings(); void SaveSettings();
#ifdef KICAD_USE_FILES_WATCHER
void FileWatcherReset();
/**
* Called by sending a event with id = ID_INIT_WATCHED_PATHS
* rebuild the list of wahtched paths
*/
void OnChangeWatchedPaths(wxCommandEvent& aEvent );
#endif
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
......
...@@ -89,6 +89,7 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, ...@@ -89,6 +89,7 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent,
PrintMsg( line ); PrintMsg( line );
RecreateBaseHToolbar(); RecreateBaseHToolbar();
ReCreateMenuBar();
m_auimgr.SetManagedWindow( this ); m_auimgr.SetManagedWindow( this );
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <appl_wxstruct.h> #include <appl_wxstruct.h>
#include <kicad.h> #include <kicad.h>
#include <menus_helpers.h> #include <menus_helpers.h>
#include <tree_project_frame.h>
/* Menubar and toolbar event table */ /* Menubar and toolbar event table */
BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME ) BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
...@@ -67,9 +68,13 @@ BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME ) ...@@ -67,9 +68,13 @@ BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
/* Range menu events */ /* Range menu events */
EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::SetLanguage ) EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::SetLanguage )
EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, KICAD_MANAGER_FRAME::OnFileHistory ) EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, KICAD_MANAGER_FRAME::OnFileHistory )
// Special functions
#ifdef KICAD_USE_FILES_WATCHER
EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths )
#endif
/* Button events */ /* Button events */
EVT_BUTTON( ID_TO_PCB, KICAD_MANAGER_FRAME::OnRunPcbNew ) EVT_BUTTON( ID_TO_PCB, KICAD_MANAGER_FRAME::OnRunPcbNew )
EVT_BUTTON( ID_TO_CVPCB, KICAD_MANAGER_FRAME::OnRunCvpcb ) EVT_BUTTON( ID_TO_CVPCB, KICAD_MANAGER_FRAME::OnRunCvpcb )
......
...@@ -222,10 +222,14 @@ void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event ) ...@@ -222,10 +222,14 @@ void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event )
SetTitle( title ); SetTitle( title );
UpdateFileHistory( m_ProjectFileName.GetFullPath() ); UpdateFileHistory( m_ProjectFileName.GetFullPath() );
#if wxCHECK_VERSION( 2, 9, 2 )
m_LeftWin->FileWatcherReset();
#endif
m_LeftWin->ReCreateTreePrj(); m_LeftWin->ReCreateTreePrj();
#ifdef KICAD_USE_FILES_WATCHER
// Rebuild the list of watched paths.
// however this is possible only when the main loop event handler is running,
// so we use it to rub the rebuild function.
wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
wxPostEvent( this, cmd);
#endif
PrintMsg( _( "Working dir: " ) + m_ProjectFileName.GetPath() + PrintMsg( _( "Working dir: " ) + m_ProjectFileName.GetPath() +
_( "\nProject: " ) + m_ProjectFileName.GetFullName() + _( "\nProject: " ) + m_ProjectFileName.GetFullName() +
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <appl_wxstruct.h> #include <appl_wxstruct.h>
#include <macros.h> #include <macros.h>
#include <kicad.h>
#include <tree_project_frame.h> #include <tree_project_frame.h>
#include <class_treeprojectfiles.h> #include <class_treeprojectfiles.h>
#include <class_treeproject_item.h> #include <class_treeproject_item.h>
...@@ -137,9 +136,8 @@ TREE_PROJECT_FRAME::TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ) : ...@@ -137,9 +136,8 @@ TREE_PROJECT_FRAME::TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ) :
m_TreeProject = NULL; m_TreeProject = NULL;
wxMenuItem* item; wxMenuItem* item;
m_PopupMenu = NULL; m_PopupMenu = NULL;
#if wxCHECK_VERSION( 2, 9, 2 ) #ifdef KICAD_USE_FILES_WATCHER
m_watcher = new wxFileSystemWatcher(); m_watcher = NULL;
m_watcher->SetOwner( this );
Connect( wxEVT_FSWATCHER, Connect( wxEVT_FSWATCHER,
wxFileSystemWatcherEventHandler( TREE_PROJECT_FRAME::OnFileSystemEvent ) ); wxFileSystemWatcherEventHandler( TREE_PROJECT_FRAME::OnFileSystemEvent ) );
#endif #endif
...@@ -235,7 +233,7 @@ TREE_PROJECT_FRAME::~TREE_PROJECT_FRAME() ...@@ -235,7 +233,7 @@ TREE_PROJECT_FRAME::~TREE_PROJECT_FRAME()
if( m_PopupMenu ) if( m_PopupMenu )
delete m_PopupMenu; delete m_PopupMenu;
#if wxCHECK_VERSION( 2, 9, 2 ) #ifdef KICAD_USE_FILES_WATCHER
delete m_watcher; delete m_watcher;
#endif #endif
} }
...@@ -935,6 +933,7 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) ...@@ -935,6 +933,7 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event )
wxTreeItemIdValue cookie; wxTreeItemIdValue cookie;
wxTreeItemId kid = m_TreeProject->GetFirstChild( itemId, cookie ); wxTreeItemId kid = m_TreeProject->GetFirstChild( itemId, cookie );
bool subdir_populated = false;
for( ; kid.IsOk(); kid = m_TreeProject->GetNextChild( itemId, cookie ) ) for( ; kid.IsOk(); kid = m_TreeProject->GetNextChild( itemId, cookie ) )
{ {
TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); TREEPROJECT_ITEM* itemData = GetItemIdData( kid );
...@@ -959,10 +958,20 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) ...@@ -959,10 +958,20 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event )
} }
itemData->m_WasPopulated = true; // set state to populated itemData->m_WasPopulated = true; // set state to populated
subdir_populated = true;
/* Sort filenames by alphabetic order */ /* Sort filenames by alphabetic order */
m_TreeProject->SortChildren( kid ); m_TreeProject->SortChildren( kid );
} }
if( subdir_populated )
{
#ifdef KICAD_USE_FILES_WATCHER
#ifndef __WINDOWS__
m_TreeProject->FileWatcherReset();
#endif
#endif
}
} }
...@@ -1032,20 +1041,16 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir ) ...@@ -1032,20 +1041,16 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); TREEPROJECT_ITEM* itemData = GetItemIdData( kid );
if( itemData ) if( itemData && ( itemData->GetType() == TREE_DIRECTORY ) )
{ {
if( itemData->GetType() != TREE_DIRECTORY )
continue;
if( itemData->m_FileName == aSubDir ) // Found! if( itemData->m_FileName == aSubDir ) // Found!
{ {
root_id = kid; root_id = kid;
break; break;
} }
// if kid is a subdir, push in list to explore it later // kid is a subdir, push in list to explore it later
if( itemData->GetType() == TREE_DIRECTORY && if( itemData->m_WasPopulated )
itemData->m_WasPopulated )
subdirs_id.push( kid ); subdirs_id.push( kid );
} }
kid = m_TreeProject->GetNextChild( root_id, cookie ); kid = m_TreeProject->GetNextChild( root_id, cookie );
...@@ -1054,10 +1059,10 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir ) ...@@ -1054,10 +1059,10 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
return root_id; return root_id;
} }
#if wxCHECK_VERSION( 2, 9, 2 ) #ifdef KICAD_USE_FILES_WATCHER
/* called when a file or directory is modified/created/deleted /* called when a file or directory is modified/created/deleted
* The tree project should be rebuilt when a file or directory * The tree project is modified when a file or directory
* is created or deleted * is created/deleted/renamed to reflect the file change
*/ */
void TREE_PROJECT_FRAME::OnFileSystemEvent( wxFileSystemWatcherEvent& event ) void TREE_PROJECT_FRAME::OnFileSystemEvent( wxFileSystemWatcherEvent& event )
{ {
...@@ -1102,28 +1107,23 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir ) ...@@ -1102,28 +1107,23 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
{ {
TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); TREEPROJECT_ITEM* itemData = GetItemIdData( kid );
if( itemData ) if( itemData && ( itemData->m_FileName == fn ) )
{ {
if( itemData->m_FileName == fn ) if( event.GetChangeType() == wxFSW_EVENT_DELETE )
m_TreeProject->Delete( kid );
else
{ {
if( event.GetChangeType() == wxFSW_EVENT_DELETE ) wxFileName newpath = event.GetNewPath();
{ wxString newfn = newpath.GetFullPath();
m_TreeProject->Delete( kid ); // Change item label and item data
} // Extension could be modified and be not an usually selected file type
else // However, here we do not filter files.
{ // This is simple, and I am not sure filtering renamed files here is better,
wxFileName newpath = event.GetNewPath(); // because they could disappear, like deleted files
wxString newfn = newpath.GetFullPath(); itemData->SetFileName( newpath.GetFullPath() );
// Change item label and item data m_TreeProject->SetItemText( kid, newpath.GetFullName() );
// Extension could be modified and be not an usually selected file type
// However, here we do not filter files.
// This is simple, and I am not sure filtering renamed files here is better,
// becuse they could disappear, like deleted files
itemData->SetFileName( newpath.GetFullPath() );
m_TreeProject->SetItemText( kid, newpath.GetFullName() );
}
return;
} }
return;
} }
kid = m_TreeProject->GetNextChild( root_id, cookie ); kid = m_TreeProject->GetNextChild( root_id, cookie );
...@@ -1134,6 +1134,11 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir ) ...@@ -1134,6 +1134,11 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
m_TreeProject->SortChildren( root_id ); m_TreeProject->SortChildren( root_id );
} }
/* Reinit the watched paths
* Should be called after opening a new project to
* rebuild the list of watched paths.
* Should be called after the main loop event handler is started
*/
void TREE_PROJECT_FRAME::FileWatcherReset() void TREE_PROJECT_FRAME::FileWatcherReset()
{ {
// Prepare file watcher: // Prepare file watcher:
...@@ -1142,15 +1147,73 @@ void TREE_PROJECT_FRAME::FileWatcherReset() ...@@ -1142,15 +1147,73 @@ void TREE_PROJECT_FRAME::FileWatcherReset()
m_watcher->SetOwner( this ); m_watcher->SetOwner( this );
// Add directories which should be monitored. // Add directories which should be monitored.
// under windows, we add the curr dir and subdirs // under windows, we add the curr dir and all subdirs
// under unix, we add only the curr dir // under unix, we add only the curr dir and the populated subdirs
// see http://docs.wxwidgets.org/trunk/classwx_file_system_watcher.htm // see http://docs.wxwidgets.org/trunk/classwx_file_system_watcher.htm
// under unix, the file watcher needs more work to be efficient // under unix, the file watcher needs more work to be efficient
// moreover, under wxWidgets 2.9.4, AddTree does not work properly.
wxFileName watched_path = wxFileName::DirName( wxGetCwd() );
#ifdef __WINDOWS__ #ifdef __WINDOWS__
m_watcher->AddTree( wxFileName::DirName( wxT( "./" ) ) ); m_watcher->AddTree( watched_path );
#else #else
m_watcher->Add( wxFileName::DirName( wxT( "./" ) ) ); m_watcher->Add( watched_path );
// Add subdirs
wxTreeItemIdValue cookie;
wxTreeItemId root_id = m_root;
std::stack < wxTreeItemId > subdirs_id;
wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie );
while( 1 )
{
if( ! kid.IsOk() )
{
if( subdirs_id.empty() ) // all items were explored
break;
else
{
root_id = subdirs_id.top();
subdirs_id.pop();
kid = m_TreeProject->GetFirstChild( root_id, cookie );
if( ! kid.IsOk() )
continue;
}
}
TREEPROJECT_ITEM* itemData = GetItemIdData( kid );
if( itemData && ( itemData->GetType() == TREE_DIRECTORY ) )
{
watched_path = wxFileName::DirName( itemData->m_FileName );
m_watcher->Add( watched_path );
// if kid is a subdir, push in list to explore it later
if( itemData->m_WasPopulated && m_TreeProject->GetChildrenCount( kid ) )
subdirs_id.push( kid );
}
kid = m_TreeProject->GetNextChild( root_id, cookie );
}
#endif #endif
#if 0 // For test only!
wxArrayString paths;
m_watcher->GetWatchedPaths( &paths );
for( unsigned ii = 0; ii < paths.GetCount(); ii++ )
wxLogMessage( paths[ii] );
#endif
}
/* Called by sending a event with id = ID_INIT_WATCHED_PATHS
* rebuild the list of whatched paths
* We are using an event called function to install or reinit a file system watcher
* because a file watcher *needs* a running loop event handler.
* this is noticeable under Linux.
* therefore the safe way to do that is to use the main event loop
* to call m_LeftWin->FileWatcherReset()
*/
void KICAD_MANAGER_FRAME::OnChangeWatchedPaths(wxCommandEvent& aEvent )
{
m_LeftWin->FileWatcherReset();
} }
#endif #endif
...@@ -29,7 +29,9 @@ ...@@ -29,7 +29,9 @@
#ifndef TREEPRJ_FRAME_H #ifndef TREEPRJ_FRAME_H
#define TREEPRJ_FRAME_H #define TREEPRJ_FRAME_H
#if wxCHECK_VERSION( 2, 9, 2 ) #include <kicad.h>
#ifdef KICAD_USE_FILES_WATCHER
#include <wx/fswatcher.h> #include <wx/fswatcher.h>
#endif #endif
...@@ -52,16 +54,22 @@ private: ...@@ -52,16 +54,22 @@ private:
wxCursor m_DragCursor; wxCursor m_DragCursor;
wxCursor m_Default; wxCursor m_Default;
#if wxCHECK_VERSION( 2, 9, 2 ) #ifdef KICAD_USE_FILES_WATCHER
wxFileSystemWatcher* m_watcher; // file system watcher wxFileSystemWatcher* m_watcher; // file system watcher (since wxWidgets 2.9.2)
#endif #endif
public: public:
TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ); TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent );
~TREE_PROJECT_FRAME(); ~TREE_PROJECT_FRAME();
void ReCreateTreePrj(); void ReCreateTreePrj();
#if wxCHECK_VERSION( 2, 9, 2 ) #ifdef KICAD_USE_FILES_WATCHER
void FileWatcherReset(); /**
* Reinit the watched paths
* Should be called after opening a new project to
* rebuild the list of watched paths.
* Should be called *atfer* the main loop event handler is started
*/
void FileWatcherReset();
#endif #endif
protected: protected:
...@@ -160,8 +168,13 @@ private: ...@@ -160,8 +168,13 @@ private:
*/ */
wxTreeItemId findSubdirTreeItem( const wxString& aSubDir ); wxTreeItemId findSubdirTreeItem( const wxString& aSubDir );
#if wxCHECK_VERSION( 2, 9, 2 ) #ifdef KICAD_USE_FILES_WATCHER
void OnFileSystemEvent( wxFileSystemWatcherEvent& event ); /**
* called when a file or directory is modified/created/deleted
* The tree project is modified when a file or directory
* is created/deleted/renamed to reflect the file change
*/
void OnFileSystemEvent( wxFileSystemWatcherEvent& event );
#endif #endif
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment