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.

417 lines
12 KiB

15 years ago
15 years ago
15 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
  5. * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
  6. * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file eeschema/files-io.cpp
  27. */
  28. #include <fctsys.h>
  29. #include <class_drawpanel.h>
  30. #include <confirm.h>
  31. #include <gestfich.h>
  32. #include <wxEeschemaStruct.h>
  33. #include <general.h>
  34. #include <protos.h>
  35. #include <eeschema_id.h>
  36. #include <class_library.h>
  37. #include <libeditframe.h>
  38. #include <sch_sheet.h>
  39. #include <wildcards_and_files_ext.h>
  40. bool SCH_EDIT_FRAME::SaveEEFile( SCH_SCREEN* aScreen, bool aSaveUnderNewName, bool aCreateBackupFile )
  41. {
  42. wxString msg;
  43. wxFileName schematicFileName, backupFileName;
  44. FILE* f;
  45. if( aScreen == NULL )
  46. aScreen = GetScreen();
  47. /* If no name exists in the window yet - save as new. */
  48. if( aScreen->GetFileName().IsEmpty() )
  49. aSaveUnderNewName = true;
  50. if( aSaveUnderNewName == false )
  51. {
  52. schematicFileName = aScreen->GetFileName();
  53. // Sheet file names are relative to the root sheet path which is the current
  54. // working directory. The IsWritable funtion expects the path to be set.
  55. if( schematicFileName.GetPath().IsEmpty() )
  56. schematicFileName.Assign( wxFileName::GetCwd(), schematicFileName.GetFullName() );
  57. if( aCreateBackupFile )
  58. {
  59. backupFileName = schematicFileName;
  60. if( !IsWritable( schematicFileName ) )
  61. return false;
  62. /* Rename the old file to a '.bak' one: */
  63. if( schematicFileName.FileExists() )
  64. {
  65. backupFileName.SetExt( SchematicBackupFileExtension );
  66. if( backupFileName.FileExists() )
  67. wxRemoveFile( backupFileName.GetFullPath() );
  68. if( !wxRenameFile( schematicFileName.GetFullPath(), backupFileName.GetFullPath() ) )
  69. {
  70. msg.Printf( _( "Could not save backup of file <%s>" ),
  71. GetChars( schematicFileName.GetFullPath() ) );
  72. DisplayError( this, msg );
  73. }
  74. }
  75. }
  76. }
  77. else
  78. {
  79. schematicFileName = aScreen->GetFileName();
  80. wxFileDialog dlg( this, _( "Schematic Files" ), wxGetCwd(),
  81. schematicFileName.GetFullName(), SchematicFileWildcard,
  82. wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
  83. if( dlg.ShowModal() == wxID_CANCEL )
  84. return false;
  85. aScreen->SetFileName( dlg.GetPath() );
  86. schematicFileName = dlg.GetPath();
  87. if( !IsWritable( schematicFileName ) )
  88. return false;
  89. }
  90. wxLogTrace( traceAutoSave,
  91. wxT( "Saving file <" ) + schematicFileName.GetFullPath() + wxT( ">" ) );
  92. if( ( f = wxFopen( schematicFileName.GetFullPath(), wxT( "wt" ) ) ) == NULL )
  93. {
  94. msg.Printf( _( "Failed to create file <%s>" ),
  95. GetChars( schematicFileName.GetFullPath() ) );
  96. DisplayError( this, msg );
  97. return false;
  98. }
  99. if( aSaveUnderNewName )
  100. aScreen->SetFileName( schematicFileName.GetFullPath() );
  101. bool success = aScreen->Save( f );
  102. if( !success )
  103. {
  104. DisplayError( this, _( "File write operation failed." ) );
  105. }
  106. else
  107. {
  108. // Delete auto save file on successful save.
  109. wxFileName autoSaveFileName = schematicFileName;
  110. autoSaveFileName.SetName( wxT( "$" ) + schematicFileName.GetName() );
  111. if( autoSaveFileName.FileExists() )
  112. {
  113. wxLogTrace( traceAutoSave,
  114. wxT( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
  115. wxT( ">" ) );
  116. wxRemoveFile( autoSaveFileName.GetFullPath() );
  117. }
  118. aScreen->ClrSave();
  119. aScreen->ClrModify();
  120. wxString msg;
  121. msg.Printf( _( "File %s saved" ), GetChars( aScreen->GetFileName() ) );
  122. SetStatusText( msg, 0 );
  123. }
  124. fclose( f );
  125. return success;
  126. }
  127. void SCH_EDIT_FRAME::Save_File( wxCommandEvent& event )
  128. {
  129. int id = event.GetId();
  130. switch( id )
  131. {
  132. case ID_UPDATE_ONE_SHEET:
  133. SaveEEFile( NULL );
  134. break;
  135. case ID_SAVE_ONE_SHEET_UNDER_NEW_NAME:
  136. SaveEEFile( NULL, true );
  137. break;
  138. }
  139. }
  140. bool SCH_EDIT_FRAME::LoadOneEEProject( const wxString& aFileName, bool aIsNew )
  141. {
  142. SCH_SCREEN* screen;
  143. wxString FullFileName, msg;
  144. bool LibCacheExist = false;
  145. SCH_SCREENS ScreenList;
  146. for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
  147. {
  148. if( screen->IsModify() )
  149. break;
  150. }
  151. if( screen )
  152. {
  153. if( !IsOK( this, _( "Discard changes to the current schematic?" ) ) )
  154. return false;
  155. }
  156. FullFileName = aFileName;
  157. if( ( FullFileName.IsEmpty() ) && !aIsNew )
  158. {
  159. wxFileDialog dlg( this, _( "Open Schematic" ), wxGetCwd(),
  160. wxEmptyString, SchematicFileWildcard,
  161. wxFD_OPEN | wxFD_FILE_MUST_EXIST );
  162. if( dlg.ShowModal() == wxID_CANCEL )
  163. return false;
  164. FullFileName = dlg.GetPath();
  165. }
  166. if( g_RootSheet )
  167. {
  168. SAFE_DELETE( g_RootSheet );
  169. }
  170. CreateScreens();
  171. screen = GetScreen();
  172. wxFileName fn = FullFileName;
  173. if( fn.IsRelative() )
  174. {
  175. fn.MakeAbsolute();
  176. FullFileName = fn.GetFullPath();
  177. }
  178. wxLogDebug( wxT( "Loading schematic " ) + FullFileName );
  179. wxSetWorkingDirectory( fn.GetPath() );
  180. screen->SetFileName( FullFileName );
  181. g_RootSheet->SetFileName( FullFileName );
  182. SetStatusText( wxEmptyString );
  183. ClearMsgPanel();
  184. screen->ClrModify();
  185. if( aIsNew )
  186. {
  187. /* SCH_SCREEN constructor does this now
  188. screen->SetPageSettings( PAGE_INFO( wxT( "A4" ) ) );
  189. */
  190. screen->SetZoom( 32 );
  191. screen->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
  192. TITLE_BLOCK tb;
  193. wxString title;
  194. title += NAMELESS_PROJECT;
  195. title += wxT( ".sch" );
  196. tb.SetTitle( title );
  197. screen->SetTitleBlock( tb );
  198. GetScreen()->SetFileName( title );
  199. LoadProjectFile( wxEmptyString, true );
  200. Zoom_Automatique( false );
  201. SetSheetNumberAndCount();
  202. m_canvas->Refresh();
  203. return true;
  204. }
  205. // Reloading configuration.
  206. msg = _( "Ready\nWorking dir: \n" ) + wxGetCwd();
  207. PrintMsg( msg );
  208. LoadProjectFile( wxEmptyString, false );
  209. // Clear (if needed) the current active library in libedit because it could be
  210. // removed from memory
  211. LIB_EDIT_FRAME::EnsureActiveLibExists();
  212. // Delete old caches.
  213. CMP_LIBRARY::RemoveCacheLibrary();
  214. /* Loading the project library cache
  215. * until apr 2009 the lib is named <root_name>.cache.lib
  216. * and after (due to code change): <root_name>-cache.lib
  217. * so if the <name>-cache.lib is not found, the old way will be tried
  218. */
  219. fn = g_RootSheet->GetScreen()->GetFileName();
  220. bool use_oldcachename = false;
  221. wxString cachename = fn.GetName() + wxT( "-cache" );
  222. fn.SetName( cachename );
  223. fn.SetExt( SchematicLibraryFileExtension );
  224. if( ! fn.FileExists() )
  225. {
  226. fn = g_RootSheet->GetScreen()->GetFileName();
  227. fn.SetExt( wxT( "cache.lib" ) );
  228. use_oldcachename = true;
  229. }
  230. if( fn.FileExists() )
  231. {
  232. wxString errMsg;
  233. wxLogDebug( wxT( "LoadOneEEProject() load schematic cache library file <%s>" ),
  234. GetChars( fn.GetFullPath() ) );
  235. msg = wxT( "Load " ) + fn.GetFullPath();
  236. CMP_LIBRARY* LibCache = CMP_LIBRARY::LoadLibrary( fn, errMsg );
  237. if( LibCache )
  238. {
  239. LibCache->SetCache();
  240. msg += wxT( " OK" );
  241. if ( use_oldcachename ) // set the new name
  242. {
  243. fn.SetName( cachename );
  244. fn.SetExt( SchematicLibraryFileExtension );
  245. LibCache->SetFileName( fn );
  246. }
  247. LibCacheExist = true;
  248. CMP_LIBRARY::GetLibraryList().push_back( LibCache );
  249. }
  250. else
  251. {
  252. wxString prompt;
  253. prompt.Printf( _( "Component library <%s> failed to load.\nError: %s" ),
  254. GetChars( fn.GetFullPath() ),
  255. GetChars( errMsg ) );
  256. DisplayError( this, prompt );
  257. msg += _( " ->Error" );
  258. }
  259. PrintMsg( msg );
  260. }
  261. if( !wxFileExists( g_RootSheet->GetScreen()->GetFileName() ) && !LibCacheExist )
  262. {
  263. Zoom_Automatique( false );
  264. msg.Printf( _( "File <%s> not found." ),
  265. GetChars( g_RootSheet->GetScreen()->GetFileName() ) );
  266. DisplayInfoMessage( this, msg );
  267. return false;
  268. }
  269. // load the project.
  270. g_RootSheet->SetScreen( NULL );
  271. bool diag = g_RootSheet->Load( this );
  272. SetScreen( m_CurrentSheet->LastScreen() );
  273. UpdateFileHistory( g_RootSheet->GetScreen()->GetFileName() );
  274. /* Redraw base screen (ROOT) if necessary. */
  275. GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
  276. Zoom_Automatique( false );
  277. SetSheetNumberAndCount();
  278. m_canvas->Refresh( true );
  279. return diag;
  280. }
  281. void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent )
  282. {
  283. SCH_SCREEN* screen;
  284. wxFileName fn;
  285. wxFileName tmp;
  286. SCH_SCREENS ScreenList;
  287. fn = g_RootSheet->GetFileName();
  288. tmp.AssignDir( fn.GetPath() );
  289. if( !IsWritable( tmp ) )
  290. return;
  291. for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
  292. SaveEEFile( screen );
  293. wxString cachename = fn.GetName() + wxT( "-cache" );
  294. fn.SetName( cachename );
  295. fn.SetExt( SchematicLibraryFileExtension );
  296. CreateArchiveLibrary( fn.GetFullPath() );
  297. }
  298. bool SCH_EDIT_FRAME::doAutoSave()
  299. {
  300. wxFileName tmpFileName = g_RootSheet->GetFileName();
  301. wxFileName fn = tmpFileName;
  302. wxFileName tmp;
  303. SCH_SCREENS screens;
  304. bool autoSaveOk = true;
  305. tmp.AssignDir( fn.GetPath() );
  306. if( !IsWritable( tmp ) )
  307. return false;
  308. for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
  309. {
  310. // Only create auto save files for the schematics that have been modified.
  311. if( !screen->IsSave() )
  312. continue;
  313. tmpFileName = fn = screen->GetFileName();
  314. // Auto save file name is the normal file name prefixed with $.
  315. fn.SetName( wxT( "$" ) + fn.GetName() );
  316. screen->SetFileName( fn.GetFullPath() );
  317. if( SaveEEFile( screen, false, NO_BACKUP_FILE ) )
  318. screen->SetModify();
  319. else
  320. autoSaveOk = false;
  321. screen->SetFileName( tmpFileName.GetFullPath() );
  322. }
  323. if( autoSaveOk )
  324. m_autoSaveState = false;
  325. return autoSaveOk;
  326. }