|
2 | 2 | unicode_literals)
|
3 | 3 | import six
|
4 | 4 |
|
| 5 | +import functools |
5 | 6 | import os
|
6 | 7 | import re
|
7 | 8 | import signal
|
|
18 | 19 | from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
|
19 | 20 | from matplotlib.figure import Figure
|
20 | 21 |
|
21 |
| -from .qt_compat import (QtCore, QtGui, QtWidgets, _getSaveFileName, |
22 |
| - __version__, is_pyqt5) |
| 22 | +from .qt_compat import ( |
| 23 | + QtCore, QtGui, QtWidgets, _getSaveFileName, is_pyqt5, __version__, QT_API) |
23 | 24 |
|
24 | 25 | backend_version = __version__
|
25 | 26 |
|
@@ -132,6 +133,51 @@ def _create_qApp():
|
132 | 133 | pass
|
133 | 134 |
|
134 | 135 |
|
| 136 | +def _allow_super_init(__init__): |
| 137 | + """ |
| 138 | + Decorator for ``__init__`` to allow ``super().__init__`` on PyQt4/PySide2. |
| 139 | + """ |
| 140 | + |
| 141 | + if QT_API == "PyQt5": |
| 142 | + |
| 143 | + return __init__ |
| 144 | + |
| 145 | + else: |
| 146 | + # To work around lack of cooperative inheritance in PyQt4, PySide, |
| 147 | + # and PySide2, when calling FigureCanvasQT.__init__, we temporarily |
| 148 | + # patch QWidget.__init__ by a cooperative version, that first calls |
| 149 | + # QWidget.__init__ with no additional arguments, and then finds the |
| 150 | + # next class in the MRO with an __init__ that does support cooperative |
| 151 | + # inheritance (i.e., not defined by the PyQt4, PySide, PySide2, sip |
| 152 | + # or Shiboken packages), and manually call its `__init__`, once again |
| 153 | + # passing the additional arguments. |
| 154 | + |
| 155 | + qwidget_init = QtWidgets.QWidget.__init__ |
| 156 | + |
| 157 | + def cooperative_qwidget_init(self, *args, **kwargs): |
| 158 | + qwidget_init(self) |
| 159 | + mro = type(self).__mro__ |
| 160 | + next_coop_init = next( |
| 161 | + cls for cls in mro[mro.index(QtWidgets.QWidget) + 1:] |
| 162 | + if cls.__module__.split(".")[0] not in [ |
| 163 | + "PyQt4", "sip", "PySide", "PySide2", "Shiboken"]) |
| 164 | + next_coop_init.__init__(self, *args, **kwargs) |
| 165 | + |
| 166 | + @functools.wraps(__init__) |
| 167 | + def wrapper(self, **kwargs): |
| 168 | + try: |
| 169 | + QtWidgets.QWidget.__init__ = cooperative_qwidget_init |
| 170 | + __init__(self, **kwargs) |
| 171 | + finally: |
| 172 | + try: |
| 173 | + # Restore __init__ to sip.simplewrapper.__init__. |
| 174 | + del QtWidgets.QWidget.__init__ |
| 175 | + except AttributeError: |
| 176 | + pass |
| 177 | + |
| 178 | + return wrapper |
| 179 | + |
| 180 | + |
135 | 181 | class TimerQT(TimerBase):
|
136 | 182 | '''
|
137 | 183 | Subclass of :class:`backend_bases.TimerBase` that uses Qt timer events.
|
@@ -186,23 +232,20 @@ def _update_figure_dpi(self):
|
186 | 232 | dpi = self._dpi_ratio * self.figure._original_dpi
|
187 | 233 | self.figure._set_dpi(dpi, forward=False)
|
188 | 234 |
|
| 235 | + @_allow_super_init |
189 | 236 | def __init__(self, figure):
|
190 | 237 | _create_qApp()
|
191 | 238 | figure._original_dpi = figure.dpi
|
192 | 239 |
|
193 |
| - # NB: Using super for this call to avoid a TypeError: |
194 |
| - # __init__() takes exactly 2 arguments (1 given) on QWidget |
195 |
| - # PyQt5 |
196 |
| - # The need for this change is documented here |
197 |
| - # http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html#cooperative-multi-inheritance |
198 | 240 | super(FigureCanvasQT, self).__init__(figure=figure)
|
| 241 | + |
199 | 242 | self.figure = figure
|
200 | 243 | self._update_figure_dpi()
|
201 | 244 |
|
202 |
| - self.setMouseTracking(True) |
203 | 245 | w, h = self.get_width_height()
|
204 | 246 | self.resize(w, h)
|
205 | 247 |
|
| 248 | + self.setMouseTracking(True) |
206 | 249 | # Key auto-repeat enabled by default
|
207 | 250 | self._keyautorepeat = True
|
208 | 251 |
|
|
0 commit comments