From c592505cb44ca42c78843547f4def5052af20e15 Mon Sep 17 00:00:00 2001 From: vsv Date: Thu, 15 Nov 2018 18:04:17 +0300 Subject: [PATCH] Make selection --- src/CollectionPlugin/CMakeLists.txt | 1 + src/Filters/Filters_HorizontalPlane.cpp | 2 +- src/Filters/Filters_HorizontalPlane.h | 2 + src/Filters/Filters_VerticalPlane.cpp | 4 +- src/Filters/Filters_VerticalPlane.h | 2 + src/ModelAPI/ModelAPI_Filter.h | 26 ++- .../ModuleBase_WidgetSelectionFilter.cpp | 202 +++++++++++++++++- .../ModuleBase_WidgetSelectionFilter.h | 23 ++ 8 files changed, 249 insertions(+), 13 deletions(-) diff --git a/src/CollectionPlugin/CMakeLists.txt b/src/CollectionPlugin/CMakeLists.txt index 674ea7e08..93d9b5203 100644 --- a/src/CollectionPlugin/CMakeLists.txt +++ b/src/CollectionPlugin/CMakeLists.txt @@ -36,6 +36,7 @@ SET(PROJECT_HEADERS CollectionPlugin_WidgetCreator.h CollectionPlugin_WidgetField.h CollectionPlugin_Validators.h + CollectionPlugin_GroupFilters.h ) SET(PROJECT_MOC_HEADERS diff --git a/src/Filters/Filters_HorizontalPlane.cpp b/src/Filters/Filters_HorizontalPlane.cpp index 13d5595cc..13012a5f0 100644 --- a/src/Filters/Filters_HorizontalPlane.cpp +++ b/src/Filters/Filters_HorizontalPlane.cpp @@ -30,7 +30,7 @@ bool Filters_HorizontalPlane::isOk(const GeomShapePtr& theShape) const if (!theShape->isPlanar()) return false; - GeomFacePtr aFace = std::dynamic_pointer_cast(theShape); + GeomFacePtr aFace(new GeomAPI_Face(theShape)); GeomPlanePtr aPlane = aFace->getPlane(); GeomDirPtr aDir = aPlane->direction(); diff --git a/src/Filters/Filters_HorizontalPlane.h b/src/Filters/Filters_HorizontalPlane.h index e5ad861f5..cca9a8816 100644 --- a/src/Filters/Filters_HorizontalPlane.h +++ b/src/Filters/Filters_HorizontalPlane.h @@ -28,6 +28,8 @@ class Filters_HorizontalPlane : public ModelAPI_Filter { public: + Filters_HorizontalPlane() : ModelAPI_Filter() {} + virtual bool isOk(const GeomShapePtr& theShape) const; /// Returns list of supported types of shapes (see GeomAPI_Shape::ShapeType) diff --git a/src/Filters/Filters_VerticalPlane.cpp b/src/Filters/Filters_VerticalPlane.cpp index 48334749d..ac09a7239 100644 --- a/src/Filters/Filters_VerticalPlane.cpp +++ b/src/Filters/Filters_VerticalPlane.cpp @@ -30,11 +30,11 @@ bool Filters_VerticalPlane::isOk(const GeomShapePtr& theShape) const if (!theShape->isPlanar()) return false; - GeomFacePtr aFace = std::dynamic_pointer_cast(theShape); + GeomFacePtr aFace(new GeomAPI_Face(theShape)); GeomPlanePtr aPlane = aFace->getPlane(); GeomDirPtr aDir = aPlane->direction(); - if (aDir->z() <= 1.e-7) + if (fabs(aDir->z()) <= 1.e-7) return true; return false; } diff --git a/src/Filters/Filters_VerticalPlane.h b/src/Filters/Filters_VerticalPlane.h index 2dc201fd5..69fb248b2 100644 --- a/src/Filters/Filters_VerticalPlane.h +++ b/src/Filters/Filters_VerticalPlane.h @@ -28,6 +28,8 @@ class Filters_VerticalPlane : public ModelAPI_Filter { public: + Filters_VerticalPlane() : ModelAPI_Filter() {} + virtual bool isOk(const GeomShapePtr& theShape) const; /// Returns list of supported types of shapes (see GeomAPI_Shape::ShapeType) diff --git a/src/ModelAPI/ModelAPI_Filter.h b/src/ModelAPI/ModelAPI_Filter.h index 660cb2692..76f3549ce 100644 --- a/src/ModelAPI/ModelAPI_Filter.h +++ b/src/ModelAPI/ModelAPI_Filter.h @@ -43,13 +43,11 @@ public: ObjectParameter }; + ModelAPI_Filter(): myIsReverse(false) {} + /// Returns name of the filter to represent it in GUI virtual std::string name() const = 0; - /// Returns true if the given shape is accepted by filter - /// \param theShape the given shape - virtual bool isOk(const GeomShapePtr& theShape) const = 0; - /// Returns list of supported types of shapes (see GeomAPI_Shape::ShapeType) virtual std::list shapeTypes() const = 0; @@ -77,6 +75,26 @@ public: /// Returns shape parameter type. Types from GeomAPI_Shape have to be used. /// A type GeomAPI_Shape::SHAPE means any shape virtual int shapeParameterType() const { return GeomAPI_Shape::SHAPE; } + + /// Set reversed flag for the filter + void setReversed(bool theRev) { myIsReverse = theRev; } + + bool isReversed() const { return myIsReverse; } + + bool isValid(const GeomShapePtr& theShape) + { + if (myIsReverse) + return !isOk(theShape); + return isOk(theShape); + } + +protected: + /// Returns true if the given shape is accepted by filter + /// \param theShape the given shape + virtual bool isOk(const GeomShapePtr& theShape) const = 0; + +private: + bool myIsReverse; }; typedef std::shared_ptr FilterPtr; diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp index 7f91db2b3..07d0ff4d5 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp @@ -22,11 +22,18 @@ #include "ModuleBase_Tools.h" #include "ModuleBase_IWorkshop.h" #include "ModuleBase_IModule.h" +#include "ModuleBase_IViewer.h" #include "ModuleBase_IPropertyPanel.h" #include "ModuleBase_PageWidget.h" -#include "ModuleBase_WidgetSelector.h" +#include "ModuleBase_WidgetMultiSelector.h" #include +#include + +#include +#include +#include +#include #include #include @@ -68,8 +75,11 @@ ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature void ModuleBase_FilterStarter::onFiltersLaunch() { SelectionType = myShapeType; - ModuleBase_WidgetSelector* aSelector = dynamic_cast(parent()); + ModuleBase_WidgetMultiSelector* aSelector = + dynamic_cast(parent()); + aSelector->onSelectionTypeChanged(); // In order to clear current selection aSelector->storeValue(); // Store values defined by user + ModuleBase_OperationFeature* aFOperation = dynamic_cast (myWorkshop->module()->createOperation(myFeatureName)); myWorkshop->processLaunchOperation(aFOperation); @@ -113,6 +123,7 @@ ModuleBase_FilterItem::ModuleBase_FilterItem(const FilterPtr& theFilter, QWidget myRevBtn->setChecked(false); myRevBtn->setAutoRaise(true); myRevBtn->setIcon(QIcon(":pictures/accept.png")); + myRevBtn->setToolTip(tr("Reverse the filter")); connect(myRevBtn, SIGNAL(toggled(bool)), SLOT(onReverse(bool))); aLayout->addWidget(myRevBtn); @@ -121,13 +132,17 @@ ModuleBase_FilterItem::ModuleBase_FilterItem(const FilterPtr& theFilter, QWidget QToolButton* aDelBtn = new QToolButton(this); aDelBtn->setIcon(QIcon(":pictures/button_cancel.png")); aDelBtn->setAutoRaise(true); + aDelBtn->setToolTip(tr("Delete the filter")); connect(aDelBtn, SIGNAL(clicked(bool)), SLOT(onDelete())); aLayout->addWidget(aDelBtn); + + myRevBtn->setChecked(myFilter->isReversed()); } void ModuleBase_FilterItem::onReverse(bool theCheck) { + myFilter->setReversed(theCheck); if (theCheck) myRevBtn->setIcon(QIcon(":pictures/stop.png")); else @@ -148,6 +163,8 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP : ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop), mySelectionType(SelectionType) { + myOwners = new SelectMgr_IndexedMapOfOwner(); + QVBoxLayout* aMainLayout = new QVBoxLayout(this); ModuleBase_Tools::adjustMargins(aMainLayout); @@ -176,7 +193,7 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP QToolButton* aAddBtn = new QToolButton(aFiltersWgt); aAddBtn->setIcon(QIcon(":pictures/add.png")); aAddBtn->setAutoRaise(true); - aAddBtn->setToolTip(tr("Add current filter")); + aAddBtn->setToolTip(tr("Add the current filter")); connect(aAddBtn, SIGNAL(clicked()), SLOT(onAddItem())); aFiltersLay->addWidget(aFilterLbl); @@ -187,21 +204,70 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP aMainLayout->addWidget(myFiltersGroup); + // Select Button QWidget* aBtnWgt = new QWidget(this); QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnWgt); ModuleBase_Tools::adjustMargins(aBtnLayout); aBtnLayout->addStretch(1); - QPushButton* aSelectBtn = new QPushButton(tr("Select"), aBtnWgt); - connect(aSelectBtn, SIGNAL(clicked()), SLOT(onSelect())); - aBtnLayout->addWidget(aSelectBtn); + mySelectBtn = new QPushButton(tr("Select"), aBtnWgt); + connect(mySelectBtn, SIGNAL(clicked()), SLOT(onSelect())); + aBtnLayout->addWidget(mySelectBtn); aMainLayout->addWidget(aBtnWgt); + // Label widgets + QWidget* aLblWgt = new QWidget(this); + QHBoxLayout* aLblLayout = new QHBoxLayout(aLblWgt); + ModuleBase_Tools::adjustMargins(aLblLayout); + + aLblLayout->addWidget(new QLabel(tr("Number of selected objects:"), aLblWgt)); + + myNbLbl = new QLabel("0", aLblWgt); + aLblLayout->addWidget(myNbLbl); + + aMainLayout->addWidget(aLblWgt); + + // Show only button + QWidget* aBtn2Wgt = new QWidget(this); + QHBoxLayout* aBtn2Layout = new QHBoxLayout(aBtn2Wgt); + ModuleBase_Tools::adjustMargins(aBtn2Layout); + + aBtn2Layout->addStretch(1); + + myShowBtn = new QPushButton(tr("Show only"), aBtn2Wgt); + myShowBtn->setCheckable(true); + connect(myShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool))); + aBtn2Layout->addWidget(myShowBtn); + + aMainLayout->addWidget(aBtn2Wgt); + aMainLayout->addStretch(1); + + updateSelectBtn(); } +ModuleBase_WidgetSelectionFilter::~ModuleBase_WidgetSelectionFilter() +{ + myOwners.Nullify(); + if ((!myPreview.IsNull()) && myShowBtn->isChecked()) { + Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext(); + aCtx->Remove(myPreview, false); + myPreview.Nullify(); + AIS_ListOfInteractive::const_iterator aIt; + Handle(AIS_Shape) aShapeIO; + for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) { + aShapeIO = Handle(AIS_Shape)::DownCast(*aIt); + if (!aShapeIO.IsNull()) { + aCtx->Display(aShapeIO, false); + } + } + aCtx->UpdateCurrentViewer(); + } +} + + void ModuleBase_WidgetSelectionFilter::onAddItem() { int aId = myFiltersCombo->currentIndex(); @@ -224,6 +290,9 @@ void ModuleBase_WidgetSelectionFilter::onAddItem() SLOT(onDeleteItem(ModuleBase_FilterItem*))); myGroupLayout->addWidget(aItem); } + updateSelectBtn(); + clearCurrentSelection(true); + updateNumberSelected(); } void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theItem) @@ -235,14 +304,135 @@ void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theIt myUseFilters.remove(aFilter); myFilters.push_back(aFilter); myFiltersCombo->addItem(aFilter->name().c_str()); + + updateSelectBtn(); + clearCurrentSelection(true); + updateNumberSelected(); } void ModuleBase_WidgetSelectionFilter::onSelect() { + if (myUseFilters.size() == 0) + return; + Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext(); + if (aCtx.IsNull()) + return; + + clearCurrentSelection(); + + BRep_Builder aBuilder; + TopoDS_Compound aComp; + aBuilder.MakeCompound(aComp); + + if (!myShowBtn->isChecked()) { + aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO); + if (!myPreview.IsNull()) + myListIO.Remove(myPreview); + } + AIS_ListOfInteractive::const_iterator aIt; + Handle(AIS_Shape) aShapeIO; + for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) { + aShapeIO = Handle(AIS_Shape)::DownCast(*aIt); + if (!aShapeIO.IsNull()) { + GeomShapePtr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aShapeIO->Shape())); + std::list aSubShapes = + aShape->subShapes((GeomAPI_Shape::ShapeType)mySelectionType); + std::list::const_iterator aShapesIt; + for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) { + GeomShapePtr aShape = (*aShapesIt); + bool isValid = true; + std::list::const_iterator aFilterIt; + for (aFilterIt = myUseFilters.cbegin(); aFilterIt != myUseFilters.cend(); aFilterIt++) { + if (!(*aFilterIt)->isValid(aShape)) { + isValid = false; + break; + } + } + if (isValid) { + TopoDS_Shape aTShape = aShape->impl(); + Handle(StdSelect_BRepOwner) aOwner = new StdSelect_BRepOwner(aTShape, aShapeIO, true); + myOwners->Add(aOwner); + aBuilder.Add(aComp, aTShape); + } + } + } + } + if (myOwners->Size() > 0) + updatePreview(aComp); + updateNumberSelected(); +} + +void ModuleBase_WidgetSelectionFilter::updatePreview(const TopoDS_Shape& theShape) +{ + Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext(); + if (aCtx.IsNull()) + return; + + if (myPreview.IsNull()) { + myPreview = new AIS_Shape(theShape); + myPreview->SetDisplayMode(myShowBtn->isChecked()? AIS_Shaded : AIS_WireFrame); + myPreview->SetColor(Quantity_NOC_YELLOW); + myPreview->SetTransparency(); + aCtx->Display(myPreview, true); + aCtx->Deactivate(myPreview); + } + else { + myPreview->Set(theShape); + aCtx->Redisplay(myPreview, true); + } +} + + +void ModuleBase_WidgetSelectionFilter::onShowOnly(bool theErase) +{ + if (myPreview.IsNull()) + return; + Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext(); + + if (theErase) { + aCtx->SetDisplayMode(myPreview, AIS_Shaded, false); + myListIO.Clear(); + aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO); + myListIO.Remove(myPreview); + } + else { + aCtx->SetDisplayMode(myPreview, AIS_WireFrame, false); + } + AIS_ListOfInteractive::const_iterator aIt; + Handle(AIS_Shape) aShapeIO; + for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) { + aShapeIO = Handle(AIS_Shape)::DownCast(*aIt); + if (!aShapeIO.IsNull()) { + if (theErase) + aCtx->Erase(aShapeIO, false); + else + aCtx->Display(aShapeIO, false); + } + } + aCtx->UpdateCurrentViewer(); +} +void ModuleBase_WidgetSelectionFilter::updateSelectBtn() +{ + mySelectBtn->setEnabled(myUseFilters.size() > 0); } +void ModuleBase_WidgetSelectionFilter::updateNumberSelected() +{ + myNbLbl->setText(QString::number(myOwners->Size())); +} QList ModuleBase_WidgetSelectionFilter::getControls() const { return QList(); } + +void ModuleBase_WidgetSelectionFilter::clearCurrentSelection(bool toUpdate) +{ + myOwners->Clear(); + if (!myPreview.IsNull()) { + Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext(); + aCtx->Remove(myPreview, toUpdate); + myPreview.Nullify(); + } +} diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h index 842f236a5..797af8a99 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h +++ b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h @@ -25,6 +25,11 @@ #include "ModuleBase_ModelWidget.h" #include + +#include +#include +#include + #include class QLabel; @@ -32,6 +37,7 @@ class QComboBox; class QGroupBox; class QToolButton; class QVBoxLayout; +class QPushButton; class ModuleBase_IWorkshop; @@ -86,6 +92,8 @@ public: ModuleBase_WidgetSelectionFilter(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData); + ~ModuleBase_WidgetSelectionFilter(); + /// Returns list of widget controls /// \return a control list virtual QList getControls() const; @@ -102,6 +110,13 @@ private slots: void onAddItem(); void onDeleteItem(ModuleBase_FilterItem* theItem); void onSelect(); + void onShowOnly(bool theErase); + +private: + void updateSelectBtn(); + void updateNumberSelected(); + void clearCurrentSelection(bool toUpdate = false); + void updatePreview(const TopoDS_Shape& theShape); private: ModuleBase_IWorkshop* myWorkshop; @@ -109,10 +124,18 @@ private: QComboBox* myFiltersCombo; QGroupBox* myFiltersGroup; QVBoxLayout* myGroupLayout; + QPushButton* mySelectBtn; + QLabel* myNbLbl; + QPushButton* myShowBtn; int mySelectionType; std::list myFilters; std::list myUseFilters; + + Handle(SelectMgr_IndexedMapOfOwner) myOwners; + Handle(AIS_Shape) myPreview; + + AIS_ListOfInteractive myListIO; }; -- 2.39.2