Salome HOME
#1581 crash when create fillet
[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) ||*/ // this type should be mentioned in XML, poor selection otherwise
82       aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result/*TopAbs_SHAPE*/)) {
83     // it should be selectable for both, "solids" and "objects" types
84     aShapeTypes.append(TopAbs_COMPSOLID);
85   }
86   return aShapeTypes;
87 }
88
89 //********************************************************************
90 QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetSelector::getAttributeSelection() const
91 {
92   return QList<ModuleBase_ViewerPrsPtr>();
93 }
94
95 //********************************************************************
96 bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape,
97                                                const ResultPtr& theResult) const
98 {
99   bool aValid = false;
100
101   GeomShapePtr aShape = theShape;
102
103   QIntList aShapeTypes = getShapeTypes();
104   if (aShapeTypes.empty()) {
105     aValid = true;
106     return aValid;
107   }
108   // when the SHAPE type is provided by XML as Object, the whole result shape should be selected.
109   if (!aShape.get() && aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result)) {
110     aValid = true;
111     return aValid;
112   }
113
114   if (!aShape.get() && theResult.get()) {
115     if (theResult.get())
116       aShape = theResult->shape();
117   }
118   TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
119   if (aShape.get()) {
120     // Check that the selection corresponds to selection type
121     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
122     aShapeType = aTopoShape.ShapeType();
123     // for compounds check sub-shapes: it may be compound of needed type:
124     // Booleans may produce compounds of Solids
125     if (aShapeType == TopAbs_COMPOUND) {
126       aShapeType = ModuleBase_Tools::getCompoundSubType(aTopoShape);
127     }
128   }
129
130   QIntList::const_iterator anIt = aShapeTypes.begin(), aLast = aShapeTypes.end();
131   for (; anIt != aLast && !aValid; anIt++) {
132     TopAbs_ShapeEnum aCurrentShapeType = (TopAbs_ShapeEnum)*anIt;
133     if (aShapeType == aCurrentShapeType)
134       aValid = true;
135     else if (aCurrentShapeType == TopAbs_FACE) {
136       // try to process the construction shape only if there is no a selected shape in the viewer
137       if (!theShape.get() && theResult.get()) {
138         ResultConstructionPtr aCResult =
139                                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theResult);
140         aValid = aCResult.get() && aCResult->facesNum() > 0;
141       }
142     }
143   }
144   return aValid;
145 }
146
147 //********************************************************************
148 bool ModuleBase_WidgetSelector::activateSelectionAndFilters(bool toActivate)
149 {
150   updateSelectionName();
151
152   if (toActivate) {
153     myWorkshop->activateSubShapesSelection(getShapeTypes());
154   } else {
155     myWorkshop->deactivateSubShapesSelection();
156   }
157   return activateFilters(toActivate);
158 }
159
160 //********************************************************************
161 void ModuleBase_WidgetSelector::activateCustom()
162 {
163   connect(myWorkshop, SIGNAL(selectionChanged()), this,
164           SLOT(onSelectionChanged()), Qt::UniqueConnection);
165   
166   activateSelectionAndFilters(true);
167
168   // Restore selection in the viewer by the attribute selection list
169   // it should be postponed to have current widget as active to validate restored selection
170   static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
171   ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
172 }
173
174 //********************************************************************
175 bool ModuleBase_WidgetSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
176 {
177   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
178   ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
179   bool aValid = acceptSubShape(aShape, aResult);
180
181   if (aValid) {
182     // In order to avoid selection of the same object
183     ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
184     FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aResult);
185     aValid = aSelectedFeature != myFeature;
186   }
187   return aValid;
188 }
189
190 //********************************************************************
191 bool ModuleBase_WidgetSelector::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
192 {
193   ObjectPtr anObject;
194   GeomShapePtr aShape;
195   getGeomSelection(thePrs, anObject, aShape);
196
197   // the last flag is to be depending on hasObject is called before. To be corrected later
198   return ModuleBase_Tools::setObject(attribute(), anObject, aShape, myWorkshop, myIsInValidate, 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 }