Esempio n. 1
0
void QNmeaPositionInfoSourcePrivate::emitPendingUpdate()
{
    if (m_pendingUpdate.isValid()) {
        m_updateTimeoutSent = false;
        m_noUpdateLastInterval = false;
        emitUpdated(m_pendingUpdate);
        m_pendingUpdate = QGeoPositionInfo();
    } else {
        if (m_noUpdateLastInterval && !m_updateTimeoutSent) {
            m_updateTimeoutSent = true;
            m_pendingUpdate = QGeoPositionInfo();
            emit m_source->updateTimeout();
        }
        m_noUpdateLastInterval = true;
    }
}
Esempio n. 2
0
void QNmeaPositionInfoSourcePrivate::startUpdates()
{
    if (m_invokedStart)
        return;

    m_invokedStart = true;
    m_pendingUpdate = QGeoPositionInfo();
    m_noUpdateLastInterval = false;

    bool initialized = initialize();
    if (!initialized)
        return;

    if (m_updateMode == QNmeaPositionInfoSource::RealTimeMode) {
        // skip over any buffered data - we only want the newest data
        if (m_device->bytesAvailable()) {
            if (m_device->isSequential())
                m_device->readAll();
            else
                m_device->seek(m_device->bytesAvailable());
        }
    }

    if (m_updateTimer)
        m_updateTimer->stop();

    if (m_source->updateInterval() > 0) {
        if (!m_updateTimer)
            m_updateTimer = new QBasicTimer;
        m_updateTimer->start(m_source->updateInterval(), this);
    }

    if (initialized)
        prepareSourceDevice();
}
// 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();
        }
    }
}
// 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;
}
void tst_QNmeaPositionInfoSource::lastKnownPosition()
{
    QNmeaPositionInfoSource source(m_mode);
    QNmeaPositionInfoSourceProxyFactory factory;
    QNmeaPositionInfoSourceProxy *proxy = static_cast<QNmeaPositionInfoSourceProxy*>(factory.createProxy(&source));

    QCOMPARE(proxy->source()->lastKnownPosition(), QGeoPositionInfo());

    // source may need requestUpdate() or startUpdates() to be called to
    // trigger reading of data channel
    QSignalSpy spyTimeout(proxy->source(), SIGNAL(updateTimeout()));
    proxy->source()->requestUpdate(proxy->source()->minimumUpdateInterval());
    QTRY_COMPARE(spyTimeout.count(), 1);

    // If an update is received and startUpdates() or requestUpdate() hasn't
    // been called, it should still be available through lastKnownPosition()
    QDateTime dt = QDateTime::currentDateTime().toUTC();
    proxy->feedUpdate(dt);
    QTRY_COMPARE(proxy->source()->lastKnownPosition().timestamp(), dt);

    QList<QDateTime> dateTimes = createDateTimes(5);
    for (int i=0; i<dateTimes.count(); i++) {
        proxy->source()->requestUpdate();
        proxy->feedUpdate(dateTimes[i]);
        QTRY_COMPARE(proxy->source()->lastKnownPosition().timestamp(), dateTimes[i]);
    }

    proxy->source()->startUpdates();
    dateTimes = createDateTimes(5);
    for (int i=0; i<dateTimes.count(); i++) {
        proxy->feedUpdate(dateTimes[i]);
        QTRY_COMPARE(proxy->source()->lastKnownPosition().timestamp(), dateTimes[i]);
    }
}
Esempio n. 6
0
void QNmeaPositionInfoSourcePrivate::stopUpdates()
{
    m_invokedStart = false;
    if (m_updateTimer)
        m_updateTimer->stop();
    m_pendingUpdate = QGeoPositionInfo();
    m_noUpdateLastInterval = false;
}
    void addTestData_info()
    {
        QTest::addColumn<QGeoPositionInfo>("info");

        QTest::newRow("invalid") << QGeoPositionInfo();

        QTest::newRow("coord") << QGeoPositionInfo(QGeoCoordinate(-27.3422,150.2342), QDateTime());
        QTest::newRow("datetime") << QGeoPositionInfo(QGeoCoordinate(), QDateTime::currentDateTime());

        QList<QGeoPositionInfo::Attribute> attributes = tst_qgeopositioninfo_getAttributes();
        QList<qreal> values = tst_qgeopositioninfo_qrealTestValues();
        for (int i=0; i<attributes.count(); i++) {
            for (int j=0; j<values.count(); j++) {
                QTest::newRow(qPrintable(QString("Attribute %1 = %2").arg(attributes[i]).arg(values[j])))
                        << infoWithAttribute(attributes[i], values[j]);
            }
        }
    }
// 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();
}
/*!
    \internal
*/
void QDeclarativePositionSource::setNmeaSource(const QUrl &nmeaSource)
{
    if (nmeaSource.scheme() == QLatin1String("socket")) {
        if (m_nmeaSocket
                && nmeaSource.host() == m_nmeaSocket->peerName()
                && nmeaSource.port() == m_nmeaSocket->peerPort()) {
            return;
        }

        delete m_nmeaSocket;
        m_nmeaSocket = new QTcpSocket();

        connect(m_nmeaSocket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)> (&QAbstractSocket::error),
                this, &QDeclarativePositionSource::socketError);
        connect(m_nmeaSocket, &QTcpSocket::connected,
                this, &QDeclarativePositionSource::socketConnected);

        m_nmeaSocket->connectToHost(nmeaSource.host(), nmeaSource.port(), QTcpSocket::ReadOnly);
    } else {
        // Strip the filename. This is clumsy but the file may be prefixed in several
        // ways: "file:///", "qrc:///", "/", "" in platform dependent manner.
        QString localFileName = nmeaSource.toString();
        if (!QFile::exists(localFileName)) {
            if (localFileName.startsWith("qrc:///")) {
                localFileName.remove(0, 7);
            } else if (localFileName.startsWith("file:///")) {
                localFileName.remove(0, 7);
            } else if (localFileName.startsWith("qrc:/")) {
                localFileName.remove(0, 5);
            }
            if (!QFile::exists(localFileName) && localFileName.startsWith('/')) {
                localFileName.remove(0,1);
            }
        }
        if (m_nmeaFileName == localFileName)
            return;
        m_nmeaFileName = localFileName;

        PositioningMethods previousPositioningMethods = supportedPositioningMethods();

        // The current position source needs to be deleted
        // because QNmeaPositionInfoSource can be bound only to a one file.
        delete m_nmeaSocket;
        m_nmeaSocket = 0;
        delete m_positionSource;
        m_positionSource = 0;
        setPosition(QGeoPositionInfo());
        // Create the NMEA source based on the given data. QML has automatically set QUrl
        // type to point to correct path. If the file is not found, check if the file actually
        // was an embedded resource file.
        delete m_nmeaFile;
        m_nmeaFile = new QFile(localFileName);
        if (!m_nmeaFile->exists()) {
            localFileName.prepend(":");
            m_nmeaFile->setFileName(localFileName);
        }
        if (m_nmeaFile->exists()) {
#ifdef QDECLARATIVE_POSITION_DEBUG
            qDebug() << "QDeclarativePositionSource NMEA File was found: " << localFileName;
#endif
            m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode);
            (qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setDevice(m_nmeaFile);
            connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
                    this, SLOT(positionUpdateReceived(QGeoPositionInfo)));
            connect(m_positionSource, SIGNAL(error(QGeoPositionInfoSource::Error)),
                    this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error)));
            connect(m_positionSource, SIGNAL(updateTimeout()),
                    this, SLOT(updateTimeoutReceived()));

            setPosition(m_positionSource->lastKnownPosition());
            if (m_active && !m_singleUpdate) {
                // Keep on updating even though source changed
                QTimer::singleShot(0, this, SLOT(start()));
            }
        } else {
            qmlInfo(this) << QStringLiteral("Nmea file not found") << localFileName;
#ifdef QDECLARATIVE_POSITION_DEBUG
            qDebug() << "QDeclarativePositionSource NMEA File was not found: " << localFileName;
#endif
            if (m_active) {
                m_active = false;
                m_singleUpdate = false;
                emit activeChanged();
            }
        }

        if (previousPositioningMethods != supportedPositioningMethods())
            emit supportedPositioningMethodsChanged();
    }

    m_nmeaSource = nmeaSource;
    emit nmeaSourceChanged();
}