From 0bedc275daffebba5b2fe29f05b62c1282faab50 Mon Sep 17 00:00:00 2001 From: Martyn Gigg <martyn.gigg@gmail.com> Date: Fri, 12 Jan 2018 17:44:13 +0000 Subject: [PATCH] Add support for executing selected pieces of code Refs #21251 --- .../widgets/codeeditor/interpreter.py | 41 +++++++++++++------ .../codeeditor/multifileinterpreter.py | 4 +- .../codeeditor/test/test_codeeditor.py | 17 ++++++++ .../mantidqt/widgets/src/_widgetscore.sip | 10 +++++ 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/qt/python/mantidqt/widgets/codeeditor/interpreter.py b/qt/python/mantidqt/widgets/codeeditor/interpreter.py index 858a66db013..1d19431193a 100644 --- a/qt/python/mantidqt/widgets/codeeditor/interpreter.py +++ b/qt/python/mantidqt/widgets/codeeditor/interpreter.py @@ -53,8 +53,8 @@ class PythonFileInterpreter(QWidget): # presenter self._presenter = PythonFileInterpreterPresenter(self, PythonCodeExecution()) - def execute_all_async(self): - self._presenter.req_execute_all_async() + def execute_async(self): + self._presenter.req_execute_async() def set_editor_readonly(self, ro): self.editor.setReadOnly(ro) @@ -88,30 +88,41 @@ class PythonFileInterpreterPresenter(QObject): def __init__(self, view, model): super(PythonFileInterpreterPresenter, self).__init__() + # attributes self.view = view self.model = model + # offset of executing code from start of the file + self._code_start_offset = 0 # connect signals - self.model.sig_exec_success.connect(self.on_exec_success) - self.model.sig_exec_error.connect(self.on_exec_error) - self.model.sig_exec_progress.connect(self.view.editor.updateProgressMarker) + self.model.sig_exec_success.connect(self._on_exec_success) + self.model.sig_exec_error.connect(self._on_exec_error) + self.model.sig_exec_progress.connect(self._on_progress_update) # starts idle self.view.set_status_message(IDLE_STATUS_MSG) - def req_execute_all_async(self): - text = self.view.editor.text() - if not text: - return + def req_execute_async(self): + code_str, self._code_start_offset = self._get_code_for_execution() self.view.set_editor_readonly(True) self.view.set_status_message(RUNNING_STATUS_MSG) - return self.model.execute_async(text) + return self.model.execute_async(code_str) - def on_exec_success(self): + def _get_code_for_execution(self): + editor = self.view.editor + if editor.hasSelectedText(): + code_str = editor.selectedText() + line_from, _, _, _ = editor.getSelection() + else: + code_str = editor.text() + line_from = 0 + return code_str, line_from + + def _on_exec_success(self): self.view.set_editor_readonly(False) self.view.set_status_message(IDLE_STATUS_MSG) - def on_exec_error(self, task_error): + def _on_exec_error(self, task_error): if isinstance(task_error.exception, SyntaxError): lineno = task_error.exception.lineno else: @@ -119,3 +130,9 @@ class PythonFileInterpreterPresenter(QObject): self.view.editor.updateProgressMarker(lineno, True) self.view.set_editor_readonly(False) self.view.set_status_message(IDLE_STATUS_MSG) + + def _on_progress_update(self, lineno): + """Update progress on the view taking into account if a selection of code is + running""" + self.view.editor.updateProgressMarker(lineno + self._code_start_offset, + False) \ No newline at end of file diff --git a/qt/python/mantidqt/widgets/codeeditor/multifileinterpreter.py b/qt/python/mantidqt/widgets/codeeditor/multifileinterpreter.py index 4e9ee97534f..7f62d5a02f5 100644 --- a/qt/python/mantidqt/widgets/codeeditor/multifileinterpreter.py +++ b/qt/python/mantidqt/widgets/codeeditor/multifileinterpreter.py @@ -51,7 +51,9 @@ class MultiPythonFileInterpreter(QWidget): return self._editors.currentWidget() def execute_current(self): - self.current_editor().execute_all_async() + """Execute content of the current file. If a selection is active + then only this portion of code is executed""" + self.current_editor().execute_async() def append_new_editor(self): title = "New" diff --git a/qt/python/mantidqt/widgets/codeeditor/test/test_codeeditor.py b/qt/python/mantidqt/widgets/codeeditor/test/test_codeeditor.py index ff465ee2e81..933547f4e0c 100644 --- a/qt/python/mantidqt/widgets/codeeditor/test/test_codeeditor.py +++ b/qt/python/mantidqt/widgets/codeeditor/test/test_codeeditor.py @@ -60,6 +60,23 @@ class CodeEditorTest(unittest.TestCase): widget.setReadOnly(True) self.assertTrue(widget.isReadOnly()) + def test_get_selection_for_empty_selection(self): + widget = CodeEditor(TEST_LANG) + res = widget.getSelection() + self.assertEqual((-1, -1, -1, -1), res) + + def test_get_selection_for_non_empty_selection(self): + widget = CodeEditor(TEST_LANG) + widget.setText("""first line + second line + third line + fourth line + """) + selected = (0, 2, 3, 4) + widget.setSelection(*selected) + res = widget.getSelection() + self.assertEqual(selected, res) + # --------------------------------------------------------------- # Failure tests # --------------------------------------------------------------- diff --git a/qt/python/mantidqt/widgets/src/_widgetscore.sip b/qt/python/mantidqt/widgets/src/_widgetscore.sip index 75136926fb4..67752d51f85 100644 --- a/qt/python/mantidqt/widgets/src/_widgetscore.sip +++ b/qt/python/mantidqt/widgets/src/_widgetscore.sip @@ -65,7 +65,16 @@ public: QWidget *parent /TransferThis/ = 0) throw(std::invalid_argument); QString fileName() const; + SIP_PYTUPLE getSelection() const; +%MethodCode + int lineFrom(-1), indexFrom(-1), lineTo(-1), indexTo(-1); + sipCpp->getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo); + sipRes = sipBuildResult(nullptr, "(iiii)", lineFrom, indexFrom, + lineTo, indexTo); +%End + bool hasSelectedText() const; bool isReadOnly() const; + QString selectedText() const; QString text() const; void setCaretLineBackgroundColor (const QColor & col); @@ -74,6 +83,7 @@ public: void setFont(const QFont &f); void setMarginWidth(int margin, int width); void setReadOnly(bool ro); + void setSelection(int lineFrom, int indexFrom, int lineTo, int indexTo); void setText(const QString &text); public slots: -- GitLab