##// END OF EJS Templates
fix inverted OSX platform check
MinRK -
Show More
@@ -1,806 +1,806 b''
1 """The Qt MainWindow for the QtConsole
1 """The Qt MainWindow for the QtConsole
2
2
3 This is a tabbed pseudo-terminal of IPython sessions, with a menu bar for
3 This is a tabbed pseudo-terminal of IPython sessions, with a menu bar for
4 common actions.
4 common actions.
5
5
6 Authors:
6 Authors:
7
7
8 * Evan Patterson
8 * Evan Patterson
9 * Min RK
9 * Min RK
10 * Erik Tollerud
10 * Erik Tollerud
11 * Fernando Perez
11 * Fernando Perez
12 * Bussonnier Matthias
12 * Bussonnier Matthias
13 * Thomas Kluyver
13 * Thomas Kluyver
14
14
15 """
15 """
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 # stdlib imports
21 # stdlib imports
22 import sys
22 import sys
23 import webbrowser
23 import webbrowser
24
24
25 # System library imports
25 # System library imports
26 from IPython.external.qt import QtGui,QtCore
26 from IPython.external.qt import QtGui,QtCore
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Classes
29 # Classes
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 class MainWindow(QtGui.QMainWindow):
32 class MainWindow(QtGui.QMainWindow):
33
33
34 #---------------------------------------------------------------------------
34 #---------------------------------------------------------------------------
35 # 'object' interface
35 # 'object' interface
36 #---------------------------------------------------------------------------
36 #---------------------------------------------------------------------------
37
37
38 def __init__(self, app,
38 def __init__(self, app,
39 confirm_exit=True,
39 confirm_exit=True,
40 new_frontend_factory=None, slave_frontend_factory=None,
40 new_frontend_factory=None, slave_frontend_factory=None,
41 ):
41 ):
42 """ Create a tabbed MainWindow for managing IPython FrontendWidgets
42 """ Create a tabbed MainWindow for managing IPython FrontendWidgets
43
43
44 Parameters
44 Parameters
45 ----------
45 ----------
46
46
47 app : reference to QApplication parent
47 app : reference to QApplication parent
48 confirm_exit : bool, optional
48 confirm_exit : bool, optional
49 Whether we should prompt on close of tabs
49 Whether we should prompt on close of tabs
50 new_frontend_factory : callable
50 new_frontend_factory : callable
51 A callable that returns a new IPythonWidget instance, attached to
51 A callable that returns a new IPythonWidget instance, attached to
52 its own running kernel.
52 its own running kernel.
53 slave_frontend_factory : callable
53 slave_frontend_factory : callable
54 A callable that takes an existing IPythonWidget, and returns a new
54 A callable that takes an existing IPythonWidget, and returns a new
55 IPythonWidget instance, attached to the same kernel.
55 IPythonWidget instance, attached to the same kernel.
56 """
56 """
57
57
58 super(MainWindow, self).__init__()
58 super(MainWindow, self).__init__()
59 self._app = app
59 self._app = app
60 self.confirm_exit = confirm_exit
60 self.confirm_exit = confirm_exit
61 self.new_frontend_factory = new_frontend_factory
61 self.new_frontend_factory = new_frontend_factory
62 self.slave_frontend_factory = slave_frontend_factory
62 self.slave_frontend_factory = slave_frontend_factory
63
63
64 self.tab_widget = QtGui.QTabWidget(self)
64 self.tab_widget = QtGui.QTabWidget(self)
65 self.tab_widget.setDocumentMode(True)
65 self.tab_widget.setDocumentMode(True)
66 self.tab_widget.setTabsClosable(True)
66 self.tab_widget.setTabsClosable(True)
67 self.tab_widget.tabCloseRequested[int].connect(self.close_tab)
67 self.tab_widget.tabCloseRequested[int].connect(self.close_tab)
68
68
69 self.setCentralWidget(self.tab_widget)
69 self.setCentralWidget(self.tab_widget)
70 self.tab_widget.tabBar().setVisible(False)
70 self.tab_widget.tabBar().setVisible(False)
71
71
72 def update_tab_bar_visibility(self):
72 def update_tab_bar_visibility(self):
73 """ update visibility of the tabBar depending of the number of tab
73 """ update visibility of the tabBar depending of the number of tab
74
74
75 0 or 1 tab, tabBar hidden
75 0 or 1 tab, tabBar hidden
76 2+ tabs, tabBar visible
76 2+ tabs, tabBar visible
77
77
78 send a self.close if number of tab ==0
78 send a self.close if number of tab ==0
79
79
80 need to be called explicitely, or be connected to tabInserted/tabRemoved
80 need to be called explicitely, or be connected to tabInserted/tabRemoved
81 """
81 """
82 if self.tab_widget.count() <= 1:
82 if self.tab_widget.count() <= 1:
83 self.tab_widget.tabBar().setVisible(False)
83 self.tab_widget.tabBar().setVisible(False)
84 else:
84 else:
85 self.tab_widget.tabBar().setVisible(True)
85 self.tab_widget.tabBar().setVisible(True)
86 if self.tab_widget.count()==0 :
86 if self.tab_widget.count()==0 :
87 self.close()
87 self.close()
88
88
89 @property
89 @property
90 def active_frontend(self):
90 def active_frontend(self):
91 return self.tab_widget.currentWidget()
91 return self.tab_widget.currentWidget()
92
92
93 def create_tab_with_new_frontend(self):
93 def create_tab_with_new_frontend(self):
94 """create a new frontend and attach it to a new tab"""
94 """create a new frontend and attach it to a new tab"""
95 widget = self.new_frontend_factory()
95 widget = self.new_frontend_factory()
96 self.add_tab_with_frontend(widget)
96 self.add_tab_with_frontend(widget)
97
97
98 def create_tab_with_current_kernel(self):
98 def create_tab_with_current_kernel(self):
99 """create a new frontend attached to the same kernel as the current tab"""
99 """create a new frontend attached to the same kernel as the current tab"""
100 current_widget = self.tab_widget.currentWidget()
100 current_widget = self.tab_widget.currentWidget()
101 current_widget_index = self.tab_widget.indexOf(current_widget)
101 current_widget_index = self.tab_widget.indexOf(current_widget)
102 current_widget_name = self.tab_widget.tabText(current_widget_index)
102 current_widget_name = self.tab_widget.tabText(current_widget_index)
103 widget = self.slave_frontend_factory(current_widget)
103 widget = self.slave_frontend_factory(current_widget)
104 if 'slave' in current_widget_name:
104 if 'slave' in current_widget_name:
105 # don't keep stacking slaves
105 # don't keep stacking slaves
106 name = current_widget_name
106 name = current_widget_name
107 else:
107 else:
108 name = str('('+current_widget_name+') slave')
108 name = str('('+current_widget_name+') slave')
109 self.add_tab_with_frontend(widget,name=name)
109 self.add_tab_with_frontend(widget,name=name)
110
110
111 def close_tab(self,current_tab):
111 def close_tab(self,current_tab):
112 """ Called when you need to try to close a tab.
112 """ Called when you need to try to close a tab.
113
113
114 It takes the number of the tab to be closed as argument, or a referece
114 It takes the number of the tab to be closed as argument, or a referece
115 to the wiget insite this tab
115 to the wiget insite this tab
116 """
116 """
117
117
118 # let's be sure "tab" and "closing widget are respectivey the index of the tab to close
118 # let's be sure "tab" and "closing widget are respectivey the index of the tab to close
119 # and a reference to the trontend to close
119 # and a reference to the trontend to close
120 if type(current_tab) is not int :
120 if type(current_tab) is not int :
121 current_tab = self.tab_widget.indexOf(current_tab)
121 current_tab = self.tab_widget.indexOf(current_tab)
122 closing_widget=self.tab_widget.widget(current_tab)
122 closing_widget=self.tab_widget.widget(current_tab)
123
123
124
124
125 # when trying to be closed, widget might re-send a request to be closed again, but will
125 # when trying to be closed, widget might re-send a request to be closed again, but will
126 # be deleted when event will be processed. So need to check that widget still exist and
126 # be deleted when event will be processed. So need to check that widget still exist and
127 # skip if not. One example of this is when 'exit' is send in a slave tab. 'exit' will be
127 # skip if not. One example of this is when 'exit' is send in a slave tab. 'exit' will be
128 # re-send by this fonction on the master widget, which ask all slaves widget to exit
128 # re-send by this fonction on the master widget, which ask all slaves widget to exit
129 if closing_widget==None:
129 if closing_widget==None:
130 return
130 return
131
131
132 #get a list of all slave widgets on the same kernel.
132 #get a list of all slave widgets on the same kernel.
133 slave_tabs = self.find_slave_widgets(closing_widget)
133 slave_tabs = self.find_slave_widgets(closing_widget)
134
134
135 keepkernel = None #Use the prompt by default
135 keepkernel = None #Use the prompt by default
136 if hasattr(closing_widget,'_keep_kernel_on_exit'): #set by exit magic
136 if hasattr(closing_widget,'_keep_kernel_on_exit'): #set by exit magic
137 keepkernel = closing_widget._keep_kernel_on_exit
137 keepkernel = closing_widget._keep_kernel_on_exit
138 # If signal sent by exit magic (_keep_kernel_on_exit, exist and not None)
138 # If signal sent by exit magic (_keep_kernel_on_exit, exist and not None)
139 # we set local slave tabs._hidden to True to avoid prompting for kernel
139 # we set local slave tabs._hidden to True to avoid prompting for kernel
140 # restart when they get the signal. and then "forward" the 'exit'
140 # restart when they get the signal. and then "forward" the 'exit'
141 # to the main window
141 # to the main window
142 if keepkernel is not None:
142 if keepkernel is not None:
143 for tab in slave_tabs:
143 for tab in slave_tabs:
144 tab._hidden = True
144 tab._hidden = True
145 if closing_widget in slave_tabs:
145 if closing_widget in slave_tabs:
146 try :
146 try :
147 self.find_master_tab(closing_widget).execute('exit')
147 self.find_master_tab(closing_widget).execute('exit')
148 except AttributeError:
148 except AttributeError:
149 self.log.info("Master already closed or not local, closing only current tab")
149 self.log.info("Master already closed or not local, closing only current tab")
150 self.tab_widget.removeTab(current_tab)
150 self.tab_widget.removeTab(current_tab)
151 self.update_tab_bar_visibility()
151 self.update_tab_bar_visibility()
152 return
152 return
153
153
154 kernel_manager = closing_widget.kernel_manager
154 kernel_manager = closing_widget.kernel_manager
155
155
156 if keepkernel is None and not closing_widget._confirm_exit:
156 if keepkernel is None and not closing_widget._confirm_exit:
157 # don't prompt, just terminate the kernel if we own it
157 # don't prompt, just terminate the kernel if we own it
158 # or leave it alone if we don't
158 # or leave it alone if we don't
159 keepkernel = closing_widget._existing
159 keepkernel = closing_widget._existing
160 if keepkernel is None: #show prompt
160 if keepkernel is None: #show prompt
161 if kernel_manager and kernel_manager.channels_running:
161 if kernel_manager and kernel_manager.channels_running:
162 title = self.window().windowTitle()
162 title = self.window().windowTitle()
163 cancel = QtGui.QMessageBox.Cancel
163 cancel = QtGui.QMessageBox.Cancel
164 okay = QtGui.QMessageBox.Ok
164 okay = QtGui.QMessageBox.Ok
165 if closing_widget._may_close:
165 if closing_widget._may_close:
166 msg = "You are closing the tab : "+'"'+self.tab_widget.tabText(current_tab)+'"'
166 msg = "You are closing the tab : "+'"'+self.tab_widget.tabText(current_tab)+'"'
167 info = "Would you like to quit the Kernel and close all attached Consoles as well?"
167 info = "Would you like to quit the Kernel and close all attached Consoles as well?"
168 justthis = QtGui.QPushButton("&No, just this Tab", self)
168 justthis = QtGui.QPushButton("&No, just this Tab", self)
169 justthis.setShortcut('N')
169 justthis.setShortcut('N')
170 closeall = QtGui.QPushButton("&Yes, close all", self)
170 closeall = QtGui.QPushButton("&Yes, close all", self)
171 closeall.setShortcut('Y')
171 closeall.setShortcut('Y')
172 box = QtGui.QMessageBox(QtGui.QMessageBox.Question,
172 box = QtGui.QMessageBox(QtGui.QMessageBox.Question,
173 title, msg)
173 title, msg)
174 box.setInformativeText(info)
174 box.setInformativeText(info)
175 box.addButton(cancel)
175 box.addButton(cancel)
176 box.addButton(justthis, QtGui.QMessageBox.NoRole)
176 box.addButton(justthis, QtGui.QMessageBox.NoRole)
177 box.addButton(closeall, QtGui.QMessageBox.YesRole)
177 box.addButton(closeall, QtGui.QMessageBox.YesRole)
178 box.setDefaultButton(closeall)
178 box.setDefaultButton(closeall)
179 box.setEscapeButton(cancel)
179 box.setEscapeButton(cancel)
180 pixmap = QtGui.QPixmap(self._app.icon.pixmap(QtCore.QSize(64,64)))
180 pixmap = QtGui.QPixmap(self._app.icon.pixmap(QtCore.QSize(64,64)))
181 box.setIconPixmap(pixmap)
181 box.setIconPixmap(pixmap)
182 reply = box.exec_()
182 reply = box.exec_()
183 if reply == 1: # close All
183 if reply == 1: # close All
184 for slave in slave_tabs:
184 for slave in slave_tabs:
185 self.tab_widget.removeTab(self.tab_widget.indexOf(slave))
185 self.tab_widget.removeTab(self.tab_widget.indexOf(slave))
186 closing_widget.execute("exit")
186 closing_widget.execute("exit")
187 self.tab_widget.removeTab(current_tab)
187 self.tab_widget.removeTab(current_tab)
188 elif reply == 0: # close Console
188 elif reply == 0: # close Console
189 if not closing_widget._existing:
189 if not closing_widget._existing:
190 # Have kernel: don't quit, just close the tab
190 # Have kernel: don't quit, just close the tab
191 closing_widget.execute("exit True")
191 closing_widget.execute("exit True")
192 self.tab_widget.removeTab(current_tab)
192 self.tab_widget.removeTab(current_tab)
193 else:
193 else:
194 reply = QtGui.QMessageBox.question(self, title,
194 reply = QtGui.QMessageBox.question(self, title,
195 "Are you sure you want to close this Console?"+
195 "Are you sure you want to close this Console?"+
196 "\nThe Kernel and other Consoles will remain active.",
196 "\nThe Kernel and other Consoles will remain active.",
197 okay|cancel,
197 okay|cancel,
198 defaultButton=okay
198 defaultButton=okay
199 )
199 )
200 if reply == okay:
200 if reply == okay:
201 self.tab_widget.removeTab(current_tab)
201 self.tab_widget.removeTab(current_tab)
202 elif keepkernel: #close console but leave kernel running (no prompt)
202 elif keepkernel: #close console but leave kernel running (no prompt)
203 self.tab_widget.removeTab(current_tab)
203 self.tab_widget.removeTab(current_tab)
204 if kernel_manager and kernel_manager.channels_running:
204 if kernel_manager and kernel_manager.channels_running:
205 kernel_manager.stop_channels()
205 kernel_manager.stop_channels()
206 else: #close console and kernel (no prompt)
206 else: #close console and kernel (no prompt)
207 self.tab_widget.removeTab(current_tab)
207 self.tab_widget.removeTab(current_tab)
208 if kernel_manager and kernel_manager.channels_running:
208 if kernel_manager and kernel_manager.channels_running:
209 kernel_manager.shutdown_kernel()
209 kernel_manager.shutdown_kernel()
210 for slave in slave_tabs:
210 for slave in slave_tabs:
211 slave.kernel_manager.stop_channels()
211 slave.kernel_manager.stop_channels()
212 self.tab_widget.removeTab(self.tab_widget.indexOf(slave))
212 self.tab_widget.removeTab(self.tab_widget.indexOf(slave))
213
213
214 self.update_tab_bar_visibility()
214 self.update_tab_bar_visibility()
215
215
216 def add_tab_with_frontend(self,frontend,name=None):
216 def add_tab_with_frontend(self,frontend,name=None):
217 """ insert a tab with a given frontend in the tab bar, and give it a name
217 """ insert a tab with a given frontend in the tab bar, and give it a name
218
218
219 """
219 """
220 if not name:
220 if not name:
221 name=str('kernel '+str(self.tab_widget.count()))
221 name=str('kernel '+str(self.tab_widget.count()))
222 self.tab_widget.addTab(frontend,name)
222 self.tab_widget.addTab(frontend,name)
223 self.update_tab_bar_visibility()
223 self.update_tab_bar_visibility()
224 self.make_frontend_visible(frontend)
224 self.make_frontend_visible(frontend)
225 frontend.exit_requested.connect(self.close_tab)
225 frontend.exit_requested.connect(self.close_tab)
226
226
227 def next_tab(self):
227 def next_tab(self):
228 self.tab_widget.setCurrentIndex((self.tab_widget.currentIndex()+1))
228 self.tab_widget.setCurrentIndex((self.tab_widget.currentIndex()+1))
229
229
230 def prev_tab(self):
230 def prev_tab(self):
231 self.tab_widget.setCurrentIndex((self.tab_widget.currentIndex()-1))
231 self.tab_widget.setCurrentIndex((self.tab_widget.currentIndex()-1))
232
232
233 def make_frontend_visible(self,frontend):
233 def make_frontend_visible(self,frontend):
234 widget_index=self.tab_widget.indexOf(frontend)
234 widget_index=self.tab_widget.indexOf(frontend)
235 if widget_index > 0 :
235 if widget_index > 0 :
236 self.tab_widget.setCurrentIndex(widget_index)
236 self.tab_widget.setCurrentIndex(widget_index)
237
237
238 def find_master_tab(self,tab,as_list=False):
238 def find_master_tab(self,tab,as_list=False):
239 """
239 """
240 Try to return the frontend that own the kernel attached to the given widget/tab.
240 Try to return the frontend that own the kernel attached to the given widget/tab.
241
241
242 Only find frontend owed by the current application. Selection
242 Only find frontend owed by the current application. Selection
243 based on port of the kernel, might be inacurate if several kernel
243 based on port of the kernel, might be inacurate if several kernel
244 on different ip use same port number.
244 on different ip use same port number.
245
245
246 This fonction does the conversion tabNumber/widget if needed.
246 This fonction does the conversion tabNumber/widget if needed.
247 Might return None if no master widget (non local kernel)
247 Might return None if no master widget (non local kernel)
248 Will crash IPython if more than 1 masterWidget
248 Will crash IPython if more than 1 masterWidget
249
249
250 When asList set to True, always return a list of widget(s) owning
250 When asList set to True, always return a list of widget(s) owning
251 the kernel. The list might be empty or containing several Widget.
251 the kernel. The list might be empty or containing several Widget.
252 """
252 """
253
253
254 #convert from/to int/richIpythonWidget if needed
254 #convert from/to int/richIpythonWidget if needed
255 if isinstance(tab, int):
255 if isinstance(tab, int):
256 tab = self.tab_widget.widget(tab)
256 tab = self.tab_widget.widget(tab)
257 km=tab.kernel_manager
257 km=tab.kernel_manager
258
258
259 #build list of all widgets
259 #build list of all widgets
260 widget_list = [self.tab_widget.widget(i) for i in range(self.tab_widget.count())]
260 widget_list = [self.tab_widget.widget(i) for i in range(self.tab_widget.count())]
261
261
262 # widget that are candidate to be the owner of the kernel does have all the same port of the curent widget
262 # widget that are candidate to be the owner of the kernel does have all the same port of the curent widget
263 # And should have a _may_close attribute
263 # And should have a _may_close attribute
264 filtered_widget_list = [ widget for widget in widget_list if
264 filtered_widget_list = [ widget for widget in widget_list if
265 widget.kernel_manager.connection_file == km.connection_file and
265 widget.kernel_manager.connection_file == km.connection_file and
266 hasattr(widget,'_may_close') ]
266 hasattr(widget,'_may_close') ]
267 # the master widget is the one that may close the kernel
267 # the master widget is the one that may close the kernel
268 master_widget= [ widget for widget in filtered_widget_list if widget._may_close]
268 master_widget= [ widget for widget in filtered_widget_list if widget._may_close]
269 if as_list:
269 if as_list:
270 return master_widget
270 return master_widget
271 assert(len(master_widget)<=1 )
271 assert(len(master_widget)<=1 )
272 if len(master_widget)==0:
272 if len(master_widget)==0:
273 return None
273 return None
274
274
275 return master_widget[0]
275 return master_widget[0]
276
276
277 def find_slave_widgets(self,tab):
277 def find_slave_widgets(self,tab):
278 """return all the frontends that do not own the kernel attached to the given widget/tab.
278 """return all the frontends that do not own the kernel attached to the given widget/tab.
279
279
280 Only find frontends owned by the current application. Selection
280 Only find frontends owned by the current application. Selection
281 based on connection file of the kernel.
281 based on connection file of the kernel.
282
282
283 This function does the conversion tabNumber/widget if needed.
283 This function does the conversion tabNumber/widget if needed.
284 """
284 """
285 #convert from/to int/richIpythonWidget if needed
285 #convert from/to int/richIpythonWidget if needed
286 if isinstance(tab, int):
286 if isinstance(tab, int):
287 tab = self.tab_widget.widget(tab)
287 tab = self.tab_widget.widget(tab)
288 km=tab.kernel_manager
288 km=tab.kernel_manager
289
289
290 #build list of all widgets
290 #build list of all widgets
291 widget_list = [self.tab_widget.widget(i) for i in range(self.tab_widget.count())]
291 widget_list = [self.tab_widget.widget(i) for i in range(self.tab_widget.count())]
292
292
293 # widget that are candidate not to be the owner of the kernel does have all the same port of the curent widget
293 # widget that are candidate not to be the owner of the kernel does have all the same port of the curent widget
294 filtered_widget_list = ( widget for widget in widget_list if
294 filtered_widget_list = ( widget for widget in widget_list if
295 widget.kernel_manager.connection_file == km.connection_file)
295 widget.kernel_manager.connection_file == km.connection_file)
296 # Get a list of all widget owning the same kernel and removed it from
296 # Get a list of all widget owning the same kernel and removed it from
297 # the previous cadidate. (better using sets ?)
297 # the previous cadidate. (better using sets ?)
298 master_widget_list = self.find_master_tab(tab, as_list=True)
298 master_widget_list = self.find_master_tab(tab, as_list=True)
299 slave_list = [widget for widget in filtered_widget_list if widget not in master_widget_list]
299 slave_list = [widget for widget in filtered_widget_list if widget not in master_widget_list]
300
300
301 return slave_list
301 return slave_list
302
302
303 # Populate the menu bar with common actions and shortcuts
303 # Populate the menu bar with common actions and shortcuts
304 def add_menu_action(self, menu, action):
304 def add_menu_action(self, menu, action):
305 """Add action to menu as well as self
305 """Add action to menu as well as self
306
306
307 So that when the menu bar is invisible, its actions are still available.
307 So that when the menu bar is invisible, its actions are still available.
308 """
308 """
309 menu.addAction(action)
309 menu.addAction(action)
310 self.addAction(action)
310 self.addAction(action)
311
311
312 def init_menu_bar(self):
312 def init_menu_bar(self):
313 #create menu in the order they should appear in the menu bar
313 #create menu in the order they should appear in the menu bar
314 self.init_file_menu()
314 self.init_file_menu()
315 self.init_edit_menu()
315 self.init_edit_menu()
316 self.init_view_menu()
316 self.init_view_menu()
317 self.init_kernel_menu()
317 self.init_kernel_menu()
318 self.init_magic_menu()
318 self.init_magic_menu()
319 self.init_window_menu()
319 self.init_window_menu()
320 self.init_help_menu()
320 self.init_help_menu()
321
321
322 def init_file_menu(self):
322 def init_file_menu(self):
323 self.file_menu = self.menuBar().addMenu("&File")
323 self.file_menu = self.menuBar().addMenu("&File")
324
324
325 self.new_kernel_tab_act = QtGui.QAction("New Tab with &New kernel",
325 self.new_kernel_tab_act = QtGui.QAction("New Tab with &New kernel",
326 self,
326 self,
327 shortcut="Ctrl+T",
327 shortcut="Ctrl+T",
328 triggered=self.create_tab_with_new_frontend)
328 triggered=self.create_tab_with_new_frontend)
329 self.add_menu_action(self.file_menu, self.new_kernel_tab_act)
329 self.add_menu_action(self.file_menu, self.new_kernel_tab_act)
330
330
331 self.slave_kernel_tab_act = QtGui.QAction("New Tab with Sa&me kernel",
331 self.slave_kernel_tab_act = QtGui.QAction("New Tab with Sa&me kernel",
332 self,
332 self,
333 shortcut="Ctrl+Shift+T",
333 shortcut="Ctrl+Shift+T",
334 triggered=self.create_tab_with_current_kernel)
334 triggered=self.create_tab_with_current_kernel)
335 self.add_menu_action(self.file_menu, self.slave_kernel_tab_act)
335 self.add_menu_action(self.file_menu, self.slave_kernel_tab_act)
336
336
337 self.file_menu.addSeparator()
337 self.file_menu.addSeparator()
338
338
339 self.close_action=QtGui.QAction("&Close Tab",
339 self.close_action=QtGui.QAction("&Close Tab",
340 self,
340 self,
341 shortcut="Ctrl+W",
341 shortcut="Ctrl+W",
342 triggered=self.close_active_frontend
342 triggered=self.close_active_frontend
343 )
343 )
344 self.add_menu_action(self.file_menu, self.close_action)
344 self.add_menu_action(self.file_menu, self.close_action)
345
345
346 self.export_action=QtGui.QAction("&Save to HTML/XHTML",
346 self.export_action=QtGui.QAction("&Save to HTML/XHTML",
347 self,
347 self,
348 shortcut="Ctrl+S",
348 shortcut="Ctrl+S",
349 triggered=self.export_action_active_frontend
349 triggered=self.export_action_active_frontend
350 )
350 )
351 self.add_menu_action(self.file_menu, self.export_action)
351 self.add_menu_action(self.file_menu, self.export_action)
352
352
353 self.file_menu.addSeparator()
353 self.file_menu.addSeparator()
354
354
355 # Ctrl actually maps to Cmd on OSX, which avoids conflict with history
355 # Ctrl actually maps to Cmd on OSX, which avoids conflict with history
356 # action, which is already bound to true Ctrl+P
356 # action, which is already bound to true Ctrl+P
357 print_shortcut = "Ctrl+P" if sys.platform == 'darwin' else 'Ctrl+Shift+P'
357 print_shortcut = "Ctrl+P" if sys.platform == 'darwin' else 'Ctrl+Shift+P'
358 self.print_action = QtGui.QAction("&Print",
358 self.print_action = QtGui.QAction("&Print",
359 self,
359 self,
360 shortcut=print_shortcut,
360 shortcut=print_shortcut,
361 triggered=self.print_action_active_frontend)
361 triggered=self.print_action_active_frontend)
362 self.add_menu_action(self.file_menu, self.print_action)
362 self.add_menu_action(self.file_menu, self.print_action)
363
363
364 if sys.platform == 'darwin':
364 if sys.platform != 'darwin':
365 # OSX always has Quit in the Application menu, only add it
365 # OSX always has Quit in the Application menu, only add it
366 # to the File menu elsewhere.
366 # to the File menu elsewhere.
367
367
368 self.file_menu.addSeparator()
368 self.file_menu.addSeparator()
369
369
370 self.quit_action = QtGui.QAction("&Quit",
370 self.quit_action = QtGui.QAction("&Quit",
371 self,
371 self,
372 shortcut=QtGui.QKeySequence.Quit,
372 shortcut=QtGui.QKeySequence.Quit,
373 triggered=self.close,
373 triggered=self.close,
374 )
374 )
375 self.add_menu_action(self.file_menu, self.quit_action)
375 self.add_menu_action(self.file_menu, self.quit_action)
376
376
377
377
378 def init_edit_menu(self):
378 def init_edit_menu(self):
379 self.edit_menu = self.menuBar().addMenu("&Edit")
379 self.edit_menu = self.menuBar().addMenu("&Edit")
380
380
381 self.undo_action = QtGui.QAction("&Undo",
381 self.undo_action = QtGui.QAction("&Undo",
382 self,
382 self,
383 shortcut="Ctrl+Z",
383 shortcut="Ctrl+Z",
384 statusTip="Undo last action if possible",
384 statusTip="Undo last action if possible",
385 triggered=self.undo_active_frontend
385 triggered=self.undo_active_frontend
386 )
386 )
387 self.add_menu_action(self.edit_menu, self.undo_action)
387 self.add_menu_action(self.edit_menu, self.undo_action)
388
388
389 self.redo_action = QtGui.QAction("&Redo",
389 self.redo_action = QtGui.QAction("&Redo",
390 self,
390 self,
391 shortcut="Ctrl+Shift+Z",
391 shortcut="Ctrl+Shift+Z",
392 statusTip="Redo last action if possible",
392 statusTip="Redo last action if possible",
393 triggered=self.redo_active_frontend)
393 triggered=self.redo_active_frontend)
394 self.add_menu_action(self.edit_menu, self.redo_action)
394 self.add_menu_action(self.edit_menu, self.redo_action)
395
395
396 self.edit_menu.addSeparator()
396 self.edit_menu.addSeparator()
397
397
398 self.cut_action = QtGui.QAction("&Cut",
398 self.cut_action = QtGui.QAction("&Cut",
399 self,
399 self,
400 shortcut=QtGui.QKeySequence.Cut,
400 shortcut=QtGui.QKeySequence.Cut,
401 triggered=self.cut_active_frontend
401 triggered=self.cut_active_frontend
402 )
402 )
403 self.add_menu_action(self.edit_menu, self.cut_action)
403 self.add_menu_action(self.edit_menu, self.cut_action)
404
404
405 self.copy_action = QtGui.QAction("&Copy",
405 self.copy_action = QtGui.QAction("&Copy",
406 self,
406 self,
407 shortcut=QtGui.QKeySequence.Copy,
407 shortcut=QtGui.QKeySequence.Copy,
408 triggered=self.copy_active_frontend
408 triggered=self.copy_active_frontend
409 )
409 )
410 self.add_menu_action(self.edit_menu, self.copy_action)
410 self.add_menu_action(self.edit_menu, self.copy_action)
411
411
412 self.copy_raw_action = QtGui.QAction("Copy (&Raw Text)",
412 self.copy_raw_action = QtGui.QAction("Copy (&Raw Text)",
413 self,
413 self,
414 shortcut="Ctrl+Shift+C",
414 shortcut="Ctrl+Shift+C",
415 triggered=self.copy_raw_active_frontend
415 triggered=self.copy_raw_active_frontend
416 )
416 )
417 self.add_menu_action(self.edit_menu, self.copy_raw_action)
417 self.add_menu_action(self.edit_menu, self.copy_raw_action)
418
418
419 self.paste_action = QtGui.QAction("&Paste",
419 self.paste_action = QtGui.QAction("&Paste",
420 self,
420 self,
421 shortcut=QtGui.QKeySequence.Paste,
421 shortcut=QtGui.QKeySequence.Paste,
422 triggered=self.paste_active_frontend
422 triggered=self.paste_active_frontend
423 )
423 )
424 self.add_menu_action(self.edit_menu, self.paste_action)
424 self.add_menu_action(self.edit_menu, self.paste_action)
425
425
426 self.edit_menu.addSeparator()
426 self.edit_menu.addSeparator()
427
427
428 self.select_all_action = QtGui.QAction("Select &All",
428 self.select_all_action = QtGui.QAction("Select &All",
429 self,
429 self,
430 shortcut="Ctrl+A",
430 shortcut="Ctrl+A",
431 triggered=self.select_all_active_frontend
431 triggered=self.select_all_active_frontend
432 )
432 )
433 self.add_menu_action(self.edit_menu, self.select_all_action)
433 self.add_menu_action(self.edit_menu, self.select_all_action)
434
434
435
435
436 def init_view_menu(self):
436 def init_view_menu(self):
437 self.view_menu = self.menuBar().addMenu("&View")
437 self.view_menu = self.menuBar().addMenu("&View")
438
438
439 if sys.platform != 'darwin':
439 if sys.platform != 'darwin':
440 # disable on OSX, where there is always a menu bar
440 # disable on OSX, where there is always a menu bar
441 self.toggle_menu_bar_act = QtGui.QAction("Toggle &Menu Bar",
441 self.toggle_menu_bar_act = QtGui.QAction("Toggle &Menu Bar",
442 self,
442 self,
443 shortcut="Ctrl+Shift+M",
443 shortcut="Ctrl+Shift+M",
444 statusTip="Toggle visibility of menubar",
444 statusTip="Toggle visibility of menubar",
445 triggered=self.toggle_menu_bar)
445 triggered=self.toggle_menu_bar)
446 self.add_menu_action(self.view_menu, self.toggle_menu_bar_act)
446 self.add_menu_action(self.view_menu, self.toggle_menu_bar_act)
447
447
448 fs_key = "Ctrl+Meta+F" if sys.platform == 'darwin' else "F11"
448 fs_key = "Ctrl+Meta+F" if sys.platform == 'darwin' else "F11"
449 self.full_screen_act = QtGui.QAction("&Full Screen",
449 self.full_screen_act = QtGui.QAction("&Full Screen",
450 self,
450 self,
451 shortcut=fs_key,
451 shortcut=fs_key,
452 statusTip="Toggle between Fullscreen and Normal Size",
452 statusTip="Toggle between Fullscreen and Normal Size",
453 triggered=self.toggleFullScreen)
453 triggered=self.toggleFullScreen)
454 self.add_menu_action(self.view_menu, self.full_screen_act)
454 self.add_menu_action(self.view_menu, self.full_screen_act)
455
455
456 self.view_menu.addSeparator()
456 self.view_menu.addSeparator()
457
457
458 self.increase_font_size = QtGui.QAction("Zoom &In",
458 self.increase_font_size = QtGui.QAction("Zoom &In",
459 self,
459 self,
460 shortcut="Ctrl++",
460 shortcut="Ctrl++",
461 triggered=self.increase_font_size_active_frontend
461 triggered=self.increase_font_size_active_frontend
462 )
462 )
463 self.add_menu_action(self.view_menu, self.increase_font_size)
463 self.add_menu_action(self.view_menu, self.increase_font_size)
464
464
465 self.decrease_font_size = QtGui.QAction("Zoom &Out",
465 self.decrease_font_size = QtGui.QAction("Zoom &Out",
466 self,
466 self,
467 shortcut="Ctrl+-",
467 shortcut="Ctrl+-",
468 triggered=self.decrease_font_size_active_frontend
468 triggered=self.decrease_font_size_active_frontend
469 )
469 )
470 self.add_menu_action(self.view_menu, self.decrease_font_size)
470 self.add_menu_action(self.view_menu, self.decrease_font_size)
471
471
472 self.reset_font_size = QtGui.QAction("Zoom &Reset",
472 self.reset_font_size = QtGui.QAction("Zoom &Reset",
473 self,
473 self,
474 shortcut="Ctrl+0",
474 shortcut="Ctrl+0",
475 triggered=self.reset_font_size_active_frontend
475 triggered=self.reset_font_size_active_frontend
476 )
476 )
477 self.add_menu_action(self.view_menu, self.reset_font_size)
477 self.add_menu_action(self.view_menu, self.reset_font_size)
478
478
479 self.view_menu.addSeparator()
479 self.view_menu.addSeparator()
480
480
481 self.clear_action = QtGui.QAction("&Clear Screen",
481 self.clear_action = QtGui.QAction("&Clear Screen",
482 self,
482 self,
483 shortcut='Ctrl+L',
483 shortcut='Ctrl+L',
484 statusTip="Clear the console",
484 statusTip="Clear the console",
485 triggered=self.clear_magic_active_frontend)
485 triggered=self.clear_magic_active_frontend)
486 self.add_menu_action(self.view_menu, self.clear_action)
486 self.add_menu_action(self.view_menu, self.clear_action)
487
487
488 def init_kernel_menu(self):
488 def init_kernel_menu(self):
489 self.kernel_menu = self.menuBar().addMenu("&Kernel")
489 self.kernel_menu = self.menuBar().addMenu("&Kernel")
490 # Qt on OSX maps Ctrl to Cmd, and Meta to Ctrl
490 # Qt on OSX maps Ctrl to Cmd, and Meta to Ctrl
491 # keep the signal shortcuts to ctrl, rather than
491 # keep the signal shortcuts to ctrl, rather than
492 # platform-default like we do elsewhere.
492 # platform-default like we do elsewhere.
493
493
494 ctrl = "Meta" if sys.platform == 'darwin' else "Ctrl"
494 ctrl = "Meta" if sys.platform == 'darwin' else "Ctrl"
495
495
496 self.interrupt_kernel_action = QtGui.QAction("Interrupt current Kernel",
496 self.interrupt_kernel_action = QtGui.QAction("Interrupt current Kernel",
497 self,
497 self,
498 triggered=self.interrupt_kernel_active_frontend,
498 triggered=self.interrupt_kernel_active_frontend,
499 shortcut=ctrl+"+C",
499 shortcut=ctrl+"+C",
500 )
500 )
501 self.add_menu_action(self.kernel_menu, self.interrupt_kernel_action)
501 self.add_menu_action(self.kernel_menu, self.interrupt_kernel_action)
502
502
503 self.restart_kernel_action = QtGui.QAction("Restart current Kernel",
503 self.restart_kernel_action = QtGui.QAction("Restart current Kernel",
504 self,
504 self,
505 triggered=self.restart_kernel_active_frontend,
505 triggered=self.restart_kernel_active_frontend,
506 shortcut=ctrl+"+.",
506 shortcut=ctrl+"+.",
507 )
507 )
508 self.add_menu_action(self.kernel_menu, self.restart_kernel_action)
508 self.add_menu_action(self.kernel_menu, self.restart_kernel_action)
509
509
510 self.kernel_menu.addSeparator()
510 self.kernel_menu.addSeparator()
511
511
512 def init_magic_menu(self):
512 def init_magic_menu(self):
513 self.magic_menu = self.menuBar().addMenu("&Magic")
513 self.magic_menu = self.menuBar().addMenu("&Magic")
514 self.all_magic_menu = self.magic_menu.addMenu("&All Magics")
514 self.all_magic_menu = self.magic_menu.addMenu("&All Magics")
515
515
516 self.reset_action = QtGui.QAction("&Reset",
516 self.reset_action = QtGui.QAction("&Reset",
517 self,
517 self,
518 statusTip="Clear all varible from workspace",
518 statusTip="Clear all varible from workspace",
519 triggered=self.reset_magic_active_frontend)
519 triggered=self.reset_magic_active_frontend)
520 self.add_menu_action(self.magic_menu, self.reset_action)
520 self.add_menu_action(self.magic_menu, self.reset_action)
521
521
522 self.history_action = QtGui.QAction("&History",
522 self.history_action = QtGui.QAction("&History",
523 self,
523 self,
524 statusTip="show command history",
524 statusTip="show command history",
525 triggered=self.history_magic_active_frontend)
525 triggered=self.history_magic_active_frontend)
526 self.add_menu_action(self.magic_menu, self.history_action)
526 self.add_menu_action(self.magic_menu, self.history_action)
527
527
528 self.save_action = QtGui.QAction("E&xport History ",
528 self.save_action = QtGui.QAction("E&xport History ",
529 self,
529 self,
530 statusTip="Export History as Python File",
530 statusTip="Export History as Python File",
531 triggered=self.save_magic_active_frontend)
531 triggered=self.save_magic_active_frontend)
532 self.add_menu_action(self.magic_menu, self.save_action)
532 self.add_menu_action(self.magic_menu, self.save_action)
533
533
534 self.who_action = QtGui.QAction("&Who",
534 self.who_action = QtGui.QAction("&Who",
535 self,
535 self,
536 statusTip="List interactive variable",
536 statusTip="List interactive variable",
537 triggered=self.who_magic_active_frontend)
537 triggered=self.who_magic_active_frontend)
538 self.add_menu_action(self.magic_menu, self.who_action)
538 self.add_menu_action(self.magic_menu, self.who_action)
539
539
540 self.who_ls_action = QtGui.QAction("Wh&o ls",
540 self.who_ls_action = QtGui.QAction("Wh&o ls",
541 self,
541 self,
542 statusTip="Return a list of interactive variable",
542 statusTip="Return a list of interactive variable",
543 triggered=self.who_ls_magic_active_frontend)
543 triggered=self.who_ls_magic_active_frontend)
544 self.add_menu_action(self.magic_menu, self.who_ls_action)
544 self.add_menu_action(self.magic_menu, self.who_ls_action)
545
545
546 self.whos_action = QtGui.QAction("Who&s",
546 self.whos_action = QtGui.QAction("Who&s",
547 self,
547 self,
548 statusTip="List interactive variable with detail",
548 statusTip="List interactive variable with detail",
549 triggered=self.whos_magic_active_frontend)
549 triggered=self.whos_magic_active_frontend)
550 self.add_menu_action(self.magic_menu, self.whos_action)
550 self.add_menu_action(self.magic_menu, self.whos_action)
551
551
552 # allmagics submenu:
552 # allmagics submenu:
553
553
554 #for now this is just a copy and paste, but we should get this dynamically
554 #for now this is just a copy and paste, but we should get this dynamically
555 magiclist=["%alias", "%autocall", "%automagic", "%bookmark", "%cd", "%clear",
555 magiclist=["%alias", "%autocall", "%automagic", "%bookmark", "%cd", "%clear",
556 "%colors", "%debug", "%dhist", "%dirs", "%doctest_mode", "%ed", "%edit", "%env", "%gui",
556 "%colors", "%debug", "%dhist", "%dirs", "%doctest_mode", "%ed", "%edit", "%env", "%gui",
557 "%guiref", "%hist", "%history", "%install_default_config", "%install_profiles",
557 "%guiref", "%hist", "%history", "%install_default_config", "%install_profiles",
558 "%less", "%load_ext", "%loadpy", "%logoff", "%logon", "%logstart", "%logstate",
558 "%less", "%load_ext", "%loadpy", "%logoff", "%logon", "%logstart", "%logstate",
559 "%logstop", "%lsmagic", "%macro", "%magic", "%man", "%more", "%notebook", "%page",
559 "%logstop", "%lsmagic", "%macro", "%magic", "%man", "%more", "%notebook", "%page",
560 "%pastebin", "%pdb", "%pdef", "%pdoc", "%pfile", "%pinfo", "%pinfo2", "%popd", "%pprint",
560 "%pastebin", "%pdb", "%pdef", "%pdoc", "%pfile", "%pinfo", "%pinfo2", "%popd", "%pprint",
561 "%precision", "%profile", "%prun", "%psearch", "%psource", "%pushd", "%pwd", "%pycat",
561 "%precision", "%profile", "%prun", "%psearch", "%psource", "%pushd", "%pwd", "%pycat",
562 "%pylab", "%quickref", "%recall", "%rehashx", "%reload_ext", "%rep", "%rerun",
562 "%pylab", "%quickref", "%recall", "%rehashx", "%reload_ext", "%rep", "%rerun",
563 "%reset", "%reset_selective", "%run", "%save", "%sc", "%sx", "%tb", "%time", "%timeit",
563 "%reset", "%reset_selective", "%run", "%save", "%sc", "%sx", "%tb", "%time", "%timeit",
564 "%unalias", "%unload_ext", "%who", "%who_ls", "%whos", "%xdel", "%xmode"]
564 "%unalias", "%unload_ext", "%who", "%who_ls", "%whos", "%xdel", "%xmode"]
565
565
566 def make_dynamic_magic(i):
566 def make_dynamic_magic(i):
567 def inner_dynamic_magic():
567 def inner_dynamic_magic():
568 self.active_frontend.execute(i)
568 self.active_frontend.execute(i)
569 inner_dynamic_magic.__name__ = "dynamics_magic_%s" % i
569 inner_dynamic_magic.__name__ = "dynamics_magic_%s" % i
570 return inner_dynamic_magic
570 return inner_dynamic_magic
571
571
572 for magic in magiclist:
572 for magic in magiclist:
573 xaction = QtGui.QAction(magic,
573 xaction = QtGui.QAction(magic,
574 self,
574 self,
575 triggered=make_dynamic_magic(magic)
575 triggered=make_dynamic_magic(magic)
576 )
576 )
577 self.all_magic_menu.addAction(xaction)
577 self.all_magic_menu.addAction(xaction)
578
578
579 def init_window_menu(self):
579 def init_window_menu(self):
580 self.window_menu = self.menuBar().addMenu("&Window")
580 self.window_menu = self.menuBar().addMenu("&Window")
581 if sys.platform == 'darwin':
581 if sys.platform == 'darwin':
582 # add min/maximize actions to OSX, which lacks default bindings.
582 # add min/maximize actions to OSX, which lacks default bindings.
583 self.minimizeAct = QtGui.QAction("Mini&mize",
583 self.minimizeAct = QtGui.QAction("Mini&mize",
584 self,
584 self,
585 shortcut="Ctrl+m",
585 shortcut="Ctrl+m",
586 statusTip="Minimize the window/Restore Normal Size",
586 statusTip="Minimize the window/Restore Normal Size",
587 triggered=self.toggleMinimized)
587 triggered=self.toggleMinimized)
588 # maximize is called 'Zoom' on OSX for some reason
588 # maximize is called 'Zoom' on OSX for some reason
589 self.maximizeAct = QtGui.QAction("&Zoom",
589 self.maximizeAct = QtGui.QAction("&Zoom",
590 self,
590 self,
591 shortcut="Ctrl+Shift+M",
591 shortcut="Ctrl+Shift+M",
592 statusTip="Maximize the window/Restore Normal Size",
592 statusTip="Maximize the window/Restore Normal Size",
593 triggered=self.toggleMaximized)
593 triggered=self.toggleMaximized)
594
594
595 self.add_menu_action(self.window_menu, self.minimizeAct)
595 self.add_menu_action(self.window_menu, self.minimizeAct)
596 self.add_menu_action(self.window_menu, self.maximizeAct)
596 self.add_menu_action(self.window_menu, self.maximizeAct)
597 self.window_menu.addSeparator()
597 self.window_menu.addSeparator()
598
598
599 prev_key = "Ctrl+Shift+Left" if sys.platform == 'darwin' else "Ctrl+PgUp"
599 prev_key = "Ctrl+Shift+Left" if sys.platform == 'darwin' else "Ctrl+PgUp"
600 self.prev_tab_act = QtGui.QAction("Pre&vious Tab",
600 self.prev_tab_act = QtGui.QAction("Pre&vious Tab",
601 self,
601 self,
602 shortcut=prev_key,
602 shortcut=prev_key,
603 statusTip="Select previous tab",
603 statusTip="Select previous tab",
604 triggered=self.prev_tab)
604 triggered=self.prev_tab)
605 self.add_menu_action(self.window_menu, self.prev_tab_act)
605 self.add_menu_action(self.window_menu, self.prev_tab_act)
606
606
607 next_key = "Ctrl+Shift+Right" if sys.platform == 'darwin' else "Ctrl+PgDown"
607 next_key = "Ctrl+Shift+Right" if sys.platform == 'darwin' else "Ctrl+PgDown"
608 self.next_tab_act = QtGui.QAction("Ne&xt Tab",
608 self.next_tab_act = QtGui.QAction("Ne&xt Tab",
609 self,
609 self,
610 shortcut=next_key,
610 shortcut=next_key,
611 statusTip="Select next tab",
611 statusTip="Select next tab",
612 triggered=self.next_tab)
612 triggered=self.next_tab)
613 self.add_menu_action(self.window_menu, self.next_tab_act)
613 self.add_menu_action(self.window_menu, self.next_tab_act)
614
614
615 def init_help_menu(self):
615 def init_help_menu(self):
616 # please keep the Help menu in Mac Os even if empty. It will
616 # please keep the Help menu in Mac Os even if empty. It will
617 # automatically contain a search field to search inside menus and
617 # automatically contain a search field to search inside menus and
618 # please keep it spelled in English, as long as Qt Doesn't support
618 # please keep it spelled in English, as long as Qt Doesn't support
619 # a QAction.MenuRole like HelpMenuRole otherwise it will loose
619 # a QAction.MenuRole like HelpMenuRole otherwise it will loose
620 # this search field fonctionality
620 # this search field fonctionality
621
621
622 self.help_menu = self.menuBar().addMenu("&Help")
622 self.help_menu = self.menuBar().addMenu("&Help")
623
623
624
624
625 # Help Menu
625 # Help Menu
626
626
627 self.intro_active_frontend_action = QtGui.QAction("&Intro to IPython",
627 self.intro_active_frontend_action = QtGui.QAction("&Intro to IPython",
628 self,
628 self,
629 triggered=self.intro_active_frontend
629 triggered=self.intro_active_frontend
630 )
630 )
631 self.add_menu_action(self.help_menu, self.intro_active_frontend_action)
631 self.add_menu_action(self.help_menu, self.intro_active_frontend_action)
632
632
633 self.quickref_active_frontend_action = QtGui.QAction("IPython &Cheat Sheet",
633 self.quickref_active_frontend_action = QtGui.QAction("IPython &Cheat Sheet",
634 self,
634 self,
635 triggered=self.quickref_active_frontend
635 triggered=self.quickref_active_frontend
636 )
636 )
637 self.add_menu_action(self.help_menu, self.quickref_active_frontend_action)
637 self.add_menu_action(self.help_menu, self.quickref_active_frontend_action)
638
638
639 self.guiref_active_frontend_action = QtGui.QAction("&Qt Console",
639 self.guiref_active_frontend_action = QtGui.QAction("&Qt Console",
640 self,
640 self,
641 triggered=self.guiref_active_frontend
641 triggered=self.guiref_active_frontend
642 )
642 )
643 self.add_menu_action(self.help_menu, self.guiref_active_frontend_action)
643 self.add_menu_action(self.help_menu, self.guiref_active_frontend_action)
644
644
645 self.onlineHelpAct = QtGui.QAction("Open Online &Help",
645 self.onlineHelpAct = QtGui.QAction("Open Online &Help",
646 self,
646 self,
647 triggered=self._open_online_help)
647 triggered=self._open_online_help)
648 self.add_menu_action(self.help_menu, self.onlineHelpAct)
648 self.add_menu_action(self.help_menu, self.onlineHelpAct)
649
649
650 # minimize/maximize/fullscreen actions:
650 # minimize/maximize/fullscreen actions:
651
651
652 def toggle_menu_bar(self):
652 def toggle_menu_bar(self):
653 menu_bar = self.menuBar()
653 menu_bar = self.menuBar()
654 if menu_bar.isVisible():
654 if menu_bar.isVisible():
655 menu_bar.setVisible(False)
655 menu_bar.setVisible(False)
656 else:
656 else:
657 menu_bar.setVisible(True)
657 menu_bar.setVisible(True)
658
658
659 def toggleMinimized(self):
659 def toggleMinimized(self):
660 if not self.isMinimized():
660 if not self.isMinimized():
661 self.showMinimized()
661 self.showMinimized()
662 else:
662 else:
663 self.showNormal()
663 self.showNormal()
664
664
665 def _open_online_help(self):
665 def _open_online_help(self):
666 filename="http://ipython.org/ipython-doc/stable/index.html"
666 filename="http://ipython.org/ipython-doc/stable/index.html"
667 webbrowser.open(filename, new=1, autoraise=True)
667 webbrowser.open(filename, new=1, autoraise=True)
668
668
669 def toggleMaximized(self):
669 def toggleMaximized(self):
670 if not self.isMaximized():
670 if not self.isMaximized():
671 self.showMaximized()
671 self.showMaximized()
672 else:
672 else:
673 self.showNormal()
673 self.showNormal()
674
674
675 # Min/Max imizing while in full screen give a bug
675 # Min/Max imizing while in full screen give a bug
676 # when going out of full screen, at least on OSX
676 # when going out of full screen, at least on OSX
677 def toggleFullScreen(self):
677 def toggleFullScreen(self):
678 if not self.isFullScreen():
678 if not self.isFullScreen():
679 self.showFullScreen()
679 self.showFullScreen()
680 if sys.platform == 'darwin':
680 if sys.platform == 'darwin':
681 self.maximizeAct.setEnabled(False)
681 self.maximizeAct.setEnabled(False)
682 self.minimizeAct.setEnabled(False)
682 self.minimizeAct.setEnabled(False)
683 else:
683 else:
684 self.showNormal()
684 self.showNormal()
685 if sys.platform == 'darwin':
685 if sys.platform == 'darwin':
686 self.maximizeAct.setEnabled(True)
686 self.maximizeAct.setEnabled(True)
687 self.minimizeAct.setEnabled(True)
687 self.minimizeAct.setEnabled(True)
688
688
689 def close_active_frontend(self):
689 def close_active_frontend(self):
690 self.close_tab(self.active_frontend)
690 self.close_tab(self.active_frontend)
691
691
692 def restart_kernel_active_frontend(self):
692 def restart_kernel_active_frontend(self):
693 self.active_frontend.request_restart_kernel()
693 self.active_frontend.request_restart_kernel()
694
694
695 def interrupt_kernel_active_frontend(self):
695 def interrupt_kernel_active_frontend(self):
696 self.active_frontend.request_interrupt_kernel()
696 self.active_frontend.request_interrupt_kernel()
697
697
698 def cut_active_frontend(self):
698 def cut_active_frontend(self):
699 self.active_frontend.cut_action.trigger()
699 self.active_frontend.cut_action.trigger()
700
700
701 def copy_active_frontend(self):
701 def copy_active_frontend(self):
702 self.active_frontend.copy_action.trigger()
702 self.active_frontend.copy_action.trigger()
703
703
704 def copy_raw_active_frontend(self):
704 def copy_raw_active_frontend(self):
705 self.active_frontend._copy_raw_action.trigger()
705 self.active_frontend._copy_raw_action.trigger()
706
706
707 def paste_active_frontend(self):
707 def paste_active_frontend(self):
708 self.active_frontend.paste_action.trigger()
708 self.active_frontend.paste_action.trigger()
709
709
710 def undo_active_frontend(self):
710 def undo_active_frontend(self):
711 self.active_frontend.undo()
711 self.active_frontend.undo()
712
712
713 def redo_active_frontend(self):
713 def redo_active_frontend(self):
714 self.active_frontend.redo()
714 self.active_frontend.redo()
715
715
716 def reset_magic_active_frontend(self):
716 def reset_magic_active_frontend(self):
717 self.active_frontend.execute("%reset")
717 self.active_frontend.execute("%reset")
718
718
719 def history_magic_active_frontend(self):
719 def history_magic_active_frontend(self):
720 self.active_frontend.execute("%history")
720 self.active_frontend.execute("%history")
721
721
722 def save_magic_active_frontend(self):
722 def save_magic_active_frontend(self):
723 self.active_frontend.save_magic()
723 self.active_frontend.save_magic()
724
724
725 def clear_magic_active_frontend(self):
725 def clear_magic_active_frontend(self):
726 self.active_frontend.execute("%clear")
726 self.active_frontend.execute("%clear")
727
727
728 def who_magic_active_frontend(self):
728 def who_magic_active_frontend(self):
729 self.active_frontend.execute("%who")
729 self.active_frontend.execute("%who")
730
730
731 def who_ls_magic_active_frontend(self):
731 def who_ls_magic_active_frontend(self):
732 self.active_frontend.execute("%who_ls")
732 self.active_frontend.execute("%who_ls")
733
733
734 def whos_magic_active_frontend(self):
734 def whos_magic_active_frontend(self):
735 self.active_frontend.execute("%whos")
735 self.active_frontend.execute("%whos")
736
736
737 def print_action_active_frontend(self):
737 def print_action_active_frontend(self):
738 self.active_frontend.print_action.trigger()
738 self.active_frontend.print_action.trigger()
739
739
740 def export_action_active_frontend(self):
740 def export_action_active_frontend(self):
741 self.active_frontend.export_action.trigger()
741 self.active_frontend.export_action.trigger()
742
742
743 def select_all_active_frontend(self):
743 def select_all_active_frontend(self):
744 self.active_frontend.select_all_action.trigger()
744 self.active_frontend.select_all_action.trigger()
745
745
746 def increase_font_size_active_frontend(self):
746 def increase_font_size_active_frontend(self):
747 self.active_frontend.increase_font_size.trigger()
747 self.active_frontend.increase_font_size.trigger()
748
748
749 def decrease_font_size_active_frontend(self):
749 def decrease_font_size_active_frontend(self):
750 self.active_frontend.decrease_font_size.trigger()
750 self.active_frontend.decrease_font_size.trigger()
751
751
752 def reset_font_size_active_frontend(self):
752 def reset_font_size_active_frontend(self):
753 self.active_frontend.reset_font_size.trigger()
753 self.active_frontend.reset_font_size.trigger()
754
754
755 def guiref_active_frontend(self):
755 def guiref_active_frontend(self):
756 self.active_frontend.execute("%guiref")
756 self.active_frontend.execute("%guiref")
757
757
758 def intro_active_frontend(self):
758 def intro_active_frontend(self):
759 self.active_frontend.execute("?")
759 self.active_frontend.execute("?")
760
760
761 def quickref_active_frontend(self):
761 def quickref_active_frontend(self):
762 self.active_frontend.execute("%quickref")
762 self.active_frontend.execute("%quickref")
763 #---------------------------------------------------------------------------
763 #---------------------------------------------------------------------------
764 # QWidget interface
764 # QWidget interface
765 #---------------------------------------------------------------------------
765 #---------------------------------------------------------------------------
766
766
767 def closeEvent(self, event):
767 def closeEvent(self, event):
768 """ Forward the close event to every tabs contained by the windows
768 """ Forward the close event to every tabs contained by the windows
769 """
769 """
770 if self.tab_widget.count() == 0:
770 if self.tab_widget.count() == 0:
771 # no tabs, just close
771 # no tabs, just close
772 event.accept()
772 event.accept()
773 return
773 return
774 # Do Not loop on the widget count as it change while closing
774 # Do Not loop on the widget count as it change while closing
775 title = self.window().windowTitle()
775 title = self.window().windowTitle()
776 cancel = QtGui.QMessageBox.Cancel
776 cancel = QtGui.QMessageBox.Cancel
777 okay = QtGui.QMessageBox.Ok
777 okay = QtGui.QMessageBox.Ok
778
778
779 if self.confirm_exit:
779 if self.confirm_exit:
780 msg = "Close all tabs, stop all kernels, and Quit?"
780 msg = "Close all tabs, stop all kernels, and Quit?"
781 closeall = QtGui.QPushButton("&Yes, quit everything", self)
781 closeall = QtGui.QPushButton("&Yes, quit everything", self)
782 closeall.setShortcut('Y')
782 closeall.setShortcut('Y')
783 box = QtGui.QMessageBox(QtGui.QMessageBox.Question,
783 box = QtGui.QMessageBox(QtGui.QMessageBox.Question,
784 title, msg)
784 title, msg)
785 # box.setInformativeText(info)
785 # box.setInformativeText(info)
786 box.addButton(cancel)
786 box.addButton(cancel)
787 box.addButton(closeall, QtGui.QMessageBox.YesRole)
787 box.addButton(closeall, QtGui.QMessageBox.YesRole)
788 box.setDefaultButton(closeall)
788 box.setDefaultButton(closeall)
789 box.setEscapeButton(cancel)
789 box.setEscapeButton(cancel)
790 pixmap = QtGui.QPixmap(self._app.icon.pixmap(QtCore.QSize(64,64)))
790 pixmap = QtGui.QPixmap(self._app.icon.pixmap(QtCore.QSize(64,64)))
791 box.setIconPixmap(pixmap)
791 box.setIconPixmap(pixmap)
792 reply = box.exec_()
792 reply = box.exec_()
793 else:
793 else:
794 reply = okay
794 reply = okay
795
795
796 if reply == cancel:
796 if reply == cancel:
797 return
797 return
798 if reply == okay:
798 if reply == okay:
799 while self.tab_widget.count() >= 1:
799 while self.tab_widget.count() >= 1:
800 # prevent further confirmations:
800 # prevent further confirmations:
801 widget = self.active_frontend
801 widget = self.active_frontend
802 widget._confirm_exit = False
802 widget._confirm_exit = False
803 self.close_tab(widget)
803 self.close_tab(widget)
804
804
805 event.accept()
805 event.accept()
806
806
General Comments 0
You need to be logged in to leave comments. Login now