KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_footprint_import_reconciler.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 2
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 <memory>
21#include <set>
22#include <vector>
23
26
27#include <wx/dir.h>
28#include <wx/filefn.h>
29#include <wx/filename.h>
30#include <wx/stdpaths.h>
31
32#include <board.h>
33#include <footprint.h>
34#include <lib_id.h>
35#include <pgm_base.h>
36#include <project.h>
37#include <project_pcb.h>
38#include <reporter.h>
49#include <tool/tool_manager.h>
50
52
53
54namespace
55{
57wxString stageProject( const wxString& aStem )
58{
59 wxString sep = wxFileName::GetPathSeparator();
60 wxString dir = wxStandardPaths::Get().GetTempDir() + sep + aStem + wxT( "-fpreconcile-qa" );
61
62 if( wxDirExists( dir ) )
63 wxFileName::Rmdir( dir, wxPATH_RMDIR_RECURSIVE );
64
65 wxFileName::Mkdir( dir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
66
67 wxString projectPath = dir + sep + aStem + wxT( ".kicad_pro" );
68
69 Pgm().GetSettingsManager().LoadProject( projectPath );
71 Pgm().GetSettingsManager().Prj().GetProjectDirectory() );
72
74}
75
76
78struct IMPORTED_BOARD
79{
80 std::unique_ptr<PCB_IO_EASYEDAPRO_V3> m_plugin;
81 std::unique_ptr<BOARD> m_board;
82 std::vector<std::unique_ptr<FOOTPRINT>> m_definitions;
83 std::unique_ptr<KI_TEST::TEMPORARY_DIRECTORY> m_sourceDir;
84};
85
86
87IMPORTED_BOARD importSampleBoard( PROJECT& aProject, const std::string& aTag )
88{
89 IMPORTED_BOARD sample;
90
91 const wxString archiveName = wxS( "ProProject_LS2K0300Core_2025-11-14.epro2" );
92
93 wxFileName srcFn( wxString::FromUTF8( KI_TEST::GetPcbnewTestDataDir() ) );
94 srcFn.AppendDir( wxS( "plugins" ) );
95 srcFn.AppendDir( wxS( "easyedapro" ) );
96 srcFn.SetFullName( archiveName );
97 BOOST_REQUIRE_MESSAGE( srcFn.FileExists(), "Missing EasyEDA Pro v3 board fixture" );
98
99 sample.m_sourceDir = std::make_unique<KI_TEST::TEMPORARY_DIRECTORY>( aTag, "" );
100
101 wxFileName importFn( wxString::FromUTF8( sample.m_sourceDir->GetPath().string() ),
102 archiveName );
103 BOOST_REQUIRE( wxCopyFile( srcFn.GetFullPath(), importFn.GetFullPath() ) );
104
105 std::map<std::string, UTF8> properties;
106 properties["pcb_id"] = "eb9fbfba682940f7a002816e66fbb3d7";
107
108 sample.m_plugin = std::make_unique<PCB_IO_EASYEDAPRO_V3>();
109 sample.m_board = std::make_unique<BOARD>();
110 sample.m_board->SetProject( &aProject );
111 sample.m_plugin->LoadBoard( importFn.GetFullPath(), sample.m_board.get(), &properties,
112 &aProject );
113
114 BOOST_REQUIRE_GT( sample.m_board->Footprints().size(), 0 );
115
116 for( FOOTPRINT* fp : sample.m_plugin->GetImportedCachedLibraryFootprints() )
117 sample.m_definitions.emplace_back( fp );
118
119 BOOST_REQUIRE_GT( sample.m_definitions.size(), 0 );
120
121 return sample;
122}
123
124
126void publishLibrary( PROJECT& aProject, FOOTPRINT_LIBRARY_ADAPTER& aAdapter,
127 const wxString& aNickname, const wxString& aDirStem,
128 const FOOTPRINT& aFootprint )
129{
130 wxFileName libDir( aProject.GetProjectPath(), aDirStem,
132 wxString libPath = libDir.GetFullPath();
133
135 BOOST_REQUIRE( pi );
136
137 pi->CreateLibrary( libPath );
138
139 std::unique_ptr<FOOTPRINT> copy( static_cast<FOOTPRINT*>( aFootprint.Clone() ) );
140 copy->SetFPID( LIB_ID( aNickname, aFootprint.GetFPID().GetUniStringLibItemName() ) );
141 copy->SetReference( wxS( "REF**" ) );
142 pi->FootprintSave( libPath, copy.get() );
143
144 LIBRARY_TABLE* table = aAdapter.ProjectTable().value_or( nullptr );
146
147 LIBRARY_TABLE_ROW& row = table->InsertRow();
148 row.SetNickname( aNickname );
149 row.SetURI( wxS( "${KIPRJMOD}/" ) + libDir.GetFullName() );
150 row.SetType( wxS( "KiCad" ) );
152
153 BOOST_REQUIRE( table->Save().has_value() );
154 aAdapter.LoadOne( aNickname );
155}
156
157
159struct COLLISION_CANDIDATE
160{
161 FOOTPRINT* m_footprint = nullptr;
162 wxString m_nickname;
163 wxString m_name;
164};
165
166
167COLLISION_CANDIDATE findCandidate( IMPORTED_BOARD& aSample )
168{
169 COLLISION_CANDIDATE candidate;
170
171 for( FOOTPRINT* fp : aSample.m_board->Footprints() )
172 {
173 wxString nick = fp->GetFPID().GetUniStringLibNickname();
174 wxString name = fp->GetFPID().GetUniStringLibItemName();
175
176 if( nick.IsEmpty() || name.IsEmpty() )
177 continue;
178
179 for( const std::unique_ptr<FOOTPRINT>& def : aSample.m_definitions )
180 {
181 if( def->GetFPID().GetUniStringLibItemName() != name || def->Pads().empty() )
182 continue;
183
184 candidate.m_footprint = fp;
185 candidate.m_nickname = nick;
186 candidate.m_name = name;
187
188 return candidate;
189 }
190 }
191
192 return candidate;
193}
194} // namespace
195
196
197BOOST_AUTO_TEST_SUITE( FootprintImportReconciler )
198
199
200// Eagle board reconciles to a generated cache: .pretty published, row added, every FPID resolves
201// fails on revert, since Eagle FPIDs keep empty nicknames
202BOOST_AUTO_TEST_CASE( EagleBoardResolvesToGeneratedCache )
203{
204 wxString projectPath = stageProject( wxS( "eagle_fpreconcile" ) );
206
207 wxFileName brdFn( KI_TEST::GetEeschemaTestDataDir() );
208 brdFn.AppendDir( wxS( "io" ) );
209 brdFn.AppendDir( wxS( "eagle" ) );
210 brdFn.SetFullName( wxS( "eagle-import-testfile.brd" ) );
211 BOOST_REQUIRE_MESSAGE( brdFn.FileExists(), "Missing Eagle board fixture" );
212
213 PCB_IO_EAGLE plugin;
214 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
215 board->SetProject( &project );
216 plugin.LoadBoard( brdFn.GetFullPath(), board.get(), nullptr, &project );
217
218 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
219
220 std::vector<FOOTPRINT*> raw = plugin.GetImportedCachedLibraryFootprints();
221 std::vector<std::unique_ptr<FOOTPRINT>> defs;
222
223 for( FOOTPRINT* fp : raw )
224 defs.emplace_back( fp );
225
227 BOOST_REQUIRE( adapter );
228
229 const wxString cacheNick = wxS( "eagle_test-import-fps" );
230 FOOTPRINT_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
231
233 reconciler.Reconcile( board.get(), std::move( defs ), cacheNick, {} );
234
235 // cache library published
236 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
237 BOOST_CHECK_GT( result.m_savedToCache, 0 );
238
239 wxFileName prettyDir( project.GetProjectPath(), cacheNick,
241 BOOST_CHECK_MESSAGE( wxDir::Exists( prettyDir.GetFullPath() ),
242 "Generated .pretty was not published" );
243
244 // project fp-lib table gained the row
245 LIBRARY_TABLE* projectTable = adapter->ProjectTable().value_or( nullptr );
246 BOOST_REQUIRE( projectTable );
247 BOOST_CHECK( projectTable->HasRow( cacheNick ) );
248
249 // every board FPID resolves via the adapter
250 int resolved = 0;
251
252 for( FOOTPRINT* fp : board->Footprints() )
253 {
254 wxString name = fp->GetFPID().GetUniStringLibItemName();
255
256 if( name.IsEmpty() )
257 continue;
258
259 wxString nick = fp->GetFPID().GetUniStringLibNickname();
260
261 BOOST_CHECK_MESSAGE( !nick.IsEmpty(),
262 wxString::Format( "Board footprint '%s' left with empty nickname",
263 name ) );
264 BOOST_CHECK_MESSAGE( adapter->FootprintExists( nick, name ),
265 wxString::Format( "FPID '%s:%s' does not resolve after reconciliation",
266 nick, name ) );
267 resolved++;
268 }
269
270 BOOST_CHECK_GT( resolved, 0 );
271 BOOST_CHECK_EQUAL( result.m_unresolved, 0 );
272}
273
274
275// Altium footprints carry a source-.PcbLib nick not registered here, so all fall back to the cache
276// and resolve through the adapter
277BOOST_AUTO_TEST_CASE( AltiumBoardResolvesToGeneratedCache )
278{
279 stageProject( wxS( "altium_fpreconcile" ) );
281
282 std::string dataPath =
283 KI_TEST::GetPcbnewTestDataDir() + "plugins/altium/HiFive/HiFive1.B01.PcbDoc";
284
286 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
287 board->SetProject( &project );
288 plugin.LoadBoard( dataPath, board.get(), nullptr, &project );
289
290 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
291
292 std::vector<FOOTPRINT*> raw = plugin.GetImportedCachedLibraryFootprints();
293 std::vector<std::unique_ptr<FOOTPRINT>> defs;
294
295 for( FOOTPRINT* fp : raw )
296 defs.emplace_back( fp );
297
299 BOOST_REQUIRE( adapter );
300
301 const wxString cacheNick = wxS( "hifive-import-fps" );
302 FOOTPRINT_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
303
305 reconciler.Reconcile( board.get(), std::move( defs ), cacheNick, {} );
306
307 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
308 BOOST_CHECK_EQUAL( result.m_unresolved, 0 );
309
310 int resolved = 0;
311
312 for( FOOTPRINT* fp : board->Footprints() )
313 {
314 wxString name = fp->GetFPID().GetUniStringLibItemName();
315
316 if( name.IsEmpty() )
317 continue;
318
319 wxString nick = fp->GetFPID().GetUniStringLibNickname();
320
321 BOOST_CHECK_MESSAGE( adapter->FootprintExists( nick, name ),
322 wxString::Format( "FPID '%s:%s' does not resolve after reconciliation",
323 nick, name ) );
324 resolved++;
325 }
326
327 BOOST_CHECK_GT( resolved, 0 );
328}
329
330
331// EasyEDA Pro v3 hands definitions over the standard hook, leaving the source directory untouched
332// fails on revert, since LoadBoard then publishes its own .pretty beside the archive
333BOOST_AUTO_TEST_CASE( EasyEdaProV3BoardResolvesToGeneratedCache )
334{
335 stageProject( wxS( "easyedapro_v3_fpreconcile" ) );
337
338 IMPORTED_BOARD sample = importSampleBoard( project, "easyedapro_v3_fpreconcile_src" );
339 BOARD* board = sample.m_board.get();
340
341 // the importer must not have published anything of its own beside the archive
342 wxFileName srcDir( wxString::FromUTF8( sample.m_sourceDir->GetPath().string() ),
343 wxEmptyString );
344 wxFileName strayLib( srcDir.GetPath(),
345 EASYEDAPRO::ShortenLibName( wxS( "ProProject_LS2K0300Core_2025-11-14" ) ),
347 BOOST_CHECK_MESSAGE( !wxDir::Exists( strayLib.GetFullPath() ),
348 "LoadBoard wrote a library into the source directory" );
349
351 BOOST_REQUIRE( adapter );
352
353 const wxString cacheNick = wxS( "ls2k0300-import-fps" );
354 FOOTPRINT_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
355
357 reconciler.Reconcile( board, std::move( sample.m_definitions ), cacheNick, {} );
358
359 // the cache lands in the project directory, not next to the source archive
360 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
361 BOOST_CHECK_GT( result.m_savedToCache, 0 );
362
363 wxFileName prettyDir( project.GetProjectPath(), cacheNick,
365 BOOST_CHECK_MESSAGE( wxDir::Exists( prettyDir.GetFullPath() ),
366 "Generated .pretty was not published into the project" );
367
368 LIBRARY_TABLE* projectTable = adapter->ProjectTable().value_or( nullptr );
369 BOOST_REQUIRE( projectTable );
370 BOOST_CHECK( projectTable->HasRow( cacheNick ) );
371
372 int resolved = 0;
373
374 for( FOOTPRINT* fp : board->Footprints() )
375 {
376 wxString name = fp->GetFPID().GetUniStringLibItemName();
377
378 if( name.IsEmpty() )
379 continue;
380
381 wxString nick = fp->GetFPID().GetUniStringLibNickname();
382
383 BOOST_CHECK_MESSAGE( adapter->FootprintExists( nick, name ),
384 wxString::Format( "FPID '%s:%s' does not resolve after reconciliation",
385 nick, name ) );
386 resolved++;
387 }
388
389 BOOST_CHECK_GT( resolved, 0 );
390 BOOST_CHECK_EQUAL( result.m_unresolved, 0 );
391}
392
393
394// An unrelated library that happens to carry the nickname the importer emitted must not swallow
395// the imported definition; without the provenance check the footprint relinks to the wrong part
396BOOST_AUTO_TEST_CASE( CollidingNicknameDoesNotStealTheLink )
397{
398 stageProject( wxS( "fpreconcile_collide" ) );
400
401 IMPORTED_BOARD sample = importSampleBoard( project, "fpreconcile_collide_src" );
402 COLLISION_CANDIDATE candidate = findCandidate( sample );
403 BOOST_REQUIRE( candidate.m_footprint );
404
406 BOOST_REQUIRE( adapter );
407
408 // a padless namesake registered under the importer's nickname: same name, different part
409 FOOTPRINT impostor( nullptr );
410 impostor.SetFPID( LIB_ID( candidate.m_nickname, candidate.m_name ) );
411 BOOST_REQUIRE( impostor.Pads().empty() );
412 publishLibrary( project, *adapter, candidate.m_nickname, wxS( "impostor" ), impostor );
413
414 const wxString cacheNick = wxS( "collide-import-fps" );
415 FOOTPRINT_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
416
418 sample.m_board.get(), std::move( sample.m_definitions ), cacheNick, {} );
419
420 BOOST_CHECK_EQUAL( result.m_cacheNickname, cacheNick );
421
422 // the imported definition is kept in the cache rather than dropped for the namesake
423 BOOST_CHECK_EQUAL( candidate.m_footprint->GetFPID().GetUniStringLibNickname(), cacheNick );
424
425 std::unique_ptr<FOOTPRINT> linked( adapter->LoadFootprint( cacheNick, candidate.m_name,
426 true ) );
427 BOOST_REQUIRE( linked );
428 BOOST_CHECK_GT( linked->Pads().size(), 0 );
429}
430
431
432// A project row already owning the cache nickname is a user library even when no .pretty sits at
433// the generated path, so publishing must not rewrite its URI
434BOOST_AUTO_TEST_CASE( ExistingUserRowIsNotRepurposed )
435{
436 stageProject( wxS( "fpreconcile_row" ) );
438
439 IMPORTED_BOARD sample = importSampleBoard( project, "fpreconcile_row_src" );
440
442 BOOST_REQUIRE( adapter );
443
444 const wxString cacheNick = wxS( "row-import-fps" );
445
446 // the user's row owns the nickname but points at a library of its own
447 FOOTPRINT owned( nullptr );
448 owned.SetFPID( LIB_ID( cacheNick, wxS( "UserPart" ) ) );
449 publishLibrary( project, *adapter, cacheNick, wxS( "user-owned" ), owned );
450
451 LIBRARY_TABLE* table = adapter->ProjectTable().value_or( nullptr );
453
454 LIBRARY_TABLE_ROW* row = table->Row( cacheNick ).value_or( nullptr );
455 BOOST_REQUIRE( row );
456
457 const wxString uriBefore = row->URI();
458
459 FOOTPRINT_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
460
462 sample.m_board.get(), std::move( sample.m_definitions ), cacheNick, {} );
463
464 BOOST_CHECK( result.m_cacheNickname.IsEmpty() );
465 BOOST_CHECK_EQUAL( row->URI(), uriBefore );
466
467 wxFileName prettyDir( project.GetProjectPath(), cacheNick,
469 BOOST_CHECK_MESSAGE( !wxDir::Exists( prettyDir.GetFullPath() ),
470 "Published a cache over a nickname the user already owns" );
471}
472
473
474// regression gate for a netlist of reconciled FPIDs applying via BOARD_NETLIST_UPDATER with 0 errors
475// and no not-found, over the same adapter path Update PCB from Schematic uses
476BOOST_AUTO_TEST_CASE( ReconciledFootprintsResolveViaNetlistUpdater )
477{
478 stageProject( wxS( "eagle_netlist_roundtrip" ) );
480
481 wxFileName brdFn( KI_TEST::GetEeschemaTestDataDir() );
482 brdFn.AppendDir( wxS( "io" ) );
483 brdFn.AppendDir( wxS( "eagle" ) );
484 brdFn.SetFullName( wxS( "eagle-import-testfile.brd" ) );
485 BOOST_REQUIRE( brdFn.FileExists() );
486
487 PCB_IO_EAGLE plugin;
488 std::unique_ptr<BOARD> imported = std::make_unique<BOARD>();
489 imported->SetProject( &project );
490 plugin.LoadBoard( brdFn.GetFullPath(), imported.get(), nullptr, &project );
491
492 std::vector<FOOTPRINT*> raw = plugin.GetImportedCachedLibraryFootprints();
493 std::vector<std::unique_ptr<FOOTPRINT>> defs;
494
495 for( FOOTPRINT* fp : raw )
496 defs.emplace_back( fp );
497
499 BOOST_REQUIRE( adapter );
500
501 const wxString cacheNick = wxS( "eagle_test-import-fps" );
502 FOOTPRINT_IMPORT_RECONCILER reconciler( *adapter, project.GetProjectPath() );
503 reconciler.Reconcile( imported.get(), std::move( defs ), cacheNick, {} );
504
505 // netlist of distinct reconciled FPIDs, one fresh component each
507 std::set<wxString> seen;
508 int expectedComponents = 0;
509
510 for( FOOTPRINT* fp : imported->Footprints() )
511 {
512 LIB_ID fpid = fp->GetFPID();
513
514 if( fpid.GetUniStringLibItemName().IsEmpty() || !seen.insert( fpid.GetUniStringLibId() ).second )
515 continue;
516
517 wxString ref = wxString::Format( wxS( "U%d" ), ++expectedComponents );
518 netlist.AddComponent(
519 new COMPONENT( fpid, ref, ref, KIID_PATH(), std::vector<KIID>{ KIID() } ) );
520 }
521
522 BOOST_REQUIRE_GT( expectedComponents, 0 );
523
524 // updater must load each footprint from the reconciled lib onto a fresh board
525 std::unique_ptr<BOARD> target = std::make_unique<BOARD>();
526 target->SetProject( &project );
527
528 TOOL_MANAGER toolMgr;
529 toolMgr.SetEnvironment( target.get(), nullptr, nullptr, nullptr, nullptr );
530 toolMgr.RegisterTool( new KI_TEST::DUMMY_TOOL() );
531
533 BOARD_NETLIST_UPDATER updater( &toolMgr, target.get() );
534 updater.SetReporter( &reporter );
535 updater.SetReplaceFootprints( false );
536 updater.SetDeleteUnusedFootprints( false );
537
538 BOOST_REQUIRE( updater.UpdateNetlist( netlist ) );
539
540 BOOST_CHECK_EQUAL( updater.GetErrorCount(), 0 );
541 BOOST_CHECK_MESSAGE( !reporter.GetMessages().Lower().Contains( wxS( "not found" ) ),
542 "Netlist updater reported a footprint not found after reconciliation" );
543 BOOST_CHECK_EQUAL( static_cast<int>( target->Footprints().size() ), expectedComponents );
544}
545
546
const char * name
Update the BOARD with a new netlist.
void SetReporter(REPORTER *aReporter)
Enable dry run mode (just report, no changes to PCB).
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
void SetDeleteUnusedFootprints(bool aEnabled)
void SetReplaceFootprints(bool aEnabled)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:373
const FOOTPRINTS & Footprints() const
Definition board.h:421
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:212
Frame-independent, non-interactive service that reconciles the footprint-library references of a fres...
FOOTPRINT_IMPORT_RECONCILE_RESULT Reconcile(BOARD *aBoard, std::vector< std::unique_ptr< FOOTPRINT > > aDefinitions, const wxString &aCacheNickname, const std::vector< wxString > &aSourceLibNicknames)
Reconcile aBoard against the importer definitions and the provenance source libraries.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
FOOTPRINT * LoadFootprint(const wxString &aNickname, const wxString &aName, bool aKeepUUID)
Load a FOOTPRINT having aName from the library given by aNickname.
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
bool FootprintExists(const wxString &aNickname, const wxString &aName)
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:445
EDA_ITEM * Clone() const override
Invoke a function on all children.
std::deque< PAD * > & Pads()
Definition footprint.h:375
const LIB_ID & GetFPID() const
Definition footprint.h:444
Definition kiid.h:46
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
void LoadProjectTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the project library tables in the given list, or all tables if no list is given
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetURI(const wxString &aUri)
void SetScope(LIBRARY_TABLE_SCOPE aScope)
const wxString & URI() const
bool HasRow(const wxString &aNickname) const
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
wxString GetUniStringLibId() const
Definition lib_id.h:144
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
Definition lib_id.h:108
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
Works with Eagle 6.x XML board files and footprints to implement the Pcbnew #PLUGIN API or a portion ...
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:54
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:124
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:126
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Container for project specific data.
Definition project.h:63
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:183
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
Master controller class:
void RegisterTool(TOOL_BASE *aTool)
Add a tool to the manager set and sets it up.
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
A wrapper for reporting to a wxString object.
Definition reporter.h:225
static const std::string KiCadFootprintLibPathExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
PROJECT & Prj()
Definition kicad.cpp:728
wxString ShortenLibName(wxString aProjectName)
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Outcome of a post-import footprint-library reconciliation pass.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(EagleBoardResolvesToGeneratedCache)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
std::string netlist
IbisParser parser & reporter
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")