I’m currently looking to find or create a boilerplate for dockable PySide window for Maya, as the title says.
Until now I was using MayaQDockWidget from MayaMixin. And it was working fine for my tool’s windows until Maya 2017 came out. It still works fine, but it only docks on far-left and far-right of the screen, while there are a lot more dock options now.
And it works perfectly, I was able to create a base class and base module out of this, which I can use. It docks everywhere, next to the outliner, within any tab, etc, allowing for full customization.
But, there’s one problem, now self.setMenuBar(self.menubar_thing) command from PySide wont’ work. There are no errors, menu bar just does not appear. As well as QStatusBar with self.setStatusBar() command.
I’m clearly missing something, and hope someone might help. I’m looking either for a solution for the menu bar and status bar problems with current setup (the one from GitHub), or an alternative boilerplate for Maya dockable pyside window, compatible with old and new Maya versions (well, at least starting with 2014).
So, the final goal here is to find and compile a base module and class for Dockable PySide windows in Maya, with support of menuBar and statusBar and backwards compatible with older versions of Maya (2014-2016). Backwards compatibility can, of course, be in a form of fallback to old docking methods.
So looking at that code, can’t test it currently, but I think I’ve got a rough idea of what it is trying to do.
What happens when you try self.ui.setMenuBar?
I’m not sure right now, but I think it said that self.ui has no such function as setMenuBar()
By the way, if I use similar code in Maya 2016 with dockControl instead of workspaceControl - menubars work fine. But dockControl works quite differently, however. I’m currently also researching studiolibrary’s and Red9’s code to find out how it’s done there. In Red9’s code I found a few comments which clearly show author’s frustration with new workspaceControl
New docking system is clearly not backwards compatible, as Maya 2016 and below don’t have workspaceControl command at all. And old dockControl or Docking class from MayaMixin have limited docking functionality.
“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.
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!
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()?
@Mark-J Hi there, yeah, I had a laugh while reading them
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()” 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)