]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp
Salome HOME
2fe1ab684075b5f43af9fd37a8a852c8c0f896e4
[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   QList<ModuleBase_ViewerPrs> aSelected = myWorkshop->selection()->getSelected(ModuleBase_ISelection::AllControls);
218   bool aHasObject = setSelection(aSelected);
219
220   // the updateObject method should be called to flush the updated sigal. The workshop listens it,
221   // calls validators for the feature and, as a result, updates the Apply button state.
222   updateObject(myFeature);
223   // the widget loses the focus only if the selected object is set
224   if (aHasObject)
225     emit focusOutWidget(this);
226 }
227
228 //********************************************************************
229 bool ModuleBase_WidgetShapeSelector::acceptSubShape(const TopoDS_Shape& theShape) const
230 {
231   foreach (QString aType, myShapeTypes) {
232     if (theShape.ShapeType() == ModuleBase_Tools::shapeType(aType))
233       return true;
234   }
235   return false;
236 }
237
238 //********************************************************************
239 GeomShapePtr ModuleBase_WidgetShapeSelector::getShape() const
240 {
241   GeomShapePtr aShape;
242   DataPtr aData = myFeature->data();
243   if (!aData->isValid())
244     return aShape;
245
246   AttributeSelectionPtr aSelect = aData->selection(attributeID());
247   if (aSelect)
248     aShape = aSelect->value();
249
250   return aShape;
251 }
252
253 //********************************************************************
254 void ModuleBase_WidgetShapeSelector::updateSelectionName()
255 {
256   DataPtr aData = myFeature->data();
257   if (!aData->isValid())
258     return;
259
260   bool isNameUpdated = false;
261   AttributeSelectionPtr aSelect = aData->selection(attributeID());
262   if (aSelect) {
263     myTextLine->setText(QString::fromStdString(aSelect->namingName(getDefaultValue())));
264     isNameUpdated = true;
265   }
266   if (!isNameUpdated) {
267     ObjectPtr anObject = GeomValidators_Tools::getObject(myFeature->attribute(attributeID()));
268     if (anObject.get() != NULL) {
269       std::string aName = anObject->data()->name();
270       myTextLine->setText(QString::fromStdString(aName));
271     } else {
272       AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
273       if (aRefAttr && aRefAttr->attr().get() != NULL) {
274         //myIsObject = aRefAttr->isObject();
275         AttributePtr anAttr = aRefAttr->attr();
276         if (anAttr.get() != NULL) {
277           std::stringstream aName;
278           aName <<anAttr->owner()->data()->name()<<"/"<<anAttr->id();
279           myTextLine->setText(QString::fromStdString(aName.str()));
280         }
281       }
282       else {
283         myTextLine->setText(getDefaultValue().c_str());
284       }
285     }
286   }
287 }
288
289
290 //********************************************************************
291 void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
292 {
293   updateSelectionName();
294
295   if (toActivate) {
296     QIntList aList;
297     foreach (QString aType, myShapeTypes) {
298       aList.append(ModuleBase_Tools::shapeType(aType));
299     }
300     myWorkshop->activateSubShapesSelection(aList);
301   } else {
302     myWorkshop->deactivateSubShapesSelection();
303   }
304 }
305
306 //********************************************************************
307 void ModuleBase_WidgetShapeSelector::raisePanel() const
308 {
309   QWidget* aParent = this->parentWidget();
310   QWidget* aLastPanel = 0;
311   while (!aParent->inherits("QDockWidget")) {
312     aLastPanel = aParent;
313     aParent = aParent->parentWidget();
314     if (!aParent)
315       return;
316   }
317   if (aParent->inherits("QDockWidget")) {
318     QDockWidget* aTabWgt = (QDockWidget*) aParent;
319     aTabWgt->raise();
320   }
321 }
322
323 //********************************************************************
324 void ModuleBase_WidgetShapeSelector::activateCustom()
325 {
326   connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
327   activateSelection(true);
328
329   // Restore selection in the viewer by the attribute selection list
330   myWorkshop->setSelected(getAttributeSelection());
331
332   activateFilters(myWorkshop, true);
333 }
334
335 //********************************************************************
336 void ModuleBase_WidgetShapeSelector::storeAttributeValue()
337 {
338   DataPtr aData = myFeature->data();
339   AttributePtr anAttribute = myFeature->attribute(attributeID());
340
341   myObject = GeomValidators_Tools::getObject(anAttribute);
342   myShape = getShape();
343   myRefAttribute = AttributePtr();
344   myIsObject = false;
345   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
346   if (aRefAttr) {
347     myIsObject = aRefAttr->isObject();
348     myRefAttribute = aRefAttr->attr();
349   }
350 }
351
352 //********************************************************************
353 void ModuleBase_WidgetShapeSelector::restoreAttributeValue(bool theValid)
354 {
355   DataPtr aData = myFeature->data();
356   AttributePtr anAttribute = myFeature->attribute(attributeID());
357
358   setObject(myObject, myShape);
359   AttributeRefAttrPtr aRefAttr = aData->refattr(attributeID());
360   if (aRefAttr) {
361     if (!myIsObject)
362       aRefAttr->setAttr(myRefAttribute);
363   }
364 }
365
366 //********************************************************************
367 bool ModuleBase_WidgetShapeSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
368 {
369 #ifdef DEBUG_SHAPE_VALIDATION_PREVIOUS
370   return true;
371 #endif
372
373   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
374   bool aValid;
375   // if there is no selected shape, the method returns true
376   if (!aShape.get())
377     aValid = true;
378   else {
379     // Check that the selection corresponds to selection type
380     TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
381     aValid = acceptSubShape(aTopoShape);
382   }
383   return aValid;
384 }
385
386 //********************************************************************
387 bool ModuleBase_WidgetShapeSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
388 {
389   bool isDone = false;
390
391   ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
392
393   // It should be checked by corresponded validator
394   //ObjectPtr aObject = thePrs.object();
395   //ObjectPtr aCurrentObject = GeomValidators_Tools::getObject(myFeature->attribute(attributeID()));
396   /*
397   if ((!aCurrentObject) && (!aObject))
398     return false;*/
399
400   // It should be checked by corresponded validator
401   // Check that the selected object is result (others can not be accepted)
402   //ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
403   //if (!aRes)
404   //  return false;
405   /*if (myFeature) {
406     // We can not select a result of our feature
407     const std::list<std::shared_ptr<ModelAPI_Result>>& aResList = myFeature->results();
408     std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aIt;
409     for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
410       if ((*aIt) == aRes)
411         return false;
412     }
413   }
414   */
415   // It should be checked by corresponded validator
416   /*
417   // Check that object belongs to active document or PartSet
418   DocumentPtr aDoc = aRes->document();
419   SessionPtr aMgr = ModelAPI_Session::get();
420   if (!(aDoc == aMgr->activeDocument()) && !(aDoc == aMgr->moduleDocument()))
421     return false;*/
422
423 #ifdef DEBUG_SHAPE_VALIDATION_PREVIOUS
424   // It should be checked by corresponded validator
425   // Check that the result has a shape
426   GeomShapePtr aShape = ModelAPI_Tools::shape(aRes);
427   if (!aShape)
428     return false;
429
430   // Get sub-shapes from local selection
431   if (!thePrs.shape().IsNull()) {
432     aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
433     aShape->setImpl(new TopoDS_Shape(thePrs.shape()));
434   }
435
436   // Check that the selection corresponds to selection type
437   TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
438   if (!acceptSubShape(aTopoShape))
439     return false;
440 #else
441   // the difference is that the next method returns an empty shape if the result has the same shape
442   // to be checked for all cases and uncommented
443   GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
444 #endif
445
446   setObject(aResult, aShape);
447   return true;
448 }
449
450 //********************************************************************
451 void ModuleBase_WidgetShapeSelector::deactivate()
452 {
453   activateSelection(false);
454   activateFilters(myWorkshop, false);
455   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
456 }