@@ -54,22 +54,10 @@ void QgsGeometryValidationService::onLayersAdded( const QList<QgsMapLayer *> &la
54
54
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
55
55
if ( vectorLayer )
56
56
{
57
- connect ( vectorLayer, &QgsVectorLayer::featureAdded , this , [this , vectorLayer]( QgsFeatureId fid )
57
+ connect ( vectorLayer-> geometryOptions () , &QgsGeometryOptions::checkConfigurationChanged , this , [this , vectorLayer]()
58
58
{
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 );
73
61
74
62
enableLayerChecks ( vectorLayer );
75
63
}
@@ -78,7 +66,7 @@ void QgsGeometryValidationService::onLayersAdded( const QList<QgsMapLayer *> &la
78
66
79
67
void QgsGeometryValidationService::onFeatureAdded ( QgsVectorLayer *layer, QgsFeatureId fid )
80
68
{
81
- if ( !mLayerCheckStates [layer].topologyChecks .empty () )
69
+ if ( !mLayerChecks [layer].topologyChecks .empty () )
82
70
{
83
71
// TODO: Cancel topology checks
84
72
layer->setAllowCommit ( false );
@@ -88,7 +76,7 @@ void QgsGeometryValidationService::onFeatureAdded( QgsVectorLayer *layer, QgsFea
88
76
89
77
void QgsGeometryValidationService::onGeometryChanged ( QgsVectorLayer *layer, QgsFeatureId fid, const QgsGeometry &geometry )
90
78
{
91
- if ( !mLayerCheckStates [layer].topologyChecks .empty () )
79
+ if ( !mLayerChecks [layer].topologyChecks .empty () )
92
80
{
93
81
// TODO: Cancel topology checks
94
82
layer->setAllowCommit ( false );
@@ -101,7 +89,7 @@ void QgsGeometryValidationService::onGeometryChanged( QgsVectorLayer *layer, Qgs
101
89
102
90
void QgsGeometryValidationService::onFeatureDeleted ( QgsVectorLayer *layer, QgsFeatureId fid )
103
91
{
104
- if ( !mLayerCheckStates [layer].topologyChecks .empty () )
92
+ if ( !mLayerChecks [layer].topologyChecks .empty () )
105
93
{
106
94
// TODO: Cancel topology checks
107
95
layer->setAllowCommit ( false );
@@ -112,7 +100,7 @@ void QgsGeometryValidationService::onFeatureDeleted( QgsVectorLayer *layer, QgsF
112
100
113
101
void QgsGeometryValidationService::onBeforeCommitChanges ( QgsVectorLayer *layer )
114
102
{
115
- if ( !mLayerCheckStates [layer].topologyChecks .empty () ) // TODO && topologyChecks not fulfilled
103
+ if ( !mLayerChecks [layer].topologyChecks .empty () ) // TODO && topologyChecks not fulfilled
116
104
{
117
105
if ( !layer->allowCommit () )
118
106
{
@@ -124,12 +112,29 @@ void QgsGeometryValidationService::onBeforeCommitChanges( QgsVectorLayer *layer
124
112
125
113
void QgsGeometryValidationService::enableLayerChecks ( QgsVectorLayer *layer )
126
114
{
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 () );
130
137
131
- // TODO: ownership and lifetime of the context!!
132
- auto context = new QgsGeometryCheckContext ( log10 ( layer->geometryOptions ()->geometryPrecision () ) * -1 , mProject ->crs (), mProject ->transformContext () );
133
138
QList<QgsGeometryCheck *> layerChecks;
134
139
135
140
QgsGeometryCheckRegistry *checkRegistry = QgsAnalysis::instance ()->geometryCheckRegistry ();
@@ -144,7 +149,7 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
144
149
if ( activeChecks.contains ( checkId ) )
145
150
{
146
151
const QVariantMap checkConfiguration = layer->geometryOptions ()->checkConfiguration ( checkId );
147
- layerChecks.append ( factory->createGeometryCheck ( context, checkConfiguration ) );
152
+ layerChecks.append ( factory->createGeometryCheck ( checkInformation. context , checkConfiguration ) );
148
153
}
149
154
}
150
155
@@ -155,7 +160,7 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
155
160
singleGeometryChecks.append ( dynamic_cast <QgsSingleGeometryCheck *>( check ) );
156
161
}
157
162
158
- mLayerCheckStates [layer] .singleFeatureChecks = singleGeometryChecks;
163
+ checkInformation .singleFeatureChecks = singleGeometryChecks;
159
164
160
165
// Topology checks
161
166
QList<QgsGeometryCheck *> topologyChecks;
@@ -167,31 +172,56 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
167
172
if ( activeChecks.contains ( checkId ) )
168
173
{
169
174
const QVariantMap checkConfiguration = layer->geometryOptions ()->checkConfiguration ( checkId );
170
- topologyChecks.append ( factory->createGeometryCheck ( context, checkConfiguration ) );
175
+ topologyChecks.append ( factory->createGeometryCheck ( checkInformation. context , checkConfiguration ) );
171
176
}
172
177
}
173
178
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 );
175
205
}
176
206
177
207
void QgsGeometryValidationService::cancelTopologyCheck ( QgsVectorLayer *layer )
178
208
{
179
- QFutureWatcher<void > *futureWatcher = mLayerCheckStates [layer].topologyCheckFutureWatcher ;
209
+ QFutureWatcher<void > *futureWatcher = mLayerChecks [layer].topologyCheckFutureWatcher ;
180
210
if ( futureWatcher )
181
211
{
182
212
// Make sure no more checks are started first
183
213
futureWatcher->cancel ();
184
214
185
215
// Tell all checks to stop asap
186
- const auto feedbacks = mLayerCheckStates [layer].topologyCheckFeedbacks ;
216
+ const auto feedbacks = mLayerChecks [layer].topologyCheckFeedbacks ;
187
217
for ( QgsFeedback *feedback : feedbacks )
188
218
{
189
219
if ( feedback )
190
220
feedback->cancel ();
191
221
}
192
222
193
223
futureWatcher->waitForFinished ();
194
- mLayerCheckStates [layer].topologyCheckFutureWatcher = nullptr ;
224
+ mLayerChecks [layer].topologyCheckFutureWatcher = nullptr ;
195
225
}
196
226
}
197
227
@@ -206,7 +236,7 @@ void QgsGeometryValidationService::processFeature( QgsVectorLayer *layer, QgsFea
206
236
207
237
QgsFeature feature = layer->getFeature ( fid );
208
238
209
- const auto &checks = mLayerCheckStates [layer].singleFeatureChecks ;
239
+ const auto &checks = mLayerChecks [layer].singleFeatureChecks ;
210
240
211
241
// The errors are going to be sent out via a signal. We cannot keep ownership in here (or can we?)
212
242
// 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
232
262
233
263
// TODO: ownership of these objects...
234
264
QgsVectorLayerFeaturePool *featurePool = new QgsVectorLayerFeaturePool ( layer );
235
- QList<QgsGeometryCheckError *> &allErrors = mLayerCheckStates [layer].topologyCheckErrors ;
265
+ QList<QgsGeometryCheckError *> &allErrors = mLayerChecks [layer].topologyCheckErrors ;
236
266
QMap<QString, QgsFeatureIds> layerIds;
237
267
238
268
QgsFeatureRequest request = QgsFeatureRequest ( affectedFeatureIds ).setSubsetOfAttributes ( QgsAttributeList () );
@@ -255,13 +285,13 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
255
285
mFeaturePools .insert ( layer->id (), featurePool );
256
286
}
257
287
258
- const QList<QgsGeometryCheck *> checks = mLayerCheckStates [layer].topologyChecks ;
288
+ const QList<QgsGeometryCheck *> checks = mLayerChecks [layer].topologyChecks ;
259
289
260
290
QMap<const QgsGeometryCheck *, QgsFeedback *> feedbacks;
261
291
for ( QgsGeometryCheck *check : checks )
262
292
feedbacks.insert ( check, new QgsFeedback () );
263
293
264
- mLayerCheckStates [layer].topologyCheckFeedbacks = feedbacks.values ();
294
+ mLayerChecks [layer].topologyCheckFeedbacks = feedbacks.values ();
265
295
266
296
QFuture<void > future = QtConcurrent::map ( checks, [&allErrors, layerFeatureIds, layer, feedbacks, this ]( const QgsGeometryCheck * check )
267
297
{
@@ -296,9 +326,9 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
296
326
errorLocker.unlock ();
297
327
qDeleteAll ( feedbacks.values () );
298
328
futureWatcher->deleteLater ();
299
- if ( mLayerCheckStates [layer].topologyCheckFutureWatcher == futureWatcher )
300
- mLayerCheckStates [layer].topologyCheckFutureWatcher = nullptr ;
329
+ if ( mLayerChecks [layer].topologyCheckFutureWatcher == futureWatcher )
330
+ mLayerChecks [layer].topologyCheckFutureWatcher = nullptr ;
301
331
} );
302
332
303
- mLayerCheckStates [layer].topologyCheckFutureWatcher = futureWatcher;
333
+ mLayerChecks [layer].topologyCheckFutureWatcher = futureWatcher;
304
334
}
0 commit comments