Example #1
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)
    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)
    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)

        # 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()
Example #5
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()
Example #6
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()
Example #7
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()