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>
39 #include <AIS_InteractiveContext.hxx>
40 #include <StdSelect_BRepOwner.hxx>
41 #include <TopoDS_Compound.hxx>
42 #include <BRep_Builder.hxx>
45 #include <QPushButton>
50 #include <QToolButton>
53 static FeaturePtr SelectorFeature;
54 static std::string AttributeId;
57 GeomAPI_Shape::ShapeType selectionType(const QString& theType)
59 QString aType = theType.toUpper();
60 if ((aType == "VERTEX") || (aType == "VERTICES"))
61 return GeomAPI_Shape::VERTEX;
62 else if ((aType == "EDGE") || (aType == "EDGES"))
63 return GeomAPI_Shape::EDGE;
64 else if ((aType == "WIRE") || (aType == "WIRES"))
65 return GeomAPI_Shape::WIRE;
66 else if ((aType == "FACE") || (aType == "FACES"))
67 return GeomAPI_Shape::FACE;
68 else if ((aType == "SHELL") || (aType == "SHELLS"))
69 return GeomAPI_Shape::SHELL;
70 else if ((aType == "SOLID") || (aType == "SOLIDS"))
71 return GeomAPI_Shape::SOLID;
72 else if ((aType == "COMPSOLID") || (aType == "COMPSOLIDS"))
73 return GeomAPI_Shape::COMPSOLID;
74 else if ((aType == "COMPOUND") || (aType == "COMPOUNDS"))
75 return GeomAPI_Shape::COMPOUND;
77 return GeomAPI_Shape::SHAPE;
81 ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature,
82 QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
84 myFeatureName(theFeature),
85 myWorkshop(theWorkshop)
87 QHBoxLayout* aMainLayout = new QHBoxLayout(this);
88 ModuleBase_Tools::adjustMargins(aMainLayout);
90 aMainLayout->addStretch(1);
91 QPushButton* aLaunchBtn = new QPushButton(tr("Selection by filters"), this);
92 connect(aLaunchBtn, SIGNAL(clicked()), SLOT(onFiltersLaunch()));
93 aMainLayout->addWidget(aLaunchBtn);
95 myFilterLbl = new QLabel(this);
96 myFilterLbl->setPixmap(QPixmap(":pictures/filter.png"));
97 aMainLayout->addWidget(myFilterLbl);
99 myModifyLbl = new QLabel(this);
100 myModifyLbl->setPixmap(QPixmap(":pictures/plus_minus.png"));
101 aMainLayout->addWidget(myModifyLbl);
102 aMainLayout->addStretch(1);
108 void ModuleBase_FilterStarter::onFiltersLaunch()
110 ModuleBase_Operation* aParentOp = myWorkshop->currentOperation();
111 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(aParentOp);
113 // Open transaction on filters operation finish
114 aFeatureOp->openTransactionOnResume();
116 QWidget* aParent = parentWidget();
117 ModuleBase_WidgetMultiSelector* aSelector =
118 dynamic_cast<ModuleBase_WidgetMultiSelector*>(aParent);
120 aParent = aParent->parentWidget();
121 aSelector = dynamic_cast<ModuleBase_WidgetMultiSelector*>(aParent);
125 SelectorFeature = aSelector->feature();
126 AttributeId = aSelector->attributeID();
128 // Launch Filters operation
129 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
130 (myWorkshop->module()->createOperation(myFeatureName));
131 myWorkshop->processLaunchOperation(aFOperation);
134 //*****************************************************************************
135 //*****************************************************************************
136 //*****************************************************************************
137 ModuleBase_FilterItem::ModuleBase_FilterItem(
138 const std::string& theFilter, ModuleBase_WidgetSelectionFilter* theParent)
139 : QWidget(theParent->filtersWidget()), myFilterID(theFilter),
140 mySelection(std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theParent->feature()))
142 std::string aXmlString = ModelAPI_Session::get()->filters()->filter(theFilter)->xmlRepresentation();
143 if (aXmlString.length() == 0)
146 ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop());
147 QVBoxLayout* aLayout = new QVBoxLayout(this);
148 ModuleBase_Tools::zeroMargins(aLayout);
150 QWidget* aItemRow = new QWidget(this);
151 addItemRow(aItemRow);
152 aLayout->addWidget(aItemRow);
154 ModuleBase_PageWidget* aParamsWgt = new ModuleBase_PageWidget(this);
155 aParamsWgt->setFrameStyle(QFrame::Box | QFrame::Raised);
156 aFactory.createWidget(aParamsWgt);
157 ModuleBase_Tools::zeroMargins(aParamsWgt->layout());
158 myWidgets = aFactory.getModelWidgets();
159 foreach(ModuleBase_ModelWidget* aWidget, myWidgets) {
160 aWidget->setFeature(theParent->feature());
161 connect(aWidget, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)),
162 theParent, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)));
163 connect(aWidget, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)),
164 theParent, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)));
166 aLayout->addWidget(aParamsWgt);
170 void ModuleBase_FilterItem::addItemRow(QWidget* theParent)
172 QHBoxLayout* aLayout = new QHBoxLayout(theParent);
173 ModuleBase_Tools::zeroMargins(aLayout);
175 // Reverse filter button
176 myRevBtn = new QToolButton(theParent);
177 myRevBtn->setCheckable(true);
178 myRevBtn->setChecked(false);
179 myRevBtn->setAutoRaise(true);
180 myRevBtn->setIcon(QIcon(":pictures/add.png"));
181 myRevBtn->setToolTip(tr("Reverse the filter"));
182 connect(myRevBtn, SIGNAL(toggled(bool)), SLOT(onReverse(bool)));
183 aLayout->addWidget(myRevBtn);
185 const std::string& aFilterName = ModelAPI_Session::get()->filters()->filter(myFilterID)->name();
186 aLayout->addWidget(new QLabel(aFilterName.c_str(), theParent), 1);
188 QToolButton* aDelBtn = new QToolButton(theParent);
189 aDelBtn->setIcon(QIcon(":pictures/delete.png"));
190 aDelBtn->setAutoRaise(true);
191 aDelBtn->setToolTip(tr("Delete the filter"));
192 connect(aDelBtn, SIGNAL(clicked(bool)), SLOT(onDelete()));
193 aLayout->addWidget(aDelBtn);
196 void ModuleBase_FilterItem::onReverse(bool theCheck)
198 mySelection->setReversed(myFilterID, theCheck);
200 myRevBtn->setIcon(QIcon(":pictures/reverce.png"));
202 myRevBtn->setIcon(QIcon(":pictures/add.png"));
203 emit reversedItem(this);
206 void ModuleBase_FilterItem::onDelete()
208 emit deleteItem(this);
211 QList<QWidget*> ModuleBase_FilterItem::getControls() const
213 QList<QWidget*> aWidgetsList;
214 foreach(ModuleBase_ModelWidget* aWgt, myWidgets) {
215 QList<QWidget*> aSubList = aWgt->getControls();
216 foreach(QWidget* aSub, aSubList) {
217 aWidgetsList.append(aSub);
225 //*****************************************************************************
226 //*****************************************************************************
227 //*****************************************************************************
228 ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theParent,
229 ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData)
230 : ModuleBase_ModelWidget(theParent, theData),
231 myWorkshop(theWorkshop),
232 mySelectorFeature(SelectorFeature),
233 mySelectorAttribute(AttributeId)
235 // Clear Old selection
236 AttributePtr aAttr = SelectorFeature->attribute(AttributeId);
237 AttributeSelectionListPtr aSelListAttr =
238 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
239 mySelectionType = selectionType(aSelListAttr->selectionType().c_str());
240 aSelListAttr->clear();
243 QVBoxLayout* aMainLayout = new QVBoxLayout(this);
244 ModuleBase_Tools::adjustMargins(aMainLayout);
246 QGroupBox* aFiltersGroup = new QGroupBox(tr("Filters"), this);
247 QVBoxLayout* aGroupLayout = new QVBoxLayout(aFiltersGroup);
248 aGroupLayout->setContentsMargins(0, 0, 0, 0);
249 aGroupLayout->setSpacing(0);
251 myFiltersWgt = new QWidget();
252 myFiltersLayout = new QVBoxLayout(myFiltersWgt);
253 myFiltersLayout->setContentsMargins(0, 0, 0, 0);
254 aGroupLayout->addWidget(myFiltersWgt);
256 myFiltersCombo = new QComboBox(aFiltersGroup);
257 myFiltersCombo->addItem(tr("Add new filter..."));
258 SessionPtr aSession = ModelAPI_Session::get();
259 std::list<FilterPtr> allFilters =
260 aSession->filters()->filters((GeomAPI_Shape::ShapeType) mySelectionType);
262 std::list<FilterPtr>::const_iterator aIt;
263 for (aIt = allFilters.cbegin(); aIt != allFilters.cend(); aIt++) {
264 aItems.push_back((*aIt)->name().c_str());
265 myFilters.push_back(aSession->filters()->id(*aIt));
267 myFiltersCombo->addItems(aItems);
268 connect(myFiltersCombo, SIGNAL(currentIndexChanged(int)), SLOT(onAddFilter(int)));
270 aGroupLayout->addWidget(myFiltersCombo);
271 aMainLayout->addWidget(aFiltersGroup);
274 QWidget* aBtnWgt = new QWidget(this);
275 QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnWgt);
276 ModuleBase_Tools::adjustMargins(aBtnLayout);
278 aBtnLayout->addStretch(1);
280 mySelectBtn = new QPushButton(tr("Select"), aBtnWgt);
281 connect(mySelectBtn, SIGNAL(clicked()), SLOT(onSelect()));
282 aBtnLayout->addWidget(mySelectBtn);
284 aMainLayout->addWidget(aBtnWgt);
287 QWidget* aLblWgt = new QWidget(this);
288 QHBoxLayout* aLblLayout = new QHBoxLayout(aLblWgt);
289 ModuleBase_Tools::zeroMargins(aLblLayout);
291 aLblLayout->addWidget(new QLabel(tr("Number of selected objects:"), aLblWgt));
293 myNbLbl = new QLabel("0", aLblWgt);
294 aLblLayout->addWidget(myNbLbl);
297 myShowBtn = new QCheckBox(tr("Show only"), this);
298 connect(myShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
299 aLblLayout->addWidget(myShowBtn);
301 aMainLayout->addWidget(aLblWgt);
303 aMainLayout->addStretch(1);
308 ModuleBase_WidgetSelectionFilter::~ModuleBase_WidgetSelectionFilter()
311 if (!myPreview.IsNull()) {
312 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
313 aCtx->Remove(myPreview, false);
315 if (myShowBtn->isChecked()) {
316 AIS_ListOfInteractive::const_iterator aIt;
317 Handle(AIS_Shape) aShapeIO;
318 for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
319 aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
320 if (!aShapeIO.IsNull()) {
321 aCtx->Display(aShapeIO, false);
325 aCtx->UpdateCurrentViewer();
327 SelectorFeature = FeaturePtr();
331 void ModuleBase_WidgetSelectionFilter::onAddFilter(int theIndex)
336 std::list<std::string>::iterator aIt;
339 for (aIt = myFilters.begin(), i = 0; aIt != myFilters.cend(); i++, aIt++) {
340 if (i == (theIndex - 1)) {
342 myFilters.erase(aIt);
346 if (!aFilter.empty()) {
347 myUseFilters.push_back(aFilter);
348 ModuleBase_FilterItem* aItem = new ModuleBase_FilterItem(aFilter, this);
349 connect(aItem, SIGNAL(deleteItem(ModuleBase_FilterItem*)),
350 SLOT(onDeleteItem(ModuleBase_FilterItem*)));
351 connect(aItem, SIGNAL(reversedItem(ModuleBase_FilterItem*)),
352 SLOT(onReverseItem(ModuleBase_FilterItem*)));
353 myFiltersLayout->addWidget(aItem);
355 FiltersFeaturePtr aFiltersFeature =
356 std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
357 aFiltersFeature->addFilter(aFilter);
360 clearCurrentSelection(true);
361 updateNumberSelected();
362 myFiltersCombo->setCurrentIndex(0);
363 myFiltersCombo->removeItem(theIndex);
365 enableFocusProcessing();
368 void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theItem)
370 std::string aFilter = theItem->filter();
371 QList<ModuleBase_ModelWidget*> aWidgets = theItem->widgets();
372 foreach(ModuleBase_ModelWidget* aWgt, aWidgets) {
375 myFiltersLayout->removeWidget(theItem);
376 theItem->deleteLater();
378 myUseFilters.remove(aFilter);
379 myFilters.push_back(aFilter);
380 myFiltersCombo->addItem(ModelAPI_Session::get()->filters()->filter(aFilter)->name().c_str());
382 FiltersFeaturePtr aFiltersFeature =
383 std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
384 aFiltersFeature->removeFilter(aFilter);
387 clearCurrentSelection(true);
388 updateNumberSelected();
390 enableFocusProcessing();
391 myWorkshop->deactivateCurrentSelector();
392 myWorkshop->selectionActivate()->updateSelectionModes();
393 myWorkshop->selectionActivate()->updateSelectionFilters();
398 void ModuleBase_WidgetSelectionFilter::redisplayFeature()
400 static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
401 ModelAPI_EventCreator::get()->sendUpdated(myFeature, aDispEvent);
402 Events_Loop::loop()->flush(aDispEvent);
405 void ModuleBase_WidgetSelectionFilter::onReverseItem(ModuleBase_FilterItem* theItem)
408 clearCurrentSelection(true);
409 updateNumberSelected();
412 void ModuleBase_WidgetSelectionFilter::onSelect()
414 if (myUseFilters.size() == 0)
416 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
420 clearCurrentSelection();
422 BRep_Builder aBuilder;
423 TopoDS_Compound aComp;
424 aBuilder.MakeCompound(aComp);
426 if (!myShowBtn->isChecked()) {
428 aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO);
429 if (!myPreview.IsNull())
430 myListIO.Remove(myPreview);
432 AIS_ListOfInteractive::const_iterator aIt;
433 Handle(ModuleBase_ResultPrs) aShapeIO;
434 for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
435 aShapeIO = Handle(ModuleBase_ResultPrs)::DownCast(*aIt);
436 if (!aShapeIO.IsNull()) {
437 GeomShapePtr aShape(new GeomAPI_Shape);
438 aShape->setImpl(new TopoDS_Shape(aShapeIO->Shape()));
439 std::list<GeomShapePtr> aSubShapes =
440 aShape->subShapes((GeomAPI_Shape::ShapeType)mySelectionType);
441 std::list<GeomShapePtr>::const_iterator aShapesIt;
442 for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) {
443 GeomShapePtr aShape = (*aShapesIt);
444 SessionPtr aSession = ModelAPI_Session::get();
445 bool isValid = aSession->filters()->isValid(myFeature, aShape);
447 TopoDS_Shape aTShape = aShape->impl<TopoDS_Shape>();
448 Handle(StdSelect_BRepOwner) aOwner = new StdSelect_BRepOwner(aTShape, aShapeIO, true);
449 aBuilder.Add(aComp, aTShape);
451 ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aShapeIO->getResult(), aShape, aOwner));
452 myValues.append(aValue);
457 if (myValues.size() > 0)
458 updatePreview(aComp);
459 updateNumberSelected();
462 void ModuleBase_WidgetSelectionFilter::updatePreview(const TopoDS_Shape& theShape)
464 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
468 if (myPreview.IsNull()) {
469 myPreview = new AIS_Shape(theShape);
470 //myPreview->SetDisplayMode(myShowBtn->isChecked()? AIS_Shaded : AIS_WireFrame);
471 myPreview->SetDisplayMode(AIS_Shaded);
472 myPreview->SetColor(Quantity_NOC_BLUE1);
473 myPreview->SetTransparency();
474 aCtx->Display(myPreview, true);
475 aCtx->Deactivate(myPreview);
478 myPreview->Set(theShape);
479 aCtx->Redisplay(myPreview, true);
484 void ModuleBase_WidgetSelectionFilter::onShowOnly(bool theShow)
486 if (myPreview.IsNull())
488 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
492 aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO);
493 myListIO.Remove(myPreview);
495 AIS_ListOfInteractive::const_iterator aIt;
496 Handle(AIS_Shape) aShapeIO;
497 for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
498 aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
499 if (!aShapeIO.IsNull()) {
501 aCtx->Erase(aShapeIO, false);
503 aCtx->Display(aShapeIO, false);
506 aCtx->UpdateCurrentViewer();
509 void ModuleBase_WidgetSelectionFilter::updateSelectBtn()
511 mySelectBtn->setEnabled(myUseFilters.size() > 0);
514 void ModuleBase_WidgetSelectionFilter::updateNumberSelected()
516 myNbLbl->setText(QString::number(myValues.size()));
518 QList<QWidget*> ModuleBase_WidgetSelectionFilter::getControls() const
520 QList<QWidget*> aWidgets;
521 QList<ModuleBase_FilterItem*> aItems = myFiltersWgt->findChildren<ModuleBase_FilterItem*>();
522 foreach(ModuleBase_FilterItem* aItem, aItems) {
523 QList<QWidget*> aSubList = aItem->getControls();
524 foreach(QWidget* aWgt, aSubList) {
525 aWidgets.append(aWgt);
531 void ModuleBase_WidgetSelectionFilter::clearCurrentSelection(bool toUpdate)
534 if (!myPreview.IsNull()) {
535 Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
536 aCtx->Remove(myPreview, toUpdate);
541 void ModuleBase_WidgetSelectionFilter::onFeatureAccepted()
543 AttributePtr aAttr = mySelectorFeature->attribute(mySelectorAttribute);
544 AttributeSelectionListPtr aSelListAttr =
545 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
546 aSelListAttr->clear();
547 foreach(ModuleBase_ViewerPrsPtr aPrs, myValues) {
548 aSelListAttr->append(aPrs->object(), aPrs->shape());
552 bool ModuleBase_WidgetSelectionFilter::storeValueCustom()
557 bool ModuleBase_WidgetSelectionFilter::restoreValueCustom()
559 ModuleBase_ModelWidget* aActive = myWorkshop->propertyPanel()->activeWidget();
561 return aActive->restoreValue();