- Qt 5.15
- Qt Positioning
- Qt Positioning Examples
- Log File Position Source (C++)
- Qt 5.15.18 Reference Documentation

# 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() 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;
         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() 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(":/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);
                 }
             }
         }
     }

Example project @ code.qt.io