X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModuleBase%2FModuleBase_WidgetMultiSelector.cpp;h=f071f3d98e7322b3a125a24bbfbaae7e2af53dae;hb=90a04fa2943fd985a9dbabc839313a8744d898fc;hp=d144f33821c377a605e3bed8e80daee5059919a8;hpb=1d95654c34de2fb1fb9e0833470661cd64e39c32;p=modules%2Fshaper.git diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp old mode 100755 new mode 100644 index d144f3382..f071f3d98 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2022 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,23 +12,32 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include -#include + +#include + +#include +#include +#include +#include +#include #include -#include +#include +#include #include +#include +#include +#include #include -#include -#include #include -#include -#include +#include +#include +#include #include #include @@ -40,6 +49,8 @@ #include +#include + #include #include #include @@ -47,132 +58,177 @@ #include #include #include -#include #include #include #include #include +#include +#include #include #include -const int ATTRIBUTE_SELECTION_INDEX_ROLE = Qt::UserRole + 1; +//#define DEBUG_UNDO_REDO -/** -* Customization of a List Widget to make it to be placed on full width of container -*/ -class CustomListWidget : public QListWidget +#ifdef DEBUG_UNDO_REDO +void printHistoryInfo(const QString& theMethodName, int theCurrentHistoryIndex, + QList > > theSelectedHistoryValues) { -public: - /// Constructor - /// \param theParent a parent widget - CustomListWidget( QWidget* theParent ) - : QListWidget( theParent ) - { - } + QStringList aSizes; + for (int i = 0; i < theSelectedHistoryValues.size(); i++) + aSizes.append(QString::number(theSelectedHistoryValues[i].size())); + + std::cout << theMethodName.toStdString() + << " current = " << theCurrentHistoryIndex + << " size(history) = " << theSelectedHistoryValues.size() + << " (" << aSizes.join(", ").toStdString() << ")" + << std::endl; +} +#endif - /// Redefinition of virtual method - virtual QSize sizeHint() const - { - int aHeight = 2*QFontMetrics( font() ).height(); - QSize aSize = QListWidget::sizeHint(); - return QSize( aSize.width(), aHeight ); - } - /// Redefinition of virtual method - virtual QSize minimumSizeHint() const - { - int aHeight = 4/*2*/*QFontMetrics( font() ).height(); - QSize aSize = QListWidget::minimumSizeHint(); - return QSize( aSize.width(), aHeight ); +QStringList getIconsList(const QStringList& theNames) +{ + QStringList aIcons; + foreach (QString aName, theNames) { + QString aUName = aName.toUpper(); + if ((aUName == "VERTICES") || (aUName == "VERTEX")) + aIcons << ":pictures/vertex32.png"; + else if ((aUName == "EDGES") || (aUName == "EDGE")) + aIcons << ":pictures/edge32.png"; + else if ((aUName == "FACES") || (aUName == "FACE")) + aIcons << ":pictures/face32.png"; + else if ((aUName == "SOLIDS") || (aUName == "SOLID")) + aIcons << ":pictures/solid32.png"; } + return aIcons; +} + +/// Stores default values of selected option (selection mode) +/// It is used only in case if myTypeCtrl is used +static QMap defaultValues; -#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) : ModuleBase_WidgetSelector(theParent, theWorkshop, theData), - myIsSetSelectionBlocked(false) + myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1), + myIsFirst(true), myFiltersWgt(0), myShowOnlyBtn(0) { - QGridLayout* aMainLay = new QGridLayout(this); - ModuleBase_Tools::adjustMargins(aMainLay); + std::string aPropertyTypes = theData->getProperty("shape_types"); + QString aTypesStr = aPropertyTypes.c_str(); + myShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts); + myIsUseChoice = theData->getBooleanAttribute("use_choice", false); - QLabel* aTypeLabel = new QLabel(tr("Type"), this); - aMainLay->addWidget(aTypeLabel, 0, 0); + QString aAllowedList(theData->getProperty("allow_objects").c_str()); + if (!aAllowedList.isEmpty()) + myAllowedObjects = aAllowedList.split(' ', QString::SkipEmptyParts); - myTypeCombo = new QComboBox(this); - // There is no sense to parameterize list of types while we can not parameterize selection mode + myMainLayout = new QVBoxLayout(this); + ModuleBase_Tools::adjustMargins(myMainLayout); - std::string aPropertyTypes = theData->getProperty("type_choice"); - QString aTypesStr = aPropertyTypes.c_str(); - QStringList aShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts); - myIsUseChoice = theData->getBooleanAttribute("use_choice", false); + QStringList aIconsList; + std::string aIcons = theData->getProperty("type_icons"); + if (aIcons.size() > 0) + aIconsList = QString(aIcons.c_str()).split(' ', QString::SkipEmptyParts); + + if (aIconsList.size() != myShapeTypes.size()) + aIconsList = getIconsList(myShapeTypes); - if (!aShapeTypes.empty()) - myTypeCombo->addItems(aShapeTypes); - aMainLay->addWidget(myTypeCombo, 0, 1); + myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList); + myTypeCtrl->setLabel(tr("Type")); + if (!myShapeTypes.empty()) { + std::string aDefType = theData->getProperty("default_type"); + if (aDefType.size() > 0) { + bool aOk = false; + int aId = QString(aDefType.c_str()).toInt(&aOk); + if (aOk) { + myTypeCtrl->setValue(aId); + myDefMode = myShapeTypes.at(aId).toStdString(); + } + } + if (myDefMode.size() == 0) { + myTypeCtrl->setValue(0); + myDefMode = myShapeTypes.first().toStdString(); + } + } + myMainLayout->addWidget(myTypeCtrl); + + // There is no sense to parameterize list of types while we can not parameterize selection mode // if the xml definition contains one type, the controls to select a type should not be shown - if (aShapeTypes.size() <= 1 || !myIsUseChoice) { - aTypeLabel->setVisible(false); - myTypeCombo->setVisible(false); + if (myShapeTypes.size() <= 1 || !myIsUseChoice) { + myTypeCtrl->setVisible(false); } 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) { - QString aLabelIcon = QString::fromStdString(theData->widgetIcon()); - if (!aLabelIcon.isEmpty()) { - QLabel* aSelectedLabel = new QLabel("", this); - 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); + if (aLabelText.size() > 0) { + QWidget* aLabelWgt = new QWidget(this); + QHBoxLayout* aLabelLayout = new QHBoxLayout(aLabelWgt); + aLabelLayout->setContentsMargins(0, 0, 0, 0); + myMainLayout->addWidget(aLabelWgt); + + QLabel* aListLabel = new QLabel(aLabelText, this); + aLabelLayout->addWidget(aListLabel); + // if the xml definition contains one type, an information label + // should be shown near to the latest + if (myShapeTypes.size() <= 1) { + QString aLabelIcon = QString::fromStdString(theData->widgetIcon()); + if (!aLabelIcon.isEmpty()) { + QLabel* aSelectedLabel = new QLabel("", this); + aSelectedLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon)); + aLabelLayout->addWidget(aSelectedLabel); + aLabelLayout->addStretch(1); + } + } + } + + QString aToolTip = translate(theData->widgetTooltip()); 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)??? - //aMainLay->setRowMinimumHeight(3, 20); - //this->setLayout(aMainLay); - connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged())); - - myCopyAction = ModuleBase_Tools::createAction(QIcon(":pictures/copy.png"), tr("Copy"), - myWorkshop->desktop(), this, SLOT(onCopyItem())); - myCopyAction->setShortcut(QKeySequence::Copy); - myCopyAction->setEnabled(false); - 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())); + myListView = new ModuleBase_ListView(this, anObjName, aToolTip); + connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection())); + connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem())); + connect(myListView, SIGNAL(listActivated()), SLOT(onListActivated())); + + myMainLayout->addWidget(myListView->getControl()); + connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged())); + + myUseFilters = theData->getProperty("use_filters"); + if (myUseFilters.length() > 0) { + QWidget* aFltrWgt = new QWidget(this); + QHBoxLayout* aFltrLayout = new QHBoxLayout(aFltrWgt); + + myFiltersWgt = new ModuleBase_FilterStarter(myUseFilters, aFltrWgt, theWorkshop); + aFltrLayout->addWidget(myFiltersWgt); + + aFltrLayout->addStretch(); + + myShowOnlyBtn = new QPushButton(tr("Show only"), aFltrWgt); + myShowOnlyBtn->setCheckable(true); + myShowOnlyBtn->setChecked(false); + connect(myShowOnlyBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool))); + aFltrLayout->addWidget(myShowOnlyBtn); + + myMainLayout->addWidget(aFltrWgt); + } + + bool aSameTop = theData->getBooleanAttribute("same_topology", false); + if (aSameTop) { + myGeomCheck = new QCheckBox(tr("Add elements that share the same topology"), this); + myMainLayout->addWidget(myGeomCheck); + connect(myGeomCheck, SIGNAL(toggled(bool)), SLOT(onSameTopology(bool))); + } + else + myGeomCheck = 0; myIsNeutralPointClear = theData->getBooleanAttribute("clear_in_neutral_point", true); + if (myShapeTypes.size() > 1 || myIsUseChoice) { + if (defaultValues.contains(myFeatureId + attributeID())) { + myDefMode = defaultValues[myFeatureId + attributeID()]; + myTypeCtrl->setValue(myDefMode.c_str()); + } + } } ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector() @@ -184,16 +240,67 @@ void ModuleBase_WidgetMultiSelector::activateCustom() { ModuleBase_WidgetSelector::activateCustom(); - myWorkshop->module()->activateCustomPrs(myFeature, + ModuleBase_IModule* aModule = myWorkshop->module(); + aModule->activateCustomPrs(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects, true); + clearSelectedHistory(); + if (myAllowedObjects.length() > 0) { + Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter); + if (!aFilter.IsNull()) { + Handle(ModuleBase_ShapeDocumentFilter) aDocFilter = + Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter); + if (!aDocFilter.IsNull()) { + QStringList aSelFilters = aDocFilter->nonSelectableTypes(); + foreach(QString aType, aSelFilters) { + if (aSelFilters.contains(aType)) { + aDocFilter->removeNonSelectableType(aType); + myTmpAllowed.append(aType); + } + } + } + } + } } //******************************************************************** void ModuleBase_WidgetMultiSelector::deactivate() { + myWorkshop->module()->enableCustomModes(); + ModuleBase_WidgetSelector::deactivate(); + if (myVisibleObjects.size()) + myShowOnlyBtn->setChecked(false); myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true); + clearSelectedHistory(); + if (myTmpAllowed.length() > 0) { + ModuleBase_IModule* aModule = myWorkshop->module(); + Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_GlobalFilter); + if (!aFilter.IsNull()) { + Handle(ModuleBase_ShapeDocumentFilter) aDocFilter = + Handle(ModuleBase_ShapeDocumentFilter)::DownCast(aFilter); + if (!aDocFilter.IsNull()) { + foreach(QString aType, myTmpAllowed) { + aDocFilter->addNonSelectableType(aType); + } + } + } + myTmpAllowed.clear(); + } +} + +//******************************************************************** +void ModuleBase_WidgetMultiSelector::updateAfterDeactivation() +{ + // restore previous Undo/Redo workshop state + myWorkshop->updateCommandStatus(); +} + +//******************************************************************** +void ModuleBase_WidgetMultiSelector::updateAfterActivation() +{ + // fill Undo/Redo actions with current information + myWorkshop->updateCommandStatus(); } //******************************************************************** @@ -208,7 +315,23 @@ bool ModuleBase_WidgetMultiSelector::storeValueCustom() std::string aType = anAttribute->attributeType(); if (aType == ModelAPI_AttributeSelectionList::typeId()) { AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString()); + if (myTypeCtrl->isVisible()) { + std::string aMode = myTypeCtrl->textValue().toStdString(); + if (myIsFirst && (!myDefMode.empty())) + aMode = myDefMode; + + aSelectionListAttr->setSelectionType(aMode); + myIsFirst = false; + } else { // no type, set the type as a first element of the list shape type when it is appeared + if (aSelectionListAttr->size()) { + AttributeSelectionPtr aSel = aSelectionListAttr->value(0); + GeomShapePtr aFirstVal = aSel->value(); + if (!aFirstVal.get() && aSel->context().get()) + aFirstVal = aSel->context()->shape(); + if (aFirstVal.get() && !aFirstVal->isNull()) + aSelectionListAttr->setSelectionType(aFirstVal->shapeTypeStr()); + } + } } return true; } @@ -221,14 +344,21 @@ bool ModuleBase_WidgetMultiSelector::restoreValueCustom() return false; AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(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())); + if (aSelectionType.empty()) + aSelectionListAttr->setSelectionType(myDefMode); + else { + setCurrentShapeType(aSelectionType.c_str()); + myDefMode = aSelectionType; + myIsFirst = false; + } } + if (myGeomCheck) + myGeomCheck->setChecked(aSelectionListAttr->isGeometricalSelection()); updateSelectionList(); return true; } @@ -278,6 +408,12 @@ bool ModuleBase_WidgetMultiSelector::setSelection(QList // if there is at least one set, the result is true isDone = isDone || aProcessed; } + // Check the selection with validators + QString aError = getError(); + if (aError.length() > 0) { + aSelectionListAttr->clear(); + isDone = false; + } // updateObject - to update/redisplay feature // it is commented in order to perfom it outside the method //if (isDone) { @@ -294,7 +430,7 @@ bool ModuleBase_WidgetMultiSelector::setSelection(QList 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, + myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeArguments, true);/// hope that something is redisplayed by object updated return isDone; @@ -309,12 +445,72 @@ void ModuleBase_WidgetMultiSelector::getHighlighted(QList 0 + : (mySelectedHistoryValues.size() > 0 && + myCurrentHistoryIndex < mySelectedHistoryValues.size() - 1); + } + break; + default: + aCanProcess = ModuleBase_WidgetSelector::canProcessAction(theActionType, isActionEnabled); + break; + } + return aCanProcess; +} + +//******************************************************************** +bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType, + const ActionParamPtr& theParam) +{ + switch (theActionType) { + case ActionUndo: + case ActionRedo: { + ActionIntParamPtr aParam = + std::dynamic_pointer_cast(theParam); + int aNb = aParam->value(); + if (theActionType == ActionUndo) + myCurrentHistoryIndex -= aNb; + else + myCurrentHistoryIndex += aNb; + QList aSelected = mySelectedHistoryValues[myCurrentHistoryIndex]; + // equal vertices should not be used here + ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected); + bool isDone = setSelection(aSelected, + false /*need not validate because values already was in list*/); + updateOnSelectionChanged(isDone); + + myWorkshop->updateCommandStatus(); +#ifdef DEBUG_UNDO_REDO + printHistoryInfo(QString("processAction %1").arg(theActionType == ActionUndo ? "Undo" + : "Redo"), myCurrentHistoryIndex, mySelectedHistoryValues); +#endif + return true; + } + default: + return ModuleBase_ModelWidget::processAction(theActionType, theParam); + } +} + //******************************************************************** bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) { bool aValid = ModuleBase_WidgetSelector::isValidSelectionCustom(thePrs); if (aValid) { ResultPtr aResult = myWorkshop->selection()->getResult(thePrs); + if (!aResult.get()) { // In case if a feature was selected + FeaturePtr aFeature = std::dynamic_pointer_cast(thePrs->object()); + if (aFeature.get()) + aResult = aFeature->firstResult(); + } aValid = aResult.get() != NULL; if (aValid) { if (myFeature) { @@ -340,11 +536,13 @@ bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_Vie //******************************************************************** bool ModuleBase_WidgetMultiSelector::processDelete() { + appendFirstSelectionInHistory(); + // find attribute indices to delete std::set anAttributeIds; getSelectedAttributeIndices(anAttributeIds); - QModelIndexList aIndexes = myListControl->selectionModel()->selectedIndexes(); + QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes(); // refill attribute by the items which indices are not in the list of ids bool aDone = false; @@ -376,38 +574,38 @@ bool ModuleBase_WidgetMultiSelector::processDelete() myWorkshop->setSelected(getAttributeSelection()); // may be the feature's result is not displayed, but attributes should be - myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments, + myWorkshop->module()->customizeFeature(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; + myListView->restoreSelection(anIndices); + + appendSelectionInHistory(); + return true/*aDone*/; // following #2438 Delete should be processed even if nothing is delete } //******************************************************************** QList ModuleBase_WidgetMultiSelector::getControls() const { QList result; - //result << myTypeCombo; - result << myListControl; + if (myTypeCtrl->isVisible()) + result << myTypeCtrl; + result << myListView->getControl(); return result; } //******************************************************************** void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged() { - activateSelectionAndFilters(true); + // Clear current selection in order to avoid updating of object browser with obsolete indexes + // which can appear because of results deletetion after changing a type of selection + QString aSelectionType = myTypeCtrl->textValue(); + QList aEmptyList; + myWorkshop->setSelected(aEmptyList); + + updateSelectionModesAndFilters(true); + myWorkshop->selectionActivate()->updateSelectionModes(); if (!myFeature) return; @@ -416,7 +614,7 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged() std::string aType = anAttribute->attributeType(); if (aType == ModelAPI_AttributeSelectionList::typeId()) { AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); - aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString()); + aSelectionListAttr->setSelectionType(aSelectionType.toStdString()); } // clear attribute values @@ -441,12 +639,18 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged() 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 + // hope that something is redisplayed by object updated + myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeArguments, false); + myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeResults, true); + // clear history should follow after set selected to do not increase history by setSelected + clearSelectedHistory(); + + if (myWorkshop->propertyPanel()->activeWidget() != this) + myWorkshop->propertyPanel()->activateWidget(this); } //******************************************************************** -void ModuleBase_WidgetMultiSelector::onSelectionChanged() +bool ModuleBase_WidgetMultiSelector::processSelection() { if (!myIsNeutralPointClear) { QList aSelected = getFilteredSelected(); @@ -458,18 +662,59 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged() static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent); Events_Loop::loop()->flush(anEvent); - return; + return true; } } } - ModuleBase_WidgetSelector::onSelectionChanged(); + appendFirstSelectionInHistory(); + bool aDone = ModuleBase_WidgetSelector::processSelection(); + appendSelectionInHistory(); + return aDone; +} + +void ModuleBase_WidgetMultiSelector::appendFirstSelectionInHistory() +{ + if (mySelectedHistoryValues.empty()) { + myCurrentHistoryIndex++; + mySelectedHistoryValues.append(getAttributeSelection()); + +#ifdef DEBUG_UNDO_REDO + printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues); +#endif + } +} + +void ModuleBase_WidgetMultiSelector::appendSelectionInHistory() +{ + while (myCurrentHistoryIndex != mySelectedHistoryValues.count() - 1) + mySelectedHistoryValues.removeLast(); + + QList aSelected = getFilteredSelected(); + myCurrentHistoryIndex++; + mySelectedHistoryValues.append(aSelected); + myWorkshop->updateCommandStatus(); + +#ifdef DEBUG_UNDO_REDO + printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues); +#endif +} + +void ModuleBase_WidgetMultiSelector::clearSelectedHistory() +{ + mySelectedHistoryValues.clear(); + myCurrentHistoryIndex = -1; + myWorkshop->updateCommandStatus(); + +#ifdef DEBUG_UNDO_REDO + printHistoryInfo("clearSelectedHistory", myCurrentHistoryIndex, mySelectedHistoryValues); +#endif } void ModuleBase_WidgetMultiSelector::updateFocus() { // Set focus to List control in order to make possible // to use Tab key for transfer the focus to next widgets - ModuleBase_Tools::setFocus(myListControl, + ModuleBase_Tools::setFocus(myListView->getControl(), "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()"); } @@ -506,33 +751,39 @@ QIntList ModuleBase_WidgetMultiSelector::shapeTypes() const { QIntList aShapeTypes; - if (myTypeCombo->count() > 1 && myIsUseChoice) { - aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->currentText())); + if (myShapeTypes.length() > 1 && myIsUseChoice) { + QStringList aTypes = myTypeCtrl->textValue().split("|", QString::SkipEmptyParts); + for(QString aType: aTypes) { + aShapeTypes.append(ModuleBase_Tools::shapeType(aType)); + } } else { - for (int i = 0, aCount = myTypeCombo->count(); i < aCount; i++) - aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->itemText(i))); + foreach (QString aType, myShapeTypes) { + QStringList aSubTypes = aType.split("|", QString::SkipEmptyParts); + for(QString aSubType: aSubTypes) { + aShapeTypes.append(ModuleBase_Tools::shapeType(aSubType)); + } + } } return aShapeTypes; } //******************************************************************** -void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const int theShapeType) -{ - QString aShapeTypeName; - - for (int idx = 0; idx < myTypeCombo->count(); ++idx) { - aShapeTypeName = myTypeCombo->itemText(idx); - int aRefType = ModuleBase_Tools::shapeType(aShapeTypeName); - if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) { - bool aWasActivated = activateSelectionAndFilters(false); - bool isBlocked = myTypeCombo->blockSignals(true); - myTypeCombo->setCurrentIndex(idx); - myTypeCombo->blockSignals(isBlocked); - if (aWasActivated) - activateSelectionAndFilters(true); +void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const QString& theShapeType) +{ + int idx = 0; + GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::shapeTypeByStr(theShapeType.toStdString()); + foreach (QString aShapeTypeName, myShapeTypes) { + if(GeomAPI_Shape::shapeTypeByStr(aShapeTypeName.toStdString()) == aShapeType && + idx != myTypeCtrl->value()) { + updateSelectionModesAndFilters(false); + bool isBlocked = myTypeCtrl->blockSignals(true); + myTypeCtrl->setValue(idx); + myTypeCtrl->blockSignals(isBlocked); + updateSelectionModesAndFilters(true); break; } + idx++; } } @@ -546,7 +797,7 @@ QList ModuleBase_WidgetMultiSelector::getAttributeSelec //******************************************************************** void ModuleBase_WidgetMultiSelector::updateSelectionList() { - myListControl->clear(); + myListView->getControl()->clear(); DataPtr aData = myFeature->data(); AttributePtr anAttribute = aData->attribute(attributeID()); @@ -555,9 +806,7 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList() AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID()); for (int i = 0; i < aSelectionListAttr->size(); i++) { AttributeSelectionPtr aAttr = aSelectionListAttr->value(i); - QListWidgetItem* anItem = new QListWidgetItem(aAttr->namingName().c_str(), myListControl); - anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i); - myListControl->addItem(anItem); + myListView->addItem(QString::fromStdWString(aAttr->namingName()), i); } } else if (aType == ModelAPI_AttributeRefList::typeId()) { @@ -565,36 +814,31 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList() for (int i = 0; i < aRefListAttr->size(); i++) { ObjectPtr anObject = aRefListAttr->object(i); if (anObject.get()) { - QListWidgetItem* anItem = new QListWidgetItem(anObject->data()->name().c_str(), - myListControl); - anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i); - myListControl->addItem(anItem); + myListView->addItem(QString::fromStdWString(anObject->data()->name()), i); } } } else if (aType == ModelAPI_AttributeRefAttrList::typeId()) { AttributeRefAttrListPtr aRefAttrListAttr = aData->refattrlist(attributeID()); for (int i = 0; i < aRefAttrListAttr->size(); i++) { - AttributePtr anAttribute = aRefAttrListAttr->attribute(i); + AttributePtr anAttr = aRefAttrListAttr->attribute(i); QString aName; - if (anAttribute.get()) { - std::string anAttrName = generateName(anAttribute, myWorkshop); - aName = QString::fromStdString(anAttrName); + if (anAttr.get()) { + std::wstring anAttrName = ModuleBase_Tools::generateName(anAttr, myWorkshop); + aName = QString::fromStdWString(anAttrName); } else { ObjectPtr anObject = aRefAttrListAttr->object(i); if (anObject.get()) { - aName = anObject->data()->name().c_str(); + aName = QString::fromStdWString(anObject->data()->name()); } } - QListWidgetItem* anItem = new QListWidgetItem(aName, myListControl); - anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i); - myListControl->addItem(anItem); + myListView->addItem(aName, i); } } // We have to call repaint because sometimes the List control is not updated - myListControl->repaint(); + myListView->getControl()->update(); } //******************************************************************** @@ -622,29 +866,13 @@ void ModuleBase_WidgetMultiSelector::clearSelection() QList anEmptyList; // This method will call Selection changed event which will call onSelectionChanged - // To clear mySelection, myListControl and storeValue() + // To clear mySelection, myListView and storeValue() // So, we don't need to call it myWorkshop->setSelected(anEmptyList); myIsNeutralPointClear = isClearInNeutralPoint; } -//******************************************************************** -void ModuleBase_WidgetMultiSelector::onCopyItem() -{ - QList aItems = myListControl->selectedItems(); - QString aRes; - foreach(QListWidgetItem* aItem, aItems) { - if (!aRes.isEmpty()) - aRes += "\n"; - aRes += aItem->text(); - } - if (!aRes.isEmpty()) { - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(aRes); - } -} - //******************************************************************** void ModuleBase_WidgetMultiSelector::onDeleteItem() { @@ -654,23 +882,14 @@ void ModuleBase_WidgetMultiSelector::onDeleteItem() //******************************************************************** void ModuleBase_WidgetMultiSelector::onListSelection() { - QList aItems = myListControl->selectedItems(); - myCopyAction->setEnabled(!aItems.isEmpty()); - myDeleteAction->setEnabled(!aItems.isEmpty()); - - myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects, - true); + myWorkshop->module()->customizeFeature(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); - } + myListView->getSelectedIndices(theAttributeIds); } void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::set theAttributeIds, @@ -689,7 +908,7 @@ void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::setvalue(i); - ResultPtr anObject = anAttr->context(); + ObjectPtr anObject = anAttr->contextObject(); if (anObject.get()) theValues.append(std::shared_ptr( new ModuleBase_ViewerPrs(anObject, anAttr->value(), NULL))); @@ -718,9 +937,9 @@ void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::setattribute(i); - if (anAttribute.get()) { - GeomShapePtr aGeomShape = ModuleBase_Tools::getShape(anAttribute, myWorkshop); + AttributePtr anAttr = aRefAttrListAttr->attribute(i); + if (anAttr.get()) { + GeomShapePtr aGeomShape = ModuleBase_Tools::getShape(anAttr, myWorkshop); theValues.append(std::shared_ptr( new ModuleBase_ViewerPrs(anObject, aGeomShape, NULL))); } @@ -739,18 +958,25 @@ bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects std::string aType = anAttribute->attributeType(); std::set aShapes; std::set anIndicesToBeRemoved; + FeaturePtr aFeature; 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, - myWorkshop); + ObjectPtr aContextObject = anAttr->contextObject(); + GeomShapePtr aShape; + aFeature = std::dynamic_pointer_cast(aContextObject); + if (!aFeature.get()) + aShape = anAttr->value(); + + bool aFound = findInSelection(aContextObject, aShape, aGeomSelection, myWorkshop); if (!aFound) anIndicesToBeRemoved.insert(i); } isDone = anIndicesToBeRemoved.size() > 0; - aSelectionListAttr->remove(anIndicesToBeRemoved); + if (isDone) + aSelectionListAttr->remove(anIndicesToBeRemoved); } else if (aType == ModelAPI_AttributeRefList::typeId()) { AttributeRefListPtr aRefListAttr = aData->reflist(attributeID()); @@ -784,8 +1010,8 @@ bool ModuleBase_WidgetMultiSelector::removeUnusedAttributeObjects 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(); + AttributePtr anAttr = aRefAttrListAttr->attribute(i); + aFound = anAttributes.find(anAttr) != anAttributes.end(); } else { aFound = findInSelection(aRefAttrListAttr->object(i), GeomShapePtr(), aGeomSelection, @@ -832,27 +1058,192 @@ bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject, const std::map >& theGeomSelection, ModuleBase_IWorkshop* theWorkshop) { + if (!theObject.get()) + return false; // issue #2154: we should not remove from list objects hidden in the viewer if selection // was done with SHIFT button if (theWorkshop->hasSHIFTPressed() && !theObject->isDisplayed()) return true; bool aFound = false; - GeomShapePtr anEmptyShape(new GeomAPI_Shape()); - if (theShape.get()) { // treat shape equal to context as null: 2219, keep order of shapes in list - const ResultPtr aContext = std::dynamic_pointer_cast(theObject); - if (aContext.get() && aContext->shape()->isEqual(theShape)) - theShape.reset(); + GeomShapePtr aShape = theShape; + if (!aShape.get()) { + // #2429 (the preselection of a sketch is not taken into account) + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aResult.get()) + aShape = aResult->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()) + { + // treat shape equal to context as null: 2219, keep order of shapes in list + if (aCShape->isNull()) { // in selection, shape of result is equal to selected shape + // if so, here we need to check shape of result + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if (aResult.get()) + aCShape = aResult->shape(); + } aFound = aCShape->isSame(aShape); + } } } + + // issue #2903: (Possibility to hide faces) - check whether given shape is a hidden sub-shape + if (!aFound && theShape.get() && theWorkshop->hasSHIFTPressed() && theObject->isDisplayed()) { + AISObjectPtr anAIS = theWorkshop->findPresentation(theObject); + if (anAIS.get() != NULL) { + Handle(AIS_InteractiveObject) anAISIO = anAIS->impl(); + + Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(anAISIO); + if (!aResultPrs.IsNull() && aResultPrs->isSubShapeHidden(theShape->impl())) + return true; + } + } + return aFound; } + +QList + ModuleBase_WidgetMultiSelector::actionsList(ModuleBase_ActionType theActionType) const +{ + QList aList; + if (myCurrentHistoryIndex > -1) { + int i = 0; + QString aTitle("Selection %1 items"); + QString aTit("Selection %1 item"); + QIcon aIcon(":pictures/selection.png"); + int aNb; + switch (theActionType) { + case ActionUndo: + i = 1; + while (i <= myCurrentHistoryIndex) { + aNb = mySelectedHistoryValues.at(i).count(); + if (aNb == 1) { + ActionInfo aInfo(aIcon, aTit.arg(aNb)); + aList.insert(0, aInfo); + } else { + ActionInfo aInfo(aIcon, aTitle.arg(aNb)); + aList.insert(0, aInfo); + } + i++; + } + break; + case ActionRedo: + i = mySelectedHistoryValues.length() - 1; + while (i > myCurrentHistoryIndex) { + aNb = mySelectedHistoryValues.at(i).count(); + if (aNb == 1) { + ActionInfo aInfo(aIcon, aTit.arg(mySelectedHistoryValues.at(i).count())); + aList.insert(0, aInfo); + } else { + ActionInfo aInfo(aIcon, aTitle.arg(mySelectedHistoryValues.at(i).count())); + aList.insert(0, aInfo); + } + i--; + } + break; + default: // [to avoid compilation warning] + break; + } + } + return aList; +} + + +void ModuleBase_WidgetMultiSelector::onFeatureAccepted() +{ + defaultValues[myFeatureId + attributeID()] = myDefMode; +} + +void ModuleBase_WidgetMultiSelector::onListActivated() +{ + //focusTo(); + emitFocusInWidget(); +} + +void ModuleBase_WidgetMultiSelector::onSameTopology(bool theOn) +{ + AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + std::string aType = anAttribute->attributeType(); + if (aType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID()); + aSelectionListAttr->setGeometricalSelection(theOn); + updateObject(myFeature); + } +} + +void ModuleBase_WidgetMultiSelector::onShowOnly(bool theChecked) +{ + std::list aResults = myFeature->results(); + std::list::const_iterator aIt; + if (theChecked) { + myVisibleObjects = myWorkshop->displayedObjects(); + for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) { + myVisibleObjects.removeAll(*aIt); + } + myWorkshop->module()->disableCustomMode(ModuleBase_IModule::CustomizeArguments); + } + else + myWorkshop->module()->enableCustomModes(); + + foreach(ObjectPtr aObj, myVisibleObjects) { + aObj->setDisplayed(!theChecked); + } + + if (!theChecked) { + // Hide and show the group result in order to make it above all objects + bool aOldState = myWorkshop->enableUpdateViewer(false); + for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) { + (*aIt)->setDisplayed(false); + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) { + (*aIt)->setDisplayed(true); + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + myWorkshop->enableUpdateViewer(aOldState); + + myVisibleObjects.clear(); + } else + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + myWorkshop->viewer()->update(); +} + +bool ModuleBase_WidgetMultiSelector::isModified() const +{ + return myListView->getControl()->count() > 0; +} + + +void ModuleBase_WidgetMultiSelector::setReadOnly(bool isReadOnly) +{ + ModuleBase_WidgetSelector::setReadOnly(isReadOnly); + if (myShowOnlyBtn) + myShowOnlyBtn->hide(); + if (myFiltersWgt) { + myFiltersWgt->hide(); + + AttributeSelectionListPtr aAttrList = feature()->selectionList(attributeID()); + if (aAttrList.get()) { + FiltersFeaturePtr aFilters = aAttrList->filters(); + if (aFilters.get()) { + ModuleBase_WidgetSelectionFilter::SelectorFeature = feature(); + ModuleBase_WidgetSelectionFilter::AttributeId = attributeID(); + + std::string aXmlCfg, aDescription; + myWorkshop->module()->getXMLRepresentation(myUseFilters, aXmlCfg, aDescription); + + ModuleBase_WidgetSelectionFilter* aWgt = + new ModuleBase_WidgetSelectionFilter(this, myWorkshop, + new Config_WidgetAPI(aDescription), true); + aWgt->setFeature(aFilters); + aWgt->restoreValue(); + myMainLayout->addWidget(aWgt); + } + } + } +}