PyQt Error - Custom Panel in Shotgun Desktop

Hi,

I have a custom publish plugin in SG desktop that includes a UI. I’m using the create_settings_widget method in the plugin script to instantiate and return my custom qt panel.

This works fine if only one item is in the publish queue.

However if another item is dropped in the gueue the previous panel get deleted and I get an Internal C++ object error.

I thought that each item in the queue was treated separately and that each panel UI belonged to that item parent instance. What is deleting the original panel, then?

You have to post the actual error. But likely something is getting incorrect arguments, which can trigger such an error, for instance.

1 Like
Traceback (most recent call last):
  File "\\network\configs\install\app_store\tk-multi-publish2\v2.6.0\python\tk_multi_publish2\api\plugins\publish_plugin_instance.py", line 308, in _handle_plugin_error
    yield
  File \\network\configs\\install\app_store\tk-multi-publish2\v2.6.0\python\tk_multi_publish2\api\plugins\publish_plugin_instance.py", line 180, in run_validate
    status = self._hook_instance.validate(settings, item)
  File "\\network\configs\config\hooks\tk-maya\supervisor_settings.py", line 252, in validate
    self._panel_values_changed(item, logger)
  File "\\network\configs\config\hooks\tk-maya\supervisor_settings.py", line 393, in _panel_values_changed
    appr_checked = self.widget.appr_checked
  File "\\network\configs\config\hooks\tk-maya\supervisor_settings.py", line 951, in appr_checked
    return self.chk_appr.isChecked()
RuntimeError: Internal C++ object (PySide2.QtWidgets.QCheckBox) already deleted.

in the supervisor_settings.py script I’m using

    def create_settings_widget(self, parent):
        self.widget = SupervisorWidget()
        return self.widget  

to set the UI I’m creating to the parent.

I think part of my confusion is that I misunderstood what the parent was here. I thought the parent was UI components of the item that was dropped into the publisher. Not the whole UI component.

What I think is happening is that each time a new supervisor_settings panel is created, it’s destroying the one previous to it.

It’s unclear how I can get that UI instance to stay in memory.

Shouldn’t you parent the SupervisorWidget to the passed parent in the function?
Yeah for some reason the widget gets destroyed before the check. If you think a previous one gets deleted, then checking if chk_appr (or whatever) might work?

Apologies. The snippet was meant to be an example. I should have clarified what arguments were being passed.

for the sake of brevity, I’m keeping most of my other arguments and methods out:

    def create_settings_widget(self, parent):
        self.widget = SupervisorWidget(parent, self.item, self.user)
        return self.widget 
class SupervisorWidget(QtGui.QWidget):
    """
    Custom UI for Supervisor plugin.
    """
    def __init__(self, parent, item, user):
        super(SupervisorWidget, self).__init__(parent)

Alright I see. This seems to be correct.

So to clarify, the issue only happens if more than one item gets dropped into the publisher.
image

The UI creates the separate override panels and I set up the get and set_ui_settings to preserve the UI state.

It works great when there’s only one item for publish. It seems like the publisher destroys the UI instance when the new one is created but it doesn’t re-draw the UI to remove the dead panel.

So when I click any of the check boxes and I run validate (I have a validate method in the supervisor settings plugin to check for UI changes) the panel that’s not currently selected complains about the destroyed UI instance.

I can check to see if it still sees the state of the non-active panel rather than examine the panel instance components which will have been destroyed by that point anyway.

Oh, in this case yes probably when you switch to another item, the old ui is destroyed, but some handler still triggers.
But during validation you do not need to work with the Qt widgets, rather all changes should be saved to the settings object, which you can then examine.

That was exactly the reason. Call it a misunderstanding of how to use it on my part.
Using the settings instead of the UI connections did the trick.

Thanks!