Source code
Revision control
Copy as Markdown
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "roles.h"
#include "satellitemodel.h"
using namespace Qt::StringLiterals;
static QString systemString(QGeoSatelliteInfo::SatelliteSystem system)
{
switch (system) {
case QGeoSatelliteInfo::Undefined:
return u"Undefined"_s;
case QGeoSatelliteInfo::GPS:
return u"GPS"_s;
case QGeoSatelliteInfo::GLONASS:
return u"GLONASS"_s;
case QGeoSatelliteInfo::GALILEO:
return u"GALILEO"_s;
case QGeoSatelliteInfo::BEIDOU:
return u"BEIDOU"_s;
case QGeoSatelliteInfo::QZSS:
return u"QZSS"_s;
case QGeoSatelliteInfo::IRNSS:
return u"IRNSS"_s;
case QGeoSatelliteInfo::SBAS:
return u"SBAS"_s;
case QGeoSatelliteInfo::Multiple:
return u"Multiple"_s;
case QGeoSatelliteInfo::CustomType:
return u"CustomType"_s;
}
return u"Undefined"_s;
}
SatelliteModel::SatelliteModel(QObject *parent)
: QAbstractListModel{parent}
{
}
int SatelliteModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return static_cast<int>(m_satellites.size());
}
QVariant SatelliteModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() >= rowCount())
return QVariant();
const QGeoSatelliteInfo &info = m_satellites.at(index.row());
switch (role) {
case Roles::IdRole:
return info.satelliteIdentifier();
case Roles::RssiRole:
return info.signalStrength();
case Roles::AzimuthRole:
return info.attribute(QGeoSatelliteInfo::Azimuth);
case Roles::ElevationRole:
return info.attribute(QGeoSatelliteInfo::Elevation);
case Roles::SystemRole:
return systemString(info.satelliteSystem());
case Roles::SystemIdRole:
return info.satelliteSystem();
case Roles::InUseRole:
return m_inUseIds.contains(getUid(info));
case Roles::VisibleNameRole:
return u"%1-%2"_s.arg(systemString(info.satelliteSystem()),
QString::number(info.satelliteIdentifier()));
}
return QVariant();
}
//! [0]
QHash<int, QByteArray> SatelliteModel::roleNames() const
{
return {
{Roles::IdRole, "id"},
{Roles::RssiRole, "rssi"},
{Roles::AzimuthRole, "azimuth"},
{Roles::ElevationRole, "elevation"},
{Roles::SystemRole, "system"},
{Roles::SystemIdRole, "systemId"},
{Roles::InUseRole, "inUse"},
{Roles::VisibleNameRole, "name"}
};
}
//! [0]
void SatelliteModel::updateSatellitesInView(const QList<QGeoSatelliteInfo> &inView)
{
const bool emitSizeChanged = inView.size() != m_satellites.size();
QSet<UniqueId> idsInUpdate;
for (const QGeoSatelliteInfo &info : inView)
idsInUpdate.insert(getUid(info));
// 1. Get the ids of all satellites to be removed.
const auto toBeRemoved = m_allIds - idsInUpdate;
// 2. Remove them and call {begin,end}RemoveRows() for each of them
qsizetype idx = 0;
while (idx < m_satellites.size()) {
const auto &sat = m_satellites.at(idx);
if (toBeRemoved.contains(getUid(sat))) {
beginRemoveRows(QModelIndex(), idx, idx);
m_satellites.removeAt(idx);
endRemoveRows();
} else {
++idx;
}
}
// 3. Get ids of all new elements.
const auto toBeAdded = idsInUpdate - m_allIds;
// 4. Sort the input items, so that we always have the same order of
// elements during comparison
auto inViewCopy = inView;
std::sort(inViewCopy.begin(), inViewCopy.end(),
[](const auto &lhs, const auto &rhs) {
if (lhs.satelliteIdentifier() == rhs.satelliteIdentifier())
return lhs.satelliteSystem() < rhs.satelliteSystem();
return lhs.satelliteIdentifier() < rhs.satelliteIdentifier();
});
// 5. Iterate through the list:
// * if the id of the satellite is new, use {begin,end}InsertRows()
// * otherwise use dataChanged()
for (idx = 0; idx < inViewCopy.size(); ++idx) {
const auto &sat = inViewCopy.at(idx);
if (toBeAdded.contains(getUid(sat))) {
beginInsertRows(QModelIndex(), idx, idx);
m_satellites.insert(idx, inViewCopy.at(idx));
endInsertRows();
} else {
m_satellites[idx] = inViewCopy.at(idx);
emit dataChanged(index(idx), index(idx),
{Roles::RssiRole, Roles::AzimuthRole, Roles::ElevationRole});
}
}
m_allIds = idsInUpdate;
if (emitSizeChanged)
emit sizeChanged();
}
void SatelliteModel::updateSatellitesInUse(const QList<QGeoSatelliteInfo> &inUse)
{
m_inUseIds.clear();
for (const QGeoSatelliteInfo &info : inUse)
m_inUseIds.insert(getUid(info));
emit dataChanged(index(0), index(m_satellites.size() - 1), {Roles::InUseRole});
}
SatelliteModel::UniqueId SatelliteModel::getUid(const QGeoSatelliteInfo &info)
{
return std::make_pair(static_cast<int>(info.satelliteSystem()), info.satelliteIdentifier());
}