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 <[email protected]>
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
164  + "|" + fileFilters;
165  }
166 
167 
168  wxString path;
169  wxString name;
170 
171  if( fileName.FileExists() )
172  {
173  path = fileName.GetPath();
174  name = fileName.GetFullName();
175  }
176  else
177  {
178  path = aParent->GetMruPath();
179 
180  if( path.IsEmpty() )
182  // leave name empty
183  }
184 
185  wxFileDialog dlg( aParent,
186  aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
187  path, name, fileFilters, 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
590  {
591  return SavePcbFile( GetBoard()->GetFileName() );
592  } ) )
593  {
594  return false;
595  }
596  }
597 
598  // Release the lock file, until the new file is actually loaded
599  ReleaseFile();
600 
601  wxFileName pro = fullFileName;
602  pro.SetExt( ProjectFileExtension );
603 
604  bool is_new = !wxFileName::IsFileReadable( fullFileName );
605 
606  // If its a non-existent schematic and caller thinks it exists
607  if( is_new && !( aCtl & KICTL_CREATE ) )
608  {
609  // notify user that fullFileName does not exist, ask if user wants to create it.
610  msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
611 
612  if( !IsOK( this, msg ) )
613  return false;
614  }
615 
616  // Get rid of any existing warnings about the old board
617  GetInfoBar()->Dismiss();
618 
619  WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Creating PCB" )
620  : _( "Loading PCB" ), 1 );
621 
622  // No save prompt (we already prompted above), and only reset to a new blank board if new
623  Clear_Pcb( false, !is_new );
624 
625  IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
626 
627  bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
628 
629  // Loading a project should only be done under carefully considered circumstances.
630 
631  // The calling code should know not to ask me here to change projects unless
632  // it knows what consequences that will have on other KIFACEs running and using
633  // this same PROJECT. It can be very harmful if that calling code is stupid.
635 
636  if( pro.GetFullPath() != mgr->Prj().GetProjectFullName() )
637  {
638  // calls SaveProject
640 
641  GetBoard()->ClearProject();
642  mgr->UnloadProject( &mgr->Prj() );
643 
644  mgr->LoadProject( pro.GetFullPath() );
645 
646  // Do not allow saving a project if one doesn't exist. This normally happens if we are
647  // standalone and opening a board that has been moved from its project folder.
648  // For converted projects, we don't want to set the read-only flag because we want a project
649  // to be saved for the new file in case things like netclasses got migrated.
650  Prj().SetReadOnly( !pro.Exists() && !converted );
651  }
652 
653  // Clear the cache footprint list which may be project specific
655 
656  if( is_new )
657  {
658  // Link the existing blank board to the new project
659  GetBoard()->SetProject( &Prj() );
660 
661  GetBoard()->SetFileName( fullFileName );
662 
663  OnModify();
664  }
665  else
666  {
667  BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
668  PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
669 
670  LAYER_REMAPPABLE_PLUGIN* layerRemappablePlugin =
671  dynamic_cast< LAYER_REMAPPABLE_PLUGIN* >( (PLUGIN*) pi );
672 
673  if( layerRemappablePlugin )
674  {
675  layerRemappablePlugin->RegisterLayerMappingCallback(
676  std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) );
677  }
678 
679  // This will rename the file if there is an autosave and the user want to recover
680  CheckForAutoSaveFile( fullFileName );
681 
682  bool failedLoad = false;
683 
684  try
685  {
686  PROPERTIES props;
687  char xbuf[30];
688  char ybuf[30];
689 
690  // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
691  sprintf( xbuf, "%d", GetPageSizeIU().x );
692  sprintf( ybuf, "%d", GetPageSizeIU().y );
693 
694  props["page_width"] = xbuf;
695  props["page_height"] = ybuf;
696 
697 #if USE_INSTRUMENTATION
698  // measure the time to load a BOARD.
699  unsigned startTime = GetRunningMicroSecs();
700 #endif
701 
702  loadedBoard = pi->Load( fullFileName, nullptr, &props, &Prj(), &progressReporter );
703 
704 #if USE_INSTRUMENTATION
705  unsigned stopTime = GetRunningMicroSecs();
706  printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
707 #endif
708  }
709  catch( const FUTURE_FORMAT_ERROR& ffe )
710  {
711  msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
712  progressReporter.Hide();
713  DisplayErrorMessage( this, msg, ffe.Problem() );
714 
715  failedLoad = true;
716  }
717  catch( const IO_ERROR& ioe )
718  {
719  if( ioe.Problem() != wxT( "CANCEL" ) )
720  {
721  msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
722  progressReporter.Hide();
723  DisplayErrorMessage( this, msg, ioe.What() );
724  }
725 
726  failedLoad = true;
727  }
728  catch( const std::bad_alloc& )
729  {
730  msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
731  progressReporter.Hide();
732  DisplayErrorMessage( this, msg, wxEmptyString );
733 
734  failedLoad = true;
735  }
736 
737  if( failedLoad )
738  {
739  // We didn't create a new blank board above, so do that now
740  Clear_Pcb( false );
741 
742  return false;
743  }
744 
745  // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
746  // cause any issues on macOS and Windows. If it does, it will have to be conditionally
747  // compiled.
748  Raise();
749 
750  // Skip (possibly expensive) connectivity build here; we build it below after load
751  SetBoard( loadedBoard, false, &progressReporter );
752 
753  if( GFootprintList.GetCount() == 0 )
754  GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + "fp-info-cache" );
755 
756  if( loadedBoard->m_LegacyDesignSettingsLoaded )
757  {
758  Prj().SetReadOnly( false );
759 
761 
762  // Before we had a copper edge clearance setting, the edge line widths could be used
763  // as a kludge to control them. So if there's no setting then infer it from the
764  // edge widths.
765  if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
766  {
767  int edgeClearance = inferLegacyEdgeClearance( loadedBoard );
768  loadedBoard->GetDesignSettings().SetCopperEdgeClearance( edgeClearance );
769  }
770 
771  // On save; design settings will be removed from the board
772  loadedBoard->SetModified();
773  }
774 
775  // Move legacy view settings to local project settings
776  if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
777  {
779  loadedBoard->SetModified();
780  }
781 
782  if( !loadedBoard->m_LegacyVisibleItems.test( GAL_LAYER_INDEX( GAL_LAYER_ID_BITMASK_END ) ) )
783  {
785  loadedBoard->SetModified();
786  }
787 
788  // we should not ask PLUGINs to do these items:
789  loadedBoard->BuildListOfNets();
792 
793  if( loadedBoard->IsModified() )
794  OnModify();
795  else
796  GetScreen()->SetContentModified( false );
797 
798  if( ( pluginType == IO_MGR::LEGACY )
799  || ( pluginType == IO_MGR::KICAD_SEXP
801  && loadedBoard->GetGenerator().Lower() != "gerbview" ) )
802  {
805  m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
806  "It will be converted to the new format when saved." ),
807  wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
808  }
809 
810  // Import footprints into a project-specific library
811  //==================================================
812  // TODO: This should be refactored out of here into somewhere specific to the Project Import
813  // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
814  if( aCtl & KICTL_IMPORT_LIB )
815  {
816  wxFileName loadedBoardFn( fullFileName );
817  wxString libNickName = loadedBoardFn.GetName();
818 
819  // Extract a footprint library from the design and add it to the fp-lib-table
820  // The footprints are saved in a new .pretty library.
821  // If this library already exists, all previous footprints will be deleted
822  std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
823  wxString newLibPath = CreateNewProjectLibrary( libNickName );
824 
825  // Only create the new library if CreateNewLibrary succeeded (note that this fails if
826  // the library already exists and the user aborts after seeing the warning message
827  // which prompts the user to continue with overwrite or abort)
828  if( newLibPath.Length() > 0 )
829  {
831 
832  for( FOOTPRINT* footprint : loadedFootprints )
833  {
834  try
835  {
836  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
837  {
838  footprint->SetReference( "REF**" );
839  piSexpr->FootprintSave( newLibPath, footprint );
840  delete footprint;
841  }
842  }
843  catch( const IO_ERROR& ioe )
844  {
845  wxLogError( _( "Error saving footprint %s to project specific library." )
846  + wxS( "\n%s" ),
847  footprint->GetFPID().GetUniStringLibItemName(),
848  ioe.What() );
849  }
850  }
851 
852  FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
853  const wxString& project_env = PROJECT_VAR_NAME;
854  wxString rel_path, env_path;
855 
856  wxASSERT_MSG( wxGetEnv( project_env, &env_path ), "There is no project variable?" );
857 
858  wxString result( newLibPath );
859  rel_path = result.Replace( env_path, wxString( "$(" + project_env + ")" ) ) ? result
860  : "";
861 
862  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
863  wxT( "KiCad" ), wxEmptyString );
864  prjlibtable->InsertRow( row );
865 
866  wxString tblName = Prj().FootprintLibTblName();
867 
868  try
869  {
870  Prj().PcbFootprintLibs()->Save( tblName );
871  }
872  catch( const IO_ERROR& ioe )
873  {
874  wxLogError( _( "Error saving project specific footprint library table." )
875  + wxS( "\n%s" ),
876  ioe.What() );
877  }
878 
879  // Update footprint LIB_IDs to point to the just imported library
880  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
881  {
882  LIB_ID libId = footprint->GetFPID();
883 
884  if( libId.GetLibItemName().empty() )
885  continue;
886 
887  libId.SetLibNickname( libNickName );
888  footprint->SetFPID( libId );
889  }
890  }
891  }
892  }
893 
894  {
895  wxFileName fn = fullFileName;
896 
897  if( converted )
898  fn.SetExt( PcbFileExtension );
899 
900  wxString fname = fn.GetFullPath();
901 
902  fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
903 
904  GetBoard()->SetFileName( fname );
905  }
906 
907  // Lock the file newly opened:
908  m_file_checker.reset( lockFile.release() );
909 
910  if( !converted )
911  UpdateFileHistory( GetBoard()->GetFileName() );
912 
913  // Rebuild list of nets (full ratsnest rebuild)
914  progressReporter.Report( _( "Updating nets" ) );
915  GetBoard()->BuildConnectivity( &progressReporter );
916 
917  // Load project settings after setting up board; some of them depend on the nets list
919 
920  // Syncs the UI (appearance panel, etc) with the loaded board and project
921  onBoardLoaded();
922 
923  // Refresh the 3D view, if any
924  EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
925 
926  if( draw3DFrame )
927  draw3DFrame->NewDisplay();
928 
929 #if 0 && defined(DEBUG)
930  // Output the board object tree to stdout, but please run from command prompt:
931  GetBoard()->Show( 0, std::cout );
932 #endif
933 
934  // from EDA_APPL which was first loaded BOARD only:
935  {
936  /* For an obscure reason the focus is lost after loading a board file
937  * when starting up the process.
938  * (seems due to the recreation of the layer manager after loading the file)
939  * Give focus to main window and Drawpanel
940  * must be done for these 2 windows (for an obscure reason ...)
941  * Linux specific
942  * This is more a workaround than a fix.
943  */
944  SetFocus();
945  GetCanvas()->SetFocus();
946  }
947 
948  return true;
949 }
950 
951 
952 bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
953  bool aChangeProject )
954 {
955  // please, keep it simple. prompting goes elsewhere.
956  wxFileName pcbFileName = aFileName;
957 
958  if( pcbFileName.GetExt() == LegacyPcbFileExtension )
959  pcbFileName.SetExt( KiCadPcbFileExtension );
960 
961  // Write through symlinks, don't replace them
963 
964  if( !IsWritable( pcbFileName ) )
965  {
966  wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
967  pcbFileName.GetFullPath() );
968 
969  DisplayError( this, msg );
970  return false;
971  }
972 
973  // TODO: these will break if we ever go multi-board
974  wxFileName projectFile( pcbFileName );
975  wxFileName rulesFile( pcbFileName );
976  wxString msg;
977 
978  projectFile.SetExt( ProjectFileExtension );
979  rulesFile.SetExt( DesignRulesFileExtension );
980 
981  if( !projectFile.FileExists() && aChangeProject )
982  {
983  Prj().SetReadOnly( false );
984  GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
985  }
986 
987  wxFileName currentRules( GetDesignRulesPath() );
988 
989  if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
990  KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
991 
992  if( !msg.IsEmpty() )
993  {
994  DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
995  rulesFile.GetFullPath() ) );
996  }
997 
998  if( projectFile.FileExists() )
999  {
1000  // Save various DRC parameters, such as violation severities (which may have been
1001  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1003 
1006  }
1007 
1008  wxFileName tempFile( aFileName );
1009  wxString upperTxt;
1010  wxString lowerTxt;
1011 
1012  tempFile.SetName( wxT( "." ) + tempFile.GetName() );
1013  tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
1014 
1015  try
1016  {
1018 
1019  wxASSERT( tempFile.IsAbsolute() );
1020 
1021  pi->Save( tempFile.GetFullPath(), GetBoard(), nullptr );
1022  }
1023  catch( const IO_ERROR& ioe )
1024  {
1025  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1026  pcbFileName.GetFullPath(),
1027  ioe.What() ) );
1028 
1029  lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile.GetFullPath() );
1030 
1031  SetMsgPanel( upperTxt, lowerTxt );
1032 
1033  // In case we started a file but didn't fully write it, clean up
1034  wxRemoveFile( tempFile.GetFullPath() );
1035 
1036  return false;
1037  }
1038 
1039  // If save succeeded, replace the original with what we just wrote
1040  if( !wxRenameFile( tempFile.GetFullPath(), pcbFileName.GetFullPath() ) )
1041  {
1042  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n"
1043  "Failed to rename temporary file '%s." ),
1044  pcbFileName.GetFullPath(),
1045  tempFile.GetFullPath() ) );
1046 
1047  lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1048  tempFile.GetFullPath() );
1049 
1050  SetMsgPanel( upperTxt, lowerTxt );
1051 
1052  return false;
1053  }
1054 
1055  if( !Kiface().IsSingle() )
1056  {
1057  WX_STRING_REPORTER backupReporter( &upperTxt );
1058 
1059  if( GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1060  upperTxt.clear();
1061  }
1062 
1063  GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1064 
1065  // Update the lock in case it was a Save As
1066  LockFile( pcbFileName.GetFullPath() );
1067 
1068  // Put the saved file in File History if requested
1069  if( addToHistory )
1070  UpdateFileHistory( GetBoard()->GetFileName() );
1071 
1072  // Delete auto save file on successful save.
1073  wxFileName autoSaveFileName = pcbFileName;
1074 
1075  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + pcbFileName.GetName() );
1076 
1077  if( autoSaveFileName.FileExists() )
1078  wxRemoveFile( autoSaveFileName.GetFullPath() );
1079 
1080  lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1081 
1082  SetStatusText( lowerTxt, 0 );
1083 
1084  // Get rid of the old version conversion warning, or any other dismissable warning :)
1086  m_infoBar->Dismiss();
1087 
1088  if( m_infoBar->IsShown() && m_infoBar->HasCloseButton() )
1089  m_infoBar->Dismiss();
1090 
1091  GetScreen()->SetContentModified( false );
1092  UpdateTitle();
1093  return true;
1094 }
1095 
1096 
1097 bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject )
1098 {
1099  wxFileName pcbFileName = aFileName;
1100 
1101  // Ensure the file ext is the right ext:
1102  pcbFileName.SetExt( KiCadPcbFileExtension );
1103 
1104  if( !IsWritable( pcbFileName ) )
1105  {
1106  DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1107  pcbFileName.GetFullPath() ) );
1108  return false;
1109  }
1110 
1111  // Save various DRC parameters, such as violation severities (which may have been
1112  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1114 
1116 
1117  try
1118  {
1120 
1121  wxASSERT( pcbFileName.IsAbsolute() );
1122 
1123  pi->Save( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1124  }
1125  catch( const IO_ERROR& ioe )
1126  {
1127  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1128  pcbFileName.GetFullPath(),
1129  ioe.What() ) );
1130 
1131  return false;
1132  }
1133 
1134  wxFileName projectFile( pcbFileName );
1135  wxFileName rulesFile( pcbFileName );
1136  wxString msg;
1137 
1138  projectFile.SetExt( ProjectFileExtension );
1139  rulesFile.SetExt( DesignRulesFileExtension );
1140 
1141  if( aCreateProject && !projectFile.FileExists() )
1142  GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1143 
1144  wxFileName currentRules( GetDesignRulesPath() );
1145 
1146  if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1147  KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1148 
1149  if( !msg.IsEmpty() )
1150  {
1151  DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1152  rulesFile.GetFullPath() ) );
1153  }
1154 
1155  DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n%s" ),
1156  pcbFileName.GetFullPath() ) );
1157 
1158  return true;
1159 }
1160 
1161 
1163 {
1164  wxFileName tmpFileName;
1165 
1166  // Don't run autosave if content has not been modified
1167  if( !IsContentModified() )
1168  return true;
1169 
1170  wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1171 
1172  if( GetBoard()->GetFileName().IsEmpty() )
1173  {
1174  tmpFileName = wxFileName( PATHS::GetDefaultUserProjectsPath(), NAMELESS_PROJECT,
1176  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1177  }
1178  else
1179  {
1180  tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
1181  }
1182 
1183  wxFileName autoSaveFileName = tmpFileName;
1184 
1185  // Auto save file name is the board file name prepended with autosaveFilePrefix string.
1186  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + autoSaveFileName.GetName() );
1187 
1188  if( !autoSaveFileName.IsOk() )
1189  return false;
1190 
1191  // If the board file path is not writable, try writing to a platform specific temp file
1192  // path. If that path isn't writable, give up.
1193  if( !autoSaveFileName.IsDirWritable() )
1194  {
1195  autoSaveFileName.SetPath( wxFileName::GetTempDir() );
1196 
1197  if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
1198  return false;
1199  }
1200 
1201  wxLogTrace( traceAutoSave, "Creating auto save file <" + autoSaveFileName.GetFullPath() + ">" );
1202 
1203  if( SavePcbFile( autoSaveFileName.GetFullPath(), false, false ) )
1204  {
1206  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1207  UpdateTitle();
1208  m_autoSaveState = false;
1209 
1210  if( !Kiface().IsSingle() &&
1211  GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1212  {
1214  }
1215 
1216  SetTitle( title ); // Restore initial frame title
1217 
1218  return true;
1219  }
1220 
1221  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1222 
1223  SetTitle( title ); // Restore initial frame title
1224 
1225  return false;
1226 }
1227 
1228 
1229 bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
1230 {
1231  switch( (IO_MGR::PCB_FILE_T) aFileType )
1232  {
1234  case IO_MGR::EAGLE:
1235  return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
1237 
1238  default:
1239  return false;
1240  }
1241 
1242  return false;
1243 }
1244 
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:279
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:659
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:239
void SetCopperEdgeClearance(int aDistance)
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
Definition: pcb_plugin.h:105
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:269
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:292
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:117
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
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:214
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:96
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:293
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.
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
virtual void Report(const wxString &aMessage) override
Display aMessage in the progress bar dialog.
const wxString & GetFileName() const
Definition: board.h:229
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
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:222
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:79
bool m_LegacyCopperEdgeClearanceLoaded
Definition: board.h:270
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:82
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1391
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 (.
virtual 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:249
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.
void SetBoard(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr) override
Set the #m_Pcb member in such as way as to ensure deleting any previous BOARD.
FOOTPRINTS & Footprints()
Definition: board.h:234
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:1384
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 SetFileName(const wxString &aFileName)
Definition: board.h:227
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:173
int GetFileFormatVersionAtLoad() const
Definition: board.h:290
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
void BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:137
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:143
< 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.
const char * name
Definition: DXF_plotter.cpp:56
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Checks if aFileName can be written.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
WX_INFOBAR * m_infoBar
void Files_io(wxCommandEvent &event)
Call Files_io_from_id with the wxCommandEvent id.
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapsed 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:444
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:307
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:323
bool IsEmpty() const
Definition: board.h:282
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:265
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:266