# define _separator_ '/'
#endif
+//---------------------------------------------------------
+#define USE_DEBUG
+#define MB_IGNORE_QT
+//#define MB_FULL_DUMP
+#define MBCLASSNAME "Model_Document"
+#include "MBDebug.h"
+// <-- insert includes for addtional debug headers here!
+//---------------------------------------------------------
+
static const int UNDO_LIMIT = 1000; // number of possible undo operations (big for sketcher)
static const int TAG_GENERAL = 1; // general properties tag
Handle(TDocStd_Document) theDoc,
const TCollection_ExtendedString& theFilename)
{
+ DBG_FUNC();
PCDM_StoreStatus aStatus;
try {
// create the directory to save the document
}
bool Model_Document::save(
- const char* theDirName, const char* theFileName, std::list<std::string>& theResults)
+ const char* theDirName, const char* theFileName,
+ std::list<std::string>& theResults,
+ bool doBackup/*=false*/)
{
+ DBG_FUN();
+ ARG(theDirName);
+ ARG(theFileName);
+ ARG(doBackup);
+
// if the history line is not in the end, move it to the end before save, otherwise
// problems with results restore and (the most important) naming problems will appear
// due to change evolution to SELECTION (problems in NamedShape and Name)
//! \param theResults the result full file names that were stored by "save"
//! \returns true if file was stored successfully
MODEL_EXPORT virtual bool save(
- const char* theDirName, const char* theFileName, std::list<std::string>& theResults);
+ const char* theDirName, const char* theFileName, std::list<std::string>& theResults, bool doBackup=false);
//! Export the list of features to the file
//! \param theFilename path to save the file
#include <TopoDS_Shape.hxx>
+//---------------------------------------------------------
+#define USE_DEBUG
+#define MB_IGNORE_QT
+//#define MB_FULL_DUMP
+#define MBCLASSNAME "Model_Session"
+#include "MBDebug.h"
+// <-- insert includes for addtional debug headers here!
+//---------------------------------------------------------
+
static Model_Session* myImpl = new Model_Session();
// to redirect all calls to the root document
return aRes;
}
-bool Model_Session::save(const char* theFileName, std::list<std::string>& theResults)
+bool Model_Session::save(const char* theFileName, std::list<std::string>& theResults, bool doBackup=false)
{
- return ROOT_DOC->save(theFileName, "root", theResults);
+ DBG_FUN();
+ ARG(theFileName);
+ ARG(doBackup);
+ return ROOT_DOC->save(theFileName, "root", theResults, doBackup);
}
void Model_Session::closeAll()
//! \param theFileName full name of the file to store
//! \param theResults the result full file names that were stored by "save"
//! \returns true if file was stored successfully
- MODEL_EXPORT virtual bool save(const char* theFileName, std::list<std::string>& theResults);
+ MODEL_EXPORT virtual bool save(const char* theFileName, std::list<std::string>& theResults, bool dobackup=false);
//! Closes all documents
MODEL_EXPORT virtual void closeAll();
//! \param theFileName full name of the file to store
//! \param theResults the result full file names that were stored by "save"
//! \returns true if file was stored successfully
- virtual bool save(const char* theFileName, std::list<std::string>& theResults) = 0;
+ virtual bool save(const char* theFileName, std::list<std::string>& theResults, bool isBackup=false) = 0;
//! Closes all documents
virtual void closeAll() = 0;
"part_visualization_study");
thePref->setItemProperty("strings", visuItemList, visuId);
thePref->setItemProperty("indexes", visuIdList, visuId);
+
+#if 1
+ // Group related to automatic backup
+ group = thePref->addPreference(QObject::tr("Automatically backup a study"), generalTab,
+ SUIT_PreferenceMgr::Auto, QString(), QString());
+
+ thePref->addPreference(QObject::tr("Enable automatic backup"), group, SUIT_PreferenceMgr::Bool,
+ ModuleBase_Preferences::GENERAL_SECTION, "use_auto_backup");
+
+ int delay = thePref->addPreference(QObject::tr("Backup Interval" ), group, SUIT_PreferenceMgr::IntSpin,
+ ModuleBase_Preferences::GENERAL_SECTION, "backup_interval" );
+ thePref->setItemProperty( "min", 5, delay );
+ thePref->setItemProperty( "max", 1440, delay );
+ thePref->setItemProperty( "suffix", " min", delay );
+
+ int folderPref = thePref->addPreference(QObject::tr("Backup Folder"), group, SUIT_PreferenceMgr::File, "backup_folder", QString()/*platform*/);
+ thePref->setItemProperty( "mode", Qtx::PT_Directory, folderPref );
+
+ visuItemList.clear();
+ visuItemList << QObject::tr("Store last backup only")
+ << QObject::tr("Store full backup history");
+ visuIdList.clear();
+ visuIdList << 0 << 1;
+ visuId = thePref->addPreference(QObject::tr("Backup Storage"), group, SUIT_PreferenceMgr::Selector,
+ ModuleBase_Preferences::GENERAL_SECTION,
+ "auto_backup_storage");
+ thePref->setItemProperty("strings", visuItemList, visuId);
+ thePref->setItemProperty("indexes", visuIdList, visuId);
+#endif
}
void ModuleBase_Preferences::updateSketchTab(ModuleBase_IPrefMgr* thePref, int thePageId)
SET(PROJECT_HEADERS
SHAPER_SHAPERGUI.h
SHAPERGUI.h
+ SHAPERGUI_CheckBackup.h
SHAPERGUI_DataModel.h
SHAPERGUI_OCCSelector.h
SHAPERGUI_SalomeViewer.h
SET(PROJECT_MOC_HEADERS
SHAPERGUI.h
+ SHAPERGUI_CheckBackup.h
SHAPERGUI_DataModel.h
SHAPERGUI_NestedButton.h
SHAPERGUI_SalomeViewer.h
SET(PROJECT_SOURCES
SHAPERGUI.cpp
+ SHAPERGUI_CheckBackup.cpp
SHAPERGUI_DataModel.cpp
SHAPERGUI_OCCSelector.cpp
SHAPERGUI_SalomeViewer.cpp
//
#include "SHAPERGUI.h"
+#include "SHAPERGUI_CheckBackup.h"
#include "SHAPERGUI_DataModel.h"
#include "SHAPERGUI_OCCSelector.h"
#include "SHAPERGUI_NestedButton.h"
#include <QTimer>
#include <QMenu>
#include <QToolBar>
+#include <QFileInfo>
+#include <QDir>
+
+#include <chrono>
+#include <future>
+#include <thread>
#include <ModelAPI_Session.h>
#include <Events_MessageBool.h>
+//---------------------------------------------------------
+#define USE_DEBUG
+//#define MB_IGNORE_QT
+//#define MB_FULL_DUMP
+#define MBCLASSNAME "SHAPERGUI"
+#include "MBDebug.h"
+// <-- insert includes for addtional debug headers here!
+//---------------------------------------------------------
+
#if OCC_VERSION_HEX < 0x070400
#define SALOME_PATCH_FOR_CTRL_WHEEL
#endif
};
+// static void DumpOperations(XGUI_Workshop *wshop)
+// {
+// XGUI_OperationMgr *aOpMgr = wshop->operationMgr();
+// if (!aOpMgr) return;
+// QStringList operations = aOpMgr->operationList();
+// SHOW(operations);
+// }
//******************************************************
myInspectionPanel(0), myIsFacesPanelVisible(false), myIsToolbarsModified(false),
myAxisArrowRate(-1)
{
+ DBG_FUN();
myWorkshop = new XGUI_Workshop(this);
connect(myWorkshop, SIGNAL(commandStatusUpdated()),
this, SLOT(onUpdateCommandStatus()));
ModuleBase_Preferences::setResourceMgr(application()->resourceMgr());
+ // initialize backup timer
+ myBackupTimer = new QTimer( this );
+ myBackupTimer->setSingleShot( true );
+ connect( myBackupTimer, SIGNAL( timeout() ), this, SLOT( onBackupDoc() ) );
+ connect( this, SIGNAL( backupDone(QString,bool) ), this, SLOT( onBackupDone(QString,bool) ));
+
// It will be called in XGUI_Workshop::startApplication
// ModuleBase_Preferences::loadCustomProps();
}
//******************************************************
SHAPERGUI::~SHAPERGUI()
{
+ DBG_FUN();
delete myWorkshop;
delete myProxyViewer;
}
//******************************************************
void SHAPERGUI::initialize(CAM_Application* theApp)
{
+ DBG_FUN();
LightApp_Module::initialize(theApp);
myWorkshop->startApplication();
//******************************************************
bool SHAPERGUI::activateModule(SUIT_Study* theStudy)
{
+ DBG_FUN();
ModelAPI_Session::get()->moduleDocument(); // initialize a root document if not done yet
// this must be done in the initialization and in activation (on the second activation
this, SLOT(onSaveDocByShaper()));
connect(getApp()->action(LightApp_Application::FileSaveAsId), SIGNAL(triggered(bool)),
this, SLOT(onSaveAsDocByShaper()));
+
+ //MBS:
+ SUIT_ResourceMgr* aResMgr = application()->resourceMgr();
+ if ( aResMgr && application()->activeStudy() ) {
+ bool useBackup = aResMgr->booleanValue( "General", "use_auto_backup", true );
+ if (useBackup) {
+ int backupInterval = aResMgr->integerValue( "General", "backup_interval", 1 );
+ if ( backupInterval > 0 ){
+ backupInterval = 1;
+ MSGEL("....starting BackupTimer: interval=" << backupInterval);
+ myBackupTimer->start( backupInterval*60000 );
+ }
+ }
+ }
+ //connect();
+
updateInfoPanel();
//connect(myWorkshop->operationMgr(), SIGNAL(operationResumed(ModuleBase_Operation*)),
//******************************************************
void SHAPERGUI::hideInternalWindows()
{
+ DBG_FUN();
myProxyViewer->activateViewer(false);
setMenuShown(false);
setToolShown(false);
//******************************************************
bool SHAPERGUI::deactivateModule(SUIT_Study* theStudy)
{
+ DBG_FUN();
saveToolbarsConfig();
myWorkshop->deactivateModule();
+ MSGEL("....stopping BackupTimer");
+ myBackupTimer->stop();
+
myIsInspectionVisible = myInspectionPanel->isVisible();
myIsFacesPanelVisible = myWorkshop->facesPanel()->isVisible();
hideInternalWindows();
-
// the active operation should be stopped for the next activation.
// There should not be active operation and visualized preview.
// Abort operation should be performed before the selection's remove
event );
}
+class WaitBackupResetter {
+public:
+ WaitBackupResetter(XGUI_Workshop *theWshop)
+ :myWorkshop(theWshop)
+ {
+ }
+ WaitBackupResetter() = delete;
+ ~WaitBackupResetter()
+ {
+ if (myWorkshop)
+ {
+ myWorkshop->setWaitForBackup(false);
+ myWorkshop = nullptr;
+ }
+ }
+private:
+ XGUI_Workshop *myWorkshop;
+};
+
//******************************************************
void SHAPERGUI::onOperationCommitted(ModuleBase_Operation* theOperation)
{
+ DBG_FUN();
+ SHOW(theOperation->id());
+
onOperationGeneric(theOperation, moduleName(), "committed");
+
+ if (myWorkshop && myWorkshop->waitForBackup())
+ {
+ XGUI_OperationMgr *operMgr = myWorkshop->operationMgr();
+ if (operMgr && operMgr->hasOperation())
+ {
+ // If the user is still running an operation, e.g. we left the line creation
+ // during sketch creation, do not yet create the backup
+ std::cout << "---> There are still active operations!" << std::endl;
+ return;
+ }
+ // There are no more active operations => we can now do the backup
+ WaitBackupResetter _resetter(myWorkshop);
+ onBackupDoc();
+ }
}
//******************************************************
void SHAPERGUI::onOperationAborted(ModuleBase_Operation* theOperation)
{
+ DBG_FUN();
+ SHOW(theOperation->id());
+
onOperationGeneric(theOperation, moduleName(), "aborted");
+
+ if (myWorkshop && myWorkshop->waitForBackup())
+ {
+ XGUI_OperationMgr *operMgr = myWorkshop->operationMgr();
+ if (operMgr && operMgr->hasOperation())
+ {
+ // If the user is still running an operation, e.g. we left the line creation
+ // during sketch creation, do not yet create the backup
+ std::cout << "---> There are still active operations!" << std::endl;
+ return;
+ }
+ // There are no more active operations => we can now do the backup
+ WaitBackupResetter _resetter(myWorkshop);
+ onBackupDoc();
+ }
}
//******************************************************
void SHAPERGUI::onViewManagerAdded(SUIT_ViewManager* theMgr)
{
+ DBG_FUN();
if (!mySelector) {
mySelector = createSelector(theMgr);
myWorkshop->selectionActivate()->updateSelectionFilters();
//******************************************************
void SHAPERGUI::onViewManagerRemoved(SUIT_ViewManager* theMgr)
{
+ DBG_FUN();
if (mySelector) {
if (theMgr->getType() == OCCViewer_Viewer::Type()) {
OCCViewer_Viewer* aViewer = static_cast<OCCViewer_Viewer*>(theMgr->getViewModel());
//******************************************************
void SHAPERGUI::onDefaultPreferences()
{
+ DBG_FUN();
// reset main resources
ModuleBase_Preferences::resetResourcePreferences(preferences());
// reset plugin's resources
//******************************************************
void SHAPERGUI::onScriptLoaded()
{
+ DBG_FUN();
// this slot is called after processing of the LoadScriptId action of SalomeApp Application
// Each dumped script contains updateObjBrowser() that creates a new instance of Object
// Browser. When SHAPER module is active, this browser should not be used. It might be removed
//******************************************************
void SHAPERGUI::onSaveDocByShaper()
{
+ DBG_FUN();
if(!workshop()->operationMgr()->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
return;
//******************************************************
void SHAPERGUI::onSaveAsDocByShaper()
{
+ DBG_FUN();
if(!workshop()->operationMgr()->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
return;
getApp()->onSaveAsDoc();
}
+//******************************************************
+void SHAPERGUI::onBackupDoc()
+{
+ DBG_FUN();
+ MSGEL(" ...backing up current study");
+
+ if (myWorkshop && myWorkshop->operationMgr())
+ {
+ if (myWorkshop->operationMgr()->hasOperation())
+ {
+ // If the user is running an operation, only do the backup
+ // after the operation has finished (committed or cancelled).
+ myWorkshop->setWaitForBackup();
+ return;
+ }
+ // Run the backup in a separate thread!!
+ myBackupResult = std::async(std::launch::async, [this]{return this->backupDoc();});
+ }
+}
+
+class LockBackupState {
+public:
+ LockBackupState(XGUI_Workshop *wshop) : myWorkshop(wshop)
+ {
+ if (myWorkshop) myWorkshop->setBackupState();
+ }
+ ~LockBackupState()
+ {
+ if (myWorkshop) myWorkshop->setBackupState(false);
+ myWorkshop = nullptr;
+ }
+ XGUI_Workshop *myWorkshop;
+};
+
+//******************************************************
+bool SHAPERGUI::backupDoc()
+{
+ DBG_FUN();
+
+ bool isOk = false;
+#if 0
+ MSGEL("...sleep for 5 seconds");
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ isOk = true;
+ QString aName("/some/file/name.hdf");
+#else
+ SUIT_Study* study = application()->activeStudy();
+ if ( !study )
+ return false;
+
+ // if ( !abortAllOperations() )
+ // return false;
+
+ LockBackupState lockBackup(myWorkshop);
+
+ QString aName = study->studyName();
+ try
+ {
+ SHOW(aName);
+ if ( aName.isNull() )
+ return false;
+
+ const QChar aSep = QDir::separator();
+
+ QString aFolder("/home/bernhard/backups");
+
+ QDateTime now = QDateTime::currentDateTime();
+ aFolder += aSep + now.toString("yyyyMMdd_hhmmss");
+
+ QDir aDir(aFolder);
+ if (!aDir.exists()) {
+ aDir.mkpath(aFolder);
+ aDir.mkdir(aFolder);
+ }
+
+ if (study->isSaved()) {
+ // Retrieve the filename only from the fullpath
+ QFileInfo fi(aName);
+ aName = fi.completeBaseName();
+ }
+ QString aFullName = aFolder + aSep + aName + QString(".hdf");
+ SHOW(aFullName);
+
+ // Save the study into a single HDF file
+ isOk = study->saveDocumentAs( aFullName, true );
+ if (!isOk){
+ MSGEL("ERR: failed to backup study document");
+ return isOk;
+ }
+
+ // Now, dump the python script
+ LightApp_Study *lightStudy = dynamic_cast<LightApp_Study*>(study);
+ if (!lightStudy)
+ return false;
+
+ aFullName = aFolder + aSep + aName + QString(".py");
+ isOk = lightStudy->dump(aFullName, true, false, false);
+ if (!isOk){
+ MSGEL("ERR: failed to backup python script");
+ return isOk;
+ }
+
+ // Finally start another salome process and reload the saved document & script for verification
+ SHAPERGUI_CheckBackup checkBackup(aFolder, aName);
+ QString testScript("/home/bernhard/backups/checkValidity.py");
+ int aResult = checkBackup.run(testScript);
+ isOk = (aResult == 0);
+ }
+ catch (std::exception &ex)
+ {
+ std::cout << "ERROR: std::exception caught" << std::endl;
+ isOk = false;
+ }
+ catch (...)
+ {
+ std::cout << "ERROR: unknown exception caught" << std::endl;
+ isOk = false;
+ }
+ #endif
+
+ MSGEL("...emit backupDone signal");
+ emit backupDone(aName, isOk);
+ return isOk;
+}
+
+//******************************************************
+void SHAPERGUI::onBackupDone(QString aName, bool aResult)
+{
+ DBG_FUN();
+ ARG(aName);
+ ARG(aResult);
+
+ bool isOk = myBackupResult.get();
+ SHOW(isOk);
+ QFileInfo fi(aName);
+ aName = fi.canonicalPath();
+ SHOW(aName);
+ putInfo( isOk ? tr("Backup done in folder: %1").arg(aName) : tr("Failed to backup active study!"), 5000 );
+}
+
//******************************************************
void SHAPERGUI::onUpdateCommandStatus()
{
//******************************************************
SHAPERGUI_OCCSelector* SHAPERGUI::createSelector(SUIT_ViewManager* theMgr)
{
+ DBG_FUN();
if (theMgr->getType() == OCCViewer_Viewer::Type()) {
OCCViewer_Viewer* aViewer = static_cast<OCCViewer_Viewer*>(theMgr->getViewModel());
//******************************************************
CAM_DataModel* SHAPERGUI::createDataModel()
{
+ DBG_FUN();
return new SHAPERGUI_DataModel(this);
}
//******************************************************
void SHAPERGUI::createPreferences()
{
+ DBG_FUN();
LightApp_Preferences* aPref = preferences();
if (!aPref)
return;
//******************************************************
void SHAPERGUI::preferencesChanged(const QString& theSection, const QString& theParam)
{
+ DBG_FUN();
+ ARG(theSection);
+ ARG(theParam);
SUIT_ResourceMgr* aResMgr = application()->resourceMgr();
QString aVal = aResMgr->stringValue(theSection, theParam);
Config_Prop* aProp = Config_PropManager::findProp(theSection.toStdString(),
}
}
}
- else if (theSection == ModuleBase_Preferences::GENERAL_SECTION && theParam == "create_init_part") {
- bool aCreate = ModuleBase_Preferences::resourceMgr()->booleanValue(
- ModuleBase_Preferences::GENERAL_SECTION, "create_init_part", true);
- Events_MessageBool aCreateMsg(Events_Loop::eventByName(EVENT_CREATE_PART_ON_START), aCreate);
- aCreateMsg.send();
+ else if (theSection == ModuleBase_Preferences::GENERAL_SECTION) {
+ if (theParam == "create_init_part") {
+ bool aCreate = ModuleBase_Preferences::resourceMgr()->booleanValue(
+ ModuleBase_Preferences::GENERAL_SECTION, "create_init_part", true);
+ Events_MessageBool aCreateMsg(Events_Loop::eventByName(EVENT_CREATE_PART_ON_START), aCreate);
+ aCreateMsg.send();
+ }
+ else if (theParam == "use_auto_backup") {
+ bool useBackup = ModuleBase_Preferences::resourceMgr()->booleanValue(
+ ModuleBase_Preferences::GENERAL_SECTION, "use_auto_backup", true);
+ if (useBackup) {
+ int backupInterval = aResMgr->integerValue( ModuleBase_Preferences::GENERAL_SECTION, "backup_interval", 1 );
+ if ( backupInterval > 0 ){
+ backupInterval = 1;
+ MSGEL("....starting BackupTimer: interval=" << backupInterval << " min");
+ myBackupTimer->start( backupInterval*60000 );
+ }
+ else {
+ MSGEL("....stopping backup timer");
+ myBackupTimer->stop();
+ }
+ }
+ else {
+ MSGEL("....stopping backup timer");
+ myBackupTimer->stop();
+ }
+ }
}
else if (theSection == ModuleBase_Preferences::VIEWER_SECTION &&
theParam.startsWith("group_names_"))
bool SHAPERGUI::abortAllOperations()
{
+ DBG_FUN();
return workshop()->operationMgr()->abortAllOperations();
}
void SHAPERGUI::createFeatureActions()
{
+ DBG_FUN();
myWorkshop->menuMgr()->createFeatureActions();
}
void SHAPERGUI::saveToolbarsConfig()
{
+ DBG_FUN();
if (!myIsToolbarsModified)
return;
// Save toolbars configuration into map
void SHAPERGUI::loadToolbarsConfig()
{
+ DBG_FUN();
SUIT_ResourceMgr* aResMgr = application()->resourceMgr();
QStringList aToolbarNames = aResMgr->parameters(ToolbarsSection);
if (aToolbarNames.size() == 0)
void SHAPERGUI::resetToolbars()
{
+ DBG_FUN();
if (!myDefaultToolbars.isEmpty())
updateToolbars(myDefaultToolbars);
myIsToolbarsModified = false;
void SHAPERGUI::publishToStudy()
{
+ DBG_FUN();
if (isActiveModule() && ModelAPI_Session::get()->hasModuleDocument()) {
myWorkshop->module()->launchOperation("PublishToStudy", false);
#include <QList>
#include <QMap>
+#include <future>
class XGUI_Workshop;
class SHAPERGUI_OCCSelector;
virtual void updateInfoPanel();
+ signals:
+ void backupDone(QString aName, bool aResult);
+
public slots:
/// \brief The method is redefined to connect to the study viewer before the data
/// model is filled by opened file. This file open will flush redisplay signals for,
/// Save application functionality with additional processing of aborting the current operation
void onSaveAsDocByShaper();
+ /// Backup document functionality with additional file validation
+ void onBackupDoc();
+
+ /// Document has been backed-up
+ void onBackupDone(QString aName, bool aResult);
+
/// Obtains the current application and updates its actions
void onUpdateCommandStatus();
/// Abort all operations
virtual bool abortAllOperations();
+ bool backupDoc();
+
private slots:
void onWhatIs(bool isToggled);
Handle(Graphic3d_AspectMarker3d) myHighlightPointAspect;
double myAxisArrowRate;
+
+ QTimer* myBackupTimer;
+ std::future<bool> myBackupResult;
};
#endif
--- /dev/null
+// Copyright (C) 2023 CEA, EDF, OPEN CASCADE SAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "SHAPERGUI_CheckBackup.h"
+#include <QDir>
+#include <QFileInfo>
+#include <QStringList>
+
+//---------------------------------------------------------
+#define USE_DEBUG
+//#define MB_IGNORE_QT
+//#define MB_FULL_DUMP
+#define MBCLASSNAME "SHAPERGUI_CheckBackup"
+#include "MBDebug.h"
+// <-- insert includes for addtional debug headers here!
+//---------------------------------------------------------
+
+
+
+SHAPERGUI_CheckBackup::SHAPERGUI_CheckBackup(const QString &theFolder, const QString &theBaseName)
+ : myProcess(nullptr)
+ , myFolder(theFolder)
+ , myBaseName(theBaseName)
+{
+ DBG_FUN();
+ ARG(theFolder);
+ ARG(theBaseName);
+}
+
+
+int SHAPERGUI_CheckBackup::run(const QString &theTestScript)
+{
+ DBG_FUN();
+ ARG(theTestScript);
+
+ int aResult = 0;
+ if (myProcess)
+ return 1;
+
+ QString aProgName = std::getenv("PYTHONBIN");
+ if (aProgName.isEmpty())
+ aProgName = "python3";
+
+ const QChar aSep = QDir::separator();
+
+ QString testBackup("test_backup.py");
+ QStringList dirs;
+#if 0
+ dirs << QString(std::getenv("SHAPER_ROOT_DIR"))
+ << QString("bin")
+ << QString("salome")
+ << testBackup;
+#else
+ dirs << QString(std::getenv("HOME"))
+ << QString("S2")
+ << QString("SALOME-MBS-DB11")
+ << testBackup;
+#endif
+ QString scriptName = dirs.join( QDir::separator() );
+
+ QStringList args;
+ args << scriptName << myFolder << myBaseName << theTestScript;
+
+ myProcess = new QProcess(this);
+ if (!myProcess)
+ return 2;
+
+ connect(myProcess, SIGNAL(started()), this, SLOT(procStarted()));
+ connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this,
+ SLOT(procError(QProcess::ProcessError)));
+ connect(myProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this,
+ SLOT(procFinished(int, QProcess::ExitStatus)));
+
+ SHOW(aProgName);
+ SHOW(args);
+ myProcess->setStandardOutputFile((QStringList() << myFolder << myBaseName+".log").join(aSep));
+ myProcess->start(aProgName, args);
+ myProcess->waitForFinished(300000);
+ int exitStat = myProcess->exitStatus();
+ SHOW(exitStat);
+ int exitCode = myProcess->exitCode();
+ SHOW(exitCode);
+ if (exitStat == 0/*NormalExit*/ && exitCode != 0)
+ aResult = exitCode;
+ else if (exitStat == -1/*CrashExit*/)
+ aResult = 99;
+ myProcess->deleteLater();
+
+ return 0;
+}
+
+
+void SHAPERGUI_CheckBackup::procStarted()
+{
+ DBG_FUN();
+}
+
+
+void SHAPERGUI_CheckBackup::procFinished(int code, QProcess::ExitStatus stat)
+{
+ DBG_FUN();
+ ARG(code);
+ ARG2(stat, int);
+}
+
+
+void SHAPERGUI_CheckBackup::procError(QProcess::ProcessError err)
+{
+ DBG_FUN();
+ ARG2(err, int);
+}
--- /dev/null
+// Copyright (C) 2023 CEA, EDF, OPEN CASCADE SAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SHAPERGUI_CHECKBACKUP_H
+#define SHAPERGUI_CHECKBACKUP_H
+
+#include "SHAPER_SHAPERGUI.h"
+#include <QProcess>
+
+
+class SHAPERGUI_EXPORT SHAPERGUI_CheckBackup : public QObject
+{
+ Q_OBJECT
+public:
+ SHAPERGUI_CheckBackup(const QString &theFolder, const QString &theBaseName);
+ int run(const QString &theTestScript);
+
+private slots:
+ void procStarted();
+ void procFinished(int, QProcess::ExitStatus);
+ void procError(QProcess::ProcessError);
+
+private:
+ QProcess* myProcess;
+ QString myFolder;
+ QString myBaseName;
+};
+
+#endif
#include <QDir>
#include <QTextStream>
+//---------------------------------------------------------
+#define USE_DEBUG
+//#define MB_IGNORE_QT
+//#define MB_FULL_DUMP
+#define MBCLASSNAME "SHAPERGUI_DataModel"
+#include "MBDebug.h"
+// <-- insert includes for addtional debug headers here!
+//---------------------------------------------------------
+
#define DUMP_NAME "shaper_dump.py"
SHAPERGUI_DataModel::SHAPERGUI_DataModel(SHAPERGUI* theModule)
: LightApp_DataModel(theModule), myStudyPath(""), myModule(theModule)
{
+ DBG_FUN();
}
SHAPERGUI_DataModel::~SHAPERGUI_DataModel()
{
+ DBG_FUN();
}
bool SHAPERGUI_DataModel::open(const QString& thePath, CAM_Study* theStudy, QStringList theFiles)
{
+ DBG_FUN();
+ ARG(thePath);
+ ARG(theFiles);
LightApp_DataModel::open( thePath, theStudy, theFiles );
if (theFiles.size() == 0)
return false;
return true;
}
-bool SHAPERGUI_DataModel::save(QStringList& theFiles)
+bool SHAPERGUI_DataModel::save(QStringList& theFiles, bool isBackup/*=false*/)
{
+ DBG_FUN();
+ ARG(theFiles);
+ ARG(isBackup);
// Publish to study before saving of the data model
- myModule->publishToStudy();
+ //if (!isBackup)
+ myModule->publishToStudy();
- LightApp_DataModel::save( theFiles );
+ //if (!isBackup)
+ LightApp_DataModel::save( theFiles );
XGUI_Workshop* aWorkShop = myModule->workshop();
std::list<std::string> aFileNames;
return true;
}
-bool SHAPERGUI_DataModel::saveAs(const QString& thePath, CAM_Study* theStudy, QStringList& theFiles)
+bool SHAPERGUI_DataModel::saveAs(const QString& thePath, CAM_Study* theStudy, QStringList& theFiles, bool isBackup/*=false*/)
{
+ DBG_FUN();
+ ARG(thePath);
+ ARG(theFiles);
+ ARG(isBackup);
myStudyPath = thePath;
- return save(theFiles);
+ return save(theFiles, isBackup);
}
bool SHAPERGUI_DataModel::close()
{
+ DBG_FUN();
myModule->workshop()->closeDocument();
return LightApp_DataModel::close();
}
bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy,
bool isMultiFile, QStringList& theListOfFiles)
{
+ DBG_FUN();
+ ARG(thePath);
+ ARG(theListOfFiles);
LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(theStudy);
if (!aStudy)
return false;
/// Save module data to file
/// \param theFiles list of created files
- virtual bool save(QStringList& theFiles);
+ virtual bool save(QStringList& theFiles, bool isBackup=false);
/// Save module data to a file
/// \param thePath a path to the directory
/// \param theStudy a current study
/// \param theFiles a list of files to open
- virtual bool saveAs(const QString& thePath, CAM_Study* theStudy, QStringList& theFiles);
+ virtual bool saveAs(const QString& thePath, CAM_Study* theStudy, QStringList& theFiles, bool isBackup=false);
/// Close data structure
virtual bool close();
<source>Text color</source>
<translation>Couleur du texte</translation>
</message>
+ <message>
+ <source>Backup done in folder: %1</source>
+ <translation>Sauvegarde effectuée dans le dossier: %1</translation>
+ </message>
+ <message>
+ <source>Failed to backup active study!</source>
+ <translation>Échec de la sauvegarde de l'étude active!</translation>
+ </message>
</context>
<context>
<name>SHAPERGUI_ToolbarItemsDlg</name>
#include <dlfcn.h>
#endif
+//---------------------------------------------------------
+#define USE_DEBUG
+//#define MB_IGNORE_QT
+//#define MB_FULL_DUMP
+#define MBCLASSNAME "XGUI_Workshop"
+#include "MBDebug.h"
+// <-- insert includes for addtional debug headers here!
+//---------------------------------------------------------
+
//#define DEBUG_WITH_MESSAGE_REPORT
QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
myDisplayer(0),
mySalomeConnector(theConnector),
//myViewerSelMode(TopAbs_FACE),
- myInspectionPanel(0)
+ myInspectionPanel(0),
+ myDoBackup(false)
{
+ DBG_FUN();
mySelector = new XGUI_SelectionMgr(this);
myModuleConnector = new XGUI_ModuleConnector(this);
myOperationMgr = new XGUI_OperationMgr(this, myModuleConnector);
//******************************************************
XGUI_Workshop::~XGUI_Workshop(void)
{
+ DBG_FUN();
#ifdef _DEBUG
#ifdef MISSED_TRANSLATION
// Save Missed translations
//******************************************************
void XGUI_Workshop::startApplication()
{
+ DBG_FUN();
//Initialize event listening
myEventsListener->initializeEventListening();
}
+//******************************************************
+void XGUI_Workshop::setBackupState(bool doBackup/*=true*/)
+{
+ DBG_FUN();
+ ARG(doBackup);
+ myDoBackup = doBackup;
+}
+
+
+//******************************************************
+void XGUI_Workshop::setWaitForBackup(bool theDoWait/*=true*/)
+{
+ DBG_FUN();
+ ARG(theDoWait);
+ myWaitForBackup = theDoWait;
+ if (theDoWait)
+ {
+ std::cout << "..... waiting for operation to finish to start backup." << std::endl;
+ }
+}
+
+
//******************************************************
void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
{
//******************************************************
void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
{
+ DBG_FUN();
+ ARG(theOperation->getDescription()->operationId());
+
setGrantedFeatures(theOperation);
if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel
//******************************************************
void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
{
+ DBG_FUN();
+ ARG(theOperation->getDescription()->operationId());
+
updateCommandStatus();
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
//******************************************************
void XGUI_Workshop::saveDocument(const QString& theName, std::list<std::string>& theFileNames)
{
+ DBG_FUN();
+ ARG(theName);
+ ARG(theFileNames);
+ SHOW(myDoBackup);
QApplication::restoreOverrideCursor();
SessionPtr aMgr = ModelAPI_Session::get();
//******************************************************
bool XGUI_Workshop::abortAllOperations()
{
+ DBG_FUN();
return myOperationMgr->abortAllOperations();
}
//******************************************************
void XGUI_Workshop::operationStarted(ModuleBase_Operation* theOperation)
{
+ DBG_FUN();
+ ARG(theOperation->getDescription()->operationId());
setGrantedFeatures(theOperation);
if (!theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel
updateCommandStatus();
//******************************************************
void XGUI_Workshop::onOpen()
{
+ DBG_FUN();
if(!abortAllOperations())
return;
//save current file before close if modified
//******************************************************
void XGUI_Workshop::openFile(const QString& theDirectory)
{
+ DBG_FUN();
+ ARG(theDirectory);
myCurrentFile = theDirectory;
if (myCurrentFile.isEmpty())
return;
//******************************************************
bool XGUI_Workshop::onSave()
{
- if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
+ DBG_FUN();
+ SHOW(myDoBackup);
+
+ if(!myDoBackup && !myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
return false;
if (myCurrentFile.isEmpty()) {
return onSaveAs();
//******************************************************
bool XGUI_Workshop::onSaveAs()
{
+ DBG_FUN();
+ SHOW(myDoBackup);
if(!myOperationMgr->abortAllOperations(XGUI_OperationMgr::XGUI_InformationMessage))
return false;
qreal aRatio = ModuleBase_Tools::currentPixelRatio();
//******************************************************
ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
{
+ DBG_FUN();
+ ARG(theModule);
QString libName = QString::fromStdString(library(theModule.toStdString()));
if (libName.isEmpty()) {
qWarning(qPrintable(tr("Information about module \"%1\" doesn't exist.").arg(theModule)));
// all nested parts.
std::list<FeaturePtr> allFeatures(const DocumentPtr& theDocument)
{
+ DBG_FUNC();
std::list<FeaturePtr> aResultList;
std::list<FeaturePtr> anAllFeatures = theDocument->allFeatures();
foreach (const FeaturePtr& aFeature, anAllFeatures) {
// The order of appending features of the part and the part itself is important
+ MSGEL("* aFeature = [" << aFeature->getKind() << "] action=" << aFeature->isAction());
// Append features from a part feature
std::list<ResultPtr> aResults;
void showHelpPage(const QString& thePage) const;
+ void setBackupState(bool theDoBackup=true);
+
+ void setWaitForBackup(bool theDoWait=true);
+
+ bool waitForBackup() const { return myWaitForBackup; }
+
signals:
/// Emitted when selection happens in Salome viewer
void salomeViewerSelection();
Config_DataModelReader* myDataModelXMLReader; ///< XML reader of data model
XGUI_InspectionPanel* myInspectionPanel; ///< container of feature attributes widgets
QTemporaryDir myTmpDir; ///< a direcory for uncompressed files
+ bool myDoBackup; ///< whether the current save was initiated by automatic backup
+ bool myWaitForBackup; ///< whether to do a backup when current operation finishes
};
#endif
with open(testlogfile, 'r') as inputFile:
s = inputFile.read()
- #print("logfile: ", s)
+ print("logfile: ", s)
if s.find("FAIL") > 0:
isOk = False
error = s