Salome HOME
a11725988706e55c0ce67527a6d1ef867f5afe36
[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_FilterNoDegeneratedEdge.h>
13 #include <ModuleBase_ISelection.h>
14 #include <ModuleBase_IWorkshop.h>
15 #include <ModuleBase_IViewer.h>
16 #include <ModuleBase_Tools.h>
17
18 #include <ModelAPI_Data.h>
19 #include <ModelAPI_Object.h>
20
21 #include <Config_WidgetAPI.h>
22
23 #include <QGridLayout>
24 #include <QLabel>
25 #include <QListWidget>
26 #include <QObject>
27 #include <QString>
28 #include <QComboBox>
29 #include <QEvent>
30 #include <QAction>
31 #include <QApplication>
32 #include <QClipboard>
33
34 #include <memory>
35 #include <string>
36
37 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
38                                                                ModuleBase_IWorkshop* theWorkshop,
39                                                                const Config_WidgetAPI* theData,
40                                                                const std::string& theParentId)
41     : ModuleBase_ModelWidget(theParent, theData, theParentId),
42       myWorkshop(theWorkshop), myIsActive(false)
43 {
44   myMainWidget = new QWidget(theParent);
45   QGridLayout* aMainLay = new QGridLayout(myMainWidget);
46   ModuleBase_Tools::adjustMargins(aMainLay);
47
48   QLabel* aTypeLabel = new QLabel(tr("Type"), myMainWidget);
49   aMainLay->addWidget(aTypeLabel, 0, 0);
50
51   myTypeCombo = new QComboBox(myMainWidget);
52   // There is no sence to paramerize list of types while we can not parametrize selection mode
53   QString aTypesStr("Vertices Edges Faces Solids");
54   QStringList aShapeTypes = aTypesStr.split(' ');
55   myTypeCombo->addItems(aShapeTypes);
56   aMainLay->addWidget(myTypeCombo, 0, 1);
57
58   QLabel* aListLabel = new QLabel(tr("Selected objects:"), myMainWidget);
59   aMainLay->addWidget(aListLabel, 1, 0, 1, -1);
60
61   myListControl = new QListWidget(myMainWidget);
62   aMainLay->addWidget(myListControl, 2, 0, 2, -1);
63   aMainLay->setRowStretch(2, 1);
64   aMainLay->addWidget(new QLabel(myMainWidget));
65   aMainLay->setRowMinimumHeight(3, 20);
66   myMainWidget->setLayout(aMainLay);
67   connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
68
69   myCopyAction = new QAction(QIcon(":pictures/copy.png"), tr("Copy"), this);
70   myCopyAction->setShortcut(QKeySequence::Copy);
71   myCopyAction->setEnabled(false);
72   connect(myCopyAction, SIGNAL(triggered(bool)), SLOT(onCopyItem()));
73   myListControl->addAction(myCopyAction);
74   myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
75   connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
76
77   activateSelection(true);
78 }
79
80 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
81 {
82   activateSelection(false);
83 }
84
85 //********************************************************************
86 bool ModuleBase_WidgetMultiSelector::storeValue() const
87 {
88   // A rare case when plugin was not loaded. 
89   if(!myFeature)
90     return false;
91   DataPtr aData = myFeature->data();
92   AttributeSelectionListPtr aSelectionListAttr = 
93     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
94
95   if (aSelectionListAttr) {
96     aSelectionListAttr->clear();
97     // Store shapes type
98     TopAbs_ShapeEnum aCurrentType =
99           ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
100     aSelectionListAttr->setSelectionType((int) aCurrentType);
101     // Store selection in the attribute
102     foreach (GeomSelection aSelec, mySelection) {
103       aSelectionListAttr->append(aSelec.first, aSelec.second);
104     }
105     //updateSelectionList(aSelectionListAttr);
106     updateObject(myFeature);
107     return true;
108   }
109   return false;
110 }
111
112 //********************************************************************
113 bool ModuleBase_WidgetMultiSelector::restoreValue()
114 {
115   // A rare case when plugin was not loaded. 
116   if(!myFeature)
117     return false;
118   DataPtr aData = myFeature->data();
119   AttributeSelectionListPtr aSelectionListAttr = 
120     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
121
122   if (aSelectionListAttr) {
123     mySelection.clear();
124     // Restore shape type
125     TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum) aSelectionListAttr->selectionType();
126     setCurrentShapeType(aShapeType);
127     // Restore selection in the list
128     for (int i = 0; i < aSelectionListAttr->size(); i++) {
129       AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
130       mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
131     }
132     updateSelectionList(aSelectionListAttr);
133     return true;
134   }
135   return false;
136 }
137
138 //********************************************************************
139 QWidget* ModuleBase_WidgetMultiSelector::getControl() const
140 {
141   return myMainWidget;
142 }
143
144 //********************************************************************
145 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
146 {
147   QList<QWidget*> result;
148   //result << myTypeCombo;
149   result << myListControl;
150   return result;
151 }
152
153 //********************************************************************
154 bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEvent)
155 {
156   //TODO: Remove maybe?
157   return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
158 }
159
160 //********************************************************************
161 void ModuleBase_WidgetMultiSelector::activateSelection(bool toActivate)
162 {
163   myIsActive = toActivate;
164   if (myIsActive) {
165     connect(myWorkshop, SIGNAL(selectionChanged()), 
166             this,       SLOT(onSelectionChanged()), 
167             Qt::UniqueConnection);
168     activateShapeSelection();
169   } else {
170     disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
171     myWorkshop->deactivateSubShapesSelection();
172
173     myWorkshop->viewer()->removeSelectionFilter(myEdgesTypeFilter);
174   }
175 }
176
177 //********************************************************************
178 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
179 {
180   activateShapeSelection();
181   QObjectPtrList anEmptyList;
182   myWorkshop->setSelected(anEmptyList);
183   // Clear mySelection, myListControl and storeValue()
184   onSelectionChanged();
185 }
186
187 //********************************************************************
188 void ModuleBase_WidgetMultiSelector::onSelectionChanged()
189 {
190   ModuleBase_ISelection* aSelection = myWorkshop->selection();
191   NCollection_List<TopoDS_Shape> aSelectedShapes; //, aFilteredShapes;
192   std::list<ObjectPtr> aOwnersList;
193   aSelection->selectedShapes(aSelectedShapes, aOwnersList);
194
195   mySelection.clear();
196   std::list<ObjectPtr>::const_iterator aIt;
197   NCollection_List<TopoDS_Shape>::Iterator aShpIt(aSelectedShapes);
198   GeomShapePtr aShape;
199   for (aIt = aOwnersList.cbegin(); aIt != aOwnersList.cend(); aShpIt.Next(), aIt++) {
200     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(*aIt);
201     if (myFeature) {
202       // We can not select a result of our feature
203       const std::list<ResultPtr>& aResList = myFeature->results();
204       std::list<ResultPtr>::const_iterator aIt;
205       bool isSkipSelf = false;
206       for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
207         if ((*aIt) == aResult) {
208           isSkipSelf = true;
209           break;
210         }
211       }
212       if(isSkipSelf)
213         continue;
214     }
215     aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
216     aShape->setImpl(new TopoDS_Shape(aShpIt.Value()));
217     mySelection.append(GeomSelection(aResult, aShape));
218   }
219   //updateSelectionList();
220   emit valuesChanged();
221 }
222
223 //********************************************************************
224 void ModuleBase_WidgetMultiSelector::filterShapes(const NCollection_List<TopoDS_Shape>& theShapesToFilter,
225                                                   NCollection_List<TopoDS_Shape>& theResult)
226 {
227   if(myTypeCombo->count() == 0 || theShapesToFilter.IsEmpty())
228     return;
229   TopAbs_ShapeEnum aReferenceType =
230       ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
231   NCollection_List<TopoDS_Shape>::Iterator anIter(theShapesToFilter);
232   for (; anIter.More(); anIter.Next()) {
233     TopoDS_Shape aShape = anIter.Value();
234     if (aShape.IsNull() || aShape.ShapeType() != aReferenceType)
235       continue;
236     theResult.Append(aShape);
237   }
238 }
239
240 //********************************************************************
241 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
242 {
243   QString aShapeTypeName;
244   
245   for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
246     aShapeTypeName = myTypeCombo->itemText(idx);
247     TopAbs_ShapeEnum aRefType = ModuleBase_WidgetShapeSelector::shapeType(aShapeTypeName);
248     if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
249       activateSelection(false);
250       bool isBlocked = myTypeCombo->blockSignals(true);
251       myTypeCombo->setCurrentIndex(idx);
252       myTypeCombo->blockSignals(isBlocked);
253       activateSelection(true);
254       break;
255     }
256   }
257 }
258
259 void ModuleBase_WidgetMultiSelector::activateShapeSelection()
260 {
261   QString aNewType = myTypeCombo->currentText();
262   QIntList aList;
263   aList.append(ModuleBase_WidgetShapeSelector::shapeType(aNewType));
264   myWorkshop->activateSubShapesSelection(aList);
265
266   // it is necessary to filter the selected edges to be non-degenerated
267   // it is not possible to build naming name for such edges
268   if (aNewType == "Edges") {
269     myEdgesTypeFilter = new ModuleBase_FilterNoDegeneratedEdge();
270     ModuleBase_IViewer* aViewer = myWorkshop->viewer();
271     aViewer->addSelectionFilter(myEdgesTypeFilter);
272   }
273   else {
274     myWorkshop->viewer()->removeSelectionFilter(myEdgesTypeFilter);
275   }
276 }
277
278 //********************************************************************
279 void ModuleBase_WidgetMultiSelector::updateSelectionList(AttributeSelectionListPtr theList)
280 {
281   myListControl->clear();
282   for (int i = 0; i < theList->size(); i++) {
283     AttributeSelectionPtr aAttr = theList->value(i);
284     myListControl->addItem(aAttr->namingName().c_str());
285   }
286 }
287
288 //********************************************************************
289 void ModuleBase_WidgetMultiSelector::onCopyItem()
290 {
291   QList<QListWidgetItem*> aItems = myListControl->selectedItems();
292   QString aRes;
293   foreach(QListWidgetItem* aItem, aItems) {
294     if (!aRes.isEmpty())
295       aRes += "\n";
296     aRes += aItem->text();
297   }
298   if (!aRes.isEmpty()) {
299     QClipboard *clipboard = QApplication::clipboard();
300     clipboard->setText(aRes);
301   }
302 }
303
304 //********************************************************************
305 void ModuleBase_WidgetMultiSelector::onListSelection()
306 {
307   QList<QListWidgetItem*> aItems = myListControl->selectedItems();
308   myCopyAction->setEnabled(!aItems.isEmpty());
309 }
310