Salome HOME
This is an improvement to use one AND filter in the viewer context. It serves to...
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetMultiSelector.cpp
1 /*
2  * ModuleBase_WidgetMultiSelector.cpp
3  *
4  *  Created on: Aug 28, 2014
5  *      Author: sbh
6  */
7
8 #include <ModuleBase_WidgetMultiSelector.h>
9 #include <ModuleBase_WidgetShapeSelector.h>
10 #include <ModuleBase_ISelection.h>
11 #include <ModuleBase_IWorkshop.h>
12 #include <ModuleBase_Tools.h>
13
14 #include <ModelAPI_Data.h>
15 #include <ModelAPI_Object.h>
16 #include <ModelAPI_AttributeSelectionList.h>
17
18 #include <Config_WidgetAPI.h>
19
20 #include <QGridLayout>
21 #include <QLabel>
22 #include <QListWidget>
23 #include <QObject>
24 #include <QString>
25 #include <QComboBox>
26 #include <QEvent>
27
28 #include <memory>
29 #include <string>
30
31 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
32                                                                ModuleBase_IWorkshop* theWorkshop,
33                                                                const Config_WidgetAPI* theData,
34                                                                const std::string& theParentId)
35     : ModuleBase_ModelWidget(theParent, theData, theParentId),
36       myWorkshop(theWorkshop), myIsActive(false), myUseSubShapes(false)
37 {
38   myMainWidget = new QWidget(theParent);
39   QGridLayout* aMainLay = new QGridLayout(myMainWidget);
40   ModuleBase_Tools::adjustMargins(aMainLay);
41
42   QLabel* aTypeLabel = new QLabel(tr("Type"), myMainWidget);
43   aMainLay->addWidget(aTypeLabel, 0, 0);
44
45   myTypeCombo = new QComboBox(myMainWidget);
46   // There is no sence to paramerize list of types while we can not parametrize selection mode
47   QString aTypesStr("Vertices Edges Faces Solids");
48   QStringList aShapeTypes = aTypesStr.split(' ');
49   myTypeCombo->addItems(aShapeTypes);
50   aMainLay->addWidget(myTypeCombo, 0, 1);
51
52   QLabel* aListLabel = new QLabel(tr("Selected objects:"), myMainWidget);
53   aMainLay->addWidget(aListLabel, 1, 0, 1, -1);
54
55   myListControl = new QListWidget(myMainWidget);
56   aMainLay->addWidget(myListControl, 2, 0, 2, -1);
57   aMainLay->setRowStretch(2, 1);
58   aMainLay->addWidget(new QLabel(myMainWidget));
59   aMainLay->setRowMinimumHeight(3, 20);
60   myMainWidget->setLayout(aMainLay);
61   //TODO: Move into the base class
62   myUseSubShapes = theData->getBooleanAttribute("use_subshapes", false);
63   //TODO_END
64   connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
65
66   activateSelection(true);
67 }
68
69 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
70 {
71   activateSelection(false);
72 }
73
74 //********************************************************************
75 bool ModuleBase_WidgetMultiSelector::storeValue() const
76 {
77   // A rare case when plugin was not loaded. 
78   if(!myFeature)
79     return false;
80   DataPtr aData = myFeature->data();
81   AttributeSelectionListPtr aSelectionListAttr = 
82     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
83
84   if (aSelectionListAttr) {
85     aSelectionListAttr->clear();
86     // Store shapes type
87     TopAbs_ShapeEnum aCurrentType =
88           ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
89     aSelectionListAttr->setSelectionType((int) aCurrentType);
90     // Store selection in the attribute
91     foreach (GeomSelection aSelec, mySelection) {
92       aSelectionListAttr->append(aSelec.first, aSelec.second);
93     }
94     updateObject(myFeature);
95     return true;
96   }
97   return false;
98 }
99
100 //********************************************************************
101 bool ModuleBase_WidgetMultiSelector::restoreValue()
102 {
103   // A rare case when plugin was not loaded. 
104   if(!myFeature)
105     return false;
106   DataPtr aData = myFeature->data();
107   AttributeSelectionListPtr aSelectionListAttr = 
108     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
109
110   if (aSelectionListAttr) {
111     mySelection.clear();
112     // Restore shape type
113     TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum) aSelectionListAttr->selectionType();
114     setCurrentShapeType(aShapeType);
115     // Restore selection in the list
116     for (int i = 0; i < aSelectionListAttr->size(); i++) {
117       AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
118       mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
119     }
120     updateSelectionList();
121     return true;
122   }
123   return false;
124 }
125
126 //********************************************************************
127 QWidget* ModuleBase_WidgetMultiSelector::getControl() const
128 {
129   return myMainWidget;
130 }
131
132 //********************************************************************
133 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
134 {
135   QList<QWidget*> result;
136   //result << myTypeCombo;
137   result << myListControl;
138   return result;
139 }
140
141 //********************************************************************
142 bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEvent)
143 {
144   //TODO: Remove maybe?
145   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
146 }
147
148 //********************************************************************
149 void ModuleBase_WidgetMultiSelector::activateSelection(bool toActivate)
150 {
151   myIsActive = toActivate;
152   if (myIsActive) {
153     connect(myWorkshop, SIGNAL(selectionChanged()), 
154             this,       SLOT(onSelectionChanged()), 
155             Qt::UniqueConnection);
156     activateShapeSelection();
157   } else {
158     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
159     myWorkshop->deactivateSubShapesSelection();
160   }
161 }
162
163 //********************************************************************
164 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
165 {
166   activateShapeSelection();
167   QObjectPtrList anEmptyList;
168   myWorkshop->setSelected(anEmptyList);
169   // Clear mySelection, myListControl and storeValue()
170   onSelectionChanged();
171 }
172
173 //********************************************************************
174 void ModuleBase_WidgetMultiSelector::onSelectionChanged()
175 {
176   ModuleBase_ISelection* aSelection = myWorkshop->selection();
177   NCollection_List<TopoDS_Shape> aSelectedShapes; //, aFilteredShapes;
178   std::list<ObjectPtr> aOwnersList;
179   aSelection->selectedShapes(aSelectedShapes, aOwnersList);
180
181   mySelection.clear();
182   std::list<ObjectPtr>::const_iterator aIt;
183   NCollection_List<TopoDS_Shape>::Iterator aShpIt(aSelectedShapes);
184   GeomShapePtr aShape;
185   for (aIt = aOwnersList.cbegin(); aIt != aOwnersList.cend(); aShpIt.Next(), aIt++) {
186     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(*aIt);
187     if (myFeature) {
188       // We can not select a result of our feature
189       const std::list<ResultPtr>& aResList = myFeature->results();
190       std::list<ResultPtr>::const_iterator aIt;
191       bool isSkipSelf = false;
192       for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
193         if ((*aIt) == aResult) {
194           isSkipSelf = true;
195           break;
196         }
197       }
198       if(isSkipSelf)
199         continue;
200     }
201     aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
202     aShape->setImpl(new TopoDS_Shape(aShpIt.Value()));
203     mySelection.append(GeomSelection(aResult, aShape));
204   }
205   updateSelectionList();
206   emit valuesChanged();
207 }
208
209 //********************************************************************
210 void ModuleBase_WidgetMultiSelector::filterShapes(const NCollection_List<TopoDS_Shape>& theShapesToFilter,
211                                                   NCollection_List<TopoDS_Shape>& theResult)
212 {
213   if(myTypeCombo->count() == 0 || theShapesToFilter.IsEmpty())
214     return;
215   TopAbs_ShapeEnum aReferenceType =
216       ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
217   NCollection_List<TopoDS_Shape>::Iterator anIter(theShapesToFilter);
218   for (; anIter.More(); anIter.Next()) {
219     TopoDS_Shape aShape = anIter.Value();
220     if (aShape.IsNull() || aShape.ShapeType() != aReferenceType)
221       continue;
222     theResult.Append(aShape);
223   }
224 }
225
226 //********************************************************************
227 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
228 {
229   QString aShapeTypeName;
230   
231   for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
232     aShapeTypeName = myTypeCombo->itemText(idx);
233     TopAbs_ShapeEnum aRefType = ModuleBase_WidgetShapeSelector::shapeType(aShapeTypeName);
234     if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
235       activateSelection(false);
236       bool isBlocked = myTypeCombo->blockSignals(true);
237       myTypeCombo->setCurrentIndex(idx);
238       myTypeCombo->blockSignals(isBlocked);
239       activateSelection(true);
240       break;
241     }
242   }
243 }
244
245 void ModuleBase_WidgetMultiSelector::activateShapeSelection()
246 {
247   QString aNewType = myTypeCombo->currentText();
248   QIntList aList;
249   aList.append(ModuleBase_WidgetShapeSelector::shapeType(aNewType));
250   myWorkshop->activateSubShapesSelection(aList);
251 }
252
253 //********************************************************************
254 void ModuleBase_WidgetMultiSelector::updateSelectionList()
255 {
256   QString aType;
257   if (myTypeCombo->currentText().toLower() == "vertices")
258     aType = "vertex";
259   else if (myTypeCombo->currentText().toLower() == "edges")
260     aType = "edge";
261   else if (myTypeCombo->currentText().toLower() == "faces")
262     aType = "face";
263   else if (myTypeCombo->currentText().toLower() == "solids")
264     aType = "solid";
265  
266   myListControl->clear();
267   int i = 1;
268   foreach (GeomSelection aSel, mySelection) {
269     QString aName(aSel.first->data()->name().c_str());
270     aName += ":" + aType + QString("_%1").arg(i);
271     myListControl->addItem(aName);
272     i++;
273   }
274   myListControl->repaint();
275 }