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 @@
#include <fctsys.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 <tree_project_frame.h>
#include <wildcards_and_files_ext.h>
......@@ -45,12 +39,6 @@
const wxString g_KicadPrjFilenameExtension( wxT( ".pro" ) );
/* Import functions */
char* GetFileName( char* FullPathName );
void ShowLogo( char* FonteFileName );
/* Local functions */
/************************************/
/* Called to initialize the program */
/************************************/
......@@ -113,7 +101,8 @@ bool EDA_APP::OnInit()
wxFileName namelessProject( wxGetCwd(), NAMELESS_PROJECT, ProjectFileExtension );
frame = new KICAD_MANAGER_FRAME( NULL, wxT( "KiCad" ),
wxPoint( 30, 20 ), wxSize( 600, 400 ) );
wxDefaultPosition, wxDefaultSize );
SetTopWindow( frame );
if( argc > 1 )
{
......@@ -141,38 +130,6 @@ bool EDA_APP::OnInit()
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->Raise();
......
......@@ -15,6 +15,12 @@
#include <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;
class RIGHT_KM_FRAME;
......@@ -77,7 +83,8 @@ enum id_kicad_frm {
ID_SELECT_PREFERED_PDF_BROWSER,
ID_SELECT_DEFAULT_PDF_BROWSER,
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,
*/
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()
};
......
......@@ -89,6 +89,7 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent,
PrintMsg( line );
RecreateBaseHToolbar();
ReCreateMenuBar();
m_auimgr.SetManagedWindow( this );
......
......@@ -31,6 +31,7 @@
#include <appl_wxstruct.h>
#include <kicad.h>
#include <menus_helpers.h>
#include <tree_project_frame.h>
/* Menubar and toolbar event table */
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 */
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 )
// Special functions
#ifdef KICAD_USE_FILES_WATCHER
EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths )
#endif
/* Button events */
EVT_BUTTON( ID_TO_PCB, KICAD_MANAGER_FRAME::OnRunPcbNew )
EVT_BUTTON( ID_TO_CVPCB, KICAD_MANAGER_FRAME::OnRunCvpcb )
......
......@@ -222,10 +222,14 @@ void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event )
SetTitle( title );
UpdateFileHistory( m_ProjectFileName.GetFullPath() );
#if wxCHECK_VERSION( 2, 9, 2 )
m_LeftWin->FileWatcherReset();
#endif
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() +
_( "\nProject: " ) + m_ProjectFileName.GetFullName() +
......
......@@ -34,7 +34,6 @@
#include <appl_wxstruct.h>
#include <macros.h>
#include <kicad.h>
#include <tree_project_frame.h>
#include <class_treeprojectfiles.h>
#include <class_treeproject_item.h>
......@@ -137,9 +136,8 @@ TREE_PROJECT_FRAME::TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ) :
m_TreeProject = NULL;
wxMenuItem* item;
m_PopupMenu = NULL;
#if wxCHECK_VERSION( 2, 9, 2 )
m_watcher = new wxFileSystemWatcher();
m_watcher->SetOwner( this );
#ifdef KICAD_USE_FILES_WATCHER
m_watcher = NULL;
Connect( wxEVT_FSWATCHER,
wxFileSystemWatcherEventHandler( TREE_PROJECT_FRAME::OnFileSystemEvent ) );
#endif
......@@ -235,7 +233,7 @@ TREE_PROJECT_FRAME::~TREE_PROJECT_FRAME()
if( m_PopupMenu )
delete m_PopupMenu;
#if wxCHECK_VERSION( 2, 9, 2 )
#ifdef KICAD_USE_FILES_WATCHER
delete m_watcher;
#endif
}
......@@ -935,6 +933,7 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event )
wxTreeItemIdValue cookie;
wxTreeItemId kid = m_TreeProject->GetFirstChild( itemId, cookie );
bool subdir_populated = false;
for( ; kid.IsOk(); kid = m_TreeProject->GetNextChild( itemId, cookie ) )
{
TREEPROJECT_ITEM* itemData = GetItemIdData( kid );
......@@ -959,10 +958,20 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event )
}
itemData->m_WasPopulated = true; // set state to populated
subdir_populated = true;
/* Sort filenames by alphabetic order */
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 )
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!
{
root_id = kid;
break;
}
// if kid is a subdir, push in list to explore it later
if( itemData->GetType() == TREE_DIRECTORY &&
itemData->m_WasPopulated )
// kid is a subdir, push in list to explore it later
if( itemData->m_WasPopulated )
subdirs_id.push( kid );
}
kid = m_TreeProject->GetNextChild( root_id, cookie );
......@@ -1054,10 +1059,10 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
return root_id;
}
#if wxCHECK_VERSION( 2, 9, 2 )
#ifdef KICAD_USE_FILES_WATCHER
/* called when a file or directory is modified/created/deleted
* The tree project should be rebuilt when a file or directory
* is created or deleted
* The tree project is modified when a file or directory
* is created/deleted/renamed to reflect the file change
*/
void TREE_PROJECT_FRAME::OnFileSystemEvent( wxFileSystemWatcherEvent& event )
{
......@@ -1102,14 +1107,10 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
{
TREEPROJECT_ITEM* itemData = GetItemIdData( kid );
if( itemData )
{
if( itemData->m_FileName == fn )
if( itemData && ( itemData->m_FileName == fn ) )
{
if( event.GetChangeType() == wxFSW_EVENT_DELETE )
{
m_TreeProject->Delete( kid );
}
else
{
wxFileName newpath = event.GetNewPath();
......@@ -1118,13 +1119,12 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
// 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
// because they could disappear, like deleted files
itemData->SetFileName( newpath.GetFullPath() );
m_TreeProject->SetItemText( kid, newpath.GetFullName() );
}
return;
}
}
kid = m_TreeProject->GetNextChild( root_id, cookie );
}
......@@ -1134,6 +1134,11 @@ wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir )
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()
{
// Prepare file watcher:
......@@ -1142,15 +1147,73 @@ void TREE_PROJECT_FRAME::FileWatcherReset()
m_watcher->SetOwner( this );
// Add directories which should be monitored.
// under windows, we add the curr dir and subdirs
// under unix, we add only the curr dir
// under windows, we add the curr dir and all subdirs
// under unix, we add only the curr dir and the populated subdirs
// see http://docs.wxwidgets.org/trunk/classwx_file_system_watcher.htm
// 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__
m_watcher->AddTree( wxFileName::DirName( wxT( "./" ) ) );
m_watcher->AddTree( watched_path );
#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
#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
......@@ -29,7 +29,9 @@
#ifndef 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>
#endif
......@@ -52,15 +54,21 @@ private:
wxCursor m_DragCursor;
wxCursor m_Default;
#if wxCHECK_VERSION( 2, 9, 2 )
wxFileSystemWatcher* m_watcher; // file system watcher
#ifdef KICAD_USE_FILES_WATCHER
wxFileSystemWatcher* m_watcher; // file system watcher (since wxWidgets 2.9.2)
#endif
public:
TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent );
~TREE_PROJECT_FRAME();
void ReCreateTreePrj();
#if wxCHECK_VERSION( 2, 9, 2 )
#ifdef KICAD_USE_FILES_WATCHER
/**
* 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
......@@ -160,7 +168,12 @@ private:
*/
wxTreeItemId findSubdirTreeItem( const wxString& aSubDir );
#if wxCHECK_VERSION( 2, 9, 2 )
#ifdef KICAD_USE_FILES_WATCHER
/**
* 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
......
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