17 #include <QtConcurrentMap> 18 #include <QFutureWatcher> 35 , mFeaturePools( featurePools )
37 for (
auto it = featurePools.constBegin(); it != mFeaturePools.constEnd(); ++it )
39 if ( it.value()->layer() )
41 it.value()->layer()->setReadOnly(
true );
43 it.value()->layer()->dataProvider()->enterUpdateMode();
50 qDeleteAll( mCheckErrors );
51 qDeleteAll( mChecks );
52 for (
auto it = mFeaturePools.constBegin(); it != mFeaturePools.constEnd(); ++it )
54 if ( it.value()->layer() )
56 it.value()->layer()->dataProvider()->leaveUpdateMode();
57 it.value()->layer()->setReadOnly(
false );
71 for (
auto it = mFeaturePools.constBegin(); it != mFeaturePools.constEnd(); ++it )
75 *totalSteps += check->isCompatible( it.value()->layer() ) ? it.value()->allFeatureIds().size() : 0;
85 QFuture<void> future = QtConcurrent::map( mChecks, RunCheckWrapper(
this ) );
87 QFutureWatcher<void> *watcher =
new QFutureWatcher<void>();
88 watcher->setFuture( future );
89 QTimer *timer =
new QTimer();
90 connect( timer, &QTimer::timeout,
this, &QgsGeometryChecker::emitProgressValue );
91 connect( watcher, &QFutureWatcherBase::finished, timer, &QObject::deleteLater );
92 connect( watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater );
98 void QgsGeometryChecker::emitProgressValue()
117 error->
check()->
fixError( mFeaturePools, error, method, mMergeAttributeIndices, changes );
120 static QVector<QString> strChangeWhat = {
"ChangeFeature",
"ChangePart",
"ChangeRing",
"ChangeNode" };
121 static QVector<QString> strChangeType = {
"ChangeAdded",
"ChangeRemoved",
"ChangeChanged" };
122 for (
const QString &layerId : changes.keys() )
124 for (
const QgsFeatureId &fid : changes[layerId].keys() )
128 QTextStream( stdout ) <<
" * Change: " << layerId <<
":" << fid <<
" :: " << strChangeWhat[change.what] <<
":" << strChangeType[change.type] <<
":(" << change.vidx.part <<
"," << change.vidx.ring <<
"," << change.vidx.vertex <<
")" << endl;
140 if ( changes.isEmpty() )
147 QMap<QString, QSet<QgsFeatureId>> recheckFeatures;
148 for (
auto it = changes.constBegin(); it != changes.constEnd(); ++it )
150 const QMap<QgsFeatureId, QList<QgsGeometryCheck::Change>> &layerChanges = it.value();
153 for (
auto layerChangeIt = layerChanges.constBegin(); layerChangeIt != layerChanges.constEnd(); ++layerChangeIt )
155 bool removed =
false;
167 if ( featurePool->
getFeature( layerChangeIt.key(), f ) )
169 recheckFeatures[it.key()].insert( layerChangeIt.key() );
180 if ( err->affectedAreaBBox().intersects( recheckArea ) )
187 QMap<QString, QgsFeatureIds> recheckAreaFeatures;
188 for (
const QString &layerId : mFeaturePools.keys() )
192 recheckAreaFeatures[layerId] = featurePool->
getIntersects( t.transform( recheckArea ) );
196 QList<QgsGeometryCheckError *> recheckErrors;
201 if ( !recheckAreaFeatures.isEmpty() )
203 check->collectErrors( mFeaturePools, recheckErrors, mMessages,
nullptr, recheckAreaFeatures );
208 if ( !recheckFeatures.isEmpty() )
210 check->collectErrors( mFeaturePools, recheckErrors, mMessages,
nullptr, recheckFeatures );
225 bool handled = err->handleChanges( changes );
232 if ( recheckErr->isEqual( err ) || recheckErr->closeMatch( err ) )
235 matchErr = recheckErr;
239 if ( nMatch == 1 && matchErr )
243 recheckErrors.removeAll( matchErr );
269 mCheckErrors.append( recheckErr );
272 if ( triggerRepaint )
274 for (
const QString &layerId : changes.keys() )
276 mFeaturePools[layerId]->layer()->triggerRepaint();
286 QList<QgsGeometryCheckError *> errors;
287 QStringList messages;
289 mErrorListMutex.lock();
290 mCheckErrors.append( errors );
291 mMessages.append( messages );
292 mErrorListMutex.unlock();
300 : mInstance( instance )
304 void QgsGeometryChecker::RunCheckWrapper::operator()(
const QgsGeometryCheck *check )
306 mInstance->runCheck( mInstance->mFeaturePools, check );
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
The error is obsolete because of other modifications.
A rectangle specified with double values.
QgsFeatureIds getIntersects(const QgsRectangle &rect) const
Gets all feature ids in the bounding box rect.
virtual void update(const QgsGeometryCheckError *other)
Update this error with the information from other.
double progress() const
Returns the current progress reported by the feedback object.
Status
The status of an error.
const QgsPointXY & location() const
The location of the error in map units.
Base configuration for geometry checks.
QgsGeometryChecker(const QList< QgsGeometryCheck *> &checks, QgsGeometryCheckContext *context, const QMap< QString, QgsFeaturePool *> &featurePools)
const QMap< QString, QgsFeaturePool * > featurePools() const
void setObsolete()
Set the error status to obsolete.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QgsVectorLayer * layer() const
Gets a pointer to the underlying layer.
Manages and runs a set of geometry checks.
The check controls geometries as a whole.
Something has been removed.
const QgsGeometryCheck * check() const
The geometry check that created this error.
void grow(double delta)
Grows the rectangle in place by the specified amount.
bool getFeature(QgsFeatureId id, QgsFeature &feature)
Retrieves the feature with the specified id into feature.
This class implements a geometry check.
QString resolutionMessage() const
A message with details, how the error has been resolved.
const QString & layerId() const
The id of the layer on which this error has been detected.
~QgsGeometryChecker() override
const QgsCoordinateReferenceSystem mapCrs
The coordinate system in which calculations should be done.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Status status() const
The status of the error.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
const double tolerance
The tolerance to allow for in geometry checks.
A feature pool is based on a vector layer and caches features.
QFuture< void > execute(int *totalSteps=nullptr)
virtual QgsRectangle affectedAreaBBox() const
The bounding box of the affected area of the error.
virtual void fixError(const QMap< QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap< QString, int > &mergeAttributeIndices, Changes &changes) const
Fixes the error error with the specified method.
Descripts a change to fix a geometry.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
bool fixError(QgsGeometryCheckError *error, int method, bool triggerRepaint=false)
virtual QString description() const
The error description.
QgsFeatureId featureId() const
The id of the feature on which this error has been detected.
This represents an error reported by a geometry check.
virtual void collectErrors(const QMap< QString, QgsFeaturePool *> &featurePools, QList< QgsGeometryCheckError *> &errors, QStringList &messages, QgsFeedback *feedback, const LayerFeatureIds &ids=QgsGeometryCheck::LayerFeatureIds()) const =0
The main worker method.
QVariant value() const
An additional value for the error.
void progressValue(int value)
const QgsVertexId & vidx() const
The id of the affected vertex.
void errorUpdated(QgsGeometryCheckError *error, bool statusChanged)
This change happens on feature level.
QgsCoordinateReferenceSystem crs
The check controls a whole layer (topology checks)
void errorAdded(QgsGeometryCheckError *error)