Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom.git into Dev_1.1.0
[modules/shaper.git] / src / Model / Model_Session.cpp
index 9e87c0560c993e7d08b5084c07523f346786c9b8..e7f21bf88a8470860d5c3bfba731f94b743dc564 100644 (file)
 #include <Model_Application.h>
 #include <Model_Events.h>
 #include <Model_Validator.h>
+#include <ModelAPI_Events.h>
 #include <Events_Loop.h>
 #include <Events_Error.h>
 #include <Config_FeatureMessage.h>
 #include <Config_AttributeMessage.h>
 #include <Config_ValidatorMessage.h>
 #include <Config_ModuleReader.h>
+#include <Config_ValidatorReader.h>
+#include <ModelAPI_ResultPart.h>
 
 #include <TDF_CopyTool.hxx>
 #include <TDF_DataSet.hxx>
@@ -33,7 +36,8 @@ static Model_Session* myImpl = new Model_Session();
 
 bool Model_Session::load(const char* theFileName)
 {
-  return ROOT_DOC->load(theFileName);
+  bool aRes = ROOT_DOC->load(theFileName);
+  return aRes;
 }
 
 bool Model_Session::save(const char* theFileName, std::list<std::string>& theResults)
@@ -47,25 +51,39 @@ void Model_Session::closeAll()
   Model_Application::getApplication()->deleteAllDocuments();
 }
 
-void Model_Session::startOperation()
+void Model_Session::startOperation(const std::string& theId)
 {
   ROOT_DOC->startOperation();
+  ROOT_DOC->operationId(theId);
   static std::shared_ptr<Events_Message> aStartedMsg
     (new Events_Message(Events_Loop::eventByName("StartOperation")));
   Events_Loop::loop()->send(aStartedMsg);
+  // remove all useless documents that has been closed: on start of operation undo/redo is cleared
+  std::list<std::shared_ptr<ModelAPI_Document> > aUsedDocs = allOpenedDocuments();
+  Model_Application::getApplication()->removeUselessDocuments(aUsedDocs);
 }
 
 void Model_Session::finishOperation()
 {
+  setCheckTransactions(false);
   ROOT_DOC->finishOperation();
+  setCheckTransactions(true);
 }
 
 void Model_Session::abortOperation()
 {
+  setCheckTransactions(false);
   ROOT_DOC->abortOperation();
+  setCheckTransactions(true);
+  // here the update mechanism may work after abort, so, supress the warnings about
+  // modifications outside of the transactions
+  bool aWasCheck = myCheckTransactions;
+  myCheckTransactions = false;
   static std::shared_ptr<Events_Message> anAbortMsg
     (new Events_Message(Events_Loop::eventByName("AbortOperation")));
   Events_Loop::loop()->send(anAbortMsg);
+  myCheckTransactions = true;
+  myCheckTransactions = aWasCheck;
 }
 
 bool Model_Session::isOperation()
@@ -85,7 +103,9 @@ bool Model_Session::canUndo()
 
 void Model_Session::undo()
 {
+  setCheckTransactions(false);
   ROOT_DOC->undo();
+  setCheckTransactions(true);
 }
 
 bool Model_Session::canRedo()
@@ -95,13 +115,27 @@ bool Model_Session::canRedo()
 
 void Model_Session::redo()
 {
+  setCheckTransactions(false);
   ROOT_DOC->redo();
+  setCheckTransactions(true);
+}
+
+//! Returns stack of performed operations
+std::list<std::string> Model_Session::undoList()
+{
+  return ROOT_DOC->undoList();
+}
+//! Returns stack of rolled back operations
+std::list<std::string> Model_Session::redoList()
+{
+  return ROOT_DOC->redoList();
 }
 
 FeaturePtr Model_Session::createFeature(string theFeatureID)
 {
-  if (this != myImpl)
+  if (this != myImpl) {
     return myImpl->createFeature(theFeatureID);
+  }
 
   // load all information about plugins, features and attributes
   LoadPluginsInfo();
@@ -117,7 +151,7 @@ FeaturePtr Model_Session::createFeature(string theFeatureID)
     myCurrentPluginName = aPlugin.first;
     if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) {
       // load plugin library if not yet done
-      Config_ModuleReader::loadLibrary(myCurrentPluginName);
+      Config_ModuleReader::loadPlugin(myCurrentPluginName);
     }
     if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) {
       FeaturePtr aCreated = myPluginObjs[myCurrentPluginName]->createFeature(theFeatureID);
@@ -139,8 +173,18 @@ FeaturePtr Model_Session::createFeature(string theFeatureID)
 
 std::shared_ptr<ModelAPI_Document> Model_Session::moduleDocument()
 {
-  return std::shared_ptr<ModelAPI_Document>(
+  bool aFirstCall = !Model_Application::getApplication()->hasDocument("root");
+  if (aFirstCall) {
+    // creation of the root document is always outside of the transaction, so, avoid checking it
+    setCheckTransactions(false);
+  }
+  std::shared_ptr<ModelAPI_Document> aDoc = std::shared_ptr<ModelAPI_Document>(
       Model_Application::getApplication()->getDocument("root"));
+  if (aFirstCall) {
+    // creation of the root document is always outside of the transaction, so, avoid checking it
+    setCheckTransactions(true);
+  }
+  return aDoc;
 }
 
 std::shared_ptr<ModelAPI_Document> Model_Session::document(std::string theDocID)
@@ -166,8 +210,18 @@ void Model_Session::setActiveDocument(
 {
   if (myCurrentDoc != theDoc) {
     myCurrentDoc = theDoc;
-    if (theSendSignal) {
-      static std::shared_ptr<Events_Message> aMsg(new Events_Message(Events_Loop::eventByName("CurrentDocumentChanged")));
+    if (theDoc.get() && theSendSignal) {
+      // syncronize the document: it may be just opened or opened but removed before
+      std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(theDoc);
+      if (aDoc.get()) {
+        bool aWasChecked = myCheckTransactions;
+        setCheckTransactions(false);
+        aDoc->synchronizeFeatures(false, true);
+        if (aWasChecked)
+            setCheckTransactions(true);
+      }
+      static std::shared_ptr<Events_Message> aMsg(
+          new Events_Message(Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED)));
       Events_Loop::loop()->send(aMsg);
     }
   }
@@ -183,8 +237,9 @@ std::list<std::shared_ptr<ModelAPI_Document> > Model_Session::allOpenedDocuments
     DocumentPtr anAPIDoc = *aDoc;
     std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(anAPIDoc);
     if (aDoc) {
-      std::set<std::string>::const_iterator aSubIter = aDoc->subDocuments().cbegin();
-      for(; aSubIter != aDoc->subDocuments().cend(); aSubIter++) {
+      const std::set<std::string> aSubs = aDoc->subDocuments(true);
+      std::set<std::string>::const_iterator aSubIter = aSubs.cbegin();
+      for(; aSubIter != aSubs.cend(); aSubIter++) {
         if (!Model_Application::getApplication()->isLoadByDemand(*aSubIter)) {
           aResult.push_back(Model_Application::getApplication()->getDocument(*aSubIter));
         }
@@ -222,7 +277,8 @@ Model_Session::Model_Session()
   ModelAPI_Session::setSession(std::shared_ptr<ModelAPI_Session>(this));
   // register the configuration reading listener
   Events_Loop* aLoop = Events_Loop::loop();
-  static const Events_ID kFeatureEvent = Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT());
+  static const Events_ID kFeatureEvent = 
+    Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT());
   aLoop->registerListener(this, kFeatureEvent);
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED), 0, true);
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED), 0, true);
@@ -232,7 +288,8 @@ Model_Session::Model_Session()
 
 void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessage)
 {
-  static const Events_ID kFeatureEvent = Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT());
+  static const Events_ID kFeatureEvent = 
+    Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT());
   static const Events_ID kValidatorEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED);
   if (theMessage->eventID() == kFeatureEvent) {
     const std::shared_ptr<Config_FeatureMessage> aMsg = 
@@ -253,7 +310,10 @@ void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessa
         if(aMsgAttr->isConcealment()) {
           validators()->registerConcealment(aMsgAttr->featureId(), aMsgAttr->attributeId());
         }
-        
+        if (!aMsgAttr->caseId().empty()) {
+          validators()->registerCase(aMsgAttr->featureId(), aMsgAttr->attributeId(),
+            aMsgAttr->switchId(), aMsgAttr->caseId());
+        }
       }
     }
     // plugins information was started to load, so, it will be loaded
@@ -272,6 +332,17 @@ void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessa
   } else {  // create/update/delete
     if (myCheckTransactions && !isOperation())
       Events_Error::send("Modification of data structure outside of the transaction");
+    // if part is deleted, make the root as the current document (on undo of Parts creations)
+    static const Events_ID kDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+    if (theMessage->eventID() == kDeletedEvent) {
+      std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleted =
+        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+      if (aDeleted && 
+          aDeleted->groups().find(ModelAPI_ResultPart::group()) != aDeleted->groups().end()) 
+      {
+        setActiveDocument(moduleDocument());
+      }
+    }
   }
 }
 
@@ -281,8 +352,15 @@ void Model_Session::LoadPluginsInfo()
     return;
 
   // Read plugins information from XML files
-  Config_ModuleReader aXMLReader(Config_FeatureMessage::MODEL_EVENT());
-  aXMLReader.readAll();
+  Config_ModuleReader aModuleReader(Config_FeatureMessage::MODEL_EVENT());
+  aModuleReader.readAll();
+  std::set<std::string> aFiles = aModuleReader.modulePluginFiles();
+  std::set<std::string>::iterator it = aFiles.begin();
+  for ( ; it != aFiles.end(); it++ ) {
+    Config_ValidatorReader aValidatorReader (*it);
+    aValidatorReader.readAll();
+  };
+
 }
 
 void Model_Session::registerPlugin(ModelAPI_Plugin* thePlugin)
@@ -291,6 +369,14 @@ void Model_Session::registerPlugin(ModelAPI_Plugin* thePlugin)
   static Events_ID EVENT_LOAD = Events_Loop::loop()->eventByName(EVENT_PLUGIN_LOADED);
   ModelAPI_EventCreator::get()->sendUpdated(ObjectPtr(), EVENT_LOAD);
   Events_Loop::loop()->flush(EVENT_LOAD);
+  // If the plugin has an ability to process GUI events, register it
+  Events_Listener* aListener = dynamic_cast<Events_Listener*>(thePlugin);
+  if (aListener) {
+    Events_Loop* aLoop = Events_Loop::loop();
+    static Events_ID aStateRequestEventId =
+        Events_Loop::loop()->eventByName(EVENT_FEATURE_STATE_REQUEST);
+    aLoop->registerListener(aListener, aStateRequestEventId);
+  }
 }
 
 ModelAPI_ValidatorsFactory* Model_Session::validators()