PyOS_InputHook python hook for Qt5. Process pending Qt events and if there's no pending keyboard input, spend a short slice of time (50ms) running the Qt event loop. As a Python ctypes callback can't raise an exception, we catch the KeyboardInterrupt and tem
()
| 98 | # hooks (they both share the got_kbdint flag) |
| 99 | |
| 100 | def inputhook_qt5(): |
| 101 | """PyOS_InputHook python hook for Qt5. |
| 102 | |
| 103 | Process pending Qt events and if there's no pending keyboard |
| 104 | input, spend a short slice of time (50ms) running the Qt event |
| 105 | loop. |
| 106 | |
| 107 | As a Python ctypes callback can't raise an exception, we catch |
| 108 | the KeyboardInterrupt and temporarily deactivate the hook, |
| 109 | which will let a *second* CTRL+C be processed normally and go |
| 110 | back to a clean prompt line. |
| 111 | """ |
| 112 | try: |
| 113 | allow_CTRL_C() |
| 114 | app = QtCore.QCoreApplication.instance() |
| 115 | if not app: # shouldn't happen, but safer if it happens anyway... |
| 116 | return 0 |
| 117 | app.processEvents(QtCore.QEventLoop.AllEvents, 300) |
| 118 | if not stdin_ready(): |
| 119 | # Generally a program would run QCoreApplication::exec() |
| 120 | # from main() to enter and process the Qt event loop until |
| 121 | # quit() or exit() is called and the program terminates. |
| 122 | # |
| 123 | # For our input hook integration, we need to repeatedly |
| 124 | # enter and process the Qt event loop for only a short |
| 125 | # amount of time (say 50ms) to ensure that Python stays |
| 126 | # responsive to other user inputs. |
| 127 | # |
| 128 | # A naive approach would be to repeatedly call |
| 129 | # QCoreApplication::exec(), using a timer to quit after a |
| 130 | # short amount of time. Unfortunately, QCoreApplication |
| 131 | # emits an aboutToQuit signal before stopping, which has |
| 132 | # the undesirable effect of closing all modal windows. |
| 133 | # |
| 134 | # To work around this problem, we instead create a |
| 135 | # QEventLoop and call QEventLoop::exec(). Other than |
| 136 | # setting some state variables which do not seem to be |
| 137 | # used anywhere, the only thing QCoreApplication adds is |
| 138 | # the aboutToQuit signal which is precisely what we are |
| 139 | # trying to avoid. |
| 140 | timer = QtCore.QTimer() |
| 141 | event_loop = QtCore.QEventLoop() |
| 142 | timer.timeout.connect(event_loop.quit) |
| 143 | while not stdin_ready(): |
| 144 | timer.start(50) |
| 145 | event_loop.exec_() |
| 146 | timer.stop() |
| 147 | except KeyboardInterrupt: |
| 148 | global got_kbdint, sigint_timer |
| 149 | |
| 150 | ignore_CTRL_C() |
| 151 | got_kbdint = True |
| 152 | mgr.clear_inputhook() |
| 153 | |
| 154 | # This generates a second SIGINT so the user doesn't have to |
| 155 | # press CTRL+C twice to get a clean prompt. |
| 156 | # |
| 157 | # Since we can't catch the resulting KeyboardInterrupt here |
nothing calls this directly
no test coverage detected