KiCad PCB EDA Suite
Loading...
Searching...
No Matches
schematic_file_util.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one at
18 * http://www.gnu.org/licenses/
19 */
20
21#include <schematic_file_util.h>
22#include <qa_utils/wx_utils/unit_test_utils.h> // GetEeschemaTestDataDir()
23
25
26#include <connection_graph.h>
27#include <lib_textbox.h>
28#include <schematic.h>
29#include <sch_screen.h>
30
31// For SCH parsing
34#include <richio.h>
35
37
38namespace KI_TEST
39{
40
41void DumpSchematicToFile( SCHEMATIC& aSchematic, SCH_SHEET& aSheet, const std::string& aFilename )
42{
44 io.SaveSchematicFile( aFilename, &aSheet, &aSchematic );
45}
46
47void LoadSheetSchematicContents( const std::string& fileName, SCH_SHEET* sheet )
48{
49 std::ifstream fileStream;
50 fileStream.open( fileName );
51 wxASSERT( fileStream.is_open() );
53 reader.SetStream( fileStream );
54 SCH_SEXPR_PARSER parser( &reader );
55 parser.ParseSchematic( sheet );
56}
57
58void LoadHierarchy( SCHEMATIC* schematic, SCH_SHEET* sheet, const std::string& sheetFilename,
59 std::unordered_map<std::string, SCH_SCREEN*>& parsedScreens )
60{
61 SCH_SCREEN* screen = nullptr;
62
63 if( !sheet->GetScreen() )
64 {
65 // Construct paths
66 const wxFileName fileName( sheetFilename );
67 const std::string filePath( fileName.GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ) );
68 const std::string fileBareName( fileName.GetFullName() );
69
70 // Check for existing screen
71 auto screenFound = parsedScreens.find( fileBareName );
72 if( screenFound != parsedScreens.end() )
73 screen = screenFound->second;
74
75 // Configure sheet with existing screen, or load screen
76 if( screen )
77 {
78 // Screen already loaded - assign to sheet
79 sheet->SetScreen( screen );
80 sheet->GetScreen()->SetParent( schematic );
81 }
82 else
83 {
84 // Load screen and assign to sheet
85 screen = new SCH_SCREEN( schematic );
86 parsedScreens.insert( { fileBareName, screen } );
87 sheet->SetScreen( screen );
88 sheet->GetScreen()->SetFileName( sheetFilename );
89 LoadSheetSchematicContents( sheetFilename, sheet );
90 }
91
92 // Recurse through child sheets
93 for( SCH_ITEM* item : sheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
94 {
95 SCH_SHEET* childSheet = static_cast<SCH_SHEET*>( item );
96 wxFileName childSheetFilename = childSheet->GetFileName();
97 if( !childSheetFilename.IsAbsolute() )
98 childSheetFilename.MakeAbsolute( filePath );
99 std::string childSheetFullFilename( childSheetFilename.GetFullPath() );
100 LoadHierarchy( schematic, childSheet, childSheetFullFilename, parsedScreens );
101 }
102 }
103}
104
105std::unique_ptr<SCHEMATIC> LoadHierarchyFromRoot( const std::string& rootFilename,
107{
108 std::unique_ptr<SCHEMATIC> schematic( new SCHEMATIC( nullptr ) );
109 std::unordered_map<std::string, SCH_SCREEN*> parsedScreens;
110
111 schematic->SetProject( project );
112 SCH_SHEET* rootSheet = new SCH_SHEET( schematic.get() );
113 schematic->SetRoot( rootSheet );
114 LoadHierarchy( schematic.get(), rootSheet, rootFilename, parsedScreens );
115
116 return schematic;
117}
118
119
120void LoadSchematic( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath,
121 std::unique_ptr<SCHEMATIC>& aSchematic )
122{
123 if( aSchematic )
124 {
125 PROJECT* prj = &aSchematic->Prj();
126
127 aSchematic->SetProject( nullptr );
128 aSettingsManager.UnloadProject( prj, false );
129 aSchematic->Reset();
130 }
131
132 std::string absPath = GetEeschemaTestDataDir() + aRelPath.ToStdString();
133 wxFileName projectFile( absPath + ".kicad_pro" );
134 wxFileName legacyProject( absPath + ".pro" );
135 std::string schematicPath = absPath + ".kicad_sch";
136
137 if( projectFile.Exists() )
138 aSettingsManager.LoadProject( projectFile.GetFullPath() );
139 else if( legacyProject.Exists() )
140 aSettingsManager.LoadProject( legacyProject.GetFullPath() );
141 else
142 aSettingsManager.LoadProject( "" );
143
144 aSettingsManager.Prj().SetElem( PROJECT::ELEM_SCH_SYMBOL_LIBS, nullptr );
145
146 aSchematic = LoadHierarchyFromRoot( schematicPath, &aSettingsManager.Prj() );
147
148 aSchematic->CurrentSheet().push_back( &aSchematic->Root() );
149
150 SCH_SCREENS screens( aSchematic->Root() );
151
152 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
153 screen->UpdateLocalLibSymbolLinks();
154
155 SCH_SHEET_LIST sheets = aSchematic->GetSheets();
156
157 // Restore all of the loaded symbol instances from the root sheet screen.
158 sheets.UpdateSymbolInstanceData( aSchematic->RootScreen()->GetSymbolInstances() );
159 sheets.UpdateSheetInstanceData( aSchematic->RootScreen()->GetSheetInstances() );
160
161 if( aSchematic->RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
163
164 if( aSchematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221206 )
165 {
166 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
167 screen->MigrateSimModels();
168 }
169
170 sheets.AnnotatePowerSymbols();
171
172 // NOTE: This is required for multi-unit symbols to be correct
173 // Normally called from SCH_EDIT_FRAME::FixupJunctions() but could be refactored
174 for( SCH_SHEET_PATH& sheet : sheets )
175 sheet.UpdateAllScreenReferences();
176
177 // NOTE: SchematicCleanUp is not called; QA schematics must already be clean or else
178 // SchematicCleanUp must be freed from its UI dependencies.
179
180 aSchematic->ConnectionGraph()->Recalculate( sheets, true );
181}
182
183} // namespace KI_TEST
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
Container for project specific data.
Definition: project.h:62
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:317
@ ELEM_SCH_SYMBOL_LIBS
Definition: project.h:225
Holds all the data relating to one schematic.
Definition: schematic.h:75
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:150
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:673
SCH_SCREEN * GetNext()
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
SCH_SCREEN * GetFirst()
EE_RTREE & Items()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:109
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:117
Object to parser s-expression symbol library and schematic file formats.
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
A SCH_PLUGIN derivation for loading schematic files using the new s-expression file format.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const STRING_UTF8_MAP *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_PLUGIN implementation knows about,...
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void UpdateSheetInstanceData(const std::vector< SCH_SHEET_INSTANCE > &aSheetInstances)
Update all of the sheet instance information using aSheetInstances.
void AnnotatePowerSymbols()
Silently annotate the not yet annotated power symbols of the entire hierarchy of the sheet path list.
void UpdateSymbolInstanceData(const std::vector< SCH_SYMBOL_INSTANCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:312
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:161
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
LINE_READER that wraps a given std::istream instance.
void SetStream(std::istream &aStream)
Set the stream for this line reader.
std::unique_ptr< SCHEMATIC > LoadHierarchyFromRoot(const std::string &rootFilename, PROJECT *project)
void LoadSheetSchematicContents(const std::string &fileName, SCH_SHEET *sheet)
void LoadHierarchy(SCHEMATIC *schematic, SCH_SHEET *sheet, const std::string &sheetFilename, std::unordered_map< std::string, SCH_SCREEN * > &parsedScreens)
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
void DumpSchematicToFile(SCHEMATIC &aSchematic, SCH_SHEET &aSheet, const std::string &aFilename)
Schematic and symbol library s-expression file format parser definitions.
@ SCH_SHEET_T
Definition: typeinfo.h:157