Exclude some files from project view.

1) schematic sheets which don't match a project name (ie: aren't a
root sheet)
2) legacy schematic sheets when a current-format sheet is also present
witht the same name

Fixes https://gitlab.com/kicad/code/kicad/issues/6801
This commit is contained in:
Jeff Young 2020-12-22 13:51:32 +00:00
parent fb7ac450d9
commit c73c20d083
2 changed files with 110 additions and 59 deletions

View File

@ -37,6 +37,7 @@
#include <trace_helpers.h> #include <trace_helpers.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <kiplatform/environment.h> #include <kiplatform/environment.h>
#include <core/kicad_algo.h>
#include "project_tree_item.h" #include "project_tree_item.h"
#include "project_tree.h" #include "project_tree.h"
@ -245,7 +246,7 @@ void PROJECT_TREE_PANE::onCreateNewDirectory( wxCommandEvent& event )
wxString full_dirname = curr_dir + wxFileName::GetPathSeparator() + new_dir; wxString full_dirname = curr_dir + wxFileName::GetPathSeparator() + new_dir;
wxMkdir( full_dirname ); wxMkdir( full_dirname );
addItemToProjectTree( full_dirname, item_data->GetId() ); addItemToProjectTree( full_dirname, item_data->GetId(), nullptr, false );
} }
} }
@ -282,18 +283,38 @@ wxString PROJECT_TREE_PANE::GetFileExt( TREE_FILE_TYPE type )
} }
std::vector<wxString> getProjects( const wxDir& dir )
{
std::vector<wxString> projects;
wxString dir_filename;
bool haveFile = dir.GetFirst( &dir_filename );
while( haveFile )
{
wxFileName file( dir_filename );
if( file.GetExt() == LegacyProjectFileExtension || file.GetExt() == ProjectFileExtension )
projects.push_back( file.GetName() );
haveFile = dir.GetNext( &dir_filename );
}
return projects;
}
wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName, wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
const wxTreeItemId& aRoot, const wxTreeItemId& aRoot,
bool aCanResetFileWatcher, bool aRecurse ) std::vector<wxString>* aProjectNames,
bool aRecurse )
{ {
wxTreeItemId newItemId;
TREE_FILE_TYPE type = TREE_FILE_TYPE::UNKNOWN; TREE_FILE_TYPE type = TREE_FILE_TYPE::UNKNOWN;
wxFileName fn( aName ); wxFileName fn( aName );
// Files/dirs names starting by "." are not visible files under unices. // Files/dirs names starting by "." are not visible files under unices.
// Skip them also under Windows // Skip them also under Windows
if( fn.GetName().StartsWith( wxT( "." ) ) ) if( fn.GetName().StartsWith( wxT( "." ) ) )
return newItemId; return wxTreeItemId();
if( wxDirExists( aName ) ) if( wxDirExists( aName ) )
{ {
@ -318,7 +339,7 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
} }
if( !addFile ) if( !addFile )
return newItemId; return wxTreeItemId();
for( int i = static_cast<int>( TREE_FILE_TYPE::LEGACY_PROJECT ); for( int i = static_cast<int>( TREE_FILE_TYPE::LEGACY_PROJECT );
i < static_cast<int>( TREE_FILE_TYPE::MAX ); i++ ) i < static_cast<int>( TREE_FILE_TYPE::MAX ); i++ )
@ -351,7 +372,14 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
if( ( type == TREE_FILE_TYPE::LEGACY_PROJECT ) if( ( type == TREE_FILE_TYPE::LEGACY_PROJECT )
&& ( currfile.GetName().CmpNoCase( project.GetName() ) == 0 ) ) && ( currfile.GetName().CmpNoCase( project.GetName() ) == 0 ) )
{ {
return newItemId; return wxTreeItemId();
}
if( currfile.GetExt() == GetFileExt( TREE_FILE_TYPE::LEGACY_SCHEMATIC )
|| currfile.GetExt() == GetFileExt( TREE_FILE_TYPE::SEXPR_SCHEMATIC ) )
{
if( aProjectNames && !alg::contains( *aProjectNames, currfile.GetName() ) )
return wxTreeItemId();
} }
// also check to see if it is already there. // also check to see if it is already there.
@ -368,8 +396,9 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
kid = m_TreeProject->GetNextChild( aRoot, cookie ); kid = m_TreeProject->GetNextChild( aRoot, cookie );
} }
// Only show the JSON project files if both legacy and JSON files are present // Only show current files if both legacy and current files are present
if( ( type == TREE_FILE_TYPE::LEGACY_PROJECT ) || ( type == TREE_FILE_TYPE::JSON_PROJECT ) ) if( type == TREE_FILE_TYPE::LEGACY_PROJECT || type == TREE_FILE_TYPE::JSON_PROJECT
|| type == TREE_FILE_TYPE::LEGACY_SCHEMATIC || type == TREE_FILE_TYPE::SEXPR_SCHEMATIC )
{ {
kid = m_TreeProject->GetFirstChild( aRoot, cookie ); kid = m_TreeProject->GetFirstChild( aRoot, cookie );
@ -383,17 +412,34 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
if( fname.GetName().CmpNoCase( currfile.GetName() ) == 0 ) if( fname.GetName().CmpNoCase( currfile.GetName() ) == 0 )
{ {
// If the tree item is the legacy project remove it. switch( type )
if( itemData->GetType() == TREE_FILE_TYPE::LEGACY_PROJECT )
{ {
m_TreeProject->Delete( kid ); case TREE_FILE_TYPE::LEGACY_PROJECT:
if( itemData->GetType() == TREE_FILE_TYPE::JSON_PROJECT )
return wxTreeItemId();
break;
case TREE_FILE_TYPE::LEGACY_SCHEMATIC:
if( itemData->GetType() == TREE_FILE_TYPE::SEXPR_SCHEMATIC )
return wxTreeItemId();
break;
case TREE_FILE_TYPE::JSON_PROJECT:
if( itemData->GetType() == TREE_FILE_TYPE::LEGACY_PROJECT )
m_TreeProject->Delete( kid );
break;
case TREE_FILE_TYPE::SEXPR_SCHEMATIC:
if( itemData->GetType() == TREE_FILE_TYPE::LEGACY_SCHEMATIC )
m_TreeProject->Delete( kid );
break;
default:
break; break;
}
// If we are the legacy project and the tree was the JSON project, ignore this file
else if( ( itemData->GetType() == TREE_FILE_TYPE::JSON_PROJECT )
&& ( type == TREE_FILE_TYPE::LEGACY_PROJECT ) )
{
return newItemId;
} }
} }
} }
@ -403,8 +449,8 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
} }
// Append the item (only appending the filename not the full path): // Append the item (only appending the filename not the full path):
newItemId = m_TreeProject->AppendItem( aRoot, file ); wxTreeItemId newItemId = m_TreeProject->AppendItem( aRoot, file );
PROJECT_TREE_ITEM* data = new PROJECT_TREE_ITEM( type, aName, m_TreeProject ); PROJECT_TREE_ITEM* data = new PROJECT_TREE_ITEM( type, aName, m_TreeProject );
m_TreeProject->SetItemData( newItemId, data ); m_TreeProject->SetItemData( newItemId, data );
data->SetState( 0 ); data->SetState( 0 );
@ -426,20 +472,22 @@ wxTreeItemId PROJECT_TREE_PANE::addItemToProjectTree( const wxString& aName,
if( dir.IsOpened() ) // protected dirs will not open properly. if( dir.IsOpened() ) // protected dirs will not open properly.
{ {
wxString dir_filename; std::vector<wxString> projects = getProjects( dir );
wxString dir_filename;
bool haveFile = dir.GetFirst( &dir_filename );
data->SetPopulated( true ); data->SetPopulated( true );
#ifndef __WINDOWS__ #ifndef __WINDOWS__
subdir_populated = aCanResetFileWatcher; subdir_populated = aRecurse;
#endif #endif
if( dir.GetFirst( &dir_filename ) ) while( haveFile )
{ {
do // Add name in tree, but do not recurse // Add name in tree, but do not recurse
{ wxString path = aName + wxFileName::GetPathSeparator() + dir_filename;
wxString path = aName + wxFileName::GetPathSeparator() + dir_filename; addItemToProjectTree( path, newItemId, &projects, false );
addItemToProjectTree( path, newItemId, false, false );
} while( dir.GetNext( &dir_filename ) ); haveFile = dir.GetNext( &dir_filename );
} }
} }
@ -510,18 +558,19 @@ void PROJECT_TREE_PANE::ReCreateTreePrj()
if( dir.IsOpened() ) // protected dirs will not open, see "man opendir()" if( dir.IsOpened() ) // protected dirs will not open, see "man opendir()"
{ {
wxString filename; std::vector<wxString> projects = getProjects( dir );
bool cont = dir.GetFirst( &filename ); wxString filename;
bool haveFile = dir.GetFirst( &filename );
while( cont ) while( haveFile )
{ {
if( filename != fn.GetFullName() ) if( filename != fn.GetFullName() )
{ {
wxString name = dir.GetName() + wxFileName::GetPathSeparator() + filename; wxString name = dir.GetName() + wxFileName::GetPathSeparator() + filename;
addItemToProjectTree( name, m_root, false ); addItemToProjectTree( name, m_root, &projects, false );
} }
cont = dir.GetNext( &filename ); haveFile = dir.GetNext( &filename );
} }
} }
} }
@ -829,21 +878,21 @@ void PROJECT_TREE_PANE::onSelect( wxTreeEvent& Event )
if( tree_data.size() != 1 ) if( tree_data.size() != 1 )
return; return;
// Bookmark the selected item but don't try and activate it until later // Bookmark the selected item but don't try and activate it until later. If we do it now,
// if we do it now, there will be more events at least on Windows in this frame // there will be more events at least on Windows in this frame that will steal focus from
// that will steal focus from any newly launched windows // any newly launched windows
m_selectedItem = tree_data[0]; m_selectedItem = tree_data[0];
} }
void PROJECT_TREE_PANE::onIdle( wxIdleEvent& aEvent ) void PROJECT_TREE_PANE::onIdle( wxIdleEvent& aEvent )
{ {
// Idle executes once all other events finished processing // Idle executes once all other events finished processing. This makes it ideal to launch
// This makes it ideal to launch a new window without starting Focus wars. // a new window without starting Focus wars.
if( m_selectedItem != nullptr ) if( m_selectedItem != nullptr )
{ {
// Activate launches a window which may run the event loop on top of us // Activate launches a window which may run the event loop on top of us and cause OnIdle
// and cause OnIdle here to get called again, so be sure to block off the activation condition first // to get called again, so be sure to block off the activation condition first.
PROJECT_TREE_ITEM* item = m_selectedItem; PROJECT_TREE_ITEM* item = m_selectedItem;
m_selectedItem = nullptr; m_selectedItem = nullptr;
@ -886,15 +935,17 @@ void PROJECT_TREE_PANE::onExpand( wxTreeEvent& Event )
if( dir.IsOpened() ) if( dir.IsOpened() )
{ {
wxString dir_filename; std::vector<wxString> projects = getProjects( dir );
wxString dir_filename;
bool haveFile = dir.GetFirst( &dir_filename );
if( dir.GetFirst( &dir_filename ) ) while( haveFile )
{ {
do // Add name to tree item, but do not recurse in subdirs: // Add name to tree item, but do not recurse in subdirs:
{ wxString name = fileName + wxFileName::GetPathSeparator() + dir_filename;
wxString name = fileName + wxFileName::GetPathSeparator() + dir_filename; addItemToProjectTree( name, kid, &projects, false );
addItemToProjectTree( name, kid, false );
} while( dir.GetNext( &dir_filename ) ); haveFile = dir.GetNext( &dir_filename );
} }
itemData->SetPopulated( true ); // set state to populated itemData->SetPopulated( true ); // set state to populated
@ -1023,7 +1074,8 @@ void PROJECT_TREE_PANE::onFileSystemEvent( wxFileSystemWatcherEvent& event )
{ {
case wxFSW_EVENT_CREATE: case wxFSW_EVENT_CREATE:
{ {
wxTreeItemId newitem = addItemToProjectTree( pathModified.GetFullPath(), root_id ); wxTreeItemId newitem = addItemToProjectTree( pathModified.GetFullPath(), root_id,
nullptr, true );
// If we are in the process of renaming a file, select the new one // If we are in the process of renaming a file, select the new one
// This is needed for MSW and OSX, since we don't get RENAME events from them, just a // This is needed for MSW and OSX, since we don't get RENAME events from them, just a
@ -1072,16 +1124,16 @@ void PROJECT_TREE_PANE::onFileSystemEvent( wxFileSystemWatcherEvent& event )
// Add the new item only if it is not the current project file (root item). // Add the new item only if it is not the current project file (root item).
// Remember: this code is called by a wxFileSystemWatcherEvent event, and not always // Remember: this code is called by a wxFileSystemWatcherEvent event, and not always
// called after an actual file rename, and the cleanup code does not explore the // called after an actual file rename, and the cleanup code does not explore the
// root item, because it cannot be renamed by the user. Also, ensure the new file actually // root item, because it cannot be renamed by the user. Also, ensure the new file
// exists on the file system before it is readded. On Linux, moving a file to the trash // actually exists on the file system before it is readded. On Linux, moving a file
// can cause the same path to be returned in both the old and new paths of the event, // to the trash can cause the same path to be returned in both the old and new paths
// even though the file isn't there anymore. // of the event, even though the file isn't there anymore.
PROJECT_TREE_ITEM* rootData = GetItemIdData( root_id ); PROJECT_TREE_ITEM* rootData = GetItemIdData( root_id );
if( newpath.Exists() && ( newfn != rootData->GetFileName() ) ) if( newpath.Exists() && ( newfn != rootData->GetFileName() ) )
{ {
wxTreeItemId newroot_id = findSubdirTreeItem( newdir ); wxTreeItemId newroot_id = findSubdirTreeItem( newdir );
wxTreeItemId newitem = addItemToProjectTree( newfn, newroot_id ); wxTreeItemId newitem = addItemToProjectTree( newfn, newroot_id, nullptr, true );
// If the item exists, select it // If the item exists, select it
if( newitem.IsOk() ) if( newitem.IsOk() )
@ -1105,10 +1157,10 @@ void PROJECT_TREE_PANE::FileWatcherReset()
#if defined( _WIN32 ) #if defined( _WIN32 )
if( KIPLATFORM::ENV::IsNetworkPath( prj_dir ) ) if( KIPLATFORM::ENV::IsNetworkPath( prj_dir ) )
{ {
// Due to a combination of a bug in SAMBA sending bad change event IDs // Due to a combination of a bug in SAMBA sending bad change event IDs and wxWidgets
// and wxWidgets choosing to fault on an invalid event ID instead of sanely ignoring them // choosing to fault on an invalid event ID instead of sanely ignoring them we need to
// We need to avoid spawning a filewatcher. Unforunately this punishes corporate environments // avoid spawning a filewatcher. Unforunately this punishes corporate environments with
// with Windows Server shares :/ // Windows Server shares :/
m_Parent->SetStatusText( _( "Network path: not monitoring folder changes" ), 0 ); m_Parent->SetStatusText( _( "Network path: not monitoring folder changes" ), 0 );
return; return;
} }
@ -1184,7 +1236,7 @@ void PROJECT_TREE_PANE::FileWatcherReset()
wxLogTrace( tracePathsAndFiles, "%s: add '%s'\n", __func__, TO_UTF8( path ) ); wxLogTrace( tracePathsAndFiles, "%s: add '%s'\n", __func__, TO_UTF8( path ) );
if( wxFileName::IsDirReadable( path ) ) // linux whines about watching protected dir if( wxFileName::IsDirReadable( path ) ) // linux whines about watching protected dir
{ {
fn.AssignDir( path ); fn.AssignDir( path );
m_watcher->Add( fn ); m_watcher->Add( fn );

View File

@ -160,13 +160,12 @@ private:
* @brief Add the file or directory aName to the project tree * @brief Add the file or directory aName to the project tree
* @param aName = the filename or the directory name to add in 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 aRoot = the wxTreeItemId item where to add sub tree items
* @param aCanResetFileWatcher = true to reset file watcher if additional conditions are met
* @param aRecurse = true to add file or subdir 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. * false to stop file add.
* @return the Id for the new tree item * @return the Id for the new tree item
*/ */
wxTreeItemId addItemToProjectTree( const wxString& aName, const wxTreeItemId& aRoot, wxTreeItemId addItemToProjectTree( const wxString& aName, const wxTreeItemId& aRoot,
bool aCanResetFileWatcher = true, bool aRecurse = true ); std::vector<wxString>* aProjectNames, bool aRecurse );
/** /**
* Function findSubdirTreeItem * Function findSubdirTreeItem