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