Add a status entry showing loaded python extensions & debugger status

This commit is contained in:
baldurk
2026-08-13 17:46:40 +01:00
parent 3c6dfd23b4
commit 02ead51303
8 changed files with 92 additions and 0 deletions
+10
View File
@@ -453,11 +453,21 @@ rdcarray<ExtensionMetadata> CaptureContext::GetInstalledExtensions()
return ret;
}
rdcarray<rdcstr> CaptureContext::GetLoadedExtensions()
{
return m_ExtensionObjects.keys();
}
bool CaptureContext::IsExtensionLoaded(rdcstr name)
{
return m_ExtensionObjects.contains(name);
}
bool CaptureContext::IsPythonDebuggerConnected()
{
return PythonContext::IsDebuggingEnabled() && PythonContext::IsDebuggerConnected();
}
rdcstr CaptureContext::LoadExtension(rdcstr name)
{
QString ret;
+2
View File
@@ -76,8 +76,10 @@ public:
// IExtensionManager
rdcarray<ExtensionMetadata> GetInstalledExtensions() override;
rdcarray<rdcstr> GetLoadedExtensions() override;
bool IsExtensionLoaded(rdcstr name) override;
rdcstr LoadExtension(rdcstr name) override;
bool IsPythonDebuggerConnected() override;
void RegisterWindowMenu(WindowMenu base, const rdcarray<rdcstr> &submenus,
ExtensionCallback callback) override;
+17
View File
@@ -1098,6 +1098,13 @@ struct IExtensionManager
)");
virtual bool IsExtensionLoaded(rdcstr name) = 0;
DOCUMENT(R"(Retrieve a list of loaded extensions.
:return: The list of installed extension names.
:rtype: List[str]
)");
virtual rdcarray<rdcstr> GetLoadedExtensions() = 0;
DOCUMENT(R"(Enable an extension by name. If the extension is already enabled, this will reload it.
:param str name: The qualified name of the extension, e.g. ``foo.bar``
@@ -1107,6 +1114,16 @@ struct IExtensionManager
)");
virtual rdcstr LoadExtension(rdcstr name) = 0;
DOCUMENT(R"(Check if a python debugger is connected.
.. note::
If python debugging is not supported or failed to load, this will return ``False``.
:return: If a python debugger is connected.
:rtype: bool
)");
virtual bool IsPythonDebuggerConnected() = 0;
//////////////////////////////////////////////////////////////////////////
// UI hook/callback registration
@@ -2113,6 +2113,22 @@ PyObject *PythonContext::outstream_trace(PyObject *self, PyObject *args, PyObjec
return self;
}
bool PythonContext::IsDebuggerConnected()
{
if(!m_DebugPy)
return false;
PyGILState_STATE gil = PyGILState_Ensure();
PyObject *is_connected = PyObject_CallMethod(m_DebugPy, "is_client_connected", NULL);
bool ret = (PyBool_Check(is_connected) && is_connected == Py_True);
Py_XDECREF(is_connected);
PyGILState_Release(gil);
return ret;
}
void PythonContext::PrepareDebuggerWait()
{
if(!m_DebugPy)
@@ -70,6 +70,9 @@ public:
static void PrepareDebugTracing();
static bool IsDebuggingEnabled() { return m_DebugPy != NULL; }
static bool IsDebuggerConnected();
static void PrepareDebuggerWait();
static bool WaitForDebugger();
static void LaunchDebugger(QWidget *window, PersistantConfig &config, QString context_location);
+38
View File
@@ -39,8 +39,10 @@
#include <QToolTip>
#include "Code/QRDUtils.h"
#include "Code/Resources.h"
#include "Code/pyrenderdoc/PythonContext.h"
#include "Widgets/Extended/RDLabel.h"
#include "Widgets/Extended/RDMenu.h"
#include "Widgets/Extended/RDToolButton.h"
#include "Widgets/ReplayOptionsSelector.h"
#include "Windows/Dialogs/AboutDialog.h"
#include "Windows/Dialogs/CaptureDialog.h"
@@ -224,6 +226,26 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
QObject::connect(statusIcon, &RDLabel::doubleClicked, this, &MainWindow::statusDoubleClicked);
QObject::connect(statusText, &RDLabel::doubleClicked, this, &MainWindow::statusDoubleClicked);
extensionStatus = new RDToolButton(this);
extensionStatus->setAutoRaise(true);
extensionStatus->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
ui->statusBar->addWidget(extensionStatus);
extensionStatus->setIcon(Icons::plugin());
extensionStatus->setVisible(false);
QObject::connect(extensionStatus, &RDToolButton::clicked, this,
&MainWindow::on_action_Manage_Extensions_triggered);
QObject::connect(PythonContext::GetExtensionContext(), &PythonContext::extensionLoaded, this,
&MainWindow::PythonStatusUpdate);
QTimer *debuggerTimer = new QTimer(this);
QObject::connect(debuggerTimer, &QTimer::timeout, this, &MainWindow::PythonStatusUpdate);
debuggerTimer->setSingleShot(false);
debuggerTimer->setInterval(500);
debuggerTimer->start();
QObject::connect(&m_MessageTick, &QTimer::timeout, this, &MainWindow::messageCheck);
m_MessageTick.setSingleShot(false);
m_MessageTick.setInterval(175);
@@ -1316,6 +1338,22 @@ void MainWindow::ClearRecentCaptureSettings()
PopulateRecentCaptureSettings();
}
void MainWindow::PythonStatusUpdate()
{
int num = m_Ctx.Extensions().GetLoadedExtensions().count();
if(num > 0 || PythonContext::IsDebuggerConnected())
{
// extensions can't be unloaded so we can just unconditionally show this now
extensionStatus->setVisible(true);
QString text = tr("%n extension(s) active", NULL, num);
if(PythonContext::IsDebuggerConnected())
text += tr(": Python debugger connected");
extensionStatus->setText(text);
}
}
void MainWindow::networkRequestFailed(QUrl url, QString error)
{
if(m_NetworkFailCallbacks.contains(url))
+4
View File
@@ -40,6 +40,7 @@ class MainWindow;
}
class RDLabel;
class RDToolButton;
class RDMenu;
class LambdaThread;
class QMimeData;
@@ -203,6 +204,8 @@ private slots:
void ClearRecentCaptureFiles();
void ClearRecentCaptureSettings();
void PythonStatusUpdate();
void networkRequestFailed(QUrl url, QString error);
void networkRequestCompleted(QUrl url, QByteArray data);
@@ -248,6 +251,7 @@ private:
RDLabel *statusIcon;
RDLabel *statusText;
RDToolButton *extensionStatus;
QProgressBar *statusProgress;
RDMenu *contextChooserMenu;
QToolButton *contextChooser;
+2
View File
@@ -375,8 +375,10 @@ struct ExtensionInvoker : ObjectForwarder<IExtensionManager>
///////////////////////////////////////////////////////////////////////
//
rdcarray<ExtensionMetadata> GetInstalledExtensions() { return m_Obj.GetInstalledExtensions(); }
rdcarray<rdcstr> GetLoadedExtensions() { return m_Obj.GetLoadedExtensions(); }
bool IsExtensionLoaded(rdcstr name) { return m_Obj.IsExtensionLoaded(name); }
rdcstr LoadExtension(rdcstr name) { return m_Obj.LoadExtension(name); }
bool IsPythonDebuggerConnected() { return m_Obj.IsPythonDebuggerConnected(); }
IMiniQtHelper &GetMiniQtHelper() { return *m_MiniQt; }
//
///////////////////////////////////////////////////////////////////////