]> SALOME platform Git repositories - modules/shaper.git/blob - src/Model/Model_Update.cpp
Salome HOME
9df4d10f0769a687844a6b8c8c1bd8a9fe58b63b
[modules/shaper.git] / src / Model / Model_Update.cpp
1 // File:        Model_Update.cxx
2 // Created:     25 Jun 2014
3 // Author:      Mikhail PONIKAROV
4
5 #include <Model_Update.h>
6 #include <Model_Document.h>
7 #include <ModelAPI_Feature.h>
8 #include <ModelAPI_Data.h>
9 #include <ModelAPI_Document.h>
10 #include <ModelAPI_Events.h>
11 #include <ModelAPI_AttributeReference.h>
12 #include <ModelAPI_AttributeRefList.h>
13 #include <ModelAPI_Result.h>
14 #include <ModelAPI_Validator.h>
15 #include <Events_Loop.h>
16 #include <Events_LongOp.h>
17 #include <Events_Error.h>
18
19 using namespace std;
20
21 Model_Update MY_INSTANCE;  /// the only one instance initialized on load of the library
22
23 Model_Update::Model_Update()
24 {
25   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
26   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
27 }
28
29 void Model_Update::processEvent(const Events_Message* theMessage)
30 {
31   if (isExecuted)
32     return;  // nothing to do: it is executed now
33   //Events_LongOp::start(this);
34   isExecuted = true;
35   const ModelAPI_ObjectUpdatedMessage* aMsg =
36       dynamic_cast<const ModelAPI_ObjectUpdatedMessage*>(theMessage);
37   myInitial = aMsg->objects();
38   // collect all documents involved into the update
39   set<boost::shared_ptr<ModelAPI_Document> > aDocs;
40   set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter = myInitial.begin();
41   for (; aFIter != myInitial.end(); aFIter++) {
42     aDocs.insert((*aFIter)->document());
43   }
44   // iterate all features of features-documents to update them (including hidden)
45   set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
46   for (; aDIter != aDocs.end(); aDIter++) {
47     int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
48     for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
49       FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(
50           (*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
51       if (aFeature)
52         updateFeature(aFeature);
53     }
54   }
55   myUpdated.clear();
56   // flush
57   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
58   Events_Loop::loop()->flush(EVENT_DISP);
59   //Events_LongOp::end(this);
60   isExecuted = false;
61 }
62
63 bool Model_Update::updateFeature(FeaturePtr theFeature)
64 {
65   // check it is already processed
66   if (myUpdated.find(theFeature) != myUpdated.end())
67     return myUpdated[theFeature];
68   // check all features this feature depended on (recursive call of updateFeature)
69   bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
70   if (theFeature) {  // only real feature contains references to other objects
71     // references
72     list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = theFeature->data()->attributes(
73         ModelAPI_AttributeReference::type());
74     list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
75     for (; aRefsIter != aRefs.end(); aRefsIter++) {
76       boost::shared_ptr<ModelAPI_Object> aSub = boost::dynamic_pointer_cast<
77           ModelAPI_AttributeReference>(*aRefsIter)->value();
78       if (updateObject(aSub)) {
79         aMustbeUpdated = true;
80       }
81     }
82     // lists of references
83     aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
84     for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
85       list<ObjectPtr> aListRef = boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)
86           ->list();
87       list<ObjectPtr>::iterator aListIter = aListRef.begin();
88       for (; aListIter != aListRef.end(); aListIter++) {
89         boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
90         if (updateObject(aSub)) {
91           aMustbeUpdated = true;
92         }
93       }
94     }
95     // execute feature if it must be updated
96     if (aMustbeUpdated) {
97
98       if (boost::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
99           !theFeature->isPersistentResult()) {
100         ModelAPI_ValidatorsFactory* aFactory = ModelAPI_PluginManager::get()->validators();
101         if (aFactory->validate(theFeature)) {
102           try {
103             theFeature->execute();
104           } catch(...) {
105             Events_Error::send(
106               "Feature " + theFeature->getKind() + " has failed during the execution");
107             theFeature->eraseResults();
108           }
109         } else {
110           theFeature->eraseResults();
111         }
112       }
113       // redisplay all results
114       static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
115       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
116       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
117       for (; aRIter != aResults.cend(); aRIter++) {
118         boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
119         myUpdated[aRes] = true;
120         ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
121       }
122       // to redisplay "presentable" feature (for ex. distance constraint)
123       ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
124     } else {  // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
125       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
126       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
127       for (; aRIter != aResults.cend(); aRIter++) {
128         if (myInitial.find(*aRIter) != myInitial.end()) {
129           aMustbeUpdated = true;
130           break;
131         }
132       }
133     }
134   }
135   myUpdated[theFeature] = aMustbeUpdated;
136   return aMustbeUpdated;
137 }
138
139 bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
140 {
141   if (!theObject)
142     return false;
143   FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
144   if (aFeature) {  // for feature just call update Feature
145     return updateFeature(aFeature);
146   }
147   // check general object, possible just a result
148   if (myUpdated.find(theObject) != myUpdated.end())
149     return myUpdated[theObject];  // already processed
150   // check the feature of this object must be executed
151   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
152   if (aResult) {
153     FeaturePtr aResFeature = aResult->document()->feature(aResult);
154     if (aResFeature) {
155       return updateFeature(aResFeature);
156     }
157   }
158   if (myInitial.find(theObject) != myInitial.end())
159     return true;
160   return false;  // nothing is known
161 }