Skip to content

Commit

Permalink
Move responsibility for managing GPS time stamp destination field
Browse files Browse the repository at this point in the history
to QgsProjectGpsSettings, and store time stamp destination fields
in projects
  • Loading branch information
nyalldawson committed Nov 8, 2022
1 parent cc7e5e3 commit ce6cf4a
Show file tree
Hide file tree
Showing 10 changed files with 248 additions and 101 deletions.
49 changes: 49 additions & 0 deletions python/core/auto_generated/project/qgsprojectgpssettings.sip.in
Expand Up @@ -98,6 +98,27 @@ Returns the destination layer to be used for storing features digitized from GPS
.. seealso:: :py:func:`setDestinationLayer`

.. seealso:: :py:func:`destinationLayerChanged`
%End

QMap< QString, QString > destinationTimeStampFields() const;
%Docstring
Returns the map of destination layer ID to target time stamp field name.

.. seealso:: :py:func:`destinationTimeStampField`

.. seealso:: :py:func:`setDestinationTimeStampField`

.. seealso:: :py:func:`setDestinationTimeStampField`
%End

QString destinationTimeStampField() const;
%Docstring
Returns the destination time stamp field name for the current :py:func:`~QgsProjectGpsSettings.destinationLayer`,
or an empty string if time stamps should not be automatically saved.

.. seealso:: :py:func:`destinationTimeStampFields`

.. seealso:: :py:func:`setDestinationTimeStampField`
%End

public slots:
Expand Down Expand Up @@ -145,6 +166,19 @@ Sets the destination ``layer`` to be used for storing features digitized from GP
.. seealso:: :py:func:`destinationLayer`

.. seealso:: :py:func:`destinationLayerChanged`
%End

void setDestinationTimeStampField( QgsVectorLayer *layer, const QString &field );
%Docstring
Sets the destination field name for automatically storing timestamps in the
specified destination ``layer``.

Set ``field`` argument to an empty string if time stamps should
not be automatically saved.

.. seealso:: :py:func:`destinationTimeStampFields`

.. seealso:: :py:func:`destinationTimeStampField`
%End

signals:
Expand Down Expand Up @@ -187,6 +221,21 @@ is changed.
.. seealso:: :py:func:`destinationLayer`

.. seealso:: :py:func:`setDestinationLayer`
%End

void destinationTimeStampFieldChanged( const QString &field );
%Docstring
Emitted whenever the destination field for automatic time stamps is
changed.

The ``field`` argument will be an empty string if time stamps should
not be automatically saved.

.. seealso:: :py:func:`destinationTimeStampFields`

.. seealso:: :py:func:`destinationTimeStampField`

.. seealso:: :py:func:`setDestinationTimeStampField`
%End

};
Expand Down
42 changes: 1 addition & 41 deletions src/app/gps/qgsappgpsdigitizing.cpp
Expand Up @@ -64,11 +64,6 @@ QgsAppGpsDigitizing::QgsAppGpsDigitizing( QgsAppGpsConnection *connection, QgsMa
connect( mAcquisitionTimer.get(), &QTimer::timeout,
this, &QgsAppGpsDigitizing::switchAcquisition );

connect( QgsProject::instance()->gpsSettings(), &QgsProjectGpsSettings::destinationLayerChanged,
this, &QgsAppGpsDigitizing::updateTimestampDestinationFields );

updateTimestampDestinationFields( QgsProject::instance()->gpsSettings()->destinationLayer() );

connect( mConnection, &QgsAppGpsConnection::stateChanged, this, &QgsAppGpsDigitizing::gpsStateChanged );
connect( mConnection, &QgsAppGpsConnection::connected, this, &QgsAppGpsDigitizing::gpsConnected );
connect( mConnection, &QgsAppGpsConnection::disconnected, this, &QgsAppGpsDigitizing::gpsDisconnected );
Expand Down Expand Up @@ -192,7 +187,7 @@ void QgsAppGpsDigitizing::createFeature()

// Handle timestamp
QgsAttributeMap attrMap;
const int idx { vlayer->fields().indexOf( mTimestampField ) };
const int idx = vlayer->fields().indexOf( QgsProject::instance()->gpsSettings()->destinationTimeStampField() );
if ( idx != -1 )
{
const QVariant ts = timestamp( vlayer, idx );
Expand Down Expand Up @@ -373,15 +368,6 @@ void QgsAppGpsDigitizing::createFeature()
QgisApp::instance()->activateWindow();
}

void QgsAppGpsDigitizing::setTimeStampDestination( const QString &fieldName )
{
if ( QgsVectorLayer *vlayer = QgsProject::instance()->gpsSettings()->destinationLayer() )
{
mPreferredTimestampFields[ vlayer->id() ] = fieldName;
}
mTimestampField = fieldName;
}

void QgsAppGpsDigitizing::setNmeaLogFile( const QString &filename )
{
if ( mLogFile )
Expand Down Expand Up @@ -564,32 +550,6 @@ void QgsAppGpsDigitizing::gpsStateChanged( const QgsGpsInformation &info )
}
}

void QgsAppGpsDigitizing::updateTimestampDestinationFields( QgsVectorLayer *vlayer )
{
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::logNmeaSentence( const QString &nmeaString )
{
if ( mEnableNmeaLogging && mLogFile && mLogFile->isOpen() )
Expand Down
13 changes: 0 additions & 13 deletions src/app/gps/qgsappgpsdigitizing.h
Expand Up @@ -54,9 +54,6 @@ class APP_EXPORT QgsAppGpsDigitizing: public QObject
void addVertex();
void resetTrack();
void createFeature();

void setTimeStampDestination( const QString &fieldName );

void setNmeaLogFile( const QString &filename );
void setNmeaLoggingEnabled( bool enabled );

Expand All @@ -67,8 +64,6 @@ class APP_EXPORT QgsAppGpsDigitizing: public QObject
*/
void trackIsEmptyChanged( bool isEmpty );

void timeStampDestinationChanged( const QString &fieldName );

private slots:
void gpsSettingsChanged();
void updateTrackAppearance();
Expand All @@ -79,10 +74,6 @@ class APP_EXPORT QgsAppGpsDigitizing: public QObject

void gpsStateChanged( const QgsGpsInformation &info );

/**
* Updates compatible fields for timestamp recording
*/
void updateTimestampDestinationFields( QgsVectorLayer *mapLayer );
void logNmeaSentence( const QString &nmeaString ); // added to handle 'raw' data

void startLogging();
Expand Down Expand Up @@ -122,10 +113,6 @@ class APP_EXPORT QgsAppGpsDigitizing: public QObject
QString mTimeZone;
int mOffsetFromUtc = 0;

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

QString mNmeaLogFile;
bool mEnableNmeaLogging = false;

Expand Down
22 changes: 12 additions & 10 deletions src/app/gps/qgsappgpssettingsmenu.cpp
Expand Up @@ -292,41 +292,43 @@ Qgis::MapRecenteringMode QgsAppGpsSettingsMenu::mapCenteringMode() const
}
}

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

void QgsAppGpsSettingsMenu::timeStampMenuAboutToShow()
{
mFieldProxyModel->sourceFieldModel()->setLayer( QgsProject::instance()->gpsSettings()->destinationLayer() );
const QString currentTimeStampField = QgsProject::instance()->gpsSettings()->destinationTimeStampField();

mTimeStampDestinationFieldMenu->clear();
bool foundPreviousField = false;
for ( int row = 0; row < mFieldProxyModel->rowCount(); ++row )
{
QAction *fieldAction = new QAction( mFieldProxyModel->data( mFieldProxyModel->index( row, 0 ) ).toString(), this );
if ( fieldAction->text().isEmpty() )
{
fieldAction->setText( tr( "Do Not Store" ) );
}
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 );
if ( mCurrentTimeStampField == fieldName )
if ( currentTimeStampField == fieldName )
{
foundPreviousField = true;
fieldAction->setChecked( mCurrentTimeStampField == fieldName );
fieldAction->setChecked( currentTimeStampField == fieldName );
}
connect( fieldAction, &QAction::triggered, this, [ = ]()
{
mCurrentTimeStampField = fieldName;
emit timeStampDestinationChanged( fieldName );
if ( QgsProject::instance()->gpsSettings()->destinationTimeStampField() != fieldName )
{
QgsProject::instance()->gpsSettings()->setDestinationTimeStampField( QgsProject::instance()->gpsSettings()->destinationLayer(), fieldName );
QgsProject::instance()->setDirty();
}
} );
mTimeStampDestinationFieldMenu->addAction( fieldAction );
}

if ( !foundPreviousField )
{
mTimeStampDestinationFieldMenu->actions().at( 0 )->setChecked( true );
mCurrentTimeStampField.clear();
}
}

6 changes: 0 additions & 6 deletions src/app/gps/qgsappgpssettingsmenu.h
Expand Up @@ -57,17 +57,12 @@ class APP_EXPORT QgsAppGpsSettingsMenu : public QMenu
bool rotateMap() const;
Qgis::MapRecenteringMode mapCenteringMode() const;

public slots:

void setCurrentTimeStampField( const QString &fieldName );

signals:

void locationMarkerToggled( bool visible );
void bearingLineToggled( bool visible );
void rotateMapToggled( bool enabled );
void mapCenteringModeChanged( Qgis::MapRecenteringMode mode );
void timeStampDestinationChanged( const QString &fieldName );
void enableNmeaLog( bool enabled );
void nmeaLogFileChanged( const QString &filename );

Expand All @@ -90,7 +85,6 @@ class APP_EXPORT QgsAppGpsSettingsMenu : public QMenu

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

friend class TestQgsGpsIntegration;

Expand Down
2 changes: 0 additions & 2 deletions src/app/qgisapp.cpp
Expand Up @@ -1418,8 +1418,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipBadLayers
connect( mGpsSettingsMenu, &QgsAppGpsSettingsMenu::mapCenteringModeChanged, mGpsCanvasBridge, &QgsGpsCanvasBridge::setMapCenteringMode );
connect( mGpsSettingsMenu, &QgsAppGpsSettingsMenu::enableNmeaLog, mGpsDigitizing, &QgsAppGpsDigitizing::setNmeaLoggingEnabled );
connect( mGpsSettingsMenu, &QgsAppGpsSettingsMenu::nmeaLogFileChanged, mGpsDigitizing, &QgsAppGpsDigitizing::setNmeaLogFile );
connect( mGpsSettingsMenu, &QgsAppGpsSettingsMenu::timeStampDestinationChanged, mGpsDigitizing, &QgsAppGpsDigitizing::setTimeStampDestination );
connect( mGpsDigitizing, &QgsAppGpsDigitizing::timeStampDestinationChanged, mGpsSettingsMenu, &QgsAppGpsSettingsMenu::setCurrentTimeStampField );
connect( mGpsDigitizing, &QgsAppGpsDigitizing::trackIsEmptyChanged, mGpsToolBar, [ = ]( bool isEmpty ) { mGpsToolBar->setResetTrackButtonEnabled( !isEmpty ); } );

mpGpsWidget = new QgsGpsInformationWidget( mGpsConnection, mMapCanvas );
Expand Down
71 changes: 71 additions & 0 deletions src/core/project/qgsprojectgpssettings.cpp
Expand Up @@ -27,6 +27,11 @@ void QgsProjectGpsSettings::resolveReferences( const QgsProject *project )
mDestinationLayer.resolveWeakly( project );

emit destinationLayerChanged( mDestinationLayer.get() );

if ( mDestinationLayer )
{
emit destinationTimeStampFieldChanged( mDestinationTimestampFields.value( mDestinationLayer->id() ) );
}
}

QgsProjectGpsSettings::~QgsProjectGpsSettings() = default;
Expand All @@ -38,11 +43,13 @@ void QgsProjectGpsSettings::reset()
mDestinationFollowsActiveLayer = true;

mDestinationLayer.setLayer( nullptr );
mDestinationTimestampFields.clear();

emit automaticallyAddTrackVerticesChanged( mAutoAddTrackVertices );
emit automaticallyCommitFeaturesChanged( mAutoCommitFeatures );
emit destinationFollowsActiveLayerChanged( mDestinationFollowsActiveLayer );
emit destinationLayerChanged( nullptr );
emit destinationTimeStampFieldChanged( QString() );
}

bool QgsProjectGpsSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
Expand All @@ -58,10 +65,24 @@ bool QgsProjectGpsSettings::readXml( const QDomElement &element, const QgsReadWr

mDestinationLayer = QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );

mDestinationTimestampFields.clear();
{
const QDomElement timeStampElement = element.firstChildElement( QStringLiteral( "timeStampFields" ) );
QDomElement layerElement = timeStampElement.firstChildElement();
while ( !layerElement.isNull() )
{
const QString layerId = layerElement.attribute( QStringLiteral( "destinationLayer" ) );
const QString field = layerElement.attribute( QStringLiteral( "field" ) );
mDestinationTimestampFields[ layerId ] = field;
layerElement = layerElement.nextSiblingElement();
}
}

emit automaticallyAddTrackVerticesChanged( mAutoAddTrackVertices );
emit automaticallyCommitFeaturesChanged( mAutoCommitFeatures );
emit destinationFollowsActiveLayerChanged( mDestinationFollowsActiveLayer );
emit destinationLayerChanged( nullptr ); // won't be set until resolve is called
emit destinationTimeStampFieldChanged( QString() );
return true;
}

Expand All @@ -85,6 +106,18 @@ QDomElement QgsProjectGpsSettings::writeXml( QDomDocument &doc, const QgsReadWri
element.setAttribute( QStringLiteral( "destinationLayer" ), QString() );
}

{
QDomElement timeStampElement = doc.createElement( QStringLiteral( "timeStampFields" ) );
for ( auto it = mDestinationTimestampFields.constBegin(); it != mDestinationTimestampFields.constEnd(); ++it )
{
QDomElement layerElement = doc.createElement( QStringLiteral( "field" ) );
layerElement.setAttribute( QStringLiteral( "destinationLayer" ), it.key() );
layerElement.setAttribute( QStringLiteral( "field" ), it.value() );
timeStampElement.appendChild( layerElement );
}
element.appendChild( timeStampElement );
}

return element;
}

Expand All @@ -108,6 +141,20 @@ QgsVectorLayer *QgsProjectGpsSettings::destinationLayer() const
return mDestinationLayer.get();
}

QMap<QString, QString> QgsProjectGpsSettings::destinationTimeStampFields() const
{
return mDestinationTimestampFields;
}

QString QgsProjectGpsSettings::destinationTimeStampField() const
{
if ( QgsVectorLayer *vl = destinationLayer() )
{
return mDestinationTimestampFields.value( vl->id() );
}
return QString();
}

void QgsProjectGpsSettings::setAutomaticallyAddTrackVertices( bool enabled )
{
if ( enabled == mAutoAddTrackVertices )
Expand Down Expand Up @@ -144,4 +191,28 @@ void QgsProjectGpsSettings::setDestinationLayer( QgsVectorLayer *layer )

mDestinationLayer.setLayer( layer );
emit destinationLayerChanged( layer );

if ( layer )
{
emit destinationTimeStampFieldChanged( mDestinationTimestampFields.value( layer->id() ) );
}
else
{
emit destinationTimeStampFieldChanged( QString() );
}
}

void QgsProjectGpsSettings::setDestinationTimeStampField( QgsVectorLayer *layer, const QString &field )
{
if ( !layer )
return;

if ( mDestinationTimestampFields.value( layer->id() ) != field )
{
mDestinationTimestampFields.insert( layer->id(), field );
if ( layer == destinationLayer() )
{
emit destinationTimeStampFieldChanged( field );
}
}
}

0 comments on commit ce6cf4a

Please sign in to comment.