]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Implementation of GUITHARE External 20547, GUITHARE Internal 790. Automatic backup
authorsln <sln@opencascade.com>
Wed, 30 Nov 2011 07:58:42 +0000 (07:58 +0000)
committersln <sln@opencascade.com>
Wed, 30 Nov 2011 07:58:42 +0000 (07:58 +0000)
see "http://doc.nnov.opencascade.com/doku.php?id=projects:guithare:gui_backup" for more info

14 files changed:
src/LightApp/LightApp_Application.cxx
src/LightApp/LightApp_Application.h
src/LightApp/LightApp_DataModel.cxx
src/LightApp/LightApp_DataModel.h
src/LightApp/LightApp_Study.cxx
src/LightApp/LightApp_Study.h
src/LightApp/resources/LightApp.xml
src/LightApp/resources/LightApp_msg_en.ts
src/SUIT/SUIT_Application.cxx
src/SUIT/SUIT_Application.h
src/SUIT/SUIT_Session.cxx
src/SUIT/SUIT_Session.h
src/SUIT/SUIT_Study.cxx
src/SUIT/resources/SUIT_msg_en.ts

index deb77a7435a4342309cbafef47c0eb0e6633ebdb..f53fa4f3a197ab668d655de95d752c62836733bb 100644 (file)
@@ -290,15 +290,15 @@ LightApp_Application::LightApp_Application()
   QStringList anAddFamilies = aResMgr->stringValue( "PyConsole", "additional_families" ).split( ";", QString::SkipEmptyParts );
   QString aFamily;
   for ( QStringList::Iterator it = anAddFamilies.begin(); it != anAddFamilies.end(); ++it )
+  {
+    aFamily = *it;
+    if ( famdb.contains(aFamily) )
     {
-      aFamily = *it;
-      if ( famdb.contains(aFamily) )
-       {
-         f.setFamily( aFamily );
-         aResMgr->setValue( "PyConsole", "font", f );
-         break;
-       }
+      f.setFamily( aFamily );
+      aResMgr->setValue( "PyConsole", "font", f );
+      break;
     }
+  }
 }
 
 /*!Destructor.
@@ -1826,6 +1826,7 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref )
   pref->addPreference( tr( "PREF_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file" );
   pref->addPreference( tr( "PREF_ASCII_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "ascii_file" );
   pref->addPreference( tr( "PREF_STORE_POS" ),  studyGroup, LightApp_Preferences::Bool, "Study", "store_positions" );
+  pref->addPreference( tr( "PREF_BACKUP" ),  studyGroup, LightApp_Preferences::DblSpin, "Study", "backup_studies" );
 
   int extgroup = pref->addPreference( tr( "PREF_GROUP_EXT_BROWSER" ), genTab );
   QString platform;
@@ -2431,6 +2432,9 @@ void LightApp_Application::preferencesChanged( const QString& sec, const QString
       aSStyle->polish(qApp);
     }
   }
+
+  double time = resMgr->doubleValue( "Study", "backup_studies", 0. );
+  SUIT_Session::session()->setBackupTime( time );
 }
 
 /*!
@@ -2907,6 +2911,10 @@ void LightApp_Application::createEmptyStudy()
 
   if ( objectBrowser() )
     objectBrowser()->updateTree();
+
+  LightApp_Study* aStudy = (LightApp_Study*)activeStudy();
+  aStudy->setRestoreFolder( myBFolder );
+  //myBFolder = "";
 }
 
 /*!
@@ -3229,4 +3237,33 @@ bool LightApp_Application::openAction( const int choice, const QString& aName )
   }
 
   return res;
-}
\ No newline at end of file
+}
+
+/*!
+ * Calls 'backup' method of active study
+ */
+void LightApp_Application::backup( const QString& fName )
+{
+  LightApp_Study* study = dynamic_cast<LightApp_Study*>( activeStudy() );
+  if ( study )
+    study->backup( fName );
+}
+
+/*!
+ * Keeps folder to be used for restoring.
+ */
+void LightApp_Application::setRestoreFolder( const QString& fName )
+{
+  myBFolder = fName;
+}
+
+/*!
+ * Gets backup time from preferences; this method is used by session when backup timer is created.
+*/
+double LightApp_Application::getBackupTime() const
+{
+  SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+  double res = resMgr->doubleValue( "Study", "backup_studies", 0. );
+  return res;
+}
+
index ae6522855878fa83609761e52823651b3749fabc..3fe5d6ced2b3e51fec03fb9964b5260edc466dd7 100644 (file)
@@ -144,6 +144,10 @@ public:
 
   virtual void                        updateDesktopTitle();
 
+  virtual void                        backup( const QString& fName );
+  virtual void                        setRestoreFolder( const QString& fName );
+  virtual double                      getBackupTime() const;
+
 signals:
   void                                studyOpened();
   void                                studySaved();
@@ -264,6 +268,8 @@ protected:
   static LightApp_Preferences*        _prefs_;
 
   static int                          lastStudyId;
+
+  QString                             myBFolder;
 };
 
 #ifdef WIN32
index 0b8b2cef6834d1adb2d45e147379a3342e12f862..e37bd9c8825b4d71bbe66beed5e827c14a437b23 100644 (file)
@@ -361,3 +361,11 @@ LightApp_DataObject* LightApp_DataModel::findObjectByEntry( SUIT_DataBrowser* th
   }
   return NULL;
 }
+
+/*!
+  to do:
+*/
+void LightApp_DataModel::backup( const QString& /*fName*/, QStringList& files )
+{
+  
+}
index 2148aab416ebf7d26f43a200fc525c0c342ba35e..91da54d4fc569ee0487d763a27837bd319858988 100644 (file)
@@ -74,6 +74,8 @@ public:
   LightApp_DataObject*                findObjectByEntry( SUIT_DataBrowser* theOB, 
                                                          const QString& theEntry );
 
+  virtual void                        backup( const QString& fName, QStringList& files );
+  
 signals:
   void                                opened();
   void                                saved();
index 900f142e86890fa88da78b46a24d968e93fae4ad..dda081079bac40716e3ad24fda5adb72d3a011d1 100644 (file)
 #include "LightApp_DataModel.h"
 #include "LightApp_DataObject.h"
 #include "LightApp_HDFDriver.h"
+#include "LightApp_Module.h"
 
 #include "SUIT_ResourceMgr.h"
 #include "SUIT_DataObjectIterator.h"
 
 #include <set>
 #include <QString>
+#include <QDir>
 
 /*!
   Constructor.
@@ -73,8 +75,17 @@ bool LightApp_Study::openDocument( const QString& theFileName )
 {
   myDriver->ClearDriverContents();
   // create files for models from theFileName
-  if( !openStudyData(theFileName))
-    return false;
+
+  if ( myRestFolder.isEmpty() )
+  {
+    if( !openStudyData(theFileName))
+      return false;
+  }
+  else 
+  {
+    // Case when study is restored from backup
+    openBackupData();
+  }
 
   setRoot( new LightApp_RootObject( this ) ); // create myRoot
 
@@ -92,6 +103,13 @@ bool LightApp_Study::openDocument( const QString& theFileName )
   bool res = CAM_Study::openDocument( theFileName );
 
   emit opened( this );
+
+  if ( !myRestFolder.isEmpty() )
+  {
+    setIsSaved( false );
+    //myRestFolder = "";
+  }
+
   return res;
 }
 
@@ -458,3 +476,181 @@ void LightApp_Study::components( QStringList& comp ) const
       comp.append( obj->entry() );
   }
 }
+
+/*!
+ * Keeps folder to be used for restoring.
+ */
+void LightApp_Study::setRestoreFolder( const QString& folder )
+{
+  myRestFolder = folder;
+}
+
+/*!
+  * - Call LightApp_DataModel::backup() for each data model
+  * - Creates "data" file in backup folder; this file contains name of opened 
+  *    HDF-file if study was stored or opened, name of temporary folder used 
+  *    by LightApp_Driver for study opening, list of backup files created by each model
+ */
+void LightApp_Study::backup( const QString& fName )
+{
+  QList<CAM_DataModel*> list; 
+  dataModels( list );
+
+  QListIterator<CAM_DataModel*> itList( list );
+  while ( itList.hasNext() ) 
+  {
+    LightApp_DataModel* model = (LightApp_DataModel*)itList.next();
+    if ( model && model->getModule() ) 
+    {
+      // writes location of hdf-file
+      QString hdfName = QString( "HDF:" ) + studyName() + "\n";
+
+      //QString tmpName = QString( " ) + GetTmpDir( "", false ).c_str() + "\n";
+      QString tmpName( "TMP:" ); 
+      
+      LightApp_Driver::ListOfFiles files = 
+        myDriver->GetListOfFiles( model->getModule()->name().toLatin1().constData() );
+      if ( files.size() > 0 )
+        tmpName += files.front().c_str();
+      else 
+      {
+        // New (not saved study). Use backup folder as default
+        tmpName += fName;
+      }
+      tmpName += '\n';
+
+      QString dataName = Qtx::addSlash( fName ) + "data";
+      FILE* f = fopen( dataName.toLatin1().constData(), "w" );
+      if ( f )
+      {
+        fputs( hdfName.toLatin1().constData(), f );
+        fputs( tmpName.toLatin1().constData(), f );
+
+        // backup model
+        QStringList backupFiles;
+        model->backup( fName, backupFiles );
+
+        // module data string
+        CAM_Module* mod = model->module();
+        {
+          QString modStr = mod->name();
+          QStringList::iterator it;
+          for ( it = backupFiles.begin(); it != backupFiles.end(); ++it )
+          {
+            const QString& curr = * it;
+            modStr += QString( "*" ) + curr;
+          }
+          fputs( modStr.toLatin1().constData(), f );
+        }
+        fclose( f );
+      }
+    }
+  }
+}
+
+/*!
+ * Prepare files to be used by data models for restoring; these files are 
+ * created from backup files and files of previously opened study.
+ */
+bool LightApp_Study::openBackupData()
+{
+  // Case when study is restored from backup
+  // Here:
+  // tmpFolder - folder where temporary files of previously opened study was saved (ex. D:\temp\84623)
+  // hdfName \96 name of HDF-file of previous study, if exists.
+  // backupFolder \96 folder with backup files. 
+
+  // Main idea: 
+  // - Parse \93data\94 file and gets file names, Fill driver with files of results tmpFolder.
+  // - Move all files from backup to tmp.
+  // - Open study using this files.
+  // - Redirect name of opened study to previous hdfName.
+
+  // Parse \93data\94
+
+  // data-file - something like this
+  // HDF:D:/sln/CATHARE/Data/1.hdf
+  // TMP:d:\temp\84623\
+  // CATHAREGUI*1.cbf
+  QString dataName = Qtx::addSlash( myRestFolder ) + "data";
+  FILE* f = fopen( dataName.toLatin1().constData(), "r" );
+  if ( !f )
+    return false;
+
+  char buff[ 1024 ];
+
+  // hdf-name
+  memset( buff, 0, 1024 );
+  fgets( buff, 1024, f );
+  QString hdfName( buff );
+  hdfName.remove( '\n' );
+  hdfName.remove( "HDF:" );
+
+  // name of temporary file
+  memset( buff, 0, 1024 );
+  fgets( buff, 1024, f );
+  QString tmpFolder( buff );
+  tmpFolder.remove( '\n' );
+  tmpFolder.remove( "TMP:" );
+
+  // list of files 
+  QString modName;
+  LightApp_Driver::ListOfFiles modFiles;
+  while( !feof( f ) )
+  {
+    modName = "";
+    modFiles.clear();
+
+    memset( buff, 0, 1024 );
+    fgets( buff, 1024, f );
+    QString modStr( buff );
+
+    QStringList lst = modStr.split( "*" );
+    QStringList::iterator it = lst.begin();
+    for ( int i = 0; it != lst.end(); ++it, ++i )
+    {
+      const QString& curr = *it;
+      if ( i == 0 )
+      {
+        modName = curr;
+        modFiles.push_back( Qtx::addSlash( tmpFolder ).toLatin1().constData() );
+        continue;
+      }
+      else 
+      modFiles.push_back( curr.toLatin1().constData() );
+    }
+
+    // fill driver
+    myDriver->SetListOfFiles( modName.toLatin1().constData(), modFiles );
+  }
+
+  fclose( f );
+
+  // Move all files from backup to tmp
+
+  if ( !QFileInfo( tmpFolder ).exists() )
+    QDir().mkdir( tmpFolder );
+
+  if ( !QFileInfo( tmpFolder ).exists() )
+    return false;
+
+  QDir restDir( myRestFolder );
+  QStringList restList = restDir.entryList ( QDir::AllEntries );
+  QStringList::iterator it;
+  for ( it = restList.begin(); it != restList.end(); ++it )
+  {
+    const QString& locName = *it;
+    if ( locName == "." || locName == ".." || locName == "data" )
+      continue;
+
+    QString oldName = QDir::convertSeparators( Qtx::addSlash( myRestFolder ) + locName );
+    QString newName = QDir::convertSeparators( Qtx::addSlash( tmpFolder ) + locName );
+    if ( oldName != newName ) // oldName == newName for non-saved study
+    {
+      QFile::remove( newName );
+      QFile::copy( oldName, newName );
+    }
+  }
+  return true;
+}
+
index 3e307ceeac32585627b890bc7a99e0ba738a6e2f..142bdbcc6e1a0049e5ea248dc4c46cf71a4174c7 100644 (file)
@@ -66,6 +66,9 @@ public:
   virtual void        children( const QString&, QStringList& ) const;
   virtual void        components( QStringList& ) const;
 
+  void                backup( const QString& fName);
+  void                setRestoreFolder( const QString& folder );
+
 protected:
   virtual void        saveModuleData ( QString theModuleName, QStringList theListOfFiles );
   virtual void        openModuleData ( QString theModuleName, QStringList& theListOfFiles );
@@ -87,9 +90,14 @@ signals:
   void                closed ( SUIT_Study* );
   void                created( SUIT_Study* );
 
+private:
+
+  bool                openBackupData();
+
 
 private:
   LightApp_Driver*    myDriver;
+  QString             myRestFolder;
 
   friend class LightApp_Application;
 };
index 80011cfaf3506ab1c41e8f90b45bb3cb03fc3a56..06cd5bff498d9b854fe0af55bc7cd357f72115a5 100644 (file)
@@ -87,6 +87,7 @@
   <section name="Study">
     <!-- General study settings -->
     <parameter name="store_positions" value="true" />
+    <parameter name="backup_studies" value="5.0" />
   </section>
   <section name="Activate">
     <!-- StartUp settings -->
index 97a13a8bfd2aa5056ad434bd156efdafbf5505a7..29985e9eab619ce3f2682d0cdd2c6c39fa17bf28 100644 (file)
@@ -81,6 +81,10 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
         <source>PREF_STORE_POS</source>
         <translation>Store positions of windows</translation>
     </message>
+    <message>
+      <source>PREF_BACKUP</source>
+      <translation>Backup every N minutes</translation>
+    </message>
     <message>
         <source>PREF_PROJECTION_MODE</source>
         <translation>Projection mode:</translation>
index c9ef2a243ca794505154d87ff21e3f95ceb8bd13..0a7b9ecf3bed91bc2fe88189ef680e6cf451c86c 100755 (executable)
@@ -694,3 +694,25 @@ void SUIT_Application::setLastUsedPrinter( const QString& thePrinterName )
   if( SUIT_ResourceMgr* aResMgr = resourceMgr() )
     aResMgr->setValue( "Printer", "last_used_printer", thePrinterName );
 }
+
+/*!
+ * Curent implementation does nothing; calls 'backup' method of active study in LightApp_Application
+ */
+void SUIT_Application::backup( const QString& /*fName*/ )
+{
+}
+
+/*!
+ * SUIT_Application does nothing; LightApp_Application keeps folder to be used for restoring.
+ */
+void SUIT_Application::setRestoreFolder( const QString& /*fName*/ )
+{
+}
+
+/*!
+ * Gets backup time from preferences; this method is used by session when backup timer is created.
+ */
+double SUIT_Application::getBackupTime() const
+{
+  return 0;
+}
index 7bf04f5a5f5280babf2e119ee0afa0754d571695..4d81b4f42f226469d99f1bdd55273edd036dfec9 100755 (executable)
@@ -109,6 +109,10 @@ public:
   //! Sets a name of the last used printer
   void                  setLastUsedPrinter( const QString& );
 
+  virtual void          backup( const QString& fName );
+  virtual void          setRestoreFolder( const QString& fName );
+  virtual double        getBackupTime() const;
+
 signals:
   void                  applicationClosed( SUIT_Application* );
   void                  activated( SUIT_Application* );
index a11ea26a624bde1a9079d4b3c40df2d4fcf7fcaf..2da346c8c5ecd41cded2c89ed89e1ee2dbd2a4f3 100755 (executable)
 //
 #include "SUIT_Session.h"
 
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
 #include "SUIT_Study.h"
 #include "SUIT_Tools.h"
 #include "SUIT_MessageBox.h"
 #include "SUIT_ResourceMgr.h"
 
 #include <QApplication>
-
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <dlfcn.h>
-#endif
+#include <QTimer>
+#include <QFileInfo>
+#include <QDir>
+#include <QSet>
 
 SUIT_Session* SUIT_Session::mySession = 0;
 
@@ -42,7 +46,9 @@ SUIT_Session::SUIT_Session()
   myActiveApp( 0 ),
   myHandler( 0 ),
   myExitStatus( NORMAL ),
-  myExitFlags ( 0 )
+  myExitFlags ( 0 ),
+  myBTimer( 0 ),
+  myBFile( 0 )
 {
   SUIT_ASSERT( !mySession )
 
@@ -63,6 +69,12 @@ SUIT_Session::~SUIT_Session()
     myResMgr = 0;
   }
   mySession = 0;
+
+  // remove backup
+  if ( myBFile )
+    fclose( myBFile );
+  if ( !myBFolder.isEmpty() )
+    Qtx::rmDir( myBFolder );
 }
 
 /*! \retval return mySession */
@@ -119,17 +131,17 @@ SUIT_Application* SUIT_Session::startApplication( const QString& name, int /*arg
     myResMgr->loadLanguage();
   }
 
-  //jfa 22.06.2005:SUIT_Application* anApp = crtInst( args, argv );
-  SUIT_Application* anApp = crtInst();
-  if ( !anApp )
+  //jfa 22.06.2005:SUIT_Application* app = crtInst( args, argv );
+  SUIT_Application* app = crtInst();
+  if ( !app )
   {
     SUIT_MessageBox::warning( 0, tr( "Error" ), tr( "Can not create application \"%1\": %2").arg( appName ).arg( lastError() ) );
     return 0;
   }
 
-  anApp->setObjectName( appName );
+  app->setObjectName( appName );
 
-  insertApplication( anApp );
+  insertApplication( app );
 
   if ( !myHandler )
   {
@@ -143,13 +155,21 @@ SUIT_Application* SUIT_Session::startApplication( const QString& name, int /*arg
       myHandler = crtHndlr();
   }
 
-  anApp->start();
+  app->start();
 
   // Application can be closed during starting (not started).
-  if ( !myAppList.contains( anApp ) )
-    anApp = 0;
+  if ( !myAppList.contains( app ) )
+    app = 0;
+
+  if ( !myBTimer )
+  {
+    myBTimer = (QTimer*)1; // block reation on creation of new application
+    restoreBackup();
+    myBTimer = 0;
+    createBTimer();
+  }
 
-  return anApp;
+  return app;
 }
 
 /*!
@@ -355,3 +375,240 @@ void SUIT_Session::onApplicationActivated( SUIT_Application* app )
 {
   myActiveApp = app;
 }
+
+/*!
+  Gets prefix to be used for  creating backup copies
+*/
+QString SUIT_Session::getBPrefix() const
+{
+  //qint64 pId = QApplication::applicationPid();
+#ifdef WNT
+  QString usr( getenv( "USERNAME" ) );
+#else 
+  QString usr( getenv( "USER" ) );
+#endif
+
+  // Create folder
+  QString anAppName;
+  SUIT_Application* app = activeApplication();
+  if ( app )
+    anAppName = app->applicationName();
+  else 
+    anAppName = "SALOME";
+
+  QString pref = anAppName + "_" + usr;
+
+  return pref;
+}
+
+/*!
+  Gets backup interval
+*/
+double SUIT_Session::backupTime() const
+{
+  double res;
+  if ( myBTimer )
+    res = myBTimer->interval() / 60. / 10e-3;
+  else 
+    res = 0;
+  return res;
+}
+
+/*!
+  Sets backup interval; this method is used by application 
+  when the interval is changed in preferences
+*/
+void SUIT_Session::setBackupTime( const double val ) const
+{
+  int newInt = val * 60 * 1e3;
+  if ( !myBTimer || newInt == myBTimer->interval() )
+    return;
+
+  myBTimer->setInterval( newInt );
+  if ( val <= 0 )
+    myBTimer->stop();
+  else 
+    myBTimer->start();
+}
+
+/*!
+  Creates timer to be used for backup
+*/
+void SUIT_Session::createBTimer()
+{
+  if ( myBTimer )
+    return;
+
+  SUIT_Application* app = activeApplication();
+  if ( !app )
+    return;
+
+  myBTimer = new QTimer( this );
+  connect( myBTimer, SIGNAL( timeout() ), this, SLOT( onBTimer() ) );
+
+  double mSec = app->getBackupTime() * 60 * 1e3;
+  if ( mSec > 0  )
+    myBTimer->start( mSec );
+
+  QString pref = QDir::convertSeparators( QDir::tempPath() + "/" + getBPrefix() );
+  myBFolder = pref;
+  int i = 0;
+  while( QFileInfo( myBFolder ).exists() )
+  {
+    myBFolder = pref + QString( "_%1" ).arg( ++i );
+  }
+
+  if ( !QDir().mkdir( myBFolder ) )
+    myBFolder = "";
+
+  if ( !myBFolder.isEmpty() )
+  {
+    QString used = Qtx::addSlash( myBFolder ) + "used";
+    myBFile = fopen( used.toLatin1().constData(), "w" );
+  }
+}
+
+/*!
+  Slot, called when backup interval is out, iterates through all opened 
+  applications, creates 'folderName' directories for them and calls app->backup( folderName );
+*/
+void SUIT_Session::onBTimer()
+{
+  QApplication::setOverrideCursor( Qt::WaitCursor );
+
+  // clear folder
+  Qtx::rmDir( myBFolder );
+  QDir().mkdir( myBFolder );
+  
+  // create backup
+  QString aName;
+  QList<SUIT_Application*> aList = applications();
+  QList<SUIT_Application*>::iterator it;
+  for ( it = aList.begin(); it != aList.end(); ++it )
+  {
+    SUIT_Application* app = *it;
+    if ( app && app->activeStudy() )
+    {
+      aName = app->activeStudy()->studyName();
+      aName.replace( ":", "%" );
+      aName.replace( "/", "+" );
+      aName.replace( "\\", "+" );
+      QString aFName = QDir::convertSeparators( myBFolder + "/" + aName );
+      QDir().mkdir( aFName );
+      QFileInfo fi( aFName );
+      if ( fi.exists() &&fi.isDir() )
+        app->backup( aFName );
+    }
+  }
+
+  QApplication::restoreOverrideCursor();
+}
+
+/*!
+  Restores crashed studies from backup
+*/
+void SUIT_Session::restoreBackup()
+{
+  QString pref = getBPrefix();
+
+  // checks whether temp folder contains old backups
+  QDir tmpDir( QDir::tempPath() );
+
+  QStringList filt;
+  filt.append( pref + "*" );
+  tmpDir.setNameFilters( filt );
+
+  QStringList sess = tmpDir.entryList ( QDir::Dirs );
+  if ( sess.count() == 0  )
+    return;
+
+  QSet<QString> stdSet;
+  QList<QString> toRestore;
+  QList<QString> toRemove;
+
+  // iterate through temp folder
+  QStringList::iterator sessIter;
+  for ( sessIter = sess.begin(); sessIter != sess.end(); ++sessIter )
+  {
+    // iterate through session folder
+    const QString& stdRoot = Qtx::addSlash( QDir::tempPath() ) + *sessIter;
+
+    // checks whether folder is not currently used
+    QString testFile = Qtx::addSlash( stdRoot ) + "used";
+    QFileInfo fi( testFile );
+    if ( fi.exists() && !QFile( testFile ).remove() )
+      continue;
+
+    toRemove.append( stdRoot );
+
+    QDir sessDir( stdRoot );
+    QStringList stdList = sessDir.entryList ( QDir::Dirs );
+
+    QStringList::iterator stdIt;
+    for ( stdIt = stdList.begin(); stdIt != stdList.end(); ++stdIt )
+    {
+      const QString& locName = *stdIt;
+      if ( *stdIt == "." || *stdIt == ".." )
+        continue;
+
+      const QString& study = Qtx::addSlash( stdRoot ) + *stdIt;
+      QDir stdDir( study );
+      QStringList fList = sessDir.entryList ( QDir::AllEntries );
+      if ( fList.count() > 2 && !stdSet.contains( locName ) )
+      {
+        stdSet.insert( locName );
+        toRestore.append( study );
+      }
+    }
+  }
+
+  // restore study if necessary
+  if ( !toRestore.isEmpty() )
+  {
+    QWidget* p = activeApplication() ? (QWidget*)activeApplication()->desktop() : 0;
+    
+    int aBtn = SUIT_MessageBox::warning( p, tr( "WRN_WARNING" ), tr( "WANT_TO_RESTORE" ),
+      SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::Yes );
+    if ( aBtn == SUIT_MessageBox::Yes )
+    {
+      QStringList::iterator it;
+      bool isFirst = true;
+      for ( it = toRestore.begin(); it != toRestore.end(); ++it )
+      {
+        SUIT_Application* app = activeApplication();
+        if ( !app )
+          return;
+
+        if ( !isFirst )
+          app = startApplication( app->objectName(), 0, 0 );
+
+        isFirst = false;
+        
+        if ( !app )
+          continue;
+
+        app->setRestoreFolder( *it );
+        
+        QString fName = *it;
+        int ind = fName.lastIndexOf( "\\" );
+        if ( ind == -1 )
+          ind = fName.lastIndexOf( "/" );
+        if ( ind >= 0 )
+          fName = fName.right( fName.length() - ind -1 );
+        fName.replace( "%", ":" );
+        fName.replace( "+", "/" );
+        fName.replace( "+", QDir::separator() );
+             if ( !app->useFile( fName ) )
+               app->closeApplication();
+      }      
+    }
+  }
+
+  // remove all backup folders
+  QStringList::iterator it;
+  for ( it = toRemove.begin(); it != toRemove.end(); ++it )
+  {
+    Qtx::rmDir( *it );
+  }
+}
+
index bc3ca3486693338c718cdaa77e3a2edfe4fa493f..70147565f412f4655b311ebfe29cbeeb4f21766d 100755 (executable)
@@ -37,6 +37,7 @@
 #endif
 
 class SUIT_ResourceMgr;
+class QTimer;
 class SUIT_ExceptionHandler;
 
 #ifdef WIN32
@@ -77,6 +78,9 @@ public:
 
   void                         insertApplication( SUIT_Application* );
 
+  double                       backupTime() const;
+  void                         setBackupTime( const double val ) const;
+
 signals:
   void                         applicationClosed( SUIT_Application* );
 
@@ -86,6 +90,12 @@ protected:
 private slots:
   void                         onApplicationClosed( SUIT_Application* );
   void                         onApplicationActivated( SUIT_Application* ); 
+  void                         onBTimer();
+
+private:
+  QString                       getBPrefix() const;
+  void                          createBTimer();
+  void                          restoreBackup();
 
 private:
   typedef QList<SUIT_Application*> AppList;
@@ -107,6 +117,10 @@ private:
 
   int                          myExitStatus;
   int                          myExitFlags;
+
+  QString                      myBFolder;
+  QTimer*                      myBTimer;
+  FILE*                        myBFile;
 };
 
 #endif
index ea1262d415352130b580165e6f2929353e2498ea..91ec41e408b53d4f43210ae56864da3a056aac4c 100755 (executable)
@@ -530,3 +530,4 @@ bool SUIT_Study::hasTransaction() const
 void SUIT_Study::restoreState(int /*savePoint*/)
 {
 }
+
index 466cbaf44fe7b0f59a83497053dd3bb7b760e5e3..507dd8d1ec4ad8683106a8252d8c00e25ba29bba 100644 (file)
@@ -131,4 +131,12 @@ Do you want to overwrite it?</translation>
         <translation>All files (*)</translation>
     </message>
 </context>
+  <context>
+    <name>SUIT_Session</name>
+    <message>
+      <source>WANT_TO_RESTORE</source>
+      <translation>Application crashed and one or several studies was unsaved.
+Do you want to restore them?</translation>
+    </message>
+  </context>
 </TS>