1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "ModuleBase_WidgetSelectionFilter.h"
21 #include "ModuleBase_Tools.h"
22 #include "ModuleBase_IWorkshop.h"
23 #include "ModuleBase_ISelectionActivate.h"
24 #include "ModuleBase_IModule.h"
25 #include "ModuleBase_IViewer.h"
26 #include "ModuleBase_IPropertyPanel.h"
27 #include "ModuleBase_PageWidget.h"
28 #include "ModuleBase_WidgetMultiSelector.h"
29 #include "ModuleBase_ResultPrs.h"
30 #include "ModuleBase_WidgetFactory.h"
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_AttributeSelectionList.h>
34 #include <ModelAPI_Events.h>
35 #include <GeomAPI_ShapeExplorer.h>
37 #include <Events_Loop.h>
38 #include <Config_ValidatorReader.h>
40 #include <AIS_InteractiveContext.hxx>
41 #include <StdSelect_BRepOwner.hxx>
42 #include <TopoDS_Compound.hxx>
43 #include <BRep_Builder.hxx>
46 #include <QPushButton>
51 #include <QToolButton>
54 static FeaturePtr SelectorFeature;
55 static std::string AttributeId;
58 GeomAPI_Shape::ShapeType selectionType(const QString& theType)
60 QString aType = theType.toUpper();
61 if ((aType == "VERTEX") || (aType == "VERTICES"))
62 return GeomAPI_Shape::VERTEX;
63 else if ((aType == "EDGE") || (aType == "EDGES"))
64 return GeomAPI_Shape::EDGE;
65 else if ((aType == "WIRE") || (aType == "WIRES"))
66 return GeomAPI_Shape::WIRE;
67 else if ((aType == "FACE") || (aType == "FACES"))
68 return GeomAPI_Shape::FACE;
69 else if ((aType == "SHELL") || (aType == "SHELLS"))
70 return GeomAPI_Shape::SHELL;
71 else if ((aType == "SOLID") || (aType == "SOLIDS"))
72 return GeomAPI_Shape::SOLID;
73 else if ((aType == "COMPSOLID") || (aType == "COMPSOLIDS"))
74 return GeomAPI_Shape::COMPSOLID;
75 else if ((aType == "COMPOUND") || (aType == "COMPOUNDS"))
76 return GeomAPI_Shape::COMPOUND;
78 return GeomAPI_Shape::SHAPE;
82 ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature,
83 QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
85 myFeatureName(theFeature),
86 myWorkshop(theWorkshop)
88 QHBoxLayout* aMainLayout = new QHBoxLayout(this);
89 ModuleBase_Tools::adjustMargins(aMainLayout);
91 aMainLayout->addStretch(1);
92 QPushButton* aLaunchBtn = new QPushButton(tr("Selection by filters"), this);
93 connect(aLaunchBtn, SIGNAL(clicked()), SLOT(onFiltersLaunch()));
94 aMainLayout->addWidget(aLaunchBtn);
96 myFilterLbl = new QLabel(this);
97 myFilterLbl->setPixmap(QPixmap(":pictures/filter.png"));
98 aMainLayout->addWidget(myFilterLbl);
100 myModifyLbl = new QLabel(this);
101 myModifyLbl->setPixmap(QPixmap(":pictures/plus_minus.png"));
102 aMainLayout->addWidget(myModifyLbl);
103 aMainLayout->addStretch(1);
109 void ModuleBase_FilterStarter::onFiltersLaunch()
111 ModuleBase_Operation* aParentOp = myWorkshop->currentOperation();
112 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(aParentOp);
114 // Open transaction on filters operation finish
115 aFeatureOp->openTransactionOnResume();
117 QWidget* aParent = parentWidget();
118 ModuleBase_WidgetMultiSelector* aSelector =
119 dynamic_cast<ModuleBase_WidgetMultiSelector*>(aParent);
121 aParent = aParent->parentWidget();
122 aSelector = dynamic_cast<ModuleBase_WidgetMultiSelector*>(aParent);
126 SelectorFeature = aSelector->feature();
127 AttributeId = aSelector->attributeID();
129 // Launch Filters operation
130 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
131 (myWorkshop->module()->createOperation(myFeatureName));
132 myWorkshop->processLaunchOperation(aFOperation);
135 //*****************************************************************************
136 //*****************************************************************************
137 //*****************************************************************************
138 ModuleBase_FilterItem::ModuleBase_FilterItem(
139 const std::string& theFilter, ModuleBase_WidgetSelectionFilter* theParent)
140 : QWidget(theParent->filtersWidget()), myFilterID(theFilter),
141 mySelection(std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theParent->feature()))
143 std::string aXmlString = ModelAPI_Session::get()->filters()->filter(theFilter)->xmlRepresentation();
144 if (aXmlString.length() == 0)
147 ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop());
148 Config_ValidatorReader aValidatorReader(aXmlString, true);
149 aValidatorReader.setFeatureId(mySelection->getKind());
150 aValidatorReader.readAll();
152 QVBoxLayout* aLayout = new QVBoxLayout(this);
153 ModuleBase_Tools::zeroMargins(aLayout);
155 QWidget* aItemRow = new QWidget(this);
156 addItemRow(aItemRow);
157 aLayout->addWidget(aItemRow);
159 ModuleBase_PageWidget* aParamsWgt = new ModuleBase_PageWidget(this);
160 aParamsWgt->setFrameStyle(QFrame::Box | QFrame::Raised);
161 aFactory.createWidget(aParamsWgt);
162 ModuleBase_Tools::zeroMargins(aParamsWgt->layout());
163 myWidgets = aFactory.getModelWidgets();
164 foreach(ModuleBase_ModelWidget* aWidget, myWidgets) {
165 aWidget->setFeature(theParent->feature());
166 connect(aWidget, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)),
167 theParent, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)));
168 connect(aWidget, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)),
169 theParent, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)));
171 aLayout->addWidget(aParamsWgt);
175 void ModuleBase_FilterItem::addItemRow(QWidget* theParent)
177 QHBoxLayout* aLayout = new QHBoxLayout(theParent);
178 ModuleBase_Tools::zeroMargins(aLayout);
180 // Reverse filter button
181 myRevBtn = new QToolButton(theParent);
182 myRevBtn->setCheckable(true);
183 myRevBtn->setChecked(false);
184 myRevBtn->setAutoRaise(true);
185 myRevBtn->setIcon(QIcon(":pictures/add.png"));
186 myRevBtn->setToolTip(tr("Reverse the filter"));
187 connect(myRevBtn, SIGNAL(toggled(bool)), SLOT(onReverse(bool)));
188 aLayout->addWidget(myRevBtn);
190 const std::string& aFilterName = ModelAPI_Session::get()->filters()->filter(myFilterID)->name();
191 aLayout->addWidget(new QLabel(aFilterName.c_str(), theParent), 1);
193 QToolButton* aDelBtn = new QToolButton(theParent);
194 aDelBtn->setIcon(QIcon(":pictures/delete.png"));
195 aDelBtn->setAutoRaise(true);
196 aDelBtn->setToolTip(tr("Delete the filter"));
197 connect(aDelBtn, SIGNAL(clicked(bool)), SLOT(onDelete()));
198 aLayout->addWidget(aDelBtn);
201 void ModuleBase_FilterItem::onReverse(bool theCheck)
203 mySelection->setReversed(myFilterID, theCheck);
205 myRevBtn->setIcon(QIcon(":pictures/reverce.png"));
207 myRevBtn->setIcon(QIcon(":pictures/add.png"));
208 emit reversedItem(this);
211 void ModuleBase_FilterItem::onDelete()
213 emit deleteItem(this);
216 QList<QWidget*> ModuleBase_FilterItem::getControls() const
218 QList<QWidget*> aWidgetsList;
219 foreach(ModuleBase_ModelWidget* aWgt, myWidgets) {
220 QList<QWidget*> aSubList = aWgt->getControls();
221 foreach(QWidget* aSub, aSubList) {
222 aWidgetsList.append(aSub);
229 //*****************************************************************************
230 //*****************************************************************************
231 //*****************************************************************************
232 ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theParent,
233 ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData)
234 : ModuleBase_ModelWidget(theParent, theData),
235 myWorkshop(theWorkshop),
236 mySelectorFeature(SelectorFeature),
237 mySelectorAttribute(AttributeId)
239 // Clear Old selection
240 AttributePtr aAttr = SelectorFeature->attribute(AttributeId);
241 AttributeSelectionListPtr aSelListAttr =
242 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
243 mySelectionType = selectionType(aSelListAttr->selectionType().c_str());
244 aSelListAttr->clear();
247 QVBoxLayout* aMainLayout = new QVBoxLayout(this);
248 ModuleBase_Tools::adjustMargins(aMainLayout);
250 QGroupBox* aFiltersGroup = new QGroupBox(tr("Filters"), this);
251 QVBoxLayout* aGroupLayout = new QVBoxLayout(aFiltersGroup);
252 aGroupLayout->setContentsMargins(0, 0, 0, 0);
253 aGroupLayout->setSpacing(0);
255 myFiltersWgt = new QWidget();
256 myFiltersLayout = new QVBoxLayout(myFiltersWgt);
257 myFiltersLayout->setContentsMargins(0, 0, 0, 0);
258 aGroupLayout->addWidget(myFiltersWgt);
260 myFiltersCombo = new QComboBox(aFiltersGroup);
261 myFiltersCombo->addItem(tr("Add new filter..."));
262 SessionPtr aSession = ModelAPI_Session::get();
263 std::list<FilterPtr> allFilters =
264 aSession->filters()->filters((GeomAPI_Shape::ShapeType) mySelectionType);
266 std::list<FilterPtr>::const_iterator aIt;
267 for (aIt = allFilters.cbegin(); aIt != allFilters.cend(); aIt++) {
268 aItems.push_back((*aIt)->name().c_str());
269 myFilters.push_back(aSession->filters()->id(*aIt));
271 myFiltersCombo->addItems(aItems);
272 connect(myFiltersCombo, SIGNAL(currentIndexChanged(int)), SLOT(onAddFilter(int)));
274 aGroupLayout->addWidget(myFiltersCombo);
275 aMainLayout->addWidget(aFiltersGroup);
278 QWidget* aBtnWgt = new QWidget(this);
279 QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnWgt);
280 ModuleBase_Tools::adjustMargins(aBtnLayout);
282 aBtnLayout->addStretch(1);
284 mySelectBtn = new QPushButton(tr("Select"), aBtnWgt);
285 connect(mySelectBtn, SIGNAL(clicked()), SLOT(onSelect()));
286 aBtnLayout->addWidget(mySelectBtn);
288 aMainLayout->addWidget(aBtnWgt);
291 QWidget* aLblWgt = new QWidget(this);
292 QHBoxLayout* aLblLayout = new QHBoxLayout(aLblWgt);
293 ModuleBase_Tools::zeroMargins(aLblLayout);
295 aLblLayout->addWidget(new QLabel(tr("Number of selected objects:"), aLblWgt));
297 myNbLbl = new QLabel("0", aLblWgt);
298 aLblLayout->addWidget(myNbLbl);
301 myShowBtn = new QCheckBox(tr("Show only"), this);
302 connect(myShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
303 aLblLayout->addWidget(myShowBtn);
305 aMainLayout->addWidget(aLblWgt);
307 aMainLayout->addStretch(1);
312 ModuleBase_WidgetSelectionFilter::~ModuleBase_WidgetSelectionFilter()
315 if (!myPreview.IsNull()) {
316 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
317 aCtx->Remove(myPreview, false);
319 if (myShowBtn->isChecked()) {
320 AIS_ListOfInteractive::const_iterator aIt;
321 Handle(AIS_Shape) aShapeIO;
322 for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
323 aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
324 if (!aShapeIO.IsNull()) {
325 aCtx->Display(aShapeIO, false);
329 aCtx->UpdateCurrentViewer();
331 SelectorFeature = FeaturePtr();
335 void ModuleBase_WidgetSelectionFilter::onAddFilter(int theIndex)
340 std::list<std::string>::iterator aIt;
343 for (aIt = myFilters.begin(), i = 0; aIt != myFilters.cend(); i++, aIt++) {
344 if (i == (theIndex - 1)) {
346 myFilters.erase(aIt);
350 if (!aFilter.empty()) {
351 myUseFilters.push_back(aFilter);
352 ModuleBase_FilterItem* aItem = new ModuleBase_FilterItem(aFilter, this);
353 connect(aItem, SIGNAL(deleteItem(ModuleBase_FilterItem*)),
354 SLOT(onDeleteItem(ModuleBase_FilterItem*)));
355 connect(aItem, SIGNAL(reversedItem(ModuleBase_FilterItem*)),
356 SLOT(onReverseItem(ModuleBase_FilterItem*)));
357 myFiltersLayout->addWidget(aItem);
359 FiltersFeaturePtr aFiltersFeature =
360 std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
361 aFiltersFeature->addFilter(aFilter);
364 clearCurrentSelection(true);
365 updateNumberSelected();
366 myFiltersCombo->setCurrentIndex(0);
367 myFiltersCombo->removeItem(theIndex);
370 void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theItem)
372 std::string aFilter = theItem->filter();
373 QList<ModuleBase_ModelWidget*> aWidgets = theItem->widgets();
374 foreach(ModuleBase_ModelWidget* aWgt, aWidgets) {
377 myFiltersLayout->removeWidget(theItem);
378 theItem->deleteLater();
380 myUseFilters.remove(aFilter);
381 myFilters.push_back(aFilter);
382 myFiltersCombo->addItem(ModelAPI_Session::get()->filters()->filter(aFilter)->name().c_str());
384 FiltersFeaturePtr aFiltersFeature =
385 std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
386 aFiltersFeature->removeFilter(aFilter);
389 clearCurrentSelection(true);
390 updateNumberSelected();
392 myWorkshop->deactivateCurrentSelector();
393 myWorkshop->selectionActivate()->updateSelectionModes();
394 myWorkshop->selectionActivate()->updateSelectionFilters();
399 void ModuleBase_WidgetSelectionFilter::redisplayFeature()
401 static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
402 ModelAPI_EventCreator::get()->sendUpdated(myFeature, aDispEvent);
403 Events_Loop::loop()->flush(aDispEvent);
406 void ModuleBase_WidgetSelectionFilter::onReverseItem(ModuleBase_FilterItem* theItem)
409 clearCurrentSelection(true);
410 updateNumberSelected();
413 void ModuleBase_WidgetSelectionFilter::onSelect()
415 if (myUseFilters.size() == 0)
417 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
421 clearCurrentSelection();
423 BRep_Builder aBuilder;
424 TopoDS_Compound aComp;
425 aBuilder.MakeCompound(aComp);
427 if (!myShowBtn->isChecked()) {
429 aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO);
430 if (!myPreview.IsNull())
431 myListIO.Remove(myPreview);
433 AIS_ListOfInteractive::const_iterator aIt;
434 Handle(ModuleBase_ResultPrs) aShapeIO;
435 for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
436 aShapeIO = Handle(ModuleBase_ResultPrs)::DownCast(*aIt);
437 if (!aShapeIO.IsNull()) {
438 GeomShapePtr aShape(new GeomAPI_Shape);
439 aShape->setImpl(new TopoDS_Shape(aShapeIO->Shape()));
440 std::list<GeomShapePtr> aSubShapes =
441 aShape->subShapes((GeomAPI_Shape::ShapeType)mySelectionType);
442 std::list<GeomShapePtr>::const_iterator aShapesIt;
443 for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) {
444 GeomShapePtr aShape = (*aShapesIt);
445 SessionPtr aSession = ModelAPI_Session::get();
446 bool isValid = aSession->filters()->isValid(myFeature, aShape);
448 TopoDS_Shape aTShape = aShape->impl<TopoDS_Shape>();
449 Handle(StdSelect_BRepOwner) aOwner = new StdSelect_BRepOwner(aTShape, aShapeIO, true);
450 aBuilder.Add(aComp, aTShape);
452 ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aShapeIO->getResult(), aShape, aOwner));
453 myValues.append(aValue);
458 if (myValues.size() > 0)
459 updatePreview(aComp);
460 updateNumberSelected();
463 void ModuleBase_WidgetSelectionFilter::updatePreview(const TopoDS_Shape& theShape)
465 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
469 if (myPreview.IsNull()) {
470 myPreview = new AIS_Shape(theShape);
471 //myPreview->SetDisplayMode(myShowBtn->isChecked()? AIS_Shaded : AIS_WireFrame);
472 myPreview->SetDisplayMode(AIS_Shaded);
473 myPreview->SetColor(Quantity_NOC_BLUE1);
474 myPreview->SetTransparency();
475 aCtx->Display(myPreview, true);
476 aCtx->Deactivate(myPreview);
479 myPreview->Set(theShape);
480 aCtx->Redisplay(myPreview, true);
485 void ModuleBase_WidgetSelectionFilter::onShowOnly(bool theShow)
487 if (myPreview.IsNull())
489 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
493 aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO);
494 myListIO.Remove(myPreview);
496 AIS_ListOfInteractive::const_iterator aIt;
497 Handle(AIS_Shape) aShapeIO;
498 for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
499 aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
500 if (!aShapeIO.IsNull()) {
502 aCtx->Erase(aShapeIO, false);
504 aCtx->Display(aShapeIO, false);
507 aCtx->UpdateCurrentViewer();
510 void ModuleBase_WidgetSelectionFilter::updateSelectBtn()
512 mySelectBtn->setEnabled(myUseFilters.size() > 0);
515 void ModuleBase_WidgetSelectionFilter::updateNumberSelected()
517 myNbLbl->setText(QString::number(myValues.size()));
519 QList<QWidget*> ModuleBase_WidgetSelectionFilter::getControls() const
521 QList<QWidget*> aWidgets;
522 QList<ModuleBase_FilterItem*> aItems = myFiltersWgt->findChildren<ModuleBase_FilterItem*>();
523 foreach(ModuleBase_FilterItem* aItem, aItems) {
524 QList<QWidget*> aSubList = aItem->getControls();
525 foreach(QWidget* aWgt, aSubList) {
526 aWidgets.append(aWgt);
532 void ModuleBase_WidgetSelectionFilter::clearCurrentSelection(bool toUpdate)
535 if (!myPreview.IsNull()) {
536 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
537 aCtx->Remove(myPreview, toUpdate);
542 void ModuleBase_WidgetSelectionFilter::onFeatureAccepted()
544 AttributePtr aAttr = mySelectorFeature->attribute(mySelectorAttribute);
545 AttributeSelectionListPtr aSelListAttr =
546 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
547 aSelListAttr->clear();
548 foreach(ModuleBase_ViewerPrsPtr aPrs, myValues) {
549 aSelListAttr->append(aPrs->object(), aPrs->shape());
553 bool ModuleBase_WidgetSelectionFilter::storeValueCustom()
558 bool ModuleBase_WidgetSelectionFilter::restoreValueCustom()
560 ModuleBase_ModelWidget* aActive = myWorkshop->propertyPanel()->activeWidget();
562 return aActive->restoreValue();