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 std::list<AttributePtr> aSelListAttributes = aParentFeature->data()->attributes(
207 ModelAPI_AttributeSelectionList::typeId());
208 if (aSelListAttributes.size() == 1) {
209 AttributePtr aFirstAttribute = aSelListAttributes.front();
211 SessionPtr aMgr = ModelAPI_Session::get();
212 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
213 std::string aValidatorID, anError;
214 bool isValidPComposite = aFactory->validate(aFirstAttribute, aValidatorID, anError);
215 if (!isValidPComposite) {
216 int anAnswer = QMessageBox::question(
217 aWorkshop->desktop(), tr("Apply current feature"),
218 tr("The current feature can not be used as an argument of the parent feature.\n\
219 After apply it will be deleted. Would you like to continue?"),
220 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
221 if (anAnswer == QMessageBox::Ok)
229 aMgr->finishOperation();
231 aMgr->abortOperation();
238 bool PartSet_WidgetSketchCreator::isSelectionMode() const
240 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
241 bool aHasValueInList = anAttrList.get() && anAttrList->size() > 0;
243 return !aHasValueInList;
246 bool PartSet_WidgetSketchCreator::setSelection(QList<ModuleBase_ViewerPrs>& theValues,
247 const bool theToValidate)
250 if (!startSketchOperation(theValues)) {
251 QList<ModuleBase_ViewerPrs>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
252 bool aProcessed = false;
253 for (; anIt != aLast; anIt++) {
254 ModuleBase_ViewerPrs aValue = *anIt;
255 if (!theToValidate || isValidInFilters(aValue))
256 aProcessed = setBaseAttributeSelection(aValue) || aProcessed;
260 emit valuesChanged();
261 updateObject(myFeature);
262 setVisibleSelectionControl(false);
263 // manually deactivation because the widget was not activated as has no focus acceptin controls
265 emit focusOutWidget(this);
271 //********************************************************************
272 void PartSet_WidgetSketchCreator::onSelectionChanged()
274 QList<ModuleBase_ViewerPrs> aSelected = getFilteredSelected();
275 bool isDone = setSelection(aSelected, true/*false*/);
278 //********************************************************************
279 void PartSet_WidgetSketchCreator::updateOnSelectionChanged(const bool theDone)
283 bool PartSet_WidgetSketchCreator::startSketchOperation(const QList<ModuleBase_ViewerPrs>& theValues)
285 bool aSketchStarted = false;
287 if (theValues.size() != 1)
288 return aSketchStarted;
290 ModuleBase_ViewerPrs aValue = theValues.front();
291 if (!PartSet_WidgetSketchLabel::canFillSketch(aValue))
292 return aSketchStarted;
294 aSketchStarted = true;
296 // manually deactivation because the widget was not activated as has no focus acceptin controls
298 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
299 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
301 // Launch Sketch operation
302 CompositeFeaturePtr aCompFeature =
303 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
305 /// add sketch feature without current feature change.
306 /// it is important to do not change the current feature in order to
307 /// after sketch edition, the extrusion cut feature becomes current
308 SessionPtr aMgr = ModelAPI_Session::get();
309 DocumentPtr aDoc = aMgr->activeDocument();
310 FeaturePtr aPreviousCurrentFeature = aDoc->currentFeature(false);
311 FeaturePtr aSketch = aCompFeature->addFeature("Sketch");
313 PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(aSketch, aValue);
315 aDoc->setCurrentFeature(aPreviousCurrentFeature, false);
317 // start edit operation for the sketch
318 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
319 (myModule->createOperation("Sketch"));
321 aFOperation->setFeature(aSketch);
322 myModule->sendOperation(aFOperation);
324 return aSketchStarted;
327 bool PartSet_WidgetSketchCreator::focusTo()
329 if (isSelectionMode()) {
330 activateSelectionControl();
334 //setVisibleSelectionControl(false);
336 connect(myModule, SIGNAL(resumed(ModuleBase_Operation*)), SLOT(onResumed(ModuleBase_Operation*)));
337 SessionPtr aMgr = ModelAPI_Session::get();
338 // Open transaction that is general for the previous nested one: it will be closed on nested commit
339 bool aIsOp = aMgr->isOperation();
341 const static std::string aNestedOpID("Parameters modification");
342 aMgr->startOperation(aNestedOpID, true);
349 void PartSet_WidgetSketchCreator::deactivate()
351 ModuleBase_WidgetSelector::deactivate();
353 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
354 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
356 XGUI_Tools::workshop(myWorkshop)->viewer()->update();
360 void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
362 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
364 CompositeFeaturePtr aCompFeature =
365 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
366 //CompositeFeaturePtr aSketchFeature =
367 // std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
368 if (aCompFeature->numberOfSubs() == 0) {
369 // do nothing, selection control should be hidden
370 setVisibleSelectionControl(false);
372 // check if the created sketch is invalid. Validate attribute selection list
373 // Shetch should be deleted if the attribute is invalid.
374 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
376 SessionPtr aMgr = ModelAPI_Session::get();
377 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
378 std::string aValidatorID, anError;
379 bool isValidPComposite = aFactory->validate(anAttrList, aValidatorID, anError);
380 /// if the sketch is not appropriate fro extrusion, it should be deleted and
381 /// the selection control should be activated again
382 if (!isValidPComposite) {
383 CompositeFeaturePtr aSketchFeature =
384 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
386 QObjectPtrList anObjects;
387 anObjects.append(aSketchFeature);
388 std::set<FeaturePtr> anIgnoredFeatures;
389 aWorkshop->deleteFeatures(anObjects, anIgnoredFeatures);
391 // do nothing, selection control should be shown
392 activateSelectionControl();
395 setVisibleSelectionControl(false);
396 // Update value in attribute selection list
397 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
398 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
399 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
400 if (aWidget->attributeID() == myAttributeListID)
401 aWidget->restoreValue();
404 // Hide sketcher result
405 CompositeFeaturePtr aSketchFeature =
406 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
407 std::list<ResultPtr> aResults = aSketchFeature->results();
408 std::list<ResultPtr>::const_iterator aIt;
409 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
410 (*aIt)->setDisplayed(false);
412 aSketchFeature->setDisplayed(false);
413 static Events_Loop* aLoop = Events_Loop::loop();
414 aLoop->flush(aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY));
416 // Add Selected body were created the sketcher to list of selected objects
417 std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::BOOLEAN_OBJECTS_ID();
418 AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
419 if (aSelList.get()) {
420 DataPtr aData = aSketchFeature->data();
421 AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
422 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
423 ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
425 SessionPtr aMgr = ModelAPI_Session::get();
426 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
427 AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
428 std::string aValidatorID, anError;
429 aSelList->append(aRes, GeomShapePtr());
430 if (aFactory->validate(anAttribute, aValidatorID, anError))
431 updateObject(aCompFeature);
440 bool PartSet_WidgetSketchCreator::setBaseAttributeSelection(const ModuleBase_ViewerPrs& theValue)
445 getGeomSelection(theValue, anObject, aShape);
447 std::string anAttributeId = myAttributeListID;
448 DataPtr aData = myFeature->data();
449 ModuleBase_Tools::setObject(aData->attribute(anAttributeId), anObject, aShape,