summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Ehrismann <jehrismann@blackberry.com>2013-10-24 16:22:40 -0400
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-11 08:14:40 +0100
commit091510cca0bb20a063a7eb4b54feda7732c1f4ad (patch)
tree2fb808a8c46975c1ceb3c9dc286a56ca59c3aac5
parente3db0e405d771e11fa6b4f98d39e90b32db9d612 (diff)
downloadqtlocation-091510cca0bb20a063a7eb4b54feda7732c1f4ad.tar.gz
Add BlackBerry positioning plugin for QtLocation
Note files in bb subfolder are considered temporary and will be removed when equivalent functionality has been incorporated in Qt Core or BB10 core on Qt5. Change-Id: I08d2c771d18914525fad410f1b6e83772ef3a0d7 Reviewed-by: Fabian Bumberger <fbumberger@rim.com> Reviewed-by: Liang Qi <liang.qi@digia.com>
-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