src/location/qnmeapositioninfosource.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 #include "qnmeapositioninfosource_p.h"
       
    42 #include "qlocationutils_p.h"
       
    43 
       
    44 #include <QIODevice>
       
    45 #include <QBasicTimer>
       
    46 #include <QTimerEvent>
       
    47 #include <QTimer>
       
    48 
       
    49 QTM_BEGIN_NAMESPACE
       
    50 
       
    51 QNmeaRealTimeReader::QNmeaRealTimeReader(QNmeaPositionInfoSourcePrivate *sourcePrivate)
       
    52         : QNmeaReader(sourcePrivate)
       
    53 {
       
    54 }
       
    55 
       
    56 void QNmeaRealTimeReader::readAvailableData()
       
    57 {
       
    58     QGeoPositionInfo update;
       
    59     bool hasFix = false;
       
    60 
       
    61     char buf[1024];
       
    62     qint64 size = m_proxy->m_device->readLine(buf, sizeof(buf));
       
    63     while (size > 0) {
       
    64         if (m_proxy->parsePosInfoFromNmeaData(buf, size, &update, &hasFix))
       
    65             m_proxy->notifyNewUpdate(&update, hasFix);
       
    66         memset(buf, 0, size);
       
    67         size = m_proxy->m_device->readLine(buf, sizeof(buf));
       
    68     }
       
    69 }
       
    70 
       
    71 
       
    72 //============================================================
       
    73 
       
    74 QNmeaSimulatedReader::QNmeaSimulatedReader(QNmeaPositionInfoSourcePrivate *sourcePrivate)
       
    75         : QNmeaReader(sourcePrivate),
       
    76         m_currTimerId(-1),
       
    77         m_hasValidDateTime(false)
       
    78 {
       
    79 }
       
    80 
       
    81 QNmeaSimulatedReader::~QNmeaSimulatedReader()
       
    82 {
       
    83     if (m_currTimerId > 0)
       
    84         killTimer(m_currTimerId);
       
    85 }
       
    86 
       
    87 void QNmeaSimulatedReader::readAvailableData()
       
    88 {
       
    89     if (m_currTimerId > 0)     // we are already reading
       
    90         return;
       
    91 
       
    92     if (!m_hasValidDateTime) {      // first update
       
    93         Q_ASSERT(m_proxy->m_device && (m_proxy->m_device->openMode() & QIODevice::ReadOnly));
       
    94 
       
    95         if (!setFirstDateTime()) {
       
    96             //m_proxy->notifyReachedEndOfFile();
       
    97             qWarning("QNmeaPositionInfoSource: cannot find NMEA sentence with valid date & time");
       
    98             return;
       
    99         }
       
   100 
       
   101         m_hasValidDateTime = true;
       
   102         simulatePendingUpdate();
       
   103 
       
   104     } else {
       
   105         // previously read to EOF, but now new data has arrived
       
   106         processNextSentence();
       
   107     }
       
   108 }
       
   109 
       
   110 bool QNmeaSimulatedReader::setFirstDateTime()
       
   111 {
       
   112     // find the first update with valid date and time
       
   113     QGeoPositionInfo update;
       
   114     bool hasFix = false;
       
   115     while (m_proxy->m_device->bytesAvailable() > 0) {
       
   116         char buf[1024];
       
   117         qint64 size = m_proxy->m_device->readLine(buf, sizeof(buf));
       
   118         if (size <= 0)
       
   119             continue;
       
   120         bool ok = m_proxy->parsePosInfoFromNmeaData(buf, size, &update, &hasFix);
       
   121         if (ok && update.timestamp().isValid()) {
       
   122             QPendingGeoPositionInfo pending;
       
   123             pending.info = update;
       
   124             pending.hasFix = hasFix;
       
   125             m_pendingUpdates.enqueue(pending);
       
   126             return true;
       
   127         }
       
   128     }
       
   129     return false;
       
   130 }
       
   131 
       
   132 void QNmeaSimulatedReader::simulatePendingUpdate()
       
   133 {
       
   134     if (m_pendingUpdates.size() > 0) {
       
   135         // will be dequeued in processNextSentence()
       
   136         QPendingGeoPositionInfo &pending = m_pendingUpdates.head();
       
   137         if (pending.info.coordinate().type() != QGeoCoordinate::InvalidCoordinate)
       
   138             m_proxy->notifyNewUpdate(&pending.info, pending.hasFix);
       
   139     }
       
   140 
       
   141     processNextSentence();
       
   142 }
       
   143 
       
   144 void QNmeaSimulatedReader::timerEvent(QTimerEvent *event)
       
   145 {
       
   146     killTimer(event->timerId());
       
   147     m_currTimerId = -1;
       
   148     simulatePendingUpdate();
       
   149 }
       
   150 
       
   151 void QNmeaSimulatedReader::processNextSentence()
       
   152 {
       
   153     QGeoPositionInfo info;
       
   154     bool hasFix = false;
       
   155     int timeToNextUpdate = -1;
       
   156     QTime prevTime;
       
   157     if (m_pendingUpdates.size() > 0)
       
   158         prevTime = m_pendingUpdates.head().info.timestamp().time();
       
   159 
       
   160     // find the next update with a valid time (as long as the time is valid,
       
   161     // we can calculate when the update should be emitted)
       
   162     while (m_proxy->m_device && m_proxy->m_device->bytesAvailable() > 0) {
       
   163         char buf[1024];
       
   164         qint64 size = m_proxy->m_device->readLine(buf, sizeof(buf));
       
   165         if (size <= 0)
       
   166             continue;
       
   167         if (m_proxy->parsePosInfoFromNmeaData(buf, size, &info, &hasFix)) {
       
   168             QTime time = info.timestamp().time();
       
   169             if (time.isValid()) {
       
   170                 if (!prevTime.isValid()) {
       
   171                     timeToNextUpdate = 0;
       
   172                     break;
       
   173                 }
       
   174                 timeToNextUpdate = prevTime.msecsTo(time);
       
   175                 if (timeToNextUpdate >= 0)
       
   176                     break;
       
   177             }
       
   178         }
       
   179     }
       
   180 
       
   181     if (timeToNextUpdate < 0)
       
   182         return;
       
   183 
       
   184     m_pendingUpdates.dequeue();
       
   185 
       
   186     QPendingGeoPositionInfo pending;
       
   187     pending.info = info;
       
   188     pending.hasFix = hasFix;
       
   189     m_pendingUpdates.enqueue(pending);
       
   190     m_currTimerId = startTimer(timeToNextUpdate);
       
   191 }
       
   192 
       
   193 
       
   194 //============================================================
       
   195 
       
   196 
       
   197 QNmeaPositionInfoSourcePrivate::QNmeaPositionInfoSourcePrivate(QNmeaPositionInfoSource *parent)
       
   198         : QObject(parent),
       
   199         m_invokedStart(false),
       
   200         m_source(parent),
       
   201         m_nmeaReader(0),
       
   202         m_updateTimer(0),
       
   203         m_requestTimer(0),
       
   204         m_noUpdateLastInterval(false),
       
   205         m_updateTimeoutSent(false),
       
   206         m_connectedReadyRead(false)
       
   207 {
       
   208 }
       
   209 
       
   210 QNmeaPositionInfoSourcePrivate::~QNmeaPositionInfoSourcePrivate()
       
   211 {
       
   212     delete m_nmeaReader;
       
   213     delete m_updateTimer;
       
   214 }
       
   215 
       
   216 bool QNmeaPositionInfoSourcePrivate::openSourceDevice()
       
   217 {
       
   218     if (!m_device) {
       
   219         qWarning("QNmeaPositionInfoSource: no QIODevice data source, call setDevice() first");
       
   220         return false;
       
   221     }
       
   222 
       
   223     if (!m_device->isOpen() && !m_device->open(QIODevice::ReadOnly)) {
       
   224         qWarning("QNmeaPositionInfoSource: cannot open QIODevice data source");
       
   225         return false;
       
   226     }
       
   227 
       
   228     connect(m_device, SIGNAL(aboutToClose()), SLOT(sourceDataClosed()));
       
   229     connect(m_device, SIGNAL(readChannelFinished()), SLOT(sourceDataClosed()));
       
   230     connect(m_device, SIGNAL(destroyed()), SLOT(sourceDataClosed()));
       
   231 
       
   232     return true;
       
   233 }
       
   234 
       
   235 void QNmeaPositionInfoSourcePrivate::sourceDataClosed()
       
   236 {
       
   237     if (m_nmeaReader && m_device && m_device->bytesAvailable())
       
   238         m_nmeaReader->readAvailableData();
       
   239 }
       
   240 
       
   241 void QNmeaPositionInfoSourcePrivate::readyRead()
       
   242 {
       
   243     if (m_nmeaReader)
       
   244         m_nmeaReader->readAvailableData();
       
   245 }
       
   246 
       
   247 bool QNmeaPositionInfoSourcePrivate::initialize()
       
   248 {
       
   249     if (m_nmeaReader)
       
   250         return true;
       
   251 
       
   252     if (!openSourceDevice())
       
   253         return false;
       
   254 
       
   255     if (m_updateMode == QNmeaPositionInfoSource::RealTimeMode)
       
   256         m_nmeaReader = new QNmeaRealTimeReader(this);
       
   257     else
       
   258         m_nmeaReader = new QNmeaSimulatedReader(this);
       
   259 
       
   260     return true;
       
   261 }
       
   262 
       
   263 void QNmeaPositionInfoSourcePrivate::prepareSourceDevice()
       
   264 {
       
   265     // some data may already be available
       
   266     if (m_updateMode == QNmeaPositionInfoSource::SimulationMode) {
       
   267         if (m_nmeaReader && m_device->bytesAvailable())
       
   268             m_nmeaReader->readAvailableData();
       
   269     }
       
   270 
       
   271     if (!m_connectedReadyRead) {
       
   272         connect(m_device, SIGNAL(readyRead()), SLOT(readyRead()));
       
   273         m_connectedReadyRead = true;
       
   274     }
       
   275 }
       
   276 
       
   277 bool QNmeaPositionInfoSourcePrivate::parsePosInfoFromNmeaData(const char *data, int size,
       
   278         QGeoPositionInfo *posInfo, bool *hasFix)
       
   279 {
       
   280     return m_source->parsePosInfoFromNmeaData(data, size, posInfo, hasFix);
       
   281 }
       
   282 
       
   283 void QNmeaPositionInfoSourcePrivate::startUpdates()
       
   284 {
       
   285     if (m_invokedStart)
       
   286         return;
       
   287 
       
   288     m_invokedStart = true;
       
   289     m_pendingUpdate = QGeoPositionInfo();
       
   290     m_noUpdateLastInterval = false;
       
   291 
       
   292     bool initialized = initialize();
       
   293     if (!initialized)
       
   294         return;
       
   295 
       
   296     if (m_updateMode == QNmeaPositionInfoSource::RealTimeMode) {
       
   297         // skip over any buffered data - we only want the newest data
       
   298         if (m_device->bytesAvailable()) {
       
   299             if (m_device->isSequential())
       
   300                 m_device->readAll();
       
   301             else
       
   302                 m_device->seek(m_device->bytesAvailable());
       
   303         }
       
   304     }
       
   305 
       
   306     if (m_updateTimer)
       
   307         m_updateTimer->stop();
       
   308 
       
   309     if (m_source->updateInterval() > 0) {
       
   310         if (!m_updateTimer)
       
   311             m_updateTimer = new QBasicTimer;
       
   312         m_updateTimer->start(m_source->updateInterval(), this);
       
   313     }
       
   314 
       
   315     if (initialized)
       
   316         prepareSourceDevice();
       
   317 }
       
   318 
       
   319 void QNmeaPositionInfoSourcePrivate::stopUpdates()
       
   320 {
       
   321     m_invokedStart = false;
       
   322     if (m_updateTimer)
       
   323         m_updateTimer->stop();
       
   324     m_pendingUpdate = QGeoPositionInfo();
       
   325     m_noUpdateLastInterval = false;
       
   326 }
       
   327 
       
   328 void QNmeaPositionInfoSourcePrivate::requestUpdate(int msec)
       
   329 {
       
   330     if (m_requestTimer && m_requestTimer->isActive())
       
   331         return;
       
   332 
       
   333     if (msec <= 0 || msec < m_source->minimumUpdateInterval()) {
       
   334         emit m_source->updateTimeout();
       
   335         return;
       
   336     }
       
   337 
       
   338     if (!m_requestTimer) {
       
   339         m_requestTimer = new QTimer(this);
       
   340         connect(m_requestTimer, SIGNAL(timeout()), SLOT(updateRequestTimeout()));
       
   341     }
       
   342 
       
   343     bool initialized = initialize();
       
   344     if (!initialized) {
       
   345         emit m_source->updateTimeout();
       
   346         return;
       
   347     }
       
   348 
       
   349     m_requestTimer->start(msec);
       
   350 
       
   351     if (initialized)
       
   352         prepareSourceDevice();
       
   353 }
       
   354 
       
   355 void QNmeaPositionInfoSourcePrivate::updateRequestTimeout()
       
   356 {
       
   357     m_requestTimer->stop();
       
   358     emit m_source->updateTimeout();
       
   359 }
       
   360 
       
   361 void QNmeaPositionInfoSourcePrivate::notifyNewUpdate(QGeoPositionInfo *update, bool hasFix)
       
   362 {
       
   363     // include <QDebug> before uncommenting
       
   364     //qDebug() << "QNmeaPositionInfoSourcePrivate::notifyNewUpdate()" << update->timestamp() << hasFix << m_invokedStart << (m_requestTimer && m_requestTimer->isActive());
       
   365 
       
   366     QDate date = update->timestamp().date();
       
   367     if (date.isValid()) {
       
   368         m_currentDate = date;
       
   369     } else {
       
   370         // some sentence have time but no date
       
   371         QTime time = update->timestamp().time();
       
   372         if (time.isValid() && m_currentDate.isValid())
       
   373             update->setTimestamp(QDateTime(m_currentDate, time, Qt::UTC));
       
   374     }
       
   375 
       
   376     if (hasFix && update->isValid()) {
       
   377         if (m_requestTimer && m_requestTimer->isActive()) {
       
   378             m_requestTimer->stop();
       
   379             emitUpdated(*update);
       
   380         } else if (m_invokedStart) {
       
   381             if (m_updateTimer && m_updateTimer->isActive()) {
       
   382                 // for periodic updates, only want the most recent update
       
   383                 m_pendingUpdate = *update;
       
   384                 if (m_noUpdateLastInterval) {
       
   385                     emitPendingUpdate();
       
   386                     m_noUpdateLastInterval = false;
       
   387                 }
       
   388             } else {
       
   389                 emitUpdated(*update);
       
   390             }
       
   391         }
       
   392         m_lastUpdate = *update;
       
   393     }
       
   394 }
       
   395 
       
   396 void QNmeaPositionInfoSourcePrivate::timerEvent(QTimerEvent *)
       
   397 {
       
   398     emitPendingUpdate();
       
   399 }
       
   400 
       
   401 void QNmeaPositionInfoSourcePrivate::emitPendingUpdate()
       
   402 {
       
   403     if (m_pendingUpdate.isValid()) {
       
   404         m_updateTimeoutSent = false;
       
   405         m_noUpdateLastInterval = false;
       
   406         emitUpdated(m_pendingUpdate);
       
   407         m_pendingUpdate = QGeoPositionInfo();
       
   408     } else {
       
   409         if (m_noUpdateLastInterval && !m_updateTimeoutSent) {
       
   410             m_updateTimeoutSent = true;
       
   411             m_pendingUpdate = QGeoPositionInfo();
       
   412             emit m_source->updateTimeout();
       
   413         }
       
   414         m_noUpdateLastInterval = true;
       
   415     }
       
   416 }
       
   417 
       
   418 void QNmeaPositionInfoSourcePrivate::emitUpdated(const QGeoPositionInfo &update)
       
   419 {
       
   420     m_lastUpdate = update;
       
   421     emit m_source->positionUpdated(update);
       
   422 }
       
   423 
       
   424 //=========================================================
       
   425 
       
   426 /*!
       
   427     \class QNmeaPositionInfoSource
       
   428     \brief The QNmeaPositionInfoSource class provides positional information using a NMEA data source.
       
   429     \ingroup location
       
   430 
       
   431     NMEA is a commonly used protocol for the specification of one's global
       
   432     position at a certain point in time. The QNmeaPositionInfoSource class reads NMEA
       
   433     data and uses it to provide positional data in the form of
       
   434     QGeoPositionInfo objects.
       
   435 
       
   436     A QNmeaPositionInfoSource instance operates in either \l {RealTimeMode} or
       
   437     \l {SimulationMode}. These modes allow NMEA data to be read from either a
       
   438     live source of positional data, or replayed for simulation purposes from
       
   439     previously recorded NMEA data.
       
   440 
       
   441     The source of NMEA data is set with setDevice().
       
   442 
       
   443     Use startUpdates() to start receiving regular position updates and stopUpdates() to stop these
       
   444     updates.  If you only require updates occasionally, you can call requestUpdate() to request a
       
   445     single update.
       
   446 
       
   447     In both cases the position information is received via the positionUpdated() signal and the
       
   448     last known position can be accessed with lastKnownPosition().
       
   449 */
       
   450 
       
   451 
       
   452 /*!
       
   453     \enum QNmeaPositionInfoSource::UpdateMode
       
   454     Defines the available update modes.
       
   455 
       
   456     \value RealTimeMode Positional data is read and distributed from the data source as it becomes available. Use this mode if you are using a live source of positional data (for example, a GPS hardware device).
       
   457     \value SimulationMode The data and time information in the NMEA source data is used to provide positional updates at the rate at which the data was originally recorded. Use this mode if the data source contains previously recorded NMEA data and you want to replay the data for simulation purposes.
       
   458 */
       
   459 
       
   460 
       
   461 /*!
       
   462     Constructs a QNmeaPositionInfoSource instance with the given \a parent
       
   463     and \a updateMode.
       
   464 */
       
   465 QNmeaPositionInfoSource::QNmeaPositionInfoSource(UpdateMode updateMode, QObject *parent)
       
   466         : QGeoPositionInfoSource(parent),
       
   467         d(new QNmeaPositionInfoSourcePrivate(this))
       
   468 {
       
   469     d->m_updateMode = updateMode;
       
   470     d->m_device = 0;
       
   471 }
       
   472 
       
   473 /*!
       
   474     Destroys the position source.
       
   475 */
       
   476 QNmeaPositionInfoSource::~QNmeaPositionInfoSource()
       
   477 {
       
   478     delete d;
       
   479 }
       
   480 
       
   481 /*!
       
   482     Parses an NMEA sentence string into a QGeoPositionInfo.
       
   483 
       
   484     The default implementation will parse standard NMEA sentences.
       
   485     This method should be reimplemented in a subclass whenever the need to deal with non-standard
       
   486     NMEA sentences arises.
       
   487 
       
   488     The parser reads \a size bytes from \a data and uses that information to setup \a posInfo and
       
   489     \a hasFix.  If \a hasFix is set to false then \a posInfo may contain only the time or the date
       
   490     and the time.
       
   491 
       
   492     Returns true if the sentence was succsesfully parsed, otherwise returns false and should not
       
   493     modifiy \a posInfo or \a hasFix.
       
   494 */
       
   495 bool QNmeaPositionInfoSource::parsePosInfoFromNmeaData(const char *data, int size,
       
   496         QGeoPositionInfo *posInfo, bool *hasFix)
       
   497 {
       
   498     return QLocationUtils::getPosInfoFromNmea(data, size, posInfo, hasFix);
       
   499 }
       
   500 
       
   501 /*!
       
   502     Returns the update mode.
       
   503 */
       
   504 QNmeaPositionInfoSource::UpdateMode QNmeaPositionInfoSource::updateMode() const
       
   505 {
       
   506     return d->m_updateMode;
       
   507 }
       
   508 
       
   509 /*!
       
   510     Sets the NMEA data source to \a device. If the device is not open, it
       
   511     will be opened in QIODevice::ReadOnly mode.
       
   512 
       
   513     The source device can only be set once and must be set before calling
       
   514     startUpdates() or requestUpdate().
       
   515 
       
   516     \bold {Note:} The \a device must emit QIODevice::readyRead() for the
       
   517     source to be notified when data is available for reading.
       
   518 */
       
   519 void QNmeaPositionInfoSource::setDevice(QIODevice *device)
       
   520 {
       
   521     if (device != d->m_device) {
       
   522         if (!d->m_device)
       
   523             d->m_device = device;
       
   524         else
       
   525             qWarning("QNmeaPositionInfoSource: source device has already been set");
       
   526     }
       
   527 }
       
   528 
       
   529 /*!
       
   530     Returns the NMEA data source.
       
   531 */
       
   532 QIODevice *QNmeaPositionInfoSource::device() const
       
   533 {
       
   534     return d->m_device;
       
   535 }
       
   536 
       
   537 /*!
       
   538     \reimp
       
   539 */
       
   540 void QNmeaPositionInfoSource::setUpdateInterval(int msec)
       
   541 {
       
   542     int interval = msec;
       
   543     if (interval != 0)
       
   544         interval = qMax(msec, minimumUpdateInterval());
       
   545     QGeoPositionInfoSource::setUpdateInterval(interval);
       
   546     if (d->m_invokedStart) {
       
   547         d->stopUpdates();
       
   548         d->startUpdates();
       
   549     }
       
   550 }
       
   551 
       
   552 /*!
       
   553     \reimp
       
   554 */
       
   555 void QNmeaPositionInfoSource::startUpdates()
       
   556 {
       
   557     d->startUpdates();
       
   558 }
       
   559 
       
   560 /*!
       
   561     \reimp
       
   562 */
       
   563 void QNmeaPositionInfoSource::stopUpdates()
       
   564 {
       
   565     d->stopUpdates();
       
   566 }
       
   567 
       
   568 /*!
       
   569     \reimp
       
   570 */
       
   571 void QNmeaPositionInfoSource::requestUpdate(int msec)
       
   572 {
       
   573     d->requestUpdate(msec == 0 ? 60000 * 5 : msec);
       
   574 }
       
   575 
       
   576 /*!
       
   577     \reimp
       
   578 */
       
   579 QGeoPositionInfo QNmeaPositionInfoSource::lastKnownPosition(bool) const
       
   580 {
       
   581     // the bool value does not matter since we only use satellite positioning
       
   582     return d->m_lastUpdate;
       
   583 }
       
   584 
       
   585 /*!
       
   586     \reimp
       
   587 */
       
   588 QGeoPositionInfoSource::PositioningMethods QNmeaPositionInfoSource::supportedPositioningMethods() const
       
   589 {
       
   590     return SatellitePositioningMethods;
       
   591 }
       
   592 
       
   593 /*!
       
   594     \reimp
       
   595 */
       
   596 int QNmeaPositionInfoSource::minimumUpdateInterval() const
       
   597 {
       
   598     return 100;
       
   599 }
       
   600 
       
   601 #include "moc_qnmeapositioninfosource.cpp"
       
   602 #include "moc_qnmeapositioninfosource_p.cpp"
       
   603 
       
   604 QTM_END_NAMESPACE