MauiKit Terminal

ksession.cpp
1/*
2 This file is part of Konsole QML plugin,
3 which is a terminal emulator from KDE.
4
5Copyright 2013 by Dmitry Zagnoyko <hiroshidi@gmail.com>
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301 USA.
21*/
22
23// Own
24#include "ksession.h"
25#include <KShell>
26
27// Qt
28#include <QtCore5Compat/QTextCodec>
29
30#include <QDir>
31#include <QDebug>
32
33// Konsole
34#include "KeyboardTranslator.h"
35#include "HistorySearch.h"
36
37
38KSession::KSession(QObject *parent) : QObject(parent)
39 ,m_session(createSession(QString()))
40{
41 connect(m_session.get(), &Konsole::Session::started, this, &KSession::started);
42 connect(m_session.get(), &Konsole::Session::finished, this, &KSession::sessionFinished);
45 connect(m_session.get(), &Konsole::Session::stateChanged, [this](int state)
46 {
47 if(!hasActiveProcess())
48 {
49 qDebug() <<"Process Finished"<< m_session->iconText() << m_session->iconName() << m_session->isMonitorSilence() << m_session->program() << state << getForegroundProcessError();
50 }else
51 {
52 qDebug() <<"Process started"<< m_session->iconText() << m_session->iconName() << m_session->isMonitorSilence() << m_session->program() << state << getForegroundProcessError();
53 }
54
55 Q_EMIT hasActiveProcessChanged();
56
57 if(m_processName != m_session->foregroundProcessName())
58 {
59 m_processName = m_session->foregroundProcessName();
60 Q_EMIT foregroundProcessNameChanged();
61 }
62 });
63
64 // m_session->setMonitorSilence(true);
65
66 connect(m_session.get(), &Konsole::Session::bellRequest, [this](QString message)
67 {
68 Q_EMIT bellRequest(message);
69 });
70
71 connect(m_session.get(), &Konsole::Session::changeTabTextColorRequest, [this](int state)
72 {
73 qDebug() << "changeTabTextColorRequest" << state;
74 });
75
76 connect(m_session.get(), &Konsole::Session::changeTabTextColorRequest, [this](int state)
77 {
78 qDebug() << "changeTabTextColorRequest" << state;
79 });
80
82 {
83 qDebug() << "changeBackgroundColorRequest" << state;
84 });
85
86 connect(m_session.get(), &Konsole::Session::openUrlRequest, [this](QString state)
87 {
88 qDebug() << "openUrlRequest" << state;
89 });
90
91 connect(m_session.get(), &Konsole::Session::activity, [this]()
92 {
93 qDebug() << "activity";
94 Q_EMIT processHasSilent(false);
95 });
96
97 connect(m_session.get(), &Konsole::Session::silence, [this]()
98 {
99 qDebug() << "silence";
100 Q_EMIT processHasSilent(true);
101 });
102}
103
104KSession::~KSession()
105{
106 if (m_session)
107 {
108 m_session->close();
109 m_session->disconnect();
110 }
111}
112
113int KSession::getForegroundProcessError() const
114{
115 return m_session->foregroundProcessError();
116}
117
118
120{
121 if(m_session->isMonitorSilence() == value)
122 return;
123
124 m_session->setMonitorSilence(value);
126}
127
129{
130 return m_session->isMonitorSilence();
131}
132
134{
135 m_session->setTitle(Session::NameRole, name);
136}
137
138std::unique_ptr<Session> KSession::createSession(QString name)
139{
140 auto session = std::make_unique<Session>();
141
142 session->setTitle(Session::NameRole, name);
143
144 /* Thats a freaking bad idea!!!!
145 * /bin/bash is not there on every system
146 * better set it to the current $SHELL
147 * Maybe you can also make a list available and then let the widget-owner decide what to use.
148 * By setting it to $SHELL right away we actually make the first filecheck obsolete.
149 * But as iam not sure if you want to do anything else ill just let both checks in and set this to $SHELL anyway.
150 */
151
152 //cool-old-term: There is another check in the code. Not sure if useful.
153
154 QString envshell = getenv("SHELL");
155 QString shellProg = !envshell.isNull() ? envshell : QStringLiteral("/bin/bash");
156 session->setProgram(shellProg);
157
158 setenv("TERM", "xterm-256color", 1);
159
160 //session->setProgram();
161
163 session->setArguments(args);
164 session->setAutoClose(true);
165
166 session->setCodec(QTextCodec::codecForName("UTF-8"));
167
168 session->setFlowControlEnabled(true);
169 session->setHistoryType(HistoryTypeBuffer(1000));
170 session->setMonitorSilenceSeconds(30);
171 session->setMonitorActivity(true);
172 // session->setDarkBackground(true);
173
174 session->setKeyBindings(QString());
175
176 return session;
177}
178
179/////////////////////////////////////////////////////////////////////////////////////
180/////////////////////////////////////////////////////////////////////////////////////
181
182
183int KSession::getRandomSeed()
184{
185 return m_session->sessionId() * 31;
186}
187
189{
190 m_session->setView(display);
191}
192
194{
195 m_session->removeView(display);
196}
197
198void KSession::sessionFinished()
199{
201}
202
203void KSession::selectionChanged(bool textSelected)
204{
205 Q_UNUSED(textSelected)
206}
207
209{
210 if (m_session->isRunning())
211 {
212 return;
213 }
214
215 m_session->run();
216}
217
218bool KSession::sendSignal(int signal)
219{
220 if (!m_session->isRunning())
221 {
222 return false;
223 }
224
225 return m_session->sendSignal(signal);
226}
227
229{
230 return m_session->processId();
231}
232
234{
235 if(currentDir() == dir)
236 return;
237 /*
238 this is a very hackish way of trying to determine if the shell is in
239 the foreground before attempting to change the directory. It may not
240 be portable to anything other than Linux.
241 */
242 QString strCmd;
243 strCmd.setNum(getShellPID());
244 strCmd.prepend(u"ps -j ");
245 strCmd.append(u" | tail -1 | awk '{ print $5 }' | grep -q \\+");
246 int retval = system(strCmd.toStdString().c_str());
247
248 if (!retval)
249 {
250 // Send prior Ctrl-E, Ctrl-U to ensure the line is empty. This is
251 // mandatory, otherwise sending a 'cd x\n' to a prompt with 'rm -rf *'
252 // would result in data loss.
253 sendText(QStringLiteral("\x05\x15"));
254
255 sendText(u"cd " + KShell::quoteArg(dir) + '\r');
257 }
258}
259
260void KSession::setEnvironment(const QStringList &environment)
261{
262 m_session->setEnvironment(environment);
263}
264
266{
267 if(m_session->program() == progname)
268 return;
269
270 m_session->setProgram(progname);
272}
273
275{
276 return m_session->program();
277}
278
280{
281 if(_initialWorkingDirectory != dir)
282 {
283 _initialWorkingDirectory = dir;
284 m_session->setInitialWorkingDirectory(dir);
287 }
288}
289
290QString KSession::getInitialWorkingDirectory()
291{
292 return _initialWorkingDirectory;
293}
294
296{
297 if(m_session->arguments() == args)
298 return;
299
300 m_session->setArguments(args);
302}
303
304void KSession::setTextCodec(QTextCodec *codec)
305{
306 m_session->setCodec(codec);
307}
308
310{
311 // if(historySize() != lines )
312 // {
313 // if (lines < 0)
314 // m_session->setHistoryType(HistoryTypeFile());
315 // else
316 // m_session->setHistoryType(HistoryTypeBuffer(lines));
317 //
318 // Q_EMIT historySizeChanged();
319 // }
320}
321
322int KSession::historySize() const
323{
324 if(m_session->historyType().isUnlimited())
325 {
326 return -1;
327 } else {
328 return m_session->historyType().maximumLineCount();
329 }
330}
331
332QString KSession::getHistory() const
333{
334 QString history;
335 QTextStream historyStream(&history);
336 PlainTextDecoder historyDecoder;
337
338 historyDecoder.begin(&historyStream);
339 m_session->emulation()->writeToStream(&historyDecoder);
340 historyDecoder.end();
341
342 return history;
343}
344
346{
347 m_session->sendText(text);
348}
349
350void KSession::sendKey(int rep, int key, int mod) const
351{
352 Q_UNUSED(rep);
353 Q_UNUSED(key);
354 Q_UNUSED(mod);
355
356 //TODO implement or remove this function.
357 // Qt::KeyboardModifier kbm = Qt::KeyboardModifier(mod);
358
359 // QKeyEvent qkey(QEvent::KeyPress, key, kbm);
360
361 // while (rep > 0){
362 // m_session->sendKey(&qkey);
363 // --rep;
364 // }
365}
366
368{
369 m_session->emulation()->clearEntireScreen();
370}
371
372void KSession::search(const QString &regexp, int startLine, int startColumn, bool forwards)
373{
374 HistorySearch *history = new HistorySearch(QPointer<Emulation>(m_session->emulation()), QRegExp(regexp), forwards, startColumn, startLine, this);
375 connect(history, &HistorySearch::matchFound, this, &KSession::matchFound);
376 connect(history, &HistorySearch::noMatchFound, this, &KSession::noMatchFound);
377 history->search();
378}
379
381{
382 m_session->setFlowControlEnabled(enabled);
383}
384
386{
387 return m_session->flowControlEnabled();
388}
389
391{
392 m_session->setKeyBindings(kb);
394}
395
396QString KSession::getKeyBindings()
397{
398 return m_session->keyBindings();
399}
400
405
407{
408 return m_session->keyBindings();
409}
410
411QString KSession::getTitle()
412{
413 // if (m_session->currentDir() == QDir::homePath()) {
414 // return m_session->currentDir();
415 // }
416 //
417 // if (m_session->currentDir() == "/")
418 // return m_session->currentDir();
419 //
420 // return QDir(m_session->currentDir()).dirName();
421
422 return m_session->userTitle();
423}
424
426{
427 return m_session->processId() != m_session->foregroundProcessId();
428}
429
431{
432 return m_session->foregroundProcessName();
433}
434
436{
437 return m_session->currentDir();
438}
439
441{
442 return m_session->arguments();
443}
QString history
The commands history.
Definition ksession.h:69
void clearScreen()
clearScreen
Definition ksession.cpp:367
void titleChanged()
titleChanged
void removeView(TerminalDisplay *display)
removeView
Definition ksession.cpp:193
void startShellProgram()
startShellProgram
Definition ksession.cpp:208
void addView(TerminalDisplay *display)
addView
Definition ksession.cpp:188
void search(const QString &regexp, int startLine=0, int startColumn=0, bool forwards=true)
Search history.
Definition ksession.cpp:372
bool sendSignal(int signal)
sendSignal
Definition ksession.cpp:218
void noMatchFound()
noMatchFound
void initialWorkingDirectoryChanged()
initialWorkingDirectoryChanged
QString keyBindings()
Return current key bindings.
Definition ksession.cpp:406
QString currentDir
The current directory of the session.
Definition ksession.h:84
void setTitle(QString name)
setTitle
Definition ksession.cpp:133
void changedKeyBindings(QString kb)
changedKeyBindings
QString foregroundProcessName
The name of the current process running.
Definition ksession.h:79
void setInitialWorkingDirectory(const QString &dir)
Initial working directory.
Definition ksession.cpp:279
void changeDir(const QString &dir)
changeDir
Definition ksession.cpp:233
void setArgs(const QStringList &args)
Shell program args, default is none.
Definition ksession.cpp:295
void setShellProgram(const QString &progname)
Shell program, default is /bin/bash
Definition ksession.cpp:265
void monitorSilenceChanged()
monitorSilenceChanged
void sendKey(int rep, int key, int mod) const
Emulate a key press.
Definition ksession.cpp:350
bool hasActiveProcess
Whether the session has an active process running.
Definition ksession.h:74
int historySize
Allows to set the amount of lines to store in the history.
Definition ksession.h:89
void setEnvironment(const QStringList &environment)
Set the custom enviroment variables.
Definition ksession.cpp:260
void matchFound(int startColumn, int startLine, int endColumn, int endLine)
matchFound
void shellProgramChanged()
shellProgramChanged
void setKeyBindings(const QString &kb)
Set named key binding for the session.
Definition ksession.cpp:390
QStringList args() const
args
Definition ksession.cpp:440
int getShellPID()
getShellPID
Definition ksession.cpp:228
void currentDirChanged()
currentDirChanged
void setHistorySize(int lines)
History size for scrolling.
Definition ksession.cpp:309
void setMonitorSilence(bool value)
setMonitorSilence
Definition ksession.cpp:119
void finished()
finished
void setFlowControlEnabled(bool enabled)
Sets whether flow control is enabled.
Definition ksession.cpp:380
void started()
started
bool flowControlEnabled(void)
Returns whether flow control is enabled.
Definition ksession.cpp:385
static QStringList availableKeyBindings()
Sets whether the flow control warning box should be shown when the flow control stop key (Ctrl+S) is ...
Definition ksession.cpp:401
void argsChanged()
argsChanged
void setTextCodec(QTextCodec *codec)
Text codec, default is UTF-8.
Definition ksession.cpp:304
void sendText(QString text)
Send some text to terminal.
Definition ksession.cpp:345
QString shellProgram
Allows to change the default shell program, by default bash is used.
Definition ksession.h:59
bool monitorSilence
Whether to monitor when the session has gone silent.
Definition ksession.h:94
QList< QString > allTranslators()
Returns a list of the names of available keyboard translators.
static KeyboardTranslatorManager * instance()
Returns the global KeyboardTranslatorManager instance.
void end() override
End decoding.
void begin(QTextStream *output) override
Begin decoding characters.
void started()
Emitted when the terminal process starts.
void finished()
Emitted when the terminal process exits.
void titleChanged()
Emitted when the session's title has changed.
void openUrlRequest(const QString &url)
TODO: Document me.
void changeTabTextColorRequest(int)
Requests that the color the text for any tabs associated with this session should be changed;.
void stateChanged(int state)
Emitted when the activity state of this session changes.
void changeBackgroundColorRequest(const QColor &)
Requests that the background color of views on this session should be changed.
@ NameRole
The name of the session.
Definition Session.h:262
void bellRequest(const QString &message)
Emitted when a bell event occurs in the session.
A widget which displays output from a terminal emulation and sends input keypresses and mouse activit...
KCOREADDONS_EXPORT QString quoteArg(const QString &arg)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString & append(QChar ch)
bool isNull() const const
QString & prepend(QChar ch)
QString & setNum(double n, char format, int precision)
std::string toStdString() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri May 2 2025 11:55:37 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.