QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsalgorithmflattenrelationships.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmflattenrelationships.h
3 ---------------------
4 begin : August 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include "qgsrelationmanager.h"
21#include "qgsvectorlayer.h"
23
24#include <QString>
25
26using namespace Qt::StringLiterals;
27
29
30QString QgsFlattenRelationshipsAlgorithm::name() const
31{
32 return u"flattenrelationships"_s;
33}
34
35QString QgsFlattenRelationshipsAlgorithm::displayName() const
36{
37 return QObject::tr( "Flatten relationship" );
38}
39
40QStringList QgsFlattenRelationshipsAlgorithm::tags() const
41{
42 return QObject::tr( "join,export,single,table" ).split( ',' );
43}
44
45QString QgsFlattenRelationshipsAlgorithm::group() const
46{
47 return QObject::tr( "Vector general" );
48}
49
50QString QgsFlattenRelationshipsAlgorithm::groupId() const
51{
52 return u"vectorgeneral"_s;
53}
54
55QString QgsFlattenRelationshipsAlgorithm::shortDescription() const
56{
57 return QObject::tr( "Flattens a relationship for a vector layer." );
58}
59
60QString QgsFlattenRelationshipsAlgorithm::shortHelpString() const
61{
62 return QObject::tr( "This algorithm flattens a relationship for a vector layer, exporting a single layer "
63 "containing one master feature per related feature. This master feature contains all "
64 "the attributes for the related features." );
65}
66
67Qgis::ProcessingAlgorithmDocumentationFlags QgsFlattenRelationshipsAlgorithm::documentationFlags() const
68{
70}
71
72Qgis::ProcessingAlgorithmFlags QgsFlattenRelationshipsAlgorithm::flags() const
73{
75}
76
77void QgsFlattenRelationshipsAlgorithm::initAlgorithm( const QVariantMap & )
78{
79 addParameter( new QgsProcessingParameterVectorLayer( u"INPUT"_s, QObject::tr( "Input layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector ) ) );
80
81 addParameter( new QgsProcessingParameterFeatureSink( u"OUTPUT"_s, QObject::tr( "Flattened layer" ), Qgis::ProcessingSourceType::VectorAnyGeometry ) );
82}
83
84QgsFlattenRelationshipsAlgorithm *QgsFlattenRelationshipsAlgorithm::createInstance() const
85{
86 return new QgsFlattenRelationshipsAlgorithm();
87}
88
89bool QgsFlattenRelationshipsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
90{
91 QgsProject *project = context.project();
92 if ( !project )
93 throw QgsProcessingException( QObject::tr( "No project available for relationships" ) );
94
95 QgsVectorLayer *layer = parameterAsVectorLayer( parameters, u"INPUT"_s, context );
96 if ( !layer )
97 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
98
99 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
100 if ( relations.size() > 1 )
101 throw QgsProcessingException( QObject::tr( "Found %n relation(s). This algorithm currently supports only a single relation.", nullptr, relations.size() ) );
102 else if ( relations.empty() )
103 throw QgsProcessingException( QObject::tr( "No relations found." ) );
104
105 mRelation = relations.at( 0 );
106
107 QgsVectorLayer *referencingLayer = mRelation.referencingLayer();
108 if ( !referencingLayer )
109 throw QgsProcessingException( QObject::tr( "Could not resolved referenced layer." ) );
110
111 mReferencingSource = std::make_unique<QgsVectorLayerFeatureSource>( referencingLayer );
112 mReferencingFields = referencingLayer->fields();
113
114 return true;
115}
116
117QVariantMap QgsFlattenRelationshipsAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
118{
119 std::unique_ptr<QgsProcessingFeatureSource> input( parameterAsSource( parameters, u"INPUT"_s, context ) );
120 if ( !input )
121 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
122
123 const QgsFields outFields = QgsProcessingUtils::combineFields( input->fields(), mReferencingFields );
124
125 QString dest;
126 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u"OUTPUT"_s, context, dest, outFields, input->wkbType(), input->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) );
127 if ( parameters.value( u"OUTPUT"_s ).isValid() && !sink )
128 throw QgsProcessingException( invalidSinkError( parameters, u"OUTPUT"_s ) );
129
130 // Create output vector layer with additional attributes
131 const double step = input->featureCount() > 0 ? 100.0 / input->featureCount() : 1;
133 long long i = 0;
134 QgsFeature feat;
135 while ( features.nextFeature( feat ) )
136 {
137 i++;
138 if ( feedback->isCanceled() )
139 {
140 break;
141 }
142
143 feedback->setProgress( i * step );
144
145 QgsFeatureRequest referencingRequest = mRelation.getRelatedFeaturesRequest( feat );
146 referencingRequest.setFlags( referencingRequest.flags() | Qgis::FeatureRequestFlag::NoGeometry );
147 QgsFeatureIterator childIt = mReferencingSource->getFeatures( referencingRequest );
148 QgsFeature relatedFeature;
149 while ( childIt.nextFeature( relatedFeature ) )
150 {
151 QgsAttributes attrs = feat.attributes();
152 attrs.append( relatedFeature.attributes() );
153 QgsFeature outFeat = feat;
154 outFeat.setAttributes( attrs );
155 if ( !sink->addFeature( outFeat, QgsFeatureSink::FastInsert ) )
156 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, u"OUTPUT"_s ) );
157 }
158 }
159
160 QVariantMap outputs;
161 if ( sink )
162 {
163 sink->finalize();
164 outputs.insert( u"OUTPUT"_s, dest );
165 }
166 return outputs;
167}
168
169
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3610
@ VectorAnyGeometry
Any vector layer with geometry.
Definition qgis.h:3604
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2254
@ RegeneratesPrimaryKey
Algorithm always drops any existing primary keys or FID values and regenerates them in outputs.
Definition qgis.h:3690
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
Definition qgis.h:3680
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3701
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition qgis.h:3782
@ RequiresProject
The algorithm requires that a valid QgsProject is available from the processing context in order to e...
Definition qgis.h:3667
A vector of attributes.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
Qgis::FeatureRequestFlags flags() const
Returns the flags which affect how features are fetched.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsAttributes attributes
Definition qgsfeature.h:69
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:55
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:63
Container of fields for a vector layer.
Definition qgsfields.h:46
virtual Qgis::ProcessingAlgorithmFlags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Contains information about the context in which a processing algorithm is executed.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A feature sink output for processing algorithms.
A vector layer (with or without geometry) parameter for processing algorithms.
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:113
QgsRelationManager * relationManager
Definition qgsproject.h:124
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
Represents a vector layer which manages a vector based dataset.