1 // File: PartSet_OperationFeatureEdit.h
2 // Created: 05 May 2014
3 // Author: Natalia ERMOLAEVA
5 #include <PartSet_OperationFeatureEdit.h>
6 #include <PartSet_Tools.h>
7 #include <PartSet_OperationSketch.h>
8 #include <SketchPlugin_Constraint.h>
10 #include <ModuleBase_OperationDescription.h>
11 #include <ModuleBase_WidgetEditor.h>
12 #include <ModuleBase_ViewerPrs.h>
13 #include <ModuleBase_IPropertyPanel.h>
14 #include <ModuleBase_ISelection.h>
15 #include <ModuleBase_IViewer.h>
17 #include <ModelAPI_Events.h>
19 #include <SketchPlugin_Feature.h>
20 #include <GeomDataAPI_Point2D.h>
22 #include <ModelAPI_Data.h>
23 #include <ModelAPI_Document.h>
24 #include <ModelAPI_Events.h>
26 #include <Events_Loop.h>
28 #include <SketchPlugin_Line.h>
30 #include <V3d_View.hxx>
31 #include <TopoDS_Vertex.hxx>
33 #include <BRep_Tool.hxx>
34 #include <AIS_DimensionOwner.hxx>
35 #include <AIS_DimensionSelectionMode.hxx>
41 #include <QMouseEvent>
45 PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId,
47 CompositeFeaturePtr theFeature)
48 : PartSet_OperationFeatureBase(theId, theParent, theFeature),
49 myIsBlockedSelection(false), myIsMultiOperation(false)
54 PartSet_OperationFeatureEdit::~PartSet_OperationFeatureEdit()
58 void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelection,
59 ModuleBase_IViewer* theViewer)
61 PartSet_OperationFeatureBase::initSelection(theSelection, theViewer);
62 // 1. unite selected and hightlighted objects in order to have an opportunity to drag
63 // by the highlighted object
64 QList<ModuleBase_ViewerPrs> aFeatures = theSelection->getSelected();
65 QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
66 // add highlighted elements if they are not selected
67 foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
68 if (!PartSet_Tools::isContainPresentation(aFeatures, aPrs))
69 aFeatures.append(aPrs);
71 myIsMultiOperation = aFeatures.size() > 1;
73 // 1. find all features with skipping features with selected vertex shapes
74 myFeature2Attribute.clear();
75 // firstly, collect the features without local selection
76 foreach (ModuleBase_ViewerPrs aPrs, aFeatures) {
77 const TopoDS_Shape& aShape = aPrs.shape();
78 if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
79 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
80 if (!aVertex.IsNull()) {
85 ObjectPtr aObject = aPrs.object();
88 FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
89 if (aFeature && myFeature2Attribute.find(aFeature) == myFeature2Attribute.end()) {
90 std::list<std::string> aList;
91 // using an empty list as a sign, that this feature should be moved itself
92 myFeature2Attribute[aFeature] = aList;
96 // 2. collect the features with a local selection on them.
97 // if the list already has this feature, the local selection is skipped
98 // that means that if the selection contains a feature and a feature with local selected point,
99 // the edit is performed for a full feature
100 Handle(V3d_View) aView = theViewer->activeView();
101 foreach (ModuleBase_ViewerPrs aPrs, aFeatures) {
102 const TopoDS_Shape& aShape = aPrs.shape();
103 if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected
104 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
105 if (aVertex.IsNull())
107 ObjectPtr aObject = aPrs.object();
110 FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
113 // if the feature is already moved, do nothing for this feature local selection
114 if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end())
117 // append the attribute of the vertex if it is found on the current feature
118 gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
120 PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aVX, aVY);
121 boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D = PartSet_Tools::getFeaturePoint(
123 std::string anAttribute = aFeature->data()->id(aPoint2D);
124 std::list<std::string> aList;
125 if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end())
126 aList = myFeature2Attribute[aFeature];
128 aList.push_back(anAttribute);
129 myFeature2Attribute[aFeature] = aList;
134 void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection)
136 if (myIsMultiOperation)
139 ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
140 if(aActiveWgt && aActiveWgt->isViewerSelector()) {
141 // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
142 PartSet_OperationFeatureBase::mousePressed(theEvent, theViewer, theSelection);
145 QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
146 QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
147 bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
148 if (aHasShift && !aHighlighted.empty()) {
149 foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
150 aSelected.append(aPrs);
154 /*if (!aSelected.empty()) {
155 aObject = aSelected.first().object();
157 if (!aHighlighted.empty())
158 aObject = aHighlighted.first().object();
160 // the priority to a highlighted object in order to edit it, even if the selected object is
161 // the feature of this operation. Otherwise, the highlighting is ignored and the selected
163 if (!aHighlighted.empty()) {
164 aObject = aHighlighted.front().object();
166 if (!aObject && !aSelected.empty()) // changed for a constrain
167 aObject = aSelected.front().object();
169 FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
170 if (!aFeature || aFeature != feature() || (aSelected.size() > 1)) {
172 theViewer->enableSelection(true);
173 emit featureConstructed(feature(), FM_Deactivation);
175 // If we have selection and prehilighting with shift pressed
176 // Then we have to select all these objects and restart as multi edit operfation
177 //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
178 //if (aHasShift && !theHighlighted.empty()) {
179 // QList<ObjectPtr> aSelected;
180 // std::list<ModuleBase_ViewerPrs>::const_iterator aIt;
181 // for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt)
182 // aSelected.append((*aIt).object());
184 // for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) {
185 // if (!aSelected.contains((*aIt).object()))
186 // aSelected.append((*aIt).object());
188 // emit setSelection(aSelected);
191 std::string anOperationType = PartSet_OperationFeatureEdit::Type();
192 restartOperation(anOperationType, aFeature);
199 void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer)
201 if (!(theEvent->buttons() & Qt::LeftButton))
203 Handle(V3d_View) aView = theViewer->activeView();
204 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
206 theViewer->enableSelection(false);
208 //blockSelection(true);
209 if (myCurPoint.myIsInitialized) {
211 PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), aView, aCurX, aCurY);
214 PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
216 double aDeltaX = aX - aCurX;
217 double aDeltaY = anY - aCurY;
219 if (myIsMultiOperation) {
220 std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
221 while (aFeatIter != myFeature2Attribute.end()) {
222 FeaturePtr aFeature = aFeatIter->first;
223 std::list<std::string> anAttributes = aFeatIter->second;
224 // perform edit for the feature
225 if (anAttributes.empty()) {
226 boost::shared_ptr<SketchPlugin_Feature> aSketchFeature =
227 boost::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
228 if (aSketchFeature) {
229 aSketchFeature->move(aDeltaX, aDeltaY);
232 // perform edit for the feature's attribute
234 std::list<std::string>::const_iterator anAttrIter = anAttributes.begin(),
235 anAttrEnd = anAttributes.end();
236 for (; anAttrIter != anAttrEnd; anAttrIter++) {
237 boost::shared_ptr<GeomDataAPI_Point2D> aPointAttr = boost::dynamic_pointer_cast<
238 GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter));
240 aPointAttr->move(aDeltaX, aDeltaY);
247 else { // multieditoperation
249 boost::shared_ptr<SketchPlugin_Feature> aSketchFeature = boost::dynamic_pointer_cast<
250 SketchPlugin_Feature>(feature());
252 bool isMoved = false;
253 // the functionality to move the feature attribute if it exists in the internal map
254 std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
255 while (aFeatIter != myFeature2Attribute.end()) {
256 FeaturePtr aFeature = aFeatIter->first;
257 std::list<std::string> anAttributes = aFeatIter->second;
258 // perform edit for the feature
259 /*if (anAttributes.empty()) {
260 boost::shared_ptr<SketchPlugin_Feature> aSketchFeature =
261 boost::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
262 if (aSketchFeature) {
263 aSketchFeature->move(aDeltaX, aDeltaY);
266 // perform edit for the feature's attribute
268 if (!anAttributes.empty()) {
269 std::list<std::string>::const_iterator anAttrIter = anAttributes.begin(),
270 anAttrEnd = anAttributes.end();
271 for (; anAttrIter != anAttrEnd; anAttrIter++) {
272 boost::shared_ptr<GeomDataAPI_Point2D> aPointAttr = boost::dynamic_pointer_cast<
273 GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter));
275 aPointAttr->move(aDeltaX, aDeltaY);
283 // the feature is moved only if there is no a local selection on this feature
285 // MPV: added condition because it could be external edge of some object, not sketch
286 if (aSketchFeature && sketch()->isSub(aSketchFeature)) {
287 aSketchFeature->move(aDeltaX, aDeltaY);
288 static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
289 ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent);
292 } // multieditoperation
296 myCurPoint.setPoint(aPoint);
299 void PartSet_OperationFeatureEdit::mouseReleased(
300 QMouseEvent* theEvent, ModuleBase_IViewer* theViewer,
301 ModuleBase_ISelection* theSelection)
303 theViewer->enableSelection(true);
304 if (myIsMultiOperation) {
306 std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
307 while (aFeatIter != myFeature2Attribute.end()) {
308 FeaturePtr aFeature = aFeatIter->first;
310 emit featureConstructed(aFeature, FM_Deactivation);
316 else { // multieditoperation
317 ModuleBase_ModelWidget* aActiveWgt = 0;
319 aActiveWgt = myPropertyPanel->activeWidget();
320 if(aActiveWgt && aActiveWgt->isViewerSelector()) {
321 // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
322 PartSet_OperationFeatureBase::mouseReleased(theEvent, theViewer, theSelection);
324 //blockSelection(false);
326 } // multieditoperation
329 void PartSet_OperationFeatureEdit::mouseDoubleClick(
330 QMouseEvent* theEvent, Handle_V3d_View theView,
331 ModuleBase_ISelection* theSelection)
333 // TODO the functionality is important only for constraint feature. Should be moved in another place
334 QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
335 if (!aSelected.empty()) {
336 ModuleBase_ViewerPrs aFeaturePrs = aSelected.first();
337 if (!aFeaturePrs.owner().IsNull()) {
338 Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast(
339 aFeaturePrs.owner());
340 if (!anOwner.IsNull() && anOwner->SelectionMode() == AIS_DSM_Text) {
342 double aValue = PartSet_Tools::featureValue(feature(), SketchPlugin_Constraint::VALUE(),
345 ModuleBase_WidgetEditor::editFeatureValue(feature(), SketchPlugin_Constraint::VALUE());
353 void PartSet_OperationFeatureEdit::startOperation()
355 PartSet_OperationSketchBase::startOperation();
356 //emit multiSelectionEnabled(false);
361 void PartSet_OperationFeatureEdit::stopOperation()
363 //emit multiSelectionEnabled(true);
365 //blockSelection(false, false);
367 myFeature2Attribute.clear();
370 //void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection)
372 // if (myIsBlockedSelection == isBlocked)
375 // myIsBlockedSelection = isBlocked;
376 // QList<ObjectPtr> aFeatureList;
377 // aFeatureList.append(feature());
379 // //if (isBlocked) {
380 // // emit setSelection(QList<ObjectPtr>());
381 // // emit stopSelection(aFeatureList, true);
383 // // emit stopSelection(aFeatureList, false);
384 // // if (isRestoreSelection)
385 // // emit setSelection(aFeatureList);
389 FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool theFlushMessage,
390 CompositeFeaturePtr theCompositeFeature)
392 // do nothing in order to do not create a new feature
396 void PartSet_OperationFeatureEdit::sendFeatures()
398 static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
400 std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
401 while (aFeatIter != myFeature2Attribute.end()) {
402 FeaturePtr aFeature = aFeatIter->first;
404 ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
409 Events_Loop::loop()->flush(anEvent);