Mel GUI needs to trigger PyQt GUI update

In Maya there is a legacy Mel GUI pipeline tool at my studio. Basic file save/export/referencing etc functionality. It’s using Maya’s built in window GUI.

I built a new PyQt window for in scene asset management that contains a list of the pipeline assets in the scene.

The PyQt asset manager window works fine independently. But I now need to add a linkage so that when an artist references a new asset using the old pipeline GUI tool, that it triggers a list update on the PyQt window. I have a method in the class for the update. But accessing it is the problem.

If I made it a class method would that help? I’ve typically used class methods for changing class variables not triggering GUI updates. Any thoughts would be super helpful!

Example:

The MEL GUI pipeline tool (needs to be able to trigger PyQt GUI):

global proc createMelGUIWindow()
{
    string $window = `window -title "Mel GUI Window" -widthHeight 300 25`;
    columnLayout -adjustableColumn true;
    button -label "Reference Asset" -command ("referenceAsset");
    setParent ..;
    showWindow $window;
}

global proc referenceAsset()
{
    // do something to trigger the PyQt GUI to update
    // somehow needs to run: AssetManagerTool().updateAssetList()
    print("Triggering referenced asset to update the PyQt GUI.");
}

createMelGUIWindow();

The PyQt window built in QtDesigner and saved as a file called assetManagerWindow.py (imported in the next block of python code):

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_AssetManagerWindow(object):
    def setupUi(self, AssetManagerWindow):
        AssetManagerWindow.setObjectName("AssetManagerWindow")
        AssetManagerWindow.resize(424, 284)
        self.layout_window = QtWidgets.QWidget(AssetManagerWindow)
        self.layout_window.setObjectName("layout_window")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layout_window)
        self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.widget_assetManagerTable = QtWidgets.QTableWidget(self.layout_window)
        self.widget_assetManagerTable.setObjectName("widget_assetManagerTable")
        self.widget_assetManagerTable.setColumnCount(1)
        self.widget_assetManagerTable.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.widget_assetManagerTable.setHorizontalHeaderItem(0, item)
        self.widget_assetManagerTable.verticalHeader().setVisible(False)
        self.verticalLayout_3.addWidget(self.widget_assetManagerTable)
        self.button_refresh = QtWidgets.QPushButton(self.layout_window)
        self.button_refresh.setObjectName("button_refresh")
        self.button_refresh.setText("Reload List Manually")
        self.verticalLayout_3.addWidget(self.button_refresh)
        AssetManagerWindow.setCentralWidget(self.layout_window)
        
        QtCore.QMetaObject.connectSlotsByName(AssetManagerWindow)

The Python I run to load the PyQt window with all the extra methods (has a Manual Reload button for testing to show the function working from the PyQt tool itself):

import os
import sys
import operator

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot, QUrl
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent

from assetManagerWindow import Ui_AssetManagerWindow

import maya.cmds as cmds

def maya_main_window():
    return {w.objectName(): w for w in QtWidgets.qApp.topLevelWidgets()}["MayaWindow"]

class AssetManagerTool(QtWidgets.QMainWindow, Ui_AssetManagerWindow):
    def __init__(self, parent=maya_main_window(), *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        
        self.setupUi(self)
        
        self.button_refresh.clicked.connect(self.updateAssetList)

        self.show()
    
    def updateAssetList(self):
        self.widget_assetManagerTable.setRowCount(1)
        item_obj = QtWidgets.QTableWidgetItem("My Item")
        self.widget_assetManagerTable.setItem(0, 0, item_obj )



AssetManagerTool().show()

Found an answer:

I’m keeping a reference to the instance in a class variable now. and now loading the UI through a function that checks for the existance of the instance and only creates the UI if the instance doesn’t exist. This is not directly needed but I wanted a single instance of the GUI.

This then uses that instance reference to load the method from that instance.

Example:

The MEL GUI pipeline tool (needs to be able to trigger PyQt GUI):

global proc createMelGUIWindow()
{
    string $window = `window -title "Mel GUI Window" -widthHeight 300 25`;
    columnLayout -adjustableColumn true;
    button -label "Reference Asset" -command ("referenceAsset");
    setParent ..;
    showWindow $window;
}

global proc referenceAsset()
{
    // uses the instance reference and calls the method for that instance
    python("AssetManagerTool.instance.updateAssetList()");
}

createMelGUIWindow();

The PyQt window built in QtDesigner and saved as a file called assetManagerWindow.py (imported in the next block of python code):

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_AssetManagerWindow(object):
    def setupUi(self, AssetManagerWindow):
        AssetManagerWindow.setObjectName("AssetManagerWindow")
        AssetManagerWindow.resize(424, 284)
        self.layout_window = QtWidgets.QWidget(AssetManagerWindow)
        self.layout_window.setObjectName("layout_window")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layout_window)
        self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.widget_assetManagerTable = QtWidgets.QTableWidget(self.layout_window)
        self.widget_assetManagerTable.setObjectName("widget_assetManagerTable")
        self.widget_assetManagerTable.setColumnCount(1)
        self.widget_assetManagerTable.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.widget_assetManagerTable.setHorizontalHeaderItem(0, item)
        self.widget_assetManagerTable.verticalHeader().setVisible(False)
        self.verticalLayout_3.addWidget(self.widget_assetManagerTable)
        self.button_refresh = QtWidgets.QPushButton(self.layout_window)
        self.button_refresh.setObjectName("button_refresh")
        self.button_refresh.setText("Reload List Manually")
        self.verticalLayout_3.addWidget(self.button_refresh)
        AssetManagerWindow.setCentralWidget(self.layout_window)
        
        QtCore.QMetaObject.connectSlotsByName(AssetManagerWindow)

The Python I run to load the PyQt window with all the extra methods. Now has a class variable storing the instance reference. Also includes a function to load the class instance and store that instance reference:

import os
import sys
import operator

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot, QUrl
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent

from assetManagerWindow import Ui_AssetManagerWindow

import maya.cmds as cmds

def maya_main_window():
    return {w.objectName(): w for w in QtWidgets.qApp.topLevelWidgets()}["MayaWindow"]

class AssetManagerTool(QtWidgets.QMainWindow, Ui_AssetManagerWindow):

    instance = None

    def __init__(self, parent=maya_main_window(), *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        
        self.setupUi(self)
        
        self.button_refresh.clicked.connect(self.updateAssetList)

        self.show()
    
    def updateAssetList(self):
        self.widget_assetManagerTable.setRowCount(1)
        item_obj = QtWidgets.QTableWidgetItem("My Item")
        self.widget_assetManagerTable.setItem(0, 0, item_obj )


def loadUI():
    if not AssetManagerTool.instance:
        AssetManagerTool.instance = AssetManagerTool()
        print(AssetManagerTool.instance)
    AssetManagerTool.instance.show()
    AssetManagerTool.instance.raise_()

loadUI()