summaryrefslogtreecommitdiff
path: root/src/plugins/position
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/position')
-rw-r--r--src/plugins/position/blackberry/bb/ppsattribute.cpp310
-rw-r--r--src/plugins/position/blackberry/bb/ppsattribute_p.h80
-rw-r--r--src/plugins/position/blackberry/bb/ppsobject.cpp743
-rw-r--r--src/plugins/position/blackberry/bb/ppsobject.h98
-rw-r--r--src/plugins/position/blackberry/bb/safeassign.h57
-rw-r--r--src/plugins/position/blackberry/blackberry.pro27
-rw-r--r--src/plugins/position/blackberry/locationmanagerutil_bb.cpp164
-rw-r--r--src/plugins/position/blackberry/locationmanagerutil_bb.h75
-rw-r--r--src/plugins/position/blackberry/plugin.json8
-rw-r--r--src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp1276
-rw-r--r--src/plugins/position/blackberry/qgeopositioninfosource_bb.h145
-rw-r--r--src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h126
-rw-r--r--src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp70
-rw-r--r--src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.h64
-rw-r--r--src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp621
-rw-r--r--src/plugins/position/blackberry/qgeosatelliteinfosource_bb.h87
-rw-r--r--src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h105
-rw-r--r--src/plugins/position/position.pro1
18 files changed, 4057 insertions, 0 deletions
diff --git a/src/plugins/position/blackberry/bb/ppsattribute.cpp b/src/plugins/position/blackberry/bb/ppsattribute.cpp
new file mode 100644
index 00000000..e59f905a
--- /dev/null
+++ b/src/plugins/position/blackberry/bb/ppsattribute.cpp
@@ -0,0 +1,310 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <bb/PpsAttribute>
+#include "ppsattribute_p.h"
+
+#include <QDebug>
+#include <QVariant>
+
+Q_DECLARE_METATYPE(QList<bb::PpsAttribute>)
+typedef QMap<QString, bb::PpsAttribute> PpsAttributeMap;
+Q_DECLARE_METATYPE(PpsAttributeMap)
+
+namespace bb
+{
+
+///////////////////////////
+//
+// PpsAttributePrivate
+//
+///////////////////////////
+
+PpsAttributePrivate::PpsAttributePrivate():
+ _type(PpsAttribute::None)
+{
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( int value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::Number;
+ attribute.d->_data = value;
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( long long value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::Number;
+ attribute.d->_data = value;
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( double value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::Number;
+ attribute.d->_data = value;
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( bool value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::Bool;
+ attribute.d->_data = value;
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( const QString &value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::String;
+ attribute.d->_data = value;
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( const QList<PpsAttribute> &value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::Array;
+ attribute.d->_data = QVariant::fromValue(value);
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( const QMap<QString, PpsAttribute> &value, PpsAttributeFlag::Types flags )
+{
+ PpsAttribute attribute;
+ attribute.d->_type = PpsAttribute::Object;
+ attribute.d->_data = QVariant::fromValue(value);
+ attribute.d->_flags = flags;
+ return attribute;
+}
+
+///////////////////////////
+//
+// PpsAttribute
+//
+///////////////////////////
+
+PpsAttribute::PpsAttribute():
+ d(new PpsAttributePrivate())
+{
+}
+
+PpsAttribute::~PpsAttribute()
+{
+}
+
+PpsAttribute::PpsAttribute(const PpsAttribute & other):
+ d(other.d)
+{
+}
+
+PpsAttribute &PpsAttribute::operator=(const PpsAttribute & other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool PpsAttribute::operator==(const PpsAttribute & other) const
+{
+ if ( type() != other.type() ) {
+ return false;
+ }
+ if ( flags() != other.flags() ) {
+ return false;
+ }
+
+ switch ( type() ) {
+ case PpsAttribute::Number:
+ case PpsAttribute::Bool:
+ case PpsAttribute::String:
+ // QVariant can compare double, int, longlong, bool, and QString for us.
+ return d->_data == other.d->_data;
+ case PpsAttribute::Array:
+ // QVariant can't compare custom types (like QList<PpsAttribute>), always returning false. So we pull
+ // the lists out manually and compare them.
+ return toList() == other.toList();
+ case PpsAttribute::Object:
+ // QVariant can't compare custom types (like QMap<QString, PpsAttribute>), always returning false. So
+ // we pull the maps out manually and compare them.
+ return toMap() == other.toMap();
+ case PpsAttribute::None:
+ // Both are "None" type, so the actual content doesn't matter.
+ return true;
+ }
+ return d->_data == other.d->_data;
+}
+
+bool PpsAttribute::operator!=(const PpsAttribute & other) const
+{
+ return !(*this == other);
+}
+
+bool PpsAttribute::isValid() const
+{
+ return d->_type != PpsAttribute::None;
+}
+
+PpsAttribute::Type PpsAttribute::type() const
+{
+ return d->_type;
+}
+
+bool PpsAttribute::isNumber() const
+{
+ return type() == PpsAttribute::Number;
+}
+
+bool PpsAttribute::isBool() const
+{
+ return type() == PpsAttribute::Bool;
+}
+
+bool PpsAttribute::isString() const
+{
+ return type() == PpsAttribute::String;
+}
+
+bool PpsAttribute::isArray() const
+{
+ return type() == PpsAttribute::Array;
+}
+
+bool PpsAttribute::isObject() const
+{
+ return type() == PpsAttribute::Object;
+}
+
+double PpsAttribute::toDouble() const
+{
+ return d->_data.toDouble();
+}
+
+qlonglong PpsAttribute::toLongLong() const
+{
+ return d->_data.toLongLong();
+}
+
+int PpsAttribute::toInt() const
+{
+ return d->_data.toInt();
+}
+
+bool PpsAttribute::toBool() const
+{
+ return d->_data.toBool();
+}
+
+QString PpsAttribute::toString() const
+{
+ return d->_data.toString();
+}
+
+QList<PpsAttribute> PpsAttribute::toList() const
+{
+ return d->_data.value< QList<PpsAttribute> >();
+}
+
+QMap<QString, PpsAttribute> PpsAttribute::toMap() const
+{
+ return d->_data.value< QMap<QString, PpsAttribute> >();
+}
+
+PpsAttributeFlag::Types PpsAttribute::flags() const
+{
+ return d->_flags;
+}
+
+QVariant PpsAttribute::toVariant() const
+{
+ return d->_data;
+}
+
+QDebug operator<<(QDebug dbg, const PpsAttribute &attribute)
+{
+ dbg << "PpsAttribute(";
+
+ switch ( attribute.type() ) {
+ case PpsAttribute::Number:
+ switch (attribute.toVariant().type()) {
+ case QVariant::Int:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toInt();
+ break;
+ case QVariant::LongLong:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toLongLong();
+ break;
+ default:
+ dbg << "Number, " << attribute.flags() << ", " << attribute.toDouble();
+ break;
+ }
+ break;
+ case PpsAttribute::Bool:
+ dbg << "Bool, " << attribute.flags() << ", " << attribute.toBool();
+ break;
+ case PpsAttribute::String:
+ dbg << "String, " << attribute.flags() << ", " << attribute.toString();
+ break;
+ case PpsAttribute::Array:
+ dbg << "Array, " << attribute.flags() << ", " << attribute.toList();
+ break;
+ case PpsAttribute::Object:
+ dbg << "Object, " << attribute.flags() << ", " << attribute.toMap();
+ break;
+ case PpsAttribute::None:
+ dbg << "None";
+ break;
+ }
+
+ dbg << ')';
+
+ return dbg;
+}
+
+} // namespace bb
diff --git a/src/plugins/position/blackberry/bb/ppsattribute_p.h b/src/plugins/position/blackberry/bb/ppsattribute_p.h
new file mode 100644
index 00000000..b3ffede1
--- /dev/null
+++ b/src/plugins/position/blackberry/bb/ppsattribute_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BB_CORE_PPSATTRIBUTEPRIVATE_HPP
+#define BB_CORE_PPSATTRIBUTEPRIVATE_HPP
+
+#include <bb/PpsAttribute>
+#include <bb/PpsAttributeFlag>
+
+#include <QList>
+#include <QMap>
+#include <QSharedData>
+#include <QString>
+#include <QVariant>
+
+namespace bb
+{
+
+class PpsAttributePrivate : public QSharedData
+{
+public:
+ PpsAttributePrivate();
+
+ static PpsAttribute ppsAttribute( double value, PpsAttributeFlag::Types flags );
+ static PpsAttribute ppsAttribute( long long value, PpsAttributeFlag::Types flags );
+ static PpsAttribute ppsAttribute( int value, PpsAttributeFlag::Types flags );
+ static PpsAttribute ppsAttribute( bool value, PpsAttributeFlag::Types flags );
+ static PpsAttribute ppsAttribute( const QString &value, PpsAttributeFlag::Types flags );
+ static PpsAttribute ppsAttribute( const QList<PpsAttribute> &value, PpsAttributeFlag::Types flags );
+ static PpsAttribute ppsAttribute( const QMap<QString, PpsAttribute> &value, PpsAttributeFlag::Types flags );
+
+private:
+ friend class PpsAttribute;
+
+ QVariant _data;
+ PpsAttribute::Type _type;
+ PpsAttributeFlag::Types _flags;
+};
+
+} // namespace bb
+
+#endif // BB_CORE_PPSOBJECTPRIVATE_HPP
diff --git a/src/plugins/position/blackberry/bb/ppsobject.cpp b/src/plugins/position/blackberry/bb/ppsobject.cpp
new file mode 100644
index 00000000..107a3a79
--- /dev/null
+++ b/src/plugins/position/blackberry/bb/ppsobject.cpp
@@ -0,0 +1,743 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Indicate which dependencies to mock when testing
+// NOTE: These defines must occur before including any headers and
+// ProxyInjector.hpp must be the first header included
+#define USE_QT_QSOCKETNOTIFIER_PROXY
+#define USE_UNISTD_PROXY
+#define USE_FCNTL_PROXY
+#define USE_ERRNO_PROXY
+#define USE_STRING_PROXY
+//#include <private/proxy/ProxyInjector.hpp>
+
+// Disable symbol renaming when testing for open, close, read, and
+// write as these dependency names conflict with member method names
+// and we don't want to rename the member methods. Instead, use dummy
+// names for the dependencies in the production code and toggle
+// between the real/proxy versions here.
+#ifdef BB_TEST_BUILD
+# undef open
+# undef close
+# undef read
+# undef write
+# define PosixOpen open_proxy
+# define PosixClose close_proxy
+# define PosixRead read_proxy
+# define PosixWrite write_proxy
+#else
+# define PosixOpen ::open
+# define PosixClose ::close
+# define PosixRead ::read
+# define PosixWrite ::write
+#endif
+
+#include "ppsobject.h"
+
+#include "ppsattribute_p.h"
+#include "safeassign.h"
+
+#include <bb/PpsAttribute>
+
+#include <QDebug>
+#include <QObject>
+#include <QSocketNotifier>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <exception>
+
+extern "C" {
+#include "sys/pps.h"
+}
+
+namespace bb
+{
+
+/**
+ * From "QNX Persistent Publish/Subscribe Developer's Guide":
+ *
+ * "the maximum size for a PPS object is 64 kilobytes"
+ */
+static const int PPS_MAX_SIZE = 64 * 1024;
+
+class PpsDecoder
+{
+public:
+ PpsDecoder(char *str)
+ {
+ throwOnPpsDecoderError( pps_decoder_initialize(&_decoder, str) );
+ }
+
+ ~PpsDecoder()
+ {
+ pps_decoder_cleanup(&_decoder);
+ }
+
+ QMap<QString, PpsAttribute> decode()
+ {
+ return decodeObject();
+ }
+
+ static QVariantMap variantMapFromPpsAttributeMap(const QMap<QString, PpsAttribute> &data)
+ {
+ QVariantMap variantMap;
+
+ for ( QMap<QString, PpsAttribute>::const_iterator it = data.begin(); it != data.end(); it++ ) {
+ variantMap[it.key()] = variantFromPpsAttribute( it.value() );
+ }
+
+ return variantMap;
+ }
+
+private:
+ pps_decoder_t _decoder;
+
+ static void throwOnPpsDecoderError(pps_decoder_error_t error)
+ {
+ switch ( error ) {
+ case PPS_DECODER_OK:
+ return;
+ default:
+ throw std::exception();
+ }
+ }
+
+ bb::PpsAttributeFlag::Types readFlags()
+ {
+ int rawFlags = pps_decoder_flags(&_decoder, NULL);
+
+ bb::PpsAttributeFlag::Types attributeFlags;
+
+ if ( rawFlags & PPS_INCOMPLETE ) {
+ attributeFlags |= bb::PpsAttributeFlag::Incomplete;
+ }
+ if ( rawFlags & PPS_DELETED ) {
+ attributeFlags |= bb::PpsAttributeFlag::Deleted;
+ }
+ if ( rawFlags & PPS_CREATED ) {
+ attributeFlags |= bb::PpsAttributeFlag::Created;
+ }
+ if ( rawFlags & PPS_TRUNCATED ) {
+ attributeFlags |= bb::PpsAttributeFlag::Truncated;
+ }
+ if ( rawFlags & PPS_PURGED ) {
+ attributeFlags |= bb::PpsAttributeFlag::Purged;
+ }
+
+ return attributeFlags;
+ }
+
+ bb::PpsAttribute decodeString()
+ {
+ const char * value = NULL;
+ throwOnPpsDecoderError( pps_decoder_get_string(&_decoder, NULL, &value) );
+ bb::PpsAttributeFlag::Types flags = readFlags();
+ return bb::PpsAttributePrivate::ppsAttribute( QString::fromUtf8(value), flags );
+ }
+
+ bb::PpsAttribute decodeNumber()
+ {
+ // In order to support more number types, we have to do something stupid because
+ // the PPS library won't let us work any other way
+ // Basically, we have to probe the encoded type in order to try to get exactly what
+ // we want
+ long long llValue;
+ double dValue;
+ int iValue;
+ bb::PpsAttributeFlag::Types flags;
+
+ if (pps_decoder_is_integer( &_decoder, NULL )) {
+ int result = pps_decoder_get_int(&_decoder, NULL, &iValue );
+ switch (result) {
+ case PPS_DECODER_OK:
+ flags = readFlags();
+ return bb::PpsAttributePrivate::ppsAttribute( iValue, flags );
+ case PPS_DECODER_CONVERSION_FAILED:
+ throwOnPpsDecoderError( pps_decoder_get_int64(&_decoder, NULL, &llValue) );
+ flags = readFlags();
+ return bb::PpsAttributePrivate::ppsAttribute( llValue, flags );
+ default:
+ throw std::exception();
+ }
+ } else {
+ throwOnPpsDecoderError( pps_decoder_get_double(&_decoder, NULL, &dValue));
+ flags = readFlags();
+ return bb::PpsAttributePrivate::ppsAttribute( dValue, flags );
+ }
+ }
+
+ bb::PpsAttribute decodeBool()
+ {
+ bool value;
+ throwOnPpsDecoderError( pps_decoder_get_bool(&_decoder, NULL, &value) );
+ bb::PpsAttributeFlag::Types flags = readFlags();
+ return bb::PpsAttributePrivate::ppsAttribute( value, flags );
+ }
+
+ bb::PpsAttribute decodeData()
+ {
+ pps_node_type_t nodeType = pps_decoder_type(&_decoder, NULL);
+ switch ( nodeType ) {
+ case PPS_TYPE_BOOL:
+ return decodeBool();
+ case PPS_TYPE_NUMBER:
+ return decodeNumber();
+ case PPS_TYPE_STRING:
+ return decodeString();
+ case PPS_TYPE_ARRAY: {
+ // We must read the flags before we push into the array, otherwise we'll get the flags for the first element in the array.
+ bb::PpsAttributeFlag::Types flags = readFlags();
+ throwOnPpsDecoderError( pps_decoder_push(&_decoder, NULL) );
+ bb::PpsAttribute returnVal = bb::PpsAttributePrivate::ppsAttribute( decodeArray(), flags );
+ throwOnPpsDecoderError( pps_decoder_pop(&_decoder) );
+ return returnVal;
+ }
+ case PPS_TYPE_OBJECT: {
+ // We must read the flags before we push into the object, otherwise we'll get the flags for the first alement in the object.
+ bb::PpsAttributeFlag::Types flags = readFlags();
+ throwOnPpsDecoderError( pps_decoder_push(&_decoder, NULL) );
+ bb::PpsAttribute returnVal = bb::PpsAttributePrivate::ppsAttribute( decodeObject(), flags );
+ throwOnPpsDecoderError( pps_decoder_pop(&_decoder) );
+ return returnVal;
+ }
+ case PPS_TYPE_NULL:
+ case PPS_TYPE_NONE:
+ case PPS_TYPE_UNKNOWN:
+ case PPS_TYPE_DELETED:
+ default:
+ return bb::PpsAttribute();
+ }
+ }
+
+ QList<bb::PpsAttribute> decodeArray()
+ {
+ QList<bb::PpsAttribute> list;
+
+ int length = pps_decoder_length( &_decoder );
+ for ( int i = 0; i < length; i += 1 ) {
+ // Force movement to a specific index.
+ throwOnPpsDecoderError( pps_decoder_goto_index(&_decoder, i) );
+ list << decodeData();
+ }
+
+ return list;
+ }
+
+ QMap<QString, bb::PpsAttribute> decodeObject()
+ {
+ QMap<QString, bb::PpsAttribute> map;
+
+ int length = pps_decoder_length(&_decoder);
+ for ( int i = 0; i < length; i += 1 ) {
+ // Force movement to a specific index.
+ throwOnPpsDecoderError( pps_decoder_goto_index(&_decoder, i) );
+ QString name = QString::fromUtf8( pps_decoder_name(&_decoder) );
+ map[name] = decodeData();
+ }
+
+ return map;
+ }
+
+ static QVariant variantFromPpsAttribute(const PpsAttribute &attribute)
+ {
+ switch ( attribute.type() ) {
+ case PpsAttribute::Number:
+ switch (attribute.toVariant().type()) {
+ case QVariant::Int:
+ return attribute.toInt();
+ break;
+ case QVariant::LongLong:
+ return attribute.toLongLong();
+ break;
+ default:
+ return attribute.toDouble();
+ break;
+ }
+ break;
+ case PpsAttribute::Bool:
+ return attribute.toBool();
+ break;
+ case PpsAttribute::String:
+ return attribute.toString();
+ break;
+ case PpsAttribute::Array: {
+ QVariantList variantList;
+ Q_FOREACH ( PpsAttribute attr, attribute.toList() ) {
+ variantList << variantFromPpsAttribute(attr);
+ }
+ return variantList;
+ }
+ case PpsAttribute::Object: {
+ return variantMapFromPpsAttributeMap( attribute.toMap() );
+ }
+ case PpsAttribute::None:
+ default:
+ return QVariant();
+ }
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class PpsEncoder
+{
+public:
+ PpsEncoder()
+ {
+ pps_encoder_initialize(&_encoder, false);
+ }
+
+ ~PpsEncoder()
+ {
+ pps_encoder_cleanup(&_encoder);
+ }
+
+ QByteArray encode(const QVariantMap &ppsData)
+ {
+ encodeObject(ppsData);
+ const char *rawData = pps_encoder_buffer(&_encoder);
+ if (!rawData) {
+ throw std::exception();
+ }
+ return QByteArray(rawData);
+ }
+
+private:
+ pps_encoder_t _encoder;
+
+ static void throwOnPpsEncoderError(pps_encoder_error_t error)
+ {
+ switch ( error ) {
+ case PPS_ENCODER_OK:
+ return;
+ default:
+ throw std::exception();
+ }
+ }
+
+ void encodeData(const char *name, QVariant data)
+ {
+ switch ( data.type() ) {
+ case QVariant::Bool:
+ throwOnPpsEncoderError( pps_encoder_add_bool(&_encoder, name, data.toBool()) );
+ break;
+ // We want to support encoding uint even though libpps doesn't support it directly. We can't encoding uint as an int
+ // since that will lose precision (e.g. 2^31+1 can't be encoded that way). However, we can convert uint to double
+ // without losing precision. QVariant.toDouble() conveniently takes care of the conversion for us.
+ case QVariant::UInt:
+ case QVariant::Double:
+ throwOnPpsEncoderError( pps_encoder_add_double(&_encoder, name, data.toDouble()) );
+ break;
+ case QVariant::Int:
+ throwOnPpsEncoderError( pps_encoder_add_int(&_encoder, name, data.toInt()) );
+ break;
+ case QVariant::LongLong:
+ throwOnPpsEncoderError( pps_encoder_add_int64(&_encoder, name, data.toLongLong()) );
+ break;
+ case QVariant::String:
+ throwOnPpsEncoderError( pps_encoder_add_string(&_encoder, name, data.toString().toUtf8().constData()) );
+ break;
+ case QVariant::List: {
+ throwOnPpsEncoderError( pps_encoder_start_array(&_encoder, name) );
+ encodeArray( data.toList() );
+ throwOnPpsEncoderError( pps_encoder_end_array(&_encoder) );
+ break;
+ }
+ case QVariant::Map: {
+ throwOnPpsEncoderError( pps_encoder_start_object(&_encoder, name) );
+ encodeObject( data.toMap() );
+ throwOnPpsEncoderError( pps_encoder_end_object(&_encoder) );
+ break;
+ }
+ case QVariant::Invalid: {
+ throwOnPpsEncoderError( pps_encoder_add_null(&_encoder, name) );
+ break;
+ }
+ default:
+ throw std::exception();
+ }
+ }
+
+ void encodeArray(QVariantList data)
+ {
+ for ( QVariantList::const_iterator it = data.constBegin(); it != data.constEnd(); it ++ ) {
+ encodeData( NULL, *it );
+ }
+ }
+
+ void encodeObject(QVariantMap data) {
+ for ( QVariantMap::const_iterator it = data.constBegin(); it != data.constEnd(); it ++ ) {
+ encodeData( it.key().toUtf8().constData(), it.value() );
+ }
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class PpsObjectPrivate
+{
+public:
+ QSocketNotifier *_notifier;
+ QString _path;
+ mutable int _error;
+ int _fd;
+ bool _readyReadEnabled;
+
+ explicit PpsObjectPrivate(const QString &path) :
+ _notifier(NULL),
+ _path(path),
+ _error(EOK),
+ _fd(-1),
+ _readyReadEnabled(true)
+ {
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+PpsObject::PpsObject(const QString &path, QObject *parent) :
+ QObject(parent),
+ d_ptr(new PpsObjectPrivate(path))
+{
+}
+
+PpsObject::~PpsObject()
+{
+ // RAII - ensure file gets closed
+ if (isOpen()) {
+ close();
+ }
+}
+
+int PpsObject::error() const
+{
+ Q_D(const PpsObject);
+ return d->_error;
+}
+
+QString PpsObject::errorString() const
+{
+ Q_D(const PpsObject);
+ return QString(strerror(d->_error));
+}
+
+bool PpsObject::isReadyReadEnabled() const
+{
+ Q_D(const PpsObject);
+
+ // query state of read ready signal
+ return d->_readyReadEnabled;
+}
+
+void PpsObject::setReadyReadEnabled(bool enable)
+{
+ Q_D(PpsObject);
+
+ // toggle whether socket notifier will emit a signal on read ready
+ d->_readyReadEnabled = enable;
+ if (isOpen()) {
+ d->_notifier->setEnabled(enable);
+ }
+}
+
+bool PpsObject::isBlocking() const
+{
+ Q_D(const PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->_error = EBADF;
+ return false;
+ }
+
+ // query file status flags
+ int flags = fcntl(d->_fd, F_GETFL);
+ if (flags != -1) {
+ // check if non-blocking flag is unset
+ return ((flags & O_NONBLOCK) != O_NONBLOCK);
+ } else {
+ d->_error = errno;
+ return false;
+ }
+}
+
+bool PpsObject::setBlocking(bool enable)
+{
+ Q_D(PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->_error = EBADF;
+ return false;
+ }
+
+ // query file status flags
+ int flags = fcntl(d->_fd, F_GETFL);
+ if (flags == -1) {
+ d->_error = errno;
+ return false;
+ }
+
+ // configure non-blocking flag
+ if (enable) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+
+ // update file status flags
+ flags = fcntl(d->_fd, F_SETFL, flags);
+ if (flags == -1) {
+ d->_error = errno;
+ return false;
+ }
+
+ return true;
+}
+
+bool PpsObject::isOpen() const
+{
+ Q_D(const PpsObject);
+ return (d->_fd != -1);
+}
+
+bool PpsObject::open(PpsOpenMode::Types mode)
+{
+ Q_D(PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // abort if file already open
+ if (isOpen()) {
+ d->_error = EBUSY;
+ return false;
+ }
+
+ // convert pps flags to open flags
+ int oflags = 0;
+ if ((mode & PpsOpenMode::Publish) && (mode & PpsOpenMode::Subscribe)) {
+ oflags |= O_RDWR;
+ } else if (mode & PpsOpenMode::Publish) {
+ oflags |= O_WRONLY;
+ } else if (mode & PpsOpenMode::Subscribe) {
+ oflags |= O_RDONLY;
+ }
+
+ if (mode & PpsOpenMode::Create) {
+ oflags |= O_CREAT | O_EXCL;
+ }
+
+ if (mode & PpsOpenMode::DeleteContents) {
+ oflags |= O_TRUNC;
+ }
+
+ // open pps file
+ d->_fd = PosixOpen(d->_path.toUtf8().data(), oflags, 0666);
+
+ // wire up socket notifier to know when reads are ready
+ if (d->_fd != -1) {
+ d->_notifier = new QSocketNotifier(d->_fd, QSocketNotifier::Read, this);
+ d->_notifier->setEnabled(d->_readyReadEnabled);
+ QObject::connect(d->_notifier, SIGNAL(activated(int)), this, SIGNAL(readyRead()));
+ return true;
+ } else {
+ d->_error = errno;
+ return false;
+ }
+}
+
+bool PpsObject::close()
+{
+ Q_D(PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->_error = EBADF;
+ return false;
+ }
+
+ // shutdown socket notifier
+ delete d->_notifier;
+ d->_notifier = NULL;
+
+ // close pps file
+ int result = PosixClose(d->_fd);
+ d->_fd = -1;
+
+ // check success of operation
+ if (result == 0) {
+ return true;
+ } else {
+ d->_error = errno;
+ return false;
+ }
+}
+
+QByteArray PpsObject::read(bool * ok)
+{
+ Q_D(PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->_error = EBADF;
+ safeAssign(ok, false);
+ return QByteArray();
+ }
+
+ QByteArray byteArray;
+ byteArray.resize(PPS_MAX_SIZE); // resize doesn't initialize the data
+ int result = PosixRead(d->_fd, byteArray.data(), byteArray.size());
+
+ // check result of read operation
+ if (result > 0) {
+ // resize byte array to amount actually read
+ byteArray.resize(result);
+ safeAssign(ok, true);
+ return byteArray;
+ } else if (result == 0) {
+ // normalize the behavior of read() when no data is ready so a pps object
+ // put in non-blocking mode via opening w/o ?wait (read returns 0) looks
+ // the same as a pps object put in non-blocking mode by setting O_NONBLOCK
+ // (read returns EAGAIN)
+ d->_error = EAGAIN;
+ safeAssign(ok, false);
+ return QByteArray(); // Specifically return a default-constructed QByteArray.
+ } else {
+ d->_error = errno;
+ qWarning() << "PpsObject::read failed to read pps data, error " << errorString();
+ safeAssign(ok, false);
+ return QByteArray(); // Specifically return a default-constructed QByteArray.
+ }
+}
+
+bool PpsObject::write(const QByteArray &byteArray)
+{
+ Q_D(PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // abort if file not open
+ if (!isOpen()) {
+ d->_error = EBADF;
+ return false;
+ }
+
+ // write entire byte array to pps file
+ int result = PosixWrite(d->_fd, byteArray.data(), byteArray.size());
+ if (result == -1) {
+ d->_error = errno;
+ }
+ return (result == byteArray.size());
+}
+
+bool PpsObject::remove()
+{
+ Q_D(PpsObject);
+
+ // reset last error
+ d->_error = EOK;
+
+ // delete pps file
+ int result = unlink(d->_path.toUtf8().data());
+
+ // check success of operation
+ if (result == 0) {
+ return true;
+ } else {
+ d->_error = errno;
+ return false;
+ }
+}
+
+QVariantMap PpsObject::decode(const QByteArray &rawData, bool *ok)
+{
+ QMap<QString, PpsAttribute> mapData = decodeWithFlags(rawData, ok);
+
+ // If *ok is false, then mapData is empty, so the resulting QVariantMap will also be empty, as desired.
+ return PpsDecoder::variantMapFromPpsAttributeMap(mapData);
+}
+
+QMap<QString, PpsAttribute> PpsObject::decodeWithFlags(const QByteArray &rawData, bool *ok)
+{
+ bb::safeAssign(ok, true);
+
+ try {
+ QByteArray mutableData(rawData);
+ PpsDecoder decoder(mutableData.data());
+ return decoder.decode();
+ } catch (...) {
+ bb::safeAssign(ok, false);
+ return QMap<QString, bb::PpsAttribute>();
+ }
+}
+
+QByteArray PpsObject::encode(const QVariantMap &ppsData, bool *ok)
+{
+ bb::safeAssign( ok, true );
+
+ try {
+ PpsEncoder encoder;
+ return encoder.encode(ppsData);
+ } catch (...) {
+ bb::safeAssign(ok, false);
+ return QByteArray();
+ }
+}
+
+} // namespace bb
diff --git a/src/plugins/position/blackberry/bb/ppsobject.h b/src/plugins/position/blackberry/bb/ppsobject.h
new file mode 100644
index 00000000..8468f40f
--- /dev/null
+++ b/src/plugins/position/blackberry/bb/ppsobject.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BB_CORE_PPSOBJECT_HPP
+#define BB_CORE_PPSOBJECT_HPP
+
+#include <bb/Global>
+#include <bb/PpsAttribute>
+#include <bb/PpsOpenMode>
+
+#include <QMap>
+#include <QObject>
+#include <QVariantMap>
+
+namespace bb
+{
+class PpsObjectPrivate;
+
+class BB_CORE_EXPORT PpsObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit PpsObject(const QString &path, QObject *parent = 0);
+ virtual ~PpsObject();
+
+ int error() const;
+ QString errorString() const;
+
+ bool isReadyReadEnabled() const;
+ bool isBlocking() const;
+ bool setBlocking(bool enable);
+ bool isOpen() const;
+ bool open(PpsOpenMode::Types mode = PpsOpenMode::PublishSubscribe);
+ bool close();
+ QByteArray read(bool * ok = 0);
+ bool write(const QByteArray &byteArray);
+ bool remove();
+
+ static QVariantMap decode( const QByteArray &rawData, bool * ok = 0 );
+ static QMap<QString, PpsAttribute> decodeWithFlags( const QByteArray &rawData, bool * ok = 0 );
+ static QByteArray encode( const QVariantMap &ppsData, bool * ok = 0 );
+
+public Q_SLOTS:
+ void setReadyReadEnabled(bool enable);
+
+Q_SIGNALS:
+ void readyRead();
+
+private:
+//!@cond PRIVATE
+ QScopedPointer<PpsObjectPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(PpsObject)
+ Q_DISABLE_COPY(PpsObject)
+//!@endcond PRIVATE
+};
+
+} // namespace bb
+
+#endif // BB_CORE_PPSOBJECT_HPP
diff --git a/src/plugins/position/blackberry/bb/safeassign.h b/src/plugins/position/blackberry/bb/safeassign.h
new file mode 100644
index 00000000..a5128581
--- /dev/null
+++ b/src/plugins/position/blackberry/bb/safeassign.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BB_CORE_SAFEASSIGN_HPP
+#define BB_CORE_SAFEASSIGN_HPP
+
+namespace bb
+{
+ template <typename T>
+ void safeAssign( T * pointer, const T & value )
+ {
+ if ( pointer ) {
+ *pointer = value;
+ }
+ }
+} // namespace bb
+
+#endif // HEADER GUARD
+
diff --git a/src/plugins/position/blackberry/blackberry.pro b/src/plugins/position/blackberry/blackberry.pro
new file mode 100644
index 00000000..e3543107
--- /dev/null
+++ b/src/plugins/position/blackberry/blackberry.pro
@@ -0,0 +1,27 @@
+TARGET = qtposition_blackberry
+QT = core positioning
+
+PLUGIN_TYPE = position
+load(qt_plugin)
+
+INCLUDEPATH += $$QT.location.includes
+
+LIBS = -lwmm -llocation_manager -lpps
+
+SOURCES += qgeopositioninfosource_bb.cpp \
+ qgeosatelliteinfosource_bb.cpp \
+ locationmanagerutil_bb.cpp \
+ qgeopositioninfosourcefactory_bb.cpp
+SOURCES += bb/ppsobject.cpp \
+ bb/ppsattribute.cpp
+HEADERS += qgeopositioninfosource_bb_p.h \
+ qgeopositioninfosource_bb.h \
+ qgeosatelliteinfosource_bb_p.h \
+ qgeosatelliteinfosource_bb.h \
+ locationmanagerutil_bb.h \
+ qgeopositioninfosourcefactory_bb.h
+HEADERS += bb/ppsobject.h \
+ bb/ppsattribute_p.h
+
+OTHER_FILES += \
+ plugin.json
diff --git a/src/plugins/position/blackberry/locationmanagerutil_bb.cpp b/src/plugins/position/blackberry/locationmanagerutil_bb.cpp
new file mode 100644
index 00000000..f9541724
--- /dev/null
+++ b/src/plugins/position/blackberry/locationmanagerutil_bb.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "locationmanagerutil_bb.h"
+
+#include <bb/PpsObject>
+
+#include <QtCore/QVariantMap>
+#include <QtCore/QByteArray>
+#include <QtDebug>
+
+#include <errno.h>
+
+namespace {
+
+// Create a QVariantMap suitable for writing to a PpsObject specifying a cancel request to the
+// Location Manager.
+QVariantMap createCancelRequest()
+{
+ QVariantMap map;
+
+ map.insert("msg", "cancel");
+ map.insert("id", ::global::libQtLocationId);
+
+ return map;
+}
+
+} // unnamed namespace
+
+namespace global {
+
+const QString libQtLocationId = "libQtLocation";
+const QString locationManagerPpsFile = "/pps/services/geolocation/control";
+const int minUpdateInterval = 1000;
+const QVariantMap cancelRequest = createCancelRequest();
+
+} // namespace global
+
+
+// send a generic server-mode request, wrapped in a @control map, to ppsObject
+bool sendRequest(bb::PpsObject &ppsObject, const QVariantMap &request)
+{
+ if (!ppsObject.isOpen()) {
+ if (!ppsObject.open()) {
+ qWarning() << "LocationManagerUtil.cpp:sendRequest(): error opening pps object, errno ="
+ << ppsObject.error() << "("
+ << strerror(ppsObject.error())
+ << "). Clients should verify that they have access_location_services "
+ "permission.";
+ return false;
+ }
+ }
+
+ // wrap the request in a @control map
+ QVariantMap map;
+ map.insert("@control", request);
+
+
+ // encode it
+ bool ok;
+ QByteArray encodedRequest = bb::PpsObject::encode(map, &ok);
+ if (!ok) {
+ qWarning() << "LocationManagerUtil.cpp:sendRequest(): error encoding position request";
+ ppsObject.close();
+ return false;
+ }
+
+ // write it
+ bool success = ppsObject.write(encodedRequest);
+ if (!success) {
+ qWarning() << "LocationManagerUtil.cpp:sendRequest(): error"
+ << ppsObject.error()
+ << "writing position request";
+ ppsObject.close();
+ return false;
+ }
+
+ return true;
+}
+
+// receive a generic server-mode reply from ppsObject, removing the @control map container
+bool receiveReply(QVariantMap *reply, bb::PpsObject &ppsObject)
+{
+ if (!ppsObject.isOpen()) {
+ if (!ppsObject.open()) {
+ qWarning() << "LocationManagerUtil.cpp:receiveReply(): error opening pps object";
+ return false;
+ }
+ }
+
+ // read the reply
+ bool ok;
+ QByteArray encodedReply = ppsObject.read(&ok);
+ if (!ok) {
+ qWarning() << "LocationManagerUtil.cpp:receiveReply(): error"
+ << ppsObject.error()
+ << "reading position reply";
+ ppsObject.close();
+ return false;
+ }
+
+ // decode the reply
+ *reply = bb::PpsObject::decode(encodedReply, &ok);
+ if (!ok) {
+ qWarning() << "LocationManagerUtil.cpp:receiveReply(): error decoding position reply";
+ ppsObject.close();
+ return false;
+ }
+
+ // peel out the control map from the reply
+ *reply = reply->value("@control").toMap();
+
+ // check for an error in the reply
+ if (reply->contains("errCode")) {
+ int errCode = reply->value("errCode").toInt();
+ if (errCode) {
+ qWarning() << "LocationManagerUtil.cpp:receiveReply(): (" << errCode << ")" <<
+ reply->value("err").toString().toLocal8Bit().constData() << ":" <<
+ reply->value("errstr").toString().toLocal8Bit().constData();
+ return false;
+ }
+ }
+
+ return true;
+}
+
diff --git a/src/plugins/position/blackberry/locationmanagerutil_bb.h b/src/plugins/position/blackberry/locationmanagerutil_bb.h
new file mode 100644
index 00000000..59d9cd52
--- /dev/null
+++ b/src/plugins/position/blackberry/locationmanagerutil_bb.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LOCATIONMANAGERUTIL_BB_H
+#define LOCATIONMANAGERUTIL_BB_H
+
+#include <QtCore/QVariantMap>
+
+namespace bb
+{
+class PpsObject;
+}
+
+namespace global {
+
+// the libQtLocation id for the server-mode accessed pps file id field
+extern const QString libQtLocationId;
+
+// the path to the location manager pps file that is the gateway for positioning requests/replies
+extern const QString locationManagerPpsFile;
+
+// the minimum interval (in msec) that positional and satellite updates can be provided for
+extern const int minUpdateInterval;
+
+// a QVariantMap suitable for writing to a PpsObject specifying a cancel request to the Location
+// Manager. This cancels the current request
+extern const QVariantMap cancelRequest;
+
+} // namespace global
+
+// send a generic server-mode request, wrapped in a @control map, to ppsObject
+bool sendRequest(bb::PpsObject &ppsObject, const QVariantMap &request);
+
+// receive a generic server-mode reply from ppsObject, removing the @control map container
+bool receiveReply(QVariantMap *reply, bb::PpsObject &ppsObject);
+
+#endif
diff --git a/src/plugins/position/blackberry/plugin.json b/src/plugins/position/blackberry/plugin.json
new file mode 100644
index 00000000..dca8e6a4
--- /dev/null
+++ b/src/plugins/position/blackberry/plugin.json
@@ -0,0 +1,8 @@
+{
+ "Keys": ["blackberry"],
+ "Provider": "blackberry",
+ "Position": true,
+ "Satellite": true,
+ "Monitor": false,
+ "Priority": 1000
+}
diff --git a/src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp b/src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp
new file mode 100644
index 00000000..80e215e0
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp
@@ -0,0 +1,1276 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeopositioninfosource_bb_p.h"
+#include "locationmanagerutil_bb.h"
+
+#ifndef BB_TEST_BUILD
+# include <bb/PpsObject>
+#else
+# include "../tests/include/PpsObjectStuntDouble.hpp"
+#endif
+
+extern "C" {
+#include <wmm/wmm.h>
+}
+
+#include <location_manager.h>
+
+#include <QMap>
+#include <QVariantMap>
+#include <QByteArray>
+#include <QtDebug>
+#include <QStringList>
+
+#include <errno.h>
+
+///////////////////////////
+//
+// local variables/functions
+//
+///////////////////////////
+
+namespace global
+{
+
+// Currently the default behavior for Location Manager is simply to set a constant default
+// interval. 5 sec has been chosen as a compromise between timely updates and conserving power.
+static const int defaultPositionUpdatePeriod = 5;
+
+} // namespace global
+
+namespace
+{
+
+// map the Location Manager reply error codes to the PositionErrorCode enum values.
+QMap<int, bb::location::PositionErrorCode::Type> createIntToPositionErrorCodeMap()
+{
+ QMap<int, bb::location::PositionErrorCode::Type> map;
+
+ map.insert(0, bb::location::PositionErrorCode::None);
+ map.insert(1, bb::location::PositionErrorCode::FatalDisabled);
+ map.insert(2, bb::location::PositionErrorCode::FatalNoLastKnownPosition);
+ map.insert(3, bb::location::PositionErrorCode::FatalInsufficientProviders);
+ map.insert(4, bb::location::PositionErrorCode::FatalInvalidRequest);
+ map.insert(5, bb::location::PositionErrorCode::FatalUnknown);
+ map.insert(6, bb::location::PositionErrorCode::FatalPermission);
+ map.insert(0x10000, bb::location::PositionErrorCode::WarnTimeout);
+ map.insert(0x10001, bb::location::PositionErrorCode::WarnLostTracking);
+ map.insert(0x10002, bb::location::PositionErrorCode::WarnStationary);
+
+ return map;
+}
+
+const QMap<int, bb::location::PositionErrorCode::Type> intToPositionErrorCodeMap =
+ createIntToPositionErrorCodeMap();
+
+bool fatalError(bb::location::PositionErrorCode::Type code)
+{
+ if ( code == bb::location::PositionErrorCode::FatalDisabled
+ || code == bb::location::PositionErrorCode::FatalNoLastKnownPosition
+ || code == bb::location::PositionErrorCode::FatalInsufficientProviders
+ || code == bb::location::PositionErrorCode::FatalInvalidRequest
+ || code == bb::location::PositionErrorCode::FatalUnknown
+ || code == bb::location::PositionErrorCode::FatalPermission ) {
+ return true;
+ }
+ return false;
+}
+
+// map the PositionErrorCode enum values to the Qt5 QGeoPositionInfoSource::Error enum values.
+QMap<bb::location::PositionErrorCode::Type, QGeoPositionInfoSource::Error>
+ createPositionErrorCodeToErrorMap()
+{
+ QMap<bb::location::PositionErrorCode::Type, QGeoPositionInfoSource::Error> map;
+
+ map.insert(bb::location::PositionErrorCode::FatalDisabled,
+ QGeoPositionInfoSource::ClosedError);
+ map.insert(bb::location::PositionErrorCode::FatalNoLastKnownPosition,
+ QGeoPositionInfoSource::UnknownSourceError);
+ map.insert(bb::location::PositionErrorCode::FatalInsufficientProviders,
+ QGeoPositionInfoSource::UnknownSourceError);
+ map.insert(bb::location::PositionErrorCode::FatalInvalidRequest,
+ QGeoPositionInfoSource::UnknownSourceError);
+ map.insert(bb::location::PositionErrorCode::FatalUnknown,
+ QGeoPositionInfoSource::UnknownSourceError);
+ map.insert(bb::location::PositionErrorCode::FatalPermission,
+ QGeoPositionInfoSource::AccessError);
+
+ return map;
+}
+
+const QMap<bb::location::PositionErrorCode::Type, QGeoPositionInfoSource::Error>
+ positionErrorCodeToErrorMap = createPositionErrorCodeToErrorMap();
+
+// map the Location Manager provider names to the QGeoPositionInfoSource positioning methods
+QMap<QGeoPositionInfoSource::PositioningMethods, QString> createPositioningMethodsToProviderMap()
+{
+ QMap<QGeoPositionInfoSource::PositioningMethods, QString> map;
+
+ map.insert(QGeoPositionInfoSource::SatellitePositioningMethods, QString("gnss"));
+ map.insert(QGeoPositionInfoSource::NonSatellitePositioningMethods, QString("network"));
+ map.insert(QGeoPositionInfoSource::AllPositioningMethods, QString("hybrid"));
+
+ return map;
+}
+
+const QMap<QGeoPositionInfoSource::PositioningMethods, QString>
+ positioningMethodsToProviderMap = createPositioningMethodsToProviderMap();
+
+// list of valid strings for the Location Manager reset types
+QStringList createValidResetTypesList()
+{
+ QStringList list;
+ list.append("cold");
+ list.append("warm");
+ list.append("hot");
+ list.append("factory");
+ list.append("ee_data");
+ list.append("almanac");
+ list.append("ephemeris");
+
+ return list;
+}
+
+const QStringList validResetTypes = createValidResetTypesList();
+
+void printGetGeomagneticFieldInputs(const wmm_location_t &location, const struct tm &date)
+{
+ qWarning() << "location = ("
+ << location.latitude_deg
+ << ","
+ << location.longitude_deg
+ << ","
+ << location.altitude_meters
+ << ")";
+ qWarning() << "date = (" << date.tm_sec <<
+ "," << date.tm_min <<
+ "," << date.tm_hour <<
+ "," << date.tm_mday <<
+ "," << date.tm_mon <<
+ "," << date.tm_year <<
+ "," << date.tm_wday <<
+ "," << date.tm_yday <<
+ "," << date.tm_isdst <<
+#ifndef BB_TEST_BUILD
+// the following fields are not present on host (at least Win32)
+ "," << date.tm_gmtoff <<
+ "," << date.tm_zone <<
+#endif
+ ")";
+}
+
+bool magneticDeclination(double *declination, const QGeoPositionInfo &position)
+{
+ if (!declination)
+ return false;
+
+ wmm_location_t location;
+ struct tm date;
+ wmm_geomagnetic_field_t field;
+
+ location.latitude_deg = position.coordinate().latitude();
+ location.longitude_deg = position.coordinate().longitude();
+ if (position.coordinate().type() == QGeoCoordinate::Coordinate3D)
+ location.altitude_meters = position.coordinate().altitude();
+ else
+ location.altitude_meters = 0.0;
+
+ time_t time = (time_t)position.timestamp().toTime_t();
+#ifdef BB_TEST_BUILD
+ // since gmtime_r() is not defined on host (at least Win32) risk reentrant side effects on the
+ // returned data.
+ struct tm *pDate = gmtime(&time);
+ if (pDate == NULL) {
+ qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): "
+ "gmtime() returned NULL";
+ return false;
+ }
+ date = *pDate;
+#else
+ if (gmtime_r(&time, &date) == NULL) {
+ qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): "
+ "gmtime_r() returned NULL";
+ return false;
+ }
+#endif
+
+ switch (wmm_get_geomagnetic_field(&location, &date, &field)) {
+ case 0:
+ break;
+
+ case 1:
+ qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): "
+ "wmm_get_geomagnetic_field() returned: inputs limited to model range";
+ printGetGeomagneticFieldInputs(location, date);
+ break;
+
+ case -1:
+ default:
+ qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): "
+ "wmm_get_geomagnetic_field() returned: error";
+ printGetGeomagneticFieldInputs(location, date);
+ return false;
+ }
+
+ *declination = field.declination_deg;
+ return true;
+}
+
+QVariantMap populateLastKnownPositionRequest(bool fromSatellitePositioningMethodsOnly)
+{
+ QVariantMap map;
+ QVariantMap datMap;
+
+ if (fromSatellitePositioningMethodsOnly)
+ datMap.insert("provider", "gnss");
+ else
+ datMap.insert("provider", "hybrid");
+
+ datMap.insert("last_known", true);
+ datMap.insert("period", 0);
+
+ map.insert("msg", "location");
+ map.insert("id", ::global::libQtLocationId);
+ map.insert("dat", datMap);
+
+ return map;
+}
+
+// From a QvariantMap representing a location response from the Location Manager fill a
+// QGeoPositionInfo instance intended to be emitted via positionUpdated() signal. Returns true
+// if the position info was successfully populated.
+bool populatePositionInfo(QGeoPositionInfo *position, const QVariantMap &map)
+{
+ // populate position
+
+ // set the reply dat property, which can be accessed by the user in the slot connected to
+ //the positionUpdated() signal
+ QVariantMap replyDat = map.value("dat").toMap();
+
+ // check for required fields
+ if (!replyDat.contains("latitude") || !replyDat.contains("longitude")
+ || !replyDat.contains("accuracy")) {
+ return false;
+ }
+
+ // set the lat/long/alt coordinate
+ QGeoCoordinate coord;
+ coord.setLatitude(replyDat.value("latitude").toDouble());
+ coord.setLongitude(replyDat.value("longitude").toDouble());
+ if (replyDat.contains("altitude"))
+ coord.setAltitude(replyDat.value("altitude").toDouble());
+
+ if (!coord.isValid())
+ return false;
+
+ position->setCoordinate(coord);
+
+ // set the time stamp
+ QDateTime dateTime;
+ dateTime.setTimeSpec(Qt::UTC);
+ if (replyDat.contains("utc") && static_cast<int>(replyDat.value("utc").toDouble()) != 0) {
+ // utc is msec since epoch (1970-01-01T00:00:00)
+ dateTime.setTime_t(qRound((replyDat.value("utc").toDouble() / 1000.0)));
+ } else {
+ // this relies on the device's clock being accurate
+ dateTime = QDateTime::currentDateTimeUtc();
+ }
+ position->setTimestamp(dateTime);
+
+ // attributes
+ if (replyDat.contains("heading")) {
+ position->setAttribute(QGeoPositionInfo::Direction,
+ static_cast<qreal>(replyDat.value("heading").toDouble()));
+ } else {
+ position->removeAttribute(QGeoPositionInfo::Direction);
+ }
+
+ if (replyDat.contains("speed")) {
+ position->setAttribute(QGeoPositionInfo::GroundSpeed,
+ static_cast<qreal>(replyDat.value("speed").toDouble()));
+ } else {
+ position->removeAttribute(QGeoPositionInfo::GroundSpeed);
+ }
+
+ if (replyDat.contains("verticalSpeed")) {
+ position->setAttribute(QGeoPositionInfo::VerticalSpeed,
+ static_cast<qreal>(replyDat.value("verticalSpeed").toDouble()));
+ } else {
+ position->removeAttribute(QGeoPositionInfo::VerticalSpeed);
+ }
+
+ if (replyDat.contains("declination")) {
+ position->setAttribute(QGeoPositionInfo::MagneticVariation,
+ static_cast<qreal>(replyDat.value("declination").toDouble()));
+ } else {
+ double declination;
+
+ if (magneticDeclination(&declination, *position) == true) {
+ position->setAttribute(QGeoPositionInfo::MagneticVariation,
+ static_cast<qreal>(declination));
+ } else {
+ position->removeAttribute(QGeoPositionInfo::MagneticVariation);
+ }
+ }
+
+ // replyDat.contains("accuracy") was confirmed above
+ position->setAttribute(QGeoPositionInfo::HorizontalAccuracy,
+ static_cast<qreal>(replyDat.value("accuracy").toDouble()));
+
+ if (replyDat.contains("altitudeAccuracy")) {
+ position->setAttribute(QGeoPositionInfo::VerticalAccuracy,
+ static_cast<qreal>(replyDat.value("altitudeAccuracy").toDouble()));
+ } else {
+ position->removeAttribute(QGeoPositionInfo::VerticalAccuracy);
+ }
+
+ return true;
+}
+
+} // unnamed namespace
+
+///////////////////////////
+//
+// QGeoPositionInfoSourceBbPrivate
+//
+///////////////////////////
+
+// Create a QVariantMap suitable for writing to a PpsObject specifying a location request to the
+// Location Manager. If the request is periodic then the update interval is used. Otherwise 0
+// indicates to the Location Manager that it is a request for a single, immediate location response.
+// singleRequestMsec applies only to the single, immediate location response. It represents the
+// expected location response time, after which it is assumed a timeout response occurs.
+QVariantMap QGeoPositionInfoSourceBbPrivate::populateLocationRequest(bool periodic,
+ int singleRequestMsec) const
+{
+ Q_Q(const QGeoPositionInfoSourceBb);
+
+ QVariantMap map;
+ QVariantMap datMap;
+
+ int period;
+ int responseTime;
+ if (periodic) {
+ // rounding is performed here because the Location Manager truncates to nearest integer
+ period = (q->updateInterval() + 500) / 1000;
+ // The Qt MObility API treats a period of 0 as indicating default behavior
+ if (period == 0) {
+ // specify global::defaultPositionUpdatePeriod as the default behavior for Location
+ // Manager
+ period = ::global::defaultPositionUpdatePeriod;
+ }
+ responseTime = qRound(_responseTime);
+ } else {
+ period = 0;
+ responseTime = (singleRequestMsec + 500) / 1000;
+ }
+
+ // period is the only mandatory field
+ datMap.insert("period", period);
+
+ if (_accuracy > 0.0)
+ datMap.insert("accuracy", _accuracy);
+ if (responseTime > 0.0)
+ datMap.insert("response_time", responseTime);
+
+ // since there is no uninitialized state for bool always specify the background mode
+ datMap.insert("background", _canRunInBackground);
+
+ QString provider = positioningMethodsToProviderMap.value(q->preferredPositioningMethods());
+ if (!provider.isEmpty())
+ datMap.insert("provider", provider);
+
+ if (!_fixType.isEmpty())
+ datMap.insert("fix_type", _fixType);
+
+ if (!_appId.isEmpty())
+ datMap.insert("app_id", _appId);
+
+ if (!_appPassword.isEmpty())
+ datMap.insert("app_password", _appPassword);
+
+ if (!_pdeUrl.isEmpty())
+ datMap.insert("pde_url", _pdeUrl.toEncoded().constData());
+
+ if (!_slpUrl.isEmpty())
+ datMap.insert("slp_url", _slpUrl.toEncoded().constData());
+
+ map.insert("msg", "location");
+ map.insert("id", global::libQtLocationId);
+ map.insert("dat", datMap);
+
+ return map;
+}
+
+QVariantMap QGeoPositionInfoSourceBbPrivate::populateResetRequest() const
+{
+ QVariantMap map;
+ QVariantMap datMap;
+
+ datMap.insert("reset_type", _resetType);
+
+ map.insert("msg", "reset");
+ map.insert("id", ::global::libQtLocationId);
+ map.insert("dat", datMap);
+
+ return map;
+}
+
+bool QGeoPositionInfoSourceBbPrivate::requestPositionInfo(bool periodic, int singleRequestMsec)
+{
+ // build up the request
+ QVariantMap request = populateLocationRequest(periodic, singleRequestMsec);
+
+ bb::PpsObject *ppsObject;
+ if (periodic)
+ ppsObject = _periodicUpdatePpsObject;
+ else
+ ppsObject = _singleUpdatePpsObject;
+
+ bool returnVal = sendRequest(*ppsObject, request);
+#ifndef BB_TEST_BUILD
+ if (!returnVal) {
+ // test for pps file error
+ switch (ppsObject->error()) {
+ case EACCES:
+ _replyErrorCode = bb::location::PositionErrorCode::FatalPermission;
+ _replyErr = "failed";
+ _replyErrStr = ppsObject->errorString();
+ break;
+
+ case EOK:
+ _replyErrorCode = bb::location::PositionErrorCode::FatalUnknown;
+ _replyErr = "failed";
+ _replyErrStr = "Unknown error occurred sending request";
+ qWarning() << "QGeoPositionInfoSourceBbPrivate::requestPositionInfo() :"
+ << _replyErrStr;
+ break;
+
+ default:
+ _replyErrorCode = bb::location::PositionErrorCode::FatalUnknown;
+ _replyErr = "failed";
+ _replyErrStr = ppsObject->errorString();
+ qWarning() << "QGeoPositionInfoSourceBbPrivate::requestPositionInfo() : "
+ "unexpected error, errno ="
+ << ppsObject->error()
+ << " ("
+ << ppsObject->errorString()
+ << ")";
+ break;
+ }
+ }
+#endif // !BB_TEST_BUILD
+
+ return returnVal;
+}
+
+void QGeoPositionInfoSourceBbPrivate::cancelPositionInfo(bool periodic)
+{
+ bb::PpsObject *ppsObject;
+ if (periodic)
+ ppsObject = _periodicUpdatePpsObject;
+ else
+ ppsObject = _singleUpdatePpsObject;
+
+ (void)sendRequest(*ppsObject, global::cancelRequest);
+}
+
+void QGeoPositionInfoSourceBbPrivate::resetLocationProviders()
+{
+ QVariantMap map = populateResetRequest();
+ (void)sendRequest(*_periodicUpdatePpsObject, map);
+}
+
+// Get the last known position from the Location Manager. Any error results in the return of an
+// invalid position.
+QGeoPositionInfo QGeoPositionInfoSourceBbPrivate::lastKnownPosition(
+ bool fromSatellitePositioningMethodsOnly) const
+{
+ QGeoPositionInfo position = QGeoPositionInfo();
+ bb::PpsObject ppsObject(global::locationManagerPpsFile);
+ QVariantMap lastKnown = populateLastKnownPositionRequest(fromSatellitePositioningMethodsOnly);
+
+ if (!ppsObject.open())
+ return position;
+
+ // Location Manager promises to reply immediately with the last known position or an error.
+ ppsObject.setBlocking(true);
+
+ if (!sendRequest(ppsObject, lastKnown))
+ return position;
+
+ if (!receiveReply(&lastKnown, ppsObject))
+ return position;
+
+ if (!lastKnown.contains("res") || lastKnown.value("res").toString() != "location")
+ return position;
+
+ // the return value of populatePositionInfo() is ignored since either way position is returned
+ // by lastKnownPosition()
+ (void)populatePositionInfo(&position, lastKnown);
+
+ return position;
+}
+
+// Constructor. Note there are two PpsObjects for handling the two different types of requests that
+// can be simultaneously made and which must be handled independently (apart from both being
+// emitted through the same signal when done-part of Qt Mobility spec.
+QGeoPositionInfoSourceBbPrivate::QGeoPositionInfoSourceBbPrivate(QGeoPositionInfoSourceBb *parent)
+ : QObject(parent),
+ _startUpdatesInvoked(false),
+ _requestUpdateInvoked(false),
+ _canEmitPeriodicUpdatesTimeout(true),
+ q_ptr(parent),
+ _periodicUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)),
+ _singleUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)),
+ _sourceError(QGeoPositionInfoSource::NoError),
+ _accuracy(0.0),
+ _responseTime(0.0),
+ _canRunInBackground(false),
+ _fixType(QString()),
+ _appId(QString()),
+ _appPassword(QString()),
+ _pdeUrl(QUrl()),
+ _slpUrl(QUrl()),
+ _replyDat(QVariantMap()),
+ _replyErrorCode(bb::location::PositionErrorCode::None),
+ _replyErr(QString()),
+ _replyErrStr(QString()),
+ _resetType(QString())
+{
+ // register bb::location::PositionErrorCode::Type so it can be used with QObject::property()
+ qRegisterMetaType<bb::location::PositionErrorCode::Type>();
+
+ // connect to periodic update PpsObject::readyRead()
+ connect(_periodicUpdatePpsObject, SIGNAL(readyRead()), SLOT(receivePeriodicPositionReply()));
+
+ // connect to single update PpsObject::readyRead()
+ connect(_singleUpdatePpsObject, SIGNAL(readyRead()), SLOT(receiveSinglePositionReply()));
+
+ // queued connection to signal updateTimeout()
+ connect(this, SIGNAL(queuedUpdateTimeout()), SLOT(emitUpdateTimeout()), Qt::QueuedConnection);
+}
+
+QGeoPositionInfoSourceBbPrivate::~QGeoPositionInfoSourceBbPrivate()
+{
+ stopUpdates();
+}
+
+// request periodic updates
+void QGeoPositionInfoSourceBbPrivate::startUpdates()
+{
+ // do nothing if periodic updates have already been started
+ if (_startUpdatesInvoked)
+ return;
+
+ // This flag is used to limit emitting the timeout signal to once per each interruption in the
+ // periodic updates. Since updates are being started here ensure the flag is set to true.
+ _canEmitPeriodicUpdatesTimeout = true;
+
+ // build a request and initiate it
+ if (requestPositionInfo(true)) {
+ _startUpdatesInvoked = true;
+ _currentPosition = QGeoPositionInfo();
+ } else {
+ // With Qt5 the error() signal was introduced. If there are any receivers emit error() else
+ // maintain QtMobility behavior.
+ _sourceError
+ = positionErrorCodeToErrorMap.value(_replyErrorCode,
+ QGeoPositionInfoSource::UnknownSourceError);
+ Q_Q(QGeoPositionInfoSourceBb);
+ if (q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) {
+ Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError);
+ } else {
+ // user is expecting a signal to be emitted, cannot emit positionUpdated() because of
+ // error so emit timeout signal. The connection is queued because it is possible for the
+ // user to call startUpdates() from within the slot handling the timeout. The queued
+ // connection avoids potential infinite recursion.
+ Q_EMIT queuedUpdateTimeout();
+ }
+ }
+}
+
+// stop periodic updates
+void QGeoPositionInfoSourceBbPrivate::stopUpdates()
+{
+ // do nothing if periodic updates have not been started
+ if (!_startUpdatesInvoked)
+ return;
+
+ cancelPositionInfo(true);
+ _startUpdatesInvoked = false;
+ _currentPosition = QGeoPositionInfo();
+
+ // close the pps file to ensure readyRead() does not spin in the event that we don't read the
+ // reply to the cancel request. Note that open() is done lazily in sendRequest().
+ _periodicUpdatePpsObject->close();
+}
+
+// periodic updates have timed out
+void QGeoPositionInfoSourceBbPrivate::periodicUpdatesTimeout()
+{
+ // do nothing if periodic updates have not been started
+ if (!_startUpdatesInvoked)
+ return;
+
+ // timeout has occurred, but periodic updates are still active. Ensure the timeout signal is
+ // emitted only once per interruption of updates. _canEmitPeriodicUpdatesTimeout is set back
+ // to true when the next successful periodic update occurs (see emitPositionUpdated()). This
+ // behavior is per the Qt Mobility Location API documentation.
+ if (_canEmitPeriodicUpdatesTimeout) {
+ _canEmitPeriodicUpdatesTimeout = false;
+ emitUpdateTimeout();
+ }
+}
+
+// request single update
+void QGeoPositionInfoSourceBbPrivate::requestUpdate(int msec)
+{
+ // do nothing if an immediate update has already been requested
+ if (_requestUpdateInvoked)
+ return;
+
+ if (msec) {
+ // If it is not possible to update in msec timeout immediately.
+ Q_Q(QGeoPositionInfoSourceBb);
+ if (msec < q->minimumUpdateInterval()) {
+ // The connection is queued because it is possible for the user to call requestUpdate()
+ // from within the slot handling the timeout. The queued connection avoids potential
+ // infinite recursion.
+ Q_EMIT queuedUpdateTimeout();
+ return;
+ }
+ }
+
+ if (requestPositionInfo(false, msec)) {
+ _requestUpdateInvoked = true;
+ } else {
+ // With Qt5 the error() signal was introduced. If there are any receivers emit error() else
+ // maintain QtMobility behavior.
+ _sourceError
+ = positionErrorCodeToErrorMap.value(_replyErrorCode,
+ QGeoPositionInfoSource::UnknownSourceError);
+ Q_Q(QGeoPositionInfoSourceBb);
+ if (q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) {
+ Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError);
+ } else {
+ // user is expecting a signal to be emitted, cannot emit positionUpdated() because of
+ // error so emit timeout signal. The connection is queued because it is possible for the
+ // user to call startUpdates() from within the slot handling the timeout. The queued
+ // connection avoids potential infinite recursion.
+ Q_EMIT queuedUpdateTimeout();
+ }
+ }
+}
+
+// single update has timed out. This is a slot for the requestUpdate timer
+void QGeoPositionInfoSourceBbPrivate::singleUpdateTimeout()
+{
+ _requestUpdateInvoked = false;
+
+ emitUpdateTimeout();
+
+ if (!_requestUpdateInvoked) {
+ // close the pps file to ensure readyRead() does not spin in the event that there are
+ // unexpected replies that we don't read. Note that open() is done lazily in sendRequest().
+ _singleUpdatePpsObject->close();
+ }
+}
+
+// This slot is intended for queued connection to the signal queuedUpdateTimeout(). If an error
+// occurs when an update is requested the error is relayed via updateTimeout() but the connection
+// is queued to avoid potential infinite recursion.
+void QGeoPositionInfoSourceBbPrivate::emitUpdateTimeout()
+{
+ Q_Q(QGeoPositionInfoSourceBb);
+ Q_EMIT q->updateTimeout();
+}
+
+void QGeoPositionInfoSourceBbPrivate::emitPositionUpdated(const QGeoPositionInfo &update)
+{
+ // having successfully received a position update, set _canEmitPeriodicUpdatesTimeout to true,
+ // which (re)enables a timeout to be emitted upon any subsequent error in periodic updating.
+ _canEmitPeriodicUpdatesTimeout = true;
+
+ Q_Q(QGeoPositionInfoSourceBb);
+ Q_EMIT q->positionUpdated(update);
+}
+
+bool QGeoPositionInfoSourceBbPrivate::receivePositionReply(bb::PpsObject &ppsObject)
+{
+ QVariantMap reply;
+ // receiveReply() tests for errors associated with the request being replied to
+ if (!receiveReply(&reply, ppsObject)) {
+ _replyErrorCode = bb::location::PositionErrorCode::FatalUnknown;
+
+ // if there is an error from Location Manager report it so user can access it through the
+ // properties when responding to the updateTimeout() signal.
+ if (reply.contains("errCode")) {
+ int errCode = reply.value("errCode").toInt();
+ _replyErrorCode
+ = intToPositionErrorCodeMap.value(errCode,
+ bb::location::PositionErrorCode::FatalUnknown);
+ if (fatalError(_replyErrorCode)) {
+ _sourceError
+ = positionErrorCodeToErrorMap.value(_replyErrorCode,
+ QGeoPositionInfoSource::UnknownSourceError);
+ }
+
+ if (reply.contains("err")) {
+ _replyErr = reply.value("err").toString();
+ if (reply.contains("errstr")) {
+ _replyErrStr = reply.value("errstr").toString();
+ }
+ }
+ } else {
+ _sourceError = QGeoPositionInfoSource::UnknownSourceError;
+ }
+ return false;
+ }
+
+ // clear any errors
+ _replyErrorCode = bb::location::PositionErrorCode::None;
+ _replyErr = QString();
+ _replyErrStr = QString();
+
+ // check that this is a location reply (could be a reply to another request type, eg. cancel,
+ // which is ignored here)
+ if (reply.contains("res") && reply.value("res").toString() == "location") {
+ // keep the raw LM reply for access via Qt properties.
+ _replyDat = reply.value("dat").toMap();
+
+ // extract the geo position info from the reply into _currentPosition
+ if (populatePositionInfo(&_currentPosition, reply)) {
+ emitPositionUpdated(_currentPosition);
+ }
+ }
+
+ return true;
+}
+
+void QGeoPositionInfoSourceBbPrivate::receivePeriodicPositionReply()
+{
+ // don't try to receive a reply if periodic updates have not been started. This is
+ // necessary because this slot is connected to PpsObject::readyRead() and could be
+ // invoked any time the pps file is updated by the server. Under error conditions
+ // this would otherwise lead to a circular calling sequence: receive, timeout due to
+ // error, cancel, receive...
+ if (!_startUpdatesInvoked)
+ return;
+
+ if (!receivePositionReply(*_periodicUpdatePpsObject)) {
+ Q_Q(QGeoPositionInfoSourceBb);
+ if (fatalError(_replyErrorCode)
+ && q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) {
+ Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError);
+ } else {
+ periodicUpdatesTimeout();
+ }
+ }
+}
+
+void QGeoPositionInfoSourceBbPrivate::receiveSinglePositionReply()
+{
+ // don't try to receive a reply if a single update has not been requested. This is
+ // necessary because this slot is connected to PpsObject::readyRead() and could be
+ // invoked any time the pps file is updated by the server. Under error conditions
+ // this would otherwise lead to a circular calling sequence: receive, timeout due to
+ // error, cancel, receive...
+ if (!_requestUpdateInvoked)
+ return;
+
+ // clear this before calling receivePositionReply() which can emit the positionUpdated()
+ // signal. It is possible to call requestUpdate() in the slot connected to
+ // positionUpdated() so for requestUpdate() to work _requestUpdateInvoked must be false
+ _requestUpdateInvoked = false;
+
+ if (!receivePositionReply(*_singleUpdatePpsObject)) {
+ Q_Q(QGeoPositionInfoSourceBb);
+ if (fatalError(_replyErrorCode)
+ && q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) {
+ Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError);
+ } else {
+ singleUpdateTimeout();
+ }
+ }
+
+ if (!_requestUpdateInvoked) {
+ // close the pps file to ensure readyRead() does not spin in the event that there are
+ // unexpected replies that we don't read. Note that open() is done lazily in sendRequest().
+ _singleUpdatePpsObject->close();
+ }
+}
+
+///////////////////////////
+//
+// QGeoPositionInfoSourceBb
+//
+///////////////////////////
+
+/*!
+ \class QGeoPositionInfoSourceBb
+ \brief The QGeoPositionInfoSourceBb class is for the distribution of positional updates obtained
+ from the underlying Qnx Location Manager.
+
+ QGeoPositionInfoSourceBb is a subclass of QGeoPositionInfoSource. The static function
+ QGeoPositionInfoSource::createDefaultSource() creates a default
+ position source that is appropriate for the platform, if one is available. On BB10 this is
+ a QGeoPositionInfoSourceBb instance.
+
+ Users of a QGeoPositionInfoSource subclass can request the current position using
+ requestUpdate(), or start and stop regular position updates using
+ startUpdates() and stopUpdates(). When an update is available,
+ positionUpdated() is emitted. The last known position can be accessed with
+ lastKnownPosition().
+
+ If regular position updates are required, setUpdateInterval() can be used
+ to specify how often these updates should be emitted. If no interval is
+ specified, updates are simply provided whenever they are available.
+ For example:
+
+ \code
+ // Emit updates every 10 seconds if available
+ QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(0);
+ if (source)
+ source->setUpdateInterval(10000);
+ \endcode
+
+ To remove an update interval that was previously set, call
+ setUpdateInterval() with a value of 0.
+
+ Note that the position source may have a minimum value requirement for
+ update intervals, as returned by minimumUpdateInterval().
+*/
+
+/*!
+ Constructs a QGeoPositionInfoSourceBb instance with the given \a parent
+ and \a updateMode.
+*/
+QGeoPositionInfoSourceBb::QGeoPositionInfoSourceBb(QObject *parent)
+ : QGeoPositionInfoSource(parent),
+ d_ptr(new QGeoPositionInfoSourceBbPrivate(this))
+{
+}
+
+/*!
+ Destroys the position source.
+*/
+QGeoPositionInfoSourceBb::~QGeoPositionInfoSourceBb()
+{
+}
+
+/*!
+ \reimp
+*/
+void QGeoPositionInfoSourceBb::setUpdateInterval(int msec)
+{
+ int interval = msec;
+ if (interval != 0)
+ interval = qMax(msec, minimumUpdateInterval());
+
+ if (interval == updateInterval())
+ return;
+
+ QGeoPositionInfoSource::setUpdateInterval(interval);
+
+ Q_D(QGeoPositionInfoSourceBb);
+ if (d->_startUpdatesInvoked) {
+ d->stopUpdates();
+ d->startUpdates();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGeoPositionInfoSourceBb::setPreferredPositioningMethods(PositioningMethods methods)
+{
+ PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
+ QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
+ if (previousPreferredPositioningMethods == preferredPositioningMethods())
+ return;
+
+ Q_D(QGeoPositionInfoSourceBb);
+ if (d->_startUpdatesInvoked) {
+ d->stopUpdates();
+ d->startUpdates();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGeoPositionInfoSourceBb::startUpdates()
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->startUpdates();
+}
+
+/*!
+ \reimp
+*/
+void QGeoPositionInfoSourceBb::stopUpdates()
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->stopUpdates();
+}
+
+/*!
+ \reimp
+*/
+void QGeoPositionInfoSourceBb::requestUpdate(int msec)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->requestUpdate(msec);
+}
+
+/*!
+ \reimp
+*/
+QGeoPositionInfo
+ QGeoPositionInfoSourceBb::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->lastKnownPosition(fromSatellitePositioningMethodsOnly);
+}
+
+/*!
+ \reimp
+*/
+QGeoPositionInfoSource::PositioningMethods
+ QGeoPositionInfoSourceBb::supportedPositioningMethods() const
+{
+ return AllPositioningMethods;
+}
+
+/*!
+ \reimp
+*/
+int QGeoPositionInfoSourceBb::minimumUpdateInterval() const
+{
+ return global::minUpdateInterval;
+}
+
+QGeoPositionInfoSource::Error QGeoPositionInfoSourceBb::error() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_sourceError;
+}
+
+// these properties extend QGeoPositionInfoSource allowing use of additional features of the Qnx Location Manager
+
+// the following properties are the fields of the dat parameter of the location request
+
+/*!
+ \property QGeoPositionInfoSourceBb::period
+ \brief This property specifies the period of the location request, in seconds. A value of
+ '0' indicates a one-time location request.
+*/
+double QGeoPositionInfoSourceBb::period() const
+{
+ // convert from msec to sec
+ return updateInterval() / 1000.0;
+}
+
+void QGeoPositionInfoSourceBb::setPeriod(double period)
+{
+ // convert from sec to msec, round to nearest msec
+ setUpdateInterval(qRound(static_cast<qreal>(period * 1000.0)));
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::accuracy
+ \brief This property specifies the desired accuracy of the fix, in meters. A value of '0'
+ disables accuracy criteria.
+*/
+double QGeoPositionInfoSourceBb::accuracy() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_accuracy;
+}
+
+void QGeoPositionInfoSourceBb::setAccuracy(double accuracy)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_accuracy = accuracy;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::responseTime
+ \brief This property specifies the desired response time of the fix, in seconds. A value of
+ '0' disables response time criteria.
+*/
+double QGeoPositionInfoSourceBb::responseTime() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_responseTime;
+}
+
+void QGeoPositionInfoSourceBb::setResponseTime(double responseTime)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_responseTime = responseTime;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::canRunInBackground
+ \brief This property determines whether or not requests are allowed to run with the device
+ in standby (i.e. screen off)
+*/
+bool QGeoPositionInfoSourceBb::canRunInBackground() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_canRunInBackground;
+}
+
+void QGeoPositionInfoSourceBb::setCanRunInBackground(bool canRunInBackground)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_canRunInBackground = canRunInBackground;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::provider
+ \brief This property specifies the location provider you wish to use (hybrid, gnss,
+ network).
+*/
+QString QGeoPositionInfoSourceBb::provider() const
+{
+ return positioningMethodsToProviderMap.value(preferredPositioningMethods());
+}
+
+void QGeoPositionInfoSourceBb::setProvider(const QString &provider)
+{
+ setPreferredPositioningMethods(positioningMethodsToProviderMap.key(provider));
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::fixType
+ \brief This property specifies the fix type you wish to use (best, gps_ms_based,
+ gps_ms_assisted, gps_autonomous, cellsite, wifi).
+*/
+QString QGeoPositionInfoSourceBb::fixType() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_fixType;
+}
+
+void QGeoPositionInfoSourceBb::setFixType(const QString &fixType)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_fixType = fixType;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::appId
+ \brief This property specifies a special application id.
+*/
+QString QGeoPositionInfoSourceBb::appId() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_appId;
+}
+
+void QGeoPositionInfoSourceBb::setAppId(const QString &appId)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_appId = appId;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::appPassword
+ \brief This property specifies a special application password, goes with appId above.
+*/
+QString QGeoPositionInfoSourceBb::appPassword() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_appPassword;
+}
+
+void QGeoPositionInfoSourceBb::setAppPassword(const QString &appPassword)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_appPassword = appPassword;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::pdeUrl
+ \brief This property specifies the PDE URL (i.e. tcp://user:pass@address.dom:1234).
+*/
+QUrl QGeoPositionInfoSourceBb::pdeUrl() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_pdeUrl;
+}
+
+void QGeoPositionInfoSourceBb::setPdeUrl(const QUrl &pdeUrl)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_pdeUrl = pdeUrl;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::slpUrl
+ \brief This property specifies the SLP URL (i.e. tcp://user:pass@address.dom:1234).
+*/
+QUrl QGeoPositionInfoSourceBb::slpUrl() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_slpUrl;
+}
+
+void QGeoPositionInfoSourceBb::setSlpUrl(const QUrl &slpUrl)
+{
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_slpUrl = slpUrl;
+}
+
+// the following read-only properties are the fields of the Location Manager generic reply
+
+/*!
+ \property QGeoPositionInfoSourceBb::replyDat
+ \brief This property specifies the object containing the reply data (such as latitude,
+ longitude, satellites, etc). If the replyErr is not empty then replyDat may be empty or
+ stale. replyDat is expected to be consumed in the slot connected to the positionUpdated()
+ signal, otherwise its contents are undefined.
+*/
+QVariantMap QGeoPositionInfoSourceBb::replyDat() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_replyDat;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::replyErrorCode
+ \brief If not empty this property indicates that an error has occurred, and identifies the
+ error.
+
+ Possible values are:
+
+ Code | Description
+ None | No error
+ FatalDisabled | Location services is disabled
+ FatalNoLastKnownPosition | There is no last known position on the device
+ FatalInsufficientProviders | There are insufficient available location technology providers
+ to process your request
+ FatalInvalidRequest | One or more of the request parameters are invalid.
+ WarnTimeout | A timeout has occurred while processing your request. The request will
+ continue until your location is obtained
+ WarnLostTracking | The location fix has been lost due to insufficient coverage. The request
+ will continue until your location is reacquired
+ WarnStationary | The device is stationary. No further updates until the device resumes
+ movement
+
+ replyErrorCode is expected to be consumed in the slot connected to the updateTimeout()
+ signal, which is emitted when an error is detected. Otherwise its contents are undefined.
+*/
+bb::location::PositionErrorCode::Type QGeoPositionInfoSourceBb::replyErrorCode() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_replyErrorCode;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::replyErr
+ \brief If not empty this property indicates that an error has occurred, and identifies the
+ error. replyErr is expected to be consumed in the slot connected to the updateTimeout()
+ signal, which is emitted when an error is detected. Otherwise its contents are undefined.
+*/
+QString QGeoPositionInfoSourceBb::replyErr() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_replyErr;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::replyErrStr
+ \brief This property is not empty if and only if the replyErr parameter is present, it
+ describes the error. replyErrStr is expected to be consumed in the slot connected to the
+ updateTimeout() signal, which is emitted when an error is detected. Otherwise its contents
+ are undefined.
+*/
+QString QGeoPositionInfoSourceBb::replyErrStr() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_replyErrStr;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::locationServicesEnabled
+ \brief This property indicates whether the location services are enabled or not. If
+ location services are disabled then no position updates will occur. The user must enable
+ location services through the Settings app before any position updates will be available.
+*/
+bool QGeoPositionInfoSourceBb::locationServicesEnabled() const
+{
+ bool locationEnabled = false;
+ if (location_manager_get_status(&locationEnabled) != 0) {
+ qWarning() << "QGeoPositionInfoSourceBb::locationServicesEnabled() : "
+ "call to location_manager_get_status() failed.";
+ }
+ return locationEnabled;
+}
+
+/*!
+ \property QGeoPositionInfoSourceBb::reset
+ \brief By setting this property a reset of all location providers is requested through the
+ Location Manager. The value of reset specifies the type of reset to be performed. Valid
+ reset types are "cold", "warm", "hot", and "factory". The reset is not actually carried out
+ until position updates are restarted. The current value of this property, i.e.
+ property("reset"), is not particularly useful, it is simply the reset type corresponding to
+ the last time setProperty("reset", resetType) was called. A Qt property must have a READ
+ method, hence the reason for defining resetType().
+*/
+QString QGeoPositionInfoSourceBb::resetType() const
+{
+ Q_D(const QGeoPositionInfoSourceBb);
+ return d->_resetType;
+}
+
+void QGeoPositionInfoSourceBb::requestReset(const QString &resetType)
+{
+ if (validResetTypes.contains(resetType)) {
+ Q_D(QGeoPositionInfoSourceBb);
+ d->_resetType = resetType;
+ d->resetLocationProviders();
+ }
+}
diff --git a/src/plugins/position/blackberry/qgeopositioninfosource_bb.h b/src/plugins/position/blackberry/qgeopositioninfosource_bb.h
new file mode 100644
index 00000000..f142dc40
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeopositioninfosource_bb.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOPOSITIONINFOSOURCE_BB_H
+#define QGEOPOSITIONINFOSOURCE_BB_H
+
+#include <QGeoPositionInfoSource>
+
+#include <bb/location/PositionErrorCode>
+
+#include <QString>
+#include <QVariantMap>
+#include <QScopedPointer>
+#include <QUrl>
+
+class QGeoPositionInfoSourceBbPrivate;
+class BB_LOCATION_EXPORT QGeoPositionInfoSourceBb : public QGeoPositionInfoSource
+{
+ Q_OBJECT
+
+ Q_PROPERTY(double period READ period WRITE setPeriod FINAL)
+ Q_PROPERTY(double accuracy READ accuracy WRITE setAccuracy FINAL)
+ Q_PROPERTY(double responseTime READ responseTime WRITE setResponseTime FINAL)
+ Q_PROPERTY(bool canRunInBackground READ canRunInBackground WRITE setCanRunInBackground FINAL)
+ Q_PROPERTY(QString provider READ provider WRITE setProvider FINAL)
+ Q_PROPERTY(QString fixType READ fixType WRITE setFixType FINAL)
+ Q_PROPERTY(QString appId READ appId WRITE setAppId FINAL)
+ Q_PROPERTY(QString appPassword READ appPassword WRITE setAppPassword FINAL)
+ Q_PROPERTY(QUrl pdeUrl READ pdeUrl WRITE setPdeUrl FINAL)
+ Q_PROPERTY(QUrl slpUrl READ slpUrl WRITE setSlpUrl FINAL)
+
+ Q_PROPERTY(QVariantMap replyDat READ replyDat FINAL)
+ Q_PROPERTY(bb::location::PositionErrorCode::Type replyErrorCode READ replyErrorCode FINAL)
+ Q_PROPERTY(QString replyErr READ replyErr FINAL)
+ Q_PROPERTY(QString replyErrStr READ replyErrStr FINAL)
+
+ Q_PROPERTY(bool locationServicesEnabled READ locationServicesEnabled FINAL)
+
+ Q_PROPERTY(QString reset READ resetType WRITE requestReset FINAL)
+
+public:
+ explicit QGeoPositionInfoSourceBb(QObject *parent = 0);
+ virtual ~QGeoPositionInfoSourceBb();
+
+ void setUpdateInterval(int msec);
+ void setPreferredPositioningMethods(PositioningMethods methods);
+ QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const;
+ PositioningMethods supportedPositioningMethods() const;
+ int minimumUpdateInterval() const;
+ Error error() const;
+
+ double period() const;
+ void setPeriod(double period);
+
+ double accuracy() const;
+ void setAccuracy(double accuracy);
+
+ double responseTime() const;
+ void setResponseTime(double responseTime);
+
+ bool canRunInBackground() const;
+ void setCanRunInBackground(bool canRunInBackground);
+
+ QString provider() const;
+ void setProvider(const QString &provider);
+
+ QString fixType() const;
+ void setFixType(const QString &fixType);
+
+ QString appId() const;
+ void setAppId(const QString &appId);
+
+ QString appPassword() const;
+ void setAppPassword(const QString &appPassword);
+
+ QUrl pdeUrl() const;
+ void setPdeUrl(const QUrl &pdeUrl);
+
+ QUrl slpUrl() const;
+ void setSlpUrl(const QUrl &slpUrl);
+
+ QVariantMap replyDat() const;
+
+ bb::location::PositionErrorCode::Type replyErrorCode() const;
+
+ QString replyErr() const;
+
+ QString replyErrStr() const;
+
+ bool locationServicesEnabled() const;
+
+ QString resetType() const;
+ void requestReset(const QString &resetType);
+
+
+public Q_SLOTS:
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int timeout = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGeoPositionInfoSourceBb)
+ Q_DISABLE_COPY(QGeoPositionInfoSourceBb)
+ QScopedPointer<QGeoPositionInfoSourceBbPrivate> d_ptr;
+};
+
+#endif
diff --git a/src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h b/src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h
new file mode 100644
index 00000000..918d4913
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOPOSITIONINFOSOURCEBB_P_H
+#define QGEOPOSITIONINFOSOURCEBB_P_H
+
+#include "qgeopositioninfosource_bb.h"
+#include "qgeopositioninfo.h"
+
+#include <bb/location/PositionErrorCode>
+
+#include <QObject>
+#include <QVariantMap>
+#include <QUrl>
+
+namespace bb
+{
+class PpsObject;
+}
+
+class QGeoPositionInfoSourceBbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ ~QGeoPositionInfoSourceBbPrivate();
+
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int msec);
+
+ bool _startUpdatesInvoked;
+ bool _requestUpdateInvoked;
+
+private Q_SLOTS:
+ void singleUpdateTimeout();
+ void receivePeriodicPositionReply();
+ void receiveSinglePositionReply();
+
+ void emitUpdateTimeout();
+
+Q_SIGNALS:
+ void queuedUpdateTimeout();
+
+private:
+ Q_DECLARE_PUBLIC(QGeoPositionInfoSourceBb)
+ explicit QGeoPositionInfoSourceBbPrivate(QGeoPositionInfoSourceBb *parent);
+
+ void periodicUpdatesTimeout();
+
+ void emitPositionUpdated(const QGeoPositionInfo &update);
+ bool requestPositionInfo(bool periodic, int singleRequestMsec = 0);
+ void cancelPositionInfo(bool periodic);
+ void resetLocationProviders();
+ QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const;
+
+ QVariantMap populateLocationRequest(bool periodic, int singleRequestMsec = 0) const;
+ QVariantMap populateResetRequest() const;
+
+ bool receivePositionReply(bb::PpsObject &ppsObject);
+
+ bool _canEmitPeriodicUpdatesTimeout;
+
+ QGeoPositionInfoSourceBb *q_ptr;
+ bb::PpsObject *_periodicUpdatePpsObject;
+ bb::PpsObject *_singleUpdatePpsObject;
+ QGeoPositionInfo _currentPosition;
+ QGeoPositionInfoSource::Error _sourceError;
+
+ // these are Location Manager parameters that are represented by properties. These parameters
+ // represent additional functionality beyond what is provided by the base class
+ // QGeoPositionInfoSource
+ double _accuracy;
+ double _responseTime;
+ bool _canRunInBackground;
+ QString _fixType;
+ QString _appId;
+ QString _appPassword;
+ QUrl _pdeUrl;
+ QUrl _slpUrl;
+ QVariantMap _replyDat;
+ bb::location::PositionErrorCode::Type _replyErrorCode;
+ QString _replyErr;
+ QString _replyErrStr;
+ QString _resetType;
+
+};
+
+#endif
diff --git a/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp b/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp
new file mode 100644
index 00000000..64a5ed9e
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeopositioninfosourcefactory_bb.h"
+#include "qgeopositioninfosource_bb.h"
+#include "qgeosatelliteinfosource_bb.h"
+
+#include <QGeoPositionInfoSource>
+#include <QGeoSatelliteInfoSource>
+
+
+///////////////////////////
+//
+// QGeoPositionInfoSourceFactoryBb
+//
+///////////////////////////
+
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryBb::positionInfoSource(QObject *parent)
+{
+ return new QGeoPositionInfoSourceBb(parent);
+}
+
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryBb::satelliteInfoSource(QObject *parent)
+{
+ return new QGeoSatelliteInfoSourceBb(parent);
+}
+
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryBb::areaMonitor(QObject *parent)
+{
+ Q_UNUSED(parent);
+ return 0;
+}
diff --git a/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.h b/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.h
new file mode 100644
index 00000000..439c2ae6
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOPOSITIONINFOSOURCEFACTORY_BB_H
+#define QGEOPOSITIONINFOSOURCEFACTORY_BB_H
+
+#include <bb/Global>
+
+#include <QGeoPositionInfoSourceFactory>
+
+#include <QObject>
+
+class QGeoPositionInfoSourceFactoryBb : public QObject, public QGeoPositionInfoSourceFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
+ FILE "plugin.json")
+ Q_INTERFACES(QGeoPositionInfoSourceFactory)
+
+public:
+ QGeoPositionInfoSource *positionInfoSource(QObject *parent);
+ QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
+};
+
+#endif // include guard
diff --git a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp
new file mode 100644
index 00000000..241b99a5
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp
@@ -0,0 +1,621 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <bb/PpsObject>
+
+#include "qgeosatelliteinfosource_bb_p.h"
+#include "locationmanagerutil_bb.h"
+
+#include <location_manager.h>
+
+extern "C" {
+#include <wmm/wmm.h>
+}
+
+#include <QVariantMap>
+#include <QByteArray>
+#include <QtDebug>
+
+#include <errno.h>
+
+///////////////////////////
+//
+// local variables/functions
+//
+///////////////////////////
+
+namespace global
+{
+
+// While waiting for a position fix a satellite update period of 1 sec is considered reasonable.
+static const double defaultSatelliteUpdatePeriod = 1.0;
+
+} // namespace global
+
+namespace
+{
+// map the Location Manager reply error codes to the QGeoSatelliteInfoSource::Error enum values.
+QMap<int, QGeoSatelliteInfoSource::Error> createIntToErrorCodeMap()
+{
+ QMap<int, QGeoSatelliteInfoSource::Error> map;
+
+ map.insert(0, QGeoSatelliteInfoSource::NoError);
+ map.insert(1, QGeoSatelliteInfoSource::ClosedError);
+ map.insert(2, QGeoSatelliteInfoSource::UnknownSourceError);
+ map.insert(3, QGeoSatelliteInfoSource::UnknownSourceError);
+ map.insert(4, QGeoSatelliteInfoSource::UnknownSourceError);
+ map.insert(5, QGeoSatelliteInfoSource::UnknownSourceError);
+ map.insert(6, QGeoSatelliteInfoSource::AccessError);
+ // the following are not considered errors from QGeoSatelliteInfoSource perspective
+ // (they are timeout conditions)
+ map.insert(0x10000, QGeoSatelliteInfoSource::NoError);
+ map.insert(0x10001, QGeoSatelliteInfoSource::NoError);
+ map.insert(0x10002, QGeoSatelliteInfoSource::NoError);
+
+ return map;
+}
+
+const QMap<int, QGeoSatelliteInfoSource::Error> intToErrorCodeMap =
+ createIntToErrorCodeMap();
+
+QGeoSatelliteInfo::SatelliteSystem determineSatSystem(int satId)
+{
+ if (satId >= 1 && satId <= 32)
+ return QGeoSatelliteInfo::GPS;
+
+ if (satId >= 65 && satId <= 88)
+ return QGeoSatelliteInfo::GLONASS;
+
+ return QGeoSatelliteInfo::Undefined;
+}
+
+}
+
+///////////////////////////
+//
+// QGeoSatelliteInfoSourceBbPrivate
+//
+///////////////////////////
+
+// Create a QVariantMap suitable for writing to a PpsObject specifying a location request to the
+// Location Manager. If the request is periodic then the update interval is used. Otherwise 0
+// indicates to the Location Manager that it is a request for a single, immediate location response.
+// singleRequestMsec applies only to the single, immediate location response. It represents the
+// expected location response time, after which it is assumed a timeout response occurs.
+QVariantMap QGeoSatelliteInfoSourceBbPrivate::populateLocationRequest(bool periodic,
+ int singleRequestMsec)
+{
+ Q_Q(const QGeoSatelliteInfoSourceBb);
+
+ QVariantMap map;
+ QVariantMap datMap;
+
+ int period;
+ int responseTime;
+ if (periodic) {
+ // rounding is performed here because the Location Manager truncates to nearest integer
+ period = (q->updateInterval() + 500) / 1000;
+ if (period == 0)
+ period = ::global::defaultSatelliteUpdatePeriod;
+
+ responseTime = _responseTime;
+ } else {
+ period = 0;
+ responseTime = (singleRequestMsec + 500) / 1000;
+ }
+
+ datMap.insert("period", period);
+ datMap.insert("accuracy", 0);
+ datMap.insert("response_time", responseTime);
+ datMap.insert("background", _backgroundMode);
+
+ datMap.insert("provider", "gnss");
+ datMap.insert("fix_type", "gps_autonomous");
+
+ // have the Location Manager return the satellite information even if it does not have a
+ // position fix.
+ datMap.insert("report_sat", true);
+
+ map.insert("msg", "location");
+ map.insert("id", global::libQtLocationId);
+ map.insert("dat", datMap);
+
+ return map;
+}
+
+// From a QvariantMap representing a location response from the Location Manager fill the lists of
+// QGeoSatelliteInfo instances intended to be emitted via satellitesInUseUpdated() and
+// satellitesInViewUpdated() signals.
+void QGeoSatelliteInfoSourceBbPrivate::populateSatelliteLists(const QVariantMap &map)
+{
+ // populate _currentSatelliteInfo
+ QVariantMap datMap = map.value("dat").toMap();
+ QVariantList satelliteList = datMap.value("satellites").toList();
+
+ _satellitesInView.clear();
+ _satellitesInUse.clear();
+
+ Q_FOREACH (const QVariant &satelliteData, satelliteList) {
+ datMap = satelliteData.toMap();
+ QGeoSatelliteInfo satelliteInfo = QGeoSatelliteInfo();
+
+ if (datMap.contains("id"))
+ satelliteInfo.setSatelliteIdentifier(static_cast<int>(datMap.value("id").toDouble()));
+
+ satelliteInfo.setSatelliteSystem(determineSatSystem(satelliteInfo.satelliteIdentifier()));
+
+ if (datMap.contains("cno"))
+ satelliteInfo.setSignalStrength(static_cast<int>(datMap.value("cno").toDouble()));
+
+ // attributes
+ if (datMap.contains("elevation"))
+ satelliteInfo.setAttribute(QGeoSatelliteInfo::Elevation,
+ static_cast<qreal>(datMap.value("elevation").toDouble()));
+ else
+ satelliteInfo.removeAttribute(QGeoSatelliteInfo::Elevation);
+
+ if (datMap.contains("azimuth"))
+ satelliteInfo.setAttribute(QGeoSatelliteInfo::Azimuth,
+ static_cast<qreal>(datMap.value("azimuth").toDouble()));
+ else
+ satelliteInfo.removeAttribute(QGeoSatelliteInfo::Azimuth);
+
+ // each satellite in this list is considered "in view"
+ _satellitesInView.append(satelliteInfo);
+
+ if (datMap.value("used").toBool() == true)
+ _satellitesInUse.append(satelliteInfo);
+ }
+}
+
+// The satellite data is retrieved from a location request
+bool QGeoSatelliteInfoSourceBbPrivate::requestSatelliteInfo(bool periodic,
+ int singleRequestMsec)
+{
+ // build up the request
+ QVariantMap request = populateLocationRequest(periodic, singleRequestMsec);
+
+ bb::PpsObject *ppsObject;
+ if (periodic)
+ ppsObject = _periodicUpdatePpsObject;
+ else
+ ppsObject = _singleUpdatePpsObject;
+
+ if (sendRequest(*ppsObject, request) == false) {
+ stopUpdates();
+
+#ifndef BB_TEST_BUILD
+ // test for pps file error
+ switch (ppsObject->error()) {
+ case EACCES:
+ _sourceError = QGeoSatelliteInfoSource::AccessError;
+ break;
+ default:
+ _sourceError = QGeoSatelliteInfoSource::UnknownSourceError;
+ break;
+ }
+#endif // !BB_TEST_BUILD
+
+ return false;
+ }
+
+ return true;
+}
+
+void QGeoSatelliteInfoSourceBbPrivate::cancelSatelliteInfo(bool periodic)
+{
+ bb::PpsObject *ppsObject;
+ if (periodic)
+ ppsObject = _periodicUpdatePpsObject;
+ else
+ ppsObject = _singleUpdatePpsObject;
+
+ (void)sendRequest(*ppsObject, global::cancelRequest);
+}
+
+// Constructor. Note there are two PpsObjects for handling the two different types of requests that
+// can be simultaneously made and which must be handled independently (apart from both being emitted
+// through the same signal when done-part of Qt Mobility spec.
+QGeoSatelliteInfoSourceBbPrivate::QGeoSatelliteInfoSourceBbPrivate(
+ QGeoSatelliteInfoSourceBb *parent)
+ : QObject(parent),
+ _startUpdatesInvoked(false),
+ _requestUpdateInvoked(false),
+ q_ptr(parent),
+ _periodicUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)),
+ _singleUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)),
+ _sourceError(QGeoSatelliteInfoSource::NoError),
+ _backgroundMode(false),
+ _responseTime(0)
+{
+ // connect to periodic update PpsObject::readyRead()
+ connect(_periodicUpdatePpsObject, SIGNAL(readyRead()), SLOT(receivePeriodicSatelliteReply()));
+
+ // connect to single update PpsObject::readyRead()
+ connect(_singleUpdatePpsObject, SIGNAL(readyRead()), SLOT(receiveSingleSatelliteReply()));
+
+ // queued connection to signal requestTimeout()
+ connect(this, SIGNAL(queuedRequestTimeout()), SLOT(emitRequestTimeout()), Qt::QueuedConnection);
+}
+
+QGeoSatelliteInfoSourceBbPrivate::~QGeoSatelliteInfoSourceBbPrivate()
+{
+ stopUpdates();
+}
+
+// request periodic updates
+void QGeoSatelliteInfoSourceBbPrivate::startUpdates()
+{
+ // do nothing if periodic updates have already been started
+ if (_startUpdatesInvoked)
+ return;
+
+ // build a request and initiate it
+ if (requestSatelliteInfo(true)) {
+ _startUpdatesInvoked = true;
+ } else {
+ Q_Q(QGeoSatelliteInfoSourceBb);
+ Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError);
+ }
+}
+
+// stop periodic updates
+void QGeoSatelliteInfoSourceBbPrivate::stopUpdates()
+{
+ // do nothing if periodic updates have not been started
+ if (!_startUpdatesInvoked)
+ return;
+
+ cancelSatelliteInfo(true);
+ _startUpdatesInvoked = false;
+
+ // close the pps file to ensure readyRead() does not spin in the event that we don't read the
+ // reply to the cancel request. Note that open() is done lazily in sendRequest().
+ _periodicUpdatePpsObject->close();
+}
+
+// request single update
+void QGeoSatelliteInfoSourceBbPrivate::requestUpdate(int msec)
+{
+ // do nothing if an immediate update has already been requested
+ if (_requestUpdateInvoked)
+ return;
+
+ if (msec) {
+ // If it is not possible to update in msec timeout immediately.
+ if (msec < global::minUpdateInterval) {
+ // The connection is queued because it is possible for the user to call requestUpdate()
+ // from within the slot handling the timeout. The queued connection avoids potential
+ // infinite recursion.
+ Q_EMIT queuedRequestTimeout();
+ return;
+ }
+ }
+
+ if (requestSatelliteInfo(false, msec)) {
+ _requestUpdateInvoked = true;
+ } else {
+ // With Qt5 the error() signal was introduced. If there are any receivers emit error() else
+ // maintain QtMobility behavior.
+ Q_Q(QGeoSatelliteInfoSourceBb);
+ if (q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) {
+ Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError);
+ } else {
+ // The connection is queued because it is possible for the user to call requestUpdate()
+ // from within the slot handling the timeout. The queued connection avoids potential
+ // infinite recursion.
+ Q_EMIT queuedRequestTimeout();
+ }
+ }
+}
+
+// single update has timed out. This is a slot for the requestUpdate timer
+void QGeoSatelliteInfoSourceBbPrivate::singleUpdateTimeout()
+{
+ _requestUpdateInvoked = false;
+
+ emitRequestTimeout();
+
+ if (!_requestUpdateInvoked) {
+ // close the pps file to ensure readyRead() does not spin in the event that there are
+ // unexpected replies that we don't read. Note that open() is done lazily in sendRequest().
+ _singleUpdatePpsObject->close();
+ }
+}
+
+// This slot is intended for queued connection to the signal queuedUpdateTimeout(). If an error
+// occurs when an update is requested the error is relayed via updateTimeout() but the connection
+// is queued to avoid potential infinite recursion.
+void QGeoSatelliteInfoSourceBbPrivate::emitRequestTimeout()
+{
+ Q_Q(QGeoSatelliteInfoSourceBb);
+ Q_EMIT q->requestTimeout();
+}
+
+bool QGeoSatelliteInfoSourceBbPrivate::receiveSatelliteReply(bool periodic)
+{
+ bb::PpsObject *ppsObject;
+ if (periodic)
+ ppsObject = _periodicUpdatePpsObject;
+ else
+ ppsObject = _singleUpdatePpsObject;
+
+ QVariantMap reply;
+ // receiveReply() tests for errors associated with the request being replied to
+ if (!receiveReply(&reply, *ppsObject)) {
+ QGeoSatelliteInfoSource::Error fatalError = QGeoSatelliteInfoSource::UnknownSourceError;
+
+ // if there is an error from Location Manager translate it to a
+ // QGeoSatelliteInfoSource::Error
+ if (reply.contains("errCode")) {
+ fatalError = intToErrorCodeMap.value(reply.value("errCode").toInt(),
+ QGeoSatelliteInfoSource::UnknownSourceError);
+ }
+
+ if (fatalError != QGeoSatelliteInfoSource::NoError)
+ _sourceError = fatalError;
+
+ if (!periodic || fatalError != QGeoSatelliteInfoSource::NoError)
+ return false;
+ }
+
+ // check that this is a location reply (could be a reply to another request type, eg. cancel,
+ // which is ignored here)
+ if (reply.contains("res") && reply.value("res").toString() == "location") {
+ // extract the satellite info from the reply into _satellitesInView and _satellitesInUse
+ populateSatelliteLists(reply);
+
+ Q_Q(QGeoSatelliteInfoSourceBb);
+ Q_EMIT q->satellitesInUseUpdated(_satellitesInUse);
+ Q_EMIT q->satellitesInViewUpdated(_satellitesInView);
+ }
+
+ return true;
+}
+
+void QGeoSatelliteInfoSourceBbPrivate::receivePeriodicSatelliteReply()
+{
+ // don't try to receive a reply if periodic updates have not been started. This is
+ // necessary because this slot is connected to PpsObject::readyRead() and could be
+ // invoked any time the pps file is updated by the server. Under error conditions
+ // this would otherwise lead to a circular calling sequence: receive, timeout due to
+ // error, cancel, receive...
+ if (!_startUpdatesInvoked)
+ return;
+
+ if (!receiveSatelliteReply(true)) {
+ Q_Q(QGeoSatelliteInfoSourceBb);
+ Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError);
+ }
+}
+
+void QGeoSatelliteInfoSourceBbPrivate::receiveSingleSatelliteReply()
+{
+ // don't try to receive a reply if a single update has not been requested. This is
+ // necessary because this slot is connected to PpsObject::readyRead() and could be
+ // invoked any time the pps file is updated by the server. Under error conditions
+ // this would otherwise lead to a circular calling sequence: receive, timeout due to
+ // error, cancel, receive...
+ if (!_requestUpdateInvoked)
+ return;
+
+ // clear this before calling receivePositionReply() which can emit the positionUpdated()
+ // signal. It is possible to call requestUpdate() in the slot connected to
+ // positionUpdated() so for requestUpdate() to work _requestUpdateInvoked must be false
+ _requestUpdateInvoked = false;
+
+ if (!receiveSatelliteReply(false)) {
+ Q_Q(QGeoSatelliteInfoSourceBb);
+ if (_sourceError != QGeoSatelliteInfoSource::NoError)
+ Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError);
+ else
+ singleUpdateTimeout();
+ }
+
+ if (!_requestUpdateInvoked) {
+ // close the pps file to ensure readyRead() does not spin in the event that there are
+ // unexpected replies that we don't read. Note that open() is done lazily in sendRequest().
+ _singleUpdatePpsObject->close();
+ }
+}
+
+///////////////////////////
+//
+// QGeoSatelliteInfoSourceBb
+//
+///////////////////////////
+
+/*!
+ \class QGeoSatelliteInfoSourceBb
+ \brief The QGeoSatelliteInfoSourceBb class is for the distribution of positional updates
+ obtained from the underlying Qnx Location Manager.
+
+ QGeoSatelliteInfoSourceBb is a subclass of QGeoSatelliteInfoSource.
+ The static function QGeoSatelliteInfoSource::createDefaultSource() creates a default
+ satellite data source that is appropriate for the platform, if one is
+ available. On BB10 this is a QGeoSatelliteInfoSourceBb instance. Otherwise, available
+ QGeoPositionInfoSourceFactory plugins will
+ be checked for one that has a satellite data source available.
+
+ Call startUpdates() and stopUpdates() to start and stop regular updates,
+ or requestUpdate() to request a single update.
+ When an update is available, satellitesInViewUpdated() and/or
+ satellitesInUseUpdated() will be emitted.
+*/
+
+
+
+/*!
+ Constructs a QGeoSatelliteInfoSourceBb instance with the given \a parent
+ and \a updateMode.
+*/
+QGeoSatelliteInfoSourceBb::QGeoSatelliteInfoSourceBb(QObject *parent)
+ : QGeoSatelliteInfoSource(parent),
+ d_ptr(new QGeoSatelliteInfoSourceBbPrivate(this))
+{
+}
+
+/*!
+ Destroys the satellite source.
+*/
+QGeoSatelliteInfoSourceBb::~QGeoSatelliteInfoSourceBb()
+{
+}
+
+/*!
+ \reimp
+*/
+int QGeoSatelliteInfoSourceBb::minimumUpdateInterval() const
+{
+ return global::minUpdateInterval;
+}
+
+/*!
+ \reimp
+*/
+void QGeoSatelliteInfoSourceBb::setUpdateInterval(int msec)
+{
+ int interval = msec;
+ if (interval != 0)
+ interval = qMax(msec, minimumUpdateInterval());
+
+ if (interval == updateInterval())
+ return;
+
+ QGeoSatelliteInfoSource::setUpdateInterval(interval);
+
+ Q_D(QGeoSatelliteInfoSourceBb);
+ if (d->_startUpdatesInvoked) {
+ d->stopUpdates();
+ d->startUpdates();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QGeoSatelliteInfoSourceBb::startUpdates()
+{
+ Q_D(QGeoSatelliteInfoSourceBb);
+ d->startUpdates();
+}
+
+/*!
+ \reimp
+*/
+void QGeoSatelliteInfoSourceBb::stopUpdates()
+{
+ Q_D(QGeoSatelliteInfoSourceBb);
+ d->stopUpdates();
+}
+
+/*!
+ \reimp
+*/
+void QGeoSatelliteInfoSourceBb::requestUpdate(int msec)
+{
+ Q_D(QGeoSatelliteInfoSourceBb);
+ d->requestUpdate(msec);
+}
+
+/*!
+ \reimp
+*/
+QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceBb::error() const
+{
+ Q_D(const QGeoSatelliteInfoSourceBb);
+ return d->_sourceError;
+}
+
+// property managers. These properties extend QGeoSatelliteInfoSource by allowing additional
+// control provided by the Location Manager
+
+/*!
+ \property QGeoSatelliteInfoSourceBb::period
+ \brief The period of the location request, in seconds. A value of '0' indicates that this
+ would be a one-time location request.
+*/
+double QGeoSatelliteInfoSourceBb::period() const
+{
+ // convert from msec to sec
+ return updateInterval() / 1000.0;
+}
+
+void QGeoSatelliteInfoSourceBb::setPeriod(double period)
+{
+ // convert from sec to msec, round to nearest msec
+ setUpdateInterval(qRound(static_cast<qreal>(period * 1000.0)));
+}
+
+
+/*!
+ \property QGeoSatelliteInfoSourceBb::backgroundMode
+ \brief This property determines whether or not requests are allowed to run with the device
+ in standby (i.e. screen off)
+*/
+bool QGeoSatelliteInfoSourceBb::backgroundMode() const
+{
+ Q_D(const QGeoSatelliteInfoSourceBb);
+ return d->_backgroundMode;
+}
+
+void QGeoSatelliteInfoSourceBb::setBackgroundMode(bool mode)
+{
+ Q_D(QGeoSatelliteInfoSourceBb);
+ d->_backgroundMode = mode;
+}
+
+/*!
+ \property QGeoSatelliteInfoSourceBb::responseTime
+ \brief This property specifies the desired response time of the fix, in seconds. A value
+ of '0' disables response time criteria.
+*/
+int QGeoSatelliteInfoSourceBb::responseTime() const
+{
+ Q_D(const QGeoSatelliteInfoSourceBb);
+ return d->_responseTime;
+}
+
+void QGeoSatelliteInfoSourceBb::setResponseTime(int responseTime)
+{
+ Q_D(QGeoSatelliteInfoSourceBb);
+ d->_responseTime = responseTime;
+}
diff --git a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.h b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.h
new file mode 100644
index 00000000..975ae3a1
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOSATELLITEINFOSOURCE_BB_H
+#define QGEOSATELLITEINFOSOURCE_BB_H
+
+#include <QGeoSatelliteInfoSource>
+
+#include <QString>
+#include <QScopedPointer>
+
+class QGeoSatelliteInfoSourceBbPrivate;
+class QGeoSatelliteInfoSourceBb : public QGeoSatelliteInfoSource
+{
+ Q_OBJECT
+
+ Q_PROPERTY(double period READ period WRITE setPeriod FINAL)
+ Q_PROPERTY(bool backgroundMode READ backgroundMode WRITE setBackgroundMode FINAL)
+ Q_PROPERTY(int responseTime READ responseTime WRITE setResponseTime FINAL)
+
+public:
+ explicit QGeoSatelliteInfoSourceBb(QObject *parent = 0);
+ virtual ~QGeoSatelliteInfoSourceBb();
+
+ void setUpdateInterval(int msec);
+ int minimumUpdateInterval() const;
+ Error error() const;
+
+ double period() const;
+ void setPeriod(double period);
+
+ bool backgroundMode() const;
+ void setBackgroundMode(bool mode);
+
+ int responseTime() const;
+ void setResponseTime(int responseTime);
+
+public Q_SLOTS:
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int timeout = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGeoSatelliteInfoSourceBb)
+ Q_DISABLE_COPY(QGeoSatelliteInfoSourceBb)
+ QScopedPointer<QGeoSatelliteInfoSourceBbPrivate> d_ptr;
+};
+
+#endif
diff --git a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h
new file mode 100644
index 00000000..63eb94b2
--- /dev/null
+++ b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOSATELLITEINFOSOURCE_BB_P_H
+#define QGEOSATELLITEINFOSOURCE_BB_P_H
+
+#include "qgeosatelliteinfosource_bb.h"
+#include "qgeosatelliteinfo.h"
+
+#include <QObject>
+#include <QtCore/QVariantMap>
+
+namespace bb
+{
+class PpsObject;
+}
+
+class QGeoSatelliteInfoSourceBbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ ~QGeoSatelliteInfoSourceBbPrivate();
+
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int msec);
+
+ bool _startUpdatesInvoked;
+ bool _requestUpdateInvoked;
+
+private Q_SLOTS:
+ void singleUpdateTimeout();
+ void receivePeriodicSatelliteReply();
+ void receiveSingleSatelliteReply();
+
+ void emitRequestTimeout();
+
+Q_SIGNALS:
+ void queuedRequestTimeout();
+
+private:
+ Q_DECLARE_PUBLIC(QGeoSatelliteInfoSourceBb)
+ explicit QGeoSatelliteInfoSourceBbPrivate(QGeoSatelliteInfoSourceBb *parent);
+
+ void emitSatelliteUpdated(const QGeoSatelliteInfo &update);
+ bool requestSatelliteInfo(bool periodic, int singleRequestMsec = 0);
+ void cancelSatelliteInfo(bool periodic);
+
+ QVariantMap populateLocationRequest(bool periodic, int singleRequestMsec = 0);
+ void populateSatelliteLists(const QVariantMap &reply);
+
+ bool receiveSatelliteReply(bool periodic);
+
+ QGeoSatelliteInfoSourceBb *q_ptr;
+ bb::PpsObject *_periodicUpdatePpsObject;
+ bb::PpsObject *_singleUpdatePpsObject;
+ QList<QGeoSatelliteInfo> _satellitesInUse;
+ QList<QGeoSatelliteInfo> _satellitesInView;
+ QGeoSatelliteInfoSource::Error _sourceError;
+
+ // properties (extension of QGeoSatelliteInfoSource for additional Location Manager features)
+ bool _backgroundMode;
+ int _responseTime;
+
+};
+
+#endif
diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro
index c73ba9e1..af2a5009 100644
--- a/src/plugins/position/position.pro
+++ b/src/plugins/position/position.pro
@@ -3,6 +3,7 @@ TEMPLATE = subdirs
config_geoclue:SUBDIRS += geoclue
config_gypsy:SUBDIRS += gypsy
simulator:SUBDIRS += simulator
+blackberry:SUBDIRS += blackberry
SUBDIRS += \
positionpoll