GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 <[email protected]>
5  Copyright (C) 1997,1998 by Lars Doelle <[email protected]>
6 
7  Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
8  Copyright (C) 2012-2015 Jacob Dawid <[email protected]>
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(0)
47  , _emulation(0)
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 != 0 )
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 
135  }
136 
137  //connect view signals and slots
138  QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this,
139  SLOT(onViewSizeChange(int,int)));
140 
141  QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this ,
142  SLOT(viewDestroyed(QObject*)) );
143  //slot for close
144  //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close()));
145 }
146 
148 {
149  TerminalView* display = (TerminalView*)view;
150 
151  Q_ASSERT( _views.contains(display) );
152 
153  removeView(display);
154 }
155 
156 void TerminalModel::sendData(const char *buf, int len)
157 {
158  ssize_t bytesWritten = ::write(_kpty->masterFd(), buf, len);
159  (void)bytesWritten;
160 }
161 
163 {
164  _views.removeAll(widget);
165 
166  disconnect(widget,0,this,0);
167 
168  if ( _emulation != 0 )
169  {
170  // disconnect
171  // - key presses signals from widget
172  // - mouse activity signals from widget
173  // - string sending signals from widget
174  //
175  // ... and any other signals connected in addView()
176  disconnect( widget, 0, _emulation, 0);
177 
178  // disconnect state change signals emitted by emulation
179  disconnect( _emulation , 0 , widget , 0);
180  }
181 
182  // close the session automatically when the last view is removed
183  if ( _views.count() == 0 )
184  {
185  close();
186  }
187 }
188 
190 {
191  emit started();
192 }
193 
195 {
196  //FIXME: The idea here is that the notification popup will appear to tell the user than output from
197  //the terminal has stopped and the popup will disappear when the user activates the session.
198  //
199  //This breaks with the addition of multiple views of a session. The popup should disappear
200  //when any of the views of the session becomes active
201 
202 
203  //FIXME: Make message text for this notification and the activity notification more descriptive.
204  if (_monitorSilence) {
205  // KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(),
206  // QApplication::activeWindow(),
207  // KNotification::CloseWhenWidgetActivated);
209  }
210  else
211  {
213  }
214 
215  _notifiedActivity=false;
216 }
217 
219 {
220  if (state==NOTIFYBELL)
221  {
222  emit bellRequest("");
223  }
224  else if (state==NOTIFYACTIVITY)
225  {
226  if (_monitorSilence) {
227  _monitorTimer->start(_silenceSeconds*1000);
228  }
229 
230  if ( _monitorActivity ) {
231  //FIXME: See comments in Session::monitorTimerDone()
232  if (!_notifiedActivity) {
233  // KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(),
234  // QApplication::activeWindow(),
235  // KNotification::CloseWhenWidgetActivated);
236  _notifiedActivity=true;
237  }
238  }
239  }
240 
241  if ( state==NOTIFYACTIVITY && !_monitorActivity )
242  state = NOTIFYNORMAL;
243  if ( state==NOTIFYSILENCE && !_monitorSilence )
244  state = NOTIFYNORMAL;
245 
246  emit stateChanged(state);
247 }
248 
249 void TerminalModel::onViewSizeChange(int /*height*/, int /*width*/)
250 {
252 }
253 void TerminalModel::onEmulationSizeChange(int lines , int columns)
254 {
255  setSize( QSize(lines,columns) );
256 }
257 
259 {
260  QListIterator<TerminalView*> viewIter(_views);
261 
262  int minLines = -1;
263  int minColumns = -1;
264 
265  // minimum number of lines and columns that views require for
266  // their size to be taken into consideration ( to avoid problems
267  // with new view widgets which haven't yet been set to their correct size )
268  const int VIEW_LINES_THRESHOLD = 2;
269  const int VIEW_COLUMNS_THRESHOLD = 2;
270 
271  //select largest number of lines and columns that will fit in all visible views
272  while ( viewIter.hasNext() )
273  {
274  TerminalView* view = viewIter.next();
275  if ( view->isHidden() == false &&
276  view->lines() >= VIEW_LINES_THRESHOLD &&
277  view->columns() >= VIEW_COLUMNS_THRESHOLD )
278  {
279  minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );
280  minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() );
281  }
282  }
283 
284  // backend emulation must have a _terminal of at least 1 column x 1 line in size
285  if ( minLines > 0 && minColumns > 0 )
286  {
287  _emulation->setImageSize( minLines , minColumns );
288  _kpty->setWinSize (minLines, minColumns);
289  //_shellProcess->setWindowSize( minLines , minColumns );
290  }
291 }
292 
294 {
295 }
296 
298 {
299  _autoClose = true;
300  _wantedClose = true;
301 }
302 
303 void TerminalModel::sendText(const QString &text) const
304 {
305  _emulation->sendText(text);
306 }
307 
309 {
310  delete _emulation;
311 }
312 
313 void TerminalModel::setProfileKey(const QString& key)
314 {
315  _profileKey = key;
316  emit profileChanged(key);
317 }
318 QString TerminalModel::profileKey() const { return _profileKey; }
319 
321 {
322  emit finished();
323 }
324 
326 {
327  return _emulation;
328 }
329 
330 QString TerminalModel::keyBindings() const
331 {
332  return _emulation->keyBindings();
333 }
334 
335 void TerminalModel::setKeyBindings(const QString &id)
336 {
338 }
339 
341 {
342  _emulation->setHistory(hType);
343 }
344 
346 {
347  return _emulation->history();
348 }
349 
351 {
353 }
354 
355 // unused currently
357 // unused currently
359 
361 {
362  _monitorActivity=_monitor;
363  _notifiedActivity=false;
364 
366 }
367 
369 {
370  if (_monitorSilence==_monitor)
371  return;
372 
373  _monitorSilence=_monitor;
374  if (_monitorSilence)
375  {
376  _monitorTimer->start(_silenceSeconds*1000);
377  }
378  else
379  _monitorTimer->stop();
380 
382 }
383 
385 {
386  _silenceSeconds=seconds;
387  if (_monitorSilence) {
388  _monitorTimer->start(_silenceSeconds*1000);
389  }
390 }
391 
393 {
394  _addToUtmp = set;
395 }
396 
397 void TerminalModel::onReceiveBlock(const char* buf, int len )
398 {
399  _emulation->receiveData( buf, len );
400  emit receivedData( QString::fromLatin1( buf, len ) );
401 }
402 
403 QSize TerminalModel::size()
404 {
405  return _emulation->imageSize();
406 }
407 
408 void TerminalModel::setSize(const QSize& size)
409 {
410  if ((size.width() <= 1) || (size.height() <= 1))
411  return;
412 
413  emit resizeRequest(size);
414 }
bool isMonitorSilence() const
Returns true if monitoring for inactivity (silence) in the session is enabled.
void onViewSizeChange(int height, int width)
void stateChanged(int state)
Emitted when the activity state of this session changes.
void addView(TerminalView *widget)
Adds a new view for this session.
void resizeRequest(const QSize &size)
Emitted when the terminal process requests a change in the size of the terminal window.
The terminal program has triggered a bell event to get the user's attention.
Definition: Emulation.h:58
int masterFd() const
Definition: kpty.cpp:481
void setScreenWindow(ScreenWindow *window)
Sets the terminal screen section which is displayed in this widget.
void onReceiveBlock(const char *buffer, int len)
void viewDestroyed(QObject *view)
SelfListener * _selfListener
void sendText(const QString &text) const
Sends text to the current foreground terminal program.
void run()
Starts the terminal session.
void clearHistory()
Clears the history store used by this session.
static uint32_t state[624]
Definition: randmtzig.c:188
void profileChanged(const QString &profile)
Emitted when the session's profile has changed.
void receivedData(const QString &text)
Emitted when output is received from the terminal process.
int columns()
Returns the number of characters of text which can be displayed on each line in the widget...
Definition: TerminalView.h:250
void sendData(const char *buf, int len)
Base class for terminal emulation back-ends.
Definition: Emulation.h:118
void setKeyBindings(const QString &id)
Sets the key bindings used by this session.
virtual void setImageSize(int lines, int columns)
Change the size of the emulation's image.
Definition: Emulation.cpp:313
void bellRequest(const QString &message)
Emitted when a bell event occurs in the session.
bool hasDarkBackground() const
Returns true if the session has a dark background.
QSize imageSize()
Returns the size of the screen image which the emulation produces.
Definition: Emulation.cpp:327
The emulation is currently receiving data from its terminal input.
Definition: Emulation.h:63
void finished()
Emitted when the terminal process exits.
Emulation * emulation() const
Returns the terminal emulation instance being used to encode / decode characters to / from the proces...
int lines()
Returns the number of lines of text which can be displayed in the widget.
Definition: TerminalView.h:242
bool _notifiedActivity
QString profileKey() const
Returns the profile key associated with this session.
void setHistoryType(const HistoryType &type)
Sets the type of history store used by this session.
TerminalModel(KPty *kpty)
Constructs a new session.
bool _hasDarkBackground
virtual void sendText(const QString &text)=0
Interprets a sequence of characters and sends the result to the terminal.
bool programUsesMouse() const
Returns true if the active terminal program wants mouse input events.
Definition: Emulation.cpp:73
void onEmulationSizeChange(int lines, int columns)
QString keyBindings()
Returns the name of the emulation's current key bindings.
Definition: Emulation.cpp:174
void close()
Closes the terminal session.
void refresh()
Attempts to get the shell program to redraw the current display area.
bool setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
Definition: kpty.cpp:451
void updateTerminalSize()
void clearHistory()
Clears the history scroll.
Definition: Emulation.cpp:134
void profileChangeCommandReceived(const QString &text)
Emitted when a profile change command is received from the terminal.
void monitorTimerDone()
void removeView(TerminalView *widget)
Removes a view from this session.
const HistoryType & historyType() const
Returns the type of history store used by this session.
const HistoryType & history()
Returns the history store used by this emulation.
Definition: Emulation.cpp:145
QList< TerminalView * > _views
size_t size(T const (&)[z])
Definition: help.cc:103
void setSize(const QSize &size)
Emits a request to resize the session to accommodate the specified window size.
QString keyBindings() const
Returns the name of the key bindings used by this session.
void started()
Emitted when the terminal process starts.
void setAddToUtmp(bool)
Specifies whether a utmp entry should be created for the pty used by this session.
void setDarkBackground(bool darkBackground)
Sets whether the session has a dark background or not.
void setMonitorSilence(bool)
Enables monitoring for silence in the session.
QList< TerminalView * > views() const
Returns the views connected to this session.
ScreenWindow * createWindow()
Creates a new window onto the output from this emulation.
Definition: Emulation.cpp:83
void changeTabTextColorRequest(int)
Requests that the color the text for any tabs associated with this session should be changed;...
void setCodec(QTextCodec *codec)
Sets the text codec used by this session's terminal emulation.
void setMonitorSilenceSeconds(int seconds)
See setMonitorSilence()
void setCodec(const QTextCodec *)
Sets the codec used to decode incoming characters.
Definition: Emulation.cpp:150
The emulation is currently receiving user input.
Definition: Emulation.h:53
void setProfileKey(const QString &profileKey)
Sets the profile associated with this session.
Provides an xterm compatible terminal emulation based on the DEC VT102 terminal.
Emulation * _emulation
QString _profileKey
void setMonitorActivity(bool)
Enables monitoring for activity in the session.
void setUsesMouse(bool usesMouse)
Sets whether the program whoose output is being displayed in the view is interested in mouse events...
void receiveData(const char *buffer, int len)
Processes an incoming stream of characters.
Definition: Emulation.cpp:249
bool isMonitorActivity() const
Returns true if monitoring for activity is enabled.
void setHistory(const HistoryType &)
Sets the history store used by this emulation.
Definition: Emulation.cpp:138
A widget which displays output from a terminal emulation and sends input keypresses and mouse activit...
Definition: TerminalView.h:63
void activityStateSet(int)
void setKeyBindings(const QString &name)
Sets the key bindings used to key events ( received through sendKeyEvent() ) into character streams t...
Definition: Emulation.cpp:169
Provides primitives for opening & closing a pseudo TTY pair, assigning the controlling TTY...
Definition: kpty.h:35
QSize size()
Returns the terminal session's window size in lines and columns.
QTimer * _monitorTimer