i have some snippets you can use to make sure it works for all Mayas that use QT, the loadUIType and wrapinstance are taken from Nathan Horne (http://nathanhorne.com), and so far most of it seems to work fine.
haven’t done extensive tests yet:
import logging
default = "none"
try:
from PyQt4 import uic
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtGui
import sip
default = "pyqt4"
logging.Logger.manager.loggerDict["PyQt4.uic.uiparser"].setLevel(logging.CRITICAL)
logging.Logger.manager.loggerDict["PyQt4.uic.properties"].setLevel(logging.CRITICAL)
except:
try:
import xml.etree.ElementTree as xml
from cStringIO import StringIO
import pysideuic, shiboken
from PySide.QtGui import *
from PySide.QtCore import *
from PySide import QtGui
default = "pyside"
logging.Logger.manager.loggerDict["pysideuic.uiparser"].setLevel(logging.CRITICAL)
logging.Logger.manager.loggerDict["pysideuic.properties"].setLevel(logging.CRITICAL)
except:
try:
import xml.etree.ElementTree as xml
from cStringIO import StringIO
import shiboken2 as shiboken
import pyside2uic as pysideuic
from PySide2.QtGui import *
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2 import QtGui
default = "pyside2"
logging.Logger.manager.loggerDict["pyside2uic.uiparser"].setLevel(logging.CRITICAL)
logging.Logger.manager.loggerDict["pyside2uic.properties"].setLevel(logging.CRITICAL)
except:
print "PySide(2) and PyQt4 not found"
def loadUiType( uiFile ):
if default == "pyqt4":
form_class, base_class = uic.loadUiType( uiFile )
else:
parsed = xml.parse( uiFile )
widget_class = parsed.find( 'widget' ).get( 'class' )
form_class = parsed.find( 'class' ).text
with open( uiFile, 'r' ) as f:
o = StringIO()
frame = {}
pysideuic.compileUi( f, o, indent=0 )
pyc = compile( o.getvalue(), '<string>', 'exec' )
exec pyc in frame
form_class = frame[ 'Ui_%s'%form_class ]
base_class = eval( '%s'%widget_class )
return form_class, base_class
def wrapinstance( ptr, base=None ):
if ptr is None:
return None
ptr = long( ptr )
if globals().has_key( 'shiboken' ):
if base is None:
qObj = shiboken.wrapInstance( long( ptr ), QObject )
metaObj = qObj.metaObject()
cls = metaObj.className()
superCls = metaObj.superClass().className()
if hasattr( QtGui, cls ):
base = getattr( QtGui, cls )
elif hasattr( QtGui, superCls ):
base = getattr( QtGui, superCls )
else:
base = QWidget
return shiboken.wrapInstance( long( ptr ), base )
elif globals().has_key( 'sip' ):
base = QObject
return sip.wrapinstance( long( ptr ), base )
else:
return None
thanks all. As the main goal was to find Maya’s main window, went with:
try:
from PySide import QtGui as widgets
except:
from PySide2 import QtWidgets as widgets
#.. later
def mainWindow():
for widget in widgets.qApp.topLevelWidgets():
if widget.objectName()=='MayaWindow':
return widget
raise MessageException('QT Main window could not be detected')
While a one-liner, it’s both less-readable and less eficient, won’t you agree?
I guess something like below is acceptable as you’re at most building a list of one item.
main_window = [o for o in QtWidgets.qApp.topLevelWidgets() if o.objectName()=="MayaWindow"][0]
…but from my experience, the more verbose syntax always wins the readability battle. for-lopp with an if-statement reads as “i’m going through all items, looking for entry with particular name”. One-liner way says “I’m building this list of all names then keeping just the first one, because I know there will be only one and exactly the one I need”.
I’ve had to write a few tools that needed to work in other apps other than Maya so I’ve started to make this function a bit more generic. Hope this helpful to some.
try:
from PySide import QtGui as QtWidgets
except ImportError:
from PySide2 import QtWidgets
def getMainWindow():
"""
Get Main window
:return: main window
"""
mainWindow = QtWidgets.QApplication.activeWindow()
while True:
parentWin = mainWindow.parent()
if parentWin:
mainWindow = parentWin
else:
break
return mainWindow