1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <ModuleBase_WidgetMultiSelector.h>
23 #include <ModuleBase_ActionIntParameter.h>
24 #include <ModuleBase_Definitions.h>
25 #include <ModuleBase_Events.h>
26 #include <ModuleBase_IconFactory.h>
27 #include <ModuleBase_IModule.h>
28 #include <ModuleBase_ISelection.h>
29 #include <ModuleBase_ISelectionActivate.h>
30 #include <ModuleBase_IPropertyPanel.h>
31 #include <ModuleBase_IViewer.h>
32 #include <ModuleBase_IWorkshop.h>
33 #include <ModuleBase_ListView.h>
34 #include <ModuleBase_Tools.h>
35 #include <ModuleBase_ViewerPrs.h>
36 #include <ModuleBase_WidgetShapeSelector.h>
37 #include <ModuleBase_ChoiceCtrl.h>
39 #include <ModelAPI_Data.h>
40 #include <ModelAPI_Object.h>
41 #include <ModelAPI_AttributeSelectionList.h>
42 #include <ModelAPI_AttributeRefList.h>
43 #include <ModelAPI_AttributeRefAttrList.h>
44 #include <ModelAPI_Tools.h>
45 #include <ModelAPI_Events.h>
47 #include <Config_WidgetAPI.h>
49 #include <QGridLayout>
51 #include <QListWidget>
56 #include <QApplication>
59 #include <QMainWindow>
64 //#define DEBUG_UNDO_REDO
66 #ifdef DEBUG_UNDO_REDO
67 void printHistoryInfo(const QString& theMethodName, int theCurrentHistoryIndex,
68 QList<QList<std::shared_ptr<ModuleBase_ViewerPrs> > > theSelectedHistoryValues)
71 for (int i = 0; i < theSelectedHistoryValues.size(); i++)
72 aSizes.append(QString::number(theSelectedHistoryValues[i].size()));
74 std::cout << theMethodName.toStdString()
75 << " current = " << theCurrentHistoryIndex
76 << " size(history) = " << theSelectedHistoryValues.size()
77 << " (" << aSizes.join(", ").toStdString() << ")"
83 QStringList getIconsList(const QStringList& theNames)
86 foreach (QString aName, theNames) {
87 QString aUName = aName.toUpper();
88 if ((aUName == "VERTICES") || (aUName == "VERTEX"))
89 aIcons << ":pictures/vertex32.png";
90 else if ((aUName == "EDGES") || (aUName == "EDGE"))
91 aIcons << ":pictures/edge32.png";
92 else if ((aUName == "FACES") || (aUName == "FACE"))
93 aIcons << ":pictures/face32.png";
94 else if ((aUName == "SOLIDS") || (aUName == "SOLID"))
95 aIcons << ":pictures/solid32.png";
100 /// Stores default values of selected option (selection mode)
101 /// It is used only in case if myTypeCtrl is used
102 static QMap<std::string, std::string> defaultValues;
105 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
106 ModuleBase_IWorkshop* theWorkshop,
107 const Config_WidgetAPI* theData)
108 : ModuleBase_WidgetSelector(theParent, theWorkshop, theData),
109 myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1),
112 std::string aPropertyTypes = theData->getProperty("type_choice");
113 QString aTypesStr = aPropertyTypes.c_str();
114 myShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts);
115 myIsUseChoice = theData->getBooleanAttribute("use_choice", false);
117 QGridLayout* aMainLay = new QGridLayout(this);
118 ModuleBase_Tools::adjustMargins(aMainLay);
120 QStringList aIconsList = getIconsList(myShapeTypes);
121 myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
122 myTypeCtrl->setLabel(tr("Type"));
123 myTypeCtrl->setValue(0);
124 aMainLay->addWidget(myTypeCtrl, 0, 0, 1, 2);
125 myDefMode = myShapeTypes.first().toStdString();
127 // There is no sense to parameterize list of types while we can not parameterize selection mode
128 // if the xml definition contains one type, the controls to select a type should not be shown
129 if (myShapeTypes.size() <= 1 || !myIsUseChoice) {
130 myTypeCtrl->setVisible(false);
133 QString aLabelText = translate(theData->getProperty("label"));
134 QLabel* aListLabel = new QLabel(aLabelText, this);
135 aMainLay->addWidget(aListLabel, 1, 0);
136 // if the xml definition contains one type, an information label
137 // should be shown near to the latest
138 if (myShapeTypes.size() <= 1) {
139 QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
140 if (!aLabelIcon.isEmpty()) {
141 QLabel* aSelectedLabel = new QLabel("", this);
142 aSelectedLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon));
143 aMainLay->addWidget(aSelectedLabel, 1, 1);
145 aMainLay->setColumnStretch(2, 1);
148 QString aToolTip = QString::fromStdString(theData->widgetTooltip());
149 QString anObjName = QString::fromStdString(attributeID());
150 myListView = new ModuleBase_ListView(this, anObjName, aToolTip);
151 connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
152 connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
154 aMainLay->addWidget(myListView->getControl(), 2, 0, 1, -1);
155 aMainLay->setRowStretch(2, 1);
156 //aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)???
157 //aMainLay->setRowMinimumHeight(3, 20);
158 //this->setLayout(aMainLay);
159 connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
161 myIsNeutralPointClear = theData->getBooleanAttribute("clear_in_neutral_point", true);
162 if (myShapeTypes.size() > 1 || myIsUseChoice) {
163 if (defaultValues.contains(myFeatureId)) {
164 myDefMode = defaultValues[myFeatureId];
165 myTypeCtrl->setValue(myDefMode.c_str());
170 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
174 //********************************************************************
175 void ModuleBase_WidgetMultiSelector::activateCustom()
177 ModuleBase_WidgetSelector::activateCustom();
179 myWorkshop->module()->activateCustomPrs(myFeature,
180 ModuleBase_IModule::CustomizeHighlightedObjects, true);
181 clearSelectedHistory();
184 //********************************************************************
185 void ModuleBase_WidgetMultiSelector::deactivate()
187 ModuleBase_WidgetSelector::deactivate();
189 myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true);
190 clearSelectedHistory();
193 //********************************************************************
194 void ModuleBase_WidgetMultiSelector::updateAfterDeactivation()
196 // restore previous Undo/Redo workshop state
197 myWorkshop->updateCommandStatus();
200 //********************************************************************
201 void ModuleBase_WidgetMultiSelector::updateAfterActivation()
203 // fill Undo/Redo actions with current information
204 myWorkshop->updateCommandStatus();
207 //********************************************************************
208 bool ModuleBase_WidgetMultiSelector::storeValueCustom()
210 // the value is stored on the selection changed signal processing
211 // A rare case when plugin was not loaded.
215 AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
216 std::string aType = anAttribute->attributeType();
217 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
218 AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
220 std::string aMode = myTypeCtrl->textValue().toStdString();
221 if (myTypeCtrl->isVisible() && myIsFirst && (!myDefMode.empty()))
224 aSelectionListAttr->setSelectionType(aMode);
230 //********************************************************************
231 bool ModuleBase_WidgetMultiSelector::restoreValueCustom()
233 // A rare case when plugin was not loaded.
237 AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
238 std::string aType = anAttribute->attributeType();
239 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
240 AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
241 // Restore shape type
242 std::string aSelectionType = aSelectionListAttr->selectionType().c_str();
243 if (!aSelectionType.empty()) {
244 setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionType.c_str()));
245 myDefMode = aSelectionType;
249 updateSelectionList();
253 //********************************************************************
254 bool ModuleBase_WidgetMultiSelector::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
255 const bool theToValidate)
257 if (myIsSetSelectionBlocked)
260 AttributeSelectionListPtr aSelectionListAttr;
261 if (attribute()->attributeType() == ModelAPI_AttributeSelectionList::typeId())
262 aSelectionListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(attribute());
263 if (aSelectionListAttr.get())
264 aSelectionListAttr->cashValues(true);
266 /// remove unused objects from the model attribute.
267 /// It should be performed before new attributes append.
268 bool isDone = removeUnusedAttributeObjects(theValues);
270 QList<ModuleBase_ViewerPrsPtr> anInvalidValues;
271 QList<ModuleBase_ViewerPrsPtr> anAttributeValues;
272 QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
273 for (; anIt != aLast; anIt++) {
274 ModuleBase_ViewerPrsPtr aValue = *anIt;
275 // do not validate and append to attribute selection presentation if it exists in the attribute
278 getGeomSelection(aValue, anObject, aShape);
279 if (ModuleBase_Tools::hasObject(attribute(), anObject, aShape, myWorkshop, myIsInValidate)) {
280 anAttributeValues.append(aValue);
283 if (theToValidate && !isValidInFilters(aValue))
284 anInvalidValues.append(aValue);
286 bool aHasInvalidValues = anInvalidValues.size() > 0;
288 for (anIt = theValues.begin(); anIt != aLast; anIt++) {
289 ModuleBase_ViewerPrsPtr aValue = *anIt;
290 bool aProcessed = false;
291 if ((aHasInvalidValues && anInvalidValues.contains(aValue)) ||
292 anAttributeValues.contains(aValue))
294 aProcessed = setSelectionCustom(aValue); /// it is not optimal as hasObject() is already checked
295 // if there is at least one set, the result is true
296 isDone = isDone || aProcessed;
298 // updateObject - to update/redisplay feature
299 // it is commented in order to perfom it outside the method
301 //updateObject(myFeature);
302 // this emit is necessary to call store/restore method an restore type of selection
303 //emit valuesChanged();
306 if (aSelectionListAttr.get())
307 aSelectionListAttr->cashValues(false);
310 if (!anInvalidValues.empty())
311 theValues.append(anInvalidValues);
313 if (isDone) // may be the feature's result is not displayed, but attributes should be
314 myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
315 true);/// hope that something is redisplayed by object updated
320 //********************************************************************
321 void ModuleBase_WidgetMultiSelector::getHighlighted(QList<ModuleBase_ViewerPrsPtr>& theValues)
323 std::set<int> anAttributeIds;
324 getSelectedAttributeIndices(anAttributeIds);
325 if (!anAttributeIds.empty())
326 convertIndicesToViewerSelection(anAttributeIds, theValues);
329 //********************************************************************
330 bool ModuleBase_WidgetMultiSelector::canProcessAction(ModuleBase_ActionType theActionType,
331 bool& isActionEnabled)
333 isActionEnabled = false;
334 bool aCanProcess = false;
335 switch (theActionType) {
339 isActionEnabled = theActionType == ActionUndo ? myCurrentHistoryIndex > 0
340 : (mySelectedHistoryValues.size() > 0 &&
341 myCurrentHistoryIndex < mySelectedHistoryValues.size() - 1);
345 aCanProcess = ModuleBase_WidgetSelector::canProcessAction(theActionType, isActionEnabled);
351 //********************************************************************
352 bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType,
353 const ActionParamPtr& theParam)
355 switch (theActionType) {
358 ActionIntParamPtr aParam =
359 std::dynamic_pointer_cast<ModuleBase_ActionIntParameter>(theParam);
360 int aNb = aParam->value();
361 if (theActionType == ActionUndo)
362 myCurrentHistoryIndex -= aNb;
364 myCurrentHistoryIndex += aNb;
365 QList<ModuleBase_ViewerPrsPtr> aSelected = mySelectedHistoryValues[myCurrentHistoryIndex];
366 // equal vertices should not be used here
367 ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected);
368 bool isDone = setSelection(aSelected,
369 false /*need not validate because values already was in list*/);
370 updateOnSelectionChanged(isDone);
372 myWorkshop->updateCommandStatus();
373 #ifdef DEBUG_UNDO_REDO
374 printHistoryInfo(QString("processAction %1").arg(theActionType == ActionUndo ? "Undo"
375 : "Redo"), myCurrentHistoryIndex, mySelectedHistoryValues);
380 return ModuleBase_ModelWidget::processAction(theActionType, theParam);
384 //********************************************************************
385 bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
387 bool aValid = ModuleBase_WidgetSelector::isValidSelectionCustom(thePrs);
389 ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
390 aValid = aResult.get() != NULL;
393 // We can not select a result of our feature
394 std::list<ResultPtr> aResults;
395 ModelAPI_Tools::allResults(myFeature, aResults);
396 std::list<ResultPtr>::const_iterator aIt;
397 bool isSkipSelf = false;
398 for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
399 if ((*aIt) == aResult) {
412 //********************************************************************
413 bool ModuleBase_WidgetMultiSelector::processDelete()
415 appendFirstSelectionInHistory();
417 // find attribute indices to delete
418 std::set<int> anAttributeIds;
419 getSelectedAttributeIndices(anAttributeIds);
421 QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
423 // refill attribute by the items which indices are not in the list of ids
425 DataPtr aData = myFeature->data();
426 AttributePtr anAttribute = aData->attribute(attributeID());
427 std::string aType = anAttribute->attributeType();
428 aDone = !anAttributeIds.empty();
429 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
430 AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
431 aSelectionListAttr->remove(anAttributeIds);
434 else if (aType == ModelAPI_AttributeRefList::typeId()) {
435 AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
436 aRefListAttr->remove(anAttributeIds);
438 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
439 AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
440 aRefAttrListAttr->remove(anAttributeIds);
444 // update object is necessary to flush update signal. It leads to objects references map update
445 // and the operation presentation will not contain deleted items visualized as parameters of
447 updateObject(myFeature);
450 myWorkshop->setSelected(getAttributeSelection());
452 // may be the feature's result is not displayed, but attributes should be
453 myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
454 true); /// hope that something is redisplayed by object updated
458 myListView->restoreSelection(anIndices);
460 appendSelectionInHistory();
464 //********************************************************************
465 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
467 QList<QWidget*> result;
468 result << myListView->getControl();
472 //********************************************************************
473 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
475 // Clear current selection in order to avoid updating of object browser with obsolete indexes
476 // which can appear because of results deletetion after changing a type of selection
477 QList<ModuleBase_ViewerPrsPtr> aEmptyList;
478 myWorkshop->setSelected(aEmptyList);
480 updateSelectionModesAndFilters(true);
481 myWorkshop->selectionActivate()->updateSelectionModes();
485 /// store the selected type
486 AttributePtr anAttribute = myFeature->data()->attribute(attributeID());
487 std::string aType = anAttribute->attributeType();
488 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
489 AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
490 aSelectionListAttr->setSelectionType(myTypeCtrl->textValue().toStdString());
493 // clear attribute values
494 DataPtr aData = myFeature->data();
495 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
496 AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
497 aSelectionListAttr->clear();
499 else if (aType == ModelAPI_AttributeRefList::typeId()) {
500 AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
501 aRefListAttr->clear();
503 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
504 AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
505 aRefAttrListAttr->clear();
508 // update object is necessary to flush update signal. It leads to objects references map update
509 // and the operation presentation will not contain deleted items visualized as parameters of
511 updateObject(myFeature);
513 myWorkshop->setSelected(getAttributeSelection());
514 // may be the feature's result is not displayed, but attributes should be
515 myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
516 true); /// hope that something is redisplayed by object updated
517 // clear history should follow after set selected to do not increase history by setSelected
518 clearSelectedHistory();
520 if (myWorkshop->propertyPanel()->activeWidget() != this)
521 myWorkshop->propertyPanel()->activateWidget(this);
524 //********************************************************************
525 bool ModuleBase_WidgetMultiSelector::processSelection()
527 if (!myIsNeutralPointClear) {
528 QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
529 // do not clear selected object
530 if (aSelected.size() == 0) {
531 if (!getAttributeSelection().empty()) {
532 // Restore selection in the viewer by the attribute selection list
533 // it should be postponed to exit from the selectionChanged processing
534 static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
535 ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
536 Events_Loop::loop()->flush(anEvent);
541 appendFirstSelectionInHistory();
542 bool aDone = ModuleBase_WidgetSelector::processSelection();
543 appendSelectionInHistory();
547 void ModuleBase_WidgetMultiSelector::appendFirstSelectionInHistory()
549 if (mySelectedHistoryValues.empty()) {
550 myCurrentHistoryIndex++;
551 mySelectedHistoryValues.append(getAttributeSelection());
553 #ifdef DEBUG_UNDO_REDO
554 printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues);
559 void ModuleBase_WidgetMultiSelector::appendSelectionInHistory()
561 while (myCurrentHistoryIndex != mySelectedHistoryValues.count() - 1)
562 mySelectedHistoryValues.removeLast();
564 QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
565 myCurrentHistoryIndex++;
566 mySelectedHistoryValues.append(aSelected);
567 myWorkshop->updateCommandStatus();
569 #ifdef DEBUG_UNDO_REDO
570 printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues);
574 void ModuleBase_WidgetMultiSelector::clearSelectedHistory()
576 mySelectedHistoryValues.clear();
577 myCurrentHistoryIndex = -1;
578 myWorkshop->updateCommandStatus();
580 #ifdef DEBUG_UNDO_REDO
581 printHistoryInfo("clearSelectedHistory", myCurrentHistoryIndex, mySelectedHistoryValues);
585 void ModuleBase_WidgetMultiSelector::updateFocus()
587 // Set focus to List control in order to make possible
588 // to use Tab key for transfer the focus to next widgets
589 ModuleBase_Tools::setFocus(myListView->getControl(),
590 "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()");
593 //********************************************************************
594 void ModuleBase_WidgetMultiSelector::updateSelectionName()
598 //********************************************************************
599 void ModuleBase_WidgetMultiSelector::updateOnSelectionChanged(const bool theDone)
601 if (myIsSetSelectionBlocked)
603 ModuleBase_WidgetSelector::updateOnSelectionChanged(theDone);
605 // according to #2154 we need to update OB selection when selection in the viewer happens
606 // it is important to flush sinchronize selection signal after flush of Update/Create/Delete.
607 // because we need that Object Browser has been already updated when synchronize happens.
609 // Restore selection in the viewer by the attribute selection list
610 // it is possible that diring selection attribute filling, selection in Object Browser
611 // is changed(some items were removed/added) and as result, selection in the viewer
612 // differs from the selection come to this method. By next rows, we restore selection
613 // in the viewer according to content of selection attribute. Case is Edge selection in Group
614 myIsSetSelectionBlocked = true;
615 static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
616 ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
617 Events_Loop::loop()->flush(anEvent);
618 myIsSetSelectionBlocked = false;
621 //********************************************************************
622 QIntList ModuleBase_WidgetMultiSelector::shapeTypes() const
624 QIntList aShapeTypes;
626 if (myShapeTypes.length() > 1 && myIsUseChoice) {
627 aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCtrl->textValue()));
630 foreach (QString aType, myShapeTypes) {
631 aShapeTypes.append(ModuleBase_Tools::shapeType(aType));
637 //********************************************************************
638 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const int theShapeType)
640 QString aShapeTypeName;
643 foreach (QString aShapeTypeName, myShapeTypes) {
644 int aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
645 if(aRefType == theShapeType && idx != myTypeCtrl->value()) {
646 updateSelectionModesAndFilters(false);
647 bool isBlocked = myTypeCtrl->blockSignals(true);
648 myTypeCtrl->setValue(idx);
649 myTypeCtrl->blockSignals(isBlocked);
650 updateSelectionModesAndFilters(true);
657 QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetMultiSelector::getAttributeSelection() const
659 QList<ModuleBase_ViewerPrsPtr> aSelected;
660 convertIndicesToViewerSelection(std::set<int>(), aSelected);
664 //********************************************************************
665 void ModuleBase_WidgetMultiSelector::updateSelectionList()
667 myListView->getControl()->clear();
669 DataPtr aData = myFeature->data();
670 AttributePtr anAttribute = aData->attribute(attributeID());
671 std::string aType = anAttribute->attributeType();
672 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
673 AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
674 for (int i = 0; i < aSelectionListAttr->size(); i++) {
675 AttributeSelectionPtr aAttr = aSelectionListAttr->value(i);
676 myListView->addItem(aAttr->namingName().c_str(), i);
679 else if (aType == ModelAPI_AttributeRefList::typeId()) {
680 AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
681 for (int i = 0; i < aRefListAttr->size(); i++) {
682 ObjectPtr anObject = aRefListAttr->object(i);
683 if (anObject.get()) {
684 myListView->addItem(anObject->data()->name().c_str(), i);
688 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
689 AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
690 for (int i = 0; i < aRefAttrListAttr->size(); i++) {
691 AttributePtr anAttribute = aRefAttrListAttr->attribute(i);
693 if (anAttribute.get()) {
694 std::string anAttrName = generateName(anAttribute, myWorkshop);
695 aName = QString::fromStdString(anAttrName);
698 ObjectPtr anObject = aRefAttrListAttr->object(i);
699 if (anObject.get()) {
700 aName = anObject->data()->name().c_str();
703 myListView->addItem(aName, i);
707 // We have to call repaint because sometimes the List control is not updated
708 myListView->getControl()->repaint();
711 //********************************************************************
712 std::string ModuleBase_WidgetMultiSelector::validatorType(const QString& theType) const
716 if (theType == "Vertices")
718 else if (theType == "Edges")
720 else if (theType == "Faces")
722 else if (theType == "Solids")
728 //********************************************************************
729 void ModuleBase_WidgetMultiSelector::clearSelection()
731 bool isClearInNeutralPoint = myIsNeutralPointClear;
732 myIsNeutralPointClear = true;
734 QList<ModuleBase_ViewerPrsPtr> anEmptyList;
735 // This method will call Selection changed event which will call onSelectionChanged
736 // To clear mySelection, myListView and storeValue()
737 // So, we don't need to call it
738 myWorkshop->setSelected(anEmptyList);
740 myIsNeutralPointClear = isClearInNeutralPoint;
743 //********************************************************************
744 void ModuleBase_WidgetMultiSelector::onDeleteItem()
749 //********************************************************************
750 void ModuleBase_WidgetMultiSelector::onListSelection()
752 myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
756 //********************************************************************
757 void ModuleBase_WidgetMultiSelector::getSelectedAttributeIndices(std::set<int>& theAttributeIds)
759 myListView->getSelectedIndices(theAttributeIds);
762 void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::set<int> theAttributeIds,
763 QList<ModuleBase_ViewerPrsPtr>& theValues) const
765 if(myFeature.get() == NULL)
768 DataPtr aData = myFeature->data();
769 AttributePtr anAttribute = aData->attribute(attributeID());
770 std::string aType = anAttribute->attributeType();
771 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
772 AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
773 for (int i = 0; i < aSelectionListAttr->size(); i++) {
774 // filter by attribute indices only if the container is not empty otherwise return all items
775 if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end())
777 AttributeSelectionPtr anAttr = aSelectionListAttr->value(i);
778 ResultPtr anObject = anAttr->context();
780 theValues.append(std::shared_ptr<ModuleBase_ViewerPrs>(
781 new ModuleBase_ViewerPrs(anObject, anAttr->value(), NULL)));
784 else if (aType == ModelAPI_AttributeRefList::typeId()) {
785 AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
786 for (int i = 0; i < aRefListAttr->size(); i++) {
787 // filter by attribute indices only if the container is not empty otherwise return all items
788 if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end())
790 ObjectPtr anObject = aRefListAttr->object(i);
791 if (anObject.get()) {
792 theValues.append(std::shared_ptr<ModuleBase_ViewerPrs>(
793 new ModuleBase_ViewerPrs(anObject, GeomShapePtr(), NULL)));
797 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
798 AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
799 for (int i = 0; i < aRefAttrListAttr->size(); i++) {
800 // filter by attribute indices only if the container is not empty otherwise return all items
801 if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end())
803 ObjectPtr anObject = aRefAttrListAttr->object(i);
807 AttributePtr anAttribute = aRefAttrListAttr->attribute(i);
808 if (anAttribute.get()) {
809 GeomShapePtr aGeomShape = ModuleBase_Tools::getShape(anAttribute, myWorkshop);
810 theValues.append(std::shared_ptr<ModuleBase_ViewerPrs>(
811 new ModuleBase_ViewerPrs(anObject, aGeomShape, NULL)));
817 bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects
818 (QList<ModuleBase_ViewerPrsPtr>& theValues)
822 std::map<ObjectPtr, std::set<GeomShapePtr> > aGeomSelection = convertSelection(theValues);
823 DataPtr aData = myFeature->data();
824 AttributePtr anAttribute = aData->attribute(attributeID());
825 std::string aType = anAttribute->attributeType();
826 std::set<GeomShapePtr> aShapes;
827 std::set<int> anIndicesToBeRemoved;
828 if (aType == ModelAPI_AttributeSelectionList::typeId()) {
829 // iteration through data model to find not selected elements to remove them
830 AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
831 for (int i = 0; i < aSelectionListAttr->size(); i++) {
832 AttributeSelectionPtr anAttr = aSelectionListAttr->value(i);
833 bool aFound = findInSelection(anAttr->context(), anAttr->value(), aGeomSelection,
836 anIndicesToBeRemoved.insert(i);
838 isDone = anIndicesToBeRemoved.size() > 0;
839 aSelectionListAttr->remove(anIndicesToBeRemoved);
841 else if (aType == ModelAPI_AttributeRefList::typeId()) {
842 AttributeRefListPtr aRefListAttr = aData->reflist(attributeID());
843 for (int i = 0; i < aRefListAttr->size(); i++) {
844 ObjectPtr anObject = aRefListAttr->object(i);
845 if (anObject.get()) {
846 bool aFound = findInSelection(anObject, GeomShapePtr(), aGeomSelection,
849 anIndicesToBeRemoved.insert(i);
852 isDone = anIndicesToBeRemoved.size() > 0;
853 aRefListAttr->remove(anIndicesToBeRemoved);
855 else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
856 std::set<AttributePtr> anAttributes;
857 QList<ModuleBase_ViewerPrsPtr>::const_iterator
858 anIt = theValues.begin(), aLast = theValues.end();
861 for (; anIt != aLast; anIt++) {
862 ModuleBase_ViewerPrsPtr aPrs = *anIt;
863 getGeomSelection(aPrs, anObject, aShape);
864 AttributePtr anAttr = myWorkshop->module()->findAttribute(anObject, aShape);
865 if (anAttr.get() && anAttributes.find(anAttr) == anAttributes.end())
866 anAttributes.insert(anAttr);
869 AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID());
870 for (int i = 0; i < aRefAttrListAttr->size(); i++) {
872 if (aRefAttrListAttr->isAttribute(i)) {
873 AttributePtr anAttribute = aRefAttrListAttr->attribute(i);
874 aFound = anAttributes.find(anAttribute) != anAttributes.end();
877 aFound = findInSelection(aRefAttrListAttr->object(i), GeomShapePtr(), aGeomSelection,
881 anIndicesToBeRemoved.insert(i);
883 isDone = anIndicesToBeRemoved.size() > 0;
884 aRefAttrListAttr->remove(anIndicesToBeRemoved);
890 std::map<ObjectPtr, std::set<GeomShapePtr> > ModuleBase_WidgetMultiSelector::convertSelection
891 (QList<ModuleBase_ViewerPrsPtr>& theValues)
893 // convert prs list to objects map
894 std::map<ObjectPtr, std::set<GeomShapePtr> > aGeomSelection;
895 std::set<GeomShapePtr> aShapes;
896 QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
899 GeomShapePtr anEmptyShape(new GeomAPI_Shape());
900 for (; anIt != aLast; anIt++) {
901 ModuleBase_ViewerPrsPtr aPrs = *anIt;
902 getGeomSelection(aPrs, anObject, aShape);
904 if (aGeomSelection.find(anObject) != aGeomSelection.end()) // found
905 aShapes = aGeomSelection[anObject];
906 // we need to know if there was an empty shape in selection for the object
908 aShape = anEmptyShape;
909 if (aShape.get() && aShapes.find(aShape) == aShapes.end()) // not found
910 aShapes.insert(aShape);
911 aGeomSelection[anObject] = aShapes;
913 return aGeomSelection;
916 bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject,
917 GeomShapePtr theShape,
918 const std::map<ObjectPtr, std::set<GeomShapePtr> >& theGeomSelection,
919 ModuleBase_IWorkshop* theWorkshop)
921 // issue #2154: we should not remove from list objects hidden in the viewer if selection
922 // was done with SHIFT button
923 if (theWorkshop->hasSHIFTPressed() && !theObject->isDisplayed())
927 GeomShapePtr anEmptyShape(new GeomAPI_Shape());
928 if (theShape.get()) { // treat shape equal to context as null: 2219, keep order of shapes in list
929 const ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
930 if (aContext.get() && aContext->shape()->isEqual(theShape))
933 GeomShapePtr aShape = theShape.get() ? theShape : anEmptyShape;
934 if (theGeomSelection.find(theObject) != theGeomSelection.end()) {// found
935 const std::set<GeomShapePtr>& aShapes = theGeomSelection.at(theObject);
936 std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
937 for (; anIt != aLast && !aFound; anIt++) {
938 GeomShapePtr aCShape = *anIt;
940 aFound = aCShape->isSame(aShape);
947 ModuleBase_WidgetMultiSelector::actionsList(ModuleBase_ActionType theActionType) const
949 QList<ActionInfo> aList;
950 if (myCurrentHistoryIndex > -1) {
952 QString aTitle("Selection %1 items");
953 QString aTit("Selection %1 item");
954 QIcon aIcon(":pictures/selection.png");
956 switch (theActionType) {
959 while (i <= myCurrentHistoryIndex) {
960 aNb = mySelectedHistoryValues.at(i).count();
962 ActionInfo aInfo(aIcon, aTit.arg(aNb));
963 aList.insert(0, aInfo);
965 ActionInfo aInfo(aIcon, aTitle.arg(aNb));
966 aList.insert(0, aInfo);
972 i = mySelectedHistoryValues.length() - 1;
973 while (i > myCurrentHistoryIndex) {
974 aNb = mySelectedHistoryValues.at(i).count();
976 ActionInfo aInfo(aIcon, aTit.arg(mySelectedHistoryValues.at(i).count()));
977 aList.insert(0, aInfo);
979 ActionInfo aInfo(aIcon, aTitle.arg(mySelectedHistoryValues.at(i).count()));
980 aList.insert(0, aInfo);
991 void ModuleBase_WidgetMultiSelector::onFeatureAccepted()
993 defaultValues[myFeatureId] = myDefMode;