GNU Octave 7.1.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
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
92void TerminalModel::setDarkBackground(bool darkBackground)
93{
94 _hasDarkBackground = darkBackground;
95}
97{
98 return _hasDarkBackground;
99}
100
101void 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
161void 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);
242 }
243 }
244 }
245
250
251 emit stateChanged(state);
252}
253
254void TerminalModel::onViewSizeChange(int /*height*/, int /*width*/)
255{
257}
258void 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
308void TerminalModel::sendText(const QString &text) const
309{
310 _emulation->sendText(text);
311}
312
314{
315 delete _emulation;
316}
317
318void TerminalModel::setProfileKey(const QString& key)
319{
320 _profileKey = key;
321 emit profileChanged(key);
322}
323QString 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
340void 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
402void TerminalModel::onReceiveBlock(const char* buf, int len )
403{
404 _emulation->receiveData( buf, len );
405 emit receivedData( QString::fromLatin1( buf, len ) );
406}
407
409{
410 return _emulation->imageSize();
411}
412
413void 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:482
bool setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
Definition: kpty.cpp:452
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:192
F77_RET_T len
Definition: xerbla.cc:61