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()
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()
def test_add_editor(self): widget = MultiPythonFileInterpreter() self.assertEqual(1, widget.editor_count) widget.append_new_editor() self.assertEqual(2, widget.editor_count)
class MultiFileEditor(PluginWidget): """ Provides the container for the widget containing the CodeEditors in the Workbench """ def __init__(self, parent, font=None): super(MultiFileEditor, self).__init__(parent) if not font: font = text_font() # layout self.editors = MultiPythonFileInterpreter( font=font, default_content=DEFAULT_SCRIPT_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.editors_zoom_level = 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 self.editors_zoom_level = self.editors.current_editor().editor.getZoom( ) 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) zoom_level = settings.get(ZOOM_LEVEL_KEY) except KeyError: return self.restore_session_tabs(prev_session_tabs) self.editors.current_editor().editor.zoomTo(int(zoom_level)) def writeSettings(self, settings): settings.set(ZOOM_LEVEL_KEY, self.editors_zoom_level) no_duplicates = [] [ no_duplicates.append(x) for x in self.tabs_open_on_closing if x not in no_duplicates ] settings.set(TAB_SETTINGS_KEY, no_duplicates) 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 open_script_in_new_tab(self, content): self.editors.append_new_editor(content=content) self.editors.mark_current_tab_modified(True) def save_current_file(self): self.editors.save_current_file() def save_current_file_as(self): self.editors.save_current_file_as()