X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModuleBase%2FModuleBase_WidgetSelector.cpp;h=59e836e47229cbfd0d4da1051a68ad8d2b53e37b;hb=2632fd4da93042ee9d7787467aed233f4d272fff;hp=f5b5af3b1023fb98326f9317d5fe6ac92b61bce4;hpb=32d1a4d19ab1a5d7c172e9660130fcf8ecb1e520;p=modules%2Fshaper.git diff --git a/src/ModuleBase/ModuleBase_WidgetSelector.cpp b/src/ModuleBase/ModuleBase_WidgetSelector.cpp index f5b5af3b1..59e836e47 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelector.cpp @@ -1,96 +1,54 @@ -// File: ModuleBase_WidgetSelector.h -// Created: 2 June 2014 -// Author: Vitaly Smetannikov - -#include "ModuleBase_WidgetSelector.h" -#include "ModuleBase_IWorkshop.h" - -#include +// Copyright (C) 2014-2019 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// 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 -#include -#include -#include -#include -#include -#include - -#include - -typedef QMap ShapeTypes; -static ShapeTypes MyShapeTypes; - -TopAbs_ShapeEnum ModuleBase_WidgetSelector::shapeType(const QString& theType) -{ - if (MyShapeTypes.count() == 0) { - MyShapeTypes["face"] = TopAbs_FACE; - MyShapeTypes["vertex"] = TopAbs_VERTEX; - MyShapeTypes["wire"] = TopAbs_WIRE; - MyShapeTypes["edge"] = TopAbs_EDGE; - MyShapeTypes["shell"] = TopAbs_SHELL; - MyShapeTypes["solid"] = TopAbs_SOLID; - } - if (MyShapeTypes.contains(theType)) - return MyShapeTypes[theType]; - throw std::invalid_argument("Shape type defined in XML is not implemented!"); -} +#include ModuleBase_WidgetSelector::ModuleBase_WidgetSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, - const Config_WidgetAPI* theData, - const std::string& theParentId) - : ModuleBase_ModelWidget(theParent, theData, theParentId), - myWorkshop(theWorkshop) + const Config_WidgetAPI* theData) +: ModuleBase_WidgetValidated(theParent, theWorkshop, theData), +myIsPointsFiltering(true) { - myContainer = new QWidget(theParent); - QHBoxLayout* aLayout = new QHBoxLayout(myContainer); - - aLayout->setContentsMargins(0, 0, 0, 0); - QString aLabelText = QString::fromStdString(theData->widgetLabel()); - QString aLabelIcon = QString::fromStdString(theData->widgetIcon()); - myLabel = new QLabel(aLabelText, myContainer); - if (!aLabelIcon.isEmpty()) - myLabel->setPixmap(QPixmap(aLabelIcon)); - - aLayout->addWidget(myLabel); - - QString aToolTip = QString::fromStdString(theData->widgetTooltip()); - myTextLine = new QLineEdit(myContainer); - myTextLine->setReadOnly(true); - myTextLine->setToolTip(aToolTip); - myTextLine->installEventFilter(this); - - myBasePalet = myTextLine->palette(); - myInactivePalet = myBasePalet; - myInactivePalet.setBrush(QPalette::Base, QBrush(Qt::gray, Qt::Dense6Pattern)); - myTextLine->setPalette(myInactivePalet); - - aLayout->addWidget(myTextLine, 1); - - myActivateBtn = new QToolButton(myContainer); - myActivateBtn->setIcon(QIcon(":icons/hand_point.png")); - myActivateBtn->setCheckable(true); - myActivateBtn->setToolTip(tr("Activate/Deactivate selection")); - connect(myActivateBtn, SIGNAL(toggled(bool)), this, SLOT(activateSelection(bool))); - - aLayout->addWidget(myActivateBtn); - - std::string aTypes = theData->getProperty("shape_types"); - myShapeTypes = QString(aTypes.c_str()).split(' '); + QString aFiltering = QString::fromStdString(theData->getProperty("filter_points")); + if (aFiltering.toLower() == "false") + myIsPointsFiltering = false; } //******************************************************************** @@ -99,165 +57,213 @@ ModuleBase_WidgetSelector::~ModuleBase_WidgetSelector() } //******************************************************************** -bool ModuleBase_WidgetSelector::storeValue() const +void ModuleBase_WidgetSelector::getGeomSelection(const ModuleBase_ViewerPrsPtr& thePrs, + ObjectPtr& theObject, + GeomShapePtr& theShape) { - FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(mySelectedObject); - if (aSelectedFeature == myFeature) // In order to avoid selection of the same object - return false; - - DataPtr aData = myFeature->data(); - boost::shared_ptr aRef = boost::dynamic_pointer_cast< - ModelAPI_AttributeReference>(aData->attribute(attributeID())); - - ObjectPtr aObject = aRef->value(); - if (!(aObject && aObject->isSame(mySelectedObject))) { - aRef->setValue(mySelectedObject); - updateObject(myFeature); - } - return true; + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + theObject = aSelection->getResult(thePrs); + if (!theObject.get()) + theObject = thePrs->object(); + theShape = aSelection->getShape(thePrs); } //******************************************************************** -bool ModuleBase_WidgetSelector::restoreValue() +bool ModuleBase_WidgetSelector::processSelection() { - DataPtr aData = myFeature->data(); - boost::shared_ptr aRef = aData->reference(attributeID()); + QList aSelected = getFilteredSelected(); + // equal vertices should not be used here + if (myIsPointsFiltering) + ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected); - bool isBlocked = this->blockSignals(true); - mySelectedObject = aRef->value(); - updateSelectionName(); + bool isDone = setSelection(aSelected, true/*false*/); + updateOnSelectionChanged(isDone); - this->blockSignals(isBlocked); - return true; + return isDone; } //******************************************************************** -QList ModuleBase_WidgetSelector::getControls() const +void ModuleBase_WidgetSelector::updateOnSelectionChanged(const bool theDone) { - QList aControls; - aControls.append(myLabel); - aControls.append(myTextLine); - aControls.append(myActivateBtn); - return aControls; + // "false" flag should be used here, it connects to the #26658 OCC bug, when the user click in + // the same place repeatedly without mouse moved. In the case validation by filters is not + // perfromed, so an invalid object is selected. E.g. distance constraint, selection of a point. + // the 3rd click in the same point allow using this point. + emit valuesChanged(); + // the updateObject method should be called to flush the updated sigal. The workshop listens it, + // calls validators for the feature and, as a result, updates the Apply button state. + updateObject(myFeature); + + // we need to forget about previous validation result as the current selection can influence on it + clearValidatedCash(); + + if (theDone) + updateFocus(); } //******************************************************************** -void ModuleBase_WidgetSelector::onSelectionChanged() +QIntList ModuleBase_WidgetSelector::getShapeTypes() const { - QList aObjects = myWorkshop->selectedObjects(); - if (aObjects.size() > 0) { - ObjectPtr aObject = aObjects.first(); - if ((!mySelectedObject) && (!aObject)) - return; - if (mySelectedObject && aObject && mySelectedObject->isSame(aObject)) - return; - - // Check that the selection corresponds to selection type - if (!isAccepted(aObject)) - return; - - mySelectedObject = aObject; - if (mySelectedObject) { - updateSelectionName(); - myActivateBtn->setChecked(false); - raisePanel(); - } else { - myTextLine->setText(""); - } - emit valuesChanged(); - emit focusOutWidget(this); + QIntList aShapeTypes = shapeTypes(); + // this type should be mentioned in XML, poor selection otherwise + if (/*aShapeTypes.contains(TopAbs_SOLID) ||*/ + aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result/*TopAbs_SHAPE*/)) { + // it should be selectable for both, "solids" and "objects" types + aShapeTypes.append(TopAbs_COMPSOLID); } + return aShapeTypes; +} + +//******************************************************************** +QList ModuleBase_WidgetSelector::getAttributeSelection() const +{ + return QList(); } //******************************************************************** -bool ModuleBase_WidgetSelector::isAccepted(const ObjectPtr theResult) const +bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape, + const ResultPtr& theResult) const { - ResultPtr aResult = boost::dynamic_pointer_cast(theResult); - boost::shared_ptr aShapePtr = ModelAPI_Tools::shape(aResult); - if (!aShapePtr) - return false; - TopoDS_Shape aShape = aShapePtr->impl(); - if (aShape.IsNull()) - return false; - - TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); - if (aShapeType == TopAbs_COMPOUND) { - foreach (QString aType, myShapeTypes) { - TopExp_Explorer aEx(aShape, shapeType(aType)); - if (aEx.More()) - return true; + bool aValid = false; + + GeomShapePtr aShape = theShape; + + QIntList aShapeTypes = getShapeTypes(); + if (aShapeTypes.empty()) { + aValid = true; + return aValid; + } + // when the SHAPE type is provided by XML as Object, the whole result shape should be selected. + //if (!aShape.get() && aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result)) { + // In case of selection of a feature aShape could be not NULL, but result has to be selected + if (aShapeTypes.contains(ModuleBase_ResultPrs::Sel_Result)) { + aValid = true; + return aValid; + } + + if (!aShape.get() && theResult.get()) { + if (theResult.get()) + aShape = theResult->shape(); + } + TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE; + if (aShape.get()) { + // Check that the selection corresponds to selection type + TopoDS_Shape aTopoShape = aShape->impl(); + if (!aTopoShape.IsNull()) { + aShapeType = aTopoShape.ShapeType(); + // for compounds check sub-shapes: it may be compound of needed type: + // Booleans may produce compounds of Solids + if (aShapeType == TopAbs_COMPOUND) { + aShapeType = ModuleBase_Tools::getCompoundSubType(aTopoShape); + } } - } else { - foreach (QString aType, myShapeTypes) { - if (shapeType(aType) == aShapeType) - return true; + } + + QIntList::const_iterator anIt = aShapeTypes.begin(), aLast = aShapeTypes.end(); + for (; anIt != aLast && !aValid; anIt++) { + TopAbs_ShapeEnum aCurrentShapeType = (TopAbs_ShapeEnum)*anIt; + if (aShapeType == aCurrentShapeType) + aValid = true; + else if (aCurrentShapeType == TopAbs_FACE) { + // try to process the construction shape only if there is no a selected shape in the viewer + if (!theShape.get() && theResult.get()) { + ResultConstructionPtr aCResult = + std::dynamic_pointer_cast(theResult); + aValid = aCResult.get() && aCResult->facesNum() > 0; + } } } - return false; + return aValid; } //******************************************************************** -void ModuleBase_WidgetSelector::updateSelectionName() +void ModuleBase_WidgetSelector::selectionModes(int& theModuleSelectionModes, QIntList& theModes) { - if (mySelectedObject) { - std::string aName = mySelectedObject->data()->name(); + theModuleSelectionModes = -1; + theModes.append(getShapeTypes()); +} - myTextLine->setText(QString::fromStdString(aName)); - } else - myTextLine->setText(""); +//******************************************************************** +void ModuleBase_WidgetSelector::updateSelectionModesAndFilters(bool toActivate) +{ + updateSelectionName(); + + myWorkshop->selectionActivate()->updateSelectionFilters(); + myWorkshop->selectionActivate()->updateSelectionModes(); + + if (!toActivate) + clearValidatedCash(); +} + +//******************************************************************** +void ModuleBase_WidgetSelector::activateCustom() +{ + // Restore selection in the viewer by the attribute selection list + // it should be postponed to have current widget as active to validate restored selection + static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION); + ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent); } //******************************************************************** -void ModuleBase_WidgetSelector::enableOthersControls(bool toEnable) const +bool ModuleBase_WidgetSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) { - QWidget* aParent = myContainer->parentWidget(); - QList aChldList = aParent->findChildren(); - foreach(QWidget* aWgt, aChldList) - { - if ((aWgt != myLabel) && (aWgt != myActivateBtn) && (aWgt != myTextLine) - && (aWgt != myContainer)) - aWgt->setEnabled(toEnable); + GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs); + ResultPtr aResult = myWorkshop->selection()->getResult(thePrs); + bool aValid = aResult.get(); + if (!isWholeResultAllowed()) + aValid = acceptSubShape(aShape, aResult); + + if (aValid) { + // In order to avoid selection of the same object + ResultPtr aResult = myWorkshop->selection()->getResult(thePrs); + FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aResult); + aValid = aSelectedFeature != myFeature; } + return aValid; } //******************************************************************** -void ModuleBase_WidgetSelector::activateSelection(bool toActivate) +bool ModuleBase_WidgetSelector::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) { - enableOthersControls(!toActivate); - //myTextLine->setEnabled(toActivate); - if (toActivate) - myTextLine->setPalette(myBasePalet); - else - myTextLine->setPalette(myInactivePalet); - - if (toActivate) - connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); - else - disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged())); - - myActivateBtn->setDown(toActivate); + ObjectPtr anObject; + GeomShapePtr aShape; + getGeomSelection(thePrs, anObject, aShape); + + // the last flag is to be depending on hasObject is called before. To be corrected later + return ModuleBase_Tools::setObject(attribute(), anObject, aShape, + myWorkshop, myIsInValidate, true); } //******************************************************************** -void ModuleBase_WidgetSelector::raisePanel() const +void ModuleBase_WidgetSelector::deactivate() { - QWidget* aParent = myContainer->parentWidget(); - QWidget* aLastPanel = 0; - while (!aParent->inherits("QDockWidget")) { - aLastPanel = aParent; - aParent = aParent->parentWidget(); - if (!aParent) - return; + ModuleBase_WidgetValidated::deactivate(); + /// clear temporary cash + AttributePtr anAttribute = attribute(); + if (!anAttribute.get()) + return; + std::string aType = anAttribute->attributeType(); + if (anAttribute->attributeType() == ModelAPI_AttributeSelection::typeId()) { + AttributeSelectionPtr aSelectAttr = + std::dynamic_pointer_cast(anAttribute); + aSelectAttr->removeTemporaryValues(); } - if (aParent->inherits("QDockWidget")) { - QDockWidget* aTabWgt = (QDockWidget*) aParent; - aTabWgt->raise(); + else if (anAttribute->attributeType() == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectAttr = + std::dynamic_pointer_cast(anAttribute); + aSelectAttr->removeTemporaryValues(); } } //******************************************************************** -bool ModuleBase_WidgetSelector::focusTo() +bool ModuleBase_WidgetSelector::isWholeResultAllowed() const { - myActivateBtn->setChecked(true); - return true; + AttributePtr anAttribute = attribute(); + if (anAttribute.get()) { + AttributeSelectionListPtr aSelAttr = + std::dynamic_pointer_cast(anAttribute); + if (aSelAttr.get()) + return aSelAttr->isWholeResultAllowed(); + } + return false; }