KiCad PCB EDA Suite
pcbnew/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) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2016-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <fctsys.h>
27 #include <confirm.h>
28 #include <kicad_string.h>
29 #include <gestfich.h>
30 #include <pcb_edit_frame.h>
31 #include <macros.h>
33 #include <richio.h>
34 #include <pgm_base.h>
35 #include <msgpanel.h>
36 #include <fp_lib_table.h>
37 #include <kiway.h>
38 #include <kiway_player.h>
39 #include <trace_helpers.h>
40 #include <lockfile.cpp>
42 #include <pcbnew.h>
43 #include <pcbnew_id.h>
44 #include <io_mgr.h>
46 #include <tool/tool_manager.h>
47 #include <drc/drc.h>
48 #include <class_board.h>
49 #include <wx/stdpaths.h>
50 #include <pcb_layer_widget.h>
51 #include <ratsnest/ratsnest_data.h>
52 
53 #include <wx/wupdlock.h>
55 #include <project/project_file.h>
57 
58 
59 //#define USE_INSTRUMENTATION 1
60 #define USE_INSTRUMENTATION 0
61 
62 
75 bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bool aKicadFilesOnly )
76 {
77  // This is a subset of all PLUGINs which are trusted to be able to
78  // load a BOARD. User may occasionally use the wrong plugin to load a
79  // *.brd file (since both legacy and eagle use *.brd extension),
80  // but eventually *.kicad_pcb will be more common than legacy *.brd files.
81 
82  // clang-format off
83  static const struct
84  {
85  const wxString& filter;
86  IO_MGR::PCB_FILE_T pluginType;
87  } loaders[] =
88  {
89  { PcbFileWildcard(), IO_MGR::KICAD_SEXP }, // Current Kicad board files
90  { LegacyPcbFileWildcard(), IO_MGR::LEGACY }, // Old Kicad board files
91  { EaglePcbFileWildcard(), IO_MGR::EAGLE }, // Import Eagle board files
92  { PCadPcbFileWildcard(), IO_MGR::PCAD }, // Import PCAD board files
93  { AltiumDesignerPcbFileWildcard(), IO_MGR::ALTIUM_DESIGNER }, // Import Altium Designer board files
94  { AltiumCircuitStudioPcbFileWildcard(), IO_MGR::ALTIUM_CIRCUIT_STUDIO }, // Import Altium Circuit Studio board files
95  { AltiumCircuitMakerPcbFileWildcard(), IO_MGR::ALTIUM_CIRCUIT_MAKER }, // Import Altium Circuit Maker board files
96  };
97  // clang-format on
98 
99  wxFileName fileName( *aFileName );
100  wxString fileFilters;
101 
102  if( aKicadFilesOnly )
103  {
104  for( unsigned ii = 0; ii < 2; ++ii )
105  {
106  if( !fileFilters.IsEmpty() )
107  fileFilters += wxChar( '|' );
108 
109  fileFilters += wxGetTranslation( loaders[ii].filter );
110  }
111  }
112  else
113  {
114  for( unsigned ii = 2; ii < arrayDim( loaders ); ++ii )
115  {
116  if( !fileFilters.IsEmpty() )
117  fileFilters += wxChar( '|' );
118 
119  fileFilters += wxGetTranslation( loaders[ii].filter );
120  }
121  }
122 
123  wxString path;
124  wxString name;
125 
126  if( fileName.FileExists() )
127  {
128  path = fileName.GetPath();
129  name = fileName.GetFullName();
130  }
131  else
132  {
133  path = wxStandardPaths::Get().GetDocumentsDir();
134  // leave name empty
135  }
136 
137  wxFileDialog dlg( aParent,
138  aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
139  path, name, fileFilters,
140  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
141 
142  if( dlg.ShowModal() == wxID_OK )
143  {
144  // For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin.
145  // It's the only special case because of the duplicate use of the *.brd file extension.
146  // Other cases are clear because of unique file extensions.
147  *aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD;
148  *aFileName = dlg.GetPath();
149  return true;
150  }
151  else
152  return false;
153 }
154 
155 
166 bool AskSaveBoardFileName( wxWindow* aParent, wxString* aFileName )
167 {
168  wxString wildcard = PcbFileWildcard();
169  wxFileName fn = *aFileName;
170 
171  fn.SetExt( KiCadPcbFileExtension );
172 
173  wxFileDialog dlg( aParent,
174  _( "Save Board File As" ),
175  fn.GetPath(),
176  fn.GetFullName(),
177  wildcard,
178  wxFD_SAVE | wxFD_OVERWRITE_PROMPT
179  );
180 
181  if( dlg.ShowModal() != wxID_OK )
182  return false;
183 
184  fn = dlg.GetPath();
185 
186  // always enforce filename extension, user may not have entered it.
187  fn.SetExt( KiCadPcbFileExtension );
188 
189  *aFileName = fn.GetFullPath();
190 
191  return true;
192 }
193 
194 
195 void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
196 {
197  wxString fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
198 
199  if( !!fn )
200  {
201  int open_ctl = 0;
202 
203  if( !wxFileName::IsFileReadable( fn ) )
204  {
205  if( !AskLoadBoardFileName( this, &open_ctl, &fn, true ) )
206  return;
207  }
208 
209  OpenProjectFiles( std::vector<wxString>( 1, fn ), open_ctl );
210  }
211 }
212 
213 
214 void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
215 {
217 }
218 
219 
220 void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
221 {
222  int id = event.GetId();
223  Files_io_from_id( id );
224 }
225 
226 
228 {
229  wxString msg;
230 
231  switch( id )
232  {
233  case ID_LOAD_FILE:
234  {
235  int open_ctl = 0;
236  wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
237 
238  return AskLoadBoardFileName( this, &open_ctl, &fileName, true )
239  && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
240  }
241 
243  {
244  int open_ctl = 1;
245  wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
246 
247  return AskLoadBoardFileName( this, &open_ctl, &fileName, false )
248  && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
249  }
250 
252  {
253  wxFileName currfn = Prj().AbsolutePath( GetBoard()->GetFileName() );
254  wxFileName fn = currfn;
255 
256  wxString rec_name = GetAutoSaveFilePrefix() + fn.GetName();
257  fn.SetName( rec_name );
258 
259  if( !fn.FileExists() )
260  {
261  msg.Printf( _( "Recovery file \"%s\" not found." ), fn.GetFullPath() );
262  DisplayInfoMessage( this, msg );
263  return false;
264  }
265 
266  msg.Printf( _( "OK to load recovery file \"%s\"" ), fn.GetFullPath() );
267 
268  if( !IsOK( this, msg ) )
269  return false;
270 
271  GetScreen()->ClrModify(); // do not prompt the user for changes
272 
273  if( OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) ) )
274  {
275  // Re-set the name since name or extension was changed
276  GetBoard()->SetFileName( currfn.GetFullPath() );
277  UpdateTitle();
278  return true;
279  }
280  return false;
281  }
282 
283  case ID_NEW_BOARD:
284  {
285  if( IsContentModified() )
286  {
287  wxFileName fileName = GetBoard()->GetFileName();
288  wxString saveMsg =
289  _( "Current board will be closed, save changes to \"%s\" before continuing?" );
290 
291  if( !HandleUnsavedChanges( this, wxString::Format( saveMsg, fileName.GetFullName() ),
292  [&]()->bool { return Files_io_from_id( ID_SAVE_BOARD ); } ) )
293  return false;
294  }
295  else if( !GetBoard()->IsEmpty() )
296  {
297  if( !IsOK( this, _( "Current Board will be closed. Continue?" ) ) )
298  return false;
299  }
300 
302 
303  mgr->SaveProject( mgr->Prj().GetProjectFullName() );
304  mgr->UnloadProject( &mgr->Prj() );
305 
306  GetBoard()->ClearProject();
307 
308  wxFileName fn( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
310 
311  mgr->LoadProject( fn.GetFullPath() );
312 
314 
315  if( !Clear_Pcb( false ) )
316  return false;
317 
318  onBoardLoaded();
319 
320  OnModify();
321  return true;
322  }
323 
324  case ID_SAVE_BOARD:
325  if( !GetBoard()->GetFileName().IsEmpty() )
326  return SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
327 
329 
330  case ID_COPY_BOARD_AS:
331  case ID_SAVE_BOARD_AS:
332  {
333  wxString orig_name;
334  wxFileName::SplitPath( GetBoard()->GetFileName(),
335  nullptr, nullptr, &orig_name, nullptr );
336 
337  if( orig_name.IsEmpty() )
338  orig_name = _( "noname" );
339 
340  wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() );
341  wxFileName fn( pro_dir, orig_name, KiCadPcbFileExtension );
342  wxString filename = fn.GetFullPath();
343 
344  if( AskSaveBoardFileName( this, &filename ) )
345  {
346  if( id == ID_COPY_BOARD_AS )
347  return SavePcbCopy( filename );
348  else
349  return SavePcbFile( filename, false );
350  }
351  return false;
352  }
353 
354  default:
355  wxLogDebug( wxT( "File_io Internal Error" ) );
356  return false;
357  }
358 }
359 
360 
361 // The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
362 // determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
363 // bit flag.
364 IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
365 {
366  IO_MGR::PCB_FILE_T pluginType;
367 
368  wxFileName fn = aFileName;
369 
370  // Note: file extensions are expected to be in lower case.
371  // This is not always true, especially when importing files, so the string
372  // comparisons are case insensitive to try to find the suitable plugin.
373 
374  if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) ) == 0 )
375  {
376  // both legacy and eagle share a common file extension.
377  pluginType = ( aCtl & KICTL_EAGLE_BRD ) ? IO_MGR::EAGLE : IO_MGR::LEGACY;
378  }
379  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::PCAD ) ) == 0 )
380  {
381  pluginType = IO_MGR::PCAD;
382  }
383  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_DESIGNER ) ) == 0 )
384  {
385  pluginType = IO_MGR::ALTIUM_DESIGNER;
386  }
387  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_STUDIO ) ) == 0 )
388  {
389  pluginType = IO_MGR::ALTIUM_CIRCUIT_STUDIO;
390  }
391  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_MAKER ) ) == 0 )
392  {
393  pluginType = IO_MGR::ALTIUM_CIRCUIT_MAKER;
394  }
395  else
396  {
397  pluginType = IO_MGR::KICAD_SEXP;
398  }
399 
400  return pluginType;
401 }
402 
403 
405 {
406  PCB_LAYER_COLLECTOR collector;
407 
408  collector.SetLayerId( Edge_Cuts );
409  collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
410 
411  int edgeWidth = -1;
412  bool mixed = false;
413 
414  for( int i = 0; i < collector.GetCount(); i++ )
415  {
416  if( collector[i]->Type() == PCB_LINE_T )
417  {
418  int itemWidth = static_cast<DRAWSEGMENT*>( collector[i] )->GetWidth();
419 
420  if( edgeWidth != -1 && edgeWidth != itemWidth )
421  {
422  mixed = true;
423  edgeWidth = std::max( edgeWidth, itemWidth );
424  }
425  else
426  {
427  edgeWidth = itemWidth;
428  }
429  }
430  }
431 
432  if( mixed )
433  {
434  // If they had different widths then we can't ensure that fills will be the same.
435  wxMessageBox( _( "If the zones on this board are refilled the Copper Edge Clearance\n"
436  "setting will be used (see Board Setup > Design Rules). This may\n"
437  "result in different fills from previous Kicad versions which used\n"
438  "the line thickness of the board boundary on the Edge Cuts layer." ),
439  _( "Edge Clearance Warning" ), wxOK|wxICON_WARNING, this );
440  }
441 
442  return std::max( 0, edgeWidth / 2 );
443 }
444 
445 
446 bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
447 {
448  // This is for python:
449  if( aFileSet.size() != 1 )
450  {
451  UTF8 msg = StrPrintf( "Pcbnew:%s() takes only a single filename", __func__ );
452  DisplayError( this, msg );
453  return false;
454  }
455 
456  wxString fullFileName( aFileSet[0] );
457 
458  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
459  wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "Path is not absolute!" ) );
460 
461  std::unique_ptr<wxSingleInstanceChecker> lockFile = ::LockFile( fullFileName );
462 
463  if( !lockFile )
464  {
465  wxString msg = wxString::Format( _( "PCB file \"%s\" is already open." ), fullFileName );
466  DisplayError( this, msg );
467  return false;
468  }
469 
470  if( IsContentModified() )
471  {
472  if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
473  [&]()->bool { return SavePcbFile( GetBoard()->GetFileName() ); } ) )
474  {
475  return false;
476  }
477  }
478 
479  // Release the lock file, until the new file is actually loaded
480  ReleaseFile();
481 
482  wxFileName pro = fullFileName;
483  pro.SetExt( ProjectFileExtension );
484 
485  bool is_new = !wxFileName::IsFileReadable( fullFileName );
486 
487  // If its a non-existent schematic and caller thinks it exists
488  if( is_new && !( aCtl & KICTL_CREATE ) )
489  {
490  // notify user that fullFileName does not exist, ask if user wants to create it.
491  wxString ask = wxString::Format( _( "PCB \"%s\" does not exist. Do you wish to create it?" ),
492  fullFileName );
493  if( !IsOK( this, ask ) )
494  return false;
495  }
496 
497  wxWindowUpdateLocker no_update( m_Layers ); // Avoid flicker when rebuilding m_Layers
498 
499  // Unlink the old project if needed
500  GetBoard()->ClearProject();
501 
502  // No save prompt (we already prompted above), and only reset to a new blank board if new
503  Clear_Pcb( false, !is_new );
504 
505  IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
506 
507  bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
508 
509  if( !converted )
510  {
511  // Loading a project should only be done under carefully considered circumstances.
512 
513  // The calling code should know not to ask me here to change projects unless
514  // it knows what consequences that will have on other KIFACEs running and using
515  // this same PROJECT. It can be very harmful if that calling code is stupid.
517 
518  if( pro.GetFullPath() != mgr->Prj().GetProjectFullName() )
519  {
520  mgr->SaveProject( mgr->Prj().GetProjectFullName() );
521  mgr->UnloadProject( &mgr->Prj() );
522 
523  mgr->LoadProject( pro.GetFullPath() );
524  }
525 
526  // load project settings before BOARD
528  }
529 
530  if( is_new )
531  {
532  OnModify();
533  }
534  else
535  {
536  BOARD* loadedBoard = 0; // it will be set to non-NULL if loaded OK
537 
538  PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
539 
540  // This will rename the file if there is an autosave and the user want to recover
541  CheckForAutoSaveFile( fullFileName );
542 
543  try
544  {
545  PROPERTIES props;
546  char xbuf[30];
547  char ybuf[30];
548 
549  // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
550  sprintf( xbuf, "%d", GetPageSizeIU().x );
551  sprintf( ybuf, "%d", GetPageSizeIU().y );
552 
553  props["page_width"] = xbuf;
554  props["page_height"] = ybuf;
555 
556 #if USE_INSTRUMENTATION
557  // measure the time to load a BOARD.
558  unsigned startTime = GetRunningMicroSecs();
559 #endif
560 
561  loadedBoard = pi->Load( fullFileName, NULL, &props );
562 
563 #if USE_INSTRUMENTATION
564  unsigned stopTime = GetRunningMicroSecs();
565  printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
566 #endif
567  }
568  catch( const IO_ERROR& ioe )
569  {
570  if( ioe.Problem() != wxT( "CANCEL" ) )
571  {
572  wxString msg = wxString::Format( _( "Error loading board file:\n%s" ), fullFileName );
573  DisplayErrorMessage( this, msg, ioe.What() );
574  }
575 
576  // We didn't create a new blank board above, so do that now
577  Clear_Pcb( false );
578 
579  return false;
580  }
581 
582  SetBoard( loadedBoard );
583 
584  // On save; design settings will be removed from the board
585  if( loadedBoard->m_LegacyDesignSettingsLoaded )
586  loadedBoard->SetModified();
587 
588  // Move legacy view settings to local project settings
589  if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
590  {
592  loadedBoard->SetModified();
593  }
594 
595  if( !loadedBoard->m_LegacyVisibleItems.test( GAL_LAYER_INDEX( GAL_LAYER_ID_BITMASK_END ) ) )
596  {
598  loadedBoard->SetModified();
599  }
600 
601  // we should not ask PLUGINs to do these items:
602  loadedBoard->BuildListOfNets();
603  loadedBoard->SynchronizeNetsAndNetClasses();
605 
606  if( loadedBoard->IsModified() )
607  OnModify();
608  else
609  GetScreen()->ClrModify();
610 
611  if( pluginType == IO_MGR::LEGACY &&
612  loadedBoard->GetFileFormatVersionAtLoad() < LEGACY_BOARD_FILE_VERSION )
613  {
614  DisplayInfoMessage( this,
615  _( "This file was created by an older version of Pcbnew.\n"
616  "It will be stored in the new file format when you save this file again." ) );
617  }
618  }
619 
620  {
621  wxFileName fn = fullFileName;
622 
623  if( converted )
624  fn.SetExt( PcbFileExtension );
625 
626  wxString fname = fn.GetFullPath();
627 
628  fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
629 
630  GetBoard()->SetFileName( fname );
631  }
632 
633  // Lock the file newly opened:
634  m_file_checker.reset( lockFile.release() );
635 
636  if( !converted )
637  UpdateFileHistory( GetBoard()->GetFileName() );
638 
639  // Select netclass Default as current netclass (it always exists)
641 
642  // Rebuild list of nets (full ratsnest rebuild)
644  Compile_Ratsnest( true );
645 
646  onBoardLoaded();
647 
648  // Refresh the 3D view, if any
649  EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame();
650 
651  if( draw3DFrame )
652  draw3DFrame->NewDisplay();
653 
654 #if 0 && defined(DEBUG)
655  // Output the board object tree to stdout, but please run from command prompt:
656  GetBoard()->Show( 0, std::cout );
657 #endif
658 
659  // from EDA_APPL which was first loaded BOARD only:
660  {
661  /* For an obscure reason the focus is lost after loading a board file
662  * when starting up the process.
663  * (seems due to the recreation of the layer manager after loading the file)
664  * Give focus to main window and Drawpanel
665  * must be done for these 2 windows (for an obscure reason ...)
666  * Linux specific
667  * This is more a workaround than a fix.
668  */
669  SetFocus();
670  GetCanvas()->SetFocus();
671  }
672 
673  return true;
674 }
675 
676 
677 bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory )
678 {
679  // please, keep it simple. prompting goes elsewhere.
680 
681  wxFileName pcbFileName = aFileName;
682 
683  if( pcbFileName.GetExt() == LegacyPcbFileExtension )
684  pcbFileName.SetExt( KiCadPcbFileExtension );
685 
686  if( !IsWritable( pcbFileName ) )
687  {
688  wxString msg = wxString::Format( _(
689  "No access rights to write to file \"%s\"" ),
690  pcbFileName.GetFullPath() );
691 
692  DisplayError( this, msg );
693  return false;
694  }
695 
696  // TODO: this will break if we ever go multi-board
697  wxFileName projectFile( pcbFileName );
698  projectFile.SetExt( ProjectFileExtension );
699 
700  if( !projectFile.FileExists() )
701  {
702  // If this is a new board, project filename won't be set yet
703  if( projectFile.GetFullPath() != Prj().GetProjectFullName() )
704  {
705  GetBoard()->ClearProject();
706 
708 
709  mgr->SaveProject( Prj().GetProjectFullName() );
710  mgr->UnloadProject( &Prj() );
711 
712  mgr->LoadProject( projectFile.GetFullPath() );
713  GetBoard()->SetProject( &Prj() );
714  }
715  }
716 
717  wxFileName tempFile( aFileName );
718  tempFile.SetName( wxT( "." ) + tempFile.GetName() );
719  tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
720 
722 
723  // Select default Netclass before writing file. Useful to save default values in headers.
725 
726  // Save various DRC parameters, such as violation severities (which may have been
727  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
729 
731 
732  ClearMsgPanel();
733 
734  wxString upperTxt;
735  wxString lowerTxt;
736 
737  try
738  {
740 
741  wxASSERT( tempFile.IsAbsolute() );
742 
743  pi->Save( tempFile.GetFullPath(), GetBoard(), NULL );
744  }
745  catch( const IO_ERROR& ioe )
746  {
747  wxString msg = wxString::Format( _(
748  "Error saving board file \"%s\".\n%s" ),
749  pcbFileName.GetFullPath(), ioe.What()
750  );
751  DisplayError( this, msg );
752 
753  lowerTxt.Printf( _( "Failed to create temporary file \"%s\"" ), tempFile.GetFullPath() );
754 
755  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
756 
757  // In case we started a file but didn't fully write it, clean up
758  wxRemoveFile( tempFile.GetFullPath() );
759 
760  return false;
761  }
762 
763  // If save succeeded, replace the original with what we just wrote
764  if( !wxRenameFile( tempFile.GetFullPath(), pcbFileName.GetFullPath() ) )
765  {
766  wxString msg = wxString::Format( _(
767  "Error saving board file \"%s\".\nFailed to rename temporary file \"%s\"" ),
768  pcbFileName.GetFullPath(), tempFile.GetFullPath()
769  );
770  DisplayError( this, msg );
771 
772  lowerTxt.Printf( _( "Failed to rename temporary file \"%s\"" ), tempFile.GetFullPath() );
773 
774  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
775 
776  return false;
777  }
778 
779  GetBoard()->SetFileName( pcbFileName.GetFullPath() );
780  UpdateTitle();
781 
782  // Put the saved file in File History if requested
783  if( addToHistory )
784  UpdateFileHistory( GetBoard()->GetFileName() );
785 
786  // Delete auto save file on successful save.
787  wxFileName autoSaveFileName = pcbFileName;
788 
789  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + pcbFileName.GetName() );
790 
791  if( autoSaveFileName.FileExists() )
792  wxRemoveFile( autoSaveFileName.GetFullPath() );
793 
794 
795  lowerTxt.Printf( _( "Wrote board file: \"%s\"" ), pcbFileName.GetFullPath() );
796 
797  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
798 
799  GetScreen()->ClrModify();
800  GetScreen()->ClrSave();
801  return true;
802 }
803 
804 
805 bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName )
806 {
807  wxFileName pcbFileName = aFileName;
808 
809  // Ensure the file ext is the right ext:
810  pcbFileName.SetExt( KiCadPcbFileExtension );
811 
812  if( !IsWritable( pcbFileName ) )
813  {
814  wxString msg = wxString::Format( _(
815  "No access rights to write to file \"%s\"" ),
816  pcbFileName.GetFullPath() );
817 
818  DisplayError( this, msg );
819  return false;
820  }
821 
823 
824  // Select default Netclass before writing file.
825  // Useful to save default values in headers
827 
828  try
829  {
831 
832  wxASSERT( pcbFileName.IsAbsolute() );
833 
834  pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
835  }
836  catch( const IO_ERROR& ioe )
837  {
838  wxString msg = wxString::Format( _(
839  "Error saving board file \"%s\".\n%s" ),
840  pcbFileName.GetFullPath(), ioe.What()
841  );
842  DisplayError( this, msg );
843 
844  return false;
845  }
846 
847  DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n\"%s\"" ),
848  pcbFileName.GetFullPath() ) );
849 
850  return true;
851 }
852 
853 
855 {
856  wxFileName tmpFileName;
857 
858  if( GetBoard()->GetFileName().IsEmpty() )
859  {
860  tmpFileName = wxFileName( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
862  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
863  }
864  else
865  {
866  tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
867  }
868 
869  wxFileName autoSaveFileName = tmpFileName;
870 
871  // Auto save file name is the board file name prepended with autosaveFilePrefix string.
872  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + autoSaveFileName.GetName() );
873 
874  if( !autoSaveFileName.IsOk() )
875  return false;
876 
877  // If the board file path is not writable, try writing to a platform specific temp file
878  // path. If that path isn't writabe, give up.
879  if( !autoSaveFileName.IsDirWritable() )
880  {
881  autoSaveFileName.SetPath( wxFileName::GetTempDir() );
882 
883  if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
884  return false;
885  }
886 
887  wxLogTrace( traceAutoSave, "Creating auto save file <" + autoSaveFileName.GetFullPath() + ">" );
888 
889  if( SavePcbFile( autoSaveFileName.GetFullPath(), false ) )
890  {
891  GetScreen()->SetModify();
892  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
893  UpdateTitle();
894  m_autoSaveState = false;
895  return true;
896  }
897 
898  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
899 
900  return false;
901 }
902 
903 
904 bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
905 {
906  switch( (IO_MGR::PCB_FILE_T) aFileType )
907  {
908  case IO_MGR::EAGLE:
909  if( OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_EAGLE_BRD ) )
910  {
911  wxString projectpath = Kiway().Prj().GetProjectPath();
912  wxFileName newfilename;
913 
914  newfilename.SetPath( Prj().GetProjectPath() );
915  newfilename.SetName( Prj().GetProjectName() );
916  newfilename.SetExt( KiCadPcbFileExtension );
917 
918  GetBoard()->SetFileName( newfilename.GetFullPath() );
919  UpdateTitle();
920  OnModify();
921 
922  // Extract a footprint library from the design and add it to the fp-lib-table
923  wxString newLibPath;
924  ArchiveModulesOnBoard( true, newfilename.GetName(), &newLibPath );
925 
926  if( newLibPath.Length() > 0 )
927  {
928  FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
929  const wxString& project_env = PROJECT_VAR_NAME;
930  wxString rel_path, env_path;
931 
932  wxGetEnv( project_env, &env_path );
933 
934  wxString result( newLibPath );
935  rel_path = result.Replace( env_path,
936  wxString( "$(" + project_env + ")" ) ) ? result : "" ;
937 
938  if( !rel_path.IsEmpty() )
939  newLibPath = rel_path;
940 
941  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( newfilename.GetName(),
942  newLibPath, wxT( "KiCad" ), wxEmptyString );
943  prjlibtable->InsertRow( row );
944  }
945 
946  if( !GetBoard()->GetFileName().IsEmpty() )
947  {
948  wxString tblName = Prj().FootprintLibTblName();
949 
950  try
951  {
952  Prj().PcbFootprintLibs()->Save( tblName );
953  }
954  catch( const IO_ERROR& ioe )
955  {
956  wxString msg = wxString::Format( _(
957  "Error occurred saving project specific footprint library "
958  "table:\n\n%s" ), ioe.What() );
959  wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
960  }
961  }
962 
963 
964  // Update module LIB_IDs to point to the just imported Eagle library
965  for( MODULE* module : GetBoard()->Modules() )
966  {
967  LIB_ID libId = module->GetFPID();
968 
969  if( libId.GetLibItemName().empty() )
970  continue;
971 
972  libId.SetLibNickname( newfilename.GetName() );
973  module->SetFPID( libId );
974  }
975 
976 
977  // Store net names for all pads, to create net remap information
978  std::unordered_map<D_PAD*, wxString> netMap;
979 
980  for( const auto& pad : GetBoard()->GetPads() )
981  {
982  NETINFO_ITEM* netinfo = pad->GetNet();
983 
984  if( netinfo->GetNet() > 0 && !netinfo->GetNetname().IsEmpty() )
985  netMap[pad] = netinfo->GetNetname();
986  }
987 
988  // Two stage netlist update:
989  // - first, assign valid timestamps to footprints (no reannotation)
990  // - second, perform schematic annotation and update footprint references
991  // based on timestamps
992  NETLIST netlist;
994  DoUpdatePCBFromNetlist( netlist, false );
996  DoUpdatePCBFromNetlist( netlist, true );
997 
998  std::unordered_map<wxString, wxString> netRemap;
999 
1000  // Compare the old net names with the new net names and create a net map
1001  for( const auto& pad : GetBoard()->GetPads() )
1002  {
1003  auto it = netMap.find( pad );
1004 
1005  if( it == netMap.end() )
1006  continue;
1007 
1008  NETINFO_ITEM* netinfo = pad->GetNet();
1009 
1010  // Net name has changed, create a remap entry
1011  if( netinfo->GetNet() > 0 && netMap[pad] != netinfo->GetNetname() )
1012  netRemap[netMap[pad]] = netinfo->GetNetname();
1013  }
1014 
1015  if( !netRemap.empty() )
1016  fixEagleNets( netRemap );
1017 
1018  return true;
1019  }
1020 
1021  return false;
1022 
1023  default:
1024  return false;
1025  }
1026 
1027  return false;
1028 }
1029 
1030 
1031 bool PCB_EDIT_FRAME::fixEagleNets( const std::unordered_map<wxString, wxString>& aRemap )
1032 {
1033  bool result = true;
1034  BOARD* board = GetBoard();
1035 
1036  // perform netlist matching to prevent orphaned zones.
1037  for( auto zone : board->Zones() )
1038  {
1039  auto it = aRemap.find( zone->GetNet()->GetNetname() );
1040 
1041  if( it != aRemap.end() )
1042  {
1043  NETINFO_ITEM* net = board->FindNet( it->second );
1044 
1045  if( !net )
1046  {
1047  wxFAIL;
1048  result = false;
1049  continue;
1050  }
1051 
1052  zone->SetNet( net );
1053  }
1054  }
1055 
1056 
1057  // perform netlist matching to prevent orphaned tracks/vias.
1058  for( auto track : board->Tracks() )
1059  {
1060  auto it = aRemap.find( track->GetNet()->GetNetname() );
1061 
1062  if( it != aRemap.end() )
1063  {
1064  NETINFO_ITEM* net = board->FindNet( it->second );
1065 
1066  if( !net )
1067  {
1068  wxFAIL;
1069  result = false;
1070  continue;
1071  }
1072 
1073  track->SetNet( net );
1074  }
1075  }
1076 
1077  return result;
1078 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
void UpdateTitle()
Function UpdateTitle sets the main window title bar text.
UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to...
Definition: utf8.h:73
LSET m_VisibleLayers
Board settings.
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
void BuildListOfNets()
Definition: class_board.h:718
void SetModified()
Definition: base_struct.cpp:85
void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:201
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
#define WIN_STRING_DIR_SEP
Definition: gestfich.h:44
#define KI_FALLTHROUGH
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
wxString EaglePcbFileWildcard()
static const KICAD_T AllBoardItems[]
A scan list for all editable board items.
Definition: collectors.h:267
int StrPrintf(std::string *aResult, const char *aFormat,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: class_board.h:300
bool importFile(const wxString &aFileName, int aFileType)
Load the given filename but sets the path to the current project path.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:252
This file is part of the common library TODO brief description.
IO_MGR::PCB_FILE_T plugin_type(const wxString &aFileName, int aCtl)
SETTINGS_MANAGER * GetSettingsManager() const
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
bool IsModified() const
Definition: base_struct.h:198
FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:42
void Compile_Ratsnest(bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
This file is part of the common library.
const std::string ProjectFileExtension
const std::string LegacyPcbFileExtension
VTBL_ENTRY PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:135
bool SavePcbCopy(const wxString &aFileName)
Function SavePcbCopy writes the board data structures to a aFileName but unlike SavePcbFile,...
#define UNIX_STRING_DIR_SEP
Definition: gestfich.h:43
VTBL_ENTRY PROJECT & Prj() const
Function Prj returns the PROJECT associated with this KIWAY.
Definition: kiway.cpp:172
bool doAutoSave() override
Function doAutoSave performs auto save when the board has been modified and not saved within the auto...
#define KICTL_CREATE
caller thinks requested project files may not exist
Definition: kiway_player.h:79
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
Class that computes missing connections on a PCB.
void ResolveDRCExclusions()
Update markers to match recorded exclusions.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:38
bool LoadProjectSettings()
Load the current project's file configuration settings which are pertinent to this PCB_EDIT_FRAME ins...
void ReleaseFile()
Release the current file marked in use.
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Tests a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:601
bool SavePcbFile(const wxString &aFileName, bool addToHistory=true)
Function SavePcbFile writes the board data structures to a aFileName Creates backup when requested an...
#define KICTL_EAGLE_BRD
chosen *.brd file is Eagle according to user.
Definition: kiway_player.h:78
This is the end of the layers used for visibility bitmasks in Pcbnew There can be at most 32 layers a...
int inferLegacyEdgeClearance(BOARD *aBoard)
Use the existing edge_cut line thicknesses to infer the edge clearace.
wxString AltiumCircuitMakerPcbFileWildcard()
Collect all BOARD_ITEM objects on a given layer.
Definition: collectors.h:650
const std::string KiCadPcbFileExtension
bool IsWritable(const wxFileName &aFileName)
Checks if aFileName can be written.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
bool SetCurrentNetClass(const wxString &aNetClassName)
Function SetCurrentNetClass Must be called after a netclass selection (or after a netclass parameter ...
PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
const wxString & GetFileName() const
Definition: class_board.h:255
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:49
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:122
bool fixEagleNets(const std::unordered_map< wxString, wxString > &aRemap)
Rematch orphaned zones and vias to schematic nets.
std::unique_ptr< wxSingleInstanceChecker > m_file_checker
prevents opening same file multiple times.
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition: collectors.h:660
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:270
This file contains miscellaneous commonly used macros and functions.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetches the file name from the file history list.
RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destructor.
Definition: io_mgr.h:579
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:100
void SynchronizeNetsAndNetClasses()
Function SynchronizeNetsAndNetClasses copies NETCLASS info to each NET, based on NET membership in a ...
void OnClearFileHistory(wxCommandEvent &aEvent)
wxString LegacyPcbFileWildcard()
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
void CheckForAutoSaveFile(const wxFileName &aFileName)
Check if an auto save file exists for aFileName and takes the appropriate action depending on the use...
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:212
#define NULL
bool IsContentModified() override
Get if the current board has been modified but not saved.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Function OpenProjectFiles (was LoadOnePcbFile) loads a KiCad board (.kicad_pcb) from aFileName.
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:80
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
void onBoardLoaded()
Updates the state of the GUI after a new board is loaded or created.
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
bool AskLoadBoardFileName(wxWindow *aParent, int *aCtl, wxString *aFileName, bool aKicadFilesOnly)
Function AskLoadBoardFileName puts up a wxFileDialog asking for a BOARD filename to open.
void SaveProjectSettings() override
Function SaveProjectSettings saves changes to the project settings to the project (....
PCB_LAYER_WIDGET * m_Layers
Layer manager. It is the responsibility of the child frames to instantiate this.
Definition of file extensions used in Kicad.
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:231
Definition: color4d.h:58
wxLogTrace helper definitions.
virtual void SetFocus() override
#define PcbFileExtension
void BuildConnectivity()
Builds or rebuilds the board connectivity database for the board, especially the list of connected it...
void SetFileName(const wxString &aFileName)
Definition: class_board.h:253
VTBL_ENTRY const wxString GetProjectFullName() const
Function GetProjectFullName returns the full path and name of the project.
Definition: project.cpp:116
virtual void ClearMsgPanel()
Clear all messages from the message panel.
wxString AltiumDesignerPcbFileWildcard()
void ClearProject()
int GetFileFormatVersionAtLoad() const
Definition: class_board.h:320
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:284
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:193
void ClearFileHistory(FILE_HISTORY *aFileHistory=nullptr)
Removes all files from the file history.
static wxString GetAutoSaveFilePrefix()
wxString AltiumCircuitStudioPcbFileWildcard()
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
void SetProject(PROJECT *aProject)
Links a board to a given project.
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
void OnFileHistory(wxCommandEvent &event)
ZONE_CONTAINERS & Zones()
Definition: class_board.h:280
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:56
see class PGM_BASE
void SetBoard(BOARD *aBoard) override
Declaration of the eda_3d_viewer class.
const char * name
Definition: DXF_plotter.cpp:60
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
void DoUpdatePCBFromNetlist(NETLIST &aNetlist, bool aUseTimestamps)
Function DoUpdatePCBFromNetlist An automated version of UpdatePCBFromNetlist which skips the UI dialo...
void ArchiveModulesOnBoard(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=NULL)
Function ArchiveModulesOnBoard Save modules in a library:
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
void Files_io(wxCommandEvent &event)
Function Files_io.
#define _(s)
Definition: 3d_actions.cpp:33
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save,...
Definition: io_mgr.cpp:61
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
bool AskSaveBoardFileName(wxWindow *aParent, wxString *aFileName)
Function AskSaveBoardFileName puts up a wxFileDialog asking for a BOARD filename to save.
bool SaveProject(const wxString &aFullPath=wxEmptyString)
Saves a loaded project.
void ClrModify()
Definition: base_screen.h:184
wxString PcbFileWildcard()
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
const wxSize GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
bool Files_io_from_id(int aId)
Function Files_io_from_id Read and write board files.
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
Definition: eda_3d_viewer.h:65
BOARD * GetBoard() const
void SetModify()
Definition: base_screen.h:183
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
Message panel definition file.
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:54
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:267
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
wxString PCadPcbFileWildcard()
EDA_3D_VIEWER * Get3DViewerFrame()
bool Clear_Pcb(bool aQuery, bool aFinal=false)
Function Clear_Pcb delete all and reinitialize the current board.
Definition: initpcb.cpp:42
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:283
bool IsEmpty() const
Definition: class_board.h:311
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: class_board.h:296
void ClrSave()
Definition: base_screen.h:186
bool FetchNetlistFromSchematic(NETLIST &aNetlist, FETCH_NETLIST_MODE aMode)
TRACKS & Tracks()
Definition: class_board.h:257
VTBL_ENTRY const wxString FootprintLibTblName() const
Function FootprintLibTblName returns the path and filename of this project's fp-lib-table,...
Definition: project.cpp:140
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
bool empty() const
Definition: utf8.h:108
S-expression Pcbnew file format.
Definition: io_mgr.h:57
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:112
GAL_SET m_LegacyVisibleItems
Definition: class_board.h:297