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