source: tests/process/process-async/process-async.cpp@ 919

Last change on this file since 919 was 916, checked in by Dmitry A. Kuminov, 14 years ago

test: process-async.cmd: Added mch and sch commands.

File size: 11.7 KB
Line 
1#include <QtCore>
2
3//#include <QtGui>
4#include <QApplication>
5#include <QWidget>
6#include <QTextEdit>
7#include <QLineEdit>
8#include <QLabel>
9#include <QTabWidget>
10#include <QLayout>
11
12#include <QDebug>
13
14#define STR(expr) #expr
15#define DBG(expr) STR(expr) << "=" << (expr)
16
17class MyWidget : public QWidget
18{
19 Q_OBJECT
20
21public:
22
23 MyWidget(QWidget *aParent)
24 : QWidget(aParent), mOtherProcess(0), mRedirectedToOtherProcess(false)
25 {
26 // children
27
28 mProcess = new QProcess(this);
29
30 mEditor = new QTextEdit();
31 mEditor->setReadOnly(true);
32
33 mLineEdit = new QLineEdit();
34 mStatusLabel = new QLabel();
35
36 // connections
37
38 connect(mProcess, SIGNAL(stateChanged(QProcess::ProcessState)),
39 this, SLOT(process_stateChanged(QProcess::ProcessState)));
40 connect(mProcess, SIGNAL(error(QProcess::ProcessError)),
41 this, SLOT(process_error(QProcess::ProcessError)));
42 connect(mProcess, SIGNAL(started()),
43 this, SLOT(process_started()));
44 connect(mProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
45 this, SLOT(process_finished(int, QProcess::ExitStatus)));
46 connect(mProcess, SIGNAL(readyReadStandardOutput()),
47 this, SLOT(process_readyReadStandardOutput()));
48 connect(mProcess, SIGNAL(readyReadStandardError()),
49 this, SLOT(process_readyReadStandardError()));
50
51 connect(mLineEdit, SIGNAL(returnPressed()),
52 this, SLOT(lineEdit_returnPressed()));
53
54 // layout
55
56 QVBoxLayout *l1 = new QVBoxLayout();
57 l1->addWidget(mEditor);
58 l1->addWidget(mLineEdit);
59 l1->addWidget(mStatusLabel);
60
61 QHBoxLayout *mainLayout = new QHBoxLayout();
62 mainLayout->addLayout(l1);
63
64 setLayout(mainLayout);
65
66 mLineEdit->setFocus();
67
68 // initial values
69
70 mLineEdit->setText("D:\\Coding\\qt\\smplayer_test\\mplayer.ex");
71
72 process_stateChanged(mProcess->state());
73
74 // other
75 }
76
77 QProcess *process() const { return mProcess; }
78 void setOtherProcess(QProcess *aOtherProcess) { mOtherProcess = aOtherProcess; }
79
80private slots:
81
82 void lineEdit_returnPressed()
83 {
84 QString text = mLineEdit->text();
85 if (text.isEmpty())
86 return;
87
88 mLineEdit->clear();
89
90 text = text.trimmed();
91
92 QString cmd;
93 if (text.startsWith('>'))
94 {
95 int ws = text.indexOf(' ');
96 if (ws < 0)
97 ws = text.length();
98 cmd = text.mid(1, ws - 1);
99
100 text = text.mid(ws);
101 text = text.trimmed();
102 }
103
104 // @todo support for quoted strings
105 QStringList words = text.split(' ');
106
107 if (cmd.isNull() && mProcess->state() == QProcess::NotRunning)
108 cmd = "s";
109
110 if (cmd.isNull())
111 {
112 Q_ASSERT(mProcess->state() != QProcess::NotRunning);
113
114 /* send the line to standard input */
115 QByteArray data = (text + "\n").toLocal8Bit();
116 mProcess->write(data);
117 }
118 else if (cmd == "s" || cmd == "ss" || cmd == "scd" || cmd == "sscd")
119 {
120 /* start process (..cd changes to its directory) */
121
122 if (words.count() < 1)
123 {
124 mEditor->append(tr("> ERROR: '%1' requires one argument").arg(cmd));
125 return;
126 }
127 if (mProcess->state() != QProcess::NotRunning)
128 {
129 mEditor->append(tr("> ERROR: Process is already running"));
130 return;
131 }
132
133 QString workDir;
134 if (cmd.endsWith("cd"))
135 {
136 QDir dir = QDir(QFileInfo(words[0]).path());
137 workDir = dir.absolutePath();
138 mProcess->setWorkingDirectory(workDir);
139 }
140 else
141 {
142 workDir = QDir::currentPath();
143 mProcess->setWorkingDirectory(QString());
144 }
145 mEditor->append(tr("> Working directory: '%1'").arg(workDir));
146
147 mEditor->append(tr("> Starting: '%1'").arg(text));
148 mProcess->start(text);
149 }
150 else if (cmd == "mch" || cmd == "sch")
151 {
152 /* merge/separate stdout & stderr */
153
154 if (mProcess->state() != QProcess::NotRunning)
155 {
156 mEditor->append(tr("> ERROR: Process is already running"));
157 return;
158 }
159
160 mProcess->setProcessChannelMode(cmd == "mch" ? QProcess::MergedChannels :
161 QProcess::SeparateChannels);
162 if (cmd == "mch")
163 mEditor->append(tr("> Merged standard error stream to standard output"));
164 else
165 mEditor->append(tr("> Separated standard error stream from standard output"));
166 }
167 else if (cmd == "rso" || cmd == "rse")
168 {
169 /* redirect stdout & stderr */
170
171 if (mProcess->state() != QProcess::NotRunning)
172 {
173 mEditor->append(tr("> ERROR: Process is already running"));
174 return;
175 }
176
177 bool output = cmd == "rso";
178 output ? mProcess->setStandardOutputFile(text)
179 : mProcess->setStandardErrorFile(text);
180
181 if (!text.isEmpty())
182 mEditor->append(tr("> Redirected standard %1 stream to: '%2'")
183 .arg(output ? "output" : "error").arg(text));
184 else
185 mEditor->append(tr("> Canceled redirection of standard %1")
186 .arg(output ? "output" : "error"));
187 }
188 else if (cmd == "term")
189 {
190 /* terminate */
191
192 if (mProcess->state() == QProcess::NotRunning)
193 {
194 mEditor->append(tr("> ERROR: No process is running"));
195 return;
196 }
197
198 mEditor->append(tr("> Sent terminate process request"));
199 mProcess->terminate();
200 }
201 else if (cmd == "kill")
202 {
203 /* kill */
204
205 if (mProcess->state() == QProcess::NotRunning)
206 {
207 mEditor->append(tr("> ERROR: No process is running"));
208 return;
209 }
210
211 mEditor->append(tr("> Sent kill process request"));
212 mProcess->kill();
213 }
214 else if (cmd == "rtp")
215 {
216 /* redirect stdout to stdin of the other process */
217
218 if (mProcess->state() != QProcess::NotRunning)
219 {
220 mEditor->append(tr("> ERROR: Process is already running"));
221 return;
222 }
223
224 if (!mRedirectedToOtherProcess)
225 {
226 mRedirectedToOtherProcess = true;
227 mProcess->setStandardOutputProcess(mOtherProcess);
228 mEditor->append(tr("> Redirected standard output to standard "
229 "input of another process"));
230 }
231 else
232 {
233 mRedirectedToOtherProcess = false;
234 mProcess->setStandardErrorFile(QString::null);
235 mEditor->append(tr("> Canceled redirection of standard output"));
236 }
237 }
238 else if (cmd == "d" || cmd == "dcd")
239 {
240 QString workDir;
241 if (cmd.endsWith("cd"))
242 {
243 QDir dir = QDir(QFileInfo(words[0]).path());
244 workDir = dir.absolutePath();
245 }
246 else
247 {
248 workDir = QDir::currentPath();
249 }
250 mEditor->append(tr("> Working directory: '%1'").arg(workDir));
251
252 mEditor->append(tr("> Detaching: '%1'").arg(text));
253 QStringList args = words;
254 QString prg = args.takeFirst();
255 qint64 pid;
256 if (QProcess::startDetached(prg, args, workDir, &pid))
257 mEditor->append(tr("> Detached successfully (pid '%1')").arg(pid));
258 else
259 mEditor->append(tr("> Detach failed"));
260 }
261 else
262 {
263 mEditor->append(tr("> ERROR: '%1' command is unknown").arg(cmd));
264 return;
265 }
266 }
267
268 void process_stateChanged(QProcess::ProcessState aState)
269 {
270 QString state;
271 switch (aState)
272 {
273 case QProcess::NotRunning: state = tr("NotRunning"); break;
274 case QProcess::Starting: state = tr("Starting"); break;
275 case QProcess::Running: state = tr("Running"); break;
276 }
277 mStatusLabel->setText(tr("%1 (PID: %2)").arg(state).arg((ulong)mProcess->pid()));
278 }
279
280 void process_error(QProcess::ProcessError aError)
281 {
282 QString error;
283 switch (aError)
284 {
285 case QProcess::FailedToStart: error = tr("FailedToStart"); break;
286 case QProcess::Crashed: error = tr("Crashed"); break;
287 case QProcess::Timedout: error = tr("Timedout"); break;
288 case QProcess::WriteError: error = tr("WriteError"); break;
289 case QProcess::ReadError: error = tr("ReadError"); break;
290 case QProcess::UnknownError: error = tr("UnknownError"); break;
291 }
292 mEditor->append(tr("> ERROR: %1: %2").arg(error).arg(mProcess->errorString()));
293 }
294
295 void process_started()
296 {
297 mEditor->append(tr("> Started: PID is %1").arg((ulong)mProcess->pid()));
298 }
299
300 void process_finished(int aExitCode, QProcess::ExitStatus aExitStatus)
301 {
302 QString exitStatus;
303 switch (aExitStatus)
304 {
305 case QProcess::NormalExit: exitStatus = tr("NormalExit"); break;
306 case QProcess::CrashExit: exitStatus = tr("CrashExit"); break;
307 }
308 mEditor->append(tr("> Finished: %1 with code %2").arg(exitStatus).arg(aExitCode));
309 }
310
311 void process_readyReadStandardOutput()
312 {
313 QByteArray data = mProcess->readAllStandardOutput();
314 mEditor->append(QString::fromLocal8Bit(data));
315 }
316
317 void process_readyReadStandardError()
318 {
319 QByteArray data = mProcess->readAllStandardError();
320 mEditor->append(QString::fromLocal8Bit(data));
321 }
322
323private:
324
325 QProcess *mProcess;
326 QProcess *mOtherProcess;
327 bool mRedirectedToOtherProcess;
328
329 QTextEdit *mEditor;
330 QLineEdit *mLineEdit;
331 QLabel *mStatusLabel;
332};
333
334////////////////////////////////////////////////////////////////////////////////
335
336class MyDialog : public QWidget
337{
338 Q_OBJECT
339
340public:
341
342 MyDialog() : QWidget(0, Qt::Window)
343 {
344 // children
345
346 QTabWidget *tabs = new QTabWidget();
347
348 mWidget1 = new MyWidget(tabs);
349 mWidget2 = new MyWidget(tabs);
350
351 mWidget1->setOtherProcess(mWidget2->process());
352 mWidget2->setOtherProcess(mWidget1->process());
353
354 tabs->addTab(mWidget1, QLatin1String("Process 1"));
355 tabs->addTab(mWidget2, QLatin1String("Process 2"));
356
357 // connections
358
359 // layout
360
361 QHBoxLayout *mainLayout = new QHBoxLayout();
362 mainLayout->addWidget(tabs);
363
364 setLayout(mainLayout);
365
366 // initial values
367
368 tabs->currentWidget()->setFocus();
369
370 // other
371 }
372
373private:
374
375 MyWidget *mWidget1;
376 MyWidget *mWidget2;
377};
378
379////////////////////////////////////////////////////////////////////////////////
380
381int main(int argc, char *argv[])
382{
383#if 1
384
385 QApplication app(argc, argv);
386
387 MyDialog dialog;
388 dialog.resize(800, 400);
389 dialog.show();
390
391 return app.exec();
392
393#else
394
395 qDebug() << "Starting...";
396
397 QProcess proc;
398#if defined(Q_OS_OS2)
399 //proc.start("cmd.exe /c dir >bbb");
400 //proc.start("cmd /c start /n newview.exe");
401 proc.start("test");
402#elif defined(Q_OS_WIN)
403 proc.start("notepad.exe");
404#endif
405
406 qDebug() << "Waiting for finished...";
407 proc.waitForFinished();
408
409 qDebug() << "DONE";
410
411#endif
412}
413
414#include "process-async.moc"
415
Note: See TracBrowser for help on using the repository browser.