diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index 01c0ad1cc0..36323b94f9 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -147,6 +147,8 @@ SET(PartDesignGuiTaskDlgs_SRCS TaskFeatureParameters.h TaskSketchBasedParameters.cpp TaskSketchBasedParameters.h + TaskExtrudeParameters.cpp + TaskExtrudeParameters.h TaskPadParameters.ui TaskPadParameters.cpp TaskPadParameters.h diff --git a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp new file mode 100644 index 0000000000..c7b55b6150 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp @@ -0,0 +1,715 @@ +/*************************************************************************** + * Copyright (c) 2011 Juergen Riegel * + * * + * 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 "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + +#include "ui_TaskPadParameters.h" +#include "TaskExtrudeParameters.h" +#include +#include +#include "ReferenceSelection.h" + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskExtrudeParameters */ + +TaskExtrudeParameters::TaskExtrudeParameters(ViewProviderSketchBased *SketchBasedView, QWidget *parent, + const std::string& pixmapname, const QString& parname) + : TaskSketchBasedParameters(SketchBasedView, parent, pixmapname, parname) + , ui(new Ui_TaskPadParameters) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui->setupUi(proxy); +#if QT_VERSION >= 0x040700 + ui->lineFaceName->setPlaceholderText(tr("No face selected")); +#endif + + this->groupLayout()->addWidget(proxy); +} + +void TaskExtrudeParameters::setupDialog(bool newObj) +{ + // Get the feature data + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + Base::Quantity l = extrude->Length.getQuantityValue(); + Base::Quantity l2 = extrude->Length2.getQuantityValue(); + Base::Quantity off = extrude->Offset.getQuantityValue(); + bool alongNormal = extrude->AlongSketchNormal.getValue(); + bool useCustom = extrude->UseCustomVector.getValue(); + double xs = extrude->Direction.getValue().x; + double ys = extrude->Direction.getValue().y; + double zs = extrude->Direction.getValue().z; + bool midplane = extrude->Midplane.getValue(); + bool reversed = extrude->Reversed.getValue(); + int index = extrude->Type.getValue(); // must extract value here, clear() kills it! + App::DocumentObject* obj = extrude->UpToFace.getValue(); + std::vector subStrings = extrude->UpToFace.getSubValues(); + std::string upToFace; + int faceId = -1; + if ((obj != NULL) && !subStrings.empty()) { + upToFace = subStrings.front(); + if (upToFace.substr(0,4) == "Face") + faceId = std::atoi(&upToFace[4]); + } + + // set decimals for the direction edits + // do this here before the edits are filed to avoid rounding mistakes + int UserDecimals = Base::UnitsApi::getDecimals(); + ui->XDirectionEdit->setDecimals(UserDecimals); + ui->YDirectionEdit->setDecimals(UserDecimals); + ui->ZDirectionEdit->setDecimals(UserDecimals); + + // Fill data into dialog elements + // the direction combobox is later filled in updateUI() + ui->lengthEdit->setValue(l); + ui->lengthEdit2->setValue(l2); + ui->offsetEdit->setValue(off); + ui->checkBoxAlongDirection->setChecked(alongNormal); + ui->checkBoxDirection->setChecked(useCustom); + onDirectionToggled(useCustom); + // disable to change the direction if not custom + if (!useCustom) { + ui->XDirectionEdit->setEnabled(false); + ui->YDirectionEdit->setEnabled(false); + ui->ZDirectionEdit->setEnabled(false); + } + ui->XDirectionEdit->setValue(xs); + ui->YDirectionEdit->setValue(ys); + ui->ZDirectionEdit->setValue(zs); + + // Bind input fields to properties + ui->lengthEdit->bind(extrude->Length); + ui->lengthEdit2->bind(extrude->Length2); + ui->offsetEdit->bind(extrude->Offset); + ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(extrude, std::string("Direction.x"))); + ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(extrude, std::string("Direction.y"))); + ui->ZDirectionEdit->bind(App::ObjectIdentifier::parse(extrude, std::string("Direction.z"))); + + ui->checkBoxMidplane->setChecked(midplane); + // According to bug #0000521 the reversed option + // shouldn't be de-activated if the pad has a support face + ui->checkBoxReversed->setChecked(reversed); + + // Set object labels + if (obj && PartDesign::Feature::isDatum(obj)) { + ui->lineFaceName->setText(QString::fromUtf8(obj->Label.getValue())); + ui->lineFaceName->setProperty("FeatureName", QByteArray(obj->getNameInDocument())); + } + else if (obj && faceId >= 0) { + ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") + .arg(QString::fromUtf8(obj->Label.getValue())) + .arg(tr("Face")) + .arg(faceId)); + ui->lineFaceName->setProperty("FeatureName", QByteArray(obj->getNameInDocument())); + } + else { + ui->lineFaceName->clear(); + ui->lineFaceName->setProperty("FeatureName", QVariant()); + } + + ui->lineFaceName->setProperty("FaceName", QByteArray(upToFace.c_str())); + + translateModeList(index); + + QMetaObject::connectSlotsByName(this); + + connect(ui->lengthEdit, SIGNAL(valueChanged(double)), + this, SLOT(onLengthChanged(double))); + connect(ui->lengthEdit2, SIGNAL(valueChanged(double)), + this, SLOT(onLength2Changed(double))); + connect(ui->offsetEdit, SIGNAL(valueChanged(double)), + this, SLOT(onOffsetChanged(double))); + connect(ui->directionCB, SIGNAL(activated(int)), + this, SLOT(onDirectionCBChanged(int))); + connect(ui->checkBoxAlongDirection, SIGNAL(toggled(bool)), + this, SLOT(onAlongSketchNormalChanged(bool))); + connect(ui->checkBoxDirection, SIGNAL(toggled(bool)), + this, SLOT(onDirectionToggled(bool))); + connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)), + this, SLOT(onXDirectionEditChanged(double))); + connect(ui->YDirectionEdit, SIGNAL(valueChanged(double)), + this, SLOT(onYDirectionEditChanged(double))); + connect(ui->ZDirectionEdit, SIGNAL(valueChanged(double)), + this, SLOT(onZDirectionEditChanged(double))); + connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), + this, SLOT(onMidplaneChanged(bool))); + connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), + this, SLOT(onReversedChanged(bool))); + connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), + this, SLOT(onModeChanged(int))); + connect(ui->buttonFace, SIGNAL(clicked()), + this, SLOT(onButtonFace())); + connect(ui->lineFaceName, SIGNAL(textEdited(QString)), + this, SLOT(onFaceName(QString))); + connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), + this, SLOT(onUpdateView(bool))); + + this->propReferenceAxis = &(extrude->ReferenceAxis); + + // Due to signals attached after changes took took into effect we should update the UI now. + updateUI(index); + + // if it is a newly created object use the last value of the history + // TODO: newObj doesn't supplied normally by any caller (2015-07-24, Fat-Zer) + if (newObj){ + ui->lengthEdit->setToLastUsedValue(); + ui->lengthEdit->selectNumber(); + ui->lengthEdit2->setToLastUsedValue(); + ui->lengthEdit2->selectNumber(); + ui->offsetEdit->setToLastUsedValue(); + ui->offsetEdit->selectNumber(); + } +} + +TaskExtrudeParameters::~TaskExtrudeParameters() +{ +} + +void TaskExtrudeParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + if (msg.Type == Gui::SelectionChanges::AddSelection) { + // if we have an edge selection for the extrude direction + if (!selectionFace) { + std::vector edge; + App::DocumentObject* selObj; + if (getReferencedSelection(vp->getObject(), msg, selObj, edge) && selObj) { + exitSelectionMode(); + propReferenceAxis->setValue(selObj, edge); + recomputeFeature(); + // update direction combobox + fillDirectionCombo(); + } + } + else { // if we have a selection of a face + QString refText = onAddSelection(msg); + if (refText.length() > 0) { + ui->lineFaceName->blockSignals(true); + ui->lineFaceName->setText(refText); + ui->lineFaceName->setProperty("FeatureName", QByteArray(msg.pObjectName)); + ui->lineFaceName->setProperty("FaceName", QByteArray(msg.pSubName)); + ui->lineFaceName->blockSignals(false); + // Turn off reference selection mode + onButtonFace(false); + } + else { + ui->lineFaceName->blockSignals(true); + ui->lineFaceName->clear(); + ui->lineFaceName->setProperty("FeatureName", QVariant()); + ui->lineFaceName->setProperty("FaceName", QVariant()); + ui->lineFaceName->blockSignals(false); + } + } + } else if (msg.Type == Gui::SelectionChanges::ClrSelection && selectionFace) { + ui->lineFaceName->blockSignals(true); + ui->lineFaceName->clear(); + ui->lineFaceName->setProperty("FeatureName", QVariant()); + ui->lineFaceName->setProperty("FaceName", QVariant()); + ui->lineFaceName->blockSignals(false); + } +} + +void TaskExtrudeParameters::onLengthChanged(double len) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Length.setValue(len); + recomputeFeature(); +} + +void TaskExtrudeParameters::onLength2Changed(double len) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Length2.setValue(len); + recomputeFeature(); +} + +void TaskExtrudeParameters::onOffsetChanged(double len) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Offset.setValue(len); + recomputeFeature(); +} + +void TaskExtrudeParameters::fillDirectionCombo() +{ + bool oldVal_blockUpdate = blockUpdate; + blockUpdate = true; + + if (axesInList.empty()) { + bool hasFace = false; + ui->directionCB->clear(); + // we can have sketches or faces + // for sketches just get the sketch normal + PartDesign::ProfileBased* pcFeat = static_cast(vp->getObject()); + Part::Part2DObject* pcSketch = dynamic_cast(pcFeat->Profile.getValue()); + // for faces we test if it is verified and if we can get its normal + if (!pcSketch) { + try { + Part::Feature* pcFeature = pcFeat->getVerifiedObject(); + Base::Vector3d SketchVector = pcFeat->getProfileNormal(); + Q_UNUSED(pcFeature) + Q_UNUSED(SketchVector) + hasFace = true; + } + catch (const Base::Exception& e) { + new App::DocumentObjectExecReturn(e.what()); + } + } + if (pcSketch) + addAxisToCombo(pcSketch, "N_Axis", tr("Sketch normal")); + else if (hasFace) + addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Face normal"), false); + // add the other entries + addAxisToCombo(0, std::string(), tr("Select reference...")); + // we start with the sketch normal as proposal for the custom direction + if (pcSketch) + addAxisToCombo(pcSketch, "N_Axis", tr("Custom direction")); + else if (hasFace) + addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Custom direction"), false); + } + + // add current link, if not in list + // first, figure out the item number for current axis + int indexOfCurrent = -1; + App::DocumentObject* ax = propReferenceAxis->getValue(); + const std::vector& subList = propReferenceAxis->getSubValues(); + for (size_t i = 0; i < axesInList.size(); i++) { + if (ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) { + indexOfCurrent = i; + break; + } + } + // if the axis is not yet listed in the combobox + if (indexOfCurrent == -1 && ax) { + assert(subList.size() <= 1); + std::string sub; + if (!subList.empty()) + sub = subList[0]; + addAxisToCombo(ax, sub, getRefStr(ax, subList)); + indexOfCurrent = axesInList.size() - 1; + // the axis is not the normal, thus enable along direction + ui->checkBoxAlongDirection->setEnabled(true); + // we don't have custom direction thus disable its settings + ui->XDirectionEdit->setEnabled(false); + ui->YDirectionEdit->setEnabled(false); + ui->ZDirectionEdit->setEnabled(false); + } + + // highlight either current index or set custom direction + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + bool hasCustom = extrude->UseCustomVector.getValue(); + if (indexOfCurrent != -1 && !hasCustom) + ui->directionCB->setCurrentIndex(indexOfCurrent); + if (hasCustom) + ui->directionCB->setCurrentIndex(2); + + blockUpdate = oldVal_blockUpdate; +} + +void TaskExtrudeParameters::addAxisToCombo(App::DocumentObject* linkObj, + std::string linkSubname, QString itemText, bool hasSketch) +{ + this->ui->directionCB->addItem(itemText); + this->axesInList.emplace_back(new App::PropertyLinkSub); + App::PropertyLinkSub& lnk = *(axesInList.back()); + // if we have a face, we leave the link empty since we cannot + // store the face normal as sublink + if (hasSketch) + lnk.setValue(linkObj, std::vector(1, linkSubname)); +} + +void TaskExtrudeParameters::onDirectionCBChanged(int num) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + + if (axesInList.empty()) + return; + + // we use this scheme for 'num' + // 0: normal to sketch or face + // 1: selection mode + // 2: custom + // 3-x: edges selected in the 3D model + + // check the axis + // when the link is empty we are either in selection mode + // or we are normal to a face + App::PropertyLinkSub& lnk = *(axesInList[num]); + if (num == 1) { + // enter reference selection mode + this->blockConnection(false); + // to distinguish that this is the direction selection + selectionFace = false; + TaskSketchBasedParameters::onSelectReference(true, true, false, true, true); + return; + } + else if (lnk.getValue() != 0) { + if (!extrude->getDocument()->isIn(lnk.getValue())) { + Base::Console().Error("Object was deleted\n"); + return; + } + propReferenceAxis->Paste(lnk); + } + + // in case the user is in selection mode, but changed his mind before selecting anything + exitSelectionMode(); + + // disable AlongSketchNormal when the direction is already normal + if (num == 0) + ui->checkBoxAlongDirection->setEnabled(false); + else + ui->checkBoxAlongDirection->setEnabled(true); + // if custom direction is used, show it + if (num == 2) { + ui->checkBoxDirection->setChecked(true); + extrude->UseCustomVector.setValue(true); + } + else { + extrude->UseCustomVector.setValue(false); + } + // if we dont use custom direction, only allow to show its direction + if (num != 2) { + ui->XDirectionEdit->setEnabled(false); + ui->YDirectionEdit->setEnabled(false); + ui->ZDirectionEdit->setEnabled(false); + } + else { + ui->XDirectionEdit->setEnabled(true); + ui->YDirectionEdit->setEnabled(true); + ui->ZDirectionEdit->setEnabled(true); + } + // recompute and update the direction + extrude->ReferenceAxis.setValue(lnk.getValue(), lnk.getSubValues()); + try { + recomputeFeature(); + } + catch (const Base::Exception& e) { + e.ReportException(); + } + updateDirectionEdits(); +} + +void TaskExtrudeParameters::onAlongSketchNormalChanged(bool on) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->AlongSketchNormal.setValue(on); + recomputeFeature(); +} + +void TaskExtrudeParameters::onDirectionToggled(bool on) +{ + if (on) + ui->groupBoxDirection->show(); + else + ui->groupBoxDirection->hide(); +} + +void TaskExtrudeParameters::onXDirectionEditChanged(double len) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Direction.setValue(len, extrude->Direction.getValue().y, extrude->Direction.getValue().z); + recomputeFeature(); + // checking for case of a null vector is done in FeatureExtrude.cpp + // if there was a null vector, the normal vector of the sketch is used. + // therefore the vector component edits must be updated + updateDirectionEdits(); +} + +void TaskExtrudeParameters::onYDirectionEditChanged(double len) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Direction.setValue(extrude->Direction.getValue().x, len, extrude->Direction.getValue().z); + recomputeFeature(); + updateDirectionEdits(); +} + +void TaskExtrudeParameters::onZDirectionEditChanged(double len) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Direction.setValue(extrude->Direction.getValue().x, extrude->Direction.getValue().y, len); + recomputeFeature(); + updateDirectionEdits(); +} + +void TaskExtrudeParameters::updateDirectionEdits() +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + // we don't want to execute the onChanged edits, but just update their contents + ui->XDirectionEdit->blockSignals(true); + ui->YDirectionEdit->blockSignals(true); + ui->ZDirectionEdit->blockSignals(true); + ui->XDirectionEdit->setValue(extrude->Direction.getValue().x); + ui->YDirectionEdit->setValue(extrude->Direction.getValue().y); + ui->ZDirectionEdit->setValue(extrude->Direction.getValue().z); + ui->XDirectionEdit->blockSignals(false); + ui->YDirectionEdit->blockSignals(false); + ui->ZDirectionEdit->blockSignals(false); +} + +void TaskExtrudeParameters::onMidplaneChanged(bool on) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Midplane.setValue(on); + // reversed is not sensible when midplane + ui->checkBoxReversed->setEnabled(!on); + recomputeFeature(); +} + +void TaskExtrudeParameters::onReversedChanged(bool on) +{ + PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); + extrude->Reversed.setValue(on); + // midplane is not sensible when reversed + ui->checkBoxMidplane->setEnabled(!on); + // update the direction + recomputeFeature(); + updateDirectionEdits(); +} + +void TaskExtrudeParameters::onButtonFace(const bool pressed) +{ + this->blockConnection(!pressed); + + // to distinguish that this is the direction selection + selectionFace = true; + + // only faces are allowed + TaskSketchBasedParameters::onSelectReference(pressed, false, true, false); + + // Update button if onButtonFace() is called explicitly + ui->buttonFace->setChecked(pressed); +} + +void TaskExtrudeParameters::onFaceName(const QString& text) +{ + if (text.isEmpty()) { + // if user cleared the text field then also clear the properties + ui->lineFaceName->setProperty("FeatureName", QVariant()); + ui->lineFaceName->setProperty("FaceName", QVariant()); + } + else { + // expect that the label of an object is used + QStringList parts = text.split(QChar::fromLatin1(':')); + QString label = parts[0]; + QVariant name = objectNameByLabel(label, ui->lineFaceName->property("FeatureName")); + if (name.isValid()) { + parts[0] = name.toString(); + QString uptoface = parts.join(QString::fromLatin1(":")); + ui->lineFaceName->setProperty("FeatureName", name); + ui->lineFaceName->setProperty("FaceName", setUpToFace(uptoface)); + } + else { + ui->lineFaceName->setProperty("FeatureName", QVariant()); + ui->lineFaceName->setProperty("FaceName", QVariant()); + } + } +} + +double TaskExtrudeParameters::getLength(void) const +{ + return ui->lengthEdit->value().getValue(); +} + +double TaskExtrudeParameters::getLength2(void) const +{ + return ui->lengthEdit2->value().getValue(); +} + +double TaskExtrudeParameters::getOffset(void) const +{ + return ui->offsetEdit->value().getValue(); +} + +bool TaskExtrudeParameters::getAlongSketchNormal(void) const +{ + return ui->checkBoxAlongDirection->isChecked(); +} + +bool TaskExtrudeParameters::getCustom(void) const +{ + // index 2 is hardcoded to custom vector + return ui->directionCB->currentIndex() == 2 ? true : false; +} + +std::string TaskExtrudeParameters::getReferenceAxis(void) const +{ + std::vector sub; + App::DocumentObject* obj; + getReferenceAxis(obj, sub); + return buildLinkSingleSubPythonStr(obj, sub); +} + +double TaskExtrudeParameters::getXDirection(void) const +{ + return ui->XDirectionEdit->value(); +} + +double TaskExtrudeParameters::getYDirection(void) const +{ + return ui->YDirectionEdit->value(); +} + +double TaskExtrudeParameters::getZDirection(void) const +{ + return ui->ZDirectionEdit->value(); +} + +bool TaskExtrudeParameters::getReversed(void) const +{ + return ui->checkBoxReversed->isChecked(); +} + +bool TaskExtrudeParameters::getMidplane(void) const +{ + return ui->checkBoxMidplane->isChecked(); +} + +int TaskExtrudeParameters::getMode(void) const +{ + return ui->changeMode->currentIndex(); +} + +QString TaskExtrudeParameters::getFaceName(void) const +{ + // 'Up to face' mode + if (getMode() == 3) { + QVariant featureName = ui->lineFaceName->property("FeatureName"); + if (featureName.isValid()) { + QString faceName = ui->lineFaceName->property("FaceName").toString(); + return getFaceReference(featureName.toString(), faceName); + } + } + return QString::fromLatin1("None"); +} + +void TaskExtrudeParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->lengthEdit->blockSignals(true); + ui->lengthEdit2->blockSignals(true); + ui->offsetEdit->blockSignals(true); + ui->XDirectionEdit->blockSignals(true); + ui->YDirectionEdit->blockSignals(true); + ui->ZDirectionEdit->blockSignals(true); + ui->directionCB->blockSignals(true); + int index = ui->directionCB->currentIndex(); + ui->directionCB->clear(); + ui->directionCB->addItem(tr("Sketch normal")); + ui->directionCB->addItem(tr("Select reference...")); + ui->directionCB->addItem(tr("Custom direction")); + ui->directionCB->setCurrentIndex(index); + ui->lineFaceName->blockSignals(true); + ui->changeMode->blockSignals(true); + ui->retranslateUi(proxy); + translateModeList(ui->changeMode->currentIndex()); + + ui->lineFaceName->setPlaceholderText(tr("No face selected")); + QVariant featureName = ui->lineFaceName->property("FeatureName"); + if (featureName.isValid()) { + QStringList parts = ui->lineFaceName->text().split(QChar::fromLatin1(':')); + QByteArray upToFace = ui->lineFaceName->property("FaceName").toByteArray(); + int faceId = -1; + bool ok = false; + if (upToFace.indexOf("Face") == 0) { + faceId = upToFace.remove(0,4).toInt(&ok); + } + + if (ok) { + ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") + .arg(parts[0]) + .arg(tr("Face")) + .arg(faceId)); + } + else { + ui->lineFaceName->setText(parts[0]); + } + } + + ui->lengthEdit->blockSignals(false); + ui->lengthEdit2->blockSignals(false); + ui->offsetEdit->blockSignals(false); + ui->XDirectionEdit->blockSignals(false); + ui->YDirectionEdit->blockSignals(false); + ui->ZDirectionEdit->blockSignals(false); + ui->directionCB->blockSignals(false); + ui->lineFaceName->blockSignals(false); + ui->changeMode->blockSignals(false); + } +} + +void TaskExtrudeParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector& sub) const +{ + if (axesInList.empty()) + throw Base::RuntimeError("Not initialized!"); + + int num = ui->directionCB->currentIndex(); + const App::PropertyLinkSub& lnk = *(axesInList[num]); + if (lnk.getValue() == 0) { + // Note: It is possible that a face of an object is directly padded/pocketed without defining a profile shape + obj = nullptr; + sub.clear(); + } + else { + PartDesign::ProfileBased* pcDirection = static_cast(vp->getObject()); + if (!pcDirection->getDocument()->isIn(lnk.getValue())) + throw Base::RuntimeError("Object was deleted"); + + obj = lnk.getValue(); + sub = lnk.getSubValues(); + } +} + +void TaskExtrudeParameters::saveHistory(void) +{ + // save the user values to history + ui->lengthEdit->pushToHistory(); + ui->lengthEdit2->pushToHistory(); + ui->offsetEdit->pushToHistory(); +} + +void TaskExtrudeParameters::onModeChanged(int) +{ + // implement in sub-class +} + +void TaskExtrudeParameters::updateUI(int) +{ + // implement in sub-class +} + +void TaskExtrudeParameters::translateModeList(int) +{ + // implement in sub-class +} + +#include "moc_TaskExtrudeParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h new file mode 100644 index 0000000000..14ad607300 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h @@ -0,0 +1,107 @@ +/*************************************************************************** + * Copyright (c) 2011 Juergen Riegel * + * * + * 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 * + * * + ***************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskExtrudeParameters_H +#define GUI_TASKVIEW_TaskExtrudeParameters_H + +#include +#include +#include + +#include "TaskSketchBasedParameters.h" +#include "ViewProviderSketchBased.h" + +class Ui_TaskPadParameters; + +namespace App { +class Property; +} + +namespace PartDesignGui { + + +class TaskExtrudeParameters : public TaskSketchBasedParameters +{ + Q_OBJECT + +public: + TaskExtrudeParameters(ViewProviderSketchBased *SketchBasedView, QWidget *parent, + const std::string& pixmapname, const QString& parname); + ~TaskExtrudeParameters(); + + virtual void saveHistory() override; + + void fillDirectionCombo(); + void addAxisToCombo(App::DocumentObject* linkObj, std::string linkSubname, QString itemText, + bool hasSketch = true); + +protected Q_SLOTS: + void onLengthChanged(double); + void onLength2Changed(double); + void onOffsetChanged(double); + void onDirectionCBChanged(int); + void onAlongSketchNormalChanged(bool); + void onDirectionToggled(bool); + void onXDirectionEditChanged(double); + void onYDirectionEditChanged(double); + void onZDirectionEditChanged(double); + void onMidplaneChanged(bool); + void onReversedChanged(bool); + void onButtonFace(const bool pressed = true); + void onFaceName(const QString& text); + virtual void onModeChanged(int); + +protected: + void setupDialog(bool); + void changeEvent(QEvent *e) override; + App::PropertyLinkSub* propReferenceAxis; + void getReferenceAxis(App::DocumentObject*& obj, std::vector& sub) const; + + double getLength(void) const; + double getLength2(void) const; + bool getAlongSketchNormal(void) const; + bool getCustom(void) const; + std::string getReferenceAxis(void) const; + double getXDirection(void) const; + double getYDirection(void) const; + double getZDirection(void) const; + double getOffset(void) const; + bool getReversed(void) const; + bool getMidplane(void) const; + int getMode(void) const; + QString getFaceName(void) const; + void onSelectionChanged(const Gui::SelectionChanges& msg) override; + virtual void translateModeList(int index); + virtual void updateUI(int index); + void updateDirectionEdits(void); + +protected: + QWidget* proxy; + std::unique_ptr ui; + bool selectionFace; + std::vector> axesInList; +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TaskExtrudeParameters_H diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index 03651459d5..d193222925 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -47,7 +47,6 @@ #include #include #include -#include "TaskSketchBasedParameters.h" #include "ReferenceSelection.h" using namespace PartDesignGui; @@ -56,158 +55,32 @@ using namespace Gui; /* TRANSLATOR PartDesignGui::TaskPadParameters */ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, bool newObj) - : TaskSketchBasedParameters(PadView, parent, "PartDesign_Pad", tr("Pad parameters")) - , ui(new Ui_TaskPadParameters) + : TaskExtrudeParameters(PadView, parent, "PartDesign_Pad", tr("Pad parameters")) { - // we need a separate container widget to add all controls to - proxy = new QWidget(this); - ui->setupUi(proxy); -#if QT_VERSION >= 0x040700 - ui->lineFaceName->setPlaceholderText(tr("No face selected")); -#endif - - this->groupLayout()->addWidget(proxy); + ui->offsetEdit->setToolTip(tr("Offset from face at which pad will end")); + ui->checkBoxReversed->setToolTip(tr("Reverses pad direction")); // set the history path ui->lengthEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PadLength")); ui->lengthEdit2->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PadLength2")); ui->offsetEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PadOffset")); - // Get the feature data - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - Base::Quantity l = pcPad->Length.getQuantityValue(); - Base::Quantity l2 = pcPad->Length2.getQuantityValue(); - bool alongNormal = pcPad->AlongSketchNormal.getValue(); - bool useCustom = pcPad->UseCustomVector.getValue(); - double xs = pcPad->Direction.getValue().x; - double ys = pcPad->Direction.getValue().y; - double zs = pcPad->Direction.getValue().z; - Base::Quantity off = pcPad->Offset.getQuantityValue(); - bool midplane = pcPad->Midplane.getValue(); - bool reversed = pcPad->Reversed.getValue(); - int index = pcPad->Type.getValue(); // must extract value here, clear() kills it! - App::DocumentObject* obj = pcPad->UpToFace.getValue(); - std::vector subStrings = pcPad->UpToFace.getSubValues(); - std::string upToFace; - int faceId = -1; - if ((obj != NULL) && !subStrings.empty()) { - upToFace = subStrings.front(); - if (upToFace.substr(0,4) == "Face") - faceId = std::atoi(&upToFace[4]); - } + setupDialog(newObj); +} - // set decimals for the direction edits - // do this here before the edits are filed to avoid rounding mistakes - int UserDecimals = Base::UnitsApi::getDecimals(); - ui->XDirectionEdit->setDecimals(UserDecimals); - ui->YDirectionEdit->setDecimals(UserDecimals); - ui->ZDirectionEdit->setDecimals(UserDecimals); - - // Fill data into dialog elements - // the direction combobox is later filled in updateUI() - ui->lengthEdit->setValue(l); - ui->lengthEdit2->setValue(l2); - ui->checkBoxAlongDirection->setChecked(alongNormal); - ui->checkBoxDirection->setChecked(useCustom); - onDirectionToggled(useCustom); - // disable to change the direction if not custom - if (!useCustom) { - ui->XDirectionEdit->setEnabled(false); - ui->YDirectionEdit->setEnabled(false); - ui->ZDirectionEdit->setEnabled(false); - } - ui->XDirectionEdit->setValue(xs); - ui->YDirectionEdit->setValue(ys); - ui->ZDirectionEdit->setValue(zs); - ui->offsetEdit->setValue(off); - - // Bind input fields to properties - ui->lengthEdit->bind(pcPad->Length); - ui->lengthEdit2->bind(pcPad->Length2); - ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.x"))); - ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.y"))); - ui->ZDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.z"))); - ui->offsetEdit->bind(pcPad->Offset); - - ui->checkBoxMidplane->setChecked(midplane); - // According to bug #0000521 the reversed option - // shouldn't be de-activated if the pad has a support face - ui->checkBoxReversed->setChecked(reversed); - - // Set object labels - if (obj && PartDesign::Feature::isDatum(obj)) { - ui->lineFaceName->setText(QString::fromUtf8(obj->Label.getValue())); - ui->lineFaceName->setProperty("FeatureName", QByteArray(obj->getNameInDocument())); - } - else if (obj && faceId >= 0) { - ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") - .arg(QString::fromUtf8(obj->Label.getValue())) - .arg(tr("Face")) - .arg(faceId)); - ui->lineFaceName->setProperty("FeatureName", QByteArray(obj->getNameInDocument())); - } - else { - ui->lineFaceName->clear(); - ui->lineFaceName->setProperty("FeatureName", QVariant()); - } - ui->lineFaceName->setProperty("FaceName", QByteArray(upToFace.c_str())); +TaskPadParameters::~TaskPadParameters() +{ +} +void TaskPadParameters::translateModeList(int index) +{ ui->changeMode->clear(); - ui->changeMode->insertItem(0, tr("Dimension")); - ui->changeMode->insertItem(1, tr("To last")); - ui->changeMode->insertItem(2, tr("To first")); - ui->changeMode->insertItem(3, tr("Up to face")); - ui->changeMode->insertItem(4, tr("Two dimensions")); + ui->changeMode->addItem(tr("Dimension")); + ui->changeMode->addItem(tr("To last")); + ui->changeMode->addItem(tr("To first")); + ui->changeMode->addItem(tr("Up to face")); + ui->changeMode->addItem(tr("Two dimensions")); ui->changeMode->setCurrentIndex(index); - - QMetaObject::connectSlotsByName(this); - - connect(ui->lengthEdit, SIGNAL(valueChanged(double)), - this, SLOT(onLengthChanged(double))); - connect(ui->lengthEdit2, SIGNAL(valueChanged(double)), - this, SLOT(onLength2Changed(double))); - connect(ui->directionCB, SIGNAL(activated(int)), - this, SLOT(onDirectionCBChanged(int))); - connect(ui->checkBoxAlongDirection, SIGNAL(toggled(bool)), - this, SLOT(onAlongSketchNormalChanged(bool))); - connect(ui->checkBoxDirection, SIGNAL(toggled(bool)), - this, SLOT(onDirectionToggled(bool))); - connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)), - this, SLOT(onXDirectionEditChanged(double))); - connect(ui->YDirectionEdit, SIGNAL(valueChanged(double)), - this, SLOT(onYDirectionEditChanged(double))); - connect(ui->ZDirectionEdit, SIGNAL(valueChanged(double)), - this, SLOT(onZDirectionEditChanged(double))); - connect(ui->offsetEdit, SIGNAL(valueChanged(double)), - this, SLOT(onOffsetChanged(double))); - connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), - this, SLOT(onMidplaneChanged(bool))); - connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), - this, SLOT(onReversedChanged(bool))); - connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), - this, SLOT(onModeChanged(int))); - connect(ui->buttonFace, SIGNAL(clicked()), - this, SLOT(onButtonFace())); - connect(ui->lineFaceName, SIGNAL(textEdited(QString)), - this, SLOT(onFaceName(QString))); - connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), - this, SLOT(onUpdateView(bool))); - - this->propReferenceAxis = &(pcPad->ReferenceAxis); - - // Due to signals attached after changes took took into effect we should update the UI now. - updateUI(index); - - // if it is a newly created object use the last value of the history - // TODO: newObj doesn't supplied normally by any caller (2015-07-24, Fat-Zer) - if (newObj) { - ui->lengthEdit->setToLastUsedValue(); - ui->lengthEdit->selectNumber(); - ui->lengthEdit2->setToLastUsedValue(); - ui->lengthEdit2->selectNumber(); - ui->offsetEdit->setToLastUsedValue(); - ui->offsetEdit->selectNumber(); - } } void TaskPadParameters::updateUI(int index) @@ -293,307 +166,6 @@ void TaskPadParameters::updateUI(int index) } } -void TaskPadParameters::onSelectionChanged(const Gui::SelectionChanges& msg) -{ - if (msg.Type == Gui::SelectionChanges::AddSelection) { - // if we have an edge selection for the pad direction - if (!selectionFace) { - std::vector edge; - App::DocumentObject* selObj; - if (getReferencedSelection(vp->getObject(), msg, selObj, edge) && selObj) { - exitSelectionMode(); - propReferenceAxis->setValue(selObj, edge); - recomputeFeature(); - // update direction combobox - fillDirectionCombo(); - } - } - else { // if we have a selection of a face - QString refText = onAddSelection(msg); - if (refText.length() > 0) { - ui->lineFaceName->blockSignals(true); - ui->lineFaceName->setText(refText); - ui->lineFaceName->setProperty("FeatureName", QByteArray(msg.pObjectName)); - ui->lineFaceName->setProperty("FaceName", QByteArray(msg.pSubName)); - ui->lineFaceName->blockSignals(false); - // Turn off reference selection mode - onButtonFace(false); - } - else { - ui->lineFaceName->blockSignals(true); - ui->lineFaceName->clear(); - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - ui->lineFaceName->blockSignals(false); - } - } - } else if (msg.Type == Gui::SelectionChanges::ClrSelection && selectionFace) { - ui->lineFaceName->blockSignals(true); - ui->lineFaceName->clear(); - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - ui->lineFaceName->blockSignals(false); - } -} - -void TaskPadParameters::onLengthChanged(double len) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Length.setValue(len); - recomputeFeature(); -} - -void TaskPadParameters::onLength2Changed(double len) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Length2.setValue(len); - recomputeFeature(); -} - -void TaskPadParameters::fillDirectionCombo() -{ - bool oldVal_blockUpdate = blockUpdate; - blockUpdate = true; - - if (axesInList.empty()) { - bool hasFace = false; - ui->directionCB->clear(); - // we can have sketches or faces - // for sketches just get the sketch normal - PartDesign::ProfileBased* pcFeat = static_cast(vp->getObject()); - Part::Part2DObject* pcSketch = dynamic_cast(pcFeat->Profile.getValue()); - // for faces we test if it is verified and if we can get its normal - if (!pcSketch) { - try { - Part::Feature* pcFeature = pcFeat->getVerifiedObject(); - Base::Vector3d SketchVector = pcFeat->getProfileNormal(); - Q_UNUSED(pcFeature) - Q_UNUSED(SketchVector) - hasFace = true; - } - catch (const Base::Exception& e) { - new App::DocumentObjectExecReturn(e.what()); - } - } - if (pcSketch) - addAxisToCombo(pcSketch, "N_Axis", tr("Sketch normal")); - else if (hasFace) - addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Face normal"), false); - // add the other entries - addAxisToCombo(0, std::string(), tr("Select reference...")); - // we start with the sketch normal as proposal for the custom direction - if (pcSketch) - addAxisToCombo(pcSketch, "N_Axis", tr("Custom direction")); - else if (hasFace) - addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Custom direction"), false); - } - - // add current link, if not in list - // first, figure out the item number for current axis - int indexOfCurrent = -1; - App::DocumentObject* ax = propReferenceAxis->getValue(); - const std::vector& subList = propReferenceAxis->getSubValues(); - for (size_t i = 0; i < axesInList.size(); i++) { - if (ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) { - indexOfCurrent = i; - break; - } - } - // if the axis is not yet listed in the combobox - if (indexOfCurrent == -1 && ax) { - assert(subList.size() <= 1); - std::string sub; - if (!subList.empty()) - sub = subList[0]; - addAxisToCombo(ax, sub, getRefStr(ax, subList)); - indexOfCurrent = axesInList.size() - 1; - // the axis is not the normal, thus enable along direction - ui->checkBoxAlongDirection->setEnabled(true); - // we don't have custom direction thus disable its settings - ui->XDirectionEdit->setEnabled(false); - ui->YDirectionEdit->setEnabled(false); - ui->ZDirectionEdit->setEnabled(false); - } - - // highlight either current index or set custom direction - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - bool hasCustom = pcPad->UseCustomVector.getValue(); - if (indexOfCurrent != -1 && !hasCustom) - ui->directionCB->setCurrentIndex(indexOfCurrent); - if (hasCustom) - ui->directionCB->setCurrentIndex(2); - - blockUpdate = oldVal_blockUpdate; -} - -void TaskPadParameters::addAxisToCombo(App::DocumentObject* linkObj, - std::string linkSubname, QString itemText, bool hasSketch) -{ - this->ui->directionCB->addItem(itemText); - this->axesInList.emplace_back(new App::PropertyLinkSub); - App::PropertyLinkSub& lnk = *(axesInList.back()); - // if we have a face, we leave the link empty since we cannot - // store the face normal as sublink - if (hasSketch) - lnk.setValue(linkObj, std::vector(1, linkSubname)); -} - -void TaskPadParameters::onDirectionCBChanged(int num) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - - if (axesInList.empty()) - return; - - // we use this scheme for 'num' - // 0: normal to sketch or face - // 1: selection mode - // 2: custom - // 3-x: edges selected in the 3D model - - // check the axis - // when the link is empty we are either in selection mode - // or we are normal to a face - App::PropertyLinkSub& lnk = *(axesInList[num]); - if (num == 1) { - // enter reference selection mode - this->blockConnection(false); - // to distinguish that this is the direction selection - selectionFace = false; - TaskSketchBasedParameters::onSelectReference(true, true, false, true, true); - return; - } - else if (lnk.getValue() != 0) { - if (!pcPad->getDocument()->isIn(lnk.getValue())) { - Base::Console().Error("Object was deleted\n"); - return; - } - propReferenceAxis->Paste(lnk); - } - - // in case the user is in selection mode, but changed his mind before selecting anything - exitSelectionMode(); - - // disable AlongSketchNormal when the direction is already normal - if (num == 0) - ui->checkBoxAlongDirection->setEnabled(false); - else - ui->checkBoxAlongDirection->setEnabled(true); - // if custom direction is used, show it - if (num == 2) { - ui->checkBoxDirection->setChecked(true); - pcPad->UseCustomVector.setValue(true); - } - else { - pcPad->UseCustomVector.setValue(false); - } - // if we dont use custom direction, only allow to show its direction - if (num != 2) { - ui->XDirectionEdit->setEnabled(false); - ui->YDirectionEdit->setEnabled(false); - ui->ZDirectionEdit->setEnabled(false); - } - else { - ui->XDirectionEdit->setEnabled(true); - ui->YDirectionEdit->setEnabled(true); - ui->ZDirectionEdit->setEnabled(true); - } - // recompute and update the direction - pcPad->ReferenceAxis.setValue(lnk.getValue(), lnk.getSubValues()); - try { - recomputeFeature(); - } - catch (const Base::Exception& e) { - e.ReportException(); - } - updateDirectionEdits(); -} - -void TaskPadParameters::onAlongSketchNormalChanged(bool on) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->AlongSketchNormal.setValue(on); - recomputeFeature(); -} - -void TaskPadParameters::onDirectionToggled(bool on) -{ - if (on) - ui->groupBoxDirection->show(); - else - ui->groupBoxDirection->hide(); -} - -void TaskPadParameters::onXDirectionEditChanged(double len) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Direction.setValue(len, pcPad->Direction.getValue().y, pcPad->Direction.getValue().z); - recomputeFeature(); - // checking for case of a null vector is done in FeatureExtrude.cpp - // if there was a null vector, the normal vector of the sketch is used. - // therefore the vector component edits must be updated - updateDirectionEdits(); -} - -void TaskPadParameters::onYDirectionEditChanged(double len) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Direction.setValue(pcPad->Direction.getValue().x, len, pcPad->Direction.getValue().z); - recomputeFeature(); - updateDirectionEdits(); -} - -void TaskPadParameters::onZDirectionEditChanged(double len) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Direction.setValue(pcPad->Direction.getValue().x, pcPad->Direction.getValue().y, len); - recomputeFeature(); - updateDirectionEdits(); -} - -void TaskPadParameters::updateDirectionEdits() -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - // we don't want to execute the onChanged edits, but just update their contents - ui->XDirectionEdit->blockSignals(true); - ui->YDirectionEdit->blockSignals(true); - ui->ZDirectionEdit->blockSignals(true); - ui->XDirectionEdit->setValue(pcPad->Direction.getValue().x); - ui->YDirectionEdit->setValue(pcPad->Direction.getValue().y); - ui->ZDirectionEdit->setValue(pcPad->Direction.getValue().z); - ui->XDirectionEdit->blockSignals(false); - ui->YDirectionEdit->blockSignals(false); - ui->ZDirectionEdit->blockSignals(false); -} - -void TaskPadParameters::onOffsetChanged(double len) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Offset.setValue(len); - recomputeFeature(); -} - -void TaskPadParameters::onMidplaneChanged(bool on) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Midplane.setValue(on); - // reversed is not sensible when midplane - ui->checkBoxReversed->setEnabled(!on); - recomputeFeature(); -} - -void TaskPadParameters::onReversedChanged(bool on) -{ - PartDesign::Pad* pcPad = static_cast(vp->getObject()); - pcPad->Reversed.setValue(on); - // midplane is not sensible when reversed - ui->checkBoxMidplane->setEnabled(!on); - // update the direction - recomputeFeature(); - updateDirectionEdits(); - -} - void TaskPadParameters::onModeChanged(int index) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); @@ -615,220 +187,6 @@ void TaskPadParameters::onModeChanged(int index) recomputeFeature(); } -void TaskPadParameters::onButtonFace(const bool pressed) -{ - this->blockConnection(!pressed); - - // to distinguish that this is the direction selection - selectionFace = true; - - // only faces are allowed - TaskSketchBasedParameters::onSelectReference(pressed, false, true, false); - - // Update button if onButtonFace() is called explicitly - ui->buttonFace->setChecked(pressed); -} - -void TaskPadParameters::onFaceName(const QString& text) -{ - if (text.isEmpty()) { - // if user cleared the text field then also clear the properties - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - } - else { - // expect that the label of an object is used - QStringList parts = text.split(QChar::fromLatin1(':')); - QString label = parts[0]; - QVariant name = objectNameByLabel(label, ui->lineFaceName->property("FeatureName")); - if (name.isValid()) { - parts[0] = name.toString(); - QString uptoface = parts.join(QString::fromLatin1(":")); - ui->lineFaceName->setProperty("FeatureName", name); - ui->lineFaceName->setProperty("FaceName", setUpToFace(uptoface)); - } - else { - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - } - } -} - -double TaskPadParameters::getLength(void) const -{ - return ui->lengthEdit->value().getValue(); -} - -double TaskPadParameters::getLength2(void) const -{ - return ui->lengthEdit2->value().getValue(); -} - -bool TaskPadParameters::getAlongSketchNormal(void) const -{ - return ui->checkBoxAlongDirection->isChecked(); -} - -bool TaskPadParameters::getCustom(void) const -{ - // index 2 is hardcoded to custom vector - return ui->directionCB->currentIndex() == 2 ? true : false; -} - -std::string TaskPadParameters::getReferenceAxis(void) const -{ - std::vector sub; - App::DocumentObject* obj; - getReferenceAxis(obj, sub); - return buildLinkSingleSubPythonStr(obj, sub); -} - -double TaskPadParameters::getXDirection(void) const -{ - return ui->XDirectionEdit->value(); -} - -double TaskPadParameters::getYDirection(void) const -{ - return ui->YDirectionEdit->value(); -} - -double TaskPadParameters::getZDirection(void) const -{ - return ui->ZDirectionEdit->value(); -} - -double TaskPadParameters::getOffset(void) const -{ - return ui->offsetEdit->value().getValue(); -} - -bool TaskPadParameters::getReversed(void) const -{ - return ui->checkBoxReversed->isChecked(); -} - -bool TaskPadParameters::getMidplane(void) const -{ - return ui->checkBoxMidplane->isChecked(); -} - -int TaskPadParameters::getMode(void) const -{ - return ui->changeMode->currentIndex(); -} - -QString TaskPadParameters::getFaceName(void) const -{ - // 'Up to face' mode - if (getMode() == 3) { - QVariant featureName = ui->lineFaceName->property("FeatureName"); - if (featureName.isValid()) { - QString faceName = ui->lineFaceName->property("FaceName").toString(); - return getFaceReference(featureName.toString(), faceName); - } - } - return QString::fromLatin1("None"); -} - -TaskPadParameters::~TaskPadParameters() -{ -} - -void TaskPadParameters::changeEvent(QEvent *e) -{ - TaskBox::changeEvent(e); - if (e->type() == QEvent::LanguageChange) { - ui->lengthEdit->blockSignals(true); - ui->lengthEdit2->blockSignals(true); - ui->XDirectionEdit->blockSignals(true); - ui->YDirectionEdit->blockSignals(true); - ui->ZDirectionEdit->blockSignals(true); - ui->directionCB->blockSignals(true); - int index = ui->directionCB->currentIndex(); - ui->directionCB->clear(); - ui->directionCB->addItem(tr("Sketch normal")); - ui->directionCB->addItem(tr("Select reference...")); - ui->directionCB->addItem(tr("Custom direction")); - ui->directionCB->setCurrentIndex(index); - ui->offsetEdit->blockSignals(true); - ui->lineFaceName->blockSignals(true); - ui->changeMode->blockSignals(true); - index = ui->changeMode->currentIndex(); - ui->retranslateUi(proxy); - ui->changeMode->clear(); - ui->changeMode->addItem(tr("Dimension")); - ui->changeMode->addItem(tr("To last")); - ui->changeMode->addItem(tr("To first")); - ui->changeMode->addItem(tr("Up to face")); - ui->changeMode->addItem(tr("Two dimensions")); - ui->changeMode->setCurrentIndex(index); - - ui->lineFaceName->setPlaceholderText(tr("No face selected")); - QVariant featureName = ui->lineFaceName->property("FeatureName"); - if (featureName.isValid()) { - QStringList parts = ui->lineFaceName->text().split(QChar::fromLatin1(':')); - QByteArray upToFace = ui->lineFaceName->property("FaceName").toByteArray(); - int faceId = -1; - bool ok = false; - if (upToFace.indexOf("Face") == 0) { - faceId = upToFace.remove(0,4).toInt(&ok); - } - - if (ok) { - ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") - .arg(parts[0]) - .arg(tr("Face")) - .arg(faceId)); - } - else { - ui->lineFaceName->setText(parts[0]); - } - } - - ui->lengthEdit->blockSignals(false); - ui->lengthEdit2->blockSignals(false); - ui->XDirectionEdit->blockSignals(false); - ui->YDirectionEdit->blockSignals(false); - ui->ZDirectionEdit->blockSignals(false); - ui->directionCB->blockSignals(false); - ui->offsetEdit->blockSignals(false); - ui->lineFaceName->blockSignals(false); - ui->changeMode->blockSignals(false); - } -} - -void TaskPadParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector& sub) const -{ - if (axesInList.empty()) - throw Base::RuntimeError("Not initialized!"); - - int num = ui->directionCB->currentIndex(); - const App::PropertyLinkSub& lnk = *(axesInList[num]); - if (lnk.getValue() == 0) { - // Note: Is is possible that a face of an object is directly padded without defining a profile shape - obj = nullptr; - sub.clear(); - //throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet"); - } - else { - PartDesign::ProfileBased* pcDirection = static_cast(vp->getObject()); - if (!pcDirection->getDocument()->isIn(lnk.getValue())) - throw Base::RuntimeError("Object was deleted"); - - obj = lnk.getValue(); - sub = lnk.getSubValues(); - } -} - -void TaskPadParameters::saveHistory(void) -{ - // save the user values to history - ui->lengthEdit->pushToHistory(); - ui->lengthEdit2->pushToHistory(); - ui->offsetEdit->pushToHistory(); -} - void TaskPadParameters::apply() { auto obj = vp->getObject(); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.h b/src/Mod/PartDesign/Gui/TaskPadParameters.h index 174fe43fad..a3701e1588 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.h @@ -28,11 +28,9 @@ #include #include -#include "TaskSketchBasedParameters.h" +#include "TaskExtrudeParameters.h" #include "ViewProviderPad.h" -class Ui_TaskPadParameters; - namespace App { class Property; } @@ -44,7 +42,7 @@ class ViewProvider; namespace PartDesignGui { -class TaskPadParameters : public TaskSketchBasedParameters +class TaskPadParameters : public TaskExtrudeParameters { Q_OBJECT @@ -52,57 +50,12 @@ public: TaskPadParameters(ViewProviderPad *PadView, QWidget *parent = 0, bool newObj=false); ~TaskPadParameters(); - virtual void saveHistory() override; virtual void apply() override; - void fillDirectionCombo(); - void addAxisToCombo(App::DocumentObject* linkObj, std::string linkSubname, QString itemText, - bool hasSketch = true); - -private Q_SLOTS: - void onLengthChanged(double); - void onLength2Changed(double); - void onDirectionCBChanged(int); - void onAlongSketchNormalChanged(bool); - void onDirectionToggled(bool); - void onXDirectionEditChanged(double); - void onYDirectionEditChanged(double); - void onZDirectionEditChanged(double); - void onOffsetChanged(double); - void onMidplaneChanged(bool); - void onReversedChanged(bool); - void onButtonFace(const bool pressed = true); - void onFaceName(const QString& text); - void onModeChanged(int); - -protected: - void changeEvent(QEvent *e) override; - App::PropertyLinkSub* propReferenceAxis; - void getReferenceAxis(App::DocumentObject*& obj, std::vector& sub) const; - private: - double getLength(void) const; - double getLength2(void) const; - bool getAlongSketchNormal(void) const; - bool getCustom(void) const; - std::string getReferenceAxis(void) const; - double getXDirection(void) const; - double getYDirection(void) const; - double getZDirection(void) const; - double getOffset(void) const; - bool getReversed(void) const; - bool getMidplane(void) const; - int getMode(void) const; - QString getFaceName(void) const; - void onSelectionChanged(const Gui::SelectionChanges& msg) override; - void updateUI(int index); - void updateDirectionEdits(void); - -private: - QWidget* proxy; - std::unique_ptr ui; - bool selectionFace; - std::vector> axesInList; + void onModeChanged(int index) override; + void translateModeList(int index) override; + void updateUI(int index) override; }; /// simulation dialog for the TaskView diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.ui b/src/Mod/PartDesign/Gui/TaskPadParameters.ui index 026cd8cd77..50967168dc 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.ui @@ -58,9 +58,6 @@ - - Offset from face at which pad will end - false @@ -256,9 +253,6 @@ measured along the specified direction - - Reverses pad direction - Reversed diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp index c41d0d9a0c..d31f2e769d 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp @@ -30,7 +30,7 @@ # include #endif -#include "ui_TaskPocketParameters.h" +#include "ui_TaskPadParameters.h" #include "TaskPocketParameters.h" #include #include @@ -45,7 +45,6 @@ #include #include #include -#include "TaskSketchBasedParameters.h" #include "ReferenceSelection.h" using namespace PartDesignGui; @@ -54,157 +53,33 @@ using namespace Gui; /* TRANSLATOR PartDesignGui::TaskPocketParameters */ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidget *parent, bool newObj) - : TaskSketchBasedParameters(PocketView, parent, "PartDesign_Pocket", tr("Pocket parameters")) - , ui(new Ui_TaskPocketParameters) + : TaskExtrudeParameters(PocketView, parent, "PartDesign_Pocket", tr("Pocket parameters")) , oldLength(0) { - // we need a separate container widget to add all controls to - proxy = new QWidget(this); - ui->setupUi(proxy); -#if QT_VERSION >= 0x040700 - ui->lineFaceName->setPlaceholderText(tr("No face selected")); -#endif - - this->groupLayout()->addWidget(proxy); + ui->offsetEdit->setToolTip(tr("Offset from face at which pocket will end")); + ui->checkBoxReversed->setToolTip(tr("Reverses pocket direction")); // set the history path ui->lengthEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PocketLength")); ui->lengthEdit2->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PocketLength2")); ui->offsetEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PocketOffset")); - // Get the feature data - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - Base::Quantity l = pcPocket->Length.getQuantityValue(); - Base::Quantity l2 = pcPocket->Length2.getQuantityValue(); - Base::Quantity off = pcPocket->Offset.getQuantityValue(); - bool alongNormal = pcPocket->AlongSketchNormal.getValue(); - bool useCustom = pcPocket->UseCustomVector.getValue(); - double xs = pcPocket->Direction.getValue().x; - double ys = pcPocket->Direction.getValue().y; - double zs = pcPocket->Direction.getValue().z; - bool midplane = pcPocket->Midplane.getValue(); - bool reversed = pcPocket->Reversed.getValue(); - int index = pcPocket->Type.getValue(); // must extract value here, clear() kills it! - App::DocumentObject* obj = pcPocket->UpToFace.getValue(); - std::vector subStrings = pcPocket->UpToFace.getSubValues(); - std::string upToFace; - int faceId = -1; - if ((obj != NULL) && !subStrings.empty()) { - upToFace = subStrings.front(); - if (upToFace.substr(0,4) == "Face") - faceId = std::atoi(&upToFace[4]); - } + setupDialog(newObj); +} - // set decimals for the direction edits - // do this here before the edits are filed to avoid rounding mistakes - int UserDecimals = Base::UnitsApi::getDecimals(); - ui->XDirectionEdit->setDecimals(UserDecimals); - ui->YDirectionEdit->setDecimals(UserDecimals); - ui->ZDirectionEdit->setDecimals(UserDecimals); - - // Fill data into dialog elements - // the direction combobox is later filled in updateUI() - ui->lengthEdit->setValue(l); - ui->lengthEdit2->setValue(l2); - ui->offsetEdit->setValue(off); - ui->checkBoxAlongDirection->setChecked(alongNormal); - ui->checkBoxDirection->setChecked(useCustom); - onDirectionToggled(useCustom); - // disable to change the direction if not custom - if (!useCustom) { - ui->XDirectionEdit->setEnabled(false); - ui->YDirectionEdit->setEnabled(false); - ui->ZDirectionEdit->setEnabled(false); - } - ui->XDirectionEdit->setValue(xs); - ui->YDirectionEdit->setValue(ys); - ui->ZDirectionEdit->setValue(zs); - ui->checkBoxMidplane->setChecked(midplane); - ui->checkBoxReversed->setChecked(reversed); - - // Set object labels - if (obj && PartDesign::Feature::isDatum(obj)) { - ui->lineFaceName->setText(QString::fromUtf8(obj->Label.getValue())); - ui->lineFaceName->setProperty("FeatureName", QByteArray(obj->getNameInDocument())); - } - else if (obj && faceId >= 0) { - ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") - .arg(QString::fromUtf8(obj->Label.getValue())) - .arg(tr("Face")) - .arg(faceId)); - ui->lineFaceName->setProperty("FeatureName", QByteArray(obj->getNameInDocument())); - } - else { - ui->lineFaceName->clear(); - ui->lineFaceName->setProperty("FeatureName", QVariant()); - } - - ui->lineFaceName->setProperty("FaceName", QByteArray(upToFace.c_str())); +TaskPocketParameters::~TaskPocketParameters() +{ +} +void TaskPocketParameters::translateModeList(int index) +{ ui->changeMode->clear(); - ui->changeMode->insertItem(0, tr("Dimension")); - ui->changeMode->insertItem(1, tr("Through all")); - ui->changeMode->insertItem(2, tr("To first")); - ui->changeMode->insertItem(3, tr("Up to face")); - ui->changeMode->insertItem(4, tr("Two dimensions")); + ui->changeMode->addItem(tr("Dimension")); + ui->changeMode->addItem(tr("Through all")); + ui->changeMode->addItem(tr("To first")); + ui->changeMode->addItem(tr("Up to face")); + ui->changeMode->addItem(tr("Two dimensions")); ui->changeMode->setCurrentIndex(index); - - // Bind input fields to properties - ui->lengthEdit->bind(pcPocket->Length); - ui->lengthEdit2->bind(pcPocket->Length2); - ui->offsetEdit->bind(pcPocket->Offset); - ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(pcPocket, std::string("Direction.x"))); - ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(pcPocket, std::string("Direction.y"))); - ui->ZDirectionEdit->bind(App::ObjectIdentifier::parse(pcPocket, std::string("Direction.z"))); - - QMetaObject::connectSlotsByName(this); - - connect(ui->lengthEdit, SIGNAL(valueChanged(double)), - this, SLOT(onLengthChanged(double))); - connect(ui->lengthEdit2, SIGNAL(valueChanged(double)), - this, SLOT(onLength2Changed(double))); - connect(ui->offsetEdit, SIGNAL(valueChanged(double)), - this, SLOT(onOffsetChanged(double))); - connect(ui->directionCB, SIGNAL(activated(int)), - this, SLOT(onDirectionCBChanged(int))); - connect(ui->checkBoxAlongDirection, SIGNAL(toggled(bool)), - this, SLOT(onAlongSketchNormalChanged(bool))); - connect(ui->checkBoxDirection, SIGNAL(toggled(bool)), - this, SLOT(onDirectionToggled(bool))); - connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)), - this, SLOT(onXDirectionEditChanged(double))); - connect(ui->YDirectionEdit, SIGNAL(valueChanged(double)), - this, SLOT(onYDirectionEditChanged(double))); - connect(ui->ZDirectionEdit, SIGNAL(valueChanged(double)), - this, SLOT(onZDirectionEditChanged(double))); - connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), - this, SLOT(onMidplaneChanged(bool))); - connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), - this, SLOT(onReversedChanged(bool))); - connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), - this, SLOT(onModeChanged(int))); - connect(ui->buttonFace, SIGNAL(clicked()), - this, SLOT(onButtonFace())); - connect(ui->lineFaceName, SIGNAL(textEdited(QString)), - this, SLOT(onFaceName(QString))); - connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), - this, SLOT(onUpdateView(bool))); - - this->propReferenceAxis = &(pcPocket->ReferenceAxis); - - // Due to signals attached after changes took took into effect we should update the UI now. - updateUI(index); - - // if it is a newly created object use the last value of the history - // TODO: newObj doesn't supplied normally by any caller (2015-07-24, Fat-Zer) - if (newObj){ - ui->lengthEdit->setToLastUsedValue(); - ui->lengthEdit->selectNumber(); - ui->lengthEdit2->setToLastUsedValue(); - ui->lengthEdit2->selectNumber(); - ui->offsetEdit->setToLastUsedValue(); - ui->offsetEdit->selectNumber(); - } } void TaskPocketParameters::updateUI(int index) @@ -213,6 +88,7 @@ void TaskPocketParameters::updateUI(int index) fillDirectionCombo(); // disable/hide everything unless we are sure we don't need it + // exception: the direction parameters are in any case visible bool isLengthEditVisible = false; bool isLengthEdit2Visible = false; bool isOffsetEditVisible = false; @@ -289,307 +165,6 @@ void TaskPocketParameters::updateUI(int index) } } -void TaskPocketParameters::onSelectionChanged(const Gui::SelectionChanges& msg) -{ - if (msg.Type == Gui::SelectionChanges::AddSelection) { - // if we have an edge selection for the pocket direction - if (!selectionFace) { - std::vector edge; - App::DocumentObject* selObj; - if (getReferencedSelection(vp->getObject(), msg, selObj, edge) && selObj) { - exitSelectionMode(); - propReferenceAxis->setValue(selObj, edge); - recomputeFeature(); - // update direction combobox - fillDirectionCombo(); - } - } - else { // if we have a selection of a face - QString refText = onAddSelection(msg); - if (refText.length() > 0) { - ui->lineFaceName->blockSignals(true); - ui->lineFaceName->setText(refText); - ui->lineFaceName->setProperty("FeatureName", QByteArray(msg.pObjectName)); - ui->lineFaceName->setProperty("FaceName", QByteArray(msg.pSubName)); - ui->lineFaceName->blockSignals(false); - // Turn off reference selection mode - onButtonFace(false); - } - else { - ui->lineFaceName->blockSignals(true); - ui->lineFaceName->clear(); - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - ui->lineFaceName->blockSignals(false); - } - } - } else if (msg.Type == Gui::SelectionChanges::ClrSelection) { - ui->lineFaceName->blockSignals(true); - ui->lineFaceName->clear(); - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - ui->lineFaceName->blockSignals(false); - } -} - -void TaskPocketParameters::onLengthChanged(double len) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Length.setValue(len); - recomputeFeature(); -} - -void TaskPocketParameters::onLength2Changed(double len) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Length2.setValue(len); - recomputeFeature(); -} - -void TaskPocketParameters::onOffsetChanged(double len) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Offset.setValue(len); - recomputeFeature(); -} - -void TaskPocketParameters::fillDirectionCombo() -{ - bool oldVal_blockUpdate = blockUpdate; - blockUpdate = true; - - if (axesInList.empty()) { - bool hasFace = false; - ui->directionCB->clear(); - // we can have sketches or faces - // for sketches just get the sketch normal - PartDesign::ProfileBased* pcFeat = static_cast(vp->getObject()); - Part::Part2DObject* pcSketch = dynamic_cast(pcFeat->Profile.getValue()); - // for faces we test if it is verified and if we can get its normal - if (!pcSketch) { - try { - Part::Feature* pcFeature = pcFeat->getVerifiedObject(); - Base::Vector3d SketchVector = pcFeat->getProfileNormal(); - Q_UNUSED(pcFeature) - Q_UNUSED(SketchVector) - hasFace = true; - } - catch (const Base::Exception& e) { - new App::DocumentObjectExecReturn(e.what()); - } - } - if (pcSketch) - addAxisToCombo(pcSketch, "N_Axis", tr("Sketch normal")); - else if (hasFace) - addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Face normal"), false); - // add the other entries - addAxisToCombo(0, std::string(), tr("Select reference...")); - // we start with the sketch normal as proposal for the custom direction - if (pcSketch) - addAxisToCombo(pcSketch, "N_Axis", tr("Custom direction")); - else if (hasFace) - addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Custom direction"), false); - } - - // add current link, if not in list - // first, figure out the item number for current axis - int indexOfCurrent = -1; - App::DocumentObject* ax = propReferenceAxis->getValue(); - const std::vector& subList = propReferenceAxis->getSubValues(); - for (size_t i = 0; i < axesInList.size(); i++) { - if (ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) { - indexOfCurrent = i; - break; - } - } - // if the axis is not yet listed in the combobox - if (indexOfCurrent == -1 && ax) { - assert(subList.size() <= 1); - std::string sub; - if (!subList.empty()) - sub = subList[0]; - addAxisToCombo(ax, sub, getRefStr(ax, subList)); - indexOfCurrent = axesInList.size() - 1; - // the axis is not the normal, thus enable along direction - ui->checkBoxAlongDirection->setEnabled(true); - // we don't have custom direction thus disable its settings - ui->XDirectionEdit->setEnabled(false); - ui->YDirectionEdit->setEnabled(false); - ui->ZDirectionEdit->setEnabled(false); - } - - // highlight either current index or set custom direction - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - bool hasCustom = pcPocket->UseCustomVector.getValue(); - if (indexOfCurrent != -1 && !hasCustom) - ui->directionCB->setCurrentIndex(indexOfCurrent); - if (hasCustom) - ui->directionCB->setCurrentIndex(2); - - blockUpdate = oldVal_blockUpdate; -} - -void TaskPocketParameters::addAxisToCombo(App::DocumentObject* linkObj, - std::string linkSubname, QString itemText, bool hasSketch) -{ - this->ui->directionCB->addItem(itemText); - this->axesInList.emplace_back(new App::PropertyLinkSub); - App::PropertyLinkSub& lnk = *(axesInList.back()); - lnk.setValue(linkObj, std::vector(1, linkSubname)); - // if we have a face, we leave the link empty since we cannot - // store the face normal as sublink - if (hasSketch) - lnk.setValue(linkObj, std::vector(1, linkSubname)); -} - -void TaskPocketParameters::onDirectionCBChanged(int num) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - - if (axesInList.empty() || !pcPocket) - return; - - // we use this scheme for 'num' - // 0: normal to sketch or face - // 1: selection mode - // 2: custom - // 3-x: edges selected in the 3D model - - // check the axis - // when the link is empty we are either in selection mode - // or we are normal to a face - App::PropertyLinkSub& lnk = *(axesInList[num]); - if (num == 1) { - // enter reference selection mode - this->blockConnection(false); - // to distinguish that this is the direction selection - selectionFace = false; - TaskSketchBasedParameters::onSelectReference(true, true, false, true, true); - return; - } - else if (lnk.getValue() != 0) { - if (!pcPocket->getDocument()->isIn(lnk.getValue())) { - Base::Console().Error("Object was deleted\n"); - return; - } - propReferenceAxis->Paste(lnk); - } - - // in case the user is in selection mode, but changed his mind before selecting anything - exitSelectionMode(); - - // disable AlongSketchNormal when the direction is already normal - if (num == 0) - ui->checkBoxAlongDirection->setEnabled(false); - else - ui->checkBoxAlongDirection->setEnabled(true); - // if custom direction is used, show it - if (num == 2) { - ui->checkBoxDirection->setChecked(true); - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->UseCustomVector.setValue(true); - } - else { - pcPocket->UseCustomVector.setValue(false); - } - // if we dont use custom direction, only allow to show its direction - if (num != 2) { - ui->XDirectionEdit->setEnabled(false); - ui->YDirectionEdit->setEnabled(false); - ui->ZDirectionEdit->setEnabled(false); - } - else { - ui->XDirectionEdit->setEnabled(true); - ui->YDirectionEdit->setEnabled(true); - ui->ZDirectionEdit->setEnabled(true); - } - // recompute and update the direction - pcPocket->ReferenceAxis.setValue(lnk.getValue(), lnk.getSubValues()); - try { - recomputeFeature(); - } - catch (const Base::Exception& e) { - e.ReportException(); - } - updateDirectionEdits(); -} - -void TaskPocketParameters::onAlongSketchNormalChanged(bool on) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->AlongSketchNormal.setValue(on); - recomputeFeature(); -} - -void TaskPocketParameters::onDirectionToggled(bool on) -{ - if (on) - ui->groupBoxDirection->show(); - else - ui->groupBoxDirection->hide(); -} - -void TaskPocketParameters::onXDirectionEditChanged(double len) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Direction.setValue(len, pcPocket->Direction.getValue().y, pcPocket->Direction.getValue().z); - recomputeFeature(); - // checking for case of a null vector is done in FeatureExtrude.cpp - // if there was a null vector, the normal vector of the sketch is used. - // therefore the vector component edits must be updated - updateDirectionEdits(); -} - -void TaskPocketParameters::onYDirectionEditChanged(double len) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Direction.setValue(pcPocket->Direction.getValue().x, len, pcPocket->Direction.getValue().z); - recomputeFeature(); - updateDirectionEdits(); -} - -void TaskPocketParameters::onZDirectionEditChanged(double len) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Direction.setValue(pcPocket->Direction.getValue().x, pcPocket->Direction.getValue().y, len); - recomputeFeature(); - updateDirectionEdits(); -} - -void TaskPocketParameters::updateDirectionEdits() -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - // we don't want to execute the onChanged edits, but just update their contents - ui->XDirectionEdit->blockSignals(true); - ui->YDirectionEdit->blockSignals(true); - ui->ZDirectionEdit->blockSignals(true); - ui->XDirectionEdit->setValue(pcPocket->Direction.getValue().x); - ui->YDirectionEdit->setValue(pcPocket->Direction.getValue().y); - ui->ZDirectionEdit->setValue(pcPocket->Direction.getValue().z); - ui->XDirectionEdit->blockSignals(false); - ui->YDirectionEdit->blockSignals(false); - ui->ZDirectionEdit->blockSignals(false); -} - -void TaskPocketParameters::onMidplaneChanged(bool on) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Midplane.setValue(on); - ui->checkBoxReversed->setEnabled(!on); - recomputeFeature(); -} - -void TaskPocketParameters::onReversedChanged(bool on) -{ - PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - pcPocket->Reversed.setValue(on); - // midplane is not sensible when reversed - ui->checkBoxMidplane->setEnabled(!on); - // update the direction - recomputeFeature(); - updateDirectionEdits(); -} - void TaskPocketParameters::onModeChanged(int index) { PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); @@ -628,214 +203,6 @@ void TaskPocketParameters::onModeChanged(int index) recomputeFeature(); } -void TaskPocketParameters::onButtonFace(const bool pressed) -{ - this->blockConnection(!pressed); - - TaskSketchBasedParameters::onSelectReference(pressed, false, true, false); - - // Update button if onButtonFace() is called explicitly - ui->buttonFace->setChecked(pressed); -} - -void TaskPocketParameters::onFaceName(const QString& text) -{ - if (text.isEmpty()) { - // if user cleared the text field then also clear the properties - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - } - else { - // expect that the label of an object is used - QStringList parts = text.split(QChar::fromLatin1(':')); - QString label = parts[0]; - QVariant name = objectNameByLabel(label, ui->lineFaceName->property("FeatureName")); - if (name.isValid()) { - parts[0] = name.toString(); - QString uptoface = parts.join(QString::fromLatin1(":")); - ui->lineFaceName->setProperty("FeatureName", name); - ui->lineFaceName->setProperty("FaceName", setUpToFace(uptoface)); - } - else { - ui->lineFaceName->setProperty("FeatureName", QVariant()); - ui->lineFaceName->setProperty("FaceName", QVariant()); - } - } -} - -double TaskPocketParameters::getLength(void) const -{ - return ui->lengthEdit->value().getValue(); -} - -double TaskPocketParameters::getLength2(void) const -{ - return ui->lengthEdit2->value().getValue(); -} - -double TaskPocketParameters::getOffset(void) const -{ - return ui->offsetEdit->value().getValue(); -} - -bool TaskPocketParameters::getAlongSketchNormal(void) const -{ - return ui->checkBoxAlongDirection->isChecked(); -} - -bool TaskPocketParameters::getCustom(void) const -{ - // index 2 is hardcoded to custom vector - return ui->directionCB->currentIndex() == 2 ? true : false; -} - -std::string TaskPocketParameters::getReferenceAxis(void) const -{ - std::vector sub; - App::DocumentObject* obj; - getReferenceAxis(obj, sub); - return buildLinkSingleSubPythonStr(obj, sub); -} - -double TaskPocketParameters::getXDirection(void) const -{ - return ui->XDirectionEdit->value(); -} - -double TaskPocketParameters::getYDirection(void) const -{ - return ui->YDirectionEdit->value(); -} - -double TaskPocketParameters::getZDirection(void) const -{ - return ui->ZDirectionEdit->value(); -} - -bool TaskPocketParameters::getReversed(void) const -{ - return ui->checkBoxReversed->isChecked(); -} - -bool TaskPocketParameters::getMidplane(void) const -{ - return ui->checkBoxMidplane->isChecked(); -} - -int TaskPocketParameters::getMode(void) const -{ - return ui->changeMode->currentIndex(); -} - -QString TaskPocketParameters::getFaceName(void) const -{ - // 'Up to face' mode - if (getMode() == 3) { - QVariant featureName = ui->lineFaceName->property("FeatureName"); - if (featureName.isValid()) { - QString faceName = ui->lineFaceName->property("FaceName").toString(); - return getFaceReference(featureName.toString(), faceName); - } - } - return QString::fromLatin1("None"); -} - -TaskPocketParameters::~TaskPocketParameters() -{ -} - -void TaskPocketParameters::changeEvent(QEvent *e) -{ - TaskBox::changeEvent(e); - if (e->type() == QEvent::LanguageChange) { - ui->lengthEdit->blockSignals(true); - ui->lengthEdit2->blockSignals(true); - ui->offsetEdit->blockSignals(true); - ui->XDirectionEdit->blockSignals(true); - ui->YDirectionEdit->blockSignals(true); - ui->ZDirectionEdit->blockSignals(true); - ui->directionCB->blockSignals(true); - int index = ui->directionCB->currentIndex(); - ui->directionCB->clear(); - ui->directionCB->addItem(tr("Sketch normal")); - ui->directionCB->addItem(tr("Select reference...")); - ui->directionCB->addItem(tr("Custom direction")); - ui->directionCB->setCurrentIndex(index); - ui->lineFaceName->blockSignals(true); - ui->changeMode->blockSignals(true); - index = ui->changeMode->currentIndex(); - ui->retranslateUi(proxy); - ui->changeMode->clear(); - ui->changeMode->addItem(tr("Dimension")); - ui->changeMode->addItem(tr("Through all")); - ui->changeMode->addItem(tr("To first")); - ui->changeMode->addItem(tr("Up to face")); - ui->changeMode->addItem(tr("Two dimensions")); - ui->changeMode->setCurrentIndex(index); - -#if QT_VERSION >= 0x040700 - ui->lineFaceName->setPlaceholderText(tr("No face selected")); -#endif - QVariant featureName = ui->lineFaceName->property("FeatureName"); - if (featureName.isValid()) { - QStringList parts = ui->lineFaceName->text().split(QChar::fromLatin1(':')); - QByteArray upToFace = ui->lineFaceName->property("FaceName").toByteArray(); - int faceId = -1; - bool ok = false; - if (upToFace.indexOf("Face") == 0) { - faceId = upToFace.remove(0,4).toInt(&ok); - } - - if (ok) { - ui->lineFaceName->setText(QString::fromLatin1("%1:%2%3") - .arg(parts[0]) - .arg(tr("Face")) - .arg(faceId)); - } - else { - ui->lineFaceName->setText(parts[0]); - } - } - - ui->lengthEdit->blockSignals(false); - ui->lengthEdit2->blockSignals(false); - ui->offsetEdit->blockSignals(false); - ui->lineFaceName->blockSignals(false); - ui->changeMode->blockSignals(false); - } -} - -void TaskPocketParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector& sub) const -{ - if (axesInList.empty()) - throw Base::RuntimeError("Not initialized!"); - - int num = ui->directionCB->currentIndex(); - const App::PropertyLinkSub& lnk = *(axesInList[num]); - if (lnk.getValue() == 0) { - // Note: Is is possible that a face of an object is directly pocketed without defining a profile shape - obj = nullptr; - sub.clear(); - //throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet"); - } - else { - PartDesign::ProfileBased* pcDirection = static_cast(vp->getObject()); - if (!pcDirection->getDocument()->isIn(lnk.getValue())) - throw Base::RuntimeError("Object was deleted"); - - obj = lnk.getValue(); - sub = lnk.getSubValues(); - } -} - -void TaskPocketParameters::saveHistory(void) -{ - // save the user values to history - ui->lengthEdit->pushToHistory(); - ui->lengthEdit2->pushToHistory(); - ui->offsetEdit->pushToHistory(); -} - void TaskPocketParameters::apply() { auto obj = vp->getObject(); diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.h b/src/Mod/PartDesign/Gui/TaskPocketParameters.h index db6e8abdef..0621ac3056 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.h @@ -28,11 +28,9 @@ #include #include -#include "TaskSketchBasedParameters.h" +#include "TaskExtrudeParameters.h" #include "ViewProviderPocket.h" -class Ui_TaskPocketParameters; - namespace App { class Property; } @@ -44,7 +42,7 @@ class ViewProvider; namespace PartDesignGui { -class TaskPocketParameters : public TaskSketchBasedParameters +class TaskPocketParameters : public TaskExtrudeParameters { Q_OBJECT @@ -52,59 +50,15 @@ public: TaskPocketParameters(ViewProviderPocket *PocketView, QWidget *parent = 0, bool newObj=false); ~TaskPocketParameters(); - virtual void saveHistory() override; virtual void apply() override; - void fillDirectionCombo(); - void addAxisToCombo(App::DocumentObject* linkObj, std::string linkSubname, QString itemText, - bool hasSketch = true); - -private Q_SLOTS: - void onLengthChanged(double); - void onLength2Changed(double); - void onOffsetChanged(double); - void onDirectionCBChanged(int); - void onAlongSketchNormalChanged(bool); - void onDirectionToggled(bool); - void onXDirectionEditChanged(double); - void onYDirectionEditChanged(double); - void onZDirectionEditChanged(double); - void onMidplaneChanged(bool); - void onReversedChanged(bool); - void onButtonFace(const bool pressed = true); - void onFaceName(const QString& text); - void onModeChanged(int); - -protected: - void changeEvent(QEvent *e) override; - App::PropertyLinkSub* propReferenceAxis; - void getReferenceAxis(App::DocumentObject*& obj, std::vector& sub) const; +private: + void onModeChanged(int index) override; + void translateModeList(int index) override; + void updateUI(int index) override; private: - double getLength(void) const; - double getLength2(void) const; - double getOffset(void) const; - bool getAlongSketchNormal(void) const; - bool getCustom(void) const; - std::string getReferenceAxis(void) const; - double getXDirection(void) const; - double getYDirection(void) const; - double getZDirection(void) const; - int getMode(void) const; - bool getMidplane(void) const; - bool getReversed(void) const; - QString getFaceName(void) const; - - void onSelectionChanged(const Gui::SelectionChanges& msg) override; - void updateUI(int index); - void updateDirectionEdits(void); - -private: - QWidget* proxy; - std::unique_ptr ui; double oldLength; - bool selectionFace; - std::vector> axesInList; }; /// simulation dialog for the TaskView diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui index 4b1171b122..e67e7f6b77 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui @@ -58,9 +58,6 @@ - - Offset from face at which pocket will end - false