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