Skip to content

Commit

Permalink
Port time zone handling
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 4, 2022
1 parent 79262c7 commit f27d712
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 276 deletions.
88 changes: 75 additions & 13 deletions src/app/gps/qgsappgpsdigitizing.cpp
Expand Up @@ -27,6 +27,7 @@
#include "qgsmapcanvas.h"
#include "qgsfeatureaction.h"
#include "qgsgpsconnection.h"
#include "qgsappgpsconnection.h"

#include <QTimeZone>

Expand All @@ -35,9 +36,6 @@ QgsAppGpsDigitizing::QgsAppGpsDigitizing( QgsAppGpsConnection *connection, QgsMa
, mConnection( connection )
, mCanvas( canvas )
{
connect( QgsGui::instance(), &QgsGui::optionsChanged, this, &QgsAppGpsDigitizing::gpsSettingsChanged );
gpsSettingsChanged();

mWgs84CRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4326" ) );

mCanvasToWgs84Transform = QgsCoordinateTransform( mCanvas->mapSettings().destinationCrs(), mWgs84CRS, QgsProject::instance() );
Expand Down Expand Up @@ -65,6 +63,16 @@ QgsAppGpsDigitizing::QgsAppGpsDigitizing( QgsAppGpsConnection *connection, QgsMa

connect( mAcquisitionTimer.get(), &QTimer::timeout,
this, &QgsAppGpsDigitizing::switchAcquisition );

connect( mCanvas, &QgsMapCanvas::currentLayerChanged,
this, &QgsAppGpsDigitizing::updateTimestampDestinationFields );

updateTimestampDestinationFields( mCanvas->currentLayer() );

connect( mConnection, &QgsAppGpsConnection::stateChanged, this, &QgsAppGpsDigitizing::gpsStateChanged );

connect( QgsGui::instance(), &QgsGui::optionsChanged, this, &QgsAppGpsDigitizing::gpsSettingsChanged );
gpsSettingsChanged();
}

QgsAppGpsDigitizing::~QgsAppGpsDigitizing()
Expand Down Expand Up @@ -130,7 +138,7 @@ void QgsAppGpsDigitizing::addFeature()

// Handle timestamp
QgsAttributeMap attrMap;
const int idx { vlayer->fields().indexOf( mCboTimestampField->currentText() ) };
const int idx { vlayer->fields().indexOf( mTimestampField ) };
if ( idx != -1 )
{
const QVariant ts = timestamp( vlayer, idx );
Expand Down Expand Up @@ -308,6 +316,15 @@ void QgsAppGpsDigitizing::setAutoSaveFeature( bool enabled )
mAutoSave = enabled;
}

void QgsAppGpsDigitizing::setTimeStampDestination( const QString &fieldName )
{
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ) )
{
mPreferredTimestampFields[ vlayer->id() ] = fieldName;
}
mTimestampField = fieldName;
}

void QgsAppGpsDigitizing::gpsSettingsChanged()
{
updateTrackAppearance();
Expand All @@ -331,6 +348,25 @@ void QgsAppGpsDigitizing::gpsSettingsChanged()
mAcquisitionTimer->stop();
mAcquisitionEnabled = true;

mApplyLeapSettings = settings.value( QStringLiteral( "applyLeapSeconds" ), true, QgsSettings::Gps ).toBool();
mLeapSeconds = settings.value( QStringLiteral( "leapSecondsCorrection" ), 18, QgsSettings::Gps ).toInt();

switch ( settings.value( QStringLiteral( "timeStampFormat" ), Qt::LocalTime, QgsSettings::Gps ).toInt() )
{
case 0:
mTimeStampSpec = Qt::TimeSpec::LocalTime;
break;

case 1:
mTimeStampSpec = Qt::TimeSpec::UTC;
break;

case 2:
mTimeStampSpec = Qt::TimeSpec::TimeZone;
break;
}
mTimeZone = settings.value( QStringLiteral( "timestampTimeZone" ), QVariant(), QgsSettings::Gps ).toString();

switchAcquisition();
}

Expand Down Expand Up @@ -388,6 +424,7 @@ void QgsAppGpsDigitizing::gpsStateChanged( const QgsGpsInformation &info )
newNmeaPosition.lon = nmea_degree2radian( info.longitude );
newAlt = info.elevation;
nmea_time_now( &newNmeaTime );
mLastNmeaTime = newNmeaTime;
}
else
{
Expand All @@ -412,7 +449,6 @@ void QgsAppGpsDigitizing::gpsStateChanged( const QgsGpsInformation &info )
{
mLastGpsPosition = myNewCenter;
mLastNmeaPosition = newNmeaPosition;
mLastNmeaTime = newNmeaTime;
mLastElevation = newAlt;

if ( mAutoAddVertices )
Expand All @@ -422,6 +458,33 @@ void QgsAppGpsDigitizing::gpsStateChanged( const QgsGpsInformation &info )
}
}

void QgsAppGpsDigitizing::updateTimestampDestinationFields( QgsMapLayer *mapLayer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mapLayer );
if ( vlayer )
{
// Restore preferred if stored
if ( mPreferredTimestampFields.contains( vlayer->id( ) ) )
{
const QString previousTimeStampField = mPreferredTimestampFields[ vlayer->id( ) ];
const int idx = vlayer->fields().indexOf( previousTimeStampField );
if ( idx >= 0 )
mTimestampField = previousTimeStampField;
}
// Cleanup preferred fields
const QStringList layerIds { mPreferredTimestampFields.keys( ) };
for ( const QString &layerId : layerIds )
{
if ( ! QgsProject::instance()->mapLayer( layerId ) )
{
mPreferredTimestampFields.remove( layerId );
}
}
}

emit timeStampDestinationChanged( mTimestampField );
}

void QgsAppGpsDigitizing::createRubberBand()
{
delete mRubberBand;
Expand All @@ -441,27 +504,26 @@ QVariant QgsAppGpsDigitizing::timestamp( QgsVectorLayer *vlayer, int idx )
// Time from GPS is UTC time
time.setTimeSpec( Qt::UTC );
// Apply leap seconds correction
if ( mCbxLeapSeconds->isChecked() && mLeapSeconds->value() != 0 )
if ( mApplyLeapSettings && mLeapSeconds != 0 )
{
time = time.addSecs( mLeapSeconds->value() );
time = time.addSecs( mLeapSeconds );
}
// Desired format
const Qt::TimeSpec timeSpec { static_cast<Qt::TimeSpec>( mCboTimestampFormat->currentData( ).toInt() ) };
time = time.toTimeSpec( timeSpec );
if ( timeSpec == Qt::TimeSpec::TimeZone )
time = time.toTimeSpec( mTimeStampSpec );
if ( mTimeStampSpec == Qt::TimeSpec::TimeZone )
{
// Get timezone from the combo
const QTimeZone destTz( mCboTimeZones->currentText().toUtf8() );
const QTimeZone destTz( mTimeZone.toUtf8() );
if ( destTz.isValid() )
{
time = time.toTimeZone( destTz );
}
}
else if ( timeSpec == Qt::TimeSpec::LocalTime )
else if ( mTimeStampSpec == Qt::TimeSpec::LocalTime )
{
time = time.toLocalTime();
}
else if ( timeSpec == Qt::TimeSpec::UTC )
else if ( mTimeStampSpec == Qt::TimeSpec::UTC )
{
// Do nothing: we are already in UTC
}
Expand Down
20 changes: 20 additions & 0 deletions src/app/gps/qgsappgpsdigitizing.h
Expand Up @@ -49,13 +49,24 @@ class QgsAppGpsDigitizing: public QObject
void setAutoAddVertices( bool enabled );
void setAutoSaveFeature( bool enabled );

void setTimeStampDestination( const QString &fieldName );

signals:

void timeStampDestinationChanged( const QString &fieldName );

private slots:
void gpsSettingsChanged();
void updateTrackAppearance();
void switchAcquisition();

void gpsStateChanged( const QgsGpsInformation &info );

/**
* Updates compatible fields for timestamp recording
*/
void updateTimestampDestinationFields( QgsMapLayer *mapLayer );

private:
void createRubberBand();
QVariant timestamp( QgsVectorLayer *vlayer, int idx );
Expand Down Expand Up @@ -86,6 +97,15 @@ class QgsAppGpsDigitizing: public QObject
bool mAcquisitionEnabled = true;
int mAcquisitionInterval = 0;
double mDistanceThreshold = 0;

bool mApplyLeapSettings = false;
int mLeapSeconds = 0;
Qt::TimeSpec mTimeStampSpec = Qt::TimeSpec::LocalTime;
QString mTimeZone;

//! Temporary storage of preferred fields
QMap<QString, QString> mPreferredTimestampFields;
QString mTimestampField;
};

#endif // QGSAPPGPSDIGITIZING
38 changes: 38 additions & 0 deletions src/app/gps/qgsappgpssettingsmenu.cpp
Expand Up @@ -17,6 +17,8 @@
#include "qgssettings.h"
#include "qgisapp.h"
#include "qgsapplication.h"
#include "qgsfieldproxymodel.h"
#include "qgsfieldmodel.h"

#include <QRadioButton>
#include <QButtonGroup>
Expand Down Expand Up @@ -170,6 +172,14 @@ QgsAppGpsSettingsMenu::QgsAppGpsSettingsMenu( QWidget *parent )

addAction( mAutoSaveAddedFeatureAction );

mFieldProxyModel = new QgsFieldProxyModel( this );
mFieldProxyModel->sourceFieldModel()->setAllowEmptyFieldName( true );
mFieldProxyModel->setFilters( QgsFieldProxyModel::Filter::String | QgsFieldProxyModel::Filter::DateTime );

mTimeStampFieldMenu = new QMenu( tr( "Time Stamp Destination" ), this );
connect( mTimeStampFieldMenu, &QMenu::aboutToShow, this, &QgsAppGpsSettingsMenu::timeStampMenuAboutToShow );
addMenu( mTimeStampFieldMenu );

addSeparator();
QAction *settingsAction = new QAction( tr( "GPS Settings…" ), this );
settingsAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOptions.svg" ) ) );
Expand Down Expand Up @@ -223,3 +233,31 @@ bool QgsAppGpsSettingsMenu::autoAddFeature() const
return mAutoSaveAddedFeatureAction->isChecked();
}

void QgsAppGpsSettingsMenu::setCurrentTimeStampField( const QString &fieldName )
{
mCurrentTimeStampField = fieldName;
}

void QgsAppGpsSettingsMenu::timeStampMenuAboutToShow()
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( QgisApp::instance()->activeLayer() );
mFieldProxyModel->sourceFieldModel()->setLayer( vlayer );

mTimeStampFieldMenu->clear();
for ( int row = 0; row < mFieldProxyModel->rowCount(); ++row )
{
QAction *fieldAction = new QAction( mFieldProxyModel->data( mFieldProxyModel->index( row, 0 ) ).toString(), this );
fieldAction->setIcon( mFieldProxyModel->data( mFieldProxyModel->index( row, 0 ), Qt::DecorationRole ).value< QIcon >() );
const QString fieldName = mFieldProxyModel->data( mFieldProxyModel->index( row, 0 ), QgsFieldModel::FieldNameRole ).toString();
fieldAction->setData( fieldName );
fieldAction->setCheckable( true );
fieldAction->setChecked( mCurrentTimeStampField == fieldName );
connect( fieldAction, &QAction::triggered, this, [ = ]()
{
mCurrentTimeStampField = fieldName;
emit timeStampDestinationChanged( fieldName );
} );
mTimeStampFieldMenu->addAction( fieldAction );
}
}

14 changes: 14 additions & 0 deletions src/app/gps/qgsappgpssettingsmenu.h
Expand Up @@ -20,6 +20,7 @@
#include <QWidgetAction>

class QRadioButton;
class QgsFieldProxyModel;

class QgsGpsMapRotationAction: public QWidgetAction
{
Expand Down Expand Up @@ -63,6 +64,10 @@ class QgsAppGpsSettingsMenu : public QMenu
bool autoAddTrackPoints() const;
bool autoAddFeature() const;

public slots:

void setCurrentTimeStampField( const QString &fieldName );

signals:

void locationMarkerToggled( bool visible );
Expand All @@ -71,6 +76,11 @@ class QgsAppGpsSettingsMenu : public QMenu
void mapCenteringModeChanged( MapCenteringMode mode );
void autoAddTrackPointsChanged( bool enabled );
void autoAddFeatureChanged( bool enabled );
void timeStampDestinationChanged( const QString &fieldName );

private slots:

void timeStampMenuAboutToShow();

private:

Expand All @@ -84,6 +94,10 @@ class QgsAppGpsSettingsMenu : public QMenu
QRadioButton *mRadioRecenterWhenOutside = nullptr;
QRadioButton *mRadioNeverRecenter = nullptr;

QgsFieldProxyModel *mFieldProxyModel = nullptr;
QMenu *mTimeStampFieldMenu = nullptr;
QString mCurrentTimeStampField;

};

#endif // QGSAPPGPSSETTINGSMANAGER_H

0 comments on commit f27d712

Please sign in to comment.