source: orange/Orange/OrangeCanvas/utils/qtcompat.py @ 11299:0d7f328b766a

Revision 11299:0d7f328b766a, 3.3 KB checked in by Ales Erjavec <ales.erjavec@…>, 15 months ago (diff)

PyQt4 < 4.8.3 QSettings compatibility class (type parameter for value method).

Always use the type parameter instead of QVariant transformations.

Line 
1"""
2PyQt4 compatibility utility functions.
3
4.. warning:: It is important that any `sip.setapi` (at least for QVariant
5             and QString) calls are already made before importing this
6             module.
7
8"""
9from operator import methodcaller
10
11import sip
12
13# All known api names for compatibility with version of sip where
14# `getapi` is not available ( < v4.9)
15_API_NAMES = set(["QVariant", "QString", "QDate", "QDateTime",
16                  "QTextStream", "QTime", "QUrl"])
17
18
19def sip_getapi(name):
20    """
21    Get the api version for a name.
22    """
23    if sip.SIP_VERSION < 0x40900:
24        return sip.getapi(name)
25    elif name in _API_NAMES:
26        return 1
27    else:
28        raise ValueError("unknown API {0!r}".format(name))
29
30
31HAS_QVARIANT = sip_getapi("QVariant") == 1
32HAS_QSTRING = sip_getapi("QString") == 1
33
34if HAS_QVARIANT:
35    from PyQt4.QtCore import QVariant
36
37from PyQt4.QtCore import QSettings, QByteArray
38from PyQt4.QtCore import PYQT_VERSION
39
40QSETTINGS_HAS_TYPE = PYQT_VERSION >= 0x40803
41"""QSettings.value has a `type` parameter"""
42
43
44def toPyObject(variant):
45    """
46    Return `variant` as a python object if it is wrapped in a `QVariant`
47    instance (using `variant.toPyObject()`). In case the sip API version
48    for QVariant does not export it just return the object unchanged.
49
50    """
51    if HAS_QVARIANT:
52        return variant
53    elif isinstance(variant, QVariant):
54        return variant.toPyObject()
55    else:
56        raise TypeError("Expected a 'QVariant'")
57
58
59if HAS_QVARIANT:
60    toBitArray = methodcaller("toBitArray")
61    toBool = methodcaller("toBool")
62    toByteArray = methodcaller("toByteArray")
63    toChar = methodcaller("toChar")
64    toDate = methodcaller("")
65    toPyObject = methodcaller("toPyObject")
66
67    toFlaot = methodcaller("toFlaot")
68
69
70def _check_error((val, status)):
71    if not status:
72        raise TypeError()
73    else:
74        return val
75
76
77def qvariant_to_py(variant, py_type):
78    """
79    Convert a `QVariant` object to a python object of type `py_type`.
80    """
81    if py_type == bool:
82        return variant.toBool()
83    elif py_type == int:
84        return _check_error(variant.toInt())
85    elif py_type == str:
86        return unicode(variant.toString())
87    elif py_type == unicode:
88        return unicode(variant.toString())
89    elif py_type == QByteArray:
90        return variant.toByteArray()
91
92    else:
93        raise TypeError("Unsuported type {0!s}".format(py_type))
94
95
96if not QSETTINGS_HAS_TYPE:
97    _QSettings = QSettings
98
99    class QSettings(QSettings):
100        """
101        A subclass of QSettings with a simulated `type` parameter in
102        value method.
103
104        """
105        # QSettings.value does not have `type` type before PyQt4 4.8.3
106        # We dont't check if QVariant is exported, it is assumed on such old
107        # installations the new api is not used.
108        def value(self, key,
109                  defaultValue=QVariant(),
110                  type=None):
111            """
112            Returns the value for setting key. If the setting doesn't exist,
113            returns defaultValue.
114
115            """
116            if not _QSettings.contains(self, key):
117                return defaultValue
118
119            value = _QSettings.value(self, key)
120
121            if type is not None:
122                value = qvariant_to_py(value, type)
123
124            return value
Note: See TracBrowser for help on using the repository browser.