File indexing completed on 2025-03-16 08:11:30
0001 /* 0002 This file is part of Konsole QML plugin, 0003 which is a terminal emulator from KDE. 0004 0005 SPDX-FileCopyrightText: 2013 Dmitry Zagnoyko <hiroshidi@gmail.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0017 02110-1301 USA. 0018 */ 0019 0020 // Own 0021 #include "TerminalSession.h" 0022 0023 // Qt 0024 #include <QTextCodec> 0025 0026 // Konsole 0027 #include "HistorySearch.h" 0028 #include "KeyboardTranslator.h" 0029 0030 TerminalSession::TerminalSession(QObject *parent) 0031 : QObject(parent) 0032 , m_session(createSession(QString())) 0033 { 0034 connect(m_session.get(), &Konsole::Session::started, this, &TerminalSession::started); 0035 connect(m_session.get(), &Konsole::Session::finished, this, &TerminalSession::sessionFinished); 0036 connect(m_session.get(), &Konsole::Session::titleChanged, this, &TerminalSession::titleChanged); 0037 } 0038 0039 TerminalSession::~TerminalSession() 0040 { 0041 if (m_session) { 0042 m_session->close(); 0043 m_session->disconnect(); 0044 } 0045 } 0046 0047 void TerminalSession::setTitle(QString name) 0048 { 0049 m_session->setTitle(Session::NameRole, name); 0050 } 0051 0052 std::unique_ptr<Session> TerminalSession::createSession(QString name) 0053 { 0054 auto session = std::make_unique<Session>(); 0055 0056 session->setTitle(Session::NameRole, name); 0057 0058 /* Thats a freaking bad idea!!!! 0059 * /bin/bash is not there on every system 0060 * better set it to the current $SHELL 0061 * Maybe you can also make a list available and then let the widget-owner decide what to use. 0062 * By setting it to $SHELL right away we actually make the first filecheck obsolete. 0063 * But as iam not sure if you want to do anything else ill just let both checks in and set this to $SHELL anyway. 0064 */ 0065 0066 // cool-old-term: There is another check in the code. Not sure if useful. 0067 0068 QString envshell = qEnvironmentVariable("SHELL"); 0069 QString shellProg = !envshell.isNull() ? envshell : QStringLiteral("/bin/bash"); 0070 session->setProgram(shellProg); 0071 0072 setenv("TERM", "xterm", 1); 0073 0074 // session->setProgram(); 0075 0076 QStringList args; 0077 session->setArguments(args); 0078 session->setAutoClose(true); 0079 0080 session->setCodec(QTextCodec::codecForName("UTF-8")); 0081 0082 session->setFlowControlEnabled(true); 0083 session->setHistoryType(HistoryTypeBuffer(1000)); 0084 0085 session->setDarkBackground(true); 0086 0087 session->setKeyBindings(QString()); 0088 0089 return session; 0090 } 0091 0092 ///////////////////////////////////////////////////////////////////////////////////// 0093 ///////////////////////////////////////////////////////////////////////////////////// 0094 0095 int TerminalSession::getRandomSeed() 0096 { 0097 return m_session->sessionId() * 31; 0098 } 0099 0100 void TerminalSession::addView(TerminalDisplay *display) 0101 { 0102 m_session->setView(display); 0103 } 0104 0105 void TerminalSession::removeView(TerminalDisplay *display) 0106 { 0107 m_session->removeView(display); 0108 } 0109 0110 void TerminalSession::sessionFinished() 0111 { 0112 Q_EMIT finished(); 0113 } 0114 0115 void TerminalSession::selectionChanged(bool textSelected) 0116 { 0117 Q_UNUSED(textSelected) 0118 } 0119 0120 void TerminalSession::startShellProgram() 0121 { 0122 if (m_session->isRunning()) { 0123 return; 0124 } 0125 0126 m_session->run(); 0127 } 0128 0129 bool TerminalSession::sendSignal(int signal) 0130 { 0131 if (!m_session->isRunning()) { 0132 return false; 0133 } 0134 0135 return m_session->sendSignal(signal); 0136 } 0137 0138 int TerminalSession::getShellPID() 0139 { 0140 return m_session->processId(); 0141 } 0142 0143 void TerminalSession::changeDir(const QString &dir) 0144 { 0145 /* 0146 this is a very hackish way of trying to determine if the shell is in 0147 the foreground before attempting to change the directory. It may not 0148 be portable to anything other than Linux. 0149 */ 0150 QString strCmd; 0151 strCmd.setNum(getShellPID()); 0152 strCmd.prepend(u"ps -j "); 0153 strCmd.append(u" | tail -1 | awk '{ print $5 }' | grep -q \\+"); 0154 int retval = system(strCmd.toStdString().c_str()); 0155 0156 if (!retval) { 0157 QString cmd = QStringLiteral(u"cd ") + dir + QStringLiteral("\n"); 0158 sendText(cmd); 0159 } 0160 } 0161 0162 void TerminalSession::setEnvironment(const QStringList &environment) 0163 { 0164 m_session->setEnvironment(environment); 0165 } 0166 0167 QString TerminalSession::shellProgram() const 0168 { 0169 return m_session->program(); 0170 } 0171 0172 void TerminalSession::setShellProgram(const QString &progname) 0173 { 0174 m_session->setProgram(progname); 0175 Q_EMIT shellProgramChanged(); 0176 } 0177 0178 void TerminalSession::setInitialWorkingDirectory(const QString &dir) 0179 { 0180 if (_initialWorkingDirectory != dir) { 0181 _initialWorkingDirectory = dir; 0182 m_session->setInitialWorkingDirectory(dir); 0183 Q_EMIT initialWorkingDirectoryChanged(); 0184 } 0185 } 0186 0187 QString TerminalSession::getInitialWorkingDirectory() 0188 { 0189 return _initialWorkingDirectory; 0190 } 0191 0192 QStringList TerminalSession::args() const 0193 { 0194 return m_session->arguments(); 0195 } 0196 0197 void TerminalSession::setArgs(const QStringList &args) 0198 { 0199 m_session->setArguments(args); 0200 Q_EMIT argsChanged(); 0201 } 0202 0203 void TerminalSession::setTextCodec(QTextCodec *codec) 0204 { 0205 m_session->setCodec(codec); 0206 } 0207 0208 void TerminalSession::setHistorySize(int lines) 0209 { 0210 if (historySize() != lines) { 0211 if (lines < 0) 0212 m_session->setHistoryType(HistoryTypeFile()); 0213 else 0214 m_session->setHistoryType(HistoryTypeBuffer(lines)); 0215 Q_EMIT historySizeChanged(); 0216 } 0217 } 0218 0219 int TerminalSession::historySize() const 0220 { 0221 if (m_session->historyType().isUnlimited()) { 0222 return -1; 0223 } else { 0224 return m_session->historyType().maximumLineCount(); 0225 } 0226 } 0227 0228 QString TerminalSession::getHistory() const 0229 { 0230 QString history; 0231 QTextStream historyStream(&history); 0232 PlainTextDecoder historyDecoder; 0233 0234 historyDecoder.begin(&historyStream); 0235 m_session->emulation()->writeToStream(&historyDecoder); 0236 historyDecoder.end(); 0237 0238 return history; 0239 } 0240 0241 void TerminalSession::sendText(QString text) 0242 { 0243 m_session->sendText(text); 0244 } 0245 0246 void TerminalSession::sendKey(int, int, int) const 0247 { 0248 // TODO implement or remove this function. 0249 // Qt::KeyboardModifier kbm = Qt::KeyboardModifier(mod); 0250 0251 // QKeyEvent qkey(QEvent::KeyPress, key, kbm); 0252 0253 // while (rep > 0){ 0254 // m_session->sendKey(&qkey); 0255 // --rep; 0256 // } 0257 } 0258 0259 void TerminalSession::clearScreen() 0260 { 0261 m_session->emulation()->clearEntireScreen(); 0262 } 0263 0264 void TerminalSession::search(const QString ®exp, int startLine, int startColumn, bool forwards) 0265 { 0266 HistorySearch *history = new HistorySearch(QPointer<Emulation>(m_session->emulation()), QRegExp(regexp), forwards, startColumn, startLine, this); 0267 connect(history, &HistorySearch::matchFound, this, &TerminalSession::matchFound); 0268 connect(history, &HistorySearch::noMatchFound, this, &TerminalSession::noMatchFound); 0269 history->search(); 0270 } 0271 0272 void TerminalSession::setFlowControlEnabled(bool enabled) 0273 { 0274 m_session->setFlowControlEnabled(enabled); 0275 } 0276 0277 bool TerminalSession::flowControlEnabled() 0278 { 0279 return m_session->flowControlEnabled(); 0280 } 0281 0282 void TerminalSession::setKeyBindings(const QString &kb) 0283 { 0284 m_session->setKeyBindings(kb); 0285 Q_EMIT changedKeyBindings(kb); 0286 } 0287 0288 QString TerminalSession::getKeyBindings() 0289 { 0290 return m_session->keyBindings(); 0291 } 0292 0293 QStringList TerminalSession::availableKeyBindings() 0294 { 0295 return KeyboardTranslatorManager::instance()->allTranslators(); 0296 } 0297 0298 QString TerminalSession::keyBindings() 0299 { 0300 return m_session->keyBindings(); 0301 } 0302 0303 QString TerminalSession::getTitle() 0304 { 0305 return m_session->userTitle(); 0306 } 0307 0308 bool TerminalSession::hasActiveProcess() const 0309 { 0310 return m_session->processId() != m_session->foregroundProcessId(); 0311 } 0312 0313 QString TerminalSession::foregroundProcessName() 0314 { 0315 return m_session->foregroundProcessName(); 0316 } 0317 0318 QString TerminalSession::currentDir() 0319 { 0320 return m_session->currentDir(); 0321 }