mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-24 23:46:41 +00:00
Remove 'always load' extra opt-in for extensions
* If an extension is enabled in the extension manager, it will be loaded by default after that until disabled
This commit is contained in:
@@ -45,11 +45,11 @@ To configure installed extensions, open the extension manager by opening the :gu
|
||||
|
||||
Extension Manager: Configures installed extensions.
|
||||
|
||||
From here a list of all installed extensions is presented. By default extensions are not loaded, to load an extension either select it and press :guilabel:`Load` or else tick the box in the :guilabel:`Loaded` column in the list. As with python modules, once loaded an extension cannot be unloaded until the program is restarted.
|
||||
From here a list of all installed extensions is presented. By default extensions are not enabled or loaded, to load an extension you tick the box in the :guilabel:`Enabled` column.
|
||||
|
||||
Once an extension is loaded to enable it permanently, tick the :guilabel:`Always Load` checkbox when the extension is selected. Once enabled this means the extension will always load when the UI starts without any user interaction. Extensions must be loaded first to ensure they can load without errors or crashes before enabling them to load at startup.
|
||||
Once an extension is enabled it will be loaded each time RenderDoc starts, and as normal for python modules, once loaded an extension cannot be unloaded. To disable an extension uncheck the :guilabel:`Enabled` checkbox and the extension will be disabled the next time you restart RenderDoc.
|
||||
|
||||
A loaded extension can be reloaded by pressing the :guilabel:`Reload` button which will attempt to unload and load the extension again to refresh the code. This may break so if you encounter any problems it's recommended that you restart the program to ensure a clean reload.
|
||||
A loaded extension can be reloaded if the files have changed on disk from the :doc:`python scripting <../window/python_scripting>` window. This may break especially in the presence of callbacks, open UI, registered handlers or other persistent pieces of code. If you encounter any problems it's recommended that you restart RenderDoc to ensure a clean reload.
|
||||
|
||||
Writing extensions
|
||||
------------------
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
@@ -20,17 +20,10 @@ From the dialog that appears enter a package name such as ``tutorialext``. This
|
||||
|
||||
For more information about the registration of python extensions see :doc:`../how/how_python_extension`
|
||||
|
||||
Loading the extension
|
||||
---------------------
|
||||
Enabling the extension
|
||||
----------------------
|
||||
|
||||
To load the extension, select it in the list in the extension manager and click the :guilabel:`Load` button. Python modules can't be unloaded but they can be reloaded if changes are made to the files on disk, so the button changes to :guilabel:`Reload`.
|
||||
|
||||
When the extension is loaded a ``register()`` function is called, which at the moment for us just prints a message. This message can be viewed in the output panel of the :doc:`python scripting <../window/python_scripting>` window, which you can jump to by clicking :guilabel:`View Output`. You can filter the output with the drop-down above the output text.
|
||||
|
||||
.. note::
|
||||
The output this will not show any messages from before the window was opened - you can click :guilabel:`Reload` after opening the python scripting window to see some new messages.
|
||||
|
||||
To avoid bugs in extensions from making the UI unusable easily, python extensions are not loaded by default. Once you've loaded an extension if you wish to have it automatically load on startup, you can do so by enabling :guilabel:`Always Load`.
|
||||
To load the extension, tick the :guilabel:`Enable` checkbox for its entry the extension manager. Python modules can't be unloaded but they can be reloaded if changes are made to the files on disk, which can be done from the :doc:`python scripting <../window/python_scripting>` window or the status bar.
|
||||
|
||||
Editing your extension
|
||||
----------------------
|
||||
|
||||
@@ -48,7 +48,7 @@ ExtensionManager::ExtensionManager(ICaptureContext &ctx)
|
||||
RDHeaderView *header = new RDHeaderView(Qt::Horizontal, this);
|
||||
ui->extensions->setHeader(header);
|
||||
|
||||
ui->extensions->setColumns({tr("Package"), tr("Name"), tr("Loaded")});
|
||||
ui->extensions->setColumns({tr("Package"), tr("Name"), tr("Enabled")});
|
||||
header->setColumnStretchHints({1, 4, -1});
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ ExtensionManager::ExtensionManager(ICaptureContext &ctx)
|
||||
ui->version->setText(lit("---"));
|
||||
ui->author->setText(lit("---"));
|
||||
ui->URL->setText(lit("---"));
|
||||
ui->alwaysLoad->setEnabled(false);
|
||||
ui->status->setText(lit("---"));
|
||||
|
||||
QObject::connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
|
||||
@@ -89,7 +89,7 @@ void ExtensionManager::PopulateExtensionList()
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({e.package, e.name, QString()});
|
||||
|
||||
item->setCheckState(
|
||||
2, m_Ctx.Extensions().IsExtensionLoaded(e.package) ? Qt::Checked : Qt::Unchecked);
|
||||
2, m_Ctx.Config().AlwaysLoad_Extensions.contains(e.package) ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
ui->extensions->addTopLevelItem(item);
|
||||
}
|
||||
@@ -114,13 +114,8 @@ void ExtensionManager::loadExtension(RDTreeWidgetItem *item)
|
||||
{
|
||||
// if the load succeeds, set us as checked. Otherwise, unchecked
|
||||
QString errors = m_Ctx.Extensions().LoadExtension(e.package);
|
||||
if(errors.isEmpty())
|
||||
if(!errors.isEmpty())
|
||||
{
|
||||
item->setCheckState(2, Qt::Checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setCheckState(2, Qt::Unchecked);
|
||||
RDDialog::critical(this, tr("Failed to load extension"),
|
||||
tr("Failed to load extension '%1':\n"
|
||||
"%2")
|
||||
@@ -133,28 +128,6 @@ void ExtensionManager::loadExtension(RDTreeWidgetItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionManager::on_alwaysLoad_toggled(bool checked)
|
||||
{
|
||||
RDTreeWidgetItem *item = ui->extensions->currentItem();
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
int idx = ui->extensions->indexOfTopLevelItem(item);
|
||||
|
||||
if(idx >= 0 && idx < m_Extensions.count())
|
||||
{
|
||||
const ExtensionMetadata &e = m_Extensions[idx];
|
||||
if(!e.name.isEmpty())
|
||||
{
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.removeOne(e.package);
|
||||
if(checked)
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.push_back(e.package);
|
||||
|
||||
m_Ctx.Config().Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionManager::on_extensions_currentItemChanged(RDTreeWidgetItem *item, RDTreeWidgetItem *)
|
||||
{
|
||||
update_currentItem(item);
|
||||
@@ -166,22 +139,25 @@ void ExtensionManager::on_extensions_itemChanged(RDTreeWidgetItem *item, int col
|
||||
{
|
||||
ui->extensions->setCurrentItem(item);
|
||||
|
||||
bool loaded = m_Ctx.Extensions().IsExtensionLoaded(item->text(0));
|
||||
QString package = item->text(0);
|
||||
|
||||
// if the extension is loaded, don't allow unchecking
|
||||
if(loaded && item->checkState(2) != Qt::Checked)
|
||||
bool loaded = m_Ctx.Extensions().IsExtensionLoaded(package);
|
||||
bool enabled = (item->checkState(2) == Qt::Checked);
|
||||
|
||||
// if the extension is unloaded and the user just enabled it, try to load it.
|
||||
if(!loaded && enabled)
|
||||
{
|
||||
item->setCheckState(2, Qt::Checked);
|
||||
return;
|
||||
loadExtension(item);
|
||||
}
|
||||
|
||||
// if the extension is unloaded, if we're now checked then try to load it. If
|
||||
// we're unchecked allow that (it is a code-change after we failed to load)
|
||||
if(!loaded)
|
||||
{
|
||||
if(item->checkState(2) == Qt::Checked)
|
||||
loadExtension(item);
|
||||
}
|
||||
// update the config after, in case the extension immediately has crahed
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.removeOne(package);
|
||||
if(enabled)
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.push_back(package);
|
||||
|
||||
m_Ctx.Config().Save();
|
||||
|
||||
update_currentItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,10 +194,17 @@ void ExtensionManager::update_currentItem(RDTreeWidgetItem *item)
|
||||
else
|
||||
ui->author->setText(e.author);
|
||||
|
||||
bool loaded = item->checkState(2) == Qt::Checked;
|
||||
ui->alwaysLoad->setEnabled(loaded);
|
||||
const bool enabled = m_Ctx.Config().AlwaysLoad_Extensions.contains(e.package);
|
||||
const bool loaded = m_Ctx.Extensions().IsExtensionLoaded(e.package);
|
||||
|
||||
ui->alwaysLoad->setChecked(m_Ctx.Config().AlwaysLoad_Extensions.contains(e.package));
|
||||
if(loaded && enabled)
|
||||
ui->status->setText(tr("Loaded (Enabled at startup)"));
|
||||
else if(loaded && !enabled)
|
||||
ui->status->setText(tr("Loaded (Restart required to disable)"));
|
||||
else if(!loaded && enabled)
|
||||
ui->status->setText(tr("Failed to load (Enabled at startup)"));
|
||||
else if(!loaded && !enabled)
|
||||
ui->status->setText(tr("Disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ public:
|
||||
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_alwaysLoad_toggled(bool checked);
|
||||
void on_extensions_currentItemChanged(RDTreeWidgetItem *item, RDTreeWidgetItem *);
|
||||
void on_extensions_itemChanged(RDTreeWidgetItem *item, int col);
|
||||
|
||||
|
||||
@@ -140,6 +140,23 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="text">
|
||||
<string>Status:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="status">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
@@ -149,7 +166,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QTextEdit" name="description">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
@@ -165,62 +182,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="extensionButtonsLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="alwaysLoad">
|
||||
<property name="text">
|
||||
<string>Always Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -1758,7 +1758,7 @@ void PythonShell::projectExplorer_contextMenu(const QPoint &pos)
|
||||
// if this is the root node of a UI extension, add options to filter output/reload
|
||||
if(item->parent() == m_UIExtensions)
|
||||
{
|
||||
QString itemPath = item->data(0, Qt::UserRole + 1).toString();
|
||||
rdcstr itemPath = item->data(0, Qt::UserRole + 1).toString();
|
||||
|
||||
contextMenu.insertAction(contextMenu.actions()[0], &reloadExtension);
|
||||
contextMenu.insertSeparator(contextMenu.actions()[1]);
|
||||
@@ -1783,6 +1783,18 @@ void PythonShell::projectExplorer_contextMenu(const QPoint &pos)
|
||||
QObject::connect(&reloadExtension, &QAction::triggered,
|
||||
[this, itemPath]() { m_Ctx.Extensions().LoadExtension(itemPath); });
|
||||
|
||||
if(!m_Ctx.Config().AlwaysLoad_Extensions.contains(itemPath))
|
||||
{
|
||||
reloadExtension.setEnabled(true);
|
||||
reloadExtension.setText(tr("Enable extension"));
|
||||
reloadExtension.setIcon(Icons::add());
|
||||
|
||||
QObject::connect(&reloadExtension, &QAction::triggered, [this, itemPath]() {
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.push_back(itemPath);
|
||||
m_Ctx.Config().Save();
|
||||
});
|
||||
}
|
||||
|
||||
QObject::connect(&explorerOpen, &QAction::triggered,
|
||||
[this, diskLocation]() { QDesktopServices::openUrl(diskLocation); });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user