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