Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsalgorithmdropfields.cpp 3 : : --------------------------------- 4 : : begin : November 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 : : 18 : : #include "qgsalgorithmdropfields.h" 19 : : 20 : : ///@cond PRIVATE 21 : : 22 : 0 : QgsProcessingAlgorithm::Flags QgsDropTableFieldsAlgorithm::flags() const 23 : : { 24 : 0 : return QgsProcessingFeatureBasedAlgorithm::flags() & ~QgsProcessingAlgorithm::FlagSupportsInPlaceEdits; 25 : : } 26 : : 27 : 0 : QString QgsDropTableFieldsAlgorithm::name() const 28 : : { 29 : 0 : return QStringLiteral( "deletecolumn" ); 30 : : } 31 : : 32 : 0 : QString QgsDropTableFieldsAlgorithm::displayName() const 33 : : { 34 : 0 : return QObject::tr( "Drop field(s)" ); 35 : : } 36 : : 37 : 0 : QString QgsDropTableFieldsAlgorithm::shortHelpString() const 38 : : { 39 : 0 : return QObject::tr( "This algorithm takes a vector layer and generates a new one that has the exact same content but without the selected columns." ); 40 : : } 41 : : 42 : 0 : QString QgsDropTableFieldsAlgorithm::shortDescription() const 43 : : { 44 : 0 : return QObject::tr( "Deletes fields from a vector layer." ); 45 : : } 46 : : 47 : 0 : QStringList QgsDropTableFieldsAlgorithm::tags() const 48 : : { 49 : 0 : return QObject::tr( "drop,delete,remove,fields,columns,attributes" ).split( ',' ); 50 : 0 : } 51 : : 52 : 0 : QString QgsDropTableFieldsAlgorithm::group() const 53 : : { 54 : 0 : return QObject::tr( "Vector table" ); 55 : : } 56 : : 57 : 0 : QString QgsDropTableFieldsAlgorithm::groupId() const 58 : : { 59 : 0 : return QStringLiteral( "vectortable" ); 60 : : } 61 : : 62 : 0 : QString QgsDropTableFieldsAlgorithm::outputName() const 63 : : { 64 : 0 : return QObject::tr( "Remaining fields" ); 65 : : } 66 : : 67 : 0 : QList<int> QgsDropTableFieldsAlgorithm::inputLayerTypes() const 68 : : { 69 : 0 : return QList<int>() << QgsProcessing::TypeVector; 70 : 0 : } 71 : : 72 : 0 : QgsProcessingFeatureSource::Flag QgsDropTableFieldsAlgorithm::sourceFlags() const 73 : : { 74 : 0 : return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks; 75 : : } 76 : : 77 : 0 : QgsDropTableFieldsAlgorithm *QgsDropTableFieldsAlgorithm::createInstance() const 78 : : { 79 : 0 : return new QgsDropTableFieldsAlgorithm(); 80 : : } 81 : : 82 : 0 : void QgsDropTableFieldsAlgorithm::initParameters( const QVariantMap & ) 83 : : { 84 : 0 : addParameter( new QgsProcessingParameterField( QStringLiteral( "COLUMN" ), QObject::tr( "Fields to drop" ), QVariant(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, true ) ); 85 : 0 : } 86 : : 87 : 0 : QgsFields QgsDropTableFieldsAlgorithm::outputFields( const QgsFields &inputFields ) const 88 : : { 89 : 0 : QgsFields outFields = inputFields; 90 : : // loop through twice - first we need to build up a list of original attribute indices 91 : 0 : for ( const QString &field : mFieldsToDelete ) 92 : : { 93 : 0 : const int index = inputFields.lookupField( field ); 94 : 0 : if ( index >= 0 ) 95 : 0 : mFieldIndices.append( index ); 96 : : } 97 : : 98 : : // important - make sure we remove from the end so we aren't changing used indices as we go 99 : 0 : std::sort( mFieldIndices.begin(), mFieldIndices.end(), std::greater< int >() ); 100 : : 101 : : // this second time we make a cleaned version of the fields 102 : 0 : for ( const int index : std::as_const( mFieldIndices ) ) 103 : : { 104 : 0 : outFields.remove( index ); 105 : : } 106 : 0 : return outFields; 107 : 0 : } 108 : : 109 : 0 : bool QgsDropTableFieldsAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) 110 : : { 111 : 0 : mFieldsToDelete = parameterAsFields( parameters, QStringLiteral( "COLUMN" ), context ); 112 : : 113 : 0 : if ( feedback ) 114 : : { 115 : 0 : std::unique_ptr< QgsProcessingFeatureSource> source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); 116 : 0 : if ( source ) 117 : : { 118 : 0 : for ( const QString &field : std::as_const( mFieldsToDelete ) ) 119 : : { 120 : 0 : const int index = source->fields().lookupField( field ); 121 : 0 : if ( index < 0 ) 122 : : { 123 : 0 : feedback->pushInfo( QObject::tr( "Field “%1” does not exist in input layer " ).arg( field ) ); 124 : 0 : } 125 : : } 126 : 0 : } 127 : 0 : } 128 : : 129 : 0 : return true; 130 : 0 : } 131 : : 132 : 0 : QgsFeatureList QgsDropTableFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * ) 133 : : { 134 : 0 : QgsFeature f = feature; 135 : 0 : QgsAttributes attributes = f.attributes(); 136 : 0 : for ( const int index : mFieldIndices ) 137 : : { 138 : 0 : attributes.remove( index ); 139 : : } 140 : 0 : f.setAttributes( attributes ); 141 : 0 : return QgsFeatureList() << f; 142 : 0 : } 143 : : 144 : 0 : bool QgsDropTableFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const 145 : : { 146 : : Q_UNUSED( layer ) 147 : 0 : return false; 148 : : } 149 : : 150 : : 151 : : 152 : : // 153 : : // QgsRetainTableFieldsAlgorithm 154 : : // 155 : : 156 : 0 : QgsProcessingAlgorithm::Flags QgsRetainTableFieldsAlgorithm::flags() const 157 : : { 158 : 0 : return QgsProcessingFeatureBasedAlgorithm::flags() & ~QgsProcessingAlgorithm::FlagSupportsInPlaceEdits; 159 : : } 160 : : 161 : 0 : QString QgsRetainTableFieldsAlgorithm::name() const 162 : : { 163 : 0 : return QStringLiteral( "retainfields" ); 164 : : } 165 : : 166 : 0 : QString QgsRetainTableFieldsAlgorithm::displayName() const 167 : : { 168 : 0 : return QObject::tr( "Retain fields" ); 169 : : } 170 : : 171 : 0 : QString QgsRetainTableFieldsAlgorithm::shortHelpString() const 172 : : { 173 : 0 : return QObject::tr( "This algorithm takes a vector layer and generates a new one that retains only the selected fields. All other fields will be dropped." ); 174 : : } 175 : : 176 : 0 : QString QgsRetainTableFieldsAlgorithm::shortDescription() const 177 : : { 178 : 0 : return QObject::tr( "Retains selected fields from a vector layer." ); 179 : : } 180 : : 181 : 0 : QStringList QgsRetainTableFieldsAlgorithm::tags() const 182 : : { 183 : 0 : return QObject::tr( "drop,delete,remove,retain,keep,other,fields,columns,attributes" ).split( ',' ); 184 : 0 : } 185 : : 186 : 0 : QString QgsRetainTableFieldsAlgorithm::group() const 187 : : { 188 : 0 : return QObject::tr( "Vector table" ); 189 : : } 190 : : 191 : 0 : QString QgsRetainTableFieldsAlgorithm::groupId() const 192 : : { 193 : 0 : return QStringLiteral( "vectortable" ); 194 : : } 195 : : 196 : 0 : QString QgsRetainTableFieldsAlgorithm::outputName() const 197 : : { 198 : 0 : return QObject::tr( "Retained fields" ); 199 : : } 200 : : 201 : 0 : QList<int> QgsRetainTableFieldsAlgorithm::inputLayerTypes() const 202 : : { 203 : 0 : return QList<int>() << QgsProcessing::TypeVector; 204 : 0 : } 205 : : 206 : 0 : QgsProcessingFeatureSource::Flag QgsRetainTableFieldsAlgorithm::sourceFlags() const 207 : : { 208 : 0 : return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks; 209 : : } 210 : : 211 : 0 : QgsRetainTableFieldsAlgorithm *QgsRetainTableFieldsAlgorithm::createInstance() const 212 : : { 213 : 0 : return new QgsRetainTableFieldsAlgorithm(); 214 : : } 215 : : 216 : 0 : void QgsRetainTableFieldsAlgorithm::initParameters( const QVariantMap & ) 217 : : { 218 : 0 : addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELDS" ), QObject::tr( "Fields to retain" ), QVariant(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, true ) ); 219 : 0 : } 220 : : 221 : 0 : QgsFields QgsRetainTableFieldsAlgorithm::outputFields( const QgsFields &inputFields ) const 222 : : { 223 : : // loop through twice - first we need to build up a list of original attribute indices 224 : 0 : for ( const QString &field : mFieldsToRetain ) 225 : : { 226 : 0 : const int index = inputFields.lookupField( field ); 227 : 0 : if ( index >= 0 ) 228 : 0 : mFieldIndices.append( index ); 229 : : } 230 : : 231 : 0 : std::sort( mFieldIndices.begin(), mFieldIndices.end() ); 232 : : 233 : : // this second time we make a cleaned version of the fields 234 : 0 : QgsFields outFields; 235 : 0 : for ( const int index : std::as_const( mFieldIndices ) ) 236 : : { 237 : 0 : outFields.append( inputFields.at( index ) ); 238 : : } 239 : 0 : return outFields; 240 : 0 : } 241 : : 242 : 0 : bool QgsRetainTableFieldsAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) 243 : : { 244 : 0 : mFieldsToRetain = parameterAsFields( parameters, QStringLiteral( "FIELDS" ), context ); 245 : : 246 : 0 : if ( feedback ) 247 : : { 248 : 0 : std::unique_ptr< QgsProcessingFeatureSource> source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); 249 : 0 : if ( source ) 250 : : { 251 : 0 : for ( const QString &field : std::as_const( mFieldsToRetain ) ) 252 : : { 253 : 0 : const int index = source->fields().lookupField( field ); 254 : 0 : if ( index < 0 ) 255 : : { 256 : 0 : feedback->pushInfo( QObject::tr( "Field “%1” does not exist in input layer " ).arg( field ) ); 257 : 0 : } 258 : : } 259 : 0 : } 260 : 0 : } 261 : : 262 : 0 : return true; 263 : 0 : } 264 : : 265 : 0 : QgsFeatureList QgsRetainTableFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * ) 266 : : { 267 : 0 : QgsFeature f = feature; 268 : 0 : const QgsAttributes inputAttributes = f.attributes(); 269 : 0 : QgsAttributes outputAttributes; 270 : 0 : outputAttributes.reserve( mFieldIndices.count() ); 271 : 0 : for ( const int index : mFieldIndices ) 272 : : { 273 : 0 : outputAttributes.append( inputAttributes.at( index ) ); 274 : : } 275 : 0 : f.setAttributes( outputAttributes ); 276 : 0 : return QgsFeatureList() << f; 277 : 0 : } 278 : : 279 : 0 : bool QgsRetainTableFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const 280 : : { 281 : : Q_UNUSED( layer ) 282 : 0 : return false; 283 : : } 284 : : 285 : : ///@endcond