Advertisement
opatut

Q_PROPERTY + Forward declaration + Pointers

Aug 5th, 2011
374
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.77 KB | None | 0 0
  1. // Zip archive can be found here: http://ompldr.org/vOXJybw/qproperty.zip
  2. //////////////// A.cpp ////////////////
  3.  
  4. #include "A.hpp"
  5.  
  6. A::A(QString name)
  7.     : mName(name) {}
  8.  
  9. B* A::GetB(int i) {
  10.     return mBs[i];
  11. }
  12.  
  13. void A::SayName() {
  14.     qDebug() << "A says its name: " << mName;
  15. }
  16.  
  17. //////////////// A.hpp ////////////////
  18.  
  19. #ifndef _A
  20. #define _A
  21.  
  22. #include "B.hpp"
  23.  
  24. #include <QtCore/QObject>
  25. #include <QtCore/QString>
  26.  
  27. class A : public QObject {
  28.     Q_OBJECT
  29.     Q_PROPERTY(QString name READ GetName FINAL)
  30.  
  31. public:
  32.     A(QString name);
  33.  
  34.     // need a template here because in the real project
  35.     // we inherit B
  36.     template <typename T>
  37.     void AddB(T* t) {
  38.         mBs.append(t);
  39.         t->SetA(this); // this is why we need forward declaration in B.hpp, not here
  40.     }
  41.  
  42. public slots:
  43.     // I had a const QString& here, but since slots cannot return
  44.     // references I have to copy the string :(
  45.     QString GetName() { return mName; }
  46.     B* GetB(int i);
  47.     void SayName();
  48.  
  49. private:
  50.     QString mName;
  51.     QList<B*> mBs;
  52. };
  53.  
  54. #endif
  55.  
  56. //////////////// B.cpp ////////////////
  57.  
  58. #include "B.hpp"
  59.  
  60. #include "A.hpp" // because we only forward-declared it in our header
  61.  
  62. B::B(QString name)
  63.     : mName(name),
  64.       mA(0x0) {}
  65.  
  66.  
  67. void B::SetA(A* a) {
  68.     mA = a;
  69. }
  70.  
  71. void B::SayName() {
  72.     qDebug() << "B says its name: " << mName;
  73. }
  74.  
  75. void B::SayNameOfA() {
  76.     if(mA != 0x0) {
  77.         qDebug() << "B knows its A's name: " << mA->GetName();
  78.     } else {
  79.         qDebug() << "B does not have an A";
  80.     }
  81. }
  82.  
  83. A* B::GetA() {
  84.     return mA;
  85. }
  86.  
  87. QString B::GetName() {
  88.     return mName;
  89. }
  90.  
  91. //////////////// B.hpp ////////////////
  92.  
  93. #ifndef _B
  94. #define _B
  95.  
  96. #include <QtCore/QObject>
  97. #include <QtCore/QString>
  98. #include <QtCore/QDebug>
  99.  
  100. // forward declare here, as we need B in the
  101. // template of A
  102. class A;
  103.  
  104. class B : public QObject {
  105.     Q_OBJECT
  106.     Q_PROPERTY(QString name READ GetName FINAL)
  107.  
  108.     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  109.     // The problems are here:
  110.     // - A is incomplete struct for MOC
  111.     // - GetA() returns a pointer to A, not a copy of it
  112.     // Q_PROPERTY(A a READ GetA)
  113.  
  114. public:
  115.     B(QString name);
  116.     void SetA(A* a);
  117.  
  118. public slots:
  119.     A* GetA();
  120.     QString GetName();
  121.     void SayNameOfA();
  122.     void SayName();
  123.  
  124. private:
  125.     QString mName;
  126.     A* mA;
  127. };
  128.  
  129. #endif
  130.  
  131.  
  132. //////////////// main.cpp ////////////////
  133.  
  134. #include "A.hpp"
  135. #include "B.hpp"
  136.  
  137. #include <QtCore/QCoreApplication>
  138. #include <QtScript/QScriptEngine>
  139. #include <QtScript/QScriptValue>
  140. #include <QtCore/QMetaType>
  141.  
  142. int main(int argc, char** argv) {
  143.     QCoreApplication app(argc, argv);
  144.     QScriptEngine engine;
  145.  
  146.     // I create these on the stack as the "real project"
  147.     // is using pointers in this case. Actually, these
  148.     // objects are saved in boost::ptr_containers.
  149.  
  150.     A* a = new A("the A object");
  151.     B* b = new B("the B object");
  152.     a->AddB(b);
  153.  
  154.     // test it
  155.     a->SayName();
  156.     b->SayName();
  157.     b->SayNameOfA();
  158.  
  159.     // test properties
  160.     qDebug() << "Getting name property of A: " << a->property("name").toString();
  161.     qDebug() << "Getting name property of B: " << b->property("name").toString();
  162.  
  163.     // test scripting
  164.     QScriptValue aObj = engine.newQObject(a);
  165.     engine.globalObject().setProperty("aObj", aObj);
  166.     QScriptValue bObj = engine.newQObject(b);
  167.     engine.globalObject().setProperty("bObj", bObj);
  168.  
  169.     // register A*
  170.     // qRegisterMetaType<A*>("A*");
  171.  
  172.     QScriptValue result = engine.evaluate(
  173.             "print(\"Script knows A's name: \" + aObj.name); \n"
  174.             "print(\"Script knows B's name: \" + bObj.name); \n"
  175.             "print(\"Script knows A's GetName(): \" + aObj.GetName()); \n"
  176.             "print(\"Script knows B's GetName(): \" + bObj.GetName()); \n"
  177.             "print(\"Script calls A::SayName...\"); \n"
  178.             "aObj.SayName(); \n"
  179.             "print(\"Trying to get B's A and its name: \" + bObj.GetA().GetName());");
  180.    
  181.     // Script Error in last line:
  182.     // TypeError: cannot call GetA(): unknown return type 'A*' (register
  183.     //            the type qith qScriptRegisterMetaType()))"
  184.  
  185.     if(engine.hasUncaughtException()) {
  186.         qDebug() << "Line" << engine.uncaughtExceptionLineNumber() << ": " <<
  187.             result.toString();
  188.     }
  189. }
  190.  
  191. //////////////// Makefile ////////////////
  192.  
  193. default: bake run
  194.  
  195. bake: generate compile-moc compile
  196.  
  197. generate:
  198.     mkdir -p tmp/
  199.     moc -o tmp/A.moc.hpp A.hpp
  200.     moc -o tmp/B.moc.hpp B.hpp
  201.  
  202. compile-moc:
  203.     g++ -x c++ -c tmp/A.moc.hpp -o tmp/A.moc.hpp.cxx.o
  204.     g++ -x c++ -c tmp/B.moc.hpp -o tmp/B.moc.hpp.cxx.o
  205.  
  206. compile:
  207.     g++ *.cpp tmp/*.cxx.o -lQtCore -lQtScript -oout
  208.  
  209. run:
  210.     ./out
  211.  
  212. clean:
  213.     [[ -d tmp ]] && rm -r tmp
  214.     [[ -e out ]] && rm out
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement