PDA

View Full Version : QtScript: Q_PROPERTY WRITE function of Prototype not called when object wrapped



TimShnaider
3rd July 2012, 04:22
Before I log this as a bug, hopefully someone can spot a problem with what I'm doing.

Do I have the wrong understanding of how QScriptClass and a custom prototype should be used?

I'm using the QtScript CustomClass example as the code template, where they wrap QByteArray. My code is identical in structure except
wrapping different objects.
http://qt-project.org/doc/qt-4.8/script-customclass.html

It seems that the Q_PROPERTY READ function is called when querying a property, but the WRITE function is never called (in the Prototype class)

In my derived QScriptClass::queryProperty() I am always returning 0 so this means both reads and writes should be delegated to my custom Prototype (QScriptable derived) object.

This works as expected for property reads, I verify the Prototype object is called i.e:

a = new Control();
print(a.prop1);

But when I do:

a.prop1 = 'ssss';
print(a.prop1);

the setter function in the Prototype object is not called, but instead it looks like a new property is added to 'a' chain and overrides the prototype, and now print(a.prop1) doesn't go through the Prototype object at all.

print(a.prop2) is still routed through the Prototype object.

If I return HandlesWriteAccess in queryProperty(), then setProperty() is called as expected, but I don't want that (or would prefer not too).

Changing the argument types on setXX makes no difference.



class ControlAlertPrototype : public QObject, public QScriptable
{
Q_OBJECT
Q_PROPERTY(QString title READ title WRITE setTitle)
Q_PROPERTY(QScriptValue text READ text WRITE setText)
Q_PROPERTY(QString button1 READ button1 WRITE setButton1)
Q_PROPERTY(QString button2 READ button2 WRITE setButton2)
public:
ControlAlertPrototype(QObject *parent = 0);
~ControlAlertPrototype();


private:
BFL::ControlAlert *thisAlert() const;

QString title() const { return thisAlert()->GetTitle().c_str(); }
void setTitle(const QString &v) { thisAlert()->SetTitle(v.toStdString().c_str()); }
QString text() const { return thisAlert()->GetText().c_str(); }
void setText(const QScriptValue &v) { thisAlert(); /*->SetText(v.toStdString().c_str()); */ }
QString button1() const { return thisAlert()->GetButton1().c_str(); }
void setButton1(const QString &v) { thisAlert()->SetButton1(v.toStdString().c_str()); }
QString button2() const { return thisAlert()->GetButton2().c_str(); }
void setButton2(const QString &v) { thisAlert()->SetButton2(v.toStdString().c_str()); }

public slots:
QString toString() {return "ControlAlert";}
};

high_flyer
3rd July 2012, 12:03
Did you register QScriptValue ?


Properties and Custom Types

Custom types used by properties need to be registered using the Q_DECLARE_METATYPE() macro so that their values can be stored in QVariant objects. This makes them suitable for use with both static properties declared using the Q_PROPERTY() macro in class definitions and dynamic properties created at run-time.


also:
http://qt-project.org/doc/qt-4.8/qscriptengine.html#qScriptRegisterMetaType

TimShnaider
3rd July 2012, 12:29
I have registered all the necessary types and the Prototype gets used for READ of properties, just not WRITE. So don't see how that it relevant.

I'm pretty sure it is a bug with using QScriptClass and a Prototype with properties, traced the call through to QScriptObjectDelegate::put() in QtScript source and
see that the function has all the Prototypes in the chain report back no getter/setters, so then it just creates a property directly.

Will report it is a bug when I get time.

In the meantime I've changed the architecture and got something that works exactly the way I want.

high_flyer
3rd July 2012, 12:48
In the meantime I've changed the architecture and got something that works exactly the way I want.
Would be nice if you share it here for other who get a similar problem.