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 <fctsys.h>
26 #include <wx/fs_zip.h>
27 #include <wx/wfstream.h>
28 #include <wx/zipstrm.h>
29 
30 #include <common.h>
31 #include <class_drawpanel.h>
32 #include <reporter.h>
33 #include <html_messagebox.h>
34 
35 #include <gerbview_frame.h>
36 #include <gerbview_id.h>
37 #include <gerber_file_image.h>
38 #include <gerber_file_image_list.h>
39 #include <excellon_image.h>
40 #include <gerbview_layer_widget.h>
43 
44 // HTML Messages used more than one time:
45 #define MSG_NO_MORE_LAYER\
46  _( "<b>No more available free graphic layer</b> in Gerbview to load files" )
47 #define MSG_NOT_LOADED _( "\n<b>Not loaded:</b> <i>%s</i>" )
48 
49 
50 void GERBVIEW_FRAME::OnGbrFileHistory( wxCommandEvent& event )
51 {
52  wxString fn;
53 
54  fn = GetFileFromHistory( event.GetId(), _( "Gerber files" ) );
55 
56  if( !fn.IsEmpty() )
57  {
58  Erase_Current_DrawLayer( false );
59  LoadGerberFiles( fn );
60  }
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::OnZipFileHistory( wxCommandEvent& event )
79 {
80  wxString filename;
81  filename = GetFileFromHistory( event.GetId(), _( "Zip files" ), &m_zipFileHistory );
82 
83  if( !filename.IsEmpty() )
84  {
85  Erase_Current_DrawLayer( false );
86  LoadZipArchiveFile( filename );
87  }
88 }
89 
90 
91 void GERBVIEW_FRAME::OnJobFileHistory( wxCommandEvent& event )
92 {
93  wxString filename = GetFileFromHistory( event.GetId(), _( "Job files" ), &m_jobFileHistory );
94 
95  if( !filename.IsEmpty() )
96  LoadGerberJobFile( filename );
97 }
98 
99 
100 /* File commands. */
101 void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
102 {
103  int id = event.GetId();
104 
105  switch( id )
106  {
107  case wxID_FILE:
108  LoadGerberFiles( wxEmptyString );
109  break;
110 
112  Clear_DrawLayers( false );
113  Zoom_Automatique( false );
114  m_canvas->Refresh();
115  ClearMsgPanel();
116  break;
117 
119  {
120  // Store filenames
121  wxArrayString listOfGerberFiles;
122  std::vector<int> fileType;
123 
124  for( unsigned i = 0; i < GetImagesList()->ImagesMaxCount(); i++ )
125  {
126  if( GetImagesList()->GetGbrImage( i ) == nullptr )
127  continue;
128 
129  if( !GetImagesList()->GetGbrImage( i )->m_InUse )
130  continue;
131 
132  auto* drill_file = dynamic_cast<EXCELLON_IMAGE*>( GetImagesList()->GetGbrImage( i ) );
133 
134  if( drill_file )
135  fileType.push_back( 1 );
136  else
137  fileType.push_back( 0 );
138 
139  listOfGerberFiles.Add( GetImagesList()->GetGbrImage( i )->m_FileName );
140  }
141 
142  // Clear all layers
143  Clear_DrawLayers( false );
144  Zoom_Automatique( false );
145  m_canvas->Refresh();
146  ClearMsgPanel();
147 
148  // Load the layers from stored paths
149  wxBusyCursor wait;
150  loadListOfGerberAndDrillFiles( wxEmptyString, listOfGerberFiles, &fileType );
151  }
152  break;
153 
155  LoadExcellonFiles( wxEmptyString );
156  m_canvas->Refresh();
157  break;
158 
160  LoadZipArchiveFile( wxEmptyString );
161  m_canvas->Refresh();
162  break;
163 
165  LoadGerberJobFile( wxEmptyString );
166  m_canvas->Refresh();
167  break;
168 
169  default:
170  wxFAIL_MSG( "File_io: unexpected command id" );
171  break;
172  }
173 }
174 
175 
176 bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
177 {
178  static int lastGerberFileWildcard = 0;
179  wxString filetypes;
180  wxArrayString filenamesList;
181  wxFileName filename = aFullFileName;
182  wxString currentPath;
183 
184  if( !filename.IsOk() )
185  {
186  /* Standard gerber filetypes
187  * (See http://en.wikipedia.org/wiki/Gerber_File)
188  * the .gbr (.pho in legacy files) extension is the default used in Pcbnew
189  * However there are a lot of other extensions used for gerber files
190  * Because the first letter is usually g, we accept g* as extension
191  * (Mainly internal copper layers do not have specific extension,
192  * and filenames are like *.g1, *.g2 *.gb1 ...).
193  * Now (2014) Ucamco (the company which manages the Gerber format) encourages
194  * use of .gbr only and the Gerber X2 file format.
195  */
196  filetypes = _( "Gerber files (.g* .lgr .pho)" );
197  filetypes << wxT("|");
198  filetypes += wxT("*.g*;*.G*;*.pho;*.PHO" );
199  filetypes << wxT("|");
200 
201  /* Special gerber filetypes */
202  filetypes += _( "Top layer (*.GTL)|*.GTL;*.gtl|" );
203  filetypes += _( "Bottom layer (*.GBL)|*.GBL;*.gbl|" );
204  filetypes += _( "Bottom solder resist (*.GBS)|*.GBS;*.gbs|" );
205  filetypes += _( "Top solder resist (*.GTS)|*.GTS;*.gts|" );
206  filetypes += _( "Bottom overlay (*.GBO)|*.GBO;*.gbo|" );
207  filetypes += _( "Top overlay (*.GTO)|*.GTO;*.gto|" );
208  filetypes += _( "Bottom paste (*.GBP)|*.GBP;*.gbp|" );
209  filetypes += _( "Top paste (*.GTP)|*.GTP;*.gtp|" );
210  filetypes += _( "Keep-out layer (*.GKO)|*.GKO;*.gko|" );
211  filetypes += _( "Mechanical layers (*.GMx)|*.GM1;*.gm1;*.GM2;*.gm2;*.GM3;*.gm3|" );
212  filetypes += _( "Top Pad Master (*.GPT)|*.GPT;*.gpt|" );
213  filetypes += _( "Bottom Pad Master (*.GPB)|*.GPB;*.gpb|" );
214 
215  // All filetypes
216  filetypes += AllFilesWildcard();
217 
218  // Use the current working directory if the file name path does not exist.
219  if( filename.DirExists() )
220  currentPath = filename.GetPath();
221  else
222  {
223  currentPath = m_mruPath;
224 
225  // On wxWidgets 3.1 (bug?) the path in wxFileDialog is ignored when
226  // finishing by the dir separator. Remove it if any:
227  if( currentPath.EndsWith( '\\' ) || currentPath.EndsWith( '/' ) )
228  currentPath.RemoveLast();
229  }
230 
231  wxFileDialog dlg( this, _( "Open Gerber File(s)" ),
232  currentPath,
233  filename.GetFullName(),
234  filetypes,
235  wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR );
236  dlg.SetFilterIndex( lastGerberFileWildcard );
237 
238  if( dlg.ShowModal() == wxID_CANCEL )
239  return false;
240 
241  lastGerberFileWildcard = dlg.GetFilterIndex();
242  dlg.GetPaths( filenamesList );
243  m_mruPath = currentPath = dlg.GetDirectory();
244  }
245  else
246  {
247  filenamesList.Add( aFullFileName );
248  m_mruPath = currentPath = filename.GetPath();
249  }
250 
251  Erase_Current_DrawLayer( false );
252 
253  // Set the busy cursor
254  wxBusyCursor wait;
255 
256  return loadListOfGerberAndDrillFiles( currentPath, filenamesList );
257 }
258 
259 
261  const wxArrayString& aFilenameList,
262  const std::vector<int>* aFileType )
263 {
264  wxFileName filename;
265 
266  // Read gerber files: each file is loaded on a new GerbView layer
267  bool success = true;
268  int layer = GetActiveLayer();
269  LSET visibility = GetVisibleLayers();
270 
271  // Manage errors when loading files
272  wxString msg;
273  WX_STRING_REPORTER reporter( &msg );
274 
275  // Show progress dialog after 1 second of loading
276  static const long long progressShowDelay = 1000;
277 
278  auto startTime = wxGetUTCTimeMillis();
279  std::unique_ptr<WX_PROGRESS_REPORTER> progress = nullptr;
280 
281  for( unsigned ii = 0; ii < aFilenameList.GetCount(); ii++ )
282  {
283  filename = aFilenameList[ii];
284 
285  if( !filename.IsAbsolute() )
286  filename.SetPath( aPath );
287 
288  // Check for non existing files, to avoid creating broken or useless data
289  // and report all in one error list:
290  if( !filename.FileExists() )
291  {
292  wxString warning;
293  warning << "<b>" << _( "File not found:" ) << "</b><br>"
294  << filename.GetFullPath() << "<br>";
295  reporter.Report( warning, REPORTER::RPT_WARNING );
296  success = false;
297  continue;
298  }
299 
300  if( !progress && wxGetUTCTimeMillis() - startTime > progressShowDelay )
301  {
302  progress = std::make_unique<WX_PROGRESS_REPORTER>( this,
303  _( "Loading Gerber files..." ), 1, false );
304  progress->SetMaxProgress( aFilenameList.GetCount() - 1 );
305  progress->Report( _("Loading Gerber files..." ) );
306  }
307  else if( progress )
308  {
309  progress->KeepRefreshing();
310  }
311 
312  m_lastFileName = filename.GetFullPath();
313 
314  SetActiveLayer( layer, false );
315 
316  visibility[ layer ] = true;
317 
318  if( aFileType && (*aFileType)[ii] == 1 )
319  {
320  LoadExcellonFiles( filename.GetFullPath() );
321  layer = GetActiveLayer(); // Loading NC drill file changes the active layer
322  }
323  else
324  {
325  if( Read_GERBER_File( filename.GetFullPath() ) )
326  {
328 
329  layer = getNextAvailableLayer( layer );
330 
331  if( layer == NO_AVAILABLE_LAYERS && ii < aFilenameList.GetCount()-1 )
332  {
333  success = false;
335 
336  // Report the name of not loaded files:
337  ii += 1;
338  while( ii < aFilenameList.GetCount() )
339  {
340  filename = aFilenameList[ii++];
341  wxString txt = wxString::Format( MSG_NOT_LOADED, filename.GetFullName() );
342  reporter.Report( txt, REPORTER::RPT_ERROR );
343  }
344  break;
345  }
346 
347  SetActiveLayer( layer, false );
348  }
349  }
350 
351  if( progress )
352  progress->AdvanceProgress();
353  }
354 
355  if( !success )
356  {
357  wxSafeYield(); // Allows slice of time to redraw the screen
358  // to refresh widgets, before displaying messages
359  HTML_MESSAGE_BOX mbox( this, _( "Errors" ) );
360  mbox.ListSet( msg );
361  mbox.ShowModal();
362  }
363 
364  SetVisibleLayers( visibility );
365 
366  Zoom_Automatique( false );
367 
368  // Synchronize layers tools with actual active layer:
370 
371  // TODO: it would be nice if we could set the active layer to one of the
372  // ones that was just loaded, but to maintain the previous user experience
373  // we need to set it to a blank layer in case they load another file.
374  // We can't start with the next available layer when loading files because
375  // some users expect the behavior of overwriting the active layer on load.
376  SetActiveLayer( getNextAvailableLayer( layer ), true );
377 
379  syncLayerBox( true );
380 
381  GetGalCanvas()->Refresh();
382 
383  return success;
384 }
385 
386 
387 bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName )
388 {
389  wxString filetypes;
390  wxArrayString filenamesList;
391  wxFileName filename = aFullFileName;
392  wxString currentPath;
393 
394  if( !filename.IsOk() )
395  {
396  filetypes = DrillFileWildcard();
397  filetypes << wxT( "|" );
398 
399  /* All filetypes */
400  filetypes += AllFilesWildcard();
401 
402  /* Use the current working directory if the file name path does not exist. */
403  if( filename.DirExists() )
404  currentPath = filename.GetPath();
405  else
406  currentPath = m_mruPath;
407 
408  wxFileDialog dlg( this, _( "Open NC (Excellon) Drill File(s)" ),
409  currentPath, filename.GetFullName(), filetypes,
410  wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR );
411 
412  if( dlg.ShowModal() == wxID_CANCEL )
413  return false;
414 
415  dlg.GetPaths( filenamesList );
416  currentPath = wxGetCwd();
417  m_mruPath = currentPath;
418  }
419  else
420  {
421  filenamesList.Add( aFullFileName );
422  currentPath = filename.GetPath();
423  m_mruPath = currentPath;
424  }
425 
426  // Read Excellon drill files: each file is loaded on a new GerbView layer
427  bool success = true;
428  int layer = GetActiveLayer();
429 
430  // Manage errors when loading files
431  wxString msg;
432  WX_STRING_REPORTER reporter( &msg );
433 
434  for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ )
435  {
436  filename = filenamesList[ii];
437 
438  if( !filename.IsAbsolute() )
439  filename.SetPath( currentPath );
440 
441  m_lastFileName = filename.GetFullPath();
442 
443  SetActiveLayer( layer, false );
444 
445  if( Read_EXCELLON_File( filename.GetFullPath() ) )
446  {
447  // Update the list of recent drill files.
448  UpdateFileHistory( filename.GetFullPath(), &m_drillFileHistory );
449 
450  layer = getNextAvailableLayer( layer );
451 
452  if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 )
453  {
454  success = false;
456 
457  // Report the name of not loaded files:
458  ii += 1;
459  while( ii < filenamesList.GetCount() )
460  {
461  filename = filenamesList[ii++];
462  wxString txt = wxString::Format( MSG_NOT_LOADED, filename.GetFullName() );
463  reporter.Report( txt, REPORTER::RPT_ERROR );
464  }
465  break;
466  }
467 
468  SetActiveLayer( layer, false );
469  }
470  }
471 
472  if( !success )
473  {
474  HTML_MESSAGE_BOX mbox( this, _( "Errors" ) );
475  mbox.ListSet( msg );
476  mbox.ShowModal();
477  }
478 
479  Zoom_Automatique( false );
480 
481  // Synchronize layers tools with actual active layer:
485  syncLayerBox();
486 
487  return success;
488 }
489 
490 
491 bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aReporter )
492 {
493  wxString msg;
494 
495  // Extract the path of aFullFileName. We use it to store temporary files
496  wxFileName fn( aFullFileName );
497  wxString unzipDir = fn.GetPath();
498 
499  wxFFileInputStream zipFile( aFullFileName );
500 
501  if( !zipFile.IsOk() )
502  {
503  if( aReporter )
504  {
505  msg.Printf( _( "Zip file \"%s\" cannot be opened" ), GetChars( aFullFileName ) );
506  aReporter->Report( msg, REPORTER::RPT_ERROR );
507  }
508 
509  return false;
510  }
511 
512  // Update the list of recent zip files.
513  UpdateFileHistory( aFullFileName, &m_zipFileHistory );
514 
515  // The unzipped file in only a temporary file. Give it a filename
516  // which cannot conflict with an usual filename.
517  // TODO: make Read_GERBER_File() and Read_EXCELLON_File() able to
518  // accept a stream, and avoid using a temp file.
519  wxFileName temp_fn( "$tempfile.tmp" );
520  temp_fn.MakeAbsolute( unzipDir );
521  wxString unzipped_tempfile = temp_fn.GetFullPath();
522 
523 
524  bool success = true;
525  wxZipInputStream zipArchive( zipFile );
526  wxZipEntry* entry;
527  bool reported_no_more_layer = false;
528 
529  while( ( entry = zipArchive.GetNextEntry() ) )
530  {
531  wxString fname = entry->GetName();
532  wxFileName uzfn = fname;
533  wxString curr_ext = uzfn.GetExt().Lower();
534 
535  // The archive contains Gerber and/or Excellon drill files. Use the right loader.
536  // However it can contain a few other files (reports, pdf files...),
537  // which will be skipped.
538  // Gerber files ext is usually "gbr", but can be also another value, starting by "g"
539  // old gerber files ext from kicad is .pho
540  // drill files do not have a well defined ext
541  // It is .drl in kicad, but .txt in Altium for instance
542  // Allows only .drl for drill files.
543  if( curr_ext[0] != 'g' && curr_ext != "pho" && curr_ext != "drl" )
544  {
545  if( aReporter )
546  {
547  msg.Printf( _( "Info: skip file <i>\"%s\"</i> (unknown type)\n" ),
548  GetChars( entry->GetName() ) );
549  aReporter->Report( msg, REPORTER::RPT_WARNING );
550  }
551 
552  continue;
553  }
554 
555  int layer = GetActiveLayer();
556 
557  if( layer == NO_AVAILABLE_LAYERS )
558  {
559  success = false;
560 
561  if( aReporter )
562  {
563  if( !reported_no_more_layer )
565 
566  reported_no_more_layer = true;
567 
568  // Report the name of not loaded files:
569  msg.Printf( MSG_NOT_LOADED, GetChars( entry->GetName() ) );
570  aReporter->Report( msg, REPORTER::RPT_ERROR );
571  }
572 
573  delete entry;
574  continue;
575  }
576 
577  // Create the unzipped temporary file:
578  {
579  wxFFileOutputStream temporary_ofile( unzipped_tempfile );
580 
581  if( temporary_ofile.Ok() )
582  temporary_ofile.Write( zipArchive );
583  else
584  {
585  success = false;
586 
587  if( aReporter )
588  {
589  msg.Printf( _( "<b>Unable to create temporary file \"%s\"</b>\n"),
590  GetChars( unzipped_tempfile ) );
591  aReporter->Report( msg, REPORTER::RPT_ERROR );
592  }
593  }
594  }
595 
596  bool read_ok = true;
597 
598  if( curr_ext[0] == 'g' || curr_ext == "pho" )
599  {
600  // Read gerber files: each file is loaded on a new GerbView layer
601  read_ok = Read_GERBER_File( unzipped_tempfile );
602  }
603  else // if( curr_ext == "drl" )
604  {
605  read_ok = Read_EXCELLON_File( unzipped_tempfile );
606  }
607 
608  delete entry;
609 
610  // The unzipped file is only a temporary file, delete it.
611  wxRemoveFile( unzipped_tempfile );
612 
613  if( !read_ok )
614  {
615  success = false;
616 
617  if( aReporter )
618  {
619  msg.Printf( _("<b>unzipped file %s read error</b>\n"),
620  GetChars( unzipped_tempfile ) );
621  aReporter->Report( msg, REPORTER::RPT_ERROR );
622  }
623  }
624  else
625  {
626  GERBER_FILE_IMAGE* gerber_image = GetGbrImage( layer );
627 
628  if( gerber_image )
629  gerber_image->m_FileName = fname;
630 
631  layer = getNextAvailableLayer( layer );
632  SetActiveLayer( layer, false );
633  }
634  }
635 
636  return success;
637 }
638 
639 
640 bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName )
641 {
642 #define ZipFileExtension "zip"
643 
644  wxFileName filename = aFullFileName;
645  wxString currentPath;
646 
647  if( !filename.IsOk() )
648  {
649  // Use the current working directory if the file name path does not exist.
650  if( filename.DirExists() )
651  currentPath = filename.GetPath();
652  else
653  currentPath = m_mruPath;
654 
655  wxFileDialog dlg( this,
656  _( "Open Zip File" ),
657  currentPath,
658  filename.GetFullName(),
659  ZipFileWildcard(),
660  wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
661 
662  if( dlg.ShowModal() == wxID_CANCEL )
663  return false;
664 
665  filename = dlg.GetPath();
666  currentPath = wxGetCwd();
667  m_mruPath = currentPath;
668  }
669  else
670  {
671  currentPath = filename.GetPath();
672  m_mruPath = currentPath;
673  }
674 
675  wxString msg;
676  WX_STRING_REPORTER reporter( &msg );
677 
678  if( filename.IsOk() )
679  unarchiveFiles( filename.GetFullPath(), &reporter );
680 
681  Zoom_Automatique( false );
682 
683  // Synchronize layers tools with actual active layer:
687  syncLayerBox();
688 
689  if( !msg.IsEmpty() )
690  {
691  wxSafeYield(); // Allows slice of time to redraw the screen
692  // to refresh widgets, before displaying messages
693  HTML_MESSAGE_BOX mbox( this, _( "Messages" ) );
694  mbox.ListSet( msg );
695  mbox.ShowModal();
696  }
697 
698  return true;
699 }
wxString m_lastFileName
bool Clear_DrawLayers(bool query)
wxString m_mruPath
Most recently used path.
void Files_io(wxCommandEvent &event)
void syncLayerBox(bool aRebuildLayerBox=false)
Function syncLayerBox updates the currently "selected" layer within m_SelLayerBox The currently activ...
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
FILE_HISTORY m_jobFileHistory
GERBER_LAYER_WIDGET * m_LayersManager
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:931
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...
bool loadListOfGerberAndDrillFiles(const wxString &aPath, const wxArrayString &aFilenameList, const std::vector< int > *aFileType=nullptr)
Loads a list of Gerber and NC drill files and updates the view based on them.
wxString ZipFileWildcard()
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.
wxString AllFilesWildcard()
void UpdateFileHistory(const wxString &FullFileName, wxFileHistory *aFileHistory=NULL)
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.
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.
Class LSET is a set of PCB_LAYER_IDs.
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.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
#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.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx) const
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 ...
Definition of file extensions used in Kicad.
Class HTML_MESSAGE_BOX.
FILE_HISTORY m_drillFileHistory
virtual void ClearMsgPanel()
Clear all messages from the message panel.
#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...
Class WX_STRING_REPORTER is a wrapper for reporting to a wxString object.
Definition: reporter.h:165
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:128
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:100
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
size_t i
Definition: json11.cpp:597
wxString GetFileFromHistory(int cmdId, const wxString &type, wxFileHistory *aFileHistory=NULL)
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...
void SetVisibleLayers(LSET aLayerMask)
Function SetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL)
int getNextAvailableLayer(int aLayer=0) const
Function getNextAvailableLayer finds the next empty layer starting at aLayer and returns it to the ca...
GERBER_FILE_IMAGE_LIST * GetImagesList() const
Accessors to GERBER_FILE_IMAGE_LIST and GERBER_FILE_IMAGE data.
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)