mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 10:13:19 +02:00
*all* the nested files and directories within the current working directory, it scans the first level of files and directories. When a user double-clicks on a folder, *then* the childeren of that directory are added to the wxTreeCtrl. This means that the little triangle does not appear until the user opens a directory .. but, i think this is a worthwile price to pay given below. This prevents (or at least mitigates) memory overflow in the case that kicad starts in root, or, in my case, it starts in my home directory, where thanks to wine & other sw, there are far too many directories. also modified the TreePrjItemData so that it stores the full pathnames in m_FileName, not paths relative to the CWD. I'm not sure if this is the correct thing to do, especially with the python interface, so change it back if it is more complicated. the move and rename commands threw a segfault on my system (Debian etch, wxWidgets 2.8.7), and since there are better ways to rename and move files, this functionality was disabled until somebody can fix it (alas, I don't have time for this now)
939 lines
27 KiB
C++
939 lines
27 KiB
C++
/*********************/
|
|
/* treeprj_frame.cpp */
|
|
/*********************/
|
|
|
|
#ifdef KICAD_PYTHON
|
|
#include <pyhandler.h>
|
|
#endif
|
|
|
|
#include "fctsys.h"
|
|
#include "gr_basic.h"
|
|
#include "common.h"
|
|
|
|
#include "kicad.h"
|
|
#include "protos.h"
|
|
|
|
#include "wx/image.h"
|
|
#include "wx/imaglist.h"
|
|
#include "wx/treectrl.h"
|
|
#include "wx/regex.h"
|
|
#include "wx/dir.h"
|
|
|
|
#include "bitmaps.h"
|
|
#ifdef KICAD_PYTHON
|
|
#include "bitmaps/new_python.xpm"
|
|
#endif
|
|
|
|
#include "id.h"
|
|
|
|
|
|
/******************************************************************/
|
|
WinEDA_PrjFrame::WinEDA_PrjFrame( WinEDA_MainFrame* parent,
|
|
const wxPoint& pos,
|
|
const wxSize& size ) :
|
|
wxSashLayoutWindow( parent, ID_LEFT_FRAME, pos, size,
|
|
wxNO_BORDER | wxSW_3D )
|
|
/******************************************************************/
|
|
{
|
|
m_Parent = parent;
|
|
m_TreeProject = NULL;
|
|
wxMenuItem* item;
|
|
m_PopupMenu = NULL;
|
|
|
|
/* Filtering is now inverted: the filters are actually used to _enable_ support
|
|
* for a given file type.
|
|
*/
|
|
m_Filters.push_back( wxT( "^.*\\.sch$" ) ); // note: sch filter must be first because of a test in AddFile() below
|
|
m_Filters.push_back( wxT( "^.*\\.pro$" ) );
|
|
m_Filters.push_back( wxT( "^.*\\.pdf$" ) );
|
|
m_Filters.push_back( wxT( "^[^$].*\\.brd$" ) );
|
|
m_Filters.push_back( wxT( "^.*\\.net$" ) );
|
|
m_Filters.push_back( wxT( "^.*\\.txt$" ) );
|
|
m_Filters.push_back( wxT( "^.*\\.pho$" ) );
|
|
m_Filters.push_back( wxT( "^no kicad files found" ) );
|
|
|
|
#ifdef KICAD_PYTHON
|
|
m_Filters.push_back( wxT( "^.*\\.py$" ) );
|
|
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::RunScript" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::EditScript" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::TreeContextMenu" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::TreeAddFile" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::NewFile" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::NewDirectory" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::DeleteFile" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::RenameFile" ) );
|
|
PyHandler::GetInstance()->DeclareEvent( wxT( "kicad::MoveFile" ) );
|
|
#endif
|
|
|
|
for( int i = 0; i < TREE_MAX; i++ )
|
|
m_ContextMenus.push_back( new wxMenu() );
|
|
|
|
// Python script context menu:
|
|
|
|
wxMenu* menu = m_ContextMenus[TREE_PY];
|
|
|
|
#ifdef KICAD_PYTHON
|
|
item = new wxMenuItem( menu, ID_PROJECT_RUNPY,
|
|
_( "&Run" ),
|
|
_( "Run the Python Script" ) );
|
|
|
|
item->SetBitmap( icon_python_small_xpm );
|
|
menu->Append( item );
|
|
#endif
|
|
|
|
item = new wxMenuItem( menu, ID_PROJECT_TXTEDIT,
|
|
_( "&Edit in a text editor" ),
|
|
_( "&Open the file in a Text Editor" ) );
|
|
|
|
item->SetBitmap( icon_txt_xpm );
|
|
menu->Append( item );
|
|
|
|
// New files context menu:
|
|
wxMenu* menus[2];
|
|
menus[0] = m_ContextMenus[TREE_DIRECTORY];
|
|
menus[1] = m_ContextMenus[TREE_PROJECT];
|
|
|
|
for( int i = 0; i < 2; i++ )
|
|
{
|
|
menu = menus[i];
|
|
|
|
item = new wxMenuItem( menu, ID_PROJECT_NEWDIR, _( "New D&irectory" ), _(
|
|
"Create a New Directory" ) );
|
|
|
|
item->SetBitmap( directory_xpm );
|
|
menu->Append( item );
|
|
|
|
#ifdef KICAD_PYTHON
|
|
item = new wxMenuItem( menu, ID_PROJECT_NEWPY, _( "New P&ython Script" ), _(
|
|
"Create a New Python Script" ) );
|
|
|
|
item->SetBitmap( new_python_xpm );
|
|
menu->Append( item );
|
|
#endif
|
|
|
|
item = new wxMenuItem( menu, ID_PROJECT_NEWTXT, _( "New &Text File" ), _(
|
|
"Create a New Txt File" ) );
|
|
|
|
item->SetBitmap( new_txt_xpm );
|
|
menu->Append( item );
|
|
|
|
item = new wxMenuItem( menu, ID_PROJECT_NEWFILE, _( "New &File" ), _( "Create a New File" ) );
|
|
|
|
item->SetBitmap( new_xpm );
|
|
menu->Append( item );
|
|
}
|
|
|
|
// Put the Rename and Delete file menu commands:
|
|
for( int i = TREE_PROJECT + 1; i < TREE_MAX; i++ )
|
|
{
|
|
menu = m_ContextMenus[i];
|
|
item = new wxMenuItem( menu, ID_PROJECT_RENAME,
|
|
TREE_DIRECTORY != i ? _ ("&Rename File") : _( "&Rename Directory" ),
|
|
TREE_DIRECTORY != i ? _ ("Rename the File") : _( "&Rename the Directory" ) );
|
|
|
|
item->SetBitmap( right_xpm );
|
|
menu->Append( item );
|
|
if( TREE_DIRECTORY != i )
|
|
{
|
|
item = new wxMenuItem( menu, ID_PROJECT_TXTEDIT,
|
|
_( "&Edit in a text editor" ),
|
|
_( "Open the file in a Text Editor" ) );
|
|
|
|
item->SetBitmap( icon_txt_xpm );
|
|
menu->Append( item );
|
|
}
|
|
item = new wxMenuItem( menu, ID_PROJECT_DELETE,
|
|
TREE_DIRECTORY != i ? _ ("&Delete File") : _( "&Delete Directory" ),
|
|
TREE_DIRECTORY != i ? _ ("Delete the File") : _(
|
|
"&Delete the Directory and its content" ) );
|
|
|
|
item->SetBitmap( delete_xpm );
|
|
menu->Append( item );
|
|
}
|
|
|
|
ReCreateTreePrj();
|
|
}
|
|
|
|
|
|
BEGIN_EVENT_TABLE( WinEDA_PrjFrame, wxSashLayoutWindow )
|
|
|
|
EVT_TREE_BEGIN_LABEL_EDIT( ID_PROJECT_TREE, WinEDA_PrjFrame::OnRenameAsk )
|
|
EVT_TREE_END_LABEL_EDIT( ID_PROJECT_TREE, WinEDA_PrjFrame::OnRename )
|
|
EVT_TREE_ITEM_ACTIVATED( ID_PROJECT_TREE, WinEDA_PrjFrame::OnSelect )
|
|
EVT_TREE_ITEM_RIGHT_CLICK( ID_PROJECT_TREE, WinEDA_PrjFrame::OnRight )
|
|
EVT_TREE_BEGIN_DRAG( ID_PROJECT_TREE, WinEDA_PrjFrame::OnDragStart )
|
|
EVT_TREE_END_DRAG( ID_PROJECT_TREE, WinEDA_PrjFrame::OnDragEnd )
|
|
EVT_MENU( ID_PROJECT_TXTEDIT, WinEDA_PrjFrame::OnTxtEdit )
|
|
EVT_MENU( ID_PROJECT_NEWFILE, WinEDA_PrjFrame::OnNewFile )
|
|
EVT_MENU( ID_PROJECT_NEWDIR, WinEDA_PrjFrame::OnNewDirectory )
|
|
EVT_MENU( ID_PROJECT_NEWPY, WinEDA_PrjFrame::OnNewPyFile )
|
|
EVT_MENU( ID_PROJECT_NEWTXT, WinEDA_PrjFrame::OnNewTxtFile )
|
|
EVT_MENU( ID_PROJECT_DELETE, WinEDA_PrjFrame::OnDeleteFile )
|
|
EVT_MENU( ID_PROJECT_RENAME, WinEDA_PrjFrame::OnRenameFile )
|
|
|
|
#ifdef KICAD_PYTHON
|
|
EVT_MENU( ID_PROJECT_RUNPY, WinEDA_PrjFrame::OnRunPy )
|
|
#endif
|
|
END_EVENT_TABLE()
|
|
|
|
/********************************/
|
|
WinEDA_TreePrj::~WinEDA_TreePrj()
|
|
/********************************/
|
|
{
|
|
}
|
|
|
|
|
|
/*******************************************************/
|
|
void WinEDA_PrjFrame::OnDragStart( wxTreeEvent& event )
|
|
/*******************************************************/
|
|
|
|
// Allowing drag&drop of file other than the currently opened project
|
|
{
|
|
/* Ensure item is selected (Under Windows start drag does not activate the item) */
|
|
wxTreeItemId curr_item = event.GetItem();
|
|
|
|
m_TreeProject->SelectItem( curr_item );
|
|
TreePrjItemData* data = GetSelectedData();
|
|
if( data->GetFileName() == m_Parent->m_PrjFileName )
|
|
return;
|
|
|
|
wxTreeItemId id = m_TreeProject->GetSelection();
|
|
|
|
wxImage img = m_TreeProject->GetImageList()->GetBitmap( data->GetType() -
|
|
1 ).ConvertToImage();
|
|
m_DragCursor = wxCursor( img );
|
|
m_Parent->wxWindow::SetCursor( (wxCursor &)m_DragCursor );
|
|
event.Allow();
|
|
}
|
|
|
|
|
|
/*******************************************************/
|
|
void WinEDA_PrjFrame::OnDragEnd( wxTreeEvent& event )
|
|
/*******************************************************/
|
|
{
|
|
m_Parent->SetCursor( wxNullCursor );
|
|
|
|
wxTreeItemId moved = m_TreeProject->GetSelection();
|
|
TreePrjItemData* source_data = GetSelectedData();
|
|
wxTreeItemId dest = event.GetItem();
|
|
if( !dest.IsOk() )
|
|
return; // Cancelled ...
|
|
TreePrjItemData* destData = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData( dest ) );
|
|
if( !destData )
|
|
return;
|
|
|
|
// the item can be a member of the selected directory; get the directory itself
|
|
if( TREE_DIRECTORY != destData->GetType() && !m_TreeProject->ItemHasChildren( dest ) )
|
|
{ // the item is a member of the selected directory; get the directory itself
|
|
dest = m_TreeProject->GetItemParent( dest );
|
|
if( !dest.IsOk() )
|
|
return; // no parent ?
|
|
|
|
// Select the right destData:
|
|
destData = dynamic_cast<TreePrjItemData*>( m_TreeProject->GetItemData( dest ) );
|
|
if( !destData )
|
|
return;
|
|
}
|
|
|
|
source_data->Move( destData );
|
|
|
|
#if 0
|
|
/* Sort filenames by alphabetic order */
|
|
m_TreeProject->SortChildren( dest );
|
|
#endif
|
|
}
|
|
|
|
|
|
/************************************/
|
|
void WinEDA_PrjFrame::ClearFilters()
|
|
/************************************/
|
|
{
|
|
m_Filters.clear();
|
|
}
|
|
|
|
|
|
/*************************************************************/
|
|
void WinEDA_PrjFrame::RemoveFilter( const wxString& filter )
|
|
/*************************************************************/
|
|
{
|
|
for( unsigned int i = 0; i < m_Filters.size(); i++ )
|
|
{
|
|
if( filter == m_Filters[i] )
|
|
{
|
|
m_Filters.erase( m_Filters.begin() + i );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef KICAD_PYTHON
|
|
|
|
/********************************************************************************/
|
|
TreePrjItemData* WinEDA_PrjFrame::FindItemData( const boost::python::str& name )
|
|
/********************************************************************************/
|
|
|
|
// Return the data corresponding to the file, or NULL
|
|
{
|
|
// (Interative tree parsing)
|
|
std::vector< wxTreeItemId > roots1, roots2;
|
|
std::vector< wxTreeItemId > * root, * reserve;
|
|
wxString filename = PyHandler::MakeStr( name );
|
|
|
|
root = &roots1;
|
|
reserve = &roots2;
|
|
|
|
root->push_back( m_TreeProject->GetRootItem() );
|
|
|
|
// if we look for the root, return it ...
|
|
TreePrjItemData* data = dynamic_cast< TreePrjItemData*>(
|
|
m_TreeProject->GetItemData( root->at( 0 ) ) );
|
|
|
|
if( data->GetFileName() == filename )
|
|
return data;
|
|
|
|
// Then find in its child
|
|
while( root->size() )
|
|
{
|
|
// look in all roots
|
|
for( unsigned int i = 0; i < root->size(); i++ )
|
|
{
|
|
wxTreeItemId id = root->at( i );
|
|
|
|
// for each root check any child:
|
|
void* cookie = NULL;
|
|
wxTreeItemId child = m_TreeProject->GetFirstChild( id, cookie );
|
|
|
|
while( child.IsOk() )
|
|
{
|
|
TreePrjItemData* data = dynamic_cast< TreePrjItemData*>(
|
|
m_TreeProject->GetItemData( child ) );
|
|
|
|
if( data )
|
|
{
|
|
if( data->GetFileName() == filename )
|
|
return data;
|
|
if( m_TreeProject->ItemHasChildren( child ) )
|
|
reserve->push_back( child );
|
|
}
|
|
child = m_TreeProject->GetNextSibling( child );
|
|
}
|
|
}
|
|
|
|
// Swap the roots
|
|
root->clear();
|
|
std::vector< wxTreeItemId > * tmp;
|
|
tmp = root;
|
|
root = reserve;
|
|
reserve = tmp;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
void WinEDA_PrjFrame::RemoveFilterPy( const boost::python::str& filter )
|
|
/******************************************************************/
|
|
{
|
|
RemoveFilter( PyHandler::MakeStr( filter ) );
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
void WinEDA_PrjFrame::AddFilter( const boost::python::str& filter )
|
|
/******************************************************************/
|
|
{
|
|
wxRegEx reg;
|
|
wxString text = PyHandler::MakeStr( filter );
|
|
|
|
if( !reg.Compile( text ) )
|
|
return;
|
|
m_Filters.push_back( text );
|
|
}
|
|
|
|
#endif
|
|
|
|
/******************************************************************/
|
|
const std::vector<wxString>& WinEDA_PrjFrame::GetFilters()
|
|
/******************************************************************/
|
|
{
|
|
return m_Filters;
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
wxMenu* WinEDA_PrjFrame::GetContextMenu( int type )
|
|
/******************************************************************/
|
|
{
|
|
return m_ContextMenus[type];
|
|
}
|
|
|
|
|
|
void WinEDA_PrjFrame::OnNewDirectory( wxCommandEvent& event )
|
|
{
|
|
NewFile( TREE_DIRECTORY );
|
|
}
|
|
void WinEDA_PrjFrame::OnNewFile( wxCommandEvent& event )
|
|
{
|
|
NewFile( TREE_UNKNOWN );
|
|
}
|
|
void WinEDA_PrjFrame::OnNewPyFile( wxCommandEvent& event )
|
|
{
|
|
NewFile( TREE_PY );
|
|
}
|
|
void WinEDA_PrjFrame::OnNewTxtFile( wxCommandEvent& event )
|
|
{
|
|
NewFile( TREE_TXT );
|
|
}
|
|
|
|
/******************************************************************/
|
|
void WinEDA_PrjFrame::NewFile( TreeFileType type )
|
|
/******************************************************************/
|
|
{
|
|
wxString filename;
|
|
wxString mask = GetFileExt( type );
|
|
const wxString sep = wxFileName().GetPathSeparator();
|
|
|
|
// Get the directory:
|
|
wxString dir;
|
|
|
|
TreePrjItemData* treeData;
|
|
wxString FullFileName;
|
|
|
|
treeData = GetSelectedData();
|
|
if( !treeData )
|
|
return;
|
|
|
|
dir = treeData->GetDir();
|
|
|
|
// Ask for the new file name
|
|
|
|
filename = EDA_FileSelector( TREE_DIRECTORY !=
|
|
type ? _( "Create New File:" ) : _( "Create New Directory" ),
|
|
wxGetCwd() + sep + dir, /* Chemin par defaut */
|
|
_( "noname" ) + mask, /* nom fichier par defaut */
|
|
mask, /* extension par defaut */
|
|
mask, /* Masque d'affichage */
|
|
this,
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
|
|
TRUE
|
|
);
|
|
if( filename.IsEmpty() )
|
|
return;
|
|
|
|
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,
|
|
TreeFileType type, wxTreeItemId& root )
|
|
/******************************************************************/
|
|
{
|
|
if( TREE_DIRECTORY != type )
|
|
{
|
|
wxFile( name, wxFile::write );
|
|
#ifdef KICAD_PYTHON
|
|
PyHandler::GetInstance()->TriggerEvent(
|
|
wxT( "kicad::NewFile" ), PyHandler::Convert( name ) );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
wxMkdir( name );
|
|
#ifdef KICAD_PYTHON
|
|
PyHandler::GetInstance()->TriggerEvent(
|
|
wxT( "kicad::NewDirectory" ), PyHandler::Convert( name ) );
|
|
#endif
|
|
}
|
|
|
|
AddFile( name, root );
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
wxString WinEDA_PrjFrame::GetFileExt( TreeFileType type )
|
|
/******************************************************************/
|
|
{
|
|
wxString ext;
|
|
|
|
switch( type )
|
|
{
|
|
case 0:
|
|
break; // 0 is not used
|
|
|
|
case TREE_PROJECT:
|
|
ext = wxT( ".pro" );
|
|
break;
|
|
|
|
case TREE_SCHEMA:
|
|
ext = g_SchExtBuffer;
|
|
break;
|
|
|
|
case TREE_PCB:
|
|
ext = g_BoardExtBuffer;
|
|
break;
|
|
|
|
case TREE_PY:
|
|
ext = wxT( ".py" );
|
|
break;
|
|
|
|
case TREE_GERBER:
|
|
ext = g_GerberExtBuffer;
|
|
break;
|
|
|
|
case TREE_PDF:
|
|
ext = wxT( ".pdf" );
|
|
break;
|
|
|
|
case TREE_TXT:
|
|
ext = wxT( ".txt" );
|
|
break;
|
|
|
|
case TREE_NET:
|
|
ext = wxT( ".net" );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ext;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
bool WinEDA_PrjFrame::AddFile( const wxString& name, wxTreeItemId& root )
|
|
/**************************************************************************/
|
|
|
|
/* add filename "name" to the tree
|
|
* if name is a directory, add the sub directory file names
|
|
*/
|
|
{
|
|
wxTreeItemId cellule;
|
|
|
|
// Check the file type
|
|
TreeFileType type = TREE_UNKNOWN;
|
|
|
|
if( wxDirExists( name ) )
|
|
{
|
|
type = TREE_DIRECTORY;
|
|
}
|
|
else
|
|
{
|
|
// Filter
|
|
wxRegEx reg;
|
|
|
|
bool isSchematic=false;
|
|
bool addFile=false;
|
|
for( unsigned i=0; i < m_Filters.size(); i++ )
|
|
{
|
|
reg.Compile( m_Filters[i], wxRE_ICASE );
|
|
if( reg.Matches( name ) )
|
|
{
|
|
addFile=true;
|
|
if( i==0 )
|
|
isSchematic = true;
|
|
}
|
|
}
|
|
if( !addFile )
|
|
return false;
|
|
|
|
// only show the schematic if it is a top level schematic. eeschema
|
|
// cannot open a schematic and display it properly unless it starts
|
|
// at the top of the hierarchy. The schematic is top level only if
|
|
// there is a line in the header saying:
|
|
// "Sheet 1 "
|
|
if( isSchematic )
|
|
{
|
|
char line[128]; // small because we just need a few bytes from the start of a line
|
|
FILE* fp;
|
|
|
|
wxString FullFileName = name;
|
|
|
|
fp = wxFopen( FullFileName, wxT( "rt" ) );
|
|
if( fp == NULL )
|
|
{
|
|
//printf("Unable to open \"%s\"\n", (const char*) FullFileName.mb_str() );
|
|
return false; // why show a file we cannot open?
|
|
}
|
|
|
|
addFile = false;
|
|
for( int i=0; i<20; ++i )
|
|
{
|
|
if( !fgets( line, sizeof(line), fp ) )
|
|
break;
|
|
|
|
if( !strncmp( line, "Sheet 1 ", 8 ) )
|
|
{
|
|
addFile = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
if( !addFile )
|
|
return false; // it is a non-top-level schematic
|
|
}
|
|
|
|
for( int i = TREE_PROJECT; i < TREE_MAX; i++ )
|
|
{
|
|
wxString ext = GetFileExt( (TreeFileType) i );
|
|
|
|
if( ext == wxT( "" ) )
|
|
continue;
|
|
|
|
reg.Compile( wxString::FromAscii( "^.*\\" ) + ext +
|
|
wxString::FromAscii("$" ), wxRE_ICASE );
|
|
|
|
if( reg.Matches( name ) )
|
|
{
|
|
type = (TreeFileType) i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//also check to see if it is already there.
|
|
wxTreeItemIdValue cookie;
|
|
wxTreeItemId kid = m_TreeProject->GetFirstChild(root, cookie);
|
|
while(kid.IsOk())
|
|
{
|
|
TreePrjItemData* itemData = (TreePrjItemData*)
|
|
m_TreeProject->GetItemData(kid);
|
|
if( itemData ){
|
|
if( itemData->m_FileName == name ){
|
|
return true; //well, we would have added it, but it is already here!
|
|
}
|
|
}
|
|
kid = m_TreeProject->GetNextChild(root, cookie);
|
|
}
|
|
// Append the item (only appending the filename not the full path):
|
|
|
|
wxString file = wxFileNameFromPath( name );
|
|
cellule = m_TreeProject->AppendItem( root, file );
|
|
TreePrjItemData* data = new TreePrjItemData( type, name, m_TreeProject );
|
|
|
|
m_TreeProject->SetItemFont( cellule, *g_StdFont );
|
|
m_TreeProject->SetItemData( cellule, data );
|
|
data->SetState( 0 );
|
|
|
|
/* Mark root files (files which have the same name as the project) */
|
|
wxFileName project( m_Parent->m_PrjFileName );
|
|
wxFileName currfile( file );
|
|
|
|
if( currfile.GetName().CmpNoCase( project.GetName() ) == 0 )
|
|
data->m_IsRootFile = true;
|
|
else
|
|
data->m_IsRootFile = false;
|
|
|
|
#ifdef KICAD_PYTHON
|
|
PyHandler::GetInstance()->TriggerEvent( wxT( "kicad::TreeAddFile" ), PyHandler::Convert( name ) );
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
/******************************************/
|
|
void WinEDA_PrjFrame::ReCreateTreePrj()
|
|
/******************************************/
|
|
|
|
/* Create or modify the tree showing project file names
|
|
*/
|
|
{
|
|
wxTreeItemId rootcellule;
|
|
wxString Text;
|
|
bool prjOpened = false;
|
|
|
|
if( !m_TreeProject )
|
|
m_TreeProject = new WinEDA_TreePrj( this );
|
|
else
|
|
m_TreeProject->DeleteAllItems();
|
|
|
|
m_TreeProject->SetFont( *g_StdFont );
|
|
|
|
if( m_Parent->m_PrjFileName.IsEmpty() )
|
|
Text = wxT( "noname" );
|
|
else
|
|
Text = wxFileNameFromPath( m_Parent->m_PrjFileName );
|
|
|
|
prjOpened = wxFileExists( Text );
|
|
|
|
// 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 ) );
|
|
|
|
m_TreeProject->SetItemFont( rootcellule, *g_StdFont );
|
|
|
|
ChangeFileNameExt( Text, wxEmptyString );
|
|
|
|
// Add at least a .scn / .brd if not existing:
|
|
if( !wxFileExists( Text + g_SchExtBuffer ) )
|
|
AddFile( Text + g_SchExtBuffer, m_root );
|
|
|
|
if( !wxFileExists( Text + g_BoardExtBuffer ) )
|
|
AddFile( Text + g_BoardExtBuffer, m_root );
|
|
|
|
// Now adding all current files if available
|
|
if( prjOpened )
|
|
{
|
|
wxDir dir( wxGetCwd() );
|
|
wxString dir_str = dir.GetName();
|
|
wxString sep = wxFileName().GetPathSeparator();
|
|
wxString filename;
|
|
|
|
if( dir.GetFirst( &filename ) )
|
|
{
|
|
do
|
|
{
|
|
if( filename == Text + wxT( ".pro" ) )
|
|
continue;
|
|
|
|
AddFile(dir_str + sep + filename, m_root );
|
|
|
|
} while( dir.GetNext( &filename ) );
|
|
}
|
|
}
|
|
|
|
m_TreeProject->Expand( rootcellule );
|
|
|
|
/* Sort filenames by alphabetic order */
|
|
m_TreeProject->SortChildren( m_root );
|
|
}
|
|
|
|
|
|
/**************************************************/
|
|
void WinEDA_PrjFrame::OnRight( wxTreeEvent& Event )
|
|
/**************************************************/
|
|
|
|
// Opens (popup) the context menu
|
|
{
|
|
int tree_id;
|
|
TreePrjItemData* tree_data;
|
|
wxString FullFileName;
|
|
wxTreeItemId curr_item = Event.GetItem();
|
|
|
|
/* Ensure item is selected (Under Windows right click does not select the item) */
|
|
m_TreeProject->SelectItem( curr_item );
|
|
|
|
// Delete and recreate the context menu
|
|
delete( m_PopupMenu );
|
|
m_PopupMenu = new wxMenu();
|
|
|
|
// Get the current filename:
|
|
tree_data = GetSelectedData();
|
|
if( !tree_data )
|
|
return;
|
|
|
|
tree_id = tree_data->GetType();
|
|
FullFileName = tree_data->GetFileName();
|
|
|
|
// copy menu contents in order of the next array:
|
|
wxMenu* menus[] =
|
|
{
|
|
GetContextMenu( tree_id ),
|
|
const_cast<wxMenu*>( tree_data->GetMenu() )
|
|
};
|
|
|
|
for( unsigned int j=0; j < sizeof(menus)/sizeof(wxMenu*); j++ )
|
|
{
|
|
wxMenu* menu = menus[j];
|
|
if( !menu )
|
|
continue;
|
|
|
|
wxMenuItemList list = menu->GetMenuItems();
|
|
|
|
for( unsigned int i = 0; i < list.GetCount(); i++ )
|
|
{
|
|
// Grrrr! wxMenu does not have any copy constructor !! (do it by hand)
|
|
wxMenuItem* src = list[i];
|
|
wxString label = src->GetText();
|
|
|
|
// for obscure reasons, the & is translated into _ ... so replace it
|
|
label.Replace( wxT( "_" ), wxT( "&" ), true );
|
|
wxMenuItem* item = new wxMenuItem( m_PopupMenu, src->GetId(),
|
|
label, src->GetHelp(), src->GetKind() );
|
|
|
|
item->SetBitmap( src->GetBitmap() );
|
|
m_PopupMenu->Append( item );
|
|
}
|
|
}
|
|
|
|
// At last, call python to let python add menu items "on the fly"
|
|
|
|
#ifdef KICAD_PYTHON
|
|
PyHandler::GetInstance()->TriggerEvent( wxT( "kicad::TreeContextMenu" ),
|
|
PyHandler::Convert( FullFileName ) );
|
|
#endif
|
|
|
|
if( m_PopupMenu )
|
|
PopupMenu( m_PopupMenu );
|
|
}
|
|
|
|
|
|
/*******************************************************/
|
|
void WinEDA_PrjFrame::OnTxtEdit( wxCommandEvent& event )
|
|
/*******************************************************/
|
|
{
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
|
|
wxString FullFileName = tree_data->GetFileName();
|
|
AddDelimiterString( FullFileName );
|
|
wxString editorname = GetEditorName();
|
|
if( !editorname.IsEmpty() )
|
|
{
|
|
#ifdef KICAD_PYTHON
|
|
PyHandler::GetInstance()->TriggerEvent( wxT( "kicad::EditScript" ),
|
|
PyHandler::Convert( FullFileName ) );
|
|
#endif
|
|
ExecuteFile( this, editorname, FullFileName );
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************/
|
|
void WinEDA_PrjFrame::OnDeleteFile( wxCommandEvent& )
|
|
/***************************************************/
|
|
{
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
tree_data->Delete();
|
|
}
|
|
|
|
|
|
/***************************************************/
|
|
void WinEDA_PrjFrame::OnRenameFile( wxCommandEvent& )
|
|
/***************************************************/
|
|
{
|
|
wxTreeItemId curr_item = m_TreeProject->GetSelection();
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
|
|
wxString buffer = m_TreeProject->GetItemText( curr_item );
|
|
wxString msg = _( "Change File Name: " ) + tree_data->m_FileName;
|
|
if( Get_Message( msg, buffer, this ) != 0 )
|
|
return; //Abort command
|
|
|
|
if( tree_data->Rename( buffer, true ) )
|
|
{
|
|
m_TreeProject->SetItemText( curr_item, buffer );
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef KICAD_PYTHON
|
|
/***************************************************/
|
|
void WinEDA_PrjFrame::OnRunPy( wxCommandEvent& event )
|
|
/***************************************************/
|
|
{
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
|
|
wxString FullFileName = tree_data->GetFileName();
|
|
PyHandler::GetInstance()->TriggerEvent( wxT( "kicad::RunScript" ),
|
|
PyHandler::Convert( FullFileName ) );
|
|
PyHandler::GetInstance()->RunScript( FullFileName );
|
|
}
|
|
|
|
|
|
/****************************************************************/
|
|
int WinEDA_PrjFrame::AddStatePy( boost::python::object& bitmap )
|
|
/****************************************************************/
|
|
|
|
// Add a state to the image list ...
|
|
{
|
|
wxBitmap* image;
|
|
bool success = wxPyConvertSwigPtr( bitmap.ptr(), (void**) &image, _T( "wxBitmap" ) );
|
|
|
|
if( !success )
|
|
return -1;
|
|
|
|
wxImageList* list = m_TreeProject->GetImageList();
|
|
int ret = list->GetImageCount() / ( TREE_MAX - 2 );
|
|
|
|
for( int i = 0; i < TREE_MAX - 1; i++ )
|
|
{
|
|
wxBitmap composed( list->GetBitmap ( i ) );
|
|
|
|
wxMemoryDC dc;
|
|
dc.SelectObject( composed );
|
|
dc.DrawBitmap( *image, 0, 0, true );
|
|
list->Add( composed );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
/***************************************************/
|
|
void WinEDA_PrjFrame::OnRenameAsk( wxTreeEvent& event )
|
|
/***************************************************/
|
|
/* Prevent the main project to be renamed */
|
|
{
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
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 */
|
|
{
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
|
|
tree_data->OnRename( event );
|
|
}
|
|
|
|
|
|
/**************************************************/
|
|
void WinEDA_PrjFrame::OnSelect( wxTreeEvent& Event )
|
|
/**************************************************/
|
|
{
|
|
wxString FullFileName;
|
|
|
|
TreePrjItemData* tree_data = GetSelectedData();
|
|
|
|
if( !tree_data )
|
|
return;
|
|
tree_data->Activate(this);
|
|
}
|