Salome HOME
Fix for crash and invisible bodies on Debian Squeeze SALOME version.
[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 <boost/smart_ptr/shared_ptr.hpp>
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->setColumnStretch(1, 1);
58   myMainWidget->setLayout(aMainLay);
59
60   //TODO: Move into the base class
61   myUseSubShapes = theData->getBooleanAttribute("use_subshapes", false);
62   //TODO_END
63   connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
64
65   activateSelection(true);
66 }
67
68 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
69 {
70   activateSelection(false);
71 }
72
73 //********************************************************************
74 bool ModuleBase_WidgetMultiSelector::storeValue() const
75 {
76   // A rare case when plugin was not loaded. 
77   if(!myFeature)
78     return false;
79   DataPtr aData = myFeature->data();
80   AttributeSelectionListPtr aSelectionListAttr = 
81     boost::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
82
83   if (aSelectionListAttr) {
84     aSelectionListAttr->clear();
85     // Store shapes type
86     TopAbs_ShapeEnum aCurrentType =
87           ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
88     aSelectionListAttr->setSelectionType((int) aCurrentType);
89     // Store selection in the attribute
90     foreach (GeomSelection aSelec, mySelection) {
91       aSelectionListAttr->append(aSelec.first, aSelec.second);
92     }
93     updateObject(myFeature);
94     return true;
95   }
96   return false;
97 }
98
99 //********************************************************************
100 bool ModuleBase_WidgetMultiSelector::restoreValue()
101 {
102   // A rare case when plugin was not loaded. 
103   if(!myFeature)
104     return false;
105   DataPtr aData = myFeature->data();
106   AttributeSelectionListPtr aSelectionListAttr = 
107     boost::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
108
109   if (aSelectionListAttr) {
110     mySelection.clear();
111     // Restore shape type
112     TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum) aSelectionListAttr->selectionType();
113     setCurrentShapeType(aShapeType);
114     // Restore selection in the list
115     for (int i = 0; i < aSelectionListAttr->size(); i++) {
116       AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
117       mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
118     }
119     updateSelectionList();
120     return true;
121   }
122   return false;
123 }
124
125 //********************************************************************
126 QWidget* ModuleBase_WidgetMultiSelector::getControl() const
127 {
128   return myMainWidget;
129 }
130
131 //********************************************************************
132 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
133 {
134   QList<QWidget*> result;
135   //result << myTypeCombo;
136   result << myListControl;
137   return result;
138 }
139
140 //********************************************************************
141 bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEvent)
142 {
143   //TODO: Remove maybe?
144   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
145 }
146
147 //********************************************************************
148 void ModuleBase_WidgetMultiSelector::activateSelection(bool toActivate)
149 {
150   myIsActive = toActivate;
151   if (myIsActive) {
152     connect(myWorkshop, SIGNAL(selectionChanged()), 
153             this,       SLOT(onSelectionChanged()), 
154             Qt::UniqueConnection);
155     activateShapeSelection();
156   } else {
157     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
158     myWorkshop->deactivateSubShapesSelection();
159   }
160 }
161
162 //********************************************************************
163 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
164 {
165   activateShapeSelection();
166   QList<ObjectPtr> anEmptyList;
167   myWorkshop->setSelected(anEmptyList);
168   // Clear mySelection, myListControl and storeValue()
169   onSelectionChanged();
170 }
171
172 //********************************************************************
173 void ModuleBase_WidgetMultiSelector::onSelectionChanged()
174 {
175   ModuleBase_ISelection* aSelection = myWorkshop->selection();
176   NCollection_List<TopoDS_Shape> aSelectedShapes; //, aFilteredShapes;
177   std::list<ObjectPtr> aOwnersList;
178   aSelection->selectedShapes(aSelectedShapes, aOwnersList);
179
180   mySelection.clear();
181   std::list<ObjectPtr>::const_iterator aIt;
182   NCollection_List<TopoDS_Shape>::Iterator aShpIt(aSelectedShapes);
183   GeomShapePtr aShape;
184   for (aIt = aOwnersList.cbegin(); aIt != aOwnersList.cend(); aShpIt.Next(), aIt++) {
185     ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(*aIt);
186     if (myFeature) {
187       // We can not select a result of our feature
188       const std::list<ResultPtr>& aResList = myFeature->results();
189       std::list<ResultPtr>::const_iterator aIt;
190       bool isSkipSelf = false;
191       for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
192         if ((*aIt) == aResult) {
193           isSkipSelf = true;
194           break;
195         }
196       }
197       if(isSkipSelf)
198         continue;
199     }
200     aShape = boost::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
201     aShape->setImpl(new TopoDS_Shape(aShpIt.Value()));
202     mySelection.append(GeomSelection(aResult, aShape));
203   }
204   updateSelectionList();
205   emit valuesChanged();
206 }
207
208 //********************************************************************
209 void ModuleBase_WidgetMultiSelector::filterShapes(const NCollection_List<TopoDS_Shape>& theShapesToFilter,
210                                                   NCollection_List<TopoDS_Shape>& theResult)
211 {
212   if(myTypeCombo->count() == 0 || theShapesToFilter.IsEmpty())
213     return;
214   TopAbs_ShapeEnum aReferenceType =
215       ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
216   NCollection_List<TopoDS_Shape>::Iterator anIter(theShapesToFilter);
217   for (; anIter.More(); anIter.Next()) {
218     TopoDS_Shape aShape = anIter.Value();
219     if (aShape.IsNull() || aShape.ShapeType() != aReferenceType)
220       continue;
221     theResult.Append(aShape);
222   }
223 }
224
225 //********************************************************************
226 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
227 {
228   QString aShapeTypeName;
229   
230   for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
231     aShapeTypeName = myTypeCombo->itemText(idx);
232     TopAbs_ShapeEnum aRefType = ModuleBase_WidgetShapeSelector::shapeType(aShapeTypeName);
233     if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
234       activateSelection(false);
235       bool isBlocked = myTypeCombo->blockSignals(true);
236       myTypeCombo->setCurrentIndex(idx);
237       myTypeCombo->blockSignals(isBlocked);
238       activateSelection(true);
239       break;
240     }
241   }
242 }
243
244 void ModuleBase_WidgetMultiSelector::activateShapeSelection()
245 {
246   QString aNewType = myTypeCombo->currentText();
247   QIntList aList;
248   aList.append(ModuleBase_WidgetShapeSelector::shapeType(aNewType));
249   myWorkshop->activateSubShapesSelection(aList);
250 }
251
252 //********************************************************************
253 void ModuleBase_WidgetMultiSelector::updateSelectionList()
254 {
255   QString aType;
256   if (myTypeCombo->currentText().toLower() == "vertices")
257     aType = "vertex";
258   else if (myTypeCombo->currentText().toLower() == "edges")
259     aType = "edge";
260   else if (myTypeCombo->currentText().toLower() == "faces")
261     aType = "face";
262   else if (myTypeCombo->currentText().toLower() == "solids")
263     aType = "solid";
264  
265   myListControl->clear();
266   int i = 1;
267   foreach (GeomSelection aSel, mySelection) {
268     QString aName(aSel.first->data()->name().c_str());
269     aName += ":" + aType + QString("_%1").arg(i);
270     myListControl->addItem(aName);
271     i++;
272   }
273   myListControl->repaint();
274 }