diff --git a/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp b/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp index b860b160ee..baf69e1b7f 100644 --- a/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskChamferParameters.cpp @@ -162,13 +162,16 @@ void TaskChamferParameters::onSelectionChanged(const Gui::SelectionChanges& msg) void TaskChamferParameters::onCheckBoxUseAllEdgesToggled(bool checked) { - if(checked) - setSelectionMode(none); - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - ui->buttonRefSel->setEnabled(!checked); - ui->listWidgetReferences->setEnabled(!checked); - pcChamfer->UseAllEdges.setValue(checked); - pcChamfer->getDocument()->recomputeFeature(pcChamfer); + if (auto chamfer = getObject()) { + if (checked) { + setSelectionMode(none); + } + + ui->buttonRefSel->setEnabled(!checked); + ui->listWidgetReferences->setEnabled(!checked); + chamfer->UseAllEdges.setValue(checked); + chamfer->recomputeFeature(); + } } void TaskChamferParameters::setButtons(const selectionModes mode) @@ -189,58 +192,63 @@ void TaskChamferParameters::onAddAllEdges() void TaskChamferParameters::onTypeChanged(int index) { - setSelectionMode(none); - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - pcChamfer->ChamferType.setValue(index); - ui->stackedWidget->setCurrentIndex(index); - ui->flipDirection->setEnabled(index != 0); // Enable if type is not "Equal distance" - pcChamfer->getDocument()->recomputeFeature(pcChamfer); - // hide the chamfer if there was a computation error - hideOnError(); + if (auto chamfer = getObject()) { + setSelectionMode(none); + chamfer->ChamferType.setValue(index); + ui->stackedWidget->setCurrentIndex(index); + ui->flipDirection->setEnabled(index != 0); // Enable if type is not "Equal distance" + chamfer->recomputeFeature(); + // hide the chamfer if there was a computation error + hideOnError(); + } } void TaskChamferParameters::onSizeChanged(double len) { - setSelectionMode(none); - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - setupTransaction(); - pcChamfer->Size.setValue(len); - pcChamfer->getDocument()->recomputeFeature(pcChamfer); - // hide the chamfer if there was a computation error - hideOnError(); + if (auto chamfer = getObject()) { + setSelectionMode(none); + setupTransaction(); + chamfer->Size.setValue(len); + chamfer->recomputeFeature(); + // hide the chamfer if there was a computation error + hideOnError(); + } } void TaskChamferParameters::onSize2Changed(double len) { - setSelectionMode(none); - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - setupTransaction(); - pcChamfer->Size2.setValue(len); - pcChamfer->getDocument()->recomputeFeature(pcChamfer); - // hide the chamfer if there was a computation error - hideOnError(); + if (auto chamfer = getObject()) { + setSelectionMode(none); + setupTransaction(); + chamfer->Size2.setValue(len); + chamfer->recomputeFeature(); + // hide the chamfer if there was a computation error + hideOnError(); + } } void TaskChamferParameters::onAngleChanged(double angle) { - setSelectionMode(none); - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - setupTransaction(); - pcChamfer->Angle.setValue(angle); - pcChamfer->getDocument()->recomputeFeature(pcChamfer); - // hide the chamfer if there was a computation error - hideOnError(); + if (auto chamfer = getObject()) { + setSelectionMode(none); + setupTransaction(); + chamfer->Angle.setValue(angle); + chamfer->recomputeFeature(); + // hide the chamfer if there was a computation error + hideOnError(); + } } void TaskChamferParameters::onFlipDirection(bool flip) { - setSelectionMode(none); - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - setupTransaction(); - pcChamfer->FlipDirection.setValue(flip); - pcChamfer->getDocument()->recomputeFeature(pcChamfer); - // hide the chamfer if there was a computation error - hideOnError(); + if (auto chamfer = getObject()) { + setSelectionMode(none); + setupTransaction(); + chamfer->FlipDirection.setValue(flip); + chamfer->recomputeFeature(); + // hide the chamfer if there was a computation error + hideOnError(); + } } int TaskChamferParameters::getType() const @@ -295,13 +303,9 @@ void TaskChamferParameters::changeEvent(QEvent *e) void TaskChamferParameters::apply() { - std::string name = DressUpView->getObject()->getNameInDocument(); + auto chamfer = getObject(); - //Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Chamfer changed")); - - PartDesign::Chamfer* pcChamfer = static_cast(DressUpView->getObject()); - - const int chamfertype = pcChamfer->ChamferType.getValue(); + const int chamfertype = chamfer->ChamferType.getValue(); switch(chamfertype) { diff --git a/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp b/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp index ef5eac6fa9..5759661edf 100644 --- a/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDraftParameters.cpp @@ -126,9 +126,9 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg) referenceSelected(msg, ui->listWidgetReferences); } else if (selectionMode == plane) { - PartDesign::Draft* pcDraft = static_cast(DressUpView->getObject()); + auto pcDraft = getObject(); std::vector planes; - App::DocumentObject* selObj; + App::DocumentObject* selObj {}; getReferencedSelection(pcDraft, msg, selObj, planes); if(!selObj) return; @@ -138,12 +138,12 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg) pcDraft->getDocument()->recomputeFeature(pcDraft); // highlight existing references for possible further selections - DressUpView->highlightReferences(true); + getDressUpView()->highlightReferences(true); // hide the draft if there was a computation error hideOnError(); } else if (selectionMode == line) { - PartDesign::Draft* pcDraft = static_cast(DressUpView->getObject()); + auto pcDraft = getObject(); std::vector edges; App::DocumentObject* selObj; getReferencedSelection(pcDraft, msg, selObj, edges); @@ -155,7 +155,7 @@ void TaskDraftParameters::onSelectionChanged(const Gui::SelectionChanges& msg) pcDraft->getDocument()->recomputeFeature(pcDraft); // highlight existing references for possible further selections - DressUpView->highlightReferences(true); + getDressUpView()->highlightReferences(true); // hide the draft if there was a computation error hideOnError(); } @@ -204,7 +204,7 @@ void TaskDraftParameters::getPlane(App::DocumentObject*& obj, std::vector(1,""); QStringList parts = ui->linePlane->text().split(QChar::fromLatin1(':')); - obj = DressUpView->getObject()->getDocument()->getObject(parts[0].toStdString().c_str()); + obj = getObject()->getDocument()->getObject(parts[0].toStdString().c_str()); if (parts.size() > 1) sub[0] = parts[1].toStdString(); } @@ -213,20 +213,21 @@ void TaskDraftParameters::getLine(App::DocumentObject*& obj, std::vector(1,""); QStringList parts = ui->lineLine->text().split(QChar::fromLatin1(':')); - obj = DressUpView->getObject()->getDocument()->getObject(parts[0].toStdString().c_str()); + obj = getObject()->getDocument()->getObject(parts[0].toStdString().c_str()); if (parts.size() > 1) sub[0] = parts[1].toStdString(); } void TaskDraftParameters::onAngleChanged(double angle) { - setButtons(none); - PartDesign::Draft* pcDraft = static_cast(DressUpView->getObject()); - setupTransaction(); - pcDraft->Angle.setValue(angle); - pcDraft->getDocument()->recomputeFeature(pcDraft); - // hide the draft if there was a computation error - hideOnError(); + if (auto draft = getObject()) { + setButtons(none); + setupTransaction(); + draft->Angle.setValue(angle); + draft->recomputeFeature(); + // hide the draft if there was a computation error + hideOnError(); + } } double TaskDraftParameters::getAngle() const @@ -234,14 +235,16 @@ double TaskDraftParameters::getAngle() const return ui->draftAngle->value().getValue(); } -void TaskDraftParameters::onReversedChanged(const bool on) { - setButtons(none); - PartDesign::Draft* pcDraft = static_cast(DressUpView->getObject()); - setupTransaction(); - pcDraft->Reversed.setValue(on); - pcDraft->getDocument()->recomputeFeature(pcDraft); - // hide the draft if there was a computation error - hideOnError(); +void TaskDraftParameters::onReversedChanged(const bool on) +{ + if (auto draft = getObject()) { + setButtons(none); + setupTransaction(); + draft->Reversed.setValue(on); + draft->recomputeFeature(); + // hide the draft if there was a computation error + hideOnError(); + } } bool TaskDraftParameters::getReversed() const diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp index 02bb857985..dc2bd94bbc 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.cpp @@ -60,11 +60,11 @@ TaskDressUpParameters::TaskDressUpParameters(ViewProviderDressUp *DressUpView, b true, parent) , proxy(nullptr) - , DressUpView(DressUpView) , deleteAction(nullptr) , addAllEdgesAction(nullptr) , allowFaces(selectFaces) , allowEdges(selectEdges) + , DressUpView(DressUpView) { // remember initial transaction ID App::GetApplication().getActiveTransaction(&transactionID); @@ -93,7 +93,7 @@ const QString TaskDressUpParameters::btnSelectStr() void TaskDressUpParameters::setupTransaction() { - if (!DressUpView) + if (DressUpView.expired()) return; int tid = 0; @@ -143,7 +143,7 @@ void TaskDressUpParameters::addAllEdges(QListWidget* widget) #ifdef FC_USE_TNP_FIX Q_UNUSED(widget) - if (!DressUpView) { + if (DressUpView.expired()) { return; } @@ -401,18 +401,31 @@ void TaskDressUpParameters::showObject() } } +ViewProviderDressUp* TaskDressUpParameters::getDressUpView() const +{ + return DressUpView.expired() ? nullptr : DressUpView.get(); +} + Part::Feature* TaskDressUpParameters::getBase() const { - PartDesign::DressUp* pcDressUp = static_cast(DressUpView->getObject()); - // Unlikely but this may throw an exception in case we are started to edit an object which base feature - // was deleted. This exception will be likely unhandled inside the dialog and pass upper, But an error - // message inside the report view is better than a SEGFAULT. - // Generally this situation should be prevented in ViewProviderDressUp::setEdit() - return pcDressUp->getBaseObject(); + if (ViewProviderDressUp* vp = getDressUpView()) { + auto dressUp = dynamic_cast(vp->getObject()); + // Unlikely but this may throw an exception in case we are started to edit an object which + // base feature was deleted. This exception will be likely unhandled inside the dialog and + // pass upper. But an error message inside the report view is better than a SEGFAULT. + // Generally this situation should be prevented in ViewProviderDressUp::setEdit() + return dressUp->getBaseObject(); + } + + return nullptr; } void TaskDressUpParameters::setSelectionMode(selectionModes mode) { + if (DressUpView.expired()) { + return; + } + selectionMode = mode; setButtons(mode); diff --git a/src/Mod/PartDesign/Gui/TaskDressUpParameters.h b/src/Mod/PartDesign/Gui/TaskDressUpParameters.h index 4036f72be2..8173309acd 100644 --- a/src/Mod/PartDesign/Gui/TaskDressUpParameters.h +++ b/src/Mod/PartDesign/Gui/TaskDressUpParameters.h @@ -24,6 +24,7 @@ #ifndef GUI_TASKVIEW_TaskDressUpParameters_H #define GUI_TASKVIEW_TaskDressUpParameters_H +#include #include #include @@ -87,12 +88,20 @@ protected: virtual void setButtons(const selectionModes mode) = 0; static void removeItemFromListWidget(QListWidget* widget, const char* itemstr); - ViewProviderDressUp* getDressUpView() const - { return DressUpView; } + ViewProviderDressUp* getDressUpView() const; + + template T* getObject() const + { + static_assert(std::is_base_of::value, "Wrong template argument"); + if (!DressUpView.expired()) { + return dynamic_cast(DressUpView->getObject()); + } + + return nullptr; + } protected: QWidget* proxy; - ViewProviderDressUp *DressUpView; QAction* deleteAction; QAction* addAllEdgesAction; @@ -102,6 +111,9 @@ protected: static const QString btnPreviewStr(); static const QString btnSelectStr(); + +private: + Gui::WeakPtrT DressUpView; }; /// simulation dialog for the TaskView diff --git a/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp b/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp index 8e81ae18d3..cfe7175f71 100644 --- a/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskFilletParameters.cpp @@ -115,13 +115,16 @@ void TaskFilletParameters::onSelectionChanged(const Gui::SelectionChanges& msg) void TaskFilletParameters::onCheckBoxUseAllEdgesToggled(bool checked) { - if (checked) - setSelectionMode(none); - PartDesign::Fillet* pcFillet = static_cast(DressUpView->getObject()); - ui->buttonRefSel->setEnabled(!checked); - ui->listWidgetReferences->setEnabled(!checked); - pcFillet->UseAllEdges.setValue(checked); - pcFillet->getDocument()->recomputeFeature(pcFillet); + if (auto fillet = getObject()) { + if (checked) { + setSelectionMode(none); + } + + ui->buttonRefSel->setEnabled(!checked); + ui->listWidgetReferences->setEnabled(!checked); + fillet->UseAllEdges.setValue(checked); + fillet->recomputeFeature(); + } } void TaskFilletParameters::setButtons(const selectionModes mode) @@ -142,13 +145,14 @@ void TaskFilletParameters::onAddAllEdges() void TaskFilletParameters::onLengthChanged(double len) { - setSelectionMode(none); - PartDesign::Fillet* pcFillet = static_cast(DressUpView->getObject()); - setupTransaction(); - pcFillet->Radius.setValue(len); - pcFillet->getDocument()->recomputeFeature(pcFillet); - // hide the fillet if there was a computation error - hideOnError(); + if (auto fillet = getObject()) { + setSelectionMode(none); + setupTransaction(); + fillet->Radius.setValue(len); + fillet->recomputeFeature(); + // hide the fillet if there was a computation error + hideOnError(); + } } double TaskFilletParameters::getLength() const diff --git a/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp b/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp index 05b974c5c3..31ccf74721 100644 --- a/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskThicknessParameters.cpp @@ -63,8 +63,8 @@ void TaskThicknessParameters::addContainerWidget() void TaskThicknessParameters::initControls() { - auto pcThickness = dynamic_cast(DressUpView->getObject()); - double a = pcThickness->Value.getValue(); + auto thickness = getObject(); + double a = thickness->Value.getValue(); ui->Value->setMinimum(0.0); ui->Value->setValue(a); @@ -72,25 +72,25 @@ void TaskThicknessParameters::initControls() QMetaObject::invokeMethod(ui->Value, "setFocus", Qt::QueuedConnection); // Bind input fields to properties - ui->Value->bind(pcThickness->Value); + ui->Value->bind(thickness->Value); - bool r = pcThickness->Reversed.getValue(); + bool r = thickness->Reversed.getValue(); ui->checkReverse->setChecked(r); - bool i = pcThickness->Intersection.getValue(); + bool i = thickness->Intersection.getValue(); ui->checkIntersection->setChecked(i); - std::vector strings = pcThickness->Base.getSubValues(); + std::vector strings = thickness->Base.getSubValues(); for (const auto& string : strings) { ui->listWidgetReferences->addItem(QString::fromStdString(string)); } setupConnections(); - int mode = static_cast(pcThickness->Mode.getValue()); + int mode = static_cast(thickness->Mode.getValue()); ui->modeComboBox->setCurrentIndex(mode); - int join = static_cast(pcThickness->Join.getValue()); + int join = static_cast(thickness->Join.getValue()); ui->joinComboBox->setCurrentIndex(join); if (strings.empty()) { @@ -156,7 +156,7 @@ PartDesign::Thickness* TaskThicknessParameters::onBeforeChange() { setButtons(none); setupTransaction(); - return dynamic_cast(DressUpView->getObject()); + return getObject(); } void TaskThicknessParameters::onAfterChange(PartDesign::Thickness* obj) @@ -168,25 +168,26 @@ void TaskThicknessParameters::onAfterChange(PartDesign::Thickness* obj) void TaskThicknessParameters::onValueChanged(double angle) { - PartDesign::Thickness* thickness = onBeforeChange(); - thickness->Value.setValue(angle); - onAfterChange(thickness); + if (PartDesign::Thickness* thickness = onBeforeChange()) { + thickness->Value.setValue(angle); + onAfterChange(thickness); + } } void TaskThicknessParameters::onJoinTypeChanged(int join) { - - PartDesign::Thickness* thickness = onBeforeChange(); - thickness->Join.setValue(join); - onAfterChange(thickness); + if (PartDesign::Thickness* thickness = onBeforeChange()) { + thickness->Join.setValue(join); + onAfterChange(thickness); + } } void TaskThicknessParameters::onModeChanged(int mode) { - - PartDesign::Thickness* thickness = onBeforeChange(); - thickness->Mode.setValue(mode); - onAfterChange(thickness); + if (PartDesign::Thickness* thickness = onBeforeChange()) { + thickness->Mode.setValue(mode); + onAfterChange(thickness); + } } double TaskThicknessParameters::getValue() const @@ -196,9 +197,10 @@ double TaskThicknessParameters::getValue() const void TaskThicknessParameters::onReversedChanged(bool on) { - PartDesign::Thickness* thickness = onBeforeChange(); - thickness->Reversed.setValue(on); - onAfterChange(thickness); + if (PartDesign::Thickness* thickness = onBeforeChange()) { + thickness->Reversed.setValue(on); + onAfterChange(thickness); + } } bool TaskThicknessParameters::getReversed() const @@ -208,9 +210,10 @@ bool TaskThicknessParameters::getReversed() const void TaskThicknessParameters::onIntersectionChanged(bool on) { - PartDesign::Thickness* thickness = onBeforeChange(); - thickness->Intersection.setValue(on); - onAfterChange(thickness); + if (PartDesign::Thickness* thickness = onBeforeChange()) { + thickness->Intersection.setValue(on); + onAfterChange(thickness); + } } bool TaskThicknessParameters::getIntersection() const