From 45b01a5c9cb30ad6dd9b4de3b653cd64de09c36f Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 31 Dec 2012 09:12:29 +0100 Subject: [PATCH] Kicad manager: first use of wxFileSystemWatcher (only with wxWidgets >= 2.9.2) to monitor files list. --- kicad/class_treeproject_item.cpp | 192 ++++++----- kicad/class_treeproject_item.h | 43 +-- kicad/class_treeprojectfiles.cpp | 2 +- kicad/mainframe.cpp | 3 +- kicad/prjconfig.cpp | 16 +- kicad/project_template.cpp | 3 +- kicad/tree_project_frame.cpp | 550 +++++++++++++++++++------------ kicad/tree_project_frame.h | 135 +++++--- 8 files changed, 572 insertions(+), 372 deletions(-) diff --git a/kicad/class_treeproject_item.cpp b/kicad/class_treeproject_item.cpp index 1a86ba9a02..c8dfb3f175 100644 --- a/kicad/class_treeproject_item.cpp +++ b/kicad/class_treeproject_item.cpp @@ -1,10 +1,34 @@ /** * @file class_treeproject_item.cpp * - * Class TREEPROJECT_ITEM is a derived class from wxTreeItemData that + * @brief Class TREEPROJECT_ITEM is a derived class from wxTreeItemData and * store info about a file or directory shown in the KiCad tree project files */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + #include #include #include @@ -18,37 +42,30 @@ #include #include -/* sort function for tree items. - * items are sorted : - * directory names first by alphabetic order - * root file names after - * file names last by alphabetic order - */ - - - TREEPROJECT_ITEM::TREEPROJECT_ITEM( enum TreeFileType type, const wxString& data, - wxTreeCtrl* parent ) : + wxTreeCtrl* parent ) : wxTreeItemData() { - m_Type = type; - m_Parent = parent; - m_FileName = data; - m_IsRootFile = false; // true only for the root item of the tree (the project name) - m_WasPopulated = false; + m_Type = type; + m_parent = parent; + m_FileName = data; + m_IsRootFile = false; // true only for the root item of the tree (the project name) + m_WasPopulated = false; } + // Set the state used in the icon list void TREEPROJECT_ITEM::SetState( int state ) { - wxImageList* imglist = m_Parent->GetImageList(); + wxImageList* imglist = m_parent->GetImageList(); if( !imglist || state < 0 || state >= imglist->GetImageCount() / ( TREE_MAX - 2 ) ) return; - m_State = state; + + m_state = state; int imgid = m_Type - 1 + state * ( TREE_MAX - 1 ); - m_Parent->SetItemImage( GetId(), imgid ); - m_Parent->SetItemImage( GetId(), imgid, wxTreeItemIcon_Selected ); + m_parent->SetItemImage( GetId(), imgid ); + m_parent->SetItemImage( GetId(), imgid, wxTreeItemIcon_Selected ); } @@ -62,9 +79,10 @@ wxString TREEPROJECT_ITEM::GetDir() const filename.MakeRelativeTo( wxGetCwd() ); - wxArrayString dirs = filename.GetDirs(); + wxArrayString dirs = filename.GetDirs(); + + wxString dir; - wxString dir; for( unsigned int i = 0; i < dirs.Count(); i++ ) { dir += dirs[i] + filename.GetPathSeparator(); @@ -74,49 +92,42 @@ wxString TREEPROJECT_ITEM::GetDir() const } -/* Called upon tree item rename */ -void TREEPROJECT_ITEM::OnRename( wxTreeEvent& event, bool check ) -{ - //this segfaults on linux (in wxEvtHandler::ProcessEvent), wx version 2.8.7 - //therefore, until it is fixed, we must cancel the rename. - event.Veto(); - return; - - if( !Rename( event.GetLabel(), check ) ) - event.Veto(); -} - - // Move the object to dest void TREEPROJECT_ITEM::Move( TREEPROJECT_ITEM* dest ) { - //function not safe. + // function not safe. return; const wxString sep = wxFileName().GetPathSeparator(); if( m_Type == TREE_DIRECTORY ) return; + if( !dest ) return; - if( m_Parent != dest->m_Parent ) + + if( m_parent != dest->m_parent ) return; // Can not cross move! + if( dest == this ) return; // Can not move to ourself... - wxTreeItemId parent = m_Parent->GetItemParent( GetId() ); - if( dest == dynamic_cast( m_Parent->GetItemData( parent ) ) ) + wxTreeItemId parent = m_parent->GetItemParent( GetId() ); + + if( dest == dynamic_cast( m_parent->GetItemData( parent ) ) ) return; // same parent ? // We need to create a new item from us, and move // data to there ... // First move file on the disk - wxFileName fname( m_FileName ); + wxFileName fname( m_FileName ); + + wxString destName; - wxString destName; if( !dest->GetDir().IsEmpty() ) destName = dest->GetDir() + sep; + destName += fname.GetFullName(); if( destName == GetFileName() ) @@ -125,7 +136,7 @@ void TREEPROJECT_ITEM::Move( TREEPROJECT_ITEM* dest ) // Move the file on the disk: if( !wxRenameFile( GetFileName(), destName, false ) ) { - wxMessageDialog( m_Parent, _( "Unable to move file ... " ), + wxMessageDialog( m_parent, _( "Unable to move file ... " ), _( "Permission error ?" ), wxICON_ERROR | wxOK ); return; } @@ -135,39 +146,38 @@ void TREEPROJECT_ITEM::Move( TREEPROJECT_ITEM* dest ) if( TREE_DIRECTORY != GetType() ) { // Move the tree item itself now: - wxTreeItemId oldId = GetId(); - int i = m_Parent->GetItemImage( oldId ); - wxString text = m_Parent->GetItemText( oldId ); + wxTreeItemId oldId = GetId(); + int i = m_parent->GetItemImage( oldId ); + wxString text = m_parent->GetItemText( oldId ); // Bye bye old Id :'( - wxTreeItemId newId = m_Parent->AppendItem( dest->GetId(), text, i ); - m_Parent->SetItemData( newId, this ); - m_Parent->SetItemData( oldId, NULL ); - m_Parent->Delete( oldId ); + wxTreeItemId newId = m_parent->AppendItem( dest->GetId(), text, i ); + m_parent->SetItemData( newId, this ); + m_parent->SetItemData( oldId, NULL ); + m_parent->Delete( oldId ); } else { // We should move recursively all files, but that's quite boring // let's just refresh that's all ... TODO (change this to a better code ...) wxCommandEvent dummy; - dynamic_cast( m_Parent )->GetParent()->m_Parent->OnRefresh( dummy ); + dynamic_cast( m_parent )->GetParent()->m_Parent->OnRefresh( dummy ); } } - /* rename the file checking if extension change occurs */ bool TREEPROJECT_ITEM::Rename( const wxString& name, bool check ) { - //this is broken & unsafe to use on linux. + // this is broken & unsafe to use on linux. if( m_Type == TREE_DIRECTORY ) return false; if( name.IsEmpty() ) return false; - const wxString sep = wxFileName().GetPathSeparator(); - wxString newFile; - wxString dirs = GetDir(); + const wxString sep = wxFileName().GetPathSeparator(); + wxString newFile; + wxString dirs = GetDir(); if( !dirs.IsEmpty() && GetType() != TREE_DIRECTORY ) newFile = dirs + sep + name; @@ -177,15 +187,16 @@ bool TREEPROJECT_ITEM::Rename( const wxString& name, bool check ) if( newFile == m_FileName ) return false; - wxString ext = TREE_PROJECT_FRAME::GetFileExt( GetType() ); + wxString ext = TREE_PROJECT_FRAME::GetFileExt( GetType() ); - wxRegEx reg( wxT ( "^.*\\" ) + ext + wxT( "$" ), wxRE_ICASE ); + 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 ?" ), + wxMessageDialog dialog( m_parent, + _( + "Changing file extension will change file \ +type.\n Do you want to continue ?" ), _( "Rename File" ), wxYES_NO | wxICON_QUESTION ); @@ -194,16 +205,19 @@ type.\n Do you want to continue ?" ), } #if ( ( wxMAJOR_VERSION < 2 ) || ( ( wxMAJOR_VERSION == 2 ) \ - && ( wxMINOR_VERSION < 7 ) ) ) + && ( wxMINOR_VERSION < 7 ) ) ) + if( !wxRenameFile( m_FileName, newFile ) ) #else + if( !wxRenameFile( m_FileName, newFile, false ) ) #endif { - wxMessageDialog( m_Parent, _( "Unable to rename file ... " ), + wxMessageDialog( m_parent, _( "Unable to rename file ... " ), _( "Permission error ?" ), wxICON_ERROR | wxOK ); return false; } + SetFileName( newFile ); return true; @@ -215,17 +229,18 @@ bool TREEPROJECT_ITEM::Delete( bool check ) /*******************************************/ /* delete a file */ { - wxString msg; - msg.Printf( _("Do you really want to delete '%s'"), GetChars(GetFileName() ) ); - wxMessageDialog dialog( m_Parent, msg, + wxString msg; + + msg.Printf( _( "Do you really want to delete '%s'" ), GetChars( GetFileName() ) ); + wxMessageDialog dialog( m_parent, msg, _( "Delete File" ), wxYES_NO | wxICON_QUESTION ); if( !check || wxID_YES == dialog.ShowModal() ) { + bool success; + if( !wxDirExists( m_FileName ) ) - { - wxRemoveFile( m_FileName ); - } + success = wxRemoveFile( m_FileName ); else { wxArrayString filelist; @@ -235,12 +250,15 @@ bool TREEPROJECT_ITEM::Delete( bool check ) for( unsigned int i = 0; i < filelist.Count(); i++ ) wxRemoveFile( filelist[i] ); - wxRmdir( m_FileName ); + success = wxRmdir( m_FileName ); } - m_Parent->Delete( GetId() ); - return true; + if( success ) + m_parent->Delete( GetId() ); + + return success; } + return false; } @@ -248,31 +266,32 @@ bool TREEPROJECT_ITEM::Delete( bool check ) /* Called under item activation */ void TREEPROJECT_ITEM::Activate( TREE_PROJECT_FRAME* prjframe ) { - wxString sep = wxFileName().GetPathSeparator(); - wxString FullFileName = GetFileName(); - wxTreeItemId id = GetId(); + wxString sep = wxFileName().GetPathSeparator(); + wxString FullFileName = GetFileName(); + wxTreeItemId id = GetId(); AddDelimiterString( FullFileName ); + switch( GetType() ) { case TREE_PROJECT: break; case TREE_DIRECTORY: - m_Parent->Toggle( id ); + m_parent->Toggle( id ); break; case TREE_SCHEMA: - ExecuteFile( m_Parent, EESCHEMA_EXE, FullFileName ); + ExecuteFile( m_parent, EESCHEMA_EXE, FullFileName ); break; case TREE_LEGACY_PCB: case TREE_SEXP_PCB: - ExecuteFile( m_Parent, PCBNEW_EXE, FullFileName ); + ExecuteFile( m_parent, PCBNEW_EXE, FullFileName ); break; case TREE_GERBER: - ExecuteFile( m_Parent, GERBVIEW_EXE, FullFileName ); + ExecuteFile( m_parent, GERBVIEW_EXE, FullFileName ); break; case TREE_PDF: @@ -280,20 +299,21 @@ void TREEPROJECT_ITEM::Activate( TREE_PROJECT_FRAME* prjframe ) break; case TREE_NET: - ExecuteFile( m_Parent, CVPCB_EXE, FullFileName ); + ExecuteFile( m_parent, CVPCB_EXE, FullFileName ); break; case TREE_TXT: - { - wxString editorname = wxGetApp().GetEditorName(); - if( !editorname.IsEmpty() ) - ExecuteFile( m_Parent, editorname, FullFileName ); - break; - } + { + wxString editorname = wxGetApp().GetEditorName(); + + if( !editorname.IsEmpty() ) + ExecuteFile( m_parent, editorname, FullFileName ); + + break; + } default: OpenFile( FullFileName ); break; } } - diff --git a/kicad/class_treeproject_item.h b/kicad/class_treeproject_item.h index 8942574c42..059391324a 100644 --- a/kicad/class_treeproject_item.h +++ b/kicad/class_treeproject_item.h @@ -9,28 +9,24 @@ class TREEPROJECT_ITEM : public wxTreeItemData { public: - TreeFileType m_Type; // = TREE_PROJECT, TREE_DIRECTORY ... - wxString m_FileName; // Filename for a file, or directory name - bool m_IsRootFile; // True if m_Filename is a root schematic (same name as project) - bool m_WasPopulated; // True the name is a directory, and its containt was read - + TreeFileType m_Type; // = TREE_PROJECT, TREE_DIRECTORY ... + wxString m_FileName; // Filename for a file, or directory name + bool m_IsRootFile; // True if m_Filename is a root schematic (same name as project) + bool m_WasPopulated; // True the name is a directory, and its content was read private: - wxTreeCtrl* m_Parent; - wxMenu m_fileMenu; - int m_State; - + wxTreeCtrl* m_parent; + wxMenu m_fileMenu; + int m_state; public: TREEPROJECT_ITEM( TreeFileType type, const wxString& data, wxTreeCtrl* parent ); - TREEPROJECT_ITEM() : m_Parent( NULL ) { } + TREEPROJECT_ITEM() : m_parent( NULL ) { } TREEPROJECT_ITEM( const TREEPROJECT_ITEM& src ) : - m_Type( src.m_Type ), - m_FileName( src.m_FileName ), - m_Parent( src.m_Parent ) + m_Type( src.m_Type ), m_FileName( src.m_FileName ), m_parent( src.m_parent ) { - SetState( src.m_State ); + SetState( src.m_state ); m_WasPopulated = false; } @@ -39,39 +35,32 @@ public: return m_Type; } - void SetType( TreeFileType aType ) { m_Type = aType; } - wxString GetFileName() const { return m_FileName; } - void SetFileName( const wxString& name ) { m_FileName = name; } + wxString GetDir() const; - wxString GetDir() const; - - void OnRename( wxTreeEvent& event, bool check = true ); - bool Rename( const wxString& name, bool check = true ); - bool Delete( bool check = true ); - void Move( TREEPROJECT_ITEM* dest ); - void Activate( TREE_PROJECT_FRAME* prjframe ); + bool Rename( const wxString& name, bool check = true ); + bool Delete( bool check = true ); + void Move( TREEPROJECT_ITEM* dest ); + void Activate( TREE_PROJECT_FRAME* prjframe ); const wxMenu* GetMenu() { return &m_fileMenu; } - - void SetState( int state ); - + void SetState( int state ); }; diff --git a/kicad/class_treeprojectfiles.cpp b/kicad/class_treeprojectfiles.cpp index 5f3c0e89d2..0a3b909a65 100644 --- a/kicad/class_treeprojectfiles.cpp +++ b/kicad/class_treeprojectfiles.cpp @@ -45,7 +45,7 @@ IMPLEMENT_ABSTRACT_CLASS( TREEPROJECTFILES, wxTreeCtrl ) TREEPROJECTFILES::TREEPROJECTFILES( TREE_PROJECT_FRAME* parent ) : wxTreeCtrl( parent, ID_PROJECT_TREE, wxDefaultPosition, wxDefaultSize, - wxTR_HAS_BUTTONS | wxTR_EDIT_LABELS, wxDefaultValidator, + wxTR_HAS_BUTTONS, wxDefaultValidator, wxT( "EDATreeCtrl" ) ) { m_Parent = parent; diff --git a/kicad/mainframe.cpp b/kicad/mainframe.cpp index 2bd8cb5426..dd06cdb2b5 100644 --- a/kicad/mainframe.cpp +++ b/kicad/mainframe.cpp @@ -258,8 +258,9 @@ void KICAD_MANAGER_FRAME::OnOpenFileInTextEditor( wxCommandEvent& event ) #endif mask = _( "Text file (" ) + mask + wxT( ")|" ) + mask; + wxString default_dir = wxGetCwd(); - wxFileDialog dlg( this, _( "Load File to Edit" ), wxGetCwd(), + wxFileDialog dlg( this, _( "Load File to Edit" ), default_dir, wxEmptyString, mask, wxFD_OPEN ); if( dlg.ShowModal() == wxID_CANCEL ) diff --git a/kicad/prjconfig.cpp b/kicad/prjconfig.cpp index 5c34cea6f5..c8d2fa104f 100644 --- a/kicad/prjconfig.cpp +++ b/kicad/prjconfig.cpp @@ -148,13 +148,14 @@ void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event ) { int style; wxString title; + bool newProject = ( event.GetId() == ID_NEW_PROJECT ) || + ( event.GetId() == ID_NEW_PROJECT_FROM_TEMPLATE ); ClearMsg(); if( event.GetId() != wxID_ANY ) { - if( ( event.GetId() == ID_NEW_PROJECT ) || - ( event.GetId() == ID_NEW_PROJECT_FROM_TEMPLATE ) ) + if( newProject ) { title = _( "Create New Project" ); style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT; @@ -165,15 +166,16 @@ void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event ) style = wxFD_OPEN | wxFD_FILE_MUST_EXIST; } - wxFileDialog dlg( this, title, wxGetCwd(), wxEmptyString, ProjectFileWildcard, style ); + wxString default_dir = wxGetCwd(); + wxFileDialog dlg( this, title, default_dir, wxEmptyString, + ProjectFileWildcard, style ); if( dlg.ShowModal() == wxID_CANCEL ) return; m_ProjectFileName = dlg.GetPath(); - if( ( event.GetId() == ID_NEW_PROJECT ) || - ( event.GetId() == ID_NEW_PROJECT_FROM_TEMPLATE ) ) + if( newProject ) { if ( !m_ProjectFileName.GetFullPath().EndsWith( g_KicadPrjFilenameExtension ) ) { @@ -220,12 +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(); PrintMsg( _( "Working dir: " ) + m_ProjectFileName.GetPath() + _( "\nProject: " ) + m_ProjectFileName.GetFullName() + wxT( "\n" ) ); - } diff --git a/kicad/project_template.cpp b/kicad/project_template.cpp index 2e6de3e872..474e08e610 100644 --- a/kicad/project_template.cpp +++ b/kicad/project_template.cpp @@ -161,7 +161,8 @@ bool PROJECT_TEMPLATE::CreateProject( wxFileName& aNewProjectPath ) wxString* PROJECT_TEMPLATE::GetTitle(void) { wxFileInputStream input( GetHtmlFile().GetFullPath() ); - wxTextInputStream text( input, wxT( "\x9" ), wxConvUTF8 ); + wxString separator( wxT( "\x9" ) ); + wxTextInputStream text( input, separator, wxConvUTF8 ); /* Open HTML file and get the text between the title tags */ if( title == wxEmptyString ) diff --git a/kicad/tree_project_frame.cpp b/kicad/tree_project_frame.cpp index 08d53713b3..244611ef04 100644 --- a/kicad/tree_project_frame.cpp +++ b/kicad/tree_project_frame.cpp @@ -44,6 +44,7 @@ #include #include #include +#include /* Note about the tree project build process: @@ -77,13 +78,13 @@ static const wxChar* s_allowedExtensionsToList[] = wxT( "^.*\\.sxw$" ), wxT( "^.*\\.htm$" ), wxT( "^.*\\.html$" ), - wxT( "^.*\\.rpt$" ), // Report files - wxT( "^.*\\.csv$" ), // Report files in comma separateed format - wxT( "^.*\\.pos$" ), // Footprint position files - wxT( "^.*\\.cmp$" ), // Cvpcb cmp/footprint link files - wxT( "^.*\\.drl$" ), // Excellon drill files - wxT( "^.*\\.svg$" ), // SVG print/plot files - NULL // end of list + wxT( "^.*\\.rpt$" ), // Report files + wxT( "^.*\\.csv$" ), // Report files in comma separateed format + wxT( "^.*\\.pos$" ), // Footprint position files + wxT( "^.*\\.cmp$" ), // Cvpcb cmp/footprint link files + wxT( "^.*\\.drl$" ), // Excellon drill files + wxT( "^.*\\.svg$" ), // SVG print/plot files + NULL // end of list }; @@ -93,10 +94,10 @@ static const wxChar* s_allowedExtensionsToList[] = */ /* File extension definitions. */ -const wxString TextFileExtension( wxT( "txt" ) ); +const wxString TextFileExtension( wxT( "txt" ) ); /* File wildcard definitions. */ -const wxString TextFileWildcard( wxT( "Text files (*.txt)|*.txt" ) ); +const wxString TextFileWildcard( wxT( "Text files (*.txt)|*.txt" ) ); /** @@ -109,17 +110,16 @@ const wxString TextFileWildcard( wxT( "Text files (*.txt)|*.txt" ) ); /*****************************************************************************/ BEGIN_EVENT_TABLE( TREE_PROJECT_FRAME, wxSashLayoutWindow ) - EVT_TREE_BEGIN_LABEL_EDIT( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnRenameAsk ) - EVT_TREE_END_LABEL_EDIT( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnRename ) - EVT_TREE_ITEM_ACTIVATED( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnSelect ) - EVT_TREE_ITEM_EXPANDED( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnExpand ) - EVT_TREE_ITEM_RIGHT_CLICK( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnRight ) - EVT_TREE_BEGIN_DRAG( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnDragStart ) - EVT_TREE_END_DRAG( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnDragEnd ) - EVT_MENU( ID_PROJECT_TXTEDIT, TREE_PROJECT_FRAME::OnTxtEdit ) - EVT_MENU( ID_PROJECT_NEWDIR, TREE_PROJECT_FRAME::OnCreateNewDirectory ) - EVT_MENU( ID_PROJECT_DELETE, TREE_PROJECT_FRAME::OnDeleteFile ) - EVT_MENU( ID_PROJECT_RENAME, TREE_PROJECT_FRAME::OnRenameFile ) +EVT_TREE_ITEM_ACTIVATED( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnSelect ) +EVT_TREE_ITEM_EXPANDED( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnExpand ) +EVT_TREE_ITEM_RIGHT_CLICK( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnRight ) +EVT_TREE_BEGIN_DRAG( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnDragStart ) +EVT_TREE_END_DRAG( ID_PROJECT_TREE, TREE_PROJECT_FRAME::OnDragEnd ) +EVT_MENU( ID_PROJECT_TXTEDIT, TREE_PROJECT_FRAME::OnOpenSelectedFileWithTextEditor ) +EVT_MENU( ID_PROJECT_NEWDIR, TREE_PROJECT_FRAME::OnCreateNewDirectory ) +EVT_MENU( ID_PROJECT_DELETE, TREE_PROJECT_FRAME::OnDeleteFile ) +EVT_MENU( ID_PROJECT_RENAME, TREE_PROJECT_FRAME::OnRenameFile ) + END_EVENT_TABLE() /*****************************************************************************/ @@ -137,30 +137,34 @@ 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 ); + Connect( wxEVT_FSWATCHER, + wxFileSystemWatcherEventHandler( TREE_PROJECT_FRAME::OnFileSystemEvent ) ); +#endif /* * Filtering is now inverted: the filters are actually used to _enable_ support * for a given file type. */ // NOTE: sch filter must be first because of a test in AddFile() below - m_Filters.push_back( wxT( "^.*\\.sch$" ) ); - for( int ii = 0; s_allowedExtensionsToList[ii] != NULL; ii++ ) - { - m_Filters.push_back( s_allowedExtensionsToList[ii] ); - } + m_filters.push_back( wxT( "^.*\\.sch$" ) ); - m_Filters.push_back( wxT( "^no KiCad files found" ) ); + for( int ii = 0; s_allowedExtensionsToList[ii] != NULL; ii++ ) + m_filters.push_back( s_allowedExtensionsToList[ii] ); + + m_filters.push_back( wxT( "^no KiCad files found" ) ); for( int i = 0; i < TREE_MAX; i++ ) m_ContextMenus.push_back( new wxMenu() ); - wxMenu *menu; + wxMenu* menu; // New files context menu: wxMenu* menus[2]; - menus[0] = m_ContextMenus[TREE_DIRECTORY]; - menus[1] = m_ContextMenus[TREE_PROJECT]; + menus[0] = m_ContextMenus[TREE_DIRECTORY]; + menus[1] = m_ContextMenus[TREE_PROJECT]; for( int i = 0; i < 2; i++ ) { @@ -173,7 +177,6 @@ TREE_PROJECT_FRAME::TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ) : _( "Create a New Directory" ) ); item->SetBitmap( KiBitmap( directory_xpm ) ); menu->Append( item ); - } @@ -231,6 +234,10 @@ TREE_PROJECT_FRAME::~TREE_PROJECT_FRAME() if( m_PopupMenu ) delete m_PopupMenu; + +#if wxCHECK_VERSION( 2, 9, 2 ) + delete m_watcher; +#endif } @@ -242,18 +249,19 @@ void TREE_PROJECT_FRAME::OnDragStart( wxTreeEvent& event ) /*****************************************************************************/ { /* Ensure item is selected - * (Under Windows start drag does not activate the item) */ - wxTreeItemId curr_item = event.GetItem(); + * (Under Windows start drag does not activate the item) + */ + wxTreeItemId curr_item = event.GetItem(); m_TreeProject->SelectItem( curr_item ); - TREEPROJECT_ITEM* data = GetSelectedData(); + TREEPROJECT_ITEM* data = GetSelectedData(); if( data->GetFileName() == m_Parent->m_ProjectFileName.GetFullPath() ) return; wxImage img = m_TreeProject->GetImageList()->GetBitmap( data->GetType() - 1 ).ConvertToImage(); m_DragCursor = wxCursor( img ); - m_Parent->wxWindow::SetCursor( (wxCursor &)m_DragCursor ); + m_Parent->wxWindow::SetCursor( (wxCursor&) m_DragCursor ); event.Allow(); } @@ -264,11 +272,11 @@ void TREE_PROJECT_FRAME::OnDragEnd( wxTreeEvent& event ) { m_Parent->SetCursor( wxNullCursor ); - TREEPROJECT_ITEM* source_data = GetSelectedData(); - wxTreeItemId dest = event.GetItem(); + TREEPROJECT_ITEM* source_data = GetSelectedData(); + wxTreeItemId dest = event.GetItem(); if( !dest.IsOk() ) - return; // Cancelled ... + return; // Cancelled ... TREEPROJECT_ITEM* destData = dynamic_cast( m_TreeProject->GetItemData( dest ) ); @@ -278,12 +286,13 @@ void TREE_PROJECT_FRAME::OnDragEnd( wxTreeEvent& event ) // the item can be a member of the selected directory; get the directory itself if( TREE_DIRECTORY != destData->GetType() - && !m_TreeProject->ItemHasChildren( dest ) ) + && !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 ? + return; // no parent ? // Select the right destData: destData = @@ -294,19 +303,6 @@ void TREE_PROJECT_FRAME::OnDragEnd( wxTreeEvent& event ) } source_data->Move( destData ); - -#if 0 - /* Sort filenames by alphabetic order */ - m_TreeProject->SortChildren( dest ); -#endif -} - - -/*****************************************************************************/ -void TREE_PROJECT_FRAME::ClearFilters() -/*****************************************************************************/ -{ - m_Filters.clear(); } @@ -314,28 +310,17 @@ void TREE_PROJECT_FRAME::ClearFilters() void TREE_PROJECT_FRAME::RemoveFilter( const wxString& filter ) /*****************************************************************************/ { - for( unsigned int i = 0; i < m_Filters.size(); i++ ) + for( unsigned int i = 0; i < m_filters.size(); i++ ) { - if( filter == m_Filters[i] ) + if( filter == m_filters[i] ) { - m_Filters.erase( m_Filters.begin() + i ); + m_filters.erase( m_filters.begin() + i ); return; } } } -/** - * @brief TODO - */ -/*****************************************************************************/ -const std::vector& TREE_PROJECT_FRAME::GetFilters() -/*****************************************************************************/ -{ - return m_Filters; -} - - /** * @brief TODO */ @@ -349,18 +334,19 @@ wxMenu* TREE_PROJECT_FRAME::GetContextMenu( int type ) /** * Called by the popup menu in the tree frame - * Creates a new subdirectory inside the current kicad project directory + * Creates a new subdirectory inside the current kicad project directory * the user is prompted to enter a directory name */ void TREE_PROJECT_FRAME::OnCreateNewDirectory( wxCommandEvent& event ) { // Get the root directory name: TREEPROJECT_ITEM* treeData = GetSelectedData(); + if( !treeData ) return; - TreeFileType rootType = treeData->GetType(); - wxTreeItemId root; + TreeFileType rootType = treeData->GetType(); + wxTreeItemId root; if( TREE_DIRECTORY == rootType ) { @@ -369,6 +355,7 @@ void TREE_PROJECT_FRAME::OnCreateNewDirectory( wxCommandEvent& event ) else { root = m_TreeProject->GetItemParent( m_TreeProject->GetSelection() ); + if( !root.IsOk() ) root = m_TreeProject->GetSelection(); } @@ -377,32 +364,28 @@ void TREE_PROJECT_FRAME::OnCreateNewDirectory( wxCommandEvent& event ) wxString curr_dir = treeData->GetDir(); // Make the current subdir relative to the current path: - if( !curr_dir.IsEmpty() ) // A subdir is selected + if( !curr_dir.IsEmpty() ) // A subdir is selected { - curr_dir += wxFileName::GetPathSeparator(); - curr_dir += wxT("dummy"); - wxFileName fn(curr_dir); + curr_dir += wxFileName::GetPathSeparator(); + curr_dir += wxT( "dummy" ); + wxFileName fn( curr_dir ); fn.MakeRelativeTo(); curr_dir = fn.GetPath() + wxFileName::GetPathSeparator(); } - wxString msg; - msg.Printf( wxT("Current working directory:\n%s"), GetChars( wxGetCwd() ) ); - wxString subdir = wxGetTextFromUser( msg, _( "Create New Directory" ), curr_dir ); + + wxString msg; + msg.Printf( wxT( "Current working directory:\n%s" ), GetChars( wxGetCwd() ) ); + wxString subdir = wxGetTextFromUser( msg, _( "Create New Directory" ), curr_dir ); if( subdir.IsEmpty() ) return; if( wxMkdir( subdir ) ) - AddFileToTree( subdir, root ); + AddItemToTreeProject( subdir, root ); } -/** - * @brief TODO - */ -/*****************************************************************************/ wxString TREE_PROJECT_FRAME::GetFileExt( TreeFileType type ) -/*****************************************************************************/ { wxString ext; @@ -467,6 +450,7 @@ wxString TREE_PROJECT_FRAME::GetFileExt( TreeFileType type ) return ext; } + /* * Return the wxFileDialog wildcard string for the selected file type. */ @@ -534,28 +518,29 @@ wxString TREE_PROJECT_FRAME::GetFileWildcard( TreeFileType type ) /** - * Function AddFileToTree + * Function AddItemToTreeProject * @brief Add filename "name" to the tree \n * if name is a directory, add the sub directory file names * @param aName = the filename or the dirctory name to add * @param aRoot = the wxTreeItemId item where to add sub tree items - * @param aRecurse = true to filenames or sub dir names to the current tree item + * @param aRecurse = true to add file or subdir names to the current tree item * false to stop file add. * @return true if the file (or directory) is added. */ -bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, - wxTreeItemId& aRoot, bool aRecurse ) +bool TREE_PROJECT_FRAME::AddItemToTreeProject( const wxString& aName, + wxTreeItemId& aRoot, bool aRecurse ) { - wxTreeItemId cellule; + wxTreeItemId cellule; // Check the file type - TreeFileType type = TREE_UNKNOWN; + TreeFileType type = TREE_UNKNOWN; // Skip not visible files and dirs - wxFileName fn(aName); + wxFileName fn( aName ); + // Files/dirs names starting by "." are not visible files under unices. // Skip them also under Windows - if( fn.GetName().StartsWith(wxT(".") ) ) + if( fn.GetName().StartsWith( wxT( "." ) ) ) return false; if( wxDirExists( aName ) ) @@ -569,17 +554,20 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, bool isSchematic = false; bool addFile = false; - for( unsigned i = 0; i < m_Filters.size(); i++ ) + + for( unsigned i = 0; i < m_filters.size(); i++ ) { - wxCHECK2_MSG( reg.Compile( m_Filters[i], wxRE_ICASE ), continue, - wxT( "Regular expression " ) + m_Filters[i] + + wxCHECK2_MSG( reg.Compile( m_filters[i], wxRE_ICASE ), continue, + wxT( "Regular expression " ) + m_filters[i] + wxT( " failed to compile." ) ); if( reg.Matches( aName ) ) { addFile = true; + if( i==0 ) isSchematic = true; + break; } } @@ -594,12 +582,13 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, // "Sheet 1 " if( isSchematic ) { - char line[128]; // small because we just need a few bytes from the start of a line - FILE* fp; + char line[128]; // small because we just need a few bytes from the start of a line + FILE* fp; - wxString FullFileName = aName; + wxString FullFileName = aName; fp = wxFopen( FullFileName, wxT( "rt" ) ); + if( fp == NULL ) { return false; @@ -608,7 +597,7 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, addFile = false; // check the first 100 lines for the "Sheet 1" string - for( int i = 0; i<100; ++i ) + for( int i = 0; i<100; ++i ) { if( !fgets( line, sizeof(line), fp ) ) break; @@ -623,7 +612,7 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, fclose( fp ); if( !addFile ) - return false; // it is a non-top-level schematic + return false; // it is a non-top-level schematic } for( int i = TREE_PROJECT; i < TREE_MAX; i++ ) @@ -644,32 +633,36 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, } } - //also check to see if it is already there. - wxTreeItemIdValue cookie; - wxTreeItemId kid = m_TreeProject->GetFirstChild( aRoot, cookie ); + // also check to see if it is already there. + wxTreeItemIdValue cookie; + wxTreeItemId kid = m_TreeProject->GetFirstChild( aRoot, cookie ); + while( kid.IsOk() ) { TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + if( itemData ) { if( itemData->m_FileName == aName ) { - return true; //well, we would have added it, but it is already here! + return true; // well, we would have added it, but it is already here! } } + kid = m_TreeProject->GetNextChild( aRoot, cookie ); } + // Append the item (only appending the filename not the full path): - wxString file = wxFileNameFromPath( aName ); + wxString file = wxFileNameFromPath( aName ); cellule = m_TreeProject->AppendItem( aRoot, file ); - TREEPROJECT_ITEM* data = new TREEPROJECT_ITEM( type, aName, m_TreeProject ); + TREEPROJECT_ITEM* data = new TREEPROJECT_ITEM( type, aName, m_TreeProject ); m_TreeProject->SetItemData( cellule, data ); data->SetState( 0 ); /* Mark root files (files which have the same aName as the project) */ - wxFileName project( m_Parent->m_ProjectFileName ); - wxFileName currfile( file ); + wxFileName project( m_Parent->m_ProjectFileName ); + wxFileName currfile( file ); if( currfile.GetName().CmpNoCase( project.GetName() ) == 0 ) data->m_IsRootFile = true; @@ -680,15 +673,16 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, // in this case AddFile is recursive, but for the first level only. if( TREE_DIRECTORY == type && aRecurse ) { - const wxString sep = wxFileName().GetPathSeparator(); - wxDir dir( aName ); - wxString dir_filename; + const wxString sep = wxFileName().GetPathSeparator(); + wxDir dir( aName ); + wxString dir_filename; data->m_WasPopulated = true; // set state to populated + if( dir.GetFirst( &dir_filename ) ) { - do // Add name in tree, but do not recurse + do // Add name in tree, but do not recurse { - AddFileToTree( aName + sep + dir_filename, cellule, false ); + AddItemToTreeProject( aName + sep + dir_filename, cellule, false ); } while( dir.GetNext( &dir_filename ) ); } @@ -703,13 +697,11 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, /** * @brief Create or modify the tree showing project file names */ -/*****************************************************************************/ void TREE_PROJECT_FRAME::ReCreateTreePrj() -/*****************************************************************************/ { - wxTreeItemId rootcellule; - wxFileName fn; - bool prjOpened = false; + wxTreeItemId rootcellule; + wxFileName fn; + bool prjOpened = false; if( !m_TreeProject ) m_TreeProject = new TREEPROJECTFILES( this ); @@ -737,29 +729,29 @@ void TREE_PROJECT_FRAME::ReCreateTreePrj() m_TreeProject->SetItemData( rootcellule, new TREEPROJECT_ITEM( TREE_PROJECT, - wxEmptyString, - m_TreeProject ) ); + wxEmptyString, + m_TreeProject ) ); // Now adding all current files if available if( prjOpened ) { - wxString filename; - wxDir dir( wxGetCwd() ); - bool cont = dir.GetFirst( &filename ); + wxString filename; + wxDir dir( wxGetCwd() ); + bool cont = dir.GetFirst( &filename ); while( cont ) { if( filename != fn.GetFullName() ) - AddFileToTree( dir.GetName() + wxFileName::GetPathSeparator() + - filename, m_root ); + AddItemToTreeProject( dir.GetName() + wxFileName::GetPathSeparator() + + filename, m_root ); cont = dir.GetNext( &filename ); } - } - else - { - m_TreeProject->AppendItem( m_root, wxT("Empty project") ); - } + } + else + { + m_TreeProject->AppendItem( m_root, wxT( "Empty project" ) ); + } m_TreeProject->Expand( rootcellule ); @@ -777,10 +769,10 @@ void TREE_PROJECT_FRAME::ReCreateTreePrj() void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event ) /*****************************************************************************/ { - int tree_id; - TREEPROJECT_ITEM* tree_data; - wxString FullFileName; - wxTreeItemId curr_item = Event.GetItem(); + int tree_id; + TREEPROJECT_ITEM* 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 ); @@ -791,6 +783,7 @@ void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event ) // Get the current filename: tree_data = GetSelectedData(); + if( !tree_data ) return; @@ -804,9 +797,10 @@ void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event ) const_cast( tree_data->GetMenu() ) }; - for( unsigned int j = 0; j < sizeof(menus) / sizeof(wxMenu*); j++ ) + for( unsigned int j = 0; j < sizeof(menus) / sizeof(wxMenu*); j++ ) { wxMenu* menu = menus[j]; + if( !menu ) continue; @@ -815,8 +809,8 @@ void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event ) 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->GetItemLabelText(); + wxMenuItem* src = list[i]; + wxString label = src->GetItemLabelText(); // for obscure reasons, the & is translated into _ ... so replace it label.Replace( wxT( "_" ), wxT( "&" ), true ); @@ -833,106 +827,73 @@ void TREE_PROJECT_FRAME::OnRight( wxTreeEvent& Event ) PopupMenu( m_PopupMenu ); } - -/** - * @brief TODO +/* + * Called by the popup menu, when right clicking on a file name + * Launch the text editor to open the selected file */ -/*****************************************************************************/ -void TREE_PROJECT_FRAME::OnTxtEdit( wxCommandEvent& event ) -/*****************************************************************************/ +void TREE_PROJECT_FRAME::OnOpenSelectedFileWithTextEditor( wxCommandEvent& event ) { TREEPROJECT_ITEM* tree_data = GetSelectedData(); if( !tree_data ) return; - wxString FullFileName = tree_data->GetFileName(); + wxString FullFileName = tree_data->GetFileName(); AddDelimiterString( FullFileName ); - wxString editorname = wxGetApp().GetEditorName(); + wxString editorname = wxGetApp().GetEditorName(); if( !editorname.IsEmpty() ) ExecuteFile( this, editorname, FullFileName ); } -/** - * @brief TODO +/* Called via the popup menu, when right clicking on a file name + * or a directory name to delete the selected file or directory + * in the tree project */ -/*****************************************************************************/ void TREE_PROJECT_FRAME::OnDeleteFile( wxCommandEvent& ) -/*****************************************************************************/ { TREEPROJECT_ITEM* tree_data = GetSelectedData(); if( !tree_data ) return; + tree_data->Delete(); } -/** - * @brief TODO +/* Called via the popup menu, when right clicking on a file name + * or a directory name to rename the selected file or directory + * in the tree project */ -/*****************************************************************************/ void TREE_PROJECT_FRAME::OnRenameFile( wxCommandEvent& ) -/*****************************************************************************/ { - wxTreeItemId curr_item = m_TreeProject->GetSelection(); - TREEPROJECT_ITEM* tree_data = GetSelectedData(); + wxTreeItemId curr_item = m_TreeProject->GetSelection(); + TREEPROJECT_ITEM* tree_data = GetSelectedData(); if( !tree_data ) return; - wxString buffer = m_TreeProject->GetItemText( curr_item ); - wxString msg = _( "Change filename: " ) + tree_data->m_FileName; + wxString buffer = m_TreeProject->GetItemText( curr_item ); + wxString msg = _( "Change filename: " ) + tree_data->m_FileName; + + wxTextEntryDialog dlg( this, msg, _( "Change filename" ), buffer ); - wxTextEntryDialog dlg( this, msg, _( "Change filename" ), buffer ); if( dlg.ShowModal() != wxID_OK ) return; // cancelled by user - buffer = dlg.GetValue( ); + buffer = dlg.GetValue(); buffer.Trim( true ); buffer.Trim( false ); + if( buffer.IsEmpty() ) - return; // empty file name not allowed + return; // empty file name not allowed if( tree_data->Rename( buffer, true ) ) m_TreeProject->SetItemText( curr_item, buffer ); } -/** - * @brief Prevent the main project to be renamed - */ -/*****************************************************************************/ -void TREE_PROJECT_FRAME::OnRenameAsk( wxTreeEvent& event ) -/*****************************************************************************/ -{ - TREEPROJECT_ITEM* tree_data = GetSelectedData(); - - if( !tree_data ) - return; - if( m_Parent->m_ProjectFileName.GetFullPath() == tree_data->GetFileName() ) - event.Veto(); -} - - -/** - * @brief Rename a tree item on demand of the context menu - */ -/*****************************************************************************/ -void TREE_PROJECT_FRAME::OnRename( wxTreeEvent& event ) -/*****************************************************************************/ -{ - TREEPROJECT_ITEM* tree_data = GetSelectedData(); - - if( !tree_data ) - return; - - tree_data->OnRename( event ); -} - - /** * @brief TODO */ @@ -940,15 +901,17 @@ void TREE_PROJECT_FRAME::OnRename( wxTreeEvent& event ) void TREE_PROJECT_FRAME::OnSelect( wxTreeEvent& Event ) /*****************************************************************************/ { - wxString FullFileName; + wxString FullFileName; - TREEPROJECT_ITEM* tree_data = GetSelectedData(); + TREEPROJECT_ITEM* tree_data = GetSelectedData(); if( !tree_data ) return; + tree_data->Activate( this ); } + /** * @brief Called when expanding an item of the tree * populate tree items corresponding to subdirectories not already populated @@ -957,10 +920,10 @@ void TREE_PROJECT_FRAME::OnSelect( wxTreeEvent& Event ) void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) /*****************************************************************************/ { - wxString FullFileName; + wxString FullFileName; - wxTreeItemId itemId = Event.GetItem(); - TREEPROJECT_ITEM* tree_data = GetItemIdData( itemId ); + wxTreeItemId itemId = Event.GetItem(); + TREEPROJECT_ITEM* tree_data = GetItemIdData( itemId ); if( !tree_data ) return; @@ -968,28 +931,33 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) if( tree_data->GetType() != TREE_DIRECTORY ) return; - //explore list of non populated subdirs, and populate them - wxTreeItemIdValue cookie; - wxTreeItemId kid = m_TreeProject->GetFirstChild( itemId, cookie ); + // explore list of non populated subdirs, and populate them + wxTreeItemIdValue cookie; + wxTreeItemId kid = m_TreeProject->GetFirstChild( itemId, cookie ); + for( ; kid.IsOk(); kid = m_TreeProject->GetNextChild( itemId, cookie ) ) { TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + if( !itemData || itemData->GetType() != TREE_DIRECTORY ) continue; - if ( itemData->m_WasPopulated ) + + if( itemData->m_WasPopulated ) continue; - wxString fileName = itemData->GetFileName(); - const wxString sep = wxFileName().GetPathSeparator(); - wxDir dir( fileName ); - wxString dir_filename; + wxString fileName = itemData->GetFileName(); + const wxString sep = wxFileName().GetPathSeparator(); + wxDir dir( fileName ); + wxString dir_filename; + if( dir.GetFirst( &dir_filename ) ) { - do // Add name to tree item, but do not recurse in subdirs: + do // Add name to tree item, but do not recurse in subdirs: { - AddFileToTree( fileName + sep + dir_filename, kid, false ); + AddItemToTreeProject( fileName + sep + dir_filename, kid, false ); } while( dir.GetNext( &dir_filename ) ); } + itemData->m_WasPopulated = true; // set state to populated /* Sort filenames by alphabetic order */ @@ -997,6 +965,7 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) } } + /** * Function GetSelectedData * return the item data from item currently selected (highlighted) @@ -1005,18 +974,183 @@ void TREE_PROJECT_FRAME::OnExpand( wxTreeEvent& Event ) */ TREEPROJECT_ITEM* TREE_PROJECT_FRAME::GetSelectedData() { - return dynamic_cast( m_TreeProject->GetItemData( m_TreeProject->GetSelection() ) ); + return dynamic_cast( m_TreeProject->GetItemData + ( m_TreeProject->GetSelection() ) ); } + /** * Function GetItemIdData * return the item data corresponding to a wxTreeItemId identifier * @param aId = the wxTreeItemId identifier. * @return a TREEPROJECT_ITEM pointer correspondinfg to item id aId */ -TREEPROJECT_ITEM* TREE_PROJECT_FRAME::GetItemIdData(wxTreeItemId aId) +TREEPROJECT_ITEM* TREE_PROJECT_FRAME::GetItemIdData( wxTreeItemId aId ) { return dynamic_cast( m_TreeProject->GetItemData( aId ) ); } +/* Search for the item in tree project which is the + * node of the subdirectory aSubDir + * param aSubDir = the directory to find in tree + * return the opaque reference to the tree item. + * if not found, return an invalid tree item. + * therefore wxTreeItemId::IsOk should be used to test + * the returned value + */ +wxTreeItemId TREE_PROJECT_FRAME::findSubdirTreeItem( const wxString& aSubDir ) +{ + // If the subdir is the current working directory, return m_root + // in main list: + if( wxGetCwd() == aSubDir ) + return m_root; + // The subdir is in the main tree or in a subdir: Locate it + 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 + { + root_id = kid; // Not found: return an invalid wxTreeItemId + 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 ) + { + 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 ) + subdirs_id.push( kid ); + } + kid = m_TreeProject->GetNextChild( root_id, cookie ); + } + + return root_id; +} + +#if wxCHECK_VERSION( 2, 9, 2 ) +/* 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 + */ + void TREE_PROJECT_FRAME::OnFileSystemEvent( wxFileSystemWatcherEvent& event ) +{ + + switch( event.GetChangeType() ) + { + case wxFSW_EVENT_DELETE: + break; + + case wxFSW_EVENT_CREATE: + break; + + case wxFSW_EVENT_RENAME: + break; + + case wxFSW_EVENT_MODIFY: + case wxFSW_EVENT_ACCESS: + default: + return; + } + + wxFileName pathModified = event.GetPath(); + wxString subdir = pathModified.GetPath(); + wxString fn = pathModified.GetFullPath(); + + wxTreeItemId root_id = findSubdirTreeItem( subdir ); + if( !root_id.IsOk() ) + return; + + // Add item if it is created + if( event.GetChangeType() == wxFSW_EVENT_CREATE ) + AddItemToTreeProject( pathModified.GetFullPath(), root_id, false ); + + // search for item to delete/rename. + if( event.GetChangeType() == wxFSW_EVENT_DELETE || + event.GetChangeType() == wxFSW_EVENT_RENAME ) + { + wxTreeItemIdValue cookie; // dummy variable needed by GetFirstChild() + wxTreeItemId kid = m_TreeProject->GetFirstChild( root_id, cookie ); + + while( kid.IsOk() ) + { + TREEPROJECT_ITEM* itemData = GetItemIdData( kid ); + + if( itemData ) + { + if( itemData->m_FileName == fn ) + { + if( event.GetChangeType() == wxFSW_EVENT_DELETE ) + { + m_TreeProject->Delete( kid ); + } + else + { + wxFileName newpath = event.GetNewPath(); + wxString newfn = newpath.GetFullPath(); + // Change item label and item data + // 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; + } + } + + kid = m_TreeProject->GetNextChild( root_id, cookie ); + } + } + + /* Sort filenames by alphabetic order */ + m_TreeProject->SortChildren( root_id ); +} + +void TREE_PROJECT_FRAME::FileWatcherReset() +{ + // Prepare file watcher: + delete m_watcher; + m_watcher = new wxFileSystemWatcher(); + 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 + // see http://docs.wxwidgets.org/trunk/classwx_file_system_watcher.htm + // under unix, the file watcher needs more work to be efficient +#ifdef __WINDOWS__ + m_watcher->AddTree( wxFileName::DirName( wxT( "./" ) ) ); +#else + m_watcher->Add( wxFileName::DirName( wxT( "./" ) ) ); +#endif +} + +#endif diff --git a/kicad/tree_project_frame.h b/kicad/tree_project_frame.h index 942c289f2f..91e719de35 100644 --- a/kicad/tree_project_frame.h +++ b/kicad/tree_project_frame.h @@ -5,8 +5,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2009 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr - * Copyright (C) 1992-2009 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 1992-2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,6 +29,10 @@ #ifndef TREEPRJ_FRAME_H #define TREEPRJ_FRAME_H +#if wxCHECK_VERSION( 2, 9, 2 ) +#include +#endif + class TREEPROJECT_ITEM; /** class TREE_PROJECT_FRAME @@ -36,17 +40,34 @@ class TREEPROJECT_ITEM; */ class TREE_PROJECT_FRAME : public wxSashLayoutWindow { + friend class TREEPROJECT_ITEM; +public: + KICAD_MANAGER_FRAME* m_Parent; + TREEPROJECTFILES* m_TreeProject; + wxTreeItemId m_root; private: + std::vector m_ContextMenus; + std::vector m_filters; + wxMenu* m_PopupMenu; + wxCursor m_DragCursor; + wxCursor m_Default; - std::vector m_ContextMenus; - std::vector m_Filters; +#if wxCHECK_VERSION( 2, 9, 2 ) + wxFileSystemWatcher* m_watcher; // file system watcher +#endif - wxMenu* m_PopupMenu; - wxCursor m_DragCursor; - wxCursor m_Default; +public: + TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ); + ~TREE_PROJECT_FRAME(); + void ReCreateTreePrj(); +#if wxCHECK_VERSION( 2, 9, 2 ) + void FileWatcherReset(); +#endif protected: - wxMenu* GetContextMenu( int type ); + wxMenu* GetContextMenu( int type ); + static wxString GetFileExt( TreeFileType type ); + static wxString GetFileWildcard( TreeFileType type ); /** * Function GetSelectedData @@ -54,66 +75,96 @@ protected: * Note this is not necessary the "clicked" item, * because when expanding, collapsing an item this item is not selected */ - TREEPROJECT_ITEM* GetSelectedData(); + TREEPROJECT_ITEM* GetSelectedData(); + /** * Function GetItemIdData * return the item data corresponding to a wxTreeItemId identifier * @param aId = the wxTreeItemId identifier. * @return a TREEPROJECT_ITEM pointer correspondinfg to item id aId */ - TREEPROJECT_ITEM* GetItemIdData(wxTreeItemId aId); + TREEPROJECT_ITEM* GetItemIdData( wxTreeItemId aId ); -public: - KICAD_MANAGER_FRAME* m_Parent; - TREEPROJECTFILES* m_TreeProject; +private: + void OnSelect( wxTreeEvent& Event ); + void OnExpand( wxTreeEvent& Event ); + void OnDragStart( wxTreeEvent& event ); + void OnDragEnd( wxTreeEvent& event ); + void OnRight( wxTreeEvent& Event ); - wxTreeItemId m_root; + /** + * Function OnOpenSelectedFileWithTextEditor + * Called via the popup menu, when right clicking on a file name + * Call the text editor to open the selected file + * in the tree project + */ + void OnOpenSelectedFileWithTextEditor( wxCommandEvent& event ); -public: - static wxString GetFileExt( TreeFileType type ); - static wxString GetFileWildcard( TreeFileType type ); + /** + * Function OnDeleteFile + * Called via the popup menu, when right clicking on a file name + * or a directory name to delete the selected file or directory + * in the tree project + */ + void OnDeleteFile( wxCommandEvent& event ); - TREE_PROJECT_FRAME( KICAD_MANAGER_FRAME* parent ); - ~TREE_PROJECT_FRAME(); - void OnSelect( wxTreeEvent& Event ); - void OnExpand( wxTreeEvent& Event ); - void OnRenameAsk( wxTreeEvent& Event ); - void OnRename( wxTreeEvent& Event ); - void OnDragStart( wxTreeEvent& event ); - void OnDragEnd( wxTreeEvent& event ); - void OnRight( wxTreeEvent& Event ); - void ReCreateTreePrj(); - - void OnTxtEdit( wxCommandEvent& event ); - - void OnDeleteFile( wxCommandEvent& event ); - void OnRenameFile( wxCommandEvent& event ); + /** + * Function OnRenameFile + * Called via the popup menu, when right clicking on a file name + * or a directory name to rename the selected file or directory + * in the tree project + */ + void OnRenameFile( wxCommandEvent& event ); /** * Function OnCreateNewDirectory * Creates a new subdirectory inside the current kicad project directory * the user is prompted to enter a directory name */ - void OnCreateNewDirectory( wxCommandEvent& event ); + void OnCreateNewDirectory( wxCommandEvent& event ); - void ClearFilters(); + void ClearFilters() + { + m_filters.clear(); + } - const std::vector& GetFilters(); - void RemoveFilter( const wxString& filter ); + const std::vector& GetFilters() + { + return m_filters; + } - /** - * Function AddFileToTree + void RemoveFilter( const wxString& filter ); + + /** + * Function AddItemToTreeProject * @brief Add the file or directory aName to the project tree * @param aName = the filename or the directory name to add in tree * @param aRoot = the wxTreeItemId item where to add sub tree items - * @param aRecurse = true to filenames or sub dir names to the current tree item + * @param aRecurse = true to add file or subdir names to the current tree item * false to stop file add. * @return true if the file (or directory) is added. */ - bool AddFileToTree( const wxString& aName, - wxTreeItemId& aRoot, bool aRecurse = true); + bool AddItemToTreeProject( const wxString& aName, + wxTreeItemId& aRoot, + bool aRecurse = true ); + + /** + * function findSubdirTreeItem + * Search for the item in tree project which is the + * node of the subdirectory aSubDir + * @param aSubDir = the directory to find in tree + * @return the opaque reference to the tree item. + * if not found, return an invalid tree item. + * therefore wxTreeItemId::IsOk should be used to test + * the returned value + */ + wxTreeItemId findSubdirTreeItem( const wxString& aSubDir ); + +#if wxCHECK_VERSION( 2, 9, 2 ) + void OnFileSystemEvent( wxFileSystemWatcherEvent& event ); +#endif DECLARE_EVENT_TABLE() }; -#endif // TREEPRJ_FRAME_H +#endif // TREEPRJ_FRAME_H