KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_gen_footprint_position.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
24/*
25 * 1 - create ASCII files for automatic placement of smd components
26 * 2 - create a footprint report (pos and footprint descr) (ascii file)
27 */
28
30#include <confirm.h>
31#include <pcb_edit_frame.h>
32#include <pcbnew_settings.h>
34#include <bitmaps.h>
35#include <reporter.h>
38#include <kiface_base.h>
44
45#include <wx/dirdlg.h>
46#include <wx/msgdlg.h>
47
48
51 m_editFrame( aEditFrame ),
52 m_job( nullptr )
53{
54 m_messagesPanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
56 initDialog();
57
58 SetupStandardButtons( { { wxID_OK, _( "Generate Position File" ) },
59 { wxID_CANCEL, _( "Close" ) } } );
60
61 GetSizer()->SetSizeHints( this );
62 Centre();
63}
64
65
66
68 PCB_EDIT_FRAME* aEditFrame,
69 wxWindow* aParent ) :
71 m_editFrame( aEditFrame ),
72 m_job( aJob )
73{
74 m_messagesPanel->Hide();
75 initDialog();
76
78
79 GetSizer()->SetSizeHints( this );
80 Centre();
81}
82
83
85{
86 if( !m_job )
87 {
88 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
89
90 PROJECT_FILE& projectFile = m_editFrame->Prj().GetProjectFile();
91
93 {
94 m_units = cfg->m_PlaceFile.units == 0 ? EDA_UNITS::INCH : EDA_UNITS::MM;
95
96 // Output directory
98
99 // Update Options
100 m_unitsCtrl->SetSelection( cfg->m_PlaceFile.units );
101 m_singleFile->SetValue( cfg->m_PlaceFile.file_options == 1 );
102 m_formatCtrl->SetSelection( cfg->m_PlaceFile.file_format );
103 m_cbIncludeBoardEdge->SetValue( cfg->m_PlaceFile.include_board_edge );
104 m_useDrillPlaceOrigin->SetValue( cfg->m_PlaceFile.use_aux_origin );
105 m_onlySMD->SetValue( cfg->m_PlaceFile.only_SMD );
106 m_negateXcb->SetValue( cfg->m_PlaceFile.negate_xcoord );
107 m_excludeTH->SetValue( cfg->m_PlaceFile.exclude_TH );
108 }
109
110 // Update sizes and sizers:
111 m_messagesPanel->MsgPanelSetMinSize( wxSize( -1, 160 ) );
112 }
113 else
114 {
115 SetTitle( m_job->GetSettingsDialogTitle() );
116
117 m_browseButton->Hide();
118 m_units = m_job->m_units == JOB_EXPORT_PCB_POS::UNITS::INCH ? EDA_UNITS::INCH : EDA_UNITS::MM;
119 m_staticTextDir->SetLabel( _( "Output file:" ) );
121
122 m_unitsCtrl->SetSelection( static_cast<int>( m_job->m_units ) );
123 m_singleFile->SetValue( m_job->m_singleFile );
124 m_formatCtrl->SetSelection( static_cast<int>( m_job->m_format ) );
127 m_onlySMD->SetValue( m_job->m_smdOnly );
128 m_negateXcb->SetValue( m_job->m_negateBottomX );
130 m_excludeDNP->SetValue( m_job->m_excludeDNP );
131
132 m_messagesPanel->Hide();
133 }
134
135 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
136 // non-job versions (which have different sizes).
137 m_hash_key = TO_UTF8( GetTitle() );
138
139 GetSizer()->SetSizeHints( this );
140}
141
142
144{
145 m_unitsLabel->Enable( m_formatCtrl->GetSelection() != 2 );
146 m_unitsCtrl->Enable( m_formatCtrl->GetSelection() != 2 );
147}
148
149
151{
152 m_singleFile->Enable( m_formatCtrl->GetSelection() != 2 );
153}
154
155
157{
158 if( m_formatCtrl->GetSelection() == 2 )
159 {
160 m_onlySMD->SetValue( false );
161 m_onlySMD->Enable( false );
162 }
163 else
164 {
165 m_onlySMD->Enable( true );
166 }
167}
168
169
171{
172 if( m_formatCtrl->GetSelection() == 2 )
173 {
174 m_negateXcb->SetValue( false );
175 m_negateXcb->Enable( false );
176 }
177 else
178 {
179 m_negateXcb->Enable( true );
180 }
181}
182
184{
185 if( m_formatCtrl->GetSelection() == 2 )
186 {
187 m_excludeTH->SetValue( false );
188 m_excludeTH->Enable( false );
189 }
190 else
191 {
192 m_excludeTH->Enable( true );
193 }
194}
195
196
198{
199 return m_unitsCtrl->GetSelection() == 1;
200}
201
202
204{
205 return m_singleFile->GetValue();
206}
207
208
210{
211 return m_onlySMD->GetValue();
212}
213
214
216{
217 return m_excludeTH->GetValue();
218}
219
220
222{
223 return m_excludeDNP->GetValue();
224}
225
226
228{
229 m_cbIncludeBoardEdge->Enable( m_formatCtrl->GetSelection() == 2 );
230}
231
232
234{
235 // Build the absolute path of current output directory to preselect it in the file browser.
236 wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
237 path = Prj().AbsolutePath( path );
238
239 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
240
241 if( dirDialog.ShowModal() == wxID_CANCEL )
242 return;
243
244 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
245
246 wxMessageDialog dialog( this, _( "Use a relative path?"), _( "Plot Output Directory" ),
247 wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
248
249 if( dialog.ShowModal() == wxID_YES )
250 {
251 wxString boardFilePath = ( (wxFileName) m_editFrame->GetBoard()->GetFileName() ).GetPath();
252
253 if( !dirName.MakeRelativeTo( boardFilePath ) )
254 {
255 wxMessageBox( _( "Cannot make path relative (target volume different from board "
256 "file volume)!" ),
257 _( "Plot Output Directory" ), wxOK | wxICON_ERROR );
258 }
259 }
260
261 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
262}
263
264
265void DIALOG_GEN_FOOTPRINT_POSITION::onGenerate( wxCommandEvent& event )
266{
267 if( !m_job )
268 {
269 m_units = m_unitsCtrl->GetSelection() == 0 ? EDA_UNITS::INCH : EDA_UNITS::MM;
270
271 wxString dirStr = m_outputDirectoryName->GetValue();
272 // Keep unix directory format convention in cfg files
273 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
274
276
278 {
279 cfg->m_PlaceFile.output_directory = dirStr;
280 cfg->m_PlaceFile.units = m_units == EDA_UNITS::INCH ? 0 : 1;
281 cfg->m_PlaceFile.file_options = m_singleFile->GetValue() ? 1 : 0;
282 cfg->m_PlaceFile.file_format = m_formatCtrl->GetSelection();
283 cfg->m_PlaceFile.include_board_edge = m_cbIncludeBoardEdge->GetValue();
284 cfg->m_PlaceFile.exclude_TH = m_excludeTH->GetValue();
285 cfg->m_PlaceFile.only_SMD = m_onlySMD->GetValue();
286 cfg->m_PlaceFile.use_aux_origin = m_useDrillPlaceOrigin->GetValue();
287 cfg->m_PlaceFile.negate_xcoord = m_negateXcb->GetValue();
288 }
289
290 if( m_formatCtrl->GetSelection() == 2 )
292 else
294 }
295 else
296 {
300 m_job->m_format = static_cast<JOB_EXPORT_PCB_POS::FORMAT>( m_formatCtrl->GetSelection() );
302 m_job->m_singleFile = m_singleFile->GetValue();
305 m_job->m_smdOnly = m_onlySMD->GetValue();
307 m_job->m_negateBottomX = m_negateXcb->GetValue();
308 m_job->m_excludeDNP = m_excludeDNP->GetValue();
309
310 event.Skip(); // Allow normal close action
311 }
312}
313
314
316{
317 BOARD* brd = m_editFrame->GetBoard();
318 wxString msg;
319 int fullcount = 0;
320
321 // Create output directory if it does not exist (also transform it in absolute form).
322 // Bail if it fails.
323
324 std::function<bool( wxString* )> textResolver =
325 [&]( wxString* token ) -> bool
326 {
327 // Handles board->GetTitleBlock() *and* board->GetProject()
328 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
329 };
330
332 path = ExpandTextVars( path, &textResolver );
333 path = ExpandEnvVarSubstitutions( path, nullptr );
334
335 wxFileName outputDir = wxFileName::DirName( path );
336 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
337
339
340 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) )
341 {
342 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
343 DisplayError( this, msg );
344 return false;
345 }
346
347 wxFileName fn = m_editFrame->GetBoard()->GetFileName();
348 fn.SetPath( outputDir.GetPath() );
349
350 // Create the Front and Top side placement files. Gerber P&P files are always separated.
351 // Not also they include all footprints
352 PLACEFILE_GERBER_WRITER exporter( brd );
353 wxString filename = exporter.GetPlaceFileName( fn.GetFullPath(), F_Cu );
354
355 int fpcount = exporter.CreatePlaceFile( filename, F_Cu, m_cbIncludeBoardEdge->GetValue(),
356 m_excludeDNP->GetValue() );
357
358 if( fpcount < 0 )
359 {
360 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
361 wxMessageBox( msg );
363 return false;
364 }
365
366 msg.Printf( _( "Front (top side) placement file: '%s'." ), filename );
368
369 msg.Printf( _( "Component count: %d." ), fpcount );
371
372 // Create the Back or Bottom side placement file
373 fullcount = fpcount;
374
375 filename = exporter.GetPlaceFileName( fn.GetFullPath(), B_Cu );
376
377 fpcount = exporter.CreatePlaceFile( filename, B_Cu, m_cbIncludeBoardEdge->GetValue(),
378 m_excludeDNP->GetValue() );
379
380 if( fpcount < 0 )
381 {
382 msg.Printf( _( "Failed to create file '%s'." ), filename );
384 wxMessageBox( msg );
385 return false;
386 }
387
388 // Display results
389 msg.Printf( _( "Back (bottom side) placement file: '%s'." ), filename );
391
392 msg.Printf( _( "Component count: %d." ), fpcount );
394
395 fullcount += fpcount;
396 msg.Printf( _( "Full component count: %d." ), fullcount );
398
399 m_reporter->Report( _( "Done." ), RPT_SEVERITY_INFO );
400
401 return true;
402}
403
404
406{
407 BOARD* brd = m_editFrame->GetBoard();
408 wxString msg;
409 bool singleFile = OneFileOnly();
410 bool useCSVfmt = m_formatCtrl->GetSelection() == 1;
411 bool useAuxOrigin = m_useDrillPlaceOrigin->GetValue();
412 int fullcount = 0;
413 int topSide = true;
414 int bottomSide = true;
415 bool negateBottomX = m_negateXcb->GetValue();
416
417 // Test for any footprint candidate in list.
418 {
420 topSide, bottomSide, useCSVfmt, useAuxOrigin, negateBottomX );
421 exporter.GenPositionData();
422
423 if( exporter.GetFootprintCount() == 0 )
424 {
425 wxMessageBox( _( "No footprint for automated placement." ) );
426 return false;
427 }
428 }
429
430 // Create output directory if it does not exist (also transform it in absolute form).
431 // Bail if it fails.
432
433 std::function<bool( wxString* )> textResolver =
434 [&]( wxString* token ) -> bool
435 {
436 // Handles board->GetTitleBlock() *and* board->GetProject()
437 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
438 };
439
441 path = ExpandTextVars( path, &textResolver );
442 path = ExpandEnvVarSubstitutions( path, nullptr );
443
444 wxFileName outputDir = wxFileName::DirName( path );
445 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
446
448
449 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) )
450 {
451 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
452 DisplayError( this, msg );
453 return false;
454 }
455
456 wxFileName fn = m_editFrame->GetBoard()->GetFileName();
457 fn.SetPath( outputDir.GetPath() );
458
459 // Create the Front or Top side placement file, or a single file
460 topSide = true;
461 bottomSide = singleFile;
462
463 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( fn.GetName(), topSide, bottomSide ) );
465
466 if( useCSVfmt )
467 {
468 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
469 fn.SetExt( wxT( "csv" ) );
470 }
471
472 int fpcount = m_editFrame->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), OnlySMD(),
473 ExcludeAllTH(), ExcludeDNP(), topSide, bottomSide,
474 useCSVfmt, useAuxOrigin, negateBottomX );
475 if( fpcount < 0 )
476 {
477 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
478 wxMessageBox( msg );
480 return false;
481 }
482
483 if( singleFile )
484 msg.Printf( _( "Placement file: '%s'." ), fn.GetFullPath() );
485 else
486 msg.Printf( _( "Front (top side) placement file: '%s'." ), fn.GetFullPath() );
487
489
490 msg.Printf( _( "Component count: %d." ), fpcount );
492
493 if( singleFile )
494 {
495 m_reporter->Report( _( "Done." ), RPT_SEVERITY_INFO );
496 return true;
497 }
498
499 // Create the Back or Bottom side placement file
500 fullcount = fpcount;
501 topSide = false;
502 bottomSide = true;
503 fn = brd->GetFileName();
504 fn.SetPath( outputDir.GetPath() );
505 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( fn.GetName(), topSide, bottomSide ) );
507
508 if( useCSVfmt )
509 {
510 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
511 fn.SetExt( wxT( "csv" ) );
512 }
513
514 fpcount = m_editFrame->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), OnlySMD(),
515 ExcludeAllTH(), ExcludeDNP(), topSide, bottomSide,
516 useCSVfmt, useAuxOrigin, negateBottomX );
517
518 if( fpcount < 0 )
519 {
520 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
522 wxMessageBox( msg );
523 return false;
524 }
525
526 // Display results
527 if( !singleFile )
528 {
529 msg.Printf( _( "Back (bottom side) placement file: '%s'." ), fn.GetFullPath() );
531
532 msg.Printf( _( "Component count: %d." ), fpcount );
534 }
535
536 if( !singleFile )
537 {
538 fullcount += fpcount;
539 msg.Printf( _( "Full component count: %d." ), fullcount );
541 }
542
543 m_reporter->Report( _( "Done." ), RPT_SEVERITY_INFO );
544 return true;
545}
546
547
549{
550 DIALOG_GEN_FOOTPRINT_POSITION dlg( getEditFrame<PCB_EDIT_FRAME>() );
551 dlg.ShowModal();
552 return 0;
553}
554
555
556int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName, bool aUnitsMM,
557 bool aOnlySMD, bool aNoTHItems, bool aExcludeDNP,
558 bool aTopSide, bool aBottomSide, bool aFormatCSV,
559 bool aUseAuxOrigin, bool aNegateBottomX )
560{
561 FILE * file = nullptr;
562
563 if( !aFullFileName.IsEmpty() )
564 {
565 file = wxFopen( aFullFileName, wxT( "wt" ) );
566
567 if( file == nullptr )
568 return -1;
569 }
570
571 std::string data;
572 PLACE_FILE_EXPORTER exporter( GetBoard(), aUnitsMM, aOnlySMD, aNoTHItems, aExcludeDNP, aTopSide,
573 aBottomSide, aFormatCSV, aUseAuxOrigin, aNegateBottomX );
574 data = exporter.GenPositionData();
575
576 // if aFullFileName is empty, the file is not created, only the
577 // count of footprints to place is returned
578 if( file )
579 {
580 // Creates a footprint position file
581 // aSide = 0 -> Back (bottom) side)
582 // aSide = 1 -> Front (top) side)
583 // aSide = 2 -> both sides
584 fputs( data.c_str(), file );
585 fclose( file );
586 }
587
588 return exporter.GetFootprintCount();
589}
590
591
593{
595 wxFileName fn;
596
597 wxString boardFilePath = ( (wxFileName) board->GetFileName() ).GetPath();
598 wxDirDialog dirDialog( m_frame, _( "Select Output Directory" ), boardFilePath );
599
600 if( dirDialog.ShowModal() == wxID_CANCEL )
601 return 0;
602
603 fn = board->GetFileName();
604 fn.SetPath( dirDialog.GetPath() );
605 fn.SetExt( wxT( "rpt" ) );
606
607 FILE* rptfile = wxFopen( fn.GetFullPath(), wxT( "wt" ) );
608
609 if( rptfile == nullptr )
610 {
611 wxMessageBox( wxString::Format( _( "Footprint report file created:\n'%s'." ), fn.GetFullPath() ),
612 _( "Footprint Report" ), wxICON_INFORMATION );
613
614 return 0;
615 }
616
617 std::string data;
618 PLACE_FILE_EXPORTER exporter( board, m_frame->GetUserUnits() == EDA_UNITS::MM,
619 false, // aOnlySMD
620 false, // aNoTHItems
621 false, // aExcludeDNP
622 true, true, // aTopSide, aBottomSide
623 false, // aFormatCSV
624 true, // aUseAuxOrigin
625 false ); // aNegateBottomX
626 data = exporter.GenReportData();
627
628 fputs( data.c_str(), rptfile );
629 fclose( rptfile );
630
631 wxMessageBox( wxString::Format( _( "Footprint report file created:\n'%s'." ), fn.GetFullPath() ),
632 _( "Footprint Report" ), wxICON_INFORMATION );
633
634 return 0;
635}
636
637
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
int GenFootprintsReport(const TOOL_EVENT &aEvent)
int GeneratePosFile(const TOOL_EVENT &aEvent)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:317
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:499
const wxString & GetFileName() const
Definition: board.h:354
Class DIALOG_GEN_FOOTPRINT_POSITION_BASE.
The dialog to create footprint position files and choose options (one or 2 files, units and force all...
void onUpdateUIincludeBoardEdge(wxUpdateUIEvent &event) override
void onUpdateUIExcludeTH(wxUpdateUIEvent &event) override
bool CreateGerberFiles()
Creates placement files in gerber format.
void onGenerate(wxCommandEvent &event) override
void onUpdateUIFileOpt(wxUpdateUIEvent &event) override
void onUpdateUIOnlySMD(wxUpdateUIEvent &event) override
DIALOG_GEN_FOOTPRINT_POSITION(PCB_EDIT_FRAME *aEditFrame)
bool CreateAsciiFiles()
Creates files in text or csv format.
void onUpdateUInegXcoord(wxUpdateUIEvent &event) override
void onOutputDirectoryBrowseClicked(wxCommandEvent &event) override
void onUpdateUIUnits(wxUpdateUIEvent &event) override
EDA_UNITS m_units
Definition: dialog_shim.h:193
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:194
int ShowModal() override
wxString GetSettingsDialogTitle() const override
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
Definition: job.cpp:153
wxString GetConfiguredOutputPath() const
Returns the configured output path for the job.
Definition: job.h:227
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
DIALOG_PLACE_FILE m_PlaceFile
PCBNEW_SETTINGS * GetPcbNewSettings() const
BOARD * GetBoard() const
The main frame for Pcbnew.
int DoGenFootprintsPositionFile(const wxString &aFullFileName, bool aUnitsMM, bool aOnlySMD, bool aNoTHItems, bool aExcludeDNP, bool aTopSide, bool aBottomSide, bool aFormatCSV, bool aUseAuxOrigin, bool aNegateBottomX)
Create an ASCII footprint position file.
BOARD * board() const
Used to create Gerber drill files.
const wxString GetPlaceFileName(const wxString &aFullBaseFilename, PCB_LAYER_ID aLayer) const
int CreatePlaceFile(const wxString &aFullFilename, PCB_LAYER_ID aLayer, bool aIncludeBrdEdges, bool aExcludeDNP)
Create an pnp gerber file.
The ASCII format of the kicad place file is:
static wxString DecorateFilename(const wxString &aBaseName, bool aFront, bool aBack)
std::string GenPositionData()
build a string filled with the position data
std::string GenReportData()
build a string filled with the pad report data This report does not used options aForceSmdItems,...
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:74
wxString m_PcbLastPath[LAST_PATH_SIZE]
MRU path storage.
Definition: project_file.h:179
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:204
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:372
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition: reporter.h:102
void SetBitmap(const wxBitmapBundle &aBmp)
Generic, UI-independent tool event.
Definition: tool_event.h:168
EDA_UNITS GetUserUnits() const
void MsgPanelSetMinSize(const wxSize &aMinSize)
Set the min size of the area which displays html messages.
void SetFileName(const wxString &aReportFileName)
Set the report full file name to the string.
REPORTER & Reporter()
Return the reporter object that reports to this panel.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:355
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition: common.cpp:59
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
Definition: common.cpp:376
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
#define _(s)
Classes used in place file generation.
static const std::string FootprintPlaceFileExtension
@ B_Cu
Definition: layer_ids.h:65
@ F_Cu
Definition: layer_ids.h:64
@ LAST_PATH_POS_FILES
Definition: project_file.h:58
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
Definition of file extensions used in Kicad.