##// END OF EJS Templates
BUG: QtKernelManagerMixin does not define PyQt4-safe signals.
epatters -
Show More
@@ -1,258 +1,260 b''
1 """ Defines a KernelManager that provides signals and slots.
1 """ Defines a KernelManager that provides signals and slots.
2 """
2 """
3
3
4 # System library imports.
4 # System library imports.
5 from IPython.external.qt import QtCore
5 from IPython.external.qt import QtCore
6
6
7 # IPython imports.
7 # IPython imports.
8 from IPython.utils.traitlets import Type
8 from IPython.utils.traitlets import HasTraits, Type
9 from util import SuperQObject
9 from util import MetaQObjectHasTraits, SuperQObject
10
10
11
11
12 class ChannelQObject(SuperQObject):
12 class ChannelQObject(SuperQObject):
13
13
14 # Emitted when the channel is started.
14 # Emitted when the channel is started.
15 started = QtCore.Signal()
15 started = QtCore.Signal()
16
16
17 # Emitted when the channel is stopped.
17 # Emitted when the channel is stopped.
18 stopped = QtCore.Signal()
18 stopped = QtCore.Signal()
19
19
20 #---------------------------------------------------------------------------
20 #---------------------------------------------------------------------------
21 # Channel interface
21 # Channel interface
22 #---------------------------------------------------------------------------
22 #---------------------------------------------------------------------------
23
23
24 def start(self):
24 def start(self):
25 """ Reimplemented to emit signal.
25 """ Reimplemented to emit signal.
26 """
26 """
27 super(ChannelQObject, self).start()
27 super(ChannelQObject, self).start()
28 self.started.emit()
28 self.started.emit()
29
29
30 def stop(self):
30 def stop(self):
31 """ Reimplemented to emit signal.
31 """ Reimplemented to emit signal.
32 """
32 """
33 super(ChannelQObject, self).stop()
33 super(ChannelQObject, self).stop()
34 self.stopped.emit()
34 self.stopped.emit()
35
35
36 #---------------------------------------------------------------------------
36 #---------------------------------------------------------------------------
37 # EmbeddedChannel interface
37 # EmbeddedChannel interface
38 #---------------------------------------------------------------------------
38 #---------------------------------------------------------------------------
39
39
40 def call_handlers_later(self, *args, **kwds):
40 def call_handlers_later(self, *args, **kwds):
41 """ Call the message handlers later.
41 """ Call the message handlers later.
42 """
42 """
43 do_later = lambda: self.call_handlers(*args, **kwds)
43 do_later = lambda: self.call_handlers(*args, **kwds)
44 QtCore.QTimer.singleShot(0, do_later)
44 QtCore.QTimer.singleShot(0, do_later)
45
45
46 def process_events(self):
46 def process_events(self):
47 """ Process any pending GUI events.
47 """ Process any pending GUI events.
48 """
48 """
49 QtCore.QCoreApplication.instance().processEvents()
49 QtCore.QCoreApplication.instance().processEvents()
50
50
51
51
52 class QtShellChannelMixin(ChannelQObject):
52 class QtShellChannelMixin(ChannelQObject):
53
53
54 # Emitted when any message is received.
54 # Emitted when any message is received.
55 message_received = QtCore.Signal(object)
55 message_received = QtCore.Signal(object)
56
56
57 # Emitted when a reply has been received for the corresponding request
57 # Emitted when a reply has been received for the corresponding request
58 # type.
58 # type.
59 execute_reply = QtCore.Signal(object)
59 execute_reply = QtCore.Signal(object)
60 complete_reply = QtCore.Signal(object)
60 complete_reply = QtCore.Signal(object)
61 object_info_reply = QtCore.Signal(object)
61 object_info_reply = QtCore.Signal(object)
62 history_reply = QtCore.Signal(object)
62 history_reply = QtCore.Signal(object)
63
63
64 # Emitted when the first reply comes back.
64 # Emitted when the first reply comes back.
65 first_reply = QtCore.Signal()
65 first_reply = QtCore.Signal()
66
66
67 # Used by the first_reply signal logic to determine if a reply is the
67 # Used by the first_reply signal logic to determine if a reply is the
68 # first.
68 # first.
69 _handlers_called = False
69 _handlers_called = False
70
70
71 #---------------------------------------------------------------------------
71 #---------------------------------------------------------------------------
72 # 'ShellSocketChannel' interface
72 # 'ShellSocketChannel' interface
73 #---------------------------------------------------------------------------
73 #---------------------------------------------------------------------------
74
74
75 def call_handlers(self, msg):
75 def call_handlers(self, msg):
76 """ Reimplemented to emit signals instead of making callbacks.
76 """ Reimplemented to emit signals instead of making callbacks.
77 """
77 """
78 # Emit the generic signal.
78 # Emit the generic signal.
79 self.message_received.emit(msg)
79 self.message_received.emit(msg)
80
80
81 # Emit signals for specialized message types.
81 # Emit signals for specialized message types.
82 msg_type = msg['header']['msg_type']
82 msg_type = msg['header']['msg_type']
83 signal = getattr(self, msg_type, None)
83 signal = getattr(self, msg_type, None)
84 if signal:
84 if signal:
85 signal.emit(msg)
85 signal.emit(msg)
86
86
87 if not self._handlers_called:
87 if not self._handlers_called:
88 self.first_reply.emit()
88 self.first_reply.emit()
89 self._handlers_called = True
89 self._handlers_called = True
90
90
91 #---------------------------------------------------------------------------
91 #---------------------------------------------------------------------------
92 # 'QtShellChannelMixin' interface
92 # 'QtShellChannelMixin' interface
93 #---------------------------------------------------------------------------
93 #---------------------------------------------------------------------------
94
94
95 def reset_first_reply(self):
95 def reset_first_reply(self):
96 """ Reset the first_reply signal to fire again on the next reply.
96 """ Reset the first_reply signal to fire again on the next reply.
97 """
97 """
98 self._handlers_called = False
98 self._handlers_called = False
99
99
100
100
101 class QtSubChannelMixin(ChannelQObject):
101 class QtSubChannelMixin(ChannelQObject):
102
102
103 # Emitted when any message is received.
103 # Emitted when any message is received.
104 message_received = QtCore.Signal(object)
104 message_received = QtCore.Signal(object)
105
105
106 # Emitted when a message of type 'stream' is received.
106 # Emitted when a message of type 'stream' is received.
107 stream_received = QtCore.Signal(object)
107 stream_received = QtCore.Signal(object)
108
108
109 # Emitted when a message of type 'pyin' is received.
109 # Emitted when a message of type 'pyin' is received.
110 pyin_received = QtCore.Signal(object)
110 pyin_received = QtCore.Signal(object)
111
111
112 # Emitted when a message of type 'pyout' is received.
112 # Emitted when a message of type 'pyout' is received.
113 pyout_received = QtCore.Signal(object)
113 pyout_received = QtCore.Signal(object)
114
114
115 # Emitted when a message of type 'pyerr' is received.
115 # Emitted when a message of type 'pyerr' is received.
116 pyerr_received = QtCore.Signal(object)
116 pyerr_received = QtCore.Signal(object)
117
117
118 # Emitted when a message of type 'display_data' is received
118 # Emitted when a message of type 'display_data' is received
119 display_data_received = QtCore.Signal(object)
119 display_data_received = QtCore.Signal(object)
120
120
121 # Emitted when a crash report message is received from the kernel's
121 # Emitted when a crash report message is received from the kernel's
122 # last-resort sys.excepthook.
122 # last-resort sys.excepthook.
123 crash_received = QtCore.Signal(object)
123 crash_received = QtCore.Signal(object)
124
124
125 # Emitted when a shutdown is noticed.
125 # Emitted when a shutdown is noticed.
126 shutdown_reply_received = QtCore.Signal(object)
126 shutdown_reply_received = QtCore.Signal(object)
127
127
128 #---------------------------------------------------------------------------
128 #---------------------------------------------------------------------------
129 # 'SubSocketChannel' interface
129 # 'SubSocketChannel' interface
130 #---------------------------------------------------------------------------
130 #---------------------------------------------------------------------------
131
131
132 def call_handlers(self, msg):
132 def call_handlers(self, msg):
133 """ Reimplemented to emit signals instead of making callbacks.
133 """ Reimplemented to emit signals instead of making callbacks.
134 """
134 """
135 # Emit the generic signal.
135 # Emit the generic signal.
136 self.message_received.emit(msg)
136 self.message_received.emit(msg)
137 # Emit signals for specialized message types.
137 # Emit signals for specialized message types.
138 msg_type = msg['header']['msg_type']
138 msg_type = msg['header']['msg_type']
139 signal = getattr(self, msg_type + '_received', None)
139 signal = getattr(self, msg_type + '_received', None)
140 if signal:
140 if signal:
141 signal.emit(msg)
141 signal.emit(msg)
142 elif msg_type in ('stdout', 'stderr'):
142 elif msg_type in ('stdout', 'stderr'):
143 self.stream_received.emit(msg)
143 self.stream_received.emit(msg)
144
144
145 def flush(self):
145 def flush(self):
146 """ Reimplemented to ensure that signals are dispatched immediately.
146 """ Reimplemented to ensure that signals are dispatched immediately.
147 """
147 """
148 super(QtSubChannelMixin, self).flush()
148 super(QtSubChannelMixin, self).flush()
149 QtCore.QCoreApplication.instance().processEvents()
149 QtCore.QCoreApplication.instance().processEvents()
150
150
151
151
152 class QtStdInChannelMixin(ChannelQObject):
152 class QtStdInChannelMixin(ChannelQObject):
153
153
154 # Emitted when any message is received.
154 # Emitted when any message is received.
155 message_received = QtCore.Signal(object)
155 message_received = QtCore.Signal(object)
156
156
157 # Emitted when an input request is received.
157 # Emitted when an input request is received.
158 input_requested = QtCore.Signal(object)
158 input_requested = QtCore.Signal(object)
159
159
160 #---------------------------------------------------------------------------
160 #---------------------------------------------------------------------------
161 # 'StdInSocketChannel' interface
161 # 'StdInSocketChannel' interface
162 #---------------------------------------------------------------------------
162 #---------------------------------------------------------------------------
163
163
164 def call_handlers(self, msg):
164 def call_handlers(self, msg):
165 """ Reimplemented to emit signals instead of making callbacks.
165 """ Reimplemented to emit signals instead of making callbacks.
166 """
166 """
167 # Emit the generic signal.
167 # Emit the generic signal.
168 self.message_received.emit(msg)
168 self.message_received.emit(msg)
169
169
170 # Emit signals for specialized message types.
170 # Emit signals for specialized message types.
171 msg_type = msg['header']['msg_type']
171 msg_type = msg['header']['msg_type']
172 if msg_type == 'input_request':
172 if msg_type == 'input_request':
173 self.input_requested.emit(msg)
173 self.input_requested.emit(msg)
174
174
175
175
176 class QtHBChannelMixin(ChannelQObject):
176 class QtHBChannelMixin(ChannelQObject):
177
177
178 # Emitted when the kernel has died.
178 # Emitted when the kernel has died.
179 kernel_died = QtCore.Signal(object)
179 kernel_died = QtCore.Signal(object)
180
180
181 #---------------------------------------------------------------------------
181 #---------------------------------------------------------------------------
182 # 'HBSocketChannel' interface
182 # 'HBSocketChannel' interface
183 #---------------------------------------------------------------------------
183 #---------------------------------------------------------------------------
184
184
185 def call_handlers(self, since_last_heartbeat):
185 def call_handlers(self, since_last_heartbeat):
186 """ Reimplemented to emit signals instead of making callbacks.
186 """ Reimplemented to emit signals instead of making callbacks.
187 """
187 """
188 # Emit the generic signal.
188 # Emit the generic signal.
189 self.kernel_died.emit(since_last_heartbeat)
189 self.kernel_died.emit(since_last_heartbeat)
190
190
191
191
192 class QtKernelManagerMixin(object):
192 class QtKernelManagerMixin(HasTraits, SuperQObject):
193 """ A KernelManager that provides signals and slots.
193 """ A KernelManager that provides signals and slots.
194 """
194 """
195
195
196 __metaclass__ = MetaQObjectHasTraits
197
196 # Emitted when the kernel manager has started listening.
198 # Emitted when the kernel manager has started listening.
197 started_kernel = QtCore.Signal()
199 started_kernel = QtCore.Signal()
198
200
199 # Emitted when the kernel manager has started listening.
201 # Emitted when the kernel manager has started listening.
200 started_channels = QtCore.Signal()
202 started_channels = QtCore.Signal()
201
203
202 # Emitted when the kernel manager has stopped listening.
204 # Emitted when the kernel manager has stopped listening.
203 stopped_channels = QtCore.Signal()
205 stopped_channels = QtCore.Signal()
204
206
205 # Use Qt-specific channel classes that emit signals.
207 # Use Qt-specific channel classes that emit signals.
206 sub_channel_class = Type(QtSubChannelMixin)
208 sub_channel_class = Type(QtSubChannelMixin)
207 shell_channel_class = Type(QtShellChannelMixin)
209 shell_channel_class = Type(QtShellChannelMixin)
208 stdin_channel_class = Type(QtStdInChannelMixin)
210 stdin_channel_class = Type(QtStdInChannelMixin)
209 hb_channel_class = Type(QtHBChannelMixin)
211 hb_channel_class = Type(QtHBChannelMixin)
210
212
211 #---------------------------------------------------------------------------
213 #---------------------------------------------------------------------------
212 # 'KernelManager' interface
214 # 'KernelManager' interface
213 #---------------------------------------------------------------------------
215 #---------------------------------------------------------------------------
214
216
215 #------ Kernel process management ------------------------------------------
217 #------ Kernel process management ------------------------------------------
216
218
217 def start_kernel(self, *args, **kw):
219 def start_kernel(self, *args, **kw):
218 """ Reimplemented for proper heartbeat management.
220 """ Reimplemented for proper heartbeat management.
219 """
221 """
220 if self._shell_channel is not None:
222 if self._shell_channel is not None:
221 self._shell_channel.reset_first_reply()
223 self._shell_channel.reset_first_reply()
222 super(QtKernelManagerMixin, self).start_kernel(*args, **kw)
224 super(QtKernelManagerMixin, self).start_kernel(*args, **kw)
223 self.started_kernel.emit()
225 self.started_kernel.emit()
224
226
225 #------ Channel management -------------------------------------------------
227 #------ Channel management -------------------------------------------------
226
228
227 def start_channels(self, *args, **kw):
229 def start_channels(self, *args, **kw):
228 """ Reimplemented to emit signal.
230 """ Reimplemented to emit signal.
229 """
231 """
230 super(QtKernelManagerMixin, self).start_channels(*args, **kw)
232 super(QtKernelManagerMixin, self).start_channels(*args, **kw)
231 self.started_channels.emit()
233 self.started_channels.emit()
232
234
233 def stop_channels(self):
235 def stop_channels(self):
234 """ Reimplemented to emit signal.
236 """ Reimplemented to emit signal.
235 """
237 """
236 super(QtKernelManagerMixin, self).stop_channels()
238 super(QtKernelManagerMixin, self).stop_channels()
237 self.stopped_channels.emit()
239 self.stopped_channels.emit()
238
240
239 @property
241 @property
240 def shell_channel(self):
242 def shell_channel(self):
241 """ Reimplemented for proper heartbeat management.
243 """ Reimplemented for proper heartbeat management.
242 """
244 """
243 if self._shell_channel is None:
245 if self._shell_channel is None:
244 self._shell_channel = super(QtKernelManagerMixin,self).shell_channel
246 self._shell_channel = super(QtKernelManagerMixin,self).shell_channel
245 self._shell_channel.first_reply.connect(self._first_reply)
247 self._shell_channel.first_reply.connect(self._first_reply)
246 return self._shell_channel
248 return self._shell_channel
247
249
248 #---------------------------------------------------------------------------
250 #---------------------------------------------------------------------------
249 # Protected interface
251 # Protected interface
250 #---------------------------------------------------------------------------
252 #---------------------------------------------------------------------------
251
253
252 def _first_reply(self):
254 def _first_reply(self):
253 """ Unpauses the heartbeat channel when the first reply is received on
255 """ Unpauses the heartbeat channel when the first reply is received on
254 the execute channel. Note that this will *not* start the heartbeat
256 the execute channel. Note that this will *not* start the heartbeat
255 channel if it is not already running!
257 channel if it is not already running!
256 """
258 """
257 if self._hb_channel is not None:
259 if self._hb_channel is not None:
258 self._hb_channel.unpause()
260 self._hb_channel.unpause()
@@ -1,37 +1,33 b''
1 """ Defines an embedded KernelManager that provides signals and slots.
1 """ Defines an embedded KernelManager that provides signals and slots.
2 """
2 """
3
3
4 # Local imports.
4 # Local imports.
5 from IPython.embedded.kernelmanager import \
5 from IPython.embedded.kernelmanager import \
6 ShellEmbeddedChannel, SubEmbeddedChannel, StdInEmbeddedChannel, \
6 ShellEmbeddedChannel, SubEmbeddedChannel, StdInEmbeddedChannel, \
7 HBEmbeddedChannel, EmbeddedKernelManager
7 HBEmbeddedChannel, EmbeddedKernelManager
8 from IPython.utils.traitlets import Type
8 from IPython.utils.traitlets import Type
9 from base_kernelmanager import QtShellChannelMixin, QtSubChannelMixin, \
9 from base_kernelmanager import QtShellChannelMixin, QtSubChannelMixin, \
10 QtStdInChannelMixin, QtHBChannelMixin, QtKernelManagerMixin
10 QtStdInChannelMixin, QtHBChannelMixin, QtKernelManagerMixin
11 from util import MetaQObjectHasTraits, SuperQObject
12
11
13
12
14 class QtShellEmbeddedChannel(QtShellChannelMixin, ShellEmbeddedChannel):
13 class QtShellEmbeddedChannel(QtShellChannelMixin, ShellEmbeddedChannel):
15 pass
14 pass
16
15
17 class QtSubEmbeddedChannel(QtSubChannelMixin, SubEmbeddedChannel):
16 class QtSubEmbeddedChannel(QtSubChannelMixin, SubEmbeddedChannel):
18 pass
17 pass
19
18
20 class QtStdInEmbeddedChannel(QtStdInChannelMixin, StdInEmbeddedChannel):
19 class QtStdInEmbeddedChannel(QtStdInChannelMixin, StdInEmbeddedChannel):
21 pass
20 pass
22
21
23 class QtHBEmbeddedChannel(QtHBChannelMixin, HBEmbeddedChannel):
22 class QtHBEmbeddedChannel(QtHBChannelMixin, HBEmbeddedChannel):
24 pass
23 pass
25
24
26
25
27 class QtEmbeddedKernelManager(QtKernelManagerMixin,
26 class QtEmbeddedKernelManager(QtKernelManagerMixin, EmbeddedKernelManager):
28 EmbeddedKernelManager, SuperQObject):
29 """ An embedded KernelManager that provides signals and slots.
27 """ An embedded KernelManager that provides signals and slots.
30 """
28 """
31
29
32 __metaclass__ = MetaQObjectHasTraits
33
34 sub_channel_class = Type(QtSubEmbeddedChannel)
30 sub_channel_class = Type(QtSubEmbeddedChannel)
35 shell_channel_class = Type(QtShellEmbeddedChannel)
31 shell_channel_class = Type(QtShellEmbeddedChannel)
36 stdin_channel_class = Type(QtStdInEmbeddedChannel)
32 stdin_channel_class = Type(QtStdInEmbeddedChannel)
37 hb_channel_class = Type(QtHBEmbeddedChannel)
33 hb_channel_class = Type(QtHBEmbeddedChannel)
@@ -1,35 +1,32 b''
1 """ Defines a KernelManager that provides signals and slots.
1 """ Defines a KernelManager that provides signals and slots.
2 """
2 """
3
3
4 # Local imports.
4 # Local imports.
5 from IPython.utils.traitlets import Type
5 from IPython.utils.traitlets import Type
6 from IPython.zmq.kernelmanager import ShellSocketChannel, SubSocketChannel, \
6 from IPython.zmq.kernelmanager import ShellSocketChannel, SubSocketChannel, \
7 StdInSocketChannel, HBSocketChannel, KernelManager
7 StdInSocketChannel, HBSocketChannel, KernelManager
8 from base_kernelmanager import QtShellChannelMixin, QtSubChannelMixin, \
8 from base_kernelmanager import QtShellChannelMixin, QtSubChannelMixin, \
9 QtStdInChannelMixin, QtHBChannelMixin, QtKernelManagerMixin
9 QtStdInChannelMixin, QtHBChannelMixin, QtKernelManagerMixin
10 from util import MetaQObjectHasTraits, SuperQObject
11
10
12
11
13 class QtShellSocketChannel(QtShellChannelMixin, ShellSocketChannel):
12 class QtShellSocketChannel(QtShellChannelMixin, ShellSocketChannel):
14 pass
13 pass
15
14
16 class QtSubSocketChannel(QtSubChannelMixin, SubSocketChannel):
15 class QtSubSocketChannel(QtSubChannelMixin, SubSocketChannel):
17 pass
16 pass
18
17
19 class QtStdInSocketChannel(QtStdInChannelMixin, StdInSocketChannel):
18 class QtStdInSocketChannel(QtStdInChannelMixin, StdInSocketChannel):
20 pass
19 pass
21
20
22 class QtHBSocketChannel(QtHBChannelMixin, HBSocketChannel):
21 class QtHBSocketChannel(QtHBChannelMixin, HBSocketChannel):
23 pass
22 pass
24
23
25
24
26 class QtKernelManager(QtKernelManagerMixin, KernelManager, SuperQObject):
25 class QtKernelManager(QtKernelManagerMixin, KernelManager):
27 """ A KernelManager that provides signals and slots.
26 """ A KernelManager that provides signals and slots.
28 """
27 """
29
28
30 __metaclass__ = MetaQObjectHasTraits
31
32 sub_channel_class = Type(QtSubSocketChannel)
29 sub_channel_class = Type(QtSubSocketChannel)
33 shell_channel_class = Type(QtShellSocketChannel)
30 shell_channel_class = Type(QtShellSocketChannel)
34 stdin_channel_class = Type(QtStdInSocketChannel)
31 stdin_channel_class = Type(QtStdInSocketChannel)
35 hb_channel_class = Type(QtHBSocketChannel)
32 hb_channel_class = Type(QtHBSocketChannel)
@@ -1,106 +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.
4 # Standard library imports.
5 import inspect
5 import inspect
6
6
7 # System library imports.
7 # System library imports.
8 from IPython.external.qt import QtCore, QtGui
8 from IPython.external.qt import QtCore, QtGui
9
9
10 # IPython imports.
10 # IPython imports.
11 from IPython.utils.traitlets import HasTraits, TraitType
11 from IPython.utils.traitlets import HasTraits, TraitType
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Metaclasses
14 # Metaclasses
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 MetaHasTraits = type(HasTraits)
17 MetaHasTraits = type(HasTraits)
18 MetaQObject = type(QtCore.QObject)
18 MetaQObject = type(QtCore.QObject)
19
19
20 class MetaQObjectHasTraits(MetaQObject, MetaHasTraits):
20 class MetaQObjectHasTraits(MetaQObject, MetaHasTraits):
21 """ A metaclass that inherits from the metaclasses of HasTraits and QObject.
21 """ A metaclass that inherits from the metaclasses of HasTraits and QObject.
22
22
23 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
24 QObject. Using SuperQObject instead of QObject is highly recommended. See
24 QObject. Using SuperQObject instead of QObject is highly recommended. See
25 QtKernelManager for an example.
25 QtKernelManager for an example.
26 """
26 """
27 def __new__(mcls, name, bases, classdict):
27 def __new__(mcls, name, bases, classdict):
28 # FIXME: this duplicates the code from MetaHasTraits.
28 # FIXME: this duplicates the code from MetaHasTraits.
29 # I don't think a super() call will help me here.
29 # I don't think a super() call will help me here.
30 for k,v in classdict.iteritems():
30 for k,v in classdict.iteritems():
31 if isinstance(v, TraitType):
31 if isinstance(v, TraitType):
32 v.name = k
32 v.name = k
33 elif inspect.isclass(v):
33 elif inspect.isclass(v):
34 if issubclass(v, TraitType):
34 if issubclass(v, TraitType):
35 vinst = v()
35 vinst = v()
36 vinst.name = k
36 vinst.name = k
37 classdict[k] = vinst
37 classdict[k] = vinst
38 cls = MetaQObject.__new__(mcls, name, bases, classdict)
38 cls = MetaQObject.__new__(mcls, name, bases, classdict)
39 return cls
39 return cls
40
40
41 def __init__(mcls, name, bases, classdict):
41 def __init__(mcls, name, bases, classdict):
42 # Note: super() did not work, so we explicitly call these.
42 # Note: super() did not work, so we explicitly call these.
43 MetaQObject.__init__(mcls, name, bases, classdict)
43 MetaQObject.__init__(mcls, name, bases, classdict)
44 MetaHasTraits.__init__(mcls, name, bases, classdict)
44 MetaHasTraits.__init__(mcls, name, bases, classdict)
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Classes
47 # Classes
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 class SuperQObject(QtCore.QObject):
50 class SuperQObject(QtCore.QObject):
51 """ Permits the use of super() in class hierarchies that contain QObject.
51 """ Permits the use of super() in class hierarchies that contain QObject.
52
52
53 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,
54 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
55 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
56 they don't inherit QObject.)
56 they don't inherit QObject.)
57
57
58 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
59 classes. See QtKernelManager for an example.
59 classes. See QtKernelManagerMixin for an example.
60 """
60 """
61
61
62 def __new__(cls, *args, **kw):
62 def __new__(cls, *args, **kw):
63 # We initialize QObject as early as possible. Without this, Qt complains
63 # We initialize QObject as early as possible. Without this, Qt complains
64 # 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.
65 inst = QtCore.QObject.__new__(cls)
65 inst = QtCore.QObject.__new__(cls)
66 QtCore.QObject.__init__(inst)
66 QtCore.QObject.__init__(inst)
67 return inst
67 return inst
68
68
69 def __init__(self, *args, **kw):
69 def __init__(self, *args, **kw):
70 # 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.
71 mro = self.__class__.mro()
71 mro = self.__class__.mro()
72 for qt_class in QtCore.QObject.mro():
72 for qt_class in QtCore.QObject.mro():
73 mro.remove(qt_class)
73 mro.remove(qt_class)
74 next_index = mro.index(SuperQObject) + 1
74 next_index = mro.index(SuperQObject) + 1
75 if next_index < len(mro):
75 if next_index < len(mro):
76 mro[next_index].__init__(self, *args, **kw)
76 mro[next_index].__init__(self, *args, **kw)
77
77
78 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
79 # Functions
79 # Functions
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81
81
82 def get_font(family, fallback=None):
82 def get_font(family, fallback=None):
83 """Return a font of the requested family, using fallback as alternative.
83 """Return a font of the requested family, using fallback as alternative.
84
84
85 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
86 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
87 algorithms may automatically choose a fallback font.
87 algorithms may automatically choose a fallback font.
88
88
89 Parameters
89 Parameters
90 ----------
90 ----------
91 family : str
91 family : str
92 A font name.
92 A font name.
93 fallback : str
93 fallback : str
94 A font name.
94 A font name.
95
95
96 Returns
96 Returns
97 -------
97 -------
98 font : QFont object
98 font : QFont object
99 """
99 """
100 font = QtGui.QFont(family)
100 font = QtGui.QFont(family)
101 # Check whether we got what we wanted using QFontInfo, since exactMatch()
101 # Check whether we got what we wanted using QFontInfo, since exactMatch()
102 # is overly strict and returns false in too many cases.
102 # is overly strict and returns false in too many cases.
103 font_info = QtGui.QFontInfo(font)
103 font_info = QtGui.QFontInfo(font)
104 if fallback is not None and font_info.family() != family:
104 if fallback is not None and font_info.family() != family:
105 font = QtGui.QFont(fallback)
105 font = QtGui.QFont(fallback)
106 return font
106 return font
General Comments 0
You need to be logged in to leave comments. Login now