Esempio n. 1
0
    def __init__(self, parent, font=None):
        super(MultiFileEditor, self).__init__(parent)
        if not font:
            font = text_font()

        completion_enabled = True
        if CONF.has(ENABLE_COMPLETION_KEY):
            completion_enabled = CONF.get(ENABLE_COMPLETION_KEY)

        # layout
        self.editors = MultiPythonFileInterpreter(
            font=font,
            default_content=DEFAULT_SCRIPT_CONTENT,
            parent=self,
            completion_enabled=completion_enabled)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.setAcceptDrops(True)

        # attributes
        self.tabs_open_on_closing = None
        self.editors_zoom_level = None
Esempio n. 2
0
class MultiFileEditor(PluginWidget):
    """Provides a tab widget for editing multiple files"""
    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(
            default_content=DEFAULT_CONTENT, parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        # attributes
        self.run_action = create_action(
            self,
            "Run",
            on_triggered=self.editors.execute_current,
            shortcut="Ctrl+Return",
            shortcut_context=Qt.ApplicationShortcut)
        self.abort_action = create_action(
            self, "Abort", on_triggered=self.editors.abort_current)

        self.editor_actions = [self.run_action, self.abort_action]

    def execute_current(self):
        '''This is used by MainWindow to execute a file after opening it'''
        return self.editors.execute_current()

    # ----------- Plugin API --------------------

    def app_closing(self):
        """
        Tries to close all editors
        :return: True if editors can be closed, false if cancelled
        """
        return self.editors.close_all()

    def get_plugin_title(self):
        return "Editor"

    def readSettings(self, _):
        pass

    def writeSettings(self, _):
        pass

    def register_plugin(self):
        self.main.add_dockwidget(self)
        # menus
        add_actions(self.main.editor_menu, self.editor_actions)

    # ----------- Plugin Behaviour --------------------

    def open_file_in_new_tab(self, filepath):
        return self.editors.open_file_in_new_tab(filepath)

    def save_current_file(self):
        self.editors.save_current_file()
Esempio n. 3
0
class MultiFileEditor(PluginWidget):
    """Provides a tab widget for editing multiple files"""

    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(default_content=DEFAULT_CONTENT,
                                                  parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        # attributes
        self.run_action = create_action(self, "Run",
                                        on_triggered=self.editors.execute_current,
                                        shortcut="Ctrl+Return",
                                        shortcut_context=Qt.ApplicationShortcut)
        self.abort_action = create_action(self, "Abort",
                                          on_triggered=self.editors.abort_current)

        self.editor_actions = [self.run_action, self.abort_action]

    def execute_current(self):
        '''This is used by MainWindow to execute a file after opening it'''
        return self.editors.execute_current()

    # ----------- Plugin API --------------------

    def app_closing(self):
        """
        Tries to close all editors
        :return: True if editors can be closed, false if cancelled
        """
        return self.editors.close_all()

    def get_plugin_title(self):
        return "Editor"

    def readSettings(self, _):
        pass

    def writeSettings(self, _):
        pass

    def register_plugin(self):
        self.main.add_dockwidget(self)
        # menus
        add_actions(self.main.editor_menu, self.editor_actions)

    # ----------- Plugin Behaviour --------------------

    def open_file_in_new_tab(self, filepath):
        return self.editors.open_file_in_new_tab(filepath)

    def save_current_file(self):
        self.editors.save_current_file()
 def test_open_file_in_new_tab_no_import_added(self):
     test_string = "Test file\n"
     widget = MultiPythonFileInterpreter()
     mock_open_func = mock.mock_open(read_data=test_string)
     with mock.patch(widget.__module__ + '.open', mock_open_func, create=True):
         with mock.patch(PERMISSION_BOX_FUNC, lambda: True):
             widget.open_file_in_new_tab(test_string)
     self.assertNotIn(MANTID_API_IMPORT,
                      widget.current_editor().editor.text())
Esempio n. 5
0
 def test_open_file_in_new_tab_no_import_added(self):
     test_string = "Test file\n"
     widget = MultiPythonFileInterpreter()
     mock_open_func = mock.mock_open(read_data=test_string)
     with mock.patch(widget.__module__ + '.open',
                     mock_open_func,
                     create=True):
         with mock.patch(PERMISSION_BOX_FUNC, lambda: True):
             widget.open_file_in_new_tab(test_string)
     self.assertNotIn(MANTID_API_IMPORT,
                      widget.current_editor().editor.text())
 def test_open_file_in_new_tab_import_added(self):
     test_string = "Test file\nLoad()"
     widget = MultiPythonFileInterpreter()
     mock_open_func = mock.mock_open(read_data=test_string)
     with mock.patch(widget.__module__ + '.open', mock_open_func, create=True):
         with mock.patch(PERMISSION_BOX_FUNC, lambda: True):
             widget.open_file_in_new_tab(test_string)
     self.assertEqual(widget.current_editor().editor.isModified(), True,
                      msg="Script not marked as modified.")
     self.assertIn(MANTID_API_IMPORT, widget.current_editor().editor.text(),
                   msg="'simpleapi' import not added to script.")
Esempio n. 7
0
    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(font=text_font(),
                                                  default_content=DEFAULT_CONTENT,
                                                  parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.setAcceptDrops(True)

        # attributes
        self.tabs_open_on_closing = None
Esempio n. 8
0
    def test_editor_widget_deletes_find_replace_dialog(self):
        widget = MultiPythonFileInterpreter()
        self.assertEqual(1, widget.editor_count)
        widget.append_new_editor()
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 2)
        widget.current_editor().show_find_replace_dialog()
        self.assert_number_of_widgets_matching("Embedded", 1)

        widget.close_tab(1)

        QApplication.processEvents()
        # there will always be 1, because we never allow an empty editor widget
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 1)
        self.assert_number_of_widgets_matching("Embedded", 0)

        # close the whole widget, this should delete everything from the QApplication
        widget.close()
        QApplication.processEvents()
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 0)
        self.assert_no_toplevel_widgets()
Esempio n. 9
0
    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(
            default_content=DEFAULT_CONTENT, parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        # attributes
        self.run_action = create_action(
            self,
            "Run",
            on_triggered=self.editors.execute_current,
            shortcut="Ctrl+Return",
            shortcut_context=Qt.ApplicationShortcut)
        self.abort_action = create_action(
            self, "Abort", on_triggered=self.editors.abort_current)

        self.editor_actions = [self.run_action, self.abort_action]
Esempio n. 10
0
    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(default_content=DEFAULT_CONTENT,
                                                  parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        # attributes
        self.run_action = create_action(self, "Run",
                                        on_triggered=self.editors.execute_current,
                                        shortcut="Ctrl+Return",
                                        shortcut_context=Qt.ApplicationShortcut)
        self.abort_action = create_action(self, "Abort",
                                          on_triggered=self.editors.abort_current)

        self.editor_actions = [self.run_action, self.abort_action]
    def test_editor_widget_doesnt_create_find_replace_unless_requested(self):
        widget = MultiPythonFileInterpreter()
        self.assertEqual(1, widget.editor_count)
        widget.append_new_editor()
        self.assert_number_of_widgets_matching(
            ".interpreter.PythonFileInterpreter", 2)
        self.assert_number_of_widgets_matching("Embedded", 0)

        widget.close_tab(1)

        QApplication.processEvents()
        # there will always be 1, because we never allow an empty editor widget
        self.assert_number_of_widgets_matching(
            ".interpreter.PythonFileInterpreter", 1)
        self.assert_number_of_widgets_matching("Embedded", 0)
Esempio n. 12
0
 def test_open_file_in_new_tab_import_added(self):
     test_string = "Test file\nLoad()"
     widget = MultiPythonFileInterpreter()
     mock_open_func = mock.mock_open(read_data=test_string)
     with mock.patch(widget.__module__ + '.open',
                     mock_open_func,
                     create=True):
         with mock.patch(PERMISSION_BOX_FUNC, lambda: True):
             widget.open_file_in_new_tab(test_string)
     self.assertEqual(widget.current_editor().editor.isModified(),
                      True,
                      msg="Script not marked as modified.")
     self.assertIn(MANTID_API_IMPORT,
                   widget.current_editor().editor.text(),
                   msg="'simpleapi' import not added to script.")
Esempio n. 13
0
class MultiFileEditor(PluginWidget):
    """Provides a tab widget for editing multiple files"""
    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(
            default_content=DEFAULT_CONTENT, parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.setAcceptDrops(True)

        # attributes
        self.tabs_open_on_closing = None

        self.run_action = create_action(
            self,
            "Run",
            on_triggered=self.editors.execute_current,
            shortcut=("Ctrl+Return", "Ctrl+Enter"),
            shortcut_context=Qt.ApplicationShortcut)

        self.abort_action = create_action(
            self, "Abort", on_triggered=self.editors.abort_current)

        # menu action to toggle the find/replace dialog
        self.toggle_find_replace = create_action(
            self,
            'Find/Replace...',
            on_triggered=self.editors.toggle_find_replace_dialog,
            shortcut='Ctrl+F')

        self.toggle_comment_action = create_action(
            self.editors.current_editor(),
            "Comment/Uncomment",
            on_triggered=self.editors.toggle_comment_current,
            shortcut="Ctrl+/",
            shortcut_context=Qt.ApplicationShortcut)

        self.tabs_to_spaces_action = create_action(
            self,
            'Tabs to Spaces',
            on_triggered=self.editors.tabs_to_spaces_current)

        self.spaces_to_tabs_action = create_action(
            self,
            'Spaces to Tabs',
            on_triggered=self.editors.spaces_to_tabs_current)

        self.toggle_whitespace_action = create_action(
            self,
            'Toggle Whitespace Visible',
            on_triggered=self.editors.toggle_whitespace_visible_all)

        # Store actions for adding to menu bar; None will add a separator
        self.editor_actions = [
            self.run_action, self.abort_action, None, self.toggle_find_replace,
            None, self.toggle_comment_action, self.toggle_whitespace_action,
            None, self.tabs_to_spaces_action, self.spaces_to_tabs_action, None
        ]

    def execute_current(self):
        '''This is used by MainWindow to execute a file after opening it'''
        return self.editors.execute_current()

    def restore_session_tabs(self, session_tabs):
        self.open_files_in_new_tabs(session_tabs, startup=True)
        self.editors.close_tab(0)  # close default empty tab

    # ----------- Plugin API --------------------

    def app_closing(self):
        """
        Tries to close all editors
        :return: True if editors can be closed, false if cancelled
        """
        self.tabs_open_on_closing = self.editors.tab_filepaths
        return self.editors.close_all()

    def dragEnterEvent(self, event):
        data = event.mimeData()
        if data.hasText() and data.hasUrls():
            filepaths = [url.toLocalFile() for url in data.urls()]
            for filepath in filepaths:
                if osp.splitext(filepath)[1] in ACCEPTED_FILE_EXTENSIONS:
                    event.acceptProposedAction()

    def dropEvent(self, event):
        data = event.mimeData()
        for url in data.urls():
            filepath = url.toLocalFile()
            if osp.splitext(filepath)[1] in ACCEPTED_FILE_EXTENSIONS:
                try:
                    self.open_file_in_new_tab(filepath)
                except IOError as io_error:
                    logger.warning("Could not load file:\n  '{}'"
                                   "".format(io_error))

    def get_plugin_title(self):
        return "Editor"

    def readSettings(self, settings):
        try:
            prev_session_tabs = settings.get(TAB_SETTINGS_KEY)
        except KeyError:
            return
        self.restore_session_tabs(prev_session_tabs)

    def writeSettings(self, settings):
        settings.set(TAB_SETTINGS_KEY, self.tabs_open_on_closing)

    def register_plugin(self):
        self.main.add_dockwidget(self)
        # menus
        add_actions(self.main.editor_menu, self.editor_actions)

    # ----------- Plugin Behaviour --------------------

    def open_file_in_new_tab(self, filepath, startup=False):
        return self.editors.open_file_in_new_tab(filepath, startup)

    def open_files_in_new_tabs(self, filepaths, startup=False):
        for filepath in filepaths:
            try:
                self.open_file_in_new_tab(filepath, startup)
            except IOError as io_error:
                logger.warning("Could not load file:\n  {}"
                               "".format(io_error))

    def save_current_file(self):
        self.editors.save_current_file()
Esempio n. 14
0
 def test_add_editor(self):
     widget = MultiPythonFileInterpreter()
     self.assertEqual(1, widget.editor_count)
     widget.append_new_editor()
     self.assertEqual(2, widget.editor_count)
Esempio n. 15
0
    def test_editor_widget_not_leaked(self):
        widget = MultiPythonFileInterpreter()
        self.assertEqual(1, widget.editor_count)
        widget.append_new_editor()
        self.assertEqual(2, widget.editor_count)
        widget.append_new_editor()
        self.assertEqual(3, widget.editor_count)

        widget.close_tab(0)

        QApplication.processEvents()
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 2)
        widget.close_tab(0)

        QApplication.processEvents()
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 1)

        widget.close_all()

        QApplication.processEvents()
        # there should be zero interpreters
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 0)

        # close the whole widget, this should delete everything from the QApplication
        widget.close()
        QApplication.processEvents()
        self.assert_number_of_widgets_matching(".interpreter.PythonFileInterpreter", 0)
        self.assert_no_toplevel_widgets()
    def test_editor_widget_not_leaked(self):
        widget = MultiPythonFileInterpreter()
        self.assertEqual(1, widget.editor_count)
        widget.append_new_editor()
        self.assertEqual(2, widget.editor_count)
        widget.append_new_editor()
        self.assertEqual(3, widget.editor_count)

        widget.close_tab(0)

        QApplication.processEvents()
        self.assert_number_of_widgets_matching(
            ".interpreter.PythonFileInterpreter", 2)
        widget.close_tab(0)

        QApplication.processEvents()
        self.assert_number_of_widgets_matching(
            ".interpreter.PythonFileInterpreter", 1)

        widget.close_all()

        QApplication.processEvents()
        # there will always be 1, because we never allow an empty editor widget
        self.assert_number_of_widgets_matching(
            ".interpreter.PythonFileInterpreter", 1)
Esempio n. 17
0
class MultiFileEditor(PluginWidget):
    """
    Provides the container for the widget containing the CodeEditors in the Workbench
    """

    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(font=text_font(),
                                                  default_content=DEFAULT_CONTENT,
                                                  parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.setAcceptDrops(True)

        # attributes
        self.tabs_open_on_closing = None

    def load_settings_from_config(self, config):
        self.editors.load_settings_from_config(config)

    def execute_current_async(self):
        """
        Executes the selection in the currently active code editor.
        This is used by MainWindow to execute a file after opening it.

        """
        return self.editors.execute_current_async()

    def execute_async(self):
        """
        Executes _everything_ in currently active code editor.
        :return:
        """
        return self.editors.execute_async()

    def restore_session_tabs(self, session_tabs):
        self.open_files_in_new_tabs(session_tabs, startup=True)
        self.editors.close_tab(0)  # close default empty tab

    # ----------- Plugin API --------------------

    def app_closing(self):
        """
        Tries to close all editors
        :return: True if editors can be closed, false if cancelled
        """
        self.tabs_open_on_closing = self.editors.tab_filepaths
        return self.editors.close_all()

    def dragEnterEvent(self, event):
        data = event.mimeData()
        if data.hasText() and data.hasUrls():
            filepaths = [url.toLocalFile() for url in data.urls()]
            for filepath in filepaths:
                if osp.splitext(filepath)[1] in ACCEPTED_FILE_EXTENSIONS:
                    event.acceptProposedAction()

    def dropEvent(self, event):
        data = event.mimeData()
        for url in data.urls():
            filepath = url.toLocalFile()
            if osp.splitext(filepath)[1] in ACCEPTED_FILE_EXTENSIONS:
                try:
                    self.open_file_in_new_tab(filepath)
                except IOError as io_error:
                    logger.warning("Could not load file:\n  '{}'"
                                   "".format(io_error))

    def get_plugin_title(self):
        return "Editor"

    def readSettings(self, settings):
        try:
            prev_session_tabs = settings.get(TAB_SETTINGS_KEY)
        except KeyError:
            return
        self.restore_session_tabs(prev_session_tabs)

    def writeSettings(self, settings):
        settings.set(TAB_SETTINGS_KEY, set(self.tabs_open_on_closing))

    def register_plugin(self):
        self.main.add_dockwidget(self)

    # ----------- Plugin Behaviour --------------------

    def open_file_in_new_tab(self, filepath, startup=False):
        return self.editors.open_file_in_new_tab(filepath, startup)

    def open_files_in_new_tabs(self, filepaths, startup=False):
        for filepath in filepaths:
            try:
                self.open_file_in_new_tab(filepath, startup)
            except IOError as io_error:
                logger.warning("Could not load file:\n  {}"
                               "".format(io_error))

    def save_current_file(self):
        self.editors.save_current_file()

    def save_current_file_as(self):
        self.editors.save_current_file_as()
Esempio n. 18
0
 def test_add_editor(self):
     widget = MultiPythonFileInterpreter()
     self.assertEqual(1, widget.editor_count)
     widget.append_new_editor()
     self.assertEqual(2, widget.editor_count)
Esempio n. 19
0
 def test_default_contains_single_editor(self):
     widget = MultiPythonFileInterpreter()
     self.assertEqual(1, widget.editor_count)
Esempio n. 20
0
    def __init__(self, parent):
        super(MultiFileEditor, self).__init__(parent)

        # layout
        self.editors = MultiPythonFileInterpreter(
            default_content=DEFAULT_CONTENT, parent=self)
        layout = QVBoxLayout()
        layout.addWidget(self.editors)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.setAcceptDrops(True)

        # attributes
        self.tabs_open_on_closing = None

        self.run_action = create_action(
            self,
            "Run",
            on_triggered=self.editors.execute_current,
            shortcut=("Ctrl+Return", "Ctrl+Enter"),
            shortcut_context=Qt.ApplicationShortcut)

        self.abort_action = create_action(
            self, "Abort", on_triggered=self.editors.abort_current)

        # menu action to toggle the find/replace dialog
        self.toggle_find_replace = create_action(
            self,
            'Find/Replace...',
            on_triggered=self.editors.toggle_find_replace_dialog,
            shortcut='Ctrl+F')

        self.toggle_comment_action = create_action(
            self.editors.current_editor(),
            "Comment/Uncomment",
            on_triggered=self.editors.toggle_comment_current,
            shortcut="Ctrl+/",
            shortcut_context=Qt.ApplicationShortcut)

        self.tabs_to_spaces_action = create_action(
            self,
            'Tabs to Spaces',
            on_triggered=self.editors.tabs_to_spaces_current)

        self.spaces_to_tabs_action = create_action(
            self,
            'Spaces to Tabs',
            on_triggered=self.editors.spaces_to_tabs_current)

        self.toggle_whitespace_action = create_action(
            self,
            'Toggle Whitespace Visible',
            on_triggered=self.editors.toggle_whitespace_visible_all)

        # Store actions for adding to menu bar; None will add a separator
        self.editor_actions = [
            self.run_action, self.abort_action, None, self.toggle_find_replace,
            None, self.toggle_comment_action, self.toggle_whitespace_action,
            None, self.tabs_to_spaces_action, self.spaces_to_tabs_action, None
        ]