Salome HOME
Preselection using in operations: using of external objects correction.
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetShapeSelector.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModuleBase_WidgetShapeSelector.h
4 // Created:     2 June 2014
5 // Author:      Vitaly Smetannikov
6
7 #include <ModuleBase_WidgetShapeSelector.h>
8 #include <ModuleBase_Definitions.h>
9 #include <ModuleBase_ISelection.h>
10 #include <ModuleBase_IWorkshop.h>
11 #include <ModuleBase_IViewer.h>
12 #include <ModuleBase_Tools.h>
13 #include <ModuleBase_FilterFactory.h>
14 #include <ModuleBase_Filter.h>
15
16 #include <GeomValidators_ShapeType.h>
17
18 #include <Config_WidgetAPI.h>
19 #include <Events_Loop.h>
20 #include <Events_Message.h>
21 #include <GeomAPI_Interface.h>
22 #include <GeomAPI_Shape.h>
23 #include <GeomValidators_Tools.h>
24
25 #include <ModelAPI_AttributeReference.h>
26 #include <ModelAPI_Data.h>
27 #include <ModelAPI_Document.h>
28 #include <ModelAPI_Events.h>
29 #include <ModelAPI_Feature.h>
30 #include <ModelAPI_Result.h>
31 #include <ModelAPI_ResultConstruction.h>
32 #include <ModelAPI_AttributeReference.h>
33 #include <ModelAPI_AttributeSelection.h>
34 #include <ModelAPI_Session.h>
35 #include <ModelAPI_Tools.h>
36 #include <ModelAPI_ResultBody.h>
37 #include <ModelAPI_AttributeRefAttr.h>
38 #include <ModelAPI_Validator.h>
39 #include <ModelAPI_AttributeValidator.h>
40 #include <ModelAPI_ShapeValidator.h>
41
42 #include <Config_WidgetAPI.h>
43 #include <Events_Error.h>
44
45 #include <GeomAPI_Shape.h>
46
47 #include <SelectMgr_ListIteratorOfListOfFilter.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopExp_Explorer.hxx>
50
51 #include <QWidget>
52 #include <QLayout>
53 #include <QLabel>
54 #include <QLineEdit>
55 #include <QToolButton>
56 #include <QString>
57 #include <QEvent>
58 #include <QDockWidget>
59 #include <QApplication>
60 #include <QFormLayout>
61
62 #include <TopExp_Explorer.hxx>
63 #include <TopoDS_Shape.hxx>
64
65 #include <memory>
66
67 #include <list>
68 #include <string>
69
70 ModuleBase_WidgetShapeSelector::ModuleBase_WidgetShapeSelector(QWidget* theParent,
71                                                      ModuleBase_IWorkshop* theWorkshop,
72                                                      const Config_WidgetAPI* theData,
73                                                      const std::string& theParentId)
74     : ModuleBase_WidgetValidated(theParent, theData, theParentId),
75       myWorkshop(theWorkshop)
76 {
77   QFormLayout* aLayout = new QFormLayout(this);
78   ModuleBase_Tools::adjustMargins(aLayout);
79
80   QString aLabelText = QString::fromStdString(theData->widgetLabel());
81   QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
82   myLabel = new QLabel(aLabelText, this);
83   if (!aLabelIcon.isEmpty())
84     myLabel->setPixmap(QPixmap(aLabelIcon));
85
86
87   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
88   myTextLine = new QLineEdit(this);
89   myTextLine->setReadOnly(true);
90   myTextLine->setToolTip(aToolTip);
91   myTextLine->installEventFilter(this);
92
93   aLayout->addRow(myLabel, myTextLine);
94
95   std::string aTypes = theData->getProperty("shape_types");
96   myShapeTypes = QString(aTypes.c_str()).split(' ', QString::SkipEmptyParts);
97
98   myShapeValidator = new GeomValidators_ShapeType();
99 }
100
101 //********************************************************************
102 ModuleBase_WidgetShapeSelector::~ModuleBase_WidgetShapeSelector()
103 {
104   delete myShapeValidator;
105 }
106
107 //********************************************************************
108 bool ModuleBase_WidgetShapeSelector::storeValueCustom() const
109 {
110   // the value is stored on the selection changed signal processing 
111   return true;
112 }
113
114 //********************************************************************
115 void ModuleBase_WidgetShapeSelector::setObject(ObjectPtr theSelectedObject,
116                                                GeomShapePtr theShape)
117 {
118   DataPtr aData = myFeature->data();
119   AttributeReferencePtr aRef = aData->reference(attributeID());
120   if (aRef) {
121     ObjectPtr aObject = aRef->value();
122     if (!(aObject && aObject->isSame(theSelectedObject))) {
123       aRef->setValue(theSelectedObject);
124     }
125   } else {
126     AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
127     if (aRefAttr) {
128       ObjectPtr aObject = aRefAttr->object();
129       if (!(aObject && aObject->isSame(theSelectedObject))) {
130         aRefAttr->setObject(theSelectedObject);
131       }
132     } else {
133       AttributeSelectionPtr aSelectAttr = aData->selection(attributeID());
134       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
135       if (aSelectAttr.get() != NULL) {
136         aSelectAttr->setValue(aResult, theShape);
137       }
138     }
139   }
140 }
141
142 //********************************************************************
143 QList<ModuleBase_ViewerPrs> ModuleBase_WidgetShapeSelector::getAttributeSelection() const
144 {
145   QList<ModuleBase_ViewerPrs> aSelected;
146   if(myFeature) {
147     DataPtr aData = myFeature->data();
148     AttributePtr anAttribute = myFeature->attribute(attributeID());
149
150     ObjectPtr anObject = GeomValidators_Tools::getObject(anAttribute);
151     TopoDS_Shape aShape;
152     std::shared_ptr<GeomAPI_Shape> aShapePtr = getShape();
153     if (aShapePtr.get()) {
154       aShape = aShapePtr->impl<TopoDS_Shape>();
155     }
156     ModuleBase_ViewerPrs aPrs(anObject, aShape, NULL);
157     aSelected.append(aPrs);
158   }
159   return aSelected;
160 }
161
162 //********************************************************************
163 void ModuleBase_WidgetShapeSelector::getGeomSelection(const ModuleBase_ViewerPrs& thePrs,
164                                                       ObjectPtr& theObject,
165                                                       GeomShapePtr& theShape)
166 {
167   theObject = myWorkshop->selection()->getResult(thePrs);
168   theShape = myWorkshop->selection()->getShape(thePrs);
169 }
170
171 //********************************************************************
172 void ModuleBase_WidgetShapeSelector::clearAttribute()
173 {
174   DataPtr aData = myFeature->data();
175   AttributeSelectionPtr aSelect = aData->selection(attributeID());
176   if (aSelect) {
177     aSelect->setValue(ResultPtr(), std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape()));
178     return;
179   }
180   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
181   if (aRefAttr) {
182     aRefAttr->setObject(ObjectPtr());
183     return;
184   }
185   AttributeReferencePtr aRef = aData->reference(attributeID());
186   if (aRef) {
187     aRef->setObject(ObjectPtr());
188   }
189 }
190
191 //********************************************************************
192 bool ModuleBase_WidgetShapeSelector::restoreValue()
193 {
194   bool isBlocked = this->blockSignals(true);
195   updateSelectionName();
196   this->blockSignals(isBlocked);
197
198   return true;
199 }
200
201 //********************************************************************
202 QList<QWidget*> ModuleBase_WidgetShapeSelector::getControls() const
203 {
204   QList<QWidget*> aControls;
205   aControls.append(myTextLine);
206   return aControls;
207 }
208
209 //********************************************************************
210 void ModuleBase_WidgetShapeSelector::onSelectionChanged()
211 {
212   // In order to make reselection possible, set empty object and shape should be done
213   setObject(ObjectPtr(), std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape()));
214
215   QList<ModuleBase_ViewerPrs> aSelected = myWorkshop->selection()->getSelected(ModuleBase_ISelection::AllControls);
216   bool aHasObject = setSelection(aSelected);
217
218   // the updateObject method should be called to flush the updated sigal. The workshop listens it,
219   // calls validators for the feature and, as a result, updates the Apply button state.
220   updateObject(myFeature);
221   // the widget loses the focus only if the selected object is set
222   if (aHasObject)
223     emit focusOutWidget(this);
224 }
225
226 //********************************************************************
227 bool ModuleBase_WidgetShapeSelector::acceptSubShape(const TopoDS_Shape& theShape) const
228 {
229   foreach (QString aType, myShapeTypes) {
230     if (theShape.ShapeType() == ModuleBase_Tools::shapeType(aType))
231       return true;
232   }
233   return false;
234 }
235
236 //********************************************************************
237 GeomShapePtr ModuleBase_WidgetShapeSelector::getShape() const
238 {
239   GeomShapePtr aShape;
240   DataPtr aData = myFeature->data();
241   if (!aData->isValid())
242     return aShape;
243
244   AttributeSelectionPtr aSelect = aData->selection(attributeID());
245   if (aSelect)
246     aShape = aSelect->value();
247
248   return aShape;
249 }
250
251 //********************************************************************
252 void ModuleBase_WidgetShapeSelector::updateSelectionName()
253 {
254   DataPtr aData = myFeature->data();
255   if (!aData->isValid())
256     return;
257
258   bool isNameUpdated = false;
259   AttributeSelectionPtr aSelect = aData->selection(attributeID());
260   if (aSelect) {
261     myTextLine->setText(QString::fromStdString(aSelect->namingName(getDefaultValue())));
262     isNameUpdated = true;
263   }
264   if (!isNameUpdated) {
265     ObjectPtr anObject = GeomValidators_Tools::getObject(myFeature->attribute(attributeID()));
266     if (anObject.get() != NULL) {
267       std::string aName = anObject->data()->name();
268       myTextLine->setText(QString::fromStdString(aName));
269     } else {
270       AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
271       if (aRefAttr && aRefAttr->attr().get() != NULL) {
272         //myIsObject = aRefAttr->isObject();
273         AttributePtr anAttr = aRefAttr->attr();
274         if (anAttr.get() != NULL) {
275           std::stringstream aName;
276           aName <<anAttr->owner()->data()->name()<<"/"<<anAttr->id();
277           myTextLine->setText(QString::fromStdString(aName.str()));
278         }
279       }
280       else {
281         myTextLine->setText(getDefaultValue().c_str());
282       }
283     }
284   }
285 }
286
287
288 //********************************************************************
289 void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
290 {
291   updateSelectionName();
292
293   if (toActivate) {
294     QIntList aList;
295     foreach (QString aType, myShapeTypes) {
296       aList.append(ModuleBase_Tools::shapeType(aType));
297     }
298     myWorkshop->activateSubShapesSelection(aList);
299   } else {
300     myWorkshop->deactivateSubShapesSelection();
301   }
302 }
303
304 //********************************************************************
305 void ModuleBase_WidgetShapeSelector::raisePanel() const
306 {
307   QWidget* aParent = this->parentWidget();
308   QWidget* aLastPanel = 0;
309   while (!aParent->inherits("QDockWidget")) {
310     aLastPanel = aParent;
311     aParent = aParent->parentWidget();
312     if (!aParent)
313       return;
314   }
315   if (aParent->inherits("QDockWidget")) {
316     QDockWidget* aTabWgt = (QDockWidget*) aParent;
317     aTabWgt->raise();
318   }
319 }
320
321 //********************************************************************
322 void ModuleBase_WidgetShapeSelector::activateCustom()
323 {
324   connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
325   activateSelection(true);
326
327   // Restore selection in the viewer by the attribute selection list
328   myWorkshop->setSelected(getAttributeSelection());
329
330   activateFilters(myWorkshop, true);
331 }
332
333 //********************************************************************
334 void ModuleBase_WidgetShapeSelector::storeAttributeValue()
335 {
336   DataPtr aData = myFeature->data();
337   AttributePtr anAttribute = myFeature->attribute(attributeID());
338
339   myObject = GeomValidators_Tools::getObject(anAttribute);
340   myShape = getShape();
341   myRefAttribute = AttributePtr();
342   myIsObject = false;
343   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
344   if (aRefAttr) {
345     myIsObject = aRefAttr->isObject();
346     myRefAttribute = aRefAttr->attr();
347   }
348 }
349
350 //********************************************************************
351 void ModuleBase_WidgetShapeSelector::restoreAttributeValue(bool theValid)
352 {
353   DataPtr aData = myFeature->data();
354   AttributePtr anAttribute = myFeature->attribute(attributeID());
355
356   setObject(myObject, myShape);
357   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
358   if (aRefAttr) {
359     if (!myIsObject)
360       aRefAttr->setAttr(myRefAttribute);
361   }
362 }
363
364 //********************************************************************
365 bool ModuleBase_WidgetShapeSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
366 {
367   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
368   bool aValid;
369   // if there is no selected shape, the method returns true
370   if (!aShape.get())
371     aValid = true;
372   else {
373     // Check that the selection corresponds to selection type
374     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
375     aValid = acceptSubShape(aTopoShape);
376   }
377   if (aValid) {
378     // In order to avoid selection of the same object
379     ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
380     FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aResult);
381     aValid = aSelectedFeature != myFeature;
382   }
383   return aValid;
384 }
385
386 //********************************************************************
387 bool ModuleBase_WidgetShapeSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
388 {
389   ObjectPtr anObject;
390   GeomShapePtr aShape;
391   getGeomSelection(thePrs, anObject, aShape);
392
393   setObject(anObject, aShape);
394   return true;
395 }
396
397 //********************************************************************
398 void ModuleBase_WidgetShapeSelector::deactivate()
399 {
400   activateSelection(false);
401   activateFilters(myWorkshop, false);
402   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
403 }