Results 1 to 7 of 7

Thread: Exposing a Qt container property to QtScript, READ and WRITE

  1. #1

    Default Exposing a Qt container property to QtScript, READ and WRITE

    I am attempting to expose a Q_PROPERTY that references a Qt container to QtScript, that allows for both reading from the container and writing to the container. According to all the Qt documentation, this should be possible. I have spent a week trying everything I can think of, and searching this forum and the whole of the Google index to no avail. There are several similar threads on this forum, but none answer the question, really.

    Everything I have tried allows the script to see the values in the container, but not alter the values in that container. Even the QtScript Debugger sees the values, but cannot modify them interactively.

    Minimal, compilable code follows:

    myclass.h (inlined for ease of posting)
    Qt Code:
    1. class MyClass : public QObject
    2. {
    3. Q_OBJECT
    4. Q_PROPERTY(QStringList strings READ getStrings WRITE setStrings);
    5.  
    6. public:
    7. MyClass() { strings << "abc" << "def" << "ghi" << "jkl"; };
    8. ~MyClass() {};
    9.  
    10. QStringList getStrings() const { return strings; };
    11.  
    12. public slots:
    13. void setStrings(const QStringList& list) { strings = list; };
    14.  
    15. private:
    16. QStringList strings;
    17. };
    To copy to clipboard, switch view to plain text mode 

    main.cpp
    Qt Code:
    1. #include "myclass.h"
    2.  
    3. Q_DECLARE_METATYPE(QStringList);
    4.  
    5. int main(int argc, char *argv[])
    6. {
    7. QCoreApplication a(argc, argv);
    8.  
    9. QScriptEngine *scriptEngine = new QScriptEngine;
    10. qScriptRegisterSequenceMetaType<QStringList>(scriptEngine);
    11.  
    12. MyClass *myclass = new MyClass();
    13. QScriptValue value = scriptEngine->newQObject(myclass);
    14. scriptEngine->globalObject().setProperty("AAA", value);
    15.  
    16. qDebug("Before: " + myclass->getStrings().join("~").toAscii());
    17.  
    18. scriptEngine->evaluate("AAA.strings[1] = 'xxx';");
    19.  
    20. qDebug("After : " + myclass->getStrings().join("~").toAscii());
    21. }
    To copy to clipboard, switch view to plain text mode 

    Output:
    Qt Code:
    1. Before: abc~def~ghi~jkl
    2. After : abc~def~ghi~jkl
    To copy to clipboard, switch view to plain text mode 

    There is something obvious I am missing, but for the life of me, I can't figure it out. This is not limited to the QStringList container, I cannot WRITE to QVector, QList, QMap, or any other Qt containers.

    Another hint: A breakpoint that is put on the "setStrings" method is never triggered, indicating to me that something is wrong with my syntax, in that the script engine has not been instructed properly to bind with my WRITE method.

    I have also tried using the "qScriptRegisterMetaType" approach, and defining my own methods for converting the QStringList to and from QScriptValue, but that has not been successful either.

    Representative threads (there are many) where this same topic has gone unanswered:
    http://www.qtcentre.org/threads/6540...signer-plugins
    http://www.qtcentre.org/threads/2522...Y-of-type-QMap

    Any pointers are appreciated.

  2. #2

    Default Re: Exposing a Qt container property to QtScript, READ and WRITE

    Well, as 50 people have looked at this since I posted it (at this time of this writing), and there have been no replies, can I assume that this is either:
    • A bug
    • Not something that Qt is expected to do?


    If anyone could confirm either of those, that would be quite helpful in and of itself.

    Here's another thread where wysota (who has > 22,500 posts on this forum), suggests that WRITEing to a containerized Q_PROPERTY is perfectly valid. He even provides code that he claims will work (but doesn't). wysota has commented in the other threads I linked to above as well, so even a veteran poster thinks this should work.

    http://www.qtcentre.org/threads/18849-Plotting-points

    OTOH, is there something obvious I am missing?

  3. #3

    Default Re: Exposing a Qt container property to QtScript, READ and WRITE

    Yea! 102 views.

    Here are some more examples of code that should work:
    http://code.google.com/p/optra/sourc...terface.h?r=19
    http://code.google.com/p/optra/sourc...rface.cpp?r=19

    There are a number of examples one can find where projects tried to do something like "Q_PROPERTY(QList<QVariant>..." as in the above links, and then in future revisions, removed that code, because it simply didn't work.

    And here's a little bit of KDE that uses a Q_PROPERTY with a container:
    http://api.kde.org/4.x-api/kdelibs-a...8h_source.html
    http://api.kde.org/4.x-api/kdelibs-a...pp_source.html

    I assume this code works correctly, but I don't know why. I frankly don't have the ability to run KDE in a debugger and step through it. I have created some sample code modeled from the code in the above links, including the private class design pattern, but have still not had any luck.

    Also, I have tried setting the property from C++ code, like so:

    Qt Code:
    1. QStringList newStrings;
    2. newStrings << "www" << "xxx" << "yyy" << "zzz";
    3. myclass->setProperty("AAA", newStrings);
    To copy to clipboard, switch view to plain text mode 

    This doesn't work either, so maybe this problem is not specific to QtScript, but is an overall limitation with Qt's property system? From my research, it sure looks like containers should work with Q_PROPERTY, but maybe I am wrong. Anyone have any idea?

  4. #4

    Default Re: Exposing a Qt container property to QtScript, READ and WRITE

    With the release of 4.7.3 I thought I would update this thread as it still doesn't work.

    wysota: are you around? All of your examples in this forum indicate that this should work. Any thoughts?

    I'll update my compilable code example too, as I have determined that this is indeed a direct problem with QtScript; this works just fine when using property system methods.

    main.cpp
    Qt Code:
    1. #include <QtCore\QCoreApplication>
    2. #include <QtScript>
    3. #include "myclass.h"
    4.  
    5. Q_DECLARE_METATYPE(QStringList);
    6.  
    7. int main(int argc, char *argv[])
    8. {
    9. QCoreApplication a(argc, argv);
    10.  
    11. qRegisterMetaType<QStringList>();
    12. MyClass *myclass = new MyClass();
    13.  
    14. qDebug("Before: " + myclass->getStrings().join("~").toAscii());
    15.  
    16. // Test 1 - set property via setProperty (WORKS AS EXPECTED)
    17. QStringList newStrings;
    18. newStrings << "www" << "xxx" << "yyy" << "zzz";
    19. myclass->setProperty("strings", newStrings);
    20. qDebug("Test1: " + myclass->getStrings().join("~").toAscii());
    21.  
    22. // Test 2 - set property via QtScript (FAILS SILENTLY)
    23. QScriptEngine scriptEngine;
    24. QScriptValue scriptQObject = scriptEngine.newQObject(myclass);
    25. scriptEngine.globalObject().setProperty("myclass", scriptQObject);
    26. scriptEngine.evaluate("myclass.strings[0] = 'aaa';");
    27. qDebug("Test2: " + myclass->getStrings().join("~").toAscii());
    28. }
    To copy to clipboard, switch view to plain text mode 

    myclass.h
    Qt Code:
    1. #ifndef MYCLASS_H
    2. #define MYCLASS_H
    3.  
    4. #include <QObject>
    5. #include <QStringList>
    6. #include <QVariant>
    7.  
    8. class MyClass : public QObject
    9. {
    10. Q_OBJECT
    11. Q_PROPERTY(QStringList strings READ getStrings WRITE setStrings);
    12.  
    13. public:
    14. MyClass() { strings << "abc" << "def" << "ghi" << "jkl"; };
    15. ~MyClass() {};
    16.  
    17. QStringList getStrings() const { return strings; };
    18. void setStrings(const QStringList& list) { strings = list; };
    19.  
    20. QStringList strings;
    21. };
    22.  
    23. #endif // MYCLASS_H
    To copy to clipboard, switch view to plain text mode 

    Actual output:
    Qt Code:
    1. Before: abc~def~ghi~jkl
    2. Test1: www~xxx~yyy~zzz
    3. Test2: www~xxx~yyy~zzz
    To copy to clipboard, switch view to plain text mode 

    Expected output:
    Qt Code:
    1. Before: abc~def~ghi~jkl
    2. Test1: www~xxx~yyy~zzz
    3. Test2: aaa~xxx~yyy~zzz
    To copy to clipboard, switch view to plain text mode 

    As before, the setStrings method never gets called when the script is executed. Is the signature of that method wrong? All the examples that I can find in this forum and elsewhere have a signature like that.

  5. #5

    Default Re: Exposing a Qt container property to QtScript, READ and WRITE

    So I'm either an idiot who doesn't know a compiler from their arsehole, or this does not operate as advertised?

    Anyone have an opinion? Seriously? Three weeks, 200 views and not a *single* person has an opinion?

  6. #6

    Default Re: Exposing a Qt container property to QtScript, READ and WRITE


  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Exposing a Qt container property to QtScript, READ and WRITE

    Sorry, I haven't noticed your thread earlier. So you say this doesn't work?

    Qt Code:
    1. #include <QtGui>
    2.  
    3. class Object : public QObject {
    4. Q_OBJECT
    5. Q_PROPERTY(QStringList list READ list WRITE setList)
    6. public:
    7. const QStringList &list() const { return m_sl; }
    8. public slots:
    9. void setList(const QStringList &sl) { m_sl = sl; }
    10. private:
    11. };
    12.  
    13. #include "main.moc"
    14.  
    15. int main(int argc, char **argv){
    16. // QApplication app(argc, argv);
    17. Object o;
    18. QStringList sl = QStringList() << "a" << "b" << "c";
    19. o.setList(sl);
    20. qDebug() << o.list();
    21. return 0;
    22. }
    To copy to clipboard, switch view to plain text mode 
    It works perfectly fine for me...

    Edit: By the way, this also works, if added near the end of main():

    Qt Code:
    1. QScriptEngine engine;
    2. QScriptValue v = engine.newQObject(&o);
    3. engine.globalObject().setProperty("o", v);
    4. qDebug() << "READ:" << engine.evaluate("o.list").toString();
    5. engine.evaluate("var arr = new Array; arr[0] = 'd'; o.list = arr;").toString();
    6. qDebug() << "WRITE:" << engine.evaluate("o.list").toString();
    To copy to clipboard, switch view to plain text mode 

    or even this:
    Qt Code:
    1. qDebug() << "READ:" << engine.evaluate("o.list").toString();
    2. engine.evaluate("o.list = ['q', 'w', 'e', 'r', 't', 'y'];").toString();
    3. qDebug() << "WRITE:" << engine.evaluate("o.list").toString();
    To copy to clipboard, switch view to plain text mode 
    Last edited by wysota; 12th May 2011 at 07:53.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Replies: 2
    Last Post: 2nd November 2010, 05:15
  2. read and write on qtcpsocket
    By dognzhe in forum Qt Programming
    Replies: 1
    Last Post: 2nd June 2009, 09:42
  3. file read & write help....
    By aj2903 in forum Qt Programming
    Replies: 1
    Last Post: 17th November 2008, 11:58
  4. Read/Write from QTextStream
    By tonde in forum Qt Programming
    Replies: 7
    Last Post: 31st July 2008, 16:51
  5. XML -read-write
    By hgedek in forum Qt Programming
    Replies: 2
    Last Post: 3rd September 2007, 18:10

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.