Maya PyQt Dockable window - close callback

I’ve got a tool that’s created with QtDesigner, comverted to a .py file and then loaded by inheriting from this .py file. It has also been made dockable by use of Pymel’s dockcontrol. Relevant code:



def OnClose():
    print "Close Event fired!"
    



class MainWindow(QtGui.QMainWindow, Exportsets_UI.Ui_ExportSets):

    def __init__(self, parent=qtUtils.getAppWindow()):
	
        super(MainWindow, self).__init__(parent)

        
        self.setupUi(self)
        self.setObjectName('ExportSets_MainWindow')

	if pm.dockControl( 'ExportSets_Dock', q = 1, ex = 1 ):
	    pm.deleteUI( 'ExportSets_Dock' )                
        
        floatingLayout = pm.paneLayout( configuration = 'single', w=300)
        
        allowedAreas = ['right', 'left']
        pm.dockControl('ExportSets_Dock', aa=allowedAreas, a='right', fl=False, con=floatingLayout, label='ExportSets', w=300)

        pm.control('ExportSets_MainWindow', e=True, parent=floatingLayout)
	
	pm.scriptJob(uid=['ExportSets_MainWindow', 'ExportsetsMain.OnClose()'], runOnce=True)

    def closeEvent(self):
        ExportsetsMain.OnClose()

         -----the rest of the code follows after this


So, you can see that i have tried to set up 2 methods for a callback on close of my window. Before I made this thing dockable, overriding the closeEvent() actually worked. Ever since it became dockable, it stopped working, I presume because of parenting it to the pymel control.
However, the scriptjob doesn’t work properly either. It doesn’t fire on close, it fires on reopen! I assume this is because closing the dockable window doesn’t actually delete it? Or perhaps I’m attaching the scriptjob to the wrong UI? I’m kind of lost here; there is soooo little info on this stuff online, it’s crazy…

[QUOTE=Xoliul;21845]
So, you can see that i have tried to set up 2 methods for a callback on close of my window. Before I made this thing dockable, overriding the closeEvent() actually worked. Ever since it became dockable, it stopped working, I presume because of parenting it to the pymel control.
However, the scriptjob doesn’t work properly either. It doesn’t fire on close, it fires on reopen! I assume this is because closing the dockable window doesn’t actually delete it? Or perhaps I’m attaching the scriptjob to the wrong UI? I’m kind of lost here; there is soooo little info on this stuff online, it’s crazy…[/QUOTE]

So I’ve ran into this issue a few months ago. So the closeEvent() stops working once you dock the UI (This could be because when you close the dock UI it’s just hiding the UI and not closing it).
In dockControl You need to pass a proc to the vcc (visibleChangeCommand) flag. So once the UI is hidden it will run this callback.

cmds.dockControl( self.dock_name, area = ‘right’, label = self.window_title, content = window, allowedArea = [‘right’], w = ui_width, vcc = self.PROC )

I’m coming out with some Maya Callback examples soon with this example. Here’s one of the main Callback classes.
http://nicholas-silveira.blogspot.com/2013/07/test_4190.html

Hope that helps!
-Nick

You can also override the hideEvent method as you did with the closeEvent

Hey both suggestions work, but they also fire on open. the proc to the VCC flag is because it’s called on both hidden to shown and vice-versa. What would be a way to differentiate?

The hideEvent override is because of this piece of code:

if pm.dockControl( 'ExportSets_Dock', q = 1, ex = 1 ):
	    pm.deleteUI( 'ExportSets_Dock' )

Is there a better way to disable multiple windows? Been struggling a bit to find an elegant way to do this…

Edit: looking into it further, I’m not sure what or how the control actually gets shown? I’m creating those pymel controls but never explicitly telling them to show, yet my window still shows up by calling the constructor. I’d prefer to be able to init it once, and then call a show() function. Easy for a standard Qt window, not as obvious for a dockable window…

Nobody has tips for preventing multiples windows with a dockable? I’ve tried deleting the dockcontrol in the hideEvent (trying to force a close on hide), but that crashes Maya completely…
Still puzzled as well where in my constructor I’m actually telling the window to show?

Closing a dockControl is just hiding, not deleting.
This is the same as pyqt show()/hide() which are just setting the visibliity.

If you want the dockControl to only init once, don’t delete it - just show the existing one after it is created.

dockControl() also will automatically show() the contents (your pyqt window), so make sure not to call show() on the pyqt window directly to avoid duplicate windows.


show_export_sets_window():
    #If dockControl exists, show it and bring it to the front
    if pm.dockControl('ExportSets_Dock', query=True, ex=True):
        pm.dockControl('ExportSets_Dock', edit=True, vis=True, r=True)
    else:
        #dockControl does not exist, create it (this will show it).
        # [... all the other init code ...]
        pm.dockControl('ExportSets_Dock', aa=allowedAreas, a='right', fl=False, con=floatingLayout, label='ExportSets', w=300)

For your visibilityChangedCallback, you can query the state of the dockControl to determine if the visibility change is due to it being ‘closed’ (hidden),
so you will only do your code “onClose()”.


export_sets_visibility_callback():

    closeEvent = True

    if pm.dockControl('ExportSets_Dock', q=True, ex=True):
        #see if the dockControl is visible (which means this is a "showEvent", the dock became visible)
        if pm.dockControl('ExportSets_Dock', query=True, vis=True):
            closeEvent = False
    
    if closeEvent:
        #do your closeEvent() logic here.  
        pass

I am running into very similar issues with making my Qt UI’s dockable.

the main issue I am running into is with the visibilityChangeCommand deleting the dockControl when the control is set to Floating. For a brief moment, the dockControl is invisible and obscured, before it re-appears as a floating window, thus getting destroyed halfway through the process.