FreeCAD / src /Mod /Part /Gui /DlgExtrusion.cpp
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <BRepAdaptor_Curve.hxx>
#include <BRep_Tool.hxx>
#include <Precision.hxx>
#include <ShapeExtend_Explorer.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <QKeyEvent>
#include <QMessageBox>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <App/Part.h>
#include <Base/UnitsApi.h>
#include <Base/Tools.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/Utilities.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/Part/App/Part2DObject.h>
#include "ui_DlgExtrusion.h"
#include "DlgExtrusion.h"
FC_LOG_LEVEL_INIT("Part", true, true)
using namespace PartGui;
class DlgExtrusion::EdgeSelection: public Gui::SelectionFilterGate
{
public:
bool canSelect;
EdgeSelection()
: Gui::SelectionFilterGate(nullPointer())
{
canSelect = false;
}
bool allow(App::Document* /*pDoc*/, App::DocumentObject* pObj, const char* sSubName) override
{
this->canSelect = false;
if (Base::Tools::isNullOrEmpty(sSubName)) {
return false;
}
std::string element(sSubName);
if (element.substr(0, 4) != "Edge") {
return false;
}
Part::TopoShape part = Part::Feature::getTopoShape(
pObj,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform
);
if (part.isNull()) {
return false;
}
try {
TopoDS_Shape sub = Part::Feature::getTopoShape(
pObj,
Part::ShapeOption::NeedSubElement | Part::ShapeOption::ResolveLink
| Part::ShapeOption::Transform,
sSubName
)
.getShape();
if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) {
const TopoDS_Edge& edge = TopoDS::Edge(sub);
BRepAdaptor_Curve adapt(edge);
if (adapt.GetType() == GeomAbs_Line) {
this->canSelect = true;
return true;
}
}
}
catch (...) {
}
return false;
}
};
DlgExtrusion::DlgExtrusion(QWidget* parent, Qt::WindowFlags fl)
: QDialog(parent, fl)
, ui(new Ui_DlgExtrusion)
, filter(nullptr)
{
ui->setupUi(this);
setupConnections();
ui->statusLabel->clear();
ui->dirX->setDecimals(Base::UnitsApi::getDecimals());
ui->dirY->setDecimals(Base::UnitsApi::getDecimals());
ui->dirZ->setDecimals(Base::UnitsApi::getDecimals());
ui->spinLenFwd->setUnit(Base::Unit::Length);
ui->spinLenFwd->setValue(10.0);
ui->spinLenRev->setUnit(Base::Unit::Length);
ui->spinTaperAngle->setUnit(Base::Unit::Angle);
ui->spinTaperAngle->setUnit(Base::Unit::Angle);
findShapes();
Gui::ItemViewSelection sel(ui->treeWidget);
sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Link::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Part::getClassTypeId()));
this->onDirModeChanged();
ui->spinLenFwd->selectAll();
// Make sure that the spin box has the focus to get key events
// Calling setFocus() directly doesn't work because the spin box is not
// yet visible.
QMetaObject::invokeMethod(ui->spinLenFwd, "setFocus", Qt::QueuedConnection);
this->autoSolid();
}
/*
* Destroys the object and frees any allocated resources
*/
DlgExtrusion::~DlgExtrusion()
{
if (filter) {
Gui::Selection().rmvSelectionGate();
filter = nullptr;
}
// no need to delete child widgets, Qt does it all for us
}
void DlgExtrusion::setupConnections()
{
// clang-format off
connect(ui->rbDirModeCustom, &QRadioButton::toggled,
this, &DlgExtrusion::onDirModeCustomToggled);
connect(ui->rbDirModeEdge, &QRadioButton::toggled,
this, &DlgExtrusion::onDirModeEdgeToggled);
connect(ui->rbDirModeNormal, &QRadioButton::toggled,
this, &DlgExtrusion::onDirModeNormalToggled);
connect(ui->btnSelectEdge, &QPushButton::clicked,
this, &DlgExtrusion::onSelectEdgeClicked);
connect(ui->btnX, &QPushButton::clicked,
this, &DlgExtrusion::onButtnoXClicked);
connect(ui->btnY, &QPushButton::clicked,
this, &DlgExtrusion::onButtonYClicked);
connect(ui->btnZ, &QPushButton::clicked,
this, &DlgExtrusion::onButtonZClicked);
connect(ui->chkSymmetric, &QCheckBox::toggled,
this, &DlgExtrusion::onCheckSymmetricToggled);
connect(ui->txtLink, &QLineEdit::textChanged,
this, &DlgExtrusion::onTextLinkTextChanged);
// clang-format on
}
void DlgExtrusion::changeEvent(QEvent* e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
QDialog::changeEvent(e);
}
void DlgExtrusion::keyPressEvent(QKeyEvent* ke)
{
// The extrusion dialog is embedded into a task panel
// which is a parent widget and will handle the event
ke->ignore();
}
void DlgExtrusion::onDirModeCustomToggled(bool on)
{
if (on) { // this check prevents dual fire of dirmode changed - on radio buttons, one will come
// on, and other will come off, causing two events.
this->onDirModeChanged();
}
}
void DlgExtrusion::onDirModeEdgeToggled(bool on)
{
if (on) {
this->onDirModeChanged();
}
}
void DlgExtrusion::onDirModeNormalToggled(bool on)
{
if (on) {
this->onDirModeChanged();
}
}
void DlgExtrusion::onSelectEdgeClicked()
{
if (!filter) {
filter = new EdgeSelection();
Gui::Selection().addSelectionGate(filter);
ui->btnSelectEdge->setText(tr("Selecting…"));
// visibility automation
try {
QString code = QStringLiteral(
"import Show\n"
"tv = Show.TempoVis(App.ActiveDocument, tag= 'PartGui::DlgExtrusion')\n"
"tv.hide([%1])"
);
std::vector<App::DocumentObject*> sources = getShapesToExtrude();
QString features_to_hide;
for (App::DocumentObject* obj : sources) {
if (!obj) {
continue;
}
features_to_hide.append(QStringLiteral("App.ActiveDocument."));
features_to_hide.append(QString::fromLatin1(obj->getNameInDocument()));
features_to_hide.append(QStringLiteral(", \n"));
}
QByteArray code_2 = code.arg(features_to_hide).toLatin1();
Base::Interpreter().runString(code_2.constData());
}
catch (Base::PyException& e) {
e.reportException();
}
}
else {
Gui::Selection().rmvSelectionGate();
filter = nullptr;
ui->btnSelectEdge->setText(tr("Select"));
// visibility automation
try {
Base::Interpreter().runString("del(tv)");
}
catch (Base::PyException& e) {
e.reportException();
}
}
}
void DlgExtrusion::onButtnoXClicked()
{
Base::Vector3d axis(1.0, 0.0, 0.0);
if ((getDir() - axis).Length() < 1e-7) {
axis = axis * (-1);
}
setDirMode(Part::Extrusion::dmCustom);
setDir(axis);
}
void DlgExtrusion::onButtonYClicked()
{
Base::Vector3d axis(0.0, 1.0, 0.0);
if ((getDir() - axis).Length() < 1e-7) {
axis = axis * (-1);
}
setDirMode(Part::Extrusion::dmCustom);
setDir(axis);
}
void DlgExtrusion::onButtonZClicked()
{
Base::Vector3d axis(0.0, 0.0, 1.0);
if ((getDir() - axis).Length() < 1e-7) {
axis = axis * (-1);
}
setDirMode(Part::Extrusion::dmCustom);
setDir(axis);
}
void DlgExtrusion::onCheckSymmetricToggled(bool on)
{
ui->spinLenRev->setEnabled(!on);
}
void DlgExtrusion::onTextLinkTextChanged(QString)
{
this->fetchDir();
}
void DlgExtrusion::onDirModeChanged()
{
Part::Extrusion::eDirMode dirMode = this->getDirMode();
ui->dirX->setEnabled(dirMode == Part::Extrusion::dmCustom);
ui->dirY->setEnabled(dirMode == Part::Extrusion::dmCustom);
ui->dirZ->setEnabled(dirMode == Part::Extrusion::dmCustom);
ui->txtLink->setEnabled(dirMode == Part::Extrusion::dmEdge);
this->fetchDir();
}
void DlgExtrusion::onSelectionChanged(const Gui::SelectionChanges& msg)
{
if (msg.Type == Gui::SelectionChanges::AddSelection) {
if (filter && filter->canSelect) {
this->setAxisLink(msg.pObjectName, msg.pSubName);
this->setDirMode(Part::Extrusion::dmEdge);
}
}
}
App::DocumentObject& DlgExtrusion::getShapeToExtrude() const
{
std::vector<App::DocumentObject*> objs = this->getShapesToExtrude();
if (objs.empty()) {
throw Base::ValueError("No shapes selected");
}
return *(objs[0]);
}
void DlgExtrusion::fetchDir()
{
bool lengths_are_at_defaults = (fabs(ui->spinLenFwd->value().getValue() - 10.0) < 1e-7)
&& (fabs(ui->spinLenRev->value().getValue() - 0.0) < 1e-7);
bool lengths_are_zero = (fabs(ui->spinLenFwd->value().getValue() - 0.0) < 1e-7)
&& (fabs(ui->spinLenRev->value().getValue() - 0.0) < 1e-7);
try {
Base::Vector3d pos, dir;
bool fetched = false;
bool dir_has_valid_magnitude = false;
if (this->getDirMode() == Part::Extrusion::dmEdge) {
App::PropertyLinkSub lnk;
this->getAxisLink(lnk);
fetched = Part::Extrusion::fetchAxisLink(lnk, pos, dir);
dir_has_valid_magnitude = fetched;
}
else if (this->getDirMode() == Part::Extrusion::dmNormal) {
App::PropertyLink lnk;
lnk.setValue(&this->getShapeToExtrude());
dir = Part::Extrusion::calculateShapeNormal(lnk);
fetched = true;
}
if (dir_has_valid_magnitude && lengths_are_at_defaults) {
ui->spinLenFwd->setValue(0);
}
else if (!dir_has_valid_magnitude && lengths_are_zero) {
ui->spinLenFwd->setValue(1.0);
}
if (fetched) {
this->setDir(dir);
}
}
catch (Base::Exception&) {
}
catch (...) {
}
}
void DlgExtrusion::autoSolid()
{
try {
App::DocumentObject* dobj = &this->getShapeToExtrude();
Part::TopoShape shape = Part::Feature::getTopoShape(
dobj,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform
);
if (shape.isNull()) {
return;
}
TopoDS_Shape sh = shape.getShape();
if (sh.IsNull()) {
return;
}
ShapeExtend_Explorer xp;
Handle(TopTools_HSequenceOfShape) leaves
= xp.SeqFromCompound(sh, /*recursive= */ Standard_True);
int cntClosedWires = 0;
for (int i = 0; i < leaves->Length(); i++) {
const TopoDS_Shape& leaf = leaves->Value(i + 1);
if (leaf.IsNull()) {
return;
}
if (leaf.ShapeType() == TopAbs_WIRE || leaf.ShapeType() == TopAbs_EDGE) {
if (BRep_Tool::IsClosed(leaf)) {
cntClosedWires++;
}
}
}
ui->chkSolid->setChecked(cntClosedWires == leaves->Length());
}
catch (...) {
}
}
void DlgExtrusion::findShapes()
{
App::Document* activeDoc = App::GetApplication().getActiveDocument();
if (!activeDoc) {
return;
}
Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
this->document = activeDoc->getName();
this->label = activeDoc->Label.getValue();
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (auto obj : objs) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(
obj,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform
);
if (topoShape.isNull()) {
continue;
}
TopoDS_Shape shape = topoShape.getShape();
if (shape.IsNull()) {
continue;
}
if (canExtrude(shape)) {
QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeWidget);
item->setText(0, QString::fromUtf8(obj->Label.getValue()));
item->setData(0, Qt::UserRole, QString::fromLatin1(obj->getNameInDocument()));
Gui::ViewProvider* vp = activeGui->getViewProvider(obj);
if (vp) {
item->setIcon(0, vp->getIcon());
}
}
}
}
bool DlgExtrusion::canExtrude(const TopoDS_Shape& shape) const
{
if (shape.IsNull()) {
return false;
}
TopAbs_ShapeEnum type = shape.ShapeType();
if (type == TopAbs_VERTEX || type == TopAbs_EDGE || type == TopAbs_WIRE || type == TopAbs_FACE
|| type == TopAbs_SHELL) {
return true;
}
if (type == TopAbs_COMPOUND) {
TopExp_Explorer xp;
xp.Init(shape, TopAbs_SOLID);
while (xp.More()) {
return false;
}
xp.Init(shape, TopAbs_COMPSOLID);
while (xp.More()) {
return false;
}
return true;
}
return false;
}
void DlgExtrusion::accept()
{
try {
apply();
QDialog::accept();
}
catch (Base::AbortException&) {
};
}
void DlgExtrusion::apply()
{
try {
if (!validate()) {
throw Base::AbortException();
}
if (filter) { // if still selecting edge - stop. This is important for visibility automation.
this->onSelectEdgeClicked();
}
Gui::WaitCursor wc;
App::Document* activeDoc = App::GetApplication().getDocument(this->document.c_str());
if (!activeDoc) {
QMessageBox::critical(
this,
windowTitle(),
tr("The document '%1' doesn't exist.").arg(QString::fromUtf8(this->label.c_str()))
);
return;
}
activeDoc->openTransaction("Extrude");
Base::Reference<ParameterGrp> hGrp = App::GetApplication()
.GetUserParameter()
.GetGroup("BaseApp")
->GetGroup("Preferences")
->GetGroup("Mod/Part");
bool addBaseName = hGrp->GetBool("AddBaseObjectName", false);
std::vector<App::DocumentObject*> objects = this->getShapesToExtrude();
for (App::DocumentObject* sourceObj : objects) {
assert(sourceObj);
if (Part::Feature::getTopoShape(
sourceObj,
Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform
)
.isNull()) {
FC_ERR(
"Object " << sourceObj->getFullName() << " is not a Part object because it has no OCC shape. Extrusion is not possible."
);
continue;
}
std::string name;
name = sourceObj->getDocument()->getUniqueObjectName("Extrude").c_str();
if (addBaseName) {
// FIXME: implement
// QString baseName = QStringLiteral("Extrude_%1").arg(sourceObjectName);
// label = QStringLiteral("%1_Extrude").arg((*it)->text(0));
}
FCMD_OBJ_DOC_CMD(sourceObj, "addObject('Part::Extrusion','" << name << "')");
auto newObj = sourceObj->getDocument()->getObject(name.c_str());
this->writeParametersToFeature(*newObj, sourceObj);
if (!sourceObj->isDerivedFrom<Part::Part2DObject>()) {
Gui::Command::copyVisual(newObj, "ShapeAppearance", sourceObj);
Gui::Command::copyVisual(newObj, "LineColor", sourceObj);
Gui::Command::copyVisual(newObj, "PointColor", sourceObj);
}
FCMD_OBJ_HIDE(sourceObj);
}
activeDoc->commitTransaction();
Gui::Command::updateActive();
}
catch (Base::AbortException&) {
throw;
}
catch (Base::Exception& err) {
QMessageBox::critical(
this,
windowTitle(),
tr("Creating extrusion failed.\n%1").arg(QCoreApplication::translate("Exception", err.what()))
);
return;
}
catch (...) {
QMessageBox::critical(
this,
windowTitle(),
tr("Creating Extrusion failed.\n%1").arg(QStringLiteral("Unknown error"))
);
return;
}
}
void DlgExtrusion::reject()
{
if (filter) { // if still selecting edge - stop.
this->onSelectEdgeClicked();
}
QDialog::reject();
}
Base::Vector3d DlgExtrusion::getDir() const
{
return Base::Vector3d(ui->dirX->value(), ui->dirY->value(), ui->dirZ->value());
}
void DlgExtrusion::setDir(Base::Vector3d newDir)
{
ui->dirX->setValue(newDir.x);
ui->dirY->setValue(newDir.y);
ui->dirZ->setValue(newDir.z);
}
Part::Extrusion::eDirMode DlgExtrusion::getDirMode() const
{
if (ui->rbDirModeCustom->isChecked()) {
return Part::Extrusion::dmCustom;
}
if (ui->rbDirModeEdge->isChecked()) {
return Part::Extrusion::dmEdge;
}
if (ui->rbDirModeNormal->isChecked()) {
return Part::Extrusion::dmNormal;
}
// we shouldn't get here...
return Part::Extrusion::dmCustom;
}
void DlgExtrusion::setDirMode(Part::Extrusion::eDirMode newMode)
{
ui->rbDirModeCustom->blockSignals(true);
ui->rbDirModeEdge->blockSignals(true);
ui->rbDirModeNormal->blockSignals(true);
ui->rbDirModeCustom->setChecked(newMode == Part::Extrusion::dmCustom);
ui->rbDirModeEdge->setChecked(newMode == Part::Extrusion::dmEdge);
ui->rbDirModeNormal->setChecked(newMode == Part::Extrusion::dmNormal);
ui->rbDirModeCustom->blockSignals(false);
ui->rbDirModeEdge->blockSignals(false);
ui->rbDirModeNormal->blockSignals(false);
this->onDirModeChanged();
}
void DlgExtrusion::getAxisLink(App::PropertyLinkSub& lnk) const
{
QString text = ui->txtLink->text();
if (text.length() == 0) {
lnk.setValue(nullptr);
}
else {
QStringList parts = text.split(QChar::fromLatin1(':'));
App::DocumentObject* obj = App::GetApplication().getActiveDocument()->getObject(
parts[0].toLatin1()
);
if (!obj) {
throw Base::ValueError(tr("Object not found: %1").arg(parts[0]).toUtf8().constData());
}
lnk.setValue(obj);
if (parts.size() == 1) {
return;
}
else if (parts.size() == 2) {
std::vector<std::string> subs;
subs.emplace_back(parts[1].toLatin1().constData());
lnk.setValue(obj, subs);
}
}
}
void DlgExtrusion::setAxisLink(const App::PropertyLinkSub& lnk)
{
if (!lnk.getValue()) {
ui->txtLink->clear();
return;
}
if (lnk.getSubValues().size() == 1) {
this->setAxisLink(lnk.getValue()->getNameInDocument(), lnk.getSubValues()[0].c_str());
}
else {
this->setAxisLink(lnk.getValue()->getNameInDocument(), "");
}
}
void DlgExtrusion::setAxisLink(const char* objname, const char* subname)
{
if (objname && strlen(objname) > 0) {
QString txt = QString::fromLatin1(objname);
if (subname && strlen(subname) > 0) {
txt = txt + QStringLiteral(":") + QString::fromLatin1(subname);
}
ui->txtLink->setText(txt);
}
else {
ui->txtLink->clear();
}
}
std::vector<App::DocumentObject*> DlgExtrusion::getShapesToExtrude() const
{
QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
App::Document* doc = App::GetApplication().getDocument(this->document.c_str());
if (!doc) {
throw Base::RuntimeError("Document lost");
}
std::vector<App::DocumentObject*> objects;
for (auto item : items) {
App::DocumentObject* obj = doc->getObject(item->data(0, Qt::UserRole).toString().toLatin1());
if (!obj) {
throw Base::RuntimeError("Object not found");
}
objects.push_back(obj);
}
return objects;
}
bool DlgExtrusion::validate()
{
// check source shapes
if (ui->treeWidget->selectedItems().isEmpty()) {
QMessageBox::critical(this, windowTitle(), tr("No shapes selected for extrusion."));
return false;
}
// check axis link
QString errmsg;
bool hasValidAxisLink = false;
try {
App::PropertyLinkSub lnk;
this->getAxisLink(lnk);
Base::Vector3d dir, base;
hasValidAxisLink = Part::Extrusion::fetchAxisLink(lnk, base, dir);
}
catch (Base::Exception& err) {
errmsg = QCoreApplication::translate("Exception", err.what());
}
catch (Standard_Failure& err) {
errmsg = QString::fromLocal8Bit(err.GetMessageString());
}
catch (...) {
errmsg = tr("Unknown error");
}
if (this->getDirMode() == Part::Extrusion::dmEdge && !hasValidAxisLink) {
if (errmsg.length() > 0) {
QMessageBox::critical(
this,
windowTitle(),
tr("Extrusion direction link is invalid.\n\n%1").arg(errmsg)
);
}
else {
QMessageBox::critical(
this,
windowTitle(),
tr("Direction mode is to use an edge, but no edge is linked.")
);
}
ui->txtLink->setFocus();
return false;
}
else if (this->getDirMode() != Part::Extrusion::dmEdge && !hasValidAxisLink) {
// axis link is invalid, but it is not required by the mode. We shouldn't complain it's
// invalid then...
ui->txtLink->clear();
}
// check normal
if (this->getDirMode() == Part::Extrusion::dmNormal) {
errmsg.clear();
try {
App::PropertyLink lnk;
lnk.setValue(&this->getShapeToExtrude()); // simplified - check only for the first shape.
Part::Extrusion::calculateShapeNormal(lnk);
}
catch (Base::Exception& err) {
errmsg = QCoreApplication::translate("Exception", err.what());
}
catch (Standard_Failure& err) {
errmsg = QString::fromLocal8Bit(err.GetMessageString());
}
catch (...) {
errmsg = QStringLiteral("Unknown error");
}
if (errmsg.length() > 0) {
QMessageBox::critical(
this,
windowTitle(),
tr("Cannot determine normal vector of shape to be extruded. Use other mode. "
"\n\n(%1)")
.arg(errmsg)
);
ui->rbDirModeNormal->setFocus();
return false;
}
}
// check axis dir
if (this->getDirMode() == Part::Extrusion::dmCustom) {
if (this->getDir().Length() < Precision::Confusion()) {
QMessageBox::critical(
this,
windowTitle(),
tr("Extrusion direction vector is zero-length. It must be non-zero.")
);
ui->dirX->setFocus();
return false;
}
}
// check lengths
if (!ui->chkSymmetric->isChecked()
&& fabs(ui->spinLenFwd->value().getValue() + ui->spinLenRev->value().getValue())
< Precision::Confusion()
&& !(
fabs(ui->spinLenFwd->value().getValue() - ui->spinLenRev->value().getValue())
< Precision::Confusion()
)) {
QMessageBox::critical(
this,
windowTitle(),
tr("Total extrusion length is zero (length1 == -length2). It must be nonzero.")
);
ui->spinLenFwd->setFocus();
return false;
}
return true;
}
void DlgExtrusion::writeParametersToFeature(App::DocumentObject& feature, App::DocumentObject* base) const
{
Gui::Command::doCommand(
Gui::Command::Doc,
"f = App.getDocument('%s').getObject('%s')",
feature.getDocument()->getName(),
feature.getNameInDocument()
);
if (base) {
Gui::Command::doCommand(
Gui::Command::Doc,
"f.Base = App.getDocument('%s').getObject('%s')",
base->getDocument()->getName(),
base->getNameInDocument()
);
}
Part::Extrusion::eDirMode dirMode = this->getDirMode();
const char* modestr = Part::Extrusion::eDirModeStrings[dirMode];
Gui::Command::doCommand(Gui::Command::Doc, "f.DirMode = \"%s\"", modestr);
if (dirMode == Part::Extrusion::dmCustom) {
Base::Vector3d dir = this->getDir();
Gui::Command::doCommand(
Gui::Command::Doc,
"f.Dir = App.Vector(%.15f, %.15f, %.15f)",
dir.x,
dir.y,
dir.z
);
}
App::PropertyLinkSub lnk;
this->getAxisLink(lnk);
std::stringstream linkstr;
if (!lnk.getValue()) {
linkstr << "None";
}
else {
linkstr << "(App.getDocument(\"" << lnk.getValue()->getDocument()->getName() << "\")."
<< lnk.getValue()->getNameInDocument();
linkstr << ", [";
for (const std::string& str : lnk.getSubValues()) {
linkstr << "\"" << str << "\"";
}
linkstr << "])";
}
Gui::Command::doCommand(Gui::Command::Doc, "f.DirLink = %s", linkstr.str().c_str());
Gui::Command::doCommand(Gui::Command::Doc, "f.LengthFwd = %.15f", ui->spinLenFwd->value().getValue());
Gui::Command::doCommand(Gui::Command::Doc, "f.LengthRev = %.15f", ui->spinLenRev->value().getValue());
Gui::Command::doCommand(
Gui::Command::Doc,
"f.Solid = %s",
ui->chkSolid->isChecked() ? "True" : "False"
);
Gui::Command::doCommand(
Gui::Command::Doc,
"f.Reversed = %s",
ui->chkReversed->isChecked() ? "True" : "False"
);
Gui::Command::doCommand(
Gui::Command::Doc,
"f.Symmetric = %s",
ui->chkSymmetric->isChecked() ? "True" : "False"
);
Gui::Command::doCommand(
Gui::Command::Doc,
"f.TaperAngle = %.15f",
ui->spinTaperAngle->value().getValue()
);
Gui::Command::doCommand(
Gui::Command::Doc,
"f.TaperAngleRev = %.15f",
ui->spinTaperAngleRev->value().getValue()
);
}
// ---------------------------------------
TaskExtrusion::TaskExtrusion()
{
widget = new DlgExtrusion();
addTaskBox(Gui::BitmapFactory().pixmap("Part_Extrude"), widget);
}
bool TaskExtrusion::accept()
{
widget->accept();
return (widget->result() == QDialog::Accepted);
}
bool TaskExtrusion::reject()
{
widget->reject();
return true;
}
void TaskExtrusion::clicked(int id)
{
if (id == QDialogButtonBox::Apply) {
try {
widget->apply();
}
catch (Base::AbortException&) {
};
}
}
#include "moc_DlgExtrusion.cpp"