def closeEvent(self, event): """ Forward the close event to every tabs contained by the windows """ if self.tab_widget.count() == 0: # no tabs, just close event.accept() return # Do Not loop on the widget count as it change while closing title = self.window().windowTitle() cancel = QtGui.QMessageBox.Cancel okay = QtGui.QMessageBox.Ok accept_role = QtGui.QMessageBox.AcceptRole if self.confirm_exit: if self.tab_widget.count() > 1: msg = "Close all tabs, stop all kernels, and Quit?" else: msg = "Close console, stop kernel, and Quit?" info = "Kernels not started here (e.g. notebooks) will be left alone." closeall = QtGui.QPushButton("&Quit", self) closeall.setShortcut('Q') box = QtGui.QMessageBox(QtGui.QMessageBox.Question, title, msg) box.setInformativeText(info) box.addButton(cancel) box.addButton(closeall, QtGui.QMessageBox.YesRole) box.setDefaultButton(closeall) box.setEscapeButton(cancel) pixmap = QtGui.QPixmap(self._app.icon.pixmap(QtCore.QSize(64, 64))) box.setIconPixmap(pixmap) reply = box.exec_() else: reply = okay if reply == cancel: event.ignore() return if reply == okay or reply == accept_role: while self.tab_widget.count() >= 1: # prevent further confirmations: widget = self.active_frontend widget._confirm_exit = False self.close_tab(widget) event.accept()
def close_tab(self, current_tab): """ Called when you need to try to close a tab. It takes the number of the tab to be closed as argument, or a reference to the widget inside this tab """ # let's be sure "tab" and "closing widget" are respectively the index # of the tab to close and a reference to the frontend to close if type(current_tab) is not int: current_tab = self.tab_widget.indexOf(current_tab) closing_widget = self.tab_widget.widget(current_tab) # when trying to be closed, widget might re-send a request to be # closed again, but will be deleted when event will be processed. So # need to check that widget still exists and skip if not. One example # of this is when 'exit' is sent in a slave tab. 'exit' will be # re-sent by this function on the master widget, which ask all slave # widgets to exit if closing_widget is None: return #get a list of all slave widgets on the same kernel. slave_tabs = self.find_slave_widgets(closing_widget) keepkernel = None #Use the prompt by default if hasattr(closing_widget, '_keep_kernel_on_exit'): #set by exit magic keepkernel = closing_widget._keep_kernel_on_exit # If signal sent by exit magic (_keep_kernel_on_exit, exist and not None) # we set local slave tabs._hidden to True to avoid prompting for kernel # restart when they get the signal. and then "forward" the 'exit' # to the main window if keepkernel is not None: for tab in slave_tabs: tab._hidden = True if closing_widget in slave_tabs: try: self.find_master_tab(closing_widget).execute('exit') except AttributeError: self.log.info( "Master already closed or not local, closing only current tab" ) self.tab_widget.removeTab(current_tab) self.update_tab_bar_visibility() return kernel_client = closing_widget.kernel_client kernel_manager = closing_widget.kernel_manager if keepkernel is None and not closing_widget._confirm_exit: # don't prompt, just terminate the kernel if we own it # or leave it alone if we don't keepkernel = closing_widget._existing if keepkernel is None: #show prompt if kernel_client and kernel_client.channels_running: title = self.window().windowTitle() cancel = QtGui.QMessageBox.Cancel okay = QtGui.QMessageBox.Ok if closing_widget._may_close: msg = "You are closing the tab : " + '"' + self.tab_widget.tabText( current_tab) + '"' info = "Would you like to quit the Kernel and close all attached Consoles as well?" justthis = QtGui.QPushButton("&No, just this Tab", self) justthis.setShortcut('N') closeall = QtGui.QPushButton("&Yes, close all", self) closeall.setShortcut('Y') # allow ctrl-d ctrl-d exit, like in terminal closeall.setShortcut('Ctrl+D') box = QtGui.QMessageBox(QtGui.QMessageBox.Question, title, msg) box.setInformativeText(info) box.addButton(cancel) box.addButton(justthis, QtGui.QMessageBox.NoRole) box.addButton(closeall, QtGui.QMessageBox.YesRole) box.setDefaultButton(closeall) box.setEscapeButton(cancel) pixmap = QtGui.QPixmap( self._app.icon.pixmap(QtCore.QSize(64, 64))) box.setIconPixmap(pixmap) reply = box.exec_() if reply == 1: # close All for slave in slave_tabs: background(slave.kernel_client.stop_channels) self.tab_widget.removeTab( self.tab_widget.indexOf(slave)) kernel_manager.shutdown_kernel() self.tab_widget.removeTab(current_tab) background(kernel_client.stop_channels) elif reply == 0: # close Console if not closing_widget._existing: # Have kernel: don't quit, just close the tab closing_widget.execute("exit True") self.tab_widget.removeTab(current_tab) background(kernel_client.stop_channels) else: reply = QtGui.QMessageBox.question( self, title, "Are you sure you want to close this Console?" + "\nThe Kernel and other Consoles will remain active.", okay | cancel, defaultButton=okay) if reply == okay: self.tab_widget.removeTab(current_tab) elif keepkernel: #close console but leave kernel running (no prompt) self.tab_widget.removeTab(current_tab) background(kernel_client.stop_channels) else: #close console and kernel (no prompt) self.tab_widget.removeTab(current_tab) if kernel_client and kernel_client.channels_running: for slave in slave_tabs: background(slave.kernel_client.stop_channels) self.tab_widget.removeTab(self.tab_widget.indexOf(slave)) if kernel_manager: kernel_manager.shutdown_kernel() background(kernel_client.stop_channels) self.update_tab_bar_visibility()