Salome HOME
Disable undo on active operation (to prevent crash on undo the sketch creation)
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
index 8c76c2fd11cf18d84788e79300b9b76ea9b50242..c7a98185b9d71246dce94c5d101a9e77e0bae25b 100644 (file)
@@ -14,7 +14,6 @@
 #include "XGUI_Displayer.h"
 #include "XGUI_OperationMgr.h"
 #include "XGUI_SalomeConnector.h"
-#include "XGUI_SalomeViewer.h"
 #include "XGUI_ActionsMgr.h"
 #include "XGUI_ErrorDialog.h"
 #include "XGUI_ViewerProxy.h"
@@ -44,7 +43,9 @@
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_OperationDescription.h>
 #include <ModuleBase_SelectionValidator.h>
-#include "ModuleBase_WidgetFactory.h"
+#include <ModuleBase_WidgetFactory.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_IViewer.h>
 
 #include <Config_Common.h>
 #include <Config_FeatureMessage.h>
@@ -112,14 +113,17 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
 
   myModuleConnector = new XGUI_ModuleConnector(this);
 
-  connect(myOperationMgr, SIGNAL(operationStarted()), SLOT(onOperationStarted()));
+  connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)), 
+          SLOT(onOperationStarted()));
   connect(myOperationMgr, SIGNAL(operationResumed()), SLOT(onOperationStarted()));
   connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
           SLOT(onOperationStopped(ModuleBase_Operation*)));
   connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
-  connect(myOperationMgr, SIGNAL(operationStarted()), myActionsMgr, SLOT(update()));
-  connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)), myActionsMgr,
-          SLOT(update()));
+  // TODO(sbh): It seems that application works properly without update on operationStarted
+  connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)),
+          myActionsMgr,   SLOT(update()));
+  connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
+          myActionsMgr,   SLOT(update()));
   connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&)));
 }
 
@@ -136,9 +140,7 @@ void XGUI_Workshop::startApplication()
   //Initialize event listening
   Events_Loop* aLoop = Events_Loop::loop();
   aLoop->registerListener(this, Events_Error::errorID());  //!< Listening application errors.
-  //TODO(sbh): Implement static method to extract event id [SEID]
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_LOADED));
-  // TODO Is it good to use non standard event within workshop?
+  aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OPERATION_LAUNCHED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
@@ -177,6 +179,11 @@ void XGUI_Workshop::initMenu()
                                                 false);
     connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRedo()));
     salomeConnector()->addEditMenuSeparator();
+    aAction = salomeConnector()->addEditCommand("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
+                                                QIcon(":pictures/rebuild.png"), QKeySequence(),
+                                                false);
+    connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onRebuild()));
+    salomeConnector()->addEditMenuSeparator();
     return;
   }
   // File commands group
@@ -250,7 +257,7 @@ void XGUI_Workshop::processEvent(const boost::shared_ptr<Events_Message>& theMes
   }
 
   //A message to start feature creation received.
-  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_LOADED)) {
+  if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
     boost::shared_ptr<Config_FeatureMessage> aFeatureMsg =
        boost::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
     if (!aFeatureMsg->isInternal()) {
@@ -339,10 +346,10 @@ void XGUI_Workshop::processEvent(const boost::shared_ptr<Events_Message>& theMes
     }
   }
   else if (theMessage->eventID() == Events_Loop::loop()->eventByName("CurrentDocumentChanged")) {
+    myActionsMgr->update();
     // Find and Activate active part
     if (myPartActivating)
       return;
-    myActionsMgr->update();
     SessionPtr aMgr = ModelAPI_Session::get();
     DocumentPtr aActiveDoc = aMgr->activeDocument();
     DocumentPtr aDoc = aMgr->moduleDocument();
@@ -409,9 +416,15 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const boost::shared_ptr<ModelAPI_Objec
 {
   std::set<ObjectPtr> aObjects = theMsg->objects();
   std::set<ObjectPtr>::const_iterator aIt;
+  QIntList aModes;
   for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
     ObjectPtr aObj = (*aIt);
-    if (!aObj->data() || !aObj->data()->isValid() || aObj->document()->isConcealed(aObj))
+    bool aHide = !aObj->data() || !aObj->data()->isValid();
+    if (!aHide) { // check that this is not hidden result
+      ResultPtr aRes = boost::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+      aHide = aRes && aRes->isConcealed();
+    }
+    if (aHide)
       myDisplayer->erase(aObj, false);
     else {
       if (myDisplayer->isVisible(aObj))  {
@@ -420,7 +433,7 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const boost::shared_ptr<ModelAPI_Objec
           ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
           if (!aOperation->hasObject(aObj))
             if (!myDisplayer->isActive(aObj))
-              myDisplayer->activate(aObj);
+              myDisplayer->activate(aObj, aModes);
         }
       } else {
         if (myOperationMgr->hasOperation()) {
@@ -455,8 +468,7 @@ void XGUI_Workshop::onFeatureCreatedMsg(const boost::shared_ptr<ModelAPI_ObjectU
       // it doesn't stored in the operation mgr and doesn't displayed
     } else if (myOperationMgr->hasOperation()) {
       ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-      if (!(*aIt)->document()->isConcealed(*aIt) &&
-          aOperation->hasObject(*aIt)) {  // Display only current operation results
+      if (aOperation->hasObject(*aIt)) {  // Display only current operation results
         myDisplayer->display(*aIt, false);
         isDisplayed = true;
       }
@@ -498,12 +510,10 @@ void XGUI_Workshop::onOperationStarted()
 
     myPropertyPanel->cleanContent();
     aFactory.createWidget(myPropertyPanel->contentWidget());
+    ModuleBase_Tools::zeroMargins(myPropertyPanel->contentWidget());
 
     QList<ModuleBase_ModelWidget*> aWidgets = aFactory.getModelWidgets();
-    QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
-    ModuleBase_ModelWidget* aWidget;
-    for (; anIt != aLast; anIt++) {
-      aWidget = *anIt;
+    foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
       aWidget->setFeature(aOperation->feature());
       aWidget->enableFocusProcessing();
       QObject::connect(aWidget, SIGNAL(valuesChanged()), this, SLOT(onWidgetValuesChanged()));
@@ -513,8 +523,10 @@ void XGUI_Workshop::onOperationStarted()
       }
     }
 
+    aOperation->setPropertyPanel(myPropertyPanel);
     myPropertyPanel->setModelWidgets(aWidgets);
-    myPropertyPanel->onActivateNextWidget(NULL);
+    if (!aOperation->activateByPreselection())
+      myPropertyPanel->activateNextWidget(NULL);
     // Widget activation (from the previous method) may commit the current operation
     // if pre-selection is enougth for it. So we shouldn't update prop panel's title
     if(myOperationMgr->isCurrentOperation(aOperation)) {
@@ -571,6 +583,8 @@ void XGUI_Workshop::addFeature(const boost::shared_ptr<Config_FeatureMessage>& t
                                                      QKeySequence(),
                                                      isUsePropPanel);
     salomeConnector()->setNestedActions(aFeatureId, aNestedFeatures.split(" ", QString::SkipEmptyParts));
+    salomeConnector()->setDocumentKind(aFeatureId, QString::fromStdString(theMessage->documentKind()));
+
     myActionsMgr->addCommand(aAction);
     myModule->featureCreated(aAction);
   } else {
@@ -879,7 +893,7 @@ ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
   }
 #endif
 
-  ModuleBase_IModule* aModule = crtInst ? crtInst(this) : 0;
+  ModuleBase_IModule* aModule = crtInst ? crtInst(myModuleConnector) : 0;
 
   if (!err.isEmpty()) {
     if (mainWindow()) {
@@ -917,8 +931,7 @@ void XGUI_Workshop::updateCommandStatus()
   }
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->hasModuleDocument()) {
-    QAction* aUndoCmd;
-    QAction* aRedoCmd;
+    QAction *aUndoCmd, *aRedoCmd;
     foreach(QAction* aCmd, aCommands) {
       QString aId = aCmd->data().toString();
       if (aId == "UNDO_CMD")
@@ -929,8 +942,8 @@ void XGUI_Workshop::updateCommandStatus()
         // Enable all commands
         aCmd->setEnabled(true);
     }
-    aUndoCmd->setEnabled(aMgr->canUndo());
-    aRedoCmd->setEnabled(aMgr->canRedo());
+    aUndoCmd->setEnabled(aMgr->canUndo() && !aMgr->isOperation());
+    aRedoCmd->setEnabled(aMgr->canRedo() && !aMgr->isOperation());
   } else {
     foreach(QAction* aCmd, aCommands) {
       QString aId = aCmd->data().toString();
@@ -994,6 +1007,7 @@ void XGUI_Workshop::createDockWidgets()
   hidePropertyPanel();  //<! Invisible by default
   hideObjectBrowser();
   aDesktop->tabifyDockWidget(aObjDock, myPropertyPanel);
+  myPropertyPanel->installEventFilter(myOperationMgr);
 
   QPushButton* aOkBtn = myPropertyPanel->findChild<QPushButton*>(XGUI::PROP_PANEL_OK);
   connect(aOkBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onCommitOperation()));
@@ -1001,10 +1015,6 @@ void XGUI_Workshop::createDockWidgets()
   connect(aCancelBtn, SIGNAL(clicked()), myOperationMgr, SLOT(onAbortOperation()));
   connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)), myOperationMgr,
           SLOT(onKeyReleased(QKeyEvent*)));
-  connect(myPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)), myOperationMgr,
-          SLOT(onWidgetActivated(ModuleBase_ModelWidget*)));
-  connect(myOperationMgr, SIGNAL(activateNextWidget(ModuleBase_ModelWidget*)), myPropertyPanel,
-          SLOT(onActivateNextWidget(ModuleBase_ModelWidget*)));
   connect(myOperationMgr, SIGNAL(operationValidated(bool)), myPropertyPanel,
           SLOT(setAcceptEnabled(bool)));
 
@@ -1076,7 +1086,7 @@ void XGUI_Workshop::salomeViewerSelectionChanged()
 }
 
 //**************************************************************
-XGUI_SalomeViewer* XGUI_Workshop::salomeViewer() const
+ModuleBase_IViewer* XGUI_Workshop::salomeViewer() const
 {
   return mySalomeConnector->viewer();
 }
@@ -1295,3 +1305,15 @@ void XGUI_Workshop::setDisplayMode(const QList<ObjectPtr>& theList, int theMode)
   if (theList.size() > 0)
     myDisplayer->updateViewer();
 }
+
+//**************************************************************
+void XGUI_Workshop::closeDocument()
+{
+  myDisplayer->closeLocalContexts();
+  myDisplayer->eraseAll();
+  objectBrowser()->clearContent();
+
+  SessionPtr aMgr = ModelAPI_Session::get();
+  aMgr->moduleDocument()->close();
+  objectBrowser()->clearContent();
+}