// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2007 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DlgPrimitives.h" #include "ui_DlgPrimitives.h" #include "ui_Location.h" using namespace PartGui; namespace PartGui { QString getAutoGroupCommandStr(QString objectName) // Helper function to get the python code to add the newly created object to the active Part object // if present { App::Part* activePart = Gui::Application::Instance->activeView()->getActiveObject( "part" ); if (activePart) { QString activeObjectName = QString::fromUtf8(activePart->getNameInDocument()); return QStringLiteral( "App.ActiveDocument.getObject('%1\')." "addObject(App.ActiveDocument.getObject('%2\'))\n" ) .arg(activeObjectName, objectName); } return QStringLiteral("# Object %1 created at document root").arg(objectName); } const char* gce_ErrorStatusText(gce_ErrorType et) { switch (et) { case gce_Done: return "Construction was successful"; case gce_ConfusedPoints: return "Two points are coincident"; case gce_NegativeRadius: return "Radius value is negative"; case gce_ColinearPoints: return "Three points are collinear"; case gce_IntersectionError: return "Intersection cannot be computed"; case gce_NullAxis: return "Axis is undefined"; case gce_NullAngle: return "Angle value is invalid (usually null)"; case gce_NullRadius: return "Radius is null"; case gce_InvertAxis: return "Axis value is invalid"; case gce_BadAngle: return "Angle value is invalid"; case gce_InvertRadius: return "Radius value is incorrect (usually with respect to another radius)"; case gce_NullFocusLength: return "Focal distance is null"; case gce_NullVector: return "Vector is null"; case gce_BadEquation: return "Coefficients are incorrect (applies to the equation of a geometric object)"; default: return "Creation of geometry failed"; } } static QString safeQuantityQString(Gui::QuantitySpinBox* qs) { return QString::fromStdString(qs->value().getSafeUserString()); } void Picker::createPrimitive(QWidget* widget, const QString& descr, Gui::Document* doc) { try { App::Document* app = doc->getDocument(); QString cmd = this->command(app); // Execute the Python block doc->openCommand(descr.toUtf8()); Gui::Command::runCommand(Gui::Command::Doc, cmd.toUtf8()); doc->commitCommand(); Gui::Command::runCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); Gui::Command::runCommand(Gui::Command::Gui, "Gui.SendMsgToActiveView(\"ViewFit\")"); } catch (const Base::Exception& e) { QMessageBox::warning(widget, descr, QCoreApplication::translate("Exception", e.what())); } } QString Picker::toPlacement(const gp_Ax2& axis) const { gp_Dir dir = axis.Direction(); gp_Pnt pnt = gp_Pnt(0.0, 0.0, 0.0); gp_Ax3 ax3(pnt, dir, axis.XDirection()); gp_Trsf Trf; Trf.SetTransformation(ax3); Trf.Invert(); gp_XYZ theAxis(0, 0, 1); Standard_Real theAngle = 0.0; Trf.GetRotation(theAxis, theAngle); Base::Rotation rot(Base::convertTo(theAxis), theAngle); gp_Pnt loc = axis.Location(); return QStringLiteral("Base.Placement(Base.Vector(%1,%2,%3),Base.Rotation(%4,%5,%6,%7))") .arg(loc.X(), 0, 'g', Base::UnitsApi::getDecimals()) .arg(loc.Y(), 0, 'g', Base::UnitsApi::getDecimals()) .arg(loc.Z(), 0, 'g', Base::UnitsApi::getDecimals()) .arg(rot[0], 0, 'g', Base::UnitsApi::getDecimals()) .arg(rot[1], 0, 'g', Base::UnitsApi::getDecimals()) .arg(rot[2], 0, 'g', Base::UnitsApi::getDecimals()) .arg(rot[3], 0, 'g', Base::UnitsApi::getDecimals()); } class CircleFromThreePoints: public Picker { public: CircleFromThreePoints() : Picker() {} bool pickedPoint(const SoPickedPoint* point) override { SbVec3f pnt = point->getPoint(); points.emplace_back(pnt[0], pnt[1], pnt[2]); return points.size() == 3; } QString command(App::Document* doc) const override { GC_MakeArcOfCircle arc(points[0], points[1], points[2]); if (!arc.IsDone()) { throw Base::CADKernelError(gce_ErrorStatusText(arc.Status())); } Handle(Geom_TrimmedCurve) trim = arc.Value(); Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(trim->BasisCurve()); QString name = QString::fromUtf8(doc->getUniqueObjectName("Circle").c_str()); return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Circle\",\"%1\")\n" "App.ActiveDocument.%1.Radius=%2\n" "App.ActiveDocument.%1.Angle1=%3\n" "App.ActiveDocument.%1.Angle2=%4\n" "App.ActiveDocument.%1.Placement=%5\n" ) .arg(name) .arg(circle->Radius(), 0, 'g', Base::UnitsApi::getDecimals()) .arg(Base::toDegrees(trim->FirstParameter()), 0, 'g', Base::UnitsApi::getDecimals()) .arg(Base::toDegrees(trim->LastParameter()), 0, 'g', Base::UnitsApi::getDecimals()) .arg(toPlacement(circle->Position())); } private: std::vector points; }; } // namespace PartGui // ---------------------------------------------------------------------------- AbstractPrimitive::AbstractPrimitive(Part::Primitive* feature) : featurePtr(feature) {} bool AbstractPrimitive::hasValidPrimitive() const { return (!featurePtr.expired()); } void AbstractPrimitive::connectSignalMapper(QSignalMapper* mapper) { connect(mapper, &QSignalMapper::mappedObject, this, &AbstractPrimitive::changeValue); } namespace PartGui { void mapSignalMapper(QObject* sender, QSignalMapper* mapper) { mapper->setMapping(sender, sender); } template void connectMapSignalMapper( typename QtPrivate::FunctionPointer::Object* sender, Function func, QSignalMapper* mapper ) { QObject::connect(sender, func, mapper, qOverload<>(&QSignalMapper::map)); mapSignalMapper(sender, mapper); } } // namespace PartGui // ---------------------------------------------------------------------------- PlanePrimitive::PlanePrimitive(std::shared_ptr ui, Part::Plane* feature) : AbstractPrimitive(feature) , ui(ui) { ui->planeLength->setRange(0, std::numeric_limits::max()); ui->planeWidth->setRange(0, std::numeric_limits::max()); if (feature) { ui->planeLength->setValue(feature->Length.getQuantityValue()); ui->planeLength->bind(feature->Length); ui->planeWidth->setValue(feature->Width.getQuantityValue()); ui->planeWidth->bind(feature->Width); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->planeLength, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->planeWidth, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* PlanePrimitive::getDefaultName() const { return "Plane"; } QString PlanePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Plane\",\"%1\")\n" "App.ActiveDocument.%1.Length='%2'\n" "App.ActiveDocument.%1.Width='%3'\n" "App.ActiveDocument.%1.Placement=%4\n" "App.ActiveDocument.%1.Label='%5'\n" ) .arg( objectName, safeQuantityQString(ui->planeLength), safeQuantityQString(ui->planeWidth), placement, DlgPrimitives::tr("Plane") ); } QString PlanePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Length='%2'\n" "%1.Width='%3'\n" "%1.Placement=%4\n" ) .arg( objectName, safeQuantityQString(ui->planeLength), safeQuantityQString(ui->planeWidth), placement ); } void PlanePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Plane* plane = featurePtr.get(); if (widget == ui->planeLength) { plane->Length.setValue(ui->planeLength->value().getValue()); } else if (widget == ui->planeWidth) { plane->Width.setValue(ui->planeWidth->value().getValue()); } plane->recomputeFeature(); } // ---------------------------------------------------------------------------- BoxPrimitive::BoxPrimitive(std::shared_ptr ui, Part::Box* feature) : AbstractPrimitive(feature) , ui(ui) { ui->boxLength->setRange(0, std::numeric_limits::max()); ui->boxWidth->setRange(0, std::numeric_limits::max()); ui->boxHeight->setRange(0, std::numeric_limits::max()); if (feature) { ui->boxLength->setValue(feature->Length.getQuantityValue()); ui->boxLength->bind(feature->Length); ui->boxWidth->setValue(feature->Width.getQuantityValue()); ui->boxWidth->bind(feature->Width); ui->boxHeight->setValue(feature->Height.getQuantityValue()); ui->boxHeight->bind(feature->Height); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->boxLength, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->boxWidth, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->boxHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* BoxPrimitive::getDefaultName() const { return "Box"; } QString BoxPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Box\",\"%1\")\n" "App.ActiveDocument.%1.Length='%2'\n" "App.ActiveDocument.%1.Width='%3'\n" "App.ActiveDocument.%1.Height='%4'\n" "App.ActiveDocument.%1.Placement=%5\n" "App.ActiveDocument.%1.Label='%6'\n" ) .arg( objectName, safeQuantityQString(ui->boxLength), safeQuantityQString(ui->boxWidth), safeQuantityQString(ui->boxHeight), placement, DlgPrimitives::tr("Box") ); } QString BoxPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Length='%2'\n" "%1.Width='%3'\n" "%1.Height='%4'\n" "%1.Placement=%5\n" ) .arg( objectName, safeQuantityQString(ui->boxLength), safeQuantityQString(ui->boxWidth), safeQuantityQString(ui->boxHeight), placement ); } void BoxPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Box* box = featurePtr.get(); if (widget == ui->boxLength) { box->Length.setValue(ui->boxLength->value().getValue()); } else if (widget == ui->boxWidth) { box->Width.setValue(ui->boxWidth->value().getValue()); } else if (widget == ui->boxHeight) { box->Height.setValue(ui->boxHeight->value().getValue()); } box->recomputeFeature(); } // ---------------------------------------------------------------------------- CylinderPrimitive::CylinderPrimitive(std::shared_ptr ui, Part::Cylinder* feature) : AbstractPrimitive(feature) , ui(ui) { ui->cylinderRadius->setRange(0, std::numeric_limits::max()); ui->cylinderHeight->setRange(0, std::numeric_limits::max()); ui->cylinderAngle->setRange(0, 360); if (feature) { ui->cylinderRadius->setValue(feature->Radius.getQuantityValue()); ui->cylinderRadius->bind(feature->Radius); ui->cylinderHeight->setValue(feature->Height.getQuantityValue()); ui->cylinderHeight->bind(feature->Height); ui->cylinderXSkew->setValue(feature->FirstAngle.getQuantityValue()); ui->cylinderXSkew->bind(feature->FirstAngle); ui->cylinderYSkew->setValue(feature->SecondAngle.getQuantityValue()); ui->cylinderYSkew->bind(feature->SecondAngle); ui->cylinderAngle->setValue(feature->Angle.getQuantityValue()); ui->cylinderAngle->bind(feature->Angle); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->cylinderRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->cylinderHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->cylinderXSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->cylinderYSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->cylinderAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* CylinderPrimitive::getDefaultName() const { return "Cylinder"; } QString CylinderPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Cylinder\",\"%1\")\n" "App.ActiveDocument.%1.Radius='%2'\n" "App.ActiveDocument.%1.Height='%3'\n" "App.ActiveDocument.%1.Angle='%4'\n" "App.ActiveDocument.%1.FirstAngle='%5'\n" "App.ActiveDocument.%1.SecondAngle='%6'\n" "App.ActiveDocument.%1.Placement=%7\n" "App.ActiveDocument.%1.Label='%8'\n" ) .arg( objectName, safeQuantityQString(ui->cylinderRadius), safeQuantityQString(ui->cylinderHeight), safeQuantityQString(ui->cylinderAngle), safeQuantityQString(ui->cylinderXSkew), safeQuantityQString(ui->cylinderYSkew), placement, DlgPrimitives::tr("Cylinder") ); } QString CylinderPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Radius='%2'\n" "%1.Height='%3'\n" "%1.Angle='%4'\n" "%1.FirstAngle='%5'\n" "%1.SecondAngle='%6'\n" "%1.Placement=%7\n" ) .arg( objectName, safeQuantityQString(ui->cylinderRadius), safeQuantityQString(ui->cylinderHeight), safeQuantityQString(ui->cylinderAngle), safeQuantityQString(ui->cylinderXSkew), safeQuantityQString(ui->cylinderYSkew), placement ); } void CylinderPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Cylinder* cyl = featurePtr.get(); if (widget == ui->cylinderRadius) { cyl->Radius.setValue(ui->cylinderRadius->value().getValue()); } else if (widget == ui->cylinderHeight) { cyl->Height.setValue(ui->cylinderHeight->value().getValue()); } else if (widget == ui->cylinderAngle) { cyl->Angle.setValue(ui->cylinderAngle->value().getValue()); } else if (widget == ui->cylinderXSkew) { cyl->FirstAngle.setValue(ui->cylinderXSkew->value().getValue()); } else if (widget == ui->cylinderYSkew) { cyl->SecondAngle.setValue(ui->cylinderYSkew->value().getValue()); } cyl->recomputeFeature(); } // ---------------------------------------------------------------------------- ConePrimitive::ConePrimitive(std::shared_ptr ui, Part::Cone* feature) : AbstractPrimitive(feature) , ui(ui) { ui->coneRadius1->setRange(0, std::numeric_limits::max()); ui->coneRadius2->setRange(0, std::numeric_limits::max()); ui->coneHeight->setRange(0, std::numeric_limits::max()); ui->coneAngle->setRange(0, 360); if (feature) { ui->coneRadius1->setValue(feature->Radius1.getQuantityValue()); ui->coneRadius1->bind(feature->Radius1); ui->coneRadius2->setValue(feature->Radius2.getQuantityValue()); ui->coneRadius2->bind(feature->Radius2); ui->coneHeight->setValue(feature->Height.getQuantityValue()); ui->coneHeight->bind(feature->Height); ui->coneAngle->setValue(feature->Angle.getQuantityValue()); ui->coneAngle->bind(feature->Angle); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->coneRadius1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->coneRadius2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->coneHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->coneAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* ConePrimitive::getDefaultName() const { return "Cone"; } QString ConePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Cone\",\"%1\")\n" "App.ActiveDocument.%1.Radius1='%2'\n" "App.ActiveDocument.%1.Radius2='%3'\n" "App.ActiveDocument.%1.Height='%4'\n" "App.ActiveDocument.%1.Angle='%5'\n" "App.ActiveDocument.%1.Placement=%6\n" "App.ActiveDocument.%1.Label='%7'\n" ) .arg( objectName, safeQuantityQString(ui->coneRadius1), safeQuantityQString(ui->coneRadius2), safeQuantityQString(ui->coneHeight), safeQuantityQString(ui->coneAngle), placement, DlgPrimitives::tr("Cone") ); } QString ConePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Radius1='%2'\n" "%1.Radius2='%3'\n" "%1.Height='%4'\n" "%1.Angle='%5'\n" "%1.Placement=%6\n" ) .arg( objectName, safeQuantityQString(ui->coneRadius1), safeQuantityQString(ui->coneRadius2), safeQuantityQString(ui->coneHeight), safeQuantityQString(ui->coneAngle), placement ); } void ConePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Cone* cone = featurePtr.get(); if (widget == ui->coneRadius1) { cone->Radius1.setValue(ui->coneRadius1->value().getValue()); } else if (widget == ui->coneRadius2) { cone->Radius2.setValue(ui->coneRadius2->value().getValue()); } else if (widget == ui->coneHeight) { cone->Height.setValue(ui->coneHeight->value().getValue()); } else if (widget == ui->coneAngle) { cone->Angle.setValue(ui->coneAngle->value().getValue()); } cone->recomputeFeature(); } // ---------------------------------------------------------------------------- SpherePrimitive::SpherePrimitive(std::shared_ptr ui, Part::Sphere* feature) : AbstractPrimitive(feature) , ui(ui) { ui->sphereRadius->setRange(0, std::numeric_limits::max()); ui->sphereAngle1->setRange(-90, 90); ui->sphereAngle2->setRange(-90, 90); ui->sphereAngle3->setRange(0, 360); if (feature) { ui->sphereRadius->setValue(feature->Radius.getQuantityValue()); ui->sphereRadius->bind(feature->Radius); ui->sphereAngle1->setValue(feature->Angle1.getQuantityValue()); ui->sphereAngle1->bind(feature->Angle1); ui->sphereAngle2->setValue(feature->Angle2.getQuantityValue()); ui->sphereAngle2->bind(feature->Angle2); ui->sphereAngle3->setValue(feature->Angle3.getQuantityValue()); ui->sphereAngle3->bind(feature->Angle3); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->sphereRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->sphereAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->sphereAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->sphereAngle3, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* SpherePrimitive::getDefaultName() const { return "Sphere"; } QString SpherePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Sphere\",\"%1\")\n" "App.ActiveDocument.%1.Radius='%2'\n" "App.ActiveDocument.%1.Angle1='%3'\n" "App.ActiveDocument.%1.Angle2='%4'\n" "App.ActiveDocument.%1.Angle3='%5'\n" "App.ActiveDocument.%1.Placement=%6\n" "App.ActiveDocument.%1.Label='%7'\n" ) .arg( objectName, safeQuantityQString(ui->sphereRadius), safeQuantityQString(ui->sphereAngle1), safeQuantityQString(ui->sphereAngle2), safeQuantityQString(ui->sphereAngle3), placement, DlgPrimitives::tr("Sphere") ); } QString SpherePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Radius='%2'\n" "%1.Angle1='%3'\n" "%1.Angle2='%4'\n" "%1.Angle3='%5'\n" "%1.Placement=%6\n" ) .arg( objectName, safeQuantityQString(ui->sphereRadius), safeQuantityQString(ui->sphereAngle1), safeQuantityQString(ui->sphereAngle2), safeQuantityQString(ui->sphereAngle3), placement ); } void SpherePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Sphere* sphere = featurePtr.get(); if (widget == ui->sphereRadius) { sphere->Radius.setValue(ui->sphereRadius->value().getValue()); } else if (widget == ui->sphereAngle1) { sphere->Angle1.setValue(ui->sphereAngle1->value().getValue()); } else if (widget == ui->sphereAngle2) { sphere->Angle2.setValue(ui->sphereAngle2->value().getValue()); } else if (widget == ui->sphereAngle3) { sphere->Angle3.setValue(ui->sphereAngle3->value().getValue()); } sphere->recomputeFeature(); } // ---------------------------------------------------------------------------- EllipsoidPrimitive::EllipsoidPrimitive(std::shared_ptr ui, Part::Ellipsoid* feature) : AbstractPrimitive(feature) , ui(ui) { ui->ellipsoidRadius1->setRange(0, std::numeric_limits::max()); ui->ellipsoidRadius2->setRange(0, std::numeric_limits::max()); ui->ellipsoidRadius3->setRange(0, std::numeric_limits::max()); ui->ellipsoidAngle1->setRange(-90, 90); ui->ellipsoidAngle2->setRange(-90, 90); ui->ellipsoidAngle3->setRange(0, 360); if (feature) { ui->ellipsoidRadius1->setValue(feature->Radius1.getQuantityValue()); ui->ellipsoidRadius1->bind(feature->Radius1); ui->ellipsoidRadius2->setValue(feature->Radius2.getQuantityValue()); ui->ellipsoidRadius2->bind(feature->Radius2); ui->ellipsoidRadius3->setValue(feature->Radius3.getQuantityValue()); ui->ellipsoidRadius3->bind(feature->Radius3); ui->ellipsoidAngle1->setValue(feature->Angle1.getQuantityValue()); ui->ellipsoidAngle1->bind(feature->Angle1); ui->ellipsoidAngle2->setValue(feature->Angle2.getQuantityValue()); ui->ellipsoidAngle2->bind(feature->Angle2); ui->ellipsoidAngle3->setValue(feature->Angle3.getQuantityValue()); ui->ellipsoidAngle3->bind(feature->Angle3); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->ellipsoidRadius1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipsoidRadius2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipsoidRadius3, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipsoidAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipsoidAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipsoidAngle3, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* EllipsoidPrimitive::getDefaultName() const { return "Ellipsoid"; } QString EllipsoidPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Ellipsoid\",\"%1\")\n" "App.ActiveDocument.%1.Radius1='%2'\n" "App.ActiveDocument.%1.Radius2='%3'\n" "App.ActiveDocument.%1.Radius3='%4'\n" "App.ActiveDocument.%1.Angle1='%5'\n" "App.ActiveDocument.%1.Angle2='%6'\n" "App.ActiveDocument.%1.Angle3='%7'\n" "App.ActiveDocument.%1.Placement=%8\n" "App.ActiveDocument.%1.Label='%9'\n" ) .arg( objectName, safeQuantityQString(ui->ellipsoidRadius1), safeQuantityQString(ui->ellipsoidRadius2), safeQuantityQString(ui->ellipsoidRadius3), safeQuantityQString(ui->ellipsoidAngle1), safeQuantityQString(ui->ellipsoidAngle2), safeQuantityQString(ui->ellipsoidAngle3), placement, DlgPrimitives::tr("Ellipsoid") ); } QString EllipsoidPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Radius1='%2'\n" "%1.Radius2='%3'\n" "%1.Radius3='%4'\n" "%1.Angle1='%5'\n" "%1.Angle2='%6'\n" "%1.Angle3='%7'\n" "%1.Placement=%8\n" ) .arg( objectName, safeQuantityQString(ui->ellipsoidRadius1), safeQuantityQString(ui->ellipsoidRadius2), safeQuantityQString(ui->ellipsoidRadius3), safeQuantityQString(ui->ellipsoidAngle1), safeQuantityQString(ui->ellipsoidAngle2), safeQuantityQString(ui->ellipsoidAngle3), placement ); } void EllipsoidPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Ellipsoid* ell = featurePtr.get(); if (widget == ui->ellipsoidRadius1) { ell->Radius1.setValue(ui->ellipsoidRadius1->value().getValue()); } else if (widget == ui->ellipsoidRadius2) { ell->Radius2.setValue(ui->ellipsoidRadius2->value().getValue()); } else if (widget == ui->ellipsoidRadius3) { ell->Radius3.setValue(ui->ellipsoidRadius3->value().getValue()); } else if (widget == ui->ellipsoidAngle1) { ell->Angle1.setValue(ui->ellipsoidAngle1->value().getValue()); } else if (widget == ui->ellipsoidAngle2) { ell->Angle2.setValue(ui->ellipsoidAngle2->value().getValue()); } else if (widget == ui->ellipsoidAngle3) { ell->Angle3.setValue(ui->ellipsoidAngle3->value().getValue()); } ell->recomputeFeature(); } // ---------------------------------------------------------------------------- TorusPrimitive::TorusPrimitive(std::shared_ptr ui, Part::Torus* feature) : AbstractPrimitive(feature) , ui(ui) { ui->torusRadius1->setRange(0, std::numeric_limits::max()); ui->torusRadius2->setRange(0, std::numeric_limits::max()); ui->torusAngle1->setRange(-180, 180); ui->torusAngle2->setRange(-180, 180); ui->torusAngle3->setRange(0, 360); if (feature) { ui->torusRadius1->setValue(feature->Radius1.getQuantityValue()); ui->torusRadius1->bind(feature->Radius1); ui->torusRadius2->setValue(feature->Radius2.getQuantityValue()); ui->torusRadius2->bind(feature->Radius2); ui->torusAngle1->setValue(feature->Angle1.getQuantityValue()); ui->torusAngle1->bind(feature->Angle1); ui->torusAngle2->setValue(feature->Angle2.getQuantityValue()); ui->torusAngle2->bind(feature->Angle2); ui->torusAngle3->setValue(feature->Angle3.getQuantityValue()); ui->torusAngle3->bind(feature->Angle3); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->torusRadius1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->torusRadius2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->torusAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->torusAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->torusAngle3, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* TorusPrimitive::getDefaultName() const { return "Torus"; } QString TorusPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Torus\",\"%1\")\n" "App.ActiveDocument.%1.Radius1='%2'\n" "App.ActiveDocument.%1.Radius2='%3'\n" "App.ActiveDocument.%1.Angle1='%4'\n" "App.ActiveDocument.%1.Angle2='%5'\n" "App.ActiveDocument.%1.Angle3='%6'\n" "App.ActiveDocument.%1.Placement=%7\n" "App.ActiveDocument.%1.Label='%8'\n" ) .arg( objectName, safeQuantityQString(ui->torusRadius1), safeQuantityQString(ui->torusRadius2), safeQuantityQString(ui->torusAngle1), safeQuantityQString(ui->torusAngle2), safeQuantityQString(ui->torusAngle3), placement, DlgPrimitives::tr("Torus") ); } QString TorusPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Radius1='%2'\n" "%1.Radius2='%3'\n" "%1.Angle1='%4'\n" "%1.Angle2='%5'\n" "%1.Angle3='%6'\n" "%1.Placement=%7\n" ) .arg( objectName, safeQuantityQString(ui->torusRadius1), safeQuantityQString(ui->torusRadius2), safeQuantityQString(ui->torusAngle1), safeQuantityQString(ui->torusAngle2), safeQuantityQString(ui->torusAngle3), placement ); } void TorusPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Torus* torus = featurePtr.get(); if (widget == ui->torusRadius1) { torus->Radius1.setValue(ui->torusRadius1->value().getValue()); } else if (widget == ui->torusRadius2) { torus->Radius2.setValue(ui->torusRadius2->value().getValue()); } else if (widget == ui->torusAngle1) { torus->Angle1.setValue(ui->torusAngle1->value().getValue()); } else if (widget == ui->torusAngle2) { torus->Angle2.setValue(ui->torusAngle2->value().getValue()); } else if (widget == ui->torusAngle3) { torus->Angle3.setValue(ui->torusAngle3->value().getValue()); } torus->recomputeFeature(); } // ---------------------------------------------------------------------------- PrismPrimitive::PrismPrimitive(std::shared_ptr ui, Part::Prism* feature) : AbstractPrimitive(feature) , ui(ui) { ui->prismCircumradius->setRange(0, std::numeric_limits::max()); ui->prismHeight->setRange(0, std::numeric_limits::max()); if (feature) { ui->prismPolygon->setValue(feature->Polygon.getValue()); ui->prismCircumradius->setValue(feature->Circumradius.getQuantityValue()); ui->prismCircumradius->bind(feature->Circumradius); ui->prismHeight->setValue(feature->Height.getQuantityValue()); ui->prismHeight->bind(feature->Height); ui->prismXSkew->setValue(feature->FirstAngle.getQuantityValue()); ui->prismXSkew->bind(feature->FirstAngle); ui->prismYSkew->setValue(feature->SecondAngle.getQuantityValue()); ui->prismYSkew->bind(feature->SecondAngle); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper(ui->prismPolygon, qOverload(&QSpinBox::valueChanged), mapper); connectMapSignalMapper( ui->prismCircumradius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->prismHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->prismXSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->prismYSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* PrismPrimitive::getDefaultName() const { return "Prism"; } QString PrismPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Prism\",\"%1\")\n" "App.ActiveDocument.%1.Polygon=%2\n" "App.ActiveDocument.%1.Circumradius='%3'\n" "App.ActiveDocument.%1.Height='%4'\n" "App.ActiveDocument.%1.FirstAngle='%5'\n" "App.ActiveDocument.%1.SecondAngle='%6'\n" "App.ActiveDocument.%1.Placement=%7\n" "App.ActiveDocument.%1.Label='%8'\n" ) .arg( objectName, QString::number(ui->prismPolygon->value()), safeQuantityQString(ui->prismCircumradius), safeQuantityQString(ui->prismHeight), safeQuantityQString(ui->prismXSkew), safeQuantityQString(ui->prismYSkew), placement, DlgPrimitives::tr("Prism") ); } QString PrismPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Polygon=%2\n" "%1.Circumradius='%3'\n" "%1.Height='%4'\n" "%1.FirstAngle='%5'\n" "%1.SecondAngle='%6'\n" "%1.Placement=%7\n" ) .arg( objectName, QString::number(ui->prismPolygon->value()), safeQuantityQString(ui->prismCircumradius), safeQuantityQString(ui->prismHeight), safeQuantityQString(ui->prismXSkew), safeQuantityQString(ui->prismYSkew), placement ); } void PrismPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Prism* prism = featurePtr.get(); if (widget == ui->prismPolygon) { prism->Polygon.setValue(ui->prismPolygon->value()); } else if (widget == ui->prismCircumradius) { prism->Circumradius.setValue(ui->prismCircumradius->value().getValue()); } else if (widget == ui->prismHeight) { prism->Height.setValue(ui->prismHeight->value().getValue()); } else if (widget == ui->prismXSkew) { prism->FirstAngle.setValue(ui->prismXSkew->value().getValue()); } else if (widget == ui->prismYSkew) { prism->SecondAngle.setValue(ui->prismYSkew->value().getValue()); } prism->recomputeFeature(); } // ---------------------------------------------------------------------------- WedgePrimitive::WedgePrimitive(std::shared_ptr ui, Part::Wedge* feature) : AbstractPrimitive(feature) , ui(ui) { constexpr int min = std::numeric_limits::min(); constexpr int max = std::numeric_limits::max(); ui->wedgeXmin->setMinimum(min); ui->wedgeXmin->setMaximum(max); ui->wedgeYmin->setMinimum(min); ui->wedgeYmin->setMaximum(max); ui->wedgeZmin->setMinimum(min); ui->wedgeZmin->setMaximum(max); ui->wedgeX2min->setMinimum(min); ui->wedgeX2min->setMaximum(max); ui->wedgeZ2min->setMinimum(min); ui->wedgeZ2min->setMaximum(max); ui->wedgeXmax->setMinimum(min); ui->wedgeXmax->setMaximum(max); ui->wedgeYmax->setMinimum(min); ui->wedgeYmax->setMaximum(max); ui->wedgeZmax->setMinimum(min); ui->wedgeZmax->setMaximum(max); ui->wedgeX2max->setMinimum(min); ui->wedgeX2max->setMaximum(max); ui->wedgeZ2max->setMinimum(min); ui->wedgeZ2max->setMaximum(max); if (feature) { ui->wedgeXmin->setValue(feature->Xmin.getQuantityValue()); ui->wedgeXmin->bind(feature->Xmin); ui->wedgeYmin->setValue(feature->Ymin.getQuantityValue()); ui->wedgeYmin->bind(feature->Ymin); ui->wedgeZmin->setValue(feature->Zmin.getQuantityValue()); ui->wedgeZmin->bind(feature->Zmin); ui->wedgeX2min->setValue(feature->X2min.getQuantityValue()); ui->wedgeX2min->bind(feature->X2min); ui->wedgeZ2min->setValue(feature->Z2min.getQuantityValue()); ui->wedgeZ2min->bind(feature->Z2min); ui->wedgeXmax->setValue(feature->Xmax.getQuantityValue()); ui->wedgeXmax->bind(feature->Xmax); ui->wedgeYmax->setValue(feature->Ymax.getQuantityValue()); ui->wedgeYmax->bind(feature->Ymax); ui->wedgeZmax->setValue(feature->Zmax.getQuantityValue()); ui->wedgeZmax->bind(feature->Zmax); ui->wedgeX2max->setValue(feature->X2max.getQuantityValue()); ui->wedgeX2max->bind(feature->X2max); ui->wedgeZ2max->setValue(feature->Z2max.getQuantityValue()); ui->wedgeZ2max->bind(feature->Z2max); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->wedgeXmin, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeYmin, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeZmin, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeX2min, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeZ2min, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeXmax, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeYmax, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeZmax, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeX2max, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->wedgeZ2max, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* WedgePrimitive::getDefaultName() const { return "Wedge"; } QString WedgePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Wedge\",\"%1\")\n" "App.ActiveDocument.%1.Xmin='%2'\n" "App.ActiveDocument.%1.Ymin='%3'\n" "App.ActiveDocument.%1.Zmin='%4'\n" "App.ActiveDocument.%1.X2min='%5'\n" "App.ActiveDocument.%1.Z2min='%6'\n" "App.ActiveDocument.%1.Xmax='%7'\n" "App.ActiveDocument.%1.Ymax='%8'\n" "App.ActiveDocument.%1.Zmax='%9'\n" "App.ActiveDocument.%1.X2max='%10'\n" "App.ActiveDocument.%1.Z2max='%11'\n" "App.ActiveDocument.%1.Placement=%12\n" "App.ActiveDocument.%1.Label='%13'\n" ) .arg( objectName, safeQuantityQString(ui->wedgeXmin), safeQuantityQString(ui->wedgeYmin), safeQuantityQString(ui->wedgeZmin), safeQuantityQString(ui->wedgeX2min), safeQuantityQString(ui->wedgeZ2min), safeQuantityQString(ui->wedgeXmax), safeQuantityQString(ui->wedgeYmax) ) .arg( safeQuantityQString(ui->wedgeZmax), safeQuantityQString(ui->wedgeX2max), safeQuantityQString(ui->wedgeZ2max), placement, DlgPrimitives::tr("Wedge") ); } QString WedgePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Xmin='%2'\n" "%1.Ymin='%3'\n" "%1.Zmin='%4'\n" "%1.X2min='%5'\n" "%1.Z2min='%6'\n" "%1.Xmax='%7'\n" "%1.Ymax='%8'\n" "%1.Zmax='%9'\n" "%1.X2max='%10'\n" "%1.Z2max='%11'\n" "%1.Placement=%12\n" ) .arg( objectName, safeQuantityQString(ui->wedgeXmin), safeQuantityQString(ui->wedgeYmin), safeQuantityQString(ui->wedgeZmin), safeQuantityQString(ui->wedgeX2min), safeQuantityQString(ui->wedgeZ2min), safeQuantityQString(ui->wedgeXmax), safeQuantityQString(ui->wedgeYmax), safeQuantityQString(ui->wedgeZmax) ) .arg(safeQuantityQString(ui->wedgeX2max), safeQuantityQString(ui->wedgeZ2max), placement); } void WedgePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Wedge* wedge = featurePtr.get(); if (widget == ui->wedgeXmin) { wedge->Xmin.setValue(ui->wedgeXmin->value().getValue()); } else if (widget == ui->wedgeYmin) { wedge->Ymin.setValue(ui->wedgeYmin->value().getValue()); } else if (widget == ui->wedgeZmin) { wedge->Zmin.setValue(ui->wedgeZmin->value().getValue()); } else if (widget == ui->wedgeX2min) { wedge->X2min.setValue(ui->wedgeX2min->value().getValue()); } else if (widget == ui->wedgeZ2min) { wedge->Z2min.setValue(ui->wedgeZ2min->value().getValue()); } else if (widget == ui->wedgeXmax) { wedge->Xmax.setValue(ui->wedgeXmax->value().getValue()); } else if (widget == ui->wedgeYmax) { wedge->Ymax.setValue(ui->wedgeYmax->value().getValue()); } else if (widget == ui->wedgeZmax) { wedge->Zmax.setValue(ui->wedgeZmax->value().getValue()); } else if (widget == ui->wedgeX2max) { wedge->X2max.setValue(ui->wedgeX2max->value().getValue()); } else if (widget == ui->wedgeZ2max) { wedge->Z2max.setValue(ui->wedgeZ2max->value().getValue()); } wedge->recomputeFeature(); } // ---------------------------------------------------------------------------- HelixPrimitive::HelixPrimitive(std::shared_ptr ui, Part::Helix* feature) : AbstractPrimitive(feature) , ui(ui) { ui->helixPitch->setRange(0, std::numeric_limits::max()); ui->helixHeight->setRange(0, std::numeric_limits::max()); ui->helixRadius->setRange(0, std::numeric_limits::max()); ui->helixAngle->setRange(-89.9, 89.9); if (feature) { ui->helixPitch->setValue(feature->Pitch.getQuantityValue()); ui->helixPitch->bind(feature->Pitch); ui->helixHeight->setValue(feature->Height.getQuantityValue()); ui->helixHeight->bind(feature->Height); ui->helixRadius->setValue(feature->Radius.getQuantityValue()); ui->helixRadius->bind(feature->Radius); ui->helixAngle->setValue(feature->Angle.getQuantityValue()); ui->helixAngle->bind(feature->Angle); ui->helixLocalCS->setCurrentIndex(feature->LocalCoord.getValue()); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->helixPitch, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->helixHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->helixRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->helixAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper(ui->helixLocalCS, qOverload(&QComboBox::currentIndexChanged), mapper); } } const char* HelixPrimitive::getDefaultName() const { return "Helix"; } QString HelixPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Helix\",\"%1\")\n" "App.ActiveDocument.%1.Pitch='%2'\n" "App.ActiveDocument.%1.Height='%3'\n" "App.ActiveDocument.%1.Radius='%4'\n" "App.ActiveDocument.%1.Angle='%5'\n" "App.ActiveDocument.%1.LocalCoord=%6\n" "App.ActiveDocument.%1.Style=1\n" "App.ActiveDocument.%1.Placement=%7\n" "App.ActiveDocument.%1.Label='%8'\n" ) .arg( objectName, safeQuantityQString(ui->helixPitch), safeQuantityQString(ui->helixHeight), safeQuantityQString(ui->helixRadius), safeQuantityQString(ui->helixAngle), QString::number(ui->helixLocalCS->currentIndex()), placement, DlgPrimitives::tr("Helix") ); } QString HelixPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Pitch='%2'\n" "%1.Height='%3'\n" "%1.Radius='%4'\n" "%1.Angle='%5'\n" "%1.LocalCoord=%6\n" "%1.Placement=%7\n" ) .arg( objectName, safeQuantityQString(ui->helixPitch), safeQuantityQString(ui->helixHeight), safeQuantityQString(ui->helixRadius), safeQuantityQString(ui->helixAngle), QString::number(ui->helixLocalCS->currentIndex()), placement ); } void HelixPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Helix* helix = featurePtr.get(); if (widget == ui->helixPitch) { helix->Pitch.setValue(ui->helixPitch->value().getValue()); } else if (widget == ui->helixHeight) { helix->Height.setValue(ui->helixHeight->value().getValue()); } else if (widget == ui->helixRadius) { helix->Radius.setValue(ui->helixRadius->value().getValue()); } else if (widget == ui->helixAngle) { helix->Angle.setValue(ui->helixAngle->value().getValue()); } else if (widget == ui->helixLocalCS) { helix->LocalCoord.setValue(ui->helixLocalCS->currentIndex()); } helix->recomputeFeature(); } // ---------------------------------------------------------------------------- SpiralPrimitive::SpiralPrimitive(std::shared_ptr ui, Part::Spiral* feature) : AbstractPrimitive(feature) , ui(ui) { ui->spiralGrowth->setRange(0, std::numeric_limits::max()); ui->spiralRotation->setRange(0, std::numeric_limits::max()); ui->spiralRadius->setRange(0, std::numeric_limits::max()); if (feature) { ui->spiralGrowth->setValue(feature->Growth.getQuantityValue()); ui->spiralGrowth->bind(feature->Growth); ui->spiralRotation->setValue(feature->Rotations.getQuantityValue().getValue()); ui->spiralRadius->setValue(feature->Radius.getQuantityValue()); ui->spiralRadius->bind(feature->Radius); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->spiralGrowth, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->spiralRotation, qOverload(&QDoubleSpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->spiralRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* SpiralPrimitive::getDefaultName() const { return "Spiral"; } QString SpiralPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Spiral\",\"%1\")\n" "App.ActiveDocument.%1.Growth='%2'\n" "App.ActiveDocument.%1.Rotations=%3\n" "App.ActiveDocument.%1.Radius='%4'\n" "App.ActiveDocument.%1.Placement=%5\n" "App.ActiveDocument.%1.Label='%6'\n" ) .arg( objectName, safeQuantityQString(ui->spiralGrowth), QString::number(ui->spiralRotation->value()), safeQuantityQString(ui->spiralRadius), placement, DlgPrimitives::tr("Spiral") ); } QString SpiralPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Growth='%2'\n" "%1.Rotations=%3\n" "%1.Radius='%4'\n" "%1.Placement=%5\n" ) .arg( objectName, safeQuantityQString(ui->spiralGrowth), QString::number(ui->spiralRotation->value()), safeQuantityQString(ui->spiralRadius), placement ); } void SpiralPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Spiral* spiral = featurePtr.get(); if (widget == ui->spiralGrowth) { spiral->Growth.setValue(ui->spiralGrowth->value().getValue()); } else if (widget == ui->spiralRotation) { spiral->Rotations.setValue(ui->spiralRotation->value()); } else if (widget == ui->spiralRadius) { spiral->Radius.setValue(ui->spiralRadius->value().getValue()); } spiral->recomputeFeature(); } // ---------------------------------------------------------------------------- CirclePrimitive::CirclePrimitive(std::shared_ptr ui, Part::Circle* feature) : AbstractPrimitive(feature) , ui(ui) { ui->circleRadius->setRange(0, std::numeric_limits::max()); ui->circleAngle1->setRange(0, 360); ui->circleAngle2->setRange(0, 360); if (feature) { ui->circleRadius->setValue(feature->Radius.getQuantityValue()); ui->circleRadius->bind(feature->Radius); ui->circleAngle1->setValue(feature->Angle1.getQuantityValue()); ui->circleAngle1->bind(feature->Angle1); ui->circleAngle2->setValue(feature->Angle2.getQuantityValue()); ui->circleAngle2->bind(feature->Angle2); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->circleRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->circleAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->circleAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* CirclePrimitive::getDefaultName() const { return "Circle"; } QString CirclePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Circle\",\"%1\")\n" "App.ActiveDocument.%1.Radius='%2'\n" "App.ActiveDocument.%1.Angle1='%3'\n" "App.ActiveDocument.%1.Angle2='%4'\n" "App.ActiveDocument.%1.Placement=%5\n" "App.ActiveDocument.%1.Label='%6'\n" ) .arg( objectName, safeQuantityQString(ui->circleRadius), safeQuantityQString(ui->circleAngle1), safeQuantityQString(ui->circleAngle2), placement, DlgPrimitives::tr("Circle") ); } QString CirclePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Radius='%2'\n" "%1.Angle1='%3'\n" "%1.Angle2='%4'\n" "%1.Placement=%5\n" ) .arg( objectName, safeQuantityQString(ui->circleRadius), safeQuantityQString(ui->circleAngle1), safeQuantityQString(ui->circleAngle2), placement ); } void CirclePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Circle* circle = featurePtr.get(); if (widget == ui->circleRadius) { circle->Radius.setValue(ui->circleRadius->value().getValue()); } else if (widget == ui->circleAngle1) { circle->Angle1.setValue(ui->circleAngle1->value().getValue()); } else if (widget == ui->circleAngle2) { circle->Angle2.setValue(ui->circleAngle2->value().getValue()); } circle->recomputeFeature(); } // ---------------------------------------------------------------------------- EllipsePrimitive::EllipsePrimitive(std::shared_ptr ui, Part::Ellipse* feature) : AbstractPrimitive(feature) , ui(ui) { ui->ellipseMajorRadius->setRange(0, std::numeric_limits::max()); ui->ellipseMinorRadius->setRange(0, std::numeric_limits::max()); ui->ellipseAngle1->setRange(0, 360); ui->ellipseAngle2->setRange(0, 360); if (feature) { ui->ellipseMajorRadius->setValue(feature->MajorRadius.getQuantityValue()); ui->ellipseMajorRadius->bind(feature->MajorRadius); ui->ellipseMinorRadius->setValue(feature->MinorRadius.getQuantityValue()); ui->ellipseMinorRadius->bind(feature->MinorRadius); ui->ellipseAngle1->setValue(feature->Angle1.getQuantityValue()); ui->ellipseAngle1->bind(feature->Angle1); ui->ellipseAngle2->setValue(feature->Angle2.getQuantityValue()); ui->ellipseAngle2->bind(feature->Angle2); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->ellipseMajorRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipseMinorRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipseAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->ellipseAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* EllipsePrimitive::getDefaultName() const { return "Ellipse"; } QString EllipsePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Ellipse\",\"%1\")\n" "App.ActiveDocument.%1.MajorRadius='%2'\n" "App.ActiveDocument.%1.MinorRadius='%3'\n" "App.ActiveDocument.%1.Angle1='%4'\n" "App.ActiveDocument.%1.Angle2='%5'\n" "App.ActiveDocument.%1.Placement=%6\n" "App.ActiveDocument.%1.Label='%7'\n" ) .arg( objectName, safeQuantityQString(ui->ellipseMajorRadius), safeQuantityQString(ui->ellipseMinorRadius), safeQuantityQString(ui->ellipseAngle1), safeQuantityQString(ui->ellipseAngle2), placement, DlgPrimitives::tr("Ellipse") ); } QString EllipsePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.MajorRadius='%2'\n" "%1.MinorRadius='%3'\n" "%1.Angle1='%4'\n" "%1.Angle2='%5'\n" "%1.Placement=%6\n" ) .arg( objectName, safeQuantityQString(ui->ellipseMajorRadius), safeQuantityQString(ui->ellipseMinorRadius), safeQuantityQString(ui->ellipseAngle1), safeQuantityQString(ui->ellipseAngle2), placement ); } void EllipsePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Ellipse* ell = featurePtr.get(); if (widget == ui->ellipseMajorRadius) { ell->MajorRadius.setValue(ui->ellipseMajorRadius->value().getValue()); } else if (widget == ui->ellipseMinorRadius) { ell->MinorRadius.setValue(ui->ellipseMinorRadius->value().getValue()); } else if (widget == ui->ellipseAngle1) { ell->Angle1.setValue(ui->ellipseAngle1->value().getValue()); } else if (widget == ui->ellipseAngle2) { ell->Angle2.setValue(ui->ellipseAngle2->value().getValue()); } ell->recomputeFeature(); } // ---------------------------------------------------------------------------- PolygonPrimitive::PolygonPrimitive(std::shared_ptr ui, Part::RegularPolygon* feature) : AbstractPrimitive(feature) , ui(ui) { ui->regularPolygonCircumradius->setRange(0, std::numeric_limits::max()); if (feature) { ui->regularPolygonPolygon->setValue(feature->Polygon.getValue()); ui->regularPolygonCircumradius->setValue(feature->Circumradius.getQuantityValue()); ui->regularPolygonCircumradius->bind(feature->Circumradius); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper(ui->regularPolygonPolygon, qOverload(&QSpinBox::valueChanged), mapper); connectMapSignalMapper( ui->regularPolygonCircumradius, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* PolygonPrimitive::getDefaultName() const { return "RegularPolygon"; } QString PolygonPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::RegularPolygon\",\"%1\")\n" "App.ActiveDocument.%1.Polygon=%2\n" "App.ActiveDocument.%1.Circumradius='%3'\n" "App.ActiveDocument.%1.Placement=%4\n" "App.ActiveDocument.%1.Label='%5'\n" ) .arg( objectName, QString::number(ui->regularPolygonPolygon->value()), safeQuantityQString(ui->regularPolygonCircumradius), placement, DlgPrimitives::tr("Regular polygon") ); } QString PolygonPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.Polygon=%2\n" "%1.Circumradius='%3'\n" "%1.Placement=%4\n" ) .arg( objectName, QString::number(ui->regularPolygonPolygon->value()), safeQuantityQString(ui->regularPolygonCircumradius), placement ); } void PolygonPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::RegularPolygon* poly = featurePtr.get(); if (widget == ui->regularPolygonPolygon) { poly->Polygon.setValue(ui->regularPolygonPolygon->value()); } else if (widget == ui->regularPolygonCircumradius) { poly->Circumradius.setValue(ui->regularPolygonCircumradius->value().getValue()); } poly->recomputeFeature(); } // ---------------------------------------------------------------------------- LinePrimitive::LinePrimitive(std::shared_ptr ui, Part::Line* feature) : AbstractPrimitive(feature) , ui(ui) { constexpr int min = std::numeric_limits::min(); constexpr int max = std::numeric_limits::max(); ui->edgeX1->setMaximum(max); ui->edgeX1->setMinimum(min); ui->edgeY1->setMaximum(max); ui->edgeY1->setMinimum(min); ui->edgeZ1->setMaximum(max); ui->edgeZ1->setMinimum(min); ui->edgeX2->setMaximum(max); ui->edgeX2->setMinimum(min); ui->edgeY2->setMaximum(max); ui->edgeY2->setMinimum(min); ui->edgeZ2->setMaximum(max); ui->edgeZ2->setMinimum(min); if (feature) { ui->edgeX1->setValue(feature->X1.getQuantityValue()); ui->edgeX1->bind(feature->X1); ui->edgeY1->setValue(feature->Y1.getQuantityValue()); ui->edgeY1->bind(feature->Y1); ui->edgeZ1->setValue(feature->Z1.getQuantityValue()); ui->edgeZ1->bind(feature->Z1); ui->edgeX2->setValue(feature->X2.getQuantityValue()); ui->edgeX2->bind(feature->X2); ui->edgeY2->setValue(feature->Y2.getQuantityValue()); ui->edgeY2->bind(feature->Y2); ui->edgeZ2->setValue(feature->Z2.getQuantityValue()); ui->edgeZ2->bind(feature->Z2); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper(ui->edgeX1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper); connectMapSignalMapper(ui->edgeY1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper); connectMapSignalMapper(ui->edgeZ1, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper); connectMapSignalMapper(ui->edgeX2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper); connectMapSignalMapper(ui->edgeY2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper); connectMapSignalMapper(ui->edgeZ2, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper); } } const char* LinePrimitive::getDefaultName() const { return "Line"; } QString LinePrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Line\",\"%1\")\n" "App.ActiveDocument.%1.X1='%2'\n" "App.ActiveDocument.%1.Y1='%3'\n" "App.ActiveDocument.%1.Z1='%4'\n" "App.ActiveDocument.%1.X2='%5'\n" "App.ActiveDocument.%1.Y2='%6'\n" "App.ActiveDocument.%1.Z2='%7'\n" "App.ActiveDocument.%1.Placement=%8\n" "App.ActiveDocument.%1.Label='%9'\n" ) .arg( objectName, safeQuantityQString(ui->edgeX1), safeQuantityQString(ui->edgeY1), safeQuantityQString(ui->edgeZ1), safeQuantityQString(ui->edgeX2), safeQuantityQString(ui->edgeY2), safeQuantityQString(ui->edgeZ2), placement, DlgPrimitives::tr("Line") ); } QString LinePrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.X1='%2'\n" "%1.Y1='%3'\n" "%1.Z1='%4'\n" "%1.X2='%5'\n" "%1.Y2='%6'\n" "%1.Z2='%7'\n" "%1.Placement=%8\n" ) .arg( objectName, safeQuantityQString(ui->edgeX1), safeQuantityQString(ui->edgeY1), safeQuantityQString(ui->edgeZ1), safeQuantityQString(ui->edgeX2), safeQuantityQString(ui->edgeY2), safeQuantityQString(ui->edgeZ2), placement ); } void LinePrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Line* line = featurePtr.get(); if (widget == ui->edgeX1) { line->X1.setValue(ui->edgeX1->value().getValue()); } else if (widget == ui->edgeY1) { line->Y1.setValue(ui->edgeY1->value().getValue()); } else if (widget == ui->edgeZ1) { line->Z1.setValue(ui->edgeZ1->value().getValue()); } else if (widget == ui->edgeX2) { line->X2.setValue(ui->edgeX2->value().getValue()); } else if (widget == ui->edgeY2) { line->Y2.setValue(ui->edgeY2->value().getValue()); } else if (widget == ui->edgeZ2) { line->Z2.setValue(ui->edgeZ2->value().getValue()); } line->recomputeFeature(); } // ---------------------------------------------------------------------------- VertexPrimitive::VertexPrimitive(std::shared_ptr ui, Part::Vertex* feature) : AbstractPrimitive(feature) , ui(ui) { constexpr int min = std::numeric_limits::min(); constexpr int max = std::numeric_limits::max(); ui->vertexX->setMaximum(max); ui->vertexY->setMaximum(max); ui->vertexZ->setMaximum(max); ui->vertexX->setMinimum(min); ui->vertexY->setMinimum(min); ui->vertexZ->setMinimum(min); if (feature) { ui->vertexX->setValue(feature->X.getQuantityValue()); ui->vertexX->bind(feature->X); ui->vertexY->setValue(feature->Y.getQuantityValue()); ui->vertexY->bind(feature->Y); ui->vertexZ->setValue(feature->Z.getQuantityValue()); ui->vertexZ->bind(feature->Z); QSignalMapper* mapper = new QSignalMapper(this); connectSignalMapper(mapper); connectMapSignalMapper( ui->vertexX, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->vertexY, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); connectMapSignalMapper( ui->vertexZ, qOverload(&Gui::QuantitySpinBox::valueChanged), mapper ); } } const char* VertexPrimitive::getDefaultName() const { return "Vertex"; } QString VertexPrimitive::create(const QString& objectName, const QString& placement) const { return QStringLiteral( "App.ActiveDocument.addObject(\"Part::Vertex\",\"%1\")\n" "App.ActiveDocument.%1.X='%2'\n" "App.ActiveDocument.%1.Y='%3'\n" "App.ActiveDocument.%1.Z='%4'\n" "App.ActiveDocument.%1.Placement=%5\n" "App.ActiveDocument.%1.Label='%6'\n" ) .arg( objectName, safeQuantityQString(ui->vertexX), safeQuantityQString(ui->vertexY), safeQuantityQString(ui->vertexZ), placement, DlgPrimitives::tr("Vertex") ); } QString VertexPrimitive::change(const QString& objectName, const QString& placement) const { return QStringLiteral( "%1.X='%2'\n" "%1.Y='%3'\n" "%1.Z='%4'\n" "%1.Placement=%5\n" ) .arg( objectName, safeQuantityQString(ui->vertexX), safeQuantityQString(ui->vertexY), safeQuantityQString(ui->vertexZ), placement ); } void VertexPrimitive::changeValue(QObject* widget) { if (featurePtr.expired()) { return; } Part::Vertex* v = featurePtr.get(); if (widget == ui->vertexX) { v->X.setValue(ui->vertexX->value().getValue()); } else if (widget == ui->vertexY) { v->Y.setValue(ui->vertexY->value().getValue()); } else if (widget == ui->vertexZ) { v->Z.setValue(ui->vertexZ->value().getValue()); } v->recomputeFeature(); } // ---------------------------------------------------------------------------- /* TRANSLATOR PartGui::DlgPrimitives */ DlgPrimitives::DlgPrimitives(QWidget* parent, Part::Primitive* feature) : QWidget(parent) , ui(new Ui_DlgPrimitives) , featurePtr(feature) { ui->setupUi(this); connect( ui->buttonCircleFromThreePoints, &QPushButton::clicked, this, &DlgPrimitives::buttonCircleFromThreePoints ); Gui::Command::doCommand(Gui::Command::Doc, "from FreeCAD import Base"); Gui::Command::doCommand(Gui::Command::Doc, "import Part,PartGui"); // must be in the same order as of the stacked widget addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); addPrimitive(std::make_shared(ui, dynamic_cast(feature))); if (feature) { activatePage(); } } /* * Destroys the object and frees any allocated resources */ DlgPrimitives::~DlgPrimitives() = default; void DlgPrimitives::activatePage() { int index = findIndexOfValidPrimitive(); ui->PrimitiveTypeCB->setCurrentIndex(index); ui->widgetStack2->setCurrentIndex(index); ui->PrimitiveTypeCB->setDisabled(true); } void DlgPrimitives::addPrimitive(std::shared_ptr prim) { primitive.push_back(prim); } std::shared_ptr DlgPrimitives::getPrimitive(int index) const { return primitive.at(index); } int DlgPrimitives::findIndexOfValidPrimitive() const { return std::distance( primitive.begin(), std::find_if(primitive.begin(), primitive.end(), [](std::shared_ptr prim) { return prim->hasValidPrimitive(); }) ); } void DlgPrimitives::pickCallback(void* ud, SoEventCallback* n) { const SoMouseButtonEvent* mbe = static_cast(n->getEvent()); Picker* pick = static_cast(ud); if (pick->exitCode >= 0) { pick->loop.exit(pick->exitCode); } // Mark all incoming mouse button events as handled, especially, to deactivate the selection node n->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON1) { if (mbe->getState() == SoButtonEvent::DOWN) { const SoPickedPoint* point = n->getPickedPoint(); if (point) { if (pick->pickedPoint(point)) { pick->exitCode = 0; } } } } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2) { if (mbe->getState() == SoButtonEvent::UP) { pick->loop.exit(1); } } } void DlgPrimitives::executeCallback(Picker* p) { Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (!doc) { return; } Gui::View3DInventor* view = static_cast(doc->getActiveView()); if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); if (!viewer->isEditing()) { viewer->setEditing(true); viewer->setRedirectToSceneGraph(true); SoNode* root = viewer->getSceneGraph(); int mode = 0; if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) { mode = static_cast(root)->selectionMode.getValue(); static_cast(root)->selectionMode.setValue( Gui::SoFCUnifiedSelection::OFF ); } viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, p); this->setDisabled(true); int ret = p->loop.exec(); if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) { static_cast(root)->selectionMode.setValue(mode); } this->setEnabled(true); viewer->setEditing(false); viewer->setRedirectToSceneGraph(false); viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, p); if (ret == 0) { p->createPrimitive(this, ui->PrimitiveTypeCB->currentText(), doc); } } } } void DlgPrimitives::buttonCircleFromThreePoints() { CircleFromThreePoints pp; executeCallback(&pp); } void DlgPrimitives::tryCreatePrimitive(const QString& placement) { QString cmd; QString name; App::Document* doc = App::GetApplication().getActiveDocument(); if (!doc) { QMessageBox::warning( this, tr("Create %1").arg(ui->PrimitiveTypeCB->currentText()), tr("No active document") ); return; } std::shared_ptr primitive = getPrimitive(ui->PrimitiveTypeCB->currentIndex()); name = QString::fromUtf8(doc->getUniqueObjectName(primitive->getDefaultName()).c_str()); cmd = primitive->create(name, placement); // Execute the Python block QString prim = tr("Create %1").arg(ui->PrimitiveTypeCB->currentText()); Gui::Application::Instance->activeDocument()->openCommand(prim.toUtf8()); Gui::Command::runCommand(Gui::Command::Doc, cmd.toUtf8()); Gui::Command::runCommand(Gui::Command::Doc, getAutoGroupCommandStr(name).toUtf8()); Gui::Application::Instance->activeDocument()->commitCommand(); Gui::Command::runCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); Gui::Command::runCommand(Gui::Command::Gui, "Gui.SendMsgToActiveView(\"ViewFit\")"); } void DlgPrimitives::createPrimitive(const QString& placement) { try { tryCreatePrimitive(placement); } catch (const std::exception& e) { QMessageBox::warning( this, tr("Create %1").arg(ui->PrimitiveTypeCB->currentText()), QCoreApplication::translate("Exception", e.what()) ); } catch (const Base::PyException& e) { QMessageBox::warning( this, tr("Create %1").arg(ui->PrimitiveTypeCB->currentText()), QCoreApplication::translate("Exception", e.what()) ); } } void DlgPrimitives::acceptChanges(const QString& placement) { App::Document* doc = featurePtr->getDocument(); QString objectName = QStringLiteral("App.getDocument(\"%1\").%2") .arg( QString::fromUtf8(doc->getName()), QString::fromUtf8(featurePtr->getNameInDocument()) ); // read values from the properties std::shared_ptr primitive = getPrimitive(ui->PrimitiveTypeCB->currentIndex()); QString command = primitive->change(objectName, placement); // execute command, a transaction is already opened Gui::Command::runCommand(Gui::Command::App, command.toUtf8()); } void DlgPrimitives::accept(const QString& placement) { if (featurePtr.expired()) { return; } App::Document* doc = featurePtr->getDocument(); acceptChanges(placement); doc->recompute(); // commit undo command doc->commitTransaction(); } void DlgPrimitives::reject() { if (featurePtr.expired()) { return; } App::Document* doc = featurePtr->getDocument(); doc->abortTransaction(); } // ---------------------------------------------- /* TRANSLATOR PartGui::Location */ Location::Location(QWidget* parent, Part::Feature* feature) : QWidget(parent) , ui(new Ui_Location) , featurePtr(feature) { mode = 0; ui->setupUi(this); connect(ui->viewPositionButton, &QPushButton::clicked, this, &Location::onViewPositionButton); ui->XPositionQSB->setUnit(Base::Unit::Length); ui->YPositionQSB->setUnit(Base::Unit::Length); ui->ZPositionQSB->setUnit(Base::Unit::Length); ui->AngleQSB->setUnit(Base::Unit::Angle); // fill location widget if object already exists if (feature) { setPlacement(feature); bindExpressions(feature); connectSignals(); } } Location::~Location() { // no need to delete child widgets, Qt does it all for us if (!this->activeView.isNull()) { Gui::View3DInventorViewer* viewer = static_cast(this->activeView.data())->getViewer(); viewer->setEditing(false); viewer->setRedirectToSceneGraph(false); viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, this); SoNode* root = viewer->getSceneGraph(); if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) { static_cast(root)->selectionMode.setValue(this->mode); } } } void Location::setPlacement(Part::Feature* feature) { // get the placement values auto placement = feature->Placement.getValue(); auto position = placement.getPosition(); ui->XPositionQSB->setValue(position.x); ui->YPositionQSB->setValue(position.y); ui->ZPositionQSB->setValue(position.z); double rotationAngle; Base::Vector3d rotationAxes; auto rotation = placement.getRotation(); rotation.getRawValue(rotationAxes, rotationAngle); ui->XDirectionEdit->setValue(rotationAxes.x); ui->YDirectionEdit->setValue(rotationAxes.y); ui->ZDirectionEdit->setValue(rotationAxes.z); // the angle is rad, transform it for display to degrees ui->AngleQSB->setValue(Base::toDegrees(rotationAngle)); } void Location::bindExpressions(Part::Feature* feature) { ui->XPositionQSB->bind(App::ObjectIdentifier::parse(feature, std::string("Placement.Base.x"))); ui->YPositionQSB->bind(App::ObjectIdentifier::parse(feature, std::string("Placement.Base.y"))); ui->ZPositionQSB->bind(App::ObjectIdentifier::parse(feature, std::string("Placement.Base.z"))); ui->XDirectionEdit->bind( App::ObjectIdentifier::parse(feature, std::string("Placement.Rotation.Axis.x")) ); ui->YDirectionEdit->bind( App::ObjectIdentifier::parse(feature, std::string("Placement.Rotation.Axis.y")) ); ui->ZDirectionEdit->bind( App::ObjectIdentifier::parse(feature, std::string("Placement.Rotation.Axis.z")) ); ui->AngleQSB->bind(App::ObjectIdentifier::parse(feature, std::string("Placement.Rotation.Angle"))); } void Location::connectSignals() { connect( ui->XPositionQSB, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &Location::onPlacementChanged ); connect( ui->YPositionQSB, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &Location::onPlacementChanged ); connect( ui->ZPositionQSB, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &Location::onPlacementChanged ); connect( ui->AngleQSB, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &Location::onPlacementChanged ); connect( ui->XDirectionEdit, qOverload(&Gui::DoubleSpinBox::valueChanged), this, &Location::onPlacementChanged ); connect( ui->YDirectionEdit, qOverload(&Gui::DoubleSpinBox::valueChanged), this, &Location::onPlacementChanged ); connect( ui->ZDirectionEdit, qOverload(&Gui::DoubleSpinBox::valueChanged), this, &Location::onPlacementChanged ); } void Location::onPlacementChanged() { App::GeoFeature* geom = featurePtr.get(); if (!geom) { return; } // read dialog values Base::Vector3d loc; loc.x = ui->XPositionQSB->rawValue(); loc.y = ui->YPositionQSB->rawValue(); loc.z = ui->ZPositionQSB->rawValue(); double angle = ui->AngleQSB->rawValue(); // the angle is displayed in degrees, transform it to rad angle = Base::toRadians(angle); Base::Vector3d rot; rot.x = ui->XDirectionEdit->value(); rot.y = ui->YDirectionEdit->value(); rot.z = ui->ZDirectionEdit->value(); // set placement and rotation Base::Placement placement; Base::Rotation rotation(rot, angle); placement.setPosition(loc); placement.setRotation(rotation); // apply new placement to the feature geom->Placement.setValue(placement); geom->recomputeFeature(); } void Location::onViewPositionButton() { Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (!doc) { return; } Gui::View3DInventor* view = static_cast(doc->getActiveView()); if (view && !this->activeView) { Gui::View3DInventorViewer* viewer = view->getViewer(); if (!viewer->isEditing()) { this->activeView = view; viewer->setEditing(true); viewer->setRedirectToSceneGraph(true); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, this); SoNode* root = viewer->getSceneGraph(); if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) { this->mode = static_cast(root)->selectionMode.getValue(); static_cast(root)->selectionMode.setValue( Gui::SoFCUnifiedSelection::OFF ); } } } } void Location::pickCallback(void* ud, SoEventCallback* n) { const SoMouseButtonEvent* mbe = static_cast(n->getEvent()); Gui::View3DInventorViewer* view = static_cast(n->getUserData()); // Mark all incoming mouse button events as handled, especially, to deactivate the selection node n->getAction()->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON1) { if (mbe->getState() == SoButtonEvent::DOWN) { const SoPickedPoint* point = n->getPickedPoint(); if (point) { SbVec3f pnt = point->getPoint(); SbVec3f nor = point->getNormal(); Location* dlg = static_cast(ud); dlg->ui->XPositionQSB->setValue(pnt[0]); dlg->ui->YPositionQSB->setValue(pnt[1]); dlg->ui->ZPositionQSB->setValue(pnt[2]); dlg->ui->XDirectionEdit->setValue(nor[0]); dlg->ui->YDirectionEdit->setValue(nor[1]); dlg->ui->ZDirectionEdit->setValue(nor[2]); n->setHandled(); } } } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2) { if (mbe->getState() == SoButtonEvent::UP) { n->setHandled(); view->setEditing(false); view->setRedirectToSceneGraph(false); Location* dlg = static_cast(ud); dlg->activeView = nullptr; view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, ud); SoNode* root = view->getSceneGraph(); if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) { static_cast(root)->selectionMode.setValue( static_cast(ud)->mode ); } } } } QString Location::toPlacement() const { // create a command to set the position and angle of the primitive object Base::Vector3d rot; rot.x = ui->XDirectionEdit->value(); rot.y = ui->YDirectionEdit->value(); rot.z = ui->ZDirectionEdit->value(); double angle = ui->AngleQSB->rawValue(); Base::Vector3d loc; loc.x = ui->XPositionQSB->rawValue(); loc.y = ui->YPositionQSB->rawValue(); loc.z = ui->ZPositionQSB->rawValue(); return QStringLiteral("App.Placement(App.Vector(%1,%2,%3),App.Rotation(App.Vector(%4,%5,%6),%7))") .arg(loc.x, 0, 'f', Base::UnitsApi::getDecimals()) .arg(loc.y, 0, 'f', Base::UnitsApi::getDecimals()) .arg(loc.z, 0, 'f', Base::UnitsApi::getDecimals()) .arg(rot.x, 0, 'f', Base::UnitsApi::getDecimals()) .arg(rot.y, 0, 'f', Base::UnitsApi::getDecimals()) .arg(rot.z, 0, 'f', Base::UnitsApi::getDecimals()) .arg(angle, 0, 'f', Base::UnitsApi::getDecimals()); } // ---------------------------------------------- /* TRANSLATOR PartGui::TaskPrimitives */ TaskPrimitives::TaskPrimitives() { widget = new DlgPrimitives(); addTaskBox(widget); location = new Location(); addTaskBox(location); } QDialogButtonBox::StandardButtons TaskPrimitives::getStandardButtons() const { return QDialogButtonBox::Close | QDialogButtonBox::Ok; } void TaskPrimitives::modifyStandardButtons(QDialogButtonBox* box) { QPushButton* btn = box->button(QDialogButtonBox::Ok); btn->setText(QApplication::translate("PartGui::DlgPrimitives", "&Create")); } bool TaskPrimitives::accept() { widget->createPrimitive(location->toPlacement()); return false; } bool TaskPrimitives::reject() { return true; } // ---------------------------------------------- /* TRANSLATOR PartGui::TaskPrimitivesEdit */ TaskPrimitivesEdit::TaskPrimitivesEdit(Part::Primitive* feature) { // create and show dialog for the primitives widget = new DlgPrimitives(nullptr, feature); addTaskBox(widget); // create and show dialog for the location location = new Location(nullptr, feature); addTaskBox(location); } QDialogButtonBox::StandardButtons TaskPrimitivesEdit::getStandardButtons() const { return QDialogButtonBox::Cancel | QDialogButtonBox::Ok; } bool TaskPrimitivesEdit::accept() { widget->accept(location->toPlacement()); std::string document = getDocumentName(); // needed because resetEdit() deletes this instance Gui::Command::doCommand(Gui::Command::Gui, "Gui.getDocument('%s').resetEdit()", document.c_str()); return true; } bool TaskPrimitivesEdit::reject() { widget->reject(); std::string document = getDocumentName(); // needed because resetEdit() deletes this instance Gui::Command::doCommand(Gui::Command::Gui, "Gui.getDocument('%s').resetEdit()", document.c_str()); return true; } #include "moc_DlgPrimitives.cpp"