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