Skip to content

Commit

Permalink
Merge PR #560 'Reorder qt support in kernel'
Browse files Browse the repository at this point in the history
closes gh-560
  • Loading branch information
minrk committed Jul 8, 2011
2 parents b511f6f + 2767ebe commit 0e80619
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
5 changes: 5 additions & 0 deletions IPython/external/qt.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
76 changes: 73 additions & 3 deletions IPython/external/qt_for_kernel.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,82 @@
""" Import Qt in a manner suitable for an IPython kernel.
This is the import used for the `gui=qt` or `pylab=qt` initialization.
Import Priority:
if matplotlib has been imported and doesn't support v2 (<= 1.0.1):
use PyQt4 @v1
Next, ask ETS' QT_API env variable
if QT_API not set:
ask matplotlib via rcParams['backend.qt4']
if it said PyQt:
use PyQt4 @v1
elif it said PySide:
use PySide
else: (matplotlib said nothing)
# this is the default path - nobody told us anything
try:
PyQt @v1
except:
fallback on PySide
else:
use PyQt @v2 or PySide, depending on QT_API
because ETS doesn't work with PyQt @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':
# 1.0.1 doesn't support pyside or v2, so stick with PyQt @v1,
# and ignore everything else
from PyQt4 import QtCore, QtGui
else:
from IPython.external.qt import QtCore, QtGui
# ask QT_API ETS variable *first*
QT_API = os.environ.get('QT_API', None)
if QT_API is None:
# QT_API not set, ask matplotlib if it was imported (e.g. `pylab=qt`)
if matplotlib:
mpqt = matplotlib.rcParams.get('backend.qt4', None)
else:
mpqt = None
if mpqt is None:
# matplotlib not imported or had nothing to say.
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')
elif mpqt.lower() == 'pyqt4':
# import PyQt4 unconfigured
from PyQt4 import QtCore, QtGui
elif mpqt.lower() == 'pyside':
from PySide import QtCore, QtGui
else:
raise ImportError("unhandled value for backend.qt4 from matplotlib: %r"%mpqt)
else:
# QT_API specified, use PySide or PyQt+v2 API from external.qt
# this means ETS is likely to be used, which requires v2
try:
from IPython.external.qt import QtCore, QtGui
except ValueError as e:
if 'API' in str(e):
# API mismatch, give more meaningful message
raise ImportError("""
Assigning the ETS variable `QT_API=pyqt` implies PyQt's v2 API for
QString and QVariant, but PyQt has already been imported
with v1 APIs. You must unset QT_API to work with PyQt4
in its default mode.
""")
else:
raise

40 changes: 40 additions & 0 deletions docs/source/interactive/reference.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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 its 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.

If you launch IPython in pylab mode with ``ipython pylab=qt``, then IPython
will ask matplotlib which Qt library to use (only if QT_API is *not set*),
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, since neither v2 PyQt nor PySide work.

.. warning::

Note that this means for ETS 4 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
Expand Down

0 comments on commit 0e80619

Please sign in to comment.