void CmdPartDesignMoveFeatureInTree::activated(int iMsg) { Q_UNUSED(iMsg); std::vector<App::DocumentObject*> features = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()); if (features.empty()) return; PartDesign::Body *body = PartDesignGui::getBodyFor ( features.front(), false ); App::DocumentObject * bodyBase = nullptr; // sanity check bool allFeaturesFromSameBody = true; if ( body ) { bodyBase= body->BaseFeature.getValue(); for ( auto feat: features ) { if ( !body->hasObject ( feat ) ) { allFeaturesFromSameBody = false; break; } if ( bodyBase== feat) { QMessageBox::warning (0, QObject::tr( "Selection error" ), QObject::tr( "Impossible to move the base feature of a body." ) ); return; } } } if (!body || ! allFeaturesFromSameBody) { QMessageBox::warning (0, QObject::tr( "Selection error" ), QObject::tr( "Select one or more features from the same body." ) ); return; } // Create a list of all features in this body const std::vector<App::DocumentObject*> & model = body->Group.getValues(); // Ask user to select the target feature bool ok; QStringList items; if ( bodyBase ) { items.push_back( QString::fromUtf8 ( bodyBase->Label.getValue () ) ); } else { items.push_back( QObject::tr( "Beginning of the body" ) ); } for ( auto feat: model ) { items.push_back( QString::fromUtf8 ( feat->Label.getValue() ) ); } QString text = QInputDialog::getItem(Gui::getMainWindow(), qApp->translate("PartDesign_MoveFeatureInTree", "Select feature"), qApp->translate("PartDesign_MoveFeatureInTree", "Select a feature from the list"), items, 0, false, &ok); if (!ok) return; int index = items.indexOf(text); // first object is the beginning of the body App::DocumentObject* target = index != 0 ? model[index-1] : nullptr; openCommand("Move an object inside tree"); for ( auto feat: features ) { if ( feat == target ) continue; std::string targetStr; if (target) { targetStr.append("App.activeDocument().").append(target->getNameInDocument()); } else { targetStr = "None"; } // Remove and re-insert the feature to/from the Body // TODO if tip was moved the new position of tip is quite undetermined (2015-08-07, Fat-Zer) // TODO warn the user if we are moving an object to some place before the object's link (2015-08-07, Fat-Zer) doCommand ( Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)", body->getNameInDocument(), feat->getNameInDocument() ); doCommand ( Doc, "App.activeDocument().%s.insertObject(App.activeDocument().%s, %s, True)", body->getNameInDocument(), feat->getNameInDocument(), targetStr.c_str () ); } updateActive(); }
bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, const char* sSubName) { // TODO review this function (2015-09-04, Fat-Zer) PartDesign::Body *body; App::DocumentObject* originGroupObject = nullptr; if ( support ) { body = PartDesign::Body::findBodyOf (support); } else { body = PartDesignGui::getBody (false); } if ( body ) { // Search for Part of the body originGroupObject = App::OriginGroupExtension::getGroupOfObject ( body ) ; } else if ( support ) { // if no body search part for support originGroupObject = App::OriginGroupExtension::getGroupOfObject ( support ) ; } else { // fallback to active part originGroupObject = PartDesignGui::getActivePart ( ); } App::OriginGroupExtension* originGroup = nullptr; if(originGroupObject) originGroup = originGroupObject->getExtensionByType<App::OriginGroupExtension>(); // Don't allow selection in other document if ( support && pDoc != support->getDocument() ) { return false; } // Enable selection from origin of current part/ if ( pObj->getTypeId().isDerivedFrom(App::OriginFeature::getClassTypeId()) ) { bool fits = false; if ( plane && pObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ) { fits = true; } else if ( edge && pObj->getTypeId().isDerivedFrom(App::Line::getClassTypeId()) ) { fits = true; } if (fits) { // check that it is actually belongs to the chosen body or part try { // here are some throwers if (body) { if (body->getOrigin ()->hasObject (pObj) ) { return true; } } else if (originGroup ) { if ( originGroup->getOrigin ()->hasObject (pObj) ) { return true; } } } catch (const Base::Exception) { } } return false; // The Plane/Axis doesn't fits our needs } if (pObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) { if (!body) { // Allow selecting Part::Datum features from the active Body return false; } else if (!allowOtherBody && !body->hasObject(pObj)) { return false; } if (plane && (pObj->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId()))) return true; if (edge && (pObj->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId()))) return true; if (point && (pObj->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId()))) return true; return false; } // Handle selection of geometry elements if (!sSubName || sSubName[0] == '\0') return false; if (!allowOtherBody) { if (support == NULL) return false; if (pObj != support) return false; } std::string subName(sSubName); if (edge && subName.size() > 4 && subName.substr(0,4) == "Edge") { const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue(); TopoDS_Shape sh = shape.getSubShape(subName.c_str()); const TopoDS_Edge& edge = TopoDS::Edge(sh); if (!edge.IsNull()) { if (planar) { BRepAdaptor_Curve adapt(edge); if (adapt.GetType() == GeomAbs_Line) return true; } else { return true; } } } if (plane && subName.size() > 4 && subName.substr(0,4) == "Face") { const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue(); TopoDS_Shape sh = shape.getSubShape(subName.c_str()); const TopoDS_Face& face = TopoDS::Face(sh); if (!face.IsNull()) { if (planar) { BRepAdaptor_Surface adapt(face); if (adapt.GetType() == GeomAbs_Plane) return true; } else { return true; } } } if (point && subName.size() > 6 && subName.substr(0,6) == "Vertex") { return true; } return false; }