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