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 = setSelectionCustom(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 theSelectedObject,
267 GeomShapePtr theShape)
269 // do nothing because all processing is in onSelectionChanged()
272 bool PartSet_WidgetSketchCreator::startSketchOperation(const QList<ModuleBase_ViewerPrs>& theValues)
274 bool aSketchStarted = false;
276 if (theValues.size() != 1)
277 return aSketchStarted;
279 ModuleBase_ViewerPrs aValue = theValues.front();
280 if (!PartSet_WidgetSketchLabel::canFillSketch(aValue))
281 return aSketchStarted;
283 aSketchStarted = true;
285 // manually deactivation because the widget was not activated as has no focus acceptin controls
287 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
288 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
290 // Launch Sketch operation
291 CompositeFeaturePtr aCompFeature =
292 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
294 /// add sketch feature without current feature change.
295 /// it is important to do not change the current feature in order to
296 /// after sketch edition, the extrusion cut feature becomes current
297 SessionPtr aMgr = ModelAPI_Session::get();
298 DocumentPtr aDoc = aMgr->activeDocument();
299 FeaturePtr aPreviousCurrentFeature = aDoc->currentFeature(false);
300 FeaturePtr aSketch = aCompFeature->addFeature("Sketch");
302 PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(aSketch, aValue);
304 aDoc->setCurrentFeature(aPreviousCurrentFeature, false);
306 // start edit operation for the sketch
307 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
308 (myModule->createOperation("Sketch"));
310 aFOperation->setFeature(aSketch);
311 myModule->sendOperation(aFOperation);
313 return aSketchStarted;
316 bool PartSet_WidgetSketchCreator::focusTo()
318 if (isSelectionMode()) {
319 activateSelectionControl();
323 //setVisibleSelectionControl(false);
325 connect(myModule, SIGNAL(resumed(ModuleBase_Operation*)), SLOT(onResumed(ModuleBase_Operation*)));
326 SessionPtr aMgr = ModelAPI_Session::get();
327 // Open transaction that is general for the previous nested one: it will be closed on nested commit
328 bool aIsOp = aMgr->isOperation();
330 const static std::string aNestedOpID("Parameters modification");
331 aMgr->startOperation(aNestedOpID, true);
338 void PartSet_WidgetSketchCreator::deactivate()
340 ModuleBase_WidgetSelector::deactivate();
342 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
343 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
345 XGUI_Tools::workshop(myWorkshop)->viewer()->update();
349 void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
351 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
353 CompositeFeaturePtr aCompFeature =
354 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
355 //CompositeFeaturePtr aSketchFeature =
356 // std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
357 if (aCompFeature->numberOfSubs() == 0) {
358 // do nothing, selection control should be hidden
359 setVisibleSelectionControl(false);
361 // check if the created sketch is invalid. Validate attribute selection list
362 // Shetch should be deleted if the attribute is invalid.
363 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
365 SessionPtr aMgr = ModelAPI_Session::get();
366 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
367 std::string aValidatorID, anError;
368 bool isValidPComposite = aFactory->validate(anAttrList, aValidatorID, anError);
369 /// if the sketch is not appropriate fro extrusion, it should be deleted and
370 /// the selection control should be activated again
371 if (!isValidPComposite) {
372 CompositeFeaturePtr aSketchFeature =
373 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
375 QObjectPtrList anObjects;
376 anObjects.append(aSketchFeature);
377 std::set<FeaturePtr> anIgnoredFeatures;
378 aWorkshop->deleteFeatures(anObjects, anIgnoredFeatures);
380 // do nothing, selection control should be shown
381 activateSelectionControl();
384 // do nothing, selection control should be hidden
385 setVisibleSelectionControl(false);
386 // Update value in attribute selection list
387 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
388 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
389 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
390 if (aWidget->attributeID() == myAttributeListID)
391 aWidget->restoreValue();
394 // Hide sketcher result
395 CompositeFeaturePtr aSketchFeature =
396 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
397 std::list<ResultPtr> aResults = aSketchFeature->results();
398 std::list<ResultPtr>::const_iterator aIt;
399 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
400 (*aIt)->setDisplayed(false);
402 aSketchFeature->setDisplayed(false);
404 // restore value in the selection control
407 // Add Selected body were created the sketcher to list of selected objects
408 std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::BOOLEAN_OBJECTS_ID();
409 AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
410 if (aSelList.get()) {
411 DataPtr aData = aSketchFeature->data();
412 AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
413 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
414 ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
416 SessionPtr aMgr = ModelAPI_Session::get();
417 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
418 AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
419 std::string aValidatorID, anError;
420 aSelList->append(aRes, GeomShapePtr());
421 if (aFactory->validate(anAttribute, aValidatorID, anError))
422 updateObject(aCompFeature);