Currently KiCad applications allow opening the same file more than once, and they don't check if the files have changed in disk before saving. As a consequence, there can be situations where the user loses some data without notice.
This patch uses wxSingleInstanceChecker to create a lock on the open file. It is checked every time Eeschema tries to open a file. We can distinguish two situations: * Open a file when the application is started. In this case, if the lock is unsuccessful the application closes, it doesn't even show the alert about other instances running. * Open another file from the menu (file -> open or tool bar). In this case, if the lock is unsuccessful the application remains open with its contents unchanged. Finally, this patch is a starting point to implement similar checks in other KiCad applications. -- Jacobo
=== modified file 'common/edaappl.cpp' --- common/edaappl.cpp 2012-11-09 06:58:00 +0000 +++ common/edaappl.cpp 2013-01-03 17:22:08 +0000 @@ -273,6 +273,7 @@ EDA_APP::EDA_APP() { m_Checker = NULL; + m_oneInstancePerFileChecker = NULL; m_HtmlCtrl = NULL; m_settings = NULL; m_LanguageId = wxLANGUAGE_DEFAULT; @@ -298,6 +299,9 @@ if( m_Checker ) delete m_Checker; + if( m_oneInstancePerFileChecker ) + delete m_oneInstancePerFileChecker; + delete m_Locale; } @@ -1124,3 +1128,23 @@ } } } + +bool EDA_APP::LockFile( const wxString& fileName ) +{ + // semaphore to protect the edition of the file by more than one instance + if( m_oneInstancePerFileChecker != NULL ) + { + // it means that we had an open file and we are opening a different one + delete m_oneInstancePerFileChecker; + } + wxString lockFileName = fileName + wxT( ".lock" ); + lockFileName.Replace( wxT( "/" ), wxT( "_" ) ); + m_oneInstancePerFileChecker = new wxSingleInstanceChecker( lockFileName ); + if( m_oneInstancePerFileChecker && + m_oneInstancePerFileChecker->IsAnotherRunning() ) + { + return false; + } + + return true; +} === modified file 'eeschema/eeschema.cpp' --- eeschema/eeschema.cpp 2012-10-31 20:27:31 +0000 +++ eeschema/eeschema.cpp 2013-01-03 17:22:08 +0000 @@ -89,18 +89,33 @@ { wxFileName filename; SCH_EDIT_FRAME* frame = NULL; + bool fileReady = false; InitEDA_Appl( wxT( "Eeschema" ), APP_EESCHEMA_T ); - if( m_Checker && m_Checker->IsAnotherRunning() ) - { - if( !IsOK( NULL, _( "Eeschema is already running, Continue?" ) ) ) - return false; - } - if( argc > 1 ) filename = argv[1]; + if( filename.IsOk() ) + { + if( filename.GetExt() != SchematicFileExtension ) + filename.SetExt( SchematicFileExtension ); + + if( !wxGetApp().LockFile( filename.GetFullPath() ) ) + { + DisplayError( NULL, _( "This file is already open." ) ); + return false; + } + + fileReady = true; + } + + if( m_Checker && m_Checker->IsAnotherRunning() ) + { + if( !IsOK( NULL, _( "Eeschema is already running, Continue?" ) ) ) + return false; + } + // Give a default colour for all layers // (actual color will beinitialized by config) for( int ii = 0; ii < MAX_LAYERS; ii++ ) @@ -130,11 +145,8 @@ frame->Zoom_Automatique( true ); /* Load file specified in the command line. */ - if( filename.IsOk() ) + if( fileReady ) { - if( filename.GetExt() != SchematicFileExtension ) - filename.SetExt( SchematicFileExtension ); - wxSetWorkingDirectory( filename.GetPath() ); if( frame->LoadOneEEProject( filename.GetFullPath(), false ) ) === modified file 'eeschema/files-io.cpp' --- eeschema/files-io.cpp 2012-09-28 17:47:41 +0000 +++ eeschema/files-io.cpp 2013-01-03 17:22:08 +0000 @@ -32,6 +32,7 @@ #include <confirm.h> #include <gestfich.h> #include <wxEeschemaStruct.h> +#include <appl_wxstruct.h> #include <general.h> #include <protos.h> @@ -204,6 +205,21 @@ FullFileName = dlg.GetPath(); } + wxFileName fn = FullFileName; + + if( fn.IsRelative() ) + { + fn.MakeAbsolute(); + FullFileName = fn.GetFullPath(); + } + + if( !wxGetApp().LockFile( FullFileName ) ) + { + DisplayError( this, _( "This file is already open." ) ); + return false; + } + + // Clear the screen before open a new file if( g_RootSheet ) { SAFE_DELETE( g_RootSheet ); @@ -212,14 +228,6 @@ CreateScreens(); screen = GetScreen(); - wxFileName fn = FullFileName; - - if( fn.IsRelative() ) - { - fn.MakeAbsolute(); - FullFileName = fn.GetFullPath(); - } - wxLogDebug( wxT( "Loading schematic " ) + FullFileName ); wxSetWorkingDirectory( fn.GetPath() ); === modified file 'include/appl_wxstruct.h' --- include/appl_wxstruct.h 2012-08-02 07:47:30 +0000 +++ include/appl_wxstruct.h 2013-01-03 17:22:08 +0000 @@ -67,6 +67,9 @@ /// Used to prevent multiple instances of an application from being run at the same time. wxSingleInstanceChecker* m_Checker; + /// Used to prevent opening the same file multiple times. + wxSingleInstanceChecker* m_oneInstancePerFileChecker; + wxString m_Project; /// The application specific configuration settings. @@ -410,6 +413,13 @@ */ void InsertLibraryPath( const wxString& aPaths, size_t aIndex ); + /** + * Function LockFile + * Locks the access to a file. + * @param fileName = full path to the file. + * @return false if the file was already locked, true otherwise. + */ + bool LockFile( const wxString& fileName ); }; /*
_______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : kicad-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp