From b68da9d844131cc71c2ed2b2c808dd1fb5a2b7b1 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Fri, 31 May 2024 12:10:17 +0200 Subject: [PATCH] GUI: Add UI for Up To Shape feature Add UI for Up To Shape feature and overall refactor of Pad / Pocket. --- src/Mod/PartDesign/App/FeatureExtrude.h | 4 + src/Mod/PartDesign/Gui/AppPartDesignGui.cpp | 1 + src/Mod/PartDesign/Gui/CMakeLists.txt | 2 + .../PartDesign/Gui/TaskExtrudeParameters.cpp | 374 +++++++++++++++--- .../PartDesign/Gui/TaskExtrudeParameters.h | 80 +++- src/Mod/PartDesign/Gui/TaskPadParameters.cpp | 25 +- src/Mod/PartDesign/Gui/TaskPadParameters.h | 11 +- .../PartDesign/Gui/TaskPadPocketParameters.ui | 141 ++++++- .../PartDesign/Gui/TaskPocketParameters.cpp | 25 +- src/Mod/PartDesign/Gui/TaskPocketParameters.h | 8 +- .../Gui/TaskSketchBasedParameters.cpp | 1 - .../Gui/TaskTransformedParameters.h | 6 +- .../PartDesign/Gui/ViewProviderExtrude.cpp | 64 +++ src/Mod/PartDesign/Gui/ViewProviderExtrude.h | 48 +++ src/Mod/PartDesign/Gui/ViewProviderPad.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProviderPad.h | 4 +- src/Mod/PartDesign/Gui/ViewProviderPocket.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProviderPocket.h | 4 +- 18 files changed, 684 insertions(+), 118 deletions(-) create mode 100644 src/Mod/PartDesign/Gui/ViewProviderExtrude.cpp create mode 100644 src/Mod/PartDesign/Gui/ViewProviderExtrude.h diff --git a/src/Mod/PartDesign/App/FeatureExtrude.h b/src/Mod/PartDesign/App/FeatureExtrude.h index 088c7ce8ea..51350074de 100644 --- a/src/Mod/PartDesign/App/FeatureExtrude.h +++ b/src/Mod/PartDesign/App/FeatureExtrude.h @@ -61,6 +61,10 @@ public: //@{ short mustExecute() const override; void setupObject() override; + + const char* getViewProviderName() const override { + return "PartDesignGui::ViewProviderExtrude"; + } //@} protected: diff --git a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp index b7ffceedea..550f8d62bc 100644 --- a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp +++ b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp @@ -126,6 +126,7 @@ PyMOD_INIT_FUNC(PartDesignGui) PartDesignGui::ViewProviderPython ::init(); PartDesignGui::ViewProviderBody ::init(); PartDesignGui::ViewProviderSketchBased ::init(); + PartDesignGui::ViewProviderExtrude ::init(); PartDesignGui::ViewProviderPocket ::init(); PartDesignGui::ViewProviderHole ::init(); PartDesignGui::ViewProviderPad ::init(); diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index bd26aff846..0cbc2eff0d 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -65,6 +65,8 @@ SET(PartDesignGuiViewProvider_SRCS ViewProviderBody.h ViewProviderSketchBased.cpp ViewProviderSketchBased.h + ViewProviderExtrude.cpp + ViewProviderExtrude.h ViewProviderPad.cpp ViewProviderPad.h ViewProviderHole.cpp diff --git a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp index 6ab7dce073..2f46379845 100644 --- a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.cpp @@ -23,15 +23,18 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include #endif #include #include #include #include +#include #include "ui_TaskPadPocketParameters.h" #include "TaskExtrudeParameters.h" +#include "TaskTransformedParameters.h" #include "ReferenceSelection.h" @@ -40,7 +43,7 @@ using namespace Gui; /* TRANSLATOR PartDesignGui::TaskExtrudeParameters */ -TaskExtrudeParameters::TaskExtrudeParameters(ViewProviderSketchBased *SketchBasedView, QWidget *parent, +TaskExtrudeParameters::TaskExtrudeParameters(ViewProviderExtrude *SketchBasedView, QWidget *parent, const std::string& pixmapname, const QString& parname) : TaskSketchBasedParameters(SketchBasedView, parent, pixmapname, parname) , propReferenceAxis(nullptr) @@ -161,9 +164,24 @@ void TaskExtrudeParameters::setupDialog() ui->lineFaceName->setProperty("FaceName", QByteArray(upToFace.c_str())); + updateShapeName(); + updateShapeFaces(); + translateModeList(index); + unselectShapeFaceAction = new QAction(tr("Remove"), this); + unselectShapeFaceAction->setShortcut(QKeySequence::Delete); +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + // display shortcut behind the context menu entry + unselectShapeFaceAction->setShortcutVisibleInContextMenu(true); +#endif + + ui->listWidgetReferences->addAction(unselectShapeFaceAction); + ui->listWidgetReferences->setContextMenuPolicy(Qt::ActionsContextMenu); + connectSlots(); + + ui->checkBoxAllFaces->setChecked(ui->listWidgetReferences->count() == 0); this->propReferenceAxis = &(extrude->ReferenceAxis); @@ -215,14 +233,90 @@ void TaskExtrudeParameters::connectSlots() this, &TaskExtrudeParameters::onMidplaneChanged); connect(ui->checkBoxReversed, &QCheckBox::toggled, this, &TaskExtrudeParameters::onReversedChanged); + connect(ui->checkBoxAllFaces, &QCheckBox::toggled, + this, &TaskExtrudeParameters::onAllFacesToggled); connect(ui->changeMode, qOverload(&QComboBox::currentIndexChanged), this, &TaskExtrudeParameters::onModeChanged); - connect(ui->buttonFace, &QPushButton::toggled, - this, &TaskExtrudeParameters::onButtonFace); + connect(ui->buttonFace, &QToolButton::toggled, + this, &TaskExtrudeParameters::onSelectFaceToggle); + connect(ui->buttonShape, &QToolButton::toggled, + this, &TaskExtrudeParameters::onSelectShapeToggle); connect(ui->lineFaceName, &QLineEdit::textEdited, this, &TaskExtrudeParameters::onFaceName); connect(ui->checkBoxUpdateView, &QCheckBox::toggled, this, &TaskExtrudeParameters::onUpdateView); + connect(ui->buttonShapeFace, &QToolButton::toggled, + this, &TaskExtrudeParameters::onSelectShapeFacesToggle); + connect(ui->listWidgetReferences, &QListWidget::item, + this, &TaskExtrudeParameters::onSelectShapeFacesToggle); + connect(unselectShapeFaceAction, &QAction::triggered, + this, &TaskExtrudeParameters::onUnselectShapeFacesTrigger); +} + +void TaskExtrudeParameters::onSelectShapeFacesToggle(bool checked) +{ + if (checked) { + setSelectionMode(SelectShapeFaces); + ui->buttonShapeFace->setText(tr("Preview")); + } else { + setSelectionMode(None); + ui->buttonShapeFace->setText(tr("Select faces")); + } +} + +void PartDesignGui::TaskExtrudeParameters::onUnselectShapeFacesTrigger() +{ + auto selected = ui->listWidgetReferences->selectedItems(); + auto faces = getShapeFaces(); + + auto extrude = static_cast(vp->getObject()); + + faces.erase(std::remove_if(faces.begin(), faces.end(), [selected](const std::string &face) { + for (auto &item : selected) { + if (item->text().toStdString() == face) { + return true; + } + } + + return false; + })); + + extrude->UpToShape.setValue(extrude->UpToShape.getValue(), faces); + + updateShapeFaces(); +} + +void TaskExtrudeParameters::setSelectionMode(SelectionMode mode) +{ + if (selectionMode == mode) { + return; + } + + ui->buttonShapeFace->setChecked(mode == SelectShapeFaces); + ui->buttonFace->setChecked(mode == SelectFace); + ui->buttonShape->setChecked(mode == SelectShape); + + selectionMode = mode; + + switch (mode) { + case SelectShape: + onSelectReference(AllowSelection::WHOLE); + Gui::Selection().addSelectionGate(new SelectionFilterGate("SELECT Part::Feature COUNT 1")); + break; + case SelectFace: + onSelectReference(AllowSelection::FACE); + break; + case SelectShapeFaces: + onSelectReference(AllowSelection::FACE); + static_cast(vp)->highlightShapeFaces(getShapeFaces()); + break; + case SelectReferenceAxis: + onSelectReference(AllowSelection::EDGE | AllowSelection::PLANAR | AllowSelection::CIRCLE); + break; + default: + static_cast(vp)->highlightShapeFaces({}); + onSelectReference(AllowSelection::NONE); + } } void TaskExtrudeParameters::tryRecomputeFeature() @@ -239,27 +333,29 @@ void TaskExtrudeParameters::tryRecomputeFeature() 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) { - selectedReferenceAxis(msg); - } - // if we have a selection of a face - else { - 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(); - } + switch (selectionMode) { + case SelectShape: + selectedShape(msg); + break; + + case SelectShapeFaces: + selectedShapeFace(msg); + break; + + case SelectFace: + selectedFace(msg); + break; + + case SelectReferenceAxis: + selectedReferenceAxis(msg); + break; + + default: + // no-op + break; } } - else if (msg.Type == Gui::SelectionChanges::ClrSelection && selectionFace) { + else if (msg.Type == Gui::SelectionChanges::ClrSelection && selectionMode == SelectFace) { clearFaceName(); } } @@ -268,15 +364,103 @@ void TaskExtrudeParameters::selectedReferenceAxis(const Gui::SelectionChanges& m { std::vector edge; App::DocumentObject* selObj; + if (getReferencedSelection(vp->getObject(), msg, selObj, edge) && selObj) { - exitSelectionMode(); + setSelectionMode(None); + propReferenceAxis->setValue(selObj, edge); tryRecomputeFeature(); + // update direction combobox fillDirectionCombo(); } } +void TaskExtrudeParameters::selectedShapeFace(const Gui::SelectionChanges& msg) +{ + auto extrude = static_cast(vp->getObject()); + auto document = extrude->getDocument(); + + if (strcmp(msg.pDocName, document->getName()) != 0) { + return; + } + + auto base = static_cast(extrude->UpToShape.getValue()); + + if (strcmp(msg.pObjectName, base->getNameInDocument()) != 0) { + return; + } + + std::vector faces = getShapeFaces(); + std::string subName(msg.pSubName); + + if (subName.empty()) { + return; + } + + auto positionInList = std::find(faces.begin(), faces.end(), subName); + + if (positionInList != faces.end()) { //If it's found then it's in the list so we remove it. + faces.erase(positionInList); + } + else { //if it's not found then it's not yet in the list so we add it. + faces.push_back(subName); + } + + extrude->UpToShape.setValue(base, faces); + + updateShapeFaces(); + + tryRecomputeFeature(); +} + +void PartDesignGui::TaskExtrudeParameters::selectedFace(const Gui::SelectionChanges& msg) +{ + 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(); + } + + setSelectionMode(None); +} + +void PartDesignGui::TaskExtrudeParameters::selectedShape(const Gui::SelectionChanges& msg) +{ + auto extrude = static_cast(vp->getObject()); + auto document = extrude->getDocument(); + + if (strcmp(msg.pDocName, document->getName()) != 0) { + return; + } + + Gui::Selection().clearSelection(); + + auto base = extrude->getBaseObject(); + auto ref = document->getObject(msg.pObjectName); + + extrude->UpToShape.setValue(ref); + + ui->checkBoxAllFaces->setChecked(true); + + setSelectionMode(None); + + updateShapeName(); + updateShapeFaces(); + + tryRecomputeFeature(); +} + void TaskExtrudeParameters::clearFaceName() { QSignalBlocker block(ui->lineFaceName); @@ -286,6 +470,52 @@ void TaskExtrudeParameters::clearFaceName() } +void TaskExtrudeParameters::updateShapeName() +{ + QSignalBlocker block(ui->lineShapeName); + + auto extrude = static_cast(vp->getObject()); + auto shape = extrude->UpToShape.getValue(); + + if (shape) { + ui->lineShapeName->setText(QString::fromStdString(shape->getFullName())); + } else { + ui->lineShapeName->setText({}); + ui->lineShapeName->setPlaceholderText(tr("No shape selected")); + } +} + +void TaskExtrudeParameters::updateShapeFaces() +{ + auto extrude = static_cast(vp->getObject()); + auto faces = getShapeFaces(); + + ui->listWidgetReferences->clear(); + for (auto &ref : faces) { + ui->listWidgetReferences->addItem(QString::fromStdString(ref)); + } + + if (selectionMode == SelectShapeFaces) { + static_cast(vp)->highlightShapeFaces(faces); + } +} + +std::vector PartDesignGui::TaskExtrudeParameters::getShapeFaces() +{ + std::vector faces; + + auto extrude = static_cast(vp->getObject()); + auto allRefs = extrude->UpToShape.getSubValues(); + + std::copy_if( + allRefs.begin(), allRefs.end(), + std::back_inserter(faces), + [](const std::string& ref) { return boost::starts_with(ref, "Face"); } + ); + + return faces; +} + void TaskExtrudeParameters::onLengthChanged(double len) { PartDesign::FeatureExtrude* extrude = static_cast(vp->getObject()); @@ -418,7 +648,7 @@ void TaskExtrudeParameters::addAxisToCombo(App::DocumentObject* linkObj, std::st lnk.setValue(linkObj, std::vector(1, linkSubname)); } -void TaskExtrudeParameters::setCheckboxes(Modes mode, Type type) +void TaskExtrudeParameters::setCheckboxes(Mode mode, Type type) { // disable/hide everything unless we are sure we don't need it // exception: the direction parameters are in any case visible @@ -430,10 +660,11 @@ void TaskExtrudeParameters::setCheckboxes(Modes mode, Type type) bool isMidplaneVisible = false; bool isReversedEnabled = false; bool isFaceEditVisible = false; + bool isShapeEditVisible = false; bool isTaperEditVisible = false; bool isTaperEdit2Visible = false; - if (mode == Modes::Dimension) { + if (mode == Mode::Dimension) { isLengthEditVisible = true; ui->lengthEdit->selectNumber(); QMetaObject::invokeMethod(ui->lengthEdit, "setFocus", Qt::QueuedConnection); @@ -443,22 +674,22 @@ void TaskExtrudeParameters::setCheckboxes(Modes mode, Type type) // Reverse only makes sense if Midplane is not true isReversedEnabled = !ui->checkBoxMidplane->isChecked(); } - else if (mode == Modes::ThroughAll && type == Type::Pocket) { + else if (mode == Mode::ThroughAll && type == Type::Pocket) { isOffsetEditVisible = true; isOffsetEditEnabled = false; // offset may have some meaning for through all but it doesn't work isMidplaneEnabled = true; isMidplaneVisible = true; isReversedEnabled = !ui->checkBoxMidplane->isChecked(); } - else if (mode == Modes::ToLast && type == Type::Pad) { + else if (mode == Mode::ToLast && type == Type::Pad) { isOffsetEditVisible = true; isReversedEnabled = true; } - else if (mode == Modes::ToFirst) { + else if (mode == Mode::ToFirst) { isOffsetEditVisible = true; isReversedEnabled = true; } - else if (mode == Modes::ToFace) { + else if (mode == Mode::ToFace) { isOffsetEditVisible = true; isReversedEnabled = true; isFaceEditVisible = true; @@ -467,7 +698,15 @@ void TaskExtrudeParameters::setCheckboxes(Modes mode, Type type) if (ui->lineFaceName->property("FeatureName").isNull()) ui->buttonFace->setChecked(true); } - else if (mode == Modes::TwoDimensions) { + else if (mode == Mode::ToShape) { + isReversedEnabled = true; + isShapeEditVisible = true; + + if (!ui->checkBoxAllFaces->isChecked()) { + ui->buttonShapeFace->setChecked(true); + } + } + else if (mode == Mode::TwoDimensions) { isLengthEditVisible = true; isLengthEdit2Visible = true; isTaperEditVisible = true; @@ -506,6 +745,8 @@ void TaskExtrudeParameters::setCheckboxes(Modes mode, Type type) if (!isFaceEditVisible) { ui->buttonFace->setChecked(false); } + + ui->upToShapeList->setVisible(isShapeEditVisible); } void TaskExtrudeParameters::onDirectionCBChanged(int num) @@ -525,13 +766,11 @@ void TaskExtrudeParameters::onDirectionCBChanged(int num) // 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 == DirectionModes::Select) { // to distinguish that this is the direction selection - selectionFace = false; + setSelectionMode(SelectReferenceAxis); setDirectionMode(num); - TaskSketchBasedParameters::onSelectReference(AllowSelection::EDGE | - AllowSelection::PLANAR | - AllowSelection::CIRCLE); } else { if (lnk.getValue()) { @@ -543,9 +782,9 @@ void TaskExtrudeParameters::onDirectionCBChanged(int num) } // in case the user is in selection mode, but changed his mind before selecting anything - exitSelectionMode(); - + setSelectionMode(None); setDirectionMode(num); + extrude->ReferenceAxis.setValue(lnk.getValue(), lnk.getSubValues()); tryRecomputeFeature(); updateDirectionEdits(); @@ -561,10 +800,27 @@ void TaskExtrudeParameters::onAlongSketchNormalChanged(bool on) void TaskExtrudeParameters::onDirectionToggled(bool on) { - if (on) + if (on) { ui->groupBoxDirection->show(); - else + } + else { ui->groupBoxDirection->hide(); + } +} + +void PartDesignGui::TaskExtrudeParameters::onAllFacesToggled(bool on) +{ + ui->upToShapeFaces->setVisible(!on); + ui->buttonShapeFace->setChecked(false); + + if (on) { + auto extrude = static_cast(vp->getObject()); + extrude->UpToShape.setValue(extrude->UpToShape.getValue()); + + updateShapeFaces(); + + tryRecomputeFeature(); + } } void TaskExtrudeParameters::onXDirectionEditChanged(double len) @@ -678,18 +934,28 @@ void TaskExtrudeParameters::getReferenceAxis(App::DocumentObject*& obj, std::vec } } -void TaskExtrudeParameters::onButtonFace(const bool checked) +void TaskExtrudeParameters::onSelectFaceToggle(const bool checked) { - if (!checked) + if (!checked) { handleLineFaceNameNo(); - else + } + else { handleLineFaceNameClick(); // sets placeholder text + setSelectionMode(SelectFace); + } +} - // to distinguish that this is the direction selection - selectionFace = true; +void PartDesignGui::TaskExtrudeParameters::onSelectShapeToggle(const bool checked) +{ + if (checked) { + setSelectionMode(SelectShape); - // only faces are allowed - TaskSketchBasedParameters::onSelectReference(checked ? AllowSelection::FACE : AllowSelection::NONE); + ui->lineShapeName->setText({}); + ui->lineShapeName->setPlaceholderText(tr("Click on a shape in the model")); + } else { + setSelectionMode(None); + updateShapeName(); + } } void TaskExtrudeParameters::onFaceName(const QString& text) @@ -897,4 +1163,22 @@ void TaskExtrudeParameters::handleLineFaceNameNo() ui->lineFaceName->setPlaceholderText(tr("No face selected")); } +TaskDlgExtrudeParameters::TaskDlgExtrudeParameters(PartDesignGui::ViewProviderExtrude* vp) + : TaskDlgSketchBasedParameters(vp) +{} + +bool TaskDlgExtrudeParameters::accept() +{ + getTaskParameters()->setSelectionMode(TaskExtrudeParameters::None); + + return TaskDlgSketchBasedParameters::accept(); +} + +bool TaskDlgExtrudeParameters::reject() +{ + getTaskParameters()->setSelectionMode(TaskExtrudeParameters::None); + + return TaskDlgSketchBasedParameters::reject(); +} + #include "moc_TaskExtrudeParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h index 062030cd52..93d293ada0 100644 --- a/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h +++ b/src/Mod/PartDesign/Gui/TaskExtrudeParameters.h @@ -24,7 +24,7 @@ #define GUI_TASKVIEW_TaskExtrudeParameters_H #include "TaskSketchBasedParameters.h" -#include "ViewProviderSketchBased.h" +#include "ViewProviderExtrude.h" class Ui_TaskPadPocketParameters; @@ -52,7 +52,30 @@ class TaskExtrudeParameters : public TaskSketchBasedParameters }; public: - TaskExtrudeParameters(ViewProviderSketchBased *SketchBasedView, QWidget *parent, + enum class Type { + Pad, + Pocket + }; + + enum class Mode { + Dimension, + ThroughAll, + ToLast = ThroughAll, + ToFirst, + ToFace, + TwoDimensions, + ToShape, + }; + + enum SelectionMode { + None, + SelectFace, + SelectShape, + SelectShapeFaces, + SelectReferenceAxis + }; + + TaskExtrudeParameters(ViewProviderExtrude *ExtrudeView, QWidget *parent, const std::string& pixmapname, const QString& parname); ~TaskExtrudeParameters() override; @@ -63,18 +86,7 @@ public: bool hasSketch = true); void applyParameters(QString facename); - enum class Type { - Pad, - Pocket - }; - enum class Modes { - Dimension, - ThroughAll, - ToLast = ThroughAll, - ToFirst, - ToFace, - TwoDimensions - }; + void setSelectionMode(SelectionMode mode); protected Q_SLOTS: void onLengthChanged(double); @@ -85,17 +97,22 @@ protected Q_SLOTS: void onDirectionCBChanged(int); void onAlongSketchNormalChanged(bool); void onDirectionToggled(bool); + void onAllFacesToggled(bool); void onXDirectionEditChanged(double); void onYDirectionEditChanged(double); void onZDirectionEditChanged(double); void onMidplaneChanged(bool); void onReversedChanged(bool); - void onButtonFace(const bool checked = true); void onFaceName(const QString& text); + void onSelectFaceToggle(const bool checked = true); + void onSelectShapeToggle(const bool checked = true); + void onSelectShapeFacesToggle(const bool checked); + void onUnselectShapeFacesTrigger(); + virtual void onModeChanged(int); protected: - void setCheckboxes(Modes mode, Type type); + void setCheckboxes(Mode mode, Type type); void setupDialog(); void readValuesFromHistory(); void changeEvent(QEvent *e) override; @@ -122,18 +139,45 @@ protected: void handleLineFaceNameNo(); private: + void selectedReferenceAxis(const Gui::SelectionChanges& msg); + void selectedFace(const Gui::SelectionChanges& msg); + void selectedShape(const Gui::SelectionChanges& msg); + void selectedShapeFace(const Gui::SelectionChanges& msg); + void tryRecomputeFeature(); void translateFaceName(); void connectSlots(); bool hasProfileFace(PartDesign::ProfileBased*) const; - void selectedReferenceAxis(const Gui::SelectionChanges& msg); void clearFaceName(); + void updateShapeName(); + void updateShapeFaces(); + + std::vector getShapeFaces(); + protected: QWidget* proxy; + QAction* unselectShapeFaceAction; + std::unique_ptr ui; - bool selectionFace; std::vector> axesInList; + + SelectionMode selectionMode = None; +}; + +class TaskDlgExtrudeParameters : public TaskDlgSketchBasedParameters +{ + Q_OBJECT + +public: + explicit TaskDlgExtrudeParameters(PartDesignGui::ViewProviderExtrude *vp); + ~TaskDlgExtrudeParameters() override = default; + + bool accept() override; + bool reject() override; + +protected: + virtual TaskExtrudeParameters* getTaskParameters() = 0; }; } //namespace PartDesignGui diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index ad134ee1a6..44fb3dd410 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -72,6 +72,7 @@ void TaskPadParameters::translateModeList(int index) ui->changeMode->addItem(tr("To first")); ui->changeMode->addItem(tr("Up to face")); ui->changeMode->addItem(tr("Two dimensions")); + ui->changeMode->addItem(tr("Up to shape")); ui->changeMode->setCurrentIndex(index); } @@ -80,27 +81,27 @@ void TaskPadParameters::updateUI(int index) // update direction combobox fillDirectionCombo(); // set and enable checkboxes - setCheckboxes(static_cast(index), Type::Pad); + setCheckboxes(static_cast(index), Type::Pad); } void TaskPadParameters::onModeChanged(int index) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); - switch (static_cast(index)) { - case Modes::Dimension: + switch (static_cast(index)) { + case Mode::Dimension: pcPad->Type.setValue("Length"); // Avoid error message if (ui->lengthEdit->value() < Base::Quantity(Precision::Confusion(), Base::Unit::Length)) ui->lengthEdit->setValue(5.0); break; - case Modes::ToLast: + case Mode::ToLast: pcPad->Type.setValue("UpToLast"); break; - case Modes::ToFirst: + case Mode::ToFirst: pcPad->Type.setValue("UpToFirst"); break; - case Modes::ToFace: + case Mode::ToFace: // Note: ui->checkBoxReversed is purposely enabled because the selected face // could be a circular one around the sketch pcPad->Type.setValue("UpToFace"); @@ -109,9 +110,12 @@ void TaskPadParameters::onModeChanged(int index) handleLineFaceNameClick(); // sets placeholder text } break; - case Modes::TwoDimensions: + case Mode::TwoDimensions: pcPad->Type.setValue("TwoLengths"); break; + case Mode::ToShape: + pcPad->Type.setValue("UpToShape"); + break; } updateUI(index); @@ -121,7 +125,7 @@ void TaskPadParameters::onModeChanged(int index) void TaskPadParameters::apply() { QString facename = QString::fromLatin1("None"); - if (static_cast(getMode()) == Modes::ToFace) { + if (static_cast(getMode()) == Mode::ToFace) { facename = getFaceName(); } applyParameters(facename); @@ -133,10 +137,9 @@ void TaskPadParameters::apply() //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgPadParameters::TaskDlgPadParameters(ViewProviderPad *PadView, bool /*newObj*/) - : TaskDlgSketchBasedParameters(PadView) + : TaskDlgExtrudeParameters(PadView), parameters(new TaskPadParameters(PadView)) { - assert(vp); - Content.push_back ( new TaskPadParameters(PadView ) ); + Content.push_back(parameters); } //==== calls from the TaskView =============================================================== diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.h b/src/Mod/PartDesign/Gui/TaskPadParameters.h index 0a353f410a..a36a8fa0cd 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.h @@ -55,15 +55,20 @@ private: }; /// simulation dialog for the TaskView -class TaskDlgPadParameters : public TaskDlgSketchBasedParameters +class TaskDlgPadParameters : public TaskDlgExtrudeParameters { Q_OBJECT public: explicit TaskDlgPadParameters(ViewProviderPad *PadView, bool newObj=false); - ViewProviderPad* getPadView() const - { return static_cast(vp); } + ViewProviderPad* getPadView() const { return static_cast(vp); } + +protected: + TaskExtrudeParameters* getTaskParameters() override { return parameters; }; + +private: + TaskPadParameters* parameters; }; } //namespace PartDesignGui diff --git a/src/Mod/PartDesign/Gui/TaskPadPocketParameters.ui b/src/Mod/PartDesign/Gui/TaskPadPocketParameters.ui index edf4f6493d..9249302006 100644 --- a/src/Mod/PartDesign/Gui/TaskPadPocketParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPadPocketParameters.ui @@ -7,7 +7,7 @@ 0 0 300 - 598 + 772 @@ -40,14 +40,14 @@ - - + + false mm - + 0.000000000000000 @@ -60,8 +60,8 @@ - - + + false @@ -77,8 +77,8 @@ - - + + false @@ -88,8 +88,118 @@ + + + + QFrame::Plain + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + true + + + + + + + + 0 + 22 + + + + Select shape + + + true + + + + + + + + + true + + + Applies length symmetrically to sketch plane + + + Select all faces + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Click button to enter selection mode, + click again to end selection + + + Select + + + true + + + + + + + QAbstractItemView::ExtendedSelection + + + + + + + + + + + + + true + + + @@ -106,13 +216,6 @@ - - - - true - - - @@ -321,8 +424,8 @@ measured along the specified direction - - + + false @@ -345,8 +448,8 @@ measured along the specified direction - - + + false diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp index 3dfa4538e0..7c820fae0b 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp @@ -73,6 +73,7 @@ void TaskPocketParameters::translateModeList(int index) ui->changeMode->addItem(tr("To first")); ui->changeMode->addItem(tr("Up to face")); ui->changeMode->addItem(tr("Two dimensions")); + ui->changeMode->addItem(tr("Up to shape")); ui->changeMode->setCurrentIndex(index); } @@ -81,15 +82,15 @@ void TaskPocketParameters::updateUI(int index) // update direction combobox fillDirectionCombo(); // set and enable checkboxes - setCheckboxes(static_cast(index), Type::Pocket); + setCheckboxes(static_cast(index), Type::Pocket); } void TaskPocketParameters::onModeChanged(int index) { PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); - switch (static_cast(index)) { - case Modes::Dimension: + switch (static_cast(index)) { + case Mode::Dimension: // Why? See below for "UpToFace" if (oldLength < Precision::Confusion()) oldLength = 5.0; @@ -97,15 +98,15 @@ void TaskPocketParameters::onModeChanged(int index) ui->lengthEdit->setValue(oldLength); pcPocket->Type.setValue("Length"); break; - case Modes::ThroughAll: + case Mode::ThroughAll: oldLength = pcPocket->Length.getValue(); pcPocket->Type.setValue("ThroughAll"); break; - case Modes::ToFirst: + case Mode::ToFirst: oldLength = pcPocket->Length.getValue(); pcPocket->Type.setValue("UpToFirst"); break; - case Modes::ToFace: + case Mode::ToFace: // Note: ui->checkBoxReversed is purposely enabled because the selected face // could be a circular one around the sketch // Also note: Because of the code at the beginning of Pocket::execute() which is used @@ -119,10 +120,13 @@ void TaskPocketParameters::onModeChanged(int index) handleLineFaceNameClick(); // sets placeholder text } break; - case Modes::TwoDimensions: + case Mode::TwoDimensions: oldLength = pcPocket->Length.getValue(); pcPocket->Type.setValue("TwoLengths"); break; + case Mode::ToShape: + pcPocket->Type.setValue("UpToShape"); + break; } updateUI(index); @@ -132,7 +136,7 @@ void TaskPocketParameters::onModeChanged(int index) void TaskPocketParameters::apply() { QString facename = QString::fromLatin1("None"); - if (static_cast(getMode()) == Modes::ToFace) { + if (static_cast(getMode()) == Mode::ToFace) { facename = getFaceName(); } applyParameters(facename); @@ -144,10 +148,9 @@ void TaskPocketParameters::apply() //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgPocketParameters::TaskDlgPocketParameters(ViewProviderPocket *PocketView) - : TaskDlgSketchBasedParameters(PocketView) + : TaskDlgExtrudeParameters(PocketView), parameters(new TaskPocketParameters(PocketView)) { - assert(vp); - Content.push_back ( new TaskPocketParameters(PocketView ) ); + Content.push_back(parameters); } #include "moc_TaskPocketParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.h b/src/Mod/PartDesign/Gui/TaskPocketParameters.h index e7e27e7e2f..6de89f7b58 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.h @@ -58,7 +58,7 @@ private: }; /// simulation dialog for the TaskView -class TaskDlgPocketParameters : public TaskDlgSketchBasedParameters +class TaskDlgPocketParameters : public TaskDlgExtrudeParameters { Q_OBJECT @@ -67,6 +67,12 @@ public: ViewProviderPocket* getPocketView() const { return static_cast(vp); } + +protected: + TaskExtrudeParameters* getTaskParameters() override { return parameters; } + +private: + TaskPocketParameters* parameters; }; } //namespace PartDesignGui diff --git a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp index 4bf845c716..14fb0dce70 100644 --- a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp @@ -106,7 +106,6 @@ void TaskSketchBasedParameters::finishReferenceSelection(App::DocumentObject* pr void TaskSketchBasedParameters::onSelectReference(AllowSelectionFlags allow) { // Note: Even if there is no solid, App::Plane and Part::Datum can still be selected - PartDesign::ProfileBased* pcSketchBased = dynamic_cast(vp->getObject()); if (pcSketchBased) { // The solid this feature will be fused to diff --git a/src/Mod/PartDesign/Gui/TaskTransformedParameters.h b/src/Mod/PartDesign/Gui/TaskTransformedParameters.h index 98ebd66498..0198e8a9a8 100644 --- a/src/Mod/PartDesign/Gui/TaskTransformedParameters.h +++ b/src/Mod/PartDesign/Gui/TaskTransformedParameters.h @@ -163,6 +163,8 @@ public: /// Exit the selection mode of the associated task panel void exitSelectionMode(); + static void removeItemFromListWidget(QListWidget* widget, const QString& itemstr); + protected: /** Setup the standalone UI. * Call this in the derived destructor with ViewProvider. @@ -212,7 +214,7 @@ protected: void fillPlanesCombo(ComboLinks& combolinks, Part::Part2DObject* sketch); /** - * Returns the base transformed object + * Returns the base transformed objectfromStdString * For stand alone features it will be objects associated with this object * For features inside multitransform it will be the base multitransform object */ @@ -258,8 +260,6 @@ private: void changeEvent(QEvent* event) override; - static void removeItemFromListWidget(QListWidget* widget, const QString& itemstr); - protected: enum class SelectionMode { diff --git a/src/Mod/PartDesign/Gui/ViewProviderExtrude.cpp b/src/Mod/PartDesign/Gui/ViewProviderExtrude.cpp new file mode 100644 index 0000000000..277d69480d --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderExtrude.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * 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 +#endif + +#include +#include +#include +#include + +#include "TaskExtrudeParameters.h" +#include "ViewProviderExtrude.h" + + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderExtrude, PartDesignGui::ViewProviderSketchBased) + +void PartDesignGui::ViewProviderExtrude::highlightShapeFaces(const std::vector& faces) +{ + auto extrude = static_cast(getObject()); + auto base = static_cast(extrude->UpToShape.getValue()); + + auto baseViewProvider = + static_cast(Gui::Application::Instance->getViewProvider(base)); + + baseViewProvider->unsetHighlightedFaces(); + baseViewProvider->updateView(); + + if (faces.size() > 0) { + std::vector colors = baseViewProvider->DiffuseColor.getValues(); + + auto color = baseViewProvider->ShapeAppearance.getDiffuseColor(); + + PartGui::ReferenceHighlighter highlighter(base->Shape.getValue(), color); + highlighter.getFaceColors(faces, colors); + + baseViewProvider->setHighlightedFaces(colors); + } +} diff --git a/src/Mod/PartDesign/Gui/ViewProviderExtrude.h b/src/Mod/PartDesign/Gui/ViewProviderExtrude.h new file mode 100644 index 0000000000..02f080811d --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderExtrude.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (c) 2024 Kacper Donat * + * * + * 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 PARTGUI_ViewProviderExtrude_H +#define PARTGUI_ViewProviderExtrude_H + +#include "ViewProviderSketchBased.h" + + +namespace PartDesignGui { + +class PartDesignGuiExport ViewProviderExtrude : public ViewProviderSketchBased +{ + PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderExtrude); + +public: + ViewProviderExtrude() = default; + ~ViewProviderExtrude() override = default; + + void highlightShapeFaces(const std::vector& faces); +}; + + + +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderExtrude_H diff --git a/src/Mod/PartDesign/Gui/ViewProviderPad.cpp b/src/Mod/PartDesign/Gui/ViewProviderPad.cpp index 1d538990fd..8eb1955ebb 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPad.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPad.cpp @@ -32,7 +32,7 @@ using namespace PartDesignGui; -PROPERTY_SOURCE(PartDesignGui::ViewProviderPad,PartDesignGui::ViewProviderSketchBased) +PROPERTY_SOURCE(PartDesignGui::ViewProviderPad, PartDesignGui::ViewProviderExtrude) ViewProviderPad::ViewProviderPad() { diff --git a/src/Mod/PartDesign/Gui/ViewProviderPad.h b/src/Mod/PartDesign/Gui/ViewProviderPad.h index cdc3a8a2b6..4d14e3156c 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPad.h +++ b/src/Mod/PartDesign/Gui/ViewProviderPad.h @@ -24,11 +24,11 @@ #ifndef PARTGUI_ViewProviderPad_H #define PARTGUI_ViewProviderPad_H -#include "ViewProviderSketchBased.h" +#include "ViewProviderExtrude.h" namespace PartDesignGui { -class PartDesignGuiExport ViewProviderPad : public ViewProviderSketchBased +class PartDesignGuiExport ViewProviderPad : public ViewProviderExtrude { PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderPad); diff --git a/src/Mod/PartDesign/Gui/ViewProviderPocket.cpp b/src/Mod/PartDesign/Gui/ViewProviderPocket.cpp index d035bfdf0b..5114457c69 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPocket.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPocket.cpp @@ -33,7 +33,7 @@ using namespace PartDesignGui; -PROPERTY_SOURCE(PartDesignGui::ViewProviderPocket,PartDesignGui::ViewProviderSketchBased) +PROPERTY_SOURCE(PartDesignGui::ViewProviderPocket, PartDesignGui::ViewProviderExtrude) ViewProviderPocket::ViewProviderPocket() { diff --git a/src/Mod/PartDesign/Gui/ViewProviderPocket.h b/src/Mod/PartDesign/Gui/ViewProviderPocket.h index d51381e933..5f4b528f08 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPocket.h +++ b/src/Mod/PartDesign/Gui/ViewProviderPocket.h @@ -24,12 +24,12 @@ #ifndef PARTGUI_ViewProviderPocket_H #define PARTGUI_ViewProviderPocket_H -#include "ViewProviderSketchBased.h" +#include "ViewProviderExtrude.h" namespace PartDesignGui { -class PartDesignGuiExport ViewProviderPocket : public ViewProviderSketchBased +class PartDesignGuiExport ViewProviderPocket : public ViewProviderExtrude { PROPERTY_HEADER_WITH_OVERRIDE(PartDesignGui::ViewProviderPocket);