Qt-based BB10 API Examples Documentation

Contents

Invoke Target Example

Files:

Description

The Invoke Target example shows how to handle incoming invocation requests from other applications.

Overview

In this example we'll learn how to use the InvokeManager and InvokeRequest classes of the BB10 framework to handle incoming invocation requests from external applications.

All the business logic is encapsulated in the C++ class App, which is exported to the QML files under the name '_app'.

The UI

The UI of this sample application consists of a main page which displays a hint paragraph with a few examples on how to use this application, this display comes up when launched as an application.

In addition, there are three new pages (Composer, Picker and Previewer), which are launched when their bound target id's are invoked via the invokeclient sample application. All three are registerd and invoked as "Cards".

The Composer page consists of an TextArea with two button actions (cancel and share), which cancel the current task or mimick sharing option.

    NavigationPane {
        backButtonsVisible: false
        peekEnabled: true
        Page {
            titleBar: TitleBar {
                title: qsTr("Composer")
                acceptAction: ActionItem {
                    title: qsTr("Share")
                    onTriggered: {
                        _app.cardDone(qsTr("Content Shared."));
                    }
                }
                dismissAction: ActionItem {
                    title: qsTr("Cancel")
                    onTriggered: {
                        _app.cardDone(qsTr("Dont feel like sharing today?"));
                    }
                }
            }
            Container {
                horizontalAlignment: HorizontalAlignment.Fill
                Header {
                    title: qsTr("Share via Sample Composer")
                }
                Container {
                    horizontalAlignment: HorizontalAlignment.Fill
                    TextArea {
                        horizontalAlignment: HorizontalAlignment.Center
                        preferredHeight: 400
                        text: _app.data
                        onCreationCompleted: {
                            requestFocus();
                        }
                    }
                }
            }
        }
    }

The Picker page displays many egg images and asks the user to pick one when invoked.

    NavigationPane {
        backButtonsVisible: false
        peekEnabled: true
        Page {
            titleBar: TitleBar {
                title: qsTr("Pick an Egg")
                dismissAction: ActionItem {
                    title: qsTr("Cancel")
                    onTriggered: {
                        _app.cardDone(qsTr("Boo! No eggs today.."));
                    }
                }
            }
            Container {
                layout: DockLayout {
                }
                horizontalAlignment: HorizontalAlignment.Fill
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Left
                    verticalAlignment: VerticalAlignment.Top
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Yummy!"));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Top
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Quack Quack.."));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Right
                    verticalAlignment: VerticalAlignment.Top
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Mmmmmm.."));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Left
                    verticalAlignment: VerticalAlignment.Center
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Delicio!"));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Center
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Yuck!"));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Right
                    verticalAlignment: VerticalAlignment.Center
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Whoa!"));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Left
                    verticalAlignment: VerticalAlignment.Bottom
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Love it.."));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Bottom
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Get it cooked already!"));
                    }
                }
                ImageButton {
                    horizontalAlignment: HorizontalAlignment.Right
                    verticalAlignment: VerticalAlignment.Bottom
                    defaultImageSource: "asset:///images/egg.png"
                    onClicked: {
                        _app.cardDone(qsTr("Sunny side up"));
                    }
                }
            }
        }
    }

The Previewer page displays the image with which it was invoked using the uri variable that was passed through the invocation request.

    NavigationPane {
        backButtonsVisible: true
        peekEnabled: true
        Page {
            titleBar: TitleBar {
                title: qsTr("Previewer")
            }
            Container {
                horizontalAlignment: HorizontalAlignment.Fill
                ImageView {
                    imageSource: _app.uri
                    scalingMethod: ScalingMethod.AspectFit
                }
            }
        }
    }

App

The App object is the mediator between the UI and the bb::system::InvokeManager class. In stores the startup mode and values of incoming invocation requests and makes them available to the UI through properties.

    class App : public QObject
    {
        Q_OBJECT

        // The textual representation of the startup mode of the application
        Q_PROPERTY(QString startupMode READ startupMode NOTIFY requestChanged)

        // The values of the incoming invocation request
        Q_PROPERTY(QString source READ source NOTIFY requestChanged)
        Q_PROPERTY(QString target READ target NOTIFY requestChanged)
        Q_PROPERTY(QString action READ action NOTIFY requestChanged)
        Q_PROPERTY(QString mimeType READ mimeType NOTIFY requestChanged)
        Q_PROPERTY(QString uri READ uri NOTIFY requestChanged)
        Q_PROPERTY(QString data READ data NOTIFY requestChanged)

        // The textual representation of the card status
        Q_PROPERTY(QString status READ status NOTIFY statusChanged)

    public:
        App(QObject *parent = 0);
        void initFullUI();
        void initComposerUI();
        void initPreviewerUI();
        void initPickerUI();

    public Q_SLOTS:
        // This method is invoked to notify the invocation system that the action has been done
        void cardDone(const QString& msg);

    Q_SIGNALS:
        // The change notification signal of the properties
        void requestChanged();
        void statusChanged();

    private Q_SLOTS:
        // This slot is called whenever an invocation request is received
        void handleInvoke(const bb::system::InvokeRequest&);

        void resized(const bb::system::CardResizeMessage&);

        /**
         * This slot is triggered when a card is chosen to be pooled by the system after it is closed. The card should clear it's UI
         * and states so that it is ready for the next invocation.
         */
        void pooled(const bb::system::CardDoneMessage&);

    private:
        // The accessor methods of the properties
        QString startupMode() const;
        QString source() const;
        QString target() const;
        QString action() const;
        QString mimeType() const;
        QString uri() const;
        QString data() const;
        QString status() const;

        // The central class to manage invocations
        bb::system::InvokeManager *m_invokeManager;

        // The property values
        QString m_startupMode;
        QString m_source;
        QString m_target;
        QString m_action;
        QString m_mimeType;
        QString m_uri;
        QString m_data;
        QString m_status;
    };

Inside the constructor the member variables are initialized with default values and the UI is loaded from the main.qml file.

    App::App(QObject *parent)
        : QObject(parent)
        , m_invokeManager(new InvokeManager(this))
    {
        // Listen to incoming invocation requests
        bool ok = connect(m_invokeManager, SIGNAL(invoked(const bb::system::InvokeRequest&)),
                          this, SLOT(handleInvoke(const bb::system::InvokeRequest&)));
        Q_ASSERT(ok);
        ok = connect(m_invokeManager,
                     SIGNAL(cardResizeRequested(const bb::system::CardResizeMessage&)),
                     this, SLOT(resized(const bb::system::CardResizeMessage&)));
        Q_ASSERT(ok);
        ok = connect(m_invokeManager,
                     SIGNAL(cardPooled(const bb::system::CardDoneMessage&)), this,
                     SLOT(pooled(const bb::system::CardDoneMessage&)));
        Q_ASSERT(ok);

        m_source = m_target = m_action = m_mimeType = m_uri = m_data = m_status =
                tr("--");

        // Initialize properties with default values
        switch (m_invokeManager->startupMode()) {
        case ApplicationStartupMode::LaunchApplication:
            m_startupMode = tr("Launch");
            initFullUI();
            break;
        case ApplicationStartupMode::InvokeApplication:
            // Wait for invoked signal to determine and initialize the appropriate UI
            m_startupMode = tr("Invoke");
            break;
        case ApplicationStartupMode::InvokeCard:
            // Wait for invoked signal to determine and initialize the appropriate UI
            m_startupMode = tr("Card");
            break;
        }

        // Create the UI

    }

To get informed about incoming invocation requests, the custom slot handleInvoke() is connected against the invoked() signal of the bb::system::InvokeManager object.

    void App::handleInvoke(const InvokeRequest& request) {
        // Copy data from incoming invocation request to properties
        m_source =
                QString::fromLatin1("%1 (%2)").arg(request.source().installId()).arg(
                        request.source().groupId());
        m_target = request.target();
        m_action = request.action();
        m_mimeType = request.mimeType();
        m_uri = request.uri().toString();
        m_data = QString::fromUtf8(request.data());

        if (m_target == "com.example.bb10samples.invocation.sharecomposer") {
            initComposerUI();
        } else if (m_target
                == "com.example.bb10samples.invocation.imagepreviewer") {
            initPreviewerUI();
        } else if (m_target == "com.example.bb10samples.invocation.eggpicker") {
            initPickerUI();
        }

        // Signal that the properties have changed
        emit requestChanged();
    }

The values from the passed bb::system::InvokeRequest are copied to the property values and the UI is updated by emitting the change notification signal.

bar-descriptor.xml

To make the invoketarget application a candidate for invocations, the BB10 system must know about the invocation interface of the application. That is defined inside the bar-descriptor.xml file of the project inside an invoke-target element.

    <invoke-target id="com.example.bb10samples.invocation.openimage1">
        <invoke-target-name>InvokeTarget Image 1</invoke-target-name>
        <icon><image>icon.png</image></icon>
        <type>application</type>
        <filter>
            <action>bb.action.OPEN</action>
            <mime-type>image/png</mime-type>
        </filter>
    </invoke-target>
    <invoke-target id="com.example.bb10samples.invocation.openimage2">
        <invoke-target-name>InvokeTarget Image 2</invoke-target-name>
        <icon><image>icon.png</image></icon>
        <type>application</type>
        <filter>
            <action>bb.action.OPEN</action>
            <mime-type>image/png</mime-type>
        </filter>
    </invoke-target>
    <invoke-target id="com.example.bb10samples.invocation.card.previewer">
        <type>card.previewer</type>
        <filter>
            <action>bb.action.OPEN</action>
            <mime-type>image/png</mime-type>
        </filter>
    </invoke-target>
    <invoke-target id="com.example.bb10samples.invocation.card.composer">
        <type>card.composer</type>
        <filter>
            <action>bb.action.OPEN</action>
            <mime-type>image/png</mime-type>
        </filter>
    </invoke-target>
    <invoke-target id="com.example.bb10samples.invocation.card.picker">
        <type>card.picker</type>
        <filter>
            <action>bb.action.OPEN</action>
            <mime-type>image/png</mime-type>
        </filter>
    </invoke-target>