Showing posts with label meta system. Show all posts
Showing posts with label meta system. Show all posts

Sunday, December 1, 2013

Exposing C++ ENUM to QML

I was working on update of one of my game and I while re-factoring I was required to expose C++ Enum to QML code.

Following is how header looks like with definition of Enum GamePadButton. I am registering Enum with Qt's Metaobject system using Q_ENUMS macro.
class GamePadObserver: public QObject {
 Q_OBJECT
 Q_ENUMS(GamePadButton)
public:

 enum GamePadButton{
   A_BUTTON=0,
   B_BUTTON,
   C_BUTTON,
   X_BUTTON,
   Y_BUTTON,
   Z_BUTTON,
                 ...
   NO_BUTTON
 };

public:
 GamePadObserver(QObject* parent = 0);
 virtual ~GamePadObserver();
        ...
};
Now to be able to see this Enum to QML code we need to register GamePadObserver class to Qt Metaobject system.If you want to be able to create instance of class then you can use qmlRegisterType() macro.

In my case I dont want to create instace of GamePadObserver in QML, I just want to expose it enum to QML and for that purpose we can use qmlRegisterUncreatableType macro. Its useful for exposing enum and attached property. Following how we can use this macro.
#include 

int main(int argc, char **argv)
{
 qmlRegisterUncreatableType("GamePadObserver", 1, 0,"GamePadObserver", "");
        ...
}
Now we can use Enum from QML, following how we can do that.
...
import GamePadObserver 1.0
...

Rectangle {
    id:main
    ...

    Connections{
        target: GamePad
        onButtonPressed: {
  
            if( button == GamePadObserver.X_BUTTON
            || button == GamePadObserver.Y_BUTTON 
            || button == GamePadObserver.A_BUTTON 
            || button == GamePadObserver.B_BUTTON ) {
                ...
            } 
        }        
    }

}

Monday, July 19, 2010

Creating object dynamically from class name in Qt

Some time it could be useful to be able to create new instance of class just by knowing its name. Such as in situation like when you are receiving XML from network and you want to create certain type of parser depending upon XML received from network.

In Qt its possible by using Qt's meta object system.

Here is my sample implementation that uses QMetaType to achieve the same. In sample code Parser is base class of all parser.
class Parser
{
public:

 virtual void parse() = 0;
 
 virtual ~Parser() {};

};
Now I am creating two dummy parser which are derived from Parser.
class Parser1 : public Parser
{
public:
    
    Parser1()
    {
        qDebug() <<"Parser1::Parser1()";
    }
    
    void parse()
    {
        qDebug() << "Parser1::parse()";
    }
    
    ~Parser1()
    {
       qDebug() <<"Parser1::~Parser1()";
    }
};
Q_DECLARE_METATYPE(Parser1)
  
class Parser2 : public Parser
{
public:
    
    Parser2()
    {
        qDebug() <<"Parser2::Parser2()";
    }
    
    void parse()
    {
        qDebug() << "Parser2::parse()";
    }
    
    ~Parser2()
    {
       qDebug() <<"Parser2::~Parser2()";
    }
};
Q_DECLARE_METATYPE(Parser2)
Now in parse function I am trying to create meta type from its name.
void parse( const char* parserName ) 
{
     int id = QMetaType::type( parserName );
     if (id != -1) {
        Parser *parser = static_cast< Parser* > 
                         ( QMetaType::construct( id ) );
        parser->parse();
        delete parser;
    }
}
Some sample code to test above function.
int main ( int argc, char* argv[] )
{
    qRegisterMetaType("Parser1");
    qRegisterMetaType("Parser2");
    
    qDebug() << "###### Trying create Parser1";
    parse("Parser1");
    
    qDebug() << "###### Trying create Parser2";
    parse("Parser2");
}
and finally output.
###### Trying create Parser1 
Parser1::Parser1() 
Parser1::parse() 
Parser1::~Parser1() 
###### Trying create Parser2 
Parser2::Parser2() 
Parser2::parse() 
Parser2::~Parser2() 
so that was all, but remember to use Q_DECLARE_METATYPE, qRegisterMetaType macros for registering your custom type with Qt meta object system.