From 24fd659bce08c5fd4e98df89634e25e3f6c17b6c Mon Sep 17 00:00:00 2001 From: JamesJCode <13408010-JamesJCode@users.noreply.gitlab.com> Date: Fri, 20 Jan 2023 19:01:35 +0000 Subject: [PATCH] Eeschema: QA schematic loader now traverses hierarchical sheets (Assumes all nested schematics are in the same directory as the root schematic) --- qa/schematic_utils/schematic_file_util.cpp | 84 +++++++++++++++------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/qa/schematic_utils/schematic_file_util.cpp b/qa/schematic_utils/schematic_file_util.cpp index 3e8e8d3021..341dab9bde 100644 --- a/qa/schematic_utils/schematic_file_util.cpp +++ b/qa/schematic_utils/schematic_file_util.cpp @@ -70,40 +70,76 @@ void DumpSchematicToFile( SCHEMATIC& aSchematic, SCH_SHEET& aSheet, const std::s io.Save( aFilename, &aSheet, &aSchematic ); } - -std::unique_ptr ReadSchematicFromStream( std::istream& aStream, PROJECT* aProject ) +void LoadSheetSchematicContents( const std::string& fileName, SCH_SHEET* sheet ) { + std::ifstream fileStream; + fileStream.open( fileName ); + wxASSERT( fileStream.is_open() ); STDISTREAM_LINE_READER reader; - reader.SetStream( aStream ); + reader.SetStream( fileStream ); + SCH_SEXPR_PARSER parser( &reader ); + parser.ParseSchematic( sheet ); +} - SCH_SEXPR_PARSER parser( &reader ); - std::unique_ptr schematic( new SCHEMATIC( nullptr ) ); +void LoadHierarchy( SCHEMATIC* schematic, SCH_SHEET* sheet, const std::string& sheetFilename, + std::unordered_map& parsedScreens ) +{ + SCH_SCREEN* screen = nullptr; - try - { - schematic->SetProject( aProject ); - SCH_SHEET* newSheet = new SCH_SHEET( schematic.get() ); - schematic->SetRoot( newSheet ); - SCH_SCREEN* rootScreen = new SCH_SCREEN( schematic.get() ); - schematic->Root().SetScreen( rootScreen ); - parser.ParseSchematic( newSheet ); - } - catch( const IO_ERROR& ) + if( !sheet->GetScreen() ) { + // Construct paths + const wxFileName fileName( sheetFilename ); + const std::string filePath( fileName.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ) ); + const std::string fileBareName( fileName.GetFullName() ); + + // Check for existing screen + auto screenFound = parsedScreens.find( fileBareName ); + if( screenFound != parsedScreens.end() ) + screen = screenFound->second; + + // Configure sheet with existing screen, or load screen + if( screen ) + { + // Screen already loaded - assign to sheet + sheet->SetScreen( screen ); + sheet->GetScreen()->SetParent( schematic ); + } + else + { + // Load screen and assign to sheet + screen = new SCH_SCREEN( schematic ); + parsedScreens.insert( { fileBareName, screen } ); + sheet->SetScreen( screen ); + sheet->GetScreen()->SetFileName( sheetFilename ); + LoadSheetSchematicContents( sheetFilename, sheet ); + } + + // Recurse through child sheets + for( SCH_ITEM* item : sheet->GetScreen()->Items().OfType( SCH_SHEET_T ) ) + { + SCH_SHEET* childSheet = static_cast( item ); + wxFileName childSheetFilename = childSheet->GetFileName(); + if( !childSheetFilename.IsAbsolute() ) + childSheetFilename.MakeAbsolute( filePath ); + std::string childSheetFullFilename( childSheetFilename.GetFullPath() ); + LoadHierarchy( schematic, childSheet, childSheetFullFilename, parsedScreens ); + } } - - return schematic; } - -std::unique_ptr ReadSchematicFromFile( const std::string& aFilename, PROJECT* aProject ) +std::unique_ptr LoadHierarchyFromRoot( const std::string& rootFilename, + PROJECT* project ) { - std::ifstream file_stream; - file_stream.open( aFilename ); + std::unique_ptr schematic( new SCHEMATIC( nullptr ) ); + std::unordered_map parsedScreens; - wxASSERT( file_stream.is_open() ); + schematic->SetProject( project ); + SCH_SHEET* rootSheet = new SCH_SHEET( schematic.get() ); + schematic->SetRoot( rootSheet ); + LoadHierarchy( schematic.get(), rootSheet, rootFilename, parsedScreens ); - return ReadSchematicFromStream( file_stream, aProject ); + return schematic; } @@ -133,7 +169,7 @@ void LoadSchematic( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath aSettingsManager.Prj().SetElem( PROJECT::ELEM_SCH_SYMBOL_LIBS, nullptr ); - aSchematic = ReadSchematicFromFile( schematicPath, &aSettingsManager.Prj() ); + aSchematic = LoadHierarchyFromRoot( schematicPath, &aSettingsManager.Prj() ); aSchematic->CurrentSheet().push_back( &aSchematic->Root() );