]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_WidgetValidated.cpp
Salome HOME
Feature selector widget for recover feature.
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetValidated.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D\r
2 \r
3 #include <ModuleBase_WidgetValidated.h>\r
4 #include <ModuleBase_FilterFactory.h>\r
5 #include <ModuleBase_IViewer.h>\r
6 #include <ModuleBase_ISelection.h>\r
7 #include <ModuleBase_WidgetSelectorStore.h>\r
8 #include <ModuleBase_ViewerPrs.h>\r
9 \r
10 #include <Events_InfoMessage.h>\r
11 \r
12 #include <ModelAPI_Session.h>\r
13 #include <ModelAPI_Validator.h>\r
14 #include <ModelAPI_AttributeValidator.h>\r
15 #include <ModelAPI_Events.h>\r
16 #include <ModelAPI_ResultCompSolid.h>\r
17 #include <ModelAPI_Tools.h>\r
18 \r
19 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>\r
20 #include <SelectMgr_EntityOwner.hxx>\r
21 #include <StdSelect_BRepOwner.hxx>\r
22 \r
23 #include <Events_Loop.h>\r
24 \r
25 #include <QWidget>\r
26 \r
27 //#define DEBUG_VALID_STATE\r
28 \r
29 ModuleBase_WidgetValidated::ModuleBase_WidgetValidated(QWidget* theParent,\r
30                                                        ModuleBase_IWorkshop* theWorkshop,\r
31                                                        const Config_WidgetAPI* theData)\r
32 : ModuleBase_ModelWidget(theParent, theData),\r
33   myWorkshop(theWorkshop), myIsInValidate(false)\r
34 {\r
35   myAttributeStore = new ModuleBase_WidgetSelectorStore();\r
36 }\r
37 \r
38 ModuleBase_WidgetValidated::~ModuleBase_WidgetValidated()\r
39 {\r
40   delete myAttributeStore;\r
41 }\r
42 \r
43 //********************************************************************\r
44 ObjectPtr ModuleBase_WidgetValidated::findPresentedObject(const AISObjectPtr& theAIS) const\r
45 {\r
46   return myPresentedObject;\r
47 }\r
48 \r
49 //********************************************************************\r
50 void ModuleBase_WidgetValidated::clearValidatedCash()\r
51 {\r
52 #ifdef DEBUG_VALID_STATE\r
53   qDebug("clearValidatedCash");\r
54 #endif\r
55   myValidPrs.Clear();\r
56   myInvalidPrs.Clear();\r
57 }\r
58 \r
59 //********************************************************************\r
60 void ModuleBase_WidgetValidated::storeAttributeValue(const AttributePtr& theAttribute)\r
61 {\r
62   myIsInValidate = true;\r
63   myAttributeStore->storeAttributeValue(theAttribute, myWorkshop);\r
64 }\r
65 \r
66 //********************************************************************\r
67 void ModuleBase_WidgetValidated::restoreAttributeValue(const AttributePtr& theAttribute,\r
68                                                        const bool theValid)\r
69 {\r
70   myIsInValidate = false;\r
71   myAttributeStore->restoreAttributeValue(theAttribute, myWorkshop);\r
72 }\r
73 \r
74 //********************************************************************\r
75 bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr& thePrs)\r
76 {\r
77   bool aValid = true;\r
78   Handle(SelectMgr_EntityOwner) anOwner = thePrs->owner();\r
79 \r
80   // if an owner is null, the selection happens in the Object browser.\r
81   // creates a selection owner on the base of object shape and the object AIS object\r
82   if (anOwner.IsNull() && thePrs->owner().IsNull() && thePrs->object().get()) {\r
83     ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);\r
84     GeomShapePtr aShape = aResult.get() ? aResult->shape() : GeomShapePtr();\r
85     // some results have no shape, e.g. the parameter one. So, they should not be validated\r
86     if (aShape.get()) {\r
87       const TopoDS_Shape aTDShape = aShape->impl<TopoDS_Shape>();\r
88       Handle(AIS_InteractiveObject) anIO = myWorkshop->selection()->getIO(thePrs);\r
89       anOwner = new StdSelect_BRepOwner(aTDShape, anIO);\r
90       myPresentedObject = aResult;\r
91     }\r
92     else\r
93       aValid = false; // only results with a shape can be filtered\r
94   }\r
95   // checks the owner by the AIS context activated filters\r
96   if (!anOwner.IsNull()) {\r
97     // the widget validator filter should be active, but during check by preselection\r
98     // it is not yet activated, so we need to activate/deactivate it manually\r
99     bool isActivated = isFilterActivated();\r
100     if (!isActivated)\r
101       activateFilters(true);\r
102 \r
103     Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();\r
104     if (!aContext.IsNull()) {\r
105       const SelectMgr_ListOfFilter& aFilters = aContext->Filters();\r
106       SelectMgr_ListIteratorOfListOfFilter anIt(aFilters);\r
107       for (; anIt.More() && aValid; anIt.Next()) {\r
108         Handle(SelectMgr_Filter) aFilter = anIt.Value();\r
109         aValid = aFilter->IsOk(anOwner);\r
110       }\r
111     }\r
112     if (!isActivated)\r
113       activateFilters(false);\r
114   }\r
115 \r
116   // removes created owner\r
117   if (!anOwner.IsNull() && anOwner != thePrs->owner()) {\r
118     anOwner.Nullify();\r
119     myPresentedObject = ObjectPtr();\r
120   }\r
121   return aValid;\r
122 }\r
123 \r
124 //********************************************************************\r
125 AttributePtr ModuleBase_WidgetValidated::attribute() const\r
126 {\r
127   return myFeature->attribute(attributeID());\r
128 }\r
129 \r
130 //********************************************************************\r
131 bool ModuleBase_WidgetValidated::isValidSelection(const ModuleBase_ViewerPrsPtr& theValue)\r
132 {\r
133   bool aValid = false;\r
134   if (getValidState(theValue, aValid)) {\r
135     return aValid;\r
136   }\r
137   aValid = isValidSelectionCustom(theValue);\r
138   if (aValid)\r
139     aValid = isValidSelectionForAttribute(theValue, attribute());\r
140 \r
141   storeValidState(theValue, aValid);\r
142   return aValid;\r
143 }\r
144 \r
145 //********************************************************************\r
146 bool ModuleBase_WidgetValidated::isValidSelectionForAttribute(const ModuleBase_ViewerPrsPtr& theValue,\r
147                                                               const AttributePtr& theAttribute)\r
148 {\r
149   bool aValid = false;\r
150 \r
151   // stores the current values of the widget attribute\r
152   bool isFlushesActived, isAttributeSetInitializedBlocked;\r
153 \r
154   blockAttribute(theAttribute, true, isFlushesActived, isAttributeSetInitializedBlocked);\r
155 \r
156   storeAttributeValue(theAttribute);\r
157 \r
158   // saves the owner value to the widget attribute\r
159   aValid = setSelectionCustom(theValue);\r
160   if (aValid)\r
161     // checks the attribute validity\r
162     aValid = isValidAttribute(theAttribute);\r
163 \r
164   // restores the current values of the widget attribute\r
165   restoreAttributeValue(theAttribute, aValid);\r
166 \r
167   blockAttribute(theAttribute, false, isFlushesActived, isAttributeSetInitializedBlocked);\r
168   /// NDS: The following rows are commented for issue #1452 (to be removed after debug)\r
169   /// This is not correct to perform it here because it might cause update selection and\r
170   /// the selection mechanizm will be circled: use the scenario of the bug with preselected point.\r
171   // In particular case the results are deleted and called as redisplayed inside of this\r
172   // highlight-selection, to they must be flushed as soon as possible.\r
173   // Example: selection of group-vertices subshapes with shift pressend on body. Without\r
174   //  these 4 lines below the application crashes because of left presentations on\r
175   //  removed results still in the viewer.\r
176   /*static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);\r
177   static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);\r
178   Events_Loop::loop()->flush(aDeletedEvent);\r
179   Events_Loop::loop()->flush(aRedispEvent);\r
180   */\r
181   return aValid;\r
182 }\r
183 \r
184 //********************************************************************\r
185 bool ModuleBase_WidgetValidated::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)\r
186 {\r
187   return true;\r
188 }\r
189 \r
190 //********************************************************************\r
191 bool ModuleBase_WidgetValidated::isValidAttribute(const AttributePtr& theAttribute) const\r
192 {\r
193   SessionPtr aMgr = ModelAPI_Session::get();\r
194   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();\r
195   std::string aValidatorID;\r
196   Events_InfoMessage anError;\r
197   return aFactory->validate(theAttribute, aValidatorID, anError);\r
198 }\r
199 \r
200 bool ModuleBase_WidgetValidated::isFilterActivated() const\r
201 {\r
202   bool isActivated = false;\r
203 \r
204   Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter();\r
205   ModuleBase_IViewer* aViewer = myWorkshop->viewer();\r
206 \r
207   return aViewer->hasSelectionFilter(aSelFilter);\r
208 }\r
209 \r
210 bool ModuleBase_WidgetValidated::activateFilters(const bool toActivate)\r
211 {\r
212   ModuleBase_IViewer* aViewer = myWorkshop->viewer();\r
213 \r
214   Handle(SelectMgr_Filter) aSelFilter = myWorkshop->validatorFilter();\r
215   bool aHasSelectionFilter = aViewer->hasSelectionFilter(aSelFilter);\r
216 \r
217   if (toActivate)\r
218     aViewer->addSelectionFilter(aSelFilter);\r
219   else {\r
220     aViewer->removeSelectionFilter(aSelFilter);\r
221     clearValidatedCash();\r
222   }\r
223 \r
224   return aHasSelectionFilter;\r
225 }\r
226 \r
227 //********************************************************************\r
228 void ModuleBase_WidgetValidated::blockAttribute(const AttributePtr& theAttribute,\r
229                                                 const bool& theToBlock,\r
230                                                 bool& isFlushesActived,\r
231                                                 bool& isAttributeSetInitializedBlocked)\r
232 {\r
233   Events_Loop* aLoop = Events_Loop::loop();\r
234   DataPtr aData = myFeature->data();\r
235   if (theToBlock) {\r
236     // blocks the flush signals to avoid the temporary objects visualization in the viewer\r
237     // they should not be shown in order to do not lose highlight by erasing them\r
238     isFlushesActived = aLoop->activateFlushes(false);\r
239 \r
240     aData->blockSendAttributeUpdated(true);\r
241     isAttributeSetInitializedBlocked = theAttribute->blockSetInitialized(true);\r
242   }\r
243   else {\r
244     aData->blockSendAttributeUpdated(false, false);\r
245     theAttribute->blockSetInitialized(isAttributeSetInitializedBlocked);\r
246     aLoop->activateFlushes(isFlushesActived);\r
247   }\r
248 }\r
249 \r
250 //********************************************************************\r
251 void ModuleBase_WidgetValidated::storeValidState(const ModuleBase_ViewerPrsPtr& theValue, const bool theValid)\r
252 {\r
253   GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr();\r
254   if (aShape.get()) {\r
255     if (theValid) {\r
256       const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();\r
257       bool aValidPrsContains = myValidPrs.IsBound(aTDShape) &&\r
258                                theValue.get()->isEqual(myValidPrs.Find(aTDShape).get());\r
259       if (!aValidPrsContains) {\r
260   #ifdef LIST_OF_VALID_PRS\r
261         myValidPrs.append(theValue);\r
262   #else\r
263         myValidPrs.Bind(aTDShape, theValue);\r
264   #endif\r
265       // the commented code will be useful when the valid state of the presentation\r
266       // will be changable between activate/deactivate. Currently it does not happen.\r
267       //if (anInvalidPrs)\r
268       //  myInvalidPrs.removeOne(theValue);\r
269       }\r
270     }\r
271     else { // !theValid\r
272       if (aShape.get()) {\r
273         const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();\r
274         bool anIValidPrsContains = myInvalidPrs.IsBound(aTDShape) &&\r
275                                    theValue.get()->isEqual(myInvalidPrs.Find(aTDShape).get());\r
276         if (!anIValidPrsContains) {\r
277     #ifdef LIST_OF_VALID_PRS\r
278           myInvalidPrs.append(theValue);\r
279     #else\r
280           myInvalidPrs.Bind(aTDShape, theValue);\r
281     #endif\r
282         //if (!aValidPrs)\r
283         //  myValidPrs.removeOne(theValue);\r
284         }\r
285       }\r
286     }\r
287   }\r
288   #ifdef DEBUG_VALID_STATE\r
289     qDebug(QString("storeValidState: myValidPrs.size() = %1, myInvalidPrs.size() = %2").arg(myValidPrs.count())\r
290                    .arg(myInvalidPrs.count()).toStdString().c_str());\r
291   #endif\r
292 }\r
293 \r
294 //********************************************************************\r
295 bool ModuleBase_WidgetValidated::getValidState(const ModuleBase_ViewerPrsPtr& theValue, bool& theValid)\r
296 {\r
297   if (!theValue.get())\r
298     return false;\r
299 \r
300 #ifdef LIST_OF_VALID_PRS\r
301   bool aValidPrsContains = myValidPrs.contains(theValue);\r
302   bool anInvalidPrsContains = myInvalidPrs.contains(theValue);\r
303 #else\r
304   GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr();\r
305   if (!aShape.get())\r
306     return false;\r
307 \r
308   const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();\r
309   bool aValidPrsContains = myValidPrs.IsBound(aTDShape) &&\r
310                            theValue.get()->isEqual(myValidPrs.Find(aTDShape).get());\r
311 \r
312   bool anInvalidPrsContains = myInvalidPrs.IsBound(aTDShape) &&\r
313                               theValue.get()->isEqual(myInvalidPrs.Find(aTDShape).get());\r
314   /*\r
315   bool aValidPrsContains = false, anInvalidPrsContains = false;\r
316   GeomShapePtr aShape = theValue.get() ? theValue->shape() : GeomShapePtr();\r
317   if (aShape.get()) {\r
318     aValidPrsContains = myValidPrs.contains(aShape);\r
319     anInvalidPrsContains = myInvalidPrs.contains(aShape);\r
320 \r
321     if (aValidPrsContains)\r
322       aValidPrsContains = theValue == myValidPrs[aShape];\r
323     else\r
324       anInvalidPrsContains = theValue == myInvalidPrs[aShape];*/\r
325 #endif\r
326 \r
327   if (aValidPrsContains)\r
328     theValid = true;\r
329   else if (anInvalidPrsContains)\r
330     theValid = false;\r
331 \r
332   return aValidPrsContains || anInvalidPrsContains;\r
333 }\r
334 \r
335 //********************************************************************\r
336 QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetValidated::getFilteredSelected()\r
337 {\r
338   QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(\r
339                                                        ModuleBase_ISelection::Viewer);\r
340 \r
341   QList<ModuleBase_ViewerPrsPtr> anOBSelected = myWorkshop->selection()->getSelected(\r
342                                                        ModuleBase_ISelection::Browser);\r
343   // filter the OB presentations\r
344   filterPresentations(anOBSelected);\r
345   if (!anOBSelected.isEmpty())\r
346     ModuleBase_ISelection::appendSelected(anOBSelected, aSelected);\r
347 \r
348   filterCompSolids(aSelected);\r
349 \r
350   return aSelected;\r
351 }\r
352 \r
353 //********************************************************************\r
354 void ModuleBase_WidgetValidated::filterPresentations(QList<ModuleBase_ViewerPrsPtr>& theValues)\r
355 {\r
356   QList<ModuleBase_ViewerPrsPtr> aValidatedValues;\r
357 \r
358   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theValues.begin(), aLast = theValues.end();\r
359   bool isDone = false;\r
360   for (; anIt != aLast; anIt++) {\r
361     if (isValidInFilters(*anIt))\r
362       aValidatedValues.append(*anIt);\r
363   }\r
364   if (aValidatedValues.size() != theValues.size()) {\r
365     theValues.clear();\r
366     theValues = aValidatedValues;\r
367   }\r
368 }\r
369 \r
370 //********************************************************************\r
371 void ModuleBase_WidgetValidated::filterCompSolids(QList<ModuleBase_ViewerPrsPtr>& theValues)\r
372 {\r
373   std::set<ResultCompSolidPtr> aCompSolids;\r
374   QList<ModuleBase_ViewerPrsPtr> aValidatedValues;\r
375 \r
376   // Collect compsolids.\r
377   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theValues.begin(), aLast = theValues.end();\r
378   for (; anIt != aLast; anIt++) {\r
379     const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt;\r
380     ObjectPtr anObject = aViewerPrs->object();\r
381     ResultCompSolidPtr aResultCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(anObject);\r
382     if(aResultCompSolid.get()) {\r
383       aCompSolids.insert(aResultCompSolid);\r
384     }\r
385   }\r
386 \r
387   // Filter sub-solids of compsolids.\r
388   anIt = theValues.begin();\r
389   for (; anIt != aLast; anIt++) {\r
390     const ModuleBase_ViewerPrsPtr& aViewerPrs = *anIt;\r
391     ObjectPtr anObject = aViewerPrs->object();\r
392     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);\r
393     ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aResult);\r
394     if(aResCompSolidPtr.get() && (aCompSolids.find(aResCompSolidPtr) != aCompSolids.end())) {\r
395       // Skip sub-solid of compsolid.\r
396       continue;\r
397     } else {\r
398       aValidatedValues.append(*anIt);\r
399     }\r
400   }\r
401 \r
402   if (aValidatedValues.size() != theValues.size()) {\r
403     theValues.clear();\r
404     theValues = aValidatedValues;\r
405   }\r
406 }\r