1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
Potential Incompatibilities with Earlier Versions
=================================================
PyQt4 v4.11
-----------
Execution of Python Slots
*************************
Until the release of PyQt4 v4.9.4, when a signal was emitted to a Python slot
that was not decorated with :func:`~PyQt4.QtCore.pyqtSlot`, it would first
check that the underlying C++ receiver instance still existed. If it didn't
then the slot was ignored thereby reflecting the standard C++ behaviour.
In v4.9.4 (strictly speaking it was the release of SIP at the time) the check
was removed. It was done so that an object could connect its
:func:`~PyQt4.QtCore.QObject.destroyed` signal to itself so that it could
monitor when its underlying C++ instance was destroyed. Unfortunately this
turned out to be an undocumented and incompatible change and a potential source
of obscure bugs for more common code.
In v4.11 the check was reintroduced - hence creating an incompatibility for any
code that relies on the v4.9.4 behaviour. As a workaround for this the
``no_receiver_check`` argument has been added to
:func:`~PyQt4.QtCore.QObject.connect` which allows the check to be suppressed
on a per connection basis.
PyQt4 v4.9.2
------------
QPyNullVariant
**************
In previous versions a ``QPyNullVariant`` would always evaluate to ``True``
when converted to a bool.
In this version a ``QPyNullVariant`` will always evaluate to ``False`` when
converted to a bool. This makes it behave like ``None`` in these
circumstances.
PyQt4 v4.8.3
------------
SQL Models
**********
In previous versions, when using v2 of the QVariant API (the default for Python
v3), there was no way to represent a null ``QVariant``. Therefore when reading
values of certain types from an SQL model it was impossible to distinguish
between, for example, a null integer and an integer with the value zero.
In this version the ``QPyNullVariant`` class is used to represent a null
QVariant. Therefore the object read from an SQL model may now be a
``QPyNullVariant`` instance.
A null ``QVariant`` is only converted to a ``QPyNullVariant`` if the underlying
C++ type of the ``QVariant`` cannot be tested for null, i.e. it does not
implement an ``isNull()`` method. This ensures that existing code that uses
non-SQL models will continue to work unchanged.
PyQt4 v4.8
----------
QVariantList
************
In previous versions PyQt4 would always try and convert a Python list to a
``QVariantList``. In this version PyQt4 will first try to convert it to a
``QVariant`` containing a ``QList<QObject *>``, but only if
``QList<QObject *>`` has been registered with Qt as a meta-type.
Normally it is only the :mod:`~PyQt4.QtDeclarative` module that registers this
meta-type and so the behaviour of existing applications should be unchanged.
It is possible however that you might observe different conversion behaviour
after importing the :mod:`~PyQt4.QtDeclarative` module.
PyQt4 v4.7.4
------------
:func:`~PyQt4.QtCore.pyqtSignal` with dict and list
***************************************************
In previous versions a Qt signal defined using
:func:`~PyQt4.QtCore.pyqtSignal` that had an argument specified as a dict then,
when emitting a value, PyQt4 would try and convert the value to a
``QVariantMap`` if possible. If it wasn't possible, normally because the dict
had non-string keys, then the value would be left as a dict object.
In this version PyQt4 will not attempt to convert the value to a
``QVariantMap`` and will always leave it as a dict object. If you want the
value to be converted to a ``QVariantMap`` then define the signal argument as
``'QVariantMap'``.
The same applies to conversions between lists and ``QVariantList``.
PyQt4 v4.7.1
------------
QVariant
********
This version introduces a slight incompatibility in the conversion between
sub-classes of standard Python types and ``QVariant``.
Take, for example, the following code::
from PyQt4.QtCore import QVariant
class MyFloat(float):
pass
myfloat = MyFloat(5.0)
variant = QVariant(myfloat)
With this version of PyQt4 ``myfloat`` will be converted in such a way as to
preserve any additional attributes (including methods) and will not be
converted to a C++ ``double``. In other words, the following assertions are
true::
assert(variant.type() != QVariant.Double)
assert(variant.toPyObject() is myfloat)
Prior to this version ``myfloat`` would be converted to a C++ ``double``. In
other words, the following assertions would be true::
assert(variant.type() == QVariant.Double)
assert(variant.toPyObject() == myfloat)
assert(type(variant.toPyObject()) is float)
The same change also affects objects that implement the sequence protocol.
Prior to this version such an object would be converted to a ``QVariantList``
which would mean that it was converted back to a Python ``list`` rather than to
the original type.
PyQt4 v4.5
----------
QVariant
********
This version introduces a slight incompatibility in the conversion between
Python sub-classes of certain Qt classes and ``QVariant``. The Qt classes
affected are those that ``QVariant`` has explicit support for, e.g. ``QSize``,
``QBitmap``.
Take, for example, the following code::
from PyQt4.QtCore import QSize, QVariant
class MySize(QSize):
pass
mysize = MySize(5, 5)
variant = QVariant(mysize)
With this version of PyQt4 ``mysize`` will be converted in such a way as to
preserve any additional attributes (including methods) and will not be
converted to a C++ ``QSize`` instance. In other words, the following
assertions are true::
assert(variant.type() != QVariant.Size)
assert(variant.toPyObject() is mysize)
Prior to this version ``mysize`` would be converted to a C++ ``QSize``
instance. In other words, the following assertions would be true::
assert(variant.type() == QVariant.Size)
assert(variant.toPyObject() == mysize)
assert(type(variant.toPyObject()) is QSize)
It is hoped that this change of behaviour will not have a significant impact.
However if you need the old behaviour then simply create a copy of your
sub-class instance using the base class constructor as shown below::
variant = QVariant(QSize(mysize))
A similar issue also affects the conversion of the Python ``datetime``,
``date`` and ``time`` types to ``QVariant``. These are no longer converted to
the corresponding ``QDateTime``, ``QDate`` and ``QTime`` classes. The values
can be retrieved using ``QVariant.toPyObject()``. Again, the old behaviour can
be achieved using an explicit conversion to the Qt class before converting to
``QVariant``.
A further incompatible change is the handling of Python sub-classes of
``QObject``. In previous versions ``QVariant.userType()`` would return an
internal type and an extra reference would be kept to the Python object. In
the current version ``QVariant.userType()`` will correctly return
``QMetaType.QObjectStar`` (or ``QMetaType.QWidgetStar``) but an extra
reference to the Python object is not kept. To avoid a potential crash you
should ensure that you keep a separate reference to the Python object, either
explicitly or implicitly by giving it a parent.
:program:`pyrcc4` Support for Python v3
***************************************
:program:`pyrcc4` will now generate code for Python v3 when the new
:option:`-py3 <pyrcc4 -py3>` command line option is used. The generated code
will also work with Python v2.6 and later.
By default :program:`pyrcc4` will generate code for all Python v2 versions but
you should use the new :option:`-py2 <pyrcc4 -py2>` command line option to
enforce this in case the default is changed in the future.
|