Log File Position Source (C++)

The Logfile Position Source shows how to create and work with a custom NMEA position source, for platforms without GPS.

The data is read from a file which has positional data in NMEA format. The resulting time and position information is then displayed to the screen as simple text in date/time and latitude/longitude format.

This example class reads position data from a text file, log.txt . The file specifies position data using a simple text format: it contains one position 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() 信号。

Here is the definition of the LogFilePositionSource 类:

class LogFilePositionSource : public QGeoPositionInfoSource
{
    Q_OBJECT
public:
    LogFilePositionSource(QObject *parent = 0);
    QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const;
    PositioningMethods supportedPositioningMethods() const;
    int minimumUpdateInterval() const;
    Error error() 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() 信号。

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(":/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 /*timeout*/)
{
    // For simplicity, ignore timeout - assume that if data is not available
    // now, no data will be added to the file later
    if (logFile->canReadLine())
        readNextPosition();
    else
        emit updateTimeout();
}
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 timestamp = QDateTime::fromString(QString(data.value(0)), Qt::ISODate);
        latitude = data.value(1).toDouble(&hasLatitude);
        longitude = data.value(2).toDouble(&hasLongitude);
        if (hasLatitude && hasLongitude && timestamp.isValid()) {
            QGeoCoordinate coordinate(latitude, longitude);
            QGeoPositionInfo info(coordinate, timestamp);
            if (info.isValid()) {
                lastPosition = info;
                emit positionUpdated(info);
            }
        }
    }
}
					

范例工程 @ code.qt.io