Show More
@@ -1,87 +1,106 b'' | |||||
1 | """ Defines miscellaneous Qt-related helper classes and functions. |
|
1 | """ Defines miscellaneous Qt-related helper classes and functions. | |
2 | """ |
|
2 | """ | |
3 |
|
3 | |||
|
4 | # Standard library imports. | |||
|
5 | import inspect | |||
|
6 | ||||
4 | # System library imports. |
|
7 | # System library imports. | |
5 | from PyQt4 import QtCore, QtGui |
|
8 | from PyQt4 import QtCore, QtGui | |
6 |
|
9 | |||
7 | # IPython imports. |
|
10 | # IPython imports. | |
8 | from IPython.utils.traitlets import HasTraits |
|
11 | from IPython.utils.traitlets import HasTraits, TraitType | |
9 |
|
12 | |||
10 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
11 | # Metaclasses |
|
14 | # Metaclasses | |
12 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
13 |
|
16 | |||
14 | MetaHasTraits = type(HasTraits) |
|
17 | MetaHasTraits = type(HasTraits) | |
15 | MetaQObject = type(QtCore.QObject) |
|
18 | MetaQObject = type(QtCore.QObject) | |
16 |
|
19 | |||
17 | # You can switch the order of the parents here and it doesn't seem to matter. |
|
|||
18 | class MetaQObjectHasTraits(MetaQObject, MetaHasTraits): |
|
20 | class MetaQObjectHasTraits(MetaQObject, MetaHasTraits): | |
19 | """ A metaclass that inherits from the metaclasses of HasTraits and QObject. |
|
21 | """ A metaclass that inherits from the metaclasses of HasTraits and QObject. | |
20 |
|
22 | |||
21 | Using this metaclass allows a class to inherit from both HasTraits and |
|
23 | Using this metaclass allows a class to inherit from both HasTraits and | |
22 | QObject. Using SuperQObject instead of QObject is highly recommended. See |
|
24 | QObject. Using SuperQObject instead of QObject is highly recommended. See | |
23 | QtKernelManager for an example. |
|
25 | QtKernelManager for an example. | |
24 | """ |
|
26 | """ | |
25 | pass |
|
27 | def __new__(mcls, name, bases, classdict): | |
|
28 | # FIXME: this duplicates the code from MetaHasTraits. | |||
|
29 | # I don't think a super() call will help me here. | |||
|
30 | for k,v in classdict.iteritems(): | |||
|
31 | if isinstance(v, TraitType): | |||
|
32 | v.name = k | |||
|
33 | elif inspect.isclass(v): | |||
|
34 | if issubclass(v, TraitType): | |||
|
35 | vinst = v() | |||
|
36 | vinst.name = k | |||
|
37 | classdict[k] = vinst | |||
|
38 | cls = MetaQObject.__new__(mcls, name, bases, classdict) | |||
|
39 | return cls | |||
|
40 | ||||
|
41 | def __init__(mcls, name, bases, classdict): | |||
|
42 | # Note: super() did not work, so we explicitly call these. | |||
|
43 | MetaQObject.__init__(mcls, name, bases, classdict) | |||
|
44 | MetaHasTraits.__init__(mcls, name, bases, classdict) | |||
26 |
|
45 | |||
27 | #----------------------------------------------------------------------------- |
|
46 | #----------------------------------------------------------------------------- | |
28 | # Classes |
|
47 | # Classes | |
29 | #----------------------------------------------------------------------------- |
|
48 | #----------------------------------------------------------------------------- | |
30 |
|
49 | |||
31 | class SuperQObject(QtCore.QObject): |
|
50 | class SuperQObject(QtCore.QObject): | |
32 | """ Permits the use of super() in class hierarchies that contain QObject. |
|
51 | """ Permits the use of super() in class hierarchies that contain QObject. | |
33 |
|
52 | |||
34 | Unlike QObject, SuperQObject does not accept a QObject parent. If it did, |
|
53 | Unlike QObject, SuperQObject does not accept a QObject parent. If it did, | |
35 | super could not be emulated properly (all other classes in the heierarchy |
|
54 | super could not be emulated properly (all other classes in the heierarchy | |
36 | would have to accept the parent argument--they don't, of course, because |
|
55 | would have to accept the parent argument--they don't, of course, because | |
37 | they don't inherit QObject.) |
|
56 | they don't inherit QObject.) | |
38 |
|
57 | |||
39 | This class is primarily useful for attaching signals to existing non-Qt |
|
58 | This class is primarily useful for attaching signals to existing non-Qt | |
40 | classes. See QtKernelManager for an example. |
|
59 | classes. See QtKernelManager for an example. | |
41 | """ |
|
60 | """ | |
42 |
|
61 | |||
43 | def __new__(cls, *args, **kw): |
|
62 | def __new__(cls, *args, **kw): | |
44 | # We initialize QObject as early as possible. Without this, Qt complains |
|
63 | # We initialize QObject as early as possible. Without this, Qt complains | |
45 | # if SuperQObject is not the first class in the super class list. |
|
64 | # if SuperQObject is not the first class in the super class list. | |
46 | inst = QtCore.QObject.__new__(cls) |
|
65 | inst = QtCore.QObject.__new__(cls) | |
47 | QtCore.QObject.__init__(inst) |
|
66 | QtCore.QObject.__init__(inst) | |
48 | return inst |
|
67 | return inst | |
49 |
|
68 | |||
50 | def __init__(self, *args, **kw): |
|
69 | def __init__(self, *args, **kw): | |
51 | # Emulate super by calling the next method in the MRO, if there is one. |
|
70 | # Emulate super by calling the next method in the MRO, if there is one. | |
52 | mro = self.__class__.mro() |
|
71 | mro = self.__class__.mro() | |
53 | for qt_class in QtCore.QObject.mro(): |
|
72 | for qt_class in QtCore.QObject.mro(): | |
54 | mro.remove(qt_class) |
|
73 | mro.remove(qt_class) | |
55 | next_index = mro.index(SuperQObject) + 1 |
|
74 | next_index = mro.index(SuperQObject) + 1 | |
56 | if next_index < len(mro): |
|
75 | if next_index < len(mro): | |
57 | mro[next_index].__init__(self, *args, **kw) |
|
76 | mro[next_index].__init__(self, *args, **kw) | |
58 |
|
77 | |||
59 | #----------------------------------------------------------------------------- |
|
78 | #----------------------------------------------------------------------------- | |
60 | # Functions |
|
79 | # Functions | |
61 | #----------------------------------------------------------------------------- |
|
80 | #----------------------------------------------------------------------------- | |
62 |
|
81 | |||
63 | def get_font(family, fallback=None): |
|
82 | def get_font(family, fallback=None): | |
64 | """Return a font of the requested family, using fallback as alternative. |
|
83 | """Return a font of the requested family, using fallback as alternative. | |
65 |
|
84 | |||
66 | If a fallback is provided, it is used in case the requested family isn't |
|
85 | If a fallback is provided, it is used in case the requested family isn't | |
67 | found. If no fallback is given, no alternative is chosen and Qt's internal |
|
86 | found. If no fallback is given, no alternative is chosen and Qt's internal | |
68 | algorithms may automatically choose a fallback font. |
|
87 | algorithms may automatically choose a fallback font. | |
69 |
|
88 | |||
70 | Parameters |
|
89 | Parameters | |
71 | ---------- |
|
90 | ---------- | |
72 | family : str |
|
91 | family : str | |
73 | A font name. |
|
92 | A font name. | |
74 | fallback : str |
|
93 | fallback : str | |
75 | A font name. |
|
94 | A font name. | |
76 |
|
95 | |||
77 | Returns |
|
96 | Returns | |
78 | ------- |
|
97 | ------- | |
79 | font : QFont object |
|
98 | font : QFont object | |
80 | """ |
|
99 | """ | |
81 | font = QtGui.QFont(family) |
|
100 | font = QtGui.QFont(family) | |
82 | # Check whether we got what we wanted using QFontInfo, since exactMatch() |
|
101 | # Check whether we got what we wanted using QFontInfo, since exactMatch() | |
83 | # is overly strict and returns false in too many cases. |
|
102 | # is overly strict and returns false in too many cases. | |
84 | font_info = QtGui.QFontInfo(font) |
|
103 | font_info = QtGui.QFontInfo(font) | |
85 | if fallback is not None and font_info.family() != family: |
|
104 | if fallback is not None and font_info.family() != family: | |
86 | font = QtGui.QFont(fallback) |
|
105 | font = QtGui.QFont(fallback) | |
87 | return font |
|
106 | return font |
General Comments 0
You need to be logged in to leave comments.
Login now