From e86f7caea866db5b78cfa78e5d3a10b735b205f9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 31 Oct 2018 14:29:42 +0100 Subject: [PATCH] Improve TaskAttacher dialog: + correct handling of active document + properly handle case if the view provider or document is deleted while the dialog is still open --- src/Mod/Part/Gui/TaskAttacher.cpp | 127 +++++++++++++++++++++++------- src/Mod/Part/Gui/TaskAttacher.h | 6 +- 2 files changed, 102 insertions(+), 31 deletions(-) diff --git a/src/Mod/Part/Gui/TaskAttacher.cpp b/src/Mod/Part/Gui/TaskAttacher.cpp index 627d3cd74d..1bab787d0d 100644 --- a/src/Mod/Part/Gui/TaskAttacher.cpp +++ b/src/Mod/Part/Gui/TaskAttacher.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -111,9 +112,9 @@ TaskAttacher::TaskAttacher(Gui::ViewProviderDocumentObject *ViewProvider,QWidget ViewProvider(ViewProvider) { //check if we are attachable - if(!ViewProvider->getObject()->hasExtension(Part::AttachExtension::getExtensionClassTypeId())) - throw Base::Exception("Object has no PArt::AttachExtension"); - + if (!ViewProvider->getObject()->hasExtension(Part::AttachExtension::getExtensionClassTypeId())) + throw Base::RuntimeError("Object has no Part::AttachExtension"); + // we need a separate container widget to add all controls to proxy = new QWidget(this); ui = new Ui_TaskAttacher(); @@ -207,9 +208,11 @@ TaskAttacher::TaskAttacher(Gui::ViewProviderDocumentObject *ViewProvider,QWidget updatePreview(); // connect object deletion with slot - auto bnd = boost::bind(&TaskAttacher::objectDeleted, this, _1); + auto bnd1 = boost::bind(&TaskAttacher::objectDeleted, this, _1); + auto bnd2 = boost::bind(&TaskAttacher::documentDeleted, this, _1); Gui::Document* document = Gui::Application::Instance->getDocument(ViewProvider->getObject()->getDocument()); - connectDelObject = document->signalDeletedObject.connect(bnd); + connectDelObject = document->signalDeletedObject.connect(bnd1); + connectDelDocument = document->signalDeleteDocument.connect(bnd2); } TaskAttacher::~TaskAttacher() @@ -221,13 +224,22 @@ TaskAttacher::~TaskAttacher() } connectDelObject.disconnect(); + connectDelDocument.disconnect(); delete ui; } void TaskAttacher::objectDeleted(const Gui::ViewProviderDocumentObject& view) { - if (ViewProvider == &view) + if (ViewProvider == &view) { ViewProvider = nullptr; + this->setDisabled(true); + } +} + +void TaskAttacher::documentDeleted(const Gui::Document&) +{ + ViewProvider = nullptr; + this->setDisabled(true); } const QString makeHintText(std::set hint) @@ -244,6 +256,8 @@ const QString makeHintText(std::set hint) void TaskAttacher::updateReferencesUI() { + if (!ViewProvider) + return; Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); @@ -274,6 +288,9 @@ void TaskAttacher::updateReferencesUI() bool TaskAttacher::updatePreview() { + if (!ViewProvider) + return false; + Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); QString errMessage; bool attached = false; @@ -319,6 +336,9 @@ QLineEdit* TaskAttacher::getLine(unsigned idx) void TaskAttacher::onSelectionChanged(const Gui::SelectionChanges& msg) { + if (!ViewProvider) + return; + if (msg.Type == Gui::SelectionChanges::AddSelection) { if (iActiveRef < 0) return; @@ -405,6 +425,9 @@ void TaskAttacher::onSelectionChanged(const Gui::SelectionChanges& msg) void TaskAttacher::onAttachmentOffsetChanged(double /*val*/, int idx) { + if (!ViewProvider) + return; + Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); Base::Placement pl = pcAttach->AttachmentOffset.getValue(); @@ -447,22 +470,27 @@ void TaskAttacher::onAttachmentOffsetXChanged(double val) { onAttachmentOffsetChanged(val, 0); } + void TaskAttacher::onAttachmentOffsetYChanged(double val) { onAttachmentOffsetChanged(val, 1); } + void TaskAttacher::onAttachmentOffsetZChanged(double val) { onAttachmentOffsetChanged(val, 2); } + void TaskAttacher::onAttachmentOffsetYawChanged(double val) { onAttachmentOffsetChanged(val, 3); } + void TaskAttacher::onAttachmentOffsetPitchChanged(double val) { onAttachmentOffsetChanged(val, 4); } + void TaskAttacher::onAttachmentOffsetRollChanged(double val) { onAttachmentOffsetChanged(val, 5); @@ -470,6 +498,9 @@ void TaskAttacher::onAttachmentOffsetRollChanged(double val) void TaskAttacher::onCheckFlip(bool on) { + if (!ViewProvider) + return; + Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); pcAttach->MapReversed.setValue(on); ViewProvider->getObject()->getDocument()->recomputeFeature(ViewProvider->getObject()); @@ -493,18 +524,24 @@ void TaskAttacher::onButtonRef(const bool checked, unsigned idx) void TaskAttacher::onButtonRef1(const bool checked) { onButtonRef(checked, 0); } + void TaskAttacher::onButtonRef2(const bool checked) { onButtonRef(checked, 1); } + void TaskAttacher::onButtonRef3(const bool checked) { onButtonRef(checked, 2); } + void TaskAttacher::onButtonRef4(const bool checked) { onButtonRef(checked, 3); } void TaskAttacher::onModeSelect() { + if (!ViewProvider) + return; + Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); pcAttach->MapMode.setValue(getActiveMapMode()); updatePreview(); @@ -512,6 +549,9 @@ void TaskAttacher::onModeSelect() void TaskAttacher::onRefName(const QString& text, unsigned idx) { + if (!ViewProvider) + return; + QLineEdit* line = getLine(idx); if (line == NULL) return; @@ -621,13 +661,16 @@ void TaskAttacher::onRefName(const QString& text, unsigned idx) void TaskAttacher::updateRefButton(int idx) { + if (!ViewProvider) + return; + QAbstractButton* b; switch(idx){ case 0: b = ui->buttonRef1; break; case 1: b = ui->buttonRef2; break; case 2: b = ui->buttonRef3; break; case 3: b = ui->buttonRef4; break; - default: throw Base::Exception("button index out of range"); + default: throw Base::IndexError("button index out of range"); } Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); @@ -654,6 +697,9 @@ void TaskAttacher::updateRefButton(int idx) void TaskAttacher::updateAttachmentOffsetUI() { + if (!ViewProvider) + return; + Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); Base::Placement pl = pcAttach->AttachmentOffset.getValue(); Base::Vector3d pos = pl.getPosition(); @@ -707,6 +753,9 @@ void TaskAttacher::updateAttachmentOffsetUI() void TaskAttacher::updateListOfModes() { + if (!ViewProvider) + return; + //first up, remember currently selected mode. eMapMode curMode = mmDeactivated; auto sel = ui->listOfModes->selectedItems(); @@ -823,20 +872,22 @@ void TaskAttacher::onRefName1(const QString& text) { onRefName(text, 0); } + void TaskAttacher::onRefName2(const QString& text) { onRefName(text, 1); } + void TaskAttacher::onRefName3(const QString& text) { onRefName(text, 2); } + void TaskAttacher::onRefName4(const QString &text) { onRefName(text, 3); } - bool TaskAttacher::getFlip() const { return ui->checkBoxFlip->isChecked(); @@ -880,8 +931,8 @@ void TaskAttacher::changeEvent(QEvent *e) void TaskAttacher::visibilityAutomation(bool opening_not_closing) { - if (opening_not_closing){ - //crash guards + if (opening_not_closing) { + //crash guards if (!ViewProvider) return; if (!ViewProvider->getObject()) @@ -935,7 +986,8 @@ TaskDlgAttacher::TaskDlgAttacher(Gui::ViewProviderDocumentObject *ViewProvider, : TaskDialog(),ViewProvider(ViewProvider), parameter(nullptr) { assert(ViewProvider); - + setDocumentName(ViewProvider->getDocument()->getDocument()->getName()); + if(createBox) { parameter = new TaskAttacher(ViewProvider); Content.push_back(parameter); @@ -952,43 +1004,57 @@ TaskDlgAttacher::~TaskDlgAttacher() void TaskDlgAttacher::open() { - + } void TaskDlgAttacher::clicked(int) { - + } bool TaskDlgAttacher::accept() { - try { + Gui::DocumentT doc(getDocumentName()); + Gui::Document* document = doc.getDocument(); + if (!document || !ViewProvider) + return true; + Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType(); std::string name = ViewProvider->getObject()->getNameInDocument(); + std::string appDocument = doc.getAppDocumentPython(); + std::string guiDocument = doc.getGuiDocumentPython(); //DeepSOIC: changed this to heavily rely on dialog constantly updating feature properties if (pcAttach->AttachmentOffset.isTouched()){ Base::Placement plm = pcAttach->AttachmentOffset.getValue(); double yaw, pitch, roll; plm.getRotation().getYawPitchRoll(yaw,pitch,roll); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.AttachmentOffset = App.Placement(App.Vector(%.10f, %.10f, %.10f), App.Rotation(%.10f, %.10f, %.10f))", - name.c_str(), + Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.AttachmentOffset = App.Placement(App.Vector(%.10f, %.10f, %.10f), App.Rotation(%.10f, %.10f, %.10f))", + appDocument.c_str(), name.c_str(), plm.getPosition().x, plm.getPosition().y, plm.getPosition().z, yaw, pitch, roll); } - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.MapReversed = %s", name.c_str(), pcAttach->MapReversed.getValue() ? "True" : "False"); + Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.MapReversed = %s", + appDocument.c_str(), name.c_str(), + pcAttach->MapReversed.getValue() ? "True" : "False"); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Support = %s", name.c_str(), pcAttach->Support.getPyReprString().c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.Support = %s", + appDocument.c_str(), name.c_str(), + pcAttach->Support.getPyReprString().c_str()); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.MapMode = '%s'", name.c_str(), AttachEngine::getModeName(eMapMode(pcAttach->MapMode.getValue())).c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"%s.%s.MapMode = '%s'", + appDocument.c_str(), name.c_str(), + AttachEngine::getModeName(eMapMode(pcAttach->MapMode.getValue())).c_str()); + + Gui::Command::doCommand(Gui::Command::Doc,"%s.recompute()", appDocument.c_str()); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); if (!ViewProvider->getObject()->isValid()) - throw Base::Exception(ViewProvider->getObject()->getStatusString()); - Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); - Gui::Command::commitCommand(); + throw Base::RuntimeError(ViewProvider->getObject()->getStatusString()); + + Gui::Command::doCommand(Gui::Command::Gui, "%s.resetEdit()", guiDocument.c_str()); + document->commitCommand(); } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Datum dialog: Input error"), QString::fromLatin1(e.what())); @@ -1000,13 +1066,16 @@ bool TaskDlgAttacher::accept() bool TaskDlgAttacher::reject() { - // roll back the done things - Gui::Command::abortCommand(); - Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + Gui::DocumentT doc(getDocumentName()); + Gui::Document* document = doc.getDocument(); + if (document) { + // roll back the done things + document->abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui,"%s.resetEdit()", doc.getGuiDocumentPython().c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"%s.recompute()", doc.getAppDocumentPython().c_str()); + } + return true; } - - #include "moc_TaskAttacher.cpp" diff --git a/src/Mod/Part/Gui/TaskAttacher.h b/src/Mod/Part/Gui/TaskAttacher.h index 703eb1a45d..b7f7b2d2f1 100644 --- a/src/Mod/Part/Gui/TaskAttacher.h +++ b/src/Mod/Part/Gui/TaskAttacher.h @@ -24,12 +24,12 @@ #ifndef GUI_TASKVIEW_TaskAttacher_H #define GUI_TASKVIEW_TaskAttacher_H -#include #include +#include +#include #include #include -#include "Gui/ViewProviderDocumentObject.h" class Ui_TaskAttacher; class QLineEdit; @@ -90,6 +90,7 @@ protected: void changeEvent(QEvent *e) override; private: void objectDeleted(const Gui::ViewProviderDocumentObject&); + void documentDeleted(const Gui::Document&); void onSelectionChanged(const Gui::SelectionChanges& msg) override; void updateReferencesUI(); @@ -133,6 +134,7 @@ private: typedef boost::signals2::connection Connection; Connection connectDelObject; + Connection connectDelDocument; }; /// simulation dialog for the TaskView