Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic model for PositioningInformationView #5604

Merged
merged 24 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
745c49f
Step one: add positioning model and clear statics from qml view.
mohsenD98 Aug 30, 2024
692d094
Add Longitude And Latitude.
mohsenD98 Sep 1, 2024
85453a9
Simplify condition and remove extra codes.
mohsenD98 Sep 1, 2024
45f984a
Add altitude.
mohsenD98 Sep 1, 2024
f88ec6f
Add speed.
mohsenD98 Sep 1, 2024
2bb7bfd
Add hAccuracy and vAccuracy.
mohsenD98 Sep 1, 2024
ed9de05
Some cleanups.
mohsenD98 Sep 1, 2024
fa2419a
Refactor: single responsibility.
mohsenD98 Sep 1, 2024
6b90761
Cleanup and add dynamic info from device.
mohsenD98 Sep 1, 2024
e75383a
Rename PositioningModel to PositioningInformationModel.
mohsenD98 Sep 1, 2024
f29caf8
Add some documentations.
mohsenD98 Sep 1, 2024
61665cd
Maximum 3 columns.
mohsenD98 Sep 1, 2024
09a0ca2
Fix PR issues - step 1.
mohsenD98 Sep 2, 2024
a817081
Fix PR issues - step 2.
mohsenD98 Sep 2, 2024
d6d7cc5
Adjust altitude on antenna height changed.
mohsenD98 Sep 2, 2024
bec35ab
Handle when display CRS changes and deal with the change of device.
mohsenD98 Sep 2, 2024
64c24f7
Ensure that color of each cell is a different color from its neighbors.
mohsenD98 Sep 2, 2024
597c270
Ensure respecting the reversed axis configuration.
mohsenD98 Sep 3, 2024
a7bcdb5
Fix reordering issue.
mohsenD98 Sep 3, 2024
c006533
Remove duplicate codes.
mohsenD98 Sep 3, 2024
32d2578
Translate and cleanup.
mohsenD98 Sep 3, 2024
5a83f47
Fix antenna height, use 0 as NaN.
mohsenD98 Sep 3, 2024
5ee1832
Scroll bar when content height is > height.
mohsenD98 Sep 3, 2024
f43f996
Update src/core/positioning/positioninginformationmodel.cpp
nirvn Sep 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ set(QFIELD_CORE_SRCS
positioning/positioning.cpp
positioning/positioningdevicemodel.cpp
positioning/geofencer.cpp
positioning/positioninginformationmodel.cpp
processing/processingalgorithm.cpp
processing/processingalgorithmparametersmodel.cpp
processing/processingalgorithmsmodel.cpp
Expand Down Expand Up @@ -152,6 +153,7 @@ set(QFIELD_CORE_HDRS
positioning/tcpreceiver.h
positioning/udpreceiver.h
positioning/geofencer.h
positioning/positioninginformationmodel.h
processing/processingalgorithm.h
processing/processingalgorithmparametersmodel.h
processing/processingalgorithmsmodel.h
Expand Down
2 changes: 2 additions & 0 deletions src/core/positioning/abstractgnssreceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class AbstractGnssReceiver : public QObject

Q_INVOKABLE virtual AbstractGnssReceiver::Capabilities capabilities() const { return NoCapabilities; }

virtual QList<QPair<QString, QVariant>> details() { return {}; }

signals:
void validChanged();
void lastGnssPositionInformationChanged( GnssPositionInformation &lastGnssPositionInformation );
Expand Down
14 changes: 14 additions & 0 deletions src/core/positioning/nmeagnssreceiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,20 @@ void NmeaGnssReceiver::handleStopLogging()
mLogFile.close();
}

QList<QPair<QString, QVariant>> NmeaGnssReceiver::details()
{
QList<QPair<QString, QVariant>> dataList;

dataList.append( qMakePair( "PDOP", QLocale::system().toString( mCurrentNmeaGnssPositionInformation.pdop(), 'f', 1 ) ) );
dataList.append( qMakePair( "HDOP", QLocale::system().toString( mCurrentNmeaGnssPositionInformation.hdop(), 'f', 1 ) ) );
dataList.append( qMakePair( "VDOP", QLocale::system().toString( mCurrentNmeaGnssPositionInformation.vdop(), 'f', 1 ) ) );
dataList.append( qMakePair( "Valid", mCurrentNmeaGnssPositionInformation.isValid() ? "True" : "False" ) );
dataList.append( qMakePair( "Fix", mCurrentNmeaGnssPositionInformation.fixStatusDescription() ) );
dataList.append( qMakePair( "Quality", mCurrentNmeaGnssPositionInformation.qualityDescription() ) );

return dataList;
}

void NmeaGnssReceiver::processImuSentence( const QString &sentence )
{
static const int PARAMETER_STATUS_INDEX = 19;
Expand Down
1 change: 1 addition & 0 deletions src/core/positioning/nmeagnssreceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class NmeaGnssReceiver : public AbstractGnssReceiver
private:
void handleStartLogging() override;
void handleStopLogging() override;
QList<QPair<QString, QVariant>> details() override;

void processImuSentence( const QString &sentence );

Expand Down
307 changes: 307 additions & 0 deletions src/core/positioning/positioninginformationmodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
#include "coordinatereferencesystemutils.h"
#include "geometryutils.h"
#include "positioninginformationmodel.h"

#include <QVariant>
#include <qgsunittypes.h>

PositioningInformationModel::PositioningInformationModel( QObject *parent )
: QStandardItemModel( parent )
{
connect( this, &QStandardItemModel::dataChanged, this, &PositioningInformationModel::onDataChanged );
}

void PositioningInformationModel::refreshData()
{
if ( !mPositioningSource )
{
return;
}

const double distanceUnitFactor = QgsUnitTypes::fromUnitToUnitFactor( Qgis::DistanceUnit::Meters, distanceUnits() );
const QString distanceUnitAbbreviation = QgsUnitTypes::toAbbreviatedString( distanceUnits() );
const QList<QPair<QString, QVariant>> deviceDetails = mPositioningSource->device()->details();

updateCoordinates();

const QString altitude = getAltitude( distanceUnitFactor, distanceUnitAbbreviation );
const QString speed = getSpeed();
const QString hAccuracy = getHorizontalAccuracy( distanceUnitFactor, distanceUnitAbbreviation );
const QString vAccuracy = getVerticalAccuracy( distanceUnitFactor, distanceUnitAbbreviation );

updateInfo( tr( "Altitude" ), altitude );
updateInfo( tr( "Speed" ), speed );
updateInfo( tr( "H. Accuracy" ), hAccuracy );
updateInfo( tr( "V. Accuracy" ), vAccuracy );

for ( int i = 0; i < deviceDetails.size(); ++i )
{
const QString key = deviceDetails[i].first;
const QVariant value = deviceDetails[i].second;

updateInfo( key, value );
}
}

void PositioningInformationModel::getCoordinateLabels( QString &coord1Label, QString &coord2Label, bool coordinatesIsXY, bool isGeographic )
{
if ( coordinatesIsXY )
{
coord1Label = isGeographic ? tr( "Lon" ) : tr( "X" );
coord2Label = isGeographic ? tr( "Lat" ) : tr( "Y" );
}
else
{
coord1Label = isGeographic ? tr( "Lat" ) : tr( "Y" );
coord2Label = isGeographic ? tr( "Lon" ) : tr( "X" );
}
}

void PositioningInformationModel::getCoordinateValues( QString &coord1Value, QString &coord2Value, const QgsPoint &coordinates, bool coordinatesIsXY, bool isGeographic )
{
if ( coordinatesIsXY )
{
if ( positioningSource()->positionInformation().longitudeValid() )
{
coord1Value = QLocale::system().toString( coordinates.x(), 'f', isGeographic ? 7 : 3 );
coord2Value = QLocale::system().toString( coordinates.y(), 'f', isGeographic ? 7 : 3 );
}
else
{
coord1Value = coord2Value = tr( "N/A" );
}
}
else
{
if ( positioningSource()->positionInformation().latitudeValid() )
{
coord1Value = QLocale::system().toString( coordinates.y(), 'f', isGeographic ? 7 : 3 );
coord2Value = QLocale::system().toString( coordinates.x(), 'f', isGeographic ? 7 : 3 );
}
else
{
coord1Value = coord2Value = tr( "N/A" );
}
}
}

QString PositioningInformationModel::getAltitude( double distanceUnitFactor, const QString &distanceUnitAbbreviation )
{
if ( positioningSource()->positionInformation().elevationValid() )
{
QString altitude = QLocale::system().toString( positioningSource()->projectedPosition().z() * distanceUnitFactor, 'f', 3 ) + ' ' + distanceUnitAbbreviation + ' ';
QStringList details;

if ( positioningSource()->elevationCorrectionMode() == Positioning::ElevationCorrectionMode::OrthometricFromGeoidFile )
{
details.push_back( tr( "grid" ) );
}
else if ( positioningSource()->elevationCorrectionMode() == Positioning::ElevationCorrectionMode::OrthometricFromDevice )
{
details.push_back( tr( "ortho." ) );
}
if ( antennaHeight() != 0 )
{
details.push_back( tr( "ant." ) );
}
if ( details.length() > 0 )
{
altitude += QString( " (%1)" ).arg( details.join( ", " ) );
}
return altitude;
}
return tr( "N/A" );
}

QString PositioningInformationModel::getSpeed()
{
return positioningSource()->positionInformation().speedValid() ? QLocale::system().toString( positioningSource()->positionInformation().speed(), 'f', 3 ) + " m/s" : tr( "N/A" );
}

QString PositioningInformationModel::getHorizontalAccuracy( double distanceUnitFactor, const QString &distanceUnitAbbreviation )
{
return positioningSource()->positionInformation().haccValid() ? QLocale::system().toString( positioningSource()->positionInformation().hacc() * distanceUnitFactor, 'f', 3 ) + ' ' + distanceUnitAbbreviation : tr( "N/A" );
}

QString PositioningInformationModel::getVerticalAccuracy( double distanceUnitFactor, const QString &distanceUnitAbbreviation )
{
return positioningSource()->positionInformation().vaccValid() ? QLocale::system().toString( positioningSource()->positionInformation().vacc() * distanceUnitFactor, 'f', 3 ) + ' ' + distanceUnitAbbreviation : tr( "N/A" );
}

void PositioningInformationModel::updateInfo( const QString &name, const QVariant &value )
{
for ( int row = 0; row < rowCount(); ++row )
{
QStandardItem *rowItem = item( row );

if ( rowItem->data( NameRole ).toString() == name )
{
rowItem->setData( value.toString(), ValueRole );
return;
}
}

QStandardItem *nameItem = new QStandardItem( name );
nameItem->setData( name, NameRole );
nameItem->setData( value.toString(), ValueRole );
insertRow( rowCount(), QList<QStandardItem *>() << nameItem );
}


void PositioningInformationModel::updateCoordinates()
{
const bool coordinatesIsXY = CoordinateReferenceSystemUtils::defaultCoordinateOrderForCrsIsXY( coordinateDisplayCrs() );
const bool coordinatesIsGeographic = coordinateDisplayCrs().isGeographic();
const QgsPoint coordinates = GeometryUtils::reprojectPoint( positioningSource()->sourcePosition(), CoordinateReferenceSystemUtils::wgs84Crs(), coordinateDisplayCrs() );

QString coord1Label, coord2Label;
QString coord1Value, coord2Value;

getCoordinateLabels( coord1Label, coord2Label, coordinatesIsXY, coordinatesIsGeographic );
getCoordinateValues( coord1Value, coord2Value, coordinates, coordinatesIsXY, coordinatesIsGeographic );

if ( rowCount() == 0 )
{
updateInfo( coord1Label, coord1Value );
updateInfo( coord2Label, coord2Value );
}
else
{
QStandardItem *coordinates1 = item( 0 );
QStandardItem *coordinates2 = item( 1 );

coordinates1->setData( coord1Label, NameRole );
coordinates1->setData( coord1Value, ValueRole );
coordinates2->setData( coord2Label, NameRole );
coordinates2->setData( coord2Value, ValueRole );
}
}

bool PositioningInformationModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
QStandardItem *rowItem = item( index.row() );
if ( !rowItem )
{
return false;
}

switch ( role )
{
case NameRole:
if ( rowItem->data( NameRole ) == value )
{
return false;
}

rowItem->setData( value, NameRole );
return true;

case ValueRole:

if ( rowItem->data( ValueRole ) == value )
{
return false;
}

rowItem->setData( value, ValueRole );
return true;

default:
break;
}

return false;
}

QHash<int, QByteArray> PositioningInformationModel::roleNames() const
{
QHash<int, QByteArray> names = QStandardItemModel::roleNames();
names[NameRole] = "Name";
names[ValueRole] = "Value";
return names;
}

void PositioningInformationModel::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
{
Q_UNUSED( bottomRight )
Q_UNUSED( roles )
}

Positioning *PositioningInformationModel::positioningSource() const
{
return mPositioningSource;
}

void PositioningInformationModel::setPositioningSource( Positioning *positioningSource )
{
if ( mPositioningSource == positioningSource )
return;

if ( mPositioningSource )
{
disconnect( mPositioningSource, &Positioning::positionInformationChanged, this, &PositioningInformationModel::refreshData );
disconnect( mPositioningSource, &Positioning::deviceChanged, this, &PositioningInformationModel::softReset );
}

mPositioningSource = positioningSource;
emit positioningSourceChanged();

if ( mPositioningSource )
{
connect( mPositioningSource, &Positioning::positionInformationChanged, this, &PositioningInformationModel::refreshData );
connect( mPositioningSource, &Positioning::deviceChanged, this, &PositioningInformationModel::softReset );
refreshData();
}
}

void PositioningInformationModel::softReset()
{
if ( mPositioningSource->deviceId() == "" )
removeRows( 6, rowCount() - 6 );
}

double PositioningInformationModel::antennaHeight() const
{
return mAntennaHeight;
}

void PositioningInformationModel::setAntennaHeight( double antennaHeight )
{
if ( qFuzzyCompare( mAntennaHeight, antennaHeight ) )
return;
mAntennaHeight = antennaHeight;
emit antennaHeightChanged();

const double distanceUnitFactor = QgsUnitTypes::fromUnitToUnitFactor( Qgis::DistanceUnit::Meters, distanceUnits() );
const QString distanceUnitAbbreviation = QgsUnitTypes::toAbbreviatedString( distanceUnits() );
const QString altitude = getAltitude( distanceUnitFactor, distanceUnitAbbreviation );
updateInfo( tr( "Altitude" ), altitude );
}

Qgis::DistanceUnit PositioningInformationModel::distanceUnits() const
{
return mDistanceUnits;
}

void PositioningInformationModel::setDistanceUnits( Qgis::DistanceUnit distanceUnits )
{
if ( mDistanceUnits == distanceUnits )
return;
mDistanceUnits = distanceUnits;
emit distanceUnitsChanged();
}

QgsCoordinateReferenceSystem PositioningInformationModel::coordinateDisplayCrs() const
{
return mCoordinateDisplayCrs;
}

void PositioningInformationModel::setCoordinateDisplayCrs( const QgsCoordinateReferenceSystem &coordinateDisplayCrs )
{
if ( mCoordinateDisplayCrs == coordinateDisplayCrs )
return;
mCoordinateDisplayCrs = coordinateDisplayCrs;
emit coordinateDisplayCrsChanged();

updateCoordinates();
}
Loading
Loading