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