GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
TerminalModel.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Konsole
3 
4  Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com>
5  Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6 
7  Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
8  Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  02110-1301 USA.
24 */
25 
26 // Own
27 #include "unix/TerminalModel.h"
28 
29 // Standard
30 #include <assert.h>
31 #include <stdlib.h>
32 
33 // Qt
34 #include <QApplication>
35 #include <QtCore/QByteRef>
36 #include <QtCore/QDir>
37 #include <QtCore/QFile>
38 #include <QtCore/QRegExp>
39 #include <QtCore/QStringList>
40 #include <QtCore>
41 
42 #include "unix/TerminalView.h"
43 #include "unix/Vt102Emulation.h"
44 
46  _shellProcess(nullptr)
47  , _emulation(nullptr)
48  , _monitorActivity(false)
49  , _monitorSilence(false)
50  , _notifiedActivity(false)
51  , _autoClose(true)
52  , _wantedClose(false)
53  , _silenceSeconds(10)
54  , _addToUtmp(false)
55  , _fullScripting(false)
56  , _hasDarkBackground(false)
57 {
58  _kpty = kpty;
59 
60  //create emulation backend
61  _emulation = new Vt102Emulation();
62  connect( _emulation, SIGNAL( stateSet(int) ),
63  this, SLOT( activityStateSet(int) ) );
64  connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ),
65  this, SIGNAL( changeTabTextColorRequest( int ) ) );
66  connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)),
67  this, SIGNAL( profileChangeCommandReceived(const QString&)) );
68  // TODO
69  // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this ,
70  // SLOT(onEmulationSizeChange(int,int)) );
71 
72  _selfListener = new SelfListener(kpty->masterFd());
73  _selfListener->start();
74  connect( _selfListener, SIGNAL(recvData(const char*,int)),
75  this, SLOT(onReceiveBlock(const char*,int)), Qt::BlockingQueuedConnection);
76 
77  connect( _emulation, SIGNAL(sendData(const char*,int))
78  ,this,SLOT(sendData(const char*,int)));
79 
80  //connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) );
81  //connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) );
82 
83 
84  //connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) );
85 
86  //setup timer for monitoring session activity
87  _monitorTimer = new QTimer(this);
88  _monitorTimer->setSingleShot(true);
89  connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));
90 }
91 
92 void TerminalModel::setDarkBackground(bool darkBackground)
93 {
94  _hasDarkBackground = darkBackground;
95 }
97 {
98  return _hasDarkBackground;
99 }
100 
101 void TerminalModel::setCodec(QTextCodec* codec)
102 {
103  emulation()->setCodec(codec);
104 }
105 
107 {
108  return _views;
109 }
110 
112 {
113  Q_ASSERT( !_views.contains(widget) );
114 
115  _views.append(widget);
116 
117  if ( _emulation != nullptr )
118  {
119  // connect emulation - view signals and slots
120  connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation ,
121  SLOT(sendKeyEvent(QKeyEvent*)) );
122  connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation ,
123  SLOT(sendMouseEvent(int,int,int,int)) );
124  connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation ,
125  SLOT(sendString(const char*)) );
126 
127  // allow emulation to notify view when the foreground process
128  // indicates whether or not it is interested in mouse signals
129  connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget ,
130  SLOT(setUsesMouse(bool)) );
131 
133 
134  connect( _emulation , SIGNAL(programBracketedPasteModeChanged(bool)) ,
135  widget , SLOT(setBracketedPasteMode(bool)) );
136 
138 
140  }
141 
142  //connect view signals and slots
143  QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this,
144  SLOT(onViewSizeChange(int,int)));
145 
146  QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this ,
147  SLOT(viewDestroyed(QObject*)) );
148  //slot for close
149  //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close()));
150 }
151 
153 {
154  TerminalView* display = (TerminalView*)view;
155 
156  Q_ASSERT( _views.contains(display) );
157 
158  removeView(display);
159 }
160 
161 void TerminalModel::sendData(const char *buf, int len)
162 {
163  ssize_t bytesWritten = ::write(_kpty->masterFd(), buf, len);
164  (void)bytesWritten;
165 }
166 
168 {
169  _views.removeAll(widget);
170 
171  disconnect(widget,nullptr,this,nullptr);
172 
173  if ( _emulation != nullptr )
174  {
175  // disconnect
176  // - key presses signals from widget
177  // - mouse activity signals from widget
178  // - string sending signals from widget
179  //
180  // ... and any other signals connected in addView()
181  disconnect( widget, nullptr, _emulation, nullptr);
182 
183  // disconnect state change signals emitted by emulation
184  disconnect( _emulation , nullptr , widget , nullptr);
185  }
186 
187  // close the session automatically when the last view is removed
188  if ( _views.count() == 0 )
189  {
190  close();
191  }
192 }
193 
195 {
196  emit started();
197 }
198 
200 {
201  //FIXME: The idea here is that the notification popup will appear to tell the user than output from
202  //the terminal has stopped and the popup will disappear when the user activates the session.
203  //
204  //This breaks with the addition of multiple views of a session. The popup should disappear
205  //when any of the views of the session becomes active
206 
207 
208  //FIXME: Make message text for this notification and the activity notification more descriptive.
209  if (_monitorSilence) {
210  // KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(),
211  // QApplication::activeWindow(),
212  // KNotification::CloseWhenWidgetActivated);
214  }
215  else
216  {
218  }
219 
220  _notifiedActivity=false;
221 }
222 
224 {
225  if (state==NOTIFYBELL)
226  {
227  emit bellRequest("");
228  }
229  else if (state==NOTIFYACTIVITY)
230  {
231  if (_monitorSilence) {
232  _monitorTimer->start(_silenceSeconds*1000);
233  }
234 
235  if ( _monitorActivity ) {
236  //FIXME: See comments in Session::monitorTimerDone()
237  if (!_notifiedActivity) {
238  // KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(),
239  // QApplication::activeWindow(),
240  // KNotification::CloseWhenWidgetActivated);
241  _notifiedActivity=true;
242  }
243  }
244  }
245 
250 
251  emit stateChanged(state);
252 }
253 
254 void TerminalModel::onViewSizeChange(int /*height*/, int /*width*/)
255 {
257 }
258 void TerminalModel::onEmulationSizeChange(int lines , int columns)
259 {
260  setSize( QSize(lines,columns) );
261 }
262 
264 {
265  QListIterator<TerminalView*> viewIter(_views);
266 
267  int minLines = -1;
268  int minColumns = -1;
269 
270  // minimum number of lines and columns that views require for
271  // their size to be taken into consideration ( to avoid problems
272  // with new view widgets which haven't yet been set to their correct size )
273  const int VIEW_LINES_THRESHOLD = 2;
274  const int VIEW_COLUMNS_THRESHOLD = 2;
275 
276  //select largest number of lines and columns that will fit in all visible views
277  while ( viewIter.hasNext() )
278  {
279  TerminalView* view = viewIter.next();
280  if ( view->isHidden() == false &&
281  view->lines() >= VIEW_LINES_THRESHOLD &&
282  view->columns() >= VIEW_COLUMNS_THRESHOLD )
283  {
284  minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );
285  minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() );
286  }
287  }
288 
289  // backend emulation must have a _terminal of at least 1 column x 1 line in size
290  if ( minLines > 0 && minColumns > 0 )
291  {
292  _emulation->setImageSize( minLines , minColumns );
293  _kpty->setWinSize (minLines, minColumns);
294  //_shellProcess->setWindowSize( minLines , minColumns );
295  }
296 }
297 
299 {
300 }
301 
303 {
304  _autoClose = true;
305  _wantedClose = true;
306 }
307 
308 void TerminalModel::sendText(const QString &text) const
309 {
311 }
312 
314 {
315  delete _emulation;
316 }
317 
318 void TerminalModel::setProfileKey(const QString& key)
319 {
320  _profileKey = key;
321  emit profileChanged(key);
322 }
323 QString TerminalModel::profileKey() const { return _profileKey; }
324 
326 {
327  emit finished();
328 }
329 
331 {
332  return _emulation;
333 }
334 
336 {
337  return _emulation->keyBindings();
338 }
339 
340 void TerminalModel::setKeyBindings(const QString &id)
341 {
343 }
344 
346 {
347  _emulation->setHistory(hType);
348 }
349 
351 {
352  return _emulation->history();
353 }
354 
356 {
358 }
359 
360 // unused currently
362 // unused currently
364 
366 {
367  _monitorActivity=_monitor;
368  _notifiedActivity=false;
369 
371 }
372 
374 {
375  if (_monitorSilence==_monitor)
376  return;
377 
378  _monitorSilence=_monitor;
379  if (_monitorSilence)
380  {
381  _monitorTimer->start(_silenceSeconds*1000);
382  }
383  else
384  _monitorTimer->stop();
385 
387 }
388 
390 {
391  _silenceSeconds=seconds;
392  if (_monitorSilence) {
393  _monitorTimer->start(_silenceSeconds*1000);
394  }
395 }
396 
398 {
399  _addToUtmp = set;
400 }
401 
402 void TerminalModel::onReceiveBlock(const char* buf, int len )
403 {
404  _emulation->receiveData( buf, len );
405  emit receivedData( QString::fromLatin1( buf, len ) );
406 }
407 
408 QSize TerminalModel::size()
409 {
410  return _emulation->imageSize();
411 }
412 
413 void TerminalModel::setSize(const QSize& size)
414 {
415  if ((size.width() <= 1) || (size.height() <= 1))
416  return;
417 
418  emit resizeRequest(size);
419 }
@ NOTIFYBELL
The terminal program has triggered a bell event to get the user's attention.
Definition: Emulation.h:58
@ NOTIFYACTIVITY
The emulation is currently receiving data from its terminal input.
Definition: Emulation.h:63
@ NOTIFYSILENCE
Definition: Emulation.h:66
@ NOTIFYNORMAL
The emulation is currently receiving user input.
Definition: Emulation.h:53
Base class for terminal emulation back-ends.
Definition: Emulation.h:119
bool programUsesMouse() const
Returns true if the active terminal program wants mouse input events.
Definition: Emulation.cpp:76
void receiveData(const char *buffer, int len)
Processes an incoming stream of characters.
Definition: Emulation.cpp:262
QString keyBindings()
Returns the name of the emulation's current key bindings.
Definition: Emulation.cpp:187
const HistoryType & history()
Returns the history store used by this emulation.
Definition: Emulation.cpp:158
ScreenWindow * createWindow()
Creates a new window onto the output from this emulation.
Definition: Emulation.cpp:96
virtual void sendText(const QString &text)=0
Interprets a sequence of characters and sends the result to the terminal.
QSize imageSize()
Returns the size of the screen image which the emulation produces.
Definition: Emulation.cpp:340
virtual void setImageSize(int lines, int columns)
Change the size of the emulation's image.
Definition: Emulation.cpp:326
bool programBracketedPasteMode() const
Definition: Emulation.cpp:86
void clearHistory()
Clears the history scroll.
Definition: Emulation.cpp:147
void setKeyBindings(const QString &name)
Sets the key bindings used to key events ( received through sendKeyEvent() ) into character streams t...
Definition: Emulation.cpp:182
void setHistory(const HistoryType &)
Sets the history store used by this emulation.
Definition: Emulation.cpp:151
void setCodec(const QTextCodec *)
Sets the codec used to decode incoming characters.
Definition: Emulation.cpp:163
Provides primitives for opening & closing a pseudo TTY pair, assigning the controlling TTY,...
Definition: kpty.h:35
int masterFd() const
Definition: kpty.cpp:479
bool setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
Definition: kpty.cpp:449
void onReceiveBlock(const char *buffer, int len)
void setProfileKey(const QString &profileKey)
Sets the profile associated with this session.
void bellRequest(const QString &message)
Emitted when a bell event occurs in the session.
Emulation * _emulation
TerminalModel(KPty *kpty)
Constructs a new session.
QString keyBindings
Definition: TerminalModel.h:61
void setCodec(QTextCodec *codec)
Sets the text codec used by this session's terminal emulation.
void profileChangeCommandReceived(const QString &text)
Emitted when a profile change command is received from the terminal.
Emulation * emulation() const
Returns the terminal emulation instance being used to encode / decode characters to / from the proces...
void updateTerminalSize()
QString _profileKey
QList< TerminalView * > _views
void viewDestroyed(QObject *view)
void setMonitorSilence(bool)
Enables monitoring for silence in the session.
void sendText(const QString &text) const
Sends text to the current foreground terminal program.
void run()
Starts the terminal session.
void resizeRequest(const QSize &size)
Emitted when the terminal process requests a change in the size of the terminal window.
QList< TerminalView * > views() const
Returns the views connected to this session.
bool _hasDarkBackground
void activityStateSet(int)
void sendData(const char *buf, int len)
void addView(TerminalView *widget)
Adds a new view for this session.
QTimer * _monitorTimer
void stateChanged(int state)
Emitted when the activity state of this session changes.
void onViewSizeChange(int height, int width)
void receivedData(const QString &text)
Emitted when output is received from the terminal process.
void refresh()
Attempts to get the shell program to redraw the current display area.
const HistoryType & historyType() const
Returns the type of history store used by this session.
void onEmulationSizeChange(int lines, int columns)
bool isMonitorActivity() const
Returns true if monitoring for activity is enabled.
bool isMonitorSilence() const
Returns true if monitoring for inactivity (silence) in the session is enabled.
void setMonitorActivity(bool)
Enables monitoring for activity in the session.
void setKeyBindings(const QString &id)
Sets the key bindings used by this session.
void started()
Emitted when the terminal process starts.
void changeTabTextColorRequest(int)
Requests that the color the text for any tabs associated with this session should be changed;.
QString profileKey() const
Returns the profile key associated with this session.
void setAddToUtmp(bool)
Specifies whether a utmp entry should be created for the pty used by this session.
void clearHistory()
Clears the history store used by this session.
void setDarkBackground(bool darkBackground)
Sets whether the session has a dark background or not.
void setSize(const QSize &size)
Emits a request to resize the session to accommodate the specified window size.
void removeView(TerminalView *widget)
Removes a view from this session.
void monitorTimerDone()
bool hasDarkBackground() const
Returns true if the session has a dark background.
void profileChanged(const QString &profile)
Emitted when the session's profile has changed.
void close()
Closes the terminal session.
void finished()
Emitted when the terminal process exits.
void setMonitorSilenceSeconds(int seconds)
See setMonitorSilence()
bool _notifiedActivity
SelfListener * _selfListener
void setHistoryType(const HistoryType &type)
Sets the type of history store used by this session.
A widget which displays output from a terminal emulation and sends input keypresses and mouse activit...
Definition: TerminalView.h:64
void setUsesMouse(bool usesMouse)
Sets whether the program whoose output is being displayed in the view is interested in mouse events.
void setScreenWindow(ScreenWindow *window)
Sets the terminal screen section which is displayed in this widget.
int columns()
Returns the number of characters of text which can be displayed on each line in the widget.
Definition: TerminalView.h:237
int lines()
Returns the number of lines of text which can be displayed in the widget.
Definition: TerminalView.h:229
void setBracketedPasteMode(bool bracketedPasteMode)
Provides an xterm compatible terminal emulation based on the DEC VT102 terminal.
static uint32_t state[624]
Definition: randmtzig.cc:190
F77_RET_T len
Definition: xerbla.cc:61