1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PartSet_WidgetSketchCreator.cpp
4 // Created: 08 June 2015
5 // Author: Vitaly SMETANNIKOV
7 #include "PartSet_WidgetSketchCreator.h"
8 #include "PartSet_Module.h"
9 #include "PartSet_WidgetSketchLabel.h"
10 #include "PartSet_PreviewPlanes.h"
12 #include <Config_Keywords.h>
14 #include <XGUI_ModuleConnector.h>
15 #include <XGUI_Workshop.h>
16 #include <XGUI_Displayer.h>
17 #include <XGUI_SelectionMgr.h>
18 #include <XGUI_OperationMgr.h>
19 #include <XGUI_PropertyPanel.h>
20 #include <XGUI_Tools.h>
21 #include <XGUI_ViewerProxy.h>
23 #include <GeomAPI_Face.h>
25 #include <ModelAPI_Session.h>
26 #include <ModelAPI_ResultBody.h>
27 #include <ModelAPI_AttributeSelection.h>
28 #include <ModelAPI_AttributeSelectionList.h>
29 #include <ModelAPI_Validator.h>
30 #include <ModelAPI_Events.h>
32 #include <SketchPlugin_SketchEntity.h>
33 #include <FeaturesPlugin_CompositeBoolean.h>
35 #include <ModuleBase_Tools.h>
36 #include <ModuleBase_Operation.h>
37 #include <ModuleBase_IPropertyPanel.h>
38 #include <ModuleBase_OperationFeature.h>
39 #include <Config_WidgetAPI.h>
41 #include <Events_Loop.h>
45 //#include <QFormLayout>
46 #include <QVBoxLayout>
47 #include <QMessageBox>
48 #include <QMainWindow>
50 PartSet_WidgetSketchCreator::PartSet_WidgetSketchCreator(QWidget* theParent,
51 PartSet_Module* theModule,
52 const Config_WidgetAPI* theData)
53 : ModuleBase_WidgetSelector(theParent, theModule->workshop(), theData),
56 myAttributeListID = theData->getProperty("attribute_list_id");
58 //QFormLayout* aLayout = new QFormLayout(this);
59 QVBoxLayout* aLayout = new QVBoxLayout(this);
60 ModuleBase_Tools::zeroMargins(aLayout);
62 ModuleBase_Tools::adjustMargins(aLayout);
64 QString aLabelText = QString::fromStdString(theData->widgetLabel());
65 QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
67 myLabel = new QLabel(aLabelText, this);
68 myLabel->setWordWrap(true);
69 aLayout->addWidget(myLabel);
70 /*if (!aLabelIcon.isEmpty())
71 myLabel->setPixmap(QPixmap(aLabelIcon));
74 QString aToolTip = QString::fromStdString(theData->widgetTooltip());
75 myTextLine = new QLineEdit(this);
76 myTextLine->setReadOnly(true);
77 myTextLine->setToolTip(aToolTip);
78 myTextLine->installEventFilter(this);
80 myLabel->setToolTip(aToolTip);
82 aLayout->addRow(myLabel, myTextLine);*/
84 std::string aTypes = theData->getProperty("shape_types");
85 myShapeTypes = QString(aTypes.c_str()).split(' ', QString::SkipEmptyParts);
87 myPreviewPlanes = new PartSet_PreviewPlanes();
90 PartSet_WidgetSketchCreator::~PartSet_WidgetSketchCreator()
94 QList<QWidget*> PartSet_WidgetSketchCreator::getControls() const
96 QList<QWidget*> aControls;
97 aControls.append(myLabel);
101 bool PartSet_WidgetSketchCreator::restoreValueCustom()
103 /*CompositeFeaturePtr aCompFeature =
104 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
105 if (aCompFeature->numberOfSubs() > 0) {
106 FeaturePtr aSubFeature = aCompFeature->subFeature(0);
107 myTextLine->setText(QString::fromStdString(aSubFeature->data()->name()));
112 bool PartSet_WidgetSketchCreator::storeValueCustom() const
117 void PartSet_WidgetSketchCreator::activateSelectionControl()
119 setVisibleSelectionControl(true);
121 // we need to call activate here as the widget has no focus accepted controls
122 // if these controls are added here, activate will happens automatically after focusIn()
123 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
124 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
125 aPanel->activateWidget(this, false);
128 void PartSet_WidgetSketchCreator::setVisibleSelectionControl(const bool theSelectionControl)
130 // hide current widget, activate the next widget
131 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
132 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
133 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
134 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
135 if (theSelectionControl) { // hide other controls
137 aWidget->setVisible(false);
139 else { // hide current control
141 aWidget->setVisible(false);
143 aWidget->setVisible(true);
147 if (theSelectionControl) {
148 bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
149 if (!aBodyIsVisualized) {
150 // We have to select a plane before any operation
151 myPreviewPlanes->showPreviewPlanes(myWorkshop);
154 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
155 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
157 aWorkshop->viewer()->update();
161 QIntList PartSet_WidgetSketchCreator::getShapeTypes() const
163 QIntList aShapeTypes;
164 foreach(QString aType, myShapeTypes) {
165 aShapeTypes.append(ModuleBase_Tools::shapeType(aType));
170 void PartSet_WidgetSketchCreator::setEditingMode(bool isEditing)
172 ModuleBase_ModelWidget::setEditingMode(isEditing);
174 setVisibleSelectionControl(false);
177 bool PartSet_WidgetSketchCreator::canCommitCurrentSketch(ModuleBase_IWorkshop* theWorkshop)
179 bool aCanCommit = true;
180 ModuleBase_Operation* anOperation = theWorkshop->currentOperation();
181 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop);
182 XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
183 // check if the operation is nested
184 if (anOperation && anOpMgr->operationsCount() > 1) {
185 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(anOperation);
186 FeaturePtr aCurrentFeature = aFOperation ? aFOperation->feature() : FeaturePtr();
188 ModuleBase_Operation* aPOperation = anOpMgr->previousOperation(anOperation);
189 ModuleBase_OperationFeature* aFPOperation = dynamic_cast<ModuleBase_OperationFeature*>(aPOperation);
190 FeaturePtr aParentFeature = aFPOperation ? aFPOperation->feature() : FeaturePtr();
192 CompositeFeaturePtr aCompositeFeature =
193 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCurrentFeature);
194 CompositeFeaturePtr aPCompositeFeature =
195 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aParentFeature);
196 // check if both features are composite: extrusion and sketch
197 if (aCompositeFeature.get() && aPCompositeFeature.get()) {
198 // selection attribute list is currently filled in execute(), so we need to call it
199 // if there is no opened transaction, it should be started and finished
200 SessionPtr aMgr = ModelAPI_Session::get();
201 bool aIsOp = aMgr->isOperation();
203 aMgr->startOperation();
204 aPCompositeFeature->execute(); // to fill attribute selection list
206 aMgr->finishOperation();
208 std::list<AttributePtr> aSelListAttributes = aParentFeature->data()->attributes(
209 ModelAPI_AttributeSelectionList::typeId());
210 if (aSelListAttributes.size() == 1) {
211 AttributePtr aFirstAttribute = aSelListAttributes.front();
213 SessionPtr aMgr = ModelAPI_Session::get();
214 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
215 std::string aValidatorID, anError;
216 bool isValidPComposite = aFactory->validate(aFirstAttribute, aValidatorID, anError);
217 if (!isValidPComposite) {
218 int anAnswer = QMessageBox::question(
219 aWorkshop->desktop(), tr("Apply current feature"),
220 tr("The current feature can not be used as an argument of the parent feature.\n\
221 After apply it will be deleted. Would you like to continue?"),
222 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
223 if (anAnswer == QMessageBox::Ok)
234 bool PartSet_WidgetSketchCreator::isSelectionMode() const
236 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
237 bool aHasValueInList = anAttrList.get() && anAttrList->size() > 0;
239 return !aHasValueInList;
242 void PartSet_WidgetSketchCreator::onSelectionChanged()
244 QList<ModuleBase_ViewerPrs> aSelected = getFilteredSelected();
246 if (!startSketchOperation(aSelected)) {
247 QList<ModuleBase_ViewerPrs>::const_iterator anIt = aSelected.begin(), aLast = aSelected.end();
248 bool aProcessed = false;
249 for (; anIt != aLast; anIt++) {
250 ModuleBase_ViewerPrs aValue = *anIt;
251 if (isValidInFilters(aValue))
252 aProcessed = setBaseAttributeSelection(aValue) || aProcessed;
255 emit valuesChanged();
256 updateObject(myFeature);
257 setVisibleSelectionControl(false);
258 // manually deactivation because the widget was not activated as has no focus acceptin controls
260 emit focusOutWidget(this);
265 //********************************************************************
266 void PartSet_WidgetSketchCreator::setObject(ObjectPtr theObject,
267 GeomShapePtr theShape)
269 DataPtr aData = myFeature->data();
270 ModuleBase_Tools::setObject(aData->attribute(attributeID()), theObject, theShape,
271 myWorkshop, myIsInValidate);
273 //::setObject(aData->attribute(attributeID()), theObject, theShape);
276 bool PartSet_WidgetSketchCreator::startSketchOperation(const QList<ModuleBase_ViewerPrs>& theValues)
278 bool aSketchStarted = false;
280 if (theValues.size() != 1)
281 return aSketchStarted;
283 ModuleBase_ViewerPrs aValue = theValues.front();
284 if (!PartSet_WidgetSketchLabel::canFillSketch(aValue))
285 return aSketchStarted;
287 aSketchStarted = true;
289 // manually deactivation because the widget was not activated as has no focus acceptin controls
291 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
292 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
294 // Launch Sketch operation
295 CompositeFeaturePtr aCompFeature =
296 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
298 /// add sketch feature without current feature change.
299 /// it is important to do not change the current feature in order to
300 /// after sketch edition, the extrusion cut feature becomes current
301 SessionPtr aMgr = ModelAPI_Session::get();
302 DocumentPtr aDoc = aMgr->activeDocument();
303 FeaturePtr aPreviousCurrentFeature = aDoc->currentFeature(false);
304 FeaturePtr aSketch = aCompFeature->addFeature("Sketch");
306 PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(aSketch, aValue);
308 aDoc->setCurrentFeature(aPreviousCurrentFeature, false);
310 // start edit operation for the sketch
311 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
312 (myModule->createOperation("Sketch"));
314 aFOperation->setFeature(aSketch);
315 myModule->sendOperation(aFOperation);
317 return aSketchStarted;
320 bool PartSet_WidgetSketchCreator::focusTo()
322 if (isSelectionMode()) {
323 activateSelectionControl();
327 //setVisibleSelectionControl(false);
329 connect(myModule, SIGNAL(resumed(ModuleBase_Operation*)), SLOT(onResumed(ModuleBase_Operation*)));
330 SessionPtr aMgr = ModelAPI_Session::get();
331 // Open transaction that is general for the previous nested one: it will be closed on nested commit
332 bool aIsOp = aMgr->isOperation();
334 const static std::string aNestedOpID("Parameters modification");
335 aMgr->startOperation(aNestedOpID, true);
342 void PartSet_WidgetSketchCreator::deactivate()
344 ModuleBase_WidgetSelector::deactivate();
346 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
347 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
349 XGUI_Tools::workshop(myWorkshop)->viewer()->update();
353 void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
355 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
357 CompositeFeaturePtr aCompFeature =
358 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
359 //CompositeFeaturePtr aSketchFeature =
360 // std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
361 if (aCompFeature->numberOfSubs() == 0) {
362 // do nothing, selection control should be hidden
363 setVisibleSelectionControl(false);
365 // check if the created sketch is invalid. Validate attribute selection list
366 // Shetch should be deleted if the attribute is invalid.
367 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
369 SessionPtr aMgr = ModelAPI_Session::get();
370 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
371 std::string aValidatorID, anError;
372 bool isValidPComposite = aFactory->validate(anAttrList, aValidatorID, anError);
373 /// if the sketch is not appropriate fro extrusion, it should be deleted and
374 /// the selection control should be activated again
375 if (!isValidPComposite) {
376 CompositeFeaturePtr aSketchFeature =
377 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
379 QObjectPtrList anObjects;
380 anObjects.append(aSketchFeature);
381 std::set<FeaturePtr> anIgnoredFeatures;
382 aWorkshop->deleteFeatures(anObjects, anIgnoredFeatures);
384 // do nothing, selection control should be shown
385 activateSelectionControl();
388 // do nothing, selection control should be hidden
389 setVisibleSelectionControl(false);
390 // Update value in attribute selection list
391 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
392 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
393 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
394 if (aWidget->attributeID() == myAttributeListID)
395 aWidget->restoreValue();
398 // Hide sketcher result
399 CompositeFeaturePtr aSketchFeature =
400 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
401 std::list<ResultPtr> aResults = aSketchFeature->results();
402 std::list<ResultPtr>::const_iterator aIt;
403 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
404 (*aIt)->setDisplayed(false);
406 aSketchFeature->setDisplayed(false);
408 // restore value in the selection control
411 // Add Selected body were created the sketcher to list of selected objects
412 std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::BOOLEAN_OBJECTS_ID();
413 AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
414 if (aSelList.get()) {
415 DataPtr aData = aSketchFeature->data();
416 AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
417 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
418 ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
420 SessionPtr aMgr = ModelAPI_Session::get();
421 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
422 AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
423 std::string aValidatorID, anError;
424 aSelList->append(aRes, GeomShapePtr());
425 if (aFactory->validate(anAttribute, aValidatorID, anError))
426 updateObject(aCompFeature);
434 bool PartSet_WidgetSketchCreator::setBaseAttributeSelection(const ModuleBase_ViewerPrs& theValue)
439 getGeomSelection(theValue, anObject, aShape);
441 std::string anAttributeId = myAttributeListID;
442 DataPtr aData = myFeature->data();
443 ModuleBase_Tools::setObject(aData->attribute(anAttributeId), anObject, aShape,