1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
4 * ModuleBase_WidgetMultiSelector.cpp
6 * Created on: Aug 28, 2014
10 #include <ModuleBase_WidgetMultiSelector.h>
11 #include <ModuleBase_WidgetShapeSelector.h>
12 #include <ModuleBase_ISelection.h>
13 #include <ModuleBase_IWorkshop.h>
14 #include <ModuleBase_IViewer.h>
15 #include <ModuleBase_Tools.h>
17 #include <ModelAPI_Data.h>
18 #include <ModelAPI_Object.h>
20 #include <Config_WidgetAPI.h>
22 #include <QGridLayout>
24 #include <QListWidget>
30 #include <QApplication>
36 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
37 ModuleBase_IWorkshop* theWorkshop,
38 const Config_WidgetAPI* theData,
39 const std::string& theParentId)
40 : ModuleBase_WidgetValidated(theParent, theData, theParentId),
41 myWorkshop(theWorkshop), myIsActive(false)
43 QGridLayout* aMainLay = new QGridLayout(this);
44 ModuleBase_Tools::adjustMargins(aMainLay);
46 QLabel* aTypeLabel = new QLabel(tr("Type"), this);
47 aMainLay->addWidget(aTypeLabel, 0, 0);
49 myTypeCombo = new QComboBox(this);
50 // There is no sence to paramerize list of types while we can not parametrize selection mode
52 std::string aPropertyTypes = theData->getProperty("type_choice");
53 QString aTypesStr = aPropertyTypes.c_str();
54 QStringList aShapeTypes = aTypesStr.split(' ');
56 myTypeCombo->addItems(aShapeTypes);
57 aMainLay->addWidget(myTypeCombo, 0, 1);
58 // if the xml definition contains one type, the controls to select a type should not be shown
59 if (aShapeTypes.size() == 1) {
60 aTypeLabel->setVisible(false);
61 myTypeCombo->setVisible(false);
64 QLabel* aListLabel = new QLabel(tr("Selected objects:"), this);
65 aMainLay->addWidget(aListLabel, 1, 0);
66 // if the xml definition contains one type, an information label should be shown near to the latest
67 if (aShapeTypes.size() == 1) {
68 QString aLabelText = QString::fromStdString(theData->widgetLabel());
69 QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
70 QLabel* aSelectedLabel = new QLabel(aLabelText, this);
71 if (!aLabelIcon.isEmpty())
72 aSelectedLabel->setPixmap(QPixmap(aLabelIcon));
73 aMainLay->addWidget(aSelectedLabel, 1, 1);
74 aMainLay->setColumnStretch(2, 1);
77 myListControl = new QListWidget(this);
78 aMainLay->addWidget(myListControl, 2, 0, 2, -1);
79 aMainLay->setRowStretch(2, 1);
80 aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)???
81 aMainLay->setRowMinimumHeight(3, 20);
82 this->setLayout(aMainLay);
83 connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
85 myCopyAction = new QAction(QIcon(":pictures/copy.png"), tr("Copy"), this);
86 myCopyAction->setShortcut(QKeySequence::Copy);
87 myCopyAction->setEnabled(false);
88 connect(myCopyAction, SIGNAL(triggered(bool)), SLOT(onCopyItem()));
89 myListControl->addAction(myCopyAction);
90 myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
91 connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
94 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
97 activateShapeSelection();
100 //********************************************************************
101 void ModuleBase_WidgetMultiSelector::activateCustom()
103 ModuleBase_IViewer* aViewer = myWorkshop->viewer();
104 connect(myWorkshop, SIGNAL(selectionChanged()),
105 this, SLOT(onSelectionChanged()),
106 Qt::UniqueConnection);
109 activateShapeSelection();
112 //********************************************************************
113 void ModuleBase_WidgetMultiSelector::deactivate()
115 disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
117 activateShapeSelection();
120 //********************************************************************
121 bool ModuleBase_WidgetMultiSelector::storeValueCustom() const
123 // the value is stored on the selection changed signal processing
124 // A rare case when plugin was not loaded.
127 DataPtr aData = myFeature->data();
128 AttributeSelectionListPtr aSelectionListAttr =
129 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
131 if (aSelectionListAttr) {
133 TopAbs_ShapeEnum aCurrentType =
134 ModuleBase_WidgetShapeSelector::shapeType(myTypeCombo->currentText());
135 aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString());
140 //********************************************************************
141 bool ModuleBase_WidgetMultiSelector::restoreValue()
143 // A rare case when plugin was not loaded.
146 DataPtr aData = myFeature->data();
147 AttributeSelectionListPtr aSelectionListAttr =
148 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
150 if (aSelectionListAttr) {
151 // Restore shape type
153 ModuleBase_WidgetShapeSelector::shapeType(aSelectionListAttr->selectionType().c_str()));
154 updateSelectionList(aSelectionListAttr);
160 //********************************************************************
161 void ModuleBase_WidgetMultiSelector::storeAttributeValue()
163 DataPtr aData = myFeature->data();
164 AttributeSelectionListPtr aSelectionListAttr =
165 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
166 if (aSelectionListAttr.get() == NULL)
169 mySelectionType = aSelectionListAttr->selectionType();
171 int aSize = aSelectionListAttr->size();
172 for (int i = 0; i < aSelectionListAttr->size(); i++) {
173 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
174 mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
178 //********************************************************************
179 void ModuleBase_WidgetMultiSelector::restoreAttributeValue(bool/* theValid*/)
181 DataPtr aData = myFeature->data();
182 AttributeSelectionListPtr aSelectionListAttr =
183 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
184 if (aSelectionListAttr.get() == NULL)
186 aSelectionListAttr->clear();
189 aSelectionListAttr->setSelectionType(mySelectionType);
191 // Store selection in the attribute
192 int aSize = mySelection.size();
193 foreach (GeomSelection aSelec, mySelection) {
194 aSelectionListAttr->append(aSelec.first, aSelec.second);
198 //********************************************************************
199 bool ModuleBase_WidgetMultiSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
202 if (!thePrs.owner().IsNull()) {
203 ObjectPtr anObject = myWorkshop->selection()->getSelectableObject(thePrs.owner());
204 aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
207 aResult = std::dynamic_pointer_cast<ModelAPI_Result>(thePrs.object());
212 // We can not select a result of our feature
213 const std::list<ResultPtr>& aResList = myFeature->results();
214 std::list<ResultPtr>::const_iterator aIt;
215 bool isSkipSelf = false;
216 for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
217 if ((*aIt) == aResult) {
226 // if the result has the similar shap as the parameter shape, just the context is set to the
227 // selection list attribute.
228 DataPtr aData = myFeature->data();
229 AttributeSelectionListPtr aSelectionListAttr =
230 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
232 const TopoDS_Shape& aTDSShape = thePrs.shape();
233 // if only result is selected, an empty shape is set to the model
234 if (aTDSShape.IsNull()) {
235 aSelectionListAttr->append(aResult, GeomShapePtr());
238 GeomShapePtr aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
239 aShape->setImpl(new TopoDS_Shape(aTDSShape));
240 // We can not select a result of our feature
241 if (aShape->isEqual(aResult->shape()))
242 aSelectionListAttr->append(aResult, GeomShapePtr());
244 aSelectionListAttr->append(aResult, aShape);
249 //********************************************************************
250 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
252 QList<QWidget*> result;
253 //result << myTypeCombo;
254 result << myListControl;
258 //********************************************************************
259 bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEvent)
261 //TODO: Remove maybe?
262 return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
265 //********************************************************************
266 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
268 activateShapeSelection();
269 QObjectPtrList anEmptyList;
270 // This method will call Selection changed event which will call onSelectionChanged
271 // To clear mySelection, myListControl and storeValue()
272 // So, we don't need to call it
273 myWorkshop->setSelected(anEmptyList);
276 //********************************************************************
277 void ModuleBase_WidgetMultiSelector::onSelectionChanged()
279 QList<ModuleBase_ViewerPrs> aSelected = getSelectedEntitiesOrObjects(myWorkshop->selection());
281 DataPtr aData = myFeature->data();
282 AttributeSelectionListPtr aSelectionListAttr =
283 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
285 aSelectionListAttr->clear();
286 if (aSelected.size() > 0) {
287 foreach (ModuleBase_ViewerPrs aPrs, aSelected) {
288 if (isValidSelection(aPrs)) {
289 setSelectionCustom(aPrs);
293 emit valuesChanged();
294 // the updateObject method should be called to flush the updated sigal. The workshop listens it,
295 // calls validators for the feature and, as a result, updates the Apply button state.
296 updateObject(myFeature);
299 //********************************************************************
300 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
302 QString aShapeTypeName;
304 for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
305 aShapeTypeName = myTypeCombo->itemText(idx);
306 TopAbs_ShapeEnum aRefType = ModuleBase_WidgetShapeSelector::shapeType(aShapeTypeName);
307 if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
309 activateShapeSelection();
310 bool isBlocked = myTypeCombo->blockSignals(true);
311 myTypeCombo->setCurrentIndex(idx);
313 myTypeCombo->blockSignals(isBlocked);
314 activateShapeSelection();
320 void ModuleBase_WidgetMultiSelector::activateShapeSelection()
322 ModuleBase_IViewer* aViewer = myWorkshop->viewer();
325 QString aNewType = myTypeCombo->currentText();
327 aList.append(ModuleBase_WidgetShapeSelector::shapeType(aNewType));
328 myWorkshop->activateSubShapesSelection(aList);
330 myWorkshop->deactivateSubShapesSelection();
333 activateFilters(myWorkshop, myIsActive);
336 //********************************************************************
337 void ModuleBase_WidgetMultiSelector::updateSelectionList(AttributeSelectionListPtr theList)
339 myListControl->clear();
340 for (int i = 0; i < theList->size(); i++) {
341 AttributeSelectionPtr aAttr = theList->value(i);
342 myListControl->addItem(aAttr->namingName().c_str());
344 // We have to call repaint because sometimes the List control is not updated
345 myListControl->repaint();
348 //********************************************************************
349 void ModuleBase_WidgetMultiSelector::onCopyItem()
351 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
353 foreach(QListWidgetItem* aItem, aItems) {
356 aRes += aItem->text();
358 if (!aRes.isEmpty()) {
359 QClipboard *clipboard = QApplication::clipboard();
360 clipboard->setText(aRes);
364 //********************************************************************
365 void ModuleBase_WidgetMultiSelector::onListSelection()
367 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
368 myCopyAction->setEnabled(!aItems.isEmpty());