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 ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent,
42 ModuleBase_IWorkshop* theWorkshop,
43 const Config_WidgetAPI* theData,
44 const std::string& theParentId)
45 : ModuleBase_WidgetSelector(theParent, theWorkshop, theData, theParentId)
47 QGridLayout* aMainLay = new QGridLayout(this);
48 ModuleBase_Tools::adjustMargins(aMainLay);
50 QLabel* aTypeLabel = new QLabel(tr("Type"), this);
51 aMainLay->addWidget(aTypeLabel, 0, 0);
53 myTypeCombo = new QComboBox(this);
54 // There is no sense to parameterize list of types while we can not parameterize selection mode
56 std::string aPropertyTypes = theData->getProperty("type_choice");
57 QString aTypesStr = aPropertyTypes.c_str();
58 QStringList aShapeTypes = aTypesStr.split(' ');
60 myIsUseChoice = theData->getBooleanAttribute("use_choice", true);
62 myTypeCombo->addItems(aShapeTypes);
63 aMainLay->addWidget(myTypeCombo, 0, 1);
64 // if the xml definition contains one type, the controls to select a type should not be shown
65 if (aShapeTypes.size() == 1 || !myIsUseChoice) {
66 aTypeLabel->setVisible(false);
67 myTypeCombo->setVisible(false);
70 std::string aLabelText = theData->getProperty("label");
71 QLabel* aListLabel = new QLabel(!aLabelText.empty() ? aLabelText.c_str()
72 : tr("Selected objects:"), this);
73 aMainLay->addWidget(aListLabel, 1, 0);
74 // if the xml definition contains one type, an information label should be shown near to the latest
75 if (aShapeTypes.size() == 1) {
76 QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
77 if (!aLabelIcon.isEmpty()) {
78 QLabel* aSelectedLabel = new QLabel("", this);
79 aSelectedLabel->setPixmap(QPixmap(aLabelIcon));
80 aMainLay->addWidget(aSelectedLabel, 1, 1);
82 aMainLay->setColumnStretch(2, 1);
85 myListControl = new QListWidget(this);
86 aMainLay->addWidget(myListControl, 2, 0, 2, -1);
87 aMainLay->setRowStretch(2, 1);
88 aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)???
89 aMainLay->setRowMinimumHeight(3, 20);
90 this->setLayout(aMainLay);
91 connect(myTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionTypeChanged()));
93 myCopyAction = new QAction(QIcon(":pictures/copy.png"), tr("Copy"), this);
94 myCopyAction->setShortcut(QKeySequence::Copy);
95 myCopyAction->setEnabled(false);
96 connect(myCopyAction, SIGNAL(triggered(bool)), SLOT(onCopyItem()));
97 myListControl->addAction(myCopyAction);
98 myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
99 connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
102 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
106 //********************************************************************
107 bool ModuleBase_WidgetMultiSelector::storeValueCustom() const
109 // the value is stored on the selection changed signal processing
110 // A rare case when plugin was not loaded.
113 DataPtr aData = myFeature->data();
114 AttributeSelectionListPtr aSelectionListAttr =
115 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
117 if (aSelectionListAttr) {
119 TopAbs_ShapeEnum aCurrentType =
120 ModuleBase_Tools::shapeType(myTypeCombo->currentText());
121 aSelectionListAttr->setSelectionType(myTypeCombo->currentText().toStdString());
126 //********************************************************************
127 bool ModuleBase_WidgetMultiSelector::restoreValueCustom()
129 // A rare case when plugin was not loaded.
132 DataPtr aData = myFeature->data();
133 AttributeSelectionListPtr aSelectionListAttr =
134 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
136 if (aSelectionListAttr) {
137 // Restore shape type
138 if (!aSelectionListAttr->selectionType().empty())
139 setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
140 updateSelectionList(aSelectionListAttr);
146 //********************************************************************
147 void ModuleBase_WidgetMultiSelector::storeAttributeValue()
149 DataPtr aData = myFeature->data();
150 AttributeSelectionListPtr aSelectionListAttr =
151 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
152 if (aSelectionListAttr.get() == NULL)
155 mySelectionType = aSelectionListAttr->selectionType();
157 int aSize = aSelectionListAttr->size();
158 for (int i = 0; i < aSelectionListAttr->size(); i++) {
159 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
160 mySelection.append(GeomSelection(aSelectAttr->context(), aSelectAttr->value()));
164 //********************************************************************
165 void ModuleBase_WidgetMultiSelector::clearAttribute()
167 DataPtr aData = myFeature->data();
168 AttributeSelectionListPtr aSelectionListAttr =
169 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
170 aSelectionListAttr->clear();
173 //********************************************************************
174 void ModuleBase_WidgetMultiSelector::setObject(ObjectPtr theSelectedObject,
175 GeomShapePtr theShape)
177 DataPtr aData = myFeature->data();
178 AttributeSelectionListPtr aSelectionListAttr =
179 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
181 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
182 aSelectionListAttr->append(aResult, theShape);
185 //********************************************************************
186 void ModuleBase_WidgetMultiSelector::restoreAttributeValue(bool/* theValid*/)
191 DataPtr aData = myFeature->data();
192 AttributeSelectionListPtr aSelectionListAttr =
193 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
194 aSelectionListAttr->setSelectionType(mySelectionType);
196 // Store selection in the attribute
197 int aSize = mySelection.size();
198 foreach (GeomSelection aSelec, mySelection) {
199 setObject(aSelec.first, aSelec.second);
203 //********************************************************************
204 bool ModuleBase_WidgetMultiSelector::setSelection(QList<ModuleBase_ViewerPrs>& theValues,
205 const bool theToValidate)
207 QList<ModuleBase_ViewerPrs> aSkippedValues;
209 QList<ModuleBase_ViewerPrs>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
211 for (; anIt != aLast; anIt++) {
212 ModuleBase_ViewerPrs aValue = *anIt;
213 bool aProcessed = false;
214 if (!theToValidate || isValidInFilters(aValue)) {
215 aProcessed = setSelectionCustom(aValue);
218 aSkippedValues.append(aValue);
219 // if there is at least one set, the result is true
220 isDone = isDone || aProcessed;
222 // updateObject - to update/redisplay feature
223 // it is commented in order to perfom it outside the method
225 //updateObject(myFeature);
226 // this emit is necessary to call store/restore method an restore type of selection
227 //emit valuesChanged();
230 if (!aSkippedValues.empty())
231 theValues.append(aSkippedValues);
236 //********************************************************************
237 bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
239 bool aValid = ModuleBase_WidgetSelector::isValidSelectionCustom(thePrs);
241 ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
242 aValid = aResult.get() != NULL;
245 // We can not select a result of our feature
246 const std::list<ResultPtr>& aResList = myFeature->results();
247 std::list<ResultPtr>::const_iterator aIt;
248 bool isSkipSelf = false;
249 for (aIt = aResList.cbegin(); aIt != aResList.cend(); ++aIt) {
250 if ((*aIt) == aResult) {
263 //********************************************************************
264 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
266 QList<QWidget*> result;
267 //result << myTypeCombo;
268 result << myListControl;
272 //********************************************************************
273 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
275 activateSelection(true);
276 activateFilters(true);
277 QList<ModuleBase_ViewerPrs> anEmptyList;
278 // This method will call Selection changed event which will call onSelectionChanged
279 // To clear mySelection, myListControl and storeValue()
280 // So, we don't need to call it
281 myWorkshop->setSelected(anEmptyList);
284 void ModuleBase_WidgetMultiSelector::updateFocus()
286 // Set focus to List control in order to make possible
287 // to use Tab key for transfer the focus to next widgets
288 myListControl->setCurrentRow(myListControl->model()->rowCount() - 1);
289 myListControl->setFocus();
292 //********************************************************************
293 void ModuleBase_WidgetMultiSelector::updateSelectionName()
297 //********************************************************************
298 QIntList ModuleBase_WidgetMultiSelector::getShapeTypes() const
300 QIntList aShapeTypes;
302 if (myTypeCombo->count() > 1 && myIsUseChoice) {
303 aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->currentText()));
306 for (int i = 0, aCount = myTypeCombo->count(); i < aCount; i++) {
307 aShapeTypes.append(ModuleBase_Tools::shapeType(myTypeCombo->itemText(i)));
313 //********************************************************************
314 void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum theShapeType)
316 QString aShapeTypeName;
318 for (int idx = 0; idx < myTypeCombo->count(); ++idx) {
319 aShapeTypeName = myTypeCombo->itemText(idx);
320 TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
321 if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
322 activateSelection(false);
323 activateFilters(false);
324 bool isBlocked = myTypeCombo->blockSignals(true);
325 myTypeCombo->setCurrentIndex(idx);
326 myTypeCombo->blockSignals(isBlocked);
328 activateSelection(true);
329 activateFilters(true);
335 QList<ModuleBase_ViewerPrs> ModuleBase_WidgetMultiSelector::getAttributeSelection() const
337 QList<ModuleBase_ViewerPrs> aSelected;
338 // Restore selection in the viewer by the attribute selection list
340 DataPtr aData = myFeature->data();
341 AttributeSelectionListPtr aListAttr =
342 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
344 for (int i = 0; i < aListAttr->size(); i++) {
345 AttributeSelectionPtr anAttr = aListAttr->value(i);
346 ResultPtr anObject = anAttr->context();
347 if (anObject.get()) {
349 std::shared_ptr<GeomAPI_Shape> aShapePtr = anAttr->value();
350 if (aShapePtr.get()) {
351 aShape = aShapePtr->impl<TopoDS_Shape>();
353 aSelected.append(ModuleBase_ViewerPrs(anObject, aShape, NULL));
361 //********************************************************************
362 void ModuleBase_WidgetMultiSelector::updateSelectionList(AttributeSelectionListPtr theList)
364 myListControl->clear();
365 for (int i = 0; i < theList->size(); i++) {
366 AttributeSelectionPtr aAttr = theList->value(i);
367 myListControl->addItem(aAttr->namingName().c_str());
369 // We have to call repaint because sometimes the List control is not updated
370 myListControl->repaint();
373 //********************************************************************
374 std::string ModuleBase_WidgetMultiSelector::validatorType(const QString& theType) const
378 if (theType == "Vertices")
380 else if (theType == "Edges")
382 else if (theType == "Faces")
384 else if (theType == "Solids")
390 //********************************************************************
391 void ModuleBase_WidgetMultiSelector::onCopyItem()
393 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
395 foreach(QListWidgetItem* aItem, aItems) {
398 aRes += aItem->text();
400 if (!aRes.isEmpty()) {
401 QClipboard *clipboard = QApplication::clipboard();
402 clipboard->setText(aRes);
406 //********************************************************************
407 void ModuleBase_WidgetMultiSelector::onListSelection()
409 QList<QListWidgetItem*> aItems = myListControl->selectedItems();
410 myCopyAction->setEnabled(!aItems.isEmpty());