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::updateOnSelectionChanged(const bool theDone)
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 setVisibleSelectionControl(false);
389 // Update value in attribute selection list
390 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
391 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
392 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
393 if (aWidget->attributeID() == myAttributeListID)
394 aWidget->restoreValue();
397 // Hide sketcher result
398 CompositeFeaturePtr aSketchFeature =
399 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
400 std::list<ResultPtr> aResults = aSketchFeature->results();
401 std::list<ResultPtr>::const_iterator aIt;
402 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
403 (*aIt)->setDisplayed(false);
405 aSketchFeature->setDisplayed(false);
406 static Events_Loop* aLoop = Events_Loop::loop();
407 aLoop->flush(aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY));
409 // Add Selected body were created the sketcher to list of selected objects
410 std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::BOOLEAN_OBJECTS_ID();
411 AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
412 if (aSelList.get()) {
413 DataPtr aData = aSketchFeature->data();
414 AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
415 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
416 ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
418 SessionPtr aMgr = ModelAPI_Session::get();
419 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
420 AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
421 std::string aValidatorID, anError;
422 aSelList->append(aRes, GeomShapePtr());
423 if (aFactory->validate(anAttribute, aValidatorID, anError))
424 updateObject(aCompFeature);
433 bool PartSet_WidgetSketchCreator::setBaseAttributeSelection(const ModuleBase_ViewerPrs& theValue)
438 getGeomSelection(theValue, anObject, aShape);
440 std::string anAttributeId = myAttributeListID;
441 DataPtr aData = myFeature->data();
442 ModuleBase_Tools::setObject(aData->attribute(anAttributeId), anObject, aShape,