You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

608 lines
19 KiB

* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
15 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
  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-2017 Wayne Stambaugh <stambaughw@verizon.net>
  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. /**
  27. * @file eeschema/files-io.cpp
  28. */
  29. #include <fctsys.h>
  30. #include <class_drawpanel.h>
  31. #include <confirm.h>
  32. #include <gestfich.h>
  33. #include <schframe.h>
  34. #include <pgm_base.h>
  35. #include <kiface_i.h>
  36. #include <richio.h>
  37. #include <eeschema_id.h>
  38. #include <class_library.h>
  39. #include <libeditframe.h>
  40. #include <sch_sheet.h>
  41. #include <sch_sheet_path.h>
  42. #include <sch_component.h>
  43. #include <wildcards_and_files_ext.h>
  44. #include <project_rescue.h>
  45. #include <eeschema_config.h>
  46. #include <sch_legacy_plugin.h>
  47. //#define USE_SCH_LEGACY_IO_PLUGIN
  48. bool SCH_EDIT_FRAME::SaveEEFile( SCH_SCREEN* aScreen, bool aSaveUnderNewName,
  49. bool aCreateBackupFile )
  50. {
  51. wxString msg;
  52. wxFileName schematicFileName;
  53. bool success;
  54. if( aScreen == NULL )
  55. aScreen = GetScreen();
  56. // If no name exists in the window yet - save as new.
  57. if( aScreen->GetFileName().IsEmpty() )
  58. aSaveUnderNewName = true;
  59. // Construct the name of the file to be saved
  60. schematicFileName = Prj().AbsolutePath( aScreen->GetFileName() );
  61. if( aSaveUnderNewName )
  62. {
  63. wxFileDialog dlg( this, _( "Schematic Files" ),
  64. wxPathOnly( Prj().GetProjectFullName() ),
  65. schematicFileName.GetFullName(), SchematicFileWildcard,
  66. wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
  67. if( dlg.ShowModal() == wxID_CANCEL )
  68. return false;
  69. schematicFileName = dlg.GetPath();
  70. if( schematicFileName.GetExt() != SchematicFileExtension )
  71. schematicFileName.SetExt( SchematicFileExtension );
  72. }
  73. if( !IsWritable( schematicFileName ) )
  74. return false;
  75. // Create backup if requested
  76. if( aCreateBackupFile && schematicFileName.FileExists() )
  77. {
  78. wxFileName backupFileName = schematicFileName;
  79. // Rename the old file to a '.bak' one:
  80. backupFileName.SetExt( SchematicBackupFileExtension );
  81. if( backupFileName.FileExists() )
  82. wxRemoveFile( backupFileName.GetFullPath() );
  83. if( !wxRenameFile( schematicFileName.GetFullPath(), backupFileName.GetFullPath() ) )
  84. {
  85. msg.Printf( _( "Could not save backup of file '%s'" ),
  86. GetChars( schematicFileName.GetFullPath() ) );
  87. DisplayError( this, msg );
  88. }
  89. }
  90. // Save
  91. wxLogTrace( traceAutoSave,
  92. wxT( "Saving file <" ) + schematicFileName.GetFullPath() + wxT( ">" ) );
  93. SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
  94. try
  95. {
  96. pi->Save( schematicFileName.GetFullPath(), aScreen, &Kiway() );
  97. success = true;
  98. }
  99. catch( const IO_ERROR& ioe )
  100. {
  101. msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
  102. GetChars( schematicFileName.GetFullPath() ), GetChars( ioe.What() ) );
  103. DisplayError( this, msg );
  104. msg.Printf( _( "Failed to save '%s'" ), GetChars( schematicFileName.GetFullPath() ) );
  105. AppendMsgPanel( wxEmptyString, msg, CYAN );
  106. success = false;
  107. }
  108. if( success )
  109. {
  110. // Delete auto save file.
  111. wxFileName autoSaveFileName = schematicFileName;
  112. autoSaveFileName.SetName( AUTOSAVE_PREFIX_FILENAME + schematicFileName.GetName() );
  113. if( autoSaveFileName.FileExists() )
  114. {
  115. wxLogTrace( traceAutoSave,
  116. wxT( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
  117. wxT( ">" ) );
  118. wxRemoveFile( autoSaveFileName.GetFullPath() );
  119. }
  120. // Update the screen and frame info.
  121. if( aSaveUnderNewName )
  122. aScreen->SetFileName( schematicFileName.GetFullPath() );
  123. aScreen->ClrSave();
  124. aScreen->ClrModify();
  125. msg.Printf( _( "File %s saved" ), GetChars( aScreen->GetFileName() ) );
  126. SetStatusText( msg, 0 );
  127. }
  128. else
  129. {
  130. DisplayError( this, _( "File write operation failed." ) );
  131. }
  132. return success;
  133. }
  134. void SCH_EDIT_FRAME::Save_File( wxCommandEvent& event )
  135. {
  136. int id = event.GetId();
  137. switch( id )
  138. {
  139. case ID_UPDATE_ONE_SHEET:
  140. SaveEEFile( NULL );
  141. break;
  142. case ID_SAVE_ONE_SHEET_UNDER_NEW_NAME:
  143. if( SaveEEFile( NULL, true ) )
  144. {
  145. CreateArchiveLibraryCacheFile( true );
  146. }
  147. break;
  148. }
  149. UpdateTitle();
  150. }
  151. bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
  152. {
  153. // implement the pseudo code from KIWAY_PLAYER.h:
  154. SCH_SCREENS screenList;
  155. // This is for python:
  156. if( aFileSet.size() != 1 )
  157. {
  158. UTF8 msg = StrPrintf( "Eeschema:%s() takes only a single filename", __func__ );
  159. DisplayError( this, msg );
  160. return false;
  161. }
  162. wxString fullFileName( aFileSet[0] );
  163. // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
  164. wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
  165. wxT( "bug in single_top.cpp or project manager." ) );
  166. if( !LockFile( fullFileName ) )
  167. {
  168. wxString msg = wxString::Format( _(
  169. "Schematic file '%s' is already open." ),
  170. GetChars( fullFileName )
  171. );
  172. DisplayError( this, msg );
  173. return false;
  174. }
  175. // Save any currently open and modified project files.
  176. for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
  177. {
  178. if( screen->IsModify() )
  179. {
  180. int response = YesNoCancelDialog( this, _(
  181. "The current schematic has been modified. Do you wish to save the changes?" ),
  182. wxEmptyString,
  183. _( "Save and Load" ),
  184. _( "Load Without Saving" )
  185. );
  186. if( response == wxID_CANCEL )
  187. {
  188. return false;
  189. }
  190. else if( response == wxID_YES )
  191. {
  192. wxCommandEvent dummy;
  193. OnSaveProject( dummy );
  194. }
  195. else
  196. {
  197. // response == wxID_NO, fall thru
  198. }
  199. break;
  200. }
  201. }
  202. wxFileName pro = fullFileName;
  203. pro.SetExt( ProjectFileExtension );
  204. bool is_new = !wxFileName::IsFileReadable( fullFileName );
  205. // If its a non-existent schematic and caller thinks it exists
  206. if( is_new && !( aCtl & KICTL_CREATE ) )
  207. {
  208. // notify user that fullFileName does not exist, ask if user wants to create it.
  209. wxString ask = wxString::Format( _(
  210. "Schematic '%s' does not exist. Do you wish to create it?" ),
  211. GetChars( fullFileName )
  212. );
  213. if( !IsOK( this, ask ) )
  214. return false;
  215. }
  216. // unload current project file before loading new
  217. {
  218. delete g_RootSheet;
  219. g_RootSheet = NULL;
  220. CreateScreens();
  221. }
  222. GetScreen()->SetFileName( fullFileName );
  223. g_RootSheet->SetFileName( fullFileName );
  224. SetStatusText( wxEmptyString );
  225. ClearMsgPanel();
  226. LoadProjectFile();
  227. // PROJECT::SetProjectFullName() is an impactful function. It should only be
  228. // called under carefully considered circumstances.
  229. // The calling code should know not to ask me here to change projects unless
  230. // it knows what consequences that will have on other KIFACEs running and using
  231. // this same PROJECT. It can be very harmful if that calling code is stupid.
  232. // Don't reload the symbol libraries if we are just launching Eeschema from KiCad again.
  233. // They are already saved in the kiface project object.
  234. if( pro.GetFullPath() != Prj().GetProjectFullName()
  235. || !Prj().GetElem( PROJECT::ELEM_SCH_PART_LIBS ) )
  236. {
  237. Prj().SetProjectFullName( pro.GetFullPath() );
  238. // load the libraries here, not in SCH_SCREEN::Draw() which is a context
  239. // that will not tolerate DisplayError() dialog since we're already in an
  240. // event handler in there.
  241. // And when a schematic file is loaded, we need these libs to initialize
  242. // some parameters (links to PART LIB, dangling ends ...)
  243. Prj().SetElem( PROJECT::ELEM_SCH_PART_LIBS, NULL );
  244. Prj().SchLibs();
  245. }
  246. // Load the symbol library table, this will be used forever more.
  247. Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, NULL );
  248. Prj().SchSymbolLibTable();
  249. if( is_new )
  250. {
  251. // mark new, unsaved file as modified.
  252. GetScreen()->SetModify();
  253. }
  254. else
  255. {
  256. delete g_RootSheet; // Delete the current project.
  257. g_RootSheet = NULL; // Force CreateScreens() to build new empty project on load failure.
  258. SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
  259. try
  260. {
  261. g_RootSheet = pi->Load( fullFileName, &Kiway() );
  262. m_CurrentSheet->clear();
  263. m_CurrentSheet->push_back( g_RootSheet );
  264. }
  265. catch( const IO_ERROR& ioe )
  266. {
  267. // Do not leave g_RootSheet == NULL because it is expected to be
  268. // a valid sheet. Therefore create a dummy empty root sheet and screen.
  269. CreateScreens();
  270. Zoom_Automatique( false );
  271. wxString msg;
  272. msg.Printf( _( "Error loading schematic file '%s'.\n%s" ),
  273. GetChars( fullFileName ), GetChars( ioe.What() ) );
  274. DisplayError( this, msg );
  275. msg.Printf( _( "Failed to load '%s'" ), GetChars( fullFileName ) );
  276. AppendMsgPanel( wxEmptyString, msg, CYAN );
  277. return false;
  278. }
  279. SetScreen( m_CurrentSheet->LastScreen() );
  280. // It's possible the schematic parser fixed errors due to bugs so warn the user
  281. // that the schematic has been fixed (modified).
  282. SCH_SHEET_LIST sheetList( g_RootSheet );
  283. if( sheetList.IsModified() )
  284. {
  285. DisplayInfoMessage( this,
  286. _( "An error was found when loading the schematic that has "
  287. "been automatically fixed. Please save the schematic to "
  288. "repair the broken file or it may not be usable with other "
  289. "versions of KiCad." ) );
  290. }
  291. UpdateFileHistory( fullFileName );
  292. // Check to see whether some old library parts need to be rescued
  293. // Only do this if RescueNeverShow was not set.
  294. wxConfigBase *config = Kiface().KifaceSettings();
  295. bool rescueNeverShow = false;
  296. config->Read( RescueNeverShowEntry, &rescueNeverShow, false );
  297. if( !rescueNeverShow )
  298. {
  299. RescueProject( false );
  300. }
  301. SCH_SCREENS schematic;
  302. schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
  303. GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
  304. }
  305. GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
  306. Zoom_Automatique( false );
  307. SetSheetNumberAndCount();
  308. m_canvas->Refresh( true );
  309. return true;
  310. }
  311. bool SCH_EDIT_FRAME::AppendOneEEProject()
  312. {
  313. wxString fullFileName;
  314. SCH_SCREEN* screen = GetScreen();
  315. if( !screen )
  316. {
  317. wxLogError( wxT( "Document not ready, cannot import" ) );
  318. return false;
  319. }
  320. // open file chooser dialog
  321. wxString path = wxPathOnly( Prj().GetProjectFullName() );
  322. wxFileDialog dlg( this, _( "Import Schematic" ), path,
  323. wxEmptyString, SchematicFileWildcard,
  324. wxFD_OPEN | wxFD_FILE_MUST_EXIST );
  325. if( dlg.ShowModal() == wxID_CANCEL )
  326. return false;
  327. fullFileName = dlg.GetPath();
  328. wxFileName fn = fullFileName;
  329. if( fn.IsRelative() )
  330. {
  331. fn.MakeAbsolute();
  332. fullFileName = fn.GetFullPath();
  333. }
  334. wxString cache_name = PART_LIBS::CacheName( fullFileName );
  335. if( !!cache_name )
  336. {
  337. PART_LIBS* libs = Prj().SchLibs();
  338. try
  339. {
  340. if( PART_LIB* lib = libs->AddLibrary( cache_name ) )
  341. lib->SetCache();
  342. }
  343. catch( const IO_ERROR& ioe )
  344. {
  345. DisplayError( this, ioe.What() );
  346. }
  347. }
  348. wxLogDebug( wxT( "Importing schematic " ) + fullFileName );
  349. // Keep trace of the last item in list.
  350. // New items will be loaded after this one.
  351. SCH_ITEM* bs = screen->GetDrawItems();
  352. if( bs )
  353. {
  354. while( bs->Next() )
  355. bs = bs->Next();
  356. }
  357. // load the project
  358. bool success = LoadOneEEFile( screen, fullFileName, true );
  359. if( success )
  360. {
  361. // the new loaded items need cleaning to avoid duplicate parameters
  362. // which should be unique (ref and time stamp).
  363. // Clear ref and set a new time stamp for new items
  364. if( bs == NULL )
  365. bs = screen->GetDrawItems();
  366. else
  367. bs = bs->Next();
  368. while( bs )
  369. {
  370. SCH_ITEM* nextbs = bs->Next();
  371. // To avoid issues with the current hieratchy,
  372. // do not load included sheets files and give new filenames
  373. // and new sheet names.
  374. // There are many tricky cases (loops, creation of complex hierarchies
  375. // with duplicate file names, duplicate sheet names...)
  376. // So the included sheets names are renamed if existing,
  377. // and filenames are just renamed to avoid loops and
  378. // creation of complex hierarchies.
  379. // If someone want to change it for a better append function, remember
  380. // these cases need work to avoid issues.
  381. if( bs->Type() == SCH_SHEET_T )
  382. {
  383. SCH_SHEET * sheet = (SCH_SHEET *) bs;
  384. time_t newtimestamp = GetNewTimeStamp();
  385. sheet->SetTimeStamp( newtimestamp );
  386. // Check for existing subsheet name in the current sheet
  387. wxString tmp = sheet->GetName();
  388. sheet->SetName( wxEmptyString );
  389. const SCH_SHEET* subsheet = GetScreen()->GetSheet( tmp );
  390. if( subsheet )
  391. sheet->SetName( wxString::Format( wxT( "Sheet%8.8lX" ), (long) newtimestamp ) );
  392. else
  393. sheet->SetName( tmp );
  394. sheet->SetFileName( wxString::Format( wxT( "file%8.8lX.sch" ),
  395. (long) newtimestamp ) );
  396. SCH_SCREEN* new_screen = new SCH_SCREEN( &Kiway() );
  397. new_screen->SetMaxUndoItems( m_UndoRedoCountMax );
  398. sheet->SetScreen( new_screen );
  399. sheet->GetScreen()->SetFileName( sheet->GetFileName() );
  400. }
  401. // clear annotation and init new time stamp for the new components
  402. else if( bs->Type() == SCH_COMPONENT_T )
  403. {
  404. ( (SCH_COMPONENT*) bs )->SetTimeStamp( GetNewTimeStamp() );
  405. ( (SCH_COMPONENT*) bs )->ClearAnnotation( NULL );
  406. // Clear flags, which are set by these previous modifications:
  407. bs->ClearFlags();
  408. }
  409. bs = nextbs;
  410. }
  411. }
  412. OnModify();
  413. // redraw base screen (ROOT) if necessary
  414. GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
  415. Zoom_Automatique( false );
  416. SetSheetNumberAndCount();
  417. m_canvas->Refresh( true );
  418. return success;
  419. }
  420. void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
  421. {
  422. wxString msg = _( "This operation cannot be undone. "
  423. "Besides, take into account that hierarchical sheets will not be appended.\n\n"
  424. "Do you want to save the current document before proceeding?" );
  425. if( IsOK( this, msg ) )
  426. OnSaveProject( event );
  427. AppendOneEEProject();
  428. }
  429. void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent )
  430. {
  431. SCH_SCREEN* screen;
  432. SCH_SCREENS screenList;
  433. // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
  434. wxString fileName = Prj().AbsolutePath( g_RootSheet->GetFileName() );
  435. wxFileName fn = fileName;
  436. if( !fn.IsDirWritable() )
  437. {
  438. wxString msg = wxString::Format( _(
  439. "Directory '%s' is not writable" ),
  440. GetChars( fn.GetPath() )
  441. );
  442. DisplayError( this, msg );
  443. return;
  444. }
  445. for( screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
  446. SaveEEFile( screen );
  447. CreateArchiveLibraryCacheFile();
  448. UpdateTitle();
  449. }
  450. bool SCH_EDIT_FRAME::doAutoSave()
  451. {
  452. wxFileName tmpFileName = g_RootSheet->GetFileName();
  453. wxFileName fn = tmpFileName;
  454. wxFileName tmp;
  455. SCH_SCREENS screens;
  456. bool autoSaveOk = true;
  457. tmp.AssignDir( fn.GetPath() );
  458. if( !tmp.IsOk() )
  459. return false;
  460. if( !IsWritable( tmp ) )
  461. return false;
  462. for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
  463. {
  464. // Only create auto save files for the schematics that have been modified.
  465. if( !screen->IsSave() )
  466. continue;
  467. tmpFileName = fn = screen->GetFileName();
  468. // Auto save file name is the normal file name prefixed with AUTOSAVE_PREFIX_FILENAME.
  469. fn.SetName( AUTOSAVE_PREFIX_FILENAME + fn.GetName() );
  470. screen->SetFileName( fn.GetFullPath() );
  471. if( SaveEEFile( screen, false, NO_BACKUP_FILE ) )
  472. screen->SetModify();
  473. else
  474. autoSaveOk = false;
  475. screen->SetFileName( tmpFileName.GetFullPath() );
  476. }
  477. if( autoSaveOk )
  478. m_autoSaveState = false;
  479. return autoSaveOk;
  480. }