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.
bool getFeature(QgsFeatureId id, QgsFeature &feature, QgsFeedback *feedback=nullptr)
Retrieves the feature with the specified id into feature.
double progress() const
Returns the current progress reported by the feedback object.
const QgsCoordinateReferenceSystem mapCrs
The coordinate system in which calculations should be done.
Status
The status of an error.
const QgsPointXY & location() const
The location of the error in map units.
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...
Base configuration for geometry checks.
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.
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 double tolerance
The tolerance to allow for in geometry checks.
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.
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
Fix 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)