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; } }
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]); } }
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(); }