Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Avoid emitting QgsProject::snappingConfigChanged multiple times when …
…reading or clearing projects
  • Loading branch information
nyalldawson committed Dec 9, 2020
1 parent da51a5a commit 78cdadf
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 4 deletions.
64 changes: 60 additions & 4 deletions src/core/qgsproject.cpp
Expand Up @@ -84,6 +84,39 @@
// canonical project instance
QgsProject *QgsProject::sProject = nullptr;

///@cond PRIVATE
class ScopedIntIncrementor
{
public:

ScopedIntIncrementor( int *variable )
: mVariable( variable )
{
( *mVariable )++;
}

ScopedIntIncrementor( const ScopedIntIncrementor &other ) = delete;
ScopedIntIncrementor &operator=( const ScopedIntIncrementor &other ) = delete;

void release()
{
if ( mVariable )
( *mVariable )--;

mVariable = nullptr;
}

~ScopedIntIncrementor()
{
release();
}

private:
int *mVariable = nullptr;
};
///@endcond


/**
Take the given scope and key and convert them to a string list of key
tokens that will be used to navigate through a Property hierarchy
Expand Down Expand Up @@ -779,6 +812,7 @@ void QgsProject::setTransformContext( const QgsCoordinateTransformContext &conte

void QgsProject::clear()
{
ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );

mProjectScope.reset();
mFile.setFileName( QString() );
Expand Down Expand Up @@ -815,7 +849,6 @@ void QgsProject::clear()
mTimeSettings->reset();
mDisplaySettings->reset();
mSnappingConfig.reset();
emit snappingConfigChanged( mSnappingConfig );
emit avoidIntersectionsModeChanged();
emit topologicalEditingChanged();

Expand Down Expand Up @@ -856,11 +889,18 @@ void QgsProject::clear()
int alpha = mSettings.value( QStringLiteral( "qgis/default_selection_color_alpha" ), 255 ).toInt();
setSelectionColor( QColor( red, green, blue, alpha ) );

mSnappingConfig.clearIndividualLayerSettings();

removeAllMapLayers();
mRootGroup->clear();
if ( mMainAnnotationLayer )
mMainAnnotationLayer->reset();

snapSingleBlocker.release();

if ( !mBlockSnappingUpdates )
emit snappingConfigChanged( mSnappingConfig );

setDirty( false );
emit homePathChanged();
emit cleared();
Expand Down Expand Up @@ -1283,6 +1323,9 @@ bool QgsProject::read( QgsProject::ReadFlags flags )

bool QgsProject::readProjectFile( const QString &filename, QgsProject::ReadFlags flags )
{
// avoid multiple emission of snapping updated signals
ScopedIntIncrementor snapSignalBlock( &mBlockSnappingUpdates );

QFile projectFile( filename );
clearError();

Expand Down Expand Up @@ -1707,7 +1750,11 @@ bool QgsProject::readProjectFile( const QString &filename, QgsProject::ReadFlags
emit readProjectWithContext( *doc, context );

profile.switchTask( tr( "Updating interface" ) );
emit snappingConfigChanged( mSnappingConfig );

snapSignalBlock.release();
if ( !mBlockSnappingUpdates )
emit snappingConfigChanged( mSnappingConfig );

emit avoidIntersectionsModeChanged();
emit topologicalEditingChanged();
emit projectColorsChanged();
Expand Down Expand Up @@ -2013,13 +2060,13 @@ void QgsProject::onMapLayersAdded( const QList<QgsMapLayer *> &layers )
}
}

if ( mSnappingConfig.addLayers( layers ) )
if ( !mBlockSnappingUpdates && mSnappingConfig.addLayers( layers ) )
emit snappingConfigChanged( mSnappingConfig );
}

void QgsProject::onMapLayersRemoved( const QList<QgsMapLayer *> &layers )
{
if ( mSnappingConfig.removeLayers( layers ) )
if ( !mBlockSnappingUpdates && mSnappingConfig.removeLayers( layers ) )
emit snappingConfigChanged( mSnappingConfig );
}

Expand Down Expand Up @@ -3424,8 +3471,17 @@ QgsAnnotationLayer *QgsProject::mainAnnotationLayer()

void QgsProject::removeAllMapLayers()
{
if ( mLayerStore->count() == 0 )
return;

ScopedIntIncrementor snapSingleBlocker( &mBlockSnappingUpdates );
mProjectScope.reset();
mLayerStore->removeAllMapLayers();

snapSingleBlocker.release();
mSnappingConfig.clearIndividualLayerSettings();
if ( !mBlockSnappingUpdates )
emit snappingConfigChanged( mSnappingConfig );
}

void QgsProject::reloadAllLayers()
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsproject.h
Expand Up @@ -2072,6 +2072,8 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera

mutable std::unique_ptr< QgsExpressionContextScope > mProjectScope;

int mBlockSnappingUpdates = 0;

friend class QgsProjectDirtyBlocker;

// Required to avoid creating a new project in it's destructor
Expand Down
38 changes: 38 additions & 0 deletions tests/src/python/test_qgsproject.py
Expand Up @@ -807,6 +807,44 @@ def testUpgradeOtfFrom2x(self):
self.assertTrue(prj.crs().isValid())
self.assertEqual(prj.crs().authid(), 'EPSG:2056')

def testSnappingChangedSignal(self):
"""
Test the snappingConfigChanged signal
"""
project = QgsProject()
spy = QSignalSpy(project.snappingConfigChanged)
l0 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "points.shp"), "points", "ogr")
l1 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "lines.shp"), "lines", "ogr")
l2 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "polys.shp"), "polys", "ogr")
project.addMapLayers([l0, l1])
self.assertEqual(len(spy), 1)
project.addMapLayer(l2)
self.assertEqual(len(spy), 2)

self.assertEqual(len(project.snappingConfig().individualLayerSettings()), 3)

tmpDir = QTemporaryDir()
tmpFile = "{}/project_snap.qgs".format(tmpDir.path())
self.assertTrue(project.write(tmpFile))

# only ONE signal!
project.clear()
self.assertEqual(len(spy), 3)

self.assertFalse(project.snappingConfig().individualLayerSettings())

p2 = QgsProject()
spy2 = QSignalSpy(p2.snappingConfigChanged)
p2.read(tmpFile)
# only ONE signal!
self.assertEqual(len(spy2), 1)

self.assertEqual(len(p2.snappingConfig().individualLayerSettings()), 3)

p2.removeAllMapLayers()
self.assertEqual(len(spy2), 2)
self.assertFalse(p2.snappingConfig().individualLayerSettings())

def testRelativePaths(self):
"""
Test whether paths to layer sources are stored as relative to the project path
Expand Down

0 comments on commit 78cdadf

Please sign in to comment.