# HG changeset patch # User Torsten Lilge # Date 1654372340 -7200 # Node ID 5261a81765b049fa9e9fa66e12a5fbc1ffdd8650 # Parent 74d97efb75739076866112febe76fa47161040b8 merge input and output of exp. terminal widget into one widget * command-widget.cc (command_widget): remove obsolete elements, use new class console as terminal, update initializations; (init_command_prompt): display the first prompt, this function is called when the interpreter is ready (via main_window); (update_prompt): prompt is a QString now; (insert_interpreter_output): use m_console instead of m_output_display; (accept_input_line): moved to console; (process_input_line): string of input line is passed as argument, a new prompt is provided when interpreter is ready (notice_settings): update for m_console, remove color and configuration of obsolete line edit (console::console): initializations, create and set QTextDocument; (console::new_command_line): Prepare a new command line with prompt; (console::accept_command_line): get input string and pass it to m_command_widget for processing; (console::append_block): append a text block to the document; (console::keyPressEvent): re-implement key event for filtering return, on which accept_input_line is called * command-widget.h: new class console, update some function arguments * main-window.cc (handle_octave_ready) call init_command_prompt of terminal_dock_widget * terminal-dock-widget.cc (init_command_prompt): new function calling related function of the command widget * terminal-dock-widget.h: new function init_command_prompt diff -r 74d97efb7573 -r 5261a81765b0 libgui/src/command-widget.cc --- a/libgui/src/command-widget.cc Sat Jun 04 00:12:55 2022 +0200 +++ b/libgui/src/command-widget.cc Sat Jun 04 21:52:20 2022 +0200 @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include #include "command-widget.h" @@ -49,42 +50,27 @@ { command_widget::command_widget (base_qobject&, QWidget *p) : QWidget (p), m_incomplete_parse (false), - m_prompt (new QLabel ("", this)), - m_line_edit (new QLineEdit (this)), - m_output_display (new QTextBrowser (this)), - m_input_color (QColor ()) + m_prompt (QString ()), + m_console (new console (this)) { QPushButton *pause_button = new QPushButton (tr("Pause"), this); QPushButton *stop_button = new QPushButton (tr("Stop"), this); QPushButton *resume_button = new QPushButton (tr("Continue"), this); - QGroupBox *input_group_box = new QGroupBox (tr("Command Input")); + QGroupBox *input_group_box = new QGroupBox (); QHBoxLayout *input_layout = new QHBoxLayout; - input_layout->addWidget (m_prompt); - input_layout->addWidget (m_line_edit); input_layout->addWidget (pause_button); input_layout->addWidget (stop_button); input_layout->addWidget (resume_button); input_group_box->setLayout (input_layout); - QGroupBox *output_group_box = new QGroupBox (tr("Command Output")); - QHBoxLayout *output_layout = new QHBoxLayout (); - output_layout->addWidget (m_output_display); - output_group_box->setLayout (output_layout); - QVBoxLayout *main_layout = new QVBoxLayout (); - main_layout->addWidget (output_group_box); + main_layout->addWidget (m_console); main_layout->addWidget (input_group_box); setLayout (main_layout); - setFocusProxy (m_line_edit); - - connect (m_line_edit, &QLineEdit::returnPressed, - this, &command_widget::accept_input_line); - - connect (this, &command_widget::clear_line_edit, - m_line_edit, &QLineEdit::clear); + setFocusProxy (m_console); connect (pause_button, &QPushButton::clicked, this, &command_widget::interpreter_pause); @@ -94,39 +80,51 @@ connect (stop_button, &QPushButton::clicked, this, &command_widget::interpreter_stop); + + connect (this, &command_widget::new_command_line_signal, + m_console, &console::new_command_line); + + insert_interpreter_output ("\n\n Welcome to Octave\n\n"); + + } + + void command_widget::init_command_prompt () + { + emit interpreter_event + ([=] (interpreter& interp) + { + // INTERPRETER THREAD + + event_manager& evmgr = interp.get_event_manager (); + input_system& input_sys = interp.get_input_system (); + std::string prompt = input_sys.PS1 (); + evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + + emit new_command_line_signal (); + }); } void command_widget::update_prompt (const QString& prompt) { - m_prompt->setText (prompt); + m_prompt = prompt; + } + + QString command_widget::prompt () + { + return m_prompt; } void command_widget::insert_interpreter_output (const QString& msg) { - QTextCursor cursor = m_output_display->textCursor (); + QTextCursor cursor = m_console->textCursor (); cursor.insertText (msg); - m_output_display->setTextCursor (cursor); + m_console->setTextCursor (cursor); } - void command_widget::accept_input_line (void) + void command_widget::process_input_line (const QString& input_line) { - QTextCursor cursor = m_output_display->textCursor (); - - QString input_line = m_line_edit->text (); - - QString style; - if (! m_incomplete_parse) - { - style = QString ("
[in]:
") - .arg (m_input_color.name ()); - m_output_display->insertHtml (style); - } - style = QString ("
%2

") - .arg (m_input_color.name ()).arg (input_line); - m_output_display->insertHtml (style); - emit interpreter_event ([=] (interpreter& interp) { @@ -142,9 +140,10 @@ = m_incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); evmgr.update_prompt (command_editor::decode_prompt_string (prompt)); + + emit new_command_line_signal (); }); - emit clear_line_edit (); } void command_widget::notice_settings (const gui_settings *settings) @@ -158,20 +157,83 @@ term_font.setPointSize (settings->value (cs_font_size).toInt ()); - m_line_edit->setFont (term_font); - m_output_display->setFont (term_font); + m_console->setFont (term_font); // Colors int mode = settings->value (cs_color_mode).toInt (); QColor fgc = settings->color_value (cs_colors[0], mode); QColor bgc = settings->color_value (cs_colors[1], mode); - m_output_display->setStyleSheet (QString ("color: %1; background-color:%2;") + m_console->setStyleSheet (QString ("color: %1; background-color:%2;") .arg (fgc.name ()).arg (bgc.name ())); - m_line_edit->setStyleSheet (QString ("color: %1; background-color:%2;") - .arg (fgc.name ()).arg (bgc.name ())); + } + + + // The console itself using QTextEdit with QTextBlock and QTextCursor. + // This implementation is based on the basic concept of "qpconsole" as + // proposed by user "DerManu" in the Qt-forum thread + // https://forum.qt.io/topic/28765/command-terminal-using-qtextedit + + console::console (command_widget *p) + : QTextEdit (p), + m_command_block_number (-1), + m_command_widget (p), + m_document (new QTextDocument (this)) + { + setDocument (m_document); + } + + // Prepare a new command line with the current prompt + void console::new_command_line () + { + QTextCursor cursor (m_document->lastBlock ()); + + if (! m_document->lastBlock ().text ().isEmpty ()) + { + cursor.movePosition (QTextCursor::EndOfBlock); + cursor.insertBlock (); + } + + cursor.insertText (m_command_widget->prompt ()); + setTextCursor (cursor); + } - m_input_color = interpolate_color (fgc, bgc, 0.75, 0.5); + // Accept the current command line (or block) + void console::accept_command_line () + { + QString input_line = m_document->lastBlock().text(); + + if (input_line.startsWith (m_command_widget->prompt ())) + input_line.remove(0, m_command_widget->prompt ().length ()); + + input_line = input_line.trimmed (); + + append_block (); + + if (input_line.isEmpty ()) + new_command_line (); + else + m_command_widget->process_input_line (input_line); + } + + // Append a block to the document + void console::append_block () + { + QTextCursor cursor (m_document->lastBlock ()); + cursor.movePosition (QTextCursor::EndOfBlock); + cursor.insertBlock (); + setTextCursor (cursor); + } + + // Re-implement key event + void console::keyPressEvent (QKeyEvent *e) + { + if (e->key () == Qt::Key_Return) + // On "return", accept the current command line + accept_command_line (); + else + // Otherwise, process the expected event + QTextEdit::keyPressEvent(e); } } diff -r 74d97efb7573 -r 5261a81765b0 libgui/src/command-widget.h --- a/libgui/src/command-widget.h Sat Jun 04 00:12:55 2022 +0200 +++ b/libgui/src/command-widget.h Sat Jun 04 21:52:20 2022 +0200 @@ -27,6 +27,7 @@ #define octave_command_widget_h 1 #include +#include #include "octave-qobject.h" #include "gui-settings.h" @@ -34,11 +35,40 @@ class QLabel; class QLineEdit; class QStrung; -class QTextBrowser; +class QTextEdit; namespace octave { class base_qobject; + class command_widget; + + class console : public QTextEdit + { + Q_OBJECT + + public: + + console (command_widget *p); + + public slots: + + void new_command_line (void); + + protected: + + void keyPressEvent (QKeyEvent *e); + + private: + + void accept_command_line (void); + + void append_block (void); + + int m_command_block_number; + command_widget *m_command_widget; + QTextDocument *m_document; + + }; class command_widget : public QWidget { @@ -48,6 +78,10 @@ command_widget (base_qobject& oct_qobj, QWidget *p); + void init_command_prompt (); + + QString prompt (void); + signals: void clear_line_edit (void); @@ -59,25 +93,23 @@ void interpreter_event (const fcn_callback& fcn); void interpreter_event (const meth_callback& meth); + void new_command_line_signal (void); + public slots: + void process_input_line (const QString& input_line); + void update_prompt (const QString& prompt); void insert_interpreter_output (const QString& msg); void notice_settings (const gui_settings *settings); - protected slots: - - void accept_input_line (void); - private: bool m_incomplete_parse; - QLabel *m_prompt; - QLineEdit *m_line_edit; - QTextBrowser *m_output_display; - QColor m_input_color; + QString m_prompt; + console *m_console; }; } diff -r 74d97efb7573 -r 5261a81765b0 libgui/src/main-window.cc --- a/libgui/src/main-window.cc Sat Jun 04 00:12:55 2022 +0200 +++ b/libgui/src/main-window.cc Sat Jun 04 21:52:20 2022 +0200 @@ -1806,6 +1806,7 @@ }); } + m_command_window->init_command_prompt (); focus_command_window (); // make sure that the command window has focus } diff -r 74d97efb7573 -r 5261a81765b0 libgui/src/terminal-dock-widget.cc --- a/libgui/src/terminal-dock-widget.cc Sat Jun 04 00:12:55 2022 +0200 +++ b/libgui/src/terminal-dock-widget.cc Sat Jun 04 21:52:20 2022 +0200 @@ -155,4 +155,13 @@ emit update_prompt_signal (prompt); } + void terminal_dock_widget::init_command_prompt () + { + if (m_experimental_terminal_widget) + { + command_widget *cmd = get_command_widget (); + if (cmd) + cmd->init_command_prompt (); + } + } } diff -r 74d97efb7573 -r 5261a81765b0 libgui/src/terminal-dock-widget.h --- a/libgui/src/terminal-dock-widget.h Sat Jun 04 00:12:55 2022 +0200 +++ b/libgui/src/terminal-dock-widget.h Sat Jun 04 21:52:20 2022 +0200 @@ -49,6 +49,8 @@ bool has_focus (void) const; + void init_command_prompt (); + // FIXME: The next two functions could be eliminated (or combined) // if we had a common interface for the old and new terminal // widgets.