KiCad PCB EDA Suite
eeschema/files-io.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) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2013 CERN (www.cern.ch)
7  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <symbol_library.h>
28 #include <confirm.h>
29 #include <connection_graph.h>
30 #include <dialog_migrate_buses.h>
31 #include <dialog_symbol_remap.h>
32 #include <eeschema_settings.h>
33 #include <id.h>
34 #include <kiface_i.h>
35 #include <kiplatform/app.h>
36 #include <pgm_base.h>
37 #include <profile.h>
38 #include <project/project_file.h>
39 #include <project_rescue.h>
40 #include <wx_html_report_box.h>
42 #include <reporter.h>
43 #include <richio.h>
44 #include <sch_edit_frame.h>
46 #include <sch_file_versions.h>
47 #include <sch_sheet.h>
48 #include <sch_sheet_path.h>
49 #include <schematic.h>
51 #include <tool/actions.h>
52 #include <tool/tool_manager.h>
54 #include <trace_helpers.h>
55 #include <widgets/infobar.h>
58 #include <wx/ffile.h>
59 #include <wx/filedlg.h>
60 #include <wx/log.h>
62 #include <paths.h>
63 #include <wx_filename.h> // For ::ResolvePossibleSymlinks
65 
66 bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName )
67 {
68  wxString msg;
69  wxFileName schematicFileName;
70  wxFileName oldFileName;
71  bool success;
72 
73  if( aSheet == nullptr )
74  aSheet = GetCurrentSheet().Last();
75 
76  SCH_SCREEN* screen = aSheet->GetScreen();
77 
78  wxCHECK( screen, false );
79 
80  // If no name exists in the window yet - save as new.
81  if( screen->GetFileName().IsEmpty() )
82  aSaveUnderNewName = true;
83 
84  // Construct the name of the file to be saved
85  schematicFileName = Prj().AbsolutePath( screen->GetFileName() );
86  oldFileName = schematicFileName;
87 
88  if( aSaveUnderNewName )
89  {
90  wxFileName savePath( Prj().GetProjectFullName() );
91 
92  if( !savePath.IsOk() || !savePath.IsDirWritable() )
93  {
94  savePath = GetMruPath();
95 
96  if( !savePath.IsOk() || !savePath.IsDirWritable() )
98  }
99 
100  wxFileDialog dlg( this, _( "Schematic Files" ), savePath.GetPath(),
101  schematicFileName.GetFullName(), KiCadSchematicFileWildcard(),
102  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
103 
104  if( dlg.ShowModal() == wxID_CANCEL )
105  return false;
106 
107  schematicFileName = dlg.GetPath();
108 
109  if( schematicFileName.GetExt().IsEmpty() )
110  schematicFileName.SetExt( KiCadSchematicFileExtension );
111  }
112 
113  // Write through symlinks, don't replace them
114  WX_FILENAME::ResolvePossibleSymlinks( schematicFileName );
115 
116  if( !IsWritable( schematicFileName ) )
117  return false;
118 
119  // This is a new schematic file so make sure it has a unique ID.
120  if( aSaveUnderNewName && schematicFileName != oldFileName )
121  screen->AssignNewUuid();
122 
123  wxFileName tempFile( schematicFileName );
124  tempFile.SetName( wxT( "." ) + tempFile.GetName() );
125  tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
126 
127  // Save
128  wxLogTrace( traceAutoSave, "Saving file " + schematicFileName.GetFullPath() );
129 
130  SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromSchPath(
131  schematicFileName.GetFullPath() );
132  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( pluginType ) );
133 
134  try
135  {
136  pi->Save( tempFile.GetFullPath(), aSheet, &Schematic() );
137  success = true;
138  }
139  catch( const IO_ERROR& ioe )
140  {
141  msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
142  schematicFileName.GetFullPath(),
143  ioe.What() );
144  DisplayError( this, msg );
145 
146  msg.Printf( _( "Failed to create temporary file '%s'." ),
147  tempFile.GetFullPath() );
148  SetMsgPanel( wxEmptyString, msg );
149 
150  // In case we started a file but didn't fully write it, clean up
151  wxRemoveFile( tempFile.GetFullPath() );
152 
153  success = false;
154  }
155 
156  if( success )
157  {
158  // Replace the original with the temporary file we just wrote
159  success = wxRenameFile( tempFile.GetFullPath(), schematicFileName.GetFullPath() );
160 
161  if( !success )
162  {
163  msg.Printf( _( "Error saving schematic file '%s'.\n"
164  "Failed to rename temporary file '%s'." ),
165  schematicFileName.GetFullPath(),
166  tempFile.GetFullPath() );
167  DisplayError( this, msg );
168 
169  msg.Printf( _( "Failed to rename temporary file '%s'." ),
170  tempFile.GetFullPath() );
171  SetMsgPanel( wxEmptyString, msg );
172  }
173  }
174 
175  if( success )
176  {
177  // Delete auto save file.
178  wxFileName autoSaveFileName = schematicFileName;
179  autoSaveFileName.SetName( GetAutoSaveFilePrefix() + schematicFileName.GetName() );
180 
181  if( autoSaveFileName.FileExists() )
182  {
183  wxLogTrace( traceAutoSave,
184  wxT( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
185  wxT( ">" ) );
186 
187  wxRemoveFile( autoSaveFileName.GetFullPath() );
188  }
189 
190  // Update the screen and frame info and reset the lock file.
191  if( aSaveUnderNewName )
192  {
193  screen->SetFileName( schematicFileName.GetFullPath() );
194  aSheet->SetFileName( schematicFileName.GetFullPath() );
195  LockFile( schematicFileName.GetFullPath() );
196 
197  UpdateFileHistory( schematicFileName.GetFullPath() );
198  }
199 
200  screen->SetContentModified( false );
201  UpdateTitle();
202 
203  msg.Printf( _( "File '%s' saved." ), screen->GetFileName() );
204  SetStatusText( msg, 0 );
205  }
206  else
207  {
208  DisplayError( this, _( "File write operation failed." ) );
209  }
210 
211  return success;
212 }
213 
214 
215 void SCH_EDIT_FRAME::Save_File( bool doSaveAs )
216 {
217  if( doSaveAs )
218  {
219  if( SaveEEFile( nullptr, true ) )
220  {
221  SCH_SCREEN* screen = GetScreen();
222 
223  wxCHECK( screen, /* void */ );
224 
225  wxFileName fn = screen->GetFileName();
226 
227  if( fn.GetExt() == LegacySchematicFileExtension )
229 
230  // If we are saving under a new name, and don't have a real project yet, create one
231  fn.SetExt( ProjectFileExtension );
232 
233  if( fn.IsDirWritable() && !fn.FileExists() )
234  {
235  Prj().SetReadOnly( false );
236  GetSettingsManager()->SaveProjectAs( fn.GetFullPath() );
237  }
238  }
239  }
240  else
241  {
242  SaveEEFile( nullptr );
243  }
244 
245  UpdateTitle();
246 }
247 
248 
249 bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
250 {
251  // implement the pseudo code from KIWAY_PLAYER.h:
252  wxString msg;
253 
254  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
255 
256  // This is for python:
257  if( aFileSet.size() != 1 )
258  {
259  msg.Printf( "Eeschema:%s() takes only a single filename.", __WXFUNCTION__ );
260  DisplayError( this, msg );
261  return false;
262  }
263 
264  wxString fullFileName( aFileSet[0] );
265 
266  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
267  wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "Path is not absolute!" ) );
268 
269  if( !LockFile( fullFileName ) )
270  {
271  msg.Printf( _( "Schematic file '%s' is already open." ), fullFileName );
272  DisplayError( this, msg );
273  return false;
274  }
275 
276  if( !AskToSaveChanges() )
277  return false;
278 
279 #ifdef PROFILE
280  PROF_COUNTER openFiles( "OpenProjectFile" );
281 #endif
282 
283  wxFileName pro = fullFileName;
284  pro.SetExt( ProjectFileExtension );
285 
286  bool is_new = !wxFileName::IsFileReadable( fullFileName );
287 
288  // If its a non-existent schematic and caller thinks it exists
289  if( is_new && !( aCtl & KICTL_CREATE ) )
290  {
291  // notify user that fullFileName does not exist, ask if user wants to create it.
292  msg.Printf( _( "Schematic '%s' does not exist. Do you wish to create it?" ),
293  fullFileName );
294 
295  if( !IsOK( this, msg ) )
296  return false;
297  }
298 
299  // Loading a complex project and build data can be time
300  // consumming, so display a busy cursor
301  wxBusyCursor dummy;
302 
303  // unload current project file before loading new
304  {
305  SetScreen( nullptr );
307  CreateScreens();
308  }
309 
310  SetStatusText( wxEmptyString );
311  m_infoBar->Dismiss();
312 
313  SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromSchPath( fullFileName );
314 
315  // PROJECT::SetProjectFullName() is an impactful function. It should only be
316  // called under carefully considered circumstances.
317 
318  // The calling code should know not to ask me here to change projects unless
319  // it knows what consequences that will have on other KIFACEs running and using
320  // this same PROJECT. It can be very harmful if that calling code is stupid.
321 
322  // NOTE: The calling code should never call this in hosted (non-standalone) mode with a
323  // different project than what has been loaded by the manager frame. This will crash.
324 
325  bool differentProject = pro.GetFullPath() != Prj().GetProjectFullName();
326 
327  if( differentProject )
328  {
329  if( !Prj().IsNullProject() )
331 
332  Schematic().SetProject( nullptr );
333  GetSettingsManager()->UnloadProject( &Prj(), false );
334 
335  GetSettingsManager()->LoadProject( pro.GetFullPath() );
336 
337  wxFileName legacyPro( pro );
338  legacyPro.SetExt( LegacyProjectFileExtension );
339 
340  // Do not allow saving a project if one doesn't exist. This normally happens if we are
341  // standalone and opening a schematic that has been moved from its project folder.
342  if( !pro.Exists() && !legacyPro.Exists() && !( aCtl & KICTL_CREATE ) )
343  Prj().SetReadOnly();
344 
345  CreateScreens();
346  }
347 
348  if( schFileType == SCH_IO_MGR::SCH_LEGACY )
349  {
350  // Don't reload the symbol libraries if we are just launching Eeschema from KiCad again.
351  // They are already saved in the kiface project object.
352  if( differentProject || !Prj().GetElem( PROJECT::ELEM_SCH_SYMBOL_LIBS ) )
353  {
354  // load the libraries here, not in SCH_SCREEN::Draw() which is a context
355  // that will not tolerate DisplayError() dialog since we're already in an
356  // event handler in there.
357  // And when a schematic file is loaded, we need these libs to initialize
358  // some parameters (links to PART LIB, dangling ends ...)
360  Prj().SchLibs();
361  }
362  }
363  else
364  {
365  // No legacy symbol libraries including the cache are loaded with the new file format.
367  }
368 
369  // Load the symbol library table, this will be used forever more.
371  Prj().SchSymbolLibTable();
372 
373  // Load project settings after schematic has been set up with the project link, since this will
374  // update some of the needed schematic settings such as drawing defaults
376 
377  wxFileName rfn( GetCurrentFileName() );
378  rfn.MakeRelativeTo( Prj().GetProjectPath() );
379  LoadWindowState( rfn.GetFullPath() );
380 
381  KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Schematic file changes are unsaved" ) );
382 
383  if( Kiface().IsSingle() )
384  {
386  }
387 
388  if( is_new )
389  {
390  // mark new, unsaved file as modified.
392  GetScreen()->SetFileName( fullFileName );
393  }
394  else
395  {
396  // This will rename the file if there is an autosave and the user want to recover.
397  CheckForAutoSaveFile( fullFileName );
398 
399  SetScreen( nullptr );
400 
401  SCH_PLUGIN* plugin = SCH_IO_MGR::FindPlugin( schFileType );
402  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( plugin );
403 
404  WX_PROGRESS_REPORTER progressReporter( this, _( "Loading Schematic" ), 1 );
405  pi->SetProgressReporter( &progressReporter );
406 
407  bool failedLoad = false;
408  try
409  {
410  Schematic().SetRoot( pi->Load( fullFileName, &Schematic() ) );
411 
412  if( !pi->GetError().IsEmpty() )
413  {
414  DisplayErrorMessage( this,
415  _( "The entire schematic could not be loaded. Errors "
416  "occurred attempting to load \nhierarchical sheet "
417  "schematics." ),
418  pi->GetError() );
419  }
420  }
421  catch( const IO_ERROR& ioe )
422  {
423  msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
424  DisplayErrorMessage( this, msg, ioe.What() );
425 
426  failedLoad = true;
427  }
428  catch( const std::bad_alloc& )
429  {
430  msg.Printf( _( "Memory exhausted loading schematic file '%s'." ), fullFileName );
431  DisplayErrorMessage( this, msg );
432 
433  failedLoad = true;
434  }
435 
436  if( failedLoad )
437  {
438  // Do not leave g_RootSheet == NULL because it is expected to be
439  // a valid sheet. Therefore create a dummy empty root sheet and screen.
440  CreateScreens();
442 
443  msg.Printf( _( "Failed to load '%s'." ), fullFileName );
444  SetMsgPanel( wxEmptyString, msg );
445 
446  return false;
447  }
448 
449  // It's possible the schematic parser fixed errors due to bugs so warn the user
450  // that the schematic has been fixed (modified).
451  SCH_SHEET_LIST sheetList = Schematic().GetSheets();
452 
453  if( sheetList.IsModified() )
454  {
455  DisplayInfoMessage( this,
456  _( "An error was found when loading the schematic that has "
457  "been automatically fixed. Please save the schematic to "
458  "repair the broken file or it may not be usable with other "
459  "versions of KiCad." ) );
460  }
461 
462  if( sheetList.AllSheetPageNumbersEmpty() )
463  sheetList.SetInitialPageNumbers();
464 
465  UpdateFileHistory( fullFileName );
466 
467  SCH_SCREENS schematic( Schematic().Root() );
468 
469  // LIB_ID checks and symbol rescue only apply to the legacy file formats.
470  if( schFileType == SCH_IO_MGR::SCH_LEGACY )
471  {
472  // Convert old projects over to use symbol library table.
473  if( schematic.HasNoFullyDefinedLibIds() )
474  {
475  DIALOG_SYMBOL_REMAP dlgRemap( this );
476 
477  dlgRemap.ShowQuasiModal();
478  }
479  else
480  {
481  // Double check to ensure no legacy library list entries have been
482  // added to the projec file symbol library list.
483  wxString paths;
484  wxArrayString libNames;
485 
486  SYMBOL_LIBS::LibNamesAndPaths( &Prj(), false, &paths, &libNames );
487 
488  if( !libNames.IsEmpty() )
489  {
491  {
492  wxRichMessageDialog invalidLibDlg(
493  this,
494  _( "Illegal entry found in project file symbol library list." ),
495  _( "Project Load Warning" ),
496  wxOK | wxCENTER | wxICON_EXCLAMATION );
497  invalidLibDlg.ShowDetailedText(
498  _( "Symbol libraries defined in the project file symbol library "
499  "list are no longer supported and will be removed.\n\n"
500  "This may cause broken symbol library links under certain "
501  "conditions." ) );
502  invalidLibDlg.ShowCheckBox( _( "Do not show this dialog again." ) );
503  invalidLibDlg.ShowModal();
505  !invalidLibDlg.IsCheckBoxChecked();
506  }
507 
508  libNames.Clear();
509  paths.Clear();
510  SYMBOL_LIBS::LibNamesAndPaths( &Prj(), true, &paths, &libNames );
511  }
512 
513  if( !cfg || !cfg->m_RescueNeverShow )
514  {
516  editor->RescueSymbolLibTableProject( false );
517  }
518  }
519 
520  // Ensure there is only one legacy library loaded and that it is the cache library.
521  SYMBOL_LIBS* legacyLibs = Schematic().Prj().SchLibs();
522 
523  if( legacyLibs->GetLibraryCount() == 0 )
524  {
525  wxString extMsg;
526  wxFileName cacheFn = pro;
527 
528  cacheFn.SetName( cacheFn.GetName() + "-cache" );
529  cacheFn.SetExt( LegacySymbolLibFileExtension );
530 
531  msg.Printf( _( "The project symbol library cache file '%s' was not found." ),
532  cacheFn.GetFullName() );
533  extMsg = _( "This can result in a broken schematic under certain conditions. "
534  "If the schematic does not have any missing symbols upon opening, "
535  "save it immediately before making any changes to prevent data "
536  "loss. If there are missing symbols, either manual recovery of "
537  "the schematic or recovery of the symbol cache library file and "
538  "reloading the schematic is required." );
539 
540  wxMessageDialog dlgMissingCache( this, msg, _( "Warning" ),
541  wxOK | wxCANCEL | wxICON_EXCLAMATION | wxCENTER );
542  dlgMissingCache.SetExtendedMessage( extMsg );
543  dlgMissingCache.SetOKCancelLabels(
544  wxMessageDialog::ButtonLabel( _( "Load Without Cache File" ) ),
545  wxMessageDialog::ButtonLabel( _( "Abort" ) ) );
546 
547  if( dlgMissingCache.ShowModal() == wxID_CANCEL )
548  {
549  Schematic().Reset();
550  CreateScreens();
551  return false;
552  }
553  }
554 
555  // Update all symbol library links for all sheets.
556  schematic.UpdateSymbolLinks();
557 
560  m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
561  "It will be converted to the new format when saved." ),
562  wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
563 
564  // Legacy schematic can have duplicate time stamps so fix that before converting
565  // to the s-expression format.
566  schematic.ReplaceDuplicateTimeStamps();
567 
568  // Allow the schematic to be saved to new file format without making any edits.
569  OnModify();
570  }
571  else // S-expression schematic.
572  {
574  {
577  m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
578  "It will be converted to the new format when saved." ),
579  wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
580  }
581 
582  for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
583  screen->UpdateLocalLibSymbolLinks();
584 
585  // Restore all of the loaded symbol and sheet instances from the root sheet.
586  sheetList.UpdateSymbolInstances( Schematic().RootScreen()->GetSymbolInstances() );
587  sheetList.UpdateSheetInstances( Schematic().RootScreen()->GetSheetInstances() );
588  }
589 
591 
592  SetScreen( GetCurrentSheet().LastScreen() );
593 
594  // Migrate conflicting bus definitions
595  // TODO(JE) This should only run once based on schematic file version
596  if( Schematic().ConnectionGraph()->GetBusesNeedingMigration().size() > 0 )
597  {
598  DIALOG_MIGRATE_BUSES dlg( this );
599  dlg.ShowQuasiModal();
601  OnModify();
602  }
603 
606  }
607 
608  // Load any exclusions from the project file
610 
611  initScreenZoom();
613 
616 
617  // re-create junctions if needed. Eeschema optimizes wires by merging
618  // colinear segments. If a schematic is saved without a valid
619  // cache library or missing installed libraries, this can cause connectivity errors
620  // unless junctions are added.
621  if( schFileType == SCH_IO_MGR::SCH_LEGACY )
622  FixupJunctions();
623 
624  SyncView();
626 
628  UpdateTitle();
629 
630  wxFileName fn = Prj().AbsolutePath( GetScreen()->GetFileName() );
631 
632  if( fn.FileExists() && !fn.IsFileWritable() )
633  {
636  m_infoBar->ShowMessage( _( "Schematic is read only." ), wxICON_WARNING );
637  }
638 
639 #ifdef PROFILE
640  openFiles.Show();
641 #endif
642 
643  return true;
644 }
645 
646 
648 {
649  wxString fullFileName;
650  SCH_SCREEN* screen = GetScreen();
651 
652  if( !screen )
653  {
654  wxLogError( wxT( "Document not ready, cannot import" ) );
655  return false;
656  }
657 
658  // open file chooser dialog
659  wxString path = wxPathOnly( Prj().GetProjectFullName() );
660 
661  wxFileDialog dlg( this, _( "Insert Schematic" ), path, wxEmptyString,
662  KiCadSchematicFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
663 
664  if( dlg.ShowModal() == wxID_CANCEL )
665  return false;
666 
667  fullFileName = dlg.GetPath();
668 
669  if( !LoadSheetFromFile( GetCurrentSheet().Last(), &GetCurrentSheet(), fullFileName ) )
670  return false;
671 
672  initScreenZoom();
674 
675  SyncView();
676  OnModify();
677  HardRedraw(); // Full reinit of the current screen and the display.
678 
680 
681  return true;
682 }
683 
684 
685 void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
686 {
687  if( GetScreen() && GetScreen()->IsModified() )
688  {
689  wxString msg = _( "This operation cannot be undone.\n\n"
690  "Do you want to save the current document before proceeding?" );
691 
692  if( IsOK( this, msg ) )
693  SaveProject();
694  }
695 
696  AppendSchematic();
697 }
698 
699 
700 void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
701 {
702  if( !AskToSaveChanges() )
703  return;
704 
705  // Set the project location if none is set or if we are running in standalone mode
706  bool setProject = Prj().GetProjectFullName().IsEmpty() || Kiface().IsSingle();
707  wxString path = wxPathOnly( Prj().GetProjectFullName() );
708 
709  std::list<std::pair<const wxString, const SCH_IO_MGR::SCH_FILE_T>> loaders;
710 
711  // Import Altium schematic files.
712  loaders.emplace_back( AltiumSchematicFileWildcard(), SCH_IO_MGR::SCH_ALTIUM );
713 
714  // Import CADSTAR Schematic Archive files.
715  loaders.emplace_back( CadstarSchematicArchiveFileWildcard(), SCH_IO_MGR::SCH_CADSTAR_ARCHIVE );
716 
717  // Import Eagle schematic files.
718  loaders.emplace_back( EagleSchematicFileWildcard(), SCH_IO_MGR::SCH_EAGLE );
719 
720  wxString fileFilters;
721  wxString allWildcards;
722 
723  for( std::pair<const wxString, const SCH_IO_MGR::SCH_FILE_T>& loader : loaders )
724  {
725  if( !fileFilters.IsEmpty() )
726  fileFilters += wxChar( '|' );
727 
728  fileFilters += wxGetTranslation( loader.first );
729 
730  SCH_PLUGIN::SCH_PLUGIN_RELEASER plugin( SCH_IO_MGR::FindPlugin( loader.second ) );
731  wxCHECK( plugin, /*void*/ );
732  allWildcards += "*." + formatWildcardExt( plugin->GetFileExtension() ) + ";";
733  }
734 
735  fileFilters = _( "All supported formats|" ) + allWildcards + "|" + fileFilters;
736 
737  wxFileDialog dlg( this, _( "Import Schematic" ), path, wxEmptyString, fileFilters,
738  wxFD_OPEN | wxFD_FILE_MUST_EXIST ); // TODO
739 
740  if( dlg.ShowModal() == wxID_CANCEL )
741  return;
742 
743  if( setProject )
744  {
745  Schematic().SetProject( nullptr );
746  GetSettingsManager()->UnloadProject( &Prj(), false );
747 
748  Schematic().Reset();
749 
750  wxFileName projectFn( dlg.GetPath() );
751  projectFn.SetExt( ProjectFileExtension );
752  GetSettingsManager()->LoadProject( projectFn.GetFullPath() );
753 
754  Schematic().SetProject( &Prj() );
755  }
756 
757  wxFileName fn = dlg.GetPath();
758 
759  SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN;
760 
761  for( std::pair<const wxString, const SCH_IO_MGR::SCH_FILE_T>& loader : loaders )
762  {
763  if( fn.GetExt().CmpNoCase( SCH_IO_MGR::GetFileExtension( loader.second ) ) == 0 )
764  {
765  pluginType = loader.second;
766  break;
767  }
768  }
769 
770  if( pluginType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
771  {
772  wxLogError( wxString::Format( "unexpected file extension: %s", fn.GetExt() ) );
773  return;
774  }
775 
776  m_toolManager->GetTool<EE_SELECTION_TOOL>()->ClearSelection();
777 
778  importFile( dlg.GetPath(), pluginType );
779 
780  RefreshCanvas();
781 }
782 
783 
785 {
786  wxString msg;
787  SCH_SCREEN* screen;
788  SCH_SCREENS screens( Schematic().Root() );
789  bool success = true;
790  bool updateFileType = false;
791 
792  // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
793  wxString fileName = Prj().AbsolutePath( Schematic().Root().GetFileName() );
794  wxFileName fn = fileName;
795 
796  // If this a new schematic without a project and we are in the stand alone mode. All new
797  // sheets that are not loaded from an existing file will have to be saved to a new path
798  // along with the root sheet.
799  if( Prj().GetProjectFullName().IsEmpty() )
800  {
801  // This should only be possible in stand alone mode.
802  wxCHECK( Kiface().IsSingle(), false );
803 
804  wxFileDialog dlg( this, _( "Schematic Files" ), fn.GetPath(), fn.GetFullName(),
805  KiCadSchematicFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
806 
807  if( dlg.ShowModal() == wxID_CANCEL )
808  return false;
809 
810  wxFileName newFileName = dlg.GetPath();
811 
812  if( newFileName.GetExt().IsEmpty() )
813  newFileName.SetExt( KiCadSchematicFileExtension );
814 
815  if( ( !newFileName.DirExists() && !newFileName.Mkdir() ) || !newFileName.IsDirWritable() )
816  {
817  msg.Printf( _( "Folder '%s' could not be created.\n\n"
818  "Make sure you have write permissions and try again." ),
819  newFileName.GetPath() );
820 
821  wxMessageDialog dlgBadPath( this, msg, _( "Error" ),
822  wxOK | wxICON_EXCLAMATION | wxCENTER );
823 
824  dlgBadPath.ShowModal();
825  return false;
826  }
827 
828  Schematic().Root().SetFileName( newFileName.GetFullName() );
829  Schematic().RootScreen()->SetFileName( newFileName.GetFullPath() );
830 
831  // Set the base path to all new sheets.
832  for( size_t i = 0; i < screens.GetCount(); i++ )
833  {
834  screen = screens.GetScreen( i );
835 
836  wxCHECK2( screen, continue );
837 
838  // The root screen file name has already been set.
839  if( screen == Schematic().RootScreen() )
840  continue;
841 
842  wxFileName tmp = screen->GetFileName();
843 
844  // Assume existing sheet files are being reused and do not save them to the new
845  // path. Maybe in the future, add a user option to copy schematic files to the
846  // new project path.
847  if( tmp.FileExists() )
848  continue;
849 
850  if( tmp.GetPath().IsEmpty() )
851  {
852  tmp.SetPath( newFileName.GetPath() );
853  }
854  else if( tmp.GetPath() == fn.GetPath() )
855  {
856  tmp.SetPath( newFileName.GetPath() );
857  }
858  else if( tmp.GetPath().StartsWith( fn.GetPath() ) )
859  {
860  // NOTE: this hasn't been tested because the sheet properties dialog no longer
861  // allows adding a path specifier in the file name field.
862  wxString newPath = newFileName.GetPath();
863  newPath += tmp.GetPath().Right( fn.GetPath().Length() );
864  tmp.SetPath( newPath );
865  }
866 
867  wxLogTrace( tracePathsAndFiles,
868  wxT( "Moving schematic from '%s' to '%s'." ),
869  screen->GetFileName(),
870  tmp.GetFullPath() );
871 
872  if( !tmp.DirExists() && !tmp.Mkdir() )
873  {
874  msg.Printf( _( "Folder '%s' could not be created.\n\n"
875  "Make sure you have write permissions and try again." ),
876  newFileName.GetPath() );
877 
878  wxMessageDialog dlgBadFilePath( this, msg, _( "Error" ),
879  wxOK | wxICON_EXCLAMATION | wxCENTER );
880 
881  dlgBadFilePath.ShowModal();
882  return false;
883  }
884 
885  screen->SetFileName( tmp.GetFullPath() );
886  }
887 
888  // Attempt to make sheet file name paths relative to the new root schematic path.
889  SCH_SHEET_LIST sheets = Schematic().GetSheets();
890 
891  for( SCH_SHEET_PATH& sheet : sheets )
892  {
893  if( sheet.Last()->IsRootSheet() )
894  continue;
895 
896  sheet.MakeFilePathRelativeToParentSheet();
897  }
898  }
899 
900  // Warn user on potential file overwrite. This can happen on shared sheets.
901  wxArrayString overwrittenFiles;
902 
903  for( size_t i = 0; i < screens.GetCount(); i++ )
904  {
905  screen = screens.GetScreen( i );
906 
907  wxCHECK2( screen, continue );
908 
909  // Convert legacy schematics file name extensions for the new format.
910  wxFileName tmpFn = screen->GetFileName();
911 
912  if( !tmpFn.IsOk() )
913  continue;
914 
915  if( tmpFn.GetExt() == KiCadSchematicFileExtension )
916  continue;
917 
918  tmpFn.SetExt( KiCadSchematicFileExtension );
919 
920  if( tmpFn.FileExists() )
921  overwrittenFiles.Add( tmpFn.GetFullPath() );
922  }
923 
924  if( !overwrittenFiles.IsEmpty() )
925  {
926  for( const wxString& overwrittenFile : overwrittenFiles )
927  {
928  if( msg.IsEmpty() )
929  msg = overwrittenFile;
930  else
931  msg += "\n" + overwrittenFile;
932  }
933 
934  wxRichMessageDialog dlg( this, _( "Saving will overwrite existing files." ),
935  _( "Save Warning" ),
936  wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER |
937  wxICON_EXCLAMATION );
938  dlg.ShowDetailedText( _( "The following files will be overwritten:\n\n" ) + msg );
939  dlg.SetOKCancelLabels( wxMessageDialog::ButtonLabel( _( "Overwrite Files" ) ),
940  wxMessageDialog::ButtonLabel( _( "Abort Project Save" ) ) );
941 
942  if( dlg.ShowModal() == wxID_CANCEL )
943  return false;
944  }
945 
946  screens.BuildClientSheetPathList();
947 
948  for( size_t i = 0; i < screens.GetCount(); i++ )
949  {
950  screen = screens.GetScreen( i );
951 
952  wxCHECK2( screen, continue );
953 
954  // Convert legacy schematics file name extensions for the new format.
955  wxFileName tmpFn = screen->GetFileName();
956 
957  if( tmpFn.IsOk() && tmpFn.GetExt() != KiCadSchematicFileExtension )
958  {
959  updateFileType = true;
960  tmpFn.SetExt( KiCadSchematicFileExtension );
961 
962  for( auto item : screen->Items().OfType( SCH_SHEET_T ) )
963  {
964  SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
965  wxFileName sheetFileName = sheet->GetFileName();
966 
967  if( !sheetFileName.IsOk() || sheetFileName.GetExt() == KiCadSchematicFileExtension )
968  continue;
969 
970  sheetFileName.SetExt( KiCadSchematicFileExtension );
971  sheet->SetFileName( sheetFileName.GetFullPath() );
972  UpdateItem( sheet );
973  }
974 
975  screen->SetFileName( tmpFn.GetFullPath() );
976  }
977 
978  std::vector<SCH_SHEET_PATH>& sheets = screen->GetClientSheetPaths();
979 
980  if( sheets.size() == 1 )
981  screen->SetVirtualPageNumber( 1 );
982  else
983  screen->SetVirtualPageNumber( 0 ); // multiple uses; no way to store the real sheet #
984 
985  success &= SaveEEFile( screens.GetSheet( i ) );
986  }
987 
988  if( updateFileType )
989  UpdateFileHistory( Schematic().RootScreen()->GetFileName() );
990 
991  // Save the sheet name map to the project file
992  std::vector<FILE_INFO_PAIR>& sheets = Prj().GetProjectFile().GetSheets();
993  sheets.clear();
994 
995  for( SCH_SHEET_PATH& sheetPath : Schematic().GetSheets() )
996  {
997  SCH_SHEET* sheet = sheetPath.Last();
998 
999  wxCHECK2( sheet, continue );
1000 
1001  // Use the schematic UUID for the root sheet.
1002  if( sheet->IsRootSheet() )
1003  {
1004  screen = sheet->GetScreen();
1005 
1006  wxCHECK2( screen, continue );
1007 
1008  sheets.emplace_back( std::make_pair( screen->GetUuid(), sheet->GetName() ) );
1009  }
1010  else
1011  {
1012  sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
1013  }
1014  }
1015 
1016  if( !Prj().IsNullProject() )
1017  Pgm().GetSettingsManager().SaveProject();
1018 
1019  if( !Kiface().IsSingle() )
1020  {
1021  WX_STRING_REPORTER backupReporter( &msg );
1022 
1023  if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1024  SetStatusText( msg, 0 );
1025  }
1026 
1027  UpdateTitle();
1028 
1030 
1031  return success;
1032 }
1033 
1034 
1036 {
1037  wxFileName tmpFileName = Schematic().Root().GetFileName();
1038  wxFileName fn = tmpFileName;
1039  wxFileName tmp;
1040  SCH_SCREENS screens( Schematic().Root() );
1041 
1042  // Don't run autosave if content has not been modified
1043  if( !IsContentModified() )
1044  return true;
1045 
1046  bool autoSaveOk = true;
1047 
1048  if( fn.GetPath().IsEmpty() )
1049  tmp.AssignDir( Prj().GetProjectPath() );
1050  else
1051  tmp.AssignDir( fn.GetPath() );
1052 
1053  if( !tmp.IsOk() )
1054  return false;
1055 
1056  if( !IsWritable( tmp ) )
1057  return false;
1058 
1059  wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1060 
1061  for( size_t i = 0; i < screens.GetCount(); i++ )
1062  {
1063  // Only create auto save files for the schematics that have been modified.
1064  if( !screens.GetScreen( i )->IsContentModified() )
1065  continue;
1066 
1067  tmpFileName = fn = screens.GetScreen( i )->GetFileName();
1068 
1069  // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1070  fn.SetName( GetAutoSaveFilePrefix() + fn.GetName() );
1071 
1072  screens.GetScreen( i )->SetFileName( fn.GetFullPath() );
1073 
1074  if( SaveEEFile( screens.GetSheet( i ), false ) )
1075  screens.GetScreen( i )->SetContentModified();
1076  else
1077  autoSaveOk = false;
1078 
1079  screens.GetScreen( i )->SetFileName( tmpFileName.GetFullPath() );
1080  }
1081 
1082  if( autoSaveOk )
1083  {
1084  m_autoSaveState = false;
1085 
1086  if( !Kiface().IsSingle() &&
1088  {
1090  }
1091  }
1092 
1093  SetTitle( title );
1094 
1095  return autoSaveOk;
1096 }
1097 
1098 
1099 bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
1100 {
1101  wxFileName newfilename;
1102  SCH_SHEET_LIST sheetList = Schematic().GetSheets();
1103  SCH_IO_MGR::SCH_FILE_T fileType = (SCH_IO_MGR::SCH_FILE_T) aFileType;
1104 
1105  switch( fileType )
1106  {
1107  case SCH_IO_MGR::SCH_ALTIUM:
1108  case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
1109  case SCH_IO_MGR::SCH_EAGLE:
1110  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
1111  wxASSERT_MSG( wxFileName( aFileName ).IsAbsolute(),
1112  wxT( "Import schematic caller didn't send full filename" ) );
1113 
1114  if( !LockFile( aFileName ) )
1115  {
1116  wxString msg = wxString::Format( _( "Schematic '%s' is already open." ), aFileName );
1117  DisplayError( this, msg );
1118  return false;
1119  }
1120 
1121  try
1122  {
1123  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
1124  DIALOG_HTML_REPORTER errorReporter( this );
1125  WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
1126 
1127  pi->SetReporter( errorReporter.m_Reporter );
1128  pi->SetProgressReporter( &progressReporter );
1129  Schematic().SetRoot( pi->Load( aFileName, &Schematic() ) );
1130 
1131  if( errorReporter.m_Reporter->HasMessage() )
1132  {
1133  errorReporter.m_Reporter->Flush(); // Build HTML messages
1134  errorReporter.ShowModal();
1135  }
1136 
1137  // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works differently
1138  // to KiCad), so set it to an empty one
1139  DS_DATA_MODEL& drawingSheet = DS_DATA_MODEL::GetTheInstance();
1140  drawingSheet.SetEmptyLayout();
1141 
1142  BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";
1143  wxFileName layoutfn( Prj().GetProjectPath(), BASE_SCREEN::m_DrawingSheetFileName );
1144  wxFFile layoutfile;
1145 
1146  if( layoutfile.Open( layoutfn.GetFullPath(), "wb" ) )
1147  {
1148  layoutfile.Write( DS_DATA_MODEL::EmptyLayout() );
1149  layoutfile.Close();
1150  }
1151 
1152  newfilename.SetPath( Prj().GetProjectPath() );
1153  newfilename.SetName( Prj().GetProjectName() );
1154  newfilename.SetExt( KiCadSchematicFileExtension );
1155 
1156  SetScreen( GetCurrentSheet().LastScreen() );
1157 
1158  Schematic().Root().SetFileName( newfilename.GetFullPath() );
1159  GetScreen()->SetFileName( newfilename.GetFullPath() );
1161 
1162  // Only fix junctions for CADSTAR importer for now as it may cause issues with
1163  // other importers
1164  if( fileType == SCH_IO_MGR::SCH_CADSTAR_ARCHIVE )
1165  {
1166  FixupJunctions();
1168  }
1169 
1170  // Only perform the dangling end test on root sheet.
1172 
1174 
1175  initScreenZoom();
1177  SyncView();
1178 
1180  UpdateTitle();
1181  }
1182  catch( const IO_ERROR& ioe )
1183  {
1184  // Do not leave g_RootSheet == NULL because it is expected to be
1185  // a valid sheet. Therefore create a dummy empty root sheet and screen.
1186  CreateScreens();
1188 
1189  wxString msg = wxString::Format( _( "Error loading schematic '%s'." ), aFileName );
1190  DisplayErrorMessage( this, msg, ioe.What() );
1191 
1192  msg.Printf( _( "Failed to load '%s'." ), aFileName );
1193  SetMsgPanel( wxEmptyString, msg );
1194 
1195  return false;
1196  }
1197 
1198  return true;
1199 
1200  default:
1201  return false;
1202  }
1203 }
1204 
1205 
1207 {
1208  SCH_SCREENS screenList( Schematic().Root() );
1209 
1210  // Save any currently open and modified project files.
1211  for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
1212  {
1213  if( screen->IsContentModified() )
1214  {
1215  if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. "
1216  "Save changes?" ),
1217  [&]()->bool { return SaveProject(); } ) )
1218  {
1219  return false;
1220  }
1221  }
1222  }
1223 
1224  return true;
1225 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:252
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:216
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: infobar.cpp:134
void Save_File(bool doSaveAs=false)
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:207
const wxString & GetFileName() const
Definition: sch_screen.h:137
Handle the graphic items list to draw/plot the frame and title block.
Definition: ds_data_model.h:38
SCH_SCREEN * GetNext()
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Open a project or set of files given by aFileList.
static void LibNamesAndPaths(PROJECT *aProject, bool doSave, wxString *aPaths, wxArrayString *aNames=NULL)
Save or load the names of the currently configured symbol libraries (without paths).
bool IsContentModified() const
Definition: base_screen.h:60
void SetVirtualPageNumber(int aPageNumber)
Definition: base_screen.h:76
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:265
SETTINGS_MANAGER * GetSettingsManager() const
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
void RecalculateConnections(SCH_CLEANUP_FLAGS aCleanupFlags)
Generate the connection data for the entire schematic hierarchy.
Model changes (required full reload)
Definition: tool_base.h:80
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:129
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
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...
bool IsModified() const
Check the entire hierarchy for any modifications.
const std::string ProjectFileExtension
void SetScreen(BASE_SCREEN *aScreen) override
const std::string LegacySymbolLibFileExtension
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
void Flush()
Build the HTML messages page.
bool AskToSaveChanges()
Check if any of the screens has unsaved changes and asks the user whether to save or drop them.
wxString KiCadSchematicFileWildcard()
int GetFileFormatVersionAtLoad() const
Definition: sch_screen.h:122
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
AUTO_BACKUP m_Backup
void ResolveERCExclusions()
Update markers to match recorded exclusions.
static TOOL_ACTION zoomFitScreen
Definition: actions.h:96
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
Definition: sch_screen.cpp:972
void UpdateTitle()
Set the main window title bar text.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
void OnAppendProject(wxCommandEvent &event)
int GetLibraryCount()
void RefreshCanvas() override
void AssignNewUuid()
Definition: sch_screen.h:465
bool IsWritable(const wxFileName &aFileName)
Checks if aFileName can be written.
void UpdateAllScreenReferences()
Update all the symbol references for this sheet path.
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
A small class to help profiling.
Definition: profile.h:45
bool importFile(const wxString &aFileName, int aFileType)
Load the given filename but sets the path to the current project path.
bool SaveEEFile(SCH_SHEET *aSheet, bool aSaveUnderNewName=false)
Save aSheet to a schematic file.
void LoadWindowState(const wxString &aFileName)
bool IsContentModified() const override
Get if the current schematic has been modified but not saved.
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
void UpdateSheetInstances(const std::vector< SCH_SHEET_INSTANCE > &aSheetInstances)
Update all of the sheet instance information using aSheetInstances.
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:271
void OnImportProject(wxCommandEvent &event)
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:259
EESCHEMA_SETTINGS * eeconfig() const
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:70
void SetShutdownBlockReason(wxWindow *aWindow, const wxString &aReason)
Sets the block reason why the window/application is preventing OS shutdown.
Definition: gtk/app.cpp:83
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:104
Handle actions specific to the schematic editor.
static SCH_FILE_T GuessPluginTypeFromSchPath(const wxString &aSchematicPath)
Return a plugin type given a schematic using the file extension of aSchematicPath.
Definition: sch_io_mgr.cpp:169
wxString GetMruPath() const
wxString CadstarSchematicArchiveFileWildcard()
bool HasMessage() const override
Returns true if the reporter client is non-empty.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: infobar.cpp:176
static DS_DATA_MODEL & GetTheInstance()
static function: returns the instance of DS_DATA_MODEL used in the application
Base class that schematic file and library loading and saving plugins should derive from.
Definition: sch_io_mgr.h:152
Multi-thread safe progress reporter dialog, intended for use of tasks that paralleize reporting back ...
void SetFileName(wxString aFilename)
Definition: sch_sheet.h:321
bool LoadSheetFromFile(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, const wxString &aFileName)
Load a the KiCad schematic file aFileName into the sheet aSheet.
Definition: sheet.cpp:105
void CheckForAutoSaveFile(const wxFileName &aFileName)
Check if an auto save file exists for aFileName and takes the appropriate action depending on the use...
wxString GetName() const
Definition: sch_sheet.h:101
bool IsSingle() const
Is this KIFACE_I running under single_top?
Definition: kiface_i.h:104
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.
void HardRedraw() override
Rebuild the GAL and redraw the screen.
void SyncView()
Mark all items for refresh.
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Calls BackupProject if a new backup is needed according to the current backup policy.
static const wxString GetFileExtension(SCH_FILE_T aFileType)
Return the schematic file extension for aFileType.
Definition: sch_io_mgr.cpp:121
WX_HTML_REPORT_BOX * m_Reporter
int ShowQuasiModal()
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
bool IsRootSheet() const
Definition: sch_sheet.cpp:189
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
void initScreenZoom()
Initialize the zoom value of the current screen and mark the screen as zoom-initialized.
static void ResolvePossibleSymlinks(wxFileName &aFilename)
Definition: wx_filename.cpp:85
COMMON_SETTINGS * GetCommonSettings() const
Retrieves the common settings shared by all applications.
SCHEMATIC & Schematic() const
Class DIALOG_HTML_REPORTER.
void UpdateHierarchyNavigator(bool aForceUpdate=false)
Run the Hierarchy Navigator dialog.
void BuildClientSheetPathList()
built the list of sheet paths sharing a screen for each screen in use
Definition of file extensions used in Kicad.
bool AppendSchematic()
Import a KiCad schematic into the current sheet.
static wxString EmptyLayout()
Return a string containing the empty layout shape.
bool CreateArchiveLibraryCacheFile(bool aUseCurrentSheetFilename=false)
Create a symbol library file with the name of the root document plus the '-cache' suffix,...
Definition: libarch.cpp:42
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition for symbol library class.
#define _(s)
wxLogTrace helper definitions.
size_t GetCount() const
Definition: sch_screen.h:557
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:117
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:315
FormatType fileType(const char *aFileName)
Definition: loadmodel.cpp:273
const std::string LegacyProjectFileExtension
void SetProject(PROJECT *aPrj)
Definition: schematic.cpp:76
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:135
void UpdateSymbolInstances(const std::vector< SYMBOL_INSTANCE_REFERENCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
const std::string LegacySchematicFileExtension
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:287
bool LoadProjectSettings()
Load the KiCad project file (*.pro) settings specific to Eeschema.
A collection of SYMBOL_LIB objects.
A wrapper for reporting to a wxString object.
Definition: reporter.h:159
void DismissOutdatedSave()
Dismisses the infobar for outdated save warnings and updates the containing layout and AUI manager (i...
Definition: infobar.cpp:167
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
bool doAutoSave() override
Save the schematic files that have been modified and not yet saved.
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
const KIID m_Uuid
Definition: eda_item.h:475
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
static wxString GetAutoSaveFilePrefix()
const KIID & GetUuid() const
Definition: sch_screen.h:463
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:479
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:130
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
Definition: schematic.cpp:51
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
std::vector< FILE_INFO_PAIR > & GetSheets()
Definition: project_file.h:84
bool AllSheetPageNumbersEmpty() const
Check all of the sheet instance for empty page numbers.
SCH_SHEET & Root() const
Definition: schematic.h:92
virtual void SetReadOnly(bool aReadOnly=true)
Definition: project.h:126
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:156
see class PGM_BASE
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
wxString EagleSchematicFileWildcard()
WX_INFOBAR * m_infoBar
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition: base_screen.h:85
void RecomputeIntersheetRefs()
Update the schematic's page reference map for all global labels, and refresh the labels so that they ...
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
EE_RTREE & Items()
Definition: sch_screen.h:102
bool SaveProject(const wxString &aFullPath=wxEmptyString)
Saves a loaded project.
SCH_SHEET * GetSheet(unsigned int aIndex) const
const std::string KiCadSchematicFileExtension
wxString GetCurrentFileName() const override
Get the full filename + path of the currently opened file in the frame.
OUTDATED_SAVE Messages that should be cleared on save.
bool backup_on_autosave
Trigger a backup on autosave.
SCH_SHEET_PATH & GetCurrentSheet() const
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition: sch_screen.h:163
SCH_SCREEN * GetFirst()
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition: profile.h:102
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
void ClearDrawingState()
Clear the state flags of all the items in the screen.
Definition: sch_screen.cpp:825
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:108
static REPORTER & GetInstance()
Definition: reporter.cpp:108
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:117
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:280
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:296
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
wxString AltiumSchematicFileWildcard()
void SetInitialPageNumbers()
Set initial sheet page numbers.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:551
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
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
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:277