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  + wxT( "|" ) + 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 += wxT( "*." ) + formatWildcardExt( plugin->GetFileExtension() ) + wxT( ";" );
161  }
162 
163  fileFilters = _( "All supported formats|" ) + allWildcards + wxT( "|" ) + 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, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
187 
188  if( dlg.ShowModal() == wxID_OK )
189  {
190  // For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin.
191  // It's the only special case because of the duplicate use of the *.brd file extension.
192  // Other cases are clear because of unique file extensions.
193  *aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD;
194  *aFileName = dlg.GetPath();
195  aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
196  return true;
197  }
198  else
199  {
200  return false;
201  }
202 }
203 
204 
206 class CREATE_PROJECT_CHECKBOX : public wxPanel
207 {
208 public:
209  CREATE_PROJECT_CHECKBOX( wxWindow* aParent )
210  : wxPanel( aParent )
211  {
212  m_cbCreateProject = new wxCheckBox( this, wxID_ANY,
213  _( "Create a new project for this board" ) );
214  m_cbCreateProject->SetValue( true );
215  m_cbCreateProject->SetToolTip( _( "Creating a project will enable features such as "
216  "design rules, net classes, and layer presets" ) );
217 
218  wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
219  sizer->Add( m_cbCreateProject, 0, wxALL, 8 );
220 
221  SetSizerAndFit( sizer );
222  }
223 
224  bool GetValue() const
225  {
226  return m_cbCreateProject->GetValue();
227  }
228 
229  static wxWindow* Create( wxWindow* aParent )
230  {
231  return new CREATE_PROJECT_CHECKBOX( aParent );
232  }
233 
234 protected:
235  wxCheckBox* m_cbCreateProject;
236 };
237 
238 
248 bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
249 {
250  wxString wildcard = PcbFileWildcard();
251  wxFileName fn = *aFileName;
252 
253  fn.SetExt( KiCadPcbFileExtension );
254 
255  wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
256  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
257 
258  // Add a "Create a project" checkbox in standalone mode and one isn't loaded
259  if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
260  dlg.SetExtraControlCreator( &CREATE_PROJECT_CHECKBOX::Create );
261 
262  if( dlg.ShowModal() != wxID_OK )
263  return false;
264 
265  fn = dlg.GetPath();
266 
267  // always enforce filename extension, user may not have entered it.
268  fn.SetExt( KiCadPcbFileExtension );
269 
270  *aFileName = fn.GetFullPath();
271 
272  if( wxWindow* extraControl = dlg.GetExtraControl() )
273  *aCreateProject = static_cast<CREATE_PROJECT_CHECKBOX*>( extraControl )->GetValue();
274  else if( !aParent->Prj().IsNullProject() )
275  *aCreateProject = true;
276 
277  return true;
278 }
279 
280 
281 void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
282 {
283  wxString fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
284 
285  if( !!fn )
286  {
287  int open_ctl = 0;
288 
289  if( !wxFileName::IsFileReadable( fn ) )
290  {
291  if( !AskLoadBoardFileName( this, &open_ctl, &fn, true ) )
292  return;
293  }
294 
295  OpenProjectFiles( std::vector<wxString>( 1, fn ), open_ctl );
296  }
297 }
298 
299 
300 void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
301 {
303 }
304 
305 
306 void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
307 {
308  int id = event.GetId();
309  Files_io_from_id( id );
310 }
311 
312 
314 {
315  wxString msg;
316 
317  switch( id )
318  {
319  case ID_LOAD_FILE:
320  {
321  int open_ctl = 0;
322  wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
323 
324  return AskLoadBoardFileName( this, &open_ctl, &fileName, true )
325  && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
326  }
327 
329  {
330  int open_ctl = 1;
331  wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
332 
333  return AskLoadBoardFileName( this, &open_ctl, &fileName, false )
334  && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
335  }
336 
338  {
339  wxFileName currfn = Prj().AbsolutePath( GetBoard()->GetFileName() );
340  wxFileName fn = currfn;
341 
342  wxString rec_name = GetAutoSaveFilePrefix() + fn.GetName();
343  fn.SetName( rec_name );
344 
345  if( !fn.FileExists() )
346  {
347  msg.Printf( _( "Recovery file '%s' not found." ), fn.GetFullPath() );
348  DisplayInfoMessage( this, msg );
349  return false;
350  }
351 
352  msg.Printf( _( "OK to load recovery file '%s'?" ), fn.GetFullPath() );
353 
354  if( !IsOK( this, msg ) )
355  return false;
356 
357  GetScreen()->SetContentModified( false ); // do not prompt the user for changes
358 
359  if( OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) ) )
360  {
361  // Re-set the name since name or extension was changed
362  GetBoard()->SetFileName( currfn.GetFullPath() );
363  UpdateTitle();
364  return true;
365  }
366 
367  return false;
368  }
369 
370  case ID_NEW_BOARD:
371  {
372  if( IsContentModified() )
373  {
374  wxFileName fileName = GetBoard()->GetFileName();
375  wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
376  "continuing?" );
377 
378  if( !HandleUnsavedChanges( this, wxString::Format( saveMsg, fileName.GetFullName() ),
379  [&]()->bool
380  {
382  } ) )
383  {
384  return false;
385  }
386  }
387  else if( !GetBoard()->IsEmpty() )
388  {
389  if( !IsOK( this, _( "Current Board will be closed. Continue?" ) ) )
390  return false;
391  }
392 
394 
395  GetBoard()->ClearProject();
396 
398 
399  mgr->SaveProject( mgr->Prj().GetProjectFullName() );
400  mgr->UnloadProject( &mgr->Prj() );
401 
402  if( !Clear_Pcb( false ) )
403  return false;
404 
406 
407  onBoardLoaded();
408 
409  OnModify();
410  return true;
411  }
412 
413  case ID_SAVE_BOARD:
414  if( !GetBoard()->GetFileName().IsEmpty() )
415  return SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
416 
418 
419  case ID_COPY_BOARD_AS:
420  case ID_SAVE_BOARD_AS:
421  {
422  bool addToHistory = ( id == ID_SAVE_BOARD_AS );
423  wxString orig_name;
424 
425  wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
426 
427  if( orig_name.IsEmpty() )
428  orig_name = NAMELESS_PROJECT;
429 
430  wxFileName savePath( Prj().GetProjectFullName() );
431 
432  if( !savePath.IsOk() || !savePath.IsDirWritable() )
433  {
434  savePath = GetMruPath();
435 
436  if( !savePath.IsOk() || !savePath.IsDirWritable() )
438  }
439 
440  wxFileName fn( savePath.GetPath(), orig_name, KiCadPcbFileExtension );
441  wxString filename = fn.GetFullPath();
442  bool createProject = false;
443 
444  if( AskSaveBoardFileName( this, &filename, &createProject ) )
445  {
446  if( id == ID_COPY_BOARD_AS )
447  return SavePcbCopy( filename, createProject );
448  else
449  return SavePcbFile( filename, addToHistory, createProject );
450  }
451 
452  return false;
453  }
454 
455  default:
456  return false;
457  }
458 }
459 
460 
461 // The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
462 // determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
463 // bit flag.
464 IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
465 {
466  IO_MGR::PCB_FILE_T pluginType;
467 
468  wxFileName fn = aFileName;
469 
470  // Note: file extensions are expected to be in lower case.
471  // This is not always true, especially when importing files, so the string
472  // comparisons are case insensitive to try to find the suitable plugin.
473 
474  if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) ) == 0 )
475  {
476  // both legacy and eagle share a common file extension.
477  pluginType = ( aCtl & KICTL_EAGLE_BRD ) ? IO_MGR::EAGLE : IO_MGR::LEGACY;
478  }
479  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::PCAD ) ) == 0 )
480  {
481  pluginType = IO_MGR::PCAD;
482  }
483  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_DESIGNER ) ) == 0 )
484  {
485  pluginType = IO_MGR::ALTIUM_DESIGNER;
486  }
487  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_STUDIO ) ) == 0 )
488  {
489  pluginType = IO_MGR::ALTIUM_CIRCUIT_STUDIO;
490  }
491  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_MAKER ) ) == 0 )
492  {
493  pluginType = IO_MGR::ALTIUM_CIRCUIT_MAKER;
494  }
495  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::CADSTAR_PCB_ARCHIVE ) ) == 0 )
496  {
497  pluginType = IO_MGR::CADSTAR_PCB_ARCHIVE;
498  }
499  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::FABMASTER ) ) == 0 )
500  {
501  pluginType = IO_MGR::FABMASTER;
502  }
503  else
504  {
505  pluginType = IO_MGR::KICAD_SEXP;
506  }
507 
508  return pluginType;
509 }
510 
511 
513 {
514  PCB_LAYER_COLLECTOR collector;
515 
516  collector.SetLayerId( Edge_Cuts );
517  collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
518 
519  int edgeWidth = -1;
520  bool mixed = false;
521 
522  for( int i = 0; i < collector.GetCount(); i++ )
523  {
524  if( collector[i]->Type() == PCB_SHAPE_T )
525  {
526  int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
527 
528  if( edgeWidth != -1 && edgeWidth != itemWidth )
529  {
530  mixed = true;
531  edgeWidth = std::max( edgeWidth, itemWidth );
532  }
533  else
534  {
535  edgeWidth = itemWidth;
536  }
537  }
538  }
539 
540  if( mixed )
541  {
542  // If they had different widths then we can't ensure that fills will be the same.
543  wxMessageBox( _( "If the zones on this board are refilled the Copper Edge Clearance "
544  "setting will be used (see Board Setup > Design Rules > Constraints).\n"
545  "This may result in different fills from previous KiCad versions which "
546  "used the line thicknesses of the board boundary on the Edge Cuts "
547  "layer." ),
548  _( "Edge Clearance Warning" ), wxOK | wxICON_WARNING, this );
549  }
550 
551  return std::max( 0, edgeWidth / 2 );
552 }
553 
554 
555 bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
556 {
557  // This is for python:
558  if( aFileSet.size() != 1 )
559  {
560  UTF8 msg = StrPrintf( "Pcbnew:%s() takes a single filename", __func__ );
561  DisplayError( this, msg );
562  return false;
563  }
564 
565  wxString fullFileName( aFileSet[0] );
566  wxFileName wx_filename( fullFileName );
567  wxString msg;
568 
569  if( Kiface().IsSingle() )
571 
572  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
573  wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
574 
575  std::unique_ptr<wxSingleInstanceChecker> lockFile = ::LockFile( fullFileName );
576 
577  if( !lockFile || lockFile->IsAnotherRunning() )
578  {
579  msg.Printf( _( "PCB '%s' is already open." ), wx_filename.GetFullName() );
580 
581  if( !OverrideLock( this, msg ) )
582  return false;
583  }
584 
585  if( IsContentModified() )
586  {
587  if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
588  [&]() -> bool
589  {
590  return SavePcbFile( GetBoard()->GetFileName() );
591  } ) )
592  {
593  return false;
594  }
595  }
596 
597  // Release the lock file, until the new file is actually loaded
598  ReleaseFile();
599 
600  wxFileName pro = fullFileName;
601  pro.SetExt( ProjectFileExtension );
602 
603  bool is_new = !wxFileName::IsFileReadable( fullFileName );
604 
605  // If its a non-existent schematic and caller thinks it exists
606  if( is_new && !( aCtl & KICTL_CREATE ) )
607  {
608  // notify user that fullFileName does not exist, ask if user wants to create it.
609  msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
610 
611  if( !IsOK( this, msg ) )
612  return false;
613  }
614 
615  // Get rid of any existing warnings about the old board
616  GetInfoBar()->Dismiss();
617 
618  WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Creating PCB" )
619  : _( "Loading PCB" ), 1 );
620 
621  // No save prompt (we already prompted above), and only reset to a new blank board if new
622  Clear_Pcb( false, !is_new );
623 
624  IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
625 
626  bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
627 
628  // Loading a project should only be done under carefully considered circumstances.
629 
630  // The calling code should know not to ask me here to change projects unless
631  // it knows what consequences that will have on other KIFACEs running and using
632  // this same PROJECT. It can be very harmful if that calling code is stupid.
634 
635  if( pro.GetFullPath() != mgr->Prj().GetProjectFullName() )
636  {
637  // calls SaveProject
639 
640  GetBoard()->ClearProject();
641  mgr->UnloadProject( &mgr->Prj() );
642 
643  mgr->LoadProject( pro.GetFullPath() );
644 
645  // Do not allow saving a project if one doesn't exist. This normally happens if we are
646  // standalone and opening a board that has been moved from its project folder.
647  // For converted projects, we don't want to set the read-only flag because we want a project
648  // to be saved for the new file in case things like netclasses got migrated.
649  Prj().SetReadOnly( !pro.Exists() && !converted );
650  }
651 
652  // Clear the cache footprint list which may be project specific
654 
655  if( is_new )
656  {
657  // Link the existing blank board to the new project
658  GetBoard()->SetProject( &Prj() );
659 
660  GetBoard()->SetFileName( fullFileName );
661 
662  OnModify();
663  }
664  else
665  {
666  BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
667  PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
668 
669  LAYER_REMAPPABLE_PLUGIN* layerRemappablePlugin =
670  dynamic_cast< LAYER_REMAPPABLE_PLUGIN* >( (PLUGIN*) pi );
671 
672  if( layerRemappablePlugin )
673  {
674  layerRemappablePlugin->RegisterLayerMappingCallback(
675  std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) );
676  }
677 
678  // This will rename the file if there is an autosave and the user want to recover
679  CheckForAutoSaveFile( fullFileName );
680 
681  bool failedLoad = false;
682 
683  try
684  {
685  PROPERTIES props;
686  char xbuf[30];
687  char ybuf[30];
688 
689  // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
690  sprintf( xbuf, "%d", GetPageSizeIU().x );
691  sprintf( ybuf, "%d", GetPageSizeIU().y );
692 
693  props["page_width"] = xbuf;
694  props["page_height"] = ybuf;
695 
696 #if USE_INSTRUMENTATION
697  // measure the time to load a BOARD.
698  unsigned startTime = GetRunningMicroSecs();
699 #endif
700 
701  loadedBoard = pi->Load( fullFileName, nullptr, &props, &Prj(), &progressReporter );
702 
703 #if USE_INSTRUMENTATION
704  unsigned stopTime = GetRunningMicroSecs();
705  printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
706 #endif
707  }
708  catch( const FUTURE_FORMAT_ERROR& ffe )
709  {
710  msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
711  progressReporter.Hide();
712  DisplayErrorMessage( this, msg, ffe.Problem() );
713 
714  failedLoad = true;
715  }
716  catch( const IO_ERROR& ioe )
717  {
718  if( ioe.Problem() != wxT( "CANCEL" ) )
719  {
720  msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
721  progressReporter.Hide();
722  DisplayErrorMessage( this, msg, ioe.What() );
723  }
724 
725  failedLoad = true;
726  }
727  catch( const std::bad_alloc& )
728  {
729  msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
730  progressReporter.Hide();
731  DisplayErrorMessage( this, msg, wxEmptyString );
732 
733  failedLoad = true;
734  }
735 
736  if( failedLoad )
737  {
738  // We didn't create a new blank board above, so do that now
739  Clear_Pcb( false );
740 
741  return false;
742  }
743 
744  // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
745  // cause any issues on macOS and Windows. If it does, it will have to be conditionally
746  // compiled.
747  Raise();
748 
749  // Skip (possibly expensive) connectivity build here; we build it below after load
750  SetBoard( loadedBoard, false, &progressReporter );
751 
752  if( GFootprintList.GetCount() == 0 )
753  GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + wxT( "fp-info-cache" ) );
754 
755  if( loadedBoard->m_LegacyDesignSettingsLoaded )
756  {
757  Prj().SetReadOnly( false );
758 
760 
761  // Before we had a copper edge clearance setting, the edge line widths could be used
762  // as a kludge to control them. So if there's no setting then infer it from the
763  // edge widths.
764  if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
765  {
766  int edgeClearance = inferLegacyEdgeClearance( loadedBoard );
767  loadedBoard->GetDesignSettings().SetCopperEdgeClearance( edgeClearance );
768  }
769 
770  // On save; design settings will be removed from the board
771  loadedBoard->SetModified();
772  }
773 
774  // Move legacy view settings to local project settings
775  if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
776  {
778  loadedBoard->SetModified();
779  }
780 
781  if( !loadedBoard->m_LegacyVisibleItems.test( GAL_LAYER_INDEX( GAL_LAYER_ID_BITMASK_END ) ) )
782  {
784  loadedBoard->SetModified();
785  }
786 
787  // we should not ask PLUGINs to do these items:
788  loadedBoard->BuildListOfNets();
791 
792  if( loadedBoard->IsModified() )
793  OnModify();
794  else
795  GetScreen()->SetContentModified( false );
796 
797  if( ( pluginType == IO_MGR::LEGACY )
798  || ( pluginType == IO_MGR::KICAD_SEXP
800  && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
801  {
804  m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
805  "It will be converted to the new format when saved." ),
806  wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
807  }
808 
809  // Import footprints into a project-specific library
810  //==================================================
811  // TODO: This should be refactored out of here into somewhere specific to the Project Import
812  // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
813  if( aCtl & KICTL_IMPORT_LIB )
814  {
815  wxFileName loadedBoardFn( fullFileName );
816  wxString libNickName = loadedBoardFn.GetName();
817 
818  // Extract a footprint library from the design and add it to the fp-lib-table
819  // The footprints are saved in a new .pretty library.
820  // If this library already exists, all previous footprints will be deleted
821  std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
822  wxString newLibPath = CreateNewProjectLibrary( libNickName );
823 
824  // Only create the new library if CreateNewLibrary succeeded (note that this fails if
825  // the library already exists and the user aborts after seeing the warning message
826  // which prompts the user to continue with overwrite or abort)
827  if( newLibPath.Length() > 0 )
828  {
830 
831  for( FOOTPRINT* footprint : loadedFootprints )
832  {
833  try
834  {
835  if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
836  {
837  footprint->SetReference( "REF**" );
838  piSexpr->FootprintSave( newLibPath, footprint );
839  delete footprint;
840  }
841  }
842  catch( const IO_ERROR& ioe )
843  {
844  wxLogError( _( "Error saving footprint %s to project specific library." )
845  + wxS( "\n%s" ),
846  footprint->GetFPID().GetUniStringLibItemName(),
847  ioe.What() );
848  }
849  }
850 
851  FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
852  const wxString& project_env = PROJECT_VAR_NAME;
853  wxString rel_path, env_path;
854 
855  wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
856  wxT( "There is no project variable?" ) );
857 
858  wxString result( newLibPath );
859  rel_path = result.Replace( env_path,
860  wxT( "$(" ) + project_env + wxT( ")" ) )
861  ? result
862  : wxString( wxEmptyString );
863 
864  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
865  wxT( "KiCad" ), wxEmptyString );
866  prjlibtable->InsertRow( row );
867 
868  wxString tblName = Prj().FootprintLibTblName();
869 
870  try
871  {
872  Prj().PcbFootprintLibs()->Save( tblName );
873  }
874  catch( const IO_ERROR& ioe )
875  {
876  wxLogError( _( "Error saving project specific footprint library table." )
877  + wxS( "\n%s" ),
878  ioe.What() );
879  }
880 
881  // Update footprint LIB_IDs to point to the just imported library
882  for( FOOTPRINT* footprint : GetBoard()->Footprints() )
883  {
884  LIB_ID libId = footprint->GetFPID();
885 
886  if( libId.GetLibItemName().empty() )
887  continue;
888 
889  libId.SetLibNickname( libNickName );
890  footprint->SetFPID( libId );
891  }
892  }
893  }
894  }
895 
896  {
897  wxFileName fn = fullFileName;
898 
899  if( converted )
900  fn.SetExt( PcbFileExtension );
901 
902  wxString fname = fn.GetFullPath();
903 
904  fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
905 
906  GetBoard()->SetFileName( fname );
907  }
908 
909  // Lock the file newly opened:
910  m_file_checker.reset( lockFile.release() );
911 
912  if( !converted )
913  UpdateFileHistory( GetBoard()->GetFileName() );
914 
915  // Rebuild list of nets (full ratsnest rebuild)
916  progressReporter.Report( _( "Updating nets" ) );
917  GetBoard()->BuildConnectivity( &progressReporter );
918 
919  // Load project settings after setting up board; some of them depend on the nets list
921 
922  // Syncs the UI (appearance panel, etc) with the loaded board and project
923  onBoardLoaded();
924 
925  // Refresh the 3D view, if any
926  EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
927 
928  if( draw3DFrame )
929  draw3DFrame->NewDisplay();
930 
931 #if 0 && defined(DEBUG)
932  // Output the board object tree to stdout, but please run from command prompt:
933  GetBoard()->Show( 0, std::cout );
934 #endif
935 
936  // from EDA_APPL which was first loaded BOARD only:
937  {
938  /* For an obscure reason the focus is lost after loading a board file
939  * when starting up the process.
940  * (seems due to the recreation of the layer manager after loading the file)
941  * Give focus to main window and Drawpanel
942  * must be done for these 2 windows (for an obscure reason ...)
943  * Linux specific
944  * This is more a workaround than a fix.
945  */
946  SetFocus();
947  GetCanvas()->SetFocus();
948  }
949 
950  return true;
951 }
952 
953 
954 bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
955  bool aChangeProject )
956 {
957  // please, keep it simple. prompting goes elsewhere.
958  wxFileName pcbFileName = aFileName;
959 
960  if( pcbFileName.GetExt() == LegacyPcbFileExtension )
961  pcbFileName.SetExt( KiCadPcbFileExtension );
962 
963  // Write through symlinks, don't replace them
965 
966  if( !IsWritable( pcbFileName ) )
967  {
968  wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
969  pcbFileName.GetFullPath() );
970 
971  DisplayError( this, msg );
972  return false;
973  }
974 
975  // TODO: these will break if we ever go multi-board
976  wxFileName projectFile( pcbFileName );
977  wxFileName rulesFile( pcbFileName );
978  wxString msg;
979 
980  projectFile.SetExt( ProjectFileExtension );
981  rulesFile.SetExt( DesignRulesFileExtension );
982 
983  if( !projectFile.FileExists() && aChangeProject )
984  {
985  Prj().SetReadOnly( false );
986  GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
987  }
988 
989  wxFileName currentRules( GetDesignRulesPath() );
990 
991  if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
992  KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
993 
994  if( !msg.IsEmpty() )
995  {
996  DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
997  rulesFile.GetFullPath() ) );
998  }
999 
1000  if( projectFile.FileExists() )
1001  {
1002  // Save various DRC parameters, such as violation severities (which may have been
1003  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1005 
1008  }
1009 
1010  wxStandardPaths& paths = wxStandardPaths::Get();
1011  wxString tempFile = wxFileName::CreateTempFileName(
1012  paths.GetTempDir() + wxFileName::GetPathSeparator() + wxT( "pcbnew" ) );
1013  wxString upperTxt;
1014  wxString lowerTxt;
1015 
1016  try
1017  {
1019 
1020  pi->Save( tempFile, GetBoard(), nullptr );
1021  }
1022  catch( const IO_ERROR& ioe )
1023  {
1024  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1025  pcbFileName.GetFullPath(),
1026  ioe.What() ) );
1027 
1028  lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1029 
1030  SetMsgPanel( upperTxt, lowerTxt );
1031 
1032  // In case we started a file but didn't fully write it, clean up
1033  wxRemoveFile( tempFile );
1034 
1035  return false;
1036  }
1037 
1038  // If save succeeded, replace the original with what we just wrote
1039  if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1040  {
1041  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n"
1042  "Failed to rename temporary file '%s." ),
1043  pcbFileName.GetFullPath(),
1044  tempFile ) );
1045 
1046  lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1047  tempFile );
1048 
1049  SetMsgPanel( upperTxt, lowerTxt );
1050 
1051  return false;
1052  }
1053 
1054  if( !Kiface().IsSingle() )
1055  {
1056  WX_STRING_REPORTER backupReporter( &upperTxt );
1057 
1058  if( GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1059  upperTxt.clear();
1060  }
1061 
1062  GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1063 
1064  // Update the lock in case it was a Save As
1065  LockFile( pcbFileName.GetFullPath() );
1066 
1067  // Put the saved file in File History if requested
1068  if( addToHistory )
1069  UpdateFileHistory( GetBoard()->GetFileName() );
1070 
1071  // Delete auto save file on successful save.
1072  wxFileName autoSaveFileName = pcbFileName;
1073 
1074  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + pcbFileName.GetName() );
1075 
1076  if( autoSaveFileName.FileExists() )
1077  wxRemoveFile( autoSaveFileName.GetFullPath() );
1078 
1079  lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1080 
1081  SetStatusText( lowerTxt, 0 );
1082 
1083  // Get rid of the old version conversion warning, or any other dismissable warning :)
1085  m_infoBar->Dismiss();
1086 
1087  if( m_infoBar->IsShown() && m_infoBar->HasCloseButton() )
1088  m_infoBar->Dismiss();
1089 
1090  GetScreen()->SetContentModified( false );
1091  UpdateTitle();
1092  return true;
1093 }
1094 
1095 
1096 bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject )
1097 {
1098  wxFileName pcbFileName = aFileName;
1099 
1100  // Ensure the file ext is the right ext:
1101  pcbFileName.SetExt( KiCadPcbFileExtension );
1102 
1103  if( !IsWritable( pcbFileName ) )
1104  {
1105  DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1106  pcbFileName.GetFullPath() ) );
1107  return false;
1108  }
1109 
1110  // Save various DRC parameters, such as violation severities (which may have been
1111  // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1113 
1115 
1116  try
1117  {
1119 
1120  wxASSERT( pcbFileName.IsAbsolute() );
1121 
1122  pi->Save( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1123  }
1124  catch( const IO_ERROR& ioe )
1125  {
1126  DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1127  pcbFileName.GetFullPath(),
1128  ioe.What() ) );
1129 
1130  return false;
1131  }
1132 
1133  wxFileName projectFile( pcbFileName );
1134  wxFileName rulesFile( pcbFileName );
1135  wxString msg;
1136 
1137  projectFile.SetExt( ProjectFileExtension );
1138  rulesFile.SetExt( DesignRulesFileExtension );
1139 
1140  if( aCreateProject && !projectFile.FileExists() )
1141  GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1142 
1143  wxFileName currentRules( GetDesignRulesPath() );
1144 
1145  if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1146  KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1147 
1148  if( !msg.IsEmpty() )
1149  {
1150  DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1151  rulesFile.GetFullPath() ) );
1152  }
1153 
1154  DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n%s" ),
1155  pcbFileName.GetFullPath() ) );
1156 
1157  return true;
1158 }
1159 
1160 
1162 {
1163  wxFileName tmpFileName;
1164 
1165  // Don't run autosave if content has not been modified
1166  if( !IsContentModified() )
1167  return true;
1168 
1169  wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1170 
1171  if( GetBoard()->GetFileName().IsEmpty() )
1172  {
1173  tmpFileName = wxFileName( PATHS::GetDefaultUserProjectsPath(), NAMELESS_PROJECT,
1175  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1176  }
1177  else
1178  {
1179  tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
1180  }
1181 
1182  wxFileName autoSaveFileName = tmpFileName;
1183 
1184  // Auto save file name is the board file name prepended with autosaveFilePrefix string.
1185  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + autoSaveFileName.GetName() );
1186 
1187  if( !autoSaveFileName.IsOk() )
1188  return false;
1189 
1190  // If the board file path is not writable, try writing to a platform specific temp file
1191  // path. If that path isn't writable, give up.
1192  if( !autoSaveFileName.IsDirWritable() )
1193  {
1194  autoSaveFileName.SetPath( wxFileName::GetTempDir() );
1195 
1196  if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
1197  return false;
1198  }
1199 
1200  wxLogTrace( traceAutoSave,
1201  wxT( "Creating auto save file <" ) + autoSaveFileName.GetFullPath() + wxT( ">" ) );
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
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Saves a loaded project.
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.
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:233
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:1394
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...
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:260
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:1387
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
void SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Saves a copy of the current project under the given path.
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
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.
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Sets the currently loaded project path and saves it (pointers remain valid) Note that this will not m...
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