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>
16 #include <ModuleBase_Definitions.h>
18 #include <GeomValidators_ShapeType.h>
20 #include <ModelAPI_Data.h>
21 #include <ModelAPI_Object.h>
23 #include <Config_WidgetAPI.h>
25 #include <QGridLayout>
27 #include <QListWidget>
33 #include <QApplication>
39 //#define DEBUG_SHAPE_VALIDATION_PREVIOUS
41 class CustomListWidget : public QListWidget
44 CustomListWidget( QWidget* theParent )
45 : QListWidget( theParent )
49 virtual QSize sizeHint() const
51 int aHeight = 2*QFontMetrics( font() ).height();
52 QSize aSize = QListWidget::sizeHint();
53 return QSize( aSize.width(), aHeight );
56 virtual QSize minimumSizeHint() const
58 int aHeight = 2*QFontMetrics( font() ).height();
59 QSize aSize = QListWidget::minimumSizeHint();
60 return QSize( aSize.width(), aHeight );
64 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
65 ModuleBase_IWorkshop* theWorkshop,
66 const Config_WidgetAPI* theData,
67 const std::string& theParentId)
68 : ModuleBase_WidgetSelector(theParent, theWorkshop, theData, theParentId)
70 QGridLayout* aMainLay = new QGridLayout(this);
71 ModuleBase_Tools::adjustMargins(aMainLay);
73 QLabel* aTypeLabel = new QLabel(tr("Type"), this);
74 aMainLay->addWidget(aTypeLabel, 0, 0);
76 myTypeCombo = new QComboBox(this);
77 // There is no sense to parameterize list of types while we can not parameterize selection mode
79 std::string aPropertyTypes = theData->getProperty("type_choice");
80 QString aTypesStr = aPropertyTypes.c_str();
81 QStringList aShapeTypes = aTypesStr.split(' ');
83 myIsUseChoice = theData->getBooleanAttribute("use_choice", true);
85 myTypeCombo->addItems(aShapeTypes);
86 aMainLay->addWidget(myTypeCombo, 0, 1);
87 // if the xml definition contains one type, the controls to select a type should not be shown
88 if (aShapeTypes.size() == 1 || !myIsUseChoice) {
89 aTypeLabel->setVisible(false);
90 myTypeCombo->setVisible(false);
93 std::string aLabelText = theData->getProperty("label");
94 QLabel* aListLabel = new QLabel(!aLabelText.empty() ? aLabelText.c_str()
95 : tr("Selected objects:"), this);
96 aMainLay->addWidget(aListLabel, 1, 0);
97 // if the xml definition contains one type, an information label should be shown near to the latest
98 if (aShapeTypes.size() == 1) {
99 QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
100 if (!aLabelIcon.isEmpty()) {
101 QLabel* aSelectedLabel = new QLabel("", this);
102 aSelectedLabel->setPixmap(QPixmap(aLabelIcon));
103 aMainLay->addWidget(aSelectedLabel, 1, 1);
105 aMainLay->setColumnStretch(2, 1);
108 myListControl = new CustomListWidget(this);
109 aMainLay->addWidget(myListControl, 2, 0, 1, -1);
110 aMainLay->setRowStretch(2, 1);
111 //aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)???
112 //aMainLay->setRowMinimumHeight(3, 20);
113 //this->setLayout(aMainLay);
114 connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
116 myCopyAction = new QAction(QIcon(":pictures/copy.png"), tr("Copy"), this);
117 myCopyAction->setShortcut(QKeySequence::Copy);
118 myCopyAction->setEnabled(false);
119 connect(myCopyAction, SIGNAL(triggered(bool)), SLOT(onCopyItem()));
120 myListControl->addAction(myCopyAction);
121 myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
122 connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
125 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
129 //********************************************************************
130 bool ModuleBase_WidgetMultiSelector::storeValueCustom() const
132 // the value is stored on the selection changed signal processing
133 // A rare case when plugin was not loaded.
136 DataPtr aData = myFeature->data();
137 AttributeSelectionListPtr aSelectionListAttr =
138 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
140 if (aSelectionListAttr) {
142 TopAbs_ShapeEnum aCurrentType =
143 ModuleBase_Tools::shapeType(myTypeCombo->currentText());
144 aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString());
149 //********************************************************************
150 bool ModuleBase_WidgetMultiSelector::restoreValueCustom()
152 // A rare case when plugin was not loaded.
155 DataPtr aData = myFeature->data();
156 AttributeSelectionListPtr aSelectionListAttr =
157 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
159 if (aSelectionListAttr) {
160 // Restore shape type
161 if (!aSelectionListAttr->selectionType().empty())
162 setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
163 updateSelectionList(aSelectionListAttr);
169 //********************************************************************
170 void ModuleBase_WidgetMultiSelector::storeAttributeValue()
172 DataPtr aData = myFeature->data();
173 AttributeSelectionListPtr aSelectionListAttr =
174 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
175 if (aSelectionListAttr.get() == NULL)
178 mySelectionType = aSelectionListAttr->selectionType();
180 int aSize = aSelectionListAttr->size();
181 for (int i = 0; i < aSelectionListAttr->size(); i++) {
182 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
183 mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
187 //********************************************************************
188 void ModuleBase_WidgetMultiSelector::clearAttribute()
190 DataPtr aData = myFeature->data();
191 AttributeSelectionListPtr aSelectionListAttr =
192 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
193 aSelectionListAttr->clear();
196 //********************************************************************
197 void ModuleBase_WidgetMultiSelector::setObject(ObjectPtr theSelectedObject,
198 GeomShapePtr theShape)
200 DataPtr aData = myFeature->data();
201 AttributeSelectionListPtr aSelectionListAttr =
202 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
204 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
205 aSelectionListAttr->append(aResult, theShape);
208 //********************************************************************
209 void ModuleBase_WidgetMultiSelector::restoreAttributeValue(bool/* theValid*/)
214 DataPtr aData = myFeature->data();
215 AttributeSelectionListPtr aSelectionListAttr =
216 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
217 aSelectionListAttr->setSelectionType(mySelectionType);
219 // Store selection in the attribute
220 int aSize = mySelection.size();
221 foreach (GeomSelection aSelec, mySelection) {
222 setObject(aSelec.first, aSelec.second);
226 //********************************************************************
227 bool ModuleBase_WidgetMultiSelector::setSelection(QList<ModuleBase_ViewerPrs>& theValues,
228 const bool theToValidate)
230 QList<ModuleBase_ViewerPrs> aSkippedValues;
232 QList<ModuleBase_ViewerPrs>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
234 for (; anIt != aLast; anIt++) {
235 ModuleBase_ViewerPrs aValue = *anIt;
236 bool aProcessed = false;
237 if (!theToValidate || isValidInFilters(aValue)) {
238 aProcessed = setSelectionCustom(aValue);
241 aSkippedValues.append(aValue);
242 // if there is at least one set, the result is true
243 isDone = isDone || aProcessed;
245 // updateObject - to update/redisplay feature
246 // it is commented in order to perfom it outside the method
248 //updateObject(myFeature);
249 // this emit is necessary to call store/restore method an restore type of selection
250 //emit valuesChanged();
253 if (!aSkippedValues.empty())
254 theValues.append(aSkippedValues);
259 //********************************************************************
260 bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
262 bool aValid = ModuleBase_WidgetSelector::isValidSelectionCustom(thePrs);
264 ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
265 aValid = aResult.get() != NULL;
268 // We can not select a result of our feature
269 const std::list<ResultPtr>& aResList = myFeature->results();
270 std::list<ResultPtr>::const_iterator aIt;
271 bool isSkipSelf = false;
272 for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
273 if ((*aIt) == aResult) {
286 //********************************************************************
287 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
289 QList<QWidget*> result;
290 //result << myTypeCombo;
291 result << myListControl;
295 //********************************************************************
296 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
298 activateSelection(true);
299 activateFilters(true);
300 QList<ModuleBase_ViewerPrs> anEmptyList;
301 // This method will call Selection changed event which will call onSelectionChanged
302 // To clear mySelection, myListControl and storeValue()
303 // So, we don't need to call it
304 myWorkshop->setSelected(anEmptyList);
307 void ModuleBase_WidgetMultiSelector::updateFocus()
309 // Set focus to List control in order to make possible
310 // to use Tab key for transfer the focus to next widgets
311 myListControl->setCurrentRow(myListControl->model()->rowCount() - 1);
312 myListControl->setFocus();
315 //********************************************************************
316 void ModuleBase_WidgetMultiSelector::updateSelectionName()
320 //********************************************************************
321 QIntList ModuleBase_WidgetMultiSelector::getShapeTypes() const
323 QIntList aShapeTypes;
325 if (myTypeCombo->count() > 1 && myIsUseChoice) {
326 aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->currentText()));
329 for (int i = 0, aCount = myTypeCombo->count(); i < aCount; i++) {
330 aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->itemText(i)));
336 //********************************************************************
337 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
339 QString aShapeTypeName;
341 for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
342 aShapeTypeName = myTypeCombo->itemText(idx);
343 TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
344 if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
345 activateSelection(false);
346 activateFilters(false);
347 bool isBlocked = myTypeCombo->blockSignals(true);
348 myTypeCombo->setCurrentIndex(idx);
349 myTypeCombo->blockSignals(isBlocked);
351 activateSelection(true);
352 activateFilters(true);
358 QList<ModuleBase_ViewerPrs> ModuleBase_WidgetMultiSelector::getAttributeSelection() const
360 QList<ModuleBase_ViewerPrs> aSelected;
361 // Restore selection in the viewer by the attribute selection list
363 DataPtr aData = myFeature->data();
364 AttributeSelectionListPtr aListAttr =
365 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
367 for (int i = 0; i < aListAttr->size(); i++) {
368 AttributeSelectionPtr anAttr = aListAttr->value(i);
369 ResultPtr anObject = anAttr->context();
370 if (anObject.get()) {
372 std::shared_ptr<GeomAPI_Shape> aShapePtr = anAttr->value();
373 if (aShapePtr.get()) {
374 aShape = aShapePtr->impl<TopoDS_Shape>();
376 aSelected.append(ModuleBase_ViewerPrs(anObject, aShape, NULL));
384 //********************************************************************
385 void ModuleBase_WidgetMultiSelector::updateSelectionList(AttributeSelectionListPtr theList)
387 myListControl->clear();
388 for (int i = 0; i < theList->size(); i++) {
389 AttributeSelectionPtr aAttr = theList->value(i);
390 myListControl->addItem(aAttr->namingName().c_str());
392 // We have to call repaint because sometimes the List control is not updated
393 myListControl->repaint();
396 //********************************************************************
397 std::string ModuleBase_WidgetMultiSelector::validatorType(const QString& theType) const
401 if (theType == "Vertices")
403 else if (theType == "Edges")
405 else if (theType == "Faces")
407 else if (theType == "Solids")
413 //********************************************************************
414 void ModuleBase_WidgetMultiSelector::onCopyItem()
416 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
418 foreach(QListWidgetItem* aItem, aItems) {
421 aRes += aItem->text();
423 if (!aRes.isEmpty()) {
424 QClipboard *clipboard = QApplication::clipboard();
425 clipboard->setText(aRes);
429 //********************************************************************
430 void ModuleBase_WidgetMultiSelector::onListSelection()
432 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
433 myCopyAction->setEnabled(!aItems.isEmpty());