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-2021 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 <confirm.h>
27 #include <core/arraydim.h>
28 #include <gestfich.h>
29 #include <pcb_edit_frame.h>
30 #include <board_design_settings.h>
32 #include <widgets/msgpanel.h>
33 #include <fp_lib_table.h>
34 #include <kiface_base.h>
35 #include <macros.h>
36 #include <trace_helpers.h>
37 #include <lockfile.cpp>
39 #include <pcbnew_id.h>
40 #include <io_mgr.h>
42 #include <tool/tool_manager.h>
43 #include <board.h>
44 #include <wx/checkbox.h>
45 #include <wx/stdpaths.h>
46 #include <ratsnest/ratsnest_data.h>
47 #include <kiplatform/app.h>
49 #include <widgets/infobar.h>
52 #include <paths.h>
53 #include <project/project_file.h>
55 #include <project/net_settings.h>
59 #include <tools/pcb_actions.h>
60 #include "footprint_info_impl.h"
61 #include <wx_filename.h> // For ::ResolvePossibleSymlinks()
62 
63 #include <wx/wupdlock.h>
64 #include <wx/filedlg.h>
65 
66 
67 
68 //#define USE_INSTRUMENTATION 1
69 #define USE_INSTRUMENTATION 0
70 
71 
81 bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, int* aCtl, wxString* aFileName,
82  bool aKicadFilesOnly )
83 {
84  // This is a subset of all PLUGINs which are trusted to be able to
85  // load a BOARD. User may occasionally use the wrong plugin to load a
86  // *.brd file (since both legacy and eagle use *.brd extension),
87  // but eventually *.kicad_pcb will be more common than legacy *.brd files.
88 
89  // clang-format off
90  static const struct
91  {
92  const wxString& filter;
93  IO_MGR::PCB_FILE_T pluginType;
94  } loaders[] =
95  {
96  // Current Kicad board files.
98 
99  // Old Kicad board files.
101 
102  // Import Altium Circuit Maker board files.
104 
105  // Import Altium Circuit Studio board files.
107 
108  // Import Altium Designer board files.
110 
111  // Import Cadstar PCB Archive board files.
113 
114  // Import Eagle board files.
116 
117  // Import PCAD board files.
119 
120  // Import Fabmaster board files.
122  };
123  // clang-format on
124 
125  wxFileName fileName( *aFileName );
126  wxString fileFilters;
127 
128  if( aKicadFilesOnly )
129  {
130  std::vector<std::string> fileExtensions;
131 
132  for( unsigned ii = 0; ii < 2; ++ii )
133  {
134  if( !fileFilters.IsEmpty() )
135  fileFilters += wxChar( '|' );
136 
137  fileFilters += wxGetTranslation( loaders[ii].filter );
138 
139  PLUGIN::RELEASER plugin( IO_MGR::PluginFind( loaders[ii].pluginType ) );
140  wxCHECK( plugin, false );
141  fileExtensions.push_back( plugin->GetFileExtension().ToStdString() );
142  }
143 
144  fileFilters = _( "All KiCad Board Files" ) + AddFileExtListToFilter( fileExtensions ) + "|"
145  + fileFilters;
146  }
147  else
148  {
149  wxString allWildcards;
150 
151  for( unsigned ii = 2; ii < arrayDim( loaders ); ++ii )
152  {
153  if( !fileFilters.IsEmpty() )
154  fileFilters += wxChar( '|' );
155 
156  fileFilters += wxGetTranslation( loaders[ii].filter );
157 
158  PLUGIN::RELEASER plugin( IO_MGR::PluginFind( loaders[ii].pluginType ) );
159  wxCHECK( plugin, false );
160  allWildcards += "*." + formatWildcardExt( plugin->GetFileExtension() ) + ";";
161  }
162 
163  fileFilters = _( "All supported formats|" ) + allWildcards + "|" + fileFilters;
164  }
165 
166 
167  wxString path;
168  wxString name;
169 
170  if( fileName.FileExists() )
171  {
172  path = fileName.GetPath();
173  name = fileName.GetFullName();
174  }
175  else
176  {
177  path = aParent->GetMruPath();
178 
179  if( path.IsEmpty() )
181  // leave name empty
182  }
183 
184  wxFileDialog dlg( aParent,
185  aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
186  path, name, fileFilters,
187  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
188 
189  if( dlg.ShowModal() == wxID_OK )
190  {
191  // For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin.
192  // It's the only special case because of the duplicate use of the *.brd file extension.
193  // Other cases are clear because of unique file extensions.
194  *aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD;
195  *aFileName = dlg.GetPath();
196  aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
197  return true;
198  }
199  else
200  {
201  return false;
202  }
203 }
204 
205 
207 class CREATE_PROJECT_CHECKBOX : public wxPanel
208 {
209 public:
210  CREATE_PROJECT_CHECKBOX( wxWindow* aParent )
211  : wxPanel( aParent )
212  {
213  m_cbCreateProject = new wxCheckBox( this, wxID_ANY,
214  _( "Create a new project for this board" ) );
215  m_cbCreateProject->SetValue( true );
216  m_cbCreateProject->SetToolTip( _( "Creating a project will enable features such as "
217  "design rules, net classes, and layer presets" ) );
218 
219  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
220  sizer->Add( m_cbCreateProject, 0, wxALL, 8 );
221 
222  SetSizerAndFit( sizer );
223  }
224 
225  bool GetValue() const
226  {
227  return m_cbCreateProject->GetValue();
228  }
229 
230  static wxWindow* Create( wxWindow* aParent )
231  {
232  return new CREATE_PROJECT_CHECKBOX( aParent );
233  }
234 
235 protected:
236  wxCheckBox* m_cbCreateProject;
237 };
238 
239 
249 bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
250 {
251  wxString wildcard = PcbFileWildcard();
252  wxFileName fn = *aFileName;
253 
254  fn.SetExt( KiCadPcbFileExtension );
255 
256  wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
257  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
258 
259  // Add a "Create a project" checkbox in standalone mode and one isn't loaded
260  if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
261  dlg.SetExtraControlCreator( &CREATE_PROJECT_CHECKBOX::Create );
262 
263  if( dlg.ShowModal() != wxID_OK )
264  return false;
265 
266  fn = dlg.GetPath();
267 
268  // always enforce filename extension, user may not have entered it.
269  fn.SetExt( KiCadPcbFileExtension );
270 
271  *aFileName = fn.GetFullPath();
272 
273  if( wxWindow* extraControl = dlg.GetExtraControl() )
274  *aCreateProject = static_cast<CREATE_PROJECT_CHECKBOX*>( extraControl )->GetValue();
275  else if( !aParent->Prj().IsNullProject() )
276  *aCreateProject = true;
277 
278  return true;
279 }
280 
281 
282 void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
283 {
284  wxString fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
285 
286  if( !!fn )
287  {
288  int open_ctl = 0;
289 
290  if( !wxFileName::IsFileReadable( fn ) )
291  {
292  if( !AskLoadBoardFileName( this, &open_ctl, &fn, true ) )
293  return;
294  }
295 
296  OpenProjectFiles( std::vector<wxString>( 1, fn ), open_ctl );
297  }
298 }
299 
300 
301 void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
302 {
304 }
305 
306 
307 void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
308 {
309  int id = event.GetId();
310  Files_io_from_id( id );
311 }
312 
313 
315 {
316  wxString msg;
317 
318  switch( id )
319  {
320  case ID_LOAD_FILE:
321  {
322  int open_ctl = 0;
323  wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
324 
325  return AskLoadBoardFileName( this, &open_ctl, &fileName, true )
326  && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
327  }
328 
330  {
331  int open_ctl = 1;
332  wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
333 
334  return AskLoadBoardFileName( this, &open_ctl, &fileName, false )
335  && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
336  }
337 
339  {
340  wxFileName currfn = Prj().AbsolutePath( GetBoard()->GetFileName() );
341  wxFileName fn = currfn;
342 
343  wxString rec_name = GetAutoSaveFilePrefix() + fn.GetName();
344  fn.SetName( rec_name );
345 
346  if( !fn.FileExists() )
347  {
348  msg.Printf( _( "Recovery file '%s' not found." ), fn.GetFullPath() );
349  DisplayInfoMessage( this, msg );
350  return false;
351  }
352 
353  msg.Printf( _( "OK to load recovery file '%s'?" ), fn.GetFullPath() );
354 
355  if( !IsOK( this, msg ) )
356  return false;
357 
358  GetScreen()->SetContentModified( false ); // do not prompt the user for changes
359 
360  if( OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) ) )
361  {
362  // Re-set the name since name or extension was changed
363  GetBoard()->SetFileName( currfn.GetFullPath() );
364  UpdateTitle();
365  return true;
366  }
367 
368  return false;
369  }
370 
371  case ID_NEW_BOARD:
372  {
373  if( IsContentModified() )
374  {
375  wxFileName fileName = GetBoard()->GetFileName();
376  wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
377  "continuing?" );
378 
379  if( !HandleUnsavedChanges( this, wxString::Format( saveMsg, fileName.GetFullName() ),
380  [&]()->bool
381  {
383  } ) )
384  {
385  return false;
386  }
387  }
388  else if( !GetBoard()->IsEmpty() )
389  {
390  if( !IsOK( this, _( "Current Board will be closed. Continue?" ) ) )
391  return false;
392  }
393 
395 
396  GetBoard()->ClearProject();
397 
399 
400  mgr->SaveProject( mgr->Prj().GetProjectFullName() );
401  mgr->UnloadProject( &mgr->Prj() );
402 
403  if( !Clear_Pcb( false ) )
404  return false;
405 
407 
408  onBoardLoaded();
409 
410  OnModify();
411  return true;
412  }
413 
414  case ID_SAVE_BOARD:
415  if( !GetBoard()->GetFileName().IsEmpty() )
416  return SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
417 
419 
420  case ID_COPY_BOARD_AS:
421  case ID_SAVE_BOARD_AS:
422  {
423  bool addToHistory = ( id == ID_SAVE_BOARD_AS );
424  wxString orig_name;
425 
426  wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
427 
428  if( orig_name.IsEmpty() )
429  orig_name = NAMELESS_PROJECT;
430 
431  wxFileName savePath( Prj().GetProjectFullName() );
432 
433  if( !savePath.IsOk() || !savePath.IsDirWritable() )
434  {
435  savePath = GetMruPath();
436 
437  if( !savePath.IsOk() || !savePath.IsDirWritable() )
439  }
440 
441  wxFileName fn( savePath.GetPath(), orig_name, KiCadPcbFileExtension );
442  wxString filename = fn.GetFullPath();
443  bool createProject = false;
444 
445  if( AskSaveBoardFileName( this, &filename, &createProject ) )
446  {
447  if( id == ID_COPY_BOARD_AS )
448  return SavePcbCopy( filename, createProject );
449  else
450  return SavePcbFile( filename, addToHistory, createProject );
451  }
452 
453  return false;
454  }
455 
456  default:
457  return false;
458  }
459 }
460 
461 
462 // The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
463 // determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
464 // bit flag.
465 IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
466 {
467  IO_MGR::PCB_FILE_T pluginType;
468 
469  wxFileName fn = aFileName;
470 
471  // Note: file extensions are expected to be in lower case.
472  // This is not always true, especially when importing files, so the string
473  // comparisons are case insensitive to try to find the suitable plugin.
474 
475  if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) ) == 0 )
476  {
477  // both legacy and eagle share a common file extension.
478  pluginType = ( aCtl & KICTL_EAGLE_BRD ) ? IO_MGR::EAGLE : IO_MGR::LEGACY;
479  }
480  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::PCAD ) ) == 0 )
481  {
482  pluginType = IO_MGR::PCAD;
483  }
484  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_DESIGNER ) ) == 0 )
485  {
486  pluginType = IO_MGR::ALTIUM_DESIGNER;
487  }
488  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_STUDIO ) ) == 0 )
489  {
490  pluginType = IO_MGR::ALTIUM_CIRCUIT_STUDIO;
491  }
492  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_MAKER ) ) == 0 )
493  {
494  pluginType = IO_MGR::ALTIUM_CIRCUIT_MAKER;
495  }
496  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::CADSTAR_PCB_ARCHIVE ) ) == 0 )
497  {
498  pluginType = IO_MGR::CADSTAR_PCB_ARCHIVE;
499  }
500  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::FABMASTER ) ) == 0 )
501  {
502  pluginType = IO_MGR::FABMASTER;
503  }
504  else
505  {
506  pluginType = IO_MGR::KICAD_SEXP;
507  }
508 
509  return pluginType;
510 }
511 
512 
514 {
515  PCB_LAYER_COLLECTOR collector;
516 
517  collector.SetLayerId( Edge_Cuts );
518  collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
519 
520  int edgeWidth = -1;
521  bool mixed = false;
522 
523  for( int i = 0; i < collector.GetCount(); i++ )
524  {
525  if( collector[i]->Type() == PCB_SHAPE_T )
526  {
527  int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
528 
529  if( edgeWidth != -1 && edgeWidth != itemWidth )
530  {
531  mixed = true;
532  edgeWidth = std::max( edgeWidth, itemWidth );
533  }
534  else
535  {
536  edgeWidth = itemWidth;
537  }
538  }
539  }
540 
541  if( mixed )
542  {
543  // If they had different widths then we can't ensure that fills will be the same.
544  wxMessageBox( _( "If the zones on this board are refilled the Copper Edge Clearance "
545  "setting will be used (see Board Setup > Design Rules > Constraints).\n"
546  "This may result in different fills from previous KiCad versions which "
547  "used the line thicknesses of the board boundary on the Edge Cuts "
548  "layer." ),
549  _( "Edge Clearance Warning" ), wxOK | wxICON_WARNING, this );
550  }
551 
552  return std::max( 0, edgeWidth / 2 );
553 }
554 
555 
556 bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
557 {
558  // This is for python:
559  if( aFileSet.size() != 1 )
560  {
561  UTF8 msg = StrPrintf( "Pcbnew:%s() takes a single filename", __func__ );
562  DisplayError( this, msg );
563  return false;
564  }
565 
566  wxString fullFileName( aFileSet[0] );
567  wxFileName wx_filename( fullFileName );
568  wxString msg;
569 
570  if( Kiface().IsSingle() )
572 
573  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
574  wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
575 
576  std::unique_ptr<wxSingleInstanceChecker> lockFile = ::LockFile( fullFileName );
577 
578  if( !lockFile || lockFile->IsAnotherRunning() )
579  {
580  msg.Printf( _( "PCB '%s' is already open." ), wx_filename.GetFullName() );
581 
582  if( !OverrideLock( this, msg ) )
583  return false;
584  }
585 
586  if( IsContentModified() )
587  {
588  if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
589  [&]()->bool { return SavePcbFile( GetBoard()->GetFileName() ); } ) )
590  {
591  return false;
592  }
593  }
594 
595  // Release the lock file, until the new file is actually loaded
596  ReleaseFile();
597 
598  wxFileName pro = fullFileName;
599  pro.SetExt( ProjectFileExtension );
600 
601  bool is_new = !wxFileName::IsFileReadable( fullFileName );
602 
603  // If its a non-existent schematic and caller thinks it exists
604  if( is_new && !( aCtl & KICTL_CREATE ) )
605  {
606  // notify user that fullFileName does not exist, ask if user wants to create it.
607  msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
608 
609  if( !IsOK( this, msg ) )
610  return false;
611  }
612 
613  // Get rid of any existing warnings about the old board
614  GetInfoBar()->Dismiss();
615 
616  WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Creating PCB" )
617  : _( "Loading PCB" ), 1 );
618 
619  // No save prompt (we already prompted above), and only reset to a new blank board if new
620  Clear_Pcb( false, !is_new );
621 
622  IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
623 
624  bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
625 
626  // Loading a project should only be done under carefully considered circumstances.
627 
628  // The calling code should know not to ask me here to change projects unless
629  // it knows what consequences that will have on other KIFACEs running and using
630  // this same PROJECT. It can be very harmful if that calling code is stupid.
632 
633  if( pro.GetFullPath() != mgr->Prj().GetProjectFullName() )
634  {
635  // calls SaveProject
637 
638  GetBoard()->ClearProject();
639  mgr->UnloadProject( &mgr->Prj() );
640 
641  mgr->LoadProject( pro.GetFullPath() );
642 
643  // Do not allow saving a project if one doesn't exist. This normally happens if we are
644  // standalone and opening a board that has been moved from its project folder.
645  // For converted projects, we don't want to set the read-only flag because we want a project
646  // to be saved for the new file in case things like netclasses got migrated.
647  Prj().SetReadOnly( !pro.Exists() && !converted );
648  }
649 
650  // Clear the cache footprint list which may be project specific
652 
653  if( is_new )
654  {
655  // Link the existing blank board to the new project
656  GetBoard()->SetProject( &Prj() );
657 
658  GetBoard()->SetFileName( fullFileName );
659 
660  OnModify();
661  }
662  else
663  {
664  BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
665  PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
666 
667  LAYER_REMAPPABLE_PLUGIN* layerRemappablePlugin =
668  dynamic_cast< LAYER_REMAPPABLE_PLUGIN* >( (PLUGIN*) pi );
669 
670  if( layerRemappablePlugin )
671  {
672  layerRemappablePlugin->RegisterLayerMappingCallback(
673  std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) );
674  }
675 
676  // This will rename the file if there is an autosave and the user want to recover
677  CheckForAutoSaveFile( fullFileName );
678 
679  bool failedLoad = false;
680 
681  try
682  {
683  PROPERTIES props;
684  char xbuf[30];
685  char ybuf[30];
686 
687  // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
688  sprintf( xbuf, "%d", GetPageSizeIU().x );
689  sprintf( ybuf, "%d", GetPageSizeIU().y );
690 
691  props["page_width"] = xbuf;
692  props["page_height"] = ybuf;
693 
694 #if USE_INSTRUMENTATION
695  // measure the time to load a BOARD.
696  unsigned startTime = GetRunningMicroSecs();
697 #endif
698 
699  loadedBoard = pi->Load( fullFileName, nullptr, &props, &Prj(), &progressReporter );
700 
701 #if USE_INSTRUMENTATION
702  unsigned stopTime = GetRunningMicroSecs();
703  printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
704 #endif
705  }
706  catch( const FUTURE_FORMAT_ERROR& ffe )
707  {
708  msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
709  progressReporter.Hide();
710  DisplayErrorMessage( this, msg, ffe.Problem() );
711 
712  failedLoad = true;
713  }
714  catch( const IO_ERROR& ioe )
715  {
716  if( ioe.Problem() != wxT( "CANCEL" ) )
717  {
718  msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
719  progressReporter.Hide();
720  DisplayErrorMessage( this, msg, ioe.What() );
721  }
722 
723  failedLoad = true;
724  }
725  catch( const std::bad_alloc& )
726  {
727  msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
728  progressReporter.Hide();
729  DisplayErrorMessage( this, msg, wxEmptyString );
730 
731  failedLoad = true;
732  }
733 
734  if( failedLoad )
735  {
736  // We didn't create a new blank board above, so do that now
737  Clear_Pcb( false );
738 
739  return false;
740  }
741 
742  // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
743  // cause any issues on macOS and Windows. If it does, it will have to be conditionally
744  // compiled.
745  Raise();
746 
747  SetBoard( loadedBoard );
748 
749  if( GFootprintList.GetCount() == 0 )
750  GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + "fp-info-cache" );
751 
752  if( loadedBoard->m_LegacyDesignSettingsLoaded )
753  {
754  Prj().SetReadOnly( false );
755 
757 
758  // Before we had a copper edge clearance setting, the edge line widths could be used
759  // as a kludge to control them. So if there's no setting then infer it from the
760  // edge widths.
761  if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
762  {
763  int edgeClearance = inferLegacyEdgeClearance( loadedBoard );
764  loadedBoard->GetDesignSettings().SetCopperEdgeClearance( edgeClearance );
765  }
766 
767  // On save; design settings will be removed from the board
768  loadedBoard->SetModified();
769  }
770 
771  // Move legacy view settings to local project settings
772  if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
773  {
775  loadedBoard->SetModified();
776  }
777 
778  if( !loadedBoard->m_LegacyVisibleItems.test( GAL_LAYER_INDEX( GAL_LAYER_ID_BITMASK_END ) ) )
779  {
781  loadedBoard->SetModified();
782  }
783 
784  // we should not ask PLUGINs to do these items:
785  loadedBoard->BuildListOfNets();
788 
789  if( loadedBoard->IsModified() )
790  OnModify();
791  else
792  GetScreen()->SetContentModified( false );
793 
794  if( ( pluginType == IO_MGR::LEGACY )
795  || ( pluginType == IO_MGR::KICAD_SEXP
797  && loadedBoard->GetGenerator().Lower() != "gerbview" ) )
798  {
801  m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
802  "It will be converted to the new format when saved." ),
803  wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
804  }
805 
806  // Import footprints into a project-specific library
807  //==================================================
808  // TODO: This should be refactored out of here into somewhere specific to the Project Import
809  // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
810  if( aCtl & KICTL_IMPORT_LIB )
811  {
812  wxFileName loadedBoardFn( fullFileName );
813  wxString libNickName = loadedBoardFn.GetName();
814 
815  // Extract a footprint library from the design and add it to the fp-lib-table
816  // The footprints are saved in a new .pretty library.
817  // If this library already exists, all previous footprints will be deleted
818  std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
819  wxString newLibPath = CreateNewProjectLibrary( libNickName );
820 
821  // Only create the new library if CreateNewLibrary succeeded (note that this fails if
822  // the library already exists and the user aborts after seeing the warning message
823  // which prompts the user to continue with overwrite or abort)
824  if( newLibPath.Length() > 0 )
825  {
827 
828  for( FOOTPRINT* footprint : loadedFootprints )
829  {
830  try
831  {
832  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
833  {
834  footprint->SetReference( "REF**" );
835  piSexpr->FootprintSave( newLibPath, footprint );
836  delete footprint;
837  }
838  }
839  catch( const IO_ERROR& ioe )
840  {
841  wxLogError( _( "Error saving footprint %s to project specific library." )
842  + wxS( "\n%s" ),
843  footprint->GetFPID().GetUniStringLibItemName(),
844  ioe.What() );
845  }
846  }
847 
848  FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
849  const wxString& project_env = PROJECT_VAR_NAME;
850  wxString rel_path, env_path;
851 
852  wxASSERT_MSG( wxGetEnv( project_env, &env_path ), "There is no project variable?" );
853 
854  wxString result( newLibPath );
855  rel_path = result.Replace( env_path, wxString( "$(" + project_env + ")" ) ) ? result
856  : "";
857 
858  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
859  wxT( "KiCad" ), wxEmptyString );
860  prjlibtable->InsertRow( row );
861 
862  wxString tblName = Prj().FootprintLibTblName();
863 
864  try
865  {
866  Prj().PcbFootprintLibs()->Save( tblName );
867  }
868  catch( const IO_ERROR& ioe )
869  {
870  wxLogError( _( "Error saving project specific footprint library table." )
871  + wxS( "\n%s" ),
872  ioe.What() );
873  }
874 
875  // Update footprint LIB_IDs to point to the just imported library
876  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
877  {
878  LIB_ID libId = footprint->GetFPID();
879 
880  if( libId.GetLibItemName().empty() )
881  continue;
882 
883  libId.SetLibNickname( libNickName );
884  footprint->SetFPID( libId );
885  }
886  }
887  }
888  }
889 
890  {
891  wxFileName fn = fullFileName;
892 
893  if( converted )
894  fn.SetExt( PcbFileExtension );
895 
896  wxString fname = fn.GetFullPath();
897 
898  fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
899 
900  GetBoard()->SetFileName( fname );
901  }
902 
903  // Lock the file newly opened:
904  m_file_checker.reset( lockFile.release() );
905 
906  if( !converted )
907  UpdateFileHistory( GetBoard()->GetFileName() );
908 
909  // Rebuild list of nets (full ratsnest rebuild)
911  Compile_Ratsnest( true );
912 
913  // Load project settings after setting up board; some of them depend on the nets list
915 
916  // Syncs the UI (appearance panel, etc) with the loaded board and project
917  onBoardLoaded();
918 
919  // Refresh the 3D view, if any
920  EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
921 
922  if( draw3DFrame )
923  draw3DFrame->NewDisplay();
924 
925 #if 0 && defined(DEBUG)
926  // Output the board object tree to stdout, but please run from command prompt:
927  GetBoard()->Show( 0, std::cout );
928 #endif
929 
930  // from EDA_APPL which was first loaded BOARD only:
931  {
932  /* For an obscure reason the focus is lost after loading a board file
933  * when starting up the process.
934  * (seems due to the recreation of the layer manager after loading the file)
935  * Give focus to main window and Drawpanel
936  * must be done for these 2 windows (for an obscure reason ...)
937  * Linux specific
938  * This is more a workaround than a fix.
939  */
940  SetFocus();
941  GetCanvas()->SetFocus();
942  }
943 
944  return true;
945 }
946 
947 
948 bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
949  bool aChangeProject )
950 {
951  // please, keep it simple. prompting goes elsewhere.
952  wxFileName pcbFileName = aFileName;
953 
954  if( pcbFileName.GetExt() == LegacyPcbFileExtension )
955  pcbFileName.SetExt( KiCadPcbFileExtension );
956 
957  // Write through symlinks, don't replace them
959 
960  if( !IsWritable( pcbFileName ) )
961  {
962  wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
963  pcbFileName.GetFullPath() );
964 
965  DisplayError( this, msg );
966  return false;
967  }
968 
969  // TODO: these will break if we ever go multi-board
970  wxFileName projectFile( pcbFileName );
971  wxFileName rulesFile( pcbFileName );
972  wxString msg;
973 
974  projectFile.SetExt( ProjectFileExtension );
975  rulesFile.SetExt( DesignRulesFileExtension );
976 
977  if( !projectFile.FileExists() && aChangeProject )
978  {
979  Prj().SetReadOnly( false );
980  GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
981  }
982 
983  wxFileName currentRules( GetDesignRulesPath() );
984 
985  if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
986  KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
987 
988  if( !msg.IsEmpty() )
989  {
990  DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
991  rulesFile.GetFullPath() ) );
992  }
993 
994  if( projectFile.FileExists() )
995  {
996  // Save various DRC parameters, such as violation severities (which may have been
997  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
999 
1002  }
1003 
1004  wxFileName tempFile( aFileName );
1005  wxString upperTxt;
1006  wxString lowerTxt;
1007 
1008  tempFile.SetName( wxT( "." ) + tempFile.GetName() );
1009  tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
1010 
1011  try
1012  {
1014 
1015  wxASSERT( tempFile.IsAbsolute() );
1016 
1017  pi->Save( tempFile.GetFullPath(), GetBoard(), nullptr );
1018  }
1019  catch( const IO_ERROR& ioe )
1020  {
1021  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1022  pcbFileName.GetFullPath(),
1023  ioe.What() ) );
1024 
1025  lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile.GetFullPath() );
1026 
1027  SetMsgPanel( upperTxt, lowerTxt );
1028 
1029  // In case we started a file but didn't fully write it, clean up
1030  wxRemoveFile( tempFile.GetFullPath() );
1031 
1032  return false;
1033  }
1034 
1035  // If save succeeded, replace the original with what we just wrote
1036  if( !wxRenameFile( tempFile.GetFullPath(), pcbFileName.GetFullPath() ) )
1037  {
1038  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n"
1039  "Failed to rename temporary file '%s." ),
1040  pcbFileName.GetFullPath(),
1041  tempFile.GetFullPath() ) );
1042 
1043  lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1044  tempFile.GetFullPath() );
1045 
1046  SetMsgPanel( upperTxt, lowerTxt );
1047 
1048  return false;
1049  }
1050 
1051  if( !Kiface().IsSingle() )
1052  {
1053  WX_STRING_REPORTER backupReporter( &upperTxt );
1054 
1055  if( GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1056  upperTxt.clear();
1057  }
1058 
1059  GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1060 
1061  // Update the lock in case it was a Save As
1062  LockFile( pcbFileName.GetFullPath() );
1063 
1064  // Put the saved file in File History if requested
1065  if( addToHistory )
1066  UpdateFileHistory( GetBoard()->GetFileName() );
1067 
1068  // Delete auto save file on successful save.
1069  wxFileName autoSaveFileName = pcbFileName;
1070 
1071  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + pcbFileName.GetName() );
1072 
1073  if( autoSaveFileName.FileExists() )
1074  wxRemoveFile( autoSaveFileName.GetFullPath() );
1075 
1076  lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1077 
1078  SetStatusText( lowerTxt, 0 );
1079 
1080  // Get rid of the old version conversion warning, or any other dismissable warning :)
1082  m_infoBar->Dismiss();
1083 
1084  if( m_infoBar->IsShown() && m_infoBar->HasCloseButton() )
1085  m_infoBar->Dismiss();
1086 
1087  GetScreen()->SetContentModified( false );
1088  UpdateTitle();
1089  return true;
1090 }
1091 
1092 
1093 bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject )
1094 {
1095  wxFileName pcbFileName = aFileName;
1096 
1097  // Ensure the file ext is the right ext:
1098  pcbFileName.SetExt( KiCadPcbFileExtension );
1099 
1100  if( !IsWritable( pcbFileName ) )
1101  {
1102  DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1103  pcbFileName.GetFullPath() ) );
1104  return false;
1105  }
1106 
1107  // Save various DRC parameters, such as violation severities (which may have been
1108  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1110 
1112 
1113  try
1114  {
1116 
1117  wxASSERT( pcbFileName.IsAbsolute() );
1118 
1119  pi->Save( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1120  }
1121  catch( const IO_ERROR& ioe )
1122  {
1123  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1124  pcbFileName.GetFullPath(),
1125  ioe.What() ) );
1126 
1127  return false;
1128  }
1129 
1130  wxFileName projectFile( pcbFileName );
1131  wxFileName rulesFile( pcbFileName );
1132  wxString msg;
1133 
1134  projectFile.SetExt( ProjectFileExtension );
1135  rulesFile.SetExt( DesignRulesFileExtension );
1136 
1137  if( aCreateProject && !projectFile.FileExists() )
1138  GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1139 
1140  wxFileName currentRules( GetDesignRulesPath() );
1141 
1142  if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1143  KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1144 
1145  if( !msg.IsEmpty() )
1146  {
1147  DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1148  rulesFile.GetFullPath() ) );
1149  }
1150 
1151  DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n%s" ),
1152  pcbFileName.GetFullPath() ) );
1153 
1154  return true;
1155 }
1156 
1157 
1159 {
1160  wxFileName tmpFileName;
1161 
1162  // Don't run autosave if content has not been modified
1163  if( !IsContentModified() )
1164  return true;
1165 
1166  wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1167 
1168  if( GetBoard()->GetFileName().IsEmpty() )
1169  {
1170  tmpFileName = wxFileName( PATHS::GetDefaultUserProjectsPath(), NAMELESS_PROJECT,
1172  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1173  }
1174  else
1175  {
1176  tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
1177  }
1178 
1179  wxFileName autoSaveFileName = tmpFileName;
1180 
1181  // Auto save file name is the board file name prepended with autosaveFilePrefix string.
1182  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + autoSaveFileName.GetName() );
1183 
1184  if( !autoSaveFileName.IsOk() )
1185  return false;
1186 
1187  // If the board file path is not writable, try writing to a platform specific temp file
1188  // path. If that path isn't writable, give up.
1189  if( !autoSaveFileName.IsDirWritable() )
1190  {
1191  autoSaveFileName.SetPath( wxFileName::GetTempDir() );
1192 
1193  if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
1194  return false;
1195  }
1196 
1197  wxLogTrace( traceAutoSave, "Creating auto save file <" + autoSaveFileName.GetFullPath() + ">" );
1198 
1199  if( SavePcbFile( autoSaveFileName.GetFullPath(), false, false ) )
1200  {
1202  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1203  UpdateTitle();
1204  m_autoSaveState = false;
1205 
1206  if( !Kiface().IsSingle() &&
1207  GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1208  {
1210  }
1211 
1212  SetTitle( title ); // Restore initial frame title
1213 
1214  return true;
1215  }
1216 
1217  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1218 
1219  SetTitle( title ); // Restore initial frame title
1220 
1221  return false;
1222 }
1223 
1224 
1225 bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
1226 {
1227  switch( (IO_MGR::PCB_FILE_T) aFileType )
1228  {
1230  case IO_MGR::EAGLE:
1231  return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
1233 
1234  default:
1235  return false;
1236  }
1237 
1238  return false;
1239 }
1240 
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:271
void UpdateTitle()
Set the main window title bar text.
Plugin class for import plugins that support remappable layers.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:70
LSET m_VisibleLayers
Board settings.
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: infobar.cpp:142
void BuildListOfNets()
Definition: board.h:663
void SetModified()
Definition: eda_item.cpp:65
void OnModify() override
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:231
void SetCopperEdgeClearance(int aDistance)
const UTF8 & GetLibItemName() const
Definition: lib_id.h:104
#define WIN_STRING_DIR_SEP
Definition: gestfich.h:36
#define KICTL_IMPORT_LIB
import all footprints into a project library.
Definition: kiway_player.h:83
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
wxString EaglePcbFileWildcard()
Pcbnew PLUGIN for CADSTAR PCB Archive (*.cpa) format: an ASCII format based on S-expressions.
static const KICAD_T AllBoardItems[]
A scan list for all editable board items.
Definition: collectors.h:267
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: board.h:268
void SetMruPath(const wxString &aPath)
bool importFile(const wxString &aFileName, int aFileType)
Load the given filename but sets the path to the current project path.
bool IsContentModified() const override
Get if the current board has been modified but not saved.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:284
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: eda_item.h:118
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
EDA_3D_VIEWER_FRAME * Get3DViewerFrame()
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:40
void Compile_Ratsnest(bool aDisplayStatus)
Create the entire board ratsnest.
Definition: ratsnest.cpp:40
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.
void SaveProjectAs(const wxString &aFullPath)
Sets the currently loaded project path and saves it (pointers remain valid) Note that this will not m...
const std::string ProjectFileExtension
const std::string LegacyPcbFileExtension
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
virtual BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=nullptr, PROJECT *aProject=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Load information from some input file format that this PLUGIN implementation knows about into either ...
Definition: plugin.cpp:46
#define UNIX_STRING_DIR_SEP
Definition: gestfich.h:35
bool doAutoSave() override
Perform auto save when the board has been modified and not saved within the auto save interval.
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:145
#define KICTL_CREATE
caller thinks requested project files may not exist.
Definition: kiway_player.h:82
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.
const std::string DesignRulesFileExtension
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:38
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
Definition: cvpcb.cpp:140
bool LoadProjectSettings()
Load the current project's file configuration settings which are pertinent to this PCB_EDIT_FRAME ins...
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:334
void ReleaseFile()
Release the current file marked in use.
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Test a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:628
CREATE_PROJECT_CHECKBOX(wxWindow *aParent)
NET_SETTINGS & NetSettings()
Definition: project_file.h:94
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject=false)
Write the board data structures to aFileName.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
#define KICTL_EAGLE_BRD
chosen *.brd file is Eagle according to user.
Definition: kiway_player.h:81
const wxString & GetGenerator() const
Definition: board.h:292
int inferLegacyEdgeClearance(BOARD *aBoard)
wxString AltiumCircuitMakerPcbFileWildcard()
Collect all BOARD_ITEM objects on a given layer.
Definition: collectors.h:642
const std::string KiCadPcbFileExtension
void RebuildNetClassAssignments()
Rebuild netclass assignments from the netclass membership lists.
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
A name/value tuple with unique names and optional values.
Definition: properties.h:33
const wxString & GetFileName() const
Definition: board.h:228
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:589
std::unique_ptr< wxSingleInstanceChecker > m_file_checker
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:650
virtual void RegisterLayerMappingCallback(LAYER_MAPPING_HANDLER aLayerMappingHandler)
Register a different handler to be called when mapping of input layers to KiCad layers occurs.
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:269
This file contains miscellaneous commonly used macros and functions.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:151
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetches the file name from the file history list.
This is the end of the layers used for visibility bit masks in Pcbnew.
Definition: layer_ids.h:221
bool HasCloseButton() const
Definition: infobar.cpp:310
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:78
bool m_LegacyCopperEdgeClearanceLoaded
Definition: board.h:269
Releases a PLUGIN in the context of a potential thrown exception through its destructor.
Definition: io_mgr.h:555
wxString FabmasterPcbFileWildcard()
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1410
void OnClearFileHistory(wxCommandEvent &aEvent)
wxString GetMruPath() const
virtual std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints()
Return a container with the cached library footprints generated in the last call to Load.
Definition: plugin.cpp:54
bool AskSaveBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, bool *aCreateProject)
Put up a wxFileDialog asking for a BOARD filename to save.
wxString LegacyPcbFileWildcard()
unsigned GetCount() const
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: infobar.cpp:175
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
void SaveProjectCopy(const wxString &aFullPath)
Saves a copy of the current project under the given path.
wxString CreateNewProjectLibrary(const wxString &aLibName=wxEmptyString, const wxString &aProposedName=wxEmptyString)
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...
bool AskLoadBoardFileName(PCB_EDIT_FRAME *aParent, int *aCtl, wxString *aFileName, bool aKicadFilesOnly)
Show a wxFileDialog asking for a BOARD filename to open.
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
Definition: layer_ids.h:248
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
MESSAGE_TYPE GetMessageType() const
Definition: infobar.h:99
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
static wxWindow * Create(wxWindow *aParent)
void onBoardLoaded()
Update the state of the GUI after a new board is loaded or created.
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Calls BackupProject if a new backup is needed according to the current backup policy.
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
FOOTPRINTS & Footprints()
Definition: board.h:233
void SaveProjectSettings() override
Save changes to the project settings to the project (.pro) file.
static void ResolvePossibleSymlinks(wxFileName &aFilename)
Definition: wx_filename.cpp:85
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:1403
Definition of file extensions used in Kicad.
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
#define _(s)
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
wxLogTrace helper definitions.
virtual void SetFocus() override
#define PcbFileExtension
void BuildConnectivity()
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:136
void SetFileName(const wxString &aFileName)
Definition: board.h:226
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:116
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:134
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:286
wxString AltiumDesignerPcbFileWildcard()
void ClearProject()
Definition: board.cpp:172
int GetFileFormatVersionAtLoad() const
Definition: board.h:289
A wrapper for reporting to a wxString object.
Definition: reporter.h:163
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:283
int SetLibNickname(const UTF8 &aNickname)
Override the logical library name portion of the LIB_ID to aNickname.
Definition: lib_id.cpp:97
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
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
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)
Link a board to a given project.
Definition: board.cpp:142
< Helper widget to select whether a new project should be created for a file when saving
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:139
static std::map< wxString, PCB_LAYER_ID > GetMapModal(wxWindow *aParent, const std::vector< INPUT_LAYER_DESC > &aLayerDesc)
Create and show a dialog (modal) and returns the data from it after completion.
void OnFileHistory(wxCommandEvent &event)
virtual void SetReadOnly(bool aReadOnly=true)
Definition: project.h:126
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:158
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:55
bool SavePcbFile(const wxString &aFileName, bool addToHistory=true, bool aChangeProject=true)
Write the board data structures to a aFileName.
void SetBoard(BOARD *aBoard) override
const char * name
Definition: DXF_plotter.cpp:56
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
WX_INFOBAR * m_infoBar
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
void Files_io(wxCommandEvent &event)
Call Files_io_from_id with the wxCommandEvent id.
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapset time (in microsecondes) to class PROF_COUNTER.
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Return a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
static TOOL_ACTION repairBoard
Definition: pcb_actions.h:442
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
A base class that BOARD loading and saving plugins should derive from.
Definition: io_mgr.h:269
#define NAMELESS_PROJECT
default name for nameless projects
Definition: project.h:41
bool SaveProject(const wxString &aFullPath=wxEmptyString)
Saves a loaded project.
The main frame for Pcbnew.
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.
OUTDATED_SAVE Messages that should be cleared on save.
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)
Read and write board files according to aId.
WX_INFOBAR * GetInfoBar()
void ReadCacheFromFile(const wxString &aFilePath) override
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Definition: ki_exception.h:174
static REPORTER & GetInstance()
Definition: reporter.cpp:117
BOARD * GetBoard() const
wxString CadstarPcbArchiveFileWildcard()
bool OverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition: confirm.cpp:154
Message panel definition file.
PCB_FILE_T
The set of file types that the IO_MGR knows about, and for which there has been a plugin written.
Definition: io_mgr.h:53
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:299
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
wxString PCadPcbFileWildcard()
bool Clear_Pcb(bool aQuery, bool aFinal=false)
Delete all and reinitialize the current board.
Definition: initpcb.cpp:43
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:315
bool IsEmpty() const
Definition: board.h:281
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:264
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:104
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition: project.cpp:146
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
bool empty() const
Definition: utf8.h:103
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
bool RegisterApplicationRestart(const wxString &aCommandLine)
Registers the application for restart with the OS with the given command line string to pass as args.
Definition: gtk/app.cpp:58
S-expression Pcbnew file format.
Definition: io_mgr.h:56
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Return the file extension for aFileType.
Definition: io_mgr.cpp:109
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:276
GAL_SET m_LegacyVisibleItems
Definition: board.h:265