Salome HOME
Preselection using in operations
[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 //#define DEBUG_SHAPE_VALIDATION_PREVIOUS
71
72 ModuleBase_WidgetShapeSelector::ModuleBase_WidgetShapeSelector(QWidget* theParent,
73                                                      ModuleBase_IWorkshop* theWorkshop,
74                                                      const Config_WidgetAPI* theData,
75                                                      const std::string& theParentId)
76     : ModuleBase_WidgetValidated(theParent, theData, theParentId),
77       myWorkshop(theWorkshop)
78 {
79   QFormLayout* aLayout = new QFormLayout(this);
80   ModuleBase_Tools::adjustMargins(aLayout);
81
82   QString aLabelText = QString::fromStdString(theData->widgetLabel());
83   QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
84   myLabel = new QLabel(aLabelText, this);
85   if (!aLabelIcon.isEmpty())
86     myLabel->setPixmap(QPixmap(aLabelIcon));
87
88
89   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
90   myTextLine = new QLineEdit(this);
91   myTextLine->setReadOnly(true);
92   myTextLine->setToolTip(aToolTip);
93   myTextLine->installEventFilter(this);
94
95   aLayout->addRow(myLabel, myTextLine);
96
97   std::string aTypes = theData->getProperty("shape_types");
98   myShapeTypes = QString(aTypes.c_str()).split(' ', QString::SkipEmptyParts);
99
100   myShapeValidator = new GeomValidators_ShapeType();
101 }
102
103 //********************************************************************
104 ModuleBase_WidgetShapeSelector::~ModuleBase_WidgetShapeSelector()
105 {
106   delete myShapeValidator;
107 }
108
109 //********************************************************************
110 bool ModuleBase_WidgetShapeSelector::storeValueCustom() const
111 {
112   // the value is stored on the selection changed signal processing 
113   return true;
114 }
115
116 //********************************************************************
117 bool ModuleBase_WidgetShapeSelector::setObject(ObjectPtr theSelectedObject,
118                                                GeomShapePtr theShape)
119 {
120   bool isChanged = false;
121   FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(theSelectedObject);
122   if (aSelectedFeature == myFeature)  // In order to avoid selection of the same object
123     return isChanged;
124
125   DataPtr aData = myFeature->data();
126   AttributeReferencePtr aRef = aData->reference(attributeID());
127   if (aRef) {
128     ObjectPtr aObject = aRef->value();
129     if (!(aObject && aObject->isSame(theSelectedObject))) {
130       aRef->setValue(theSelectedObject);
131       isChanged = true;
132     }
133   } else {
134     AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
135     if (aRefAttr) {
136       ObjectPtr aObject = aRefAttr->object();
137       if (!(aObject && aObject->isSame(theSelectedObject))) {
138         aRefAttr->setObject(theSelectedObject);
139         isChanged = true;
140       }
141     } else {
142       AttributeSelectionPtr aSelectAttr = aData->selection(attributeID());
143       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
144       if (aSelectAttr.get() != NULL) {
145         aSelectAttr->setValue(aResult, theShape);
146         isChanged = true;
147       }
148     }
149   }
150   return isChanged;
151 }
152
153 //********************************************************************
154 QList<ModuleBase_ViewerPrs> ModuleBase_WidgetShapeSelector::getAttributeSelection() const
155 {
156   QList<ModuleBase_ViewerPrs> aSelected;
157   if(myFeature) {
158     DataPtr aData = myFeature->data();
159     AttributePtr anAttribute = myFeature->attribute(attributeID());
160
161     ObjectPtr anObject = GeomValidators_Tools::getObject(anAttribute);
162     TopoDS_Shape aShape;
163     std::shared_ptr<GeomAPI_Shape> aShapePtr = getShape();
164     if (aShapePtr.get()) {
165       aShape = aShapePtr->impl<TopoDS_Shape>();
166     }
167     ModuleBase_ViewerPrs aPrs(anObject, aShape, NULL);
168     aSelected.append(aPrs);
169   }
170   return aSelected;
171 }
172
173 //********************************************************************
174 void ModuleBase_WidgetShapeSelector::clearAttribute()
175 {
176   DataPtr aData = myFeature->data();
177   AttributeSelectionPtr aSelect = aData->selection(attributeID());
178   if (aSelect) {
179     aSelect->setValue(ResultPtr(), std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape()));
180     return;
181   }
182   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
183   if (aRefAttr) {
184     aRefAttr->setObject(ObjectPtr());
185     return;
186   }
187   AttributeReferencePtr aRef = aData->reference(attributeID());
188   if (aRef) {
189     aRef->setObject(ObjectPtr());
190   }
191 }
192
193 //********************************************************************
194 bool ModuleBase_WidgetShapeSelector::restoreValue()
195 {
196   bool isBlocked = this->blockSignals(true);
197   updateSelectionName();
198   this->blockSignals(isBlocked);
199
200   return true;
201 }
202
203 //********************************************************************
204 QList<QWidget*> ModuleBase_WidgetShapeSelector::getControls() const
205 {
206   QList<QWidget*> aControls;
207   aControls.append(myTextLine);
208   return aControls;
209 }
210
211 //********************************************************************
212 void ModuleBase_WidgetShapeSelector::onSelectionChanged()
213 {
214   // In order to make reselection possible, set empty object and shape should be done
215   setObject(ObjectPtr(), std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape()));
216
217   bool aHasObject = false;
218   QList<ModuleBase_ViewerPrs> aSelectedPrs = myWorkshop->selection()->getSelected(ModuleBase_ISelection::AllControls);
219   if (!aSelectedPrs.empty()) {
220     ModuleBase_ViewerPrs aPrs = aSelectedPrs.first();
221     if (!aPrs.isEmpty() && isValidSelection(aPrs)) {
222       setSelectionCustom(aPrs);
223       aHasObject = true;
224     }
225   }
226   // the updateObject method should be called to flush the updated sigal. The workshop listens it,
227   // calls validators for the feature and, as a result, updates the Apply button state.
228   updateObject(myFeature);
229   // the widget loses the focus only if the selected object is set
230   if (aHasObject)
231     emit focusOutWidget(this);
232 }
233
234 //********************************************************************
235 bool ModuleBase_WidgetShapeSelector::acceptSubShape(const TopoDS_Shape& theShape) const
236 {
237   foreach (QString aType, myShapeTypes) {
238     if (theShape.ShapeType() == ModuleBase_Tools::shapeType(aType))
239       return true;
240   }
241   return false;
242 }
243
244 //********************************************************************
245 GeomShapePtr ModuleBase_WidgetShapeSelector::getShape() const
246 {
247   GeomShapePtr aShape;
248   DataPtr aData = myFeature->data();
249   if (!aData->isValid())
250     return aShape;
251
252   AttributeSelectionPtr aSelect = aData->selection(attributeID());
253   if (aSelect)
254     aShape = aSelect->value();
255
256   return aShape;
257 }
258
259 //********************************************************************
260 void ModuleBase_WidgetShapeSelector::updateSelectionName()
261 {
262   DataPtr aData = myFeature->data();
263   if (!aData->isValid())
264     return;
265
266   bool isNameUpdated = false;
267   AttributeSelectionPtr aSelect = aData->selection(attributeID());
268   if (aSelect) {
269     myTextLine->setText(QString::fromStdString(aSelect->namingName(getDefaultValue())));
270     isNameUpdated = true;
271   }
272   if (!isNameUpdated) {
273     ObjectPtr anObject = GeomValidators_Tools::getObject(myFeature->attribute(attributeID()));
274     if (anObject.get() != NULL) {
275       std::string aName = anObject->data()->name();
276       myTextLine->setText(QString::fromStdString(aName));
277     } else {
278       AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
279       if (aRefAttr && aRefAttr->attr().get() != NULL) {
280         //myIsObject = aRefAttr->isObject();
281         AttributePtr anAttr = aRefAttr->attr();
282         if (anAttr.get() != NULL) {
283           std::stringstream aName;
284           aName <<anAttr->owner()->data()->name()<<"/"<<anAttr->id();
285           myTextLine->setText(QString::fromStdString(aName.str()));
286         }
287       }
288       else {
289         myTextLine->setText(getDefaultValue().c_str());
290       }
291     }
292   }
293 }
294
295
296 //********************************************************************
297 void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
298 {
299   updateSelectionName();
300
301   if (toActivate) {
302     QIntList aList;
303     foreach (QString aType, myShapeTypes) {
304       aList.append(ModuleBase_Tools::shapeType(aType));
305     }
306     myWorkshop->activateSubShapesSelection(aList);
307   } else {
308     myWorkshop->deactivateSubShapesSelection();
309   }
310 }
311
312 //********************************************************************
313 void ModuleBase_WidgetShapeSelector::raisePanel() const
314 {
315   QWidget* aParent = this->parentWidget();
316   QWidget* aLastPanel = 0;
317   while (!aParent->inherits("QDockWidget")) {
318     aLastPanel = aParent;
319     aParent = aParent->parentWidget();
320     if (!aParent)
321       return;
322   }
323   if (aParent->inherits("QDockWidget")) {
324     QDockWidget* aTabWgt = (QDockWidget*) aParent;
325     aTabWgt->raise();
326   }
327 }
328
329 //********************************************************************
330 void ModuleBase_WidgetShapeSelector::activateCustom()
331 {
332   connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
333   activateSelection(true);
334
335   // Restore selection in the viewer by the attribute selection list
336   myWorkshop->setSelected(getAttributeSelection());
337
338   activateFilters(myWorkshop, true);
339 }
340
341 //********************************************************************
342 void ModuleBase_WidgetShapeSelector::storeAttributeValue()
343 {
344   DataPtr aData = myFeature->data();
345   AttributePtr anAttribute = myFeature->attribute(attributeID());
346
347   myObject = GeomValidators_Tools::getObject(anAttribute);
348   myShape = getShape();
349   myRefAttribute = AttributePtr();
350   myIsObject = false;
351   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
352   if (aRefAttr) {
353     myIsObject = aRefAttr->isObject();
354     myRefAttribute = aRefAttr->attr();
355   }
356 }
357
358 //********************************************************************
359 void ModuleBase_WidgetShapeSelector::restoreAttributeValue(bool theValid)
360 {
361   DataPtr aData = myFeature->data();
362   AttributePtr anAttribute = myFeature->attribute(attributeID());
363
364   setObject(myObject, myShape);
365   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
366   if (aRefAttr) {
367     if (!myIsObject)
368       aRefAttr->setAttr(myRefAttribute);
369   }
370 }
371
372 //********************************************************************
373 void ModuleBase_WidgetShapeSelector::customValidators(
374                                     std::list<ModelAPI_Validator*>& theValidators,
375                                     std::list<std::list<std::string> >& theArguments) const
376 {
377   return;
378   theValidators.push_back(myShapeValidator);
379
380   std::list<std::string> anArguments;
381   foreach(QString aType, myShapeTypes) {
382     anArguments.push_back(aType.toStdString().c_str());
383   }
384   theArguments.push_back(anArguments);
385 }
386
387 //********************************************************************
388 bool ModuleBase_WidgetShapeSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
389 {
390 #ifdef DEBUG_SHAPE_VALIDATION_PREVIOUS
391   return true;
392 #endif
393
394   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
395   bool aValid;
396   // if there is no selected shape, the method returns true
397   if (!aShape.get())
398     aValid = true;
399   else {
400     // Check that the selection corresponds to selection type
401     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
402     aValid = acceptSubShape(aTopoShape);
403   }
404   return aValid;
405 }
406
407 //********************************************************************
408 bool ModuleBase_WidgetShapeSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
409 {
410   bool isDone = false;
411
412   ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
413
414   // It should be checked by corresponded validator
415   //ObjectPtr aObject = thePrs.object();
416   //ObjectPtr aCurrentObject = GeomValidators_Tools::getObject(myFeature->attribute(attributeID()));
417   /*
418   if ((!aCurrentObject) && (!aObject))
419     return false;*/
420
421   // It should be checked by corresponded validator
422   // Check that the selected object is result (others can not be accepted)
423   //ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
424   //if (!aRes)
425   //  return false;
426   /*if (myFeature) {
427     // We can not select a result of our feature
428     const std::list<std::shared_ptr<ModelAPI_Result>>& aResList = myFeature->results();
429     std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aIt;
430     for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
431       if ((*aIt) == aRes)
432         return false;
433     }
434   }
435   */
436   // It should be checked by corresponded validator
437   /*
438   // Check that object belongs to active document or PartSet
439   DocumentPtr aDoc = aRes->document();
440   SessionPtr aMgr = ModelAPI_Session::get();
441   if (!(aDoc == aMgr->activeDocument()) && !(aDoc == aMgr->moduleDocument()))
442     return false;*/
443
444 #ifdef DEBUG_SHAPE_VALIDATION_PREVIOUS
445   // It should be checked by corresponded validator
446   // Check that the result has a shape
447   GeomShapePtr aShape = ModelAPI_Tools::shape(aRes);
448   if (!aShape)
449     return false;
450
451   // Get sub-shapes from local selection
452   if (!thePrs.shape().IsNull()) {
453     aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
454     aShape->setImpl(new TopoDS_Shape(thePrs.shape()));
455   }
456
457   // Check that the selection corresponds to selection type
458   TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
459   if (!acceptSubShape(aTopoShape))
460     return false;
461 #else
462   // the difference is that the next method returns an empty shape if the result has the same shape
463   // to be checked for all cases and uncommented
464   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
465 #endif
466
467   setObject(aResult, aShape);
468   return true;
469 }
470
471 //********************************************************************
472 void ModuleBase_WidgetShapeSelector::deactivate()
473 {
474   activateSelection(false);
475   activateFilters(myWorkshop, false);
476   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
477 }