KiCad PCB EDA Suite
gerbview/files.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 (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU 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, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <wx/filedlg.h>
26 #include <wx/wfstream.h>
27 #include <wx/zipstrm.h>
28 #include <reporter.h>
30 #include <gerbview_frame.h>
31 #include <gerbview_id.h>
32 #include <gerber_file_image.h>
33 #include <gerber_file_image_list.h>
34 #include <excellon_image.h>
38 
39 // HTML Messages used more than one time:
40 #define MSG_NO_MORE_LAYER _( "<b>No more available layers</b> in GerbView to load files" )
41 #define MSG_NOT_LOADED _( "\n<b>Not loaded:</b> <i>%s</i>" )
42 #define MSG_OOM _( "\n<b>Memory was exhausted reading:</b> <i>%s</i>" )
43 
44 
45 void GERBVIEW_FRAME::OnGbrFileHistory( wxCommandEvent& event )
46 {
47  wxString fn;
48 
49  fn = GetFileFromHistory( event.GetId(), _( "Gerber files" ) );
50 
51  if( !fn.IsEmpty() )
52  {
53  Erase_Current_DrawLayer( false );
54  LoadGerberFiles( fn );
55  }
56 }
57 
58 void GERBVIEW_FRAME::OnClearGbrFileHistory( wxCommandEvent& aEvent )
59 {
61 }
62 
63 
64 void GERBVIEW_FRAME::OnDrlFileHistory( wxCommandEvent& event )
65 {
66  wxString fn;
67 
68  fn = GetFileFromHistory( event.GetId(), _( "Drill files" ), &m_drillFileHistory );
69 
70  if( !fn.IsEmpty() )
71  {
72  Erase_Current_DrawLayer( false );
73  LoadExcellonFiles( fn );
74  }
75 }
76 
77 
78 void GERBVIEW_FRAME::OnClearDrlFileHistory( wxCommandEvent& aEvent )
79 {
81 }
82 
83 
84 void GERBVIEW_FRAME::OnZipFileHistory( wxCommandEvent& event )
85 {
86  wxString filename;
87  filename = GetFileFromHistory( event.GetId(), _( "Zip files" ), &m_zipFileHistory );
88 
89  if( !filename.IsEmpty() )
90  {
91  Erase_Current_DrawLayer( false );
92  LoadZipArchiveFile( filename );
93  }
94 }
95 
96 
97 void GERBVIEW_FRAME::OnClearZipFileHistory( wxCommandEvent& aEvent )
98 {
100 }
101 
102 
103 void GERBVIEW_FRAME::OnJobFileHistory( wxCommandEvent& event )
104 {
105  wxString filename = GetFileFromHistory( event.GetId(), _( "Job files" ), &m_jobFileHistory );
106 
107  if( !filename.IsEmpty() )
108  LoadGerberJobFile( filename );
109 }
110 
111 
112 void GERBVIEW_FRAME::OnClearJobFileHistory( wxCommandEvent& aEvent )
113 {
115 }
116 
117 
118 bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
119 {
120  static int lastGerberFileWildcard = 0;
121  wxString filetypes;
122  wxArrayString filenamesList;
123  wxFileName filename = aFullFileName;
124  wxString currentPath;
125 
126  if( !filename.IsOk() )
127  {
128  /* Standard gerber filetypes
129  * (See http://en.wikipedia.org/wiki/Gerber_File)
130  * The .gbr (.pho in legacy files) extension is the default used in Pcbnew; however
131  * there are a lot of other extensions used for gerber files. Because the first letter
132  * is usually g, we accept g* as extension.
133  * (Mainly internal copper layers do not have specific extension, and filenames are like
134  * *.g1, *.g2 *.gb1 ...)
135  * Now (2014) Ucamco (the company which manages the Gerber format) encourages use of .gbr
136  * only and the Gerber X2 file format.
137  */
138  filetypes = _( "Gerber files (.g* .lgr .pho)" );
139  filetypes << wxT("|");
140  filetypes += wxT("*.g*;*.G*;*.pho;*.PHO" );
141  filetypes << wxT("|");
142 
143  /* Special gerber filetypes */
144  filetypes += _( "Top layer (*.GTL)|*.GTL;*.gtl|" );
145  filetypes += _( "Bottom layer (*.GBL)|*.GBL;*.gbl|" );
146  filetypes += _( "Bottom solder resist (*.GBS)|*.GBS;*.gbs|" );
147  filetypes += _( "Top solder resist (*.GTS)|*.GTS;*.gts|" );
148  filetypes += _( "Bottom overlay (*.GBO)|*.GBO;*.gbo|" );
149  filetypes += _( "Top overlay (*.GTO)|*.GTO;*.gto|" );
150  filetypes += _( "Bottom paste (*.GBP)|*.GBP;*.gbp|" );
151  filetypes += _( "Top paste (*.GTP)|*.GTP;*.gtp|" );
152  filetypes += _( "Keep-out layer (*.GKO)|*.GKO;*.gko|" );
153  filetypes += _( "Mechanical layers (*.GMx)|*.GM1;*.gm1;*.GM2;*.gm2;*.GM3;*.gm3|" );
154  filetypes += _( "Top Pad Master (*.GPT)|*.GPT;*.gpt|" );
155  filetypes += _( "Bottom Pad Master (*.GPB)|*.GPB;*.gpb|" );
156 
157  // All filetypes
158  filetypes += AllFilesWildcard();
159 
160  // Use the current working directory if the file name path does not exist.
161  if( filename.DirExists() )
162  currentPath = filename.GetPath();
163  else
164  {
165  currentPath = m_mruPath;
166 
167  // On wxWidgets 3.1 (bug?) the path in wxFileDialog is ignored when
168  // finishing by the dir separator. Remove it if any:
169  if( currentPath.EndsWith( '\\' ) || currentPath.EndsWith( '/' ) )
170  currentPath.RemoveLast();
171  }
172 
173  wxFileDialog dlg( this, _( "Open Gerber File(s)" ), currentPath, filename.GetFullName(),
174  filetypes,
175  wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR );
176  dlg.SetFilterIndex( lastGerberFileWildcard );
177 
178  if( dlg.ShowModal() == wxID_CANCEL )
179  return false;
180 
181  lastGerberFileWildcard = dlg.GetFilterIndex();
182  dlg.GetPaths( filenamesList );
183  m_mruPath = currentPath = dlg.GetDirectory();
184  }
185  else
186  {
187  filenamesList.Add( aFullFileName );
188  m_mruPath = currentPath = filename.GetPath();
189  }
190 
191  Erase_Current_DrawLayer( false );
192 
193  // Set the busy cursor
194  wxBusyCursor wait;
195 
196  return LoadListOfGerberAndDrillFiles( currentPath, filenamesList );
197 }
198 
199 
201  const wxArrayString& aFilenameList,
202  const std::vector<int>* aFileType )
203 {
204  wxFileName filename;
205 
206  // Read gerber files: each file is loaded on a new GerbView layer
207  bool success = true;
208  int layer = GetActiveLayer();
210 
211  // Manage errors when loading files
212  wxString msg;
213  WX_STRING_REPORTER reporter( &msg );
214 
215  // Create progress dialog (only used if more than 1 file to load
216  std::unique_ptr<WX_PROGRESS_REPORTER> progress = nullptr;
217 
218  for( unsigned ii = 0; ii < aFilenameList.GetCount(); ii++ )
219  {
220  filename = aFilenameList[ii];
221 
222  if( !filename.IsAbsolute() )
223  filename.SetPath( aPath );
224 
225  // Check for non existing files, to avoid creating broken or useless data
226  // and report all in one error list:
227  if( !filename.FileExists() )
228  {
229  wxString warning;
230  warning << "<b>" << _( "File not found:" ) << "</b><br>"
231  << filename.GetFullPath() << "<br>";
232  reporter.Report( warning, RPT_SEVERITY_WARNING );
233  success = false;
234  continue;
235  }
236 
237  m_lastFileName = filename.GetFullPath();
238 
239  if( !progress && ( aFilenameList.GetCount() > 1 ) )
240  {
241  progress = std::make_unique<WX_PROGRESS_REPORTER>( this,
242  _( "Loading Gerber files..." ), 1, false );
243  progress->SetMaxProgress( aFilenameList.GetCount() - 1 );
244  progress->Report( wxString::Format( _("Loading %u/%zu %s" ), ii+1,
245  aFilenameList.GetCount(), m_lastFileName ) );
246  }
247  else if( progress )
248  {
249  progress->Report( wxString::Format( _("Loading %u/%zu %s" ), ii+1,
250  aFilenameList.GetCount(), m_lastFileName ) );
251  progress->KeepRefreshing();
252  }
253 
254  SetActiveLayer( layer, false );
255 
256  visibility[ layer ] = true;
257 
258  try
259  {
260  if( aFileType && ( *aFileType )[ii] == 1 )
261  {
262  LoadExcellonFiles( filename.GetFullPath() );
263  layer = GetActiveLayer(); // Loading NC drill file changes the active layer
264  }
265  else
266  {
267  if( filename.GetExt() == GerberJobFileExtension.c_str() )
268  {
269  //We cannot read a gerber job file as a gerber plot file: skip it
270  wxString txt;
271  txt.Printf( _( "<b>A gerber job file cannot be loaded as a plot file</b> "
272  "<i>%s</i>" ),
273  filename.GetFullName() );
274  success = false;
275  reporter.Report( txt, RPT_SEVERITY_ERROR );
276  }
277  else if( Read_GERBER_File( filename.GetFullPath() ) )
278  {
280 
281  layer = getNextAvailableLayer( layer );
282 
283  if( layer == NO_AVAILABLE_LAYERS && ii < aFilenameList.GetCount() - 1 )
284  {
285  success = false;
287 
288  // Report the name of not loaded files:
289  ii += 1;
290  while( ii < aFilenameList.GetCount() )
291  {
292  filename = aFilenameList[ii++];
293  wxString txt =
294  wxString::Format( MSG_NOT_LOADED, filename.GetFullName() );
295  reporter.Report( txt, RPT_SEVERITY_ERROR );
296  }
297  break;
298  }
299 
300  SetActiveLayer( layer, false );
301  }
302  }
303  }
304  catch( const std::bad_alloc& )
305  {
306  wxString txt = wxString::Format( MSG_OOM, filename.GetFullName() );
307  reporter.Report( txt, RPT_SEVERITY_ERROR );
308  success = false;
309  continue;
310  }
311 
312  if( progress )
313  progress->AdvanceProgress();
314  }
315 
316  if( !success )
317  {
318  wxSafeYield(); // Allows slice of time to redraw the screen
319  // to refresh widgets, before displaying messages
320  HTML_MESSAGE_BOX mbox( this, _( "Errors" ) );
321  mbox.ListSet( msg );
322  mbox.ShowModal();
323  }
324 
326 
327  Zoom_Automatique( false );
328 
329  // Synchronize layers tools with actual active layer:
331 
332  // TODO: it would be nice if we could set the active layer to one of the
333  // ones that was just loaded, but to maintain the previous user experience
334  // we need to set it to a blank layer in case they load another file.
335  // We can't start with the next available layer when loading files because
336  // some users expect the behavior of overwriting the active layer on load.
337  SetActiveLayer( getNextAvailableLayer( layer ), true );
338 
340  syncLayerBox( true );
341 
342  GetCanvas()->Refresh();
343 
344  return success;
345 }
346 
347 
348 bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName )
349 {
350  wxString filetypes;
351  wxArrayString filenamesList;
352  wxFileName filename = aFullFileName;
353  wxString currentPath;
354 
355  if( !filename.IsOk() )
356  {
357  filetypes = DrillFileWildcard();
358  filetypes << wxT( "|" );
359 
360  /* All filetypes */
361  filetypes += AllFilesWildcard();
362 
363  /* Use the current working directory if the file name path does not exist. */
364  if( filename.DirExists() )
365  currentPath = filename.GetPath();
366  else
367  currentPath = m_mruPath;
368 
369  wxFileDialog dlg( this, _( "Open NC (Excellon) Drill File(s)" ),
370  currentPath, filename.GetFullName(), filetypes,
371  wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR );
372 
373  if( dlg.ShowModal() == wxID_CANCEL )
374  return false;
375 
376  dlg.GetPaths( filenamesList );
377  currentPath = wxGetCwd();
378  m_mruPath = currentPath;
379  }
380  else
381  {
382  filenamesList.Add( aFullFileName );
383  currentPath = filename.GetPath();
384  m_mruPath = currentPath;
385  }
386 
387  // Read Excellon drill files: each file is loaded on a new GerbView layer
388  bool success = true;
389  int layer = GetActiveLayer();
390 
391  // Manage errors when loading files
392  wxString msg;
393  WX_STRING_REPORTER reporter( &msg );
394 
395  for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ )
396  {
397  filename = filenamesList[ii];
398 
399  if( !filename.IsAbsolute() )
400  filename.SetPath( currentPath );
401 
402  m_lastFileName = filename.GetFullPath();
403 
404  SetActiveLayer( layer, false );
405 
406  if( Read_EXCELLON_File( filename.GetFullPath() ) )
407  {
408  // Update the list of recent drill files.
409  UpdateFileHistory( filename.GetFullPath(), &m_drillFileHistory );
410 
411  layer = getNextAvailableLayer( layer );
412 
413  if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 )
414  {
415  success = false;
417 
418  // Report the name of not loaded files:
419  ii += 1;
420  while( ii < filenamesList.GetCount() )
421  {
422  filename = filenamesList[ii++];
423  wxString txt = wxString::Format( MSG_NOT_LOADED, filename.GetFullName() );
424  reporter.Report( txt, RPT_SEVERITY_ERROR );
425  }
426  break;
427  }
428 
429  SetActiveLayer( layer, false );
430  }
431  }
432 
433  if( !success )
434  {
435  HTML_MESSAGE_BOX mbox( this, _( "Errors" ) );
436  mbox.ListSet( msg );
437  mbox.ShowModal();
438  }
439 
440  Zoom_Automatique( false );
441 
442  // Synchronize layers tools with actual active layer:
446  syncLayerBox();
447 
448  return success;
449 }
450 
451 
452 bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aReporter )
453 {
454  wxString msg;
455 
456  // Extract the path of aFullFileName. We use it to store temporary files
457  wxFileName fn( aFullFileName );
458  wxString unzipDir = fn.GetPath();
459 
460  wxFFileInputStream zipFile( aFullFileName );
461 
462  if( !zipFile.IsOk() )
463  {
464  if( aReporter )
465  {
466  msg.Printf( _( "Zip file '%s' cannot be opened." ), aFullFileName );
467  aReporter->Report( msg, RPT_SEVERITY_ERROR );
468  }
469 
470  return false;
471  }
472 
473  // Update the list of recent zip files.
474  UpdateFileHistory( aFullFileName, &m_zipFileHistory );
475 
476  // The unzipped file in only a temporary file. Give it a filename
477  // which cannot conflict with an usual filename.
478  // TODO: make Read_GERBER_File() and Read_EXCELLON_File() able to
479  // accept a stream, and avoid using a temp file.
480  wxFileName temp_fn( "$tempfile.tmp" );
481  temp_fn.MakeAbsolute( unzipDir );
482  wxString unzipped_tempfile = temp_fn.GetFullPath();
483 
484 
485  bool success = true;
486  wxZipInputStream zipArchive( zipFile );
487  wxZipEntry* entry;
488  bool reported_no_more_layer = false;
489 
490  while( ( entry = zipArchive.GetNextEntry() ) )
491  {
492  wxString fname = entry->GetName();
493  wxFileName uzfn = fname;
494  wxString curr_ext = uzfn.GetExt().Lower();
495 
496  // The archive contains Gerber and/or Excellon drill files. Use the right loader.
497  // However it can contain a few other files (reports, pdf files...),
498  // which will be skipped.
499  // Gerber files ext is usually "gbr", but can be also another value, starting by "g"
500  // old gerber files ext from kicad is .pho
501  // drill files do not have a well defined ext
502  // It is .drl in kicad, but .txt in Altium for instance
503  // Allows only .drl for drill files.
504  if( curr_ext[0] != 'g' && curr_ext != "pho" && curr_ext != "drl" )
505  {
506  if( aReporter )
507  {
508  msg.Printf( _( "Skipped file '%s' (unknown type).\n" ), entry->GetName() );
509  aReporter->Report( msg, RPT_SEVERITY_WARNING );
510  }
511 
512  continue;
513  }
514 
515  if( curr_ext == GerberJobFileExtension.c_str() )
516  {
517  //We cannot read a gerber job file as a gerber plot file: skip it
518  if( aReporter )
519  {
520  msg.Printf( _( "Skipped file '%s' (gerber job file).\n" ), entry->GetName() );
521  aReporter->Report( msg, RPT_SEVERITY_WARNING );
522  }
523 
524  continue;
525  }
526 
527  int layer = GetActiveLayer();
528 
529  if( layer == NO_AVAILABLE_LAYERS )
530  {
531  success = false;
532 
533  if( aReporter )
534  {
535  if( !reported_no_more_layer )
537 
538  reported_no_more_layer = true;
539 
540  // Report the name of not loaded files:
541  msg.Printf( MSG_NOT_LOADED, entry->GetName() );
542  aReporter->Report( msg, RPT_SEVERITY_ERROR );
543  }
544 
545  delete entry;
546  continue;
547  }
548 
549  // Create the unzipped temporary file:
550  {
551  wxFFileOutputStream temporary_ofile( unzipped_tempfile );
552 
553  if( temporary_ofile.Ok() )
554  temporary_ofile.Write( zipArchive );
555  else
556  {
557  success = false;
558 
559  if( aReporter )
560  {
561  msg.Printf( _( "<b>Unable to create temporary file '%s'.</b>\n"),
562  unzipped_tempfile );
563  aReporter->Report( msg, RPT_SEVERITY_ERROR );
564  }
565  }
566  }
567 
568  bool read_ok = true;
569 
570  if( curr_ext[0] == 'g' || curr_ext == "pho" )
571  {
572  // Read gerber files: each file is loaded on a new GerbView layer
573  read_ok = Read_GERBER_File( unzipped_tempfile );
574  }
575  else // if( curr_ext == "drl" )
576  {
577  read_ok = Read_EXCELLON_File( unzipped_tempfile );
578  }
579 
580  delete entry;
581 
582  // The unzipped file is only a temporary file, delete it.
583  wxRemoveFile( unzipped_tempfile );
584 
585  if( !read_ok )
586  {
587  success = false;
588 
589  if( aReporter )
590  {
591  msg.Printf( _("<b>unzipped file %s read error</b>\n"), unzipped_tempfile );
592  aReporter->Report( msg, RPT_SEVERITY_ERROR );
593  }
594  }
595  else
596  {
597  GERBER_FILE_IMAGE* gerber_image = GetGbrImage( layer );
598 
599  if( gerber_image )
600  gerber_image->m_FileName = fname;
601 
602  layer = getNextAvailableLayer( layer );
603  SetActiveLayer( layer, false );
604  }
605  }
606 
607  return success;
608 }
609 
610 
611 bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName )
612 {
613 #define ZipFileExtension "zip"
614 
615  wxFileName filename = aFullFileName;
616  wxString currentPath;
617 
618  if( !filename.IsOk() )
619  {
620  // Use the current working directory if the file name path does not exist.
621  if( filename.DirExists() )
622  currentPath = filename.GetPath();
623  else
624  currentPath = m_mruPath;
625 
626  wxFileDialog dlg( this, _( "Open Zip File" ), currentPath, filename.GetFullName(),
627  ZipFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
628 
629  if( dlg.ShowModal() == wxID_CANCEL )
630  return false;
631 
632  filename = dlg.GetPath();
633  currentPath = wxGetCwd();
634  m_mruPath = currentPath;
635  }
636  else
637  {
638  currentPath = filename.GetPath();
639  m_mruPath = currentPath;
640  }
641 
642  wxString msg;
643  WX_STRING_REPORTER reporter( &msg );
644 
645  if( filename.IsOk() )
646  unarchiveFiles( filename.GetFullPath(), &reporter );
647 
648  Zoom_Automatique( false );
649 
650  // Synchronize layers tools with actual active layer:
654  syncLayerBox();
655 
656  if( !msg.IsEmpty() )
657  {
658  wxSafeYield(); // Allows slice of time to redraw the screen
659  // to refresh widgets, before displaying messages
660  HTML_MESSAGE_BOX mbox( this, _( "Messages" ) );
661  mbox.ListSet( msg );
662  mbox.ShowModal();
663  }
664 
665  return true;
666 }
wxString m_lastFileName
wxString m_mruPath
void syncLayerBox(bool aRebuildLayerBox=false)
Update the currently "selected" layer within m_SelLayerBox.
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
void OnClearDrlFileHistory(wxCommandEvent &aEvent)
FILE_HISTORY m_jobFileHistory
GERBER_LAYER_WIDGET * m_LayersManager
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
bool Read_GERBER_File(const wxString &GERBER_FullFileName)
Definition: readgerb.cpp:40
Hold the image data and parameters for one gerber file and layer parameters.
void SetActiveLayer(int aLayer, bool doLayerWidgetUpdate=true)
change the currently active layer to aLayer and update the GERBER_LAYER_WIDGET.
void OnGbrFileHistory(wxCommandEvent &event)
Delete the current data and loads a Gerber file selected from history list on current layer.
wxString ZipFileWildcard()
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
void Erase_Current_DrawLayer(bool query)
void OnClearZipFileHistory(wxCommandEvent &aEvent)
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
wxString AllFilesWildcard()
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
bool LoadGerberJobFile(const wxString &aFileName)
Load a Gerber job file, and load gerber files found in job files.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetches the file name from the file history list.
void OnClearJobFileHistory(wxCommandEvent &aEvent)
FILE_HISTORY m_zipFileHistory
#define MSG_NOT_LOADED
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
LSET is a set of PCB_LAYER_IDs.
bool unarchiveFiles(const wxString &aFullFileName, REPORTER *aReporter=nullptr)
Extract gerber and drill files from the zip archive, and load them.
#define NO_AVAILABLE_LAYERS
bool LoadGerberFiles(const wxString &aFileName)
Load a photoplot (Gerber) file or many files.
bool LoadListOfGerberAndDrillFiles(const wxString &aPath, const wxArrayString &aFilenameList, const std::vector< int > *aFileType=nullptr)
Load a list of Gerber and NC drill files and updates the view based on them.
#define MSG_OOM
void ListSet(const wxString &aList)
Add a list of items.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx) const
bool LoadZipArchiveFile(const wxString &aFileName)
Load a zipped archive file.
void UpdateLayerIcons()
Update all layer manager icons (layers only).
const std::string GerberJobFileExtension
Definition of file extensions used in Kicad.
#define _(s)
void OnClearGbrFileHistory(wxCommandEvent &aEvent)
HTML_MESSAGE_BOX.
FILE_HISTORY m_drillFileHistory
#define MSG_NO_MORE_LAYER
wxString DrillFileWildcard()
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
A wrapper for reporting to a wxString object.
Definition: reporter.h:159
void ClearFileHistory(FILE_HISTORY *aFileHistory=nullptr)
Removes all files from the file history.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
int GetActiveLayer() const
Return the active layer.
void OnJobFileHistory(wxCommandEvent &event)
Delete the current data and load a gerber job file selected from the history list.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition: reporter.cpp:57
void OnDrlFileHistory(wxCommandEvent &event)
Delete the current data and load a drill file in Excellon format selected from history list on curren...
bool LoadExcellonFiles(const wxString &aFileName)
Load a drill (EXCELLON) file or many files.
void OnZipFileHistory(wxCommandEvent &event)
Delete the current data and load a zip archive file selected from the history list.
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
int getNextAvailableLayer(int aLayer=0) const
Find the next empty layer starting at aLayer and returns it to the caller.
void ReFillLayerWidget()
Change out all the layers in m_Layers; called upon loading new gerber files.
bool Read_EXCELLON_File(const wxString &aFullFileName)