c++qtqtscript

Stop the evaluation of a Qt Script


I've recently add a script function on a simulator. I've add a "Launch Script" button on the GUI, who is able to launch the evaluation of a script.

My main creates a QThread (scriptThread) who evaluate my script. My QMainWindows send signals to my main, who call scriptThread slots.

I want to be able to start, and stop the script when I want from the GUI. I've first called terminate() slots of the scriptThread. But it destroy my Qthread, and I'm not able to relunch the script after canceling it (because I've created my scriptThread on the start of my main).

This is a part of my main :

MyGUI w();
ScriptThread scriptThread();

QObject::connect(&w, SIGNAL(setScriptPath(QString)),
               &scriptThread, SLOT(setPath(QString)));
QObject::connect(&w, SIGNAL(launchScriptSignal()),
               &scriptThread, SLOT(start()));
QObject::connect(&w, SIGNAL(stopScript()),
               &scriptThread, SLOT(terminate()));

QObject::connect(&scriptThread, SIGNAL(finished()),
               &w, SLOT(scriptFinished()));

This is my run() function in my scriptThread :

QScriptEngine m_scriptEngine;
QScriptValue m_result;

QScriptValue m_scriptValue = m_scriptEngine.newQObject(m_MyQOBJECT);

m_scriptEngine.globalObject().setProperty("sc", m_scriptValue); 

QFile file(m_path);
bool result = file.open(QIODevice::ReadOnly); 

if(!result)
{
  printf("Script path not found.\n");
  emit finished();
  return;
} 

m_result = m_scriptEngine.evaluate(file.readAll());

if(m_result.toString() != "undefined")
  std::cout << m_result.toString().toStdString() << std::endl;

file.close();

if(m_scriptEngine.hasUncaughtException()) 
{
  int lineNo = m_scriptEngine.uncaughtExceptionLineNumber();
  printf("lineNo : %i\n", lineNo);
}

printf("ScriptThread finished\n");
emit finished();

The GUI interesting functions :

void myGUI::launchScript(QString path)
{
  if(!m_isScriptRunning)
  {    
    path = ui->editScriptPath->text();
    disableAll();

    ui->Script->setText("stop script");
    m_isScriptRunning = true ;

    emit setScriptPath(path);  
    emit launchScriptSignal();  
  }
  else
  {
    emit stopScript();
    scriptFinished();
  }
}

void MyGUI::scriptFinished()
{
  enableAll();

  ui->Script->setText("launch script");
  m_isScriptRunning = false ;
}

So my question is, how can I cancel the evaluation of my script, without destructing the thread ? I've tried the quit() slot, but it's only for event loop. Is there an existing slot or a litle trick to do that ?

Thanks.


Solution

  • I've succefuly tried Kamil solution.

    In Qt 4.4 and superior, there is a QScriptEngine::abortEvaluation() function who is working great.

    I've just switch my engine who was local to my function into my class.

    Working part code of ScriptThread.cpp :

    void ScriptThread::cancelScriptEvaluation()
    {
      m_scriptEngine.abortEvaluation();
      emit finished();
    }
    

    With of course in the ScriptThread.h :

    private:
      QScriptEngine m_scriptEngine;
    

    And in my main :

    QObject::connect(&w, SIGNAL(stopScript()),
                   &scriptThread, SLOT(cancelScriptEvaluation()));