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),
54 myModule(theModule), myIsCustomAttribute(false)
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 AttributePtr PartSet_WidgetSketchCreator::attribute() const
119 AttributePtr anAttribute;
120 if (myIsCustomAttribute)
121 anAttribute = myFeature->attribute(myAttributeListID);
123 anAttribute = ModuleBase_WidgetSelector::attribute();
128 //********************************************************************
129 bool PartSet_WidgetSketchCreator::isValidSelection(const ModuleBase_ViewerPrs& theValue)
132 if (getValidState(theValue, aValid)) {
135 // check selection to create new sketh (XML current attribute)
136 aValid = isValidSelectionForAttribute(theValue, attribute());
138 // check selection to fill list attribute (myAttributeListID)
139 myIsCustomAttribute = true;
140 aValid = isValidSelectionForAttribute(theValue, attribute());
141 myIsCustomAttribute = false;
143 storeValidState(theValue, aValid);
147 void PartSet_WidgetSketchCreator::activateSelectionControl()
149 setVisibleSelectionControl(true);
151 // we need to call activate here as the widget has no focus accepted controls
152 // if these controls are added here, activate will happens automatically after focusIn()
153 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
154 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
155 aPanel->activateWidget(this, false);
158 void PartSet_WidgetSketchCreator::setVisibleSelectionControl(const bool theSelectionControl)
160 // hide current widget, activate the next widget
161 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
162 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
163 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
164 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
165 if (theSelectionControl) { // hide other controls
167 aWidget->setVisible(false);
169 else { // hide current control
171 aWidget->setVisible(false);
173 aWidget->setVisible(true);
177 if (theSelectionControl) {
178 bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
179 if (!aBodyIsVisualized) {
180 // We have to select a plane before any operation
181 myPreviewPlanes->showPreviewPlanes(myWorkshop);
184 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
185 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
187 aWorkshop->viewer()->update();
191 QIntList PartSet_WidgetSketchCreator::getShapeTypes() const
193 QIntList aShapeTypes;
194 foreach(QString aType, myShapeTypes) {
195 aShapeTypes.append(ModuleBase_Tools::shapeType(aType));
200 void PartSet_WidgetSketchCreator::setEditingMode(bool isEditing)
202 ModuleBase_ModelWidget::setEditingMode(isEditing);
204 setVisibleSelectionControl(false);
207 bool PartSet_WidgetSketchCreator::canCommitCurrentSketch(ModuleBase_IWorkshop* theWorkshop)
209 bool aCanCommit = true;
210 ModuleBase_Operation* anOperation = theWorkshop->currentOperation();
211 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(theWorkshop);
212 XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
213 // check if the operation is nested
214 if (anOperation && anOpMgr->operationsCount() > 1) {
215 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(anOperation);
216 FeaturePtr aCurrentFeature = aFOperation ? aFOperation->feature() : FeaturePtr();
218 ModuleBase_Operation* aPOperation = anOpMgr->previousOperation(anOperation);
219 ModuleBase_OperationFeature* aFPOperation = dynamic_cast<ModuleBase_OperationFeature*>(aPOperation);
220 FeaturePtr aParentFeature = aFPOperation ? aFPOperation->feature() : FeaturePtr();
222 CompositeFeaturePtr aCompositeFeature =
223 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCurrentFeature);
224 CompositeFeaturePtr aPCompositeFeature =
225 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aParentFeature);
226 // check if both features are composite: extrusion and sketch
227 if (aCompositeFeature.get() && aPCompositeFeature.get()) {
228 // selection attribute list is currently filled in execute(), so we need to call it
229 // if there is no opened transaction, it should be started and finished
230 SessionPtr aMgr = ModelAPI_Session::get();
231 bool aIsOp = aMgr->isOperation();
233 aMgr->startOperation();
234 aPCompositeFeature->execute(); // to fill attribute selection list
236 std::list<AttributePtr> aSelListAttributes = aParentFeature->data()->attributes(
237 ModelAPI_AttributeSelectionList::typeId());
238 if (aSelListAttributes.size() == 1) {
239 AttributePtr aFirstAttribute = aSelListAttributes.front();
241 SessionPtr aMgr = ModelAPI_Session::get();
242 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
243 std::string aValidatorID, anError;
244 bool isValidPComposite = aFactory->validate(aFirstAttribute, aValidatorID, anError);
245 if (!isValidPComposite) {
246 int anAnswer = QMessageBox::question(
247 aWorkshop->desktop(), tr("Apply current feature"),
248 tr("The current feature can not be used as an argument of the parent feature.\n\
249 After apply it will be deleted. Would you like to continue?"),
250 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
251 if (anAnswer == QMessageBox::Ok)
259 aMgr->finishOperation();
261 aMgr->abortOperation();
268 bool PartSet_WidgetSketchCreator::isSelectionMode() const
270 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
271 bool aHasValueInList = anAttrList.get() && anAttrList->size() > 0;
273 return !aHasValueInList;
276 bool PartSet_WidgetSketchCreator::setSelection(QList<ModuleBase_ViewerPrs>& theValues,
277 const bool theToValidate)
280 if (!startSketchOperation(theValues)) {
281 myIsCustomAttribute = true;
282 QList<ModuleBase_ViewerPrs>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
283 bool aProcessed = false;
284 for (; anIt != aLast; anIt++) {
285 ModuleBase_ViewerPrs aValue = *anIt;
286 if (!theToValidate || isValidInFilters(aValue))
287 aProcessed = setSelectionCustom(aValue) || aProcessed;
289 myIsCustomAttribute = true;
292 emit valuesChanged();
293 updateObject(myFeature);
294 setVisibleSelectionControl(false);
295 // manually deactivation because the widget was not activated as has no focus acceptin controls
297 emit focusOutWidget(this);
303 //********************************************************************
304 void PartSet_WidgetSketchCreator::onSelectionChanged()
306 QList<ModuleBase_ViewerPrs> aSelected = getFilteredSelected();
307 bool isDone = setSelection(aSelected, true/*false*/);
310 //********************************************************************
311 void PartSet_WidgetSketchCreator::updateOnSelectionChanged(const bool theDone)
315 bool PartSet_WidgetSketchCreator::startSketchOperation(const QList<ModuleBase_ViewerPrs>& theValues)
317 bool aSketchStarted = false;
319 if (theValues.size() != 1)
320 return aSketchStarted;
322 ModuleBase_ViewerPrs aValue = theValues.front();
323 if (!PartSet_WidgetSketchLabel::canFillSketch(aValue))
324 return aSketchStarted;
326 aSketchStarted = true;
328 // manually deactivation because the widget was not activated as has no focus acceptin controls
330 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
331 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
333 // Launch Sketch operation
334 CompositeFeaturePtr aCompFeature =
335 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
337 /// add sketch feature without current feature change.
338 /// it is important to do not change the current feature in order to
339 /// after sketch edition, the extrusion cut feature becomes current
340 SessionPtr aMgr = ModelAPI_Session::get();
341 DocumentPtr aDoc = aMgr->activeDocument();
342 FeaturePtr aPreviousCurrentFeature = aDoc->currentFeature(false);
343 FeaturePtr aSketch = aCompFeature->addFeature("Sketch");
345 PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(aSketch, aValue);
347 aDoc->setCurrentFeature(aPreviousCurrentFeature, false);
349 // start edit operation for the sketch
350 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
351 (myModule->createOperation("Sketch"));
353 aFOperation->setFeature(aSketch);
354 myModule->sendOperation(aFOperation);
356 return aSketchStarted;
359 bool PartSet_WidgetSketchCreator::focusTo()
361 if (isSelectionMode()) {
362 activateSelectionControl();
364 SessionPtr aMgr = ModelAPI_Session::get();
365 bool aIsOp = aMgr->isOperation();
367 aMgr->startOperation(myFeature->getKind());
371 //setVisibleSelectionControl(false);
373 connect(myModule, SIGNAL(resumed(ModuleBase_Operation*)), SLOT(onResumed(ModuleBase_Operation*)));
374 SessionPtr aMgr = ModelAPI_Session::get();
375 // Open transaction that is general for the previous nested one: it will be closed on nested commit
376 bool aIsOp = aMgr->isOperation();
378 const static std::string aNestedOpID("Parameters modification");
379 aMgr->startOperation(aNestedOpID, true);
386 void PartSet_WidgetSketchCreator::deactivate()
388 ModuleBase_WidgetSelector::deactivate();
390 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
391 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
393 XGUI_Tools::workshop(myWorkshop)->viewer()->update();
397 void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
399 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
401 CompositeFeaturePtr aCompFeature =
402 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
403 //CompositeFeaturePtr aSketchFeature =
404 // std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
405 if (aCompFeature->numberOfSubs() == 0) {
406 // do nothing, selection control should be hidden
407 setVisibleSelectionControl(false);
409 // check if the created sketch is invalid. Validate attribute selection list
410 // Shetch should be deleted if the attribute is invalid.
411 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
413 SessionPtr aMgr = ModelAPI_Session::get();
414 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
415 std::string aValidatorID, anError;
416 bool isValidPComposite = aFactory->validate(anAttrList, aValidatorID, anError);
417 /// if the sketch is not appropriate fro extrusion, it should be deleted and
418 /// the selection control should be activated again
419 if (!isValidPComposite) {
420 CompositeFeaturePtr aSketchFeature =
421 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
423 QObjectPtrList anObjects;
424 anObjects.append(aSketchFeature);
425 std::set<FeaturePtr> anIgnoredFeatures;
426 aWorkshop->deleteFeatures(anObjects, anIgnoredFeatures);
428 // do nothing, selection control should be shown
429 activateSelectionControl();
432 setVisibleSelectionControl(false);
433 // Update value in attribute selection list
434 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
435 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
436 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
437 if (aWidget->attributeID() == myAttributeListID)
438 aWidget->restoreValue();
441 // Hide sketcher result
442 CompositeFeaturePtr aSketchFeature =
443 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
444 std::list<ResultPtr> aResults = aSketchFeature->results();
445 std::list<ResultPtr>::const_iterator aIt;
446 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
447 (*aIt)->setDisplayed(false);
449 aSketchFeature->setDisplayed(false);
450 static Events_Loop* aLoop = Events_Loop::loop();
451 aLoop->flush(aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY));
453 // Add Selected body were created the sketcher to list of selected objects
454 std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::OBJECTS_ID();
455 AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
456 if (aSelList.get()) {
457 DataPtr aData = aSketchFeature->data();
458 AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
459 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
460 ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
462 SessionPtr aMgr = ModelAPI_Session::get();
463 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
464 AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
465 std::string aValidatorID, anError;
466 aSelList->append(aRes, GeomShapePtr());
467 if (aFactory->validate(anAttribute, aValidatorID, anError))
468 updateObject(aCompFeature);