pyqtgraph/pyqtgraph/Qt.py
Martin Fitzpatrick 42dbd7956a Adding PyQt5 compatibility (broken)
Adding compatibility for PyQt5 via a shim in Qt.py. This restructures the PyQt5 libraries
to match the layout seen in PyQt4, allowing it to continue to be used as drop in replacement.

This works up to the point of importing, however other API changes are broken - for example
the deprectation of .scale() on GraphicsItems throws an error currently.
2014-02-14 10:29:33 +01:00

136 lines
4.1 KiB
Python

"""
This module exists to smooth out some of the differences between PySide and PyQt4:
* Automatically import either PyQt4 or PySide depending on availability
* Allow to import QtCore/QtGui pyqtgraph.Qt without specifying which Qt wrapper
you want to use.
* Declare QtCore.Signal, .Slot in PyQt4
* Declare loadUiType function for Pyside
"""
import sys, re
PYSIDE = 0
PYQT4 = 1
PYQT5 = 2
USE_QT_PY = None
## Automatically determine whether to use PyQt or PySide.
## This is done by first checking to see whether one of the libraries
## is already imported. If not, then attempt to import PyQt4, then PySide.
if 'PyQt4' in sys.modules:
USE_QT_PY = PYQT4
if 'PyQt5' in sys.modules:
USE_QT_PY = PYQT5
elif 'PySide' in sys.modules:
USE_QT_PY = PYSIDE
else:
try:
import PyQt4
USE_QT_PY = PYQT4
except ImportError:
try:
import PyQt5
USE_QT_PY = PYQT5
except ImportError:
try:
import PySide
USE_QT_PY = PYSIDE
except:
pass
if USE_QT_PY == None:
raise Exception("PyQtGraph requires one of PyQt4, PyQt5 or PySide; none of these packages could be imported.")
if USE_QT_PY == PYSIDE:
from PySide import QtGui, QtCore, QtOpenGL, QtSvg
import PySide
VERSION_INFO = 'PySide ' + PySide.__version__
# Make a loadUiType function like PyQt has
# Credit:
# http://stackoverflow.com/questions/4442286/python-code-genration-with-pyside-uic/14195313#14195313
def loadUiType(uiFile):
"""
Pyside "loadUiType" command like PyQt4 has one, so we have to convert the ui file to py code in-memory first and then execute it in a special frame to retrieve the form_class.
"""
import pysideuic
import xml.etree.ElementTree as xml
from io import StringIO
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, frame)
#Fetch the base_class and form class based on their type in the xml from designer
form_class = frame['Ui_%s'%form_class]
base_class = eval('QtGui.%s'%widget_class)
return form_class, base_class
elif USE_QT_PY == PYQT4:
from PyQt4 import QtGui, QtCore, uic
try:
from PyQt4 import QtSvg
except ImportError:
pass
try:
from PyQt4 import QtOpenGL
except ImportError:
pass
loadUiType = uic.loadUiType
QtCore.Signal = QtCore.pyqtSignal
VERSION_INFO = 'PyQt4 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
elif USE_QT_PY == PYQT5:
# We're using PyQt5 which has a different structure so we're going to use a shim to
# recreate the Qt4 structure for Qt5
from PyQt5 import QtGui, QtCore, QtWidgets, Qt, uic
try:
from PyQt5 import QtSvg
except ImportError:
pass
try:
from PyQt5 import QtOpenGL
except ImportError:
pass
QtGui.QApplication = QtWidgets.QApplication
QtGui.QGraphicsScene = QtWidgets.QGraphicsScene
QtGui.QGraphicsObject = QtWidgets.QGraphicsObject
QtGui.QGraphicsWidget = QGraphicsWidget5
QtGui.QApplication.setGraphicsSystem = None
QtCore.Signal = Qt.pyqtSignal
# Import all QtWidgets objects into QtGui
for o in dir(QtWidgets):
if o.startswith('Q'):
setattr(QtGui, o, getattr(QtWidgets,o) )
## Make sure we have Qt >= 4.7
versionReq = [4, 7]
USE_PYSIDE = USE_QT_PY == PYSIDE # still needed internally elsewhere
QtVersion = PySide.QtCore.__version__ if USE_QT_PY == PYSIDE else QtCore.QT_VERSION_STR
m = re.match(r'(\d+)\.(\d+).*', QtVersion)
if m is not None and list(map(int, m.groups())) < versionReq:
print(list(map(int, m.groups())))
raise Exception('pyqtgraph requires Qt version >= %d.%d (your version is %s)' % (versionReq[0], versionReq[1], QtVersion))