Sunday, May 5, 2013

Power of Q_OBJECT in cascades

Q_OBJECT is a powerful macro which is responsible for establishing communication between QML files and native Cpp files.

 From the QT Documentation
  
The Meta-Object Compiler, moc, is the program that handles Qt's C++ extensions.
The moc tool reads a C++ header file. If it finds one or more class declarations that contain the Q_OBJECT macro, it produces a C++ source file containing the meta-object code for those classes. Among other things, meta-object code is required for the signals and slots mechanism, the run-time type information, and the dynamic property system.
Let us make an illustration of Q_OBJECT with a simple button.I'll write down my code here.

Firstly, in my main.qml file I used a button and called cpp method on click event. Find it below


import bb.cascades 1.0
NavigationPane {
    // creates one page with a label
    Page {
        Container {
            layout: DockLayout {
            }
            Button {
                text: qsTr("Click me")
                verticalAlignment: VerticalAlignment.Center
                horizontalAlignment: HorizontalAlignment.Center
                onClicked: {
                    cppObj.onButtonClicked();
                }
            }
        }
    }
}
Here is the applicationui.hpp file


#include <QObject>
#include <bb/cascades/NavigationPane>
#include <bb/cascades/Page>

using namespace bb::cascades;

namespace bb { namespace cascades { class Application; }}

/*!
 * @brief Application pane object
 *
 *Use this object to create and init app UI, to create context objects, to register the new meta types etc.
 */
class ApplicationUI : public QObject
{
    Q_OBJECT
public:
    ApplicationUI(bb::cascades::Application *app);
    virtual ~ApplicationUI() {}
    Q_INVOKABLE void onButtonClicked();
    NavigationPane *pane;

};

Finally my applicationui.cpp goes here.
// Default empty project template
#include "applicationui.hpp"

#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
using namespace bb::cascades;

ApplicationUI::ApplicationUI(bb::cascades::Application *app) :
        QObject(app) {
    // create scene document from main.qml asset
    // set parent to created document to ensure it exists for the whole application lifetime
    QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);

    // create root object for the UI
    pane = qml->createRootObject();
    // set created root object as a scene
    app->setScene(pane);

    qml->setContextProperty("cppObj", this);
}

/**
 * Q_INVOKABLE method which can be called from attached QML file.
 * Here in case main.qml
 */
void ApplicationUI::onButtonClicked() {
    // create scene document from buttonclicked.qml asset
    // set parent to created document to ensure it exists for the whole application lifetime
    QmlDocument *qml = QmlDocument::create("asset:///buttonclicked.qml").parent(this);
    Page* root = qml->createRootObject();
    pane->push(root);
}

The above code calls the onButtonClicked() of cpp file from QML.
To check the use of Q_OBJECT, remove Q_OBJECT in .hpp file. The button will not be clicked then after.

No comments:

Post a Comment