Salome HOME
Issue #1860: fix end lines with spaces
[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   // this type should be mentioned in XML, poor selection otherwise
84   if (/*aShapeTypes.contains(TopAbs_SOLID) ||*/
85       aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result/*TopAbs_SHAPE*/)) {
86     // it should be selectable for both, "solids" and "objects" types
87     aShapeTypes.append(TopAbs_COMPSOLID);
88   }
89   return aShapeTypes;
90 }
91
92 //********************************************************************
93 QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetSelector::getAttributeSelection() const
94 {
95   return QList<ModuleBase_ViewerPrsPtr>();
96 }
97
98 //********************************************************************
99 bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape,
100                                                const ResultPtr& theResult) const
101 {
102   bool aValid = false;
103
104   GeomShapePtr aShape = theShape;
105
106   QIntList aShapeTypes = getShapeTypes();
107   if (aShapeTypes.empty()) {
108     aValid = true;
109     return aValid;
110   }
111   // when the SHAPE type is provided by XML as Object, the whole result shape should be selected.
112   if (!aShape.get() && aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result)) {
113     aValid = true;
114     return aValid;
115   }
116
117   if (!aShape.get() && theResult.get()) {
118     if (theResult.get())
119       aShape = theResult->shape();
120   }
121   TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
122   if (aShape.get()) {
123     // Check that the selection corresponds to selection type
124     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
125     aShapeType = aTopoShape.ShapeType();
126     // for compounds check sub-shapes: it may be compound of needed type:
127     // Booleans may produce compounds of Solids
128     if (aShapeType == TopAbs_COMPOUND) {
129       aShapeType = ModuleBase_Tools::getCompoundSubType(aTopoShape);
130     }
131   }
132
133   QIntList::const_iterator anIt = aShapeTypes.begin(), aLast = aShapeTypes.end();
134   for (; anIt != aLast && !aValid; anIt++) {
135     TopAbs_ShapeEnum aCurrentShapeType = (TopAbs_ShapeEnum)*anIt;
136     if (aShapeType == aCurrentShapeType)
137       aValid = true;
138     else if (aCurrentShapeType == TopAbs_FACE) {
139       // try to process the construction shape only if there is no a selected shape in the viewer
140       if (!theShape.get() && theResult.get()) {
141         ResultConstructionPtr aCResult =
142                                 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theResult);
143         aValid = aCResult.get() && aCResult->facesNum() > 0;
144       }
145     }
146   }
147   return aValid;
148 }
149
150 //********************************************************************
151 bool ModuleBase_WidgetSelector::activateSelectionAndFilters(bool toActivate)
152 {
153   updateSelectionName();
154
155   if (toActivate) {
156     myWorkshop->activateSubShapesSelection(getShapeTypes());
157   } else {
158     myWorkshop->deactivateSubShapesSelection();
159   }
160   return activateFilters(toActivate);
161 }
162
163 //********************************************************************
164 void ModuleBase_WidgetSelector::activateCustom()
165 {
166   connect(myWorkshop, SIGNAL(selectionChanged()), this,
167           SLOT(onSelectionChanged()), Qt::UniqueConnection);
168
169   activateSelectionAndFilters(true);
170
171   // Restore selection in the viewer by the attribute selection list
172   // it should be postponed to have current widget as active to validate restored selection
173   static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
174   ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
175 }
176
177 //********************************************************************
178 bool ModuleBase_WidgetSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
179 {
180   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
181   ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
182   bool aValid = acceptSubShape(aShape, aResult);
183
184   if (aValid) {
185     // In order to avoid selection of the same object
186     ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
187     FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aResult);
188     aValid = aSelectedFeature != myFeature;
189   }
190   return aValid;
191 }
192
193 //********************************************************************
194 bool ModuleBase_WidgetSelector::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
195 {
196   ObjectPtr anObject;
197   GeomShapePtr aShape;
198   getGeomSelection(thePrs, anObject, aShape);
199
200   // the last flag is to be depending on hasObject is called before. To be corrected later
201   return ModuleBase_Tools::setObject(attribute(), anObject, aShape,
202                                      myWorkshop, myIsInValidate, true);
203 }
204
205 //********************************************************************
206 void ModuleBase_WidgetSelector::deactivate()
207 {
208   ModuleBase_ModelWidget::deactivate();
209   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
210   activateSelectionAndFilters(false);
211
212   /// clear temporary cash
213   AttributePtr anAttribute = attribute();
214   std::string aType = anAttribute->attributeType();
215   if (anAttribute->attributeType() == ModelAPI_AttributeSelection::typeId()) {
216     AttributeSelectionPtr aSelectAttr =
217                              std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(anAttribute);
218     aSelectAttr->removeTemporaryValues();
219   }
220   else if (anAttribute->attributeType() == ModelAPI_AttributeSelectionList::typeId()) {
221     AttributeSelectionListPtr aSelectAttr =
222                       std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
223     aSelectAttr->removeTemporaryValues();
224   }
225 }
226
227 //********************************************************************
228 std::string ModuleBase_WidgetSelector::generateName(const AttributePtr& theAttribute,
229                                                     ModuleBase_IWorkshop* theWorkshop)
230 {
231   std::string aName;
232   if (theAttribute.get() != NULL) {
233     ModuleBase_Operation* anOperation = theWorkshop->currentOperation();
234
235     FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
236     if (aFeature.get()) {
237       std::string aXmlCfg, aDescription;
238       theWorkshop->module()->getXMLRepresentation(aFeature->getKind(), aXmlCfg, aDescription);
239
240       ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
241       std::string anAttributeTitle;
242       aFactory.getAttributeTitle(theAttribute->id(), anAttributeTitle);
243
244       std::stringstream aStreamName;
245       aStreamName << theAttribute->owner()->data()->name() << "/"<< anAttributeTitle.c_str();
246       aName = aStreamName.str();
247     }
248   }
249   return aName;
250 }