KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_io_sprint_layout.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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
26
27#include <board.h>
28#include <footprint.h>
29#include <zone.h>
30#include <font/fontconfig.h>
31#include <reporter.h>
32
33#include <ranges>
34#include <wx/filename.h>
35#include <wx/wfstream.h>
36#include <wx/dir.h>
37
38
40 PCB_IO( wxS( "Sprint Layout" ) )
41{
42}
43
44
45void PCB_IO_SPRINT_LAYOUT::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
46 bool aBestEfforts, const std::map<std::string, UTF8>* aProperties )
47{
48 wxFileName libFn( aLibraryPath );
49
50 if( libFn.FileExists() && libFn.GetExt().Upper() == wxS( "LMK" ) )
51 {
52 aFootprintNames.Add( libFn.GetName() );
53 return;
54 }
55
56 if( wxDir::Exists( aLibraryPath ) )
57 {
58 wxArrayString files;
59 wxDir::GetAllFiles( aLibraryPath, &files, wxEmptyString, wxDIR_FILES | wxDIR_DIRS );
60
61 for( const wxString& filePath : files )
62 {
63 wxFileName file( filePath );
64
65 if( file.GetExt().Upper() != wxS( "LMK" ) )
66 continue;
67
68 file.MakeRelativeTo( aLibraryPath );
69 aFootprintNames.Add( file.GetFullPath().BeforeLast( '.' ) );
70 }
71 }
72}
73
74
75FOOTPRINT* PCB_IO_SPRINT_LAYOUT::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
76 bool aKeepUUID, const std::map<std::string, UTF8>* aProperties )
77{
78 wxFileName libFn( aLibraryPath );
79 wxFileName lmkPath;
80
81 if( libFn.FileExists() && libFn.GetExt().Upper() == wxS( "LMK" ) )
82 {
83 lmkPath = libFn;
84 }
85 else
86 {
87 if( !wxDir::Exists( aLibraryPath ) )
88 return nullptr;
89
90 lmkPath = wxFileName( aLibraryPath + wxFileName::GetPathSeparator() + aFootprintName + wxS( ".LMK" ) );
91
92 if( !lmkPath.FileExists() )
93 {
94 lmkPath.SetExt( "lmk" );
95
96 if( !lmkPath.FileExists() )
97 return nullptr;
98 }
99 }
100
102
103 if( !parser.ParseMacroFile( lmkPath.GetFullPath() ) )
104 return nullptr;
105
106 return parser.CreateFootprint();
107}
108
109
111{
112 for( std::unique_ptr<FOOTPRINT>& fp : m_loadedFootprints | std::views::values )
113 fp->SetParent( nullptr );
114}
115
116
117bool PCB_IO_SPRINT_LAYOUT::CanReadBoard( const wxString& aFileName ) const
118{
119 const wxFileName fn( aFileName );
120
121 if( !fn.FileExists() )
122 return false;
123
124 wxString ext = fn.GetExt().Lower();
125
126 if( ext != wxS( "lay6" ) && ext != wxS( "lay" ) )
127 return false;
128
129 // Check magic bytes: version (<=6), 0x33, 0xAA, 0xFF
130 wxFFileInputStream stream( aFileName );
131
132 if( !stream.IsOk() || stream.GetLength() < 8 )
133 return false;
134
135 uint8_t header[4];
136 stream.Read( header, 4 );
137
138 if( stream.LastRead() != 4 )
139 return false;
140
141 if( header[0] > 6 || header[1] != 0x33 || header[2] != 0xAA || header[3] != 0xFF )
142 return false;
143
144 return true;
145}
146
147
148BOARD* PCB_IO_SPRINT_LAYOUT::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
149 const std::map<std::string, UTF8>* aProperties,
150 PROJECT* aProject )
151{
153
154 m_props = aProperties;
155 m_loadedFootprints.clear();
156
158
159 if( !parser.ParseBoard( aFileName ) )
160 {
161 THROW_IO_ERROR( wxString::Format( _( "Failed to parse Sprint Layout file '%s'" ),
162 aFileName ) );
163 }
164
165 const auto& fileData = parser.GetFileData();
166 size_t boardIndex = 0;
167
168 if( m_props && m_props->contains( "pcb_id" ) )
169 {
170 unsigned long idx = std::stoul( m_props->at( "pcb_id" ) );
171 boardIndex = static_cast<size_t>( idx );
172 }
173 else if( fileData.boards.size() > 1 && m_choose_project_handler )
174 {
175 std::vector<IMPORT_PROJECT_DESC> options;
176
177 for( size_t i = 0; i < fileData.boards.size(); i++ )
178 {
180 wxString name = wxString::FromUTF8( fileData.boards[i].name );
181
182 if( name.empty() )
183 name = wxString::Format( wxS( "Board %zu" ), i + 1 );
184
185 desc.PCBName = name;
186 desc.PCBId = wxString::Format( wxS( "%zu" ), i );
187 options.push_back( desc );
188 }
189
190 std::vector<IMPORT_PROJECT_DESC> chosen = m_choose_project_handler( options );
191
192 if( chosen.empty() )
193 return nullptr;
194
195 unsigned long idx = std::stoul( chosen[0].PCBId.ToStdString() );
196 boardIndex = static_cast<size_t>( idx );
197 }
198
199 std::unique_ptr<BOARD> newBoard( parser.CreateBoard( m_loadedFootprints, boardIndex ) );
200
201 if( !newBoard )
202 {
203 THROW_IO_ERROR( wxString::Format( _( "Failed to create board from Sprint Layout file '%s'" ),
204 aFileName ) );
205 }
206
207 if( aAppendToMe )
208 {
209 for( FOOTPRINT* fp : newBoard->Footprints() )
210 aAppendToMe->Add( static_cast<FOOTPRINT*>( fp->Clone() ) );
211
212 for( BOARD_ITEM* item : newBoard->Drawings() )
213 aAppendToMe->Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
214
215 for( ZONE* zone : newBoard->Zones() )
216 aAppendToMe->Add( static_cast<ZONE*>( zone->Clone() ) );
217
218 return aAppendToMe;
219 }
220
221 newBoard->SetFileName( aFileName );
222 return newBoard.release();
223}
224
225
227{
228 std::vector<FOOTPRINT*> result;
229
230 for( auto& [name, footprint] : m_loadedFootprints )
231 result.push_back( static_cast<FOOTPRINT*>( footprint->Clone() ) );
232
233 return result;
234}
const char * name
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1247
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
RAII class to set and restore the fontconfig reporter.
Definition reporter.h:336
static LOAD_INFO_REPORTER & GetInstance()
Definition reporter.cpp:249
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
std::map< wxString, std::unique_ptr< FOOTPRINT > > m_loadedFootprints
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
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 ...
PCB_IO(const wxString &aName)
Definition pcb_io.h:346
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
Definition pcb_io.h:356
CHOOSE_PROJECT_HANDLER m_choose_project_handler
Callback to choose projects to import.
Container for project specific data.
Definition project.h:66
const SPRINT_LAYOUT::FILE_DATA & GetFileData() const
BOARD * CreateBoard(std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, size_t aBoardIndex=0)
bool ParseMacroFile(const wxString &aFileName)
bool ParseBoard(const wxString &aFileName)
Handle a list of polygons defining a copper zone.
Definition zone.h:74
#define _(s)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
Describes how non-KiCad boards and schematics should be imported as KiCad projects.
std::vector< std::string > header
wxString result
Test unit parsing edge cases and error handling.