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
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 // NOTE: This is required for multi-unit symbols to be correct
167 // Normally called from SCH_EDIT_FRAME::FixupJunctions() but could be refactored
168 for( SCH_SHEET_PATH& sheet : sheets )
169 sheet.UpdateAllScreenReferences();
170
171 // NOTE: SchematicCleanUp is not called; QA schematics must already be clean or else
172 // SchematicCleanUp must be freed from its UI dependencies.
173
174 std::unordered_set<SCH_SCREEN*> allScreens;
175
176 for( const SCH_SHEET_PATH& path : sheets )
177 allScreens.insert( path.LastScreen() );
178
179 SCH_RULE_AREA::UpdateRuleAreasInScreens( allScreens, nullptr );
180 aSchematic->ConnectionGraph()->Recalculate( sheets, true );
181}
182
183} // 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:149
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 aIsCopyableOnly=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:818
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 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.
Test utilities for timestamps.
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