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 The 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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <schematic_file_util.h>
21#include <qa_utils/wx_utils/unit_test_utils.h> // GetEeschemaTestDataDir()
22
23#include <stdexcept>
24#include <unordered_set>
25
27
28#include <connection_graph.h>
29#include <project.h>
30#include <schematic.h>
31#include <sch_screen.h>
32#include <sch_rule_area.h>
33
34// For SCH parsing
37#include <richio.h>
38
40
41namespace KI_TEST
42{
43
44void DumpSchematicToFile( SCHEMATIC& aSchematic, SCH_SHEET& aSheet, const std::string& aFilename )
45{
47 io.SaveSchematicFile( aFilename, &aSheet, &aSchematic );
48}
49
50std::unique_ptr<SCHEMATIC> LoadHierarchyFromRoot( const std::string& rootFilename,
52{
53 auto schematic = std::make_unique<SCHEMATIC>( project );
54 schematic->Reset();
55 SCH_SHEET* defaultSheet = schematic->GetTopLevelSheet( 0 );
56
58 SCH_SHEET* rootSheet = io.LoadSchematicFile( rootFilename, schematic.get() );
59 schematic->AddTopLevelSheet( rootSheet );
60 schematic->RemoveTopLevelSheet( defaultSheet );
61 delete defaultSheet;
62
63 if( !io.GetError().IsEmpty() )
64 throw std::runtime_error( io.GetError().ToStdString( wxConvUTF8 ) );
65
66 return schematic;
67}
68
69std::unique_ptr<SCHEMATIC> ReadSchematicFromStream( std::istream& aStream, PROJECT* aProject )
70{
71 std::unique_ptr<SCHEMATIC> schematic( new SCHEMATIC( nullptr ) );
72 schematic->SetProject( aProject );
73 SCH_SHEET* rootSheet = new SCH_SHEET( schematic.get() );
74 SCH_SCREEN* screen = new SCH_SCREEN( schematic.get() );
75 rootSheet->SetScreen( screen );
76 screen->SetParent( schematic.get() );
77 schematic->SetTopLevelSheets( { rootSheet } );
78
79 // Parse from provided stream using existing parser infra
81 reader.SetStream( aStream );
82 SCH_IO_KICAD_SEXPR_PARSER parser( &reader, nullptr, 0, rootSheet );
83 parser.ParseSchematic( rootSheet );
84
85 // Link symbol instances like LoadSchematic does (single sheet case)
87 SCH_SHEET_LIST sheets = schematic->BuildSheetListSortedByPageNumbers();
88 sheets.UpdateSymbolInstanceData( schematic->RootScreen()->GetSymbolInstances() );
89 sheets.UpdateSheetInstanceData( schematic->RootScreen()->GetSheetInstances() );
90 sheets.AnnotatePowerSymbols();
91 for( SCH_SHEET_PATH& sheet : sheets )
92 sheet.UpdateAllScreenReferences();
93
94 // The IO layer normally pipes parsed override maps into the connection graph;
95 // this reload-only path has to do the same so manual chains survive a reload.
96 if( schematic->ConnectionGraph() )
97 {
98 schematic->ConnectionGraph()->SetNetChainNetClassOverrides( parser.GetNetChainNetClasses() );
99 schematic->ConnectionGraph()->SetNetChainColorOverrides( parser.GetNetChainColors() );
100
101 std::map<wxString, CONNECTION_GRAPH::CHAIN_TERMINAL_REFS> termRefs;
102
103 for( const auto& [name, terms] : parser.GetNetChainTerminalRefs() )
104 {
105 termRefs[name] = { { terms.first.ref, terms.first.pin },
106 { terms.second.ref, terms.second.pin } };
107 }
108
109 schematic->ConnectionGraph()->SetNetChainTerminalRefOverrides( termRefs );
110 schematic->ConnectionGraph()->SetNetChainMemberNetOverrides( parser.GetNetChainMemberNets() );
111 }
112
113 return schematic;
114}
115
116
117void LoadSchematic( SETTINGS_MANAGER& aSettingsManager, const wxString& aRelPath,
118 std::unique_ptr<SCHEMATIC>& aSchematic )
119{
120 if( aSchematic )
121 {
122 PROJECT* prj = &aSchematic->Project();
123
124 aSchematic->SetProject( nullptr );
125 aSettingsManager.UnloadProject( prj, false );
126 aSchematic->Reset();
127 }
128
129 std::string absPath = GetEeschemaTestDataDir() + aRelPath.ToStdString();
130 wxFileName projectFile( absPath + ".kicad_pro" );
131 wxFileName legacyProject( absPath + ".pro" );
132 std::string schematicPath = absPath + ".kicad_sch";
133
134 if( projectFile.Exists() )
135 aSettingsManager.LoadProject( projectFile.GetFullPath() );
136 else if( legacyProject.Exists() )
137 aSettingsManager.LoadProject( legacyProject.GetFullPath() );
138 else
139 aSettingsManager.LoadProject( "" );
140
141 aSettingsManager.Prj().SetElem( PROJECT::ELEM::LEGACY_SYMBOL_LIBS, nullptr );
142
143 aSchematic = LoadHierarchyFromRoot( schematicPath, &aSettingsManager.Prj() );
144
145 SCH_SCREENS screens( aSchematic->Root() );
146
147 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
148 screen->UpdateLocalLibSymbolLinks();
149
150 SCH_SHEET_LIST sheets = aSchematic->BuildSheetListSortedByPageNumbers();
151
152 // Restore all of the loaded symbol instances from the root sheet screen.
153 sheets.UpdateSymbolInstanceData( aSchematic->RootScreen()->GetSymbolInstances() );
154 sheets.UpdateSheetInstanceData( aSchematic->RootScreen()->GetSheetInstances() );
155
156 if( aSchematic->RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
158
159 if( aSchematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221206 )
160 {
161 for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
162 screen->MigrateSimModels();
163 }
164
165
166 sheets.AnnotatePowerSymbols();
167
168 // NOTE: This is required for multi-unit symbols to be correct
169 // Normally called from SCH_EDIT_FRAME::FixupJunctions() but could be refactored
170 for( SCH_SHEET_PATH& sheet : sheets )
171 sheet.UpdateAllScreenReferences();
172
173 // NOTE: SchematicCleanUp is not called; QA schematics must already be clean or else
174 // SchematicCleanUp must be freed from its UI dependencies.
175
176 std::unordered_set<SCH_SCREEN*> allScreens;
177
178 for( const SCH_SHEET_PATH& path : sheets )
179 allScreens.insert( path.LastScreen() );
180
181 SCH_RULE_AREA::UpdateRuleAreasInScreens( allScreens, nullptr );
182 aSchematic->ConnectionGraph()->Recalculate( sheets, true );
183}
184
185} // namespace KI_TEST
const char * name
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
Container for project specific data.
Definition project.h:63
virtual void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
Definition project.cpp:396
@ LEGACY_SYMBOL_LIBS
Definition project.h:70
Holds all the data relating to one schematic.
Definition schematic.h:148
Object to parser s-expression symbol library and schematic file formats.
const std::map< wxString, wxString > & GetNetChainNetClasses() const
const std::map< wxString, COLOR4D > & GetNetChainColors() const
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
const std::map< wxString, CHAIN_TERMINALS > & GetNetChainTerminalRefs() const
const std::map< wxString, std::set< wxString > > & GetNetChainMemberNets() const
A SCH_IO derivation for loading schematic files using the new s-expression file format.
const wxString & GetError() const override
Return an error string to the caller.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
static std::vector< std::pair< SCH_RULE_AREA *, SCH_SCREEN * > > UpdateRuleAreasInScreens(std::unordered_set< SCH_SCREEN * > &screens, KIGFX::SCH_VIEW *view)
Update all rule area connectvity / caches in the given sheet paths.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:758
SCH_SCREEN * GetNext()
void FixLegacyPowerSymbolMismatches()
Fix legacy power symbols that have mismatched value text fields and invisible power pin names.
SCH_SCREEN * GetFirst()
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
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:48
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister 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 > ReadSchematicFromStream(std::istream &aStream, PROJECT *aProject)
std::unique_ptr< SCHEMATIC > LoadHierarchyFromRoot(const std::string &rootFilename, PROJECT *project)
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)
std::string path