From a176849962b59a6258db931c45ad7e94adee375c Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 3 Dec 2020 11:24:39 +0000 Subject: [PATCH] Add some new helpers for managing widgets --- qrenderdoc/Code/Interface/Extensions.h | 40 +++++++++++++++++++++++++- qrenderdoc/Code/MiniQtHelper.cpp | 27 ++++++++++++++++- qrenderdoc/Code/MiniQtHelper.h | 6 +++- qrenderdoc/Windows/PythonShell.cpp | 14 +++++++-- 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/qrenderdoc/Code/Interface/Extensions.h b/qrenderdoc/Code/Interface/Extensions.h index ea844c8ca..3b27ff002 100644 --- a/qrenderdoc/Code/Interface/Extensions.h +++ b/qrenderdoc/Code/Interface/Extensions.h @@ -350,10 +350,13 @@ is a layout type widget, to allow customising how children are added. By default added in a vertical layout. :param str windowTitle: The title of any window with this widget as its root. +:param WidgetCallback closed: A callback that will be called when the widget is closed by the user. + This implicitly deletes the widget and all its children, which will no longer be valid even if a + handle to them exists. :return: The handle to the newly created widget. :rtype: ``QWidget`` )"); - virtual QWidget *CreateToplevelWidget(const rdcstr &windowTitle) = 0; + virtual QWidget *CreateToplevelWidget(const rdcstr &windowTitle, WidgetCallback closed) = 0; // widget hierarchy @@ -427,6 +430,22 @@ layout type widgets. )"); virtual QWidget *GetChild(QWidget *parent, int index) = 0; + DOCUMENT(R"(Destroy a widget. Widgets stay alive unless explicitly destroyed here, OR in one other +case when they are in a widget hiearchy under a top-level window which the user closes, which can +be detected with the callback parameter in :meth:`CreateToplevelWidget`. + +If the widget being destroyed is a top-level window, it will be closed. Otherwise if it is part of a +widget hierarchy it will be removed from its parent automatically. You can remove a widget and then +destroy it if you wish, but you must not destroy a widget then attempt to remove it from its parent, +as after the call to this function the widget is no longer valid to use. + +All children under this widget will be destroyed recursively as well, which will be made invalid +even if a handle to them exists. + +:param QWidget widget: The widget to destroy. +)"); + virtual void DestroyWidget(QWidget *widget) = 0; + // dialogs DOCUMENT(R"(Show a top-level widget as a blocking modal dialog. This is most useful to prompt the @@ -585,6 +604,25 @@ data. )"); virtual bool IsWidgetEnabled(QWidget *widget) = 0; + DOCUMENT(R"(Set whether the widget is visible or not. An invisible widget maintains its position +in the hierarchy but is not visible and cannot be interacted with in any way. + +:param QWidget widget: The widget to show or hide. +:param bool enabled: ``True`` if the widget should be made visible (shown). +)"); + virtual void SetWidgetVisible(QWidget *widget, bool visible) = 0; + + DOCUMENT(R"(Return the current visibility of a widget. See :meth:`SetWidgetVisible`. + +This query is recursive - a widget could be individually visible, but if it is under a parent which +is invisible then this widget will be returned as invisible. + +:param QWidget widget: The widget to query. +:return: ``True`` if the widget is currently visible. +:rtype: bool +)"); + virtual bool IsWidgetVisible(QWidget *widget) = 0; + // specific widgets DOCUMENT(R"(Create a groupbox widget which can optionally allow collapsing. diff --git a/qrenderdoc/Code/MiniQtHelper.cpp b/qrenderdoc/Code/MiniQtHelper.cpp index 9c836911c..7d21a5755 100644 --- a/qrenderdoc/Code/MiniQtHelper.cpp +++ b/qrenderdoc/Code/MiniQtHelper.cpp @@ -81,11 +81,15 @@ void MiniQtHelper::AddWidgetCallback(QWidget *widget, QMetaObject::Connection co }); } -QWidget *MiniQtHelper::CreateToplevelWidget(const rdcstr &windowTitle) +QWidget *MiniQtHelper::CreateToplevelWidget(const rdcstr &windowTitle, WidgetCallback closed) { QWidget *ret = new QWidget(); ret->setWindowTitle(windowTitle); ret->setLayout(new QVBoxLayout()); + if(closed) + AddWidgetCallback(ret, QObject::connect(ret, &QWidget::destroyed, [this, ret, closed]() { + closed(&m_Ctx, ret, rdcstr()); + })); return ret; } @@ -155,6 +159,11 @@ QWidget *MiniQtHelper::GetChild(QWidget *parent, int index) return item->widget(); } +void MiniQtHelper::DestroyWidget(QWidget *widget) +{ + widget->deleteLater(); +} + bool MiniQtHelper::ShowWidgetAsDialog(QWidget *widget) { QWidget *mainWindow = m_Ctx.GetMainWindow()->Widget(); @@ -395,6 +404,22 @@ bool MiniQtHelper::IsWidgetEnabled(QWidget *widget) return widget->isEnabled(); } +void MiniQtHelper::SetWidgetVisible(QWidget *widget, bool visible) +{ + if(!widget) + return; + + widget->setVisible(visible); +} + +bool MiniQtHelper::IsWidgetVisible(QWidget *widget) +{ + if(!widget) + return false; + + return widget->isVisible(); +} + QWidget *MiniQtHelper::CreateGroupBox(bool collapsible) { QWidget *ret; diff --git a/qrenderdoc/Code/MiniQtHelper.h b/qrenderdoc/Code/MiniQtHelper.h index 272090cf2..f99ce3d14 100644 --- a/qrenderdoc/Code/MiniQtHelper.h +++ b/qrenderdoc/Code/MiniQtHelper.h @@ -35,7 +35,7 @@ public: MiniQtHelper(ICaptureContext &ctx); virtual ~MiniQtHelper(); - QWidget *CreateToplevelWidget(const rdcstr &windowTitle) override; + QWidget *CreateToplevelWidget(const rdcstr &windowTitle, WidgetCallback closed) override; // widget hierarchy @@ -46,6 +46,7 @@ public: QWidget *GetParent(QWidget *widget) override; int GetNumChildren(QWidget *widget) override; QWidget *GetChild(QWidget *parent, int index) override; + void DestroyWidget(QWidget *widget) override; // dialogs @@ -75,6 +76,9 @@ public: void SetWidgetEnabled(QWidget *widget, bool enabled) override; bool IsWidgetEnabled(QWidget *widget) override; + void SetWidgetVisible(QWidget *widget, bool visible) override; + bool IsWidgetVisible(QWidget *widget) override; + // specific widgets QWidget *CreateGroupBox(bool collapsible) override; diff --git a/qrenderdoc/Windows/PythonShell.cpp b/qrenderdoc/Windows/PythonShell.cpp index f0e58b4c6..1a61caea5 100644 --- a/qrenderdoc/Windows/PythonShell.cpp +++ b/qrenderdoc/Windows/PythonShell.cpp @@ -89,9 +89,9 @@ struct MiniQtInvoker : ObjectForwarder // all functions invoke onto the UI thread since they deal with widgets! /////////////////////////////////////////////////////////////////////// - QWidget *CreateToplevelWidget(const rdcstr &windowTitle) + QWidget *CreateToplevelWidget(const rdcstr &windowTitle, WidgetCallback closed) { - return InvokeRetFunction(&IMiniQtHelper::CreateToplevelWidget, windowTitle); + return InvokeRetFunction(&IMiniQtHelper::CreateToplevelWidget, windowTitle, closed); } // widget hierarchy @@ -124,7 +124,7 @@ struct MiniQtInvoker : ObjectForwarder { return InvokeRetFunction(&IMiniQtHelper::GetChild, parent, index); } - + void DestroyWidget(QWidget *widget) { InvokeVoidFunction(&IMiniQtHelper::DestroyWidget, widget); } // dialogs bool ShowWidgetAsDialog(QWidget *widget) @@ -193,6 +193,14 @@ struct MiniQtInvoker : ObjectForwarder { return InvokeRetFunction(&IMiniQtHelper::IsWidgetEnabled, widget); } + void SetWidgetVisible(QWidget *widget, bool visible) + { + InvokeVoidFunction(&IMiniQtHelper::SetWidgetVisible, widget, visible); + } + bool IsWidgetVisible(QWidget *widget) + { + return InvokeRetFunction(&IMiniQtHelper::IsWidgetVisible, widget); + } // specific widgets