Log File Position Source (C++) | Qt Positioning 5.12.5

Qt 5.12 | Qt Positioning | Qt Positioning Examples | Log File Position Source (C++)

Qt 5.12.5 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);
                  }
              }
          }
      }

Files:

- logfilepositionsource/clientapplication.cpp
- logfilepositionsource/clientapplication.h
- logfilepositionsource/logfile.qrc
- logfilepositionsource/logfilepositionsource.cpp
- logfilepositionsource/logfilepositionsource.h
- logfilepositionsource/logfilepositionsource.pro
- logfilepositionsource/main.cpp