1 // File: Model_Update.cxx
2 // Created: 25 Jun 2014
3 // Author: Mikhail PONIKAROV
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_AttributeRefAttr.h>
14 #include <ModelAPI_Result.h>
15 #include <ModelAPI_Validator.h>
16 #include <Events_Loop.h>
17 #include <Events_LongOp.h>
18 #include <Events_Error.h>
22 Model_Update MY_INSTANCE; /// the only one instance initialized on load of the library
24 Model_Update::Model_Update()
26 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
27 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
30 void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMessage)
33 return; // nothing to do: it is executed now
34 //Events_LongOp::start(this);
36 boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
37 boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
38 myInitial = aMsg->objects();
39 // collect all documents involved into the update
40 set<boost::shared_ptr<ModelAPI_Document> > aDocs;
41 set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter = myInitial.begin();
42 for (; aFIter != myInitial.end(); aFIter++) {
43 aDocs.insert((*aFIter)->document());
45 // iterate all features of features-documents to update them (including hidden)
46 set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
47 for (; aDIter != aDocs.end(); aDIter++) {
48 int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
49 for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
50 FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(
51 (*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
53 updateFeature(aFeature);
58 static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
59 Events_Loop::loop()->flush(EVENT_DISP);
60 //Events_LongOp::end(this);
64 bool Model_Update::updateFeature(FeaturePtr theFeature)
66 // check it is already processed
67 if (myUpdated.find(theFeature) != myUpdated.end())
68 return myUpdated[theFeature];
69 // check all features this feature depended on (recursive call of updateFeature)
70 bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
71 if (theFeature) { // only real feature contains references to other objects
73 list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = theFeature->data()->attributes(
74 ModelAPI_AttributeReference::type());
75 list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
76 for (; aRefsIter != aRefs.end(); aRefsIter++) {
77 boost::shared_ptr<ModelAPI_Object> aSub = boost::dynamic_pointer_cast<
78 ModelAPI_AttributeReference>(*aRefsIter)->value();
79 if (updateObject(aSub)) {
80 aMustbeUpdated = true;
83 // reference to attribute or object
84 list<boost::shared_ptr<ModelAPI_Attribute> > aRefAttrs = theFeature->data()->attributes(
85 ModelAPI_AttributeRefAttr::type());
86 for (aRefsIter = aRefAttrs.begin(); aRefsIter != aRefAttrs.end(); aRefsIter++) {
87 boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
88 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefsIter);
90 if (aRef->isObject()) {
91 boost::shared_ptr<ModelAPI_Object> aSub = aRef->object();
92 if (updateObject(aSub)) {
93 aMustbeUpdated = true;
95 } else if (aRef->attr()) { // reference to the attribute
96 boost::shared_ptr<ModelAPI_Object> aSub = aRef->attr()->owner();
97 if (updateObject(aSub)) {
98 aMustbeUpdated = true;
102 // lists of references
103 aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
104 for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
105 list<ObjectPtr> aListRef = boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)
107 list<ObjectPtr>::iterator aListIter = aListRef.begin();
108 for (; aListIter != aListRef.end(); aListIter++) {
109 boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
110 if (updateObject(aSub)) {
111 aMustbeUpdated = true;
115 // execute feature if it must be updated
116 if (aMustbeUpdated) {
118 if (boost::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
119 !theFeature->isPersistentResult()) {
120 ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
121 if (aFactory->validate(theFeature)) {
123 theFeature->execute();
126 "Feature " + theFeature->getKind() + " has failed during the execution");
127 theFeature->eraseResults();
130 theFeature->eraseResults();
133 // redisplay all results
134 static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
135 const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
136 std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
137 for (; aRIter != aResults.cend(); aRIter++) {
138 boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
139 myUpdated[aRes] = true;
140 ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
142 // to redisplay "presentable" feature (for ex. distance constraint)
143 ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
144 } else { // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
145 const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
146 std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
147 for (; aRIter != aResults.cend(); aRIter++) {
148 if (myInitial.find(*aRIter) != myInitial.end()) {
149 aMustbeUpdated = true;
155 myUpdated[theFeature] = aMustbeUpdated;
156 return aMustbeUpdated;
159 bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
163 FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
164 if (aFeature) { // for feature just call update Feature
165 return updateFeature(aFeature);
167 // check general object, possible just a result
168 if (myUpdated.find(theObject) != myUpdated.end())
169 return myUpdated[theObject]; // already processed
170 // check the feature of this object must be executed
171 ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
173 FeaturePtr aResFeature = aResult->document()->feature(aResult);
175 return updateFeature(aResFeature);
178 if (myInitial.find(theObject) != myInitial.end())
180 return false; // nothing is known