Mercurial > octave
changeset 27556:410622ac120f
improve run selection from editor (bug #42705)
* file-editor-tab.cc (file_editor_tab): relay interpreter event signals
to the ones of the editor widget
* file-editor.cc (make_file_editor_tab): connect signal of edit area for
giving focus to console window to the new slot in main_window
* octave-qscintilla.cc: include headers required for interpreter threads
and for additionally used Qt libs;
(octave_qscintilla): connect new signals for finished run selection
action to the new related slot;
(contextmenu_run_temp_error): new method displaying a message box on
error handling temp. files;
(contextmenu_run): create a temp. file with all selected lines extended
by commands for displaying each line and add it to the command history,
disable opening a file at breakpoints, run this temp. file by the
interpreter and emit new signal when running this file is finished;
(ctx_menu_run_finished): slot when running the temp. file is finished,
removing temp. files and reset modified editor preferences;
* octave-qscintilla.h: include QSettings and interpreter-events,
interpreter signal, signal for focusing console window and signal when
running temp file is finished, new slot for the latter
* main-window.cc (focus_console_after_command): do not return the related
setting, but actually give console window the focus if desired,
(run_file_in_terminal, execute_command_in_terminal): use this new form
* main-window.h: change focus_console_method from private method into
public slot
* resource-manager.cc (resource_manager): initialize new list of created
temp. files;
(~resource_manager): remove any temp. files that are still existing;
(do_create_tmp_file): create a new temp. file with the given contents
and store its smart pointer into a list for removing the file later;
(do_remove_tmp_file): remove given temp. file and remove it from the list;
* resource-manager.h: include QPointer and QTemporaryFile,
(create_tmp_file): new static method calling internal do_create_tmp_file;
(remove_tmp_file): new static method calling internal do_create_tmp_file;
new internal methods do_create_tmp_file and do_remove_tmp_file,
new list for storing temp. file pointers
author | Torsten Lilge <ttl-octave@mailbox.org> |
---|---|
date | Fri, 25 Oct 2019 07:36:37 +0200 |
parents | c2f2fb1df9ed |
children | f9f21bb2ea1c |
files | libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor.cc libgui/src/m-editor/octave-qscintilla.cc libgui/src/m-editor/octave-qscintilla.h libgui/src/main-window.cc libgui/src/main-window.h libgui/src/resource-manager.cc libgui/src/resource-manager.h |
diffstat | 8 files changed, 251 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-tab.cc Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/m-editor/file-editor-tab.cc Fri Oct 25 07:36:37 2019 +0200 @@ -216,6 +216,15 @@ edit_area_layout->setSpacing (0); setLayout (edit_area_layout); + // Any interpreter_event signal from a file_editor_tab_widget is + // handled the same as for the parent main_window object. + + connect (m_edit_area, SIGNAL (interpreter_event (const fcn_callback&)), + this, SIGNAL (interpreter_event (const fcn_callback&))); + + connect (m_edit_area, SIGNAL (interpreter_event (const meth_callback&)), + this, SIGNAL (interpreter_event (const meth_callback&))); + // connect modified signal connect (m_edit_area, SIGNAL (modificationChanged (bool)), this, SLOT (update_window_title (bool)));
--- a/libgui/src/m-editor/file-editor.cc Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/m-editor/file-editor.cc Fri Oct 25 07:36:37 2019 +0200 @@ -2263,6 +2263,10 @@ SIGNAL (execute_command_in_terminal_signal (const QString&)), main_win (), SLOT (execute_command_in_terminal (const QString&))); + connect (f->qsci_edit_area (), + SIGNAL (focus_console_after_command_signal (void)), + main_win (), SLOT (focus_console_after_command (void))); + // Signals from the file editor_tab connect (f, SIGNAL (file_name_changed (const QString&, const QString&, bool)), this, SLOT (handle_file_name_changed (const QString&,
--- a/libgui/src/m-editor/octave-qscintilla.cc Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/m-editor/octave-qscintilla.cc Fri Oct 25 07:36:37 2019 +0200 @@ -20,7 +20,7 @@ */ -// Author: Torsten <ttl@justmail.de> +// Author: Torsten Lilge <ttl-octave@mailbox.org> #if defined (HAVE_CONFIG_H) # include "config.h" @@ -30,7 +30,9 @@ #include <Qsci/qscilexer.h> +#include <QDir> #include <QKeySequence> +#include <QMessageBox> #include <QMimeData> #include <QShortcut> #include <QToolTip> @@ -57,6 +59,11 @@ #include "resource-manager.h" #include "shortcut-manager.h" +#include "builtin-defun-decls.h" +#include "cmd-edit.h" +#include "interpreter-private.h" +#include "interpreter.h" + // Return true if CANDIDATE is a "closing" that matches OPENING, // such as "end" or "endif" for "if", or "catch" for "try". // Used for testing the last word of an "if" etc. line, @@ -112,6 +119,12 @@ connect (this, SIGNAL (cursorPositionChanged (int, int)), this, SLOT (cursor_position_changed (int, int))); + connect (this, SIGNAL (ctx_menu_run_finished_signal (bool, QTemporaryFile*, + QTemporaryFile*, QTemporaryFile*)), + this, SLOT (ctx_menu_run_finished (bool, QTemporaryFile*, + QTemporaryFile*, QTemporaryFile*)), + Qt::QueuedConnection); + // clear scintilla edit shortcuts that are handled by the editor QsciCommandSet *cmd_set = standardCommands (); @@ -748,14 +761,152 @@ emit context_menu_edit_signal (m_word_at_cursor); } + void octave_qscintilla::contextmenu_run_temp_error (void) + { + QMessageBox::critical (this, tr ("Octave Editor"), + tr ("Creating temporary files failed.\n" + "Make sure you have write access to temp. directory\n" + "%1\n\n" + "\"Run Selection\" requires temporary files.").arg (QDir::tempPath ())); + } + void octave_qscintilla::contextmenu_run (bool) { - QStringList commands = selectedText ().split (QRegExp ("[\r\n]"), - QString::SkipEmptyParts); - for (int i = 0; i < commands.size (); i++) - emit execute_command_in_terminal_signal (commands.at (i)); + + // Create tmp file required for adding command to history + QPointer<QTemporaryFile> tmp_hist + = resource_manager::create_tmp_file (); // empty tmp file for history + + // Create tmp file required for the script echoing and adding cmd to hist + QPointer<QTemporaryFile> tmp_script + = resource_manager::create_tmp_file ("m"); // tmp script file + + bool tmp = (tmp_hist && tmp_hist->open () && + tmp_script && tmp_script->open()); + if (! tmp) + { + // tmp files not working: use old way to run selection + contextmenu_run_temp_error (); + return; + } + + tmp_hist->close (); + + QString tmp_hist_name = QFileInfo (tmp_hist->fileName ()).baseName (); + QString tmp_script_name = QFileInfo (tmp_script->fileName ()).baseName (); + + // Create tmp file with script for echoing a command and adding + // the the history + QString echo_hist = QString ( + "function cnt = %2 (oldcnt, i, command, line)\n" + " cnt = oldcnt;\n" + " if cnt < i\n" + " cnt = i;\n" + " disp ([PS1, command]);\n" + " if (history_save ())\n" + " fid = fopen ('%1','w');\n" + " if (fid != -1)\n" + " fprintf (fid, [line,'\\n']);\n" + " fclose (fid);\n" + " end;\n" + " history -r '%1'\n" + " end\n" + " end\n" + " end\n").arg (tmp_hist->fileName ()).arg (tmp_script_name); + + tmp_script->write (echo_hist.toUtf8 ()); + tmp_script->close (); + + // Take selected code and extend it by commands for echoing each + // evaluated line and for adding the line to the history (use script) + + QString tmp_dir = QFileInfo (tmp_script->fileName ()).absolutePath (); + QString code = QString ("%1 = -1;\n\n").arg (tmp_hist_name); + + // Split contents into single lines and complete commands + QStringList lines = selectedText ().split (QRegExp ("[\r\n]"), + QString::SkipEmptyParts); + + for (int i = 0; i < lines.count (); i++) + { + QString line = lines.at (i); + line = line.replace (QString ("%"), QString ("%%")); + + code += QString ("%1 = %2 (%1, %3, '%4', '%5');\n" + "%4\n\n") + .arg (tmp_hist_name) + .arg (tmp_script_name) + .arg (i) + .arg (lines.at (i)) + .arg (line); + } + + code += QString ("clear %1 %2_fcn;\n") + .arg (tmp_hist_name).arg (tmp_script_name); + + // Create tmp file with the code to be executed by the interpreter + QPointer<QTemporaryFile> tmp_file + = resource_manager::create_tmp_file ("m", code); + + tmp = (tmp_file && tmp_file->open ()); + if (! tmp) + { + // tmp files not working: use old way to run selection + contextmenu_run_temp_error (); + return; + } + tmp_file->close (); + + // Disable opening a file at a breakpoint in case keyboard () is used + QSettings* settings = resource_manager::get_settings (); + bool show_dbg_file = settings->value (ed_show_dbg_file.key, + ed_show_dbg_file.def).toBool (); + settings->setValue (ed_show_dbg_file.key, false); + + emit focus_console_after_command_signal (); + + // Let the interpreter execute the tmp file + emit interpreter_event + ([this, tmp_file, tmp_hist, tmp_script, show_dbg_file] (interpreter& interp) + { + // INTERPRETER THREAD + + std::string file = tmp_file->fileName ().toStdString (); + + std::string pending_input = command_editor::get_current_line (); + + // Add tmp dir to the path for echo/hist script + octave_value_list path = + ovl (QFileInfo (tmp_script->fileName ()).absolutePath ().toStdString ()); + Faddpath (interp, path); + interp.source_file (file); + Frmpath (interp, path); + + command_editor::replace_line (""); + command_editor::set_initial_input (pending_input); + command_editor::redisplay (); + command_editor::interrupt_event_loop (); + command_editor::accept_line (); + + // Done, restore settings and remove tmp files + emit ctx_menu_run_finished_signal (show_dbg_file, + tmp_file, tmp_hist, tmp_script); + }); } + void octave_qscintilla::ctx_menu_run_finished (bool show_dbg_file, + QTemporaryFile* tmp_file, + QTemporaryFile* tmp_hist, + QTemporaryFile* tmp_script) + { + QSettings *settings = resource_manager::get_settings (); + settings->setValue (ed_show_dbg_file.key, show_dbg_file); + resource_manager::remove_tmp_file (tmp_file); + resource_manager::remove_tmp_file (tmp_hist); + resource_manager::remove_tmp_file (tmp_script); + } + + // wrappers for dbstop related context menu items // FIXME: Why can't the data be sent as the argument to the function???
--- a/libgui/src/m-editor/octave-qscintilla.h Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/m-editor/octave-qscintilla.h Fri Oct 25 07:36:37 2019 +0200 @@ -29,8 +29,11 @@ #include <QKeyEvent> #include <QLabel> #include <QMenu> +#include <QSettings> #include <Qsci/qsciscintilla.h> +#include "qt-interpreter-events.h" + namespace octave { class octave_qscintilla : public QsciScintilla @@ -83,14 +86,22 @@ void show_doc_signal (const QString&); void context_menu_break_condition_signal (int); void context_menu_break_once (int); + void interpreter_event (const meth_callback& meth); + void ctx_menu_run_finished_signal (bool, QTemporaryFile*, + QTemporaryFile*, QTemporaryFile*); + void focus_console_after_command_signal (void); private slots: + void ctx_menu_run_finished (bool, QTemporaryFile*, + QTemporaryFile*, QTemporaryFile*); + void contextmenu_help (bool); void contextmenu_doc (bool); void contextmenu_help_doc (bool); void contextmenu_edit (bool); void contextmenu_run (bool); + void contextmenu_run_temp_error (void); void contextmenu_break_condition (bool); void contextmenu_break_once (const QPoint&);
--- a/libgui/src/main-window.cc Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/main-window.cc Fri Oct 25 07:36:37 2019 +0200 @@ -1037,8 +1037,7 @@ command_editor::accept_line (); }); - if (focus_console_after_command ()) - focus_command_window (); + focus_console_after_command (); } void main_window::run_file_in_terminal (const QFileInfo& info) @@ -1082,8 +1081,7 @@ command_editor::accept_line (); }); - if (focus_console_after_command ()) - focus_command_window (); + focus_console_after_command (); } void main_window::handle_new_figure_request (void) @@ -2749,10 +2747,11 @@ qt_link->wake_all (); } - bool main_window::focus_console_after_command (void) + void main_window::focus_console_after_command (void) { QSettings *settings = resource_manager::get_settings (); - return settings->value ("terminal/focus_after_command",false).toBool (); + if (settings->value ("terminal/focus_after_command",false).toBool ()) + focus_command_window (); } void main_window::configure_shortcuts (void)
--- a/libgui/src/main-window.h Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/main-window.h Fri Oct 25 07:36:37 2019 +0200 @@ -199,6 +199,7 @@ void gui_preference (const QString& key, const QString& value, QString* read_value); + void focus_console_after_command (void); void handle_show_doc (const QString& file); void handle_register_doc (const QString& file); void handle_unregister_doc (const QString& file); @@ -283,8 +284,6 @@ QString gui_preference_adjust (const QString& key, const QString& value); - bool focus_console_after_command (void); - void configure_shortcuts (void); QList<octave_dock_widget *> dock_widget_list (void);
--- a/libgui/src/resource-manager.cc Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/resource-manager.cc Fri Oct 25 07:36:37 2019 +0200 @@ -68,7 +68,7 @@ resource_manager::resource_manager (void) : m_settings_directory (), m_settings_file (), m_settings (nullptr), - m_default_settings (nullptr) + m_default_settings (nullptr), m_temporary_files () { // Let QSettings decide where to put the ini file with gui preferences m_default_settings @@ -124,6 +124,9 @@ { delete m_settings; delete m_default_settings; + + for (int i = m_temporary_files.count () - 1; i >=0; i--) + remove_tmp_file (m_temporary_files.at (i)); } QString resource_manager::get_gui_translation_dir (void) @@ -487,4 +490,43 @@ combo->setMaxVisibleItems (12); } + + QPointer<QTemporaryFile> + resource_manager::do_create_tmp_file (const QString& extension, + const QString& contents) + { + QString ext = extension; + if ((! ext.isEmpty ()) && (! ext.startsWith ('.'))) + ext = QString (".") + ext; + + // Create octave dir within temp. dir + QString tmp_dir = QDir::tempPath () + QDir::separator() + "octave"; + QDir::temp ().mkdir ("octave"); + + // Create temp. file + QPointer<QTemporaryFile> tmp_file + = new QTemporaryFile (tmp_dir + QDir::separator() + + "octave_XXXXXX" + ext, this); + + if (tmp_file->open ()) + { + tmp_file->write (contents.toUtf8 ()); + tmp_file->close (); + + m_temporary_files << tmp_file; + } + + return tmp_file; + } + + void resource_manager::do_remove_tmp_file (QPointer<QTemporaryFile> tmp_file) + { + if (tmp_file) + { + if (tmp_file->exists ()) + tmp_file->remove (); + + m_temporary_files.removeAll (tmp_file); + } + } }
--- a/libgui/src/resource-manager.h Thu Oct 24 22:33:37 2019 +0200 +++ b/libgui/src/resource-manager.h Fri Oct 25 07:36:37 2019 +0200 @@ -27,8 +27,10 @@ #include <QDesktopServices> #include <QIcon> #include <QMap> +#include <QPointer> #include <QSettings> #include <QTranslator> +#include <QTemporaryFile> namespace octave { @@ -120,6 +122,19 @@ return instance_ok () ? instance->do_is_first_run () : true; } + static QPointer<QTemporaryFile> create_tmp_file ( + const QString& extension = QString (), + const QString& contents = QString ()) + { + return instance_ok () ? instance->do_create_tmp_file (extension, contents) : QPointer<QTemporaryFile> (); + } + + static void remove_tmp_file (QPointer<QTemporaryFile> tmp_file) + { + if (instance_ok ()) + instance->do_remove_tmp_file (tmp_file); + } + static QString storage_class_chars (void) { return "agp"; } static QStringList storage_class_names (void); static QList<QColor> storage_class_default_colors (void); @@ -152,6 +167,11 @@ QString do_get_default_font_family (void); + QPointer<QTemporaryFile> do_create_tmp_file (const QString& extension, + const QString& contents); + + void do_remove_tmp_file (QPointer<QTemporaryFile> tmp_file); + void do_reload_settings (void); void do_set_settings (const QString& file); @@ -174,6 +194,8 @@ QSettings *m_settings; QSettings *m_default_settings; + + QList<QTemporaryFile *> m_temporary_files; }; }