From 6b9cec797d466b4ab6305a869c21bfcf4b9b6978 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 17 Sep 2026 11:43:54 +0100 Subject: [PATCH] Add signal when python extensions are changed * This avoids repeatedly hitting disk to enumerate current extensions for UI updates. --- qrenderdoc/Code/CaptureContext.cpp | 7 ++++++- qrenderdoc/Code/pyrenderdoc/PythonContext.h | 1 + qrenderdoc/Windows/MainWindow.cpp | 23 ++++++++++++++++----- qrenderdoc/Windows/MainWindow.h | 7 +++++-- qrenderdoc/Windows/PythonShell.cpp | 14 +++++++++++-- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/qrenderdoc/Code/CaptureContext.cpp b/qrenderdoc/Code/CaptureContext.cpp index 8db660612..4ad3d88f8 100644 --- a/qrenderdoc/Code/CaptureContext.cpp +++ b/qrenderdoc/Code/CaptureContext.cpp @@ -577,7 +577,8 @@ rdcstr CaptureContext::LoadExtension(rdcstr name) else { m_ExtensionObjects.remove(name); - m_FailedExtensions.push_back(name); + if(!m_FailedExtensions.contains(name)) + m_FailedExtensions.push_back(name); for(QObject *o : m_PendingExtensionObjects) delete o; @@ -591,6 +592,8 @@ rdcstr CaptureContext::LoadExtension(rdcstr name) m_RegisteredMenuItems.removeAll(NULL); + emit PythonContext::GetExtensionContext()->extensionsUpdated(); + return ret; } @@ -2949,6 +2952,8 @@ void CaptureContext::ExtensionTouched(const QString &extensionPath) m_DirtyExtensions.push_back(m.package); } } + + emit PythonContext::GetExtensionContext()->extensionsUpdated(); } void CaptureContext::RaiseDockWindow(QWidget *dockWindow) diff --git a/qrenderdoc/Code/pyrenderdoc/PythonContext.h b/qrenderdoc/Code/pyrenderdoc/PythonContext.h index 4617756f1..e9d9cc5a2 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonContext.h +++ b/qrenderdoc/Code/pyrenderdoc/PythonContext.h @@ -146,6 +146,7 @@ signals: void textOutput(const QString &extension, bool isStdError, const QString &output); void extensionLoaded(const QString &extension); + void extensionsUpdated(); public slots: void executeString(const QString &source); diff --git a/qrenderdoc/Windows/MainWindow.cpp b/qrenderdoc/Windows/MainWindow.cpp index 2bad07c72..b110a0050 100644 --- a/qrenderdoc/Windows/MainWindow.cpp +++ b/qrenderdoc/Windows/MainWindow.cpp @@ -252,10 +252,21 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai m_Ctx.Extensions().LoadExtension(m.package); }); QObject::connect(PythonContext::GetExtensionContext(), &PythonContext::extensionLoaded, this, - &MainWindow::PythonStatusUpdate); + &MainWindow::PythonStatusBarUpdate); + QObject::connect(PythonContext::GetExtensionContext(), &PythonContext::extensionsUpdated, this, + &MainWindow::PythonStatusBarUpdate); QTimer *pyStatusTimer = new QTimer(this); - QObject::connect(pyStatusTimer, &QTimer::timeout, this, &MainWindow::PythonStatusUpdate); + QObject::connect(pyStatusTimer, &QTimer::timeout, [this]() { + // regularly check if a python debugger has connected or disconnected, + // and update the status bar + bool pyDebug = PythonContext::IsDebuggerConnected(); + if(pyDebug != m_CurPyDebug) + { + PythonStatusBarUpdate(); + m_CurPyDebug = pyDebug; + } + }); pyStatusTimer->setSingleShot(false); pyStatusTimer->setInterval(500); @@ -1337,7 +1348,7 @@ void MainWindow::ClearRecentCaptureSettings() PopulateRecentCaptureSettings(); } -void MainWindow::PythonStatusUpdate() +void MainWindow::PythonStatusBarUpdate() { int num = m_Ctx.Extensions().GetLoadedExtensions().count(); @@ -1348,8 +1359,10 @@ void MainWindow::PythonStatusUpdate() QString text = tr("%n extension(s) active", NULL, num); + rdcarray exts = m_Ctx.Extensions().GetInstalledExtensions(); + bool reloadVisible = false; - for(const ExtensionMetadata &m : m_Ctx.Extensions().GetInstalledExtensions()) + for(const ExtensionMetadata &m : exts) { if(m.hasChanges) { @@ -1358,7 +1371,7 @@ void MainWindow::PythonStatusUpdate() break; } } - for(const ExtensionMetadata &m : m_Ctx.Extensions().GetInstalledExtensions()) + for(const ExtensionMetadata &m : exts) { if(m.failedLoad) { diff --git a/qrenderdoc/Windows/MainWindow.h b/qrenderdoc/Windows/MainWindow.h index 88ef24749..a7e0f8071 100644 --- a/qrenderdoc/Windows/MainWindow.h +++ b/qrenderdoc/Windows/MainWindow.h @@ -203,11 +203,12 @@ private slots: void ClearRecentCaptureFiles(); void ClearRecentCaptureSettings(); - void PythonStatusUpdate(); - void networkRequestFailed(QUrl url, QString error); void networkRequestCompleted(QUrl url, QByteArray data); +public slots: + void PythonStatusBarUpdate(); + signals: void networkRequestGet(QUrl url); @@ -256,6 +257,8 @@ private: RDMenu *contextChooserMenu; QToolButton *contextChooser; + bool m_CurPyDebug = false; + QAction *updateAction = NULL; QTimer m_MessageTick; diff --git a/qrenderdoc/Windows/PythonShell.cpp b/qrenderdoc/Windows/PythonShell.cpp index 8216c2bc1..84d1a7d56 100644 --- a/qrenderdoc/Windows/PythonShell.cpp +++ b/qrenderdoc/Windows/PythonShell.cpp @@ -379,8 +379,7 @@ PythonShell::PythonShell(ICaptureContext &ctx, QWidget *parent) QObject::connect(m_Watcher, &QFileSystemWatcher::directoryChanged, this, &PythonShell::updateExtensionProjects); - QTimer *pyStatusTimer = new QTimer(this); - QObject::connect(pyStatusTimer, &QTimer::timeout, [this]() { + QObject::connect(PythonContext::GetExtensionContext(), &PythonContext::extensionsUpdated, [this]() { QList curModExts; for(const ExtensionMetadata &m : m_Ctx.Extensions().GetInstalledExtensions()) @@ -398,7 +397,10 @@ PythonShell::PythonShell(ICaptureContext &ctx, QWidget *parent) updateExtensionProjects(); m_ModifiedExtensions = curModExts; } + }); + QTimer *pyStatusTimer = new QTimer(this); + QObject::connect(pyStatusTimer, &QTimer::timeout, [this]() { bool hasDebugger = PythonContext::IsDebuggerConnected(); if(m_DebuggerAttached != hasDebugger) @@ -1049,6 +1051,8 @@ void PythonShell::updateNonDebugWarning() edit->setWarning( tr("External debugger will not work for unsaved files. " "Save script to disk to allow debugging.")); + else + edit->setWarning(QString()); } else { @@ -1933,6 +1937,9 @@ void PythonShell::projectExplorer_contextMenu(const QPoint &pos) QAction createExtension(tr("Create &New Extension"), this); createExtension.setIcon(Icons::plugin_add()); + QAction refreshExtensionList(tr("&Refresh Extension List"), this); + refreshExtensionList.setIcon(Icons::update()); + QObject::connect(&expandAll, &QAction::triggered, [this, item]() { ui->projectExplorer->expandAllItems(item); }); @@ -2019,8 +2026,11 @@ void PythonShell::projectExplorer_contextMenu(const QPoint &pos) contextMenu.addSeparator(); contextMenu.addAction(&createExtension); + contextMenu.addAction(&refreshExtensionList); QObject::connect(&createExtension, &QAction::triggered, [this]() { createExtension_clicked(); }); + QObject::connect(&refreshExtensionList, &QAction::triggered, + [this]() { updateExtensionProjects(); }); } RDDialog::show(&contextMenu, ui->projectExplorer->viewport()->mapToGlobal(pos));