Salome HOME
Make automatic/manual rebuild property and connect the "Rebuild" button
authormpv <mikhail.ponikarov@opencascade.com>
Thu, 18 Sep 2014 14:30:01 +0000 (18:30 +0400)
committermpv <mikhail.ponikarov@opencascade.com>
Thu, 18 Sep 2014 14:30:01 +0000 (18:30 +0400)
17 files changed:
src/Config/CMakeLists.txt
src/Config/Config_Prop.cpp [new file with mode: 0644]
src/Config/Config_Prop.h
src/Model/Model_Application.cpp
src/Model/Model_Application.h
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.h
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Session.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h

index c40289ab9d8771a709549f4605837543c214b12c..1be2129eda6bd0aa1a893354a57cdb5394800c6a 100644 (file)
@@ -29,6 +29,7 @@ SET(PROJECT_SOURCES
   Config_PointerMessage.cpp
   Config_Common.cpp
   Config_ValidatorMessage.cpp
+  Config_Prop.cpp
   Config_PropManager.cpp
 )
 
diff --git a/src/Config/Config_Prop.cpp b/src/Config/Config_Prop.cpp
new file mode 100644 (file)
index 0000000..7904021
--- /dev/null
@@ -0,0 +1,18 @@
+// File:        Config_Prop.cpp
+// Created:     18 Sep 2014
+// Author:      Mikhail PONIKAROV
+
+
+#include "Config_Prop.h"
+#include "Events_Loop.h"
+#include "Events_Message.h"
+
+void Config_Prop::setValue(const std::string& theValue)
+{
+  if (theValue != myValue) {
+    myValue = theValue;
+    static const Events_ID aChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged");
+    Events_Loop::loop()->send(boost::shared_ptr<Events_Message>(
+      new Events_Message(aChangedEvent, this)));
+  }
+}
index f74137c3c7ab125e0cb7ed84eaa024ae9442e563..f4ea0138b802d6173fbd213ae8998b83aa8c4036 100644 (file)
@@ -88,10 +88,8 @@ class Config_Prop
   {
     return myValue;
   }
-  void setValue(const std::string& theValue)
-  {
-    myValue = theValue;
-  }
+
+  CONFIG_EXPORT void setValue(const std::string& theValue);
 
   bool operator==(const Config_Prop* theProp) const
   {
index 797d00e19a6f3ae380a4c380a89da407529384c5..23ecf05ae7f2109317f435566ad88d2b17a63c2a 100644 (file)
@@ -61,6 +61,12 @@ void Model_Application::setLoadByDemand(std::string theID)
   myLoadedByDemand.insert(theID);
 }
 
+//=======================================================================
+bool Model_Application::isLoadByDemand(std::string theID)
+{
+  return myLoadedByDemand.find(theID) != myLoadedByDemand.end();
+}
+
 //=======================================================================
 Model_Application::Model_Application()
 {
index 09a1694c3871b9d8818cee69fd33f5bd0319d0d6..ae68024eec9443ce54dd8f0d12ccf87887f4752e 100644 (file)
@@ -41,6 +41,8 @@ class Model_Application : public TDocStd_Application
   void setLoadPath(std::string thePath);
   //! Defines that specified document must be loaded by demand
   void setLoadByDemand(std::string theID);
+  //! Returns true if specified document must be loaded by demand
+  bool isLoadByDemand(std::string theID);
 
  public:
   // Redefined OCAF methods
index 2530dd5671b15cf28790b67d5daf82d9da0ecf3f..26f537d689aa677e3e9bc36bbcd0bd1b2a79d4ee 100644 (file)
@@ -20,6 +20,7 @@
 #include <Events_Error.h>
 
 #include <TDataStd_Name.hxx>
+#include <TDataStd_UAttribute.hxx>
 
 #include <string>
 
@@ -283,3 +284,18 @@ void Model_Data::erase()
   if (!myLab.IsNull())
     myLab.ForgetAllAttributes();
 }
+
+Standard_GUID kMustBeUpdatedGUID("baede74c-31a6-4416-9c4d-e48ce65f2005");
+
+void Model_Data::mustBeUpdated(const bool theFlag)
+{
+  if (theFlag)
+    TDataStd_UAttribute::Set(myLab, kMustBeUpdatedGUID);
+  else
+    myLab.ForgetAttribute(kMustBeUpdatedGUID);
+}
+
+bool Model_Data::mustBeUpdated()
+{
+  return myLab.IsAttribute(kMustBeUpdatedGUID) == Standard_True;
+}
index 94490d4aa6e3542842df307cb3b33d05de60a123..136e4504ffa310ce30d8179a2c45237c00358f52 100644 (file)
@@ -129,6 +129,13 @@ class Model_Data : public ModelAPI_Data
   }
 
   MODEL_EXPORT virtual void erase();
+
+  /// Makes feature must be updated later (on rebuild). Normally the Updater must call it
+  /// in case of not-automatic update to true
+  MODEL_EXPORT virtual void mustBeUpdated(const bool theFlag);
+
+  /// Returns true if feature must be updated (re-executed) on rebuild
+  MODEL_EXPORT virtual bool mustBeUpdated();
 };
 
 #endif
index e67556cc966d41a3d46a3cfd19b92056bdb322d3..443d00c1036626f95e0fb2cf1437ac6b8ff84bab 100644 (file)
@@ -172,6 +172,9 @@ class Model_Document : public ModelAPI_Document
   //! Removes information that there is a reference to this object
   void objectIsNotReferenced(const ObjectPtr& theObject);
 
+  //! Returns all sub documents
+  const std::set<std::string>& subDocuments() const {return mySubs;}
+
   friend class Model_Application;
   friend class Model_Session;
   friend class Model_AttributeReference;
index a6d12d8fbc8749b39e3e89b2363887ca0d669349..d6503ee7622f8d372afcb0281e9ab2710a55eaa8 100644 (file)
@@ -147,6 +147,27 @@ void Model_Session::setActiveDocument(boost::shared_ptr<ModelAPI_Document> theDo
   }
 }
 
+std::list<boost::shared_ptr<ModelAPI_Document> > Model_Session::allOpenedDocuments()
+{
+  list<boost::shared_ptr<ModelAPI_Document> > aResult;
+  aResult.push_back(moduleDocument());
+  // add subs recursively
+  list<boost::shared_ptr<ModelAPI_Document> >::iterator aDoc = aResult.begin();
+  for(; aDoc != aResult.end(); aDoc++) {
+    DocumentPtr anAPIDoc = *aDoc;
+    boost::shared_ptr<Model_Document> aDoc = boost::dynamic_pointer_cast<Model_Document>(anAPIDoc);
+    if (aDoc) {
+      std::set<std::string>::const_iterator aSubIter = aDoc->subDocuments().cbegin();
+      for(; aSubIter != aDoc->subDocuments().cend(); aSubIter++) {
+        if (!Model_Application::getApplication()->isLoadByDemand(*aSubIter)) {
+          aResult.push_back(Model_Application::getApplication()->getDocument(*aSubIter));
+        }
+      }
+    }
+  }
+  return aResult;
+}
+
 boost::shared_ptr<ModelAPI_Document> Model_Session::copy(
     boost::shared_ptr<ModelAPI_Document> theSource, std::string theID)
 {
index dca8f220be8ce09e73458f41e904029ae31f47b1..e691cea306f281d799c829a38cb0f3e35f9de2c4 100644 (file)
@@ -75,6 +75,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   /// Defines the current document that used for current work in the application
   MODEL_EXPORT virtual void setActiveDocument(boost::shared_ptr<ModelAPI_Document> theDoc);
 
+  /// Returns all the opened documents of the session (without postponed)
+  MODEL_EXPORT virtual std::list<boost::shared_ptr<ModelAPI_Document> > allOpenedDocuments();
+
   /// Registers the plugin that creates features.
   /// It is obligatory for each plugin to call this function on loading to be found by 
   /// the plugin manager on call of the feature)
index 848f38b80e2d008f29d8e3563159665726dd51f3..70d97733047d062ec3e411032b61fae96c7fba0a 100644 (file)
 #include <Events_Loop.h>
 #include <Events_LongOp.h>
 #include <Events_Error.h>
+#include <Config_PropManager.h>
 
 using namespace std;
 
 Model_Update MY_INSTANCE;  /// the only one instance initialized on load of the library
 
-Model_Update::Model_Update()
+Model_Update::Model_Update() : isCreated(false)
 {
+  static const Events_ID kChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged");
+  Events_Loop::loop()->registerListener(this, kChangedEvent);
+  static const Events_ID kRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
+  Events_Loop::loop()->registerListener(this, kRebuildEvent);
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  Config_PropManager::registerProp("Model update", "automatic_rebuild", "Rebuild automatically",
+                                   Config_Prop::Bool, "false");
+  isAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
 }
 
 void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMessage)
 {
+  static const Events_ID kChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged");
+  static const Events_ID kRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
+  bool isAutomaticChanged = false;
+  if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed
+    isAutomatic = 
+      Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
+  } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command
+    if (isAutomatic == false) {
+      isAutomaticChanged = true;
+      isAutomatic = true;
+    }
+  }
+
   if (isExecuted)
     return;  // nothing to do: it is executed now
+  // execute just created features anyway
+  isCreated = theMessage->eventID() == Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+
   //Events_LongOp::start(this);
   isExecuted = true;
+  list<boost::shared_ptr<ModelAPI_Document> > aDocs;
   boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
       boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-  myInitial = aMsg->objects();
+  if (aMsg) myInitial = aMsg->objects();
+  else {
+    myInitial.clear();
+    // on change flag all documents must be updated
+    if (isAutomatic) {
+      aDocs = ModelAPI_Session::get()->allOpenedDocuments();
+    }
+  }
   // collect all documents involved into the update
-  set<boost::shared_ptr<ModelAPI_Document> > aDocs;
   set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter = myInitial.begin();
   for (; aFIter != myInitial.end(); aFIter++) {
-    aDocs.insert((*aFIter)->document());
+    aDocs.push_back((*aFIter)->document());
   }
   // iterate all features of features-documents to update them (including hidden)
-  set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
+  list<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
   for (; aDIter != aDocs.end(); aDIter++) {
     int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
     for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
@@ -58,6 +89,8 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   Events_Loop::loop()->flush(EVENT_DISP);
   //Events_LongOp::end(this);
+  if (isAutomaticChanged) isAutomatic = false;
+  isCreated = false;
   isExecuted = false;
 }
 
@@ -69,6 +102,7 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
   // check all features this feature depended on (recursive call of updateFeature)
   bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
   if (theFeature) {  // only real feature contains references to other objects
+    if (theFeature->data()->mustBeUpdated()) aMustbeUpdated = true;
     // references
     list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = theFeature->data()->attributes(
         ModelAPI_AttributeReference::type());
@@ -119,12 +153,19 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
           !theFeature->isPersistentResult()) {
         ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
         if (aFactory->validate(theFeature)) {
-          try {
-            theFeature->execute();
-          } catch(...) {
-            Events_Error::send(
-              "Feature " + theFeature->getKind() + " has failed during the execution");
-            theFeature->eraseResults();
+          if (isAutomatic || (isCreated && myInitial.find(theFeature) != myInitial.end()) ||
+            !theFeature->isPersistentResult() /* execute quick, not persistent results */) {
+            try {
+              theFeature->execute();
+              theFeature->data()->mustBeUpdated(false);
+            } catch(...) {
+              Events_Error::send(
+                "Feature " + theFeature->getKind() + " has failed during the execution");
+              theFeature->eraseResults();
+            }
+          } else {
+            theFeature->data()->mustBeUpdated(true);
+            aMustbeUpdated = false;
           }
         } else {
           theFeature->eraseResults();
index 5cfa0252743e2369721fb599a02050bb1f7f7a52..ff3e67660b3b4875ad31bb3c8a1def6fe30fa858 100644 (file)
@@ -20,12 +20,17 @@ class ModelAPI_Feature;
  */
 class Model_Update : public Events_Listener
 {
-  ///< initial set of updated features that must be processed
+  /// initial set of updated features that must be processed
   std::set<boost::shared_ptr<ModelAPI_Object> > myInitial;
-  ///< already updated and processed features and modificated feature flag
+  /// already updated and processed features and modificated feature flag
   std::map<boost::shared_ptr<ModelAPI_Object>, bool> myUpdated;
-  ///< to know that all next updates are caused by this execution
+  /// to know that all next updates are caused by this execution
   bool isExecuted;
+  /// to know execute or not automatically all update
+  bool isAutomatic;
+  /// execute just created features for sure
+  bool isCreated;
+
  public:
   /// Is called only once, on startup of the application
   Model_Update();
index 36838a6efc05f471da4ea4549886bd04cb719ee0..e82a4c44ab1a5f438e4814ee51595f27e789078f 100644 (file)
@@ -91,6 +91,13 @@ class MODELAPI_EXPORT ModelAPI_Data
   {
   }
 
+  /// Makes feature must be updated later (on rebuild). Normally the Updater must call it
+  /// in case of not-automatic update to true
+  virtual void mustBeUpdated(const bool theFlag) = 0;
+
+  /// Returns true if feature must be updated (re-executed) on rebuild
+  virtual bool mustBeUpdated() = 0;
+
  protected:
   /// Objects are created for features automatically
   ModelAPI_Data()
index cfd0eadf0f33c88937bf9f14fff3ff7da474ed7f..7f224da3e37622a4692823248e35945d27308e81 100644 (file)
@@ -55,7 +55,7 @@ public:
   //! \param theIndex zero-based index of feature in the group
   //! \param theHidden if it is true, it counts also the features that are not in tree
   virtual boost::shared_ptr<ModelAPI_Object>
-  object(const std::string& theGroupID, const int theIndex, const bool theHidden = false) = 0;
+    object(const std::string& theGroupID, const int theIndex, const bool theHidden = false) = 0;
 
   //! Returns the number of objects in the group of objects
   //! If theHidden is true, it counts also the features that are not in tree
index 54e807693d9ac7032af15e0f6e1aad3f7828a754..b5e4d5d3bc7a192c73553e8940bb1c7b13e78f4e 100644 (file)
@@ -77,6 +77,9 @@ class MODELAPI_EXPORT ModelAPI_Session
   /// Defines the current document that used for current work in the application
   virtual void setActiveDocument(boost::shared_ptr<ModelAPI_Document> theDoc) = 0;
 
+  /// Returns all the opened documents of the session (without postponed)
+  virtual std::list<boost::shared_ptr<ModelAPI_Document> > allOpenedDocuments() = 0;
+
   /// Copies the document to the new one with the given id
   virtual boost::shared_ptr<ModelAPI_Document> copy(boost::shared_ptr<ModelAPI_Document> theSource,
                                                     std::string theID) = 0;
index 0f3fa139cae557e8daeb4cbf4a0a2f58064fbaa2..5ed671cc7018739cd9e70394bd561e7052251773 100644 (file)
@@ -196,6 +196,7 @@ void XGUI_Workshop::initMenu()
 
   aCommand = aGroup->addFeature("REBUILD_CMD", tr("Rebuild"), tr("Rebuild data objects"),
                                 QIcon(":pictures/rebuild.png"));
+  aCommand->connectTo(this, SLOT(onRebuild()));
 
   aCommand = aGroup->addFeature("SAVEAS_CMD", tr("Save as..."), tr("Save the document into a file"),
                                 QIcon(":pictures/save.png"));
@@ -750,6 +751,14 @@ void XGUI_Workshop::onRedo()
   updateCommandStatus();
 }
 
+//******************************************************
+void XGUI_Workshop::onRebuild()
+{
+  static const Events_ID aRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
+  Events_Loop::loop()->send(boost::shared_ptr<Events_Message>(
+    new Events_Message(aRebuildEvent, this)));
+}
+
 //******************************************************
 void XGUI_Workshop::onPreferences()
 {
index c2ca4a75c7ec2b240a6c1dfb28bd8cb4109f9a78..dbb6cb60ff6015e8d78449526378978014fb9a58 100644 (file)
@@ -198,6 +198,7 @@ signals:
   void onExit();
   void onUndo();
   void onRedo();
+  void onRebuild();
   void onPreferences();
 
   void showPropertyPanel();