##// END OF EJS Templates
Merge pull request #13178 from meeseeksmachine/auto-backport-of-pr-13172-on-7.x...
Matthias Bussonnier -
r26848:1cfca27f merge
parent child Browse files
Show More
@@ -1,83 +1,83 b''
1 import sys
1 import sys
2 import os
2 import os
3 from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper
3 from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper
4 from IPython import get_ipython
4 from IPython import get_ipython
5
5
6 # If we create a QApplication, keep a reference to it so that it doesn't get
6 # If we create a QApplication, keep a reference to it so that it doesn't get
7 # garbage collected.
7 # garbage collected.
8 _appref = None
8 _appref = None
9 _already_warned = False
9 _already_warned = False
10
10
11
11
12 def _exec(obj):
12 def _exec(obj):
13 # exec on PyQt6, exec_ elsewhere.
13 # exec on PyQt6, exec_ elsewhere.
14 obj.exec() if hasattr(obj, "exec") else obj.exec_()
14 obj.exec() if hasattr(obj, "exec") else obj.exec_()
15
15
16
16
17 def _reclaim_excepthook():
17 def _reclaim_excepthook():
18 shell = get_ipython()
18 shell = get_ipython()
19 if shell is not None:
19 if shell is not None:
20 sys.excepthook = shell.excepthook
20 sys.excepthook = shell.excepthook
21
21
22
22
23 def inputhook(context):
23 def inputhook(context):
24 global _appref
24 global _appref
25 app = QtCore.QCoreApplication.instance()
25 app = QtCore.QCoreApplication.instance()
26 if not app:
26 if not app:
27 if sys.platform == 'linux':
27 if sys.platform == 'linux':
28 if not os.environ.get('DISPLAY') \
28 if not os.environ.get('DISPLAY') \
29 and not os.environ.get('WAYLAND_DISPLAY'):
29 and not os.environ.get('WAYLAND_DISPLAY'):
30 import warnings
30 import warnings
31 global _already_warned
31 global _already_warned
32 if not _already_warned:
32 if not _already_warned:
33 _already_warned = True
33 _already_warned = True
34 warnings.warn(
34 warnings.warn(
35 'The DISPLAY or WAYLAND_DISPLAY environment variable is '
35 'The DISPLAY or WAYLAND_DISPLAY environment variable is '
36 'not set or empty and Qt5 requires this environment '
36 'not set or empty and Qt5 requires this environment '
37 'variable. Deactivate Qt5 code.'
37 'variable. Deactivate Qt5 code.'
38 )
38 )
39 return
39 return
40 try:
40 try:
41 QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
41 QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
42 except AttributeError: # Only for Qt>=5.6, <6.
42 except AttributeError: # Only for Qt>=5.6, <6.
43 pass
43 pass
44 try:
44 try:
45 QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy(
45 QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy(
46 QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
46 QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
47 )
47 )
48 except AttributeError: # Only for Qt>=5.14.
48 except AttributeError: # Only for Qt>=5.14.
49 pass
49 pass
50 _appref = app = QtGui.QApplication([" "])
50 _appref = app = QtGui.QApplication([" "])
51
51
52 # "reclaim" IPython sys.excepthook after event loop starts
52 # "reclaim" IPython sys.excepthook after event loop starts
53 # without this, it defaults back to BaseIPythonApplication.excepthook
53 # without this, it defaults back to BaseIPythonApplication.excepthook
54 # and exceptions in the Qt event loop are rendered without traceback
54 # and exceptions in the Qt event loop are rendered without traceback
55 # formatting and look like "bug in IPython".
55 # formatting and look like "bug in IPython".
56 QtCore.QTimer.singleShot(0, _reclaim_excepthook)
56 QtCore.QTimer.singleShot(0, _reclaim_excepthook)
57
57
58 event_loop = QtCore.QEventLoop(app)
58 event_loop = QtCore.QEventLoop(app)
59
59
60 if sys.platform == 'win32':
60 if sys.platform == 'win32':
61 # The QSocketNotifier method doesn't appear to work on Windows.
61 # The QSocketNotifier method doesn't appear to work on Windows.
62 # Use polling instead.
62 # Use polling instead.
63 timer = QtCore.QTimer()
63 timer = QtCore.QTimer()
64 timer.timeout.connect(event_loop.quit)
64 timer.timeout.connect(event_loop.quit)
65 while not context.input_is_ready():
65 while not context.input_is_ready():
66 timer.start(50) # 50 ms
66 timer.start(50) # 50 ms
67 event_loop.exec_()
67 _exec(event_loop)
68 timer.stop()
68 timer.stop()
69 else:
69 else:
70 # On POSIX platforms, we can use a file descriptor to quit the event
70 # On POSIX platforms, we can use a file descriptor to quit the event
71 # loop when there is input ready to read.
71 # loop when there is input ready to read.
72 notifier = QtCore.QSocketNotifier(
72 notifier = QtCore.QSocketNotifier(
73 context.fileno(), enum_helper("QtCore.QSocketNotifier.Type").Read
73 context.fileno(), enum_helper("QtCore.QSocketNotifier.Type").Read
74 )
74 )
75 try:
75 try:
76 # connect the callback we care about before we turn it on
76 # connect the callback we care about before we turn it on
77 notifier.activated.connect(lambda: event_loop.exit())
77 notifier.activated.connect(lambda: event_loop.exit())
78 notifier.setEnabled(True)
78 notifier.setEnabled(True)
79 # only start the event loop we are not already flipped
79 # only start the event loop we are not already flipped
80 if not context.input_is_ready():
80 if not context.input_is_ready():
81 _exec(event_loop)
81 _exec(event_loop)
82 finally:
82 finally:
83 notifier.setEnabled(False)
83 notifier.setEnabled(False)
General Comments 0
You need to be logged in to leave comments. Login now