##// END OF EJS Templates
docstring fix in CloseEvent to conform to standards
Erik Tollerud -
Show More
@@ -1,270 +1,273 b''
1 """ A minimal application using the Qt console-style IPython frontend.
1 """ A minimal application using the Qt console-style IPython frontend.
2 """
2 """
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Imports
5 # Imports
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7
7
8 # Systemm library imports
8 # Systemm library imports
9 from PyQt4 import QtGui
9 from PyQt4 import QtGui
10 from pygments.styles import get_all_styles
10 from pygments.styles import get_all_styles
11 # Local imports
11 # Local imports
12 from IPython.external.argparse import ArgumentParser
12 from IPython.external.argparse import ArgumentParser
13 from IPython.frontend.qt.console.frontend_widget import FrontendWidget
13 from IPython.frontend.qt.console.frontend_widget import FrontendWidget
14 from IPython.frontend.qt.console.ipython_widget import IPythonWidget
14 from IPython.frontend.qt.console.ipython_widget import IPythonWidget
15 from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
15 from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
16 from IPython.frontend.qt.console import styles
16 from IPython.frontend.qt.console import styles
17 from IPython.frontend.qt.kernelmanager import QtKernelManager
17 from IPython.frontend.qt.kernelmanager import QtKernelManager
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Network Constants
20 # Network Constants
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
23 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Classes
26 # Classes
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 class MainWindow(QtGui.QMainWindow):
29 class MainWindow(QtGui.QMainWindow):
30
30
31 #---------------------------------------------------------------------------
31 #---------------------------------------------------------------------------
32 # 'object' interface
32 # 'object' interface
33 #---------------------------------------------------------------------------
33 #---------------------------------------------------------------------------
34
34
35 def __init__(self, app, frontend, existing=False, may_close=True):
35 def __init__(self, app, frontend, existing=False, may_close=True):
36 """ Create a MainWindow for the specified FrontendWidget.
36 """ Create a MainWindow for the specified FrontendWidget.
37
37
38 The app is passed as an argument to allow for different
38 The app is passed as an argument to allow for different
39 closing behavior depending on whether we are the Kernel's parent.
39 closing behavior depending on whether we are the Kernel's parent.
40
40
41 If existing is True, then this Console does not own the Kernel.
41 If existing is True, then this Console does not own the Kernel.
42
42
43 If may_close is True, then this Console is permitted to close the kernel
43 If may_close is True, then this Console is permitted to close the kernel
44 """
44 """
45 super(MainWindow, self).__init__()
45 super(MainWindow, self).__init__()
46 self._app = app
46 self._app = app
47 self._frontend = frontend
47 self._frontend = frontend
48 self._existing = existing
48 self._existing = existing
49 if existing:
49 if existing:
50 self._may_close = may_close
50 self._may_close = may_close
51 else:
51 else:
52 self._may_close = True
52 self._may_close = True
53 self._frontend.exit_requested.connect(self.close)
53 self._frontend.exit_requested.connect(self.close)
54 self.setCentralWidget(frontend)
54 self.setCentralWidget(frontend)
55
55
56 #---------------------------------------------------------------------------
56 #---------------------------------------------------------------------------
57 # QWidget interface
57 # QWidget interface
58 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
59
59
60 def closeEvent(self, event):
60 def closeEvent(self, event):
61 """ Reimplemented to prompt the user and close the kernel cleanly, or
61 """ Close the window and the kernel (if necessary).
62 close without prompt only if the exit magic is used.
62
63 This will prompt the user if they are finished with the kernel, and if
64 so, closes the kernel cleanly. Alternatively, if the exit magic is used,
65 it closes without prompt.
63 """
66 """
64 keepkernel = None #Use the prompt by default
67 keepkernel = None #Use the prompt by default
65 if hasattr(self._frontend,'_keep_kernel_on_exit'): #set by exit magic
68 if hasattr(self._frontend,'_keep_kernel_on_exit'): #set by exit magic
66 keepkernel = self._frontend._keep_kernel_on_exit
69 keepkernel = self._frontend._keep_kernel_on_exit
67
70
68 kernel_manager = self._frontend.kernel_manager
71 kernel_manager = self._frontend.kernel_manager
69
72
70 if keepkernel is None: #show prompt
73 if keepkernel is None: #show prompt
71 if kernel_manager and kernel_manager.channels_running:
74 if kernel_manager and kernel_manager.channels_running:
72 title = self.window().windowTitle()
75 title = self.window().windowTitle()
73 cancel = QtGui.QMessageBox.Cancel
76 cancel = QtGui.QMessageBox.Cancel
74 okay = QtGui.QMessageBox.Ok
77 okay = QtGui.QMessageBox.Ok
75 if self._may_close:
78 if self._may_close:
76 msg = "You are closing this Console window."
79 msg = "You are closing this Console window."
77 info = "Would you like to quit the Kernel and all attached Consoles as well?"
80 info = "Would you like to quit the Kernel and all attached Consoles as well?"
78 justthis = QtGui.QPushButton("&No, just this Console", self)
81 justthis = QtGui.QPushButton("&No, just this Console", self)
79 justthis.setShortcut('N')
82 justthis.setShortcut('N')
80 closeall = QtGui.QPushButton("&Yes, quit everything", self)
83 closeall = QtGui.QPushButton("&Yes, quit everything", self)
81 closeall.setShortcut('Y')
84 closeall.setShortcut('Y')
82 box = QtGui.QMessageBox(QtGui.QMessageBox.Question, title, msg)
85 box = QtGui.QMessageBox(QtGui.QMessageBox.Question, title, msg)
83 box.setInformativeText(info)
86 box.setInformativeText(info)
84 box.addButton(cancel)
87 box.addButton(cancel)
85 box.addButton(justthis, QtGui.QMessageBox.NoRole)
88 box.addButton(justthis, QtGui.QMessageBox.NoRole)
86 box.addButton(closeall, QtGui.QMessageBox.YesRole)
89 box.addButton(closeall, QtGui.QMessageBox.YesRole)
87 box.setDefaultButton(closeall)
90 box.setDefaultButton(closeall)
88 box.setEscapeButton(cancel)
91 box.setEscapeButton(cancel)
89 reply = box.exec_()
92 reply = box.exec_()
90 if reply == 1: # close All
93 if reply == 1: # close All
91 kernel_manager.shutdown_kernel()
94 kernel_manager.shutdown_kernel()
92 #kernel_manager.stop_channels()
95 #kernel_manager.stop_channels()
93 event.accept()
96 event.accept()
94 elif reply == 0: # close Console
97 elif reply == 0: # close Console
95 if not self._existing:
98 if not self._existing:
96 # Have kernel: don't quit, just close the window
99 # Have kernel: don't quit, just close the window
97 self._app.setQuitOnLastWindowClosed(False)
100 self._app.setQuitOnLastWindowClosed(False)
98 self.deleteLater()
101 self.deleteLater()
99 event.accept()
102 event.accept()
100 else:
103 else:
101 event.ignore()
104 event.ignore()
102 else:
105 else:
103 reply = QtGui.QMessageBox.question(self, title,
106 reply = QtGui.QMessageBox.question(self, title,
104 "Are you sure you want to close this Console?"+
107 "Are you sure you want to close this Console?"+
105 "\nThe Kernel and other Consoles will remain active.",
108 "\nThe Kernel and other Consoles will remain active.",
106 okay|cancel,
109 okay|cancel,
107 defaultButton=okay
110 defaultButton=okay
108 )
111 )
109 if reply == okay:
112 if reply == okay:
110 event.accept()
113 event.accept()
111 else:
114 else:
112 event.ignore()
115 event.ignore()
113 elif keepkernel: #close console but leave kernel running (no prompt)
116 elif keepkernel: #close console but leave kernel running (no prompt)
114 if kernel_manager and kernel_manager.channels_running:
117 if kernel_manager and kernel_manager.channels_running:
115 if not self._existing:
118 if not self._existing:
116 # I have the kernel: don't quit, just close the window
119 # I have the kernel: don't quit, just close the window
117 self._app.setQuitOnLastWindowClosed(False)
120 self._app.setQuitOnLastWindowClosed(False)
118 event.accept()
121 event.accept()
119 else: #close console and kernel (no prompt)
122 else: #close console and kernel (no prompt)
120 if kernel_manager and kernel_manager.channels_running:
123 if kernel_manager and kernel_manager.channels_running:
121 kernel_manager.shutdown_kernel()
124 kernel_manager.shutdown_kernel()
122 event.accept()
125 event.accept()
123
126
124 #-----------------------------------------------------------------------------
127 #-----------------------------------------------------------------------------
125 # Main entry point
128 # Main entry point
126 #-----------------------------------------------------------------------------
129 #-----------------------------------------------------------------------------
127
130
128 def main():
131 def main():
129 """ Entry point for application.
132 """ Entry point for application.
130 """
133 """
131 # Parse command line arguments.
134 # Parse command line arguments.
132 parser = ArgumentParser()
135 parser = ArgumentParser()
133 kgroup = parser.add_argument_group('kernel options')
136 kgroup = parser.add_argument_group('kernel options')
134 kgroup.add_argument('-e', '--existing', action='store_true',
137 kgroup.add_argument('-e', '--existing', action='store_true',
135 help='connect to an existing kernel')
138 help='connect to an existing kernel')
136 kgroup.add_argument('--ip', type=str, default=LOCALHOST,
139 kgroup.add_argument('--ip', type=str, default=LOCALHOST,
137 help=\
140 help=\
138 "set the kernel\'s IP address [default localhost].\
141 "set the kernel\'s IP address [default localhost].\
139 If the IP address is something other than localhost, then \
142 If the IP address is something other than localhost, then \
140 Consoles on other machines will be able to connect\
143 Consoles on other machines will be able to connect\
141 to the Kernel, so be careful!")
144 to the Kernel, so be careful!")
142 kgroup.add_argument('--xreq', type=int, metavar='PORT', default=0,
145 kgroup.add_argument('--xreq', type=int, metavar='PORT', default=0,
143 help='set the XREQ channel port [default random]')
146 help='set the XREQ channel port [default random]')
144 kgroup.add_argument('--sub', type=int, metavar='PORT', default=0,
147 kgroup.add_argument('--sub', type=int, metavar='PORT', default=0,
145 help='set the SUB channel port [default random]')
148 help='set the SUB channel port [default random]')
146 kgroup.add_argument('--rep', type=int, metavar='PORT', default=0,
149 kgroup.add_argument('--rep', type=int, metavar='PORT', default=0,
147 help='set the REP channel port [default random]')
150 help='set the REP channel port [default random]')
148 kgroup.add_argument('--hb', type=int, metavar='PORT', default=0,
151 kgroup.add_argument('--hb', type=int, metavar='PORT', default=0,
149 help='set the heartbeat port [default random]')
152 help='set the heartbeat port [default random]')
150
153
151 egroup = kgroup.add_mutually_exclusive_group()
154 egroup = kgroup.add_mutually_exclusive_group()
152 egroup.add_argument('--pure', action='store_true', help = \
155 egroup.add_argument('--pure', action='store_true', help = \
153 'use a pure Python kernel instead of an IPython kernel')
156 'use a pure Python kernel instead of an IPython kernel')
154 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
157 egroup.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
155 const='auto', help = \
158 const='auto', help = \
156 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
159 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
157 given, the GUI backend is matplotlib's, otherwise use one of: \
160 given, the GUI backend is matplotlib's, otherwise use one of: \
158 ['tk', 'gtk', 'qt', 'wx', 'inline'].")
161 ['tk', 'gtk', 'qt', 'wx', 'inline'].")
159
162
160 wgroup = parser.add_argument_group('widget options')
163 wgroup = parser.add_argument_group('widget options')
161 wgroup.add_argument('--paging', type=str, default='inside',
164 wgroup.add_argument('--paging', type=str, default='inside',
162 choices = ['inside', 'hsplit', 'vsplit', 'none'],
165 choices = ['inside', 'hsplit', 'vsplit', 'none'],
163 help='set the paging style [default inside]')
166 help='set the paging style [default inside]')
164 wgroup.add_argument('--rich', action='store_true',
167 wgroup.add_argument('--rich', action='store_true',
165 help='enable rich text support')
168 help='enable rich text support')
166 wgroup.add_argument('--gui-completion', action='store_true',
169 wgroup.add_argument('--gui-completion', action='store_true',
167 help='use a GUI widget for tab completion')
170 help='use a GUI widget for tab completion')
168 wgroup.add_argument('--style', type=str,
171 wgroup.add_argument('--style', type=str,
169 choices = list(get_all_styles()),
172 choices = list(get_all_styles()),
170 help='specify a pygments style for by name.')
173 help='specify a pygments style for by name.')
171 wgroup.add_argument('--stylesheet', type=str,
174 wgroup.add_argument('--stylesheet', type=str,
172 help="path to a custom CSS stylesheet.")
175 help="path to a custom CSS stylesheet.")
173 wgroup.add_argument('--colors', type=str,
176 wgroup.add_argument('--colors', type=str,
174 help="Set the color scheme (LightBG,Linux,NoColor). This is guessed\
177 help="Set the color scheme (LightBG,Linux,NoColor). This is guessed\
175 based on the pygments style if not set.")
178 based on the pygments style if not set.")
176
179
177 args = parser.parse_args()
180 args = parser.parse_args()
178
181
179 # parse the colors arg down to current known labels
182 # parse the colors arg down to current known labels
180 if args.colors:
183 if args.colors:
181 colors=args.colors.lower()
184 colors=args.colors.lower()
182 if colors in ('lightbg', 'light'):
185 if colors in ('lightbg', 'light'):
183 colors='lightbg'
186 colors='lightbg'
184 elif colors in ('dark', 'linux'):
187 elif colors in ('dark', 'linux'):
185 colors='linux'
188 colors='linux'
186 else:
189 else:
187 colors='nocolor'
190 colors='nocolor'
188 elif args.style:
191 elif args.style:
189 if args.style=='bw':
192 if args.style=='bw':
190 colors='nocolor'
193 colors='nocolor'
191 elif styles.dark_style(args.style):
194 elif styles.dark_style(args.style):
192 colors='linux'
195 colors='linux'
193 else:
196 else:
194 colors='lightbg'
197 colors='lightbg'
195 else:
198 else:
196 colors=None
199 colors=None
197
200
198 # Don't let Qt or ZMQ swallow KeyboardInterupts.
201 # Don't let Qt or ZMQ swallow KeyboardInterupts.
199 import signal
202 import signal
200 signal.signal(signal.SIGINT, signal.SIG_DFL)
203 signal.signal(signal.SIGINT, signal.SIG_DFL)
201
204
202 # Create a KernelManager and start a kernel.
205 # Create a KernelManager and start a kernel.
203 kernel_manager = QtKernelManager(xreq_address=(args.ip, args.xreq),
206 kernel_manager = QtKernelManager(xreq_address=(args.ip, args.xreq),
204 sub_address=(args.ip, args.sub),
207 sub_address=(args.ip, args.sub),
205 rep_address=(args.ip, args.rep),
208 rep_address=(args.ip, args.rep),
206 hb_address=(args.ip, args.hb))
209 hb_address=(args.ip, args.hb))
207 if not args.existing:
210 if not args.existing:
208 # if not args.ip in LOCAL_IPS+ALL_ALIAS:
211 # if not args.ip in LOCAL_IPS+ALL_ALIAS:
209 # raise ValueError("Must bind a local ip, such as: %s"%LOCAL_IPS)
212 # raise ValueError("Must bind a local ip, such as: %s"%LOCAL_IPS)
210
213
211 kwargs = dict(ip=args.ip)
214 kwargs = dict(ip=args.ip)
212 if args.pure:
215 if args.pure:
213 kwargs['ipython']=False
216 kwargs['ipython']=False
214 else:
217 else:
215 kwargs['colors']=colors
218 kwargs['colors']=colors
216 if args.pylab:
219 if args.pylab:
217 kwargs['pylab']=args.pylab
220 kwargs['pylab']=args.pylab
218
221
219 kernel_manager.start_kernel(**kwargs)
222 kernel_manager.start_kernel(**kwargs)
220 kernel_manager.start_channels()
223 kernel_manager.start_channels()
221
224
222 local_kernel = (not args.existing) or args.ip in LOCAL_IPS
225 local_kernel = (not args.existing) or args.ip in LOCAL_IPS
223 # Create the widget.
226 # Create the widget.
224 app = QtGui.QApplication([])
227 app = QtGui.QApplication([])
225 if args.pure:
228 if args.pure:
226 kind = 'rich' if args.rich else 'plain'
229 kind = 'rich' if args.rich else 'plain'
227 widget = FrontendWidget(kind=kind, paging=args.paging, local_kernel=local_kernel)
230 widget = FrontendWidget(kind=kind, paging=args.paging, local_kernel=local_kernel)
228 elif args.rich or args.pylab:
231 elif args.rich or args.pylab:
229 widget = RichIPythonWidget(paging=args.paging, local_kernel=local_kernel)
232 widget = RichIPythonWidget(paging=args.paging, local_kernel=local_kernel)
230 else:
233 else:
231 widget = IPythonWidget(paging=args.paging, local_kernel=local_kernel)
234 widget = IPythonWidget(paging=args.paging, local_kernel=local_kernel)
232 widget.gui_completion = args.gui_completion
235 widget.gui_completion = args.gui_completion
233 widget.kernel_manager = kernel_manager
236 widget.kernel_manager = kernel_manager
234
237
235 # configure the style:
238 # configure the style:
236 if not args.pure: # only IPythonWidget supports styles
239 if not args.pure: # only IPythonWidget supports styles
237 if args.style:
240 if args.style:
238 widget.syntax_style = args.style
241 widget.syntax_style = args.style
239 widget.style_sheet = styles.sheet_from_template(args.style, colors)
242 widget.style_sheet = styles.sheet_from_template(args.style, colors)
240 widget._syntax_style_changed()
243 widget._syntax_style_changed()
241 widget._style_sheet_changed()
244 widget._style_sheet_changed()
242 elif colors:
245 elif colors:
243 # use a default style
246 # use a default style
244 widget.set_default_style(colors=colors)
247 widget.set_default_style(colors=colors)
245 else:
248 else:
246 # this is redundant for now, but allows the widget's
249 # this is redundant for now, but allows the widget's
247 # defaults to change
250 # defaults to change
248 widget.set_default_style()
251 widget.set_default_style()
249
252
250 if args.stylesheet:
253 if args.stylesheet:
251 # we got an expicit stylesheet
254 # we got an expicit stylesheet
252 if os.path.isfile(args.stylesheet):
255 if os.path.isfile(args.stylesheet):
253 with open(args.stylesheet) as f:
256 with open(args.stylesheet) as f:
254 sheet = f.read()
257 sheet = f.read()
255 widget.style_sheet = sheet
258 widget.style_sheet = sheet
256 widget._style_sheet_changed()
259 widget._style_sheet_changed()
257 else:
260 else:
258 raise IOError("Stylesheet %r not found."%args.stylesheet)
261 raise IOError("Stylesheet %r not found."%args.stylesheet)
259
262
260 # Create the main window.
263 # Create the main window.
261 window = MainWindow(app, widget, args.existing, may_close=local_kernel)
264 window = MainWindow(app, widget, args.existing, may_close=local_kernel)
262 window.setWindowTitle('Python' if args.pure else 'IPython')
265 window.setWindowTitle('Python' if args.pure else 'IPython')
263 window.show()
266 window.show()
264
267
265 # Start the application main loop.
268 # Start the application main loop.
266 app.exec_()
269 app.exec_()
267
270
268
271
269 if __name__ == '__main__':
272 if __name__ == '__main__':
270 main()
273 main()
General Comments 0
You need to be logged in to leave comments. Login now