|
|
#!/usr/bin/env python
|
|
|
# encoding: utf-8
|
|
|
"""
|
|
|
Inputhook management for GUI event loop integration.
|
|
|
"""
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Copyright (C) 2008-2009 The IPython Development Team
|
|
|
#
|
|
|
# Distributed under the terms of the BSD License. The full license is in
|
|
|
# the file COPYING, distributed as part of this software.
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Imports
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
import ctypes
|
|
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
# Code
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
class InputHookManager(object):
|
|
|
"""Manage PyOS_InputHook for different GUI toolkits."""
|
|
|
|
|
|
def __init__(self):
|
|
|
self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
|
|
|
self._reset()
|
|
|
|
|
|
def _reset(self):
|
|
|
self._callback_pyfunctype = None
|
|
|
self._callback = None
|
|
|
self._installed = False
|
|
|
|
|
|
def get_pyos_inputhook(self):
|
|
|
"""Return the current PyOS_InputHook as a ctypes.c_void_p.
|
|
|
"""
|
|
|
return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
|
|
|
|
|
|
def get_pyos_inputhook_as_func(self):
|
|
|
"""Return the current PyOS_InputHook as a ctypes.PYFUNCYPE.
|
|
|
"""
|
|
|
return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
|
|
|
|
|
|
def set_inputhook(self, callback):
|
|
|
"""Set PyOS_InputHook to callback and return the previous one.
|
|
|
"""
|
|
|
self._callback = callback
|
|
|
self._callback_pyfunctype = self.PYFUNC(callback)
|
|
|
pyos_inputhook_ptr = self.get_pyos_inputhook()
|
|
|
original = self.get_pyos_inputhook_as_func()
|
|
|
pyos_inputhook_ptr.value = \
|
|
|
ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
|
|
|
self._installed = True
|
|
|
return original
|
|
|
|
|
|
def clear_inputhook(self):
|
|
|
"""Set PyOS_InputHook to NULL and return the previous one.
|
|
|
"""
|
|
|
pyos_inputhook_ptr = self.get_pyos_inputhook()
|
|
|
original = self.get_pyos_inputhook_as_func()
|
|
|
pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
|
|
|
self._reset()
|
|
|
return original
|
|
|
|
|
|
def enable_wx(self):
|
|
|
"""Enable event loop integration with wxPython.
|
|
|
|
|
|
This methods sets the PyOS_InputHook for wxPython, which allows
|
|
|
the wxPython to integrate with terminal based applications like
|
|
|
IPython.
|
|
|
|
|
|
Once this has been called, you can use wx interactively by doing::
|
|
|
|
|
|
>>> import wx
|
|
|
>>> app = wx.App(redirect=False, clearSigInt=False)
|
|
|
|
|
|
Both options this constructor are important for things to work
|
|
|
properly in an interactive context.
|
|
|
|
|
|
But, *don't start the event loop*. That is handled automatically by
|
|
|
PyOS_InputHook.
|
|
|
"""
|
|
|
from IPython.lib.inputhookwx import inputhook_wx
|
|
|
self.set_inputhook(inputhook_wx)
|
|
|
|
|
|
def disable_wx(self):
|
|
|
"""Disable event loop integration with wxPython.
|
|
|
|
|
|
This merely sets PyOS_InputHook to NULL.
|
|
|
"""
|
|
|
self.clear_inputhook()
|
|
|
|
|
|
def enable_qt4(self):
|
|
|
"""Enable event loop integration with PyQt4.
|
|
|
|
|
|
This methods sets the PyOS_InputHook for wxPython, which allows
|
|
|
the PyQt4 to integrate with terminal based applications like
|
|
|
IPython.
|
|
|
|
|
|
Once this has been called, you can simply create a QApplication and
|
|
|
use it. But, *don't start the event loop*. That is handled
|
|
|
automatically by PyOS_InputHook.
|
|
|
"""
|
|
|
from PyQt4 import QtCore
|
|
|
# PyQt4 has had this since 4.3.1. In version 4.2, PyOS_InputHook
|
|
|
# was set when QtCore was imported, but if it ever got removed,
|
|
|
# you couldn't reset it. For earlier versions we can
|
|
|
# probably implement a ctypes version.
|
|
|
try:
|
|
|
QtCore.pyqtRestoreInputHook()
|
|
|
except AttributeError:
|
|
|
pass
|
|
|
|
|
|
def disable_qt4(self):
|
|
|
"""Disable event loop integration with PyQt4.
|
|
|
|
|
|
This merely sets PyOS_InputHook to NULL.
|
|
|
"""
|
|
|
self.clear_inputhook()
|
|
|
|
|
|
def enable_gtk(self):
|
|
|
"""Enable event loop integration with PyGTK.
|
|
|
|
|
|
This methods sets the PyOS_InputHook for PyGTK, which allows
|
|
|
the PyGTK to integrate with terminal based applications like
|
|
|
IPython.
|
|
|
|
|
|
Once this has been called, you can simple create PyGTK objects and
|
|
|
use them. But, *don't start the event loop*. That is handled
|
|
|
automatically by PyOS_InputHook.
|
|
|
"""
|
|
|
import gtk
|
|
|
try:
|
|
|
gtk.set_interactive(True)
|
|
|
except AttributeError:
|
|
|
# For older versions of gtk, use our own ctypes version
|
|
|
from IPython.lib.inputhookgtk import inputhook_gtk
|
|
|
add_inputhook(inputhook_gtk)
|
|
|
|
|
|
def disable_gtk(self):
|
|
|
"""Disable event loop integration with PyGTK.
|
|
|
|
|
|
This merely sets PyOS_InputHook to NULL.
|
|
|
"""
|
|
|
self.clear_inputhook()
|
|
|
|
|
|
def enable_tk(self):
|
|
|
# Creating a Tkinter.Tk object sets PyOS_InputHook()
|
|
|
pass
|
|
|
|
|
|
def disable_tk(self):
|
|
|
"""Disable event loop integration with Tkinter.
|
|
|
|
|
|
This merely sets PyOS_InputHook to NULL.
|
|
|
"""
|
|
|
self.clear_inputhook()
|
|
|
|
|
|
inputhook_manager = InputHookManager()
|
|
|
|
|
|
enable_wx = inputhook_manager.enable_wx
|
|
|
disable_wx = inputhook_manager.disable_wx
|
|
|
enable_qt4 = inputhook_manager.enable_qt4
|
|
|
disable_qt4 = inputhook_manager.disable_qt4
|
|
|
enable_gtk = inputhook_manager.enable_gtk
|
|
|
disable_gtk = inputhook_manager.disable_gtk
|
|
|
enable_tk = inputhook_manager.enable_tk
|
|
|
disable_tk = inputhook_manager.disable_tk
|
|
|
clear_inputhook = inputhook_manager.clear_inputhook
|
|
|
set_inputhook = inputhook_manager.set_inputhook
|