##// END OF EJS Templates
inputhookqt4: need to ignore CTRL+C when exiting input hook
Christian Boos -
Show More
@@ -1,115 +1,116
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.external.qt_for_kernel import QtCore, QtGui
19 from IPython.external.qt_for_kernel import QtCore, QtGui
20 from IPython.lib.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready
20 from IPython.lib.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Code
23 # Code
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 def create_inputhook_qt4(mgr, app=None):
26 def create_inputhook_qt4(mgr, app=None):
27 """Create an input hook for running the Qt4 application event loop.
27 """Create an input hook for running the Qt4 application event loop.
28
28
29 Parameters
29 Parameters
30 ----------
30 ----------
31 mgr : an InputHookManager
31 mgr : an InputHookManager
32
32
33 app : Qt Application, optional.
33 app : Qt Application, optional.
34 Running application to use. If not given, we probe Qt for an
34 Running application to use. If not given, we probe Qt for an
35 existing application object, and create a new one if none is found.
35 existing application object, and create a new one if none is found.
36
36
37 Returns
37 Returns
38 -------
38 -------
39 A pair consisting of a Qt Application (either the one given or the
39 A pair consisting of a Qt Application (either the one given or the
40 one found or created) and a inputhook.
40 one found or created) and a inputhook.
41
41
42 Notes
42 Notes
43 -----
43 -----
44 We use a custom input hook instead of PyQt4's default one, as it
44 We use a custom input hook instead of PyQt4's default one, as it
45 interacts better with the readline packages (issue #481).
45 interacts better with the readline packages (issue #481).
46
46
47 The inputhook function works in tandem with a 'pre_prompt_hook'
47 The inputhook function works in tandem with a 'pre_prompt_hook'
48 which automatically restores the hook as an inputhook in case the
48 which automatically restores the hook as an inputhook in case the
49 latter has been temporarily disabled after having intercepted a
49 latter has been temporarily disabled after having intercepted a
50 KeyboardInterrupt.
50 KeyboardInterrupt.
51 """
51 """
52
52
53 if app is None:
53 if app is None:
54 app = QtCore.QCoreApplication.instance()
54 app = QtCore.QCoreApplication.instance()
55 if app is None:
55 if app is None:
56 app = QtGui.QApplication([" "])
56 app = QtGui.QApplication([" "])
57
57
58 # Re-use previously created inputhook if any
58 # Re-use previously created inputhook if any
59 ip = get_ipython()
59 ip = get_ipython()
60 if hasattr(ip, '_inputhook_qt4'):
60 if hasattr(ip, '_inputhook_qt4'):
61 return app, ip._inputhook_qt4
61 return app, ip._inputhook_qt4
62
62
63 # Otherwise create the inputhook_qt4/preprompthook_qt4 pair of
63 # Otherwise create the inputhook_qt4/preprompthook_qt4 pair of
64 # hooks (they both share the got_kbdint flag)
64 # hooks (they both share the got_kbdint flag)
65
65
66 got_kbdint = [False]
66 got_kbdint = [False]
67
67
68 def inputhook_qt4():
68 def inputhook_qt4():
69 """PyOS_InputHook python hook for Qt4.
69 """PyOS_InputHook python hook for Qt4.
70
70
71 Process pending Qt events and if there's no pending keyboard
71 Process pending Qt events and if there's no pending keyboard
72 input, spend a short slice of time (50ms) running the Qt event
72 input, spend a short slice of time (50ms) running the Qt event
73 loop.
73 loop.
74
74
75 As a Python ctypes callback can't raise an exception, we catch
75 As a Python ctypes callback can't raise an exception, we catch
76 the KeyboardInterrupt and temporarily deactivate the hook,
76 the KeyboardInterrupt and temporarily deactivate the hook,
77 which will let a *second* CTRL+C be processed normally and go
77 which will let a *second* CTRL+C be processed normally and go
78 back to a clean prompt line.
78 back to a clean prompt line.
79 """
79 """
80 try:
80 try:
81 allow_CTRL_C()
81 allow_CTRL_C()
82 app = QtCore.QCoreApplication.instance()
82 app = QtCore.QCoreApplication.instance()
83 app.processEvents(QtCore.QEventLoop.AllEvents, 300)
83 app.processEvents(QtCore.QEventLoop.AllEvents, 300)
84 if not stdin_ready():
84 if not stdin_ready():
85 timer = QtCore.QTimer()
85 timer = QtCore.QTimer()
86 timer.timeout.connect(app.quit)
86 timer.timeout.connect(app.quit)
87 while not stdin_ready():
87 while not stdin_ready():
88 timer.start(50)
88 timer.start(50)
89 app.exec_()
89 app.exec_()
90 timer.stop()
90 timer.stop()
91 ignore_CTRL_C()
91 except KeyboardInterrupt:
92 except KeyboardInterrupt:
92 ignore_CTRL_C()
93 ignore_CTRL_C()
93 got_kbdint[0] = True
94 got_kbdint[0] = True
94 print("\nKeyboardInterrupt - qt4 event loop interrupted!"
95 print("\nKeyboardInterrupt - qt4 event loop interrupted!"
95 "\n * hit CTRL+C again to clear the prompt"
96 "\n * hit CTRL+C again to clear the prompt"
96 "\n * use '%gui none' to disable the event loop"
97 "\n * use '%gui none' to disable the event loop"
97 " permanently"
98 " permanently"
98 "\n and '%gui qt4' to re-enable it later")
99 "\n and '%gui qt4' to re-enable it later")
99 mgr.clear_inputhook()
100 mgr.clear_inputhook()
100 return 0
101 return 0
101
102
102 def preprompthook_qt4(ishell):
103 def preprompthook_qt4(ishell):
103 """'pre_prompt_hook' used to restore the Qt4 input hook
104 """'pre_prompt_hook' used to restore the Qt4 input hook
104
105
105 (in case the latter was temporarily deactivated after a
106 (in case the latter was temporarily deactivated after a
106 CTRL+C)
107 CTRL+C)
107 """
108 """
108 if got_kbdint[0]:
109 if got_kbdint[0]:
109 mgr.set_inputhook(inputhook_qt4)
110 mgr.set_inputhook(inputhook_qt4)
110 got_kbdint[0] = False
111 got_kbdint[0] = False
111
112
112 ip._inputhook_qt4 = inputhook_qt4
113 ip._inputhook_qt4 = inputhook_qt4
113 ip.set_hook('pre_prompt_hook', preprompthook_qt4)
114 ip.set_hook('pre_prompt_hook', preprompthook_qt4)
114
115
115 return app, inputhook_qt4
116 return app, inputhook_qt4
General Comments 0
You need to be logged in to leave comments. Login now