GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
QTerminal.cc
Go to the documentation of this file.
1/*
2
3Copyright (C) 2012-2019 Michael Goffioul.
4Copyright (C) 2012-2019 Jacob Dawid.
5
6This file is part of QTerminal.
7
8This program is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program. If not,
20see <https://www.gnu.org/licenses/>.
21
22*/
23
24#if defined (HAVE_CONFIG_H)
25# include "config.h"
26#endif
27
28#include <QKeySequence>
29#include <QWidget>
30#include <QStringList>
31#include <QColor>
32#include <QList>
33#include <QMenu>
34#include <QClipboard>
35#include <QApplication>
36#include <QAction>
37
39#include "gui-preferences-cs.h"
40#include "gui-preferences-sc.h"
41#include "octave-qobject.h"
42#include "resource-manager.h"
43
44#include "QTerminal.h"
45#if defined (Q_OS_WIN32)
47#else
49#endif
50
53{
54#if defined (Q_OS_WIN32)
55 QTerminal *terminal = new QWinTerminalImpl (oct_qobj, p);
56#else
57 QTerminal *terminal = new QUnixTerminalImpl (oct_qobj, p);
58#endif
59
60 // FIXME: this function should probably be called from or part of the
61 // QTerminal constructor, but I think that would mean some major
62 // surgery because then the constructor for QTerminal and the derived
63 // Unix- and Windows-specific versions would need access to the
64 // base_qobject object, or the design would have to change significantly.
65
66 terminal->construct (oct_qobj);
67
68 return terminal;
69}
70
71// slot for the terminal's context menu
72void
74 {
75 QClipboard * cb = QApplication::clipboard ();
76 QString selected_text = selectedText();
77 bool has_selected_text = ! selected_text.isEmpty ();
78
79 _edit_action->setVisible (false);
80 m_edit_selected_action->setVisible (false);
81 m_help_selected_action->setVisible (false);
82 m_doc_selected_action->setVisible (false);
83
84#if defined (Q_OS_WIN32)
85 // include this when in windows because there is no filter for
86 // detecting links and error messages yet
87 if (has_selected_text)
88 {
89 QRegExp file ("(?:[ \\t]+)(\\S+) at line (\\d+) column (?:\\d+)");
90
91 int pos = file.indexIn (selected_text);
92
93 if (pos > -1)
94 {
95 QString file_name = file.cap (1);
96 QString line = file.cap (2);
97
98 _edit_action->setVisible (true);
99 _edit_action->setText (tr ("Edit %1 at line %2")
100 .arg (file_name).arg (line));
101
102 QStringList data;
103 data << file_name << line;
104 _edit_action->setData (data);
105 }
106 }
107#endif
108
109 if (has_selected_text)
110 {
111 QRegExp expr (".*\b*(\\w+)\b*.*");
112
113 int pos = expr.indexIn (selected_text);
114
115 if (pos > -1)
116 {
117 QString expr_found = expr.cap (1);
118
119 m_edit_selected_action->setVisible (true);
120 m_edit_selected_action->setText (tr ("Edit %1").arg (expr_found));
121 m_edit_selected_action->setData (expr_found);
122
123 m_help_selected_action->setVisible (true);
124 m_help_selected_action->setText (tr ("Help on %1").arg (expr_found));
125 m_help_selected_action->setData (expr_found);
126
127 m_doc_selected_action->setVisible (true);
128 m_doc_selected_action->setText (tr ("Documentation on %1")
129 .arg (expr_found));
130 m_doc_selected_action->setData (expr_found);
131 }
132 }
133
134 _paste_action->setEnabled (cb->text().length() > 0);
135 _copy_action->setEnabled (has_selected_text);
136 _run_selection_action->setVisible (has_selected_text);
137
138 // Get the actions of any hotspots the filters may have found
140 if (actions.length ())
141 _contextMenu->addSeparator ();
142 for (int i = 0; i < actions.length (); i++)
143 _contextMenu->addAction (actions.at(i));
144
145 // Finally, show the context menu
146 _contextMenu->exec (mapToGlobal (at));
147
148 // Cleaning up, remove actions of the hotspot
149 for (int i = 0; i < actions.length (); i++)
150 _contextMenu->removeAction (actions.at(i));
151 }
152
153// slot for running the selected code
154void
156{
157 QStringList commands = selectedText ().split (QRegExp ("[\r\n]"),
158#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
159 Qt::SkipEmptyParts);
160#else
161 QString::SkipEmptyParts);
162#endif
163 for (int i = 0; i < commands.size (); i++)
164 emit execute_command_in_terminal_signal (commands.at (i));
165
166}
167
168// slot for edit files in error messages
169void
171{
172 QString file = _edit_action->data ().toStringList ().at (0);
173 int line = _edit_action->data ().toStringList ().at (1).toInt ();
174
175 emit edit_mfile_request (file,line);
176}
177
178// slot for edit selected function names
180{
181 QString file = m_edit_selected_action->data ().toString ();
182
183 emit edit_mfile_request (file,0);
184}
185
186// slot for showing help on selected epxression
188{
189 QString expr = m_help_selected_action->data ().toString ();
190
191 emit execute_command_in_terminal_signal ("help " + expr);
192}
193
194// slot for showing documentation on selected epxression
196{
197 QString expr = m_doc_selected_action->data ().toString ();
199}
200
201void
203{
204 if (! settings)
205 return;
206
207 // Set terminal font:
208 QFont term_font = QFont ();
209 term_font.setStyleHint (QFont::TypeWriter);
210 QString default_font = settings->value (global_mono_font).toString ();
211 term_font.setFamily
212 (settings->value (cs_font.key, default_font).toString ());
213 term_font.setPointSize
214 (settings->value (cs_font_size).toInt ());
215 setTerminalFont (term_font);
216
217 QFontMetrics metrics (term_font);
218 setMinimumSize (metrics.maxWidth ()*16, metrics.height ()*3);
219
220 QString cursor_type
221 = settings->value (cs_cursor).toString ();
222
223 bool cursor_blinking;
224 if (settings->contains (global_cursor_blinking.key))
225 cursor_blinking = settings->value (global_cursor_blinking).toBool ();
226 else
227 cursor_blinking = settings->value (cs_cursor_blinking).toBool ();
228
229 for (int ct = IBeamCursor; ct <= UnderlineCursor; ct++)
230 {
231 if (cursor_type.toStdString () == cs_cursor_types[ct])
232 {
233 setCursorType ((CursorType) ct, cursor_blinking);
234 break;
235 }
236 }
237
238 bool cursorUseForegroundColor
239 = settings->value (cs_cursor_use_fgcol).toBool ();
240
241 int mode = settings->value (cs_color_mode).toInt ();
242
243 setForegroundColor (settings->color_value (cs_colors[0], mode));
244
245 setBackgroundColor (settings->color_value (cs_colors[1], mode));
246
247 setSelectionColor (settings->color_value (cs_colors[2], mode));
248
249 setCursorColor (cursorUseForegroundColor,
250 settings->color_value (cs_colors[3], mode));
251
252 setScrollBufferSize (settings->value (cs_hist_buffer).toInt ());
253
254 // If the Copy shortcut is Ctrl+C, then the Copy action also emits
255 // a signal for interrupting the current code executed by the worker.
256 // If the Copy shortcut is not Ctrl+C, an extra interrupt action is
257 // set up for emitting the interrupt signal.
258
259 QString sc = settings->sc_value (sc_main_edit_copy);
260
261 // Dis- or enable extra interrupt action: We need an extra option when
262 // copy shortcut is not Ctrl-C or when global shortcuts (like copy) are
263 // disabled.
264 bool extra_ir_action
265 = (sc != QKeySequence (Qt::ControlModifier | Qt::Key_C).toString ())
266 || settings->value (sc_prevent_rl_conflicts).toBool ();
267
268 _interrupt_action->setEnabled (extra_ir_action);
269 has_extra_interrupt (extra_ir_action);
270
271 // check whether shortcut Ctrl-D is in use by the main-window
272 bool ctrld = settings->value (sc_main_ctrld).toBool ();
273 _nop_action->setEnabled (! ctrld);
274}
275
276void
278{
280
281 // context menu
282 setContextMenuPolicy (Qt::CustomContextMenu);
283
284 _contextMenu = new QMenu (this);
285
287 = _contextMenu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this,
288 SLOT (copyClipboard ()));
289
291 = _contextMenu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this,
292 SLOT (pasteClipboard ()));
293
294 _contextMenu->addSeparator ();
295
297 = _contextMenu->addAction (tr ("Select All"), this, SLOT (selectAll ()));
298
300 = _contextMenu->addAction (tr ("Run Selection"), this,
301 SLOT (run_selection ()));
302
304 = _contextMenu->addAction (tr ("Edit selection"), this,
305 SLOT (edit_selected ()));
307 = _contextMenu->addAction (tr ("Help on selection"), this,
308 SLOT (help_on_expression ()));
310 = _contextMenu->addAction (tr ("Documentation on selection"), this,
311 SLOT (doc_on_expression ()));
312
313 _edit_action = _contextMenu->addAction (tr (""), this, SLOT (edit_file ()));
314
315 _contextMenu->addSeparator ();
316
317 _contextMenu->addAction (tr ("Clear Window"), this,
318 SIGNAL (clear_command_window_request ()));
319
320 connect (this, SIGNAL (customContextMenuRequested (QPoint)),
321 this, SLOT (handleCustomContextMenuRequested (QPoint)));
322
323 // extra interrupt action
324 _interrupt_action = new QAction (this);
325 addAction (_interrupt_action);
326
327 _interrupt_action->setShortcut
328 (QKeySequence (Qt::ControlModifier + Qt::Key_C));
329 _interrupt_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
330
331 bool ok = connect (_interrupt_action, SIGNAL (triggered ()),
332 this, SLOT (terminal_interrupt ()));
333
334 // dummy (nop) action catching Ctrl-D in terminal, no connection
335 _nop_action = new QAction (this);
336 addAction (_nop_action);
337
338 _nop_action->setShortcut (QKeySequence (Qt::ControlModifier + Qt::Key_D));
339 _nop_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
340}
void doc_on_expression(void)
Definition: QTerminal.cc:195
QAction * m_help_selected_action
Definition: QTerminal.h:165
virtual QString selectedText()=0
QAction * _edit_action
Definition: QTerminal.h:162
QAction * _paste_action
Definition: QTerminal.h:160
void run_selection(void)
Definition: QTerminal.cc:155
QAction * _run_selection_action
Definition: QTerminal.h:163
void help_on_expression(void)
Definition: QTerminal.cc:187
octave::base_qobject & m_octave_qobj
Definition: QTerminal.h:156
QMenu * _contextMenu
Definition: QTerminal.h:158
virtual void setCursorType(CursorType type, bool blinking)
Definition: QTerminal.h:79
virtual void pasteClipboard(void)=0
void construct(octave::base_qobject &oct_qobj)
Definition: QTerminal.cc:277
virtual void setBackgroundColor(const QColor &color)=0
@ IBeamCursor
Definition: QTerminal.h:74
@ UnderlineCursor
Definition: QTerminal.h:76
void notice_settings(const gui_settings *settings)
Definition: QTerminal.cc:202
QAction * _interrupt_action
Definition: QTerminal.h:168
virtual QList< QAction * > get_hotspot_actions(const QPoint &)
Definition: QTerminal.h:69
void edit_mfile_request(const QString &, int)
virtual void setSelectionColor(const QColor &color)=0
virtual void handleCustomContextMenuRequested(const QPoint &at)
Definition: QTerminal.cc:73
virtual void has_extra_interrupt(bool extra)=0
QAction * _selectall_action
Definition: QTerminal.h:161
virtual void setTerminalFont(const QFont &font)=0
QAction * _copy_action
Definition: QTerminal.h:159
virtual void setCursorColor(bool useForegroundColor, const QColor &color)=0
virtual void copyClipboard(void)=0
void terminal_interrupt(void)
Definition: QTerminal.h:133
QAction * _nop_action
Definition: QTerminal.h:169
QAction * m_doc_selected_action
Definition: QTerminal.h:166
static QTerminal * create(octave::base_qobject &oct_qobj, QWidget *xparent)
Definition: QTerminal.cc:52
void clear_command_window_request(void)
virtual void setForegroundColor(const QColor &color)=0
void execute_command_in_terminal_signal(const QString &)
void edit_file(void)
Definition: QTerminal.cc:170
QAction * m_edit_selected_action
Definition: QTerminal.h:164
virtual void setScrollBufferSize(int value=1000)=0
virtual void selectAll(void)=0
void edit_selected(void)
Definition: QTerminal.cc:179
Base class for Octave interfaces that use Qt.
resource_manager & get_resource_manager(void)
void show_documentation_window(const QString &file)
QIcon icon(const QString &icon_name, bool fallback=true)
const gui_pref cs_colors[2 *cs_colors_count]
const gui_pref cs_color_mode("terminal/color_mode", QVariant(0))
const gui_pref cs_hist_buffer("terminal/history_buffer", QVariant(1000))
const gui_pref cs_font_size("terminal/fontSize", QVariant(10))
const std::vector< std::string > cs_cursor_types
const gui_pref cs_cursor("terminal/cursorType", QVariant("ibeam"))
const gui_pref cs_cursor_use_fgcol("terminal/cursorUseForegroundColor", QVariant(true))
const gui_pref cs_font("terminal/fontName", QVariant())
const gui_pref cs_cursor_blinking("terminal/cursorBlinking", QVariant(true))
const gui_pref global_mono_font("monospace_font", global_font_family)
const gui_pref global_cursor_blinking("cursor_blinking", QVariant(true))
const gui_pref sc_main_ctrld("shortcuts/main_ctrld", QVariant(false))
const sc_pref sc_main_edit_copy(sc_main_edit+":copy", QKeySequence::Copy)
const gui_pref sc_prevent_rl_conflicts("shortcuts/prevent_readline_conflicts", QVariant(false))
const QString key