Revert "Revert "Eeschema: fix many append schematic bugs.""
This reverts commit 238fb00727
.
This commit is contained in:
parent
d86789898d
commit
23d71de75f
|
@ -386,9 +386,14 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
|
||||
bool SCH_EDIT_FRAME::AppendSchematic()
|
||||
{
|
||||
int i;
|
||||
wxString msg;
|
||||
wxString fullFileName;
|
||||
wxString topLevelSheetPath;
|
||||
wxFileName tmp;
|
||||
SCH_SCREEN* screen = GetScreen();
|
||||
bool libTableChanged = false;
|
||||
|
||||
|
||||
if( !screen )
|
||||
{
|
||||
|
@ -415,25 +420,6 @@ bool SCH_EDIT_FRAME::AppendSchematic()
|
|||
fullFileName = fn.GetFullPath();
|
||||
}
|
||||
|
||||
wxString cache_name = PART_LIBS::CacheName( fullFileName );
|
||||
|
||||
if( !!cache_name )
|
||||
{
|
||||
PART_LIBS* libs = Prj().SchLibs();
|
||||
|
||||
try
|
||||
{
|
||||
if( PART_LIB* lib = libs->AddLibrary( cache_name ) )
|
||||
lib->SetCache();
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogDebug( wxT( "Importing schematic " ) + fullFileName );
|
||||
|
||||
// Load the schematic into a temporary sheet.
|
||||
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
|
||||
std::unique_ptr< SCH_SHEET> newSheet( new SCH_SHEET );
|
||||
|
@ -464,6 +450,49 @@ bool SCH_EDIT_FRAME::AppendSchematic()
|
|||
return false;
|
||||
}
|
||||
|
||||
tmp = fn;
|
||||
|
||||
// If the appended schematic is in a different folder from the current project and
|
||||
// it contains hierarchical sheets, the hierarchical sheet paths need to be updated.
|
||||
if( fn.GetPath( wxPATH_GET_SEPARATOR ) != Prj().GetProjectPath() && newSheet->CountSheets() )
|
||||
{
|
||||
// Give the user the option to choose relative path if possible.
|
||||
if( tmp.MakeRelativeTo( Prj().GetProjectPath() ) )
|
||||
{
|
||||
wxMessageDialog msgDlg1(
|
||||
this,
|
||||
"Do you want to use a relative path to the appended "
|
||||
"schematic?", "Select Path Type",
|
||||
wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_QUESTION | wxCENTER );
|
||||
msgDlg1.SetYesNoLabels( wxMessageDialog::ButtonLabel( "Use Relative Path" ),
|
||||
wxMessageDialog::ButtonLabel( "Use Absolute Path" ) );
|
||||
int rsp = msgDlg1.ShowModal();
|
||||
|
||||
if( rsp == wxID_CANCEL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if( rsp == wxID_NO )
|
||||
{
|
||||
topLevelSheetPath = fn.GetPathWithSep();
|
||||
|
||||
if( wxFileName::GetPathSeparator() == '\\' )
|
||||
topLevelSheetPath.Replace( "\\", "/" );
|
||||
}
|
||||
else
|
||||
{
|
||||
topLevelSheetPath = tmp.GetPathWithSep( wxPATH_UNIX );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
topLevelSheetPath = tmp.GetPathWithSep();
|
||||
|
||||
if( wxFileName::GetPathSeparator() == '\\' )
|
||||
topLevelSheetPath.Replace( "\\", "/" );
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure any new sheet changes do not cause any recursion issues.
|
||||
SCH_SHEET_LIST hierarchy( g_RootSheet ); // This is the schematic sheet hierarchy.
|
||||
SCH_SHEET_LIST sheetHierarchy( newSheet.get() ); // This is the hierarchy of the import.
|
||||
|
@ -496,89 +525,231 @@ bool SCH_EDIT_FRAME::AppendSchematic()
|
|||
"remapped before it can be imported into the current project." );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there are symbol libraries in the imported schematic that are not in the
|
||||
// symbol library table of this project, there could be a lot of broken symbol
|
||||
// library links. Attempt to add the missing libraries to the project symbol
|
||||
// library table.
|
||||
newScreens.GetLibNicknames( names );
|
||||
wxArrayString newLibNames;
|
||||
|
||||
wxArrayString newLibNames;
|
||||
SCH_SCREENS prjScreens( g_RootSheet );
|
||||
|
||||
newScreens.GetLibNicknames( names );
|
||||
|
||||
wxMessageDialog::ButtonLabel okButtonLabel( _( "Continue Append" ) );
|
||||
wxMessageDialog::ButtonLabel cancelButtonLabel( _( "Cancel Append" ) );
|
||||
|
||||
if( fn.GetPath( wxPATH_GET_SEPARATOR ) == Prj().GetProjectPath()
|
||||
&& !prjScreens.HasSchematic( fullFileName ) )
|
||||
{
|
||||
// A schematic in the current project path that isn't part of the current project.
|
||||
// It's possible the user copied this schematic from another project so the library
|
||||
// links may not be avaible. Even this is check is no guarantee that all symbol
|
||||
// library links are valid but it's better than nothing.
|
||||
for( const auto& name : names )
|
||||
{
|
||||
if( !Prj().SchSymbolLibTable()->HasLibrary( name ) )
|
||||
newLibNames.Add( name );
|
||||
}
|
||||
|
||||
if( !newLibNames.IsEmpty() )
|
||||
{
|
||||
msg = _( "There are library names in the appended schematic that are missing "
|
||||
"from the project library table. This may result in broken symbol "
|
||||
"library links for the appended schematic. Do you wish to continue?" );
|
||||
wxMessageDialog msgDlg1( this, msg, _( "Continue Append Schematic" ),
|
||||
wxOK | wxCANCEL | wxCANCEL_DEFAULT |
|
||||
wxCENTER | wxICON_QUESTION );
|
||||
msgDlg1.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
|
||||
|
||||
if( msgDlg1.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( fn.GetPath( wxPATH_GET_SEPARATOR ) != Prj().GetProjectPath() )
|
||||
{
|
||||
// A schematic loaded from a path other than the current project path.
|
||||
|
||||
// If there are symbol libraries in the imported schematic that are not in the
|
||||
// symbol library table of this project, there could be a lot of broken symbol
|
||||
// library links. Attempt to add the missing libraries to the project symbol
|
||||
// library table.
|
||||
wxArrayString duplicateLibNames;
|
||||
|
||||
for( const auto& name : names )
|
||||
{
|
||||
if( !Prj().SchSymbolLibTable()->HasLibrary( name ) )
|
||||
newLibNames.Add( name );
|
||||
else
|
||||
duplicateLibNames.Add( name );
|
||||
}
|
||||
|
||||
SYMBOL_LIB_TABLE table;
|
||||
wxFileName symLibTableFn( fn.GetPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
|
||||
|
||||
if( !newLibNames.IsEmpty() && symLibTableFn.Exists() && symLibTableFn.IsFileReadable() )
|
||||
// If there are any new or duplicate libraries, check to see if it's possible that
|
||||
// there could be any missing libraries that would cause broken symbol library links.
|
||||
if( !newLibNames.IsEmpty() || !duplicateLibNames.IsEmpty() )
|
||||
{
|
||||
SYMBOL_LIB_TABLE table;
|
||||
if( !symLibTableFn.Exists() || !symLibTableFn.IsFileReadable() )
|
||||
{
|
||||
msg.Printf( _( "The project library table \"%s\" does not exist or cannot "
|
||||
"be read. This may result in broken symbol links for the "
|
||||
"appended schematic. Do you wish to continue?" ),
|
||||
fn.GetFullPath() );
|
||||
wxMessageDialog msgDlg2( this, msg, _( "Continue Append Schematic" ),
|
||||
wxOK | wxCANCEL | wxCANCEL_DEFAULT |
|
||||
wxCENTER | wxICON_QUESTION );
|
||||
msgDlg2.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
|
||||
|
||||
try
|
||||
{
|
||||
table.Load( symLibTableFn.GetFullPath() );
|
||||
if( msgDlg2.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
else
|
||||
{
|
||||
msg.Printf( _( "An error occurred loading the symbol library table \"%s\"." ),
|
||||
symLibTableFn.GetFullPath() );
|
||||
DisplayErrorMessage( NULL, msg, ioe.What() );
|
||||
}
|
||||
|
||||
if( !table.IsEmpty() )
|
||||
{
|
||||
for( const auto& libName : newLibNames )
|
||||
try
|
||||
{
|
||||
if( !table.HasLibrary( libName ) )
|
||||
continue;
|
||||
|
||||
// Don't expand environment variable because KIPRJMOD will not be correct
|
||||
// for a different project.
|
||||
wxString uri = table.GetFullURI( libName, false );
|
||||
wxFileName newLib;
|
||||
|
||||
if( uri.Contains( "${KIPRJMOD}" ) )
|
||||
{
|
||||
newLib.SetPath( fn.GetPath() );
|
||||
newLib.SetFullName( uri.AfterLast( '}' ) );
|
||||
uri = newLib.GetFullPath();
|
||||
}
|
||||
else if( uri.Contains( "$(KIPRJMOD)" ) )
|
||||
{
|
||||
newLib.SetPath( fn.GetPath() );
|
||||
newLib.SetFullName( uri.AfterLast( ')' ) );
|
||||
uri = newLib.GetFullPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = table.GetFullURI( libName );
|
||||
}
|
||||
|
||||
// Add the library from the imported project to the current project
|
||||
// symbol library table.
|
||||
const SYMBOL_LIB_TABLE_ROW* row = table.FindRow( libName );
|
||||
|
||||
wxCHECK2_MSG( row, continue, "Library '" + libName +
|
||||
"' missing from symbol library table '" +
|
||||
symLibTableFn.GetFullPath() + "'." );
|
||||
|
||||
wxString newLibName = libName;
|
||||
int libNameCnt = 1;
|
||||
|
||||
// Rename the imported symbol library if it already exists.
|
||||
while( Prj().SchSymbolLibTable()->HasLibrary( newLibName ) )
|
||||
newLibName = wxString::Format( "%s%d", libName, libNameCnt );
|
||||
|
||||
auto newRow = new SYMBOL_LIB_TABLE_ROW( newLibName, uri, row->GetType(),
|
||||
row->GetOptions(), row->GetDescr() );
|
||||
Prj().SchSymbolLibTable()->InsertRow( newRow );
|
||||
|
||||
if( libName != newLibName )
|
||||
newScreens.ChangeSymbolLibNickname( libName, newLibName );
|
||||
table.Load( symLibTableFn.GetFullPath() );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
msg.Printf( _( "An error occurred loading the symbol library table \"%s\"." ),
|
||||
symLibTableFn.GetFullPath() );
|
||||
DisplayErrorMessage( NULL, msg, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if any of the symbol libraries found in the appended schematic do
|
||||
// not exist in the current project are missing from the appended project symbol
|
||||
// library table.
|
||||
if( !newLibNames.IsEmpty() )
|
||||
{
|
||||
bool missingLibNames = table.IsEmpty();
|
||||
|
||||
if( !missingLibNames )
|
||||
{
|
||||
for( const auto& newLibName : newLibNames )
|
||||
{
|
||||
if( !table.HasLibrary( newLibName ) )
|
||||
{
|
||||
missingLibNames = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( missingLibNames )
|
||||
{
|
||||
msg = _( "There are library names in the appended schematic that are missing "
|
||||
"from the appended schematic project library table. This may result "
|
||||
"in broken symbol library links for the appended schematic. "
|
||||
"Do you wish to continue?" );
|
||||
wxMessageDialog msgDlg3( this, msg, _( "Continue Append Schematic" ),
|
||||
wxOK | wxCANCEL | wxCANCEL_DEFAULT |
|
||||
wxCENTER | wxICON_QUESTION );
|
||||
msgDlg3.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
|
||||
|
||||
if( msgDlg3.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The library name already exists in the current project. Check to see if the
|
||||
// duplicate name is the same library in the current project. If it's not, it's
|
||||
// most likely that the symbol library links will be broken.
|
||||
if( !duplicateLibNames.IsEmpty() && !table.IsEmpty() )
|
||||
{
|
||||
bool libNameConflict = false;
|
||||
|
||||
for( const auto& duplicateLibName : duplicateLibNames )
|
||||
{
|
||||
const SYMBOL_LIB_TABLE_ROW* thisRow = nullptr;
|
||||
const SYMBOL_LIB_TABLE_ROW* otherRow = nullptr;
|
||||
|
||||
if( Prj().SchSymbolLibTable()->HasLibrary( duplicateLibName ) )
|
||||
thisRow = Prj().SchSymbolLibTable()->FindRow( duplicateLibName );
|
||||
|
||||
if( table.HasLibrary( duplicateLibName ) )
|
||||
otherRow = table.FindRow( duplicateLibName );
|
||||
|
||||
// It's in the global library table so there is no conflict.
|
||||
if( thisRow && !otherRow )
|
||||
continue;
|
||||
|
||||
if( !thisRow || !otherRow )
|
||||
continue;
|
||||
|
||||
wxFileName otherUriFileName;
|
||||
wxString thisURI = thisRow->GetFullURI( true );
|
||||
wxString otherURI = otherRow->GetFullURI( false);
|
||||
|
||||
if( otherURI.Contains( "${KIPRJMOD}" ) || otherURI.Contains( "$(KIPRJMOD)" ) )
|
||||
{
|
||||
// Cannot use relative paths here, "${KIPRJMOD}../path-to-cache-lib" does
|
||||
// not expand to a valid symbol library path.
|
||||
otherUriFileName.SetPath( fn.GetPath() );
|
||||
otherUriFileName.SetFullName( otherURI.AfterLast( '}' ) );
|
||||
otherURI = otherUriFileName.GetFullPath();
|
||||
}
|
||||
|
||||
if( thisURI != otherURI )
|
||||
{
|
||||
libNameConflict = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( libNameConflict )
|
||||
{
|
||||
msg = _( "A duplicate library name that references a different library exists "
|
||||
"in the current library table. This conflict cannot be resolved and "
|
||||
"may result in broken symbol library links for the appended schematic. "
|
||||
"Do you wish to continue?" );
|
||||
wxMessageDialog msgDlg4( this, msg, _( "Continue Append Schematic" ),
|
||||
wxOK | wxCANCEL | wxCANCEL_DEFAULT |
|
||||
wxCENTER | wxICON_QUESTION );
|
||||
msgDlg4.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
|
||||
|
||||
if( msgDlg4.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All (most?) of the possible broken symbol library link cases are covered. Map the
|
||||
// new appended schematic project symbol library table entries to the current project
|
||||
// symbol library table.
|
||||
if( !newLibNames.IsEmpty() && !table.IsEmpty() )
|
||||
{
|
||||
for( const auto& libName : newLibNames )
|
||||
{
|
||||
if( !table.HasLibrary( libName )
|
||||
|| Prj().SchSymbolLibTable()->HasLibrary( libName ) )
|
||||
continue;
|
||||
|
||||
// Don't expand environment variable because KIPRJMOD will not be correct
|
||||
// for a different project.
|
||||
wxString uri = table.GetFullURI( libName, false );
|
||||
wxFileName newLib;
|
||||
|
||||
if( uri.Contains( "${KIPRJMOD}" ) || uri.Contains( "$(KIPRJMOD)" ) )
|
||||
{
|
||||
// Cannot use relative paths here, "${KIPRJMOD}../path-to-cache-lib" does
|
||||
// not expand to a valid symbol library path.
|
||||
newLib.SetPath( fn.GetPath() );
|
||||
newLib.SetFullName( uri.AfterLast( '}' ) );
|
||||
uri = newLib.GetFullPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = table.GetFullURI( libName );
|
||||
}
|
||||
|
||||
// Add the library from the imported project to the current project
|
||||
// symbol library table.
|
||||
const SYMBOL_LIB_TABLE_ROW* row = table.FindRow( libName );
|
||||
|
||||
auto newRow = new SYMBOL_LIB_TABLE_ROW( libName, uri, row->GetType(),
|
||||
row->GetOptions(), row->GetDescr() );
|
||||
|
||||
Prj().SchSymbolLibTable()->InsertRow( newRow );
|
||||
libTableChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -591,7 +762,7 @@ bool SCH_EDIT_FRAME::AppendSchematic()
|
|||
|
||||
sheets.Collect( screen->GetDrawItems(), SCH_COLLECTOR::SheetsOnly );
|
||||
|
||||
for( int i = 0; i < sheets.GetCount(); ++i )
|
||||
for( i = 0; i < sheets.GetCount(); ++i )
|
||||
{
|
||||
if( newSheet->GetScreen()->GetSheet( ( ( SCH_SHEET* ) sheets[i] )->GetName() ) )
|
||||
duplicateSheetNames.Add( ( ( SCH_SHEET* ) sheets[i] )->GetName() );
|
||||
|
@ -601,6 +772,7 @@ bool SCH_EDIT_FRAME::AppendSchematic()
|
|||
{
|
||||
msg.Printf( "Duplicate sheet names exist on the current page. Do you want to "
|
||||
"automatically rename the duplicate sheet names?" );
|
||||
|
||||
if( !IsOK( this, msg ) )
|
||||
return false;
|
||||
}
|
||||
|
@ -620,6 +792,21 @@ bool SCH_EDIT_FRAME::AppendSchematic()
|
|||
renamedSheet->SetName( wxString::Format( "Sheet%8.8lX", (unsigned long) newtimestamp ) );
|
||||
}
|
||||
|
||||
SCH_TYPE_COLLECTOR newTopLevelSheets;
|
||||
|
||||
newTopLevelSheets.Collect( newSheet->GetScreen()->GetDrawItems(), SCH_COLLECTOR::SheetsOnly );
|
||||
|
||||
for( i = 0; i < newTopLevelSheets.GetCount(); ++i )
|
||||
{
|
||||
SCH_SHEET* tmpSheet = dynamic_cast< SCH_SHEET* >( newTopLevelSheets[i] );
|
||||
wxCHECK2( tmpSheet != nullptr, continue );
|
||||
tmpSheet->SetFileName( topLevelSheetPath + tmpSheet->GetFileName() );
|
||||
}
|
||||
|
||||
if( libTableChanged )
|
||||
Prj().SchSymbolLibTable()->Save( Prj().GetProjectPath() +
|
||||
SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
|
||||
|
||||
// It is finally safe to add the imported schematic.
|
||||
screen->Append( newScreen );
|
||||
|
||||
|
|
|
@ -1607,6 +1607,18 @@ int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString&
|
|||
}
|
||||
|
||||
|
||||
bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
|
||||
{
|
||||
for( const SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
||||
{
|
||||
if( screen->GetFileName() == aSchematicFileName )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::BuildClientSheetPathList()
|
||||
{
|
||||
SCH_SHEET_LIST sheetList( g_RootSheet );
|
||||
|
|
|
@ -622,6 +622,17 @@ public:
|
|||
*/
|
||||
int ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo );
|
||||
|
||||
/**
|
||||
* Check if one of the schematics in the list of screens is \a aSchematicFileName.
|
||||
*
|
||||
* Schematic file names in SCH_SCREEN object are stored with the absolute path to
|
||||
* the schematic file.
|
||||
*
|
||||
* @param aSchematicFileName is the schematic file name to search.
|
||||
* @return true if the a schematic matching the file name has been found.
|
||||
*/
|
||||
bool HasSchematic( const wxString& aSchematicFileName );
|
||||
|
||||
/**
|
||||
* built the list of sheet paths sharing a screen for each screen in use
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue