Log File Position Source (C++)

Logfile Position Source shows how to create and work with a custom position source. It can be useful for simulating GPS data, or when the data is received in some custom format.

运行范例

要运行范例从 Qt Creator ,打开 Welcome 模式,然后选择范例从 Examples 。更多信息,拜访 构建和运行范例 .

Creating custom Position Source

In this example, the data is read from a text file, simplelog.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 simplelog.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
					

We create a custom LogFilePositionSource class, which derives from QGeoPositionInfoSource . It reads position data from the file and distributes it via the positionUpdated () 信号。

The resulting time and position information is then displayed on the screen as simple text in date/time and latitude/longitude format.

Here is the definition of the LogFilePositionSource 类:

class LogFilePositionSource : public QGeoPositionInfoSource
{
    Q_OBJECT
public:
    LogFilePositionSource(QObject *parent = 0);
    QGeoPositionInfo lastKnownPosition(bool satelliteMethodsOnly = false) const override;
    PositioningMethods supportedPositioningMethods() const override;
    int minimumUpdateInterval() const override;
    Error error() const override;
public slots:
    virtual void startUpdates() override;
    virtual void stopUpdates() override;
    virtual void requestUpdate(int timeout = 5000) override;
private slots:
    void readNextPosition();
private:
    QFile *logFile;
    QTimer *timer;
    QGeoPositionInfo lastPosition;
    Error lastError = QGeoPositionInfoSource::NoError;
};
					

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, &QTimer::timeout, this, &LogFilePositionSource::readNextPosition);
    logFile->setFileName(":/simplelog.txt");
    if (!logFile->open(QIODevice::ReadOnly))
        qWarning() << "Error: cannot open source file" << logFile->fileName();
}
void LogFilePositionSource::startUpdates()
{
    lastError = QGeoPositionInfoSource::NoError;
    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
    lastError = QGeoPositionInfoSource::NoError;
    if (logFile->canReadLine()) {
        readNextPosition();
    } else {
        lastError = QGeoPositionInfoSource::UpdateTimeoutError;
        emit QGeoPositionInfoSource::errorOccurred(lastError);
    }
}
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