Salome HOME
Updater mechanism update
[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 <ModelAPI_Feature.h>
7 #include <ModelAPI_Data.h>
8 #include <ModelAPI_Document.h>
9 #include <ModelAPI_Events.h>
10 #include <ModelAPI_AttributeReference.h>
11 #include <ModelAPI_AttributeRefList.h>
12 #include <ModelAPI_Result.h>
13 #include <Events_Loop.h>
14
15 using namespace std;
16
17 Model_Update MY_INSTANCE; /// the only one instance initialized on load of the library
18
19 Model_Update::Model_Update()
20 {
21   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
22   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
23 }
24
25 void Model_Update::processEvent(const Events_Message* theMessage)
26 {
27   const ModelAPI_ObjectUpdatedMessage* aMsg = 
28     dynamic_cast<const ModelAPI_ObjectUpdatedMessage*>(theMessage);
29   myInitial = aMsg->objects();
30   // collect all documents involved into the update
31   set<boost::shared_ptr<ModelAPI_Document> > aDocs;
32   set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter = myInitial.begin();
33   for(; aFIter != myInitial.end(); aFIter++) {
34     aDocs.insert((*aFIter)->document());
35   }
36   // iterate all features of features-documents to update them (including hidden)
37   set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
38   for(; aDIter != aDocs.end(); aDIter++) {
39     int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
40     for(int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
41       FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>
42         ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
43       if (aFeature)
44         updateFeature(aFeature);
45     }
46   }
47   myUpdated.clear();
48   // flush
49   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
50   Events_Loop::loop()->flush(EVENT_DISP);
51 }
52
53 bool Model_Update::updateFeature(FeaturePtr theFeature)
54 {
55   // check it is already processed
56   if (myUpdated.find(theFeature) != myUpdated.end())
57     return myUpdated[theFeature];
58   // check all features this feature depended on (recursive call of updateFeature)
59   bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
60   if (theFeature) { // only real feature contains references to other objects
61     // references
62     list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = 
63       theFeature->data()->attributes(ModelAPI_AttributeReference::type());
64     list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
65     for(; aRefsIter != aRefs.end(); aRefsIter++) {
66       boost::shared_ptr<ModelAPI_Object> aSub =
67         boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRefsIter)->value();
68       if (updateObject(aSub)) {
69         aMustbeUpdated = true;
70       }
71     }
72     // lists of references
73     aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
74     for(aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
75       list<ObjectPtr> aListRef = 
76         boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)->list();
77       list<ObjectPtr>::iterator aListIter = aListRef.begin();
78       for(; aListIter != aListRef.end(); aListIter++) {
79         boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
80         if (updateObject(aSub)) {
81           aMustbeUpdated = true;
82         }
83       }
84     }
85     // execute feature if it must be updated
86     if (aMustbeUpdated) {
87       theFeature->execute();
88       // redisplay all results
89       static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
90       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
91       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
92       for(; aRIter != aResults.cend(); aRIter++) {
93         boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
94         myUpdated[aRes] = true;
95         ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
96       }
97     } else { // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
98       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
99       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
100       for(; aRIter != aResults.cend(); aRIter++) {
101         if (myInitial.find(*aRIter) != myInitial.end()) {
102           aMustbeUpdated = true;
103           break;
104         }
105       }
106     }
107   }
108   myUpdated[theFeature] = aMustbeUpdated;
109   return aMustbeUpdated;
110 }
111
112 bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
113 {
114   if (!theObject) 
115     return false;
116   FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
117   if (aFeature) { // for feature just call update Feature
118     return updateFeature(aFeature);
119   }
120   // check general object, possible just a result
121   if (myUpdated.find(theObject) != myUpdated.end())
122     return myUpdated[theObject]; // already processed
123   // check the feature of this object must be executed
124   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
125   if (aResult) {
126     FeaturePtr aResFeature = aResult->document()->feature(aResult);
127     if (aResFeature) {
128       return updateFeature(aResFeature);
129     }
130   }
131   if (myInitial.find(theObject) != myInitial.end())
132     return true;
133   return false; // nothing is known
134 }