-// File: ModuleBase_WidgetSelector.h
-// Created: 2 June 2014
-// Author: Vitaly Smetannikov
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+// File: ModuleBase_WidgetSelector.cpp
+// Created: 19 June 2015
+// Author: Natalia ERMOLAEVA
-#include "ModuleBase_WidgetSelector.h"
-#include "ModuleBase_IWorkshop.h"
-#include "ModuleBase_Tools.h"
+#include <ModuleBase_WidgetSelector.h>
-#include <Events_Loop.h>
-#include <ModelAPI_Events.h>
+#include <ModuleBase_ISelection.h>
+#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_Operation.h>
+#include <ModuleBase_OperationDescription.h>
+#include <ModuleBase_WidgetFactory.h>
+#include <ModuleBase_IModule.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_Object.h>
-#include <ModelAPI_Result.h>
-#include <ModelAPI_AttributeReference.h>
-#include <Config_WidgetAPI.h>
+#include <ModelAPI_ResultConstruction.h>
-#include <GeomAPI_Shape.h>
+#include <TopoDS_Iterator.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopExp_Explorer.hxx>
-
-#include <QWidget>
-#include <QLayout>
-#include <QLabel>
-#include <QLineEdit>
-#include <QToolButton>
-#include <QString>
-#include <QEvent>
-#include <QDockWidget>
-
-#include <stdexcept>
-
-
-typedef QMap<QString, TopAbs_ShapeEnum> 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!");
-}
-
-
-
-
-ModuleBase_WidgetSelector::ModuleBase_WidgetSelector(QWidget* theParent,
- ModuleBase_IWorkshop* theWorkshop,
+ModuleBase_WidgetSelector::ModuleBase_WidgetSelector(QWidget* theParent,
+ ModuleBase_IWorkshop* theWorkshop,
const Config_WidgetAPI* theData,
const std::string& theParentId)
-: ModuleBase_ModelWidget(theParent, theData, theParentId), myWorkshop(theWorkshop), myActivateOnStart(false)
+ : ModuleBase_WidgetValidated(theParent, theWorkshop, theData, theParentId)
{
- 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);
- 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);
-
- aLayout->addWidget(myTextLine);
-
- 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);
-
- QString aActivateTxt = QString::fromStdString(theData->getProperty("activate"));
- if (!aActivateTxt.isNull()) {
- myActivateOnStart = (aActivateTxt == "true");
- }
-
- std::string aTypes = theData->getProperty("shape_types");
- myShapeTypes = QString(aTypes.c_str()).split(',');
}
//********************************************************************
}
//********************************************************************
-bool ModuleBase_WidgetSelector::storeValue(ObjectPtr theObject) const
+void ModuleBase_WidgetSelector::getGeomSelection(const ModuleBase_ViewerPrs& thePrs,
+ ObjectPtr& theObject,
+ GeomShapePtr& theShape)
{
- FeaturePtr aSelectedFeature = ModuleBase_Tools::feature(mySelectedObject);
- if (aSelectedFeature == theObject) // In order to avoid selection of the same object
- return false;
-
- DataPtr aData = theObject->data();
- boost::shared_ptr<ModelAPI_AttributeReference> aRef =
- boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(aData->attribute(attributeID()));
-
- ObjectPtr aObject = aRef->value();
- if (!(aObject && aObject->isSame(mySelectedObject))) {
- aRef->setValue(mySelectedObject);
- updateObject(theObject);
- }
- return true;
+ ModuleBase_ISelection* aSelection = myWorkshop->selection();
+ theObject = aSelection->getResult(thePrs);
+ theShape = aSelection->getShape(thePrs);
}
//********************************************************************
-bool ModuleBase_WidgetSelector::restoreValue(ObjectPtr theObject)
+void ModuleBase_WidgetSelector::onSelectionChanged()
{
- DataPtr aData = theObject->data();
- boost::shared_ptr<ModelAPI_AttributeReference> aRef = aData->reference(attributeID());
-
- bool isBlocked = this->blockSignals(true);
- mySelectedObject = aRef->value();
- updateSelectionName();
-
- this->blockSignals(isBlocked);
- return true;
+ QList<ModuleBase_ViewerPrs> aSelected = getFilteredSelected();
+
+ bool isDone = setSelection(aSelected, true/*false*/);
+ // "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 (isDone)
+ updateFocus();
}
//********************************************************************
-QList<QWidget*> ModuleBase_WidgetSelector::getControls() const
+bool ModuleBase_WidgetSelector::acceptSubShape(const GeomShapePtr& theShape,
+ const ResultPtr& theResult) const
{
- QList<QWidget*> aControls;
- aControls.append(myLabel);
- aControls.append(myTextLine);
- aControls.append(myActivateBtn);
- return aControls;
-}
+ bool aValid = false;
-//********************************************************************
-void ModuleBase_WidgetSelector::onSelectionChanged()
-{
- QList<ObjectPtr> aObjects = myWorkshop->selectedObjects();
- if (aObjects.size() > 0) {
- ObjectPtr aObject = aObjects.first();
- if ((!mySelectedObject) && (!aObject))
- return;
- if (mySelectedObject && aObject && mySelectedObject->isSame(aObject))
- return;
+ GeomShapePtr aShape = theShape;
+
+ QIntList aShapeTypes = getShapeTypes();
+ if (aShapeTypes.empty()) {
+ aValid = true;
+ return aValid;
+ }
+ // when the SHAPE type is provided by XML, the hole result shape can be selected.
+ if (!aShape.get() && aShapeTypes.contains(TopAbs_SHAPE)) {
+ 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
- if (!isAccepted(aObject)) return;
+ TopoDS_Shape aTopoShape = aShape->impl<TopoDS_Shape>();
+ 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);
+ }
+ }
- mySelectedObject = aObject;
- if (mySelectedObject) {
- updateSelectionName();
- myActivateBtn->setChecked(false);
- raisePanel();
- } else {
- myTextLine->setText("");
+ QIntList::const_iterator anIt = aShapeTypes.begin(), aLast = aShapeTypes.end();
+ for (; anIt != aLast; anIt++) {
+ if (aShapeType == *anIt)
+ aValid = true;
+ else if (*anIt == 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<ModelAPI_ResultConstruction>(theResult);
+ aValid = aCResult.get() && aCResult->facesNum() > 0;
+ }
}
- emit valuesChanged();
}
+ return aValid;
}
//********************************************************************
-bool ModuleBase_WidgetSelector::isAccepted(const ObjectPtr theResult) const
+bool ModuleBase_WidgetSelector::activateSelectionAndFilters(bool toActivate)
{
- ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theResult);
- boost::shared_ptr<GeomAPI_Shape> aShapePtr = ModuleBase_Tools::shape(aResult);
- if (!aShapePtr) return false;
- TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
- if (aShape.IsNull()) return false;
+ updateSelectionName();
- TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
- if (aShapeType == TopAbs_COMPOUND) {
- foreach (QString aType, myShapeTypes) {
- TopExp_Explorer aEx(aShape, shapeType(aType));
- if (aEx.More())
- return true;
- }
+ if (toActivate) {
+ myWorkshop->activateSubShapesSelection(getShapeTypes());
} else {
- foreach (QString aType, myShapeTypes) {
- if (shapeType(aType) == aShapeType)
- return true;
- }
+ myWorkshop->deactivateSubShapesSelection();
}
- return false;
+ return activateFilters(toActivate);
}
//********************************************************************
-void ModuleBase_WidgetSelector::updateSelectionName()
+void ModuleBase_WidgetSelector::activateCustom()
{
- if (mySelectedObject) {
- std::string aName = mySelectedObject->data()->name();
-
- myTextLine->setText(QString::fromStdString(aName));
- } else
- myTextLine->setText("");
+ connect(myWorkshop, SIGNAL(selectionChanged()), this,
+ SLOT(onSelectionChanged()), Qt::UniqueConnection);
+
+ activateSelectionAndFilters(true);
+
+ // Restore selection in the viewer by the attribute selection list
+ myWorkshop->setSelected(getAttributeSelection());
}
//********************************************************************
-bool ModuleBase_WidgetSelector::eventFilter(QObject* theObj, QEvent* theEvent)
+bool ModuleBase_WidgetSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
{
- if (theObj == myTextLine) {
- if (theEvent->type() == QEvent::Polish) {
- myActivateBtn->setChecked(myActivateOnStart);
- onSelectionChanged();
- }
+ GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
+ ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
+ bool 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 ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
+ return aValid;
}
//********************************************************************
-void ModuleBase_WidgetSelector::enableOthersControls(bool toEnable) const
+bool ModuleBase_WidgetSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
{
- QWidget* aParent = myContainer->parentWidget();
- QList<QWidget*> aChldList = aParent->findChildren<QWidget*>();
- foreach(QWidget* aWgt, aChldList) {
- if ((aWgt != myLabel) && (aWgt != myActivateBtn) && (aWgt != myTextLine) && (aWgt != myContainer))
- aWgt->setEnabled(toEnable);
- }
+ ObjectPtr anObject;
+ GeomShapePtr aShape;
+ getGeomSelection(thePrs, anObject, aShape);
+
+ setObject(anObject, aShape);
+ return true;
}
//********************************************************************
-void ModuleBase_WidgetSelector::activateSelection(bool toActivate)
+void ModuleBase_WidgetSelector::deactivate()
{
- enableOthersControls(!toActivate);
- myTextLine->setEnabled(toActivate);
-
- if (toActivate)
- connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
- else
- disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-
- myActivateBtn->setDown(toActivate);
+ ModuleBase_ModelWidget::deactivate();
+ disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
+ activateSelectionAndFilters(false);
+ ModuleBase_ModelWidget::deactivate();
}
//********************************************************************
-void ModuleBase_WidgetSelector::raisePanel() const
+std::string ModuleBase_WidgetSelector::generateName(const AttributePtr& theAttribute,
+ ModuleBase_IWorkshop* theWorkshop)
{
- QWidget* aParent = myContainer->parentWidget();
- QWidget* aLastPanel = 0;
- while (!aParent->inherits("QDockWidget")) {
- aLastPanel = aParent;
- aParent = aParent->parentWidget();
- if (!aParent) return;
- }
- if (aParent->inherits("QDockWidget")) {
- QDockWidget* aTabWgt = (QDockWidget*) aParent;
- aTabWgt->raise();
+ std::string aName;
+ if (theAttribute.get() != NULL) {
+ ModuleBase_Operation* anOperation = theWorkshop->currentOperation();
+
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
+ if (aFeature.get()) {
+ std::string aXmlCfg, aDescription;
+ theWorkshop->module()->getXMLRepresentation(aFeature->getKind(), aXmlCfg, aDescription);
+
+ ModuleBase_WidgetFactory aFactory(aXmlCfg, theWorkshop);
+ std::string anAttributeTitle;
+ aFactory.getAttributeTitle(aFeature->getKind(), theAttribute->id(), anAttributeTitle);
+
+ std::stringstream aStreamName;
+ aStreamName << theAttribute->owner()->data()->name() << "/"<< anAttributeTitle.c_str();
+ aName = aStreamName.str();
+ }
}
+ return aName;
}