87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
|
"""GUI support for the IPython ZeroMQ kernel - GTK toolkit support.
|
||
|
"""
|
||
|
#-----------------------------------------------------------------------------
|
||
|
# Copyright (C) 2010-2011 The IPython Development Team
|
||
|
#
|
||
|
# Distributed under the terms of the BSD License. The full license is in
|
||
|
# the file COPYING.txt, distributed as part of this software.
|
||
|
#-----------------------------------------------------------------------------
|
||
|
|
||
|
#-----------------------------------------------------------------------------
|
||
|
# Imports
|
||
|
#-----------------------------------------------------------------------------
|
||
|
# stdlib
|
||
|
import sys
|
||
|
|
||
|
# Third-party
|
||
|
import gobject
|
||
|
import gtk
|
||
|
|
||
|
#-----------------------------------------------------------------------------
|
||
|
# Classes and functions
|
||
|
#-----------------------------------------------------------------------------
|
||
|
|
||
|
class GTKEmbed(object):
|
||
|
"""A class to embed a kernel into the GTK main event loop.
|
||
|
"""
|
||
|
def __init__(self, kernel):
|
||
|
self.kernel = kernel
|
||
|
# These two will later store the real gtk functions when we hijack them
|
||
|
self.gtk_main = None
|
||
|
self.gtk_main_quit = None
|
||
|
|
||
|
def start(self):
|
||
|
"""Starts the GTK main event loop and sets our kernel startup routine.
|
||
|
"""
|
||
|
# Register our function to initiate the kernel and start gtk
|
||
|
gobject.idle_add(self._wire_kernel)
|
||
|
gtk.main()
|
||
|
|
||
|
def _wire_kernel(self):
|
||
|
"""Initializes the kernel inside GTK.
|
||
|
|
||
|
This is meant to run only once at startup, so it does its job and
|
||
|
returns False to ensure it doesn't get run again by GTK.
|
||
|
"""
|
||
|
self.gtk_main, self.gtk_main_quit = self._hijack_gtk()
|
||
|
gobject.timeout_add(int(1000*self.kernel._poll_interval),
|
||
|
self.iterate_kernel)
|
||
|
return False
|
||
|
|
||
|
def iterate_kernel(self):
|
||
|
"""Run one iteration of the kernel and return True.
|
||
|
|
||
|
GTK timer functions must return True to be called again, so we make the
|
||
|
call to :meth:`do_one_iteration` and then return True for GTK.
|
||
|
"""
|
||
|
self.kernel.do_one_iteration()
|
||
|
return True
|
||
|
|
||
|
def stop(self):
|
||
|
# FIXME: this one isn't getting called because we have no reliable
|
||
|
# kernel shutdown. We need to fix that: once the kernel has a
|
||
|
# shutdown mechanism, it can call this.
|
||
|
self.gtk_main_quit()
|
||
|
sys.exit()
|
||
|
|
||
|
def _hijack_gtk(self):
|
||
|
"""Hijack a few key functions in GTK for IPython integration.
|
||
|
|
||
|
Modifies pyGTK's main and main_quit with a dummy so user code does not
|
||
|
block IPython. This allows us to use %run to run arbitrary pygtk
|
||
|
scripts from a long-lived IPython session, and when they attempt to
|
||
|
start or stop
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
The original functions that have been hijacked:
|
||
|
- gtk.main
|
||
|
- gtk.main_quit
|
||
|
"""
|
||
|
def dummy(*args, **kw):
|
||
|
pass
|
||
|
# save and trap main and main_quit from gtk
|
||
|
orig_main, gtk.main = gtk.main, dummy
|
||
|
orig_main_quit, gtk.main_quit = gtk.main_quit, dummy
|
||
|
return orig_main, orig_main_quit
|