X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPartSet%2FPartSet_OperationFeatureEdit.cpp;h=d44dfa3d7f8d51084ac72356951b69aacf3334a8;hb=9e869ede4d8c56262bb20534543c2bf56cd6a91b;hp=7a16b92405ee559a0fda5f0009e1e0970e8f6193;hpb=b2a34ee4bab2fe2d97f900cbdafcaf122344c46c;p=modules%2Fshaper.git diff --git a/src/PartSet/PartSet_OperationFeatureEdit.cpp b/src/PartSet/PartSet_OperationFeatureEdit.cpp index 7a16b9240..d44dfa3d7 100644 --- a/src/PartSet/PartSet_OperationFeatureEdit.cpp +++ b/src/PartSet/PartSet_OperationFeatureEdit.cpp @@ -5,12 +5,14 @@ #include #include #include - #include #include #include #include +#include +#include +#include #include @@ -37,114 +39,388 @@ using namespace std; -PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId, QObject* theParent, - FeaturePtr theFeature) - : PartSet_OperationSketchBase(theId, theParent), - mySketch(theFeature), - myIsBlockedSelection(false) +PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId, + QObject* theParent, + CompositeFeaturePtr theFeature) + : PartSet_OperationFeatureBase(theId, theParent, theFeature), + myIsBlockedSelection(false), myIsBlockedByDoubleClick(false) { + myIsEditing = true; } PartSet_OperationFeatureEdit::~PartSet_OperationFeatureEdit() { } -std::list PartSet_OperationFeatureEdit::getSelectionModes(ObjectPtr theFeature) const +void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelection, + ModuleBase_IViewer* theViewer) { - return PartSet_OperationSketchBase::getSelectionModes(theFeature); -} + // the method of the parent should is useless here because it processes the given + // selection in different way + //PartSet_OperationFeatureBase::initSelection(theSelection, theViewer); + + QList aSelected = theSelection->getSelected(); + QList aHighlighted = theSelection->getHighlighted(); + + // there is a bug in OCC, where the highlighted objects are repeated and should be + // filtered on the unique state here + QList anUniqueHighlighted; + foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) { + if (!PartSet_Tools::isContainPresentation(anUniqueHighlighted, aPrs)) + anUniqueHighlighted.append(aPrs); + } + fillFeature2Attribute(anUniqueHighlighted, theViewer, myHighlightedFeature2Attribute); -void PartSet_OperationFeatureEdit::initFeature(FeaturePtr theFeature) -{ - setEditingFeature(theFeature); + foreach (ModuleBase_ViewerPrs aPrs, anUniqueHighlighted) { + if (!PartSet_Tools::isContainPresentation(aSelected, aPrs)) + aSelected.append(aPrs); + } + fillFeature2Attribute(aSelected, theViewer, myAllFeature2Attribute); } -FeaturePtr PartSet_OperationFeatureEdit::sketch() const +void PartSet_OperationFeatureEdit::fillFeature2Attribute( + const QList& thePresentations, + ModuleBase_IViewer* theViewer, + std::map >& theFeature2Attribute) { - return mySketch; + // 1. find all features with skipping features with selected vertex shapes + theFeature2Attribute.clear(); + // firstly, collect the features without local selection + double aX, anY; + foreach (ModuleBase_ViewerPrs aPrs, thePresentations) { + if (getViewerPoint(aPrs, theViewer, aX, anY)) + continue; + else { + ObjectPtr aObject = aPrs.object(); + if (!aObject) + continue; + FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); + if (aFeature && theFeature2Attribute.find(aFeature) == theFeature2Attribute.end()) { + std::list aList; + // using an empty list as a sign, that this feature should be moved itself + theFeature2Attribute[aFeature] = aList; + } + } + } + // 2. collect the features with a local selection on them. + // if the list already has this feature, the local selection is skipped + // that means that if the selection contains a feature and a feature with local selected point, + // the edit is performed for a full feature + foreach (ModuleBase_ViewerPrs aPrs, thePresentations) { + if (getViewerPoint(aPrs, theViewer, aX, anY)) { + ObjectPtr aObject = aPrs.object(); + if (!aObject) + continue; + FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); + if (!aFeature) + continue; + + // append the attribute of the vertex if it is found on the current feature + std::shared_ptr aPoint2D = PartSet_Tools::getFeaturePoint( + aFeature, aX, anY); + std::string anAttribute = aFeature->data()->id(aPoint2D); + std::list aList; + if (theFeature2Attribute.find(aFeature) != theFeature2Attribute.end()) + aList = theFeature2Attribute[aFeature]; + + aList.push_back(anAttribute); + theFeature2Attribute[aFeature] = aList; + } + } } -void PartSet_OperationFeatureEdit::mousePressed( - QMouseEvent* theEvent, Handle(V3d_View) theView, - const std::list& theSelected, - const std::list& theHighlighted) +void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection) { - ObjectPtr aObject; - if (!theHighlighted.empty()) - aObject = theHighlighted.front().object(); - if (!aObject && !theSelected.empty()) // changed for a constrain - aObject = theSelected.front().object(); - - FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - if (!aFeature || aFeature != feature()) { - if (commit()) { - emit featureConstructed(feature(), FM_Deactivation); - - bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - if (aHasShift && !theHighlighted.empty()) { - QList aSelected; - std::list::const_iterator aIt; - for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt) - aSelected.append((*aIt).object()); - /*for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) { - if (!aSelected.contains((*aIt).object())) - aSelected.append((*aIt).object()); - }*/ - //aSelected.push_back(feature()); - //aSelected.push_back(theHighlighted.front().object()); - emit setSelection(aSelected); - } else if (aFeature) { - restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); - } + ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); + if(aActiveWgt && aActiveWgt->isViewerSelector()) { + // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased + PartSet_OperationFeatureBase::mousePressed(theEvent, theViewer, theSelection); + // the current point should be cleared because it is saved from the previous move and + // should be reinitialized after the start moving. It is important for example for the lenght + // constraint where the first widget is a viewer selector. + myCurPoint.clear(); + } + else { + // commit always until the selection restore is realized (for feature and local selection) + // TODO: check whether the selection is changed and restart the operation only if it is modified + commit(); + emitFeaturesDeactivation(); + // find nearest feature and restart the operation for it + Handle(V3d_View) aView = theViewer->activeView(); + QList aSelected = theSelection->getSelected(); + QList aHighlighted = theSelection->getHighlighted(); + + ObjectPtr aFeature = PartSet_Tools::nearestFeature(theEvent->pos(), aView, sketch(), + aSelected, aHighlighted); + if (aFeature) { + restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); } } + // the next code is commented because the new attempt to commit/restart operation implementation: + //QList aSelected = theSelection->getSelected(); + //QList aHighlighted = theSelection->getHighlighted(); + //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); + //if (aHasShift && !aHighlighted.empty()) { + // foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) { + // aSelected.append(aPrs); + // } + //} + //ObjectPtr aObject; + ///*if (!aSelected.empty()) { + // aObject = aSelected.first().object(); + //} else { + // if (!aHighlighted.empty()) + // aObject = aHighlighted.first().object(); + //}*/ + //// the priority to a highlighted object in order to edit it, even if the selected object is + //// the feature of this operation. Otherwise, the highlighting is ignored and the selected + //// object is moved + //if (!aHighlighted.empty()) { + // aObject = aHighlighted.front().object(); + //} + //if (!aObject && !aSelected.empty()) // changed for a constrain + // aObject = aSelected.front().object(); + + //FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); + //if (!aFeature || aFeature != feature() || (aSelected.size() > 1)) { + // if (commit()) { + // theViewer->enableSelection(true); + // emit featureConstructed(feature(), FM_Deactivation); + + // // If we have selection and prehilighting with shift pressed + // // Then we have to select all these objects and restart as multi edit operfation + // //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); + // //if (aHasShift && !theHighlighted.empty()) { + // // QList aSelected; + // // std::list::const_iterator aIt; + // // for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt) + // // aSelected.append((*aIt).object()); + + // // for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) { + // // if (!aSelected.contains((*aIt).object())) + // // aSelected.append((*aIt).object()); + // // } + // // emit setSelection(aSelected); + // //} else + // if (aFeature) { + // std::string anOperationType = PartSet_OperationFeatureEdit::Type(); + // restartOperation(anOperationType, aFeature); + // } + // //} + // } + //} } -void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView) +void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer) { if (!(theEvent->buttons() & Qt::LeftButton)) return; + Handle(V3d_View) aView = theViewer->activeView(); + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView); + theViewer->enableSelection(false); - blockSelection(true); + //blockSelection(true); if (myCurPoint.myIsInitialized) { double aCurX, aCurY; - PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), theView, aCurX, aCurY); + PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), aView, aCurX, aCurY); double aX, anY; - PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY); + PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); double aDeltaX = aX - aCurX; double aDeltaY = anY - aCurY; - boost::shared_ptr aSketchFeature = boost::dynamic_pointer_cast< - SketchPlugin_Feature>(feature()); - aSketchFeature->move(aDeltaX, aDeltaY); - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent); + // the next code is commented because it is obsolete by the multi edit operation realization here + //if (myIsMultiOperation) { + // std::map>::iterator aFeatIter = myFeature2Attribute.begin(); + // while (aFeatIter != myFeature2Attribute.end()) { + // FeaturePtr aFeature = aFeatIter->first; + // std::list anAttributes = aFeatIter->second; + // // perform edit for the feature + // if (anAttributes.empty()) { + // std::shared_ptr aSketchFeature = + // std::dynamic_pointer_cast(aFeature); + // if (aSketchFeature) { + // aSketchFeature->move(aDeltaX, aDeltaY); + // } + // } + // // perform edit for the feature's attribute + // else { + // std::list::const_iterator anAttrIter = anAttributes.begin(), + // anAttrEnd = anAttributes.end(); + // for (; anAttrIter != anAttrEnd; anAttrIter++) { + // std::shared_ptr aPointAttr = std::dynamic_pointer_cast< + // GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter)); + // if (aPointAttr) { + // aPointAttr->move(aDeltaX, aDeltaY); + // } + // } + // } + // aFeatIter++; + // } + //} + //else { // multieditoperation + + //std::shared_ptr aSketchFeature = std::dynamic_pointer_cast< + // SketchPlugin_Feature>(feature()); + + bool isMoved = false; + bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); + + // the functionality to move the feature attribute if it exists in the internal map + std::map>::iterator aFeatIter, aFeatLast; + if (aHasShift || myHighlightedFeature2Attribute.empty()) { + aFeatIter = myAllFeature2Attribute.begin(); + aFeatLast = myAllFeature2Attribute.end(); + } + else { + aFeatIter = myHighlightedFeature2Attribute.begin(); + aFeatLast = myHighlightedFeature2Attribute.end(); + } + + while (aFeatIter != aFeatLast) { + FeaturePtr aFeature = aFeatIter->first; + // MPV: added condition because it could be external edge of some object, not sketch + if (aFeature && !sketch()->isSub(aFeature)) { + aFeatIter++; + continue; + } + + std::list anAttributes = aFeatIter->second; + // perform edit for the feature + if (anAttributes.empty()) { + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(aFeature); + if (aSketchFeature) { + aSketchFeature->move(aDeltaX, aDeltaY); + isMoved = true; + } + } + // perform edit for the feature's attribute + else { + std::list::const_iterator anAttrIter = anAttributes.begin(), + anAttrEnd = anAttributes.end(); + for (; anAttrIter != anAttrEnd; anAttrIter++) { + std::shared_ptr aPointAttr = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter)); + if (aPointAttr) { + aPointAttr->move(aDeltaX, aDeltaY); + isMoved = true; + } + } + } + aFeatIter++; + } + // the next code is commented because it is obsolete by the multi edit operation realization here + // the feature is moved only if there is no a local selection on this feature + //if (!isMoved) { + // // MPV: added condition because it could be external edge of some object, not sketch + // if (aSketchFeature && sketch()->isSub(aSketchFeature)) { + // aSketchFeature->move(aDeltaX, aDeltaY); + // static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + // ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent); + // } + // } + //} // multieditoperation + sendFeatures(aHasShift); } - sendFeatures(); myCurPoint.setPoint(aPoint); } void PartSet_OperationFeatureEdit::mouseReleased( - QMouseEvent* theEvent, Handle(V3d_View) theView, - const std::list& /*theSelected*/, - const std::list& /*theHighlighted*/) + QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, + ModuleBase_ISelection* theSelection) { - blockSelection(false); + // the block is processed in order to do not commit the transaction until the started + // double click functionality is performed. It is reproduced on Linux only + if (myIsBlockedByDoubleClick) + return; + + theViewer->enableSelection(true); + // the next code is commented because it is obsolete by the multi edit operation realization here + //if (myIsMultiOperation) { + // if (commit()) { + // std::map>::iterator aFeatIter = myFeature2Attribute.begin(); + // while (aFeatIter != myFeature2Attribute.end()) { + // FeaturePtr aFeature = aFeatIter->first; + // if (aFeature) { + // emit featureConstructed(aFeature, FM_Deactivation); + // } + // aFeatIter++; + // } + // } + //} + //else { // multieditoperation + ModuleBase_ModelWidget* aActiveWgt = 0; + if (myPropertyPanel) + aActiveWgt = myPropertyPanel->activeWidget(); + if(aActiveWgt && aActiveWgt->isViewerSelector()) { + // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased + PartSet_OperationFeatureBase::mouseReleased(theEvent, theViewer, theSelection); + //}// else { + ////blockSelection(false); + ////} + //} // multieditoperation + } + else { + theViewer->enableSelection(true); + + // commit operation if there is no selected an highlighted objects anymore + Handle(V3d_View) aView = theViewer->activeView(); + QList aSelected = theSelection->getSelected(); + QList aHighlighted = theSelection->getHighlighted(); + + if (aSelected.empty() && aHighlighted.empty()) { + commit(); + emitFeaturesDeactivation(); + } + else if (aSelected.size() == 1) { + /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape + /// but for other IO, for example constraint dimensions. + /// It is empty and we have to use the process mouse release to start edition operation + /// for these objects + ObjectPtr anObject = aSelected.first().object(); + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) && + aFeature != feature()) { + restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); + } + } + } } void PartSet_OperationFeatureEdit::mouseDoubleClick( QMouseEvent* theEvent, Handle_V3d_View theView, - const std::list& theSelected, - const std::list& theHighlighted) + ModuleBase_ISelection* theSelection) { // TODO the functionality is important only for constraint feature. Should be moved in another place - if (!theSelected.empty()) { - ModuleBase_ViewerPrs aFeaturePrs = theSelected.front(); + QList aSelected = theSelection->getSelected(); + // in case when the double click happens on another constraint feature when selection control is active + // we should not perform the double click functionality + // if there is no the viewer selector widget active, the operation is restarted with a correct feature + ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); + if(aActiveWgt && aActiveWgt->isViewerSelector()) { + if (!aSelected.empty()) { + if (aSelected.size() == 1) { + /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape + /// but for other IO, for example constraint dimensions. + /// It is empty and we have to use the process mouse release to start edition operation + /// for these objects + ObjectPtr anObject = aSelected.first().object(); + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) && + aFeature != feature()) { + return; + } + } + } + } + + myIsBlockedByDoubleClick = true; + if (!aSelected.empty()) { + ModuleBase_ViewerPrs aFeaturePrs = aSelected.first(); if (!aFeaturePrs.owner().IsNull()) { Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast( aFeaturePrs.owner()); @@ -159,56 +435,87 @@ void PartSet_OperationFeatureEdit::mouseDoubleClick( } } } + myIsBlockedByDoubleClick = false; } void PartSet_OperationFeatureEdit::startOperation() { PartSet_OperationSketchBase::startOperation(); - emit multiSelectionEnabled(false); + //emit multiSelectionEnabled(false); myCurPoint.clear(); } void PartSet_OperationFeatureEdit::stopOperation() { - emit multiSelectionEnabled(true); + //emit multiSelectionEnabled(true); - blockSelection(false, false); -} + //blockSelection(false, false); -void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection) -{ - if (myIsBlockedSelection == isBlocked) - return; - - myIsBlockedSelection = isBlocked; - QList aFeatureList; - aFeatureList.append(feature()); - - if (isBlocked) { - emit setSelection(QList()); - emit stopSelection(aFeatureList, true); - } else { - emit stopSelection(aFeatureList, false); - if (isRestoreSelection) - emit setSelection(aFeatureList); - } + myHighlightedFeature2Attribute.clear(); + myAllFeature2Attribute.clear(); } -FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool /*theFlushMessage*/) +//void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection) +//{ +// if (myIsBlockedSelection == isBlocked) +// return; +// +// myIsBlockedSelection = isBlocked; +// QList aFeatureList; +// aFeatureList.append(feature()); +// +// //if (isBlocked) { +// // emit setSelection(QList()); +// // emit stopSelection(aFeatureList, true); +// //} else { +// // emit stopSelection(aFeatureList, false); +// // if (isRestoreSelection) +// // emit setSelection(aFeatureList); +// //} +//} + +FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool theFlushMessage, + CompositeFeaturePtr theCompositeFeature) { // do nothing in order to do not create a new feature return FeaturePtr(); } -void PartSet_OperationFeatureEdit::sendFeatures() +void PartSet_OperationFeatureEdit::sendFeatures(const bool theIsAllFeatures) { static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - FeaturePtr aFeature = feature(); - ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); + std::map>::iterator aFeatIter, aFeatLast; + if (theIsAllFeatures || myHighlightedFeature2Attribute.empty()) { + aFeatIter = myAllFeature2Attribute.begin(); + aFeatLast = myAllFeature2Attribute.end(); + } + else { + aFeatIter = myHighlightedFeature2Attribute.begin(); + aFeatLast = myHighlightedFeature2Attribute.end(); + } + while (aFeatIter != aFeatLast) { + FeaturePtr aFeature = aFeatIter->first; + if (aFeature) { + ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); + } + aFeatIter++; + } Events_Loop::loop()->flush(anEvent); flushUpdated(); } +void PartSet_OperationFeatureEdit::emitFeaturesDeactivation() +{ + std::map>::iterator aFeatIter = myAllFeature2Attribute.begin(); + while (aFeatIter != myAllFeature2Attribute.end()) { + FeaturePtr aFeature = aFeatIter->first; + if (aFeature) { + emit featureConstructed(aFeature, FM_Deactivation); + } + aFeatIter++; + } +} +