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_Tools::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
152 setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
153 updateSelectionList(aSelectionListAttr);
159 //********************************************************************
160 void ModuleBase_WidgetMultiSelector::storeAttributeValue()
162 DataPtr aData = myFeature->data();
163 AttributeSelectionListPtr aSelectionListAttr =
164 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
165 if (aSelectionListAttr.get() == NULL)
168 mySelectionType = aSelectionListAttr->selectionType();
170 int aSize = aSelectionListAttr->size();
171 for (int i = 0; i < aSelectionListAttr->size(); i++) {
172 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
173 mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
177 //********************************************************************
178 void ModuleBase_WidgetMultiSelector::restoreAttributeValue(bool/* theValid*/)
180 DataPtr aData = myFeature->data();
181 AttributeSelectionListPtr aSelectionListAttr =
182 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
183 if (aSelectionListAttr.get() == NULL)
185 aSelectionListAttr->clear();
188 aSelectionListAttr->setSelectionType(mySelectionType);
190 // Store selection in the attribute
191 int aSize = mySelection.size();
192 foreach (GeomSelection aSelec, mySelection) {
193 aSelectionListAttr->append(aSelec.first, aSelec.second);
197 //********************************************************************
198 bool ModuleBase_WidgetMultiSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
200 TopoDS_Shape aShape = thePrs.shape();
201 if ((myTypeCombo->count() > 1) && (!aShape.IsNull())) {
202 TopAbs_ShapeEnum aType = ModuleBase_Tools::shapeType(myTypeCombo->currentText());
203 if (aShape.ShapeType() != aType)
207 if (!thePrs.owner().IsNull()) {
208 ObjectPtr anObject = myWorkshop->selection()->getSelectableObject(thePrs.owner());
209 aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
212 aResult = std::dynamic_pointer_cast<ModelAPI_Result>(thePrs.object());
217 // We can not select a result of our feature
218 const std::list<ResultPtr>& aResList = myFeature->results();
219 std::list<ResultPtr>::const_iterator aIt;
220 bool isSkipSelf = false;
221 for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
222 if ((*aIt) == aResult) {
231 // if the result has the similar shap as the parameter shape, just the context is set to the
232 // selection list attribute.
233 DataPtr aData = myFeature->data();
234 AttributeSelectionListPtr aSelectionListAttr =
235 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
237 const TopoDS_Shape& aTDSShape = thePrs.shape();
238 // if only result is selected, an empty shape is set to the model
239 if (aTDSShape.IsNull()) {
240 aSelectionListAttr->append(aResult, GeomShapePtr());
243 GeomShapePtr aShape(new GeomAPI_Shape());
244 aShape->setImpl(new TopoDS_Shape(aTDSShape));
245 // We can not select a result of our feature
246 if (aShape->isEqual(aResult->shape()))
247 aSelectionListAttr->append(aResult, GeomShapePtr());
249 aSelectionListAttr->append(aResult, aShape);
254 //********************************************************************
255 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
257 QList<QWidget*> result;
258 //result << myTypeCombo;
259 result << myListControl;
263 //********************************************************************
264 bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEvent)
266 //TODO: Remove maybe?
267 return ModuleBase_ModelWidget::eventFilter(theObj, theEvent);
270 //********************************************************************
271 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
273 activateShapeSelection();
274 QObjectPtrList anEmptyList;
275 // This method will call Selection changed event which will call onSelectionChanged
276 // To clear mySelection, myListControl and storeValue()
277 // So, we don't need to call it
278 myWorkshop->setSelected(anEmptyList);
281 //********************************************************************
282 void ModuleBase_WidgetMultiSelector::onSelectionChanged()
284 QList<ModuleBase_ViewerPrs> aSelected = getSelectedEntitiesOrObjects(myWorkshop->selection());
286 DataPtr aData = myFeature->data();
287 AttributeSelectionListPtr aSelectionListAttr =
288 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
290 aSelectionListAttr->clear();
291 if (aSelected.size() > 0) {
292 foreach (ModuleBase_ViewerPrs aPrs, aSelected) {
293 if (isValidSelection(aPrs)) {
294 setSelectionCustom(aPrs);
298 emit valuesChanged();
299 // the updateObject method should be called to flush the updated sigal. The workshop listens it,
300 // calls validators for the feature and, as a result, updates the Apply button state.
301 updateObject(myFeature);
304 //********************************************************************
305 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
307 QString aShapeTypeName;
309 for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
310 aShapeTypeName = myTypeCombo->itemText(idx);
311 TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
312 if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
314 activateShapeSelection();
315 bool isBlocked = myTypeCombo->blockSignals(true);
316 myTypeCombo->setCurrentIndex(idx);
318 myTypeCombo->blockSignals(isBlocked);
319 activateShapeSelection();
325 void ModuleBase_WidgetMultiSelector::activateShapeSelection()
327 ModuleBase_IViewer* aViewer = myWorkshop->viewer();
330 QString aNewType = myTypeCombo->currentText();
332 aList.append(ModuleBase_Tools::shapeType(aNewType));
333 myWorkshop->activateSubShapesSelection(aList);
335 myWorkshop->deactivateSubShapesSelection();
338 activateFilters(myWorkshop, myIsActive);
341 //********************************************************************
342 void ModuleBase_WidgetMultiSelector::updateSelectionList(AttributeSelectionListPtr theList)
344 myListControl->clear();
345 for (int i = 0; i < theList->size(); i++) {
346 AttributeSelectionPtr aAttr = theList->value(i);
347 myListControl->addItem(aAttr->namingName().c_str());
349 // We have to call repaint because sometimes the List control is not updated
350 myListControl->repaint();
353 //********************************************************************
354 void ModuleBase_WidgetMultiSelector::onCopyItem()
356 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
358 foreach(QListWidgetItem* aItem, aItems) {
361 aRes += aItem->text();
363 if (!aRes.isEmpty()) {
364 QClipboard *clipboard = QApplication::clipboard();
365 clipboard->setText(aRes);
369 //********************************************************************
370 void ModuleBase_WidgetMultiSelector::onListSelection()
372 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
373 myCopyAction->setEnabled(!aItems.isEmpty());