PartDesign: Transform rework

This commit is contained in:
PaddleStroke
2025-08-10 16:06:01 +02:00
committed by paddle
parent 96361625e7
commit c1ccf75918
25 changed files with 1097 additions and 1817 deletions

View File

@@ -39,8 +39,7 @@ set(PartDesignGui_UIC_SRCS
TaskTransformedMessages.ui
TaskTransformedParameters.ui
TaskMirroredParameters.ui
TaskLinearPatternParameters.ui
TaskPolarPatternParameters.ui
TaskPatternParameters.ui
TaskScaledParameters.ui
TaskMultiTransformParameters.ui
TaskShapeBinder.ui
@@ -165,12 +164,9 @@ SET(PartDesignGuiTaskDlgs_SRCS
TaskMirroredParameters.ui
TaskMirroredParameters.cpp
TaskMirroredParameters.h
TaskLinearPatternParameters.ui
TaskLinearPatternParameters.cpp
TaskLinearPatternParameters.h
TaskPolarPatternParameters.ui
TaskPolarPatternParameters.cpp
TaskPolarPatternParameters.h
TaskPatternParameters.ui
TaskPatternParameters.cpp
TaskPatternParameters.h
TaskScaledParameters.ui
TaskScaledParameters.cpp
TaskScaledParameters.h

View File

@@ -2064,6 +2064,7 @@ void CmdPartDesignLinearPattern::activated(int iMsg)
Part::Part2DObject *sketch = (static_cast<PartDesign::ProfileBased*>(features.front()))->getVerifiedSketch(/* silent =*/ true);
if (sketch) {
FCMD_OBJ_CMD(Feat,"Direction = ("<<Gui::Command::getObjectCmd(sketch)<<", ['H_Axis'])");
FCMD_OBJ_CMD(Feat,"Direction2 = ("<<Gui::Command::getObjectCmd(sketch)<<", ['V_Axis'])");
direction = true;
}
}

View File

@@ -1,438 +0,0 @@
/******************************************************************************
* Copyright (c) 2012 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
******************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QTimer>
#endif
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Origin.h>
#include <Base/Console.h>
#include <Gui/Application.h>
#include <Gui/Selection/Selection.h>
#include <Gui/Command.h>
#include <Gui/ViewProviderCoordinateSystem.h>
#include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/DatumPlane.h>
#include <Mod/PartDesign/App/FeatureLinearPattern.h>
#include "ui_TaskLinearPatternParameters.h"
#include "TaskLinearPatternParameters.h"
#include "ReferenceSelection.h"
#include "TaskMultiTransformParameters.h"
using namespace PartDesignGui;
using namespace Gui;
/* TRANSLATOR PartDesignGui::TaskLinearPatternParameters */
TaskLinearPatternParameters::TaskLinearPatternParameters(ViewProviderTransformed* TransformedView,
QWidget* parent)
: TaskTransformedParameters(TransformedView, parent)
, ui(new Ui_TaskLinearPatternParameters)
{
setupUI();
}
TaskLinearPatternParameters::TaskLinearPatternParameters(TaskMultiTransformParameters* parentTask,
QWidget* parameterWidget)
: TaskTransformedParameters(parentTask)
, ui(new Ui_TaskLinearPatternParameters)
{
setupParameterUI(parameterWidget);
}
void TaskLinearPatternParameters::setupParameterUI(QWidget* widget)
{
ui->setupUi(widget);
QMetaObject::connectSlotsByName(this);
// Get the feature data
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
ui->spinLength->bind(pcLinearPattern->Length);
ui->spinOffset->bind(pcLinearPattern->Offset);
ui->spinOccurrences->bind(pcLinearPattern->Occurrences);
ui->spinOccurrences->setMaximum(pcLinearPattern->Occurrences.getMaximum());
ui->spinOccurrences->setMinimum(pcLinearPattern->Occurrences.getMinimum());
ui->comboDirection->setEnabled(true);
ui->checkReverse->setEnabled(true);
ui->comboMode->setEnabled(true);
ui->spinLength->blockSignals(true);
ui->spinLength->setEnabled(true);
ui->spinLength->setUnit(Base::Unit::Length);
ui->spinLength->blockSignals(false);
ui->spinOffset->blockSignals(true);
ui->spinOffset->setEnabled(true);
ui->spinOffset->setUnit(Base::Unit::Length);
ui->spinOffset->blockSignals(false);
ui->spinOccurrences->setEnabled(true);
dirLinks.setCombo(*(ui->comboDirection));
App::DocumentObject* sketch = getSketchObject();
if (sketch && sketch->isDerivedFrom<Part::Part2DObject>()) {
this->fillAxisCombo(dirLinks, static_cast<Part::Part2DObject*>(sketch));
}
else {
this->fillAxisCombo(dirLinks, nullptr);
}
// show the parts coordinate system axis for selection
PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject());
if (body) {
try {
App::Origin* origin = body->getOrigin();
auto vpOrigin = static_cast<ViewProviderCoordinateSystem*>(
Gui::Application::Instance->getViewProvider(origin));
vpOrigin->setTemporaryVisibility(Gui::DatumElement::Axes);
}
catch (const Base::Exception& ex) {
Base::Console().error("%s\n", ex.what());
}
}
adaptVisibilityToMode();
updateViewTimer = new QTimer(this);
updateViewTimer->setSingleShot(true);
updateViewTimer->setInterval(getUpdateViewTimeout());
connect(updateViewTimer,
&QTimer::timeout,
this,
&TaskLinearPatternParameters::onUpdateViewTimer);
connect(ui->comboDirection,
qOverload<int>(&QComboBox::activated),
this,
&TaskLinearPatternParameters::onDirectionChanged);
connect(ui->checkReverse,
&QCheckBox::toggled,
this,
&TaskLinearPatternParameters::onCheckReverse);
connect(ui->comboMode,
qOverload<int>(&QComboBox::activated),
this,
&TaskLinearPatternParameters::onModeChanged);
connect(ui->spinLength,
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this,
&TaskLinearPatternParameters::onLength);
connect(ui->spinOffset,
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this,
&TaskLinearPatternParameters::onOffset);
connect(ui->spinOccurrences,
&Gui::UIntSpinBox::unsignedChanged,
this,
&TaskLinearPatternParameters::onOccurrences);
}
void TaskLinearPatternParameters::retranslateParameterUI(QWidget* widget)
{
ui->retranslateUi(widget);
}
void TaskLinearPatternParameters::updateUI()
{
if (blockUpdate) {
return;
}
blockUpdate = true;
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
auto mode = static_cast<PartDesign::LinearPatternMode>(pcLinearPattern->Mode.getValue());
bool reverse = pcLinearPattern->Reversed.getValue();
double length = pcLinearPattern->Length.getValue();
double offset = pcLinearPattern->Offset.getValue();
unsigned occurrences = pcLinearPattern->Occurrences.getValue();
if (dirLinks.setCurrentLink(pcLinearPattern->Direction) == -1) {
// failed to set current, because the link isn't in the list yet
dirLinks.addLink(pcLinearPattern->Direction,
getRefStr(pcLinearPattern->Direction.getValue(),
pcLinearPattern->Direction.getSubValues()));
dirLinks.setCurrentLink(pcLinearPattern->Direction);
}
// Note: This block of code would trigger change signal handlers (e.g. onOccurrences())
// and another updateUI() if we didn't check for blockUpdate
ui->checkReverse->setChecked(reverse);
ui->comboMode->setCurrentIndex(static_cast<int>(mode));
ui->spinLength->setValue(length);
ui->spinOffset->setValue(offset);
ui->spinOccurrences->setValue(occurrences);
blockUpdate = false;
}
void TaskLinearPatternParameters::adaptVisibilityToMode()
{
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
auto mode = static_cast<PartDesign::LinearPatternMode>(pcLinearPattern->Mode.getValue());
ui->lengthWrapper->setVisible(mode == PartDesign::LinearPatternMode::length);
ui->offsetWrapper->setVisible(mode == PartDesign::LinearPatternMode::offset);
updateUI();
}
void TaskLinearPatternParameters::onUpdateViewTimer()
{
setupTransaction();
recomputeFeature();
}
void TaskLinearPatternParameters::kickUpdateViewTimer() const
{
updateViewTimer->start();
}
void TaskLinearPatternParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
{
if (selectionMode != SelectionMode::None && msg.Type == Gui::SelectionChanges::AddSelection) {
if (originalSelected(msg)) {
exitSelectionMode();
}
else {
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
std::vector<std::string> directions;
App::DocumentObject* selObj = nullptr;
getReferencedSelection(pcLinearPattern, msg, selObj, directions);
if (!selObj) {
return;
}
// Note: ReferenceSelection has already checked the selection for validity
if (selectionMode == SelectionMode::Reference || selObj->isDerivedFrom<App::Line>()) {
setupTransaction();
pcLinearPattern->Direction.setValue(selObj, directions);
recomputeFeature();
updateUI();
}
exitSelectionMode();
}
}
}
void TaskLinearPatternParameters::onCheckReverse(const bool on)
{
if (blockUpdate) {
return;
}
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
pcLinearPattern->Reversed.setValue(on);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskLinearPatternParameters::onModeChanged(const int mode)
{
if (blockUpdate) {
return;
}
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
pcLinearPattern->Mode.setValue(mode);
adaptVisibilityToMode();
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskLinearPatternParameters::onLength(const double length)
{
if (blockUpdate) {
return;
}
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
pcLinearPattern->Length.setValue(length);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskLinearPatternParameters::onOffset(const double offset)
{
if (blockUpdate) {
return;
}
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
pcLinearPattern->Offset.setValue(offset);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskLinearPatternParameters::onOccurrences(const uint number)
{
if (blockUpdate) {
return;
}
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
pcLinearPattern->Occurrences.setValue(number);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskLinearPatternParameters::onDirectionChanged(int /*num*/)
{
if (blockUpdate) {
return;
}
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
try {
if (!dirLinks.getCurrentLink().getValue()) {
// enter reference selection mode
hideObject();
showBase();
selectionMode = SelectionMode::Reference;
Gui::Selection().clearSelection();
addReferenceSelectionGate(AllowSelection::EDGE | AllowSelection::FACE
| AllowSelection::PLANAR);
}
else {
exitSelectionMode();
pcLinearPattern->Direction.Paste(dirLinks.getCurrentLink());
}
}
catch (Base::Exception& e) {
QMessageBox::warning(nullptr, tr("Error"), QApplication::translate("Exception", e.what()));
}
kickUpdateViewTimer();
}
void TaskLinearPatternParameters::onUpdateView(bool on)
{
blockUpdate = !on;
if (on) {
// Do the same like in TaskDlgLinearPatternParameters::accept() but without doCommand
auto pcLinearPattern = getObject<PartDesign::LinearPattern>();
std::vector<std::string> directions;
App::DocumentObject* obj = nullptr;
setupTransaction();
getDirection(obj, directions);
pcLinearPattern->Direction.setValue(obj, directions);
pcLinearPattern->Reversed.setValue(getReverse());
pcLinearPattern->Length.setValue(getLength());
pcLinearPattern->Offset.setValue(getOffset());
pcLinearPattern->Occurrences.setValue(getOccurrences());
recomputeFeature();
}
}
void TaskLinearPatternParameters::getDirection(App::DocumentObject*& obj,
std::vector<std::string>& sub) const
{
const App::PropertyLinkSub& lnk = dirLinks.getCurrentLink();
obj = lnk.getValue();
sub = lnk.getSubValues();
}
bool TaskLinearPatternParameters::getReverse() const
{
return ui->checkReverse->isChecked();
}
int TaskLinearPatternParameters::getMode() const
{
return ui->comboMode->currentIndex();
}
double TaskLinearPatternParameters::getLength() const
{
return ui->spinLength->value().getValue();
}
double TaskLinearPatternParameters::getOffset() const
{
return ui->spinOffset->value().getValue();
}
unsigned TaskLinearPatternParameters::getOccurrences() const
{
return ui->spinOccurrences->value();
}
TaskLinearPatternParameters::~TaskLinearPatternParameters()
{
try {
// hide the parts coordinate system axis for selection
PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject());
if (body) {
App::Origin* origin = body->getOrigin();
auto vpOrigin = static_cast<ViewProviderCoordinateSystem*>(
Gui::Application::Instance->getViewProvider(origin));
vpOrigin->resetTemporaryVisibility();
}
}
catch (const Base::Exception& ex) {
Base::Console().error("%s\n", ex.what());
}
}
void TaskLinearPatternParameters::apply()
{
std::vector<std::string> directions;
App::DocumentObject* obj = nullptr;
getDirection(obj, directions);
std::string direction = buildLinkSingleSubPythonStr(obj, directions);
auto tobj = getObject();
FCMD_OBJ_CMD(tobj, "Direction = " << direction);
FCMD_OBJ_CMD(tobj, "Reversed = " << getReverse());
FCMD_OBJ_CMD(tobj, "Mode = " << getMode());
ui->spinLength->apply();
ui->spinOffset->apply();
ui->spinOccurrences->apply();
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgLinearPatternParameters::TaskDlgLinearPatternParameters(
ViewProviderLinearPattern* LinearPatternView)
: TaskDlgTransformedParameters(LinearPatternView)
{
parameter = new TaskLinearPatternParameters(LinearPatternView);
Content.push_back(parameter);
Content.push_back(preview);
}
#include "moc_TaskLinearPatternParameters.cpp"

View File

@@ -1,188 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PartDesignGui::TaskLinearPatternParameters</class>
<widget class="QWidget" name="PartDesignGui::TaskLinearPatternParameters">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>270</width>
<height>188</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="labelDirection">
<property name="text">
<string>Direction</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboDirection"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkReverse">
<property name="text">
<string>Reverse direction</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="labelMode">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboMode">
<item>
<property name="text">
<string>Overall length</string>
</property>
</item>
<item>
<property name="text">
<string>Offset</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="lengthWrapper" native="true">
<layout class="QHBoxLayout" name="_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelLength">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="spinLength" native="true">
<property name="keyboardTracking" stdset="0">
<bool>false</bool>
</property>
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
<property name="value" stdset="0">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="offsetWrapper" native="true">
<layout class="QHBoxLayout" name="_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelOffset">
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="spinOffset" native="true">
<property name="keyboardTracking" stdset="0">
<bool>false</bool>
</property>
<property name="unit" stdset="0">
<string notr="true">mm</string>
</property>
<property name="value" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Occurrences</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::UIntSpinBox" name="spinOccurrences"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
<customwidget>
<class>Gui::UIntSpinBox</class>
<extends>QSpinBox</extends>
<header>Gui/SpinBox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>comboDirection</tabstop>
<tabstop>checkReverse</tabstop>
<tabstop>spinLength</tabstop>
<tabstop>spinOccurrences</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -74,7 +74,7 @@ void TaskMirroredParameters::setupParameterUI(QWidget* widget)
this,
&TaskMirroredParameters::onPlaneChanged);
this->planeLinks.setCombo(*(ui->comboPlane));
this->planeLinks.setCombo(ui->comboPlane);
ui->comboPlane->setEnabled(true);
App::DocumentObject* sketch = getSketchObject();
@@ -131,27 +131,22 @@ void TaskMirroredParameters::onSelectionChanged(const Gui::SelectionChanges& msg
{
if (selectionMode != SelectionMode::None && msg.Type == Gui::SelectionChanges::AddSelection) {
if (originalSelected(msg)) {
exitSelectionMode();
}
else {
auto pcMirrored = getObject<PartDesign::Mirrored>();
auto pcMirrored = getObject<PartDesign::Mirrored>();
std::vector<std::string> mirrorPlanes;
App::DocumentObject* selObj = nullptr;
getReferencedSelection(pcMirrored, msg, selObj, mirrorPlanes);
if (!selObj) {
return;
}
if (selectionMode == SelectionMode::Reference || selObj->isDerivedFrom<App::Plane>()) {
setupTransaction();
pcMirrored->MirrorPlane.setValue(selObj, mirrorPlanes);
recomputeFeature();
updateUI();
}
exitSelectionMode();
std::vector<std::string> mirrorPlanes;
App::DocumentObject* selObj = nullptr;
getReferencedSelection(pcMirrored, msg, selObj, mirrorPlanes);
if (!selObj) {
return;
}
if (selectionMode == SelectionMode::Reference || selObj->isDerivedFrom<App::Plane>()) {
setupTransaction();
pcMirrored->MirrorPlane.setValue(selObj, mirrorPlanes);
recomputeFeature();
updateUI();
}
exitSelectionMode();
}
}

View File

@@ -44,8 +44,7 @@
#include "ui_TaskMultiTransformParameters.h"
#include "TaskMultiTransformParameters.h"
#include "TaskMirroredParameters.h"
#include "TaskLinearPatternParameters.h"
#include "TaskPolarPatternParameters.h"
#include "TaskPatternParameters.h"
#include "TaskScaledParameters.h"
#include "Utils.h"
@@ -170,6 +169,10 @@ void TaskMultiTransformParameters::closeSubTask()
subTask->apply();
}
delete subTask;
subTask = nullptr;
subFeature = nullptr;
// Remove all parameter ui widgets and layout
ui->subFeatureWidget->setUpdatesEnabled(false);
qDeleteAll(
@@ -177,10 +180,6 @@ void TaskMultiTransformParameters::closeSubTask()
qDeleteAll(
ui->subFeatureWidget->findChildren<QLayout*>(QString(), Qt::FindDirectChildrenOnly));
ui->subFeatureWidget->setUpdatesEnabled(true);
delete subTask;
subTask = nullptr;
subFeature = nullptr;
}
}
@@ -230,11 +229,9 @@ void TaskMultiTransformParameters::onTransformEdit()
if (subFeature->is<PartDesign::Mirrored>()) {
subTask = new TaskMirroredParameters(this, ui->subFeatureWidget);
}
else if (subFeature->is<PartDesign::LinearPattern>()) {
subTask = new TaskLinearPatternParameters(this, ui->subFeatureWidget);
}
else if (subFeature->is<PartDesign::PolarPattern>()) {
subTask = new TaskPolarPatternParameters(this, ui->subFeatureWidget);
else if (subFeature->is<PartDesign::LinearPattern>()
|| subFeature->is<PartDesign::PolarPattern>()) {
subTask = new TaskPatternParameters(this, ui->subFeatureWidget);
}
else if (subFeature->is<PartDesign::Scaled>()) {
subTask = new TaskScaledParameters(this, ui->subFeatureWidget);

View File

@@ -0,0 +1,383 @@
/******************************************************************************
* Copyright (c) 2012 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
******************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QTimer>
#include <QVBoxLayout>
#endif
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Origin.h>
#include <Base/Console.h>
#include <Gui/Application.h>
#include <Gui/MainWindow.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Selection/Selection.h>
#include <Gui/Command.h>
#include <Gui/ViewProviderCoordinateSystem.h>
#include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/DatumPlane.h>
#include <Mod/PartDesign/App/FeatureLinearPattern.h>
#include <Mod/PartDesign/App/FeaturePolarPattern.h>
#include <Mod/Part/Gui/PatternParametersWidget.h>
#include "ui_TaskPatternParameters.h"
#include "TaskPatternParameters.h"
#include "ReferenceSelection.h"
#include "TaskMultiTransformParameters.h"
using namespace PartDesignGui;
using namespace Gui;
/* TRANSLATOR PartDesignGui::TaskPatternParameters */
TaskPatternParameters::TaskPatternParameters(ViewProviderTransformed* TransformedView,
QWidget* parent)
: TaskTransformedParameters(TransformedView, parent)
, ui(new Ui_TaskPatternParameters)
{
setupUI();
}
TaskPatternParameters::TaskPatternParameters(TaskMultiTransformParameters* parentTask,
QWidget* parameterWidget)
: TaskTransformedParameters(parentTask)
, ui(new Ui::TaskPatternParameters)
{
setupParameterUI(parameterWidget);
}
void TaskPatternParameters::setupParameterUI(QWidget* widget)
{
ui->setupUi(widget); // Setup the Task's own minimal UI (placeholder)
QMetaObject::connectSlotsByName(this);
// --- Create and Embed the Parameter Widget ---
auto pattern = getObject();
if (!pattern) {
return;
}
PartGui::PatternType type = pattern->isDerivedFrom<PartDesign::LinearPattern>() ?
PartGui::PatternType::Linear : PartGui::PatternType::Polar;
// Set first direction widget
parametersWidget = new PartGui::PatternParametersWidget(type, widget);
auto* placeholderLayout = new QVBoxLayout(ui->parametersWidgetPlaceholder);
placeholderLayout->setContentsMargins(0, 0, 0, 0);
placeholderLayout->addWidget(parametersWidget);
ui->parametersWidgetPlaceholder->setLayout(placeholderLayout);
auto* sketch = dynamic_cast<Part::Part2DObject*>(getSketchObject());
this->fillAxisCombo(parametersWidget->dirLinks, sketch);
connect(parametersWidget, &PartGui::PatternParametersWidget::requestReferenceSelection,
this, &TaskPatternParameters::onParameterWidgetRequestReferenceSelection);
connect(parametersWidget, &PartGui::PatternParametersWidget::parametersChanged,
this, &TaskPatternParameters::onParameterWidgetParametersChanged);
// Add second direction widget if necessary
if (type == PartGui::PatternType::Linear) {
parametersWidget2 = new PartGui::PatternParametersWidget(type, widget);
auto* placeholderLayout2 = new QVBoxLayout(ui->parametersWidgetPlaceholder2);
placeholderLayout2->setContentsMargins(0, 0, 0, 0);
placeholderLayout2->addWidget(parametersWidget2);
ui->parametersWidgetPlaceholder2->setLayout(placeholderLayout2);
this->fillAxisCombo(parametersWidget2->dirLinks, sketch);
connect(parametersWidget2, &PartGui::PatternParametersWidget::requestReferenceSelection,
this, &TaskPatternParameters::onParameterWidgetRequestReferenceSelection2);
connect(parametersWidget2, &PartGui::PatternParametersWidget::parametersChanged,
this, &TaskPatternParameters::onParameterWidgetParametersChanged);
parametersWidget2->setTitle(tr("Direction 2"));
}
bindProperties();
// --- Task Specific Setup ---
showOriginAxes(true); // Show origin helper axes
updateViewTimer = new QTimer(this);
updateViewTimer->setSingleShot(true);
updateViewTimer->setInterval(getUpdateViewTimeout());
connect(updateViewTimer, &QTimer::timeout, this, &TaskPatternParameters::onUpdateViewTimer);
}
void TaskPatternParameters::bindProperties()
{
auto pattern = getObject();
if (!pattern) {
return;
}
if (pattern->isDerivedFrom<PartDesign::LinearPattern>()) {
auto* linear = static_cast<PartDesign::LinearPattern*>(pattern);
parametersWidget->bindProperties(&linear->Direction,
&linear->Reversed,
&linear->Mode,
&linear->Length,
&linear->Offset,
&linear->SpacingPattern,
&linear->Occurrences,
linear);
parametersWidget2->bindProperties(&linear->Direction2,
&linear->Reversed2,
&linear->Mode2,
&linear->Length2,
&linear->Offset2,
&linear->SpacingPattern2,
&linear->Occurrences2,
linear);
}
else if (pattern->isDerivedFrom<PartDesign::PolarPattern>()) {
auto* polar = static_cast<PartDesign::PolarPattern*>(pattern);
parametersWidget->bindProperties(&polar->Axis,
&polar->Reversed,
&polar->Mode,
&polar->Angle,
&polar->Offset,
&polar->SpacingPattern,
&polar->Occurrences,
polar);
}
else{
Base::Console().warning("PatternParametersWidget property binding failed. Something is wrong please report.\n");
}
}
void TaskPatternParameters::retranslateParameterUI(QWidget* widget)
{
ui->retranslateUi(widget);
}
void TaskPatternParameters::updateUI()
{
if (parametersWidget) {
parametersWidget->updateUI();
}
if (parametersWidget2) {
parametersWidget2->updateUI();
}
}
// --- Task-Specific Logic ---
void TaskPatternParameters::showOriginAxes(bool show)
{
PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject());
if (body) {
try {
App::Origin* origin = body->getOrigin();
auto vpOrigin = static_cast<ViewProviderCoordinateSystem*>(
Gui::Application::Instance->getViewProvider(origin));
if (show) {
vpOrigin->setTemporaryVisibility(Gui::DatumElement::Axes);
}
else {
vpOrigin->resetTemporaryVisibility();
}
}
catch (const Base::Exception& ex) {
Base::Console().error("TaskPatternParameters: Error accessing origin axes: %s\n", ex.what());
}
}
}
void TaskPatternParameters::enterReferenceSelectionMode()
{
if (selectionMode == SelectionMode::Reference) return;
hideObject(); // Hide the pattern feature itself
showBase(); // Show the base features/body
Gui::Selection().clearSelection();
// Add selection gate (allow edges, faces, potentially datums)
addReferenceSelectionGate(AllowSelection::EDGE | AllowSelection::FACE | AllowSelection::PLANAR);
Gui::getMainWindow()->showMessage(tr("Select a direction reference (edge, face, datum line)")); // User feedback
}
void TaskPatternParameters::exitReferenceSelectionMode()
{
exitSelectionMode();
hideBase();
Gui::getMainWindow()->showMessage(QString());
activeDirectionWidget = nullptr;
}
// --- SLOTS ---
void TaskPatternParameters::onUpdateViewTimer()
{
// Recompute is triggered when parameters change and this timer fires
setupTransaction(); // Group potential property changes
recomputeFeature();
updateUI();
}
void TaskPatternParameters::onParameterWidgetRequestReferenceSelection()
{
// The embedded widget wants to enter reference selection mode
activeDirectionWidget = parametersWidget;
enterReferenceSelectionMode();
selectionMode = SelectionMode::Reference;
}
void TaskPatternParameters::onParameterWidgetRequestReferenceSelection2()
{
// The embedded widget wants to enter reference selection mode
activeDirectionWidget = parametersWidget2;
enterReferenceSelectionMode();
selectionMode = SelectionMode::Reference;
}
void TaskPatternParameters::onParameterWidgetParametersChanged()
{
// A parameter in the embedded widget changed, trigger a recompute
if (blockUpdate) return; // Avoid loops if change originated from Task update
kickUpdateViewTimer(); // Debounce recompute
}
void TaskPatternParameters::onUpdateView(bool on)
{
// This might be less relevant now if recomputes are triggered by parametersChanged
blockUpdate = !on;
if (on) {
kickUpdateViewTimer();
}
}
void TaskPatternParameters::kickUpdateViewTimer() const
{
updateViewTimer->start();
}
void TaskPatternParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
{
// Handle selection ONLY when in reference selection mode
if (selectionMode == SelectionMode::None || msg.Type != Gui::SelectionChanges::AddSelection) {
return;
}
auto patternObj = getObject();
if (!patternObj) return;
std::vector<std::string> directions;
App::DocumentObject* selObj = nullptr;
getReferencedSelection(patternObj, msg, selObj, directions);
if (!selObj) {
Base::Console().warning(tr("Invalid selection. Select an edge, planar face, or datum line.").toStdString().c_str());
return;
}
// Note: ReferenceSelection has already checked the selection for validity
if (selectionMode == SelectionMode::Reference
|| selObj->isDerivedFrom<App::Line>()) {
setupTransaction();
if (patternObj->isDerivedFrom<PartDesign::LinearPattern>()) {
auto* linearPattern = static_cast<PartDesign::LinearPattern*>(patternObj);
if (activeDirectionWidget == parametersWidget) {
linearPattern->Direction.setValue(selObj, directions);
}
else {
linearPattern->Direction2.setValue(selObj, directions);
}
}
else if(patternObj->isDerivedFrom<PartDesign::PolarPattern>()) {
auto* polarPattern = static_cast<PartDesign::PolarPattern*>(patternObj);
polarPattern->Axis.setValue(selObj, directions);
}
recomputeFeature();
updateUI();
}
exitReferenceSelectionMode();
}
TaskPatternParameters::~TaskPatternParameters()
{
showOriginAxes(false); // Clean up temporary visibility
exitReferenceSelectionMode(); // Ensure gates are removed etc.
// ui unique_ptr handles deletion
// parametersWidget is deleted by Qt parent mechanism if added to layout correctly
}
void TaskPatternParameters::apply()
{
auto pattern = getObject();
if (!pattern || !parametersWidget) {
return;
}
std::vector<std::string> dirs;
App::DocumentObject* obj = nullptr;
parametersWidget->getAxis(obj, dirs);
std::string direction = buildLinkSingleSubPythonStr(obj, dirs);
bool isLinear = pattern->isDerivedFrom<PartDesign::LinearPattern>();
const char* propName = isLinear ? "Direction = " : "Axis = ";
FCMD_OBJ_CMD(pattern, propName << direction.c_str());
FCMD_OBJ_CMD(pattern, "Reversed = " << parametersWidget->getReverse());
FCMD_OBJ_CMD(pattern, "Mode = " << parametersWidget->getMode());
parametersWidget->applyQuantitySpinboxes();
FCMD_OBJ_CMD(pattern, "SpacingPattern = " << parametersWidget->getSpacingPatternsAsString());
if (!parametersWidget2) {
return;
}
parametersWidget2->getAxis(obj, dirs);
direction = buildLinkSingleSubPythonStr(obj, dirs);
FCMD_OBJ_CMD(pattern, "Direction2 = " << direction.c_str());
FCMD_OBJ_CMD(pattern, "Reversed2 = " << parametersWidget2->getReverse());
FCMD_OBJ_CMD(pattern, "Mode2 = " << parametersWidget2->getMode());
parametersWidget2->applyQuantitySpinboxes();
FCMD_OBJ_CMD(pattern, "SpacingPattern2 = " << parametersWidget2->getSpacingPatternsAsString());
}
//**************************************************************************
// TaskDialog Implementation (Remains largely the same)
//**************************************************************************
TaskDlgLinearPatternParameters::TaskDlgLinearPatternParameters(
ViewProviderTransformed* LinearPatternView)
: TaskDlgTransformedParameters(LinearPatternView) // Use base class constructor
{
// Create the specific parameter task panel
parameter = new TaskPatternParameters(LinearPatternView);
// Add it to the dialog's content list
Content.push_back(parameter);
Content.push_back(preview);
}
#include "moc_TaskPatternParameters.cpp"

View File

@@ -1,4 +1,4 @@
/******************************************************************************
/******************************************************************************
* Copyright (c) 2012 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
@@ -20,24 +20,18 @@
* *
******************************************************************************/
#ifndef GUI_TASKVIEW_TaskLinearPatternParameters_H
#define GUI_TASKVIEW_TaskLinearPatternParameters_H
#ifndef GUI_TASKVIEW_TaskPatternParameters_H
#define GUI_TASKVIEW_TaskPatternParameters_H
#include "TaskTransformedParameters.h"
#include "ViewProviderLinearPattern.h"
#include "ViewProviderTransformed.h"
class QTimer;
class Ui_TaskLinearPatternParameters;
class Ui_TaskPatternParameters;
namespace App
{
class Property;
}
namespace Gui
{
class ViewProvider;
namespace PartGui {
class PatternParametersWidget;
}
namespace PartDesignGui
@@ -45,17 +39,17 @@ namespace PartDesignGui
class TaskMultiTransformParameters;
class TaskLinearPatternParameters: public TaskTransformedParameters
class TaskPatternParameters : public TaskTransformedParameters
{
Q_OBJECT
public:
/// Constructor for task with ViewProvider
explicit TaskLinearPatternParameters(ViewProviderTransformed* TransformedView,
explicit TaskPatternParameters(ViewProviderTransformed* TransformedView,
QWidget* parent = nullptr);
/// Constructor for task with parent task (MultiTransform mode)
TaskLinearPatternParameters(TaskMultiTransformParameters* parentTask, QWidget* parameterWidget);
~TaskLinearPatternParameters() override;
TaskPatternParameters(TaskMultiTransformParameters* parentTask, QWidget* parameterWidget);
~TaskPatternParameters() override;
void apply() override;
@@ -64,47 +58,49 @@ protected:
private Q_SLOTS:
void onUpdateViewTimer();
void onDirectionChanged(int num);
void onCheckReverse(bool on);
void onModeChanged(int mode);
void onLength(double length);
void onOffset(double offset);
void onOccurrences(uint number);
void onUpdateView(bool /*unused*/) override;
// Slot to handle reference selection request from the widget
void onParameterWidgetRequestReferenceSelection();
void onParameterWidgetRequestReferenceSelection2();
// Slot to handle parameter changes from the widget
void onParameterWidgetParametersChanged();
// Update view signal (might be redundant now)
void onUpdateView(bool on) override;
private:
void setupParameterUI(QWidget* widget) override;
void retranslateParameterUI(QWidget* widget) override;
void connectSignals();
void updateUI();
void adaptVisibilityToMode();
void kickUpdateViewTimer() const;
void getDirection(App::DocumentObject*& obj, std::vector<std::string>& sub) const;
bool getReverse() const;
int getMode() const;
double getLength() const;
double getOffset() const;
unsigned getOccurrences() const;
void bindProperties();
private:
std::unique_ptr<Ui_TaskLinearPatternParameters> ui;
// Task-specific logic remains
void showOriginAxes(bool show);
void enterReferenceSelectionMode();
void exitReferenceSelectionMode(); // Ensure this clears gates etc.
PartGui::PatternParametersWidget* parametersWidget = nullptr;
PartGui::PatternParametersWidget* parametersWidget2 = nullptr;
PartGui::PatternParametersWidget* activeDirectionWidget = nullptr;
std::unique_ptr<Ui_TaskPatternParameters> ui;
QTimer* updateViewTimer = nullptr;
Gui::ComboLinks dirLinks;
};
/// simulation dialog for the TaskView
class TaskDlgLinearPatternParameters: public TaskDlgTransformedParameters
class TaskDlgLinearPatternParameters : public TaskDlgTransformedParameters
{
Q_OBJECT
public:
explicit TaskDlgLinearPatternParameters(ViewProviderLinearPattern* LinearPatternView);
explicit TaskDlgLinearPatternParameters(ViewProviderTransformed* LinearPatternView);
};
} // namespace PartDesignGui
#endif // GUI_TASKVIEW_TASKAPPERANCE_H
#endif // GUI_TASKVIEW_TaskPatternParameters_H

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PartDesignGui::TaskPatternParameters</class>
<widget class="QWidget" name="PartDesignGui::TaskPatternParameters">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>270</width>
<height>200</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="parametersWidgetPlaceholder" native="true"/>
</item>
<item>
<widget class="QWidget" name="parametersWidgetPlaceholder2" native="true"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1,432 +0,0 @@
/******************************************************************************
* Copyright (c) 2012 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
******************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMessageBox>
#include <QTimer>
#endif
#include <Base/UnitsApi.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/Origin.h>
#include <App/Datums.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/BitmapFactory.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Base/Console.h>
#include <Gui/Selection/Selection.h>
#include <Gui/Command.h>
#include <Gui/ViewProviderCoordinateSystem.h>
#include <Mod/PartDesign/App/FeaturePolarPattern.h>
#include <Mod/Sketcher/App/SketchObject.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/Body.h>
#include "ReferenceSelection.h"
#include "TaskMultiTransformParameters.h"
#include "Utils.h"
#include "ui_TaskPolarPatternParameters.h"
#include "TaskPolarPatternParameters.h"
using namespace PartDesignGui;
using namespace Gui;
/* TRANSLATOR PartDesignGui::TaskPolarPatternParameters */
TaskPolarPatternParameters::TaskPolarPatternParameters(ViewProviderTransformed* TransformedView,
QWidget* parent)
: TaskTransformedParameters(TransformedView, parent)
, ui(new Ui_TaskPolarPatternParameters)
{
setupUI();
}
TaskPolarPatternParameters::TaskPolarPatternParameters(TaskMultiTransformParameters* parentTask,
QWidget* parameterWidget)
: TaskTransformedParameters(parentTask)
, ui(new Ui_TaskPolarPatternParameters)
{
setupParameterUI(parameterWidget);
}
void TaskPolarPatternParameters::setupParameterUI(QWidget* widget)
{
ui->setupUi(widget);
QMetaObject::connectSlotsByName(this);
// Get the feature data
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
ui->polarAngle->bind(pcPolarPattern->Angle);
ui->angleOffset->bind(pcPolarPattern->Offset);
ui->spinOccurrences->bind(pcPolarPattern->Occurrences);
ui->spinOccurrences->setMaximum(pcPolarPattern->Occurrences.getMaximum());
ui->spinOccurrences->setMinimum(pcPolarPattern->Occurrences.getMinimum());
ui->comboAxis->setEnabled(true);
ui->comboMode->setEnabled(true);
ui->checkReverse->setEnabled(true);
ui->polarAngle->setEnabled(true);
ui->spinOccurrences->setEnabled(true);
this->axesLinks.setCombo(*(ui->comboAxis));
App::DocumentObject* sketch = getSketchObject();
if (sketch && sketch->isDerivedFrom<Part::Part2DObject>()) {
this->fillAxisCombo(axesLinks, static_cast<Part::Part2DObject*>(sketch));
}
else {
this->fillAxisCombo(axesLinks, nullptr);
}
// show the parts coordinate system axis for selection
PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject());
if (body) {
try {
App::Origin* origin = body->getOrigin();
auto vpOrigin = static_cast<ViewProviderCoordinateSystem*>(
Gui::Application::Instance->getViewProvider(origin));
vpOrigin->setTemporaryVisibility(Gui::DatumElement::Axes);
}
catch (const Base::Exception& ex) {
Base::Console().error("%s\n", ex.what());
}
}
adaptVisibilityToMode();
updateUI();
updateViewTimer = new QTimer(this);
updateViewTimer->setSingleShot(true);
updateViewTimer->setInterval(getUpdateViewTimeout());
connect(updateViewTimer,
&QTimer::timeout,
this,
&TaskPolarPatternParameters::onUpdateViewTimer);
connect(ui->comboAxis,
qOverload<int>(&QComboBox::activated),
this,
&TaskPolarPatternParameters::onAxisChanged);
connect(ui->comboMode,
qOverload<int>(&QComboBox::activated),
this,
&TaskPolarPatternParameters::onModeChanged);
connect(ui->checkReverse,
&QCheckBox::toggled,
this,
&TaskPolarPatternParameters::onCheckReverse);
connect(ui->polarAngle,
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this,
&TaskPolarPatternParameters::onAngle);
connect(ui->angleOffset,
qOverload<double>(&Gui::QuantitySpinBox::valueChanged),
this,
&TaskPolarPatternParameters::onOffset);
connect(ui->spinOccurrences,
&Gui::UIntSpinBox::unsignedChanged,
this,
&TaskPolarPatternParameters::onOccurrences);
}
void TaskPolarPatternParameters::retranslateParameterUI(QWidget* widget)
{
ui->retranslateUi(widget);
}
void TaskPolarPatternParameters::updateUI()
{
if (blockUpdate) {
return;
}
blockUpdate = true;
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
auto mode = static_cast<PartDesign::PolarPatternMode>(pcPolarPattern->Mode.getValue());
bool reverse = pcPolarPattern->Reversed.getValue();
double angle = pcPolarPattern->Angle.getValue();
double offset = pcPolarPattern->Offset.getValue();
unsigned occurrences = pcPolarPattern->Occurrences.getValue();
if (axesLinks.setCurrentLink(pcPolarPattern->Axis) == -1) {
// failed to set current, because the link isn't in the list yet
axesLinks.addLink(
pcPolarPattern->Axis,
getRefStr(pcPolarPattern->Axis.getValue(), pcPolarPattern->Axis.getSubValues()));
axesLinks.setCurrentLink(pcPolarPattern->Axis);
}
// Note: This block of code would trigger change signal handlers (e.g. onOccurrences())
// and another updateUI() if we didn't check for blockUpdate
ui->checkReverse->setChecked(reverse);
ui->comboMode->setCurrentIndex(static_cast<int>(mode));
ui->polarAngle->setValue(angle);
ui->angleOffset->setValue(offset);
ui->spinOccurrences->setValue(occurrences);
blockUpdate = false;
}
void TaskPolarPatternParameters::onUpdateViewTimer()
{
setupTransaction();
recomputeFeature();
}
void TaskPolarPatternParameters::kickUpdateViewTimer() const
{
updateViewTimer->start();
}
void TaskPolarPatternParameters::adaptVisibilityToMode()
{
auto pcLinearPattern = getObject<PartDesign::PolarPattern>();
auto mode = static_cast<PartDesign::PolarPatternMode>(pcLinearPattern->Mode.getValue());
ui->polarAngleWrapper->setVisible(mode == PartDesign::PolarPatternMode::angle);
ui->angleOffsetWrapper->setVisible(mode == PartDesign::PolarPatternMode::offset);
}
void TaskPolarPatternParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
{
if (selectionMode != SelectionMode::None && msg.Type == Gui::SelectionChanges::AddSelection) {
if (originalSelected(msg)) {
exitSelectionMode();
}
else {
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
std::vector<std::string> axes;
App::DocumentObject* selObj = nullptr;
getReferencedSelection(pcPolarPattern, msg, selObj, axes);
if (!selObj) {
return;
}
if (selectionMode == SelectionMode::Reference || selObj->isDerivedFrom<App::Line>()) {
setupTransaction();
pcPolarPattern->Axis.setValue(selObj, axes);
recomputeFeature();
updateUI();
}
exitSelectionMode();
}
}
}
void TaskPolarPatternParameters::onCheckReverse(const bool on)
{
if (blockUpdate) {
return;
}
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
pcPolarPattern->Reversed.setValue(on);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskPolarPatternParameters::onModeChanged(const int mode)
{
if (blockUpdate) {
return;
}
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
pcPolarPattern->Mode.setValue(mode);
adaptVisibilityToMode();
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskPolarPatternParameters::onAngle(const double angle)
{
if (blockUpdate) {
return;
}
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
pcPolarPattern->Angle.setValue(angle);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskPolarPatternParameters::onOffset(const double offset)
{
if (blockUpdate) {
return;
}
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
pcPolarPattern->Offset.setValue(offset);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskPolarPatternParameters::onOccurrences(const uint n)
{
if (blockUpdate) {
return;
}
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
pcPolarPattern->Occurrences.setValue(n);
exitSelectionMode();
kickUpdateViewTimer();
}
void TaskPolarPatternParameters::onAxisChanged(int /*num*/)
{
if (blockUpdate) {
return;
}
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
try {
if (!axesLinks.getCurrentLink().getValue()) {
// enter reference selection mode
hideObject();
showBase();
selectionMode = SelectionMode::Reference;
Gui::Selection().clearSelection();
addReferenceSelectionGate(AllowSelection::EDGE | AllowSelection::CIRCLE);
}
else {
exitSelectionMode();
pcPolarPattern->Axis.Paste(axesLinks.getCurrentLink());
}
}
catch (Base::Exception& e) {
QMessageBox::warning(nullptr, tr("Error"), QApplication::translate("Exception", e.what()));
}
kickUpdateViewTimer();
}
void TaskPolarPatternParameters::onUpdateView(bool on)
{
blockUpdate = !on;
if (on) {
// Do the same like in TaskDlgPolarPatternParameters::accept() but without doCommand
auto pcPolarPattern = getObject<PartDesign::PolarPattern>();
std::vector<std::string> axes;
App::DocumentObject* obj = nullptr;
setupTransaction();
getAxis(obj, axes);
pcPolarPattern->Axis.setValue(obj, axes);
pcPolarPattern->Reversed.setValue(getReverse());
pcPolarPattern->Angle.setValue(getAngle());
pcPolarPattern->Occurrences.setValue(getOccurrences());
recomputeFeature();
}
}
void TaskPolarPatternParameters::getAxis(App::DocumentObject*& obj,
std::vector<std::string>& sub) const
{
const App::PropertyLinkSub& lnk = axesLinks.getCurrentLink();
obj = lnk.getValue();
sub = lnk.getSubValues();
}
bool TaskPolarPatternParameters::getReverse() const
{
return ui->checkReverse->isChecked();
}
int TaskPolarPatternParameters::getMode() const
{
return ui->comboMode->currentIndex();
}
double TaskPolarPatternParameters::getAngle() const
{
return ui->polarAngle->value().getValue();
}
unsigned TaskPolarPatternParameters::getOccurrences() const
{
return ui->spinOccurrences->value();
}
TaskPolarPatternParameters::~TaskPolarPatternParameters()
{
// hide the parts coordinate system axis for selection
try {
PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject());
if (body) {
App::Origin* origin = body->getOrigin();
auto vpOrigin = static_cast<ViewProviderCoordinateSystem*>(
Gui::Application::Instance->getViewProvider(origin));
vpOrigin->resetTemporaryVisibility();
}
}
catch (const Base::Exception& ex) {
Base::Console().error("%s\n", ex.what());
}
}
void TaskPolarPatternParameters::apply()
{
std::vector<std::string> axes;
App::DocumentObject* obj = nullptr;
getAxis(obj, axes);
std::string axis = buildLinkSingleSubPythonStr(obj, axes);
auto tobj = getObject();
FCMD_OBJ_CMD(tobj, "Axis = " << axis.c_str());
FCMD_OBJ_CMD(tobj, "Reversed = " << getReverse());
FCMD_OBJ_CMD(tobj, "Mode = " << getMode());
ui->polarAngle->apply();
ui->angleOffset->apply();
ui->spinOccurrences->apply();
}
//**************************************************************************
//**************************************************************************
// TaskDialog
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TaskDlgPolarPatternParameters::TaskDlgPolarPatternParameters(
ViewProviderPolarPattern* PolarPatternView)
: TaskDlgTransformedParameters(PolarPatternView)
{
parameter = new TaskPolarPatternParameters(PolarPatternView);
Content.push_back(parameter);
Content.push_back(preview);
}
#include "moc_TaskPolarPatternParameters.cpp"

View File

@@ -1,111 +0,0 @@
/******************************************************************************
* Copyright (c) 2012 Jan Rheinländer <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
******************************************************************************/
#ifndef GUI_TASKVIEW_TaskPolarPatternParameters_H
#define GUI_TASKVIEW_TaskPolarPatternParameters_H
#include "TaskTransformedParameters.h"
#include "ViewProviderPolarPattern.h"
class QTimer;
class Ui_TaskPolarPatternParameters;
namespace App
{
class Property;
}
namespace Gui
{
class ViewProvider;
}
namespace PartDesignGui
{
class TaskMultiTransformParameters;
class TaskPolarPatternParameters: public TaskTransformedParameters
{
Q_OBJECT
public:
/// Constructor for task with ViewProvider
explicit TaskPolarPatternParameters(ViewProviderTransformed* TransformedView,
QWidget* parent = nullptr);
/// Constructor for task with parent task (MultiTransform mode)
TaskPolarPatternParameters(TaskMultiTransformParameters* parentTask, QWidget* parameterWidget);
~TaskPolarPatternParameters() override;
void apply() override;
protected:
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
private Q_SLOTS:
void onUpdateViewTimer();
void onAxisChanged(int num);
void onModeChanged(int mode);
void onCheckReverse(bool on);
void onAngle(double angle);
void onOffset(double offset);
void onOccurrences(uint number);
void onUpdateView(bool /*unused*/) override;
private:
void setupParameterUI(QWidget* widget) override;
void retranslateParameterUI(QWidget* widget) override;
void connectSignals();
void updateUI();
void kickUpdateViewTimer() const;
void adaptVisibilityToMode();
void getAxis(App::DocumentObject*& obj, std::vector<std::string>& sub) const;
const std::string getStdAxis() const;
const std::string getAxis() const;
bool getReverse() const;
int getMode() const;
double getAngle() const;
unsigned getOccurrences() const;
private:
std::unique_ptr<Ui_TaskPolarPatternParameters> ui;
QTimer* updateViewTimer = nullptr;
Gui::ComboLinks axesLinks;
};
/// simulation dialog for the TaskView
class TaskDlgPolarPatternParameters: public TaskDlgTransformedParameters
{
Q_OBJECT
public:
explicit TaskDlgPolarPatternParameters(ViewProviderPolarPattern* PolarPatternView);
};
} // namespace PartDesignGui
#endif // GUI_TASKVIEW_TASKAPPERANCE_H

View File

@@ -1,200 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PartDesignGui::TaskPolarPatternParameters</class>
<widget class="QWidget" name="PartDesignGui::TaskPolarPatternParameters">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>253</width>
<height>206</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="labelAxis">
<property name="text">
<string>Axis</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboAxis"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkReverse">
<property name="text">
<string>Reverse direction</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboMode">
<item>
<property name="text">
<string>Overall angle</string>
</property>
</item>
<item>
<property name="text">
<string>Offset angle</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="polarAngleWrapper" native="true">
<layout class="QHBoxLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Angle</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="polarAngle" native="true">
<property name="keyboardTracking" stdset="0">
<bool>false</bool>
</property>
<property name="unit" stdset="0">
<string notr="true">deg</string>
</property>
<property name="minimum" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="maximum" stdset="0">
<double>360.000000000000000</double>
</property>
<property name="value" stdset="0">
<double>360.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="angleOffsetWrapper" native="true">
<layout class="QHBoxLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label2">
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="angleOffset" native="true">
<property name="keyboardTracking" stdset="0">
<bool>false</bool>
</property>
<property name="unit" stdset="0">
<string notr="true">deg</string>
</property>
<property name="minimum" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="maximum" stdset="0">
<double>360.000000000000000</double>
</property>
<property name="value" stdset="0">
<double>360.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label3">
<property name="text">
<string>Occurrences</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::UIntSpinBox" name="spinOccurrences"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
<customwidget>
<class>Gui::UIntSpinBox</class>
<extends>QSpinBox</extends>
<header>Gui/SpinBox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>comboAxis</tabstop>
<tabstop>checkReverse</tabstop>
<tabstop>polarAngle</tabstop>
<tabstop>spinOccurrences</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -393,15 +393,15 @@ void TaskTransformedParameters::removeItemFromListWidget(QListWidget* widget,
}
}
void TaskTransformedParameters::fillAxisCombo(ComboLinks& combolinks, Part::Part2DObject* sketch)
void TaskTransformedParameters::fillAxisCombo(Gui::ComboLinks& combolinks, Part::Part2DObject* sketch)
{
combolinks.clear();
// add sketch axes
if (sketch) {
combolinks.addLink(sketch, "N_Axis", tr("Normal sketch axis"));
combolinks.addLink(sketch, "V_Axis", tr("Vertical sketch axis"));
combolinks.addLink(sketch, "H_Axis", tr("Horizontal sketch axis"));
combolinks.addLink(sketch, "V_Axis", tr("Vertical sketch axis"));
combolinks.addLink(sketch, "N_Axis", tr("Normal sketch axis"));
for (int i = 0; i < sketch->getAxisCount(); i++) {
QString itemText = tr("Construction line %1").arg(i + 1);
std::stringstream sub;
@@ -430,7 +430,8 @@ void TaskTransformedParameters::fillAxisCombo(ComboLinks& combolinks, Part::Part
combolinks.addLink(nullptr, std::string(), tr("Select reference…"));
}
void TaskTransformedParameters::fillPlanesCombo(ComboLinks& combolinks, Part::Part2DObject* sketch)
void TaskTransformedParameters::fillPlanesCombo(Gui::ComboLinks& combolinks,
Part::Part2DObject* sketch)
{
combolinks.clear();

View File

@@ -139,9 +139,9 @@ protected:
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
/// Fill combobox with the axis from the sketch and the own bodys origin axis
void fillAxisCombo(ComboLinks& combolinks, Part::Part2DObject* sketch);
void fillAxisCombo(Gui::ComboLinks& combolinks, Part::Part2DObject* sketch);
/// Fill combobox with the planes from the sketch and the own bodys origin planes
void fillPlanesCombo(ComboLinks& combolinks, Part::Part2DObject* sketch);
void fillPlanesCombo(Gui::ComboLinks& combolinks, Part::Part2DObject* sketch);
/**
* Returns the base transformed objectfromStdString

View File

@@ -24,7 +24,7 @@
#include "PreCompiled.h"
#include "ViewProviderLinearPattern.h"
#include "TaskLinearPatternParameters.h"
#include "TaskPatternParameters.h"
using namespace PartDesignGui;

View File

@@ -23,14 +23,14 @@
#include "PreCompiled.h"
#include "ViewProviderPolarPattern.h"
#include "TaskPolarPatternParameters.h"
#include "TaskPatternParameters.h"
using namespace PartDesignGui;
PROPERTY_SOURCE(PartDesignGui::ViewProviderPolarPattern,PartDesignGui::ViewProviderTransformed)
TaskDlgFeatureParameters *ViewProviderPolarPattern::getEditDialog() {
return new TaskDlgPolarPatternParameters (this);
return new TaskDlgLinearPatternParameters(this);
}
void ViewProviderPolarPattern::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)