PDA

View Full Version : Namespace,qobject,enum trick. How to get it to work?



BadKnees
22nd March 2009, 21:49
Im trying to do the same thing that trolltech does in qnamespace.h. When moc runs it's an object but when the compiler runs it's a namespace. I think this will enable me to use staticMetaObject and QMetaEnum to get my enums as strings also.

I am aware that i can do this in my class if i inherit QObject, but i want my enums in a namespace. Just like Qt;)

Here's what im trying:


#include <QtCore/QObject>

#ifndef Q_MOC_RUN
namespace
#else
class ICOMM_EXPORT
#endif
iComm
/*
#if defined(Q_MOC_RUN)
:public QObject
#endif
*/
{
#if defined(Q_MOC_RUN)
Q_OBJECT
Q_ENUMS(PackageType)
#endif

#if defined(Q_MOC_RUN)
public:
#endif
enum PackageType{
Unknown,
Ping,
Pong,
SendUserInfo,
UserInfo,
SendAgentInfo,
AgentInfo,
AddUser,
UpdateStatus,
SendStatusInfo,
StatusInfo,
SendOnlineStatus,
OnlineStatus,
IM
};
}
#ifdef Q_MOC_RUN
;
#endif


But moc complains:

src/iNamespace.hh:17: Error: Class contains Q_OBJECT macro but does not inherit from QObject

If i make it inherit QObject g++ complains:

src/.moc/moc_iNamespace.cpp:61: error: ‘iComm::staticMetaObject’ should have been declared inside ‘iComm’
src/.moc/moc_iNamespace.cpp:66: error: ‘const QMetaObject* iComm::metaObject()’ should have been declared inside ‘iComm’
src/.moc/moc_iNamespace.cpp:66: error: non-member function ‘const QMetaObject* iComm::metaObject()’ cannot have cv-qualifier
src/.moc/moc_iNamespace.cpp:71: error: ‘void* iComm::qt_metacast(const char*)’ should have been declared inside ‘iComm’
src/.moc/moc_iNamespace.cpp: In function ‘void* iComm::qt_metacast(const char*)’:
src/.moc/moc_iNamespace.cpp:75: error: expected type-specifier before ‘iComm’
src/.moc/moc_iNamespace.cpp:75: error: expected `>' before ‘iComm’
src/.moc/moc_iNamespace.cpp:75: error: expected `(' before ‘iComm’
src/.moc/moc_iNamespace.cpp:75: error: expected primary-expression before ‘*’ token
src/.moc/moc_iNamespace.cpp:75: error: expected primary-expression before ‘>’ token
src/.moc/moc_iNamespace.cpp:75: error: invalid use of ‘this’ in non-member function
src/.moc/moc_iNamespace.cpp:75: error: expected `)' before ‘;’ token
src/.moc/moc_iNamespace.cpp:76: error: cannot call member function ‘virtual void* QObject::qt_metacast(const char*)’ without object
src/.moc/moc_iNamespace.cpp: At global scope:
src/.moc/moc_iNamespace.cpp:79: error: ‘int iComm::qt_metacall(QMetaObject::Call, int, void**)’ should have been declared inside ‘iComm’
src/.moc/moc_iNamespace.cpp: In function ‘int iComm::qt_metacall(QMetaObject::Call, int, void**)’:
src/.moc/moc_iNamespace.cpp:81: error: cannot call member function ‘virtual int QObject::qt_metacall(QMetaObject::Call, int, void**)’ without object
make: *** [src/.obj/moc_iNamespace.o] Error 1

ComaWhite
22nd March 2009, 23:01
Like it says, you aren't inheriting from QObject. So how you expect it to work?

BadKnees
23rd March 2009, 09:57
As my post says, i have tried it as well with the results posted above. And in <qtsource>/src/corelib/global/qnamespace.h the troll do not inherit the QObject. I would really like to get this to work:crying:

jpn
23rd March 2009, 10:11
Use Q_GADGET instead of Q_OBJECT.

SnarlCat
23rd March 2009, 19:56
Use Q_GADGET instead of Q_OBJECT.

This doesn't seem to work, inheriting from QObject or not ...

Still complains about missing staticMetaObject...

BadKnees
24th March 2009, 11:38
I've given up. I've tried everything i can think of. I have examined the preprocessor output with MOC_RUN defined and without. In qtcore qnamespace.h compiles fine as a namespace with a metaobject. But i cant reproduce it in my project. So i, as a second choise, used Q_GADGET in my class. This at least enables me to use QMetaEnum with an object which does not inherit from QObject. It would have been cooler with a namespace. But i will supress my compulsions, and go on with my life:o

jpn
24th March 2009, 11:58
This doesn't seem to work, inheriting from QObject or not ...

Still complains about missing staticMetaObject...
First of all, Q_GADGET is meant for non-QObjects. Just don't forget to re-run qmake after adding or removing Q_GADGET. Just like you would do with Q_OBJECT. Furthermore, you need to include the moc file by hand if you have Q_GADGET or Q_OBJECT in a .cpp file (it should be in a header file to avoid that).

SnarlCat
24th March 2009, 23:34
Ok.. so time for a simplistic example:


// FILENAME: foo.h
#ifndef FOO_H
#define FOO_H

#include <QObject>
#ifdef Q_MOC_RUN
class foo {
Q_GADGET
Q_ENUMS(Direction)
public:
enum Direction { Up, Down, Left, Right, Front, Back };
};
#else
namespace foo {
enum Direction { Up, Down, Left, Right, Front, Back };
}
#endif

#endif // FOO_H

//FILENAME: bar.h

#include <QtCore>
#include "foo.h"

class bar: public QObject {
Q_OBJECT
public:
bar();
foo::Direction getDirection() { return _dir; }
private:
foo::Direction _dir;
};


Moc seems to work (how would I know if it didn't?), but classes that include the header the above block is in, complain that "'staticMetaObject' is not a member of 'foo'" or "'staticMetaObject': undeclared identifier"

Thoughts on getting this working?

Thanks!

jpn
25th March 2009, 08:25
It's the macro which defines the member. In your code only moc can see the macro. You define a plain name space otherwise.

SnarlCat
25th March 2009, 11:12
So you think something like:


#ifdef Q_MOC_RUN
class foo {
Q_GADGET
Q_ENUMS(Direction)
public:
enum Direction { Up, Down, Left, Right, Front, Back };
};
#else
namespace foo {
Q_ENUMS(Direction)
enum Direction { Up, Down, Left, Right, Front, Back };
}
#endif


...is what we're looking for?

This certainly wasn't evident in qnamespace.h ...

Thanks!

jpn
25th March 2009, 14:55
No, I meant just using a class. If you want to, you can fake it to be a namespace for doxygen, though.

DragonEmbers
13th February 2013, 20:05
Apologies for the necro-posting but since this is one of the top google hits:

http://comments.gmane.org/gmane.comp.lib.qt.user/5256



>> The real point is: is there some 'magic' qmake flag or something else
>> used in qnamespace.h for having
>> that working properly ?
>
> Yes, there's magic hardcoded in moc and in QMetaObject::property.

:)

src/tools/moc/moc.cpp:653:


if (def.classname != "Qt" && def.classname != "QObject" && def.superclassList.isEmpty())
error("Class contains Q_OBJECT macro but does not inherit from QObject");