MythTV  master
mythterminal.cpp
Go to the documentation of this file.
1 /*
2  * Class MythTerminal
3  *
4  * Copyright (C) Daniel Kristjansson 2008
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <cinttypes>
22 #include <utility>
23 
24 // MythTV headers
25 #include "mythlogging.h"
26 #include "mythterminal.h"
27 #include "mythuibutton.h"
28 #include "mythuibuttonlist.h"
29 #include "mythuitextedit.h"
30 
31 MythTerminal::MythTerminal(MythScreenStack *parent, QString _program,
32  QStringList _arguments) :
33  MythScreenType(parent, "terminal"),
34  m_process(new QProcess()), m_program(std::move(_program)),
35  m_arguments(std::move(_arguments))
36 {
37  m_process->setProcessChannelMode(QProcess::MergedChannels);
38  connect(m_process, SIGNAL(readyRead()),
39  this, SLOT(ProcessHasText()));
40 
41  connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
42  this, SLOT( ProcessFinished(int, QProcess::ExitStatus)));
43 }
44 
46 {
47  if (m_process)
48  {
49  QMutexLocker locker(&m_lock);
50  if (m_process)
51  {
52  if (m_running)
53  Kill();
54  m_process->disconnect();
55  m_process->deleteLater();
56  m_process = nullptr;
57  }
58  }
59 }
60 
61 void MythTerminal::AddText(const QString &_str)
62 {
63  QMutexLocker locker(&m_lock);
64  QString str = _str;
65  while (str.length())
66  {
67  int nlf = str.indexOf("\r\n");
68  nlf = (nlf < 0) ? str.indexOf("\r") : nlf;
69  nlf = (nlf < 0) ? str.indexOf("\n") : nlf;
70 
71  QString curStr = (nlf >= 0) ? str.left(nlf) : str;
72  if (curStr.length())
73  {
74  if (!m_currentLine)
76  else
78  }
79 
80  if (nlf >= 0)
81  {
84  str = str.mid(nlf + 1);
85  }
86  else
87  {
88  str = "";
89  }
90  }
91 }
92 
94 {
95  QMutexLocker locker(&m_lock);
97  m_running = true;
98 }
99 
101 {
102  QMutexLocker locker(&m_lock);
103  m_process->kill();
104  m_running = false;
105 }
106 
107 bool MythTerminal::IsDone(void) const
108 {
109  QMutexLocker locker(&m_lock);
110  return QProcess::NotRunning == m_process->state();
111 }
112 
114 {
115  QMutexLocker locker(&m_lock);
116  int64_t len = m_process->bytesAvailable();
117 
118  if (len <= 0)
119  return;
120 
121  QByteArray buf = m_process->read(len);
122  AddText(QString(buf));
123 }
124 
126 {
127  Start();
128 }
129 
131  int exitCode, QProcess::ExitStatus exitStatus)
132 {
133  QMutexLocker locker(&m_lock);
134  if (exitStatus == QProcess::CrashExit) {
135  AddText(tr("*** Crashed with status: %1 ***").arg(exitCode));
136  } else {
137  AddText(tr("*** Exited with status: %1 ***").arg(exitCode));
138  }
139  m_running = false;
140  m_enterButton->SetEnabled(false);
141  m_textEdit->SetEnabled(false);
142 }
143 
145 {
146  if (!LoadWindowFromXML("standardsetting-ui.xml", "terminal", this))
147  return false;
148 
149  bool error = false;
150  UIUtilE::Assign(this, m_output, "output", &error);
151  UIUtilE::Assign(this, m_textEdit, "textedit", &error);
152  UIUtilE::Assign(this, m_enterButton, "enter", &error);
153 
154  if (error)
155  {
156  LOG(VB_GENERAL, LOG_ERR, "Theme elements missing.");
157  return false;
158  }
159 
160  BuildFocusList();
161 
162  MythUIButton *close = nullptr;
163  UIUtilW::Assign(this, close, "close");
164  if (close)
165  connect(close, SIGNAL(Clicked()), this, SLOT(Close()));
166 
168  this,
169  [this]()
170  {
171  QMutexLocker locker(&m_lock);
172  if (m_running) // NOLINT(clang-analyzer-core.NullDereference)
173  {
174  QString text = m_textEdit->GetText() + "\r\n";
175  AddText(text);
176 
177  m_process->write(text.toLocal8Bit().constData());
178  }
179  });
180 
181  return true;
182 }
MythUIButton::Clicked
void Clicked()
error
static void error(const char *str,...)
Definition: vbi.cpp:42
MythTerminal::TeardownAll
void TeardownAll(void)
Definition: mythterminal.cpp:45
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:402
MythTerminal::m_lock
QMutex m_lock
Definition: mythterminal.h:47
MythScreenStack
Definition: mythscreenstack.h:15
arg
arg(title).arg(filename).arg(doDelete))
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:44
MythUITextEdit::GetText
QString GetText(void) const
Definition: mythuitextedit.h:47
MythTerminal::Init
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
Definition: mythterminal.cpp:125
MythTerminal::IsDone
bool IsDone(void) const
Definition: mythterminal.cpp:107
MythTerminal::Kill
void Kill(void)
Definition: mythterminal.cpp:100
MythTerminal::ProcessHasText
void ProcessHasText(void)
Definition: mythterminal.cpp:113
mythuibuttonlist.h
MythTerminal::ProcessFinished
void ProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
Definition: mythterminal.cpp:130
close
#define close
Definition: compat.h:16
MythUIButtonListItem::SetText
void SetText(const QString &text, const QString &name="", const QString &state="")
Definition: mythuibuttonlist.cpp:3272
MythUIButtonListItem
Definition: mythuibuttonlist.h:27
MythTerminal::m_arguments
QStringList m_arguments
Definition: mythterminal.h:51
MythTerminal::m_currentLine
MythUIButtonListItem * m_currentLine
Definition: mythterminal.h:52
mythlogging.h
MythTerminal::Start
void Start(void)
Definition: mythterminal.cpp:93
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:222
MythUIButton
A single button widget.
Definition: mythuibutton.h:21
MythTerminal::m_running
bool m_running
Definition: mythterminal.h:48
MythTerminal::AddText
void AddText(const QString &_str)
Definition: mythterminal.cpp:61
MythUIType::SetEnabled
void SetEnabled(bool enable)
Definition: mythuitype.cpp:1102
MythTerminal::m_program
QString m_program
Definition: mythterminal.h:50
MythTerminal::m_output
MythUIButtonList * m_output
Definition: mythterminal.h:53
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
MythUIButtonListItem::GetText
QString GetText(const QString &name="") const
Definition: mythuibuttonlist.cpp:3313
MythTerminal::m_process
QProcess * m_process
Definition: mythterminal.h:49
MythTerminal::Create
bool Create(void) override
Definition: mythterminal.cpp:144
MythTerminal::m_enterButton
MythUIButton * m_enterButton
Definition: mythterminal.h:55
mythuitextedit.h
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:692
MythTerminal::m_textEdit
MythUITextEdit * m_textEdit
Definition: mythterminal.h:54
MythUIButtonList::SetItemCurrent
void SetItemCurrent(MythUIButtonListItem *item)
Definition: mythuibuttonlist.cpp:1557
mythterminal.h
mythuibutton.h
MythTerminal::MythTerminal
MythTerminal(MythScreenStack *parent, QString program, QStringList arguments)
Definition: mythterminal.cpp:31