##// END OF EJS Templates
Updating terminal GUI support to use guisupport.py for qt4/wx.
Brian Granger -
Show More
@@ -45,17 +45,6 b' from .core.error import TryNext'
45 from .core.interactiveshell import InteractiveShell
45 from .core.interactiveshell import InteractiveShell
46 from .testing import test
46 from .testing import test
47
47
48 from .lib import (
49 enable_wx, disable_wx,
50 enable_gtk, disable_gtk,
51 enable_qt4, disable_qt4,
52 enable_tk, disable_tk,
53 set_inputhook, clear_inputhook,
54 current_gui, spin,
55 appstart_qt4, appstart_wx,
56 appstart_gtk, appstart_tk
57 )
58
59 # Release data
48 # Release data
60 __author__ = ''
49 __author__ = ''
61 for author, email in release.authors.values():
50 for author, email in release.authors.values():
@@ -55,7 +55,6 b' from IPython.core.macro import Macro'
55 from IPython.core import page
55 from IPython.core import page
56 from IPython.core.prefilter import ESC_MAGIC
56 from IPython.core.prefilter import ESC_MAGIC
57 from IPython.lib.pylabtools import mpl_runner
57 from IPython.lib.pylabtools import mpl_runner
58 from IPython.lib.inputhook import enable_gui
59 from IPython.external.Itpl import itpl, printpl
58 from IPython.external.Itpl import itpl, printpl
60 from IPython.testing import decorators as testdec
59 from IPython.testing import decorators as testdec
61 from IPython.utils.io import file_read, nlprint
60 from IPython.utils.io import file_read, nlprint
@@ -3475,7 +3474,7 b' Defaulting color scheme to \'NoColor\'"""'
3475 def magic_gui(self, parameter_s=''):
3474 def magic_gui(self, parameter_s=''):
3476 """Enable or disable IPython GUI event loop integration.
3475 """Enable or disable IPython GUI event loop integration.
3477
3476
3478 %gui [-a] [GUINAME]
3477 %gui [GUINAME]
3479
3478
3480 This magic replaces IPython's threaded shells that were activated
3479 This magic replaces IPython's threaded shells that were activated
3481 using the (pylab/wthread/etc.) command line flags. GUI toolkits
3480 using the (pylab/wthread/etc.) command line flags. GUI toolkits
@@ -3492,17 +3491,11 b' Defaulting color scheme to \'NoColor\'"""'
3492 WARNING: after any of these has been called you can simply create
3491 WARNING: after any of these has been called you can simply create
3493 an application object, but DO NOT start the event loop yourself, as
3492 an application object, but DO NOT start the event loop yourself, as
3494 we have already handled that.
3493 we have already handled that.
3495
3496 If you want us to create an appropriate application object add the
3497 "-a" flag to your command::
3498
3499 %gui -a wx
3500
3501 This is highly recommended for most users.
3502 """
3494 """
3503 opts, arg = self.parse_options(parameter_s,'a')
3495 from IPython.lib.inputhook import enable_gui
3496 opts, arg = self.parse_options(parameter_s='')
3504 if arg=='': arg = None
3497 if arg=='': arg = None
3505 return enable_gui(arg, 'a' in opts)
3498 return enable_gui(arg)
3506
3499
3507 def magic_load_ext(self, module_str):
3500 def magic_load_ext(self, module_str):
3508 """Load an IPython extension by its module name."""
3501 """Load an IPython extension by its module name."""
@@ -21,11 +21,9 b' from IPython.lib.inputhook import ('
21 enable_qt4, disable_qt4,
21 enable_qt4, disable_qt4,
22 enable_tk, disable_tk,
22 enable_tk, disable_tk,
23 set_inputhook, clear_inputhook,
23 set_inputhook, clear_inputhook,
24 current_gui, spin,
24 current_gui
25 appstart_qt4, appstart_wx,
26 appstart_gtk, appstart_tk
27 )
25 )
28
26
29 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
30 # Code
28 # Code
31 #----------------------------------------------------------------------------- No newline at end of file
29 #-----------------------------------------------------------------------------
@@ -34,137 +34,6 b" GUI_TK = 'tk'"
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36
36
37 class _DummyMainloop(object):
38 """A special manager to hijack GUI mainloops that is mostly a no-op.
39
40 We are not using this class currently as it breaks GUI code that calls
41 a mainloop function after the app has started to process pending events.
42 """
43 def __init__(self, ml, ihm, gui_type):
44 self.ml = ml
45 self.ihm = ihm
46 self.gui_type = gui_type
47
48 def __call__(self, *args, **kw):
49 if self.ihm.current_gui() == self.gui_type:
50 pass
51 else:
52 self.ml(*args, **kw)
53
54
55 #-----------------------------------------------------------------------------
56 # Appstart and spin functions
57 #-----------------------------------------------------------------------------
58
59
60 def appstart_qt4(app):
61 """Start the qt4 event loop in a way that plays with IPython.
62
63 When a qt4 app is run interactively in IPython, the event loop should
64 not be started. This function checks to see if IPython's qt4 integration
65 is activated and if so, it passes. If not, it will call the :meth:`exec_`
66 method of the main qt4 app.
67
68 This function should be used by users who want their qt4 scripts to work
69 both at the command line and in IPython. These users should put the
70 following logic at the bottom on their script, after they create a
71 :class:`QApplication` instance (called ``app`` here)::
72
73 try:
74 from IPython.lib.inputhook import appstart_qt4
75 appstart_qt4(app)
76 except ImportError:
77 app.exec_()
78 """
79 from PyQt4 import QtCore
80
81 assert isinstance(app, QtCore.QCoreApplication)
82 if app is not None:
83 if current_gui() == GUI_QT4:
84 pass
85 else:
86 app.exec_()
87
88
89 def appstart_wx(app):
90 """Start the wx event loop in a way that plays with IPython.
91
92 When a wx app is run interactively in IPython, the event loop should
93 not be started. This function checks to see if IPython's wx integration
94 is activated and if so, it passes. If not, it will call the
95 :meth:`MainLoop` method of the main qt4 app.
96
97 This function should be used by users who want their wx scripts to work
98 both at the command line and in IPython. These users should put the
99 following logic at the bottom on their script, after they create a
100 :class:`App` instance (called ``app`` here)::
101
102 try:
103 from IPython.lib.inputhook import appstart_wx
104 appstart_wx(app)
105 except ImportError:
106 app.MainLoop()
107 """
108 import wx
109
110 assert isinstance(app, wx.App)
111 if app is not None:
112 if current_gui() == GUI_WX:
113 pass
114 else:
115 app.MainLoop()
116
117
118 def appstart_tk(app):
119 """Start the tk event loop in a way that plays with IPython.
120
121 When a tk app is run interactively in IPython, the event loop should
122 not be started. This function checks to see if IPython's tk integration
123 is activated and if so, it passes. If not, it will call the
124 :meth:`mainloop` method of the tk object passed to this method.
125
126 This function should be used by users who want their tk scripts to work
127 both at the command line and in IPython. These users should put the
128 following logic at the bottom on their script, after they create a
129 :class:`Tk` instance (called ``app`` here)::
130
131 try:
132 from IPython.lib.inputhook import appstart_tk
133 appstart_tk(app)
134 except ImportError:
135 app.mainloop()
136 """
137 if app is not None:
138 if current_gui() == GUI_TK:
139 pass
140 else:
141 app.mainloop()
142
143 def appstart_gtk():
144 """Start the gtk event loop in a way that plays with IPython.
145
146 When a gtk app is run interactively in IPython, the event loop should
147 not be started. This function checks to see if IPython's gtk integration
148 is activated and if so, it passes. If not, it will call
149 :func:`gtk.main`. Unlike the other appstart implementations, this does
150 not take an ``app`` argument.
151
152 This function should be used by users who want their gtk scripts to work
153 both at the command line and in IPython. These users should put the
154 following logic at the bottom on their script::
155
156 try:
157 from IPython.lib.inputhook import appstart_gtk
158 appstart_gtk()
159 except ImportError:
160 gtk.main()
161 """
162 import gtk
163 if current_gui() == GUI_GTK:
164 pass
165 else:
166 gtk.main()
167
168 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
169 # Main InputHookManager class
38 # Main InputHookManager class
170 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
@@ -180,11 +49,6 b' class InputHookManager(object):'
180 def __init__(self):
49 def __init__(self):
181 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
50 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
182 self._apps = {}
51 self._apps = {}
183 self._spinner_dict = {
184 GUI_QT4 : self._spin_qt4,
185 GUI_WX : self._spin_wx,
186 GUI_GTK : self._spin_gtk,
187 GUI_TK : self._spin_tk}
188 self._reset()
52 self._reset()
189
53
190 def _reset(self):
54 def _reset(self):
@@ -193,122 +57,6 b' class InputHookManager(object):'
193 self._installed = False
57 self._installed = False
194 self._current_gui = None
58 self._current_gui = None
195
59
196 def _hijack_wx(self):
197 """Hijack the wx mainloop so a user calling it won't cause badness.
198
199 We are not currently using this as it breaks GUI code that calls a
200 mainloop at anytime but startup.
201 """
202 import wx
203 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
204 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
205 else: raise AttributeError('Could not find wx core module')
206 orig_mainloop = core.PyApp_MainLoop
207 core.PyApp_MainLoop = _DummyMainloop
208 return orig_mainloop
209
210 def _hijack_qt4(self):
211 """Hijack the qt4 mainloop so a user calling it won't cause badness.
212
213 We are not currently using this as it breaks GUI code that calls a
214 mainloop at anytime but startup.
215 """
216 from PyQt4 import QtGui, QtCore
217 orig_mainloop = QtGui.qApp.exec_
218 dumb_ml = _DummyMainloop(orig_mainloop, self, GUI_QT4)
219 QtGui.qApp.exec_ = dumb_ml
220 QtGui.QApplication.exec_ = dumb_ml
221 QtCore.QCoreApplication.exec_ = dumb_ml
222 return orig_mainloop
223
224 def _hijack_gtk(self):
225 """Hijack the gtk mainloop so a user calling it won't cause badness.
226
227 We are not currently using this as it breaks GUI code that calls a
228 mainloop at anytime but startup.
229 """
230 import gtk
231 orig_mainloop = gtk.main
232 dumb_ml = _DummyMainloop(orig_mainloop, self, GUI_GTK)
233 gtk.mainloop = dumb_ml
234 gtk.main = dumb_ml
235 return orig_mainloop
236
237 def _hijack_tk(self):
238 """Hijack the tk mainloop so a user calling it won't cause badness.
239
240 We are not currently using this as it breaks GUI code that calls a
241 mainloop at anytime but startup.
242 """
243 import Tkinter
244 # FIXME: gtk is not imported here and we shouldn't be using gtk.main!
245 orig_mainloop = gtk.main
246 dumb_ml = _DummyMainloop(orig_mainloop, self, GUI_TK)
247 Tkinter.Misc.mainloop = dumb_ml
248 Tkinter.mainloop = dumb_ml
249
250 def _spin_qt4(self):
251 """Process all pending events in the qt4 event loop.
252
253 This is for internal IPython use only and user code should not call this.
254 Instead, they should issue the raw GUI calls themselves.
255 """
256 from PyQt4 import QtCore
257
258 app = QtCore.QCoreApplication.instance()
259 if app is not None:
260 QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents)
261
262 def _spin_wx(self):
263 """Process all pending events in the wx event loop.
264
265 This is for internal IPython use only and user code should not call this.
266 Instead, they should issue the raw GUI calls themselves.
267 """
268 import wx
269 app = wx.GetApp()
270 if app is not None and wx.Thread_IsMain():
271 evtloop = wx.EventLoop()
272 ea = wx.EventLoopActivator(evtloop)
273 while evtloop.Pending():
274 evtloop.Dispatch()
275 app.ProcessIdle()
276 del ea
277
278 def _spin_gtk(self):
279 """Process all pending events in the gtk event loop.
280
281 This is for internal IPython use only and user code should not call this.
282 Instead, they should issue the raw GUI calls themselves.
283 """
284 import gtk
285 gtk.gdk.threads_enter()
286 while gtk.events_pending():
287 gtk.main_iteration(False)
288 gtk.gdk.flush()
289 gtk.gdk.threads_leave()
290
291 def _spin_tk(self):
292 """Process all pending events in the tk event loop.
293
294 This is for internal IPython use only and user code should not call this.
295 Instead, they should issue the raw GUI calls themselves.
296 """
297 app = self._apps.get(GUI_TK)
298 if app is not None:
299 app.update()
300
301 def spin(self):
302 """Process pending events in the current gui.
303
304 This method is just provided for IPython to use internally if needed
305 for things like testing. Third party projects should not call this
306 method, but instead should call the underlying GUI toolkit methods
307 that we are calling.
308 """
309 spinner = self._spinner_dict.get(self._current_gui, lambda: None)
310 spinner()
311
312 def get_pyos_inputhook(self):
60 def get_pyos_inputhook(self):
313 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
61 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
314 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
62 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
@@ -365,7 +113,7 b' class InputHookManager(object):'
365 elif self._apps.has_key(gui):
113 elif self._apps.has_key(gui):
366 del self._apps[gui]
114 del self._apps[gui]
367
115
368 def enable_wx(self, app=False):
116 def enable_wx(self):
369 """Enable event loop integration with wxPython.
117 """Enable event loop integration with wxPython.
370
118
371 Parameters
119 Parameters
@@ -393,22 +141,24 b' class InputHookManager(object):'
393 from IPython.lib.inputhookwx import inputhook_wx
141 from IPython.lib.inputhookwx import inputhook_wx
394 self.set_inputhook(inputhook_wx)
142 self.set_inputhook(inputhook_wx)
395 self._current_gui = GUI_WX
143 self._current_gui = GUI_WX
396 if app:
144 import wx
397 import wx
145 app = wx.GetApp()
398 app = wx.GetApp()
146 if app is None:
399 if app is None:
147 app = wx.App(redirect=False, clearSigInt=False)
400 app = wx.App(redirect=False, clearSigInt=False)
148 app._in_event_loop = True
401 self._apps[GUI_WX] = app
149 self._apps[GUI_WX] = app
402 return app
150 return app
403
151
404 def disable_wx(self):
152 def disable_wx(self):
405 """Disable event loop integration with wxPython.
153 """Disable event loop integration with wxPython.
406
154
407 This merely sets PyOS_InputHook to NULL.
155 This merely sets PyOS_InputHook to NULL.
408 """
156 """
157 if self._apps.has_key(GUI_WX):
158 self._apps[GUI_WX]._in_event_loop = False
409 self.clear_inputhook()
159 self.clear_inputhook()
410
160
411 def enable_qt4(self, app=False):
161 def enable_qt4(self):
412 """Enable event loop integration with PyQt4.
162 """Enable event loop integration with PyQt4.
413
163
414 Parameters
164 Parameters
@@ -440,19 +190,21 b' class InputHookManager(object):'
440 except AttributeError:
190 except AttributeError:
441 pass
191 pass
442 self._current_gui = GUI_QT4
192 self._current_gui = GUI_QT4
443 if app:
193 from PyQt4 import QtGui
444 from PyQt4 import QtGui
194 app = QtCore.QCoreApplication.instance()
445 app = QtCore.QCoreApplication.instance()
195 if app is None:
446 if app is None:
196 app = QtGui.QApplication([" "])
447 app = QtGui.QApplication(sys.argv)
197 app._in_event_loop = True
448 self._apps[GUI_QT4] = app
198 self._apps[GUI_QT4] = app
449 return app
199 return app
450
200
451 def disable_qt4(self):
201 def disable_qt4(self):
452 """Disable event loop integration with PyQt4.
202 """Disable event loop integration with PyQt4.
453
203
454 This merely sets PyOS_InputHook to NULL.
204 This merely sets PyOS_InputHook to NULL.
455 """
205 """
206 if self._apps.has_key(GUI_QT4):
207 self._apps[GUI_QT4]._in_event_loop = False
456 self.clear_inputhook()
208 self.clear_inputhook()
457
209
458 def enable_gtk(self, app=False):
210 def enable_gtk(self, app=False):
@@ -533,11 +285,10 b' clear_inputhook = inputhook_manager.clear_inputhook'
533 set_inputhook = inputhook_manager.set_inputhook
285 set_inputhook = inputhook_manager.set_inputhook
534 current_gui = inputhook_manager.current_gui
286 current_gui = inputhook_manager.current_gui
535 clear_app_refs = inputhook_manager.clear_app_refs
287 clear_app_refs = inputhook_manager.clear_app_refs
536 spin = inputhook_manager.spin
537
288
538
289
539 # Convenience function to switch amongst them
290 # Convenience function to switch amongst them
540 def enable_gui(gui=None, app=True):
291 def enable_gui(gui=None):
541 """Switch amongst GUI input hooks by name.
292 """Switch amongst GUI input hooks by name.
542
293
543 This is just a utility wrapper around the methods of the InputHookManager
294 This is just a utility wrapper around the methods of the InputHookManager
@@ -569,4 +320,5 b' def enable_gui(gui=None, app=True):'
569 except KeyError:
320 except KeyError:
570 e="Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
321 e="Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
571 raise ValueError(e)
322 raise ValueError(e)
572 return gui_hook(app)
323 return gui_hook()
324
@@ -3,7 +3,9 b''
3
3
4 Authors
4 Authors
5 -------
5 -------
6 Fernando Perez.
6
7 * Fernando Perez.
8 * Brian Granger
7 """
9 """
8
10
9 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
@@ -177,3 +179,4 b' def mpl_runner(safe_execfile):'
177 pylab.draw_if_interactive.called = False
179 pylab.draw_if_interactive.called = False
178
180
179 return mpl_execfile
181 return mpl_execfile
182
@@ -374,6 +374,11 b' class ZMQInteractiveShell(InteractiveShell):'
374 }
374 }
375 self.payload_manager.write_payload(payload)
375 self.payload_manager.write_payload(payload)
376
376
377 def magic_gui(self, *args, **kwargs):
378 raise NotImplementedError('GUI support must be enabled in command line options.')
379
380 def magic_pylab(self, *args, **kwargs):
381 raise NotImplementedError('pylab support must be enabled in commandl in options.')
377
382
378 def _showtraceback(self, etype, evalue, stb):
383 def _showtraceback(self, etype, evalue, stb):
379
384
General Comments 0
You need to be logged in to leave comments. Login now