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
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include <Base/Interpreter.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/DocumentObserver.h>
|
||||
#include <App/Origin.h>
|
||||
#include <App/OriginFeature.h>
|
||||
#include <App/Part.h>
|
||||
@@ -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<eRefType> hint)
|
||||
@@ -244,6 +256,8 @@ const QString makeHintText(std::set<eRefType> hint)
|
||||
|
||||
void TaskAttacher::updateReferencesUI()
|
||||
{
|
||||
if (!ViewProvider)
|
||||
return;
|
||||
|
||||
Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType<Part::AttachExtension>();
|
||||
|
||||
@@ -274,6 +288,9 @@ void TaskAttacher::updateReferencesUI()
|
||||
|
||||
bool TaskAttacher::updatePreview()
|
||||
{
|
||||
if (!ViewProvider)
|
||||
return false;
|
||||
|
||||
Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType<Part::AttachExtension>();
|
||||
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<Part::AttachExtension>();
|
||||
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<Part::AttachExtension>();
|
||||
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<Part::AttachExtension>();
|
||||
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<Part::AttachExtension>();
|
||||
@@ -654,6 +697,9 @@ void TaskAttacher::updateRefButton(int idx)
|
||||
|
||||
void TaskAttacher::updateAttachmentOffsetUI()
|
||||
{
|
||||
if (!ViewProvider)
|
||||
return;
|
||||
|
||||
Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType<Part::AttachExtension>();
|
||||
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<Part::AttachExtension>();
|
||||
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"
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#ifndef GUI_TASKVIEW_TaskAttacher_H
|
||||
#define GUI_TASKVIEW_TaskAttacher_H
|
||||
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Mod/Part/App/Attacher.h>
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user