##// END OF EJS Templates
BUG: Explicitly merge the __init__ and __new__ metaclass methods for MetaQObjectHasTraits. The MetaHasTraits code was not being executed previously.
Robert Kern -
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