Good point about the blocking of the gui with this execRun code!
I had no problems with it because I seperated the interpreter from the
gui code by wrapping the entire interpreter part in a qprocess (work I
did on mpl).
For the kturtle case it will probably be better to use QProcess.
Anyway the problem is I got swamped with work again. Started working
in construction 2 months ago for my dad's company resulting in a
friend who called me the belgian good will hunting. I laughed
(thinking I'm not that smart ;) ) but when I was filling a container
with concrete rubble and trash this morning I did get the striking
ressemblance ;). Anyway, like I said, too much work on my plate to go
and find out how to checkout/compile kturtle on my totally aged linux
box now (its not been updated since I started working on my macbook
which I love;) ). But maybe vmware can be of help for me to get a
quick recent edubuntu on my macbook ;).
Anyway here is some QProcess code which can be easily plugged into
kturtle and will indeed not block the gui:
Let's say we want to run something like 'ls -lh /home/wschrep' without
blocking and get its output:
First add the private local QProcess* exeProc; to the executer.h class
definition.
Then inside the execRun method implementation put something like
this :
void executer::execRun( ){
exeProc=new QProcess(this);
exeProc->addArgument( "ls" ); //the executable name you want to
run (can be any executable, you can give the total path like /usr/bin/
ls to be safe)
exeProc->addArgument( "-lh" ); //any arguments to the executable,
the rule here is use an addArgument whenever you type a space in
bash ;)
exeProc->addArgument("/home/wschrep");
//now to get the output from the executable you need some signal/
slots:
connect( exeProc, SIGNAL(readyReadStdout()), this, SLOT
(readFromStdout()) ); //get errors and output
connect( exeProc, SIGNAL(readyReadStderr()), this, SLOT
(readFromStderr()) );
// connect( inputTxt, SIGNAL(returnPressed()), this, SLOT(input
()) ); //this is only if you need to input code to the external
executable , as in the external exe is using cin it it's code
connect( exeProc, SIGNAL(processExited()), this, SLOT(exeDone
()) ); //signals end of execution of the external program.
That's it really :). Ok to be fair you will wonder what is inside the
readFrom... slots? Well here ya go (but you won't need these if you
just want to run an exe without getting input/output back):
void Executer::readFromStdout(){
while( exeProc->canReadLineStdout() ){ //read entire lines
output->append( exeProc->readLineStdout() ); //output is a
QTextEdit widget in my gui, have no time to check what it is in
kturtle, anyway it will probably be something similar
}
QString strOut = exeProc->readStdout(); //readStdout returns
QByteArray -> copy to qstring.
output->append( strOut ); //show the partial lines, again replace
output here with the appropriate kturtle widget name
}
readFromStderr is exactly the same but use canReadLineStderr() and
exeProc->readLineStderr() .
Now one more important method the exeDone:
void Executer::exeDone(){
statusBar->message( "Execution done!", 3000 );
delete exeProc;
exeProc=0; // I do this so that my destructor is more clean.
}
And add this inside the destructor:
Executer::~Executer(){
//... other destructor code
if( exeProc!= 0 ){
exeProc->kill();
delete exeProc;
}
}
This way you kill the process that was forked before the executer is
destroyed. For instance someone starts kturtle, runs an external
command then decides to close the application before the external
command finishes (for example something like 'ping
google.com' which
would keep on running forever in background on most distributions and
the user will be unaware it is running unless he checks his processes
with ps or something). In short the exeProc->kill() is important ;).
As for hard coding the 'hardware turtle c code' into kturtle I think
it would not be a clean way and only necessary if there where
performance or real time issues (which I did not have with the
mindstorms project). Just get the commands like
move forward, turn etc. put them in seperate executables. And call
them from kturtle using a qprocess.
Giving you a few oneliners inside the executer class if you wrap the
code shown in runExe into something like
runExecutable( const QString& command ), then replace "ls" with
command in the above code.
Then sprinkle the running of the external commands into the approprate
exeForward, exeTurn etc and you can even wrap in a define so you can
switch on/off the hardware turtle code verry easily. Should be no more
than a few hours work which unfortunately I don't even have that to
spare now or at least not in the next few weeks because of the
construction work I need to finish and some other RoR work I need to
get done for
legendskate.com :S.
Kind regards and hope it helped,
Walter