Merge pull request #7193 from AjinkyaDahale/pd-more-revol-options

PD: more options for revolution/groove
This commit is contained in:
Adrián Insaurralde Avalos
2023-11-20 13:36:34 -03:00
committed by GitHub
7 changed files with 941 additions and 77 deletions

View File

@@ -49,7 +49,8 @@ using namespace Gui;
TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* RevolutionView, QWidget *parent)
: TaskSketchBasedParameters(RevolutionView, parent, "PartDesign_Revolution", tr("Revolution parameters")),
ui(new Ui_TaskRevolutionParameters),
proxy(new QWidget(this))
proxy(new QWidget(this)),
isGroove(false)
{
// we need a separate container widget to add all controls to
ui->setupUi(proxy);
@@ -59,34 +60,36 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider*
// bind property mirrors
if (auto *rev = dynamic_cast<PartDesign::Revolution *>(vp->getObject())) {
this->propAngle = &(rev->Angle);
this->propAngle2 = &(rev->Angle2);
this->propMidPlane = &(rev->Midplane);
this->propReferenceAxis = &(rev->ReferenceAxis);
this->propReversed = &(rev->Reversed);
this->propUpToFace = &(rev->UpToFace);
ui->revolveAngle->bind(rev->Angle);
ui->revolveAngle2->bind(rev->Angle2);
}
else if (auto *rev = dynamic_cast<PartDesign::Groove *>(vp->getObject())) {
isGroove = true;
this->propAngle = &(rev->Angle);
this->propAngle2 = &(rev->Angle2);
this->propMidPlane = &(rev->Midplane);
this->propReferenceAxis = &(rev->ReferenceAxis);
this->propReversed = &(rev->Reversed);
this->propUpToFace = &(rev->UpToFace);
ui->revolveAngle->bind(rev->Angle);
ui->revolveAngle2->bind(rev->Angle2);
}
else {
throw Base::TypeError("The object is neither a Groove nor a Revolution.");
}
ui->checkBoxMidplane->setChecked(propMidPlane->getValue());
ui->checkBoxReversed->setChecked(propReversed->getValue());
ui->revolveAngle->setValue(propAngle->getValue());
ui->revolveAngle->setMaximum(propAngle->getMaximum());
ui->revolveAngle->setMinimum(propAngle->getMinimum());
setupDialog();
blockUpdate = false;
updateUI();
connectSignals();
setFocus ();
setFocus();
// show the parts coordinate system axis for selection
PartDesign::Body * body = PartDesign::Body::findBodyOf ( vp->getObject () );
@@ -103,6 +106,54 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider*
}
}
void TaskRevolutionParameters::setupDialog()
{
ui->checkBoxMidplane->setChecked(propMidPlane->getValue());
ui->checkBoxReversed->setChecked(propReversed->getValue());
ui->revolveAngle->setValue(propAngle->getValue());
ui->revolveAngle->setMaximum(propAngle->getMaximum());
ui->revolveAngle->setMinimum(propAngle->getMinimum());
int index = 0;
// TODO: This should also be implemented for groove
if (!isGroove) {
PartDesign::Revolution* rev = static_cast<PartDesign::Revolution*>(vp->getObject());
ui->revolveAngle2->setValue(propAngle2->getValue());
ui->revolveAngle2->setMaximum(propAngle2->getMaximum());
ui->revolveAngle2->setMinimum(propAngle2->getMinimum());
index = rev->Type.getValue();
}
else {
PartDesign::Groove* rev = static_cast<PartDesign::Groove*>(vp->getObject());
ui->revolveAngle2->setValue(propAngle2->getValue());
ui->revolveAngle2->setMaximum(propAngle2->getMaximum());
ui->revolveAngle2->setMinimum(propAngle2->getMinimum());
index = rev->Type.getValue();
}
translateModeList(index);
}
void TaskRevolutionParameters::translateModeList(int index)
{
ui->changeMode->clear();
ui->changeMode->addItem(tr("Dimension"));
if (!isGroove) {
ui->changeMode->addItem(tr("To last"));
}
else {
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);
}
void TaskRevolutionParameters::fillAxisCombo(bool forceRefill)
{
Base::StateLocker lock(blockUpdate, true);
@@ -179,44 +230,213 @@ void TaskRevolutionParameters::addAxisToCombo(App::DocumentObject* linkObj,
lnk.setValue(linkObj,std::vector<std::string>(1,linkSubname));
}
void TaskRevolutionParameters::connectSignals()
void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod mode)
{
connect(ui->revolveAngle, qOverload<double>(&QuantitySpinBox::valueChanged), this,
&TaskRevolutionParameters::onAngleChanged);
connect(ui->axis, qOverload<int>(&QComboBox::activated), this,
&TaskRevolutionParameters::onAxisChanged);
connect(ui->checkBoxMidplane, &QCheckBox::toggled, this,
&TaskRevolutionParameters::onMidplane);
connect(ui->checkBoxReversed, &QCheckBox::toggled, this,
&TaskRevolutionParameters::onReversed);
connect(ui->checkBoxUpdateView, &QCheckBox::toggled, this,
&TaskRevolutionParameters::onUpdateView);
// disable/hide everything unless we are sure we don't need it
// exception: the direction parameters are in any case visible
bool isRevolveAngleVisible = false;
bool isRevolveAngle2Visible = false;
bool isMidplaneEnabled = false;
bool isMidplaneVisible = false;
bool isReversedEnabled = false;
bool isFaceEditEnabled = false;
if (mode == PartDesign::Revolution::RevolMethod::Dimension) {
isRevolveAngleVisible = true;
ui->revolveAngle->selectNumber();
QMetaObject::invokeMethod(ui->revolveAngle, "setFocus", Qt::QueuedConnection);
isMidplaneVisible = true;
isMidplaneEnabled = true;
// Reverse only makes sense if Midplane is not true
isReversedEnabled = !ui->checkBoxMidplane->isChecked();
}
else if (mode == PartDesign::Revolution::RevolMethod::ThroughAll && isGroove) {
isMidplaneEnabled = true;
isMidplaneVisible = true;
isReversedEnabled = !ui->checkBoxMidplane->isChecked();
}
else if (mode == PartDesign::Revolution::RevolMethod::ToLast && !isGroove) {
isReversedEnabled = true;
}
else if (mode == PartDesign::Revolution::RevolMethod::ToFirst) {
isReversedEnabled = true;
}
else if (mode == PartDesign::Revolution::RevolMethod::ToFace) {
isReversedEnabled = true;
isFaceEditEnabled = true;
QMetaObject::invokeMethod(ui->lineFaceName, "setFocus", Qt::QueuedConnection);
// Go into reference selection mode if no face has been selected yet
if (ui->lineFaceName->property("FeatureName").isNull())
ui->buttonFace->setChecked(true);
}
else if (mode == PartDesign::Revolution::RevolMethod::TwoDimensions) {
isRevolveAngleVisible = true;
isRevolveAngle2Visible = true;
isReversedEnabled = true;
}
ui->revolveAngle->setVisible(isRevolveAngleVisible);
ui->revolveAngle->setEnabled(isRevolveAngleVisible);
ui->labelAngle->setVisible(isRevolveAngleVisible);
ui->revolveAngle2->setVisible(isRevolveAngle2Visible);
ui->revolveAngle2->setEnabled(isRevolveAngle2Visible);
ui->labelAngle2->setVisible(isRevolveAngle2Visible);
ui->checkBoxMidplane->setEnabled(isMidplaneEnabled);
ui->checkBoxMidplane->setVisible(isMidplaneVisible);
ui->checkBoxReversed->setEnabled(isReversedEnabled);
ui->buttonFace->setEnabled(isFaceEditEnabled);
ui->lineFaceName->setEnabled(isFaceEditEnabled);
if (!isFaceEditEnabled) {
ui->buttonFace->setChecked(false);
}
}
void TaskRevolutionParameters::updateUI()
void TaskRevolutionParameters::connectSignals()
{
connect(ui->revolveAngle, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this, &TaskRevolutionParameters::onAngleChanged);
connect(ui->revolveAngle2, qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this, &TaskRevolutionParameters::onAngle2Changed);
connect(ui->axis, qOverload<int>(&QComboBox::activated),
this, &TaskRevolutionParameters::onAxisChanged);
connect(ui->checkBoxMidplane, &QCheckBox::toggled,
this, &TaskRevolutionParameters::onMidplane);
connect(ui->checkBoxReversed, &QCheckBox::toggled,
this, &TaskRevolutionParameters::onReversed);
connect(ui->checkBoxUpdateView, &QCheckBox::toggled,
this, &TaskRevolutionParameters::onUpdateView);
connect(ui->changeMode, qOverload<int>(&QComboBox::currentIndexChanged),
this, &TaskRevolutionParameters::onModeChanged);
connect(ui->buttonFace, &QPushButton::toggled,
this, &TaskRevolutionParameters::onButtonFace);
connect(ui->lineFaceName, &QLineEdit::textEdited,
this, &TaskRevolutionParameters::onFaceName);
}
void TaskRevolutionParameters::updateUI(int index)
{
if (blockUpdate)
return;
Base::StateLocker lock(blockUpdate, true);
fillAxisCombo();
setCheckboxes(static_cast<PartDesign::Revolution::RevolMethod>(index));
}
void TaskRevolutionParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
{
if (msg.Type == Gui::SelectionChanges::AddSelection) {
if (selectionFace) {
QString refText = onAddSelection(msg);
if (refText.length() > 0) {
QSignalBlocker block(ui->lineFaceName);
ui->lineFaceName->setText(refText);
ui->lineFaceName->setProperty("FeatureName", QByteArray(msg.pObjectName));
ui->lineFaceName->setProperty("FaceName", QByteArray(msg.pSubName));
// Turn off reference selection mode
ui->buttonFace->setChecked(false);
}
else {
clearFaceName();
}
}
else {
exitSelectionMode();
std::vector<std::string> axis;
App::DocumentObject* selObj;
if (getReferencedSelection(vp->getObject(), msg, selObj, axis) && selObj) {
propReferenceAxis->setValue(selObj, axis);
exitSelectionMode();
std::vector<std::string> axis;
App::DocumentObject* selObj;
if (getReferencedSelection(vp->getObject(), msg, selObj, axis) && selObj) {
propReferenceAxis->setValue(selObj, axis);
recomputeFeature();
updateUI();
}
}
}
else if (msg.Type == Gui::SelectionChanges::ClrSelection && selectionFace) {
clearFaceName();
}
}
recomputeFeature();
updateUI();
void TaskRevolutionParameters::onButtonFace(const bool pressed)
{
// to distinguish that this is the direction selection
selectionFace = true;
// only faces are allowed
TaskSketchBasedParameters::onSelectReference(pressed ? AllowSelection::FACE : AllowSelection::NONE);
}
void TaskRevolutionParameters::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());
}
}
}
void TaskRevolutionParameters::translateFaceName()
{
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]);
}
}
}
QString TaskRevolutionParameters::getFaceName(void) const
{
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 TaskRevolutionParameters::clearFaceName()
{
QSignalBlocker block(ui->lineFaceName);
ui->lineFaceName->clear();
ui->lineFaceName->setProperty("FeatureName", QVariant());
ui->lineFaceName->setProperty("FaceName", QVariant());
}
void TaskRevolutionParameters::onAngleChanged(double len)
{
@@ -225,6 +445,14 @@ void TaskRevolutionParameters::onAngleChanged(double len)
recomputeFeature();
}
void TaskRevolutionParameters::onAngle2Changed(double len)
{
if (propAngle2)
propAngle2->setValue(len);
exitSelectionMode();
recomputeFeature();
}
void TaskRevolutionParameters::onAxisChanged(int num)
{
if (blockUpdate)
@@ -301,6 +529,42 @@ void TaskRevolutionParameters::onReversed(bool on)
recomputeFeature();
}
void TaskRevolutionParameters::onModeChanged(int index)
{
App::PropertyEnumeration* pcType;
if (!isGroove)
pcType = &(static_cast<PartDesign::Revolution*>(vp->getObject())->Type);
else
pcType = &(static_cast<PartDesign::Groove*>(vp->getObject())->Type);
switch (static_cast<PartDesign::Revolution::RevolMethod>(index)) {
case PartDesign::Revolution::RevolMethod::Dimension:
pcType->setValue("Angle");
// Avoid error message
// if (ui->revolveAngle->value() < Base::Quantity(Precision::Angular(), Base::Unit::Angle)) // TODO: Ensure radians/degree consistency
// ui->revolveAngle->setValue(5.0);
break;
case PartDesign::Revolution::RevolMethod::ToLast:
if (!isGroove)
pcType->setValue("UpToLast");
else
pcType->setValue("ThroughAll");
break;
case PartDesign::Revolution::RevolMethod::ToFirst:
pcType->setValue("UpToFirst");
break;
case PartDesign::Revolution::RevolMethod::ToFace:
pcType->setValue("UpToFace");
break;
case PartDesign::Revolution::RevolMethod::TwoDimensions:
pcType->setValue("TwoAngles");
break;
}
updateUI(index);
recomputeFeature();
}
void TaskRevolutionParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector<std::string>& sub) const
{
if (axesInList.empty())
@@ -354,6 +618,9 @@ void TaskRevolutionParameters::changeEvent(QEvent *event)
TaskBox::changeEvent(event);
if (event->type() == QEvent::LanguageChange) {
ui->retranslateUi(proxy);
// Translate mode items
translateModeList(ui->changeMode->currentIndex());
}
}
@@ -361,14 +628,22 @@ void TaskRevolutionParameters::apply()
{
//Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Revolution changed"));
ui->revolveAngle->apply();
ui->revolveAngle2->apply();
std::vector<std::string> sub;
App::DocumentObject* obj;
getReferenceAxis(obj, sub);
std::string axis = buildLinkSingleSubPythonStr(obj, sub);
auto tobj = vp->getObject();
FCMD_OBJ_CMD(tobj,"ReferenceAxis = " << axis);
FCMD_OBJ_CMD(tobj,"Midplane = " << (getMidplane() ? 1 : 0));
FCMD_OBJ_CMD(tobj,"Reversed = " << (getReversed() ? 1 : 0));
FCMD_OBJ_CMD(tobj, "ReferenceAxis = " << axis);
FCMD_OBJ_CMD(tobj, "Midplane = " << (getMidplane() ? 1 : 0));
FCMD_OBJ_CMD(tobj, "Reversed = " << (getReversed() ? 1 : 0));
int mode = ui->changeMode->currentIndex();
FCMD_OBJ_CMD(tobj, "Type = " << mode);
QString facename = QString::fromLatin1("None");
if (static_cast<PartDesign::Revolution::RevolMethod>(mode) == PartDesign::Revolution::RevolMethod::ToFace) {
facename = getFaceName();
}
FCMD_OBJ_CMD(tobj, "UpToFace = " << facename.toLatin1().data());
}
//**************************************************************************

View File

@@ -23,6 +23,8 @@
#ifndef GUI_TASKVIEW_TaskRevolutionParameters_H
#define GUI_TASKVIEW_TaskRevolutionParameters_H
#include <Mod/PartDesign/App/FeatureRevolution.h>
#include <Mod/PartDesign/App/FeatureGroove.h>
#include "TaskSketchBasedParameters.h"
#include "ViewProviderRevolution.h"
@@ -61,9 +63,13 @@ public:
private Q_SLOTS:
void onAngleChanged(double);
void onAngle2Changed(double);
void onAxisChanged(int);
void onMidplane(bool);
void onReversed(bool);
void onModeChanged(int);
void onButtonFace(const bool pressed = true);
void onFaceName(const QString& text);
protected:
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
@@ -71,21 +77,32 @@ protected:
void getReferenceAxis(App::DocumentObject *&obj, std::vector<std::string> &sub) const;
bool getMidplane() const;
bool getReversed() const;
QString getFaceName() const;
void setupDialog(void);
void setCheckboxes(PartDesign::Revolution::RevolMethod mode);
//mirrors of revolution's or groove's properties
//should have been done by inheriting revolution and groove from common class...
App::PropertyAngle* propAngle;
App::PropertyAngle* propAngle2;
App::PropertyBool* propReversed;
App::PropertyBool* propMidPlane;
App::PropertyLinkSub* propReferenceAxis;
App::PropertyLinkSub* propUpToFace;
private:
void connectSignals();
void updateUI();
void updateUI(int index=0); // TODO: Implement for index and remove default
void translateModeList(int index);
// TODO: This is common with extrude. Maybe send to superclass.
void translateFaceName();
void clearFaceName();
private:
std::unique_ptr<Ui_TaskRevolutionParameters> ui;
QWidget *proxy;
bool selectionFace;
bool isGroove;
/**
* @brief axesInList is the list of links corresponding to axis combo; must

View File

@@ -14,6 +14,26 @@
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayoutMode">
<item>
<widget class="QLabel" name="textLabelMode">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="changeMode">
<item>
<property name="text">
<string>Dimension</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -62,7 +82,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label">
<widget class="QLabel" name="labelAngle">
<property name="text">
<string>Angle:</string>
</property>
@@ -109,6 +129,56 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="labelAngle2">
<property name="text">
<string>2nd angle</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="revolveAngle2">
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="unit" stdset="0">
<string notr="true">deg</string>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QPushButton" name="buttonFace">
<property name="text">
<string>Face</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineFaceName"/>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">