Eeschema: fix saving hierarchical sheets in stand alone mode.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/8209
This commit is contained in:
parent
9fcd847238
commit
fdcc49d3ee
|
@ -68,7 +68,7 @@ bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName )
|
|||
wxFileName oldFileName;
|
||||
bool success;
|
||||
|
||||
if( aSheet == NULL )
|
||||
if( aSheet == nullptr )
|
||||
aSheet = GetCurrentSheet().Last();
|
||||
|
||||
SCH_SCREEN* screen = aSheet->GetScreen();
|
||||
|
@ -208,7 +208,7 @@ void SCH_EDIT_FRAME::Save_File( bool doSaveAs )
|
|||
{
|
||||
if( doSaveAs )
|
||||
{
|
||||
if( SaveEEFile( NULL, true ) )
|
||||
if( SaveEEFile( nullptr, true ) )
|
||||
{
|
||||
SCH_SCREEN* screen = GetScreen();
|
||||
|
||||
|
@ -231,7 +231,7 @@ void SCH_EDIT_FRAME::Save_File( bool doSaveAs )
|
|||
}
|
||||
else
|
||||
{
|
||||
SaveEEFile( NULL );
|
||||
SaveEEFile( nullptr );
|
||||
}
|
||||
|
||||
UpdateTitle();
|
||||
|
@ -348,18 +348,18 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
// event handler in there.
|
||||
// And when a schematic file is loaded, we need these libs to initialize
|
||||
// some parameters (links to PART LIB, dangling ends ...)
|
||||
Prj().SetElem( PROJECT::ELEM_SCH_PART_LIBS, NULL );
|
||||
Prj().SetElem( PROJECT::ELEM_SCH_PART_LIBS, nullptr );
|
||||
Prj().SchLibs();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No legacy symbol libraries including the cache are loaded with the new file format.
|
||||
Prj().SetElem( PROJECT::ELEM_SCH_PART_LIBS, NULL );
|
||||
Prj().SetElem( PROJECT::ELEM_SCH_PART_LIBS, nullptr );
|
||||
}
|
||||
|
||||
// Load the symbol library table, this will be used forever more.
|
||||
Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, NULL );
|
||||
Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, nullptr );
|
||||
Prj().SchSymbolLibTable();
|
||||
|
||||
// Load project settings after schematic has been set up with the project link, since this will
|
||||
|
@ -776,6 +776,117 @@ bool SCH_EDIT_FRAME::SaveProject()
|
|||
wxString fileName = Prj().AbsolutePath( Schematic().Root().GetFileName() );
|
||||
wxFileName fn = fileName;
|
||||
|
||||
// If this a new schematic without a project and we are in the stand alone mode. All new
|
||||
// sheets that are not loaded from an existing file will have to be saved to a new path
|
||||
// along with the root sheet.
|
||||
if( Prj().GetProjectFullName().IsEmpty() )
|
||||
{
|
||||
// This should only be possible in stand alone mode.
|
||||
wxCHECK( Kiface().IsSingle(), false );
|
||||
|
||||
wxFileDialog dlg( this, _( "Schematic Files" ), fn.GetPath(), fn.GetFullName(),
|
||||
KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
|
||||
wxFileName newFileName = dlg.GetPath();
|
||||
|
||||
if( newFileName.GetExt().IsEmpty() )
|
||||
newFileName.SetExt( KiCadSchematicFileExtension );
|
||||
|
||||
if( !newFileName.DirExists() && !newFileName.Mkdir() )
|
||||
{
|
||||
msg.Printf( _( "Cannot create folder \"%s\"." ), newFileName.GetPath() );
|
||||
|
||||
wxMessageDialog dlgBadPath( this, msg, _( "Error" ),
|
||||
wxOK | wxICON_EXCLAMATION | wxCENTER );
|
||||
|
||||
dlgBadPath.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !newFileName.IsDirWritable() )
|
||||
{
|
||||
msg.Printf( _( "You do not have write permissions to folder \"%s\"." ),
|
||||
newFileName.GetPath() );
|
||||
|
||||
wxMessageDialog dlgBadPerms( this, msg, _( "Error" ),
|
||||
wxOK | wxICON_EXCLAMATION | wxCENTER );
|
||||
|
||||
dlgBadPerms.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
||||
Schematic().Root().SetFileName( newFileName.GetFullName() );
|
||||
Schematic().RootScreen()->SetFileName( newFileName.GetFullPath() );
|
||||
|
||||
// Set the base path to all new sheets.
|
||||
for( size_t i = 0; i < screens.GetCount(); i++ )
|
||||
{
|
||||
screen = screens.GetScreen( i );
|
||||
|
||||
wxCHECK2( screen, continue );
|
||||
|
||||
// The root screen file name has already been set.
|
||||
if( screen == Schematic().RootScreen() )
|
||||
continue;
|
||||
|
||||
wxFileName tmp = screen->GetFileName();
|
||||
|
||||
// Assume existing sheet files are being reused and do not save them to the new
|
||||
// path. Maybe in the future, add a user option to copy schematic files to the
|
||||
// new project path.
|
||||
if( tmp.FileExists() )
|
||||
continue;
|
||||
|
||||
if( tmp.GetPath().IsEmpty() )
|
||||
{
|
||||
tmp.SetPath( newFileName.GetPath() );
|
||||
}
|
||||
else if( tmp.GetPath() == fn.GetPath() )
|
||||
{
|
||||
tmp.SetPath( newFileName.GetPath() );
|
||||
}
|
||||
else if( tmp.GetPath().StartsWith( fn.GetPath() ) )
|
||||
{
|
||||
// NOTE: this hasn't been tested because the sheet properties dialog no longer
|
||||
// allows adding a path specifier in the file name field.
|
||||
wxString newPath = newFileName.GetPath();
|
||||
newPath += tmp.GetPath().Right( fn.GetPath().Length() );
|
||||
tmp.SetPath( newPath );
|
||||
}
|
||||
|
||||
wxLogTrace( tracePathsAndFiles,
|
||||
wxT( "Changing schematic file name path from '%s' to '%s'." ),
|
||||
screen->GetFileName(), tmp.GetFullPath() );
|
||||
|
||||
if( !tmp.DirExists() && !tmp.Mkdir() )
|
||||
{
|
||||
msg.Printf( _( "Cannot create folder \"%s\"." ), newFileName.GetPath() );
|
||||
|
||||
wxMessageDialog dlgBadFilePath( this, msg, _( "Error" ),
|
||||
wxOK | wxICON_EXCLAMATION | wxCENTER );
|
||||
|
||||
dlgBadFilePath.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
||||
screen->SetFileName( tmp.GetFullPath() );
|
||||
}
|
||||
|
||||
// Attempt to make sheet file name paths relative to the new root schematic path.
|
||||
SCH_SHEET_LIST sheets = Schematic().GetSheets();
|
||||
|
||||
for( SCH_SHEET_PATH& sheet : sheets )
|
||||
{
|
||||
if( sheet.Last()->IsRootSheet() )
|
||||
continue;
|
||||
|
||||
sheet.MakeFilePathRelativeToParentSheet();
|
||||
}
|
||||
}
|
||||
|
||||
// Warn user on potential file overwrite. This can happen on shared sheets.
|
||||
wxArrayString overwrittenFiles;
|
||||
|
||||
|
|
|
@ -473,9 +473,53 @@ void SCH_SHEET_PATH::SetPageNumber( const wxString& aPageNumber )
|
|||
}
|
||||
|
||||
|
||||
void SCH_SHEET_PATH::MakeFilePathRelativeToParentSheet()
|
||||
{
|
||||
wxCHECK( m_sheets.size() > 1, /* void */ );
|
||||
|
||||
wxFileName sheetFileName = Last()->GetFileName();
|
||||
|
||||
// If the sheet file name is absolute, then the user requested is so don't make it relative.
|
||||
if( sheetFileName.IsAbsolute() )
|
||||
return;
|
||||
|
||||
SCH_SCREEN* screen = LastScreen();
|
||||
SCH_SCREEN* parentScreen = m_sheets[ m_sheets.size() - 2 ]->GetScreen();
|
||||
|
||||
wxCHECK( screen && parentScreen, /* void */ );
|
||||
|
||||
wxFileName fileName = screen->GetFileName();
|
||||
wxFileName parentFileName = parentScreen->GetFileName();
|
||||
|
||||
// SCH_SCREEN file names must be absolute. If they are not, someone set them incorrectly
|
||||
// on load or on creation.
|
||||
wxCHECK( fileName.IsAbsolute() && parentFileName.IsAbsolute(), /* void */ );
|
||||
|
||||
if( fileName.GetPath() == parentFileName.GetPath() )
|
||||
{
|
||||
Last()->SetFileName( fileName.GetFullName() );
|
||||
}
|
||||
else if( fileName.MakeRelativeTo( parentFileName.GetPath() ) )
|
||||
{
|
||||
Last()->SetFileName( fileName.GetFullPath() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Last()->SetFileName( screen->GetFileName() );
|
||||
}
|
||||
|
||||
wxLogTrace( tracePathsAndFiles,
|
||||
wxT( "\n File name: '%s'"
|
||||
"\n parent file name '%s',"
|
||||
"\n sheet '%s' file name '%s'." ),
|
||||
screen->GetFileName(), parentScreen->GetFileName(), PathHumanReadable(),
|
||||
Last()->GetFileName() );
|
||||
}
|
||||
|
||||
|
||||
SCH_SHEET_LIST::SCH_SHEET_LIST( SCH_SHEET* aSheet, bool aCheckIntegrity )
|
||||
{
|
||||
if( aSheet != NULL )
|
||||
if( aSheet != nullptr )
|
||||
{
|
||||
BuildSheetList( aSheet, aCheckIntegrity );
|
||||
SortByPageNumbers();
|
||||
|
@ -485,7 +529,7 @@ SCH_SHEET_LIST::SCH_SHEET_LIST( SCH_SHEET* aSheet, bool aCheckIntegrity )
|
|||
|
||||
void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
|
||||
{
|
||||
wxCHECK_RET( aSheet != NULL, wxT( "Cannot build sheet list from undefined sheet." ) );
|
||||
wxCHECK_RET( aSheet != nullptr, wxT( "Cannot build sheet list from undefined sheet." ) );
|
||||
|
||||
std::vector<SCH_SHEET*> badSheets;
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ public:
|
|||
|
||||
const SCH_SHEET* GetSheet( unsigned aIndex ) const
|
||||
{
|
||||
SCH_SHEET* retv = NULL;
|
||||
SCH_SHEET* retv = nullptr;
|
||||
|
||||
if( aIndex < size() )
|
||||
retv = at( aIndex );
|
||||
|
@ -346,6 +346,24 @@ public:
|
|||
*/
|
||||
bool TestForRecursion( const wxString& aSrcFileName, const wxString& aDestFileName );
|
||||
|
||||
/**
|
||||
* Make the sheet file name relative to it's parent sheet.
|
||||
*
|
||||
* This should only be called when changing the parent sheet path such performing a save
|
||||
* as or a new schematic without a project in stand alone mode. The sheet file name is
|
||||
* only made relative if the current file name is relative. Absolute sheet file name paths
|
||||
* are a user choice so do not change them.
|
||||
*
|
||||
* Sheet file name paths are set according to the following criteria:
|
||||
* - If the sheet file name path is in the same as the parent sheet file name path, set
|
||||
* the sheet file name to just the file name and extension with no path.
|
||||
* - If the sheet file name path can be made relative to the parent sheet file name path,
|
||||
* set the sheet file name using the relative path.
|
||||
* - If the sheet file name path cannot be converted to a relative path, then fall back to
|
||||
* the absolute file name path.
|
||||
*/
|
||||
void MakeFilePathRelativeToParentSheet();
|
||||
|
||||
bool operator==( const SCH_SHEET_PATH& d1 ) const;
|
||||
|
||||
bool operator!=( const SCH_SHEET_PATH& d1 ) const { return !( *this == d1 ) ; }
|
||||
|
|
Loading…
Reference in New Issue