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