Salome HOME
9f6172bfafdd442c6dd2947d1286bf2b383379fe
[modules/shaper.git] / src / PartSet / PartSet_WidgetSketchCreator.cpp
1 // Copyright (C) 2014-2023  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PartSet_WidgetSketchCreator.h"
21 #include "PartSet_Module.h"
22 #include "PartSet_WidgetSketchLabel.h"
23 #include "PartSet_PreviewPlanes.h"
24
25 #include <Config_Keywords.h>
26
27 #include <XGUI_ModuleConnector.h>
28 #include <XGUI_Workshop.h>
29 #include <XGUI_Displayer.h>
30 #include <XGUI_SelectionMgr.h>
31 #include <XGUI_OperationMgr.h>
32 #include <XGUI_PropertyPanel.h>
33 #include <XGUI_Tools.h>
34 #include <XGUI_ViewerProxy.h>
35
36 #include <GeomAPI_Face.h>
37
38 #include <Events_InfoMessage.h>
39
40 #include <ModelAPI_Session.h>
41 #include <ModelAPI_ResultBody.h>
42 #include <ModelAPI_AttributeSelection.h>
43 #include <ModelAPI_AttributeSelectionList.h>
44 #include <ModelAPI_Validator.h>
45 #include <ModelAPI_Events.h>
46 #include <ModelAPI_ResultConstruction.h>
47
48 #include <SketchPlugin_SketchEntity.h>
49 #include <FeaturesPlugin_CompositeBoolean.h>
50
51 #include <ModuleBase_Tools.h>
52 #include <ModuleBase_Operation.h>
53 #include <ModuleBase_IPropertyPanel.h>
54 #include <ModuleBase_OperationFeature.h>
55 #include <ModuleBase_ViewerPrs.h>
56 #include <ModuleBase_ChoiceCtrl.h>
57 #include <ModuleBase_IWorkshop.h>
58 #include <ModuleBase_ISelectionActivate.h>
59
60 #include <Config_WidgetAPI.h>
61
62 #include <Events_Loop.h>
63
64 #include <QLabel>
65 #include <QLineEdit>
66 #include <QDoubleValidator>
67 //#include <QFormLayout>
68 #include <QVBoxLayout>
69 #include <QMessageBox>
70 #include <QMainWindow>
71
72 #ifdef WIN32
73 #pragma warning(disable : 4456) // for nested foreach
74 #endif
75
76 #define DEBUG_UNDO_INVALID_SKETCH
77
78
79
80 QStringList getIconsList(const QStringList& theNames)
81 {
82   QStringList aIcons;
83   foreach(QString aName, theNames) {
84     QString aUName = aName.toUpper();
85     if ((aUName == "VERTICES") || (aUName == "VERTEX"))
86       aIcons << ":pictures/vertex32.png";
87     else if ((aUName == "EDGES") || (aUName == "EDGE"))
88       aIcons << ":pictures/edge32.png";
89     else if ((aUName == "FACES") || (aUName == "FACE"))
90       aIcons << ":pictures/face32.png";
91   }
92   return aIcons;
93 }
94
95
96
97 PartSet_WidgetSketchCreator::PartSet_WidgetSketchCreator(QWidget* theParent,
98                                                          PartSet_Module* theModule,
99                                                          const Config_WidgetAPI* theData)
100 : ModuleBase_WidgetSelector(theParent, theModule->workshop(), theData),
101   myModule(theModule), myIsCustomAttribute(false)
102 {
103   myAttributeListID = theData->getProperty("attribute_list_id");
104
105   //QFormLayout* aLayout = new QFormLayout(this);
106   QVBoxLayout* aLayout = new QVBoxLayout(this);
107   ModuleBase_Tools::zeroMargins(aLayout);
108
109   ModuleBase_Tools::adjustMargins(aLayout);
110
111   QString aLabelText = translate(theData->widgetLabel());
112   QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
113
114   // Size of the View control
115   mySizeOfViewWidget = new QWidget(this);
116   QHBoxLayout* aSizeLayout = new QHBoxLayout(mySizeOfViewWidget);
117   aSizeLayout->addWidget(new QLabel(tr("Size of the view"), mySizeOfViewWidget));
118   mySizeOfView = new QLineEdit(mySizeOfViewWidget);
119
120   QDoubleValidator* aValidator = new QDoubleValidator(0, DBL_MAX, 12, mySizeOfView);
121   aValidator->setLocale(ModuleBase_Tools::doubleLocale());
122   aValidator->setNotation(QDoubleValidator::StandardNotation);
123   mySizeOfView->setValidator(aValidator);
124   aSizeLayout->addWidget(mySizeOfView);
125
126   myLabel = new QLabel(aLabelText, this);
127   myLabel->setWordWrap(true);
128
129   aLayout->addWidget(mySizeOfViewWidget);
130   aLayout->addWidget(myLabel);
131
132   std::string aTypes = theData->getProperty("shape_types");
133   myShapeTypes = QString(aTypes.c_str()).split(' ', QString::SkipEmptyParts);
134   myIsUseChoice = theData->getBooleanAttribute("use_choice", false);
135
136   QStringList aIconsList;
137   std::string aIcons = theData->getProperty("type_icons");
138   if (aIcons.size() > 0)
139     aIconsList = QString(aIcons.c_str()).split(' ', QString::SkipEmptyParts);
140
141   if (aIconsList.size() != myShapeTypes.size())
142     aIconsList = getIconsList(myShapeTypes);
143
144   myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
145   myTypeCtrl->setLabel(tr("Type"));
146   if (!myShapeTypes.empty()) {
147     std::string aDefType = theData->getProperty("default_type");
148     if (aDefType.size() > 0) {
149       bool aOk = false;
150       int aId = QString(aDefType.c_str()).toInt(&aOk);
151       if (aOk) {
152         myTypeCtrl->setValue(aId);
153         myDefMode = myShapeTypes.at(aId).toStdString();
154       }
155     }
156     if (myDefMode.size() == 0) {
157       myTypeCtrl->setValue(0);
158       myDefMode = myShapeTypes.first().toStdString();
159     }
160   }
161   aLayout->addWidget(myTypeCtrl);
162   // There is no sense to parameterize list of types while we can not parameterize selection mode
163   // if the xml definition contains one type, the controls to select a type should not be shown
164   if (myShapeTypes.size() <= 1 || !myIsUseChoice) {
165     myTypeCtrl->setVisible(false);
166   }
167   connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
168
169   aLayout->addStretch(1);
170   myPreviewPlanes = new PartSet_PreviewPlanes();
171 }
172
173 PartSet_WidgetSketchCreator::~PartSet_WidgetSketchCreator()
174 {
175   // we need to deactivate here in order to hide preview planes if the selection mode is
176   // active
177   deactivate();
178 }
179
180 QList<QWidget*> PartSet_WidgetSketchCreator::getControls() const
181 {
182   QList<QWidget*> aControls;
183   aControls.append(myLabel);
184   return aControls;
185 }
186
187 bool PartSet_WidgetSketchCreator::restoreValueCustom()
188 {
189   return true;
190 }
191
192 bool PartSet_WidgetSketchCreator::storeValueCustom()
193 {
194   return true;
195 }
196
197 AttributePtr PartSet_WidgetSketchCreator::attribute() const
198 {
199   AttributePtr anAttribute;
200   if (myIsCustomAttribute)
201     anAttribute = myFeature->attribute(myAttributeListID);
202   else
203     anAttribute = ModuleBase_WidgetSelector::attribute();
204
205   return anAttribute;
206 }
207
208 //********************************************************************
209 void PartSet_WidgetSketchCreator::openExtrusionTransaction()
210 {
211   SessionPtr aMgr = ModelAPI_Session::get();
212   bool aIsOp = aMgr->isOperation();
213   if (!aIsOp) {
214     const static std::string aNestedOpID("Parameters modification");
215     aMgr->startOperation(aNestedOpID, true);
216   }
217 }
218
219 //********************************************************************
220 bool PartSet_WidgetSketchCreator::isValidSelection(const ModuleBase_ViewerPrsPtr& theValue)
221 {
222   bool aValid = false;
223   if (myIsCustomAttribute) {
224     // check only suiting of the value to custom attribute (myAttributeListID)
225     // do not cash of validation to avoid using states, stored for XML attribute
226     // there is an alternative is to call clearValidatedCash() in setSelection()
227     aValid = isValidSelectionForAttribute(theValue, attribute());
228   }
229   else { /// if the validated attribute is already custom
230     if (getValidState(theValue, aValid)) {
231       return aValid;
232     }
233     aValid = isValidSelectionCustom(theValue);
234     if (!aValid)
235       // check selection to create new sketh (XML current attribute)
236       aValid = isValidSelectionForAttribute(theValue, attribute());
237     if (!aValid) {
238       // check selection to fill list attribute (myAttributeListID)
239       bool isCustomAttribute = myIsCustomAttribute;
240       myIsCustomAttribute = true;
241       aValid = isValidSelectionForAttribute(theValue, attribute());
242       myIsCustomAttribute = isCustomAttribute;
243     }
244   }
245   storeValidState(theValue, aValid);
246   return aValid;
247 }
248
249 //********************************************************************
250 bool PartSet_WidgetSketchCreator::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& theValue)
251 {
252   return PartSet_WidgetSketchLabel::canFillSketch(theValue);
253 }
254
255 void PartSet_WidgetSketchCreator::activateSelectionControl()
256 {
257   // reset previously set size of view needed on restart extrusion after Sketch
258   if (myModule->sketchMgr()->previewSketchPlane()->isUseSizeOfView())
259     myModule->sketchMgr()->previewSketchPlane()->setSizeOfView(0, false);
260
261   // we need to call activate here as the widget has no focus accepted controls
262   // if these controls are added here, activate will happens automatically after focusIn()
263   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
264   XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
265   aPanel->activateWidget(this, false);
266 }
267
268 void PartSet_WidgetSketchCreator::setVisibleSelectionControl(const bool theSelectionControl)
269 {
270   // hide current widget, activate the next widget
271   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
272   XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
273   const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
274   foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
275     if (theSelectionControl) { // hide other controls
276       if (aWidget != this)
277         aWidget->setVisible(false);
278     }
279     else { // hide current control
280       if (aWidget == this)
281         aWidget->setVisible(false);
282       else {
283         aWidget->setVisible(true);
284         if (aWidget->attributeID() == myAttributeListID)
285           setEnabledModelWidget(aWidget, !hasSubObjects());
286       }
287     }
288   }
289
290   if (theSelectionControl) {
291     bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
292     bool aSketchIsVisualized = myPreviewPlanes->hasVisualizedSketch(myWorkshop);
293     if (!aBodyIsVisualized && !aSketchIsVisualized) {
294       // We have to select a plane before any operation
295       myPreviewPlanes->showPreviewPlanes(myWorkshop);
296       mySizeOfViewWidget->setVisible(true);
297     }
298     else {
299       mySizeOfViewWidget->setVisible(false);
300     }
301
302   } else {
303     bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
304     myPreviewPlanes->erasePreviewPlanes(myWorkshop);
305     if (aHidePreview)
306       aWorkshop->viewer()->update();
307   }
308 }
309
310 QIntList PartSet_WidgetSketchCreator::shapeTypes() const
311 {
312   QIntList aShapeTypes;
313   if (myShapeTypes.length() > 1 && myIsUseChoice) {
314     QStringList aTypes = myTypeCtrl->textValue().split("|", QString::SkipEmptyParts);
315     foreach(QString aType, aTypes) {
316       aShapeTypes.append(ModuleBase_Tools::shapeType(aType));
317     }
318   }
319   else {
320     foreach(QString aType, myShapeTypes) {
321       QStringList aSubTypes = aType.split("|", QString::SkipEmptyParts);
322       foreach(QString asubType, aSubTypes) {
323         aShapeTypes.append(ModuleBase_Tools::shapeType(asubType));
324       }
325     }
326   }
327   return aShapeTypes;
328 }
329
330 void PartSet_WidgetSketchCreator::setEditingMode(bool isEditing)
331 {
332   ModuleBase_ModelWidget::setEditingMode(isEditing);
333   if (isEditing) {
334     setVisibleSelectionControl(false);
335
336     ModuleBase_ModelWidget* anAttributeListWidget = 0;
337     XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
338     XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
339     const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
340     foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
341       if (aWidget->attributeID() == myAttributeListID) {
342         anAttributeListWidget = aWidget;
343         break;
344       }
345     }
346     if (anAttributeListWidget)
347       setEnabledModelWidget(anAttributeListWidget, !hasSubObjects());
348   }
349 }
350
351 bool PartSet_WidgetSketchCreator::isSelectionMode() const
352 {
353   AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
354   bool aHasValueInList = anAttrList.get() && anAttrList->size() > 0;
355
356   return !aHasValueInList;
357 }
358
359 bool PartSet_WidgetSketchCreator::hasSubObjects() const
360 {
361   bool aHasSubObjects = false;
362   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
363   if (aComposite.get())
364     aHasSubObjects = aComposite->numberOfSubs() > 0;
365   return aHasSubObjects;
366 }
367
368 bool PartSet_WidgetSketchCreator::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
369                                                const bool theToValidate)
370 {
371   bool aDone = false;
372   if (!startSketchOperation(theValues)) {
373     myIsCustomAttribute = true;
374     QList<ModuleBase_ViewerPrsPtr>::const_iterator
375       anIt = theValues.begin(), aLast = theValues.end();
376     bool aProcessed = false;
377     for (; anIt != aLast; anIt++) {
378       ModuleBase_ViewerPrsPtr aValue = *anIt;
379       if (!theToValidate || isValidInFilters(aValue))
380         aProcessed = setSelectionCustom(aValue) || aProcessed;
381     }
382     myIsCustomAttribute = false;
383     aDone = aProcessed;
384     if (aProcessed) {
385       emit valuesChanged();
386       updateObject(myFeature);
387       setVisibleSelectionControl(false);
388       // manually deactivation because the widget was
389       // not activated as has no focus acceptin controls
390       deactivate();
391       emit focusOutWidget(this);
392     }
393   }
394   return aDone;
395 }
396
397 //********************************************************************
398 bool PartSet_WidgetSketchCreator::processSelection()
399 {
400   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
401   bool isDone = setSelection(aSelected, true/*false*/);
402
403   return isDone;
404 }
405
406 //********************************************************************
407 void PartSet_WidgetSketchCreator::updateOnSelectionChanged(const bool theDone)
408 {
409 }
410
411 bool PartSet_WidgetSketchCreator::startSketchOperation(
412                               const QList<ModuleBase_ViewerPrsPtr>& theValues)
413 {
414   bool aSketchStarted = false;
415
416   if (theValues.size() != 1)
417     return aSketchStarted;
418
419   ModuleBase_ViewerPrsPtr aValue = theValues.front();
420   if (!aValue.get() || !PartSet_WidgetSketchLabel::canFillSketch(aValue))
421     return aSketchStarted;
422
423   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aValue->object());
424   /// sketch should not started by object(face) selected as global. If Local face is selected,
425   /// sketch is started
426   if (aResult.get() && aValue->shape().get() && aResult->shape()->isEqual(aValue->shape())) {
427     ResultConstructionPtr aConstruction =
428       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aResult);
429     if (!aConstruction.get() || !aConstruction->isInfinite())
430       return aSketchStarted;
431   }
432   aSketchStarted = true;
433   // Set View size if a plane is selected
434   if (myPreviewPlanes->isPreviewDisplayed() &&
435       myPreviewPlanes->isPreviewShape(aValue->shape())) {
436     // set default plane size
437     bool isSetSizeOfView = false;
438     double aSizeOfView = 0;
439     QString aSizeOfViewStr = mySizeOfView->text();
440     if (!aSizeOfViewStr.isEmpty()) {
441       aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
442       if (isSetSizeOfView && aSizeOfView <= 0) {
443         isSetSizeOfView = false;
444       }
445     }
446     if (isSetSizeOfView)
447       myModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, true);
448   }
449   // manually deactivation because the widget was not activated as has no focus acceptin controls
450   deactivate();
451   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
452
453   // start edit operation for the sketch
454   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
455                                                             (myModule->createOperation("Sketch"));
456   QList<ModuleBase_ViewerPrsPtr> aValues;
457   aValues.push_back(aValue);
458   aFOperation->setPreselection(aValues);
459
460   myWorkshop->processLaunchOperation(aFOperation);
461
462   return aSketchStarted;
463 }
464
465 bool PartSet_WidgetSketchCreator::focusTo()
466 {
467   // this method is called only in creation mode. In Edition mode this widget is hidden
468   if (isSelectionMode() && !hasSubObjects()) {
469     setVisibleSelectionControl(true);
470     activateSelectionControl();
471     openExtrusionTransaction();
472     return true;
473   }
474   else
475     connect(myModule, SIGNAL(resumed(ModuleBase_Operation*)),
476             SLOT(onResumed(ModuleBase_Operation*)));
477
478   return true;
479 }
480
481 void PartSet_WidgetSketchCreator::deactivate()
482 {
483   ModuleBase_WidgetSelector::deactivate();
484
485   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
486   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
487   if (aHidePreview)
488     XGUI_Tools::workshop(myWorkshop)->viewer()->update();
489
490 }
491
492 void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
493 {
494   SessionPtr aMgr = ModelAPI_Session::get();
495   bool aIsOp = aMgr->isOperation();
496   if (aIsOp) {
497     // in current implementation, all transactions are closed when resume happens
498     // so, this is a wrong case, which is not checked.
499     // To provide it, make correction in later rows about abort/undo transactions
500     return;
501   }
502   // Set visible only selection control
503   setVisibleSelectionControl(true);
504
505   // Validate the created sketch. If it is valid, it is set into the composite feature selection
506   // list, otherwise it is removed
507   CompositeFeaturePtr aCompFeature =
508     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
509   AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
510   if (aCompFeature->numberOfSubs() > 0) {
511     // set the sub feature to attribute selection list and check whether sketch is valid
512     const static std::string aNestedOpID("Set Sketch result into Selection list");
513     aMgr->startOperation(aNestedOpID, false); // false to not attach to Extrusion operation
514     setSketchObjectToList(aCompFeature, anAttrList);
515     aMgr->finishOperation();
516
517     if (!validateSelectionList()) {
518 #ifdef DEBUG_UNDO_INVALID_SKETCH
519       aMgr->undo(); // Extrusion modification parameters: setSketchObjectToList()
520       aMgr->undo(); /// Sketch creation
521 #else
522       aMgr->startOperation("Delete invalid Sketch feature", false);
523
524       // delete invalid sketch
525       CompositeFeaturePtr aSketchFeature =
526               std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
527       QObjectPtrList anObjects;
528       anObjects.append(aSketchFeature);
529
530       XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
531       aWorkshop->deleteFeatures(anObjects);
532
533       aMgr->finishOperation();
534 #endif
535     }
536   }
537   openExtrusionTransaction();
538
539   if (aCompFeature->numberOfSubs() == 0) {
540     // call activateWidget() of the parent to connect to the viewer seleciton
541     activateSelectionControl();
542   }
543   else {
544     // check if the created sketch is valid. If it is invalid, it will be deleted with warning else
545     /// the attribute selection list will be filled by result of this sketch.
546     setVisibleSelectionControl(false);
547
548     // Update value in attribute selection list
549     XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
550     XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
551     const QList<ModuleBase_ModelWidget*>& aWidgets = aPropertyPanel->modelWidgets();
552     ModuleBase_ModelWidget* aListWidget = 0;
553     foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
554       if (aWidget->attributeID() == myAttributeListID) {
555         aListWidget = aWidget;
556         break;
557       }
558     }
559     if (aListWidget) {
560       aListWidget->restoreValue();
561       aPropertyPanel->activateNextWidget(aListWidget);
562     }
563
564     // Hide sketcher result
565     CompositeFeaturePtr aSketchFeature =
566       std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
567     std::list<ResultPtr> aResults = aSketchFeature->results();
568     std::list<ResultPtr>::const_iterator aIt;
569     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
570       (*aIt)->setDisplayed(false);
571     }
572     aSketchFeature->setDisplayed(false);
573     static Events_Loop* aLoop = Events_Loop::loop();
574     aLoop->flush(aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY));
575
576     // Add Selected body were created the sketcher to list of selected objects
577     std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::OBJECTS_ID();
578     AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
579     if (aSelList.get()) {
580       DataPtr aData = aSketchFeature->data();
581       AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
582                                     (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
583       ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
584       if (aRes.get()) {
585         ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
586         AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
587         std::string aValidatorID;
588         Events_InfoMessage anError;
589         aSelList->append(aRes, GeomShapePtr());
590         if (aFactory->validate(anAttribute, aValidatorID, anError))
591           updateObject(aCompFeature);
592         else
593           aSelList->clear();
594       }
595     }
596   }
597   restoreValue();
598 }
599
600 bool PartSet_WidgetSketchCreator::validateSelectionList() const
601 {
602   AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
603
604   SessionPtr aMgr = ModelAPI_Session::get();
605   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
606   std::string aValidatorID;
607   Events_InfoMessage anError;
608   bool isValidPComposite = aFactory->validate(anAttrList, aValidatorID, anError);
609   if (!isValidPComposite) {
610     XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
611     // TODO(spo): translate
612     QMessageBox::question(aWorkshop->desktop(), tr("Apply current feature"),
613                   tr("Sketch is invalid and will be deleted.\nError: %1")
614                   .arg(anError.messageString().c_str()),
615                   QMessageBox::Ok);
616   }
617   return isValidPComposite;
618 }
619
620 void PartSet_WidgetSketchCreator::setSketchObjectToList(
621                             const CompositeFeaturePtr& theCompositeFeature,
622                             const AttributePtr& theAttribute)
623 {
624   if (!theCompositeFeature.get() || theCompositeFeature->numberOfSubs() != 1)
625     return;
626
627   AttributeSelectionListPtr aBaseObjectsSelectionList =
628                      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
629   if(!aBaseObjectsSelectionList.get() || aBaseObjectsSelectionList->isInitialized()) {
630     return;
631   }
632
633   FeaturePtr aSketchFeature = theCompositeFeature->subFeature(0);
634   if(!aSketchFeature.get() || aSketchFeature->results().empty()) {
635     return;
636   }
637
638   ResultPtr aSketchRes = aSketchFeature->results().front();
639   ResultConstructionPtr aConstruction =
640     std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
641   if(!aConstruction.get()) {
642     return;
643   }
644
645   if(aBaseObjectsSelectionList->size() == 0) {
646     aBaseObjectsSelectionList->append(aSketchRes, GeomShapePtr());
647   }
648 }
649
650 void PartSet_WidgetSketchCreator::setEnabledModelWidget(ModuleBase_ModelWidget* theModelWidget,
651                                                         const bool theEnabled)
652 {
653   QList<QWidget*> aMyControls = theModelWidget->getControls();
654   foreach(QWidget*  eachControl, aMyControls) {
655     eachControl->setEnabled(theEnabled);
656   }
657 }
658
659 void PartSet_WidgetSketchCreator::onSelectionTypeChanged()
660 {
661   // Clear current selection in order to avoid updating of object browser with obsolete indexes
662   // which can appear because of results deletetion after changing a type of selection
663   QString aSelectionType = myTypeCtrl->textValue();
664   QList<ModuleBase_ViewerPrsPtr> aEmptyList;
665   myWorkshop->setSelected(aEmptyList);
666
667   updateSelectionModesAndFilters(true);
668   myWorkshop->selectionActivate()->updateSelectionModes();
669
670   if (!myFeature)
671     return;
672
673   if (aSelectionType != "Faces") {
674     setVisibleSelectionControl(false);
675     myWorkshop->propertyPanel()->activateNextWidget();
676   }
677
678   /// store the selected type
679   AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
680   anAttrList->setSelectionType(aSelectionType.toStdString());
681   anAttrList->clear();
682
683   // update object is necessary to flush update signal. It leads to objects references map update
684   // and the operation presentation will not contain deleted items visualized as parameters of
685   // the feature.
686   updateObject(myFeature);
687   myWorkshop->propertyPanel()->activeWidget()->restoreValue();
688   myWorkshop->setSelected(getAttributeSelection());
689   // may be the feature's result is not displayed, but attributes should be
690   // hope that something is redisplayed by object updated
691   myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeArguments, true);
692 }