Maya dockable windows boilerplate, with support for PySide2

Oh, ok! Haha. Funny, StudioLibrary chose to just drop support of old versions. Their UI if focused on Maya 2017+. Okay :smiley:

Yes, just tried it and self.ui.setMenuBar shows PySide2.QtWidgets.QWidget object has no attribute ‘setMenuBar’`.

“setMenuBar()” is a convenience method for a QMainWindow instance. I believe setMenuBar() or menuBar() will work if your subclassing QMainWindow, not a QWidget. Otherwise, you will need to create a QMenuBar() and then add it manually to your widget’s layout.

@gonzalimator indeed. Yes, I did try to subclass QMainWindow instead of QWidget, and it did not work. Not with cmds.workspaceControl as a parent at least. And I’m not sure if I can somehow subclass workspaceControl and add QMainWidget into it’s inheritance?

And I also came to a conclusion that I will probably have to create my own ‘top-level’ layout to include menu and status bars in it.

I threw something up here that might answer this question. https://github.com/griffinanimator/share

@griffinanimator1 Hi, thanks for the snippet!

However, when I tried it, it did not work. I had to remove a few things from the code, but I don’t think they are the reason.

I removed this part:

#WINDOW_ICON = os.environ['FXS_ICON_PATH'] + '/FXS.png'
#pixmap = QtGui.QPixmap(WINDOW_ICON)
#icon = QtGui.QIcon(pixmap)

And this:

#self.ui.setWindowIcon(self.icon_img)

And it shows this error when I try to run it with win = dock_window(Test_UI):

# Error: AttributeError: file test.py line 167: 'PySide2.QtWidgets.QWidget' object has no attribute 'setCentralWidget'

I tried fiddling a bit more with this code, but it just throws more and more errors in Maya 2017

Here’s the code as I have it right now.

It is working, more or less. When I adapted my BroDynamics main window to use this class as parent class, it works perfectly both in Maya 2016 and in Maya 2017. So I suppose I’m on the right track here.

But when I try this class TestChildWindow(BroDockingUI): - it works in 2017, but shows blank window in 2016. So still working on it.

My apologies. I’m still at work and was hasty. I can prove a better example. Another consideration is that I’m using the custom QT package to provide backward compatibility.

@griffinanimator1 No worries. What package is that? If you’re referring to Qt.py - I’m using it as well, in this case at least.

So, another update. And it’s very weird.

So, take that code from my post above - it works in Maya 2017, it sort-of worked in Maya 2016, no errors, BUT the dockControl window was blank. It was there, it was created, it just did not have any contents in it. Even though it should. So I decided to check if my widget was even a child of that control.

So I added one line here (marked with <-- This line!):

    main_control = cmds.dockControl(DOCK_CONTROL_NAME, l=dialog_class.DOCK_LABEL_NAME, a='right', con=dialog_class.CONTROL_NAME, ret=False)
    # now lets get a C++ pointer to it using OpenMaya
    control_widget = omui.MQtUtil.findControl(main_control)
    # conver the C++ pointer to Qt object we can use
    control_wrap = wrapInstance(long(control_widget), QWidget)
    log.debug(control_wrap.findChild(QWidget, win.objectName()))  # <-- This line!

And guess what, it worked! But why?! :smiley:

Updated code on github with latest working version. Any ideas and suggestions welcomed.

I will take a look this evening. I went through this same issue and may be able to clear things up. In the interim, I updated the code on Github. It should work correctly now but I cant properly test from here.

The Mixin dock only docking on the left and right is a new one to me… maybe it’s worth taking another look at your original solution, Nix? My PySide2 dock builder is:

def buildMayaDock(base):
"""Get a Maya-dockable UI from the given qwidget subclass.
This is ONLY for 2017+, as MRO demands that mDock comes first, 
but QDockWidget must come after any compiled designer class"""
try:
    assert issubclass(base, QtWidgets.QWidget)
except (TypeError, AssertionError):
    print("Base class argument {0} must inherit QWidget in "
          "order to be a Maya dock widget.".format(base))
    return

class MayaDockUi(MayaQWidgetDockableMixin, base):
    """Some dock signals are replaced by method stubs:
    - dockCloseEventTriggered
    - floatingChanged
    ALSO, .show() method has args the FIRST TIME it is called, by default:
        dockable=False, floating=True, area="left", allowedArea="all", 
        width=None, height=None, x=None, y=None"""
    def __init__(self, parent=None):
        super(MayaDockUi, self).__init__(parent=parent)

return MayaDockUi

For me they can dock anywhere. I imagine your builder was similar… was the docking limited even if you play with the arguments for the initial .show()?

@clamdragon Hmm… Weird, now that you say this. I tried just this:

class DockingUI(MayaQWidgetDockableMixin, QWidget):
    def __init__(self, parent=None):
        super(DockingUI, self).__init__(parent)

my_dock = BroDockingUI().show(dockable=True)

And indeed it docks fine. I wonder why it did not work before.

But when I try to load my BroDynamics window this way Maya crashes with Fatal Error.

So, here’s updated version. There we go.

https://gist.github.com/Nixellion/f28051f1b53fee8b11a2fcd36ca244c3

Seems to be working fine in Maya 2016, 2017, 2018

Any notes, comments? Something to improve?

Just seen this comment, yes there are a few “frustrated” comments in the Red9 Studio Pack, Docking and workspaces are a pain!

@Mark-J Hi there, yeah, I had a laugh while reading them :smiley:

Well, as a matter of fact, it turned out that I was just not calling MayaQWidgetDockableMixin correctly. Like literally I was just passing wrong arguments to the “show()” :slight_smile: Once I fixed that everything started working and docking properly in all Maya versions (well, at least those I tested with: 2015-2017).

I’ll still need to find a way to dock it next to Attribute editor on startup, however.

So I wonder, is there any specific reason you’re going with cmds.workspaceContro l instead of inheriting from MayaQWidgetDockableMixin?

You should read some of the older comments in the Red9_AnimationUtils. Workspaces are a pain and whilst it’s been a while since I did that code from what I remember the dock widget no longer worked as expected in 2017 ( we took the decision in StudioPack at least to stay in cmds for the UI’s. ProPack is all QT and I think we’ll start to do migrate and upgrade the StudioPack soon when we get time)

@Mark-J Thanks, yes, cmds.dockControl works in 2017, but it has very limited docking areas, I think only far-left and far-right. Not even alongside Attribute editor, outside of that layout.

Ah, I see, I also always thought that staying with cmds should provide better support and easier upgrades from version to version, I never thought there’d be some breaking change there. But as it turned out using QT seems to be a better bet in the end.

What do you mean by next to? I’m guessing on the right, but not in the same stack as the attribute editor / channel box?

Ah thats why I switched to Workspace, I remember now, it was so we could dock into the channel box tabs and NOT to entire side of the whole application :wink: