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 aPCompositeFeature->execute(); // to fill attribute selection list
199 std::list<AttributePtr> aSelListAttributes = aParentFeature->data()->attributes(
200 ModelAPI_AttributeSelectionList::typeId());
201 if (aSelListAttributes.size() == 1) {
202 AttributePtr aFirstAttribute = aSelListAttributes.front();
204 SessionPtr aMgr = ModelAPI_Session::get();
205 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
206 std::string aValidatorID, anError;
207 bool isValidPComposite = aFactory->validate(aFirstAttribute, aValidatorID, anError);
208 if (!isValidPComposite) {
209 int anAnswer = QMessageBox::question(
210 aWorkshop->desktop(), tr("Apply current feature"),
211 tr("The current feature can not be used as an argument of the parent feature.\n\
212 After apply it will be deleted. Would you like to continue?"),
213 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
214 if (anAnswer == QMessageBox::Ok)
225 bool PartSet_WidgetSketchCreator::isSelectionMode() const
227 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
228 bool aHasValueInList = anAttrList.get() && anAttrList->size() > 0;
230 return !aHasValueInList;
233 void PartSet_WidgetSketchCreator::onSelectionChanged()
235 QList<ModuleBase_ViewerPrs> aSelected = getFilteredSelected();
237 if (!startSketchOperation(aSelected)) {
238 QList<ModuleBase_ViewerPrs>::const_iterator anIt = aSelected.begin(), aLast = aSelected.end();
239 bool aProcessed = false;
240 for (; anIt != aLast; anIt++) {
241 ModuleBase_ViewerPrs aValue = *anIt;
242 if (isValidInFilters(aValue))
243 aProcessed = setSelectionCustom(aValue) || aProcessed;
246 emit valuesChanged();
247 updateObject(myFeature);
248 setVisibleSelectionControl(false);
249 // manually deactivation because the widget was not activated as has no focus acceptin controls
251 emit focusOutWidget(this);
256 //********************************************************************
257 void PartSet_WidgetSketchCreator::setObject(ObjectPtr theSelectedObject,
258 GeomShapePtr theShape)
260 // do nothing because all processing is in onSelectionChanged()
263 bool PartSet_WidgetSketchCreator::startSketchOperation(const QList<ModuleBase_ViewerPrs>& theValues)
265 bool aSketchStarted = false;
267 if (theValues.size() != 1)
268 return aSketchStarted;
270 ModuleBase_ViewerPrs aValue = theValues.front();
271 if (!PartSet_WidgetSketchLabel::canFillSketch(aValue))
272 return aSketchStarted;
274 aSketchStarted = true;
276 // manually deactivation because the widget was not activated as has no focus acceptin controls
278 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
279 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
281 // Launch Sketch operation
282 CompositeFeaturePtr aCompFeature =
283 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
285 /// add sketch feature without current feature change.
286 /// it is important to do not change the current feature in order to
287 /// after sketch edition, the extrusion cut feature becomes current
288 SessionPtr aMgr = ModelAPI_Session::get();
289 DocumentPtr aDoc = aMgr->activeDocument();
290 FeaturePtr aPreviousCurrentFeature = aDoc->currentFeature(false);
291 FeaturePtr aSketch = aCompFeature->addFeature("Sketch");
293 PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(aSketch, aValue);
295 aDoc->setCurrentFeature(aPreviousCurrentFeature, false);
297 // start edit operation for the sketch
298 ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
299 (myModule->createOperation("Sketch"));
301 aFOperation->setFeature(aSketch);
302 myModule->sendOperation(aFOperation);
304 return aSketchStarted;
307 bool PartSet_WidgetSketchCreator::focusTo()
309 if (isSelectionMode()) {
310 activateSelectionControl();
314 //setVisibleSelectionControl(false);
316 connect(myModule, SIGNAL(resumed(ModuleBase_Operation*)), SLOT(onResumed(ModuleBase_Operation*)));
317 SessionPtr aMgr = ModelAPI_Session::get();
318 // Open transaction that is general for the previous nested one: it will be closed on nested commit
319 bool aIsOp = aMgr->isOperation();
321 const static std::string aNestedOpID("Parameters modification");
322 aMgr->startOperation(aNestedOpID, true);
329 void PartSet_WidgetSketchCreator::deactivate()
331 ModuleBase_WidgetSelector::deactivate();
333 bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
334 myPreviewPlanes->erasePreviewPlanes(myWorkshop);
336 XGUI_Tools::workshop(myWorkshop)->viewer()->update();
340 void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
342 XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
344 CompositeFeaturePtr aCompFeature =
345 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
346 //CompositeFeaturePtr aSketchFeature =
347 // std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
348 if (aCompFeature->numberOfSubs() == 0) {
349 // do nothing, selection control should be hidden
350 setVisibleSelectionControl(false);
352 // check if the created sketch is invalid. Validate attribute selection list
353 // Shetch should be deleted if the attribute is invalid.
354 AttributeSelectionListPtr anAttrList = myFeature->data()->selectionList(myAttributeListID);
356 SessionPtr aMgr = ModelAPI_Session::get();
357 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
358 std::string aValidatorID, anError;
359 bool isValidPComposite = aFactory->validate(anAttrList, aValidatorID, anError);
360 /// if the sketch is not appropriate fro extrusion, it should be deleted and
361 /// the selection control should be activated again
362 if (!isValidPComposite) {
363 CompositeFeaturePtr aSketchFeature =
364 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
366 QObjectPtrList anObjects;
367 anObjects.append(aSketchFeature);
368 std::set<FeaturePtr> anIgnoredFeatures;
369 aWorkshop->deleteFeatures(anObjects, anIgnoredFeatures);
371 // do nothing, selection control should be shown
372 activateSelectionControl();
375 // do nothing, selection control should be hidden
376 setVisibleSelectionControl(false);
377 // Update value in attribute selection list
378 XGUI_PropertyPanel* aPanel = aWorkshop->propertyPanel();
379 const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
380 foreach(ModuleBase_ModelWidget* aWidget, aWidgets) {
381 if (aWidget->attributeID() == myAttributeListID)
382 aWidget->restoreValue();
385 // Hide sketcher result
386 CompositeFeaturePtr aSketchFeature =
387 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCompFeature->subFeature(0));
388 std::list<ResultPtr> aResults = aSketchFeature->results();
389 std::list<ResultPtr>::const_iterator aIt;
390 for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
391 (*aIt)->setDisplayed(false);
393 aSketchFeature->setDisplayed(false);
395 // restore value in the selection control
398 // Add Selected body were created the sketcher to list of selected objects
399 std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::BOOLEAN_OBJECTS_ID();
400 AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute);
401 if (aSelList.get()) {
402 DataPtr aData = aSketchFeature->data();
403 AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
404 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
405 ResultPtr aRes = aSelAttr.get() ? aSelAttr->context() : ResultPtr();
407 SessionPtr aMgr = ModelAPI_Session::get();
408 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
409 AttributePtr anAttribute = myFeature->attribute(anObjectsAttribute);
410 std::string aValidatorID, anError;
411 aSelList->append(aRes, GeomShapePtr());
412 if (aFactory->validate(anAttribute, aValidatorID, anError))
413 updateObject(aCompFeature);