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();
92
93 m_units = cfg->m_PlaceFile.units == 0 ? EDA_UNITS::INCHES : EDA_UNITS::MILLIMETRES;
94
95 // Output directory
97
98 // Update Options
99 m_unitsCtrl->SetSelection( cfg->m_PlaceFile.units );
100 m_singleFile->SetValue( cfg->m_PlaceFile.file_options == 1 );
101 m_formatCtrl->SetSelection( cfg->m_PlaceFile.file_format );
104 m_onlySMD->SetValue( cfg->m_PlaceFile.only_SMD );
105 m_negateXcb->SetValue( cfg->m_PlaceFile.negate_xcoord );
106 m_excludeTH->SetValue( cfg->m_PlaceFile.exclude_TH );
107
108 // Update sizes and sizers:
109 m_messagesPanel->MsgPanelSetMinSize( wxSize( -1, 160 ) );
110 }
111 else
112 {
113 SetTitle( m_job->GetSettingsDialogTitle() );
114
115 m_browseButton->Hide();
116
118 : EDA_UNITS::MILLIMETRES;
119
120 m_staticTextDir->SetLabel( _( "Output file:" ) );
122
123 m_unitsCtrl->SetSelection( static_cast<int>( m_job->m_units ) );
124 m_singleFile->SetValue( m_job->m_singleFile );
125 m_formatCtrl->SetSelection( static_cast<int>( m_job->m_format ) );
128 m_onlySMD->SetValue( m_job->m_smdOnly );
129 m_negateXcb->SetValue( m_job->m_negateBottomX );
131 m_excludeDNP->SetValue( m_job->m_excludeDNP );
132
133 m_messagesPanel->Hide();
134 }
135
136 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
137 // non-job versions (which have different sizes).
138 m_hash_key = TO_UTF8( GetTitle() );
139
140 GetSizer()->SetSizeHints( this );
141}
142
143
145{
146 m_unitsLabel->Enable( m_formatCtrl->GetSelection() != 2 );
147 m_unitsCtrl->Enable( m_formatCtrl->GetSelection() != 2 );
148}
149
150
152{
153 m_singleFile->Enable( m_formatCtrl->GetSelection() != 2 );
154}
155
156
158{
159 if( m_formatCtrl->GetSelection() == 2 )
160 {
161 m_onlySMD->SetValue( false );
162 m_onlySMD->Enable( false );
163 }
164 else
165 {
166 m_onlySMD->Enable( true );
167 }
168}
169
170
172{
173 if( m_formatCtrl->GetSelection() == 2 )
174 {
175 m_negateXcb->SetValue( false );
176 m_negateXcb->Enable( false );
177 }
178 else
179 {
180 m_negateXcb->Enable( true );
181 }
182}
183
185{
186 if( m_formatCtrl->GetSelection() == 2 )
187 {
188 m_excludeTH->SetValue( false );
189 m_excludeTH->Enable( false );
190 }
191 else
192 {
193 m_excludeTH->Enable( true );
194 }
195}
196
197
199{
200 return m_unitsCtrl->GetSelection() == 1;
201}
202
203
205{
206 return m_singleFile->GetValue();
207}
208
209
211{
212 return m_onlySMD->GetValue();
213}
214
215
217{
218 return m_excludeTH->GetValue();
219}
220
221
223{
224 return m_excludeDNP->GetValue();
225}
226
227
229{
230 m_cbIncludeBoardEdge->Enable( m_formatCtrl->GetSelection() == 2 );
231}
232
233
235{
236 // Build the absolute path of current output directory to preselect it in the file browser.
237 wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
238 path = Prj().AbsolutePath( path );
239
240 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
241
242 if( dirDialog.ShowModal() == wxID_CANCEL )
243 return;
244
245 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
246
247 wxMessageDialog dialog( this, _( "Use a relative path?"), _( "Plot Output Directory" ),
248 wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
249
250 if( dialog.ShowModal() == wxID_YES )
251 {
252 wxString boardFilePath = ( (wxFileName) m_editFrame->GetBoard()->GetFileName() ).GetPath();
253
254 if( !dirName.MakeRelativeTo( boardFilePath ) )
255 {
256 wxMessageBox( _( "Cannot make path relative (target volume different from board "
257 "file volume)!" ),
258 _( "Plot Output Directory" ), wxOK | wxICON_ERROR );
259 }
260 }
261
262 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
263}
264
265
266void DIALOG_GEN_FOOTPRINT_POSITION::onGenerate( wxCommandEvent& event )
267{
268 if( !m_job )
269 {
270 m_units = m_unitsCtrl->GetSelection() == 0 ? EDA_UNITS::INCHES : EDA_UNITS::MILLIMETRES;
271
273
274 wxString dirStr = m_outputDirectoryName->GetValue();
275 // Keep unix directory format convention in cfg files
276 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
277
279 cfg->m_PlaceFile.output_directory = dirStr;
280 cfg->m_PlaceFile.units = m_units == EDA_UNITS::INCHES ? 0 : 1;
281 cfg->m_PlaceFile.file_options = m_singleFile->GetValue() ? 1 : 0;
282 cfg->m_PlaceFile.file_format = m_formatCtrl->GetSelection();
284 cfg->m_PlaceFile.exclude_TH = m_excludeTH->GetValue();
285 cfg->m_PlaceFile.only_SMD = m_onlySMD->GetValue();
287 cfg->m_PlaceFile.negate_xcoord = m_negateXcb->GetValue();
288
289 if( m_formatCtrl->GetSelection() == 2 )
291 else
293 }
294 else
295 {
299 m_job->m_format = static_cast<JOB_EXPORT_PCB_POS::FORMAT>( m_formatCtrl->GetSelection() );
301 m_job->m_singleFile = m_singleFile->GetValue();
304 m_job->m_smdOnly = m_onlySMD->GetValue();
306 m_job->m_negateBottomX = m_negateXcb->GetValue();
307 m_job->m_excludeDNP = m_excludeDNP->GetValue();
308
309 event.Skip(); // Allow normal close action
310 }
311}
312
313
315{
316 BOARD* brd = m_editFrame->GetBoard();
317 wxString msg;
318 int fullcount = 0;
319
320 // Create output directory if it does not exist (also transform it in absolute form).
321 // Bail if it fails.
322
323 std::function<bool( wxString* )> textResolver =
324 [&]( wxString* token ) -> bool
325 {
326 // Handles board->GetTitleBlock() *and* board->GetProject()
327 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
328 };
329
331 path = ExpandTextVars( path, &textResolver );
332 path = ExpandEnvVarSubstitutions( path, nullptr );
333
334 wxFileName outputDir = wxFileName::DirName( path );
335 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
336
338
339 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) )
340 {
341 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
342 DisplayError( this, msg );
343 return false;
344 }
345
346 wxFileName fn = m_editFrame->GetBoard()->GetFileName();
347 fn.SetPath( outputDir.GetPath() );
348
349 // Create the Front and Top side placement files. Gerber P&P files are always separated.
350 // Not also they include all footprints
351 PLACEFILE_GERBER_WRITER exporter( brd );
352 wxString filename = exporter.GetPlaceFileName( fn.GetFullPath(), F_Cu );
353
354 int fpcount = exporter.CreatePlaceFile( filename, F_Cu, m_cbIncludeBoardEdge->GetValue() );
355
356 if( fpcount < 0 )
357 {
358 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
359 wxMessageBox( msg );
361 return false;
362 }
363
364 msg.Printf( _( "Front (top side) placement file: '%s'." ), filename );
366
367 msg.Printf( _( "Component count: %d." ), fpcount );
369
370 // Create the Back or Bottom side placement file
371 fullcount = fpcount;
372
373 filename = exporter.GetPlaceFileName( fn.GetFullPath(), B_Cu );
374
375 fpcount = exporter.CreatePlaceFile( filename, B_Cu, m_cbIncludeBoardEdge->GetValue() );
376
377 if( fpcount < 0 )
378 {
379 msg.Printf( _( "Failed to create file '%s'." ), filename );
381 wxMessageBox( msg );
382 return false;
383 }
384
385 // Display results
386 msg.Printf( _( "Back (bottom side) placement file: '%s'." ), filename );
388
389 msg.Printf( _( "Component count: %d." ), fpcount );
391
392 fullcount += fpcount;
393 msg.Printf( _( "Full component count: %d." ), fullcount );
395
396 m_reporter->Report( _( "Done." ), RPT_SEVERITY_INFO );
397
398 return true;
399}
400
401
403{
404 BOARD* brd = m_editFrame->GetBoard();
405 wxString msg;
406 bool singleFile = OneFileOnly();
407 bool useCSVfmt = m_formatCtrl->GetSelection() == 1;
408 bool useAuxOrigin = m_useDrillPlaceOrigin->GetValue();
409 int fullcount = 0;
410 int topSide = true;
411 int bottomSide = true;
412 bool negateBottomX = m_negateXcb->GetValue();
413
414 // Test for any footprint candidate in list.
415 {
417 topSide, bottomSide, useCSVfmt, useAuxOrigin, negateBottomX );
418 exporter.GenPositionData();
419
420 if( exporter.GetFootprintCount() == 0 )
421 {
422 wxMessageBox( _( "No footprint for automated placement." ) );
423 return false;
424 }
425 }
426
427 // Create output directory if it does not exist (also transform it in absolute form).
428 // Bail if it fails.
429
430 std::function<bool( wxString* )> textResolver =
431 [&]( wxString* token ) -> bool
432 {
433 // Handles board->GetTitleBlock() *and* board->GetProject()
434 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
435 };
436
438 path = ExpandTextVars( path, &textResolver );
439 path = ExpandEnvVarSubstitutions( path, nullptr );
440
441 wxFileName outputDir = wxFileName::DirName( path );
442 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
443
445
446 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) )
447 {
448 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
449 DisplayError( this, msg );
450 return false;
451 }
452
453 wxFileName fn = m_editFrame->GetBoard()->GetFileName();
454 fn.SetPath( outputDir.GetPath() );
455
456 // Create the Front or Top side placement file, or a single file
457 topSide = true;
458 bottomSide = singleFile;
459
460 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( fn.GetName(), topSide, bottomSide ) );
462
463 if( useCSVfmt )
464 {
465 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
466 fn.SetExt( wxT( "csv" ) );
467 }
468
469 int fpcount = m_editFrame->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), OnlySMD(),
470 ExcludeAllTH(), ExcludeDNP(), topSide,
471 bottomSide, useCSVfmt, useAuxOrigin,
472 negateBottomX );
473 if( fpcount < 0 )
474 {
475 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
476 wxMessageBox( msg );
478 return false;
479 }
480
481 if( singleFile )
482 msg.Printf( _( "Placement file: '%s'." ), fn.GetFullPath() );
483 else
484 msg.Printf( _( "Front (top side) placement file: '%s'." ), fn.GetFullPath() );
485
487
488 msg.Printf( _( "Component count: %d." ), fpcount );
490
491 if( singleFile )
492 {
493 m_reporter->Report( _( "Done." ), RPT_SEVERITY_INFO );
494 return true;
495 }
496
497 // Create the Back or Bottom side placement file
498 fullcount = fpcount;
499 topSide = false;
500 bottomSide = true;
501 fn = brd->GetFileName();
502 fn.SetPath( outputDir.GetPath() );
503 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( fn.GetName(), topSide, bottomSide ) );
505
506 if( useCSVfmt )
507 {
508 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
509 fn.SetExt( wxT( "csv" ) );
510 }
511
512 fpcount = m_editFrame->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), OnlySMD(),
513 ExcludeAllTH(), ExcludeDNP(), topSide,
514 bottomSide, useCSVfmt,
515 useAuxOrigin, negateBottomX );
516
517 if( fpcount < 0 )
518 {
519 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
521 wxMessageBox( msg );
522 return false;
523 }
524
525 // Display results
526 if( !singleFile )
527 {
528 msg.Printf( _( "Back (bottom side) placement file: '%s'." ), fn.GetFullPath() );
530
531 msg.Printf( _( "Component count: %d." ), fpcount );
533 }
534
535 if( !singleFile )
536 {
537 fullcount += fpcount;
538 msg.Printf( _( "Full component count: %d." ), fullcount );
540 }
541
542 m_reporter->Report( _( "Done." ), RPT_SEVERITY_INFO );
543 return true;
544}
545
546
548{
549 DIALOG_GEN_FOOTPRINT_POSITION dlg( getEditFrame<PCB_EDIT_FRAME>() );
550 dlg.ShowModal();
551 return 0;
552}
553
554
555int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName, bool aUnitsMM,
556 bool aOnlySMD, bool aNoTHItems, bool aExcludeDNP,
557 bool aTopSide, bool aBottomSide, bool aFormatCSV,
558 bool aUseAuxOrigin, bool aNegateBottomX )
559{
560 FILE * file = nullptr;
561
562 if( !aFullFileName.IsEmpty() )
563 {
564 file = wxFopen( aFullFileName, wxT( "wt" ) );
565
566 if( file == nullptr )
567 return -1;
568 }
569
570 std::string data;
571 PLACE_FILE_EXPORTER exporter( GetBoard(), aUnitsMM, aOnlySMD, aNoTHItems, aExcludeDNP, aTopSide,
572 aBottomSide, aFormatCSV, aUseAuxOrigin, aNegateBottomX );
573 data = exporter.GenPositionData();
574
575 // if aFullFileName is empty, the file is not created, only the
576 // count of footprints to place is returned
577 if( file )
578 {
579 // Creates a footprint position file
580 // aSide = 0 -> Back (bottom) side)
581 // aSide = 1 -> Front (top) side)
582 // aSide = 2 -> both sides
583 fputs( data.c_str(), file );
584 fclose( file );
585 }
586
587 return exporter.GetFootprintCount();
588}
589
590
591void PCB_EDIT_FRAME::GenFootprintsReport( wxCommandEvent& event )
592{
593 wxFileName fn;
594
595 wxString boardFilePath = ( (wxFileName) GetBoard()->GetFileName() ).GetPath();
596 wxDirDialog dirDialog( this, _( "Select Output Directory" ), boardFilePath );
597
598 if( dirDialog.ShowModal() == wxID_CANCEL )
599 return;
600
601 fn = GetBoard()->GetFileName();
602 fn.SetPath( dirDialog.GetPath() );
603 fn.SetExt( wxT( "rpt" ) );
604
605 bool unitMM = GetUserUnits() == EDA_UNITS::MILLIMETRES;
606 bool success = DoGenFootprintsReport( fn.GetFullPath(), unitMM );
607
608 wxString msg;
609
610 if( success )
611 {
612 msg.Printf( _( "Footprint report file created:\n'%s'." ), fn.GetFullPath() );
613 wxMessageBox( msg, _( "Footprint Report" ), wxICON_INFORMATION );
614 }
615 else
616 {
617 msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
618 DisplayError( this, msg );
619 }
620}
621
622
623bool PCB_EDIT_FRAME::DoGenFootprintsReport( const wxString& aFullFilename, bool aUnitsMM )
624{
625 FILE* rptfile = wxFopen( aFullFilename, wxT( "wt" ) );
626
627 if( rptfile == nullptr )
628 return false;
629
630 std::string data;
631 PLACE_FILE_EXPORTER exporter( GetBoard(), aUnitsMM,
632 false, false, // SMD aOnlySMD, aNoTHItems
633 false, // aExcludeDNP
634 true, true, // aTopSide, aBottomSide
635 false, true, false // aFormatCSV, aUseAuxOrigin, aNegateBottomX
636 );
637 data = exporter.GenReportData();
638
639 fputs( data.c_str(), rptfile );
640 fclose( rptfile );
641
642 return true;
643}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
int GeneratePosFile(const TOOL_EVENT &aEvent)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:433
const wxString & GetFileName() const
Definition: board.h:332
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:229
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:230
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:226
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.
void GenFootprintsReport(wxCommandEvent &event)
Call DoGenFootprintsReport to create a footprint report file.
bool DoGenFootprintsReport(const wxString &aFullFilename, bool aUnitsMM)
Create an ASCII footprint report file giving some infos on footprints and board outlines.
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)
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:72
wxString m_PcbLastPath[LAST_PATH_SIZE]
MRU path storage.
Definition: project_file.h:167
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
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:370
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
void SetBitmap(const wxBitmapBundle &aBmp)
Generic, UI-independent tool event.
Definition: tool_event.h:168
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:351
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:372
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
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
int GetUserUnits()
Return the currently selected user unit value for the interface.
@ LAST_PATH_POS_FILES
Definition: project_file.h:56
@ 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:398
Definition of file extensions used in Kicad.