File indexing completed on 2024-04-28 05:48:33
0001 // 0002 // configview.cpp 0003 // 0004 // Description: View for configuring the set of targets to be used with the debugger 0005 // 0006 // 0007 // SPDX-FileCopyrightText: 2010 Kåre Särs <kare.sars@iki.fi> 0008 // 0009 // SPDX-License-Identifier: LGPL-2.0-only 0010 0011 #include "ioview.h" 0012 0013 #include <QDir> 0014 #include <QFontDatabase> 0015 #include <QLineEdit> 0016 #include <QScrollBar> 0017 #include <QSocketNotifier> 0018 #include <QString> 0019 #include <QTextEdit> 0020 #include <QVBoxLayout> 0021 0022 #include <KColorScheme> 0023 #include <KRandom> 0024 0025 #include <fcntl.h> 0026 #include <sys/stat.h> 0027 #include <sys/types.h> 0028 #include <unistd.h> 0029 0030 IOView::IOView(QWidget *parent) 0031 : QWidget(parent) 0032 { 0033 m_output = new QTextEdit(); 0034 m_output->setReadOnly(true); 0035 m_output->setUndoRedoEnabled(false); 0036 m_output->setAcceptRichText(false); 0037 // fixed wide font, like konsole 0038 m_output->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); 0039 // alternate color scheme, like konsole 0040 KColorScheme schemeView(QPalette::Active, KColorScheme::Complementary); 0041 m_output->setTextBackgroundColor(schemeView.background().color()); 0042 m_output->setTextColor(schemeView.foreground().color()); 0043 QPalette p = m_output->palette(); 0044 p.setColor(QPalette::Base, schemeView.background().color()); 0045 m_output->setPalette(p); 0046 0047 m_input = new QLineEdit(); 0048 m_output->setFocusProxy(m_input); // take the focus from the output 0049 0050 QVBoxLayout *layout = new QVBoxLayout(this); 0051 layout->addWidget(m_output, 10); 0052 layout->addWidget(m_input, 0); 0053 layout->setContentsMargins(0, 0, 0, 0); 0054 layout->setSpacing(0); 0055 0056 connect(m_input, &QLineEdit::returnPressed, this, &IOView::returnPressed); 0057 createFifos(); 0058 } 0059 0060 IOView::~IOView() 0061 { 0062 m_stdin.close(); 0063 0064 m_stdout.close(); 0065 m_stdout.setFileName(m_stdoutFifo); 0066 ::close(m_stdoutFD); 0067 0068 m_stderr.close(); 0069 m_stderr.setFileName(m_stderrFifo); 0070 ::close(m_stderrFD); 0071 0072 m_stdin.remove(); 0073 m_stdout.remove(); 0074 m_stderr.remove(); 0075 } 0076 0077 void IOView::createFifos() 0078 { 0079 m_stdinFifo = createFifo(QStringLiteral("stdInFifo")); 0080 m_stdoutFifo = createFifo(QStringLiteral("stdOutFifo")); 0081 m_stderrFifo = createFifo(QStringLiteral("stdErrFifo")); 0082 0083 m_stdin.setFileName(m_stdinFifo); 0084 if (!m_stdin.open(QIODevice::ReadWrite)) { 0085 return; 0086 } 0087 0088 m_stdoutD.setFileName(m_stdoutFifo); 0089 m_stdoutD.open(QIODevice::ReadWrite); 0090 0091 m_stdout.setFileName(m_stdoutFifo); 0092 m_stdoutFD = ::open(m_stdoutFifo.toLocal8Bit().data(), O_RDWR | O_NONBLOCK); 0093 if (m_stdoutFD == -1) { 0094 return; 0095 } 0096 if (!m_stdout.open(m_stdoutFD, QIODevice::ReadWrite)) { 0097 return; 0098 } 0099 0100 m_stdoutNotifier = new QSocketNotifier(m_stdoutFD, QSocketNotifier::Read, this); 0101 connect(m_stdoutNotifier, &QSocketNotifier::activated, this, &IOView::readOutput); 0102 m_stdoutNotifier->setEnabled(true); 0103 0104 m_stderrD.setFileName(m_stderrFifo); 0105 m_stderrD.open(QIODevice::ReadWrite); 0106 0107 m_stderr.setFileName(m_stderrFifo); 0108 m_stderrFD = ::open(m_stderrFifo.toLocal8Bit().data(), O_RDONLY | O_NONBLOCK); 0109 if (m_stderrFD == -1) { 0110 return; 0111 } 0112 if (!m_stderr.open(m_stderrFD, QIODevice::ReadOnly)) { 0113 return; 0114 } 0115 0116 m_stderrNotifier = new QSocketNotifier(m_stderrFD, QSocketNotifier::Read, this); 0117 connect(m_stderrNotifier, &QSocketNotifier::activated, this, &IOView::readErrors); 0118 m_stderrNotifier->setEnabled(true); 0119 0120 return; 0121 } 0122 0123 void IOView::returnPressed() 0124 { 0125 m_stdin.write(m_input->text().toLocal8Bit()); 0126 m_stdin.write("\n"); 0127 m_stdin.flush(); 0128 m_input->clear(); 0129 } 0130 0131 void IOView::readOutput() 0132 { 0133 m_stdoutNotifier->setEnabled(false); 0134 qint64 res; 0135 char chData[256]; 0136 QByteArray data; 0137 0138 do { 0139 res = m_stdout.read(chData, 255); 0140 if (res <= 0) { 0141 m_stdoutD.flush(); 0142 } else { 0143 data.append(chData, res); 0144 } 0145 0146 } while (res == 255); 0147 0148 if (data.size() > 0) { 0149 Q_EMIT stdOutText(QString::fromLocal8Bit(data)); 0150 } 0151 m_stdoutNotifier->setEnabled(true); 0152 } 0153 0154 void IOView::readErrors() 0155 { 0156 m_stderrNotifier->setEnabled(false); 0157 qint64 res; 0158 char chData[256]; 0159 QByteArray data; 0160 0161 do { 0162 res = m_stderr.read(chData, 255); 0163 if (res <= 0) { 0164 m_stderrD.flush(); 0165 } else { 0166 data.append(chData, res); 0167 } 0168 } while (res == 255); 0169 0170 if (data.size() > 0) { 0171 Q_EMIT stdErrText(QString::fromLocal8Bit(data)); 0172 } 0173 m_stderrNotifier->setEnabled(true); 0174 } 0175 0176 void IOView::addStdOutText(const QString &text) 0177 { 0178 QScrollBar *scrollb = m_output->verticalScrollBar(); 0179 if (!scrollb) { 0180 return; 0181 } 0182 bool atEnd = (scrollb->value() == scrollb->maximum()); 0183 0184 QTextCursor cursor = m_output->textCursor(); 0185 if (!cursor.atEnd()) { 0186 cursor.movePosition(QTextCursor::End); 0187 } 0188 cursor.insertText(text); 0189 0190 if (atEnd) { 0191 scrollb->setValue(scrollb->maximum()); 0192 } 0193 } 0194 0195 void IOView::addStdErrText(const QString &text) 0196 { 0197 m_output->setFontItalic(true); 0198 addStdOutText(text); 0199 m_output->setFontItalic(false); 0200 } 0201 0202 QString IOView::createFifo(const QString &prefix) 0203 { 0204 QString fifo = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + QDir::separator() + prefix + KRandom::randomString(3); 0205 int result = mkfifo(QFile::encodeName(fifo).data(), 0666); 0206 if (result != 0) { 0207 return QString(); 0208 } 0209 return fifo; 0210 } 0211 0212 const QString IOView::stdinFifo() 0213 { 0214 return m_stdinFifo; 0215 } 0216 const QString IOView::stdoutFifo() 0217 { 0218 return m_stdoutFifo; 0219 } 0220 const QString IOView::stderrFifo() 0221 { 0222 return m_stderrFifo; 0223 } 0224 0225 void IOView::enableInput(bool enable) 0226 { 0227 m_input->setEnabled(enable); 0228 } 0229 0230 void IOView::clearOutput() 0231 { 0232 m_output->clear(); 0233 } 0234 0235 #include "moc_ioview.cpp"