Salome HOME
#1821 Axis by two plains: problem in selection update
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetSelector.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModuleBase_WidgetSelector.cpp
4 // Created:     19 June 2015
5 // Author:      Natalia ERMOLAEVA
6
7 #include <ModuleBase_WidgetSelector.h>
8
9 #include <ModuleBase_ISelection.h>
10 #include <ModuleBase_IWorkshop.h>
11 #include <ModuleBase_Tools.h>
12 #include <ModuleBase_Operation.h>
13 #include <ModuleBase_OperationDescription.h>
14 #include <ModuleBase_WidgetFactory.h>
15 #include <ModuleBase_IModule.h>
16 #include <ModuleBase_ResultPrs.h>
17 #include <ModuleBase_ViewerPrs.h>
18 #include <ModuleBase_Events.h>
19
20 #include <ModelAPI_ResultConstruction.h>
21 #include <ModelAPI_Events.h>
22 #include <ModelAPI_AttributeSelection.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24
25 #include <TopoDS_Iterator.hxx>
26
27 ModuleBase_WidgetSelector::ModuleBase_WidgetSelector(QWidget* theParent,
28                                                      ModuleBase_IWorkshop* theWorkshop,
29                                                      const Config_WidgetAPI* theData)
30 : ModuleBase_WidgetValidated(theParent, theWorkshop, theData)
31 {
32 }
33
34 //********************************************************************
35 ModuleBase_WidgetSelector::~ModuleBase_WidgetSelector()
36 {
37 }
38
39 //********************************************************************
40 void ModuleBase_WidgetSelector::getGeomSelection(const ModuleBase_ViewerPrsPtr& thePrs,
41                                                       ObjectPtr& theObject,
42                                                       GeomShapePtr& theShape)
43 {
44   ModuleBase_ISelection* aSelection = myWorkshop->selection();
45   theObject = aSelection->getResult(thePrs);
46   theShape = aSelection->getShape(thePrs);
47 }
48
49 //********************************************************************
50 void ModuleBase_WidgetSelector::onSelectionChanged()
51 {
52   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
53   // equal vertices should not be used here
54   ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected);
55
56   bool isDone = setSelection(aSelected, true/*false*/);
57   updateOnSelectionChanged(isDone);
58 }
59
60 //********************************************************************
61 void ModuleBase_WidgetSelector::updateOnSelectionChanged(const bool theDone)
62 {
63   // "false" flag should be used here, it connects to the #26658 OCC bug, when the user click in 
64   // the same place repeatedly without mouse moved. In the case validation by filters is not
65   // perfromed, so an invalid object is selected. E.g. distance constraint, selection of a point.
66   // the 3rd click in the same point allow using this point.
67   emit valuesChanged();
68   // the updateObject method should be called to flush the updated sigal. The workshop listens it,
69   // calls validators for the feature and, as a result, updates the Apply button state.
70   updateObject(myFeature);
71
72   // we need to forget about previous validation result as the current selection can influence on it
73   clearValidatedCash();
74
75   if (theDone)
76     updateFocus();
77 }
78
79 //********************************************************************
80 QIntList ModuleBase_WidgetSelector::getShapeTypes() const
81 {
82   QIntList aShapeTypes = shapeTypes();
83   if (/*aShapeTypes.contains(TopAbs_SOLID) ||*/ // this type should be mentioned in XML, poor selection otherwise
84       aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result/*TopAbs_SHAPE*/)) {
85     // it should be selectable for both, "solids" and "objects" types
86     aShapeTypes.append(TopAbs_COMPSOLID);
87   }
88   return aShapeTypes;
89 }
90
91 //********************************************************************
92 QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetSelector::getAttributeSelection() const
93 {
94   return QList<ModuleBase_ViewerPrsPtr>();
95 }
96
97 //********************************************************************
98 bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape,
99                                                const ResultPtr& theResult) const
100 {
101   bool aValid = false;
102
103   GeomShapePtr aShape = theShape;
104
105   QIntList aShapeTypes = getShapeTypes();
106   if (aShapeTypes.empty()) {
107     aValid = true;
108     return aValid;
109   }
110   // when the SHAPE type is provided by XML as Object, the whole result shape should be selected.
111   if (!aShape.get() && aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result)) {
112     aValid = true;
113     return aValid;
114   }
115
116   if (!aShape.get() && theResult.get()) {
117     if (theResult.get())
118       aShape = theResult->shape();
119   }
120   TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
121   if (aShape.get()) {
122     // Check that the selection corresponds to selection type
123     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
124     aShapeType = aTopoShape.ShapeType();
125     // for compounds check sub-shapes: it may be compound of needed type:
126     // Booleans may produce compounds of Solids
127     if (aShapeType == TopAbs_COMPOUND) {
128       aShapeType = ModuleBase_Tools::getCompoundSubType(aTopoShape);
129     }
130   }
131
132   QIntList::const_iterator anIt = aShapeTypes.begin(), aLast = aShapeTypes.end();
133   for (; anIt != aLast && !aValid; anIt++) {
134     TopAbs_ShapeEnum aCurrentShapeType = (TopAbs_ShapeEnum)*anIt;
135     if (aShapeType == aCurrentShapeType)
136       aValid = true;
137     else if (aCurrentShapeType == TopAbs_FACE) {
138       // try to process the construction shape only if there is no a selected shape in the viewer
139       if (!theShape.get() && theResult.get()) {
140         ResultConstructionPtr aCResult =
141                                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theResult);
142         aValid = aCResult.get() && aCResult->facesNum() > 0;
143       }
144     }
145   }
146   return aValid;
147 }
148
149 //********************************************************************
150 bool ModuleBase_WidgetSelector::activateSelectionAndFilters(bool toActivate)
151 {
152   updateSelectionName();
153
154   if (toActivate) {
155     myWorkshop->activateSubShapesSelection(getShapeTypes());
156   } else {
157     myWorkshop->deactivateSubShapesSelection();
158   }
159   return activateFilters(toActivate);
160 }
161
162 //********************************************************************
163 void ModuleBase_WidgetSelector::activateCustom()
164 {
165   connect(myWorkshop, SIGNAL(selectionChanged()), this,
166           SLOT(onSelectionChanged()), Qt::UniqueConnection);
167   
168   activateSelectionAndFilters(true);
169
170   // Restore selection in the viewer by the attribute selection list
171   // it should be postponed to have current widget as active to validate restored selection
172   static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
173   ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
174 }
175
176 //********************************************************************
177 bool ModuleBase_WidgetSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
178 {
179   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
180   ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
181   bool aValid = acceptSubShape(aShape, aResult);
182
183   if (aValid) {
184     // In order to avoid selection of the same object
185     ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
186     FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aResult);
187     aValid = aSelectedFeature != myFeature;
188   }
189   return aValid;
190 }
191
192 //********************************************************************
193 bool ModuleBase_WidgetSelector::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
194 {
195   ObjectPtr anObject;
196   GeomShapePtr aShape;
197   getGeomSelection(thePrs, anObject, aShape);
198
199   // the last flag is to be depending on hasObject is called before. To be corrected later
200   return ModuleBase_Tools::setObject(attribute(), anObject, aShape, myWorkshop, myIsInValidate, true);
201 }
202
203 //********************************************************************
204 void ModuleBase_WidgetSelector::deactivate()
205 {
206   ModuleBase_ModelWidget::deactivate();
207   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
208   activateSelectionAndFilters(false);
209
210   /// clear temporary cash
211   AttributePtr anAttribute = attribute();
212   std::string aType = anAttribute->attributeType();
213   if (anAttribute->attributeType() == ModelAPI_AttributeSelection::typeId()) {
214     AttributeSelectionPtr aSelectAttr =
215                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(anAttribute);
216     aSelectAttr->removeTemporaryValues();
217   }
218   else if (anAttribute->attributeType() == ModelAPI_AttributeSelectionList::typeId()) {
219     AttributeSelectionListPtr aSelectAttr =
220                              std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
221     aSelectAttr->removeTemporaryValues();
222   }
223 }
224
225 //********************************************************************
226 std::string ModuleBase_WidgetSelector::generateName(const AttributePtr& theAttribute,
227                                                     ModuleBase_IWorkshop* theWorkshop)
228 {
229   std::string aName;
230   if (theAttribute.get() != NULL) {
231     ModuleBase_Operation* anOperation = theWorkshop->currentOperation();
232
233     FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
234     if (aFeature.get()) {
235       std::string aXmlCfg, aDescription;
236       theWorkshop->module()->getXMLRepresentation(aFeature->getKind(), aXmlCfg, aDescription);
237
238       ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
239       std::string anAttributeTitle;
240       aFactory.getAttributeTitle(theAttribute->id(), anAttributeTitle);
241
242       std::stringstream aStreamName;
243       aStreamName << theAttribute->owner()->data()->name() << "/"<< anAttributeTitle.c_str();
244       aName = aStreamName.str();
245     }
246   }
247   return aName;
248 }