From 965d788fe5857644cfcb3f8a5946a283eff43a06 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 5 Mar 2026 16:47:46 +0000 Subject: [PATCH] Add a settings window entry to add extra python stubs paths --- qrenderdoc/Code/Interface/PersistantConfig.h | 6 ++ qrenderdoc/Code/pyrenderdoc/PythonContext.cpp | 20 +++--- qrenderdoc/Code/pyrenderdoc/PythonContext.h | 2 +- qrenderdoc/Code/qrenderdoc.cpp | 5 +- qrenderdoc/Windows/Dialogs/SettingsDialog.cpp | 57 ++++++++++++++++- qrenderdoc/Windows/Dialogs/SettingsDialog.h | 3 + qrenderdoc/Windows/Dialogs/SettingsDialog.ui | 61 +++++++++++++++++++ 7 files changed, 140 insertions(+), 14 deletions(-) diff --git a/qrenderdoc/Code/Interface/PersistantConfig.h b/qrenderdoc/Code/Interface/PersistantConfig.h index 3212c68c3..951599746 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.h +++ b/qrenderdoc/Code/Interface/PersistantConfig.h @@ -364,6 +364,12 @@ DECLARE_REFLECTION_STRUCT(BugReport); "type: List[str]"); \ CONFIG_SETTING(public, QVariantList, rdcarray, TextureViewer_ShaderDirs) \ \ + DOCUMENT( \ + "List of extra directories to write python stubs into.\n" \ + "\n:" \ + "type: List[str]"); \ + CONFIG_SETTING(public, QVariantList, rdcarray, Python_StubDirs) \ + \ DOCUMENT( \ "``True`` if when loading a capture that was originally captured on a remote device but " \ "uses an API that can be supported locally, should be loaded locally without prompting to " \ diff --git a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp index fd1a33f2c..41b2eee0e 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp +++ b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp @@ -401,7 +401,7 @@ void PythonContext::GenerateStubs(const rdcarray &extraPaths) qInfo() << "Stubs generation processed in" << timer.elapsed() << "ms"; } -void PythonContext::GlobalInit() +void PythonContext::GlobalInit(PersistantConfig &config) { // must happen on the UI thread if(qApp->thread() != QThread::currentThread()) @@ -417,10 +417,10 @@ void PythonContext::GlobalInit() PyImport_AppendInittab("qrenderdoc", &PyInit_qrenderdoc); #if PY_VERSION_HEX > 0x030B0000 - PyConfig config; - PyConfig_InitPythonConfig(&config); - config.configure_c_stdio = 0; - config.parse_argv = 0; + PyConfig pyconfig; + PyConfig_InitPythonConfig(&pyconfig); + pyconfig.configure_c_stdio = 0; + pyconfig.parse_argv = 0; #endif #if defined(STATIC_QRENDERDOC) @@ -433,7 +433,7 @@ void PythonContext::GlobalInit() pylibs.toWCharArray(python_home); #if PY_VERSION_HEX > 0x030B0000 - config.home = python_home; + pyconfig.home = python_home; #else Py_SetPythonHome(python_home); #endif @@ -441,11 +441,11 @@ void PythonContext::GlobalInit() #endif #if PY_VERSION_HEX > 0x030B0000 - config.program_name = program_name; + pyconfig.program_name = program_name; - config.use_environment = 0; + pyconfig.use_environment = 0; - Py_InitializeFromConfig(&config); + Py_InitializeFromConfig(&pyconfig); #else Py_SetProgramName(program_name); @@ -477,7 +477,7 @@ void PythonContext::GlobalInit() main_dict = PyModule_GetDict(main_module); - GenerateStubs({}); + GenerateStubs(config.Python_StubDirs); // replace sys.stdout and sys.stderr with our own objects. These have a 'this' pointer of NULL, // which then indicates they need to forward to a global object diff --git a/qrenderdoc/Code/pyrenderdoc/PythonContext.h b/qrenderdoc/Code/pyrenderdoc/PythonContext.h index 35366f6dd..a0d6220d6 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonContext.h +++ b/qrenderdoc/Code/pyrenderdoc/PythonContext.h @@ -55,7 +55,7 @@ public: void PausePythonThreading(); void ResumePythonThreading(); - static void GlobalInit(); + static void GlobalInit(PersistantConfig &config); static void GlobalShutdown(); static QStringList GetApplicationExtensionsPaths(); diff --git a/qrenderdoc/Code/qrenderdoc.cpp b/qrenderdoc/Code/qrenderdoc.cpp index 9b9f112fa..fd71499ae 100644 --- a/qrenderdoc/Code/qrenderdoc.cpp +++ b/qrenderdoc/Code/qrenderdoc.cpp @@ -286,7 +286,8 @@ int main(int argc, char *argv[]) { QCoreApplication application(argc, mod_argv); - PythonContext::GlobalInit(); + PersistantConfig cfg; + PythonContext::GlobalInit(cfg); logstream << "Checking python binding consistency.\n"; @@ -631,7 +632,7 @@ int main(int argc, char *argv[]) } else { - PythonContext::GlobalInit(); + PythonContext::GlobalInit(config); if(updateApplied) { diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp index 1948b6a6e..be2455f25 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp @@ -31,6 +31,7 @@ #include #include "Code/Interface/QRDInterface.h" #include "Code/QRDUtils.h" +#include "Code/pyrenderdoc/PythonContext.h" #include "Styles/StyleData.h" #include "Widgets/OrderedListEditor.h" #include "Widgets/ReplayOptionsSelector.h" @@ -793,6 +794,57 @@ void SettingsDialog::on_browseRGPPath_clicked() m_Ctx.Config().Save(); } +void SettingsDialog::on_Python_StubPaths_clicked() +{ + QDialog listEditor; + + listEditor.setWindowTitle(tr("Extra python stubs generation directories")); + listEditor.setWindowFlags(listEditor.windowFlags() & ~Qt::WindowContextHelpButtonHint); + + OrderedListEditor list(tr("Stubs Directory"), + OrderedItemExtras::BrowseFolder | OrderedItemExtras::Delete); + + QVBoxLayout layout; + QDialogButtonBox okCancel; + okCancel.setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + layout.addWidget(&list); + layout.addWidget(&okCancel); + + QObject::connect(&okCancel, &QDialogButtonBox::accepted, &listEditor, &QDialog::accept); + QObject::connect(&okCancel, &QDialogButtonBox::rejected, &listEditor, &QDialog::reject); + + listEditor.setLayout(&layout); + + QStringList items; + for(const rdcstr &dir : m_Ctx.Config().Python_StubDirs) + { + items.append(dir); + } + + list.setItems(items); + + int res = RDDialog::show(&listEditor); + + if(res) + { + items = list.getItems(); + + rdcarray newDirs; + newDirs.resize(items.size()); + for(int i = 0; i < items.size(); i++) + { + newDirs[i] = items[i]; + } + + if(newDirs.size() > m_Ctx.Config().Python_StubDirs.size()) + PythonContext::GenerateStubs(newDirs); + + m_Ctx.Config().Python_StubDirs = newDirs; + + m_Ctx.Config().Save(); + } +} + // texture viewer void SettingsDialog::on_TextureViewer_PerTexSettings_toggled(bool checked) { @@ -817,7 +869,8 @@ void SettingsDialog::on_TextureViewer_ChooseShaderDirectories_clicked() listEditor.setWindowTitle(tr("Custom shaders search directories")); listEditor.setWindowFlags(listEditor.windowFlags() & ~Qt::WindowContextHelpButtonHint); - OrderedListEditor list(tr("Shaders Directory"), OrderedItemExtras::BrowseFolder); + OrderedListEditor list(tr("Shaders Directory"), + OrderedItemExtras::BrowseFolder | OrderedItemExtras::Delete); QVBoxLayout layout; QDialogButtonBox okCancel; @@ -852,6 +905,8 @@ void SettingsDialog::on_TextureViewer_ChooseShaderDirectories_clicked() } m_Ctx.Config().TextureViewer_ShaderDirs = newDirs; + + m_Ctx.Config().Save(); } } diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.h b/qrenderdoc/Windows/Dialogs/SettingsDialog.h index 35af80d87..c6fd0e1f0 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.h +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.h @@ -81,6 +81,9 @@ private slots: void on_ExternalTool_RadeonGPUProfiler_textEdited(const QString &rgp); void on_browseRGPPath_clicked(); + // python + void on_Python_StubPaths_clicked(); + // texture viewer void on_TextureViewer_PerTexSettings_toggled(bool checked); void on_TextureViewer_ResetRange_toggled(bool checked); diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui index ff89d06e6..d88f9f5c9 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.ui +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.ui @@ -677,6 +677,67 @@ After interop is enabled you will need to reload any capture. + + + Python + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Python + + + + + + + 0 + 0 + + + + Extra python stubs paths + + + + + + + Python Stub Paths + + + + + + + Qt::Vertical + + + + 20 + 387 + + + + + + + + + Replay