diff --git a/src/Mod/Part/Gui/DlgPrimitives.cpp b/src/Mod/Part/Gui/DlgPrimitives.cpp index 9a42a4ae9e..f8d7109002 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.cpp +++ b/src/Mod/Part/Gui/DlgPrimitives.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include "DlgPrimitives.h" @@ -56,6 +58,8 @@ using namespace PartGui; namespace PartGui { +const char* ObjectNameSave; + const char* gce_ErrorStatusText(gce_ErrorType et) { switch (et) @@ -180,13 +184,49 @@ private: /* TRANSLATOR PartGui::DlgPrimitives */ -DlgPrimitives::DlgPrimitives(QWidget* parent) +DlgPrimitives::DlgPrimitives(QWidget* parent, PrimitiveType type, bool edit, const char* ObjectName) : QWidget(parent) { ui.setupUi(this); Gui::Command::doCommand(Gui::Command::Doc, "from FreeCAD import Base"); Gui::Command::doCommand(Gui::Command::Doc, "import Part,PartGui"); + ui.comboBox1->setCurrentIndex(type); + ui.widgetStack2->setCurrentIndex(type); + + // fill the dialog with data if the primitives already exists + if (edit) { + // if existing, the primitive type can not be changed by the user + ui.comboBox1->setDisabled(edit); + // get the primitives object + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (!doc) + return; + auto docObj = doc->getDocument()->getObject(ObjectName); + + // read values from the properties + if (type == PrimitiveType::Helix) + { + auto Property = docObj->getPropertyByName("Pitch"); + auto value = static_cast(Property); + ui.helixPitch->setValue(value->getQuantityValue()); + Property = docObj->getPropertyByName("Height"); + value = static_cast(Property); + ui.helixHeight->setValue(value->getQuantityValue()); + Property = docObj->getPropertyByName("Radius"); + value = static_cast(Property); + ui.helixRadius->setValue(value->getQuantityValue()); + Property = docObj->getPropertyByName("Angle"); + value = static_cast(Property); + ui.helixAngle->setValue(value->getQuantityValue()); + Property = docObj->getPropertyByName("LocalCoord"); + auto HandedIndex = static_cast(Property); + ui.helixLocalCS->setCurrentIndex(HandedIndex->getValue()); + + // ToDo: connect signal if there is a preview of primitives available + } + } + // set limits // // plane @@ -682,15 +722,87 @@ void DlgPrimitives::createPrimitive(const QString& placement) } } +void DlgPrimitives::accept(const QString& placement) +{ + QString command; + + // get the current object + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (!doc) + return; + auto docObj = doc->getDocument()->getObject(ObjectNameSave); + auto ObjectName = docObj->getNameInDocument(); + + // the combox with the primitive type is fixed + // therefore by reading its state we know what we need to change + if (ui.comboBox1->currentIndex() == 9) { // helix + + command = QString::fromLatin1( + "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.Placement=%7\n" + "App.ActiveDocument.recompute()\n") + .arg(QString::fromLatin1(ObjectName)) + .arg(ui.helixPitch->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) + .arg(ui.helixHeight->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) + .arg(ui.helixRadius->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) + .arg(ui.helixAngle->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) + .arg(ui.helixLocalCS->currentIndex()) + .arg(placement); + } + + // store command for undo + doc->openCommand(command.toUtf8()); + // execute command + Gui::Command::runCommand(Gui::Command::App, command.toLatin1()); + // commit undo command + doc->commitCommand(); +} + // ---------------------------------------------- /* TRANSLATOR PartGui::Location */ -Location::Location(QWidget* parent) +Location::Location(QWidget* parent, bool edit, const char* ObjectName) { Q_UNUSED(parent); mode = 0; ui.setupUi(this); + + 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 (edit) { + // get the primitives object + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (!doc) + return; + auto docObj = doc->getDocument()->getObject(ObjectName); + // get the placement values + auto Property = docObj->getPropertyByName("Placement"); + auto placement = static_cast(Property); + + auto position = placement->getValue().getPosition(); + ui.XPositionQSB->setValue(position.x); + ui.YPositionQSB->setValue(position.y); + ui.ZPositionQSB->setValue(position.z); + + double rotationAngle; + Base::Vector3d rotationAxes; + auto rotation = placement->getValue().getRotation(); + rotation.getRawValue(rotationAxes, rotationAngle); + ui.XDirectionEdit->setValue(rotationAxes.x); + ui.YDirectionEdit->setValue(rotationAxes.y); + ui.ZDirectionEdit->setValue(rotationAxes.z); + // the angle is in this format: 180° = PI, thus transform it to deg + ui.AngleQSB->setValue(rotationAngle*180/M_PI); + } } Location::~Location() @@ -746,8 +858,12 @@ void Location::pickCallback(void * ud, SoEventCallback * n) SbVec3f pnt = point->getPoint(); SbVec3f nor = point->getNormal(); Location* dlg = reinterpret_cast(ud); - dlg->ui.loc->setPosition(Base::Vector3d(pnt[0],pnt[1],pnt[2])); - dlg->ui.loc->setDirection(Base::Vector3d(nor[0],nor[1],nor[2])); + 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(); } } @@ -769,59 +885,28 @@ void Location::pickCallback(void * ud, SoEventCallback * n) QString Location::toPlacement() const { - Base::Vector3d d = ui.loc->getDirection(); - gp_Dir dir = gp_Dir(d.x,d.y,d.z); - gp_Pnt pnt = gp_Pnt(0.0,0.0,0.0); - gp_Ax3 ax3; + // create a command to set the position and angle of the primitive object - double cosNX = dir.Dot(gp::DX()); - double cosNY = dir.Dot(gp::DY()); - double cosNZ = dir.Dot(gp::DZ()); - std::vector cosXYZ; - cosXYZ.push_back(fabs(cosNX)); - cosXYZ.push_back(fabs(cosNY)); - cosXYZ.push_back(fabs(cosNZ)); + Base::Vector3d rot; + rot.x = ui.XDirectionEdit->value(); + rot.y = ui.YDirectionEdit->value(); + rot.z = ui.ZDirectionEdit->value(); - int pos = std::max_element(cosXYZ.begin(), cosXYZ.end()) - cosXYZ.begin(); + double angle = ui.AngleQSB->rawValue(); - // +X/-X - if (pos == 0) { - if (cosNX > 0) - ax3 = gp_Ax3(pnt, dir, gp_Dir(0,1,0)); - else - ax3 = gp_Ax3(pnt, dir, gp_Dir(0,-1,0)); - } - // +Y/-Y - else if (pos == 1) { - if (cosNY > 0) - ax3 = gp_Ax3(pnt, dir, gp_Dir(0,0,1)); - else - ax3 = gp_Ax3(pnt, dir, gp_Dir(0,0,-1)); - } - // +Z/-Z - else { - ax3 = gp_Ax3(pnt, dir, gp_Dir(1,0,0)); - } + Base::Vector3d loc; + loc.x = ui.XPositionQSB->rawValue(); + loc.y = ui.YPositionQSB->rawValue(); + loc.z = ui.ZPositionQSB->rawValue(); - 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); - Base::Vector3d loc = ui.loc->getPosition(); - - return QString::fromLatin1("Base.Placement(Base.Vector(%1,%2,%3),Base.Rotation(%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[0],0,'f',Base::UnitsApi::getDecimals()) - .arg(rot[1],0,'f',Base::UnitsApi::getDecimals()) - .arg(rot[2],0,'f',Base::UnitsApi::getDecimals()) - .arg(rot[3],0,'f',Base::UnitsApi::getDecimals()); + return QString::fromLatin1("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()); } // ---------------------------------------------- @@ -832,14 +917,13 @@ TaskPrimitives::TaskPrimitives() { Gui::TaskView::TaskBox* taskbox; widget = new DlgPrimitives(); - taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(),true, 0); + taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, 0); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); location = new Location(); - taskbox = new Gui::TaskView::TaskBox(QPixmap(), location->windowTitle(),true, 0); + taskbox = new Gui::TaskView::TaskBox(QPixmap(), location->windowTitle() ,true, 0); taskbox->groupLayout()->addWidget(location); - taskbox->hideGroupBox(); Content.push_back(taskbox); } @@ -871,4 +955,57 @@ bool TaskPrimitives::reject() return true; } +// ---------------------------------------------- + +/* TRANSLATOR PartGui::TaskPrimitivesEdit */ + +TaskPrimitivesEdit::TaskPrimitivesEdit(DlgPrimitives::PrimitiveType type, const char* ObjectName) +{ + // save object name to be able to access it in accept() since if there are e.g. 3 helices + // the last one would be the active object, no matter that one is editing the first one + ObjectNameSave = ObjectName; + // create and show dialog for the primitives + Gui::TaskView::TaskBox* taskbox; + widget = new DlgPrimitives(0, type, true, ObjectName); + taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); + + // create and show dialog for the location + location = new Location(0, true, ObjectName); + taskbox = new Gui::TaskView::TaskBox(QPixmap(), location->windowTitle(), true, 0); + taskbox->groupLayout()->addWidget(location); + Content.push_back(taskbox); +} + +TaskPrimitivesEdit::~TaskPrimitivesEdit() +{ + // automatically deleted in the sub-class +} + +QDialogButtonBox::StandardButtons TaskPrimitivesEdit::getStandardButtons() const +{ + return QDialogButtonBox::Close | + QDialogButtonBox::Ok; +} + +void TaskPrimitivesEdit::modifyStandardButtons(QDialogButtonBox* box) +{ + QPushButton* btn = box->button(QDialogButtonBox::Ok); + btn->setText(QApplication::translate("PartGui::DlgPrimitives", "&OK")); +} + +bool TaskPrimitivesEdit::accept() +{ + widget->accept(location->toPlacement()); + Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); + return true; +} + +bool TaskPrimitivesEdit::reject() +{ + Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); + return true; +} + #include "moc_DlgPrimitives.cpp" diff --git a/src/Mod/Part/Gui/DlgPrimitives.h b/src/Mod/Part/Gui/DlgPrimitives.h index 14a1fd0af5..4bda9c260f 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.h +++ b/src/Mod/Part/Gui/DlgPrimitives.h @@ -60,9 +60,16 @@ class DlgPrimitives : public QWidget Q_OBJECT public: - DlgPrimitives(QWidget* parent = 0); + enum PrimitiveType { + Plane, Box, Cylinder, Cone, Sphere, Ellipsoid, Torus, Prism, Wedge, + Helix, Spiral, Circle, Ellipse, Point, Line, RegPolygon + }; + + DlgPrimitives(QWidget* parent = 0, PrimitiveType type = PrimitiveType::Plane, + bool edit = false, const char* ObjectName = ""); ~DlgPrimitives(); void createPrimitive(const QString&); + void accept(const QString&); private Q_SLOTS: void on_buttonCircleFromThreePoints_clicked(); @@ -80,7 +87,7 @@ class Location : public QWidget Q_OBJECT public: - Location(QWidget* parent = 0); + Location(QWidget* parent = 0, bool edit = false, const char* ObjectName = ""); ~Location(); QString toPlacement() const; @@ -105,7 +112,6 @@ public: public: bool accept(); bool reject(); - QDialogButtonBox::StandardButtons getStandardButtons() const; void modifyStandardButtons(QDialogButtonBox*); @@ -114,6 +120,25 @@ private: Location* location; }; +class TaskPrimitivesEdit : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskPrimitivesEdit(DlgPrimitives::PrimitiveType type, const char* ObjectName); + ~TaskPrimitivesEdit(); + +public: + bool accept(); + bool reject(); + QDialogButtonBox::StandardButtons getStandardButtons() const; + void modifyStandardButtons(QDialogButtonBox*); + +private: + DlgPrimitives* widget; + Location* location; +}; + } // namespace PartGui #endif // PARTGUI_DLGPRIMITIVES_H diff --git a/src/Mod/Part/Gui/Location.ui b/src/Mod/Part/Gui/Location.ui index 69f22d4dd1..ce1b089399 100644 --- a/src/Mod/Part/Gui/Location.ui +++ b/src/Mod/Part/Gui/Location.ui @@ -6,8 +6,8 @@ 0 0 - 209 - 205 + 280 + 307 @@ -16,52 +16,229 @@ true - - - + + + + + + 0 + 0 + + Position - - - - + - - - Qt::Horizontal + + + X - - - 40 - 20 - - - + - + + + + + + + + + + + + - 3D View + Y + + + + + + + - - - Qt::Vertical + + + + + Z + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + Rotation + + + + + + true - - - 20 - 40 - + + Use custom vector for pad direction otherwise +the sketch plane's normal vector will be used - + + Rotation axis direction + + + false + + + + + + + + x + + + + + + + x-component of direction vector + + + false + + + -100.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + y + + + + + + + y-component of direction vector + + + false + + + -100.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + z + + + + + + + z-component of direction vector + + + false + + + -100.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + + + + + + + + + + + Angle + + + + + + + + + + 5.000000000000000 + + + + @@ -71,9 +248,14 @@ - Gui::LocationWidget + Gui::QuantitySpinBox QWidget -
Gui/InputVector.h
+
Gui/QuantitySpinBox.h
+
+ + Gui::DoubleSpinBox + QDoubleSpinBox +
Gui/SpinBox.h
diff --git a/src/Mod/Part/Gui/ViewProviderHelixParametric.cpp b/src/Mod/Part/Gui/ViewProviderHelixParametric.cpp index ff39b7e10e..14678a1400 100644 --- a/src/Mod/Part/Gui/ViewProviderHelixParametric.cpp +++ b/src/Mod/Part/Gui/ViewProviderHelixParametric.cpp @@ -27,6 +27,9 @@ # include #endif +#include +#include +#include "DlgPrimitives.h" #include "ViewProviderHelixParametric.h" using namespace PartGui; @@ -55,6 +58,46 @@ std::vector ViewProviderHelixParametric::getDisplayModes(void) cons return StrList; } +void ViewProviderHelixParametric::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) +{ + QAction* act; + act = menu->addAction(QObject::tr("Edit helix"), receiver, member); + act->setData(QVariant((int)ViewProvider::Default)); + ViewProviderSpline::setupContextMenu(menu, receiver, member); +} + +void ViewProviderHelixParametric::updateData(const App::Property* prop) +{ + PartGui::ViewProviderSpline::updateData(prop); +} + +bool ViewProviderHelixParametric::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default) { + if (Gui::Control().activeDialog()) + return false; + auto ObjectName = getObject()->getNameInDocument(); + PartGui::TaskPrimitivesEdit* dlg + = new PartGui::TaskPrimitivesEdit(PartGui::DlgPrimitives::PrimitiveType::Helix, ObjectName); + Gui::Control().showDialog(dlg); + return true; + } + else { + ViewProviderSpline::setEdit(ModNum); + return true; + } +} + +void ViewProviderHelixParametric::unsetEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default) { + Gui::Control().closeDialog(); + } + else { + ViewProviderSpline::unsetEdit(ModNum); + } +} + // ------------------------------------------------------------------ PROPERTY_SOURCE(PartGui::ViewProviderSpiralParametric, PartGui::ViewProviderSpline) diff --git a/src/Mod/Part/Gui/ViewProviderHelixParametric.h b/src/Mod/Part/Gui/ViewProviderHelixParametric.h index bb868c7330..bed55bce3b 100644 --- a/src/Mod/Part/Gui/ViewProviderHelixParametric.h +++ b/src/Mod/Part/Gui/ViewProviderHelixParametric.h @@ -39,6 +39,13 @@ public: /// destructor virtual ~ViewProviderHelixParametric(); std::vector getDisplayModes(void) const; + void setupContextMenu(QMenu*, QObject*, const char*); + +protected: + void updateData(const App::Property*); + bool setEdit(int ModNum); + void unsetEdit(int ModNum); + }; class PartGuiExport ViewProviderSpiralParametric : public ViewProviderSpline