Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
New Developer
RadioRaiders
Posts: 13
Registered: ‎02-17-2010
My Device: Z10

Re: Getting the device's location

Instead of reading out the result on the terminal, how could I pass this into to be read in QML?

 

std::cout << "    horizontal accuracy = " << (double)pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) << std::endl;
Please use plain text.
BlackBerry Development Advisor
jehrismann
Posts: 68
Registered: ‎10-15-2012
My Device: Z10

Re: Getting the device's location

Hi,

 

Have you looked at http://developer.blackberry.com/native/documentation/cascades/dev/integrating_cpp_qml/index.html? It demonstrates a couple of ways you can do this.

 

Regards,

Jim

Please use plain text.
New Developer
RadioRaiders
Posts: 13
Registered: ‎02-17-2010
My Device: Z10

Re: Getting the device's location

Thanks for the fast reply. Yes I did look at that, and the example works fine:

 

QmlDocument *qml = QmlDocument::create("asset:///main.qml");
  
QDeclarativePropertyMap* propertyMap =
        new QDeclarativePropertyMap;
propertyMap->insert("name", QVariant(QString("Wes Barichak")));
propertyMap->insert("phone", QVariant(QString("519-555-0199")));
  
qml->setContextProperty("propertyMap", propertyMap);
------------------------------------------------------
Label {
    text: "User name: " + propertyMap.name
}
Label {
    text: "Phone number: " + propertyMap.phone
}
--------------------------------------------

but how/where exactly do I implement that in the GPS example that you gave?

 

I tried putting this line:

        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
        qml->setProperty("name", pos.coordinate().toString().toLatin1().constData());

 

Here:

// print out the accuracy as well, if available
    if ( pos.hasAttribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) ) {
        std::cout << "    horizontal accuracy = " << (double)pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) << std::endl;
        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
        qml->setProperty("name", pos.coordinate().toString().toLatin1().constData());

    }

 

But I'm not getting any output on the screen (?)

 

PS. QML:

import bb.cascades 1.2


Page {
    Container {
        //Todo: fill me with QML
        Label {
            // Localized text with the dynamic translation and locale updates support
            text: qsTr("Hello World") + name
            textStyle.base: SystemDefaults.TextStyles.BigText
        }
    }
}

 

 

Please use plain text.
BlackBerry Development Advisor
jehrismann
Posts: 68
Registered: ‎10-15-2012
My Device: Z10

Re: Getting the device's location

[ Edited ]

I think you are missing a couple of things. You need to do the following once only, so put it in your main.cpp or the constructor for your main  class:

 

// you might already have a line similar to this
QmlDocument *qml = QmlDocument::create("asset:///main.qml");

//  This is a declarative property map that is instantiated in C++ and accessible from QML.
// It can contain fields for any GPS (or whatever) info you want to access from QML
QDeclarativePropertyMap* gpsPropertyMap =  new QDeclarativePropertyMap;

// this makes the property map accessible from the qml content, by the id "gpsPropertyMap"
qml->setContextProperty("gpsPropertyMap", gpsPropertyMap);

 Then every time you get a position update call this:

 

if ( pos.hasAttribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) ) {
        std::cout << "    horizontal accuracy = " << (double)pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) << std::endl;
       gpsPropertyMap->insert("accuracy", pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy));
}

 

Your qml can access it like this:

 

Label {
            text: qsTr("Hello World") + gpsPropertyMap.accuracy

textStyle.base: SystemDefaults.TextStyles.BigText
}

 

Please use plain text.
New Developer
RadioRaiders
Posts: 13
Registered: ‎02-17-2010
My Device: Z10

Re: Getting the device's location

 

Thanks. I inserted the code as you mentioned directly in the example:

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);


    QDeclarativePropertyMap* gpsPropertyMap =  new QDeclarativePropertyMap;

    qml->setContextProperty("gpsPropertyMap", gpsPropertyMap);



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

    // Instantiate the default QGeoPositionInfoSource
    _source = QtMobilitySubset::QGeoPositionInfoSource::createDefaultSource(this);
    if ( _source ) {
        // connect to the QGeoPositionInfoSource's signals, to get the position info and/or error status
        connect(_source, SIGNAL(positionUpdated(const QGeoPositionInfo &)), this, SLOT(positionUpdated(const QGeoPositionInfo &)));
        connect(_source, SIGNAL(updateTimeout()), this, SLOT(positionUpdateTimeout()));
    }
}

 and

void ApplicationUI::positionUpdated(const QGeoPositionInfo & pos)
{
// print out the position in a convenient format:
std::cout << pos.coordinate().toString().toLatin1().constData() << std::endl;

// print out the accuracy as well, if available
if ( pos.hasAttribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) ) {
std::cout << " horizontal accuracy = " << (double)pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) << std::endl;

gpsPropertyMap->insert("accuracy", pos.coordinate().toString());

}

}

 but the last part gives an error:

 

error: 'gpsPropertyMap' was not declared in this scope

 

 

Did I declare the property map in the wrong place? Or ?

Please use plain text.
BlackBerry Development Advisor
jehrismann
Posts: 68
Registered: ‎10-15-2012
My Device: Z10

Re: Getting the device's location

Yes, I should've made the scope clear. In this context you're probably best off to make gpsPropertyMap a member of the ApplicationUI class, since it is accessed in both the constructor and the positionUpdated() method.

Please use plain text.
New Developer
RadioRaiders
Posts: 13
Registered: ‎02-17-2010
My Device: Z10

Re: Getting the device's location

That would make sense. But how exactly do I  do that? I tried below, but neither worked.

 

 

class ApplicationUI : public QObject
{

Q_OBJECT
public:
ApplicationUI(bb::cascades::Application *app);

    //Neither of the 2 lines below work 
    //QDeclarativePropertyMap* gpsPropertyMap;
   // QDeclarativePropertyMap* gpsPropertyMap =  new QDeclarativePropertyMap;



virtual ~ApplicationUI() {}

void startSatelliteUpdates();



public Q_SLOTS:
void positionUpdated(const QGeoPositionInfo & pos);
void positionUpdateTimeout();

private:
QtMobilitySubset::QGeoPositionInfoSource * _source;
};

 

Please use plain text.
New Developer
RadioRaiders
Posts: 13
Registered: ‎02-17-2010
My Device: Z10

Re: Getting the device's location

Ah, I forgot the include, now it works :smileyhappy:

 

applicationui.hpp

// Default empty project template
#ifndef ApplicationUI_HPP_
#define ApplicationUI_HPP_

#include <QObject>
#include <QDeclarativeView>
 #include <QDeclarativePropertyMap>

#include <QtLocationSubset/QGeoPositionInfoSource>

using ::QtMobilitySubset::QGeoPositionInfo;     // so the SIGNAL()/SLOT() macros can have matching signatures.

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);
    //QDeclarativePropertyMap gpsPropertyMap;
   // QDeclarativePropertyMap* gpsPropertyMap =  new QDeclarativePropertyMap;
    //QDeclarativePropertyMap ownerData;

    virtual ~ApplicationUI() {}
    void startSatelliteUpdates();


public Q_SLOTS:
    void positionUpdated(const QGeoPositionInfo & pos);
    void positionUpdateTimeout();

private:
    QtMobilitySubset::QGeoPositionInfoSource * _source;
    QDeclarativePropertyMap* gpsPropertyMap;

};


#endif /* ApplicationUI_HPP_ */

 

applicationui.cpp

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);

	   gpsPropertyMap =  new QDeclarativePropertyMap;
	   // this makes the property map accessible from the qml content, by the id "gpsPropertyMap"
	   qml->setContextProperty("gpsPropertyMap", gpsPropertyMap);


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

    // Instantiate the default QGeoPositionInfoSource
    _source = QtMobilitySubset::QGeoPositionInfoSource::createDefaultSource(this);
    if ( _source ) {
        // connect to the QGeoPositionInfoSource's signals, to get the position info and/or error status
        connect(_source, SIGNAL(positionUpdated(const QGeoPositionInfo &)), this, SLOT(positionUpdated(const QGeoPositionInfo &)));
        connect(_source, SIGNAL(updateTimeout()), this, SLOT(positionUpdateTimeout()));
    }
}

 

void ApplicationUI::positionUpdated(const QGeoPositionInfo & pos)
{
    // print out the position in a convenient format:
    std::cout << pos.coordinate().toString().toLatin1().constData() << std::endl;
    //QmlDocument *qml = QmlDocument::create("asset:///main.qml");
    //qmlRegisterUncreatableType<QtMobilitySubset::QGeoCoordinate>("qtmobilitysubset.qgeocoordinate", 1, 0, "QGeoCoordinate", "");
    //qml->setContextProperty("_hardware", (pos.coordinate().toString().toLatin1().constData()));




    // print out the accuracy as well, if available
    if ( pos.hasAttribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) ) {
        std::cout << "    horizontal accuracy = " << (double)pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy) << std::endl;

        gpsPropertyMap->insert("accuracy", pos.attribute(QtMobilitySubset::QGeoPositionInfo::HorizontalAccuracy));

    }

}

 

 

Please use plain text.
BlackBerry Development Advisor
jehrismann
Posts: 68
Registered: ‎10-15-2012
My Device: Z10

Re: Getting the device's location

That's good. For completeness you should make sure gpsPropertyMap is cleaned up in the end. You can set its parent to the ApplicationUI instance:

 

gpsPropertyMap =  new QDeclarativePropertyMap(this);

 or just delete it yourself in the ApplicationUI destructor.

Please use plain text.
New Developer
RadioRaiders
Posts: 13
Registered: ‎02-17-2010
My Device: Z10

Re: Getting the device's location

Thanks. Everything is working good, except for the TimeOut. If I disable Location Services on my phone before starting the program, it behaves as expected. However, if I disable Location, or switch into flight mode, or otherwise lose a location source  while the app is running, the app doesn't time-out within the setUpdateInterval time, instead the app gets stuck showing the last valid coordinate info.

 

Is this behaving as normal?

 


Handling errors with updateTimeout()

The updateTimeout() signal is emitted when the positioning source determines that it's temporarily unable to provide a fix. It continues to try to find a position, so your code doesn't need to handle retrying to find a location fix. However, your app can give the user a hint that positioning is temporarily unavailable. For example, a navigational app could give the user a "Lost satellite signal" alert or toast when it receives an updateTimeout() signal.

Your app will only get one updateTimeout() signal to indicate that it can't provide a location fix at this time. Any subsequent errors from an implicit retry won't be reported to the app.

Eventually, your app will get a positionUpdated() signal, and it will reset the timer to 0 and send another updateTimeout() signal if it determines that it can't get a location update within the timeout period.



 

Please use plain text.