Core: Enable TaskDialogs to associate view (#17373)

* Core: Add possibility for task dialogs to associate a view and be able to close when associated view is closed.

* TaskImage: Use task dialog view association.

* Sketcher: Use task dialog view association. Preventing crash (https://github.com/FreeCAD/FreeCAD/issues/16702)

* EditableDatumLabel: Use QPointer to prevent crash
This commit is contained in:
PaddleStroke
2024-10-29 15:58:11 +01:00
committed by GitHub
parent 04fb809665
commit 4f323f9580
11 changed files with 109 additions and 5 deletions

View File

@@ -1411,6 +1411,11 @@ void Application::viewActivated(MDIView* pcView)
}
}
/// Gets called if a view gets closed
void Application::viewClosed(MDIView* pcView)
{
signalCloseView(pcView);
}
void Application::updateActive()
{

View File

@@ -97,6 +97,8 @@ public:
void detachView(Gui::BaseView* pcView);
/// get called if a view gets activated, this manage the whole activation scheme
void viewActivated(Gui::MDIView* pcView);
/// get called if a view gets closed
void viewClosed(Gui::MDIView* pcView);
/// call update to all documents and all views (costly!)
void onUpdate();
/// call update to all views of the active document
@@ -137,6 +139,8 @@ public:
boost::signals2::signal<void (const Gui::Document&)> signalShowHidden;
/// signal on activating view
boost::signals2::signal<void (const Gui::MDIView*)> signalActivateView;
/// signal on closing view
boost::signals2::signal<void (const Gui::MDIView*)> signalCloseView;
/// signal on entering in edit mode
boost::signals2::signal<void (const Gui::ViewProviderDocumentObject&)> signalInEdit;
/// signal on leaving edit mode

View File

@@ -25,6 +25,7 @@
#define GUI_EDITABLEDATUMLABEL_H
#include <QObject>
#include <QPointer>
#include <Gui/QuantitySpinBox.h>
#include "SoDatumLabel.h"
@@ -98,7 +99,7 @@ private:
private:
SoSeparator* root;
SoTransform* transform;
View3DInventorViewer* viewer;
QPointer<View3DInventorViewer> viewer;
QuantitySpinBox* spinBox;
SoNodeSensor* cameraSensor;
SbVec3f midpos;

View File

@@ -209,6 +209,8 @@ void MDIView::closeEvent(QCloseEvent *e)
{
if (canClose()) {
e->accept();
Application::Instance->viewClosed(this);
if (!bIsPassive) {
// must be detached so that the last view can get asked
Document* doc = this->getGuiDocument();

View File

@@ -27,6 +27,13 @@
# include <QMessageBox>
#endif
#include <App/Document.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/View3DInventor.h>
#include <Gui/ViewProviderDocumentObject.h>
#include "TaskDialog.h"
#include "TaskView.h"
@@ -42,6 +49,8 @@ TaskDialog::TaskDialog()
: QObject(nullptr), pos(North)
, escapeButton(true)
, autoCloseTransaction(false)
, autoCloseDeletedDocument(false)
, autoCloseClosedView(false)
{
}
@@ -96,6 +105,25 @@ bool TaskDialog::canClose() const
return (ret == QMessageBox::Yes);
}
void TaskDialog::associateToObject3dView(App::DocumentObject* obj)
{
if (!obj) {
return;
}
Gui::Document* guiDoc = Gui::Application::Instance->getDocument(obj->getDocument());
auto* vp = Gui::Application::Instance->getViewProvider(obj);
auto* vpdo = static_cast<Gui::ViewProviderDocumentObject*>(vp);
auto* view = guiDoc->openEditingView3D(vpdo);
if (!view) {
return;
}
setAssociatedView(view);
setAutoCloseOnClosedView(true);
}
//==== calls from the TaskView ===============================================================
void TaskDialog::open()
@@ -118,6 +146,11 @@ void TaskDialog::autoClosedOnDeletedDocument()
}
void TaskDialog::autoClosedOnClosedView()
{
}
void TaskDialog::clicked(int)
{

View File

@@ -33,10 +33,11 @@
namespace App {
class DocumentObject;
}
namespace Gui {
class MDIView;
namespace TaskView {
class TaskContent;
@@ -104,6 +105,22 @@ public:
{ return documentName; }
void setDocumentName(const std::string& doc)
{ documentName = doc; }
/// Defines whether a task dialog must be closed if the associated view
/// is deleted.
void setAutoCloseOnClosedView(bool on) {
autoCloseClosedView = on;
}
bool isAutoCloseOnClosedView() const {
return autoCloseClosedView;
}
void associateToObject3dView(App::DocumentObject* obj);
const Gui::MDIView* getAssociatedView() const
{ return associatedView; }
void setAssociatedView(const Gui::MDIView* view)
{ associatedView = view; }
/*!
Indicates whether this task dialog allows other commands to modify
the document while it is open.
@@ -136,6 +153,9 @@ public:
/// is called by the framework when the dialog is automatically closed due to
/// deleting the document
virtual void autoClosedOnDeletedDocument();
/// is called by the framework when the dialog is automatically closed due to
/// closing of associated view
virtual void autoClosedOnClosedView();
/// is called by the framework if a button is clicked which has no accept or reject role
virtual void clicked(int);
/// is called by the framework if the dialog is accepted (Ok)
@@ -160,9 +180,11 @@ protected:
private:
std::string documentName;
const Gui::MDIView* associatedView;
bool escapeButton;
bool autoCloseTransaction;
bool autoCloseDeletedDocument;
bool autoCloseClosedView;
friend class TaskDialogAttorney;
};

View File

@@ -679,9 +679,7 @@ TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj)
{
addTaskBox(Gui::BitmapFactory().pixmap("image-plane"), widget);
auto doc = obj->getDocument();
setDocumentName(doc->getName());
setAutoCloseOnDeletedDocument(true);
associateToObject3dView(obj);
}
void TaskImageDialog::open()

View File

@@ -295,6 +295,9 @@ TaskView::TaskView(QWidget *parent)
connectApplicationDeleteDocument =
App::GetApplication().signalDeleteDocument.connect
(std::bind(&Gui::TaskView::TaskView::slotDeletedDocument, this, sp::_1));
connectApplicationClosedView =
Gui::Application::Instance->signalCloseView.connect
(std::bind(&Gui::TaskView::TaskView::slotViewClosed, this, sp::_1));
connectApplicationUndoDocument =
App::GetApplication().signalUndoDocument.connect
(std::bind(&Gui::TaskView::TaskView::slotUndoDocument, this, sp::_1));
@@ -310,6 +313,7 @@ TaskView::~TaskView()
{
connectApplicationActiveDocument.disconnect();
connectApplicationDeleteDocument.disconnect();
connectApplicationClosedView.disconnect();
connectApplicationUndoDocument.disconnect();
connectApplicationRedoDocument.disconnect();
Gui::Selection().Detach(this);
@@ -479,6 +483,29 @@ void TaskView::slotDeletedDocument(const App::Document& doc)
}
}
void TaskView::slotViewClosed(const Gui::MDIView* view)
{
// It can happen that only a view is closed an not the document
if (ActiveDialog) {
if (ActiveDialog->isAutoCloseOnClosedView()) {
const Gui::MDIView* associatedView = ActiveDialog->getAssociatedView();
if (!associatedView) {
Base::Console().Warning(std::string("TaskView::slotViewClosed"),
"No view associated\n");
}
if (associatedView == view) {
ActiveDialog->autoClosedOnClosedView();
removeDialog();
}
}
}
if (!ActiveDialog) {
updateWatcher();
}
}
void TaskView::transactionChangeOnDocument(const App::Document& doc)
{
if (ActiveDialog) {

View File

@@ -37,6 +37,7 @@ class Property;
}
namespace Gui {
class MDIView;
class ControlSingleton;
namespace DockWnd{
class ComboView;
@@ -183,6 +184,7 @@ private:
void tryRestoreWidth();
void slotActiveDocument(const App::Document&);
void slotDeletedDocument(const App::Document&);
void slotViewClosed(const Gui::MDIView*);
void slotUndoDocument(const App::Document&);
void slotRedoDocument(const App::Document&);
void transactionChangeOnDocument(const App::Document&);
@@ -210,6 +212,7 @@ protected:
Connection connectApplicationActiveDocument;
Connection connectApplicationDeleteDocument;
Connection connectApplicationClosedView;
Connection connectApplicationUndoDocument;
Connection connectApplicationRedoDocument;
};

View File

@@ -79,6 +79,8 @@ TaskDlgEditSketch::TaskDlgEditSketch(ViewProviderSketch* sketchView)
std::bind(&SketcherGui::TaskDlgEditSketch::slotToolChanged, this, sp::_1));
ToolSettings->setHidden(true);
associateToObject3dView(sketchView->getObject());
}
TaskDlgEditSketch::~TaskDlgEditSketch()
@@ -145,4 +147,10 @@ bool TaskDlgEditSketch::reject()
}
void TaskDlgEditSketch::autoClosedOnClosedView()
{
// Make sure the edit mode is exited when the view is closed.
reject();
}
#include "moc_TaskDlgEditSketch.cpp"

View File

@@ -67,6 +67,7 @@ public:
{
return false;
}
void autoClosedOnClosedView() override;
/// returns for Close and Help button
QDialogButtonBox::StandardButtons getStandardButtons() const override