1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PartSet_MenuMgr.cpp
4 // Created: 03 April 2015
5 // Author: Vitaly SMETANNIKOV
7 #include "PartSet_MenuMgr.h"
8 #include "PartSet_Module.h"
9 #include "PartSet_SketcherMgr.h"
11 #include <GeomAPI_Pnt2d.h>
12 #include <GeomDataAPI_Point2D.h>
14 #include <SketchPlugin_ConstraintCoincidence.h>
15 #include <SketchPlugin_Line.h>
16 #include <SketchPlugin_Circle.h>
17 #include <SketchPlugin_Point.h>
19 #include <ModuleBase_ISelection.h>
20 #include <ModuleBase_Operation.h>
22 #include <XGUI_ModuleConnector.h>
23 #include <XGUI_Workshop.h>
24 #include <XGUI_Displayer.h>
26 #include <Events_Loop.h>
27 #include <ModelAPI_Events.h>
28 #include <ModelAPI_Session.h>
33 PartSet_MenuMgr::PartSet_MenuMgr(PartSet_Module* theModule)
34 : QObject(theModule), myModule(theModule), myPrevId(-1)
40 QAction* PartSet_MenuMgr::action(const QString& theId) const
42 if (myActions.contains(theId))
43 return myActions[theId];
47 void PartSet_MenuMgr::addAction(const QString& theId, QAction* theAction)
49 if (myActions.contains(theId))
50 qCritical("A command with Id = '%s' already defined!", qPrintable(theId));
51 theAction->setData(theId);
52 connect(theAction, SIGNAL(triggered(bool)), this, SLOT(onAction(bool)));
53 myActions[theId] = theAction;
56 void PartSet_MenuMgr::createActions()
60 anAction = new QAction(tr("Auxiliary"), this);
61 anAction->setCheckable(true);
62 addAction("AUXILIARY_CMD", anAction);
66 void PartSet_MenuMgr::onAction(bool isChecked)
68 QAction* aAction = static_cast<QAction*>(sender());
69 QString anId = aAction->data().toString();
71 if (anId == "AUXILIARY_CMD") {
72 setAuxiliary(isChecked);
76 /// Returns point of coincidence feature
77 /// \param theFeature the coincidence feature
78 /// \param theAttribute the attribute name
79 std::shared_ptr<GeomAPI_Pnt2d> getPoint(std::shared_ptr<ModelAPI_Feature>& theFeature,
80 const std::string& theAttribute)
82 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
84 if (!theFeature->data())
85 return std::shared_ptr<GeomAPI_Pnt2d>();
88 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
89 ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
91 aFeature = ModelAPI_Feature::feature(anAttr->object());
93 if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
94 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
95 aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
97 else if (aFeature && aFeature->getKind() == SketchPlugin_Circle::ID())
98 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
99 aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
101 else if (anAttr->attr()) {
102 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
104 if (aPointAttr.get() != NULL)
105 return aPointAttr->pnt();
106 return std::shared_ptr<GeomAPI_Pnt2d>();
109 /// Returns list of features connected in a councedence feature point
110 /// \param theStartCoin the coincidence feature
111 /// \param theList a list which collects lines features
112 /// \param theAttr the attribute name
113 void findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList, std::string theAttr)
115 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
116 FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
117 if (!theList.contains(aObj)) {
118 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getPoint(theStartCoin, theAttr);
119 theList.append(aObj);
120 const std::set<AttributePtr> aRefsList = aObj->data()->refsToMe();
121 std::set<AttributePtr>::const_iterator aIt;
122 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
123 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
124 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
125 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
126 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getPoint(aConstrFeature, theAttr);
127 if (aOrig->isEqual(aPnt)) {
128 findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_A());
129 findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_B());
137 bool PartSet_MenuMgr::addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
139 ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
140 if (!PartSet_SketcherMgr::isSketchOperation(anOperation) &&
141 !PartSet_SketcherMgr::isNestedSketchOperation(anOperation))
144 myCoinsideLines.clear();
145 ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
146 QObjectPtrList aObjects = aSelection->selectedPresentations();
147 if (aObjects.size() > 0) {
148 bool hasFeature = false;
150 foreach(ObjectPtr aObject, aObjects) {
151 aFeature = ModelAPI_Feature::feature(aObject);
152 if (aFeature.get() != NULL) {
157 bool aIsDetach = false;
158 if (aObjects.size() == 1) {
159 if (aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
160 /// If the feature is coincident then we use Detach command instead Delete
161 mySelectedFeature = aFeature;
162 findCoincidences(mySelectedFeature, myCoinsideLines, SketchPlugin_ConstraintCoincidence::ENTITY_A());
163 findCoincidences(mySelectedFeature, myCoinsideLines, SketchPlugin_ConstraintCoincidence::ENTITY_B());
164 if (myCoinsideLines.size() > 0) {
166 QMenu* aSubMenu = theMenu->addMenu(tr("Detach"));
169 foreach (FeaturePtr aCoins, myCoinsideLines) {
170 aAction = aSubMenu->addAction(aCoins->data()->name().c_str());
171 aAction->setData(QVariant(i));
174 connect(aSubMenu, SIGNAL(hovered(QAction*)), SLOT(onLineHighlighted(QAction*)));
175 connect(aSubMenu, SIGNAL(aboutToHide()), SLOT(onDetachMenuHide()));
176 connect(aSubMenu, SIGNAL(triggered(QAction*)), SLOT(onLineDetach(QAction*)));
181 theMenu->addAction(theStdActions["DELETE_CMD"]);
185 if (canSetAuxiliary(isAuxiliary)) {
186 QAction* anAction = action("AUXILIARY_CMD");
187 theMenu->addAction(anAction);
188 anAction->setChecked(isAuxiliary);
193 void PartSet_MenuMgr::onLineHighlighted(QAction* theAction)
195 if (myPrevId != -1) {
196 // Restore color for previous object
197 setLineColor(myPrevId, myColor, false);
199 myPrevId = theAction->data().toInt();
200 myColor = setLineColor(myPrevId, Qt::white, true);
203 QColor PartSet_MenuMgr::setLineColor(int theId, const QColor theColor, bool theUpdate)
205 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
206 XGUI_Workshop* aWorkshop = aConnector->workshop();
207 XGUI_Displayer* aDisplayer = aWorkshop->displayer();
209 FeaturePtr aLine = myCoinsideLines.at(myPrevId);
210 std::list<ResultPtr>::const_iterator aIt;
211 const std::list<ResultPtr>& aResults = aLine->results();
213 for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
214 aColor = aDisplayer->setObjectColor((*aIt), theColor, false);
217 aDisplayer->updateViewer();
222 void PartSet_MenuMgr::onLineDetach(QAction* theAction)
224 int aId = theAction->data().toInt();
225 FeaturePtr aLine = myCoinsideLines.at(aId);
226 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getPoint(mySelectedFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
227 gp_Pnt aOr = aOrig->impl<gp_Pnt>();
228 const std::set<AttributePtr>& aRefsList = aLine->data()->refsToMe();
230 QObjectPtrList aToDelFeatures;
231 std::set<AttributePtr>::const_iterator aIt;
232 // Find all coincedences corresponded to the selected line in the selected point
233 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
234 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
235 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
236 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
237 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
238 gp_Pnt aP = aPnt->impl<gp_Pnt>();
239 if (aOrig->isEqual(aPnt)) {
240 aToDelFeatures.append(aConstrFeature);
242 aPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
243 aP = aPnt->impl<gp_Pnt>();
244 if (aOrig->isEqual(aPnt)) {
245 aToDelFeatures.append(aConstrFeature);
251 if (aToDelFeatures.size() > 0) {
252 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
253 XGUI_Workshop* aWorkshop = aConnector->workshop();
254 ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
255 if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation))
256 anOperation->abort();
258 SessionPtr aMgr = ModelAPI_Session::get();
259 std::set<FeaturePtr> anIgnoredFeatures;
260 anIgnoredFeatures.insert(myModule->sketchMgr()->activeSketch());
262 QString aName = tr("Detach %1").arg(aLine->data()->name().c_str());
263 aMgr->startOperation(aName.toStdString());
264 aWorkshop->deleteFeatures(aToDelFeatures, anIgnoredFeatures);
265 aMgr->finishOperation();
267 myCoinsideLines.clear();
271 void PartSet_MenuMgr::onDetachMenuHide()
273 if (myPrevId != -1) {
274 // Restore color for previous object
275 setLineColor(myPrevId, myColor, false);
277 // Clear previous definitions
282 void PartSet_MenuMgr::setAuxiliary(const bool isChecked)
284 ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
286 bool isActiveSketch = PartSet_SketcherMgr::isSketchOperation(anOperation) ||
287 PartSet_SketcherMgr::isNestedSketchOperation(anOperation);
291 QObjectPtrList anObjects;
292 bool isUseTransaction = false;
293 // 1. change auxiliary type of a created feature
294 if (PartSet_SketcherMgr::isNestedCreateOperation(anOperation) &&
295 PartSet_SketcherMgr::isEntityOperation(anOperation) ) {
296 anObjects.append(anOperation->feature());
299 isUseTransaction = true;
300 // 2. change auxiliary type of selected sketch entities
301 ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
302 anObjects = aSelection->selectedPresentations();
305 QAction* anAction = action("AUXILIARY_CMD");
306 SessionPtr aMgr = ModelAPI_Session::get();
307 if (isUseTransaction) {
308 if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation))
309 anOperation->abort();
310 aMgr->startOperation(anAction->text().toStdString());
312 myModule->sketchMgr()->storeSelection();
314 if (anObjects.size() > 0) {
315 QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
316 for (; anIt != aLast; anIt++) {
317 FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
318 if (aFeature.get() != NULL) {
319 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
320 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
321 if (aSketchFeature.get() != NULL) {
322 std::string anAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
324 std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
325 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(aSketchFeature->data()->attribute(anAttribute));
327 anAuxiliaryAttr->setValue(isChecked);
332 if (isUseTransaction) {
333 aMgr->finishOperation();
335 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
336 myModule->sketchMgr()->restoreSelection();
339 bool PartSet_MenuMgr::canSetAuxiliary(bool& theValue) const
341 bool anEnabled = false;
342 ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
344 bool isActiveSketch = PartSet_SketcherMgr::isSketchOperation(anOperation) ||
345 PartSet_SketcherMgr::isNestedSketchOperation(anOperation);
349 QObjectPtrList anObjects;
350 // 1. change auxiliary type of a created feature
351 if (PartSet_SketcherMgr::isNestedCreateOperation(anOperation) &&
352 PartSet_SketcherMgr::isEntityOperation(anOperation) ) {
353 anObjects.append(anOperation->feature());
356 /// The operation should not be aborted here, because the method does not changed
357 /// the auxilliary state, but checks the possibility to perform this
358 ///if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation))
359 /// anOperation->abort();
360 // 2. change auxiliary type of selected sketch entities
361 ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
362 anObjects = aSelection->selectedPresentations();
364 anEnabled = anObjects.size() > 0;
366 bool isNotAuxiliaryFound = false;
367 if (anObjects.size() > 0) {
368 QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
369 for (; anIt != aLast && !isNotAuxiliaryFound; anIt++) {
370 FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
371 if (aFeature.get() != NULL) {
372 std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
373 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
374 if (aSketchFeature.get() != NULL) {
375 std::string anAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
377 std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
378 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(aSketchFeature->data()->attribute(anAttribute));
380 isNotAuxiliaryFound = !anAuxiliaryAttr->value();
385 theValue = anObjects.size() && !isNotAuxiliaryFound;