Hi,

I needed repeatidly to start some external program from the app that I'm writing. The idea was to repeaiidly play wav files with aplay, at first I created QProcess in the gui thread and tested, but there were some delays in the playing due to other data processing in the app.

I subclassed QThread and I've combined it with QProcess so that I can execute the external app.
I'm using QT 3. I've read that the event loop runs in the gui thread and that threads are not well supported in Qt3.

Here is the code:

The header:
Qt Code:
  1. // execthread.h
  2. // Description: Thread class for executing external applications repeatedly.
  3. // The external app can be executed repeatedly until the thread is stopped,
  4. // or a definite number of times. The executed command can be given, or it
  5. // can be read from some conf file which path will be given at thread creation.
  6.  
  7. #ifndef EXECTHREAD_H
  8. #define EXECTHREAD_H
  9.  
  10. #include <qthread.h>
  11. #include <qprocess.h>
  12. #include <qstringlist.h>
  13. #include <qstring.h>
  14. #include <qapplication.h>
  15.  
  16.  
  17. class ExecThread : public QThread
  18. {
  19. Q_OBJECT
  20. public:
  21. ExecThread(const QString Conf, int RunTimes, bool config);
  22. virtual ~ExecThread();
  23.  
  24. void setCommand(const QString Cmd);
  25. void setExecTimes(const int &ExecTimesParam);
  26. int execsTillStop();
  27. void run();
  28. void stop();
  29.  
  30.  
  31. signals:
  32. void ExecFinished(); // when in RepeatMode emits a signal after it finishes the last // execution
  33.  
  34.  
  35. private:
  36. QProcess *ExecProcess;
  37. QString CommandStr; // Command to be executed
  38. int ExecTimes; // number of executions to be done till it stops
  39. bool RepeatMode; // flag if the thread is in repeated execution
  40. volatile bool stopped; // flag if thread was stopped
  41.  
  42. QString GetCommandStr(const QString Path);
  43. void SetArgs(QString Cmd);
  44.  
  45. private slots:
  46. void processExitedSlot();
  47. };
  48.  
  49. #endif
To copy to clipboard, switch view to plain text mode 

And the implementation:
Qt Code:
  1. // execthread.cpp
  2.  
  3.  
  4. #include "execthread.h"
  5.  
  6. // Function: ExecThread::ExecThread
  7. // Description: The constructor
  8. // Parameters:
  9. // QString Conf - the command to be executed, or the conf file to be read where the command is
  10. // int RunTimes - number of times the command should be executed. Default is 0, meaning
  11. // unlimited times ( till stop() method is called)
  12. // bool config - if true the first parameter (Conf) is the path to the config file where the
  13. // command is situated. By default it's false which means Conf holds the
  14. // command to be executed
  15.  
  16. ExecThread::ExecThread(const QString Conf, int RunTimes, bool config)
  17. {
  18.  
  19. stopped = true;
  20.  
  21. // setting the command to be executed
  22. if (!config)
  23. CommandStr = Conf;
  24. else
  25. CommandStr = GetCommandStr(Conf);
  26.  
  27.  
  28. // should the command be exectuted limited number of times
  29. if (RunTimes > 0)
  30. {
  31. ExecTimes = RunTimes;
  32. RepeatMode = true;
  33. }
  34. else
  35. {
  36. ExecTimes = 0;
  37. RepeatMode = false;
  38. }
  39.  
  40. CommandStr = CommandStr.stripWhiteSpace();
  41. CommandStr = CommandStr.simplifyWhiteSpace();
  42.  
  43. // create the process which will execute the command
  44. ExecProcess = new QProcess();
  45.  
  46. // QObject::connect( ExecProcess, SIGNAL(processExited()),
  47. // this, SLOT(processExitedSlot()) );
  48.  
  49. connect( ExecProcess, SIGNAL(processExited()),
  50. this, SLOT(processExitedSlot()) );
  51.  
  52.  
  53. SetArgs(CommandStr);
  54. }
  55.  
  56. // Function: ExecThread::~ExecThread
  57. // Description: The destructor
  58.  
  59. ExecThread::~ExecThread()
  60. {
  61. delete ExecProcess;
  62. }
  63.  
  64. // Funciton: GetCommandStr
  65. // Description: Parser for the file with the command string. It accepts # style comments
  66. // Parameters:
  67. // QString Path - the path to the file
  68.  
  69. QString ExecThread::GetCommandStr (const QString Path)
  70. {
  71. QFile file;
  72. QTextStream stream( &file );
  73. QString CmdStr = "";
  74. QString line;
  75. int pos;
  76.  
  77. file.setName(Path);
  78. if (!file.exists()) return "";
  79. if (file.open(IO_ReadOnly))
  80. while (( !stream.atEnd() ) or (CmdStr == ""))
  81. {
  82. line = stream.readLine();
  83.  
  84. if ((pos = line.find('#',0))>=0) // if there is a # in the line
  85. {
  86. if (pos > 0) // if the line is like " aplay /usr/test.wav # play test.wav"
  87. CmdStr = line.left(pos);
  88. }
  89. else
  90. {
  91. CmdStr = line;
  92. }
  93. }
  94. return CmdStr;
  95. }
  96.  
  97. // Funciton: setCommand
  98. // Description: Sets the command to be executed
  99. // Parameters:
  100. // QString Cmd - the command
  101.  
  102. void ExecThread::setCommand(const QString Cmd)
  103. {
  104.  
  105.  
  106. CommandStr = Cmd;
  107. CommandStr = CommandStr.stripWhiteSpace();
  108. CommandStr = CommandStr.simplifyWhiteSpace();
  109. SetArgs(CommandStr);
  110. return;
  111. }
  112.  
  113. // Funciton: setExecTimes
  114. // Description: Sets the number of times command should be exectuted.
  115. // Calling this function autmatically sets RepeatMode to true
  116. // Parameters:
  117. // int &ExecTimesParam - number of times command to be executed
  118.  
  119. void ExecThread::setExecTimes(const int &ExecTimesParam)
  120. {
  121. if (ExecTimesParam > 0)
  122. {
  123. ExecTimes = ExecTimesParam;
  124. RepeatMode = true;
  125. }
  126. else
  127. {
  128. ExecTimes = 0;
  129. RepeatMode = false;
  130. }
  131. }
  132.  
  133.  
  134. // Funciton: run
  135. // Description: Executes the command until stopped is true. In RepeatMode
  136. // decreases the number of execs to be done be executed
  137.  
  138. void ExecThread::run()
  139. {
  140. stopped = false;
  141. ExecProcess->start();
  142. if (RepeatMode)
  143. {
  144. ExecTimes--;
  145. if (ExecTimes == 0)
  146. {
  147. stopped = true;
  148. emit ExecFinished();
  149. }
  150. }
  151. }
  152.  
  153. // Function: stop
  154. // Description: Sets stopped to true. Stops the execution, but the command that is currently
  155. // running is not terminated
  156.  
  157. void ExecThread::stop()
  158. {
  159. stopped = true;
  160. }
  161.  
  162. // Function: SetArgs
  163. // Description: Sets the command arguments to ExecProcess
  164. // Parameters:
  165. // QString Cmd - the command
  166.  
  167. void ExecThread::SetArgs(QString Cmd)
  168. {
  169. int pos;
  170.  
  171. ExecProcess->clearArguments();
  172. while ((pos = Cmd.find(" ",0))> 0)
  173. {
  174. ExecProcess->addArgument(Cmd.left(pos));
  175. Cmd = Cmd.mid(pos + 1, 1000);
  176. }
  177. ExecProcess->addArgument(Cmd);
  178. }
  179.  
  180. // Function: execsTillStop
  181. // Description: Returns the number of exectutions till it stops ExecProcess
  182. int ExecThread::execsTillStop()
  183. {
  184. return ExecTimes;
  185. }
  186.  
  187.  
  188.  
  189. void ExecThread::processExitedSlot()
  190. {
  191. if (!stopped)
  192. {
  193. ExecProcess->start();
  194. if (RepeatMode)
  195. {
  196. ExecTimes--;
  197. if (ExecTimes == 0)
  198. {
  199. stopped = true;
  200. emit ExecFinished();
  201. }
  202. }
  203. }
  204. }
To copy to clipboard, switch view to plain text mode 

I've hit the wall twice

1. the connect statment gives me an error when compiling

execthread.cpp:56: error: no matching function for call to Object::connect(QProcess*&, const char [17], ExecThread* const, const char [21])
/usr/include/qt3/qobject.h:116: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*)
/usr/include/qt3/qobject.h:226: note: bool QObject::connect(const QObject*, const char*, const char*) const


2. If I comment the connect statement, the code compiles well but I get error in linking stage. I don't understand why do I get this error, ExitFinished() is defined as signal. confused

execthread.cppunhappy .text+0x7c): undefined reference to `ExecThread::ExecFinished()'execthread.o: In function `ExecThread:rocessExitedSlot()':
execthread.cppunhappy .text+0xee): undefined reference to `ExecThread::ExecFinished()'collect2: ld returned 1 exit status


TIA, chombium