Beispiel #1
0
void CmdPartDesignDuplicateSelection::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false);

    std::vector<App::DocumentObject*> beforeFeatures = getDocument()->getObjects();

    openCommand("Duplicate a PartDesign object");
    doCommand(Doc,"FreeCADGui.runCommand('Std_DuplicateSelection')");

    if (pcActiveBody) {
        // Find the features that were added
        std::vector<App::DocumentObject*> afterFeatures = getDocument()->getObjects();
        std::vector<App::DocumentObject*> newFeatures;
        std::sort(beforeFeatures.begin(), beforeFeatures.end());
        std::sort(afterFeatures.begin(), afterFeatures.end());
        std::set_difference(afterFeatures.begin(), afterFeatures.end(), beforeFeatures.begin(), beforeFeatures.end(),
                            std::back_inserter(newFeatures));

        for (auto feature : newFeatures) {
            if (PartDesign::Body::isAllowed(feature)) {
                doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",
                          pcActiveBody->getNameInDocument(), feature->getNameInDocument());
                doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", feature->getNameInDocument());
            }
        }

        // Adjust visibility of features
        doCommand(Gui,"Gui.activeDocument().show(\"%s\")", newFeatures.back()->getNameInDocument());
    }

    updateActive();
}
void TaskTransformedParameters::fillPlanesCombo(ComboLinks &combolinks,
                                                Part::Part2DObject* sketch)
{
    combolinks.clear();

    //add sketch axes
    if (sketch){
        combolinks.addLink(sketch,"V_Axis",QObject::tr("Vertical sketch axis"));
        combolinks.addLink(sketch,"H_Axis",QObject::tr("Horizontal sketch axis"));
        for (int i=0; i < sketch->getAxisCount(); i++) {
            QString itemText = tr("Construction line %1").arg(i+1);
            std::stringstream sub;
            sub << "Axis" << i;
            combolinks.addLink(sketch,sub.str(),itemText);
        }
    }

    //add part baseplanes
    App::DocumentObject* obj = getObject();
    PartDesign::Body * body = PartDesign::Body::findBodyOf ( obj );

    if (body) {
        try {
            App::Origin* orig = body->getOrigin();
            combolinks.addLink(orig->getXY(),"",tr("Base XY plane"));
            combolinks.addLink(orig->getYZ(),"",tr("Base YZ plane"));
            combolinks.addLink(orig->getXZ(),"",tr("Base XZ plane"));
        } catch (const Base::Exception &ex) {
            Base::Console().Error ("%s\n", ex.what() );
        }
    }

    //add "Select reference"
    combolinks.addLink(0,std::string(),tr("Select reference..."));
}
SbBox3f ViewProviderDatum::getRelevantBoundBox () const {
    std::vector<App::DocumentObject *> objs;

    // Probe body first
    PartDesign::Body* body = PartDesign::Body::findBodyOf ( this->getObject() );
    if (body) {
        objs = body->getFullModel ();
    } else {
        // Probe if we belongs to some group
        App::DocumentObjectGroup* group =  App::DocumentObjectGroup::getGroupOfObject ( this->getObject () );

        if(group) {
            objs = group->getObjects ();
        } else {
            // Fallback to whole document
            objs = this->getObject ()->getDocument ()->getObjects ();
        }
    }

    Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(this->getActiveView())->getViewer();
    SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion());
    SbBox3f bbox = getRelevantBoundBox (bboxAction, objs);

    if ( bbox.getVolume () < Precision::Confusion() ) {
        bbox.extendBy ( defaultBoundBox () );
    }

    return bbox;
}
void getReferencedSelection(const App::DocumentObject* thisObj, const Gui::SelectionChanges& msg,
                            App::DocumentObject*& selObj, std::vector<std::string>& selSub)
{
    if (!thisObj)
        return;

    if (strcmp(thisObj->getDocument()->getName(), msg.pDocName) != 0)
        return;
    
    selObj = thisObj->getDocument()->getObject(msg.pObjectName);
    if (selObj == thisObj)
        return;
    
    std::string subname = msg.pSubName;
    
    //check if the selection is an external reference and ask the user what to do
    //of course only if thisObj is in a body, as otherwise the old workflow would not 
    //be supportet
    PartDesign::Body* body = PartDesignGui::getBodyFor(thisObj, false);
    bool originfeature = selObj->isDerivedFrom(App::OriginFeature::getClassTypeId());
    if(!originfeature && body) {
        PartDesign::Body* selBody = PartDesignGui::getBodyFor(selObj, false);
        if(!selBody || body != selBody) {
            
            auto* pcActivePart = PartDesignGui::getPartFor(body, false);

            QDialog* dia = new QDialog;
            Ui_Dialog dlg;
            dlg.setupUi(dia);
            dia->setModal(true);
            int result = dia->exec();
            if(result == QDialog::DialogCode::Rejected) {
                selObj = NULL;
                return;
            }
            else if(!dlg.radioXRef->isChecked()) {

                    auto copy = PartDesignGui::TaskFeaturePick::makeCopy(selObj, subname, dlg.radioIndependent->isChecked());
                    if(selBody)
                        body->addObject(copy);
                    else
                        pcActivePart->addObject(copy);

                    selObj = copy;
                    subname.erase(std::remove_if(subname.begin(), subname.end(), &isdigit), subname.end());
                    subname.append("1");
            }
        
        }
    }

    // Remove subname for planes and datum features
    if (PartDesign::Feature::isDatum(selObj)) {
        subname = "";
    }

    selSub = std::vector<std::string>(1,subname);
}
void ViewProviderBody::slotChangedObjectApp ( const App::DocumentObject& obj, const App::Property& prop ) {
    
    if (!obj.isDerivedFrom ( Part::Feature::getClassTypeId () ) ||
        obj.isDerivedFrom ( Part::BodyBase::getClassTypeId () )    ) { // we are intrested only in Part::Features and not in bodies
        return;
    }

    const Part::Feature *feat = static_cast <const Part::Feature *>(&obj);

    if ( &feat->Shape != &prop && &feat->Placement != &prop) { // react only on changes in shapes and placement
        return;
    }

    PartDesign::Body *body = static_cast<PartDesign::Body*> ( getObject() );
    if ( body && body->hasFeature (&obj ) ) {
        updateOriginDatumSize ();
    }
}
Beispiel #6
0
void TaskDatumParameters::resetViewMode()
{
    //end temporary view mode of coordinate system
    PartDesign::Body * body = PartDesign::Body::findBodyOf(DatumView->getObject());
    if (body) {
        try {
            App::Origin *origin = body->getOrigin();
            ViewProviderOrigin* vpOrigin;
            vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin));
            vpOrigin->resetTemporaryVisibility();
        }
        catch (const Base::Exception &ex) {
            Base::Console().Error("%s\n", ex.what());
        }
    }

    DatumView->setPickable(true);
}
const QByteArray TaskSketchBasedParameters::onFaceName(const QString& text)
{
    if (text.length() == 0)
        return QByteArray();

    QStringList parts = text.split(QChar::fromLatin1(':'));
    if (parts.length() < 2)
        parts.push_back(QString::fromLatin1(""));
    // Check whether this is the name of an App::Plane or Part::Datum feature
    App::DocumentObject* obj = vp->getObject()->getDocument()->getObject(parts[0].toLatin1());
    if (obj == NULL)
        return QByteArray();

    PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
    if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) {
        // everything is OK (we assume a Part can only have exactly 3 App::Plane objects located at the base of the feature tree)
        return QByteArray();
    } else if (obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
        if (!activeBody->hasFeature(obj))
            return QByteArray();
        return QByteArray();
    } else {
        // We must expect that "text" is the translation of "Face" followed by an ID.
        QString name;
        QTextStream str(&name);
        str << "^" << tr("Face") << "(\\d+)$";
        QRegExp rx(name);
        if (text.indexOf(rx) < 0) {
            return QByteArray();
        }

        int faceId = rx.cap(1).toInt();
        std::stringstream ss;
        ss << "Face" << faceId;

        std::vector<std::string> upToFaces(1,ss.str());
        PartDesign::ProfileBased* pcSketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
        pcSketchBased->UpToFace.setValue(obj, upToFaces);
        recomputeFeature();

        return QByteArray(ss.str().c_str());
    }
}
TaskRevolutionParameters::~TaskRevolutionParameters()
{
    //hide the parts coordinate system axis for selection
    PartDesign::Body * body = PartDesign::Body::findBodyOf ( vp->getObject() );
    if ( body ) {
        try {
            App::Origin *origin = body->getOrigin();
            ViewProviderOrigin* vpOrigin;
            vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin));
            vpOrigin->resetTemporaryVisibility();
        } catch (const Base::Exception &ex) {
            Base::Console().Error ("%s\n", ex.what () );
        }
    }

    delete ui;

    for(size_t i = 0  ;  i < axesInList.size()  ;  i++ ){
        delete axesInList[i];
    }
}
void ViewProviderBody::slotChangedObjectGui (
        const Gui::ViewProviderDocumentObject& vp, const App::Property& prop )
{
    if (&vp.Visibility != &prop) { // react only on visability changes
        return;
    }

    if ( !vp.isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) &&
         !vp.isDerivedFrom ( Gui::ViewProviderOriginFeature::getClassTypeId () ) ) {
        // Ignore origins to avoid infinite recursion (not likely in a well-formed document,
        //          but may happen in documents designed in old versions of assembly branch )
        return;
    }

    PartDesign::Body *body = static_cast<PartDesign::Body*> ( getObject() );
    App::DocumentObject *obj = vp.getObject ();

    if ( body && obj && body->hasFeature ( obj ) ) {
        updateOriginDatumSize ();
    }
}
Beispiel #10
0
void CmdPartDesignMoveFeature::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    std::vector<App::DocumentObject*> features = getSelection().getObjectsOfType(Part::Feature::getClassTypeId());
    if (features.empty()) return;

    // Check if all features are valid to move
    if (std::any_of(std::begin(features), std::end(features), [](App::DocumentObject* obj){return !PartDesignGui::isFeatureMovable(obj); }))
    {
        //show messagebox and cancel
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Features cannot be moved"),
            QObject::tr("Some of the selected features have dependencies in the source body"));
        return;
    }

    // Collect dependenies of the selected features
    std::vector<App::DocumentObject*> dependencies = PartDesignGui::collectMovableDependencies(features);
    if (!dependencies.empty())
        features.insert(std::end(features), std::begin(dependencies), std::end(dependencies));

    // Create a list of all bodies in this part
    std::vector<App::DocumentObject*> bodies = getDocument()->getObjectsOfType(Part::BodyBase::getClassTypeId());

    std::set<App::DocumentObject*> source_bodies;
    for (auto feat : features) {
        PartDesign::Body* source = PartDesign::Body::findBodyOf(feat);
        source_bodies.insert(static_cast<App::DocumentObject*>(source));
    }

    std::vector<App::DocumentObject*> target_bodies;
    for (auto body : bodies) {
        if (!source_bodies.count(body))
            target_bodies.push_back(body);
    }

    if (target_bodies.empty())
    {
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Features cannot be moved"),
            QObject::tr("There are no other bodies to move to"));
        return;
    }

    // Ask user to select the target body (remove source bodies from list)
    bool ok;
    QStringList items;
    for (auto body : target_bodies) {
        items.push_back(QString::fromUtf8(body->Label.getValue()));
    }
    QString text = QInputDialog::getItem(Gui::getMainWindow(),
        qApp->translate("PartDesign_MoveFeature", "Select body"),
        qApp->translate("PartDesign_MoveFeature", "Select a body from the list"),
        items, 0, false, &ok);
    if (!ok) return;
    int index = items.indexOf(text);
    if (index < 0) return;

    PartDesign::Body* target = static_cast<PartDesign::Body*>(target_bodies[index]);

    openCommand("Move an object");

    for (auto feat: features) {
        // Find body of this feature
        Part::BodyBase* source = PartDesign::Body::findBodyOf(feat);
        bool featureWasTip = false;

        if (source == target) continue;

        // Remove from the source body if the feature belonged to a body
        if (source) {
            featureWasTip = (source->Tip.getValue() == feat);
            doCommand(Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)",
                      source->getNameInDocument(), (feat)->getNameInDocument());
        }

        App::DocumentObject* targetOldTip = target->Tip.getValue();

        // Add to target body (always at the Tip)
        doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",
                      target->getNameInDocument(), (feat)->getNameInDocument());
        // Recompute to update the shape
        doCommand(Gui,"App.activeDocument().recompute()");

        // Adjust visibility of features
        // TODO: May be something can be done in view provider (2015-08-05, Fat-Zer)
        // If we removed the tip of the source body, make the new tip visible
        if ( featureWasTip ) {
            App::DocumentObject * sourceNewTip = source->Tip.getValue();
            if (sourceNewTip)
                doCommand(Gui,"Gui.activeDocument().show(\"%s\")", sourceNewTip->getNameInDocument());
        }

        // Hide old tip and show new tip (the moved feature) of the target body
        App::DocumentObject* targetNewTip = target->Tip.getValue();
        if ( targetOldTip != targetNewTip ) {
            if ( targetOldTip ) {
                doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", targetOldTip->getNameInDocument());
            }
            if (targetNewTip) {
                doCommand(Gui,"Gui.activeDocument().show(\"%s\")", targetNewTip->getNameInDocument());
            }
        }

        // Fix sketch support
        if (feat->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
            Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(feat);
            try {
                PartDesignGui::fixSketchSupport(sketch);
            } catch (Base::Exception &) {
                QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Sketch plane cannot be migrated"),
                        QObject::tr("Please edit '%1' and redefine it to use a Base or Datum plane as the sketch plane.").
                        arg( QString::fromLatin1( sketch->Label.getValue () ) ) );
            }
        }

        //relink origin for sketches and datums (coordinates)
        PartDesignGui::relinkToOrigin(feat, target);
    }

    updateActive();
}
TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* RevolutionView, QWidget *parent)
    : TaskSketchBasedParameters(RevolutionView, parent, "PartDesign_Revolution",tr("Revolution parameters"))
{
    // we need a separate container widget to add all controls to
    proxy = new QWidget(this);
    ui = new Ui_TaskRevolutionParameters();
    ui->setupUi(proxy);
    QMetaObject::connectSlotsByName(this);

    connect(ui->revolveAngle, SIGNAL(valueChanged(double)),
            this, SLOT(onAngleChanged(double)));
    connect(ui->axis, SIGNAL(activated(int)),
            this, SLOT(onAxisChanged(int)));
    connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)),
            this, SLOT(onMidplane(bool)));
    connect(ui->checkBoxReversed, SIGNAL(toggled(bool)),
            this, SLOT(onReversed(bool)));
    connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)),
            this, SLOT(onUpdateView(bool)));

    this->groupLayout()->addWidget(proxy);

    // Temporarily prevent unnecessary feature recomputes
    ui->revolveAngle->blockSignals(true);
    ui->axis->blockSignals(true);
    ui->checkBoxMidplane->blockSignals(true);
    ui->checkBoxReversed->blockSignals(true);

    //bind property mirrors
    PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::ProfileBased*>(vp->getObject());
    if (pcFeat->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) {
        PartDesign::Revolution* rev = static_cast<PartDesign::Revolution*>(vp->getObject());
        this->propAngle = &(rev->Angle);
        this->propMidPlane = &(rev->Midplane);
        this->propReferenceAxis = &(rev->ReferenceAxis);
        this->propReversed = &(rev->Reversed);
    } else {
        assert(pcFeat->isDerivedFrom(PartDesign::Groove::getClassTypeId()));
        PartDesign::Groove* rev = static_cast<PartDesign::Groove*>(vp->getObject());
        this->propAngle = &(rev->Angle);
        this->propMidPlane = &(rev->Midplane);
        this->propReferenceAxis = &(rev->ReferenceAxis);
        this->propReversed = &(rev->Reversed);
    }

    double l = propAngle->getValue();
    bool mirrored = propMidPlane->getValue();
    bool reversed = propReversed->getValue();

    ui->revolveAngle->setValue(l);
    blockUpdate = false;
    updateUI();


    ui->checkBoxMidplane->setChecked(mirrored);
    ui->checkBoxReversed->setChecked(reversed);

    PartDesign::ProfileBased* sketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject());
    // TODO This is quite ugly better redo it (2015-11-02, Fat-Zer)
    if ( sketchBased->isDerivedFrom(PartDesign::Revolution::getClassTypeId() ) ) {
        ui->revolveAngle->bind(static_cast<PartDesign::Revolution *> ( sketchBased )->Angle);
    } else if ( sketchBased->isDerivedFrom(PartDesign::Groove::getClassTypeId() ) ) {
        ui->revolveAngle->bind(static_cast<PartDesign::Groove *> ( sketchBased )->Angle);
    }

    ui->revolveAngle->blockSignals(false);
    ui->axis->blockSignals(false);
    ui->checkBoxMidplane->blockSignals(false);
    ui->checkBoxReversed->blockSignals(false);

    setFocus ();

    //show the parts coordinate system axis for selection
    PartDesign::Body * body = PartDesign::Body::findBodyOf ( vp->getObject () );
    if(body) {
        try {
            App::Origin *origin = body->getOrigin();
            ViewProviderOrigin* vpOrigin;
            vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin));
            vpOrigin->setTemporaryVisibility(true, false);
        } catch (const Base::Exception &ex) {
            Base::Console().Error ("%s\n", ex.what () );
        }
     }
}
Beispiel #12
0
TaskDatumParameters::TaskDatumParameters(ViewProviderDatum *DatumView,QWidget *parent)
    : TaskBox(Gui::BitmapFactory().pixmap((QString::fromLatin1("PartDesign_") + DatumView->datumType).toLatin1()),
              DatumView->datumType + tr(" parameters"), true, parent),
      DatumView(DatumView)
{
    // we need a separate container widget to add all controls to
    proxy = new QWidget(this);
    ui = new Ui_TaskDatumParameters();
    ui->setupUi(proxy);
    QMetaObject::connectSlotsByName(this);

    connect(ui->superplacementX, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementXChanged(double)));
    connect(ui->superplacementY, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementYChanged(double)));
    connect(ui->superplacementZ, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementZChanged(double)));
    connect(ui->superplacementYaw, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementYawChanged(double)));
    connect(ui->superplacementPitch, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementPitchChanged(double)));
    connect(ui->superplacementRoll, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementRollChanged(double)));
    connect(ui->checkBoxFlip, SIGNAL(toggled(bool)),
            this, SLOT(onCheckFlip(bool)));
    connect(ui->buttonRef1, SIGNAL(clicked(bool)),
            this, SLOT(onButtonRef1(bool)));
    connect(ui->lineRef1, SIGNAL(textEdited(QString)),
            this, SLOT(onRefName1(QString)));
    connect(ui->buttonRef2, SIGNAL(clicked(bool)),
            this, SLOT(onButtonRef2(bool)));
    connect(ui->lineRef2, SIGNAL(textEdited(QString)),
            this, SLOT(onRefName2(QString)));
    connect(ui->buttonRef3, SIGNAL(clicked(bool)),
            this, SLOT(onButtonRef3(bool)));
    connect(ui->lineRef3, SIGNAL(textEdited(QString)),
            this, SLOT(onRefName3(QString)));
    connect(ui->buttonRef4, SIGNAL(clicked(bool)),
            this, SLOT(onButtonRef4(bool)));
    connect(ui->lineRef4, SIGNAL(textEdited(QString)),
            this, SLOT(onRefName4(QString)));
    connect(ui->listOfModes,SIGNAL(itemSelectionChanged()),
            this, SLOT(onModeSelect()));

    this->groupLayout()->addWidget(proxy);

    // Temporarily prevent unnecessary feature recomputes
    ui->checkBoxFlip->blockSignals(true);
    ui->buttonRef1->blockSignals(true);
    ui->lineRef1->blockSignals(true);
    ui->buttonRef2->blockSignals(true);
    ui->lineRef2->blockSignals(true);
    ui->buttonRef3->blockSignals(true);
    ui->lineRef3->blockSignals(true);
    ui->buttonRef4->blockSignals(true);
    ui->lineRef4->blockSignals(true);
    ui->listOfModes->blockSignals(true);

    // Get the feature data    
    Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject());
    //std::vector<App::DocumentObject*> refs = pcDatum->Support.getValues();
    std::vector<std::string> refnames = pcDatum->Support.getSubValues();

    ui->checkBoxFlip->setChecked(pcDatum->MapReversed.getValue());
    std::vector<QString> refstrings;
    makeRefStrings(refstrings, refnames);
    ui->lineRef1->setText(refstrings[0]);
    ui->lineRef1->setProperty("RefName", QByteArray(refnames[0].c_str()));
    ui->lineRef2->setText(refstrings[1]);
    ui->lineRef2->setProperty("RefName", QByteArray(refnames[1].c_str()));
    ui->lineRef3->setText(refstrings[2]);
    ui->lineRef3->setProperty("RefName", QByteArray(refnames[2].c_str()));
    ui->lineRef4->setText(refstrings[3]);
    ui->lineRef4->setProperty("RefName", QByteArray(refnames[3].c_str()));

    // activate and de-activate dialog elements as appropriate
    ui->checkBoxFlip->blockSignals(false);
    ui->buttonRef1->blockSignals(false);
    ui->lineRef1->blockSignals(false);
    ui->buttonRef2->blockSignals(false);
    ui->lineRef2->blockSignals(false);
    ui->buttonRef3->blockSignals(false);
    ui->lineRef3->blockSignals(false);
    ui->buttonRef4->blockSignals(false);
    ui->lineRef4->blockSignals(false);
    ui->listOfModes->blockSignals(false);

    this->iActiveRef = 0;
    if (pcDatum->Support.getSize() == 0){
        autoNext = true;
    } else {
        autoNext = false;
    }

    ui->superplacementX->bind(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Base.x")));
    ui->superplacementY->bind(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Base.y")));
    ui->superplacementZ->bind(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Base.z")));
    visibilityAutomation(true);
    updateSuperplacementUI();
    updateReferencesUI();
    updateListOfModes(eMapMode(pcDatum->MapMode.getValue()));
    updatePreview();

    //temporary show coordinate systems for selection
    PartDesign::Body * body = PartDesign::Body::findBodyOf(DatumView->getObject());
    if (body) {
        try {
            App::Origin *origin = body->getOrigin();
            ViewProviderOrigin* vpOrigin;
            vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin));
            vpOrigin->setTemporaryVisibility(true, true);
        } catch (const Base::Exception &ex) {
            Base::Console().Error ("%s\n", ex.what () );
        }
    }

    DatumView->setPickable(false);

    Gui::Selection().addSelectionGate(new NoDependentsSelection(DatumView->getObject(), true, true, true, true));

    // connect object deletion with slot
    auto bnd = boost::bind(&TaskDatumParameters::objectDeleted, this, _1);
    Gui::Document* document = Gui::Application::Instance->getDocument(DatumView->getObject()->getDocument());
    connectDelObject = document->signalDeletedObject.connect(bnd);
}
void ViewProviderBody::updateOriginDatumSize () {
    PartDesign::Body *body = static_cast<PartDesign::Body *> ( getObject() );
    
    // Use different bounding boxes for datums and for origins:
    Gui::Document* gdoc = Gui::Application::Instance->getDocument(getObject()->getDocument());
    if(!gdoc) 
        return;
    
    Gui::MDIView* view = gdoc->getViewOfViewProvider(this);
    if(!view)
        return;
    
    Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
    SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion());

    const auto & model = body->getFullModel ();

    // BBox for Datums is calculated from all visible objects but treating datums as their basepoints only
    SbBox3f bboxDatums = ViewProviderDatum::getRelevantBoundBox ( bboxAction, model );
    // BBox for origin should take into account datums size also
    SbBox3f bboxOrigins = bboxDatums;

    for(App::DocumentObject* obj : model) {
        if ( obj->isDerivedFrom ( Part::Datum::getClassTypeId () ) ) {
            ViewProvider *vp = Gui::Application::Instance->getViewProvider(obj);
            if (!vp) { continue; }

            ViewProviderDatum *vpDatum = static_cast <ViewProviderDatum *> (vp) ;

            vpDatum->setExtents ( bboxDatums );

            bboxAction.apply ( vp->getRoot () );
            bboxOrigins.extendBy ( bboxAction.getBoundingBox () );
        }
    }

    // get the bounding box values
    SbVec3f max = bboxOrigins.getMax();
    SbVec3f min = bboxOrigins.getMin();

    // obtain an Origin and it's ViewProvider
    App::Origin* origin = 0;
    Gui::ViewProviderOrigin* vpOrigin = 0;
    try {
        origin = body->getOrigin ();
        assert (origin);

        Gui::ViewProvider *vp = Gui::Application::Instance->getViewProvider(origin);
        if (!vp) {
            throw Base::Exception ("No view provider linked to the Origin");
        }
        assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) );
        vpOrigin = static_cast <Gui::ViewProviderOrigin *> ( vp );
    } catch (const Base::Exception &ex) {
        Base::Console().Error ("%s\n", ex.what() );
        return;
    }

    // calculate the desired origin size
    Base::Vector3d size;

    for (uint_fast8_t i=0; i<3; i++) {
        size[i] = std::max ( fabs ( max[i] ), fabs ( min[i] ) );
        if (size[i] < Precision::Confusion() ) {
            size[i] = Gui::ViewProviderOrigin::defaultSize();
        }
    }

    vpOrigin->Size.setValue ( size*1.2 );
}
void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) const
{
    auto selection = Gui::Selection().getSelection();
    // Add move Tip Command
    if ( selection.size () >= 1 ) {
        App::DocumentObject *feature = selection.front().pObject;
        PartDesign::Body *body =  PartDesignGui::getBodyFor ( feature, false );
        // lote of assertion so feature sould be marked as a tip
        if ( selection.size () == 1 && feature && (
            feature->isDerivedFrom ( PartDesign::Body::getClassTypeId () ) ||
            ( feature->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) && body ) ||
            ( feature->isDerivedFrom ( Part::Feature::getClassTypeId () ) && body &&
              body->BaseFeature.getValue() == feature )
        ) ) {
            *item << "PartDesign_MoveTip";
        }

        if (strcmp(recipient, "Tree") == 0) {

            Gui::MDIView *activeView = Gui::Application::Instance->activeView();

            if ( selection.size () > 0 && activeView ) {
                bool docHaveBodies = activeView->getAppDocument()->countObjectsOfType (
                                        PartDesign::Body::getClassTypeId () ) > 0;

                if ( docHaveBodies ) {
                    bool addMoveFeature = true;
                    bool addMoveFeatureInTree = (body != nullptr);
                    for (auto sel: selection) {
                        // if at least one selected feature cannot be moved to a body
                        // disable the entry
                        if ( addMoveFeature && !PartDesign::Body::isAllowed ( sel.pObject ) ) {
                            addMoveFeature = false;
                        }
                        // if all at lest one selected feature doesn't belongs to the same body
                        // disable the menu entry
                        if ( addMoveFeatureInTree && !body->hasFeature ( sel.pObject ) ) {
                            addMoveFeatureInTree = false;
                        }

                        if ( !addMoveFeatureInTree && !addMoveFeature ) {
                            break;
                        }
                    }

                    if (addMoveFeature) {
                        *item   << "PartDesign_MoveFeature";
                    }

                    if (addMoveFeatureInTree) {
                        *item   << "PartDesign_MoveFeatureInTree";
                    }
                }
            }

            if (Gui::Selection().countObjectsOfType(PartDesign::Transformed::getClassTypeId()) -
                Gui::Selection().countObjectsOfType(PartDesign::MultiTransform::getClassTypeId()) == 1 )
                *item << "PartDesign_MultiTransform";
        }
    }
}
Beispiel #15
0
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::GeoFeatureGroup *geoGroup;

    if ( support ) {
        body = PartDesign::Body::findBodyOf (support);
    } else {
        body = PartDesignGui::getBody (false);
    }

    if ( body ) { // Search for Part of the body
        geoGroup = App::GeoFeatureGroup::getGroupOfObject ( body ) ;
    } else if ( support ) { // if no body search part for support
        geoGroup = App::GeoFeatureGroup::getGroupOfObject ( support ) ;
    } else { // fallback to active part
        geoGroup = PartDesignGui::getActivePart ( );
    }

    // 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 choosen body or part
            try { // here are some throwers
                if (body) {
                    if (body->getOrigin ()->hasObject (pObj) ) {
                        return true;
                    }
                } else if (geoGroup && geoGroup->isDerivedFrom ( App::OriginGroup::getClassTypeId () ) ) {
                    if ( static_cast<App::OriginGroup *>(geoGroup)->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->hasFeature(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;
}
void TaskRevolutionParameters::fillAxisCombo(bool forceRefill)
{
    // TODO share the code with TaskTransformedParameters (2015-08-31, Fat-Zer)
    bool oldVal_blockUpdate = blockUpdate;
    blockUpdate = true;

    if(axesInList.size() == 0)
        forceRefill = true;//not filled yet, full refill

    if (forceRefill){
        ui->axis->clear();

        for(size_t i = 0  ;  i < axesInList.size()  ;  i++ ){
            delete axesInList[i];
        }
        this->axesInList.clear();

        //add sketch axes
        PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::Revolution*>(vp->getObject());
        Part::Part2DObject* pcSketch = static_cast<Part::Part2DObject*>(pcFeat->Profile.getValue());
        if (pcSketch){
            addAxisToCombo(pcSketch,"V_Axis",QObject::tr("Vertical sketch axis"));
            addAxisToCombo(pcSketch,"H_Axis",QObject::tr("Horizontal sketch axis"));
            for (int i=0; i < pcSketch->getAxisCount(); i++) {
                QString itemText = QObject::tr("Construction line %1").arg(i+1);
                std::stringstream sub;
                sub << "Axis" << i;
                addAxisToCombo(pcSketch,sub.str(),itemText);
            }
        }

        //add part axes
        App::DocumentObject* obj = vp->getObject();

        PartDesign::Body * body = PartDesign::Body::findBodyOf ( obj );
        if (body) {
            try {
                App::Origin* orig = body->getOrigin();
                addAxisToCombo(orig->getX(),"",tr("Base X axis"));
                addAxisToCombo(orig->getY(),"",tr("Base Y axis"));
                addAxisToCombo(orig->getZ(),"",tr("Base Z axis"));
            } catch (const Base::Exception &ex) {
                Base::Console().Error ("%s\n", ex.what() );
            }
        }

        //add "Select reference"
        addAxisToCombo(0,std::string(),tr("Select reference..."));
    }//endif forceRefill

    //add current link, if not in list
    //first, figure out the item number for current axis
    int indexOfCurrent = -1;
    App::DocumentObject* ax = propReferenceAxis->getValue();
    const std::vector<std::string> &subList = propReferenceAxis->getSubValues();
    for(size_t i = 0  ;  i < axesInList.size()  ;  i++) {
        if(ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues())
            indexOfCurrent = i;
    }
    if ( indexOfCurrent == -1  &&  ax ){
        assert(subList.size() <= 1);
        std::string sub;
        if (subList.size()>0)
            sub = subList[0];
        addAxisToCombo(ax, sub, getRefStr(ax, subList));
        indexOfCurrent = axesInList.size()-1;
    }

    //highlight current.
    if (indexOfCurrent != -1)
        ui->axis->setCurrentIndex(indexOfCurrent);

    blockUpdate = oldVal_blockUpdate;
}