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