]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp
Salome HOME
2c10b1adbd5f12e2f927e9a63e300f4c602b810e
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetSelectionFilter.cpp
1 // Copyright (C) 2014-2021  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
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"
31
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_AttributeSelectionList.h>
34 #include <ModelAPI_Events.h>
35 #include <ModelAPI_FiltersFactory.h>
36 #include <ModelAPI_ResultBody.h>
37
38 #include <GeomAPI_ShapeExplorer.h>
39 #include <GeomAPI_Edge.h>
40
41 #include <Events_Loop.h>
42 #include <Config_ValidatorReader.h>
43
44 #include <AIS_InteractiveContext.hxx>
45 #include <StdSelect_BRepOwner.hxx>
46 #include <TopoDS_Compound.hxx>
47 #include <BRep_Builder.hxx>
48 #include <TopExp_Explorer.hxx>
49
50 #include <QLayout>
51 #include <QPushButton>
52 #include <QLabel>
53 #include <QComboBox>
54 #include <QGroupBox>
55 #include <QDialog>
56 #include <QToolButton>
57 #include <QCheckBox>
58 #include <QDir>
59
60 FeaturePtr ModuleBase_WidgetSelectionFilter::SelectorFeature;
61 std::string ModuleBase_WidgetSelectionFilter::AttributeId;
62
63
64 GeomAPI_Shape::ShapeType selectionType(const QString& theType)
65 {
66   QString aType = theType.toUpper();
67   if ((aType == "VERTEX") || (aType == "VERTICES"))
68     return GeomAPI_Shape::VERTEX;
69   else if ((aType == "EDGE") || (aType == "EDGES"))
70     return GeomAPI_Shape::EDGE;
71   else if ((aType == "WIRE") || (aType == "WIRES"))
72     return GeomAPI_Shape::WIRE;
73   else if ((aType == "FACE") || (aType == "FACES"))
74     return GeomAPI_Shape::FACE;
75   else if ((aType == "SHELL") || (aType == "SHELLS"))
76     return GeomAPI_Shape::SHELL;
77   else if ((aType == "SOLID") || (aType == "SOLIDS"))
78     return GeomAPI_Shape::SOLID;
79   else if ((aType == "COMPSOLID") || (aType == "COMPSOLIDS"))
80     return GeomAPI_Shape::COMPSOLID;
81   else if ((aType == "COMPOUND") || (aType == "COMPOUNDS"))
82     return GeomAPI_Shape::COMPOUND;
83   else
84     return GeomAPI_Shape::SHAPE;
85 }
86
87
88 ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature,
89   QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
90   : QWidget(theParent),
91   myFeatureName(theFeature),
92   myWorkshop(theWorkshop)
93 {
94   QHBoxLayout* aMainLayout = new QHBoxLayout(this);
95   ModuleBase_Tools::adjustMargins(aMainLayout);
96
97   aMainLayout->addStretch(1);
98   QPushButton* aLaunchBtn = new QPushButton(
99       ModuleBase_Tools::translate("FiltersSelection", "Selection by filters"), this);
100   connect(aLaunchBtn, SIGNAL(clicked()), SLOT(onFiltersLaunch()));
101   aMainLayout->addWidget(aLaunchBtn);
102 }
103
104 void ModuleBase_FilterStarter::onFiltersLaunch()
105 {
106   static QString aHelpFileName = QString("FiltersPlugin") + QDir::separator() +
107     QString("FiltersPlugin.html");
108
109   ModuleBase_Operation* aParentOp = myWorkshop->currentOperation();
110   ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(aParentOp);
111   if (aFeatureOp)
112     // Open transaction on filters operation finish
113     aFeatureOp->openTransactionOnResume();
114
115   QWidget* aParent = parentWidget();
116   ModuleBase_WidgetMultiSelector* aSelector =
117     dynamic_cast<ModuleBase_WidgetMultiSelector*>(aParent);
118   while (!aSelector) {
119     aParent = aParent->parentWidget();
120     aSelector = dynamic_cast<ModuleBase_WidgetMultiSelector*>(aParent);
121   }
122   if (!aSelector)
123     return;
124   ModuleBase_WidgetSelectionFilter::SelectorFeature = aSelector->feature();
125   ModuleBase_WidgetSelectionFilter::AttributeId = aSelector->attributeID();
126
127   // Launch Filters operation
128   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
129     (myWorkshop->module()->createOperation(myFeatureName));
130
131   AttributeSelectionListPtr aAttrList =
132     ModuleBase_WidgetSelectionFilter::SelectorFeature->selectionList(
133       ModuleBase_WidgetSelectionFilter::AttributeId);
134   FiltersFeaturePtr aFilters = aAttrList->filters();
135   if (aFilters.get())
136     aFOperation->setFeature(aFilters);
137   aFOperation->setHelpFileName(aHelpFileName);
138   myWorkshop->processLaunchOperation(aFOperation);
139 }
140
141 //*****************************************************************************
142 //*****************************************************************************
143 //*****************************************************************************
144 ModuleBase_FilterItem::ModuleBase_FilterItem(
145   const std::string& theFilter, ModuleBase_WidgetSelectionFilter* theParent)
146   : QWidget(theParent->filtersWidget()), myFilterID(theFilter),
147     mySelection(std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theParent->feature()))
148 {
149   FilterPtr aFilter = ModelAPI_Session::get()->filters()->filter(theFilter);
150   std::string aXmlString = aFilter->xmlRepresentation();
151   if (aXmlString.length() == 0)
152     addItemRow(this);
153   else {
154     std::string anAttrPrefix; // this must be added to the attributes names for multiple filters
155     std::string aFilterKind = ModelAPI_Session::get()->filters()->id(aFilter);
156     if (theFilter != aFilterKind) {
157       anAttrPrefix = theFilter.substr(0, theFilter.size() - aFilterKind.size());
158     }
159     ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop(), anAttrPrefix);
160     Config_ValidatorReader aValidatorReader(aXmlString, true);
161     aValidatorReader.setFeatureId(mySelection->getKind());
162     aValidatorReader.readAll();
163
164     QVBoxLayout* aLayout = new QVBoxLayout(this);
165     ModuleBase_Tools::zeroMargins(aLayout);
166
167     QWidget* aItemRow = new QWidget(this);
168     addItemRow(aItemRow);
169     aLayout->addWidget(aItemRow);
170
171     ModuleBase_PageWidget* aParamsWgt = new ModuleBase_PageWidget(this);
172     aParamsWgt->setFrameStyle(QFrame::Box | QFrame::Raised);
173     aFactory.createWidget(aParamsWgt);
174     ModuleBase_Tools::zeroMargins(aParamsWgt->layout());
175     myWidgets = aFactory.getModelWidgets();
176     foreach(ModuleBase_ModelWidget* aWidget, myWidgets) {
177       aWidget->setFeature(theParent->feature());
178       connect(aWidget, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)),
179         theParent, SIGNAL(focusInWidget(ModuleBase_ModelWidget*)));
180       connect(aWidget, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)),
181         theParent, SIGNAL(focusOutWidget(ModuleBase_ModelWidget*)));
182       connect(aWidget, SIGNAL(objectUpdated()), theParent, SLOT(onObjectUpdated()));
183     }
184     aLayout->addWidget(aParamsWgt);
185   }
186 }
187
188 void ModuleBase_FilterItem::addItemRow(QWidget* theParent)
189 {
190   std::string aContext = mySelection->getKind();
191   QHBoxLayout* aLayout = new QHBoxLayout(theParent);
192   ModuleBase_Tools::zeroMargins(aLayout);
193
194   // Reverse filter button
195   myRevBtn = new QToolButton(theParent);
196   myRevBtn->setCheckable(true);
197   bool isReversed = mySelection->isReversed(myFilterID);
198   myRevBtn->setChecked(isReversed);
199   myRevBtn->setAutoRaise(true);
200   if (isReversed)
201     myRevBtn->setIcon(QIcon(":pictures/reverce.png"));
202   else
203     myRevBtn->setIcon(QIcon(":pictures/add.png"));
204   myRevBtn->setToolTip(ModuleBase_Tools::translate(aContext, "Reverse the filter"));
205   connect(myRevBtn, SIGNAL(toggled(bool)), SLOT(onReverse(bool)));
206   aLayout->addWidget(myRevBtn);
207
208   const std::string& aFilterName = ModelAPI_Session::get()->filters()->filter(myFilterID)->name();
209   aLayout->addWidget(new QLabel(ModuleBase_Tools::translate(aContext, aFilterName), theParent), 1);
210
211   QToolButton* aDelBtn = new QToolButton(theParent);
212   aDelBtn->setIcon(QIcon(":pictures/delete.png"));
213   aDelBtn->setAutoRaise(true);
214   aDelBtn->setToolTip(ModuleBase_Tools::translate(aContext, "Delete the filter"));
215   connect(aDelBtn, SIGNAL(clicked(bool)), SLOT(onDelete()));
216   aLayout->addWidget(aDelBtn);
217 }
218
219 void ModuleBase_FilterItem::onReverse(bool theCheck)
220 {
221   mySelection->setReversed(myFilterID, theCheck);
222   if (theCheck)
223     myRevBtn->setIcon(QIcon(":pictures/reverce.png"));
224   else
225     myRevBtn->setIcon(QIcon(":pictures/add.png"));
226   emit reversedItem(this);
227 }
228
229 void ModuleBase_FilterItem::onDelete()
230 {
231   emit deleteItem(this);
232 }
233
234
235 //*****************************************************************************
236 //*****************************************************************************
237 //*****************************************************************************
238 ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theParent,
239   ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData, bool theReadOnly)
240   : ModuleBase_ModelWidget(theParent, theData),
241   myWorkshop(theWorkshop),
242   mySelectorFeature(ModuleBase_WidgetSelectionFilter::SelectorFeature),
243   mySelectorAttribute(ModuleBase_WidgetSelectionFilter::AttributeId)
244 {
245   // Clear Old selection
246     AttributeSelectionListPtr aAttrList = mySelectorFeature->selectionList(mySelectorAttribute);
247     mySelectionType = selectionType(aAttrList->selectionType().c_str());
248   if (!theReadOnly) {
249     aAttrList->clear();
250   }
251
252   // Define widgets
253   QVBoxLayout* aMainLayout = new QVBoxLayout(this);
254   ModuleBase_Tools::adjustMargins(aMainLayout);
255
256   QGroupBox* aFiltersGroup = new QGroupBox(translate("Filters"), this);
257   QVBoxLayout* aGroupLayout = new QVBoxLayout(aFiltersGroup);
258   aGroupLayout->setContentsMargins(0, 0, 0, 0);
259   aGroupLayout->setSpacing(0);
260
261   myFiltersWgt = new QWidget();
262   myFiltersLayout = new QVBoxLayout(myFiltersWgt);
263   myFiltersLayout->setContentsMargins(0, 0, 0, 0);
264   aGroupLayout->addWidget(myFiltersWgt);
265
266   myFiltersCombo = new QComboBox(aFiltersGroup);
267   myFiltersCombo->addItem(translate("Add new filter..."));
268   SessionPtr aSession = ModelAPI_Session::get();
269   std::list<FilterPtr> allFilters =
270     aSession->filters()->filters((GeomAPI_Shape::ShapeType) mySelectionType);
271   storeFilters(allFilters);
272   QStringList aItems;
273   std::list<FilterPtr>::const_iterator aIt;
274   for (aIt = allFilters.cbegin(); aIt != allFilters.cend(); aIt++) {
275     aItems.push_back(translate((*aIt)->name().c_str()));
276   }
277   myFiltersCombo->addItems(aItems);
278   connect(myFiltersCombo, SIGNAL(currentIndexChanged(int)), SLOT(onAddFilter(int)));
279
280   aGroupLayout->addWidget(myFiltersCombo);
281   aMainLayout->addWidget(aFiltersGroup);
282
283   // Select Button
284   QWidget* aBtnWgt = new QWidget(this);
285   QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnWgt);
286   ModuleBase_Tools::adjustMargins(aBtnLayout);
287
288   aBtnLayout->addStretch(1);
289
290   mySelectBtn = new QPushButton(translate("Select"), aBtnWgt);
291   connect(mySelectBtn, SIGNAL(clicked()), SLOT(onSelect()));
292   aBtnLayout->addWidget(mySelectBtn);
293
294   aMainLayout->addWidget(aBtnWgt);
295
296   // Label widgets
297   QWidget* aLblWgt = new QWidget(this);
298   QHBoxLayout* aLblLayout = new QHBoxLayout(aLblWgt);
299   ModuleBase_Tools::zeroMargins(aLblLayout);
300
301   aLblLayout->addWidget(new QLabel(translate("Number of selected objects:"), aLblWgt));
302
303   myNbLbl = new QLabel("0", aLblWgt);
304   aLblLayout->addWidget(myNbLbl);
305
306   // Show only button
307   myShowBtn = new QCheckBox(translate("Show only"), this);
308   connect(myShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
309   aLblLayout->addWidget(myShowBtn);
310
311   aMainLayout->addWidget(aLblWgt);
312
313   aMainLayout->addStretch(1);
314
315   updateSelectBtn();
316   if (theReadOnly) {
317     myFiltersCombo->hide();
318     mySelectBtn->hide();
319     aLblWgt->hide();
320     myShowBtn->hide();
321   }
322 }
323
324 ModuleBase_WidgetSelectionFilter::~ModuleBase_WidgetSelectionFilter()
325 {
326   myValues.clear();
327   if (!myPreview.IsNull()) {
328     Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
329     aCtx->Remove(myPreview, false);
330     myPreview.Nullify();
331     if (myListIO.Size() > 0) {
332       aCtx = myWorkshop->viewer()->AISContext();
333       AIS_ListOfInteractive::const_iterator aIt;
334       Handle(AIS_Shape) aShapeIO;
335       for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
336         aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
337         if (!aShapeIO.IsNull()) {
338           aCtx->Display(aShapeIO, false);
339           std::shared_ptr<GeomAPI_AISObject> anAISObj = AISObjectPtr(new GeomAPI_AISObject());
340           anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aShapeIO));
341           myWorkshop->applyCurrentSelectionModes(anAISObj);
342         }
343       }
344       myListIO.Clear();
345       myShowBtn->setChecked(false);
346     }
347     myWorkshop->viewer()->update();
348   }
349   SelectorFeature = FeaturePtr();
350   AttributeId = "";
351 }
352
353 void ModuleBase_WidgetSelectionFilter::onAddFilter(int theIndex)
354 {
355   if (theIndex == 0)
356     return;
357
358   ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
359   FiltersFeaturePtr aFiltersFeature =
360     std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
361
362   std::string aText = myFiltersCombo->itemText(theIndex).toStdString();
363
364   std::list<FilterPtr>::iterator aIt;
365   std::string aFilter;
366   std::map<std::string, FilterPtr>::const_iterator aFound = myFilters.find(aText);
367   if (aFound == myFilters.end()) {
368     std::list<FilterPtr> aFilters = aFactory->filters((GeomAPI_Shape::ShapeType) mySelectionType);
369     storeFilters(aFilters);
370     aFound = myFilters.find(aText);
371   }
372   if (aFound != myFilters.end())
373     aFilter = aFactory->id(aFound->second);
374
375   aFiltersFeature->addFilter(aFilter);
376   updateObject(myFeature);
377
378   QList<ModuleBase_FilterItem*> aList = itemsList();
379   if (!aList.isEmpty() && (aList.last()->widgets().size() > 0))
380     aList.last()->widgets().first()->emitFocusInWidget();
381   else
382     emitFocusInWidget();
383 }
384
385 ModuleBase_FilterItem* ModuleBase_WidgetSelectionFilter::onAddFilter(const std::string& theFilter)
386 {
387   if (theFilter.length() == 0)
388     return 0;
389   ModuleBase_FilterItem* aItem = new ModuleBase_FilterItem(theFilter, this);
390   connect(aItem, SIGNAL(deleteItem(ModuleBase_FilterItem*)),
391     SLOT(onDeleteItem(ModuleBase_FilterItem*)));
392   connect(aItem, SIGNAL(reversedItem(ModuleBase_FilterItem*)),
393     SLOT(onReverseItem(ModuleBase_FilterItem*)));
394   myFiltersLayout->addWidget(aItem);
395
396   updateSelectBtn();
397   clearCurrentSelection(true);
398   updateNumberSelected();
399   return aItem;
400 }
401
402 void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theItem)
403 {
404   std::string aFilter = theItem->filter();
405   QList<ModuleBase_ModelWidget*> aWidgets = theItem->widgets();
406   foreach(ModuleBase_ModelWidget* aWgt, aWidgets) {
407     aWgt->deactivate();
408   }
409   myFiltersLayout->removeWidget(theItem);
410   theItem->deleteLater();
411
412   ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
413   if (!aFactory->filter(aFilter)->isMultiple()) {
414     //myFilters.push_back(aFilter);
415     myFiltersCombo->addItem(ModelAPI_Session::get()->filters()->filter(aFilter)->name().c_str());
416   }
417   FiltersFeaturePtr aFiltersFeature =
418     std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
419   aFiltersFeature->removeFilter(aFilter);
420
421   updateSelectBtn();
422   clearCurrentSelection(true);
423   updateNumberSelected();
424
425   myWorkshop->deactivateCurrentSelector();
426   myWorkshop->selectionActivate()->updateSelectionModes();
427   myWorkshop->selectionActivate()->updateSelectionFilters();
428   redisplayFeature();
429   emitFocusInWidget();
430   updateObject(myFeature);
431 }
432
433
434 void ModuleBase_WidgetSelectionFilter::redisplayFeature()
435 {
436   static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
437   ModelAPI_EventCreator::get()->sendUpdated(myFeature, aDispEvent);
438   Events_Loop::loop()->flush(aDispEvent);
439 }
440
441 void ModuleBase_WidgetSelectionFilter::onReverseItem(ModuleBase_FilterItem* theItem)
442 {
443   updateSelectBtn();
444   clearCurrentSelection(true);
445   updateNumberSelected();
446 }
447
448 void ModuleBase_WidgetSelectionFilter::onSelect()
449 {
450   Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
451   if (aCtx.IsNull())
452     return;
453
454   clearCurrentSelection();
455
456   BRep_Builder aBuilder;
457   TopoDS_Compound aComp;
458   aBuilder.MakeCompound(aComp);
459
460   DocumentPtr aDoc = myFeature->document();
461   int aNb = aDoc->size(ModelAPI_ResultBody::group());
462   ObjectPtr aObj;
463   ResultBodyPtr aBody;
464   for (int i = 0; i < aNb; i++) {
465     aObj = aDoc->object(ModelAPI_ResultBody::group(), i);
466     aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObj);
467     GeomShapePtr aShape = aBody->shape();
468     std::list<GeomShapePtr> aSubShapes =
469       aShape->subShapes((GeomAPI_Shape::ShapeType)mySelectionType);
470     TopTools_MapOfShape alreadyThere;
471     std::list<GeomShapePtr>::const_iterator aShapesIt;
472     for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) {
473       GeomShapePtr aSubShape = (*aShapesIt);
474       TopoDS_Shape aTShape = aSubShape->impl<TopoDS_Shape>();
475       if (!alreadyThere.Add(aTShape))
476         continue;
477
478       // degenerated edge is not valid selection
479       if ((GeomAPI_Shape::ShapeType)mySelectionType == GeomAPI_Shape::EDGE)
480         if (aSubShape->edge()->isDegenerated())
481           continue;
482
483       static SessionPtr aSession = ModelAPI_Session::get();
484       bool isValid = aSession->filters()->isValid(myFeature, aBody, aSubShape);
485
486       if (isValid) {
487         aBuilder.Add(aComp, aTShape);
488         // bos #24043: Naming on a compsolid works wrong.
489         // Find a simple sub-result for the ViewerPrs context:
490         ResultBodyPtr aContext = aBody;
491         bool isComposite = aContext->numberOfSubs() > 0;
492         while (isComposite) {
493           isComposite = false;
494           int nbSubs = aContext->numberOfSubs();
495           for (int aSubIndex = 0; aSubIndex < nbSubs; aSubIndex++) {
496             ResultBodyPtr aSubResult = aContext->subResult(aSubIndex);
497             GeomShapePtr aSubResultShape = aSubResult->shape();
498             if (aSubResultShape->isSubShape(aSubShape)) {
499               aContext = aSubResult;
500               isComposite = aContext->numberOfSubs() > 0;
501               break;
502             }
503           }
504         }
505         ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aContext, aSubShape));
506         //ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aObj, aSubShape));
507         myValues.append(aValue);
508       }
509     }
510   }
511
512   if (myValues.size() > 0)
513     updatePreview(aComp);
514   updateNumberSelected();
515   updateObject(myFeature);
516   onShowOnly(myShowBtn->isChecked());
517 }
518
519 void ModuleBase_WidgetSelectionFilter::updatePreview(const TopoDS_Shape& theShape)
520 {
521   Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
522   if (aCtx.IsNull())
523     return;
524
525   if (myPreview.IsNull()) {
526     myPreview = new AIS_Shape(theShape);
527     myPreview->SetDisplayMode(AIS_Shaded);
528     myPreview->SetColor(Quantity_NOC_BLUE1);
529     Handle(Prs3d_Drawer) aDrawer = myPreview->Attributes();
530     if (aDrawer->HasOwnPointAspect()) {
531       aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_O_STAR);
532       aDrawer->PointAspect()->SetColor(Quantity_NOC_BLUE1);
533       aDrawer->PointAspect()->SetScale(2.);
534     }
535     else
536       aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_O_STAR, Quantity_NOC_BLUE1, 2.));
537     myPreview->SetTransparency();
538     aCtx->Display(myPreview, true);
539     aCtx->Deactivate(myPreview);
540   }
541   else {
542     myPreview->Set(theShape);
543     aCtx->Redisplay(myPreview, true);
544   }
545 }
546
547
548 void ModuleBase_WidgetSelectionFilter::onShowOnly(bool theShow)
549 {
550   Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
551   if (theShow) {
552     AIS_ListOfInteractive aList;
553     aCtx->DisplayedObjects(AIS_KOI_Shape, -1, aList);
554     if (!myPreview.IsNull())
555       aList.Remove(myPreview);
556     if (aList.Size() > 0)
557       myListIO = aList;
558   }
559   AIS_ListOfInteractive::const_iterator aIt;
560   Handle(AIS_Shape) aShapeIO;
561   bool isModified = false;
562   for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
563     aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
564     if (!aShapeIO.IsNull()) {
565       if (theShow) {
566         if (aCtx->IsDisplayed(aShapeIO)) {
567           aCtx->Erase(aShapeIO, false);
568           isModified = true;
569         }
570       }
571       else {
572         if (!aCtx->IsDisplayed(aShapeIO)) {
573           aCtx->Display(aShapeIO, false);
574           std::shared_ptr<GeomAPI_AISObject> anAISObj = AISObjectPtr(new GeomAPI_AISObject());
575           anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aShapeIO));
576           myWorkshop->applyCurrentSelectionModes(anAISObj);
577           isModified = true;
578         }
579       }
580     }
581   }
582   if (isModified)
583     myWorkshop->viewer()->update();
584 }
585
586 void ModuleBase_WidgetSelectionFilter::updateSelectBtn()
587 {
588   FiltersFeaturePtr aFiltersFeature = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
589   mySelectBtn->setEnabled(aFiltersFeature.get() && (aFiltersFeature->filters().size() > 0));
590 }
591
592 void ModuleBase_WidgetSelectionFilter::updateNumberSelected()
593 {
594   int aNb = myValues.size();
595   myNbLbl->setText(QString::number(aNb));
596   if (aNb == 0) {
597     myFeature->setError(translate("Selection is empty").toStdString(), false, false);
598     myShowBtn->setChecked(false);
599     onShowOnly(false);
600     myShowBtn->setEnabled(false);
601   }
602   else {
603     myFeature->setError("", false, false);
604     myFeature->data()->execState(ModelAPI_StateDone);
605     myShowBtn->setEnabled(true);
606   }
607 }
608
609 QList<QWidget*> ModuleBase_WidgetSelectionFilter::getControls() const
610 {
611   QList<QWidget*> aWidgets;
612   aWidgets.append(myFiltersCombo);
613   return aWidgets;
614 }
615
616 void ModuleBase_WidgetSelectionFilter::clearCurrentSelection(bool toUpdate)
617 {
618   myValues.clear();
619   if (!myPreview.IsNull()) {
620     Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
621     aCtx->Remove(myPreview, toUpdate);
622     myPreview.Nullify();
623   }
624 }
625
626 void replaceSubShapesByResult(QList<ModuleBase_ViewerPrsPtr>& theResults, int theShapeType)
627 {
628   QMap<ObjectPtr, QList<GeomShapePtr>> myResShapes;
629   // Sort sub-shapes by result
630   foreach (ModuleBase_ViewerPrsPtr aPrs, theResults) {
631     if (myResShapes.contains(aPrs->object()))
632       myResShapes[aPrs->object()].append(aPrs->shape());
633     else {
634       QList<GeomShapePtr> aShapes;
635       aShapes << aPrs->shape();
636       myResShapes[aPrs->object()] = aShapes;
637     }
638   }
639   // Find Results to replace by whole result
640   QList<GeomShapePtr> aShapes;
641   QList<ObjectPtr> aToReplace;
642   std::list<GeomShapePtr> aSubShapes;
643   foreach(ObjectPtr aObj, myResShapes.keys()) {
644     aShapes = myResShapes[aObj];
645     ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
646     TopTools_MapOfShape aShapesMap;
647     if (aRes.get()) {
648       GeomShapePtr aSubShape = aRes->shape();
649       const TopoDS_Shape& aShape = aSubShape->impl<TopoDS_Shape>();
650       for (TopExp_Explorer anExp(aShape, (TopAbs_ShapeEnum)theShapeType);
651         anExp.More(); anExp.Next()) {
652         aShapesMap.Add(anExp.Current());
653       }
654     }
655     if (aShapes.count() == aShapesMap.Size())
656       aToReplace.append(aObj);
657   }
658   // Replace the found results
659   QList<ModuleBase_ViewerPrsPtr>::iterator aIt;
660   foreach(ObjectPtr aObj, aToReplace) {
661     for (aIt = theResults.begin(); aIt != theResults.end(); aIt++) {
662       if ((*aIt)->object() == aObj) {
663         theResults.removeAll(*aIt);
664         aIt--;
665       }
666     }
667     ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aObj));
668     theResults.append(aValue);
669   }
670 }
671
672 void ModuleBase_WidgetSelectionFilter::onFeatureAccepted()
673 {
674   AttributePtr aAttr = mySelectorFeature->attribute(mySelectorAttribute);
675   AttributeSelectionListPtr aSelListAttr =
676     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
677   aSelListAttr->clear();
678   if (aSelListAttr->isWholeResultAllowed())
679     replaceSubShapesByResult(myValues, selectionType(aSelListAttr->selectionType().c_str()));
680   foreach(ModuleBase_ViewerPrsPtr aPrs, myValues) {
681     aSelListAttr->append(aPrs->object(), aPrs->shape());
682   }
683 }
684
685 bool ModuleBase_WidgetSelectionFilter::storeValueCustom()
686 {
687   ModuleBase_ModelWidget* aActive = myWorkshop->propertyPanel()->activeWidget();
688   if (aActive)
689     return aActive->storeValue();
690   updateObject(myFeature);
691   return true;
692 }
693
694 QList<ModuleBase_FilterItem*> ModuleBase_WidgetSelectionFilter::itemsList() const
695 {
696   return  myFiltersWgt->findChildren<ModuleBase_FilterItem*>();
697 }
698
699
700 bool ModuleBase_WidgetSelectionFilter::restoreValueCustom()
701 {
702   ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
703   FiltersFeaturePtr aFiltersFeature = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
704
705   // Init filters member of the parent attribute
706   AttributeSelectionListPtr aAttrList = mySelectorFeature->selectionList(mySelectorAttribute);
707   if (aAttrList->filters() != aFiltersFeature) {
708     aAttrList->setFilters(aFiltersFeature);
709   }
710
711   QList<ModuleBase_FilterItem*> aItemsList = itemsList();
712   std::list<std::string> aFilters = aFiltersFeature->filters();
713
714   std::list<std::string>::const_iterator aIt;
715   int i = 0;
716   int aNbItems = aItemsList.size();
717   ModuleBase_FilterItem* aItem = 0;
718   bool isBlocked = myFiltersCombo->blockSignals(true);
719   for (aIt = aFilters.cbegin(); aIt != aFilters.cend(); aIt++, i++) {
720     std::string aStr = (*aIt);
721     aItem = 0;
722     if (i >= aNbItems) {
723       aItem = onAddFilter(aStr);
724       FilterPtr aFilterObj = aFactory->filter(aStr);
725       int aId = myFiltersCombo->findText(aFilterObj->name().c_str());
726       if ((aId != -1) && !aFilterObj->isMultiple())
727         myFiltersCombo->removeItem(aId);
728       if (aItem) {
729         QList<ModuleBase_ModelWidget*> aSubList = aItem->widgets();
730         foreach(ModuleBase_ModelWidget* aWgt, aSubList) {
731           aWgt->restoreValue();
732         }
733       }
734     }
735   }
736   myFiltersCombo->setCurrentIndex(0);
737   myFiltersCombo->blockSignals(isBlocked);
738   return true;
739 }
740
741 QString ModuleBase_WidgetSelectionFilter::getError(const bool theValueStateChecked) const
742 {
743   QString aErrorMsg = ModuleBase_ModelWidget::getError(theValueStateChecked);
744   if (aErrorMsg.isEmpty()) {
745     if (myValues.size() == 0)
746       aErrorMsg = translate("Selection is empty");
747   }
748   return aErrorMsg;
749 }
750
751 void ModuleBase_WidgetSelectionFilter::onObjectUpdated()
752 {
753   myShowBtn->setChecked(false);
754   clearCurrentSelection(true);
755   updateNumberSelected();
756
757   QList<ModuleBase_FilterItem*> aItemsList = itemsList();
758   foreach(ModuleBase_FilterItem* aItem, aItemsList) {
759     QList<ModuleBase_ModelWidget*> aWidgetsList = aItem->widgets();
760     foreach(ModuleBase_ModelWidget* aWidget, aWidgetsList) {
761       if (!aWidget->feature().get())
762         aWidget->setFeature(myFeature);
763       aWidget->restoreValue();
764     }
765   }
766   updateObject(myFeature);
767
768   // Redisplay the feature on order to Customize presentations from filters with selectors
769   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
770   ModelAPI_EventCreator::get()->sendUpdated(myFeature, EVENT_DISP);
771   Events_Loop::loop()->flush(EVENT_DISP);
772 }
773
774 void ModuleBase_WidgetSelectionFilter::storeFilters(const std::list<FilterPtr>& theFilters)
775 {
776   for (std::list<FilterPtr>::const_iterator anIt = theFilters.begin();
777        anIt != theFilters.end(); ++anIt) {
778     std::string aName = translate((*anIt)->name()).toStdString();
779     myFilters[aName] = *anIt;
780   }
781 }
782
783 QString ModuleBase_WidgetSelectionFilter::translate(const std::string& theString) const
784 {
785   return ModuleBase_Tools::translate(myFeatureId, theString);
786 }