Skip to content

Commit

Permalink
Resurrect option to follow layers
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 7, 2022
1 parent 3aae524 commit d0b4bcf
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 5 deletions.
40 changes: 40 additions & 0 deletions python/core/auto_generated/project/qgsprojectgpssettings.sip.in
Expand Up @@ -74,12 +74,27 @@ layer edit buffer).
.. seealso:: :py:func:`setAutomaticallyCommitFeatures`

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

bool destinationFollowsActiveLayer() const;
%Docstring
Returns ``True`` if the destination layer for storing features digitized from GPS
should follow the current active layer automatically.

.. seealso:: :py:func:`setDestinationFollowsActiveLayer`

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

QgsVectorLayer *destinationLayer() const;
%Docstring
Returns the destination layer to be used for storing features digitized from GPS.

.. note::

If :py:func:`~QgsProjectGpsSettings.destinationFollowsActiveLayer` is ``True`` then this layer will be changed
whenever the user changes the active layer in the QGIS interface.

.. seealso:: :py:func:`setDestinationLayer`

.. seealso:: :py:func:`destinationLayerChanged`
Expand All @@ -106,12 +121,27 @@ layer edit buffer).
.. seealso:: :py:func:`automaticallyCommitFeatures`

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

void setDestinationFollowsActiveLayer( bool follow );
%Docstring
Sets whether the destination layer for storing features digitized from GPS
should follow the current active layer automatically.

.. seealso:: :py:func:`destinationFollowsActiveLayer`

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

void setDestinationLayer( QgsVectorLayer *layer );
%Docstring
Sets the destination ``layer`` to be used for storing features digitized from GPS.

.. note::

If :py:func:`~QgsProjectGpsSettings.destinationFollowsActiveLayer` is ``True`` then this layer will be changed
whenever the user changes the active layer in the QGIS interface.

.. seealso:: :py:func:`destinationLayer`

.. seealso:: :py:func:`destinationLayerChanged`
Expand All @@ -137,6 +167,16 @@ is changed.
.. seealso:: :py:func:`automaticallyCommitFeatures`

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

void destinationFollowsActiveLayerChanged( bool follows );
%Docstring
Emitted whenever the :py:func:`~QgsProjectGpsSettings.destinationFollowsActiveLayer` setting
is changed.

.. seealso:: :py:func:`destinationFollowsActiveLayer`

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

void destinationLayerChanged( QgsVectorLayer *layer );
Expand Down
19 changes: 19 additions & 0 deletions src/app/gps/qgsappgpsdigitizing.cpp
Expand Up @@ -75,6 +75,25 @@ QgsAppGpsDigitizing::QgsAppGpsDigitizing( QgsAppGpsConnection *connection, QgsMa

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

connect( QgisApp::instance(), &QgisApp::activeLayerChanged, this, [ = ]( QgsMapLayer * layer )
{
if ( QgsProject::instance()->gpsSettings()->destinationFollowsActiveLayer() )
{
QgsProject::instance()->gpsSettings()->setDestinationLayer( qobject_cast< QgsVectorLayer *> ( layer ) );
}
} );
connect( QgsProject::instance()->gpsSettings(), &QgsProjectGpsSettings::destinationFollowsActiveLayerChanged, this, [ = ]( bool enabled )
{
if ( enabled )
{
QgsProject::instance()->gpsSettings()->setDestinationLayer( qobject_cast< QgsVectorLayer *> ( QgisApp::instance()->activeLayer() ) );
}
} );
if ( QgsProject::instance()->gpsSettings()->destinationFollowsActiveLayer() )
{
QgsProject::instance()->gpsSettings()->setDestinationLayer( qobject_cast< QgsVectorLayer *> ( QgisApp::instance()->activeLayer() ) );
}
}

QgsAppGpsDigitizing::~QgsAppGpsDigitizing()
Expand Down
18 changes: 17 additions & 1 deletion src/app/gps/qgsgpstoolbar.cpp
Expand Up @@ -275,6 +275,21 @@ void QgsGpsToolBar::destinationMenuAboutToShow()
const QString currentLayerId = QgsProject::instance()->gpsSettings()->destinationLayer() ?
QgsProject::instance()->gpsSettings()->destinationLayer()->id() : QString();

QAction *followAction = new QAction( tr( "Follow Active Layer" ), mDestinationLayerMenu );
followAction->setToolTip( tr( "Always add GPS digitized features to the active layer" ) );
followAction->setCheckable( true );
followAction->setChecked( QgsProject::instance()->gpsSettings()->destinationFollowsActiveLayer() );

connect( followAction, &QAction::toggled, this, [ = ]( bool checked )
{
if ( checked && !QgsProject::instance()->gpsSettings()->destinationFollowsActiveLayer() )
{
QgsProject::instance()->gpsSettings()->setDestinationFollowsActiveLayer( true );
QgsProject::instance()->setDirty();
}
} );
mDestinationLayerMenu->addAction( followAction );

for ( int row = 0; row < mDestinationLayerModel->rowCount(); ++row )
{
const QModelIndex index = mDestinationLayerModel->index( row, 0 );
Expand All @@ -286,7 +301,7 @@ void QgsGpsToolBar::destinationMenuAboutToShow()

const QString actionLayerId = index.data( QgsMapLayerModel::ItemDataRole::LayerIdRole ).toString();

if ( actionLayerId == currentLayerId )
if ( actionLayerId == currentLayerId && !QgsProject::instance()->gpsSettings()->destinationFollowsActiveLayer() )
layerAction->setChecked( true );

connect( layerAction, &QAction::toggled, this, [ = ]( bool checked )
Expand All @@ -296,6 +311,7 @@ void QgsGpsToolBar::destinationMenuAboutToShow()
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProject::instance()->mapLayer( actionLayerId ) );
if ( layer != QgsProject::instance()->gpsSettings()->destinationLayer() )
{
QgsProject::instance()->gpsSettings()->setDestinationFollowsActiveLayer( false );
QgsProject::instance()->gpsSettings()->setDestinationLayer( layer );
QgsProject::instance()->setDirty();
}
Expand Down
23 changes: 21 additions & 2 deletions src/core/project/qgsprojectgpssettings.cpp
Expand Up @@ -35,18 +35,21 @@ void QgsProjectGpsSettings::reset()
{
mAutoAddTrackVertices = false;
mAutoCommitFeatures = false;
mDestinationFollowsActiveLayer = true;

mDestinationLayer.setLayer( nullptr );

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

bool QgsProjectGpsSettings::readXml( const QDomElement &element, const QgsReadWriteContext & )
{
mAutoAddTrackVertices = element.attribute( QStringLiteral( "autoAddTrackVertices" ), "0" ).toInt();
mAutoCommitFeatures = element.attribute( QStringLiteral( "autoCommitFeatures" ), "0" ).toInt();
mDestinationFollowsActiveLayer = element.attribute( QStringLiteral( "destinationFollowsActiveLayer" ), "1" ).toInt();

const QString layerId = element.attribute( QStringLiteral( "destinationLayer" ) );
const QString layerName = element.attribute( QStringLiteral( "destinationLayerName" ) );
Expand All @@ -57,6 +60,7 @@ bool QgsProjectGpsSettings::readXml( const QDomElement &element, const QgsReadWr

emit automaticallyAddTrackVerticesChanged( mAutoAddTrackVertices );
emit automaticallyCommitFeaturesChanged( mAutoCommitFeatures );
emit destinationFollowsActiveLayerChanged( mDestinationFollowsActiveLayer );
emit destinationLayerChanged( nullptr ); // wont' be set until resolve is called
return true;
}
Expand All @@ -67,6 +71,7 @@ QDomElement QgsProjectGpsSettings::writeXml( QDomDocument &doc, const QgsReadWri

element.setAttribute( QStringLiteral( "autoAddTrackVertices" ), mAutoAddTrackVertices ? 1 : 0 );
element.setAttribute( QStringLiteral( "autoCommitFeatures" ), mAutoCommitFeatures ? 1 : 0 );
element.setAttribute( QStringLiteral( "destinationFollowsActiveLayer" ), mDestinationFollowsActiveLayer ? 1 : 0 );

if ( mDestinationLayer )
{
Expand All @@ -93,6 +98,11 @@ bool QgsProjectGpsSettings::automaticallyCommitFeatures() const
return mAutoCommitFeatures;
}

bool QgsProjectGpsSettings::destinationFollowsActiveLayer() const
{
return mDestinationFollowsActiveLayer;
}

QgsVectorLayer *QgsProjectGpsSettings::destinationLayer() const
{
return mDestinationLayer.get();
Expand All @@ -116,6 +126,15 @@ void QgsProjectGpsSettings::setAutomaticallyCommitFeatures( bool enabled )
emit automaticallyCommitFeaturesChanged( enabled );
}

void QgsProjectGpsSettings::setDestinationFollowsActiveLayer( bool follow )
{
if ( follow == mDestinationFollowsActiveLayer )
return;

mDestinationFollowsActiveLayer = follow;
emit destinationFollowsActiveLayerChanged( follow );
}

void QgsProjectGpsSettings::setDestinationLayer( QgsVectorLayer *layer )
{
if ( layer == mDestinationLayer.get() )
Expand Down
34 changes: 34 additions & 0 deletions src/core/project/qgsprojectgpssettings.h
Expand Up @@ -91,9 +91,21 @@ class CORE_EXPORT QgsProjectGpsSettings : public QObject
*/
bool automaticallyCommitFeatures() const;

/**
* Returns TRUE if the destination layer for storing features digitized from GPS
* should follow the current active layer automatically.
*
* \see setDestinationFollowsActiveLayer()
* \see destinationFollowsActiveLayerChanged()
*/
bool destinationFollowsActiveLayer() const;

/**
* Returns the destination layer to be used for storing features digitized from GPS.
*
* \note If destinationFollowsActiveLayer() is TRUE then this layer will be changed
* whenever the user changes the active layer in the QGIS interface.
*
* \see setDestinationLayer()
* \see destinationLayerChanged()
*/
Expand All @@ -120,9 +132,21 @@ class CORE_EXPORT QgsProjectGpsSettings : public QObject
*/
void setAutomaticallyCommitFeatures( bool enabled );

/**
* Sets whether the destination layer for storing features digitized from GPS
* should follow the current active layer automatically.
*
* \see destinationFollowsActiveLayer()
* \see destinationFollowsActiveLayerChanged()
*/
void setDestinationFollowsActiveLayer( bool follow );

/**
* Sets the destination \a layer to be used for storing features digitized from GPS.
*
* \note If destinationFollowsActiveLayer() is TRUE then this layer will be changed
* whenever the user changes the active layer in the QGIS interface.
*
* \see destinationLayer()
* \see destinationLayerChanged()
*/
Expand All @@ -148,6 +172,15 @@ class CORE_EXPORT QgsProjectGpsSettings : public QObject
*/
void automaticallyCommitFeaturesChanged( bool enabled );

/**
* Emitted whenever the destinationFollowsActiveLayer() setting
* is changed.
*
* \see destinationFollowsActiveLayer()
* \see setDestinationFollowsActiveLayer()
*/
void destinationFollowsActiveLayerChanged( bool follows );

/**
* Emitted whenever the destination layer for features digitized from GPS
* is changed.
Expand All @@ -162,6 +195,7 @@ class CORE_EXPORT QgsProjectGpsSettings : public QObject
bool mAutoAddTrackVertices = false;
bool mAutoCommitFeatures = false;

bool mDestinationFollowsActiveLayer = true;
QgsVectorLayerRef mDestinationLayer;

};
Expand Down
28 changes: 26 additions & 2 deletions tests/src/python/test_qgsprojectgpssettings.py
Expand Up @@ -52,9 +52,11 @@ def testSettings(self):
p = QgsProjectGpsSettings()
self.assertFalse(p.automaticallyCommitFeatures())
self.assertFalse(p.automaticallyAddTrackVertices())
self.assertTrue(p.destinationFollowsActiveLayer())

spy_add_track = QSignalSpy(p.automaticallyAddTrackVerticesChanged)
spy_auto_commit = QSignalSpy(p.automaticallyCommitFeaturesChanged)
spy_destination_follows_active = QSignalSpy(p.destinationFollowsActiveLayerChanged)

p.setAutomaticallyAddTrackVertices(True)
self.assertEqual(len(spy_add_track), 1)
Expand All @@ -80,6 +82,18 @@ def testSettings(self):
self.assertEqual(len(spy_auto_commit), 2)
self.assertFalse(spy_auto_commit[-1][0])

p.setDestinationFollowsActiveLayer(False)
self.assertEqual(len(spy_destination_follows_active), 1)
self.assertFalse(spy_destination_follows_active[-1][0])

p.setDestinationFollowsActiveLayer(False)
self.assertEqual(len(spy_destination_follows_active), 1)

self.assertFalse(p.destinationFollowsActiveLayer())
p.setDestinationFollowsActiveLayer(True)
self.assertEqual(len(spy_destination_follows_active), 2)
self.assertTrue(spy_destination_follows_active[-1][0])

layer1 = QgsVectorLayer(os.path.join(unitTestDataPath(), 'lines.shp'), 'layer1')
self.assertTrue(layer1.isValid())
layer2 = QgsVectorLayer(os.path.join(unitTestDataPath(), 'points.shp'), 'layer2')
Expand Down Expand Up @@ -107,9 +121,11 @@ def testReset(self):
p = QgsProjectGpsSettings()
self.assertFalse(p.automaticallyCommitFeatures())
self.assertFalse(p.automaticallyAddTrackVertices())
self.assertTrue(p.destinationFollowsActiveLayer())

p.setAutomaticallyCommitFeatures(True)
p.setAutomaticallyAddTrackVertices(True)
p.setDestinationFollowsActiveLayer(False)

layer1 = QgsVectorLayer(os.path.join(unitTestDataPath(), 'lines.shp'), 'layer1')
self.assertTrue(layer1.isValid())
Expand All @@ -118,23 +134,28 @@ def testReset(self):
spy_add_track = QSignalSpy(p.automaticallyAddTrackVerticesChanged)
spy_auto_commit = QSignalSpy(p.automaticallyCommitFeaturesChanged)
spy_dest_layer_changed = QSignalSpy(p.destinationLayerChanged)
spy_destination_follows_active = QSignalSpy(p.destinationFollowsActiveLayerChanged)

p.reset()
self.assertFalse(p.automaticallyAddTrackVertices())
self.assertFalse(p.automaticallyCommitFeatures())
self.assertFalse(p.destinationLayer())
self.assertTrue(p.destinationFollowsActiveLayer())

self.assertEqual(len(spy_add_track), 1)
self.assertFalse(spy_auto_commit[-1][0])
self.assertEqual(len(spy_auto_commit), 1)
self.assertFalse(spy_auto_commit[-1][0])
self.assertEqual(len(spy_dest_layer_changed), 1)
self.assertEqual(len(spy_destination_follows_active), 1)
self.assertTrue(spy_destination_follows_active[-1][0])

def testReadWrite(self):
p = QgsProjectGpsSettings()

p.setAutomaticallyCommitFeatures(True)
p.setAutomaticallyAddTrackVertices(True)
p.setDestinationFollowsActiveLayer(False)

layer1 = QgsVectorLayer(os.path.join(unitTestDataPath(), 'lines.shp'), 'layer1')
self.assertTrue(layer1.isValid())
Expand All @@ -150,13 +171,16 @@ def testReadWrite(self):
spy = QSignalSpy(p2.automaticallyAddTrackVerticesChanged)
spy2 = QSignalSpy(p2.automaticallyCommitFeaturesChanged)
spy_dest_layer_changed = QSignalSpy(p2.destinationLayerChanged)
spy_destination_follows_active = QSignalSpy(p2.destinationFollowsActiveLayerChanged)

self.assertTrue(p2.readXml(elem, QgsReadWriteContext()))
self.assertEqual(len(spy), 1)
self.assertEqual(len(spy2), 1)
self.assertEqual(len(spy_dest_layer_changed), 1)
self.assertTrue(p.automaticallyCommitFeatures())
self.assertTrue(p.automaticallyAddTrackVertices())
self.assertEqual(len(spy_destination_follows_active), 1)
self.assertTrue(p2.automaticallyCommitFeatures())
self.assertTrue(p2.automaticallyAddTrackVertices())
self.assertFalse(p2.destinationFollowsActiveLayer())
# needs to be resolved first
self.assertFalse(p2.destinationLayer())

Expand Down

0 comments on commit d0b4bcf

Please sign in to comment.