Example: Creating a custom location data source
Generally, the capabilities provided by the default position source as returned by QGeoPositionInfoSource::createDefaultSource(), along with the QNmeaPositionInfoSource class, are sufficient for retrieving location data. However, in some cases developers may wish to write their own custom location data sources.
The LogFilePositionSource class in examples/logfilepositionsource shows how to subclass QGeoPositionInfoSource to create a custom location data source.
This example class reads location data from a text file, log.txt. The file specifies location data using a simple text format: it contains one location update per line, where each line contains a date/time, a latitude and a longitude, separated by spaces. The date/time is in ISO 8601 format and the latitude and longitude are in degrees decimal format. Here is an excerpt from log.txt:
2009-08-24T22:25:01 -27.576082 153.092415
2009-08-24T22:25:02 -27.576223 153.092530
2009-08-24T22:25:03 -27.576364 153.092648
The class reads this data and distributes it via the positionUpdated() signal.
Here is the definition of the LogFilePositionSource class:
class LogFilePositionSource : public QGeoPositionInfoSource
{
Q_OBJECT
public:
LogFilePositionSource(QObject *parent = 0);
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const;
PositioningMethods supportedPositioningMethods() const;
int minimumUpdateInterval() const;
public slots:
virtual void startUpdates();
virtual void stopUpdates();
virtual void requestUpdate(int timeout = 5000);
private slots:
void readNextPosition();
private:
QFile *logFile;
QTimer *timer;
QGeoPositionInfo lastPosition;
};
The main methods overrided by the subclass are:
- startUpdates(): called by client applications to start regular position updates
- stopUpdates(): called by client applications to stop regular position updates
- requestUpdate(): called by client applications to request a single update, with a specified timeout
When a position update is available, the subclass emits the positionUpdated() signal.
Here are the key methods in the class implementation:
LogFilePositionSource::LogFilePositionSource(QObject *parent)
: QGeoPositionInfoSource(parent),
logFile(new QFile(this)),
timer(new QTimer(this))
{
connect(timer, SIGNAL(timeout()), this, SLOT(readNextPosition()));
logFile->setFileName(QCoreApplication::applicationDirPath()
+ QDir::separator() + "simplelog.txt");
if (!logFile->open(QIODevice::ReadOnly))
qWarning() << "Error: cannot open source file" << logFile->fileName();
}
void LogFilePositionSource::startUpdates()
{
int interval = updateInterval();
if (interval < minimumUpdateInterval())
interval = minimumUpdateInterval();
timer->start(interval);
}
void LogFilePositionSource::stopUpdates()
{
timer->stop();
}
void LogFilePositionSource::requestUpdate(int )
{
if (logFile->canReadLine())
readNextPosition();
else
emit requestTimeout();
}
void LogFilePositionSource::readNextPosition()
{
QByteArray line = logFile->readLine().trimmed();
if (!line.isEmpty()) {
QList<QByteArray> data = line.split(' ');
double latitude;
double longitude;
bool hasLatitude = false;
bool hasLongitude = false;
QDateTime dateTime = QDateTime::fromString(QString(data.value(0)), Qt::ISODate);
latitude = data.value(1).toDouble(&hasLatitude);
longitude = data.value(2).toDouble(&hasLongitude);
if (hasLatitude && hasLongitude && dateTime.isValid()) {
QGeoCoordinate coordinate(latitude, longitude);
QGeoPositionInfo info(coordinate, dateTime);
if (info.isValid()) {
lastPosition = info;
emit positionUpdated(info);
}
}
}
}
The example includes a ClientApplication class that requests updates from the LogFilePositionSource class. Run the exaple to see the data that is received by ClientApplication.
Before running the example, make sure you have done both make and make install.
Classes