Revision control

Copy as Markdown

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtPositioning/qgeopositioninfosourcefactory.h>
#include <QtPositioning/qgeosatelliteinfosource.h>
#include <QObject>
#include <QtPlugin>
#include <QTimer>
QT_USE_NAMESPACE
using namespace Qt::StringLiterals;
class SatelliteSource : public QGeoSatelliteInfoSource
{
Q_OBJECT
public:
SatelliteSource(const QVariantMap &parameters, QObject *parent=0);
~SatelliteSource();
void startUpdates() override;
void stopUpdates() override;
void requestUpdate(int timeout = 5000) override;
void setUpdateInterval(int msec) override;
int minimumUpdateInterval() const override;
Error error() const override;
bool setBackendProperty(const QString &name, const QVariant &value) override;
QVariant backendProperty(const QString &name) const override;
private slots:
void doTimeout();
void updateSatelliteInfo();
private:
QTimer *timer;
QTimer *timeoutTimer;
QTimer *singleUpdateTimer;
Error lastError = QGeoSatelliteInfoSource::NoError;
QList<QGeoSatelliteInfo> satellitesInView;
QList<QGeoSatelliteInfo> satellitesInUse;
qsizetype desiredInViewCount = 5;
qsizetype desiredInUseCount = 3;
bool useElevation = false;
bool useAzimuth = false;
QGeoSatelliteInfo::SatelliteSystem desiredSystem = QGeoSatelliteInfo::GPS;
};
SatelliteSource::SatelliteSource(const QVariantMap &parameters, QObject *parent)
: QGeoSatelliteInfoSource(parent),
timer(new QTimer(this)),
timeoutTimer(new QTimer(this)),
singleUpdateTimer(new QTimer(this))
{
QVariant systemType = parameters.value("satellitesystem"_L1, QVariant());
if (systemType.isValid())
desiredSystem = systemType.value<QGeoSatelliteInfo::SatelliteSystem>();
timer->setInterval(200);
connect(timer, &QTimer::timeout, this, &SatelliteSource::updateSatelliteInfo);
connect(singleUpdateTimer, &QTimer::timeout, this, &SatelliteSource::updateSatelliteInfo);
connect(timeoutTimer, &QTimer::timeout, this, &SatelliteSource::doTimeout);
}
SatelliteSource::~SatelliteSource()
{
}
QGeoSatelliteInfoSource::Error SatelliteSource::error() const
{
return lastError;
}
bool SatelliteSource::setBackendProperty(const QString &name, const QVariant &value)
{
if (name == "desiredInViewCount"_L1)
desiredInViewCount = value.value<qsizetype>();
else if (name == "desiredInUseCount"_L1)
desiredInUseCount = value.value<qsizetype>();
else if (name == "useElevation"_L1)
useElevation = value.toBool();
else if (name == "useAzimuth"_L1)
useAzimuth = value.toBool();
else
return false;
return true;
}
QVariant SatelliteSource::backendProperty(const QString &name) const
{
if (name == "desiredInViewCount"_L1)
return desiredInViewCount;
else if (name == "desiredInUseCount"_L1)
return desiredInUseCount;
else if (name == "useElevation"_L1)
return useElevation;
else if (name == "useAzimuth"_L1)
return useAzimuth;
return {};
}
void SatelliteSource::setUpdateInterval(int msec)
{
const int minInterval = minimumUpdateInterval();
if (msec == 0) {
timer->setInterval(minInterval);
} else if (msec < minInterval) {
msec = minInterval;
timer->setInterval(msec);
} else {
timer->setInterval(msec);
}
QGeoSatelliteInfoSource::setUpdateInterval(msec);
}
int SatelliteSource::minimumUpdateInterval() const
{
return 200;
}
void SatelliteSource::startUpdates()
{
lastError = QGeoSatelliteInfoSource::NoError;
timer->start();
}
void SatelliteSource::stopUpdates()
{
timer->stop();
}
void SatelliteSource::requestUpdate(int timeout)
{
if (timeoutTimer->isActive())
return; // already requested an update
lastError = QGeoSatelliteInfoSource::NoError;
// Such logic for timeout handling is needed for tst_qgeosatelliteinfosource.
// It expects an immediate error in case of negative timeout.
if (timeout == 0)
timeout = 5000;
if (timeout < 0)
timeout = 0;
timeoutTimer->setInterval(timeout);
timeoutTimer->start();
if (timer->isActive()) {
timer->stop();
timer->start();
}
singleUpdateTimer->start(minimumUpdateInterval());
}
void SatelliteSource::doTimeout()
{
timeoutTimer->stop();
singleUpdateTimer->stop();
lastError = QGeoSatelliteInfoSource::UpdateTimeoutError;
emit errorOccurred(lastError);
}
void SatelliteSource::updateSatelliteInfo()
{
timeoutTimer->stop();
singleUpdateTimer->stop();
if (desiredInUseCount > desiredInViewCount)
desiredInUseCount = desiredInViewCount;
satellitesInView.clear();
satellitesInUse.clear();
for (qsizetype i = 0; i < desiredInViewCount; ++i) {
QGeoSatelliteInfo si;
si.setSatelliteSystem(desiredSystem);
si.setSatelliteIdentifier(i + 1);
si.setSignalStrength(5 * (i + 1));
if (useElevation)
si.setAttribute(QGeoSatelliteInfo::Elevation, 3.0 * (i + 1));
if (useAzimuth)
si.setAttribute(QGeoSatelliteInfo::Azimuth, 0.5 * (i + 1));
satellitesInView.push_back(si);
if (i < desiredInUseCount)
satellitesInUse.push_back(si);
}
emit satellitesInViewUpdated(satellitesInView);
emit satellitesInUseUpdated(satellitesInUse);
}
class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/6.0"
FILE "plugin.json")
Q_INTERFACES(QGeoPositionInfoSourceFactory)
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent,
const QVariantMap &parameters) override;
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent,
const QVariantMap &parameters) override;
QGeoAreaMonitorSource *areaMonitor(QObject *parent, const QVariantMap &parameters) override;
};
QGeoPositionInfoSource *
QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent, const QVariantMap &parameters)
{
Q_UNUSED(parent);
Q_UNUSED(parameters);
return nullptr;
}
QGeoSatelliteInfoSource *
QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(QObject *parent, const QVariantMap &parameters)
{
return new SatelliteSource(parameters, parent);
}
QGeoAreaMonitorSource *
QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject *parent, const QVariantMap &parameters)
{
Q_UNUSED(parent);
Q_UNUSED(parameters);
return nullptr;
}
#include "plugin.moc"