##// END OF EJS Templates
inputhookqt4: polish the qt4 related hooks...
Christian Boos -
Show More
@@ -1,91 +1,111 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Qt4's inputhook support function
3 Qt4's inputhook support function
4
4
5 Author: Christian Boos
5 Author: Christian Boos
6 """
6 """
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
9 # Copyright (C) 2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from IPython.core import ipapi
19 from IPython.core import ipapi
20 from IPython.external.qt_for_kernel import QtCore, QtGui
20 from IPython.external.qt_for_kernel import QtCore, QtGui
21 from IPython.lib.inputhook import stdin_ready
21 from IPython.lib.inputhook import stdin_ready
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Code
24 # Code
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 def create_inputhook_qt4(mgr, app=None):
27 def create_inputhook_qt4(mgr, app=None):
28 """Create an input hook for running the Qt4 application event loop.
28 """Create an input hook for running the Qt4 application event loop.
29
29
30 Parameters
30 Parameters
31 ----------
31 ----------
32 mgr : an InputHookManager
32 mgr : an InputHookManager
33
33
34 app : Qt Application, optional.
34 app : Qt Application, optional.
35 Running application to use. If not given, we probe Qt for an
35 Running application to use. If not given, we probe Qt for an
36 existing application object, and create a new one if none is found.
36 existing application object, and create a new one if none is found.
37
37
38 Returns
38 Returns
39 -------
39 -------
40 A pair consisting of a Qt Application (either the one given or the
40 A pair consisting of a Qt Application (either the one given or the
41 one found or created) and a inputhook.
41 one found or created) and a inputhook.
42
42
43 Notes
43 Notes
44 -----
44 -----
45 We use a custom input hook instead of PyQt4's default one, as it
46 interacts better with the readline packages (issue #481).
47
45 The inputhook function works in tandem with a 'pre_prompt_hook'
48 The inputhook function works in tandem with a 'pre_prompt_hook'
46 which automatically restores the hook as an inputhook in case the
49 which automatically restores the hook as an inputhook in case the
47 latter has been temporarily disabled after having intercepted a
50 latter has been temporarily disabled after having intercepted a
48 KeyboardInterrupt.
51 KeyboardInterrupt.
49 """
52 """
53
50 if app is None:
54 if app is None:
51 app = QtCore.QCoreApplication.instance()
55 app = QtCore.QCoreApplication.instance()
52 if app is None:
56 if app is None:
53 app = QtGui.QApplication([" "])
57 app = QtGui.QApplication([" "])
54
58
55 # Always use a custom input hook instead of PyQt4's default
59 # Re-use previously created inputhook if any
56 # one, as it interacts better with readline packages (issue
60 ip = ipapi.get()
57 # #481).
61 if hasattr(ip, '_inputhook_qt4'):
62 return app, ip._inputhook_qt4
58
63
59 # Note that we can't let KeyboardInterrupt escape from that
64 # Otherwise create the inputhook_qt4/preprompthook_qt4 pair of
60 # hook, as no exception can be raised from within a ctypes
65 # hooks (they both share the got_kbdint flag)
61 # python callback. We need to make a compromise: a trapped
62 # KeyboardInterrupt will temporarily disable the input hook
63 # until we start over with a new prompt line with a second
64 # CTRL+C.
65
66
66 got_kbdint = [False]
67 got_kbdint = [False]
67
68
68 def inputhook_qt4():
69 def inputhook_qt4():
70 """PyOS_InputHook python hook for Qt4.
71
72 Process pending Qt events and if there's no pending keyboard
73 input, spend a short slice of time (50ms) running the Qt event
74 loop.
75
76 As a Python ctypes callback can't raise an exception, we catch
77 the KeyboardInterrupt and temporarily deactivate the hook,
78 which will let a *second* CTRL+C be processed normally and go
79 back to a clean prompt line.
80 """
69 try:
81 try:
82 app = QtCore.QCoreApplication.instance()
70 app.processEvents(QtCore.QEventLoop.AllEvents, 300)
83 app.processEvents(QtCore.QEventLoop.AllEvents, 300)
71 if not stdin_ready():
84 if not stdin_ready():
72 timer = QtCore.QTimer()
85 timer = QtCore.QTimer()
73 timer.timeout.connect(app.quit)
86 timer.timeout.connect(app.quit)
74 while not stdin_ready():
87 while not stdin_ready():
75 timer.start(50)
88 timer.start(50)
76 app.exec_()
89 app.exec_()
77 timer.stop()
90 timer.stop()
78 except KeyboardInterrupt:
91 except KeyboardInterrupt:
79 got_kbdint[0] = True
92 got_kbdint[0] = True
80 mgr.clear_inputhook()
93 mgr.clear_inputhook()
81 print("\n(event loop interrupted - "
94 print("\n(event loop interrupted - "
82 "hit CTRL+C again to clear the prompt)")
95 "hit CTRL+C again to clear the prompt)")
83 return 0
96 return 0
84
97
85 def preprompthook_qt4(ishell):
98 def preprompthook_qt4(ishell):
99 """'pre_prompt_hook' used to restore the Qt4 input hook
100
101 (in case the latter was temporarily deactivated after a
102 CTRL+C)
103 """
86 if got_kbdint[0]:
104 if got_kbdint[0]:
87 mgr.set_inputhook(inputhook_qt4)
105 mgr.set_inputhook(inputhook_qt4)
88 got_kbdint[0] = False
106 got_kbdint[0] = False
89 ipapi.get().set_hook('pre_prompt_hook', preprompthook_qt4)
107
108 ip._inputhook_qt4 = inputhook_qt4
109 ip.set_hook('pre_prompt_hook', preprompthook_qt4)
90
110
91 return app, inputhook_qt4
111 return app, inputhook_qt4
General Comments 0
You need to be logged in to leave comments. Login now