##// END OF EJS Templates
Fixing wx related issue in guisupport.py.
Brian Granger -
Show More
@@ -1,145 +1,147 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # coding: utf-8
2 # coding: utf-8
3 """
3 """
4 Support for creating GUI apps and starting event loops.
4 Support for creating GUI apps and starting event loops.
5
5
6 IPython's GUI integration allows interative plotting and GUI usage in IPython
6 IPython's GUI integration allows interative plotting and GUI usage in IPython
7 session. IPython has two different types of GUI integration:
7 session. IPython has two different types of GUI integration:
8
8
9 1. The terminal based IPython supports GUI event loops through Python's
9 1. The terminal based IPython supports GUI event loops through Python's
10 PyOS_InputHook. PyOS_InputHook is a hook that Python calls periodically
10 PyOS_InputHook. PyOS_InputHook is a hook that Python calls periodically
11 whenever raw_input is waiting for a user to type code. We implement GUI
11 whenever raw_input is waiting for a user to type code. We implement GUI
12 support in the terminal by setting PyOS_InputHook to a function that
12 support in the terminal by setting PyOS_InputHook to a function that
13 iterates the event loop for a short while. It is important to note that
13 iterates the event loop for a short while. It is important to note that
14 in this situation, the real GUI event loop is NOT run in the normal
14 in this situation, the real GUI event loop is NOT run in the normal
15 manner, so you can't use the normal means to detect that it is running.
15 manner, so you can't use the normal means to detect that it is running.
16 2. In the two process IPython kernel/frontend, the GUI event loop is run in
16 2. In the two process IPython kernel/frontend, the GUI event loop is run in
17 the kernel. In this case, the event loop is run in the normal manner by
17 the kernel. In this case, the event loop is run in the normal manner by
18 calling the function or method of the GUI toolkit that starts the event
18 calling the function or method of the GUI toolkit that starts the event
19 loop.
19 loop.
20
20
21 In addition to starting the GUI event loops in one of these two ways, IPython
21 In addition to starting the GUI event loops in one of these two ways, IPython
22 will *always* create an appropriate GUI application object when GUi
22 will *always* create an appropriate GUI application object when GUi
23 integration is enabled.
23 integration is enabled.
24
24
25 If you want your GUI apps to run in IPython you need to do two things:
25 If you want your GUI apps to run in IPython you need to do two things:
26
26
27 1. Test to see if there is already an existing main application object. If
27 1. Test to see if there is already an existing main application object. If
28 there is, you should use it. If there is not an existing application object
28 there is, you should use it. If there is not an existing application object
29 you should create one.
29 you should create one.
30 2. Test to see if the GUI event loop is running. If it is, you should not
30 2. Test to see if the GUI event loop is running. If it is, you should not
31 start it. If the event loop is not running you may start it.
31 start it. If the event loop is not running you may start it.
32
32
33 This module contains functions for each toolkit that perform these things
33 This module contains functions for each toolkit that perform these things
34 in a consistent manner. Because of how PyOS_InputHook runs the event loop
34 in a consistent manner. Because of how PyOS_InputHook runs the event loop
35 you cannot detect if the event loop is running using the traditional calls
35 you cannot detect if the event loop is running using the traditional calls
36 (such as ``wx.GetApp.IsMainLoopRunning()`` in wxPython). If PyOS_InputHook is
36 (such as ``wx.GetApp.IsMainLoopRunning()`` in wxPython). If PyOS_InputHook is
37 set These methods will return a false negative. That is, they will say the
37 set These methods will return a false negative. That is, they will say the
38 event loop is not running, when is actually is. To work around this limitation
38 event loop is not running, when is actually is. To work around this limitation
39 we proposed the following informal protocol:
39 we proposed the following informal protocol:
40
40
41 * Whenever someone starts the event loop, they *must* set the ``_in_event_loop``
41 * Whenever someone starts the event loop, they *must* set the ``_in_event_loop``
42 attribute of the main application object to ``True``. This should be done
42 attribute of the main application object to ``True``. This should be done
43 regardless of how the event loop is actually run.
43 regardless of how the event loop is actually run.
44 * Whenever someone stops the event loop, they *must* set the ``_in_event_loop``
44 * Whenever someone stops the event loop, they *must* set the ``_in_event_loop``
45 attribute of the main application object to ``False``.
45 attribute of the main application object to ``False``.
46 * If you want to see if the event loop is running, you *must* use ``hasattr``
46 * If you want to see if the event loop is running, you *must* use ``hasattr``
47 to see if ``_in_event_loop`` attribute has been set. If it is set, you
47 to see if ``_in_event_loop`` attribute has been set. If it is set, you
48 *must* use its value. If it has not been set, you can query the toolkit
48 *must* use its value. If it has not been set, you can query the toolkit
49 in the normal manner.
49 in the normal manner.
50 * If you want GUI support and no one else has created an application or
50 * If you want GUI support and no one else has created an application or
51 started the event loop you *must* do this. We don't want projects to
51 started the event loop you *must* do this. We don't want projects to
52 attempt to defer these things to someone else if they themselves need it.
52 attempt to defer these things to someone else if they themselves need it.
53
53
54 The functions below implement this logic for each GUI toolkit. If you need
54 The functions below implement this logic for each GUI toolkit. If you need
55 to create custom application subclasses, you will likely have to modify this
55 to create custom application subclasses, you will likely have to modify this
56 code for your own purposes. This code can be copied into your own project
56 code for your own purposes. This code can be copied into your own project
57 so you don't have to depend on IPython.
57 so you don't have to depend on IPython.
58
58
59 """
59 """
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 # Copyright (C) 2008-2010 The IPython Development Team
62 # Copyright (C) 2008-2010 The IPython Development Team
63 #
63 #
64 # Distributed under the terms of the BSD License. The full license is in
64 # Distributed under the terms of the BSD License. The full license is in
65 # the file COPYING, distributed as part of this software.
65 # the file COPYING, distributed as part of this software.
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67
67
68 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
69 # Imports
69 # Imports
70 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
71
71
72 #-----------------------------------------------------------------------------
72 #-----------------------------------------------------------------------------
73 # wx
73 # wx
74 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
75
75
76 def get_app_wx(*args, **kwargs):
76 def get_app_wx(*args, **kwargs):
77 """Create a new wx app or return an exiting one."""
77 """Create a new wx app or return an exiting one."""
78 import wx
78 import wx
79 app = wx.GetApp()
79 app = wx.GetApp()
80 if app is None:
80 if app is None:
81 if not kwargs.has_key('redirect'):
82 kwargs['redirect'] = False
81 app = wx.PySimpleApp(*args, **kwargs)
83 app = wx.PySimpleApp(*args, **kwargs)
82 return app
84 return app
83
85
84 def is_event_loop_running_wx(app=None):
86 def is_event_loop_running_wx(app=None):
85 """Is the wx event loop running."""
87 """Is the wx event loop running."""
86 if app is None:
88 if app is None:
87 app = get_app_wx()
89 app = get_app_wx()
88 if hasattr(app, '_in_event_loop'):
90 if hasattr(app, '_in_event_loop'):
89 return app._in_event_loop
91 return app._in_event_loop
90 else:
92 else:
91 return app.IsMainLoopRunning()
93 return app.IsMainLoopRunning()
92
94
93 def start_event_loop_wx(app=None):
95 def start_event_loop_wx(app=None):
94 """Start the wx event loop in a consistent manner."""
96 """Start the wx event loop in a consistent manner."""
95 if app is None:
97 if app is None:
96 app = get_app_wx()
98 app = get_app_wx()
97 if not is_event_loop_running_wx(app):
99 if not is_event_loop_running_wx(app):
98 app._in_event_loop = True
100 app._in_event_loop = True
99 app.MainLoop()
101 app.MainLoop()
100 app._in_event_loop = False
102 app._in_event_loop = False
101 else:
103 else:
102 app._in_event_loop = True
104 app._in_event_loop = True
103
105
104 #-----------------------------------------------------------------------------
106 #-----------------------------------------------------------------------------
105 # qt4
107 # qt4
106 #-----------------------------------------------------------------------------
108 #-----------------------------------------------------------------------------
107
109
108 def get_app_qt4(*args, **kwargs):
110 def get_app_qt4(*args, **kwargs):
109 """Create a new qt4 app or return an existing one."""
111 """Create a new qt4 app or return an existing one."""
110 from PyQt4 import QtGui
112 from PyQt4 import QtGui
111 app = QtGui.QApplication.instance()
113 app = QtGui.QApplication.instance()
112 if app is None:
114 if app is None:
113 if not args:
115 if not args:
114 args = ([''],)
116 args = ([''],)
115 app = QtGui.QApplication(*args, **kwargs)
117 app = QtGui.QApplication(*args, **kwargs)
116 return app
118 return app
117
119
118 def is_event_loop_running_qt4(app=None):
120 def is_event_loop_running_qt4(app=None):
119 """Is the qt4 event loop running."""
121 """Is the qt4 event loop running."""
120 if app is None:
122 if app is None:
121 app = get_app_qt4([''])
123 app = get_app_qt4([''])
122 if hasattr(app, '_in_event_loop'):
124 if hasattr(app, '_in_event_loop'):
123 return app._in_event_loop
125 return app._in_event_loop
124 else:
126 else:
125 # Does qt4 provide a other way to detect this?
127 # Does qt4 provide a other way to detect this?
126 return False
128 return False
127
129
128 def start_event_loop_qt4(app=None):
130 def start_event_loop_qt4(app=None):
129 """Start the qt4 event loop in a consistent manner."""
131 """Start the qt4 event loop in a consistent manner."""
130 if app is None:
132 if app is None:
131 app = get_app_qt4([''])
133 app = get_app_qt4([''])
132 if not is_event_loop_running_qt4(app):
134 if not is_event_loop_running_qt4(app):
133 app._in_event_loop = True
135 app._in_event_loop = True
134 app.exec_()
136 app.exec_()
135 app._in_event_loop = False
137 app._in_event_loop = False
136 else:
138 else:
137 app._in_event_loop = True
139 app._in_event_loop = True
138
140
139 #-----------------------------------------------------------------------------
141 #-----------------------------------------------------------------------------
140 # Tk
142 # Tk
141 #-----------------------------------------------------------------------------
143 #-----------------------------------------------------------------------------
142
144
143 #-----------------------------------------------------------------------------
145 #-----------------------------------------------------------------------------
144 # gtk
146 # gtk
145 #-----------------------------------------------------------------------------
147 #-----------------------------------------------------------------------------
General Comments 0
You need to be logged in to leave comments. Login now