From eb3e4ce56c2b69d3a6a066ab80929ba9bd5c6c03 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Sun, 15 Mar 2020 11:08:28 -0400 Subject: [PATCH] [TD]fix crash when Section deleted during creation - if the Section is deleted while the section dialog is still in progress, further processing in the dialog would cause a crash. - should have "update intent" locks to prevent this --- src/Mod/TechDraw/Gui/TaskSectionView.cpp | 256 +++++++++++++---------- src/Mod/TechDraw/Gui/TaskSectionView.h | 19 +- 2 files changed, 155 insertions(+), 120 deletions(-) diff --git a/src/Mod/TechDraw/Gui/TaskSectionView.cpp b/src/Mod/TechDraw/Gui/TaskSectionView.cpp index c5c8c5567e..9ac053debc 100644 --- a/src/Mod/TechDraw/Gui/TaskSectionView.cpp +++ b/src/Mod/TechDraw/Gui/TaskSectionView.cpp @@ -78,7 +78,8 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewPart* base) : m_section(nullptr), m_dirName(""), m_createMode(true), - m_saved(false) + m_saved(false), + m_abort(false) { // Base::Console().Message("TSV::TSV() - create mode\n"); if (m_base == nullptr) { @@ -87,8 +88,12 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewPart* base) : Base::Console().Error((msg + "\n").c_str()); return; } + m_sectionName = std::string(); + m_doc = m_base->getDocument(); + m_saveBaseName = m_base->getNameInDocument(); m_savePageName = m_base->findParentPage()->getNameInDocument(); + ui->setupUi(this); @@ -113,9 +118,9 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewSection* section) : m_base(nullptr), m_section(section), m_createMode(false), - m_saved(false) + m_saved(false), + m_abort(false) { -// Base::Console().Message("TS::TS() - edit mode\n"); if (m_section == nullptr) { //should be caught in CMD caller @@ -124,6 +129,7 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewSection* section) : return; } + m_sectionName = m_section->getNameInDocument(); App::DocumentObject* newObj = m_section->BaseView.getValue(); m_base = dynamic_cast(newObj); if ( (newObj == nullptr) || @@ -229,7 +235,6 @@ void TaskSectionView::blockButtons(bool b) Q_UNUSED(b); } -// cardinal: 0 - left, 1 - right, 2 - up, 3 - down void TaskSectionView::onUpClicked(bool b) { // Base::Console().Message("TSV::onUpClicked()\n"); @@ -274,29 +279,6 @@ void TaskSectionView::onApplyClicked(bool b) apply(); } -bool TaskSectionView::apply(void) -{ -// Base::Console().Message("TSV::apply() - m_dirName: %s\n", m_dirName.c_str()); - if (m_dirName.empty()) { - std::string msg = Base::Tools::toStdString(tr("TaskSectionView::apply - No section direction picked yet")); - Base::Console().Error((msg + "\n").c_str()); - return false; - } - if (m_section == nullptr) { - return false; - } - App::Document* doc = m_section->getDocument(); - App::DocumentObject* baseObj = doc->getObject(m_saveBaseName.c_str()); - TechDraw::DrawViewPart* dvp = dynamic_cast(baseObj); - if (dvp == nullptr) { - return false; - } - - checkAll(false); - applyQuick(m_dirName); - return true; -} - void TaskSectionView::checkAll(bool b) { ui->pbUp->setChecked(b); @@ -306,20 +288,42 @@ void TaskSectionView::checkAll(bool b) } //****************************************************************************** +bool TaskSectionView::apply(void) +{ +// Base::Console().Message("TSV::apply() - m_dirName: %s\n", m_dirName.c_str()); + if (m_dirName.empty()) { + std::string msg = + Base::Tools::toStdString(tr("TSV::apply - Nothing to apply. No section direction picked yet")); + Base::Console().Error((msg + "\n").c_str()); + return false; + } + if (m_section == nullptr) { //didn't create the feature yet + return false; + } + + checkAll(false); + applyQuick(m_dirName); + return true; +} + void TaskSectionView::applyQuick(std::string dir) { // Base::Console().Message("TSV::applyQuick(%s)\n", dir.c_str()); Gui::Command::openCommand("Apply Quick"); m_dirName = dir; if (m_section == nullptr) { - m_section = createSectionView(); + createSectionView(); } - if (m_section != nullptr) { + if (isSectionValid()) { updateSectionView(); - m_section->recomputeFeature(); + m_section->recomputeFeature(); + } else { + failNoObject(m_sectionName); } - if (m_base != nullptr) { + + if (isBaseValid()) { m_base->requestPaint(); + return; } } @@ -330,18 +334,19 @@ void TaskSectionView::applyAligned(void) m_dirName = "Aligned"; //fiddle with directions here -// m_section->recomputeFeature(); //???? m_section->requestPaint(); m_base->requestPaint(); } -TechDraw::DrawViewSection* TaskSectionView::createSectionView(void) +//********************************************************************* + +//pointer to created view is not returned, but stored in m_section +void TaskSectionView::createSectionView(void) { // Base::Console().Message("TSV::createSectionView()\n"); - - if (m_base == nullptr) { - Base::Console().Error("TSV::createSectionView - base object not found!\n"); - return nullptr; + if (!isBaseValid()) { + failNoObject(m_baseName); + return; } std::string sectionName; @@ -349,134 +354,160 @@ TechDraw::DrawViewSection* TaskSectionView::createSectionView(void) double baseScale = m_base->getScale(); Gui::Command::openCommand("Create SectionView"); - TechDraw::DrawViewSection* newSection = nullptr; if (m_section == nullptr) { - sectionName = m_base->getDocument()->getUniqueObjectName("SectionView"); + m_sectionName = m_base->getDocument()->getUniqueObjectName("SectionView"); std::string sectionType = "TechDraw::DrawViewSection"; - TechDraw::DrawPage* page = m_base->findParentPage(); - std::string pageName = page->getNameInDocument(); - Command::doCommand(Command::Doc,"App.activeDocument().addObject('%s','%s')", - sectionType.c_str(),sectionName.c_str()); + sectionType.c_str(),m_sectionName.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)", - pageName.c_str(), sectionName.c_str()); + m_savePageName.c_str(), m_sectionName.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s", - sectionName.c_str(),baseName.c_str()); + m_sectionName.c_str(),baseName.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.Source = App.activeDocument().%s.Source", - sectionName.c_str(),baseName.c_str()); + m_sectionName.c_str(),baseName.c_str()); + Command::doCommand(Command::Doc, + "App.activeDocument().%s.SectionOrigin = FreeCAD.Vector(%.3f,%.3f,%.3f)", + m_sectionName.c_str(), + ui->sbOrgX->value().getValue(), + ui->sbOrgY->value().getValue(), + ui->sbOrgZ->value().getValue()); Command::doCommand(Command::Doc,"App.activeDocument().%s.Scale = %0.6f", - sectionName.c_str(), baseScale); + m_sectionName.c_str(), baseScale); - App::DocumentObject* newObj = m_base->getDocument()->getObject(sectionName.c_str()); - newSection = dynamic_cast(newObj); + App::DocumentObject* newObj = m_base->getDocument()->getObject(m_sectionName.c_str()); + m_section = dynamic_cast(newObj); if ( (newObj == nullptr) || - (newSection == nullptr) ) { + (m_section == nullptr) ) { throw Base::RuntimeError("TaskSectionView - new section object not found"); } } - return newSection; + Gui::Command::updateActive(); + Gui::Command::commitCommand(); + + return; } void TaskSectionView::updateSectionView(void) { -// Base::Console().Message("TSV::updateSectionView()\n"); +// Base::Console().Message("TSV::updateSectionView() - m_sectionName: %s\n", m_sectionName.c_str()); + if (!isSectionValid()) { + failNoObject(m_sectionName); + return; + } + if (m_section != nullptr) { - std::string sectionName = m_section->getNameInDocument(); Command::doCommand(Command::Doc,"App.activeDocument().%s.SectionDirection = '%s'", - sectionName.c_str(),m_dirName.c_str()); + m_sectionName.c_str(),m_dirName.c_str()); Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionOrigin = FreeCAD.Vector(%.3f,%.3f,%.3f)", - sectionName.c_str(), + m_sectionName.c_str(), ui->sbOrgX->value().getValue(), ui->sbOrgY->value().getValue(), ui->sbOrgZ->value().getValue()); QString qTemp = ui->leSymbol->text(); std::string temp = Base::Tools::toStdString(qTemp); Command::doCommand(Command::Doc,"App.activeDocument().%s.SectionSymbol = '%s'", - sectionName.c_str(), + m_sectionName.c_str(), temp.c_str()); std::string lblText = "Section " + temp + " - " + temp; Command::doCommand(Command::Doc,"App.activeDocument().%s.Label = '%s'", - sectionName.c_str(), + m_sectionName.c_str(), lblText.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.Scale = %0.6f", - sectionName.c_str(), + m_sectionName.c_str(), ui->sbScale->value()); m_section->setCSFromBase(m_dirName.c_str()); } } +void TaskSectionView::failNoObject(std::string objectName) +{ + QString qObjectName = Base::Tools::fromStdString(objectName); + QString msg = tr("Can not continue. Object * %1 * not found.").arg(qObjectName); + QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Operation Failed"), msg); + Gui::Control().closeDialog(); + m_abort = true; +} + +bool TaskSectionView::isBaseValid(void) +{ + bool result = true; + if (m_base == nullptr) { + result = false; + } else { + App::DocumentObject* baseObj = m_doc->getObject(m_saveBaseName.c_str()); + if (baseObj == nullptr) { + result = false; + } + } + return result; +} + +bool TaskSectionView::isSectionValid(void) +{ + bool result = true; + if (m_section == nullptr) { + result = false; + } else { + App::DocumentObject* sectionObj = m_doc->getObject(m_sectionName.c_str()); + if (sectionObj == nullptr) { + result = false; + } + } + return result; +} //****************************************************************************** bool TaskSectionView::accept() { // Base::Console().Message("TSV::accept()\n"); - if (m_createMode) { - if (m_section == nullptr) { - apply(); - } else { - updateSectionView(); - } - Gui::Command::updateActive(); - Gui::Command::commitCommand(); - } else { - Gui::Command::openCommand("Edit SectionView"); - try { - updateSectionView(); - } - catch (...) { - Base::Console().Error("TSV::accept - failed to update section\n"); - } - - Gui::Command::updateActive(); - Gui::Command::commitCommand(); + if (m_abort) { + return true; } + apply(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()"); - if (m_section != nullptr) { - m_section->requestPaint(); - App::Document* doc = m_section->getDocument(); - App::DocumentObject* baseObj = doc->getObject(m_saveBaseName.c_str()); - TechDraw::DrawViewPart* dvp = dynamic_cast(baseObj); - if (dvp != nullptr) { - dvp->requestPaint(); - } - } return true; } bool TaskSectionView::reject() { // Base::Console().Message("TSV::reject()\n"); - if (m_section != nullptr) { - if (m_createMode) { - std::string SectionName = m_section->getNameInDocument(); - Gui::Command::doCommand(Gui::Command::Gui, - "App.activeDocument().%s.removeView(App.activeDocument().%s)", - m_savePageName.c_str(),SectionName.c_str()); - Gui::Command::doCommand(Gui::Command::Gui, - "App.activeDocument().removeObject('%s')", - SectionName.c_str()); - } else { - restoreSectionState(); - //check undo stack? - if (m_section != nullptr) { - m_section->requestPaint(); - App::Document* doc = m_section->getDocument(); - App::DocumentObject* baseObj = doc->getObject(m_saveBaseName.c_str()); - TechDraw::DrawViewPart* dvp = dynamic_cast(baseObj); - if (dvp != nullptr) { - dvp->requestPaint(); - } - } - } + if (m_section == nullptr) { //no section created, nothing to undo + Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()"); + return false; + } + + if (!isSectionValid()) { //section !exist. nothing to undo + if (isBaseValid()) { + m_base->requestPaint(); + } + Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()"); + return false; + } + + if (m_createMode) { + std::string SectionName = m_section->getNameInDocument(); + Gui::Command::doCommand(Gui::Command::Gui, + "App.activeDocument().%s.removeView(App.activeDocument().%s)", + m_savePageName.c_str(),SectionName.c_str()); + Gui::Command::doCommand(Gui::Command::Gui, + "App.activeDocument().removeObject('%s')", + SectionName.c_str()); + } else { + restoreSectionState(); + m_section->recomputeFeature(); + m_section->requestPaint(); + } + + if (isBaseValid()) { + m_base->requestPaint(); } - Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().recompute()"); Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()"); return false; @@ -529,13 +560,6 @@ bool TaskDlgSectionView::accept() return true; } -//bool TaskDlgSectionView::apply() -//{ -// Base::Console().Message("TDSV::apply()\n"); -// widget->apply(); -// return true; -//} - bool TaskDlgSectionView::reject() { widget->reject(); diff --git a/src/Mod/TechDraw/Gui/TaskSectionView.h b/src/Mod/TechDraw/Gui/TaskSectionView.h index b66fa0a66c..acd2f74d30 100644 --- a/src/Mod/TechDraw/Gui/TaskSectionView.h +++ b/src/Mod/TechDraw/Gui/TaskSectionView.h @@ -68,7 +68,7 @@ protected: void applyQuick(std::string dir); void applyAligned(void); - TechDraw::DrawViewSection* createSectionView(void); + void createSectionView(void); void updateSectionView(void); void setUiPrimary(); @@ -76,6 +76,10 @@ protected: void checkAll(bool b); + void failNoObject(std::string objName); + bool isBaseValid(void); + bool isSectionValid(void); + private: Ui_TaskSectionView * ui; TechDraw::DrawViewPart* m_base; @@ -93,6 +97,9 @@ private: double m_saveScale; std::string m_dirName; + std::string m_sectionName; + std::string m_baseName; + App::Document* m_doc; bool m_createMode; bool m_saved; @@ -100,6 +107,8 @@ private: std::string m_saveBaseName; std::string m_savePageName; + bool m_abort; + }; class TaskDlgSectionView : public Gui::TaskView::TaskDialog @@ -123,15 +132,17 @@ public: /// is called by the framework if the user presses the help button virtual void helpRequested() { return;} - virtual bool isAllowedAlterDocument(void) const - { return false; } - virtual QDialogButtonBox::StandardButtons getStandardButtons() const { return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; } /* virtual void modifyStandardButtons(QDialogButtonBox* box);*/ void update(); + virtual bool isAllowedAlterSelection(void) const + { return false; } + virtual bool isAllowedAlterDocument(void) const + { return false; } + protected: private: