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-2017 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 
31 #include <fctsys.h>
32 #include <class_drawpanel.h>
33 #include <confirm.h>
34 #include <gestfich.h>
35 #include <schframe.h>
36 #include <pgm_base.h>
37 #include <kiface_i.h>
38 #include <richio.h>
39 
40 #include <eeschema_id.h>
41 #include <class_library.h>
42 #include <libeditframe.h>
43 #include <sch_sheet.h>
44 #include <sch_sheet_path.h>
45 #include <sch_component.h>
47 #include <project_rescue.h>
48 #include <eeschema_config.h>
49 #include <sch_legacy_plugin.h>
50 #include <sch_eagle_plugin.h>
51 #include <symbol_lib_table.h>
52 #include <dialog_symbol_remap.h>
53 
54 
55 bool SCH_EDIT_FRAME::SaveEEFile( SCH_SCREEN* aScreen, bool aSaveUnderNewName,
56  bool aCreateBackupFile )
57 {
58  wxString msg;
59  wxFileName schematicFileName;
60  bool success;
61 
62  if( aScreen == NULL )
63  aScreen = GetScreen();
64 
65  // If no name exists in the window yet - save as new.
66  if( aScreen->GetFileName().IsEmpty() )
67  aSaveUnderNewName = true;
68 
69  // Construct the name of the file to be saved
70  schematicFileName = Prj().AbsolutePath( aScreen->GetFileName() );
71 
72  if( aSaveUnderNewName )
73  {
74  wxFileDialog dlg( this, _( "Schematic Files" ),
75  wxPathOnly( Prj().GetProjectFullName() ),
76  schematicFileName.GetFullName(), SchematicFileWildcard(),
77  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
78 
79  if( dlg.ShowModal() == wxID_CANCEL )
80  return false;
81 
82  schematicFileName = dlg.GetPath();
83 
84  if( schematicFileName.GetExt() != SchematicFileExtension )
85  schematicFileName.SetExt( SchematicFileExtension );
86  }
87 
88  if( !IsWritable( schematicFileName ) )
89  return false;
90 
91  // Create backup if requested
92  if( aCreateBackupFile && schematicFileName.FileExists() )
93  {
94  wxFileName backupFileName = schematicFileName;
95 
96  // Rename the old file to a '.bak' one:
97  backupFileName.SetExt( SchematicBackupFileExtension );
98 
99  if( backupFileName.FileExists() )
100  wxRemoveFile( backupFileName.GetFullPath() );
101 
102  if( !wxRenameFile( schematicFileName.GetFullPath(), backupFileName.GetFullPath() ) )
103  {
104  msg.Printf( _( "Could not save backup of file \"%s\"" ),
105  GetChars( schematicFileName.GetFullPath() ) );
106  DisplayError( this, msg );
107  }
108  }
109 
110  // Save
111  wxLogTrace( traceAutoSave,
112  wxT( "Saving file <" ) + schematicFileName.GetFullPath() + wxT( ">" ) );
113 
114  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
115 
116  try
117  {
118  pi->Save( schematicFileName.GetFullPath(), aScreen, &Kiway() );
119  success = true;
120  }
121  catch( const IO_ERROR& ioe )
122  {
123  msg.Printf( _( "Error saving schematic file \"%s\".\n%s" ),
124  GetChars( schematicFileName.GetFullPath() ), GetChars( ioe.What() ) );
125  DisplayError( this, msg );
126 
127  msg.Printf( _( "Failed to save \"%s\"" ), GetChars( schematicFileName.GetFullPath() ) );
128  AppendMsgPanel( wxEmptyString, msg, CYAN );
129 
130  success = false;
131  }
132 
133  if( success )
134  {
135  // Delete auto save file.
136  wxFileName autoSaveFileName = schematicFileName;
137  autoSaveFileName.SetName( AUTOSAVE_PREFIX_FILENAME + schematicFileName.GetName() );
138 
139  if( autoSaveFileName.FileExists() )
140  {
141  wxLogTrace( traceAutoSave,
142  wxT( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
143  wxT( ">" ) );
144 
145  wxRemoveFile( autoSaveFileName.GetFullPath() );
146  }
147 
148  // Update the screen and frame info.
149  if( aSaveUnderNewName )
150  aScreen->SetFileName( schematicFileName.GetFullPath() );
151 
152  aScreen->ClrSave();
153  aScreen->ClrModify();
154 
155  msg.Printf( _( "File %s saved" ), GetChars( aScreen->GetFileName() ) );
156  SetStatusText( msg, 0 );
157  }
158  else
159  {
160  DisplayError( this, _( "File write operation failed." ) );
161  }
162 
163  return success;
164 }
165 
166 
167 void SCH_EDIT_FRAME::Save_File( wxCommandEvent& event )
168 {
169  int id = event.GetId();
170 
171  switch( id )
172  {
173  case ID_UPDATE_ONE_SHEET:
174  SaveEEFile( NULL );
175  break;
176 
178  if( SaveEEFile( NULL, true ) )
179  {
181  }
182  break;
183  }
184 
185  UpdateTitle();
186 }
187 
188 
189 bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
190 {
191  // implement the pseudo code from KIWAY_PLAYER.h:
192 
193  // This is for python:
194  if( aFileSet.size() != 1 )
195  {
196  UTF8 msg = StrPrintf( "Eeschema:%s() takes only a single filename.", __func__ );
197  DisplayError( this, msg );
198  return false;
199  }
200 
201  wxString fullFileName( aFileSet[0] );
202 
203  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
204  wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
205  wxT( "bug in single_top.cpp or project manager." ) );
206 
207  if( !LockFile( fullFileName ) )
208  {
209  wxString msg = wxString::Format( _(
210  "Schematic file \"%s\" is already open." ),
211  GetChars( fullFileName )
212  );
213  DisplayError( this, msg );
214  return false;
215  }
216 
217  if( !AskToSaveChanges() )
218  return false;
219 
220  wxFileName pro = fullFileName;
221  pro.SetExt( ProjectFileExtension );
222 
223  bool is_new = !wxFileName::IsFileReadable( fullFileName );
224 
225  // If its a non-existent schematic and caller thinks it exists
226  if( is_new && !( aCtl & KICTL_CREATE ) )
227  {
228  // notify user that fullFileName does not exist, ask if user wants to create it.
229  wxString ask = wxString::Format( _(
230  "Schematic \"%s\" does not exist. Do you wish to create it?" ),
231  GetChars( fullFileName )
232  );
233  if( !IsOK( this, ask ) )
234  return false;
235  }
236 
237  // unload current project file before loading new
238  {
239  delete g_RootSheet;
240  g_RootSheet = NULL;
241 
242  CreateScreens();
243  }
244 
245  GetScreen()->SetFileName( fullFileName );
246  g_RootSheet->SetFileName( fullFileName );
247 
248  SetStatusText( wxEmptyString );
249  ClearMsgPanel();
250 
251  LoadProjectFile();
252 
253  // PROJECT::SetProjectFullName() is an impactful function. It should only be
254  // called under carefully considered circumstances.
255 
256  // The calling code should know not to ask me here to change projects unless
257  // it knows what consequences that will have on other KIFACEs running and using
258  // this same PROJECT. It can be very harmful if that calling code is stupid.
259 
260  // Don't reload the symbol libraries if we are just launching Eeschema from KiCad again.
261  // They are already saved in the kiface project object.
262  if( pro.GetFullPath() != Prj().GetProjectFullName()
264  {
265  Prj().SetProjectFullName( pro.GetFullPath() );
266 
267  // load the libraries here, not in SCH_SCREEN::Draw() which is a context
268  // that will not tolerate DisplayError() dialog since we're already in an
269  // event handler in there.
270  // And when a schematic file is loaded, we need these libs to initialize
271  // some parameters (links to PART LIB, dangling ends ...)
273  Prj().SchLibs();
274  }
275 
276  // Load the symbol library table, this will be used forever more.
278  Prj().SchSymbolLibTable();
279 
280  if( is_new )
281  {
282  // mark new, unsaved file as modified.
283  GetScreen()->SetModify();
284  }
285  else
286  {
287  delete g_RootSheet; // Delete the current project.
288  g_RootSheet = NULL; // Force CreateScreens() to build new empty project on load failure.
289  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
290 
291  try
292  {
293  g_RootSheet = pi->Load( fullFileName, &Kiway() );
294  m_CurrentSheet->clear();
295  m_CurrentSheet->push_back( g_RootSheet );
296 
297  if( !pi->GetError().IsEmpty() )
298  {
299  DisplayErrorMessage( this,
300  _( "The entire schematic could not be load. Errors "
301  "occurred attempting to load hierarchical sheet "
302  "schematics." ),
303  pi->GetError() );
304  }
305  }
306  catch( const IO_ERROR& ioe )
307  {
308  // Do not leave g_RootSheet == NULL because it is expected to be
309  // a valid sheet. Therefore create a dummy empty root sheet and screen.
310  CreateScreens();
311  Zoom_Automatique( false );
312 
313  wxString msg;
314  msg.Printf( _( "Error loading schematic file \"%s\".\n%s" ),
315  GetChars( fullFileName ), GetChars( ioe.What() ) );
316  DisplayError( this, msg );
317 
318  msg.Printf( _( "Failed to load \"%s\"" ), GetChars( fullFileName ) );
319  AppendMsgPanel( wxEmptyString, msg, CYAN );
320 
321  return false;
322  }
323 
325 
326  // It's possible the schematic parser fixed errors due to bugs so warn the user
327  // that the schematic has been fixed (modified).
328  SCH_SHEET_LIST sheetList( g_RootSheet );
329 
330  if( sheetList.IsModified() )
331  {
332  DisplayInfoMessage( this,
333  _( "An error was found when loading the schematic that has "
334  "been automatically fixed. Please save the schematic to "
335  "repair the broken file or it may not be usable with other "
336  "versions of KiCad." ) );
337  }
338 
339  UpdateFileHistory( fullFileName );
340 
341  SCH_SCREENS schematic;
342 
343  // Convert old projects over to use symbol library table.
344  if( schematic.HasNoFullyDefinedLibIds() )
345  {
346  // Ignore the never show rescue setting for one last rescue of legacy symbol
347  // libraries before remapping to the symbol library table. This ensures the
348  // best remapping results.
349  RescueLegacyProject( false );
350 
351  DIALOG_SYMBOL_REMAP dlgRemap( this );
352 
353  dlgRemap.ShowQuasiModal();
354  }
355  else
356  {
357  // Check to see whether some old library parts need to be rescued
358  // Only do this if RescueNeverShow was not set.
359  wxConfigBase *config = Kiface().KifaceSettings();
360  bool rescueNeverShow = false;
361  config->Read( RescueNeverShowEntry, &rescueNeverShow, false );
362 
363  if( !rescueNeverShow )
365  }
366 
367  schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
368 
369  // Ensure the schematic is fully segmented on first display
371  SchematicCleanUp( true );
372  GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
373  GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
374  }
375 
377  Zoom_Automatique( false );
379  m_canvas->Refresh( true );
380 
381  return true;
382 }
383 
384 
386 {
387  wxString msg;
388  wxString fullFileName;
389 
390  SCH_SCREEN* screen = GetScreen();
391 
392  if( !screen )
393  {
394  wxLogError( wxT( "Document not ready, cannot import" ) );
395  return false;
396  }
397 
398  // open file chooser dialog
399  wxString path = wxPathOnly( Prj().GetProjectFullName() );
400 
401  wxFileDialog dlg( this, _( "Append Schematic" ), path,
402  wxEmptyString, SchematicFileWildcard(),
403  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
404 
405  if( dlg.ShowModal() == wxID_CANCEL )
406  return false;
407 
408  fullFileName = dlg.GetPath();
409 
410  wxFileName fn = fullFileName;
411 
412  if( fn.IsRelative() )
413  {
414  fn.MakeAbsolute();
415  fullFileName = fn.GetFullPath();
416  }
417 
418  wxString cache_name = PART_LIBS::CacheName( fullFileName );
419 
420  if( !!cache_name )
421  {
422  PART_LIBS* libs = Prj().SchLibs();
423 
424  try
425  {
426  if( PART_LIB* lib = libs->AddLibrary( cache_name ) )
427  lib->SetCache();
428  }
429  catch( const IO_ERROR& ioe )
430  {
431  DisplayError( this, ioe.What() );
432  }
433  }
434 
435  wxLogDebug( wxT( "Importing schematic " ) + fullFileName );
436 
437  // Load the schematic into a temporary sheet.
438  SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
439  std::unique_ptr< SCH_SHEET> newSheet( new SCH_SHEET );
440 
441  newSheet->SetFileName( fullFileName );
442 
443  try
444  {
445  pi->Load( fullFileName, &Kiway(), newSheet.get() );
446 
447  if( !pi->GetError().IsEmpty() )
448  {
449  DisplayErrorMessage( this,
450  _( "The entire schematic could not be load. Errors "
451  "occurred attempting to load hierarchical sheet "
452  "schematics." ),
453  pi->GetError() );
454  }
455  }
456  catch( const IO_ERROR& ioe )
457  {
458  msg.Printf( _( "Error occurred loading schematic file \"%s\"." ), fullFileName );
459  DisplayErrorMessage( this, msg, ioe.What() );
460 
461  msg.Printf( _( "Failed to load schematic \"%s\"" ), fullFileName );
462  AppendMsgPanel( wxEmptyString, msg, CYAN );
463 
464  return false;
465  }
466 
467  // Make sure any new sheet changes do not cause any recursion issues.
468  SCH_SHEET_LIST hierarchy( g_RootSheet ); // This is the schematic sheet hierarchy.
469  SCH_SHEET_LIST sheetHierarchy( newSheet.get() ); // This is the hierarchy of the import.
470 
471  wxFileName destFile = screen->GetFileName();
472 
473  if( destFile.IsRelative() )
474  destFile.MakeAbsolute( Prj().GetProjectPath() );
475 
476  if( hierarchy.TestForRecursion( sheetHierarchy, destFile.GetFullPath( wxPATH_UNIX ) ) )
477  {
478  msg.Printf( _( "The sheet changes cannot be made because the destination sheet already "
479  "has the sheet \"%s\" or one of it's subsheets as a parent somewhere in "
480  "the schematic hierarchy." ),
481  destFile.GetFullPath() );
482  DisplayError( this, msg );
483  return false;
484  }
485 
486  wxArrayString names;
487 
488  // Make sure the imported schematic has been remapped to the symbol library table.
489  SCH_SCREENS newScreens( newSheet.get() ); // All screens associated with the import.
490 
491  if( newScreens.HasNoFullyDefinedLibIds() )
492  {
493  if( !IsOK( this,
494  "This schematic has not been remapped to the symbol library table. "
495  "Therefore, all of the library symbol links will be broken. Do you "
496  "want to continue?" ) )
497  return false;
498  }
499  else
500  {
501  // If there are symbol libraries in the imported schematic that are not in the
502  // symbol library table of this project, there could be a lot of broken symbol
503  // library links. Attempt to add the missing libraries to the project symbol
504  // library table.
505  newScreens.GetLibNicknames( names );
506  wxArrayString newLibNames;
507 
508  for( auto name : names )
509  {
510  if( !Prj().SchSymbolLibTable()->HasLibrary( name ) )
511  newLibNames.Add( name );
512  }
513 
514  wxFileName symLibTableFn( fn.GetPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
515 
516  if( !newLibNames.IsEmpty() && symLibTableFn.Exists() && symLibTableFn.IsFileReadable() )
517  {
518  SYMBOL_LIB_TABLE table;
519 
520  try
521  {
522  table.Load( symLibTableFn.GetFullPath() );
523  }
524  catch( const IO_ERROR& ioe )
525  {
526  msg.Printf( _( "An error occurred loading the symbol library table \"%s\"." ),
527  symLibTableFn.GetFullPath() );
528  DisplayErrorMessage( NULL, msg, ioe.What() );
529  }
530 
531  if( !table.IsEmpty() )
532  {
533  for( auto libName : newLibNames )
534  {
535  if( !table.HasLibrary( libName ) )
536  continue;
537 
538  // Don't expand environment variable because KIPRJMOD will not be correct
539  // for a different project.
540  wxString uri = table.GetFullURI( libName, false );
541 
542  wxFileName newLib;
543 
544  if( uri.Contains( "${KIPRJMOD}" ) )
545  {
546  newLib.SetPath( fn.GetPath() );
547  newLib.SetFullName( uri.AfterLast( '}' ) );
548  uri = newLib.GetFullPath();
549  }
550  else
551  {
552  uri = table.GetFullURI( libName );
553  }
554 
555  // Add the library from the imported project to the current project
556  // symbol library table.
557  const SYMBOL_LIB_TABLE_ROW* row = table.FindRow( libName );
558 
559  wxCHECK2_MSG( row, continue, "Library '" + libName +
560  "' missing from symbol library table '" +
561  symLibTableFn.GetFullPath() + "'." );
562 
563  wxString newLibName = libName;
564  int libNameCnt = 1;
565 
566  // Rename the imported symbol library if it already exists.
567  while( Prj().SchSymbolLibTable()->HasLibrary( newLibName ) )
568  {
569  newLibName = wxString::Format( "%s%d", libName, libNameCnt );
570  }
571 
572  SYMBOL_LIB_TABLE_ROW* newRow = new SYMBOL_LIB_TABLE_ROW( newLibName,
573  uri,
574  row->GetType(),
575  row->GetOptions(),
576  row->GetDescr() );
577  Prj().SchSymbolLibTable()->InsertRow( newRow );
578 
579  if( libName != newLibName )
580  newScreens.ChangeSymbolLibNickname( libName, newLibName );
581  }
582  }
583  }
584  }
585 
586  // Check for duplicate sheet names in the current page.
587  wxArrayString duplicateSheetNames;
588  SCH_TYPE_COLLECTOR sheets;
589 
590  sheets.Collect( screen->GetDrawItems(), SCH_COLLECTOR::SheetsOnly );
591 
592  for( int i = 0; i < sheets.GetCount(); ++i )
593  {
594  if( newSheet->GetScreen()->GetSheet( ( ( SCH_SHEET* ) sheets[i] )->GetName() ) )
595  duplicateSheetNames.Add( ( ( SCH_SHEET* ) sheets[i] )->GetName() );
596  }
597 
598  if( !duplicateSheetNames.IsEmpty() )
599  {
600  msg.Printf( "Duplicate sheet names exist on the current page. Do you want to "
601  "automatically rename the duplicate sheet names?" );
602  if( !IsOK( this, msg ) )
603  return false;
604  }
605 
606  SCH_SCREEN* newScreen = newSheet->GetScreen();
607  wxCHECK_MSG( newScreen, false, "No screen defined for imported sheet." );
608 
609  for( auto duplicateName : duplicateSheetNames )
610  {
611  SCH_SHEET* renamedSheet = newScreen->GetSheet( duplicateName );
612 
613  wxCHECK2_MSG( renamedSheet, continue,
614  "Sheet " + duplicateName + " not found in imported schematic." );
615 
616  timestamp_t newtimestamp = GetNewTimeStamp();
617  renamedSheet->SetTimeStamp( newtimestamp );
618  renamedSheet->SetName( wxString::Format( "Sheet%8.8lX", (unsigned long) newtimestamp ) );
619  }
620 
621  // Clear all annotation in the imported schematic to prevent clashes with existing annotation.
622  newScreens.ClearAnnotation();
623 
624  // It is finally save to add the imported schematic.
625  screen->Append( newScreen );
626 
627  SCH_SCREENS allScreens;
628  allScreens.ReplaceDuplicateTimeStamps();
629 
630  OnModify();
631 
632  // redraw base screen (ROOT) if necessary
633  SCH_SCREENS screens( GetCurrentSheet().Last() );
634 
635  screens.UpdateSymbolLinks( true );
637  Zoom_Automatique( false );
639  m_canvas->Refresh( true );
640  return true;
641 }
642 
643 
644 void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
645 {
646  if( GetScreen() && GetScreen()->IsModified() )
647  {
648  wxString msg = _( "This operation cannot be undone.\n\n"
649  "Do you want to save the current document before proceeding?" );
650 
651  if( IsOK( this, msg ) )
652  OnSaveProject( event );
653  }
654 
655  AppendSchematic();
656 }
657 
658 
659 void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
660 {
661  if( !AskToSaveChanges() )
662  return;
663 
664  wxString path = wxPathOnly( Prj().GetProjectFullName() );
665 
666  wxFileDialog dlg( this, _( "Import Schematic" ), path,
667  wxEmptyString, EagleSchematicFileWildcard(),
668  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
669 
670  if( dlg.ShowModal() == wxID_CANCEL )
671  return;
672 
673  // For now there is only one import plugin
674  ImportFile( dlg.GetPath(), SCH_IO_MGR::SCH_EAGLE );
675 }
676 
677 
678 void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent )
679 {
680  SCH_SCREEN* screen;
681  SCH_SCREENS screenList;
682 
683  // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
684  wxString fileName = Prj().AbsolutePath( g_RootSheet->GetFileName() );
685 
686  wxFileName fn = fileName;
687 
688  if( !fn.IsDirWritable() )
689  {
690  wxString msg = wxString::Format( _( "Directory \"%s\" is not writable." ), fn.GetPath() );
691 
692  DisplayError( this, msg );
693  return;
694  }
695 
696  for( screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
697  SaveEEFile( screen );
698 
700 
701  UpdateTitle();
702 }
703 
704 
706 {
707  wxFileName tmpFileName = g_RootSheet->GetFileName();
708  wxFileName fn = tmpFileName;
709  wxFileName tmp;
710  SCH_SCREENS screens;
711 
712  bool autoSaveOk = true;
713 
714  tmp.AssignDir( fn.GetPath() );
715 
716  if( !tmp.IsOk() )
717  return false;
718 
719  if( !IsWritable( tmp ) )
720  return false;
721 
722  for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
723  {
724  // Only create auto save files for the schematics that have been modified.
725  if( !screen->IsSave() )
726  continue;
727 
728  tmpFileName = fn = screen->GetFileName();
729 
730  // Auto save file name is the normal file name prefixed with AUTOSAVE_PREFIX_FILENAME.
731  fn.SetName( AUTOSAVE_PREFIX_FILENAME + fn.GetName() );
732 
733  screen->SetFileName( fn.GetFullPath() );
734 
735  if( SaveEEFile( screen, false, NO_BACKUP_FILE ) )
736  screen->SetModify();
737  else
738  autoSaveOk = false;
739 
740  screen->SetFileName( tmpFileName.GetFullPath() );
741  }
742 
743  if( autoSaveOk )
744  m_autoSaveState = false;
745 
746  return autoSaveOk;
747 }
748 
749 
750 bool SCH_EDIT_FRAME::ImportFile( const wxString& aFileName, int aFileType )
751 {
752  wxString fullFileName( aFileName );
753 
755  wxString projectpath;
756  wxFileName newfilename;
757  SCH_SHEET_LIST sheetList( g_RootSheet );
758  SCH_SCREENS schematic;
759 
760  switch( (SCH_IO_MGR::SCH_FILE_T) aFileType )
761  {
762  case SCH_IO_MGR::SCH_EAGLE:
763  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
764  wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
765  wxT( "Import eagle schematic caller didn't send full filename" ) );
766 
767  if( !LockFile( fullFileName ) )
768  {
769  wxString msg = wxString::Format( _( "Schematic file \"%s\" is already open." ),
770  GetChars( fullFileName ) );
771  DisplayError( this, msg );
772  return false;
773  }
774 
775  try
776  {
777  pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) );
778  g_RootSheet = pi->Load( fullFileName, &Kiway() );
779 
780  projectpath = Kiway().Prj().GetProjectPath();
781  newfilename = Prj().AbsolutePath( Prj().GetProjectName() );
782  newfilename.SetExt( SchematicFileExtension );
783 
784  m_CurrentSheet->clear();
785  m_CurrentSheet->push_back( g_RootSheet );
787 
788  g_RootSheet->SetFileName( newfilename.GetFullPath() );
789  GetScreen()->SetFileName( newfilename.GetFullPath() );
790  GetScreen()->SetModify();
791 
792  UpdateFileHistory( fullFileName );
793  schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
794 
795  // Ensure the schematic is fully segmented on first display
797  SchematicCleanUp( true );
798  GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
799  GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
800 
802  Zoom_Automatique( false );
804  m_canvas->Refresh( true );
805  UpdateTitle();
806  }
807  catch( const IO_ERROR& ioe )
808  {
809  // Do not leave g_RootSheet == NULL because it is expected to be
810  // a valid sheet. Therefore create a dummy empty root sheet and screen.
811  CreateScreens();
812  Zoom_Automatique( false );
813 
814  wxString msg;
815  msg.Printf( _( "Error loading schematic file \"%s\".\n%s" ),
816  fullFileName, ioe.What() );
817  DisplayError( this, msg );
818 
819  msg.Printf( _( "Failed to load \"%s\"" ), fullFileName );
820  AppendMsgPanel( wxEmptyString, msg, CYAN );
821 
822  return false;
823  }
824 
825  return true;
826 
827  default:
828  return false;
829  }
830 
831  return false;
832 }
833 
834 
836 {
837  SCH_SCREENS screenList;
838 
839  // Save any currently open and modified project files.
840  for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
841  {
842  if( screen->IsModify() )
843  {
844  int response = YesNoCancelDialog( m_parent, _(
845  "The current schematic has been modified. Do you wish to save the changes?" ),
846  wxEmptyString,
847  _( "Save and Load" ),
848  _( "Load Without Saving" )
849  );
850 
851  if( response == wxID_CANCEL )
852  {
853  return false;
854  }
855  else if( response == wxID_YES )
856  {
857  wxCommandEvent dummy;
858  OnSaveProject( dummy );
859  }
860  // else wxID_NO, so do not save
861 
862  break;
863  }
864  }
865 
866  return true;
867 }
Definition of the SCH_SHEET class for Eeschema.
Class UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion supp...
Definition: utf8.h:73
Class SCH_SHEET_LIST.
int GetCount() const
Function GetCount returns the number of objects in the list.
bool m_autoSaveState
Flag to indicate the last auto save state.
Definition: wxstruct.h:155
static const wxString & GetSymbolLibTableFileName()
long timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
Definition: base_struct.h:171
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
bool SchematicCleanUp(bool aAppend=false)
Performs routine schematic cleaning including breaking wire and buses and deleting identical objects ...
SCH_SCREEN * GetNext()
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
Class TYPE_COLLECTOR merely gathers up all SCH_ITEMs of a given set of KICAD_T type(s).
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
wxString SchematicFileWildcard()
This file is part of the common library TODO brief description.
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Update the board display after modifying it bu a python script (note: it is automatically called by a...
Definition: draw_panel.cpp:332
This file is part of the common library.
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:467
SCH_SHEET * GetSheet(const wxString &aName)
Returns a sheet object pointer that is named aName.
Definition: sch_screen.cpp:630
void OnModify()
Must be called after a schematic change in order to set the "modify" flag of the current screen* and ...
Definition: schframe.cpp:773
const wxString ProjectFileExtension
void SetScreen(BASE_SCREEN *aScreen)
Definition: draw_frame.h:141
#define KICTL_CREATE
caller thinks requested project files may not exist
Definition: kiway_player.h:131
const wxString & GetFileName() const
bool AskToSaveChanges()
Checks if any of the screens has unsaved changes and asks the user whether to save or drop them...
bool BreakSegmentsOnJunctions(bool aApped=false)
Tests all junctions and bus entries in the schematic for intersections with wires and buses and break...
#define NO_BACKUP_FILE
Definition: wxstruct.h:60
virtual SCH_SHEET * Load(const wxString &aFileName, KIWAY *aKiway, SCH_SHEET *aAppendToMe=NULL, const PROPERTIES *aProperties=NULL)
Load information from some input file format that this SCH_PLUGIN implementation knows about...
Definition: sch_plugin.cpp:50
const wxChar RescueNeverShowEntry[]
void UpdateTitle()
Set the main window title bar text.
Definition: schframe.cpp:1465
void OnAppendProject(wxCommandEvent &event)
VTBL_ENTRY const wxString GetProjectFullName() const
Function GetProjectFullName returns the full path and name of the project.
Definition: project.cpp:96
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
virtual wxConfigBase * config()
Function config returns the wxConfigBase used in SaveSettings(), and is overloaded in KICAD_MANAGER_F...
Definition: basicframe.cpp:380
void set(SCH_PLUGIN *aPlugin)
Definition: sch_io_mgr.h:551
SCH_SCREEN * LastScreen() const
Function LastScreen.
VTBL_ENTRY _ELEM * GetElem(ELEM_T aIndex)
Typically wrapped somewhere else in a more meaningful function wrapper.
Definition: project.cpp:207
bool IsWritable(const wxFileName &aFileName)
Function IsWritable checks if aFileName can be written.
Definition: basicframe.cpp:553
static const wxString CacheName(const wxString &aFullProjectFilename)
Return the name of the cache library after potentially fixing it from an older naming scheme...
bool ImportFile(const wxString &aFileName, int aFileType) override
Load the given filename but sets the path to the current project path.
void UpdateFileHistory(const wxString &FullFileName, wxFileHistory *aFileHistory=NULL)
Function UpdateFileHistory Updates the list of recently opened files.
Definition: basicframe.cpp:407
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
void OnImportProject(wxCommandEvent &event)
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:219
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
SCH_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: schframe.cpp:532
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
SCH_SHEET_PATH * m_CurrentSheet
which sheet we are presently working on.
Definition: schframe.h:121
void Zoom_Automatique(bool aWarpPointer)
Function Zoom_Automatique redraws the screen with best zoom level and the best centering that shows a...
Definition: zoom.cpp:77
timestamp_t GetNewTimeStamp()
Definition: common.cpp:166
void Save_File(wxCommandEvent &event)
const wxString SchematicBackupFileExtension
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:87
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:55
void SetName(const wxString &aName)
Definition: sch_sheet.h:269
int ShowQuasiModal()
VTBL_ENTRY PROJECT & Prj() const
Function Prj returns the PROJECT associated with this KIWAY.
Definition: kiway.cpp:144
const wxString GetType() const override
Return the type of symbol library table represented by this row.
SCH_SHEET_PATH & GetCurrentSheet()
Definition: schframe.cpp:577
PART_LIB * AddLibrary(const wxString &aFileName)
Allocate and adds a part library to the library list.
Definition: colors.h:59
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:382
The common library.
bool AppendSchematic()
Import a KiCad schematic into the current page.
bool SaveEEFile(SCH_SCREEN *aScreen, bool aSaveUnderNewName=false, bool aCreateBackupFile=CREATE_BACKUP_FILE)
Save aScreen to a schematic file.
bool CreateArchiveLibraryCacheFile(bool aUseCurrentSheetFilename=false)
Create a symbol library file with the name of the root document plus the '-cache' suffix...
Definition: libarch.cpp:44
void OnSaveProject(wxCommandEvent &aEvent)
Command event handler to save the entire project and create a component library archive.
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
bool LoadProjectFile()
Loads the KiCad project file (*.pro) settings specific to Eeschema.
virtual const wxString & GetError() const
Return an error string to the caller.
Definition: sch_plugin.cpp:193
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString aExtraInfo)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:104
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set...
int m_LastGridSizeId
Definition: draw_frame.h:78
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
const wxString & GetDescr() const
Return the description of the library referenced by this row.
VTBL_ENTRY void SetProjectFullName(const wxString &aFullPathAndName)
Function SetProjectFullName sets the: 1) full directory, 2) basename, and 3) extension of the project...
Definition: project.cpp:65
wxString GetFileName(void) const
Return the filename corresponding to this sheet.
Definition: sch_sheet.cpp:645
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:209
virtual bool doAutoSave() override
Save the schematic files that have been modified and not yet saved.
void CreateScreens()
Definition: schframe.cpp:546
A collection of PART_LIB objects.
Helper object to release a SCH_PLUGIN in the context of a potential thrown exception through its dest...
Definition: sch_io_mgr.h:523
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:93
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
Definition: draw_frame.cpp:764
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
SCH_ITEM * GetDrawItems() const
Definition the SCH_COMPONENT class for Eeschema.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
see class PGM_BASE
void UpdateSymbolLinks(bool aForce=false)
Initialize or reinitialize the weak reference to the LIB_PART for each SCH_COMPONENT found in the ful...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void Append(SCH_ITEM *aItem)
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
Definition: schframe.cpp:497
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
wxString EagleSchematicFileWildcard()
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
Definition: sch_screen.cpp:879
void Collect(SCH_ITEM *aBoard, const KICAD_T aScanList[])
Function Collect scans a BOARD_ITEM using this class's Inspector method, which does the collection...
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:102
static const KICAD_T SheetsOnly[]
A scan list for schematic sheet items only.
bool RescueSymbolLibTableProject(bool aRunningOnDemand)
const char * name
bool HasLibrary(const wxString &aNickname) const
Test for the existence of aNickname in the library table.
int ReplaceDuplicateTimeStamps()
Test all sheet and component objects in the schematic for duplicate time stamps and replaces them as ...
SCH_SCREEN * GetFirst()
virtual void ClearUndoORRedoList(UNDO_REDO_CONTAINER &aList, int aItemCount=-1) override
Free the undo or redo list from aList element.
Definition: sch_screen.cpp:552
void SetFileName(const wxString &aFileName)
Definition for part library class.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
int SetGrid(const wxRealPoint &size)
set the current grid size m_Grid.
bool RescueLegacyProject(bool aRunningOnDemand)
#define AUTOSAVE_PREFIX_FILENAME
Prefix to create filenames for schematic files or other difile when auto-saved to retrieve a crash...
Definition: wxstruct.h:71
Object used to load, save, search, and otherwise manipulate symbol library files. ...
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nickames into aLibNicknames.
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:73
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
int YesNoCancelDialog(wxWindow *aParent, const wxString &aPrimaryMessage, const wxString &aSecondaryMessage, const wxString &aYesButtonText, const wxString &aNoButtonText, const wxString &aCancelButtonText)
Function YesNoCancelDialog displays a yes/no/cancel dialog with aMessage and returns the user respons...
Definition: confirm.cpp:168
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:131
void ClearMsgPanel(void)
Clear all messages from the message panel.
Definition: draw_frame.cpp:775
Definition of class LIB_EDIT_FRAME.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
const wxString SchematicFileExtension
bool IsEmpty(bool aIncludeFallback=true)
Return true if the table is empty.
bool LockFile(const wxString &aFileName)
Function LockFile marks a schematic file as being in use.
Definition: draw_frame.cpp:246
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName) const
Function TestForRecursion.
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:230
const wxChar traceAutoSave[]
Flag to enable auto save feature debug tracing.
Definition: basicframe.cpp:53