1 /*************************************************************************** 2 qgsgeometryvalidationservice.h 3 -------------------------------------- 4 Date : 7.9.2018 5 Copyright : (C) 2018 by Matthias Kuhn 6 email : matthias@opengis.ch 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 16 #ifndef QGSGEOMETRYVALIDATIONSERVICE_H 17 #define QGSGEOMETRYVALIDATIONSERVICE_H 18 19 #include <QObject> 20 #include <QMap> 21 #include <QFuture> 22 #include <QReadWriteLock> 23 24 #include "qgsfeature.h" 25 #include "qgsgeometrycheckcontext.h" 26 27 class QgsProject; 28 class QgsMapLayer; 29 class QgsVectorLayer; 30 class QgsGeometryCheck; 31 class QgsSingleGeometryCheck; 32 class QgsSingleGeometryCheckError; 33 class QgsGeometryCheckError; 34 class QgsFeedback; 35 class QgsFeaturePool; 36 class QgsMessageBar; 37 class QgsMessageBarItem; 38 39 /** 40 * This service connects to all layers in a project and triggers validation 41 * of features whenever they are edited. 42 * It is responsible for executing validation checks and sending out signals 43 * upon failure and success. 44 * It will also make sure, that a layer can only be saved, if all errors have 45 * been resolved. 46 */ 47 class QgsGeometryValidationService : public QObject 48 { 49 Q_OBJECT 50 51 public: 52 struct FeatureError 53 { 54 FeatureError() = default; FeatureErrorFeatureError55 FeatureError( QgsFeatureId fid, QgsGeometry::Error error ) 56 : featureId( fid ) 57 , error( error ) 58 {} 59 QgsFeatureId featureId = std::numeric_limits<QgsFeatureId>::min(); 60 QgsGeometry::Error error; 61 }; 62 63 typedef QList<FeatureError> FeatureErrors; 64 65 QgsGeometryValidationService( QgsProject *project ); 66 67 void fixError( QgsGeometryCheckError *error, int method ); 68 69 void triggerTopologyChecks( QgsVectorLayer *layer, bool stopEditing ); 70 71 void setMessageBar( QgsMessageBar *messageBar ); 72 73 signals: 74 75 /** 76 * Emitted when geometry checks for this layer have been disabled and 77 * any existing cached result should be cleared. 78 */ 79 void singleGeometryCheckCleared( QgsVectorLayer *layer ); 80 81 void geometryCheckStarted( QgsVectorLayer *layer, QgsFeatureId fid ); 82 void geometryCheckCompleted( QgsVectorLayer *layer, QgsFeatureId fid, const QList<std::shared_ptr<QgsSingleGeometryCheckError>> &errors ); 83 void topologyChecksUpdated( QgsVectorLayer *layer, const QList<std::shared_ptr<QgsGeometryCheckError> > &errors ); 84 void topologyChecksCleared( QgsVectorLayer *layer ); 85 void topologyErrorUpdated( QgsVectorLayer *layer, QgsGeometryCheckError *error ); 86 87 void warning( const QString &message ); 88 void clearWarning(); 89 90 private slots: 91 void onLayersAdded( const QList<QgsMapLayer *> &layers ); 92 void onFeatureAdded( QgsVectorLayer *layer, QgsFeatureId fid ); 93 void onGeometryChanged( QgsVectorLayer *layer, QgsFeatureId fid, const QgsGeometry &geometry ); 94 void onFeatureDeleted( QgsVectorLayer *layer, QgsFeatureId fid ); 95 void onBeforeCommitChanges( QgsVectorLayer *layer, bool stopEditing ); 96 void onEditingStopped( QgsVectorLayer *layer ); 97 98 private: 99 void showMessage( const QString &message ); 100 void cleanupLayerChecks( QgsVectorLayer *layer ); 101 void enableLayerChecks( QgsVectorLayer *layer ); 102 103 void cancelTopologyCheck( QgsVectorLayer *layer ); 104 105 void clearTopologyChecks( QgsVectorLayer *layer ); 106 107 void invalidateTopologyChecks( QgsVectorLayer *layer ); 108 109 void processFeature( QgsVectorLayer *layer, QgsFeatureId fid ); 110 111 QgsProject *mProject = nullptr; 112 113 struct VectorLayerCheckInformation 114 { 115 QList< QgsSingleGeometryCheck * > singleFeatureChecks; 116 QMap<QgsFeatureId, QList< std::shared_ptr<QgsSingleGeometryCheckError > > > singleFeatureCheckErrors; 117 QList< QgsGeometryCheck *> topologyChecks; 118 QFutureWatcher<void> *topologyCheckFutureWatcher = nullptr; 119 QList<QgsFeedback *> topologyCheckFeedbacks; // will be deleted when topologyCheckFutureWatcher is delteed 120 QList<std::shared_ptr<QgsGeometryCheckError>> topologyCheckErrors; 121 QList<QMetaObject::Connection> connections; 122 std::shared_ptr<QgsGeometryCheckContext> context; 123 bool commitPending = false; 124 }; 125 126 QReadWriteLock mTopologyCheckLock; 127 QHash<QgsVectorLayer *, VectorLayerCheckInformation> mLayerChecks; 128 QMap<QString, QgsFeaturePool *> mFeaturePools; 129 QgsMessageBar *mMessageBar = nullptr; 130 QgsMessageBarItem *mMessageBarItem = nullptr; 131 132 // when checks do complete successfully and changes need to be saved 133 // this variable is used to indicate that it's safe to bypass the checks 134 bool mBypassChecks = false; 135 136 }; 137 138 #endif // QGSGEOMETRYVALIDATIONSERVICE_H 139