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