Browse files

reorder qt support in kernel

import priority:

1. ask matplotlib (if imported) - if PyQt4 specified, use API v1
2. ask QT_API - if pyqt specified, use API v2
3. if nothing specified, try PyQt4 v1, fallback on PySide.
  • Loading branch information...
1 parent 3207b26 commit 6bc24fa32394bb740edaaa6199b9f70cbfe2c37f @minrk committed Jul 6, 2011
Showing with 112 additions and 4 deletions.
  1. +5 −0 IPython/external/
  2. +67 −4 IPython/external/
  3. +40 −0 docs/source/interactive/reference.txt
@@ -1,4 +1,9 @@
""" A Qt API selector that can be used to switch between PyQt and PySide.
+This uses the ETS 4.0 selection pattern of:
+PySide first, PyQt with API v2. second.
+Do not use this if you need PyQt with the old QString/QVariant API.
import os
@@ -1,12 +1,75 @@
""" Import Qt in a manner suitable for an IPython kernel.
+This is the import used for the `gui=qt` or `pylab=qt` initialization.
+if matplotlib has been imported:
+ # get here with pylab=qt
+ if matplotlib doesn't support v2 (<= 1.0.1):
+ use PyQt4 @v1
+ else:
+ ask matplotlib which Qt it's using
+ if it said PyQt:
+ use PyQt4 @v1
+ elif it said PySide:
+ use PySide
+if matplotlib had nothing to say, or matplotlib not imported:
+ # get here with gui=qt, or if matplotlib didn't tell us anything
+ ask ETS' QT_API env variable
+ if QT_API not set:
+ # this is the *default* path - no information was given
+ try:
+ PyQt @v1
+ except:
+ fallback on PySide
+ else:
+ use PyQt @v2 or PySide, depending on QT_API
+ because ETS doesn't work with v1.
+import os
import sys
-# Older versions of matplotlib do not support PyQt4 v2 APIs or PySide, so we
-# cannot go through the preferred mechanism.
matplotlib = sys.modules.get('matplotlib')
-if matplotlib and matplotlib.__version__ <= '1.0.1':
+if matplotlib:
+ # ask matplotlib first (get here with pylab=qt)
+ if matplotlib.__version__ <= '1.0.1':
+ # 1.0.1 doesn't support pyside or v2, so force PyQt @v1
+ mod = 'PyQt4'
+ else:
+ # this rc option has been proposed, but is yet not in matplotlib master
+ # as of writing.
+ mod = matplotlib.rcParams.get('backend.qt4', None)
+ # get here with `gui=qt`
+ mod = None
+if mod is None:
+ # matplotlib not imported or had nothing to say.
+ # ask QT_API ETS variable
+ QT_API = os.environ.get('QT_API', None)
+ if QT_API is None:
+ try:
+ # default to unconfigured PyQt4
+ from PyQt4 import QtCore, QtGui
+ except ImportError:
+ # fallback on PySide
+ try:
+ from PySide import QtCore, QtGui
+ except ImportError:
+ raise ImportError('Cannot import PySide or PyQt4')
+ else:
+ # QT_API specified, use PySide or PyQt+v2 API from external.qt
+ # this means ETS is likely to be used, which requires v2
+ from IPython.external.qt import QtCore, QtGui
+elif mod.lower() == 'pyqt4':
+ # import PyQt4 unconfigured
from PyQt4 import QtCore, QtGui
+elif mod.lower() == 'pyside':
+ from PySide import QtCore, QtGui
- from IPython.external.qt import QtCore, QtGui
+ raise ImportError("unhandled value for backend.qt4 from matplotlib: %r"%mod)
@@ -1256,6 +1256,46 @@ process pending events at critical points.
Finally, we also have a number of examples in our source directory
:file:`docs/examples/lib` that demonstrate these capabilities.
+PyQt and PySide
+.. attempt at explanation of the complete mess that is Qt support
+When you use ``gui=qt`` or ``pylab=qt``, IPython can work with either
+PyQt4 or PySide. There are three options for configuration here, because
+PyQt4 has two APIs for QString and QVariant - v1, which is the default on
+Python 2, and the more natural v2, which is the only API supported by PySide.
+v2 is also the default for PyQt4 on Python 3. IPython's code for the QtConsole
+uses v2, but you can still use any interface in your code, since the
+Qt frontend is in a different process.
+If you launch IPython in pylab mode with ``ipython pylab=qt``, then IPython
+will ask matplotlib which Qt library to use, via the 'backend.qt4' rcParam.
+If matplotlib is version 1.0.1 or older, then IPython will always use PyQt4
+without setting the v2 APIs.
+If you just integrate the Qt event loop with ``ipython gui=qt``, then IPython
+has a few more possibilities. The default will be to import PyQt4 without
+configuration of the APIs, thus matching what most applications would expect.
+It will fall back of PySide if PyQt4 is unavailable.
+If specified, IPython will respect the environment variable ``QT_API`` used
+by ETS. ETS 4.0 also works with both PyQt4 and PySide, but it requires
+PyQt4 to use the v2 API. So if ``QT_API=pyside`` PySide will be used,
+and if ``QT_API=pyqt`` then PyQt4 will be used with the v2 API for
+QString and QVariant, so ETS codes like MayaVi will also work with IPython.
+.. warning::
+ Note that this means for ETS to work with PyQt4, ``QT_API`` *must* be set to
+ work with IPython's qt integration, because otherwise PyQt4 will be loaded in
+ an incompatible mode.
+ It also means that you must not have ``QT_API`` set if you want to
+ use ``gui=qt`` with code that requires PyQt4 API v1.
.. _matplotlib_support:
Plotting with matplotlib

0 comments on commit 6bc24fa

Please sign in to comment.