How to properly connect to QObject's destroyed
signal from Qt Script?
When I connect to it like to your average signal, it does not work. I did test that I removed the object and that other QObjects did get the signal, but the script function I connected to it is not invoked.
Below is the sample I'm using for testing. The most important part is the line:
_engine.evaluate("obj.destroyed.connect(function() { debug(\"obj destroyed\") })");
I'd expect it to invoke that function when obj
is destroyed. The code below ensures that object is deleted when even loop already started and it also tests that the object did send destroyed
signal to another QObject. What I want to fix is for the script to invoke the script function with debug("obj destroyed")
after destroyed
signal is emitted.
ScriptTester.h:
#ifndef SCRIPTTESTER_H
#define SCRIPTTESTER_H
#include <QtScript>
#include <QtCore>
class ScriptTester: public QObject {
Q_OBJECT
public:
explicit ScriptTester(QObject *parent = 0);
private slots:
void signalTest();
void boo();
private:
QScriptEngine _engine;
};
#endif // SCRIPTTESTER_H
ScriptTester.cpp:
#include "ScriptTester.h"
static QScriptValue scriptDebug(QScriptContext *context, QScriptEngine *engine) {
Q_UNUSED(engine);
if (context->argumentCount() >= 1) {
QString msg = context->argument(0).toString();
for (int i = 1; i < context->argumentCount(); ++i) {
msg = msg.arg(context->argument(i).toString());
}
qDebug() << msg;
}
return QScriptValue();
}
ScriptTester::ScriptTester(QObject *parent) :
QObject(parent)
{
QTimer::singleShot(0, Qt::CoarseTimer, this, SLOT(signalTest()));
_engine.globalObject().setProperty("debug", _engine.newFunction(scriptDebug, 1));
}
void ScriptTester::signalTest() {
QObject *obj = new QObject(this);
_engine.globalObject().setProperty("obj", _engine.newQObject(obj));
_engine.evaluate("obj.destroyed.connect(function() { debug(\"obj destroyed\") })");
if (_engine.hasUncaughtException()) {
qDebug() << "Exception:" << _engine.uncaughtException().toString();
}
connect(obj, SIGNAL(destroyed()), this, SLOT(boo()));
QTimer *timer = new QTimer;
_engine.globalObject().setProperty("timer", _engine.newQObject(timer));
_engine.evaluate("timer.timeout.connect(function() { debug(\"timer timeout\"); obj.deleteLater(); })");
if (_engine.hasUncaughtException()) {
qDebug() << "Exception:" << _engine.uncaughtException().toString();
}
timer->setSingleShot(true);
timer->start(100);
}
void ScriptTester::boo() {
qDebug() << "was destroyed!";
}
Note that I don't want a hack like passing destroyed
first to C++ code and then manually or by a signal informing script of that. I'm searching for an implementation that's done fully in the script.