2
votes

I am using Blackberry Cascades 10 Beta 3 SDK with C++ QT & QML with the Blackberry 10 Dev Alpha Simulator and the QNX Momentics IDE, and I'm trying to implement the ability to click on a button with a phone number from QML and have it bring up a dialpad with that number in from at which point the user should be able to press call and it would call that number. The following is the sort of thing I have done:

Button {
    text: "555-555-5555" //just a sample number - I don't actually use this number
    onClicked: Foo.phone(text) //I don't actually use the class name Foo
}

and I have: ...

class Foo : public QObject {
    Q_OBJECT
public:
    ...
    Q_INVOKABLE void phone(QString number);
}
...

and I have:

void Foo::phone(QString number) {
    bb::system::phone::Phone phone;
    phone.requestDialpad(number, bb::system::phone::LineType::Cellular);
}

But when I click on the button it doesn't do anything - I need the dialpad to show up - does anyone have any idea what I'm doing wrong?

1
In case your wondering - other Q_INVOKABLE member functions in the same class that phone is in - are callable from the same qml document as phone is in - so it's not an issue of the class not being registered through a certain variable to that specific qml document, nor is it an issue of not using the right variable name to refer to that class from the qml in the onClicked event handleruser1296259
are you using qmlRegisterType<Foo> to make the Foo class available to the QML?donturner
Yes, I am using qmlRegisterType<Foo>user1296259

1 Answers

2
votes

Change the code of your class Foo to the following:

Foo.hpp

#ifndef FOO_HPP_
#define FOO_HPP_

#include <QObject>
#include <bb/system/InvokeManager>

class Foo : public QObject {
    Q_OBJECT

public:
    Foo();
    virtual ~Foo();

    Q_INVOKABLE void callNumber(const QString& number);

private Q_SLOTS:
    void processInvokeReply(); // This slot handles the result of an invocation

private:
    bb::system::InvokeManager* _invokeManager;

    Q_DISABLE_COPY(Foo);
};
#endif /* FOO_HPP_ */

Foo.cpp:

#include <bb/system/InvokeAction>
#include <bb/system/InvokeReply>
#include <bb/system/InvokeTargetReply>
#include <bb/system/InvokeRequest>
#include <bb/PpsObject>
#include "Foo.hpp"

Foo::Foo() :
        _invokeManager(new InvokeManager(this)) {
}


Foo::~Foo() {
}

void Foo::processInvokeReply() {
    InvokeReply *reply = qobject_cast<InvokeReply*>(sender());     // Get the reply from the sender object

    // Check for errors during invocation
    switch (reply->error()) {
        case InvokeReplyError::BadRequest:
                qDebug("[ErrorBadRequest] Invoke Failed!");
            break;
        case InvokeReplyError::Internal:
                qDebug("[ErrorInternal] Invoke Failed!");
            break;
        case InvokeReplyError::NoTarget:
                qDebug("[ErrorNoTarget] Invoke Failed!");
            break;
        case InvokeReplyError::TargetNotOwned:
                qDebug("[ErrorTargetNotOwned] Invoke Failed.");
            break;
        default:
                qDebug("[Odd Error %d] Invoke failed", reply->error());
            break;
    }
    reply->deleteLater();     // Delete the reply later on
}


void Foo::callNumber(const QString& number) {
    QVariantMap map;
    map.insert("number", number);    // required
    QByteArray requestData = bb::PpsObject::encode(map, NULL);
    InvokeRequest request;
    request.setAction("bb.action.DIAL");
    request.setData(requestData);
    request.setMimeType("application/vnd.blackberry.phone.startcall");
    const InvokeTargetReply *reply = _invokeManager->invoke(request);
    if (reply) {
        QObject::connect(reply, SIGNAL(finished()), this, SLOT(processInvokeReply()));
    } else {
        qWarning() << "Invoke Failed! InvokeReply is empty.";
    }
}

Expose it via initialisation cpp code where you launch your app:

Foo* _foo = new Foo();
qml->setContextProperty("_foo", _foo);

Then use it in QML like that:

Button {
    onClicked: {
        _foo.callNumber("555-555-5555")
    }
}

ADDED:

Also, there's an easier way for doing this:

in main.cpp:

#include <bb/system/phone/Phone>
#include <bb/data/DataSource>

// skipped ...

Q_DECL_EXPORT int main(int argc, char **argv)
{
     // ...skipped 
        qmlRegisterType<bb::system::phone::Phone>("bb.system.phone", 1, 0, "Phone");
        bb::data::DataSource::registerQmlTypes();
     // ...skipped
}

then in QML file:

import bb.cascades 1.0
import bb.system.phone 1.0

// Creates one page with a button. When you tap the button,
// a dial pad with a specific phone number is displayed.

Page {
    Container {
        layout: DockLayout {
        }
        verticalAlignment: VerticalAlignment.Center
        horizontalAlignment: HorizontalAlignment.Center

        Button {
            id: callButton
            text: "Call me, maybe"

            onClicked: {
                phone.requestDialpad("(519) 555-0100")
            }
        }
    }
    attachedObjects: [
        Phone {
            id: phone
        }
    ]
}

Read more about this example here - http://developer.blackberry.com/cascades/documentation/device_comm/phone/index.html