Salome HOME
Issue #2975: Do not select groups in all operations except operations on groups
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetMultiSelector.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 <ModuleBase_WidgetMultiSelector.h>
21
22 #include <GeomAPI_AISObject.h>
23
24 #include <ModuleBase_ActionIntParameter.h>
25 #include <ModuleBase_Definitions.h>
26 #include <ModuleBase_Events.h>
27 #include <ModuleBase_IconFactory.h>
28 #include <ModuleBase_IModule.h>
29 #include <ModuleBase_ISelection.h>
30 #include <ModuleBase_ISelectionActivate.h>
31 #include <ModuleBase_IPropertyPanel.h>
32 #include <ModuleBase_IViewer.h>
33 #include <ModuleBase_IWorkshop.h>
34 #include <ModuleBase_ListView.h>
35 #include <ModuleBase_ResultPrs.h>
36 #include <ModuleBase_Tools.h>
37 #include <ModuleBase_ViewerPrs.h>
38 #include <ModuleBase_WidgetShapeSelector.h>
39 #include <ModuleBase_ChoiceCtrl.h>
40 #include <ModuleBase_WidgetSelectionFilter.h>
41
42 #include <ModelAPI_Data.h>
43 #include <ModelAPI_Object.h>
44 #include <ModelAPI_AttributeSelectionList.h>
45 #include <ModelAPI_AttributeRefList.h>
46 #include <ModelAPI_AttributeRefAttrList.h>
47 #include <ModelAPI_Tools.h>
48 #include <ModelAPI_Events.h>
49
50 #include <Config_WidgetAPI.h>
51
52 #include <AIS_InteractiveObject.hxx>
53
54 #include <QGridLayout>
55 #include <QLabel>
56 #include <QListWidget>
57 #include <QObject>
58 #include <QString>
59 #include <QComboBox>
60 #include <QEvent>
61 #include <QApplication>
62 #include <QClipboard>
63 #include <QTimer>
64 #include <QMainWindow>
65 #include <QCheckBox>
66 #include <QPushButton>
67
68 #include <memory>
69 #include <string>
70
71 //#define DEBUG_UNDO_REDO
72
73 #ifdef DEBUG_UNDO_REDO
74 void printHistoryInfo(const QString& theMethodName, int theCurrentHistoryIndex,
75   QList<QList<std::shared_ptr<ModuleBase_ViewerPrs> > > theSelectedHistoryValues)
76 {
77   QStringList aSizes;
78   for (int i = 0; i < theSelectedHistoryValues.size(); i++)
79     aSizes.append(QString::number(theSelectedHistoryValues[i].size()));
80
81   std::cout << theMethodName.toStdString()
82             << "  current = " << theCurrentHistoryIndex
83             << " size(history) =  " << theSelectedHistoryValues.size()
84             << " (" << aSizes.join(", ").toStdString() << ")"
85             << std::endl;
86 }
87 #endif
88
89
90 QStringList getIconsList(const QStringList& theNames)
91 {
92   QStringList aIcons;
93   foreach (QString aName, theNames) {
94     QString aUName = aName.toUpper();
95     if ((aUName == "VERTICES") || (aUName == "VERTEX"))
96       aIcons << ":pictures/vertex32.png";
97     else if ((aUName == "EDGES") || (aUName == "EDGE"))
98       aIcons << ":pictures/edge32.png";
99     else if ((aUName == "FACES") || (aUName == "FACE"))
100       aIcons << ":pictures/face32.png";
101     else if ((aUName == "SOLIDS") || (aUName == "SOLID"))
102       aIcons << ":pictures/solid32.png";
103   }
104   return aIcons;
105 }
106
107 /// Stores default values of selected option (selection mode)
108 /// It is used only in case if myTypeCtrl is used
109 static QMap<std::string, std::string> defaultValues;
110
111
112 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
113                                                                ModuleBase_IWorkshop* theWorkshop,
114                                                                const Config_WidgetAPI* theData)
115 : ModuleBase_WidgetSelector(theParent, theWorkshop, theData),
116   myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1),
117   myIsFirst(true), myFiltersWgt(0)
118 {
119   std::string aPropertyTypes = theData->getProperty("shape_types");
120   QString aTypesStr = aPropertyTypes.c_str();
121   myShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts);
122   myIsUseChoice = theData->getBooleanAttribute("use_choice", false);
123
124   QString aAllowedList(theData->getProperty("allow_objects").c_str());
125   if (!aAllowedList.isEmpty())
126     myAllowedObjects = aAllowedList.split(' ', QString::SkipEmptyParts);
127
128   QVBoxLayout* aMainLay = new QVBoxLayout(this);
129   ModuleBase_Tools::adjustMargins(aMainLay);
130
131   QStringList aIconsList = getIconsList(myShapeTypes);
132   myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
133   myTypeCtrl->setLabel(tr("Type"));
134   myTypeCtrl->setValue(0);
135   aMainLay->addWidget(myTypeCtrl);
136   myDefMode = myShapeTypes.first().toStdString();
137
138   // There is no sense to parameterize list of types while we can not parameterize selection mode
139   // if the xml definition contains one type, the controls to select a type should not be shown
140   if (myShapeTypes.size() <= 1 || !myIsUseChoice) {
141     myTypeCtrl->setVisible(false);
142   }
143
144   QString aLabelText = translate(theData->getProperty("label"));
145   if (aLabelText.size() > 0) {
146     QWidget* aLabelWgt = new QWidget(this);
147     QHBoxLayout* aLabelLayout = new QHBoxLayout(aLabelWgt);
148     aLabelLayout->setContentsMargins(0, 0, 0, 0);
149     aMainLay->addWidget(aLabelWgt);
150
151     QLabel* aListLabel = new QLabel(aLabelText, this);
152     aLabelLayout->addWidget(aListLabel);
153     // if the xml definition contains one type, an information label
154     // should be shown near to the latest
155     if (myShapeTypes.size() <= 1) {
156       QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
157       if (!aLabelIcon.isEmpty()) {
158         QLabel* aSelectedLabel = new QLabel("", this);
159         aSelectedLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon));
160         aLabelLayout->addWidget(aSelectedLabel);
161         aLabelLayout->addStretch(1);
162       }
163     }
164   }
165
166   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
167   QString anObjName = QString::fromStdString(attributeID());
168   myListView = new ModuleBase_ListView(this, anObjName, aToolTip);
169   connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
170   connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
171   connect(myListView, SIGNAL(listActivated()), SLOT(onListActivated()));
172
173   aMainLay->addWidget(myListView->getControl());
174   connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
175
176   std::string aUseFilters = theData->getProperty("use_filters");
177   if (aUseFilters.length() > 0) {
178     QWidget* aFltrWgt = new QWidget(this);
179     QHBoxLayout* aFltrLayout = new QHBoxLayout(aFltrWgt);
180
181     myFiltersWgt = new ModuleBase_FilterStarter(aUseFilters.c_str(), aFltrWgt, theWorkshop);
182     aFltrLayout->addWidget(myFiltersWgt);
183
184     aFltrLayout->addStretch();
185
186     QPushButton* aShowBtn = new QPushButton(tr("Show only"), aFltrWgt);
187     aShowBtn->setCheckable(true);
188     aShowBtn->setChecked(false);
189     connect(aShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
190     aFltrLayout->addWidget(aShowBtn);
191
192     aMainLay->addWidget(aFltrWgt);
193   }
194
195   bool aSameTop = theData->getBooleanAttribute("same_topology", false);
196   if (aSameTop) {
197     myGeomCheck = new QCheckBox(tr("Add elements that share the same topology"), this);
198     aMainLay->addWidget(myGeomCheck);
199     connect(myGeomCheck, SIGNAL(toggled(bool)), SLOT(onSameTopology(bool)));
200   }
201   else
202     myGeomCheck = 0;
203
204   myIsNeutralPointClear = theData->getBooleanAttribute("clear_in_neutral_point", true);
205   if (myShapeTypes.size() > 1 || myIsUseChoice) {
206     if (defaultValues.contains(myFeatureId + attributeID())) {
207       myDefMode = defaultValues[myFeatureId + attributeID()];
208       myTypeCtrl->setValue(myDefMode.c_str());
209     }
210   }
211 }
212
213 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
214 {
215 }
216
217 //********************************************************************
218 void ModuleBase_WidgetMultiSelector::activateCustom()
219 {
220   ModuleBase_WidgetSelector::activateCustom();
221
222   ModuleBase_IModule* aModule = myWorkshop->module();
223   aModule->activateCustomPrs(myFeature,
224                             ModuleBase_IModule::CustomizeHighlightedObjects, true);
225   clearSelectedHistory();
226   if (myAllowedObjects.length() > 0) {
227     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter);
228     if (!aFilter.IsNull()) {
229       Handle(ModuleBase_ShapeDocumentFilter) aDocFilter =
230         Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter);
231       if (!aDocFilter.IsNull()) {
232         QStringList aSelFilters = aDocFilter->nonSelectableTypes();
233         foreach(QString aType, aSelFilters) {
234           if (aSelFilters.contains(aType)) {
235             aDocFilter->removeNonSelectableType(aType);
236             myTmpAllowed.append(aType);
237           }
238         }
239       }
240     }
241   }
242 }
243
244 //********************************************************************
245 void ModuleBase_WidgetMultiSelector::deactivate()
246 {
247   myWorkshop->module()->enableCustomModes();
248
249   ModuleBase_WidgetSelector::deactivate();
250   if (myVisibleObjects.size())
251     onShowOnly(false);
252
253   myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true);
254   clearSelectedHistory();
255   if (myTmpAllowed.length() > 0) {
256     ModuleBase_IModule* aModule = myWorkshop->module();
257     Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter);
258     if (!aFilter.IsNull()) {
259       Handle(ModuleBase_ShapeDocumentFilter) aDocFilter =
260         Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter);
261       if (!aDocFilter.IsNull()) {
262         foreach(QString aType, myTmpAllowed) {
263           aDocFilter->addNonSelectableType(aType);
264         }
265       }
266     }
267     myTmpAllowed.clear();
268   }
269 }
270
271 //********************************************************************
272 void ModuleBase_WidgetMultiSelector::updateAfterDeactivation()
273 {
274   // restore previous Undo/Redo workshop state
275   myWorkshop->updateCommandStatus();
276 }
277
278 //********************************************************************
279 void ModuleBase_WidgetMultiSelector::updateAfterActivation()
280 {
281   // fill Undo/Redo actions with current information
282   myWorkshop->updateCommandStatus();
283 }
284
285 //********************************************************************
286 bool ModuleBase_WidgetMultiSelector::storeValueCustom()
287 {
288   // the value is stored on the selection changed signal processing
289   // A rare case when plugin was not loaded.
290   if (!myFeature)
291     return false;
292
293   AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
294   std::string aType = anAttribute->attributeType();
295   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
296     AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
297     std::string aMode = myTypeCtrl->textValue().toStdString();
298     if (myTypeCtrl->isVisible() && myIsFirst && (!myDefMode.empty()))
299       aMode = myDefMode;
300
301     aSelectionListAttr->setSelectionType(aMode);
302     myIsFirst = false;
303   }
304   return true;
305 }
306
307 //********************************************************************
308 bool ModuleBase_WidgetMultiSelector::restoreValueCustom()
309 {
310   // A rare case when plugin was not loaded.
311   if (!myFeature)
312     return false;
313
314   AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
315   AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
316   std::string aType = anAttribute->attributeType();
317   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
318     // Restore shape type
319     std::string aSelectionType = aSelectionListAttr->selectionType().c_str();
320     if (!aSelectionType.empty()) {
321       setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionType.c_str()));
322       myDefMode = aSelectionType;
323       myIsFirst = false;
324     }
325   }
326   if (myGeomCheck)
327     myGeomCheck->setChecked(aSelectionListAttr->isGeometricalSelection());
328   updateSelectionList();
329   return true;
330 }
331
332 //********************************************************************
333 bool ModuleBase_WidgetMultiSelector::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
334                                                   const bool theToValidate)
335 {
336   if (myIsSetSelectionBlocked)
337     return false;
338
339   AttributeSelectionListPtr aSelectionListAttr;
340   if (attribute()->attributeType() == ModelAPI_AttributeSelectionList::typeId())
341     aSelectionListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(attribute());
342   if (aSelectionListAttr.get())
343     aSelectionListAttr->cashValues(true);
344
345   /// remove unused objects from the model attribute.
346   /// It should be performed before new attributes append.
347   bool isDone = removeUnusedAttributeObjects(theValues);
348
349   QList<ModuleBase_ViewerPrsPtr> anInvalidValues;
350   QList<ModuleBase_ViewerPrsPtr> anAttributeValues;
351   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
352   for (; anIt != aLast; anIt++) {
353     ModuleBase_ViewerPrsPtr aValue = *anIt;
354     // do not validate and append to attribute selection presentation if it exists in the attribute
355     ObjectPtr anObject;
356     GeomShapePtr aShape;
357     getGeomSelection(aValue, anObject, aShape);
358     if (ModuleBase_Tools::hasObject(attribute(), anObject, aShape, myWorkshop, myIsInValidate)) {
359       anAttributeValues.append(aValue);
360       continue;
361     }
362     if (theToValidate && !isValidInFilters(aValue))
363       anInvalidValues.append(aValue);
364   }
365   bool aHasInvalidValues = anInvalidValues.size() > 0;
366
367   for (anIt = theValues.begin(); anIt != aLast; anIt++) {
368     ModuleBase_ViewerPrsPtr aValue = *anIt;
369     bool aProcessed = false;
370     if ((aHasInvalidValues && anInvalidValues.contains(aValue)) ||
371         anAttributeValues.contains(aValue))
372       continue;
373     aProcessed = setSelectionCustom(aValue); /// it is not optimal as hasObject() is already checked
374     // if there is at least one set, the result is true
375     isDone = isDone || aProcessed;
376   }
377   // Check the selection with validators
378   QString aError = getError();
379   if (aError.length() > 0) {
380     aSelectionListAttr->clear();
381     isDone = false;
382   }
383   // updateObject - to update/redisplay feature
384   // it is commented in order to perfom it outside the method
385   //if (isDone) {
386     //updateObject(myFeature);
387     // this emit is necessary to call store/restore method an restore type of selection
388     //emit valuesChanged();
389   //}
390
391   if (aSelectionListAttr.get())
392     aSelectionListAttr->cashValues(false);
393
394   theValues.clear();
395   if (!anInvalidValues.empty())
396     theValues.append(anInvalidValues);
397
398   if (isDone) // may be the feature's result is not displayed, but attributes should be
399     myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
400                              true);/// hope that something is redisplayed by object updated
401
402   return isDone;
403 }
404
405 //********************************************************************
406 void ModuleBase_WidgetMultiSelector::getHighlighted(QList<ModuleBase_ViewerPrsPtr>& theValues)
407 {
408   std::set<int> anAttributeIds;
409   getSelectedAttributeIndices(anAttributeIds);
410   if (!anAttributeIds.empty())
411     convertIndicesToViewerSelection(anAttributeIds, theValues);
412 }
413
414 //********************************************************************
415 bool ModuleBase_WidgetMultiSelector::canProcessAction(ModuleBase_ActionType theActionType,
416                                                       bool& isActionEnabled)
417 {
418   isActionEnabled = false;
419   bool aCanProcess = false;
420   switch (theActionType) {
421     case ActionUndo:
422     case ActionRedo: {
423       aCanProcess = true;
424       isActionEnabled = theActionType == ActionUndo ? myCurrentHistoryIndex > 0
425           : (mySelectedHistoryValues.size() > 0 &&
426              myCurrentHistoryIndex < mySelectedHistoryValues.size() - 1);
427     }
428     break;
429     default:
430       aCanProcess = ModuleBase_WidgetSelector::canProcessAction(theActionType, isActionEnabled);
431     break;
432   }
433   return aCanProcess;
434 }
435
436 //********************************************************************
437 bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType,
438                                                    const ActionParamPtr& theParam)
439 {
440   switch (theActionType) {
441     case ActionUndo:
442     case ActionRedo: {
443       ActionIntParamPtr aParam =
444         std::dynamic_pointer_cast<ModuleBase_ActionIntParameter>(theParam);
445       int aNb = aParam->value();
446       if (theActionType == ActionUndo)
447         myCurrentHistoryIndex -= aNb;
448       else
449         myCurrentHistoryIndex += aNb;
450       QList<ModuleBase_ViewerPrsPtr> aSelected = mySelectedHistoryValues[myCurrentHistoryIndex];
451       // equal vertices should not be used here
452       ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected);
453       bool isDone = setSelection(aSelected,
454                                  false /*need not validate because values already was in list*/);
455       updateOnSelectionChanged(isDone);
456
457       myWorkshop->updateCommandStatus();
458 #ifdef DEBUG_UNDO_REDO
459       printHistoryInfo(QString("processAction %1").arg(theActionType == ActionUndo ? "Undo"
460         : "Redo"), myCurrentHistoryIndex, mySelectedHistoryValues);
461 #endif
462       return true;
463     }
464     default:
465       return ModuleBase_ModelWidget::processAction(theActionType, theParam);
466   }
467 }
468
469 //********************************************************************
470 bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
471 {
472   bool aValid = ModuleBase_WidgetSelector::isValidSelectionCustom(thePrs);
473   if (aValid) {
474     ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
475     if (!aResult.get()) { // In case if a feature was selected
476       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(thePrs->object());
477       if (aFeature.get())
478         aResult = aFeature->firstResult();
479     }
480     aValid = aResult.get() != NULL;
481     if (aValid) {
482       if (myFeature) {
483         // We can not select a result of our feature
484         std::list<ResultPtr> aResults;
485         ModelAPI_Tools::allResults(myFeature, aResults);
486         std::list<ResultPtr>::const_iterator aIt;
487         bool isSkipSelf = false;
488         for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
489           if ((*aIt) == aResult) {
490             isSkipSelf = true;
491             break;
492           }
493         }
494         if (isSkipSelf)
495           aValid = false;
496       }
497     }
498   }
499   return aValid;
500 }
501
502 //********************************************************************
503 bool ModuleBase_WidgetMultiSelector::processDelete()
504 {
505   appendFirstSelectionInHistory();
506
507   // find attribute indices to delete
508   std::set<int> anAttributeIds;
509   getSelectedAttributeIndices(anAttributeIds);
510
511   QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
512
513   // refill attribute by the items which indices are not in the list of ids
514   bool aDone = false;
515   DataPtr aData = myFeature->data();
516   AttributePtr anAttribute = aData->attribute(attributeID());
517   std::string aType = anAttribute->attributeType();
518   aDone = !anAttributeIds.empty();
519   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
520     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
521     aSelectionListAttr->remove(anAttributeIds);
522
523   }
524   else if (aType == ModelAPI_AttributeRefList::typeId()) {
525     AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
526     aRefListAttr->remove(anAttributeIds);
527   }
528   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
529     AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
530     aRefAttrListAttr->remove(anAttributeIds);
531   }
532
533   if (aDone) {
534     // update object is necessary to flush update signal. It leads to objects references map update
535     // and the operation presentation will not contain deleted items visualized as parameters of
536     // the feature.
537     updateObject(myFeature);
538
539     restoreValue();
540     myWorkshop->setSelected(getAttributeSelection());
541
542     // may be the feature's result is not displayed, but attributes should be
543     myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
544                               true); /// hope that something is redisplayed by object updated
545   }
546
547   // Restore selection
548   myListView->restoreSelection(anIndices);
549
550   appendSelectionInHistory();
551   return true/*aDone*/; // following #2438 Delete should be processed even if nothing is delete
552 }
553
554 //********************************************************************
555 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
556 {
557   QList<QWidget*> result;
558   result << myListView->getControl();
559   return result;
560 }
561
562 //********************************************************************
563 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
564 {
565   // Clear current selection in order to avoid updating of object browser with obsolete indexes
566   // which can appear because of results deletetion after changing a type of selection
567   QString aSelectionType = myTypeCtrl->textValue();
568   QList<ModuleBase_ViewerPrsPtr> aEmptyList;
569   myWorkshop->setSelected(aEmptyList);
570
571   updateSelectionModesAndFilters(true);
572   myWorkshop->selectionActivate()->updateSelectionModes();
573
574   if (!myFeature)
575     return;
576   /// store the selected type
577   AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
578   std::string aType = anAttribute->attributeType();
579   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
580     AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
581     aSelectionListAttr->setSelectionType(aSelectionType.toStdString());
582   }
583
584   // clear attribute values
585   DataPtr aData = myFeature->data();
586   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
587     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
588     aSelectionListAttr->clear();
589   }
590   else if (aType == ModelAPI_AttributeRefList::typeId()) {
591     AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
592     aRefListAttr->clear();
593   }
594   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
595     AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
596     aRefAttrListAttr->clear();
597   }
598
599   // update object is necessary to flush update signal. It leads to objects references map update
600   // and the operation presentation will not contain deleted items visualized as parameters of
601   // the feature.
602   updateObject(myFeature);
603   restoreValue();
604   myWorkshop->setSelected(getAttributeSelection());
605   // may be the feature's result is not displayed, but attributes should be
606   myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
607                             true); /// hope that something is redisplayed by object updated
608   // clear history should follow after set selected to do not increase history by setSelected
609   clearSelectedHistory();
610
611   if (myWorkshop->propertyPanel()->activeWidget() != this)
612     myWorkshop->propertyPanel()->activateWidget(this);
613 }
614
615 //********************************************************************
616 bool ModuleBase_WidgetMultiSelector::processSelection()
617 {
618   if (!myIsNeutralPointClear) {
619     QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
620     // do not clear selected object
621     if (aSelected.size() == 0) {
622       if (!getAttributeSelection().empty()) {
623         // Restore selection in the viewer by the attribute selection list
624         // it should be postponed to exit from the selectionChanged processing
625         static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
626         ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
627         Events_Loop::loop()->flush(anEvent);
628         return true;
629       }
630     }
631   }
632   appendFirstSelectionInHistory();
633   bool aDone = ModuleBase_WidgetSelector::processSelection();
634   appendSelectionInHistory();
635   return aDone;
636 }
637
638 void ModuleBase_WidgetMultiSelector::appendFirstSelectionInHistory()
639 {
640   if (mySelectedHistoryValues.empty()) {
641     myCurrentHistoryIndex++;
642     mySelectedHistoryValues.append(getAttributeSelection());
643
644 #ifdef DEBUG_UNDO_REDO
645     printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues);
646 #endif
647   }
648 }
649
650 void ModuleBase_WidgetMultiSelector::appendSelectionInHistory()
651 {
652   while (myCurrentHistoryIndex != mySelectedHistoryValues.count() - 1)
653     mySelectedHistoryValues.removeLast();
654
655   QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
656   myCurrentHistoryIndex++;
657   mySelectedHistoryValues.append(aSelected);
658   myWorkshop->updateCommandStatus();
659
660 #ifdef DEBUG_UNDO_REDO
661   printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues);
662 #endif
663 }
664
665 void ModuleBase_WidgetMultiSelector::clearSelectedHistory()
666 {
667   mySelectedHistoryValues.clear();
668   myCurrentHistoryIndex = -1;
669   myWorkshop->updateCommandStatus();
670
671 #ifdef DEBUG_UNDO_REDO
672   printHistoryInfo("clearSelectedHistory", myCurrentHistoryIndex, mySelectedHistoryValues);
673 #endif
674 }
675
676 void ModuleBase_WidgetMultiSelector::updateFocus()
677 {
678   // Set focus to List control in order to make possible
679   // to use Tab key for transfer the focus to next widgets
680   ModuleBase_Tools::setFocus(myListView->getControl(),
681                              "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()");
682 }
683
684 //********************************************************************
685 void ModuleBase_WidgetMultiSelector::updateSelectionName()
686 {
687 }
688
689 //********************************************************************
690 void ModuleBase_WidgetMultiSelector::updateOnSelectionChanged(const bool theDone)
691 {
692   if (myIsSetSelectionBlocked)
693     return;
694   ModuleBase_WidgetSelector::updateOnSelectionChanged(theDone);
695
696   // according to #2154 we need to update OB selection when selection in the viewer happens
697   // it is important to flush sinchronize selection signal after flush of Update/Create/Delete.
698   // because we need that Object Browser has been already updated when synchronize happens.
699
700   // Restore selection in the viewer by the attribute selection list
701   // it is possible that diring selection attribute filling, selection in Object Browser
702   // is changed(some items were removed/added) and as result, selection in the viewer
703   // differs from the selection come to this method. By next rows, we restore selection
704   // in the viewer according to content of selection attribute. Case is Edge selection in Group
705   myIsSetSelectionBlocked = true;
706   static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
707   ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
708   Events_Loop::loop()->flush(anEvent);
709   myIsSetSelectionBlocked = false;
710 }
711
712 //********************************************************************
713 QIntList ModuleBase_WidgetMultiSelector::shapeTypes() const
714 {
715   QIntList aShapeTypes;
716
717   if (myShapeTypes.length() > 1 && myIsUseChoice) {
718     aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCtrl->textValue()));
719   }
720   else {
721     foreach (QString aType, myShapeTypes) {
722       aShapeTypes.append(ModuleBase_Tools::shapeType(aType));
723     }
724   }
725   return aShapeTypes;
726 }
727
728 //********************************************************************
729 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const int theShapeType)
730 {
731   QString aShapeTypeName;
732
733   int idx = 0;
734   foreach (QString aShapeTypeName, myShapeTypes) {
735     int aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
736     if(aRefType == theShapeType && idx != myTypeCtrl->value()) {
737       updateSelectionModesAndFilters(false);
738       bool isBlocked = myTypeCtrl->blockSignals(true);
739       myTypeCtrl->setValue(idx);
740       myTypeCtrl->blockSignals(isBlocked);
741       updateSelectionModesAndFilters(true);
742       break;
743     }
744     idx++;
745   }
746 }
747
748 QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetMultiSelector::getAttributeSelection() const
749 {
750   QList<ModuleBase_ViewerPrsPtr> aSelected;
751   convertIndicesToViewerSelection(std::set<int>(), aSelected);
752   return aSelected;
753 }
754
755 //********************************************************************
756 void ModuleBase_WidgetMultiSelector::updateSelectionList()
757 {
758   myListView->getControl()->clear();
759
760   DataPtr aData = myFeature->data();
761   AttributePtr anAttribute = aData->attribute(attributeID());
762   std::string aType = anAttribute->attributeType();
763   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
764     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
765     for (int i = 0; i < aSelectionListAttr->size(); i++) {
766       AttributeSelectionPtr aAttr = aSelectionListAttr->value(i);
767       myListView->addItem(aAttr->namingName().c_str(), i);
768     }
769   }
770   else if (aType == ModelAPI_AttributeRefList::typeId()) {
771     AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
772     for (int i = 0; i < aRefListAttr->size(); i++) {
773       ObjectPtr anObject = aRefListAttr->object(i);
774       if (anObject.get()) {
775         myListView->addItem(anObject->data()->name().c_str(), i);
776       }
777     }
778   }
779   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
780     AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
781     for (int i = 0; i < aRefAttrListAttr->size(); i++) {
782       AttributePtr anAttribute = aRefAttrListAttr->attribute(i);
783       QString aName;
784       if (anAttribute.get()) {
785         std::string anAttrName = ModuleBase_Tools::generateName(anAttribute, myWorkshop);
786         aName = QString::fromStdString(anAttrName);
787       }
788       else {
789         ObjectPtr anObject = aRefAttrListAttr->object(i);
790         if (anObject.get()) {
791           aName = anObject->data()->name().c_str();
792         }
793       }
794       myListView->addItem(aName, i);
795     }
796   }
797
798   // We have to call repaint because sometimes the List control is not updated
799   myListView->getControl()->repaint();
800 }
801
802 //********************************************************************
803 std::string ModuleBase_WidgetMultiSelector::validatorType(const QString& theType) const
804 {
805   std::string aType;
806
807   if (theType == "Vertices")
808     aType = "vertex";
809   else if (theType == "Edges")
810     aType = "edge";
811   else if (theType == "Faces")
812     aType = "face";
813   else if (theType == "Solids")
814     aType = "solid";
815
816   return aType;
817 }
818
819 //********************************************************************
820 void ModuleBase_WidgetMultiSelector::clearSelection()
821 {
822   bool isClearInNeutralPoint = myIsNeutralPointClear;
823   myIsNeutralPointClear = true;
824
825   QList<ModuleBase_ViewerPrsPtr> anEmptyList;
826   // This method will call Selection changed event which will call onSelectionChanged
827   // To clear mySelection, myListView and storeValue()
828   // So, we don't need to call it
829   myWorkshop->setSelected(anEmptyList);
830
831   myIsNeutralPointClear = isClearInNeutralPoint;
832 }
833
834 //********************************************************************
835 void ModuleBase_WidgetMultiSelector::onDeleteItem()
836 {
837   processDelete();
838 }
839
840 //********************************************************************
841 void ModuleBase_WidgetMultiSelector::onListSelection()
842 {
843   myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
844                                         true);
845 }
846
847 //********************************************************************
848 void ModuleBase_WidgetMultiSelector::getSelectedAttributeIndices(std::set<int>& theAttributeIds)
849 {
850   myListView->getSelectedIndices(theAttributeIds);
851 }
852
853 void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::set<int> theAttributeIds,
854                                                    QList<ModuleBase_ViewerPrsPtr>& theValues) const
855 {
856   if(myFeature.get() == NULL)
857     return;
858
859   DataPtr aData = myFeature->data();
860   AttributePtr anAttribute = aData->attribute(attributeID());
861   std::string aType = anAttribute->attributeType();
862   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
863     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
864     for (int i = 0; i < aSelectionListAttr->size(); i++) {
865       // filter by attribute indices only if the container is not empty otherwise return all items
866       if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end())
867         continue;
868       AttributeSelectionPtr anAttr = aSelectionListAttr->value(i);
869       ObjectPtr anObject = anAttr->contextObject();
870       if (anObject.get())
871         theValues.append(std::shared_ptr<ModuleBase_ViewerPrs>(
872                new ModuleBase_ViewerPrs(anObject, anAttr->value(), NULL)));
873     }
874   }
875   else if (aType == ModelAPI_AttributeRefList::typeId()) {
876     AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
877     for (int i = 0; i < aRefListAttr->size(); i++) {
878       // filter by attribute indices only if the container is not empty otherwise return all items
879       if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end())
880         continue;
881       ObjectPtr anObject = aRefListAttr->object(i);
882       if (anObject.get()) {
883         theValues.append(std::shared_ptr<ModuleBase_ViewerPrs>(
884                new ModuleBase_ViewerPrs(anObject, GeomShapePtr(), NULL)));
885       }
886     }
887   }
888   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
889     AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
890     for (int i = 0; i < aRefAttrListAttr->size(); i++) {
891       // filter by attribute indices only if the container is not empty otherwise return all items
892       if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end())
893         continue;
894       ObjectPtr anObject = aRefAttrListAttr->object(i);
895       if (!anObject.get())
896         continue;
897       TopoDS_Shape aShape;
898       AttributePtr anAttribute = aRefAttrListAttr->attribute(i);
899       if (anAttribute.get()) {
900         GeomShapePtr aGeomShape = ModuleBase_Tools::getShape(anAttribute, myWorkshop);
901         theValues.append(std::shared_ptr<ModuleBase_ViewerPrs>(
902                new ModuleBase_ViewerPrs(anObject, aGeomShape, NULL)));
903       }
904     }
905   }
906 }
907
908 bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects
909                                                  (QList<ModuleBase_ViewerPrsPtr>& theValues)
910 {
911   bool isDone = false;
912
913   std::map<ObjectPtr, std::set<GeomShapePtr> > aGeomSelection = convertSelection(theValues);
914   DataPtr aData = myFeature->data();
915   AttributePtr anAttribute = aData->attribute(attributeID());
916   std::string aType = anAttribute->attributeType();
917   std::set<GeomShapePtr> aShapes;
918   std::set<int> anIndicesToBeRemoved;
919   FeaturePtr aFeature;
920   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
921     // iteration through data model to find not selected elements to remove them
922     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
923     for (int i = 0; i < aSelectionListAttr->size(); i++) {
924       AttributeSelectionPtr anAttr = aSelectionListAttr->value(i);
925       //aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->contextObject());
926       //if (!aFeature.get()) { // Feature can not be found as geometry selection
927         bool aFound = findInSelection(
928           anAttr->contextObject(), anAttr->value(), aGeomSelection, myWorkshop);
929         if (!aFound)
930           anIndicesToBeRemoved.insert(i);
931 //      }
932     }
933     isDone = anIndicesToBeRemoved.size() > 0;
934     if (isDone)
935       aSelectionListAttr->remove(anIndicesToBeRemoved);
936   }
937   else if (aType == ModelAPI_AttributeRefList::typeId()) {
938     AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
939     for (int i = 0; i < aRefListAttr->size(); i++) {
940       ObjectPtr anObject = aRefListAttr->object(i);
941       if (anObject.get()) {
942         bool aFound = findInSelection(anObject, GeomShapePtr(), aGeomSelection,
943                                       myWorkshop);
944         if (!aFound)
945           anIndicesToBeRemoved.insert(i);
946       }
947     }
948     isDone = anIndicesToBeRemoved.size() > 0;
949     aRefListAttr->remove(anIndicesToBeRemoved);
950   }
951   else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
952     std::set<AttributePtr> anAttributes;
953     QList<ModuleBase_ViewerPrsPtr>::const_iterator
954       anIt = theValues.begin(), aLast = theValues.end();
955     ObjectPtr anObject;
956     GeomShapePtr aShape;
957     for (; anIt != aLast; anIt++) {
958       ModuleBase_ViewerPrsPtr aPrs = *anIt;
959       getGeomSelection(aPrs, anObject, aShape);
960       AttributePtr anAttr = myWorkshop->module()->findAttribute(anObject, aShape);
961       if (anAttr.get() && anAttributes.find(anAttr) == anAttributes.end())
962         anAttributes.insert(anAttr);
963     }
964
965     AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
966     for (int i = 0; i < aRefAttrListAttr->size(); i++) {
967       bool aFound = false;
968       if (aRefAttrListAttr->isAttribute(i)) {
969         AttributePtr anAttribute = aRefAttrListAttr->attribute(i);
970         aFound = anAttributes.find(anAttribute) != anAttributes.end();
971       }
972       else {
973         aFound = findInSelection(aRefAttrListAttr->object(i), GeomShapePtr(), aGeomSelection,
974                                  myWorkshop);
975       }
976       if (!aFound)
977         anIndicesToBeRemoved.insert(i);
978     }
979     isDone = anIndicesToBeRemoved.size() > 0;
980     aRefAttrListAttr->remove(anIndicesToBeRemoved);
981   }
982
983   return isDone;
984 }
985
986 std::map<ObjectPtr, std::set<GeomShapePtr> > ModuleBase_WidgetMultiSelector::convertSelection
987                                                      (QList<ModuleBase_ViewerPrsPtr>& theValues)
988 {
989   // convert prs list to objects map
990   std::map<ObjectPtr, std::set<GeomShapePtr> > aGeomSelection;
991   std::set<GeomShapePtr> aShapes;
992   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
993   ObjectPtr anObject;
994   GeomShapePtr aShape;
995   GeomShapePtr anEmptyShape(new GeomAPI_Shape());
996   for (; anIt != aLast; anIt++) {
997     ModuleBase_ViewerPrsPtr aPrs = *anIt;
998     getGeomSelection(aPrs, anObject, aShape);
999     aShapes.clear();
1000     if (aGeomSelection.find(anObject) != aGeomSelection.end()) // found
1001       aShapes = aGeomSelection[anObject];
1002     // we need to know if there was an empty shape in selection for the object
1003     if (!aShape.get())
1004       aShape = anEmptyShape;
1005     if (aShape.get() && aShapes.find(aShape) == aShapes.end()) // not found
1006       aShapes.insert(aShape);
1007     aGeomSelection[anObject] = aShapes;
1008   }
1009   return aGeomSelection;
1010 }
1011
1012 bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject,
1013                               GeomShapePtr theShape,
1014                               const std::map<ObjectPtr, std::set<GeomShapePtr> >& theGeomSelection,
1015                               ModuleBase_IWorkshop* theWorkshop)
1016 {
1017   if (!theObject.get())
1018     return false;
1019   // issue #2154: we should not remove from list objects hidden in the viewer if selection
1020   // was done with SHIFT button
1021   if (theWorkshop->hasSHIFTPressed() && !theObject->isDisplayed())
1022     return true;
1023
1024   bool aFound = false;
1025   GeomShapePtr aShape = theShape;
1026   if (!aShape.get()) {
1027     // #2429 (the preselection of a sketch is not taken into account)
1028     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1029     if (aResult.get())
1030       aShape = aResult->shape();
1031   }
1032   if (theGeomSelection.find(theObject) != theGeomSelection.end()) {// found
1033     const std::set<GeomShapePtr>& aShapes = theGeomSelection.at(theObject);
1034     std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
1035     for (; anIt != aLast && !aFound; anIt++) {
1036       GeomShapePtr aCShape = *anIt;
1037       if (aCShape.get())
1038       {
1039         // treat shape equal to context as null: 2219, keep order of shapes in list
1040         if (aCShape->isNull()) { // in selection, shape of result is equal to selected shape
1041           // if so, here we need to check shape of result
1042           ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
1043           if (aResult.get())
1044             aCShape = aResult->shape();
1045         }
1046         aFound = aCShape->isSame(aShape);
1047       }
1048     }
1049   }
1050
1051   // issue #2903: (Possibility to hide faces) - check whether given shape is a hidden sub-shape
1052   if (!aFound && theShape.get() && theWorkshop->hasSHIFTPressed() && theObject->isDisplayed()) {
1053     AISObjectPtr anAIS = theWorkshop->findPresentation(theObject);
1054     if (anAIS.get() != NULL) {
1055       Handle(AIS_InteractiveObject) anAISIO = anAIS->impl<Handle(AIS_InteractiveObject)>();
1056
1057       Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO);
1058       if (!aResultPrs.IsNull() && aResultPrs->isSubShapeHidden(theShape->impl<TopoDS_Shape>()))
1059         return true;
1060     }
1061   }
1062
1063   return aFound;
1064 }
1065
1066 QList<ActionInfo>
1067   ModuleBase_WidgetMultiSelector::actionsList(ModuleBase_ActionType theActionType) const
1068 {
1069   QList<ActionInfo> aList;
1070   if (myCurrentHistoryIndex > -1) {
1071     int i = 0;
1072     QString aTitle("Selection %1 items");
1073     QString aTit("Selection %1 item");
1074     QIcon aIcon(":pictures/selection.png");
1075     int aNb;
1076     switch (theActionType) {
1077     case ActionUndo:
1078       i = 1;
1079       while (i <= myCurrentHistoryIndex) {
1080         aNb = mySelectedHistoryValues.at(i).count();
1081         if (aNb == 1) {
1082           ActionInfo aInfo(aIcon, aTit.arg(aNb));
1083           aList.insert(0, aInfo);
1084         } else {
1085           ActionInfo aInfo(aIcon, aTitle.arg(aNb));
1086           aList.insert(0, aInfo);
1087         }
1088         i++;
1089       }
1090       break;
1091     case ActionRedo:
1092       i = mySelectedHistoryValues.length() - 1;
1093       while (i > myCurrentHistoryIndex) {
1094         aNb = mySelectedHistoryValues.at(i).count();
1095         if (aNb == 1) {
1096           ActionInfo aInfo(aIcon, aTit.arg(mySelectedHistoryValues.at(i).count()));
1097           aList.insert(0, aInfo);
1098         } else {
1099           ActionInfo aInfo(aIcon, aTitle.arg(mySelectedHistoryValues.at(i).count()));
1100           aList.insert(0, aInfo);
1101         }
1102         i--;
1103       }
1104       break;
1105     }
1106   }
1107   return aList;
1108 }
1109
1110
1111 void ModuleBase_WidgetMultiSelector::onFeatureAccepted()
1112 {
1113   defaultValues[myFeatureId + attributeID()] = myDefMode;
1114 }
1115
1116 void ModuleBase_WidgetMultiSelector::onListActivated()
1117 {
1118   //focusTo();
1119   emitFocusInWidget();
1120 }
1121
1122 void ModuleBase_WidgetMultiSelector::onSameTopology(bool theOn)
1123 {
1124   AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
1125   std::string aType = anAttribute->attributeType();
1126   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
1127     AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
1128     aSelectionListAttr->setGeometricalSelection(theOn);
1129     updateObject(myFeature);
1130   }
1131 }
1132
1133 void ModuleBase_WidgetMultiSelector::onShowOnly(bool theChecked)
1134 {
1135   std::list<ResultPtr> aResults = myFeature->results();
1136    std::list<ResultPtr>::const_iterator aIt;
1137   if (theChecked) {
1138     myVisibleObjects = myWorkshop->displayedObjects();
1139     for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
1140       myVisibleObjects.removeAll(*aIt);
1141     }
1142     myWorkshop->module()->disableCustomMode(ModuleBase_IModule::CustomizeArguments);
1143   }
1144   else
1145     myWorkshop->module()->enableCustomModes();
1146
1147   foreach(ObjectPtr aObj, myVisibleObjects) {
1148     aObj->setDisplayed(!theChecked);
1149   }
1150
1151   if (!theChecked) {
1152     // Hide and show the group result in order to make it above all objects
1153     bool aOldState = myWorkshop->enableUpdateViewer(false);
1154     for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
1155       (*aIt)->setDisplayed(false);
1156     }
1157     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1158     for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
1159       (*aIt)->setDisplayed(true);
1160     }
1161     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1162     myWorkshop->enableUpdateViewer(aOldState);
1163
1164     myVisibleObjects.clear();
1165   } else
1166     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
1167 }