Set up your project

Setting up an app is pretty similar whether we're using QML or C++, so once we're done with the setup we build the UI both ways.

Create a project

Since we want to build this application from scratch, there's a little bit of setup that we need to take care of first. Let's start by creating an empty Cascades project to work from:

  1. In the Momentics IDE for BlackBerry, on the File menu, click New > BlackBerry Project.
  2. In the New BlackBerry Project Wizard, select Application > Cascades and click Next.
  3. Click Standard empty project and click Next.
  4. In the Project Name field, provide a name for your project (for example, MyFirstApp). Click Next.
  5. In the API Level page, select the API level that you want to use and click Finish.
  6. If you're prompted to open the QML Editing perspective, click Yes.

When you open the QML Editing perspective, you are using the QML support tools, which are built into the Momentics IDE. If you have experience with Eclipse, most of the features of the IDE should be familiar to you.

You can find features that are specific to Cascades, such as the QML preview and Components view, using the QML Editing perspective.

To open the QML Editing perspective:

  1. Click Window > Open Perspective > Other.
  2. Click QML Editing.
  3. Click OK.

After you finish creating a project from a template, a new project appears in the Project Explorer view with the project name that you specified. Your project is built automatically as soon as you create it. Take a peek in the Console view to see the results of the build.

You can see the files in your project in the Project Explorer view. The Project Explorer view is standard for Eclipse, but it has a few files that are specific to Cascades projects:

  • A .pro project file, which includes specific configurations and settings for your project
  • A standard Makefile for your project
  • An src folder for C++ source files
  • An assets folder for QML files and images

Import images

Now you need to import the assets required for the project. For the LightningCrossfade sample, we need four images.

Daytime image asset for Cascades first app.
Nighttime image asset for Cascades first app.
Moon image asset for Cascades first app.
Sun image asset for Cascades first app.

day.jpg

The foreground image, which fades in as the slider moves to the right

night.jpg

The background image, which disappears as the foreground image fades in

moon.png

An icon used for the nighttime position of the slider

sun.png

An icon used for the daytime position of the slider

To import images into your project:

  1. Download the images.zip file.
  2. Extract the images folder to the project's assets folder in your workspace. For example, C:\<your_workspace>\<project_name>\assets.
  3. In the Project Explorer view, refresh your project to display the imported images.
Screen showing project images for Cascades first app in Project Explorer.

Import images for devices with physical keyboards

If you want your app to support devices with physical keyboards, you need two more images that are scaled to fit the 720x720 screen resolution of devices with physical keyboards. These images are stored in a 720x720 folder in your assets folder.

To import these images into your project:

  1. Open the images.zip file that you downloaded previously.

  2. Extract the 720x720 folder to the project's assets folder in your workspace. For example, C:\<your_workspace>\<project_name>\assets.

  3. In the Project Explorer view, refresh your project to display the imported images. Notice that the 720x720 folder has its own images folder with the two images you need if you are testing your app on a device with a physical keyboard.

Daytime image asset for a device with a physical keyboard.

day.jpg

An alternate foreground image for a device with a physical keyboard

Nighttime image asset for a device with a physical keyboard.

night.jpg

An alternate background image for a device with a physical keyboard

Now your assets folder should look like the image to the right.

The 720x720 folder is a part of the Cascades static asset selector feature. This feature lets you use different sets of assets in your apps, depending on the resolution or theme of the device that your app is running on.

For more information, see Static Asset Selection.

Screen showing project images and 720x720 asset selector for Cascades first app in Project Explorer.

Run the app

Even though the project is nearly empty, your application is actually ready to run. Let's build and run it to see the output.

Before you try to run the application, you need to make sure that you have a device or simulator set up as a target in the Momentics IDE.

For information about setting up the development environment, see Getting started.

To run the application:

  1. Make sure your app is selected in the Active Project drop-down list.
  2. Click the Run button to see the "Hello World" message.
  3. Check out the Console messages. You can review information about the settings that are active in your environment. For example, QML debugging is enabled and orientation support is set to automatic.
Screen showing an app that uses the Standard empty template running on a device.

You can learn more about these settings in Build, test, and deploy your app.

Discover how an app is started

Now that your app is running, let's have a closer look at how it's done. In the src folder, double-click the main.cpp file to open it in the editor. Typically, this is how you're going to set up your Cascades applications.

#include <bb/cascades/Application>

#include <QLocale>
#include <QTranslator>
#include "applicationui.hpp"

#include <Qt/qdeclarativedebug.h>

using namespace bb::cascades;

Q_DECL_EXPORT int main(int argc, char **argv)
{
    Application app(argc, argv);

    // Create the Application UI object. This is where the main.qml
    // file is loaded and the application scene is set.
    new ApplicationUI(&app);

    // Enter the application main event loop.
    return Application::exec();
}

The first few lines are the required include statements. The  Application class contains the main event loop for your app, which handles all interactions between the user and your application (for example, touch events or button clicks). The Application class also handles the application's initialization and finalization.  QLocale and  QTranslator are Qt classes that are used for handling localized strings. The applicationui.hpp include is for the header file for a class that was automatically created in your project. This class is where you implement your application UI and logic. The last include is a class that is used to enable your application for debugging and profiling.

You can learn about these tools in Build, test, and deploy your app.

#include <bb/cascades/Application>
#include <QLocale>
#include <QTranslator>
#include "applicationui.hpp"
#include <Qt/qdeclarativedebug.h>

The next line is a declaration for using the bb::cascades namespace. By using the namespace, the application can call bb::cascades functions without having to specify the bb::cascades namespace each time.

using namespace bb::cascades;

The next line is the function definition for main(). This is the first function that runs when a Cascades application starts.

Q_DECL_EXPORT int main(int argc, char **argv)
{

Inside the body for main(), an Application object is created.

Application app(argc, argv); 

Next, we instantiate our ApplicationUI class (the class created with your project for application UI and logic) passing the address of app. In the next part of the tutorial, we see how this class is used to import a QML file containing the application's UI.

new ApplicationUI(&app);

The last thing we do is tell Application to start its event loop. Once the event loop ends (for example, when a user exits the app), the Application deletes the scene and all of its children, and cleans up application resources.

    return Application::exec();
}

Load a QML file into your app

Now that you've seen how an application is started, let's have a look at how to load a QML file into it. In the src folder, double-click the applicationui.cpp file located in your project.

#include "applicationui.hpp"

#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/LocaleHandler>

using namespace bb::cascades;

ApplicationUI::ApplicationUI(bb::cascades::Application *app) :
        QObject(app)
{
    // prepare the localization
    m_pTranslator = new QTranslator(this);
    m_pLocaleHandler = new LocaleHandler(this);

    bool res = QObject::connect(m_pLocaleHandler, 
        SIGNAL(systemLanguageChanged()), 
        this, 
        SLOT(onSystemLanguageChanged()));

    // This is only available in Debug builds
    Q_ASSERT(res);
    // Since the variable is not used in the app, 
    // this is added to avoid a compiler warning.
    Q_UNUSED(res);

    // initial load
    onSystemLanguageChanged();

    // Create scene document from main.qml asset, the parent is set
    // to ensure the document gets destroyed properly at shut down.
    QmlDocument *qml = 
        QmlDocument::create("asset:///main.qml").parent(this);

    // Create root object for the UI
    AbstractPane *root = qml->createRootObject<AbstractPane>();

    // Set created root object as the application scene
    app->setScene(root);
}

void ApplicationUI::onSystemLanguageChanged()
{
    QCoreApplication::instance()->removeTranslator(m_pTranslator);
    // Initiate, load and install the application translation files.
    QString locale_string = QLocale().name();
    QString file_name = QString("MyFirstApp_%1").arg(locale_string);
    if (m_pTranslator->load(file_name, "app/native/qm")) {
        QCoreApplication::instance()
            ->installTranslator(m_pTranslator);
    }
}

At the top of the file, the required header files and classes are included. After the include statements, there's a using directive for the bb::cascades namespace. This directive allows the application to use all the classes in bb::cascades without specifying the namespace on each instance.

#include "applicationui.hpp"

#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/LocaleHandler>

using namespace bb::cascades;

In the constructor for ApplicationUI, we set up the localization of our content before we create any of the application UI. We create a QTranslator object to handle localization of any text output in our app and a LocaleHandler to listen for changes to the locale of the device that is running our app. We also connect the systemLanguageChanged() signal to a slot that we define in our main.cpp.

ApplicationUI::ApplicationUI(bb::cascades::Application *app) :
        QObject(app)
{
    // prepare the localization
    m_pTranslator = new QTranslator(this);
    m_pLocaleHandler = new LocaleHandler(this);

    bool res = QObject::connect(m_pLocaleHandler, 
        SIGNAL(systemLanguageChanged()), 
        this, 
        SLOT(onSystemLanguageChanged()));

    // This is only available in Debug builds
    Q_ASSERT(res);
    // Since the variable is not used in the app, 
    // this is added to avoid a compiler warning.
    Q_UNUSED(res);

    // initial load
    onSystemLanguageChanged();
;

Next in the constructor for ApplicationUI, we call the QObject constructor to set the parent of app. This ensures that when the application stops running, the ApplicationUI object is deleted. Next, a QmlDocument object is created using the main.qml file located in the project's assets folder. Then, we set the parent of the QmlDocument object to this application. The QmlDocument object represents a QML file that is loaded into your app.

// Create scene document from main.qml asset, the parent is set
// to ensure the document gets destroyed properly at shut down.
QmlDocument *qml = 
    QmlDocument::create("asset:///main.qml").parent(this);

And finally, the root object is retrieved from the QmlDocument object. The root object must be a subclass of AbstractPane and is used to set the scene for the application.

    // Create root object for the UI
    AbstractPane *root = qml->createRootObject<AbstractPane>();

    // Set created root object as the application scene
    app->setScene(root);
}

That's our constructor completed. We still have to define that slot that we connected to the systemLanguageChanged() signal. This slot removes any existing translators attached to your app, finds the current country and language of the device running your app, and installs a translator for the new locale.

void ApplicationUI::onSystemLanguageChanged()
{
    QCoreApplication::instance()->removeTranslator(m_pTranslator);
    // Initiate, load and install the application translation files.
    QString locale_string = QLocale().name();
    QString file_name = QString("MyFirstApp_%1").arg(locale_string);
    if (m_pTranslator->load(file_name, "app/native/qm")) {
        QCoreApplication::instance()
            ->installTranslator(m_pTranslator);
    }
}

If you take a look at your applicationui.hpp file, you can see all of the declarations that you need to use these classes as well as two private global declarations for the QTranslator and LocaleHandler that your app will use. You won't usually have to make any changes to these classes or declarations.

If you would like to learn more, you can check out Internationalization.

#ifndef ApplicationUI_HPP_
#define ApplicationUI_HPP_

#include <QObject>

namespace bb
{
    namespace cascades
    {
        class Application;
        class LocaleHandler;
    }
}

class QTranslator;

/*!
 * @brief Application object
 *
 *
 */

class ApplicationUI : public QObject
{
    Q_OBJECT
public:
    ApplicationUI(bb::cascades::Application *app);
    virtual ~ApplicationUI() { }
private slots:
    void onSystemLanguageChanged();
private:
    QTranslator* m_pTranslator;
    bb::cascades::LocaleHandler* m_pLocaleHandler;
};

#endif /* ApplicationUI_HPP_ */

Now that we've seen how an app is started and how the QML is loaded, let's get to the good stuff: creating your UI using QML!

If you'd like to skip the QML part of the tutorial, you can jump ahead to the last part of the tutorial and create your UI using C++.

Last modified: 2014-01-23

comments powered by Disqus