Eeschema: move recursion check from SCH_SHEET_PATH to SCH_SHEET.
* Add const and non-const version of GetRootSheet() to SCH_SHEET. * Add GetSheetPaths() function to SCH_SHEET which behaves the same way as SCH_SHEET_LIST except it uses standard C++ containers and is a much simpler design.
This commit is contained in:
parent
50db57f4d5
commit
0ef1eee2c6
|
@ -475,9 +475,10 @@ void SCH_EDIT_FRAME::PasteListOfItems( wxDC* DC )
|
|||
if( srcFn.IsRelative() )
|
||||
srcFn.MakeAbsolute( Prj().GetProjectPath() );
|
||||
|
||||
SCH_SHEET_LIST sheetHierarchy( sheet );
|
||||
std::vector< std::vector< const SCH_SHEET* > > sheetHierarchy;
|
||||
sheet->GetSheetPaths( sheetHierarchy );
|
||||
|
||||
if( hierarchy.TestForRecursion( sheetHierarchy,
|
||||
if( g_RootSheet->TestForRecursion( sheetHierarchy,
|
||||
destFn.GetFullPath( wxPATH_UNIX ) ) )
|
||||
{
|
||||
wxString msg;
|
||||
|
|
|
@ -1187,10 +1187,31 @@ unsigned SCH_SHEET::GetSheets( std::vector<const SCH_SHEET*>& aSheetList ) const
|
|||
}
|
||||
|
||||
|
||||
SCH_SHEET* SCH_SHEET::GetRootSheet()
|
||||
void SCH_SHEET::GetSheetPaths( std::vector< std::vector< const SCH_SHEET* > >& aSheetPaths ) const
|
||||
{
|
||||
static std::vector< const SCH_SHEET* > path;
|
||||
|
||||
path.push_back( const_cast< SCH_SHEET* >( this ) );
|
||||
aSheetPaths.push_back( path );
|
||||
|
||||
SCH_ITEM* item = m_screen->GetDrawItems();
|
||||
|
||||
while( item )
|
||||
{
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
( (SCH_SHEET*) item )->GetSheetPaths( aSheetPaths );
|
||||
|
||||
item = item->Next();
|
||||
}
|
||||
|
||||
path.pop_back();
|
||||
}
|
||||
|
||||
|
||||
const SCH_SHEET* SCH_SHEET::GetRootSheet() const
|
||||
{
|
||||
EDA_ITEM* parent = GetParent();
|
||||
SCH_SHEET* rootSheet = this;
|
||||
const SCH_SHEET* rootSheet = const_cast< SCH_SHEET* >( this );
|
||||
|
||||
while( parent )
|
||||
{
|
||||
|
@ -1200,7 +1221,7 @@ SCH_SHEET* SCH_SHEET::GetRootSheet()
|
|||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
return rootSheet;
|
||||
return const_cast< SCH_SHEET* >( rootSheet );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1582,6 +1603,88 @@ int SCH_SHEET::operator-( const SCH_SHEET& aRhs ) const
|
|||
}
|
||||
|
||||
|
||||
bool SCH_SHEET::TestForRecursion( std::vector< std::vector< const SCH_SHEET* > >& aSrcSheetHierarchy,
|
||||
const wxString& aDestFileName ) const
|
||||
{
|
||||
std::vector< std::vector< const SCH_SHEET* > > hierarchy;
|
||||
wxFileName rootFn = GetRootSheet()->GetFileName();
|
||||
wxFileName destFn = aDestFileName;
|
||||
|
||||
if( destFn.IsRelative() )
|
||||
destFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
GetRootSheet()->GetSheetPaths( hierarchy );
|
||||
|
||||
// Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
|
||||
for( unsigned i = 0; i < hierarchy.size(); i++ )
|
||||
{
|
||||
// Test each SCH_SHEET_PATH in the source sheet.
|
||||
for( unsigned j = 0; j < aSrcSheetHierarchy.size(); j++ )
|
||||
{
|
||||
std::vector< const SCH_SHEET* > sheetPath = aSrcSheetHierarchy[ j ];
|
||||
|
||||
for( unsigned k = 0; k < sheetPath.size(); k++ )
|
||||
{
|
||||
wxFileName srcFn = sheetPath[k]->GetFileName();
|
||||
|
||||
if( srcFn.IsRelative() )
|
||||
srcFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
// The source and destination sheet file names cannot be the same.
|
||||
if( srcFn == destFn )
|
||||
return true;
|
||||
|
||||
/// @todo Store sheet file names with full path, either relative to project path
|
||||
/// or absolute path. The current design always assumes subsheet files are
|
||||
/// located in the project folder which may or may not be desirable.
|
||||
std::vector< const SCH_SHEET* > destPath = hierarchy[i];
|
||||
unsigned l = 0;
|
||||
|
||||
while( l < destPath.size() )
|
||||
{
|
||||
wxFileName cmpFn = destPath[i]->GetFileName();
|
||||
|
||||
if( cmpFn.IsRelative() )
|
||||
cmpFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
// Test if the file name of the destination sheet is in anywhere in the
|
||||
// source sheet path.
|
||||
if( cmpFn == destFn )
|
||||
break;
|
||||
|
||||
l++;
|
||||
}
|
||||
|
||||
// The destination sheet file name was not found in the any of the source sheet
|
||||
// path or the destination sheet file name is the root sheet so no recursion is
|
||||
// possible.
|
||||
if( l >= destPath.size() || l == 0 )
|
||||
return false;
|
||||
|
||||
// Walk back up to the root sheet to see if the source file name is already a
|
||||
// parent in destination the sheet path. If so, recursion will occur.
|
||||
do
|
||||
{
|
||||
l -= 1;
|
||||
|
||||
wxFileName cmpFn = destPath[i]->GetFileName();
|
||||
|
||||
if( cmpFn.IsRelative() )
|
||||
cmpFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
if( cmpFn == srcFn )
|
||||
return true;
|
||||
|
||||
} while( l != 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The source sheet file can safely be added to the destination sheet file.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
||||
void SCH_SHEET::Show( int nestLevel, std::ostream& os ) const
|
||||
|
|
|
@ -250,6 +250,8 @@ class SCH_SHEET : public SCH_ITEM
|
|||
// than assigned in the order the sheets were parsed and loaded.
|
||||
int m_number;
|
||||
|
||||
SCH_SHEET* getRootSheet();
|
||||
|
||||
public:
|
||||
SCH_SHEET( const wxPoint& pos = wxPoint( 0, 0 ) );
|
||||
|
||||
|
@ -599,6 +601,18 @@ public:
|
|||
*/
|
||||
unsigned GetSheets( std::vector<const SCH_SHEET*>& aSheetList ) const;
|
||||
|
||||
/**
|
||||
* Function GetSheetPaths
|
||||
*
|
||||
* Returns a list of lists of #SCH_SHEET pointers to \a sSheetPaths.
|
||||
*
|
||||
* This is analagous to the old SCH_SHEET_LIST::BuildSheetList(). It creates a list of
|
||||
* stacks to the sheet pointer hierarchy.
|
||||
*
|
||||
* @param aSheetPaths is a vector of vector of #SCH_SHEET pointers.
|
||||
*/
|
||||
void GetSheetPaths( std::vector< std::vector< const SCH_SHEET* > >& aSheetPaths ) const;
|
||||
|
||||
/**
|
||||
* Function GetRootSheet
|
||||
*
|
||||
|
@ -610,7 +624,12 @@ public:
|
|||
*
|
||||
* @return a SCH_SHEET pointer to the root sheet.
|
||||
*/
|
||||
SCH_SHEET* GetRootSheet();
|
||||
const SCH_SHEET* GetRootSheet() const;
|
||||
|
||||
SCH_SHEET* GetRootSheet()
|
||||
{
|
||||
return const_cast< SCH_SHEET* >( static_cast< const SCH_SHEET&>( *this ).GetRootSheet() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function IsRootSheet
|
||||
|
@ -747,6 +766,20 @@ public:
|
|||
*/
|
||||
SCH_ITEM* FindNextItem( KICAD_T aType, SCH_ITEM* aLastItem = NULL, bool aWrap = false ) const;
|
||||
|
||||
/**
|
||||
* Function TestForRecursion
|
||||
*
|
||||
* test every SCH_SHEET in the SCH_SHEET hierarchy to verify if adding the sheets stored
|
||||
* in \a aSrcSheetHierarchy to the sheet stored in \a aDestFileName will cause recursion.
|
||||
*
|
||||
* @param aSrcSheetHierarchy is a list #SCH_SHEET pointer lists of the source sheet add
|
||||
* to \a aDestFileName.
|
||||
* @param aDestFileName is the file name of the destination sheet for \a aSrcFileName.
|
||||
* @return true if \a aFileName will cause recursion in the sheet path. Otherwise false.
|
||||
*/
|
||||
bool TestForRecursion( std::vector< std::vector< const SCH_SHEET* > >& aSrcSheetHierarchy,
|
||||
const wxString& aDestFileName ) const;
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Show( int nestLevel, std::ostream& os ) const; // override
|
||||
#endif
|
||||
|
|
|
@ -294,69 +294,6 @@ bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 ) const
|
|||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_PATH::TestForRecursion( const wxString& aSrcFileName,
|
||||
const wxString& aDestFileName ) const
|
||||
{
|
||||
wxFileName rootFn = g_RootSheet->GetFileName();
|
||||
wxFileName srcFn = aSrcFileName;
|
||||
wxFileName destFn = aDestFileName;
|
||||
|
||||
if( srcFn.IsRelative() )
|
||||
srcFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
if( destFn.IsRelative() )
|
||||
destFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
|
||||
// The source and destination sheet file names cannot be the same.
|
||||
if( srcFn == destFn )
|
||||
return true;
|
||||
|
||||
/// @todo Store sheet file names with full path, either relative to project path
|
||||
/// or absolute path. The current design always assumes subsheet files are
|
||||
/// located in the project folder which may or may not be desirable.
|
||||
unsigned i = 0;
|
||||
|
||||
while( i < m_numSheets )
|
||||
{
|
||||
wxFileName cmpFn = m_sheets[i]->GetFileName();
|
||||
|
||||
if( cmpFn.IsRelative() )
|
||||
cmpFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
// Test if the file name of the destination sheet is in anywhere in this sheet path.
|
||||
if( cmpFn == destFn )
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// The destination sheet file name was not found in the sheet path or the destination
|
||||
// sheet file name is the root sheet so no recursion is possible.
|
||||
if( i >= m_numSheets || i == 0 )
|
||||
return false;
|
||||
|
||||
// Walk back up to the root sheet to see if the source file name is already a parent in
|
||||
// the sheet path. If so, recursion will occur.
|
||||
do
|
||||
{
|
||||
i -= 1;
|
||||
|
||||
wxFileName cmpFn = m_sheets[i]->GetFileName();
|
||||
|
||||
if( cmpFn.IsRelative() )
|
||||
cmpFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
if( cmpFn == srcFn )
|
||||
return true;
|
||||
|
||||
} while( i != 0 );
|
||||
|
||||
// The source sheet file name is not a parent of the destination sheet file name.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int SCH_SHEET_PATH::FindSheet( const wxString& aFileName ) const
|
||||
{
|
||||
for( unsigned i = 0; i < m_numSheets; i++ )
|
||||
|
@ -600,37 +537,6 @@ SCH_ITEM* SCH_SHEET_LIST::FindPreviousItem( KICAD_T aType, SCH_SHEET_PATH** aShe
|
|||
}
|
||||
|
||||
|
||||
bool SCH_SHEET_LIST::TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
|
||||
const wxString& aDestFileName ) const
|
||||
{
|
||||
wxFileName rootFn = g_RootSheet->GetFileName();
|
||||
wxFileName destFn = aDestFileName;
|
||||
|
||||
if( destFn.IsRelative() )
|
||||
destFn.MakeAbsolute( rootFn.GetPath() );
|
||||
|
||||
// Test each SCH_SHEET_PATH in this SCH_SHEET_LIST for potential recursion.
|
||||
for( int i = 0; i < m_count; i++ )
|
||||
{
|
||||
// Test each SCH_SHEET_PATH in the source sheet.
|
||||
for( int j = 0; j < aSrcSheetHierarchy.GetCount(); j++ )
|
||||
{
|
||||
SCH_SHEET_PATH* sheetPath = aSrcSheetHierarchy.GetSheet( j );
|
||||
|
||||
for( unsigned k = 0; k < sheetPath->GetCount(); k++ )
|
||||
{
|
||||
if( m_list[i].TestForRecursion( sheetPath->GetSheet( k )->GetFileName(),
|
||||
aDestFileName ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The source sheet file can safely be added to the destination sheet file.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHEET* SCH_SHEET_LIST::FindSheetByName( const wxString& aSheetName )
|
||||
{
|
||||
for( int i = 0; i < m_count; i++ )
|
||||
|
|
|
@ -220,19 +220,6 @@ public:
|
|||
*/
|
||||
SCH_ITEM* FindPreviousItem( KICAD_T aType, SCH_ITEM* aLastItem = NULL, bool aWrap = false ) const;
|
||||
|
||||
/**
|
||||
* Function TestForRecursion
|
||||
*
|
||||
* test the SCH_SHEET_PATH file names to check adding the sheet stored in the file
|
||||
* \a aSrcFileName to the sheet stored in file \a aDestFileName will cause a sheet
|
||||
* path recursion.
|
||||
*
|
||||
* @param aSrcFileName is the source file name of the sheet add to \a aDestFileName.
|
||||
* @param aDestFileName is the file name of the destination sheet for \a aSrcFileName.
|
||||
* @return true if \a aFileName will cause recursion in the sheet path. Otherwise false.
|
||||
*/
|
||||
bool TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName ) const;
|
||||
|
||||
int FindSheet( const wxString& aFileName ) const;
|
||||
|
||||
/**
|
||||
|
@ -388,19 +375,6 @@ public:
|
|||
SCH_ITEM* FindPreviousItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFound = NULL,
|
||||
SCH_ITEM* aLastItem = NULL, bool aWrap = true );
|
||||
|
||||
/**
|
||||
* Function TestForRecursion
|
||||
*
|
||||
* test every SCH_SHEET_PATH in the SCH_SHEET_LIST to verify if adding the sheets stored
|
||||
* in \a aSrcSheetHierarchy to the sheet stored in \a aDestFileName will cause recursion.
|
||||
*
|
||||
* @param aSrcSheetHierarchy is the SCH_SHEET_LIST of the source sheet add to \a aDestFileName.
|
||||
* @param aDestFileName is the file name of the destination sheet for \a aSrcFileName.
|
||||
* @return true if \a aFileName will cause recursion in the sheet path. Otherwise false.
|
||||
*/
|
||||
bool TestForRecursion( const SCH_SHEET_LIST& aSrcSheetHierarchy,
|
||||
const wxString& aDestFileName ) const;
|
||||
|
||||
/**
|
||||
* Function FindSheetByName
|
||||
*
|
||||
|
|
|
@ -983,7 +983,7 @@ void SCH_EDIT_FRAME::OnEditItem( wxCommandEvent& aEvent )
|
|||
}
|
||||
|
||||
case SCH_SHEET_T:
|
||||
if( EditSheet( (SCH_SHEET*) item, m_CurrentSheet ) )
|
||||
if( EditSheet( (SCH_SHEET*) item, m_CurrentSheet->Last() ) )
|
||||
m_canvas->Refresh();
|
||||
break;
|
||||
|
||||
|
|
|
@ -1274,7 +1274,7 @@ void SCH_EDIT_FRAME::addCurrentItemToList( bool aRedraw )
|
|||
// the m_mouseCaptureCallback function.
|
||||
m_canvas->SetMouseCapture( NULL, NULL );
|
||||
|
||||
if( !EditSheet( (SCH_SHEET*)item, m_CurrentSheet ) )
|
||||
if( !EditSheet( (SCH_SHEET*)item, m_CurrentSheet->Last() ) )
|
||||
{
|
||||
screen->SetCurItem( NULL );
|
||||
delete item;
|
||||
|
|
|
@ -1015,7 +1015,7 @@ public:
|
|||
*
|
||||
* Note: the screen is not refresh. The caller is responsible to do that
|
||||
*/
|
||||
bool EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy );
|
||||
bool EditSheet( SCH_SHEET* aSheet, SCH_SHEET* aHierarchy );
|
||||
|
||||
wxPoint GetLastSheetPinPosition() const { return m_lastSheetPinPosition; }
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include <project.h>
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
|
||||
bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET* aHierarchy )
|
||||
{
|
||||
if( aSheet == NULL || aHierarchy == NULL )
|
||||
return false;
|
||||
|
@ -235,15 +235,16 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy )
|
|||
(long unsigned) aSheet->GetTimeStamp() ) );
|
||||
|
||||
// Make sure the sheet changes do not cause any recursion.
|
||||
SCH_SHEET_LIST sheetHierarchy( aSheet );
|
||||
std::vector< std::vector< const SCH_SHEET* > > sheetHierarchy;
|
||||
aSheet->GetSheetPaths( sheetHierarchy );
|
||||
|
||||
// Make sure files have fully qualified path and file name.
|
||||
wxFileName destFn = aHierarchy->Last()->GetFileName();
|
||||
wxFileName destFn = aHierarchy->GetFileName();
|
||||
|
||||
if( destFn.IsRelative() )
|
||||
destFn.MakeAbsolute( Prj().GetProjectPath() );
|
||||
|
||||
if( hierarchy.TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
|
||||
if( g_RootSheet->TestForRecursion( sheetHierarchy, destFn.GetFullPath( wxPATH_UNIX ) ) )
|
||||
{
|
||||
msg.Printf( _( "The sheet changes cannot be made because the destination sheet already "
|
||||
"has the sheet <%s> or one of it's subsheets as a parent somewhere in "
|
||||
|
|
Loading…
Reference in New Issue