From 9216c7b683958cb985aa7bd0fd0723a60419c193 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 28 Feb 2019 19:29:00 +0100 Subject: [PATCH 1/3] Use new API to open notebooks directly from Spyder's 'Open file' dialog --- spyder_notebook/notebookplugin.py | 33 +++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/spyder_notebook/notebookplugin.py b/spyder_notebook/notebookplugin.py index ec2ab32a..54615bf5 100644 --- a/spyder_notebook/notebookplugin.py +++ b/spyder_notebook/notebookplugin.py @@ -13,7 +13,7 @@ # Qt imports from qtpy import PYQT4, PYSIDE -from qtpy.compat import getsavefilename, getopenfilenames +from qtpy.compat import getsavefilename from qtpy.QtCore import Qt, QEventLoop, QTimer, Signal from qtpy.QtGui import QIcon from qtpy.QtWidgets import QApplication, QMessageBox, QVBoxLayout, QMenu @@ -63,6 +63,9 @@ class NotebookPlugin(SpyderPluginWidget): CONF_SECTION = 'notebook' focus_changed = Signal() + # To open these file extensions directly here + file_extensions = ['.ipynb'] + def __init__(self, parent, testing=False): """Constructor.""" SpyderPluginWidget.__init__(self, parent) @@ -114,7 +117,7 @@ def __init__(self, parent, testing=False): layout.addWidget(self.tabwidget) self.setLayout(layout) - # ------ SpyderPluginMixin API -------------------------------------------- + # ------ SpyderPluginWidget API ------------------------------------------- def on_first_registration(self): """Action to be performed on first plugin registration.""" self.main.tabify_plugins(self.main.editor, self) @@ -125,7 +128,6 @@ def update_font(self): # this. pass - # ------ SpyderPluginWidget API ------------------------------------------- def get_plugin_title(self): """Return widget title.""" title = _('Notebook') @@ -169,10 +171,6 @@ def get_plugin_actions(self): _("Save as..."), icon=ima.icon('filesaveas'), triggered=self.save_as) - open_action = create_action(self, - _("Open..."), - icon=ima.icon('fileopen'), - triggered=self.open_notebook) self.open_console_action = create_action(self, _("Open console"), icon=ima.icon( @@ -182,9 +180,11 @@ def get_plugin_actions(self): create_action(self, _("Clear this list"), triggered=self.clear_recent_notebooks) # Plugin actions - self.menu_actions = [create_nb_action, open_action, - self.recent_notebook_menu, MENU_SEPARATOR, - self.save_as_action, MENU_SEPARATOR, + self.menu_actions = [create_nb_action, + self.recent_notebook_menu, + MENU_SEPARATOR, + self.save_as_action, + MENU_SEPARATOR, self.open_console_action] self.setup_menu_actions() @@ -213,6 +213,10 @@ def check_compatibility(self): value = False return value, message + def open_file(self, filename): + """Open notebooks using Spyder's 'Open file' dialog.""" + self.create_new_client(filename=filename) + # ------ Public API (for clients) ----------------------------------------- def setup_menu_actions(self): """Setup and update the menu actions.""" @@ -427,15 +431,6 @@ def save_as(self, name=None, close=False): self.close_client(save=True) self.create_new_client(filename=filename) - def open_notebook(self, filenames=None): - """Open a notebook from file.""" - if not filenames: - filenames, _selfilter = getopenfilenames(self, _("Open notebook"), - '', FILES_FILTER) - if filenames: - for filename in filenames: - self.create_new_client(filename=filename) - def open_console(self, client=None): """Open an IPython console for the given client or the current one.""" if not client: From 2036fca900f7a02f2caa7d4633669efe7061c1bd Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 28 Feb 2019 19:30:52 +0100 Subject: [PATCH 2/3] Use switch_to_plugin when adding a new tab instead of raise This makes things work with undocked windows in Spyder 4 --- spyder_notebook/notebookplugin.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spyder_notebook/notebookplugin.py b/spyder_notebook/notebookplugin.py index 54615bf5..d38c09f4 100644 --- a/spyder_notebook/notebookplugin.py +++ b/spyder_notebook/notebookplugin.py @@ -456,9 +456,8 @@ def add_tab(self, widget): index = self.tabwidget.addTab(widget, widget.get_short_name()) self.tabwidget.setCurrentIndex(index) self.tabwidget.setTabToolTip(index, widget.get_filename()) - if self.dockwidget and not self.ismaximized: - self.dockwidget.setVisible(True) - self.dockwidget.raise_() + if self.dockwidget: + self.switch_to_plugin() self.activateWindow() widget.notebookwidget.setFocus() From c88909bf9f7a6713df4207eba25b241f5268eaa7 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 2 Mar 2019 15:47:50 +0100 Subject: [PATCH 3/3] Use public API to save notebooks when pressing the Save button in Spyder's toolbar --- spyder_notebook/notebookplugin.py | 54 ++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/spyder_notebook/notebookplugin.py b/spyder_notebook/notebookplugin.py index d38c09f4..c3bc77ed 100644 --- a/spyder_notebook/notebookplugin.py +++ b/spyder_notebook/notebookplugin.py @@ -66,6 +66,9 @@ class NotebookPlugin(SpyderPluginWidget): # To open these file extensions directly here file_extensions = ['.ipynb'] + # Tell Spyder that this plugin is able to save files + can_save_files = True + def __init__(self, parent, testing=False): """Constructor.""" SpyderPluginWidget.__init__(self, parent) @@ -369,24 +372,7 @@ def close_client(self, index=None, client=None, save=False): is_welcome = client.get_filename() == WELCOME if not save and not is_welcome: - client.save() - wait_save = QEventLoop() - QTimer.singleShot(1000, wait_save.quit) - wait_save.exec_() - path = client.get_filename() - fname = osp.basename(path) - nb_contents = nbformat.read(path, as_version=4) - - if ('untitled' in fname and len(nb_contents['cells']) > 0 and - len(nb_contents['cells'][0]['source']) > 0): - buttons = QMessageBox.Yes | QMessageBox.No - answer = QMessageBox.question(self, self.get_plugin_title(), - _("{0} has been modified." - "
Do you want to " - "save changes?".format(fname)), - buttons) - if answer == QMessageBox.Yes: - self.save_as(close=True) + self.save_untitled() if not is_welcome: client.shutdown_kernel() client.close() @@ -413,6 +399,38 @@ def create_welcome_client(self): self.add_tab(client) return client + def save_file(self): + """Save current notebook.""" + client = self.get_current_client() + if 'untitled' in client.get_filename(): + self.save_untitled() + else: + client.save() + + def save_untitled(self): + """Save operation for untitled notebooks.""" + client = self.get_current_client() + client.save() + wait_save = QEventLoop() + QTimer.singleShot(1000, wait_save.quit) + wait_save.exec_() + path = client.get_filename() + fname = osp.basename(path) + nb_contents = nbformat.read(path, as_version=4) + + if ('untitled' in fname and len(nb_contents['cells']) > 0 and + len(nb_contents['cells'][0]['source']) > 0): + buttons = QMessageBox.Yes | QMessageBox.No + answer = QMessageBox.question( + self, + self.get_plugin_title(), + _("{0} has been modified." + "
Do you want to " + "save changes?".format(fname)), + buttons) + if answer == QMessageBox.Yes: + self.save_as(close=True) + def save_as(self, name=None, close=False): """Save notebook as.""" current_client = self.get_current_client()