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

Last change on this file since 903 was 903, checked in by Dmitry A. Kuminov, 9 years ago

tests/process: Renamed the process part to process-async.

File size: 11.0 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 == "rso" || cmd == "rse")
151        {
152            /* redirect stdout & stderr */
153
154            if (mProcess->state() != QProcess::NotRunning)
155            {
156                mEditor->append(tr("> ERROR: Process is already running"));
157                return;
158            }
159
160            bool output = cmd == "rso";
161            output ? mProcess->setStandardOutputFile(text)
162                   : mProcess->setStandardErrorFile(text);
163
164            if (!text.isEmpty())
165                mEditor->append(tr("> Redirected standard %1 stream to: '%2'")
166                                .arg(output ? "output" : "error").arg(text));
167            else
168                mEditor->append(tr("> Canceled redirection of standard %1")
169                                .arg(output ? "output" : "error"));
170        }
171        else if (cmd == "term")
172        {
173            /* terminate */
174
175            if (mProcess->state() == QProcess::NotRunning)
176            {
177                mEditor->append(tr("> ERROR: No process is running"));
178                return;
179            }
180
181            mEditor->append(tr("> Sent terminate process request"));
182            mProcess->terminate();
183        }
184        else if (cmd == "kill")
185        {
186            /* kill */
187
188            if (mProcess->state() == QProcess::NotRunning)
189            {
190                mEditor->append(tr("> ERROR: No process is running"));
191                return;
192            }
193
194            mEditor->append(tr("> Sent kill process request"));
195            mProcess->kill();
196        }
197        else if (cmd == "rtp")
198        {
199            /* redirect stdout to stdin of the other process */
200
201            if (mProcess->state() != QProcess::NotRunning)
202            {
203                mEditor->append(tr("> ERROR: Process is already running"));
204                return;
205            }
206
207            if (!mRedirectedToOtherProcess)
208            {
209                mRedirectedToOtherProcess = true;
210                mProcess->setStandardOutputProcess(mOtherProcess);
211                mEditor->append(tr("> Redirected standard output to standard "
212                                   "input of another process"));
213            }
214            else
215            {
216                mRedirectedToOtherProcess = false;
217                mProcess->setStandardErrorFile(QString::null);
218                mEditor->append(tr("> Canceled redirection of standard output"));
219            }
220        }
221        else if (cmd == "d" || cmd == "dcd")
222        {
223            QString workDir;
224            if (cmd.endsWith("cd"))
225            {
226                QDir dir = QDir(QFileInfo(words[0]).path());
227                workDir = dir.absolutePath();
228            }
229            else
230            {
231                workDir = QDir::currentPath();
232            }
233            mEditor->append(tr("> Working directory: '%1'").arg(workDir));
234
235            mEditor->append(tr("> Detaching: '%1'").arg(text));
236            QStringList args = words;
237            QString prg = args.takeFirst();
238            qint64 pid;
239            if (QProcess::startDetached(prg, args, workDir, &pid))
240                mEditor->append(tr("> Detached successfully (pid '%1')").arg(pid));
241            else
242                mEditor->append(tr("> Detach failed"));
243        }
244        else
245        {
246            mEditor->append(tr("> ERROR: '%1' command is unknown").arg(cmd));
247            return;
248        }
249    }
250
251    void process_stateChanged(QProcess::ProcessState aState)
252    {
253        QString state;
254        switch (aState)
255        {
256            case QProcess::NotRunning: state = tr("NotRunning"); break;
257            case QProcess::Starting: state = tr("Starting"); break;
258            case QProcess::Running: state = tr("Running"); break;
259        }
260        mStatusLabel->setText(tr("%1 (PID: %2)").arg(state).arg((ulong)mProcess->pid()));
261    }
262
263    void process_error(QProcess::ProcessError aError)
264    {
265        QString error;
266        switch (aError)
267        {
268            case QProcess::FailedToStart: error = tr("FailedToStart"); break;
269            case QProcess::Crashed: error = tr("Crashed"); break;
270            case QProcess::Timedout: error = tr("Timedout"); break;
271            case QProcess::WriteError: error = tr("WriteError"); break;
272            case QProcess::ReadError: error = tr("ReadError"); break;
273            case QProcess::UnknownError: error = tr("UnknownError"); break;
274        }
275        mEditor->append(tr("> ERROR: %1: %2").arg(error).arg(mProcess->errorString()));
276    }
277
278    void process_started()
279    {
280        mEditor->append(tr("> Started: PID is %1").arg((ulong)mProcess->pid()));
281    }
282
283    void process_finished(int aExitCode, QProcess::ExitStatus aExitStatus)
284    {
285        QString exitStatus;
286        switch (aExitStatus)
287        {
288            case QProcess::NormalExit: exitStatus = tr("NormalExit"); break;
289            case QProcess::CrashExit: exitStatus = tr("CrashExit"); break;
290        }
291        mEditor->append(tr("> Finished: %1 with code %2").arg(exitStatus).arg(aExitCode));
292    }
293
294    void process_readyReadStandardOutput()
295    {
296        QByteArray data = mProcess->readAllStandardOutput();
297        mEditor->append(QString::fromLocal8Bit(data));
298    }
299
300    void process_readyReadStandardError()
301    {
302        QByteArray data = mProcess->readAllStandardError();
303        mEditor->append(QString::fromLocal8Bit(data));
304    }
305
306private:
307
308    QProcess *mProcess;
309    QProcess *mOtherProcess;
310    bool mRedirectedToOtherProcess;
311
312    QTextEdit *mEditor;
313    QLineEdit *mLineEdit;
314    QLabel *mStatusLabel;
315};
316
317////////////////////////////////////////////////////////////////////////////////
318
319class MyDialog : public QWidget
320{
321    Q_OBJECT
322
323public:
324
325    MyDialog() : QWidget(0, Qt::Window)
326    {
327        // children
328
329        QTabWidget *tabs = new QTabWidget();
330
331        mWidget1 = new MyWidget(tabs);
332        mWidget2 = new MyWidget(tabs);
333
334        mWidget1->setOtherProcess(mWidget2->process());
335        mWidget2->setOtherProcess(mWidget1->process());
336
337        tabs->addTab(mWidget1, QLatin1String("Process 1"));
338        tabs->addTab(mWidget2, QLatin1String("Process 2"));
339
340        // connections
341
342        // layout
343
344        QHBoxLayout *mainLayout = new QHBoxLayout();
345        mainLayout->addWidget(tabs);
346
347        setLayout(mainLayout);
348
349        // initial values
350
351        tabs->currentWidget()->setFocus();
352
353        // other
354    }
355
356private:
357
358    MyWidget *mWidget1;
359    MyWidget *mWidget2;
360};
361
362////////////////////////////////////////////////////////////////////////////////
363
364int main(int argc, char *argv[])
365{
366#if 1
367
368    QApplication app(argc, argv);
369
370    MyDialog dialog;
371    dialog.resize(800, 400);
372    dialog.show();
373
374        return app.exec();
375
376#else
377
378    qDebug() << "Starting...";
379
380    QProcess proc;
381#if defined(Q_OS_OS2)
382    //proc.start("cmd.exe /c dir >bbb");
383    //proc.start("cmd /c start /n newview.exe");
384    proc.start("test");
385#elif defined(Q_OS_WIN)
386    proc.start("notepad.exe");
387#endif
388
389    qDebug() << "Waiting for finished...";
390    proc.waitForFinished();
391
392    qDebug() << "DONE";
393
394#endif
395}
396
397#include "process-async.moc"
398
Note: See TracBrowser for help on using the repository browser.