X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModuleBase%2FModuleBase_WidgetMultiSelector.cpp;h=fe5e99ecc75774a09de5d31c28f4b29f7b17edd5;hb=39aa2839a4269a2fc87cfe3b4487cce8f3df9a6f;hp=0af14a9555727fc26a5a875aad1771ba077d0338;hpb=df65199c64b66949f428cf92ec8e01cdf8290bdd;p=modules%2Fshaper.git diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp index 0af14a955..fe5e99ecc 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -14,13 +14,18 @@ #include #include #include - -#include +#include +#include +#include +#include #include #include #include #include +#include +#include +#include #include @@ -34,18 +39,28 @@ #include #include #include +#include +#include #include #include +const int ATTRIBUTE_SELECTION_INDEX_ROLE = Qt::UserRole + 1; + +/** +* Customization of a List Widget to make it to be placed on full width of container +*/ class CustomListWidget : public QListWidget { public: + /// Constructor + /// \param theParent a parent widget CustomListWidget( QWidget* theParent ) : QListWidget( theParent ) { } + /// Redefinition of virtual method virtual QSize sizeHint() const { int aHeight = 2*QFontMetrics( font() ).height(); @@ -53,20 +68,30 @@ public: return QSize( aSize.width(), aHeight ); } + /// Redefinition of virtual method virtual QSize minimumSizeHint() const { - int aHeight = 2*QFontMetrics( font() ).height(); + int aHeight = 4/*2*/*QFontMetrics( font() ).height(); QSize aSize = QListWidget::minimumSizeHint(); return QSize( aSize.width(), aHeight ); } + +#ifndef WIN32 +// The code is necessary only for Linux because +//it can not update viewport on widget resize +protected: + void resizeEvent(QResizeEvent* theEvent) + { + QListWidget::resizeEvent(theEvent); + QTimer::singleShot(5, viewport(), SLOT(repaint())); + } +#endif }; ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_WidgetSelector(theParent, theWorkshop, theData, theParentId), - mySelectionCount(0) + const Config_WidgetAPI* theData) +: ModuleBase_WidgetSelector(theParent, theWorkshop, theData) { QGridLayout* aMainLay = new QGridLayout(this); ModuleBase_Tools::adjustMargins(aMainLay); @@ -79,34 +104,41 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen std::string aPropertyTypes = theData->getProperty("type_choice"); QString aTypesStr = aPropertyTypes.c_str(); - QStringList aShapeTypes = aTypesStr.split(' '); + QStringList aShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts); - myIsUseChoice = theData->getBooleanAttribute("use_choice", true); + myIsUseChoice = theData->getBooleanAttribute("use_choice", false); - myTypeCombo->addItems(aShapeTypes); + if (!aShapeTypes.empty()) + myTypeCombo->addItems(aShapeTypes); aMainLay->addWidget(myTypeCombo, 0, 1); // if the xml definition contains one type, the controls to select a type should not be shown - if (aShapeTypes.size() == 1 || !myIsUseChoice) { + if (aShapeTypes.size() <= 1 || !myIsUseChoice) { aTypeLabel->setVisible(false); myTypeCombo->setVisible(false); } - std::string aLabelText = theData->getProperty("label"); - QLabel* aListLabel = new QLabel(!aLabelText.empty() ? aLabelText.c_str() - : tr("Selected objects:"), this); + QString aLabelText = translate(theData->getProperty("label")); + QLabel* aListLabel = new QLabel(aLabelText, this); aMainLay->addWidget(aListLabel, 1, 0); - // if the xml definition contains one type, an information label should be shown near to the latest - if (aShapeTypes.size() == 1) { + // if the xml definition contains one type, an information label + // should be shown near to the latest + if (aShapeTypes.size() <= 1) { QString aLabelIcon = QString::fromStdString(theData->widgetIcon()); if (!aLabelIcon.isEmpty()) { QLabel* aSelectedLabel = new QLabel("", this); - aSelectedLabel->setPixmap(QPixmap(aLabelIcon)); + aSelectedLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon)); aMainLay->addWidget(aSelectedLabel, 1, 1); } aMainLay->setColumnStretch(2, 1); } + QString aToolTip = QString::fromStdString(theData->widgetTooltip()); myListControl = new CustomListWidget(this); + QString anObjName = QString::fromStdString(attributeID()); + myListControl->setObjectName(anObjName); + myListControl->setToolTip(aToolTip); + myListControl->setSelectionMode(QAbstractItemView::ExtendedSelection); + aMainLay->addWidget(myListControl, 2, 0, 1, -1); aMainLay->setRowStretch(2, 1); //aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)??? @@ -114,13 +146,21 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen //this->setLayout(aMainLay); connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged())); - myCopyAction = new QAction(QIcon(":pictures/copy.png"), tr("Copy"), this); + myCopyAction = ModuleBase_Tools::createAction(QIcon(":pictures/copy.png"), tr("Copy"), + myWorkshop->desktop(), this, SLOT(onCopyItem())); myCopyAction->setShortcut(QKeySequence::Copy); myCopyAction->setEnabled(false); - connect(myCopyAction, SIGNAL(triggered(bool)), SLOT(onCopyItem())); myListControl->addAction(myCopyAction); + + myDeleteAction = ModuleBase_Tools::createAction(QIcon(":pictures/delete.png"), tr("Delete"), + myWorkshop->desktop(), this, SLOT(onDeleteItem())); + myDeleteAction->setEnabled(false); + myListControl->addAction(myDeleteAction); + myListControl->setContextMenuPolicy(Qt::ActionsContextMenu); connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection())); + + myIsNeutralPointClear = theData->getBooleanAttribute("clear_in_neutral_point", true); } ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector() @@ -128,120 +168,98 @@ ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector() } //******************************************************************** -bool ModuleBase_WidgetMultiSelector::storeValueCustom() const +void ModuleBase_WidgetMultiSelector::activateCustom() { - // the value is stored on the selection changed signal processing - // A rare case when plugin was not loaded. - if (!myFeature) - return false; + ModuleBase_WidgetSelector::activateCustom(); - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString()); - } - return true; + myWorkshop->module()->activateCustomPrs(myFeature, + ModuleBase_IModule::CustomizeHighlightedObjects, true); } //******************************************************************** -bool ModuleBase_WidgetMultiSelector::restoreValueCustom() +void ModuleBase_WidgetMultiSelector::deactivate() { - // A rare case when plugin was not loaded. - if (!myFeature) - return false; + ModuleBase_WidgetSelector::deactivate(); - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - // Restore shape type - if (!aSelectionListAttr->selectionType().empty()) - setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str())); - } - updateSelectionList(); - return true; + myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true); } //******************************************************************** -void ModuleBase_WidgetMultiSelector::storeAttributeValue() +bool ModuleBase_WidgetMultiSelector::storeValueCustom() { - ModuleBase_WidgetValidated::storeAttributeValue(); + // the value is stored on the selection changed signal processing + // A rare case when plugin was not loaded. + if (!myFeature) + return false; - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - mySelectionType = aSelectionListAttr->selectionType(); - mySelectionCount = aSelectionListAttr->size(); - } - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); - mySelectionCount = aRefListAttr->size(); + AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); + aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString()); } + return true; } //******************************************************************** -void ModuleBase_WidgetMultiSelector::restoreAttributeValue(bool theValid) +bool ModuleBase_WidgetMultiSelector::restoreValueCustom() { - ModuleBase_WidgetValidated::restoreAttributeValue(theValid); - - // Store shape type - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - aSelectionListAttr->setSelectionType(mySelectionType); + // A rare case when plugin was not loaded. + if (!myFeature) + return false; - // restore selection in the attribute. Indeed there is only one stored object - int aCountAppened = aSelectionListAttr->size() - mySelectionCount; - for (int i = 0; i < aCountAppened; i++) - aSelectionListAttr->removeLast(); - } - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); - // restore objects in the attribute. Indeed there is only one stored object - int aCountAppened = aRefListAttr->size() - mySelectionCount; - for (int i = 0; i < aCountAppened; i++) - aRefListAttr->removeLast(); + AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); + // Restore shape type + std::string aSelectionType = aSelectionListAttr->selectionType().c_str(); + if (!aSelectionType.empty()) + setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionType.c_str())); } + updateSelectionList(); + return true; } //******************************************************************** -void ModuleBase_WidgetMultiSelector::clearAttribute() +bool ModuleBase_WidgetMultiSelector::setSelection(QList& theValues, + const bool theToValidate) { - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); + AttributeSelectionListPtr aSelectionListAttr; + if (attribute()->attributeType() == ModelAPI_AttributeSelectionList::typeId()) + aSelectionListAttr = std::dynamic_pointer_cast(attribute()); if (aSelectionListAttr.get()) - aSelectionListAttr->clear(); - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); - aRefListAttr->clear(); - } -} + aSelectionListAttr->cashValues(true); -//******************************************************************** -void ModuleBase_WidgetMultiSelector::setObject(ObjectPtr theSelectedObject, - GeomShapePtr theShape) -{ - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - ResultPtr aResult = std::dynamic_pointer_cast(theSelectedObject); - aSelectionListAttr->append(aResult, theShape, myIsInValidate); - } - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); - aRefListAttr->append(theSelectedObject); - } -} + /// remove unused objects from the model attribute. + /// It should be performed before new attributes append. + bool isDone = removeUnusedAttributeObjects(theValues); -//******************************************************************** -bool ModuleBase_WidgetMultiSelector::setSelection(QList& theValues, - const bool theToValidate) -{ - QList aSkippedValues; - - QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); - bool isDone = false; + QList anInvalidValues; + QList anAttributeValues; + QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); for (; anIt != aLast; anIt++) { - ModuleBase_ViewerPrs aValue = *anIt; - bool aProcessed = false; - if (!theToValidate || isValidInFilters(aValue)) { - aProcessed = setSelectionCustom(aValue); + ModuleBase_ViewerPrsPtr aValue = *anIt; + // do not validate and append to attribute selection presentation if it exists in the attribute + ObjectPtr anObject; + GeomShapePtr aShape; + getGeomSelection(aValue, anObject, aShape); + if (ModuleBase_Tools::hasObject(attribute(), anObject, aShape, myWorkshop, myIsInValidate)) { + anAttributeValues.append(aValue); + continue; } - else - aSkippedValues.append(aValue); + if (theToValidate && !isValidInFilters(aValue)) + anInvalidValues.append(aValue); + } + bool aHasInvalidValues = anInvalidValues.size() > 0; + + for (anIt = theValues.begin(); anIt != aLast; anIt++) { + ModuleBase_ViewerPrsPtr aValue = *anIt; + bool aProcessed = false; + if ((aHasInvalidValues && anInvalidValues.contains(aValue)) || + anAttributeValues.contains(aValue)) + continue; + aProcessed = setSelectionCustom(aValue); /// it is not optimal as hasObject() is already checked // if there is at least one set, the result is true isDone = isDone || aProcessed; } @@ -252,15 +270,32 @@ bool ModuleBase_WidgetMultiSelector::setSelection(QList& t // this emit is necessary to call store/restore method an restore type of selection //emit valuesChanged(); //} + + if (aSelectionListAttr.get()) + aSelectionListAttr->cashValues(false); + theValues.clear(); - if (!aSkippedValues.empty()) - theValues.append(aSkippedValues); + if (!anInvalidValues.empty()) + theValues.append(anInvalidValues); + + if (isDone) // may be the feature's result is not displayed, but attributes should be + myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments, + true);/// hope that something is redisplayed by object updated return isDone; } //******************************************************************** -bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs) +void ModuleBase_WidgetMultiSelector::getHighlighted(QList& theValues) +{ + std::set anAttributeIds; + getSelectedAttributeIndices(anAttributeIds); + if (!anAttributeIds.empty()) + convertIndicesToViewerSelection(anAttributeIds, theValues); +} + +//******************************************************************** +bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) { bool aValid = ModuleBase_WidgetSelector::isValidSelectionCustom(thePrs); if (aValid) { @@ -269,10 +304,11 @@ bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_Vie if (aValid) { if (myFeature) { // We can not select a result of our feature - const std::list& aResList = myFeature->results(); + std::list aResults; + ModelAPI_Tools::allResults(myFeature, aResults); std::list::const_iterator aIt; bool isSkipSelf = false; - for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) { + for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { if ((*aIt) == aResult) { isSkipSelf = true; break; @@ -286,6 +322,64 @@ bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_Vie return aValid; } +//******************************************************************** +bool ModuleBase_WidgetMultiSelector::processDelete() +{ + // find attribute indices to delete + std::set anAttributeIds; + getSelectedAttributeIndices(anAttributeIds); + + QModelIndexList aIndexes = myListControl->selectionModel()->selectedIndexes(); + + // refill attribute by the items which indices are not in the list of ids + bool aDone = false; + DataPtr aData = myFeature->data(); + AttributePtr anAttribute = aData->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + aDone = !anAttributeIds.empty(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID()); + aSelectionListAttr->remove(anAttributeIds); + + } + else if (aType == ModelAPI_AttributeRefList::typeId()) { + AttributeRefListPtr aRefListAttr = aData->reflist(attributeID()); + aRefListAttr->remove(anAttributeIds); + } + else if (aType == ModelAPI_AttributeRefAttrList::typeId()) { + AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID()); + aRefAttrListAttr->remove(anAttributeIds); + } + + if (aDone) { + // update object is necessary to flush update signal. It leads to objects references map update + // and the operation presentation will not contain deleted items visualized as parameters of + // the feature. + updateObject(myFeature); + + restoreValue(); + myWorkshop->setSelected(getAttributeSelection()); + + // may be the feature's result is not displayed, but attributes should be + myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments, + true); /// hope that something is redisplayed by object updated + } + + // Restore selection + int aRows = myListControl->model()->rowCount(); + if (aRows > 0) { + foreach(QModelIndex aIndex, aIndexes) { + if (aIndex.row() < aRows) + myListControl->selectionModel()->select(aIndex, QItemSelectionModel::Select); + else { + QModelIndex aIdx = myListControl->model()->index(aRows - 1, 0); + myListControl->selectionModel()->select(aIdx, QItemSelectionModel::Select); + } + } + } + return aDone; +} + //******************************************************************** QList ModuleBase_WidgetMultiSelector::getControls() const { @@ -298,21 +392,71 @@ QList ModuleBase_WidgetMultiSelector::getControls() const //******************************************************************** void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged() { - activateSelection(true); - activateFilters(true); - QList anEmptyList; - // This method will call Selection changed event which will call onSelectionChanged - // To clear mySelection, myListControl and storeValue() - // So, we don't need to call it - myWorkshop->setSelected(anEmptyList); + activateSelectionAndFilters(true); + + if (!myFeature) + return; + /// store the selected type + AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); + aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString()); + } + + // clear attribute values + DataPtr aData = myFeature->data(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID()); + aSelectionListAttr->clear(); + } + else if (aType == ModelAPI_AttributeRefList::typeId()) { + AttributeRefListPtr aRefListAttr = aData->reflist(attributeID()); + aRefListAttr->clear(); + } + else if (aType == ModelAPI_AttributeRefAttrList::typeId()) { + AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID()); + aRefAttrListAttr->clear(); + } + + // update object is necessary to flush update signal. It leads to objects references map update + // and the operation presentation will not contain deleted items visualized as parameters of + // the feature. + updateObject(myFeature); + restoreValue(); + myWorkshop->setSelected(getAttributeSelection()); + // may be the feature's result is not displayed, but attributes should be + myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments, + true); /// hope that something is redisplayed by object updated +} + +//******************************************************************** +void ModuleBase_WidgetMultiSelector::onSelectionChanged() +{ + if (!myIsNeutralPointClear) { + QList aSelected = getFilteredSelected(); + // do not clear selected object + if (aSelected.size() == 0) { + if (!getAttributeSelection().empty()) { + // Restore selection in the viewer by the attribute selection list + // it should be postponed to exit from the selectionChanged processing + static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); + ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent); + Events_Loop::loop()->flush(anEvent); + return; + } + } + } + ModuleBase_WidgetSelector::onSelectionChanged(); } void ModuleBase_WidgetMultiSelector::updateFocus() { - // Set focus to List control in order to make possible + // Set focus to List control in order to make possible // to use Tab key for transfer the focus to next widgets myListControl->setCurrentRow(myListControl->model()->rowCount() - 1); - myListControl->setFocus(); + ModuleBase_Tools::setFocus(myListControl, + "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()"); } //******************************************************************** @@ -321,7 +465,7 @@ void ModuleBase_WidgetMultiSelector::updateSelectionName() } //******************************************************************** -QIntList ModuleBase_WidgetMultiSelector::getShapeTypes() const +QIntList ModuleBase_WidgetMultiSelector::shapeTypes() const { QIntList aShapeTypes; @@ -329,67 +473,36 @@ QIntList ModuleBase_WidgetMultiSelector::getShapeTypes() const aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->currentText())); } else { - for (int i = 0, aCount = myTypeCombo->count(); i < aCount; i++) { + for (int i = 0, aCount = myTypeCombo->count(); i < aCount; i++) aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->itemText(i))); - } } return aShapeTypes; } //******************************************************************** -void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType) +void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const int theShapeType) { QString aShapeTypeName; - + for (int idx = 0; idx < myTypeCombo->count(); ++idx) { aShapeTypeName = myTypeCombo->itemText(idx); - TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName); + int aRefType = ModuleBase_Tools::shapeType(aShapeTypeName); if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) { - activateSelection(false); - activateFilters(false); + bool aWasActivated = activateSelectionAndFilters(false); bool isBlocked = myTypeCombo->blockSignals(true); myTypeCombo->setCurrentIndex(idx); myTypeCombo->blockSignals(isBlocked); - - activateSelection(true); - activateFilters(true); + if (aWasActivated) + activateSelectionAndFilters(true); break; } } } -QList ModuleBase_WidgetMultiSelector::getAttributeSelection() const +QList ModuleBase_WidgetMultiSelector::getAttributeSelection() const { - QList aSelected; - // Restore selection in the viewer by the attribute selection list - if(myFeature) { - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { - for (int i = 0; i < aSelectionListAttr->size(); i++) { - AttributeSelectionPtr anAttr = aSelectionListAttr->value(i); - ResultPtr anObject = anAttr->context(); - if (anObject.get()) { - TopoDS_Shape aShape; - std::shared_ptr aShapePtr = anAttr->value(); - if (aShapePtr.get()) { - aShape = aShapePtr->impl(); - } - aSelected.append(ModuleBase_ViewerPrs(anObject, aShape, NULL)); - } - } - } - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); - if (aRefListAttr.get()) { - for (int i = 0; i < aRefListAttr->size(); i++) { - ObjectPtr anObject = aRefListAttr->object(i); - if (anObject.get()) { - aSelected.append(ModuleBase_ViewerPrs(anObject, TopoDS_Shape(), NULL)); - } - } - } - } - } + QList aSelected; + convertIndicesToViewerSelection(std::set(), aSelected); return aSelected; } @@ -398,21 +511,51 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList() { myListControl->clear(); - AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - if (aSelectionListAttr.get()) { + DataPtr aData = myFeature->data(); + AttributePtr anAttribute = aData->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID()); for (int i = 0; i < aSelectionListAttr->size(); i++) { AttributeSelectionPtr aAttr = aSelectionListAttr->value(i); - myListControl->addItem(aAttr->namingName().c_str()); + QListWidgetItem* anItem = new QListWidgetItem(aAttr->namingName().c_str(), myListControl); + anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i); + myListControl->addItem(anItem); } } - else { - AttributeRefListPtr aRefListAttr = myFeature->data()->reflist(attributeID()); + else if (aType == ModelAPI_AttributeRefList::typeId()) { + AttributeRefListPtr aRefListAttr = aData->reflist(attributeID()); for (int i = 0; i < aRefListAttr->size(); i++) { ObjectPtr anObject = aRefListAttr->object(i); - if (anObject.get()) - myListControl->addItem(anObject->data()->name().c_str()); + if (anObject.get()) { + QListWidgetItem* anItem = new QListWidgetItem(anObject->data()->name().c_str(), + myListControl); + anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i); + myListControl->addItem(anItem); + } + } + } + else if (aType == ModelAPI_AttributeRefAttrList::typeId()) { + AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID()); + for (int i = 0; i < aRefAttrListAttr->size(); i++) { + AttributePtr anAttribute = aRefAttrListAttr->attribute(i); + QString aName; + if (anAttribute.get()) { + std::string anAttrName = generateName(anAttribute, myWorkshop); + aName = QString::fromStdString(anAttrName); + } + else { + ObjectPtr anObject = aRefAttrListAttr->object(i); + if (anObject.get()) { + aName = anObject->data()->name().c_str(); + } + } + QListWidgetItem* anItem = new QListWidgetItem(aName, myListControl); + anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i); + myListControl->addItem(anItem); } } + // We have to call repaint because sometimes the List control is not updated myListControl->repaint(); } @@ -434,6 +577,21 @@ std::string ModuleBase_WidgetMultiSelector::validatorType(const QString& theType return aType; } +//******************************************************************** +void ModuleBase_WidgetMultiSelector::clearSelection() +{ + bool isClearInNeutralPoint = myIsNeutralPointClear; + myIsNeutralPointClear = true; + + QList anEmptyList; + // This method will call Selection changed event which will call onSelectionChanged + // To clear mySelection, myListControl and storeValue() + // So, we don't need to call it + myWorkshop->setSelected(anEmptyList); + + myIsNeutralPointClear = isClearInNeutralPoint; +} + //******************************************************************** void ModuleBase_WidgetMultiSelector::onCopyItem() { @@ -450,9 +608,200 @@ void ModuleBase_WidgetMultiSelector::onCopyItem() } } +//******************************************************************** +void ModuleBase_WidgetMultiSelector::onDeleteItem() +{ + processDelete(); +} + //******************************************************************** void ModuleBase_WidgetMultiSelector::onListSelection() { QList aItems = myListControl->selectedItems(); myCopyAction->setEnabled(!aItems.isEmpty()); + myDeleteAction->setEnabled(!aItems.isEmpty()); + + myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects, + true); +} + +//******************************************************************** +void ModuleBase_WidgetMultiSelector::getSelectedAttributeIndices(std::set& theAttributeIds) +{ + QList aItems = myListControl->selectedItems(); + foreach(QListWidgetItem* anItem, aItems) { + int anIndex = anItem->data(ATTRIBUTE_SELECTION_INDEX_ROLE).toInt(); + if (theAttributeIds.find(anIndex) == theAttributeIds.end()) + theAttributeIds.insert(anIndex); + } +} + +void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::set theAttributeIds, + QList& theValues) const +{ + if(myFeature.get() == NULL) + return; + + DataPtr aData = myFeature->data(); + AttributePtr anAttribute = aData->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID()); + for (int i = 0; i < aSelectionListAttr->size(); i++) { + // filter by attribute indices only if the container is not empty otherwise return all items + if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end()) + continue; + AttributeSelectionPtr anAttr = aSelectionListAttr->value(i); + ResultPtr anObject = anAttr->context(); + if (anObject.get()) + theValues.append(std::shared_ptr( + new ModuleBase_ViewerPrs(anObject, anAttr->value(), NULL))); + } + } + else if (aType == ModelAPI_AttributeRefList::typeId()) { + AttributeRefListPtr aRefListAttr = aData->reflist(attributeID()); + for (int i = 0; i < aRefListAttr->size(); i++) { + // filter by attribute indices only if the container is not empty otherwise return all items + if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end()) + continue; + ObjectPtr anObject = aRefListAttr->object(i); + if (anObject.get()) { + theValues.append(std::shared_ptr( + new ModuleBase_ViewerPrs(anObject, GeomShapePtr(), NULL))); + } + } + } + else if (aType == ModelAPI_AttributeRefAttrList::typeId()) { + AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID()); + for (int i = 0; i < aRefAttrListAttr->size(); i++) { + // filter by attribute indices only if the container is not empty otherwise return all items + if (!theAttributeIds.empty() && theAttributeIds.find(i) == theAttributeIds.end()) + continue; + ObjectPtr anObject = aRefAttrListAttr->object(i); + if (!anObject.get()) + continue; + TopoDS_Shape aShape; + AttributePtr anAttribute = aRefAttrListAttr->attribute(i); + if (anAttribute.get()) { + GeomShapePtr aGeomShape = ModuleBase_Tools::getShape(anAttribute, myWorkshop); + theValues.append(std::shared_ptr( + new ModuleBase_ViewerPrs(anObject, aGeomShape, NULL))); + } + } + } +} + +bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects + (QList& theValues) +{ + bool isDone = false; + + std::map > aGeomSelection = convertSelection(theValues); + DataPtr aData = myFeature->data(); + AttributePtr anAttribute = aData->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + std::set aShapes; + std::set anIndicesToBeRemoved; + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + // iteration through data model to find not selected elements to remove them + AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID()); + for (int i = 0; i < aSelectionListAttr->size(); i++) { + AttributeSelectionPtr anAttr = aSelectionListAttr->value(i); + bool aFound = findInSelection(anAttr->context(), anAttr->value(), aGeomSelection); + if (!aFound) + anIndicesToBeRemoved.insert(i); + } + isDone = anIndicesToBeRemoved.size() > 0; + aSelectionListAttr->remove(anIndicesToBeRemoved); + } + else if (aType == ModelAPI_AttributeRefList::typeId()) { + AttributeRefListPtr aRefListAttr = aData->reflist(attributeID()); + for (int i = 0; i < aRefListAttr->size(); i++) { + ObjectPtr anObject = aRefListAttr->object(i); + if (anObject.get()) { + bool aFound = findInSelection(anObject, GeomShapePtr(), aGeomSelection); + if (!aFound) + anIndicesToBeRemoved.insert(i); + } + } + isDone = anIndicesToBeRemoved.size() > 0; + aRefListAttr->remove(anIndicesToBeRemoved); + } + else if (aType == ModelAPI_AttributeRefAttrList::typeId()) { + std::set anAttributes; + QList::const_iterator + anIt = theValues.begin(), aLast = theValues.end(); + ObjectPtr anObject; + GeomShapePtr aShape; + for (; anIt != aLast; anIt++) { + ModuleBase_ViewerPrsPtr aPrs = *anIt; + getGeomSelection(aPrs, anObject, aShape); + AttributePtr anAttr = myWorkshop->module()->findAttribute(anObject, aShape); + if (anAttr.get() && anAttributes.find(anAttr) == anAttributes.end()) + anAttributes.insert(anAttr); + } + + AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID()); + for (int i = 0; i < aRefAttrListAttr->size(); i++) { + bool aFound = false; + if (aRefAttrListAttr->isAttribute(i)) { + AttributePtr anAttribute = aRefAttrListAttr->attribute(i); + aFound = anAttributes.find(anAttribute) != anAttributes.end(); + } + else { + aFound = findInSelection(aRefAttrListAttr->object(i), GeomShapePtr(), aGeomSelection); + } + if (!aFound) + anIndicesToBeRemoved.insert(i); + } + isDone = anIndicesToBeRemoved.size() > 0; + aRefAttrListAttr->remove(anIndicesToBeRemoved); + } + + return isDone; +} + +std::map > ModuleBase_WidgetMultiSelector::convertSelection + (QList& theValues) +{ + // convert prs list to objects map + std::map > aGeomSelection; + std::set aShapes; + QList::const_iterator anIt = theValues.begin(), aLast = theValues.end(); + ObjectPtr anObject; + GeomShapePtr aShape; + GeomShapePtr anEmptyShape(new GeomAPI_Shape()); + for (; anIt != aLast; anIt++) { + ModuleBase_ViewerPrsPtr aPrs = *anIt; + getGeomSelection(aPrs, anObject, aShape); + aShapes.clear(); + if (aGeomSelection.find(anObject) != aGeomSelection.end()) // found + aShapes = aGeomSelection[anObject]; + // we need to know if there was an empty shape in selection for the object + if (!aShape.get()) + aShape = anEmptyShape; + if (aShape.get() && aShapes.find(aShape) == aShapes.end()) // not found + aShapes.insert(aShape); + aGeomSelection[anObject] = aShapes; + } + return aGeomSelection; +} + +bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject, + const GeomShapePtr& theShape, + const std::map >& theGeomSelection) +{ + bool aFound = false; + GeomShapePtr anEmptyShape(new GeomAPI_Shape()); + GeomShapePtr aShape = theShape.get() ? theShape : anEmptyShape; + if (theGeomSelection.find(theObject) != theGeomSelection.end()) {// found + const std::set& aShapes = theGeomSelection.at(theObject); + std::set::const_iterator anIt = aShapes.begin(), aLast = aShapes.end(); + for (; anIt != aLast && !aFound; anIt++) { + GeomShapePtr aCShape = *anIt; + if (aCShape.get()) + aFound = aCShape->isEqual(aShape); + } + } + return aFound; }