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