Skip to content

Commit 46efc9a

Browse files
committedOct 15, 2018
Re-initialize layer checks on configuration changes
1 parent 273d3c8 commit 46efc9a

File tree

2 files changed

+73
-40
lines changed

2 files changed

+73
-40
lines changed
 

‎src/app/qgsgeometryvalidationservice.cpp

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,10 @@ void QgsGeometryValidationService::onLayersAdded( const QList<QgsMapLayer *> &la
5454
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
5555
if ( vectorLayer )
5656
{
57-
connect( vectorLayer, &QgsVectorLayer::featureAdded, this, [this, vectorLayer]( QgsFeatureId fid )
57+
connect( vectorLayer->geometryOptions(), &QgsGeometryOptions::checkConfigurationChanged, this, [this, vectorLayer]()
5858
{
59-
onFeatureAdded( vectorLayer, fid );
60-
} );
61-
connect( vectorLayer, &QgsVectorLayer::geometryChanged, this, [this, vectorLayer]( QgsFeatureId fid, const QgsGeometry & geometry )
62-
{
63-
onGeometryChanged( vectorLayer, fid, geometry );
64-
} );
65-
connect( vectorLayer, &QgsVectorLayer::featureDeleted, this, [this, vectorLayer]( QgsFeatureId fid )
66-
{
67-
onFeatureDeleted( vectorLayer, fid );
68-
} );
69-
connect( vectorLayer, &QgsVectorLayer::beforeCommitChanges, this, [this, vectorLayer]()
70-
{
71-
onBeforeCommitChanges( vectorLayer );
72-
} );
59+
enableLayerChecks( vectorLayer );
60+
}, Qt::UniqueConnection );
7361

7462
enableLayerChecks( vectorLayer );
7563
}
@@ -78,7 +66,7 @@ void QgsGeometryValidationService::onLayersAdded( const QList<QgsMapLayer *> &la
7866

7967
void QgsGeometryValidationService::onFeatureAdded( QgsVectorLayer *layer, QgsFeatureId fid )
8068
{
81-
if ( !mLayerCheckStates[layer].topologyChecks.empty() )
69+
if ( !mLayerChecks[layer].topologyChecks.empty() )
8270
{
8371
// TODO: Cancel topology checks
8472
layer->setAllowCommit( false );
@@ -88,7 +76,7 @@ void QgsGeometryValidationService::onFeatureAdded( QgsVectorLayer *layer, QgsFea
8876

8977
void QgsGeometryValidationService::onGeometryChanged( QgsVectorLayer *layer, QgsFeatureId fid, const QgsGeometry &geometry )
9078
{
91-
if ( !mLayerCheckStates[layer].topologyChecks.empty() )
79+
if ( !mLayerChecks[layer].topologyChecks.empty() )
9280
{
9381
// TODO: Cancel topology checks
9482
layer->setAllowCommit( false );
@@ -101,7 +89,7 @@ void QgsGeometryValidationService::onGeometryChanged( QgsVectorLayer *layer, Qgs
10189

10290
void QgsGeometryValidationService::onFeatureDeleted( QgsVectorLayer *layer, QgsFeatureId fid )
10391
{
104-
if ( !mLayerCheckStates[layer].topologyChecks.empty() )
92+
if ( !mLayerChecks[layer].topologyChecks.empty() )
10593
{
10694
// TODO: Cancel topology checks
10795
layer->setAllowCommit( false );
@@ -112,7 +100,7 @@ void QgsGeometryValidationService::onFeatureDeleted( QgsVectorLayer *layer, QgsF
112100

113101
void QgsGeometryValidationService::onBeforeCommitChanges( QgsVectorLayer *layer )
114102
{
115-
if ( !mLayerCheckStates[layer].topologyChecks.empty() ) // TODO && topologyChecks not fulfilled
103+
if ( !mLayerChecks[layer].topologyChecks.empty() ) // TODO && topologyChecks not fulfilled
116104
{
117105
if ( !layer->allowCommit() )
118106
{
@@ -124,12 +112,29 @@ void QgsGeometryValidationService::onBeforeCommitChanges( QgsVectorLayer *layer
124112

125113
void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
126114
{
127-
// TODO: finish all ongoing checks
128-
qDeleteAll( mLayerCheckStates[layer].singleFeatureChecks );
129-
qDeleteAll( mLayerCheckStates[layer].topologyChecks );
115+
if ( layer->geometryOptions()->geometryChecks().empty() && !mLayerChecks.contains( layer ) )
116+
return;
117+
118+
VectorLayerCheckInformation &checkInformation = mLayerChecks[layer];
119+
120+
cancelTopologyCheck( layer );
121+
122+
qDeleteAll( checkInformation.singleFeatureChecks );
123+
qDeleteAll( checkInformation.topologyChecks );
124+
delete checkInformation.context;
125+
126+
if ( layer->geometryOptions()->geometryChecks().empty() )
127+
{
128+
for ( QMetaObject::Connection connection : qgis::as_const( checkInformation.connections ) )
129+
{
130+
disconnect( connection );
131+
}
132+
checkInformation.connections.clear();
133+
return;
134+
}
135+
136+
checkInformation.context = new QgsGeometryCheckContext( log10( layer->geometryOptions()->geometryPrecision() ) * -1, mProject->crs(), mProject->transformContext() );
130137

131-
// TODO: ownership and lifetime of the context!!
132-
auto context = new QgsGeometryCheckContext( log10( layer->geometryOptions()->geometryPrecision() ) * -1, mProject->crs(), mProject->transformContext() );
133138
QList<QgsGeometryCheck *> layerChecks;
134139

135140
QgsGeometryCheckRegistry *checkRegistry = QgsAnalysis::instance()->geometryCheckRegistry();
@@ -144,7 +149,7 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
144149
if ( activeChecks.contains( checkId ) )
145150
{
146151
const QVariantMap checkConfiguration = layer->geometryOptions()->checkConfiguration( checkId );
147-
layerChecks.append( factory->createGeometryCheck( context, checkConfiguration ) );
152+
layerChecks.append( factory->createGeometryCheck( checkInformation.context, checkConfiguration ) );
148153
}
149154
}
150155

@@ -155,7 +160,7 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
155160
singleGeometryChecks.append( dynamic_cast<QgsSingleGeometryCheck *>( check ) );
156161
}
157162

158-
mLayerCheckStates[layer].singleFeatureChecks = singleGeometryChecks;
163+
checkInformation.singleFeatureChecks = singleGeometryChecks;
159164

160165
// Topology checks
161166
QList<QgsGeometryCheck *> topologyChecks;
@@ -167,31 +172,56 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
167172
if ( activeChecks.contains( checkId ) )
168173
{
169174
const QVariantMap checkConfiguration = layer->geometryOptions()->checkConfiguration( checkId );
170-
topologyChecks.append( factory->createGeometryCheck( context, checkConfiguration ) );
175+
topologyChecks.append( factory->createGeometryCheck( checkInformation.context, checkConfiguration ) );
171176
}
172177
}
173178

174-
mLayerCheckStates[layer].topologyChecks = topologyChecks;
179+
checkInformation.topologyChecks = topologyChecks;
180+
181+
// Connect to all modifications on a layer that can introduce a geometry or topology error
182+
// Also connect to the beforeCommitChanges signal, so we can trigger topology checks
183+
// We keep all connections around in a list, so if in the future all checks get disabled
184+
// we can kill those connections to be sure the layer does not even get a tiny bit of overhead.
185+
checkInformation.connections
186+
<< connect( layer, &QgsVectorLayer::featureAdded, this, [this, layer]( QgsFeatureId fid )
187+
{
188+
onFeatureAdded( layer, fid );
189+
}, Qt::UniqueConnection );
190+
checkInformation.connections
191+
<< connect( layer, &QgsVectorLayer::geometryChanged, this, [this, layer]( QgsFeatureId fid, const QgsGeometry & geometry )
192+
{
193+
onGeometryChanged( layer, fid, geometry );
194+
}, Qt::UniqueConnection );
195+
checkInformation.connections
196+
<< connect( layer, &QgsVectorLayer::featureDeleted, this, [this, layer]( QgsFeatureId fid )
197+
{
198+
onFeatureDeleted( layer, fid );
199+
}, Qt::UniqueConnection );
200+
checkInformation.connections
201+
<< connect( layer, &QgsVectorLayer::beforeCommitChanges, this, [this, layer]()
202+
{
203+
onBeforeCommitChanges( layer );
204+
}, Qt::UniqueConnection );
175205
}
176206

177207
void QgsGeometryValidationService::cancelTopologyCheck( QgsVectorLayer *layer )
178208
{
179-
QFutureWatcher<void> *futureWatcher = mLayerCheckStates[layer].topologyCheckFutureWatcher;
209+
QFutureWatcher<void> *futureWatcher = mLayerChecks[layer].topologyCheckFutureWatcher;
180210
if ( futureWatcher )
181211
{
182212
// Make sure no more checks are started first
183213
futureWatcher->cancel();
184214

185215
// Tell all checks to stop asap
186-
const auto feedbacks = mLayerCheckStates[layer].topologyCheckFeedbacks;
216+
const auto feedbacks = mLayerChecks[layer].topologyCheckFeedbacks;
187217
for ( QgsFeedback *feedback : feedbacks )
188218
{
189219
if ( feedback )
190220
feedback->cancel();
191221
}
192222

193223
futureWatcher->waitForFinished();
194-
mLayerCheckStates[layer].topologyCheckFutureWatcher = nullptr;
224+
mLayerChecks[layer].topologyCheckFutureWatcher = nullptr;
195225
}
196226
}
197227

@@ -206,7 +236,7 @@ void QgsGeometryValidationService::processFeature( QgsVectorLayer *layer, QgsFea
206236

207237
QgsFeature feature = layer->getFeature( fid );
208238

209-
const auto &checks = mLayerCheckStates[layer].singleFeatureChecks;
239+
const auto &checks = mLayerChecks[layer].singleFeatureChecks;
210240

211241
// The errors are going to be sent out via a signal. We cannot keep ownership in here (or can we?)
212242
// nor can we be sure that a single slot is connected to the signal. So make it a shared_ptr.
@@ -232,7 +262,7 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
232262

233263
// TODO: ownership of these objects...
234264
QgsVectorLayerFeaturePool *featurePool = new QgsVectorLayerFeaturePool( layer );
235-
QList<QgsGeometryCheckError *> &allErrors = mLayerCheckStates[layer].topologyCheckErrors;
265+
QList<QgsGeometryCheckError *> &allErrors = mLayerChecks[layer].topologyCheckErrors;
236266
QMap<QString, QgsFeatureIds> layerIds;
237267

238268
QgsFeatureRequest request = QgsFeatureRequest( affectedFeatureIds ).setSubsetOfAttributes( QgsAttributeList() );
@@ -255,13 +285,13 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
255285
mFeaturePools.insert( layer->id(), featurePool );
256286
}
257287

258-
const QList<QgsGeometryCheck *> checks = mLayerCheckStates[layer].topologyChecks;
288+
const QList<QgsGeometryCheck *> checks = mLayerChecks[layer].topologyChecks;
259289

260290
QMap<const QgsGeometryCheck *, QgsFeedback *> feedbacks;
261291
for ( QgsGeometryCheck *check : checks )
262292
feedbacks.insert( check, new QgsFeedback() );
263293

264-
mLayerCheckStates[layer].topologyCheckFeedbacks = feedbacks.values();
294+
mLayerChecks[layer].topologyCheckFeedbacks = feedbacks.values();
265295

266296
QFuture<void> future = QtConcurrent::map( checks, [&allErrors, layerFeatureIds, layer, feedbacks, this]( const QgsGeometryCheck * check )
267297
{
@@ -296,9 +326,9 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
296326
errorLocker.unlock();
297327
qDeleteAll( feedbacks.values() );
298328
futureWatcher->deleteLater();
299-
if ( mLayerCheckStates[layer].topologyCheckFutureWatcher == futureWatcher )
300-
mLayerCheckStates[layer].topologyCheckFutureWatcher = nullptr;
329+
if ( mLayerChecks[layer].topologyCheckFutureWatcher == futureWatcher )
330+
mLayerChecks[layer].topologyCheckFutureWatcher = nullptr;
301331
} );
302332

303-
mLayerCheckStates[layer].topologyCheckFutureWatcher = futureWatcher;
333+
mLayerChecks[layer].topologyCheckFutureWatcher = futureWatcher;
304334
}

‎src/app/qgsgeometryvalidationservice.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class QgsSingleGeometryCheckError;
3232
class QgsGeometryCheckError;
3333
class QgsFeedback;
3434
class QgsFeaturePool;
35+
struct QgsGeometryCheckContext;
3536

3637
/**
3738
* This service connects to all layers in a project and triggers validation
@@ -95,17 +96,19 @@ class QgsGeometryValidationService : public QObject
9596

9697
QgsProject *mProject = nullptr;
9798

98-
struct VectorCheckState
99+
struct VectorLayerCheckInformation
99100
{
100101
QList< QgsSingleGeometryCheck * > singleFeatureChecks;
101102
QList< QgsGeometryCheck *> topologyChecks;
102103
QFutureWatcher<void> *topologyCheckFutureWatcher = nullptr;
103104
QList<QgsFeedback *> topologyCheckFeedbacks; // will be deleted when topologyCheckFutureWatcher is delteed
104105
QList<QgsGeometryCheckError *> topologyCheckErrors;
106+
QList<QMetaObject::Connection> connections;
107+
QgsGeometryCheckContext *context = nullptr;
105108
};
106109

107110
QReadWriteLock mTopologyCheckLock;
108-
QHash<QgsVectorLayer *, VectorCheckState> mLayerCheckStates;
111+
QHash<QgsVectorLayer *, VectorLayerCheckInformation> mLayerChecks;
109112
QMap<QString, QgsFeaturePool *> mFeaturePools;
110113
};
111114

0 commit comments

Comments
 (0)
Please sign in to comment.