The SatelliteInfo example shows the available satellites at the user's current position and marks the satellites currently contributing to the GPS fix as pink.
Key Qt Positioning 类被用于此范例:
The example displays the signal strength of all satellites in view. Any satellite that is currently used to calculate the GPS fix is marked pink. The number at the bottom of each signal bar is the individual satellite identifier.
The application operates in three different modes:
应用程序模式 | 描述 |
---|---|
running | The application continuously queries the system for satellite updates. When new data is available it will be displayed. |
stopped | The application stops updating the satellite information. |
single | The application makes a single update request with a timeout of 10s. The display remains empty until the request was answered by the system. |
If the platform does not provide satellite information, the application automatically switches into a demo mode, whereby it continuously switches between predefined sets of satellite data.
要运行范例从 Qt Creator ,打开 欢迎 模式,然后选择范例从 范例 。更多信息,拜访 构建和运行范例 .
The key part of this example is the
SatelliteModel
data model. It represents the information about the satellites. It uses the
Q_PROPERTY
and
QML_ELEMENT
macros, so that it can be available from QML.
class SatelliteModel : public QAbstractListModel, public QQmlParserStatus { Q_OBJECT Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged) Q_PROPERTY(bool satelliteInfoAvailable READ canProvideSatelliteInfo NOTIFY canProvideSatelliteInfoChanged) Q_PROPERTY(int entryCount READ entryCount NOTIFY entryCountChanged) Q_PROPERTY(bool singleRequestMode READ isSingleRequest WRITE setSingleRequest NOTIFY singleRequestChanged) Q_INTERFACES(QQmlParserStatus) QML_ELEMENT public: explicit SatelliteModel(QObject *parent = 0); enum { IdentifierRole = Qt::UserRole + 1, InUseRole, SignalStrengthRole, ElevationRole, AzimuthRole }; //From QAbstractListModel int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; QHash<int, QByteArray> roleNames() const override; //From QQmlParserStatus void classBegin() override {} void componentComplete() override; signals: void runningChanged(); void entryCountChanged(); void errorFound(int code); void canProvideSatelliteInfoChanged(); void singleRequestChanged(); public slots: void clearModel(); void updateDemoData(); };
SatelliteModel
object creates an instance of
QGeoSatelliteInfoSource
使用
createDefaultSource()
method. Once the source is created, the
satellitesInViewUpdated()
and
satellitesInUseUpdated()
signals are used to notify about the changes in satellite information.
SatelliteModel::SatelliteModel(QObject *parent) : QAbstractListModel(parent), source(0), m_componentCompleted(false), m_running(false), m_runningRequested(false), demo(false), isSingle(false), singleRequestServed(false) { source = QGeoSatelliteInfoSource::createDefaultSource(this); if (!demo && !source) { qWarning() << "No satellite data source found. Changing to demo mode."; demo = true; } if (!demo) { source->setUpdateInterval(3000); connect(source, SIGNAL(satellitesInViewUpdated(QList<QGeoSatelliteInfo>)), this, SLOT(satellitesInViewUpdated(QList<QGeoSatelliteInfo>))); connect(source, SIGNAL(satellitesInUseUpdated(QList<QGeoSatelliteInfo>)), this, SLOT(satellitesInUseUpdated(QList<QGeoSatelliteInfo>))); connect(source, SIGNAL(errorOccurred(QGeoSatelliteInfoSource::Error)), this, SLOT(error(QGeoSatelliteInfoSource::Error))); } if (demo) { timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateDemoData())); timer->start(3000); } }
The aforementioned signals provide the lists of QGeoSatelliteInfo objects that represent satellites in view and satellites in use, respectively. This data is used to update the model.
void SatelliteModel::satellitesInViewUpdated(const QList<QGeoSatelliteInfo> &infos) { if (!running()) return; int oldEntryCount = knownSatellites.count(); QSet<int> satelliteIdsInUpdate; foreach (const QGeoSatelliteInfo &info, infos) satelliteIdsInUpdate.insert(info.satelliteIdentifier()); QSet<int> toBeRemoved = knownSatelliteIds - satelliteIdsInUpdate; //We reset the model as in reality just about all entry values change //and there are generally a lot of inserts and removals each time //Hence we don't bother with complex model update logic beyond resetModel() beginResetModel(); knownSatellites = infos; //sort them for presentation purposes std::sort(knownSatellites.begin(), knownSatellites.end()); //remove old "InUse" data //new satellites are by default not in "InUse" //existing satellites keep their "inUse" state satellitesInUse -= toBeRemoved; knownSatelliteIds = satelliteIdsInUpdate; endResetModel(); if (oldEntryCount != knownSatellites.count()) emit entryCountChanged(); } void SatelliteModel::satellitesInUseUpdated(const QList<QGeoSatelliteInfo> &infos) { if (!running()) return; beginResetModel(); satellitesInUse.clear(); foreach (const QGeoSatelliteInfo &info, infos) satellitesInUse.insert(info.satelliteIdentifier()); endResetModel(); }
If the satellite info source is not available, demo data is used to simulate satellite information updates.
void SatelliteModel::updateDemoData() { static bool flag = true; QList<QGeoSatelliteInfo> satellites; if (flag) { for (int i = 0; i<5; i++) { QGeoSatelliteInfo info; info.setSatelliteIdentifier(i); info.setSignalStrength(20 + 20*i); satellites.append(info); } } else { for (int i = 0; i<9; i++) { QGeoSatelliteInfo info; info.setSatelliteIdentifier(i*2); info.setSignalStrength(20 + 10*i); satellites.append(info); } } satellitesInViewUpdated(satellites); flag ? satellitesInUseUpdated(QList<QGeoSatelliteInfo>() << satellites.at(2)) : satellitesInUseUpdated(QList<QGeoSatelliteInfo>() << satellites.at(3)); flag = !flag; emit errorFound(flag); if (isSingleRequest() && !singleRequestServed) { singleRequestServed = true; setRunning(false); } }
The model is later used in QML to visualize the data.
To expose
SatelliteModel
to QML, we use the
QML_ELEMENT
macro. See the
QQmlEngine
class documentation for more details on it.
To make the type available in QML, we need to update our build accordingly.
For a CMake-based build, we need to add the following to the
CMakeLists.txt
:
qt_add_qml_module(satelliteinfo URI Local VERSION 1.0 QML_FILES satelliteinfo.qml NO_RESOURCE_TARGET_PATH )
For a qmake build, we need to modify the
satelliteinfo.pro
file in the following way:
CONFIG += qmltypes QML_IMPORT_NAME = Local QML_IMPORT_MAJOR_VERSION = 1