← Back to team overview

kicad-developers team mailing list archive

[patch 1/1] kicad-project-editor-binding-second-pass.patch

 

This patch improves (again) the binding, add some little features to the 
project editor, and some bug fixes :

bug fixes:
- project file incorrect renaming while not the current project
- directory removing (should remove files as well)
- create file in tree, instead of using EDA_Fileselect+Refresh
- don't refresh on delete file/directory
- segfault when renaming to the same name

features add (and improvements):
- tie up data and tree items
- move delete, rename to tree nodes
- clean python binding code
- kicad.h reindentation
- move open file (activate) operation to tree data
- open directory on dbl click

python binding adds:
- tree refresh
- common.currentScript => to name
- file extension from type
- clear console
- get the tree widget
- get the data out of a tree item
- rename file
- deletefile
- newfile
- activate file (open file from tree)

if the patch does not apply correctly, try to dos2unix the corresponding 
files (sorry for inconvinience)

I am attaching some python scripts as example (I'll update the 
documentation soon)

PS: I'll probably make 2 patches more on the project editor before going 
to pcbnew
---
common/pyhandler.cpp | 20 +++
include/pyhandler.h | 16 --
kicad/kicad.cpp | 100 ++++++++++++---
kicad/kicad.h | 76 +++++++++--
kicad/treeprj.cpp | 334 +++++++++++++++++++++++++++++----------------------
5 files changed, 365 insertions(+), 181 deletions(-)

 --------------010706010506060404050703 Content-Type: text/x-patch;
name="kicad-project-editor-binding-second-pass.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="kicad-project-editor-binding-second-pass.patch"

This patch improves (again) the binding, add some little features to the project editor, and some bug fixes :

bug fixes:
- project file incorrect renaming while not the current project
- directory removing (should remove files as well)
- create file in tree, instead of using EDA_Fileselect+Refresh
- don't refresh on delete file/directory
- segfault when renaming to the same name

features add (and improvements):
- tie up data and tree items
- move delete, rename to tree nodes
- clean python binding code
- kicad.h reindentation
- move open file (activate) operation to tree data
- open directory on dbl click

python binding adds:
- tree refresh
- common.currentScript => to name
- file extension from type
- clear console
- get the tree widget
- get the data out of a tree item
- rename file
- deletefile
- newfile
- activate file (open file from tree)

if the patch does not apply correctly, try to dos2unix the corresponding files (sorry for inconvinience)

---
common/pyhandler.cpp | 20 +++
include/pyhandler.h | 16 --
kicad/kicad.cpp | 100 ++++++++++++---
kicad/kicad.h | 76 +++++++++--
kicad/treeprj.cpp | 334 +++++++++++++++++++++++++++++----------------------
5 files changed, 365 insertions(+), 181 deletions(-)


Index: kicad-dev/kicad/kicad.cpp
===================================================================
--- kicad-dev.orig/kicad/kicad.cpp	2007-04-30 21:58:10.000000000 +0200
+++ kicad-dev/kicad/kicad.cpp	2007-05-02 01:47:17.000000000 +0200
@@ -48,19 +48,18 @@
#ifdef KICAD_PYTHON
using namespace boost::python;

-static WinEDA_MainFrame& GetMainFrame(void) { return *( wxGetApp().m_MainFrame ); }
-object WinEDA_MainFrame::GetPrjName() const { return PyHandler::Convert( m_PrjFileName ); }
-static void WinEDAPrint( str msg ) { GetMainFrame().PrintMsg( PyHandler::MakeStr( msg ) + wxT("\n") ); }
-object WinEDA_MainFrame::ToWx() { return object( handle<>( borrowed( wxPyMake_wxObject( this, false ) ) ) ); }
-object WinEDA_PrjFrame::ToWx() { return object( handle<>( borrowed( wxPyMake_wxObject( this, false ) ) ) ); }
-WinEDA_PrjFrame* WinEDA_MainFrame::GetTree() const { return m_LeftWin; }
-object WinEDA_PrjFrame::GetFtExPy( enum TreeFileType type ) const { return PyHandler::Convert( GetFileExt( type ) ); }
-object WinEDA_PrjFrame::GetMenuPy( enum TreeFileType type )
-{
- return object( handle<>( borrowed( wxPyMake_wxObject( GetContextMenu( (int) type ), false ) ) ) );
-}
-
-void WinEDA_PrjFrame::AddFilePy( str & file ) { AddFile( PyHandler::MakeStr( file ), m_root ); }
+// Global functions:
+static WinEDA_MainFrame& GetMainFrame(void) { return *( wxGetApp().m_MainFrame ); }
+static void WinEDAPrint( str msg ) { GetMainFrame().PrintMsg( PyHandler::MakeStr( msg ) + wxT("\n") ); }
+static void WinEDAClear() { GetMainFrame().ClearMsg(); }
+static object GetTypeExt( enum TreeFileType type ) { return PyHandler::Convert( WinEDA_PrjFrame::GetFileExt( type ) ); }
+
+// WinEDA_MainFrame Special binding functions:
+// (one line functions are simple wrappers)
+
+object WinEDA_MainFrame::GetPrjName() const { return PyHandler::Convert( m_PrjFileName ); }
+object WinEDA_MainFrame::ToWx() { return object( handle<>( borrowed( wxPyMake_wxObject( this, false ) ) ) ); }
+WinEDA_PrjFrame* WinEDA_MainFrame::GetTree() const { return m_LeftWin;	}

void WinEDA_MainFrame::AddFastLaunchPy( object & button )
{
@@ -72,9 +71,65 @@
AddFastLaunch( btn );
}

+// WinEDA_PrjFrame Special binding functions:
+// (one line functions are simple wrappers)
+
+object WinEDA_PrjFrame::ToWx() { return object( handle<>( borrowed( wxPyMake_wxObject( this, false ) ) ) ); }
+object WinEDA_PrjFrame::GetFtExPy( enum TreeFileType type ) const { return PyHandler::Convert( GetFileExt( type ) ); }
+object WinEDA_PrjFrame::GetMenuPy( enum TreeFileType type ) { return object( handle<>( borrowed( wxPyMake_wxObject( GetContextMenu( (int) type ), false ) ) ) ); }
+object WinEDA_PrjFrame::GetTreeCtrl() { return object( handle<>( borrowed( wxPyMake_wxObject( m_TreeProject, false ) ) ) ); }
+
+void WinEDA_PrjFrame::NewFilePy( const str & name, enum TreeFileType type, object & id )
+{
+	wxTreeItemId root;
+	if (! wxPyConvertSwigPtr( id.ptr(), (void**)&root, _T("wxTreeItemId") ) ) return;
+	NewFile( PyHandler::MakeStr( name ), type, root );
+}
+
+void WinEDA_PrjFrame::AddFilePy( const str & file, object & root )
+/* Add a file to the tree under root, or m_root if conversion is wrong */
+{
+	wxTreeItemId * theroot = &m_root;
+	if ( !wxPyConvertSwigPtr( root.ptr(), (void**)&root, _T("wxTreeItemId") ) )
+	{
+	theroot = &m_root;
+	}
+	AddFile( PyHandler::MakeStr( file ), *theroot );
+}
+
+TreePrjItemData * WinEDA_PrjFrame::GetItemData( const object & item )
+/* convert wxTreeItem into TreePrjItemData */
+{
+	wxTreeItemId *id = NULL;
+	if ( !wxPyConvertSwigPtr( item.ptr(), (void**)&id, _T("wxTreeItemId") ) ) return NULL;
+	return dynamic_cast<TreePrjItemData *>( m_TreeProject->GetItemData( *id ) );
+}
+
+// TreePrjItemData Special binding functions
+// (one line functions are simple wrappers)
+
+bool TreePrjItemData::RenamePy( const str & newname, bool check ) { return Rename( PyHandler::MakeStr(newname), check ); }
+object TreePrjItemData::GetDirPy() const { return PyHandler::Convert( GetDir() ); }
+object TreePrjItemData::GetFileNamePy() const	{ return PyHandler::Convert( GetFileName() ); }
+
+// kicad module init function
+// ( this function is called from PyHandler to init the kicad module )
+
static void py_kicad_init(void)
{
def( "GetMainFrame", &GetMainFrame, return_value_policy< reference_existing_object >() );
+ def( "GetTypeExtension", &GetTypeExt );
+
+	class_<TreePrjItemData>( "PrjItem" )
+	// Internal data:
+	.def( "GetFileName", &TreePrjItemData::GetFileNamePy )
+	.def( "GetDir",	&TreePrjItemData::GetDirPy )
+	.def( "GetType",	&TreePrjItemData::GetType )
+	// Item control
+	.def( "Rename", &TreePrjItemData::RenamePy )
+	.def( "Delete", &TreePrjItemData::Delete )
+	.def( "Activate", &TreePrjItemData::Activate )
+	;

enum_<TreeFileType>( "FileType" )
.value( "PROJECT", TREE_PROJECT )
@@ -90,31 +145,45 @@
.value( "MAX", TREE_MAX );

class_<WinEDA_PrjFrame>( "TreeWindow" )
+	// wx Interface
.def( "ToWx",	&WinEDA_PrjFrame::ToWx )
+	// common features
.def( "GetContextMenu", &WinEDA_PrjFrame::GetMenuPy )
.def( "GetFileExtension", &WinEDA_PrjFrame::GetFtExPy )
-	.def( "AddFile",	&WinEDA_PrjFrame::AddFilePy )
+	// file filters control
.def( "AddFilter", &WinEDA_PrjFrame::AddFilter )
.def( "ClearFilters", &WinEDA_PrjFrame::ClearFilters )
.def( "RemoveFilter", &WinEDA_PrjFrame::RemoveFilterPy )
.def( "GetFilters", &WinEDA_PrjFrame::GetFilters, return_value_policy < copy_const_reference >() )
+	// Project tree control
+	.def( "GetTreeCtrl",	&WinEDA_PrjFrame::GetTreeCtrl )
+ .def( "GetItemData", &WinEDA_PrjFrame::GetItemData, return_value_policy < reference_existing_object >() )
+	.def( "NewFile", &WinEDA_PrjFrame::NewFilePy )
+	.def( "AddFile",	&WinEDA_PrjFrame::AddFilePy )
;

class_<WinEDA_MainFrame>( "MainFrame" )
-	.def( "ToWx",	&WinEDA_MainFrame::ToWx )
+	// Wx interface
+	.def( "ToWx",	&WinEDA_MainFrame::ToWx )
+	// Common controls
.def( "AddFastLaunch",	&WinEDA_MainFrame::AddFastLaunchPy )
+ .def( "Refresh", &WinEDA_MainFrame::OnRefreshPy )
.def( "GetProjectName",	&WinEDA_MainFrame::GetPrjName )
.def( "GetProjectWindow",	&WinEDA_MainFrame::GetTree, return_value_policy< reference_existing_object >() );

}

+// common module init function
+
static void py_common_init(void)
{
def( "Print", &WinEDAPrint );
+ def( "Clear", &WinEDAClear );
}

#endif

+
bool WinEDA_App::OnInit(void)
{
EDA_Appl = this;
@@ -171,3 +240,4 @@
return TRUE;
}

+// vim: tabstop=4 : noexpandtab :
Index: kicad-dev/kicad/kicad.h
===================================================================
--- kicad-dev.orig/kicad/kicad.h	2007-04-30 21:07:16.000000000 +0200
+++ kicad-dev/kicad/kicad.h	2007-05-02 01:46:59.000000000 +0200
@@ -68,6 +68,7 @@
void RecreateBaseHToolbar(void);
void CreateCommandToolbar(void);
void PrintMsg(const wxString & text);
+ void ClearMsg();
void SetLanguage(wxCommandEvent& event);
void OnRefresh(wxCommandEvent& event);

@@ -75,6 +76,7 @@
void UnZipArchive(const wxString FullFileName);

#ifdef KICAD_PYTHON
+ void OnRefreshPy();
boost::python::object GetPrjName() const;
WinEDA_MainFrame( const WinEDA_MainFrame& ) {}
WinEDA_MainFrame() {}
@@ -100,10 +102,50 @@
TREE_TXT,
TREE_NET,
TREE_UNKNOWN,
- TREE_DIRECTORY,
+	TREE_DIRECTORY,
TREE_MAX,
};

+/***********************************************************/
+/* Classes pour l'arbre de hierarchie de gestion du projet */
+/***********************************************************/
+class TreePrjItemData: public wxTreeItemData
+{
+
+private:
+	enum TreeFileType m_Type;
+	wxString m_FileName;
+	wxTreeCtrl * m_Parent;
+
+public:
+
+	TreePrjItemData() : m_Parent(NULL) {}
+	TreePrjItemData( const TreePrjItemData & src )
+	: m_Type( src.m_Type )
+	, m_FileName( src.m_FileName )
+	, m_Parent( src.m_Parent )
+	{
+	}
+	TreePrjItemData(enum TreeFileType type, const wxString & data, wxTreeCtrl * parent);
+
+	enum TreeFileType GetType() const { return m_Type; }
+	wxString GetFileName() const { return m_FileName; }
+	void SetFileName( const wxString & name ) { m_FileName = name; }
+
+	wxString GetDir() const;
+
+	void OnRename( wxTreeEvent & event, bool check = true );
+	bool Rename( const wxString & name, bool check = true );
+	bool Delete( bool check = true );
+	void Activate();
+
+	#ifdef KICAD_PYTHON
+	boost::python::object GetFileNamePy() const;
+	bool RenamePy( const boost::python::str & newname, bool check = true );
+	boost::python::object GetDirPy() const;
+	#endif
+};
+
/* Fenetre d'affichage des fichiers du projet */
class WinEDA_PrjFrame : public wxSashLayoutWindow
{
@@ -115,8 +157,8 @@
protected:
wxMenu * GetContextMenu( int type );
void NewFile( wxCommandEvent & event, enum TreeFileType type );
+	void NewFile( const wxString & name, enum TreeFileType type, wxTreeItemId & root );

-	wxString GetFileExt( enum TreeFileType type ) const;

public:
WinEDA_MainFrame * m_Parent;
@@ -125,8 +167,10 @@
wxTreeItemId m_root;

public:
+	static wxString GetFileExt( enum TreeFileType type );
+
WinEDA_PrjFrame(WinEDA_MainFrame * parent,
-	const wxPoint & pos, const wxSize & size );
+	const wxPoint & pos, const wxSize & size );
~WinEDA_PrjFrame(void) {}
void OnSelect(wxTreeEvent & Event);
void OnRenameAsk(wxTreeEvent & Event);
@@ -147,21 +191,28 @@
void OnNewTxtFile(wxCommandEvent & event);
void OnNewNetFile(wxCommandEvent & event);

- void ClearFilters();
- const std::vector<wxString > & GetFilters();
- void RemoveFilter( const wxString & filter );
+	void ClearFilters();
+	const std::vector<wxString > & GetFilters();
+	void RemoveFilter( const wxString & filter );

#ifdef KICAD_PYTHON
-	void OnRunPy(wxCommandEvent & event);
boost::python::object ToWx();
-	boost::python::object GetMenuPy( enum TreeFileType );
-	boost::python::object GetFtExPy ( enum TreeFileType ) const;
-	void AddFilePy( boost::python::str & name );
+
WinEDA_PrjFrame() {}
WinEDA_PrjFrame( const WinEDA_PrjFrame & ) {}

- void RemoveFilterPy( const boost::python::str & filter );
- void AddFilter( const boost::python::str & filter );
+	void OnRunPy(wxCommandEvent & event);
+	boost::python::object GetMenuPy( enum TreeFileType );
+	boost::python::object GetFtExPy ( enum TreeFileType ) const;
+
+ void RemoveFilterPy( const boost::python::str & filter );
+ void AddFilter( const boost::python::str & filter );
+
+	boost::python::object GetTreeCtrl();
+	TreePrjItemData * GetItemData( const boost::python::object & item );
+	void AddFilePy( const boost::python::str & name, boost::python::object & root );
+	void NewFilePy( const boost::python::str & name, enum TreeFileType type, boost::python::object & root );
+
#endif

void AddFile( const wxString & name, wxTreeItemId & root );
@@ -197,3 +248,4 @@
#endif

#endif
+// vim: tabstop=4 : noexpandtab :
Index: kicad-dev/kicad/treeprj.cpp
===================================================================
--- kicad-dev.orig/kicad/treeprj.cpp	2007-04-30 21:58:02.000000000 +0200
+++ kicad-dev/kicad/treeprj.cpp	2007-05-02 01:47:13.000000000 +0200
@@ -36,40 +36,163 @@
#include "id.h"


-/***********************************************************/
-/* Classes pour l'arbre de hierarchie de gestion du projet */
-/***********************************************************/
-class TreePrjItemData: public wxTreeItemData
-{
-public:
-	int m_Id;
-	wxString m_FileName;
+TreePrjItemData::TreePrjItemData(enum TreeFileType type, const wxString & data, wxTreeCtrl * parent)
+: wxTreeItemData()
+, m_Type( type )
+, m_Parent( parent )
+{
+	if ( data ) m_FileName = data;
+}
+
+
+wxString TreePrjItemData::GetDir() const
+/* Get the directory containing the file */
+{
+	if (TREE_DIRECTORY == m_Type ) return m_FileName;
+
+	wxFileName filename = wxFileName( m_FileName );
+	filename.MakeRelativeTo( wxGetCwd() );
+	wxArrayString dirs = filename.GetDirs();

-public:
-	TreePrjItemData(int tree_id, const wxString & data) :wxTreeItemData()
+	wxString dir;
+	for ( unsigned int i = 0; i < dirs.Count(); i ++ )
{
-	m_Id = tree_id;
-	if ( data ) m_FileName = data;
+	dir += dirs[i] + filename.GetPathSeparator();
}
+	return dir;
+}

- wxString GetDir() const
- {
- if (TREE_DIRECTORY == m_Id ) return m_FileName;
+void TreePrjItemData::OnRename( wxTreeEvent & event, bool check )
+/* Called upon tree item rename */
+{
+	if ( !Rename( event.GetLabel(), check ) ) event.Veto();
+}

- wxFileName filename = wxFileName( m_FileName );
- filename.MakeRelativeTo( wxGetCwd() );
- wxArrayString dirs = filename.GetDirs();
+bool TreePrjItemData::Rename( const wxString & name, bool check )
+/* rename the file checking if extension change occurs */
+{
+	if ( name.IsEmpty() ) return false;

- wxString dir;
- for ( unsigned int i = 0; i < dirs.Count(); i ++ )
- {
- dir += dirs[i] + filename.GetPathSeparator();
- }
- return dir;
- }
-};
+ const wxString sep = wxFileName().GetPathSeparator();
+	wxString newFile;
+	wxString dirs = GetDir();
+
+	if ( !dirs.IsEmpty() ) newFile = dirs + sep + name;
+	else newFile = name;
+
+	if ( newFile == m_FileName ) return false;

+	wxString ext = WinEDA_PrjFrame::GetFileExt( GetType() );
+
+	wxRegEx reg( wxT( "^.*\\" ) + ext + wxT( "$" ), wxRE_ICASE );
+	if ( check && !ext.IsEmpty() && !reg.Matches( newFile ) )
+	{
+	wxMessageDialog dialog( m_Parent
+	, _("Changing file extension will change file type.\n Do you want to continue ?")
+	, _("Rename File")
+	, wxYES_NO | wxICON_QUESTION );
+
+	if ( wxID_YES != dialog.ShowModal() ) return false;
+	}

+	wxRenameFile( m_FileName, newFile );
+	SetFileName( newFile );
+
+	#ifdef KICAD_PYTHON
+	boost::python::object param = boost::python::make_tuple( PyHandler::Convert( m_FileName )
+	, PyHandler::Convert( newFile ) );
+	PyHandler::GetInstance()->TriggerEvent( wxT("kicad::RenameFile"), param );
+	#endif
+	return true;
+}
+
+bool TreePrjItemData::Delete( bool check )
+/* delete a file */
+{
+	wxMessageDialog dialog( m_Parent, _("Do you really want to delete ") + GetFileName(), _("Delete File")
+	, wxYES_NO | wxICON_QUESTION );
+
+	if ( !check || wxID_YES == dialog.ShowModal() )
+	{
+	if ( !wxDirExists( m_FileName ) )
+	{
+	wxRemoveFile( m_FileName );
+	}
+	else
+	{
+	wxArrayString filelist;
+	wxDir::GetAllFiles( m_FileName, &filelist );
+	for ( unsigned int i = 0; i < filelist.Count(); i++ ) wxRemoveFile( filelist[i] );
+	wxRmdir( m_FileName );
+	}
+	m_Parent->Delete( GetId() );
+	#ifdef KICAD_PYTHON
+	PyHandler::GetInstance()->TriggerEvent( wxT("kicad::DeleteFile"), PyHandler::Convert( m_FileName ) );
+	#endif
+	return true;
+	}
+	return false;
+}
+
+void TreePrjItemData::Activate()
+/* Called under item activation */
+{
+	wxString FullFileName = GetFileName();
+
+	switch ( GetType() )
+	{
+	case TREE_PROJECT:
+	break;
+
+	case TREE_DIRECTORY:
+	m_Parent->Toggle( GetId() );
+	break;
+
+	case TREE_SCHEMA:
+	{
+	AddDelimiterString( FullFileName );
+	ExecuteFile(m_Parent, EESCHEMA_EXE, FullFileName);
+	break;
+	}
+
+	case TREE_PCB:
+	AddDelimiterString( FullFileName );
+	ExecuteFile(m_Parent, PCBNEW_EXE, FullFileName);
+	break;
+
+ #ifdef KICAD_PYTHON
+ case TREE_PY:
+	PyHandler::GetInstance()->RunScript( FullFileName );
+	break;
+	#endif
+
+	case TREE_GERBER:
+	AddDelimiterString(FullFileName);
+	ExecuteFile(m_Parent, GERBVIEW_EXE, FullFileName);
+	break;
+
+	case TREE_PDF:
+	OpenPDF( FullFileName );
+	break;
+
+	case TREE_NET:
+	AddDelimiterString(FullFileName);
+	ExecuteFile(m_Parent, CVPCB_EXE, FullFileName);
+	break;
+
+	case TREE_TXT:
+	{
+	wxString editorname = GetEditorName();
+	if ( !editorname.IsEmpty() ) ExecuteFile(m_Parent, editorname, FullFileName);
+	break;
+	}
+
+	default:
+	OpenFile( FullFileName );
+	break;
+
+	}
+}

/**********************************************************************/
/* Methodes de la Frame de l'arbre de hierarchie de gestion du projet */
@@ -275,24 +398,43 @@
);
if ( filename.IsEmpty() ) return;

+	enum TreeFileType rootType = treeData->GetType();
+ wxTreeItemId root;
+
+ if ( TREE_DIRECTORY == rootType )
+ {
+ root = m_TreeProject->GetSelection();
+ }
+ else
+ {
+ root = m_TreeProject->GetItemParent( m_TreeProject->GetSelection() );
+ if ( !root.IsOk() ) root = m_TreeProject->GetSelection();
+ }
+
+	NewFile( filename, type, root );
+}
+
+void WinEDA_PrjFrame::NewFile( const wxString & name, enum TreeFileType type, wxTreeItemId & root )
+{
if ( TREE_DIRECTORY != type )
{
- wxFile( filename, wxFile::write );
+ wxFile( name, wxFile::write );
#ifdef KICAD_PYTHON
- PyHandler::GetInstance()->TriggerEvent( wxT("kicad::NewFile"), PyHandler::Convert(filename) );
+ PyHandler::GetInstance()->TriggerEvent( wxT("kicad::NewFile"), PyHandler::Convert(name) );
#endif
}
else
{
- wxMkdir( filename );
+ wxMkdir( name );
#ifdef KICAD_PYTHON
- PyHandler::GetInstance()->TriggerEvent( wxT("kicad::NewDirectory"), PyHandler::Convert(filename) );
+ PyHandler::GetInstance()->TriggerEvent( wxT("kicad::NewDirectory"), PyHandler::Convert(name) );
#endif
}
-	m_Parent->OnRefresh( event );
+
+ AddFile( name, root );
}

-wxString WinEDA_PrjFrame::GetFileExt( enum TreeFileType type ) const
+wxString WinEDA_PrjFrame::GetFileExt( enum TreeFileType type )
{
wxString extensions[] =
{
@@ -353,7 +495,7 @@

wxString file = wxFileNameFromPath( name );
cellule = m_TreeProject->AppendItem( root, file );
-	m_TreeProject->SetItemData( cellule, new TreePrjItemData( type, name ) );
+	m_TreeProject->SetItemData( cellule, new TreePrjItemData( (enum TreeFileType) type, name, m_TreeProject ) );
m_TreeProject->SetItemFont( cellule, *g_StdFont );
m_TreeProject->SetItemImage( cellule, type - 1 );
m_TreeProject->SetItemImage( cellule, type - 1, wxTreeItemIcon_Selected );
@@ -399,7 +541,7 @@
// root tree:
m_root = rootcellule = m_TreeProject->AddRoot(Text, TREE_PROJECT - 1, TREE_PROJECT - 1);
m_TreeProject->SetItemBold(rootcellule, TRUE);
-	m_TreeProject->SetItemData( rootcellule, new TreePrjItemData(TREE_PROJECT, wxEmptyString) );
+	m_TreeProject->SetItemData( rootcellule, new TreePrjItemData(TREE_PROJECT, wxEmptyString, m_TreeProject) );
m_TreeProject->SetItemFont(rootcellule, *g_StdFont);

ChangeFileNameExt(Text, wxEmptyString);
@@ -435,8 +577,8 @@
tree_data = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;

-	tree_id = tree_data->m_Id;
-	FullFileName = tree_data->m_FileName;
+	tree_id = tree_data->GetType();
+	FullFileName = tree_data->GetFileName();

#ifdef KICAD_PYTHON
PyHandler::GetInstance()->TriggerEvent( wxT("kicad::TreeContextMenu"), PyHandler::Convert( FullFileName ) );
@@ -451,12 +593,18 @@
m_LeftWin->ReCreateTreePrj();
}

+void WinEDA_MainFrame::ClearMsg() { m_DialogWin->Clear(); }
+
+#ifdef KICAD_PYTHON
+void WinEDA_MainFrame::OnRefreshPy() { m_LeftWin->ReCreateTreePrj(); }
+#endif
+
void WinEDA_PrjFrame::OnTxtEdit(wxCommandEvent & event )
{
TreePrjItemData * tree_data = dynamic_cast<TreePrjItemData*> (m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;

-	wxString FullFileName = tree_data->m_FileName;
+	wxString FullFileName = tree_data->GetFileName();
AddDelimiterString( FullFileName );
wxString editorname = GetEditorName();
if ( !editorname.IsEmpty() )
@@ -466,23 +614,11 @@
}
}

-void WinEDA_PrjFrame::OnDeleteFile(wxCommandEvent &event )
+void WinEDA_PrjFrame::OnDeleteFile(wxCommandEvent &)
{
TreePrjItemData * tree_data = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;
-	wxString filename = tree_data->m_FileName;
-
-	wxMessageDialog dialog( this, _("Do you really want to delete ") + filename, _("Delete File") 
-	, wxYES_NO | wxICON_QUESTION );
-
-	if ( wxID_YES == dialog.ShowModal() )
-	{
-	wxRemoveFile( filename );
-	m_Parent->OnRefresh( event );
-	#ifdef KICAD_PYTHON
-	PyHandler::GetInstance()->TriggerEvent( wxT("kicad::DeleteFile"), PyHandler::Convert( filename) );
-	#endif
-	}
+	tree_data->Delete();
}

#ifdef KICAD_PYTHON
@@ -491,52 +627,27 @@
TreePrjItemData * tree_data = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;

-	wxString FullFileName = tree_data->m_FileName;
+	wxString FullFileName = tree_data->GetFileName();
PyHandler::GetInstance()->TriggerEvent( wxT("kicad::RunScript"), PyHandler::Convert( FullFileName ) );
PyHandler::GetInstance()->RunScript( FullFileName );
}
#endif

-void WinEDA_PrjFrame::OnRenameAsk(wxTreeEvent & Event)
+void WinEDA_PrjFrame::OnRenameAsk(wxTreeEvent & event)
+/* Prevent the main project to be renamed */
{
TreePrjItemData * tree_data = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;
-
-	int tree_id = tree_data->m_Id;
-	if ( TREE_PROJECT == tree_id ) Event.Veto();
+	if ( m_Parent->m_PrjFileName == tree_data->GetFileName() ) event.Veto();
}
+
void WinEDA_PrjFrame::OnRename(wxTreeEvent & event)
+/* rename a tree item on demand of the context menu */
{
- const wxString sep = wxFileName().GetPathSeparator();
-
TreePrjItemData * tree_data = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;

-	int tree_id = tree_data->m_Id;
-	wxString filename = tree_data->m_FileName;
-	wxString newFile = tree_data->GetDir() + sep + event.GetLabel();
-	
-	wxRegEx reg( wxString::FromAscii( "^.*\\" ) + GetFileExt( (enum TreeFileType) tree_id ) + wxString::FromAscii( "$" ), wxRE_ICASE );
-	if ( tree_id != TREE_UNKNOWN && !reg.Matches( newFile ) )
-	{
-	wxMessageDialog dialog( this, _("Changing file extension will change file type.\n Do you want to continue ?"), _("Rename File") 
-	, wxYES_NO | wxICON_QUESTION );
-	if ( wxID_YES != dialog.ShowModal() )
-	{
-	event.Veto();
-	return;
-	}
-	}
-
-	wxRenameFile( filename, newFile );
-
- tree_data->m_FileName = newFile;
-
-	#ifdef KICAD_PYTHON
-	boost::python::object param = boost::python::make_tuple( PyHandler::Convert( filename )
-	, PyHandler::Convert( newFile ) );
-	PyHandler::GetInstance()->TriggerEvent( wxT("kicad::RenameFile"), param );
-	#endif
+	tree_data->OnRename( event );
}


@@ -544,64 +655,11 @@
void WinEDA_PrjFrame::OnSelect(wxTreeEvent & Event)
/**************************************************/
{
-int tree_id;
wxString FullFileName;

TreePrjItemData * tree_data = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData(m_TreeProject->GetSelection()) );
if (!tree_data) return;
-
-	tree_id = tree_data->m_Id;
-	FullFileName = tree_data->m_FileName;
-
-	switch ( tree_id )
-	{
-	case TREE_PROJECT:
-	break;
-
-	case TREE_SCHEMA:
-	{
-	AddDelimiterString( FullFileName );
-	ExecuteFile(this, EESCHEMA_EXE, FullFileName);
-	break;
-	}
-
-	case TREE_PCB:
-	AddDelimiterString( FullFileName );
-	ExecuteFile(this, PCBNEW_EXE, FullFileName);
-	break;
-
- #ifdef KICAD_PYTHON
- case TREE_PY:
-	PyHandler::GetInstance()->RunScript( FullFileName );
-	break;
-	#endif
-
-	case TREE_GERBER:
-	AddDelimiterString(FullFileName);
-	ExecuteFile(this, GERBVIEW_EXE, FullFileName);
-	break;
-
-	case TREE_PDF:
-	OpenPDF( FullFileName );
-	break;
-
-	case TREE_NET:
-	AddDelimiterString(FullFileName);
-	ExecuteFile(this, CVPCB_EXE, FullFileName);
-	break;
-
-	case TREE_TXT:
-	{
-	wxString editorname = GetEditorName();
-	if ( !editorname.IsEmpty() ) ExecuteFile(this, editorname, FullFileName);
-	break;
-	}
-
-	default:
-	OpenFile( FullFileName );
-	break;
-
-	}
+	tree_data->Activate();
}


@@ -640,4 +698,4 @@
{
}

-
+// vim: tabstop=4 : noexpandtab :
Index: kicad-dev/common/pyhandler.cpp
===================================================================
--- kicad-dev.orig/common/pyhandler.cpp	2007-04-30 22:44:21.000000000 +0200
+++ kicad-dev/common/pyhandler.cpp	2007-05-01 16:44:44.000000000 +0200
@@ -48,6 +48,7 @@
}

static void Print( str message ) { std::cout << extract<char *>(message) << std::endl; }
+static void Clear() {}

static void RegisterCb( str objKey, object callback )
{ PyHandler::GetInstance()->RegisterCallback( PyHandler::MakeStr(objKey), callback ); }
@@ -62,6 +63,7 @@
def ( "GetLastID", &GetLastID );

def ( "Print", &Print );
+ def ( "Clear", &Clear);
}

static void InitPyModules() { PyHandler::GetInstance()->InitNextModule(); } // Dummy boost callback
@@ -70,6 +72,23 @@
/* PyHandler */
/*****************************************************************************/

+// std::vector< T > -> python object implicit conversion
+template <typename T> struct std_vector_to_tuple
+{
+	static PyObject * makeItem( const wxString & str ) { return boost::python::incref( PyHandler::Convert( str ).ptr() ); }
+	static PyObject * makeItem( const std::string & str ) { return boost::python::incref( boost::python::str( str.c_str() ).ptr() ); }
+	static PyObject * makeItem( int item ) { return boost::python::incref( PyInt_FromLong( item ) ); }
+
+	static PyObject * convert( const T& vect )
+	{
+	PyObject * tuple = PyTuple_New( vect.size() );
+	for ( unsigned int i = 0; i < vect.size() ; i++ )
+	{
+	PyTuple_SET_ITEM( tuple, i, makeItem( vect[i] ) );
+	}
+	return tuple;
+	}
+};

PyHandler* PyHandler::m_instance = NULL;

@@ -237,6 +256,7 @@

try
{
+	ns["currentScript"] = Convert( name );
handle<> ignored( PyRun_File( file, name.fn_str(), Py_file_input, ns.ptr(), ns.ptr() ) );
}
catch ( error_already_set )
Index: kicad-dev/include/pyhandler.h
===================================================================
--- kicad-dev.orig/include/pyhandler.h	2007-05-01 16:06:19.000000000 +0200
+++ kicad-dev/include/pyhandler.h	2007-05-01 16:07:37.000000000 +0200
@@ -93,21 +93,5 @@
static boost::python::object Convert( const wxString & wxStr );
};

-template <typename T> struct std_vector_to_tuple
-{
-	static PyObject * makeItem( const wxString & str ) { return boost::python::incref( PyHandler::Convert( str ).ptr() ); }
-	static PyObject * makeItem( const std::string & str ) { return boost::python::incref( boost::python::str( str.c_str() ).ptr() ); }
-	static PyObject * makeItem( int item ) { return boost::python::incref( PyInt_FromLong( item ) ); }
-
-	static PyObject * convert( const T& vect )
-	{
-	PyObject * tuple = PyTuple_New( vect.size() );
-	for ( unsigned int i = 0; i < vect.size() ; i++ )
-	{
-	PyTuple_SET_ITEM( tuple, i, makeItem( vect[i] ) );
-	}
-	return tuple;
-	}
-};
// vim: set tabstop=4 :
#endif
 --------------010706010506060404050703 Content-Type: text/x-python;
name="file_extensions.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="file_extensions.py"

import common
import kicad

x = kicad.FileType.PROJECT

while x < kicad.FileType.MAX :
common.Print( "Filetype " + str( x ) 
+ " has extension " 
+ kicad.GetTypeExtension( kicad.FileType( x ) ) )
x = x + 1
 --------------010706010506060404050703 Content-Type: text/x-python;
name="list_files.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="list_files.py"

# This example print the full content of the project tree including some informations :
import kicad
import common

# First clear the console
common.Clear()

# Get the project frame and the tree container
prjframe = kicad.GetMainFrame().GetProjectWindow()
tree = prjframe.GetTreeCtrl()

# Log one record
def Log (tree, item, ident ) :
itemData = prjframe.GetItemData( item )
line = ident + tree.GetItemText( item )
line += " represents " + itemData.GetFileName()
line += " in directory " + itemData.GetDir()
line += " (type " + str( itemData.GetType() ) + ")"
common.Print ( str( line ) )

# Show data function (recursive)
def ShowData( tree, item, ident ) :
# Print the current item
Log( tree, item, ident )

# Go deep first
cur = tree.GetFirstChild( item )
if len( cur ) != 0 and cur[0] :
ShowData( tree, cur[0], " " + ident )

# Show all sibling
sib = tree.GetNextSibling( item )
if sib :
ShowData( tree, sib, ident )
sib = tree.GetNextSibling( sib )
# We can do anything using the data of the item:
# data = tree.GetItemData( sib )
# if we want we could rename/delete/activate the item using :
# data.Rename( "newname", true ) // true means ask confirmation on ext change
# data.Delete()
# data.Activate()

# Initiate the process:
item = tree.GetRootItem()
ShowData( tree, item, "- " )
 --------------010706010506060404050703 Content-Type: text/x-python;
name="script_name.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="script_name.py"

import common

common.Print( currentScript + " is currently running" )
 --------------010706010506060404050703--