KiCad PCB EDA Suite
Loading...
Searching...
No Matches
headless_pcb_context.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 * @author Jon Evans <[email protected]>
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
22#include <board.h>
23#include <board_loader.h>
24#include <common.h>
26#include <drc/drc_engine.h>
27#include <footprint.h>
28#include <gestfich.h>
32#include <pcbnew_settings.h>
33#include <pgm_base.h>
34#include <project.h>
35#include <reporter.h>
37#include <spread_footprints.h>
38#include <tool/tool_manager.h>
39#include <tools/drc_tool.h>
40#include <wx/debug.h>
41
42
43HEADLESS_PCB_CONTEXT::HEADLESS_PCB_CONTEXT( std::unique_ptr<BOARD> aBoard, PROJECT* aProject,
44 APP_SETTINGS_BASE* aSettings,
45 KIWAY* aKiway ) :
46 m_board( std::move( aBoard ) ),
47 m_project( aProject ),
48 m_kiway( aKiway ),
49 m_toolManager( std::make_unique<TOOL_MANAGER>() )
50{
51 wxCHECK( m_board, /* void */ );
52 wxCHECK( m_project, /* void */ );
53
54 m_board->SetProject( m_project );
55 m_toolManager->SetEnvironment( m_board.get(), nullptr, nullptr, aSettings, nullptr );
56}
57
58
60{
61 // Sever the board↔project linkage before destruction. The PROJECT holds a raw pointer
62 // (m_BoardSettings) to the board's design settings. If the board is destroyed while the
63 // project still exists, that pointer becomes dangling.
64 if( m_board )
65 m_board->ClearProject();
66}
67
68
70{
71 return m_board.get();
72}
73
74
76{
77 // Shouldn't be able to construct this without a project
78 wxASSERT( m_project );
79 return *m_project;
80}
81
82
87
88
90{
91 if( !m_board )
92 return wxEmptyString;
93
94 return m_board->GetFileName();
95}
96
97
99{
100 if( !m_board )
101 return false;
102
103 wxString fileName = m_board->GetFileName();
104
105 if( fileName.IsEmpty() )
106 return false;
107
108 bool success = BOARD_LOADER::SaveBoard( fileName, *m_board );
109
110 if( success )
111 {
112 m_contentModified = false;
113
114 wxFileName pro = fileName;
115 pro.SetExt( FILEEXT::ProjectFileExtension );
116 pro.MakeAbsolute();
117
118 Pgm().GetSettingsManager().SaveProjectAs( pro.GetFullPath(), m_board->GetProject() );
119 }
120
121 return success;
122}
123
124
125bool HEADLESS_PCB_CONTEXT::SaveBoardAs( const wxString& aFileName )
126{
127 if( !m_board || aFileName.IsEmpty() )
128 return false;
129
130 wxFileName boardPath( EnsureFileExtension( aFileName, FILEEXT::KiCadPcbFileExtension ) );
131 boardPath.MakeAbsolute();
132
133 if( boardPath.GetName().IsEmpty() )
134 return false;
135
136 if( ( !boardPath.DirExists() && !boardPath.Mkdir() ) || !boardPath.IsDirWritable() )
137 return false;
138
139 wxString outPath = boardPath.GetFullPath();
140
141 if( !BOARD_LOADER::SaveBoard( outPath, *m_board ) )
142 return false;
143
144 m_board->SetFileName( outPath );
145 m_contentModified = false;
146
147 wxFileName pro( boardPath );
148 pro.SetExt( FILEEXT::ProjectFileExtension );
149
150 Pgm().GetSettingsManager().SaveProjectAs( pro.GetFullPath(), m_board->GetProject() );
151
152 return true;
153}
154
155
156bool HEADLESS_PCB_CONTEXT::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
157{
158 if( !m_board || aFileName.IsEmpty() )
159 return false;
160
161 wxFileName pro = aFileName;
162 pro.SetExt( FILEEXT::ProjectFileExtension );
163 pro.MakeAbsolute();
164
165 if( aCreateProject && pro.FileExists() )
166 return false;
167
168 wxFileName currentRules( m_board->GetDesignRulesPath() );
169 wxFileName rulesFile = aFileName;
170 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
171 rulesFile.MakeAbsolute();
172
173 if( currentRules.FileExists() && rulesFile.FileExists() )
174 return false;
175
176 wxString outPath = aFileName;
177
178 bool success = BOARD_LOADER::SaveBoard( outPath, *m_board );
179
180 if( success && aCreateProject )
181 Pgm().GetSettingsManager().SaveProjectCopy( pro.GetFullPath(), m_board->GetProject() );
182
183 if( currentRules.FileExists() )
184 {
185 wxString msg;
186 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
187 }
188
189 return success;
190}
191
192
193bool HEADLESS_PCB_CONTEXT::ReadNetlistFromFile( const wxString& aFilename, NETLIST& aNetlist, REPORTER& aReporter )
194{
195 wxString msg;
196
197 try
198 {
199 std::unique_ptr<NETLIST_READER> netlistReader(
200 NETLIST_READER::GetNetlistReader( &aNetlist, aFilename, wxEmptyString ) );
201
202 if( !netlistReader.get() )
203 {
204 msg.Printf( _( "Cannot open netlist file '%s'." ), aFilename );
205 aReporter.Report( msg, RPT_SEVERITY_ERROR );
206 return false;
207 }
208
209 netlistReader->LoadNetlist();
210 LoadNetlistFootprints( GetBoard(), aNetlist, aReporter );
211 }
212 catch( const IO_ERROR& ioe )
213 {
214 msg.Printf( _( "Error loading netlist.\n%s" ), ioe.What().GetData() );
215 aReporter.Report( msg, RPT_SEVERITY_ERROR );
216 return false;
217 }
218
219 return true;
220}
221
222
223std::unique_ptr<BOARD_NETLIST_UPDATER> HEADLESS_PCB_CONTEXT::MakeNetlistUpdater()
224{
225 return std::make_unique<BOARD_NETLIST_UPDATER>( GetToolManager(), GetBoard() );
226}
227
228
230{
231 BOARD* board = GetBoard();
232
233 // Re-sync nets and netclasses
234 board->SynchronizeNetsAndNetClasses( false );
235
236 // Recompute component classes
239
240 // Resync DRC rules to account for new aggregate netclass / component class rules
241 if( DRC_TOOL* drcTool = m_toolManager->GetTool<DRC_TOOL>() )
242 {
243 if( drcTool->GetDRCEngine() )
244 {
245 try
246 {
247 drcTool->GetDRCEngine()->InitEngine( board->GetDesignRulesPath() );
248 }
249 catch( PARSE_ERROR& )
250 {
251 }
252 }
253 }
254
255 std::vector<FOOTPRINT*> newFootprints = aUpdater.GetAddedFootprints();
256 SpreadFootprints( &newFootprints, { 0, 0 }, true );
257
258 board->CompileRatsnest();
259
261}
262
263
265{
266 wxCHECK( m_board && m_project, false );
267
268 wxString fileName = m_board->GetFileName();
269
270 if( fileName.IsEmpty() || !wxFileExists( fileName ) )
271 return false;
272
274
275 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
276 return false;
277
278 std::unique_ptr<BOARD> reloaded;
279
280 try
281 {
282 reloaded = BOARD_LOADER::Load( fileName, pluginType, m_project );
283 }
284 catch( ... )
285 {
286 return false;
287 }
288
289 if( !reloaded )
290 return false;
291
292 m_board = std::move( reloaded );
293 m_board->SetProject( m_project );
294 m_toolManager->SetEnvironment( m_board.get(), nullptr, nullptr, GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" ),
295 nullptr );
296 m_contentModified = false;
297
298 return true;
299}
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
static bool SaveBoard(wxString &aFileName, BOARD &aBoard, PCB_IO_MGR::PCB_FILE_T aFormat)
static std::unique_ptr< BOARD > Load(const wxString &aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, PROJECT *aProject, const OPTIONS &aOptions)
Update the BOARD with a new netlist.
std::vector< FOOTPRINT * > GetAddedFootprints() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
void CompileRatsnest()
Rebuild the entire board ratsnest.
Definition board.cpp:4060
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:3423
wxString GetDesignRulesPath() const
Return the absolute path to the design rules file for this board.
Definition board.cpp:438
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition board.h:1677
void InvalidateComponentClasses()
Invalidates any caches component classes and recomputes caches if required.
void RebuildRequiredCaches(FOOTPRINT *aFootprint=nullptr) const
Rebuilds any caches that may be required by custom assignment rules.
BOARD * GetBoard() const override
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject, bool aHeadless) override
void OnNetlistChanged(BOARD_NETLIST_UPDATER &aUpdater) override
Post-import board sync (nets, classes, DRC, ratsnest, new footprint placement).
PROJECT & Prj() const override
bool SaveBoardAs(const wxString &aFileName) override
Save the board to a new path and change the active board/project.
TOOL_MANAGER * GetToolManager() const override
std::unique_ptr< TOOL_MANAGER > m_toolManager
void SetContentModified(bool aModified=true) override
HEADLESS_PCB_CONTEXT(std::unique_ptr< BOARD > aBoard, PROJECT *aProject, APP_SETTINGS_BASE *aSettings, KIWAY *aKiway=nullptr)
std::unique_ptr< BOARD > m_board
std::unique_ptr< BOARD_NETLIST_UPDATER > MakeNetlistUpdater() override
Create a netlist updater bound to this context's board.
bool ReadNetlistFromFile(const wxString &aFilename, NETLIST &aNetlist, REPORTER &aReporter) override
Read a netlist file and preload component footprints.
wxString GetCurrentFileName() const override
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:348
static NETLIST_READER * GetNetlistReader(NETLIST *aNetlist, const wxString &aNetlistFileName, const wxString &aCompFootprintFileName=wxEmptyString)
Attempt to determine the net list file type of aNetlistFileName and return the appropriate NETLIST_RE...
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:52
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
Container for project specific data.
Definition project.h:63
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Set the currently loaded project path and saves it (pointers remain valid).
bool SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Save a copy of the current project under the given path.
Master controller class:
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition common.cpp:848
#define _(s)
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:348
static const std::string ProjectFileExtension
static const std::string DesignRulesFileExtension
static const std::string KiCadPcbFileExtension
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
STL namespace.
void LoadNetlistFootprints(BOARD *aBoard, NETLIST &aNetlist, REPORTER &aReporter)
Load the footprints for each SCH_SYMBOL in aNetlist from the list of libraries.
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
@ RPT_SEVERITY_ERROR
T * GetAppSettings(const char *aFilename)
void SpreadFootprints(std::vector< FOOTPRINT * > *aFootprints, const VECTOR2I &aTargetBoxPosition, bool aGroupBySheet, int aComponentGap, int aGroupGap)
Footprints (after loaded by reading a netlist for instance) are moved to be in a small free area (out...
A filename or source description, a problem input line, a line number, a byte offset,...