Salome HOME
Issue #2612 : Re-calculate model after modification of parameters
authormpv <mpv@opencascade.com>
Thu, 6 Sep 2018 08:13:28 +0000 (11:13 +0300)
committermpv <mpv@opencascade.com>
Thu, 6 Sep 2018 08:13:43 +0000 (11:13 +0300)
Support of persistent storage of the flag

src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/ModelAPI/ModelAPI_Session.h

index def62f2e24db7946c42c4c49da1b8eeba7c09f93..7acdecde220b777596bc253df61c14321945cff3 100755 (executable)
@@ -52,6 +52,7 @@
 #include <TDF_ListIteratorOfLabelList.hxx>
 #include <TDF_LabelMap.hxx>
 #include <TDF_DeltaOnAddition.hxx>
+#include <TDataStd_UAttribute.hxx>
 #include <TNaming_Builder.hxx>
 #include <TNaming_SameShapeIterator.hxx>
 #include <TNaming_Iterator.hxx>
@@ -84,7 +85,8 @@ static const int TAG_GENERAL = 1;  // general properties tag
 // general sub-labels
 /// where the reference to the current feature label is located (or no attribute if null feature)
 static const int TAG_CURRENT_FEATURE = 1; ///< reference to the current feature
-static const int TAG_CURRENT_TRANSACTION = 2; ///< integer, index of the transaction
+/// integer, index of the transaction + GUID for auto recomutation blocking
+static const int TAG_CURRENT_TRANSACTION = 2;
 static const int TAG_SELECTION_FEATURE = 3; ///< integer, tag of the selection feature label
 static const int TAG_NODES_STATE = 4; ///< array, tag of the Object Browser nodes states
 ///< naming structures constructions selected from other document
@@ -1903,3 +1905,34 @@ void Model_Document::setExecuteFeatures(const bool theFlag)
     subDoc(*aSubIter)->setExecuteFeatures(theFlag);
   }
 }
+
+void Model_Document::appendTransactionToPrevious()
+{
+  Transaction anAppended =  myTransactions.back();
+  myTransactions.pop_back();
+  if (!myTransactions.empty()) { // if it is empty, just forget the appended
+    myTransactions.back().myOCAFNum += anAppended.myOCAFNum;
+  }
+  // propagate the same action to sub-documents
+  const std::set<int> aSubs = subDocuments();
+  for (std::set<int>::iterator aSubIter = aSubs.begin(); aSubIter != aSubs.end(); aSubIter++) {
+    subDoc(*aSubIter)->appendTransactionToPrevious();
+  }
+}
+
+/// GUID for keeping information about the auto-recomputation state
+static const Standard_GUID kAutoRecomputationID("8493fb74-0674-4912-a100-1cf46c7cfab3");
+
+void Model_Document::setAutoRecomutationState(const bool theState)
+{
+  if (theState)
+    generalLabel().FindChild(TAG_CURRENT_TRANSACTION).ForgetAttribute(kAutoRecomputationID);
+  else
+    TDataStd_UAttribute::Set(
+      generalLabel().FindChild(TAG_CURRENT_TRANSACTION), kAutoRecomputationID);
+}
+
+bool Model_Document::autoRecomutationState() const
+{
+  return !generalLabel().FindChild(TAG_CURRENT_TRANSACTION).IsAttribute(kAutoRecomputationID);
+}
index e40b2e928a1a87143aa2eb78c52bfc13978797d5..0842d3d326b5b53fdf16b85cb584f0c060cb0efa 100644 (file)
@@ -379,6 +379,14 @@ class Model_Document : public ModelAPI_Document
   /// returns true if theThis is later in the features trre and dependencies than theOther
   bool isLaterByDep(FeaturePtr theThis, FeaturePtr theOther);
 
+  /// appends the latest transaction to the previous one (used for AutoUpdate enabling transaction)
+  void appendTransactionToPrevious();
+
+  /// Sets the automatic recomutation flag: true means enabled
+  void setAutoRecomutationState(const bool theState);
+  /// Returns the current automatic recomutation flag: true means enabled
+  bool autoRecomutationState() const;
+
   friend class Model_Application;
   friend class Model_Session;
   friend class Model_Update;
index 07f3e98f042f5e1364caa5e4a76419d874ddbc6a..2a830e788a740f3414a5ad29d9de423470f07db3 100644 (file)
@@ -424,7 +424,6 @@ Model_Session::Model_Session()
   myPluginsInfoLoaded = false;
   myCheckTransactions = true;
   myOperationAttachedToNext = false;
-  myIsAutoUpdateBlocked = false;
   ModelAPI_Session::setSession(std::shared_ptr<ModelAPI_Session>(this));
   // register the configuration reading listener
   Events_Loop* aLoop = Events_Loop::loop();
@@ -579,19 +578,41 @@ int Model_Session::transactionID()
   return ROOT_DOC->transactionID();
 }
 
+bool Model_Session::isAutoUpdateBlocked()
+{
+  Handle(Model_Application) anApp = Model_Application::getApplication();
+  if (!anApp->hasRoot()) // when document is not yet created, do not create it by such simple call
+    return false;
+  return !ROOT_DOC->autoRecomutationState();
+}
+
 void Model_Session::blockAutoUpdate(const bool theBlock)
 {
-  if (myIsAutoUpdateBlocked != theBlock) {
-    myIsAutoUpdateBlocked = theBlock;
+  bool aCurrentState = isAutoUpdateBlocked();
+  if (aCurrentState != theBlock) {
+    // if there is no operation, start it to avoid modifications outside of transaction
+    bool isOperation = this->isOperation();
+    if (!isOperation)
+      startOperation("Auto update");
+    ROOT_DOC->setAutoRecomutationState(!theBlock);
     static Events_Loop* aLoop = Events_Loop::loop();
     if (theBlock) {
       static const Events_ID kAutoOff = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_DISABLE);
       std::shared_ptr<Events_Message> aMsg(new Events_Message(kAutoOff));
       aLoop->send(aMsg);
     } else {
+      // if there is no operation, start it to avoid modifications outside of transaction
+      bool isOperation = this->isOperation();
+      if (!isOperation)
+        startOperation("Auto update enabling");
       static const Events_ID kAutoOn = aLoop->eventByName(EVENT_AUTOMATIC_RECOMPUTATION_ENABLE);
       std::shared_ptr<Events_Message> aMsg(new Events_Message(kAutoOn));
       aLoop->send(aMsg);
     }
+    if (!isOperation) {
+      finishOperation();
+      // append this transaction to the previous one: ne don't need this separated operation in list
+      ROOT_DOC->appendTransactionToPrevious();
+    }
   }
 }
index 11655c8a3a73f4b79ddbdac8179fd4fa10e4ad94..7b7afe2b585f72703359e20e3d4c0d9d3809b129 100644 (file)
@@ -50,7 +50,6 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   /// if true, generates error if document is updated outside of transaction
   bool myCheckTransactions;
   bool myOperationAttachedToNext; ///< the current operation must be committed twice, with nested
-  bool myIsAutoUpdateBlocked; ///< the current state of the auto-update flag in the application
  public:
 
   //! Loads the OCAF document from the file.
@@ -147,9 +146,7 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
 
 
   /// Returns true if auto-update in the application is blocked
-  MODEL_EXPORT virtual bool isAutoUpdateBlocked() const {
-    return myIsAutoUpdateBlocked;
-  }
+  MODEL_EXPORT virtual bool isAutoUpdateBlocked();
 
   /// Set state of the auto-update of features result in the application
   MODEL_EXPORT virtual void blockAutoUpdate(const bool theBlock);
index 91f3b8bbcfce077499a20f76bf456a476cb9a188..546108c956de92a937b143418edecf02064f6d7e 100644 (file)
@@ -130,7 +130,7 @@ class MODELAPI_EXPORT ModelAPI_Session
   virtual int transactionID() = 0;
 
   /// Returns true if auto-update in the application is blocked
-  virtual bool isAutoUpdateBlocked() const = 0;
+  virtual bool isAutoUpdateBlocked() = 0;
 
   /// Set state of the auto-update of features result in the application
   virtual void blockAutoUpdate(const bool theBlock) = 0;