##// 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 45 from .core.interactiveshell import InteractiveShell
46 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 48 # Release data
60 49 __author__ = ''
61 50 for author, email in release.authors.values():
@@ -55,7 +55,6 b' from IPython.core.macro import Macro'
55 55 from IPython.core import page
56 56 from IPython.core.prefilter import ESC_MAGIC
57 57 from IPython.lib.pylabtools import mpl_runner
58 from IPython.lib.inputhook import enable_gui
59 58 from IPython.external.Itpl import itpl, printpl
60 59 from IPython.testing import decorators as testdec
61 60 from IPython.utils.io import file_read, nlprint
@@ -3475,7 +3474,7 b' Defaulting color scheme to \'NoColor\'"""'
3475 3474 def magic_gui(self, parameter_s=''):
3476 3475 """Enable or disable IPython GUI event loop integration.
3477 3476
3478 %gui [-a] [GUINAME]
3477 %gui [GUINAME]
3479 3478
3480 3479 This magic replaces IPython's threaded shells that were activated
3481 3480 using the (pylab/wthread/etc.) command line flags. GUI toolkits
@@ -3492,17 +3491,11 b' Defaulting color scheme to \'NoColor\'"""'
3492 3491 WARNING: after any of these has been called you can simply create
3493 3492 an application object, but DO NOT start the event loop yourself, as
3494 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 3497 if arg=='': arg = None
3505 return enable_gui(arg, 'a' in opts)
3498 return enable_gui(arg)
3506 3499
3507 3500 def magic_load_ext(self, module_str):
3508 3501 """Load an IPython extension by its module name."""
@@ -21,11 +21,9 b' from IPython.lib.inputhook import ('
21 21 enable_qt4, disable_qt4,
22 22 enable_tk, disable_tk,
23 23 set_inputhook, clear_inputhook,
24 current_gui, spin,
25 appstart_qt4, appstart_wx,
26 appstart_gtk, appstart_tk
24 current_gui
27 25 )
28 26
29 27 #-----------------------------------------------------------------------------
30 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 38 # Main InputHookManager class
170 39 #-----------------------------------------------------------------------------
@@ -180,11 +49,6 b' class InputHookManager(object):'
180 49 def __init__(self):
181 50 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
182 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 52 self._reset()
189 53
190 54 def _reset(self):
@@ -193,122 +57,6 b' class InputHookManager(object):'
193 57 self._installed = False
194 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 60 def get_pyos_inputhook(self):
313 61 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
314 62 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
@@ -365,7 +113,7 b' class InputHookManager(object):'
365 113 elif self._apps.has_key(gui):
366 114 del self._apps[gui]
367 115
368 def enable_wx(self, app=False):
116 def enable_wx(self):
369 117 """Enable event loop integration with wxPython.
370 118
371 119 Parameters
@@ -393,22 +141,24 b' class InputHookManager(object):'
393 141 from IPython.lib.inputhookwx import inputhook_wx
394 142 self.set_inputhook(inputhook_wx)
395 143 self._current_gui = GUI_WX
396 if app:
397 import wx
398 app = wx.GetApp()
399 if app is None:
400 app = wx.App(redirect=False, clearSigInt=False)
401 self._apps[GUI_WX] = app
402 return app
144 import wx
145 app = wx.GetApp()
146 if app is None:
147 app = wx.App(redirect=False, clearSigInt=False)
148 app._in_event_loop = True
149 self._apps[GUI_WX] = app
150 return app
403 151
404 152 def disable_wx(self):
405 153 """Disable event loop integration with wxPython.
406 154
407 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 159 self.clear_inputhook()
410 160
411 def enable_qt4(self, app=False):
161 def enable_qt4(self):
412 162 """Enable event loop integration with PyQt4.
413 163
414 164 Parameters
@@ -440,19 +190,21 b' class InputHookManager(object):'
440 190 except AttributeError:
441 191 pass
442 192 self._current_gui = GUI_QT4
443 if app:
444 from PyQt4 import QtGui
445 app = QtCore.QCoreApplication.instance()
446 if app is None:
447 app = QtGui.QApplication(sys.argv)
448 self._apps[GUI_QT4] = app
449 return app
193 from PyQt4 import QtGui
194 app = QtCore.QCoreApplication.instance()
195 if app is None:
196 app = QtGui.QApplication([" "])
197 app._in_event_loop = True
198 self._apps[GUI_QT4] = app
199 return app
450 200
451 201 def disable_qt4(self):
452 202 """Disable event loop integration with PyQt4.
453 203
454 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 208 self.clear_inputhook()
457 209
458 210 def enable_gtk(self, app=False):
@@ -533,11 +285,10 b' clear_inputhook = inputhook_manager.clear_inputhook'
533 285 set_inputhook = inputhook_manager.set_inputhook
534 286 current_gui = inputhook_manager.current_gui
535 287 clear_app_refs = inputhook_manager.clear_app_refs
536 spin = inputhook_manager.spin
537 288
538 289
539 290 # Convenience function to switch amongst them
540 def enable_gui(gui=None, app=True):
291 def enable_gui(gui=None):
541 292 """Switch amongst GUI input hooks by name.
542 293
543 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 320 except KeyError:
570 321 e="Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
571 322 raise ValueError(e)
572 return gui_hook(app)
323 return gui_hook()
324
@@ -3,7 +3,9 b''
3 3
4 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 179 pylab.draw_if_interactive.called = False
178 180
179 181 return mpl_execfile
182
@@ -374,6 +374,11 b' class ZMQInteractiveShell(InteractiveShell):'
374 374 }
375 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 383 def _showtraceback(self, etype, evalue, stb):
379 384
General Comments 0
You need to be logged in to leave comments. Login now