41 return QList<QgsRasterLayer *>();
43 QList<QgsRasterLayer *> layers;
48 if ( canUseLayer( l ) )
56 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
65 return QList<QgsVectorLayer *>();
67 QList<QgsVectorLayer *> layers;
71 if ( canUseLayer( l, geometryTypes ) )
79 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
88 return QList<QgsMeshLayer *>();
90 QList<QgsMeshLayer *> layers;
94 if ( canUseLayer( l ) )
102 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
111 return QList<QgsMapLayer *>();
113 QList<QgsMapLayer *> layers;
131 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
139 return QStringLiteral(
"%1://%2" ).arg( providerKey, uri );
144 QRegularExpression re( QStringLiteral(
"^(\\w+?):\\/\\/(.+)$" ) );
145 const QRegularExpressionMatch match = re.match(
string );
146 if ( !match.hasMatch() )
149 providerKey = match.captured( 1 );
150 uri = match.captured( 2 );
158 if ( !store ||
string.isEmpty() )
161 QList< QgsMapLayer * > layers = store->
mapLayers().values();
163 layers.erase( std::remove_if( layers.begin(), layers.end(), [](
QgsMapLayer * layer )
165 switch ( layer->type() )
167 case QgsMapLayerType::VectorLayer:
168 return !canUseLayer( qobject_cast< QgsVectorLayer * >( layer ) );
169 case QgsMapLayerType::RasterLayer:
170 return !canUseLayer( qobject_cast< QgsRasterLayer * >( layer ) );
171 case QgsMapLayerType::PluginLayer:
173 case QgsMapLayerType::MeshLayer:
174 return !canUseLayer( qobject_cast< QgsMeshLayer * >( layer ) );
175 case QgsMapLayerType::VectorTileLayer:
176 return !canUseLayer( qobject_cast< QgsVectorTileLayer * >( layer ) );
181 auto isCompatibleType = [typeHint](
QgsMapLayer * l ) ->
bool
185 case LayerHint::UnknownType:
188 case LayerHint::Vector:
191 case LayerHint::Raster:
194 case LayerHint::Mesh:
202 if ( isCompatibleType( l ) && l->id() == string )
207 if ( isCompatibleType( l ) && l->name() == string )
212 if ( isCompatibleType( l ) && normalizeLayerSource( l->source() ) == normalizeLayerSource(
string ) )
228 if ( !useProvider || ( provider == QLatin1String(
"ogr" ) || provider == QLatin1String(
"gdal" ) || provider == QLatin1String(
"mdal" ) ) )
230 QStringList components = uri.split(
'|' );
231 if ( components.isEmpty() )
235 if ( QFileInfo::exists( uri ) )
236 fi = QFileInfo( uri );
237 else if ( QFileInfo::exists( components.at( 0 ) ) )
238 fi = QFileInfo( components.at( 0 ) );
241 name = fi.baseName();
252 options.loadDefaultStyle =
false;
253 options.skipCrsValidation =
true;
255 std::unique_ptr< QgsVectorLayer > layer;
258 layer = qgis::make_unique<QgsVectorLayer>( uri, name, provider, options );
263 layer = qgis::make_unique<QgsVectorLayer>( uri, name, QStringLiteral(
"ogr" ), options );
265 if ( layer->isValid() )
267 return layer.release();
276 std::unique_ptr< QgsRasterLayer > rasterLayer;
279 rasterLayer = qgis::make_unique< QgsRasterLayer >( uri, name, provider, rasterOptions );
284 rasterLayer = qgis::make_unique< QgsRasterLayer >( uri, name, QStringLiteral(
"gdal" ), rasterOptions );
287 if ( rasterLayer->isValid() )
289 return rasterLayer.release();
297 std::unique_ptr< QgsMeshLayer > meshLayer;
300 meshLayer = qgis::make_unique< QgsMeshLayer >( uri, name, provider, meshOptions );
304 meshLayer = qgis::make_unique< QgsMeshLayer >( uri, name, QStringLiteral(
"mdal" ), meshOptions );
306 if ( meshLayer->isValid() )
308 return meshLayer.release();
316 if (
string.isEmpty() )
332 if ( !allowLoadingNewLayers )
335 layer = loadMapLayerFromString(
string, context.
transformContext(), typeHint );
349 QVariant val = value;
350 bool selectedFeaturesOnly =
false;
351 long long featureLimit = -1;
352 bool overrideGeometryCheck =
false;
361 overrideGeometryCheck = fromVar.
flags & QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck;
371 if (
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( val ) ) )
373 std::unique_ptr< QgsProcessingFeatureSource> source = qgis::make_unique< QgsProcessingFeatureSource >( layer, context,
false, featureLimit );
374 if ( overrideGeometryCheck )
375 source->setInvalidGeometryCheck( geometryCheck );
376 return source.release();
384 else if ( !val.isValid() || val.toString().isEmpty() )
387 if (
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( fallbackValue ) ) )
389 std::unique_ptr< QgsProcessingFeatureSource> source = qgis::make_unique< QgsProcessingFeatureSource >( layer, context,
false, featureLimit );
390 if ( overrideGeometryCheck )
391 source->setInvalidGeometryCheck( geometryCheck );
392 return source.release();
395 layerRef = fallbackValue.toString();
399 layerRef = val.toString();
402 if ( layerRef.isEmpty() )
409 std::unique_ptr< QgsProcessingFeatureSource> source;
410 if ( selectedFeaturesOnly )
416 source = qgis::make_unique< QgsProcessingFeatureSource >( vl, context,
false, featureLimit );
419 if ( overrideGeometryCheck )
420 source->setInvalidGeometryCheck( geometryCheck );
421 return source.release();
426 QVariant val = value;
452 if (
QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) ) )
458 if ( !val.isValid() )
464 QString crsText = val.toString();
465 if ( crsText.isEmpty() )
466 crsText = fallbackValue.toString();
468 if ( crsText.isEmpty() )
472 if ( context.
project() && crsText.compare( QLatin1String(
"ProjectCrs" ), Qt::CaseInsensitive ) == 0 )
485 bool QgsProcessingUtils::canUseLayer(
const QgsMeshLayer *layer )
492 return layer && layer->
isValid();
495 bool QgsProcessingUtils::canUseLayer(
const QgsRasterLayer *layer )
497 return layer && layer->
isValid();
500 bool QgsProcessingUtils::canUseLayer(
const QgsVectorLayer *layer,
const QList<int> &sourceTypes )
502 return layer && layer->
isValid() &&
503 ( sourceTypes.isEmpty()
514 QString normalized = source;
515 normalized.replace(
'\\',
'/' );
516 return normalized.trimmed();
521 if ( !value.isValid() )
522 return QStringLiteral(
"None" );
525 return QStringLiteral(
"QgsProperty.fromExpression('%1')" ).arg( value.value<
QgsProperty >().
asExpression() );
529 return QStringLiteral(
"QgsCoordinateReferenceSystem()" );
563 switch ( value.type() )
566 return value.toBool() ? QStringLiteral(
"True" ) : QStringLiteral(
"False" );
568 case QVariant::Double:
569 return QString::number( value.toDouble() );
573 return QString::number( value.toInt() );
575 case QVariant::LongLong:
576 case QVariant::ULongLong:
577 return QString::number( value.toLongLong() );
582 const QVariantList vl = value.toList();
583 for (
const QVariant &v : vl )
587 return parts.join(
',' ).prepend(
'[' ).append(
']' );
592 const QVariantMap map = value.toMap();
594 parts.reserve( map.size() );
595 for (
auto it = map.constBegin(); it != map.constEnd(); ++it )
599 return parts.join(
',' ).prepend(
'{' ).append(
'}' );
612 s.replace(
'\\', QStringLiteral(
"\\\\" ) );
613 s.replace(
'\n', QStringLiteral(
"\\n" ) );
614 s.replace(
'\r', QStringLiteral(
"\\r" ) );
615 s.replace(
'\t', QStringLiteral(
"\\t" ) );
616 s.replace(
'"', QStringLiteral(
"\\\"" ) );
617 s.replace(
'\'', QStringLiteral(
"\\\'" ) );
618 s = s.prepend(
'\'' ).append(
'\'' );
622 void QgsProcessingUtils::parseDestinationString( QString &destination, QString &providerKey, QString &uri, QString &layerName, QString &format, QMap<QString, QVariant> &options,
bool &useWriter, QString &extension )
629 QRegularExpression splitRx( QStringLiteral(
"^(.{3,}?):(.*)$" ) );
630 QRegularExpressionMatch match = splitRx.match( destination );
631 if ( match.hasMatch() )
633 providerKey = match.captured( 1 );
634 uri = match.captured( 2 );
641 if ( providerKey == QStringLiteral(
"postgis" ) )
643 providerKey = QStringLiteral(
"postgres" );
645 if ( providerKey == QLatin1String(
"ogr" ) )
648 if ( !dsUri.database().isEmpty() )
650 if ( !dsUri.table().isEmpty() )
652 layerName = dsUri.table();
653 options.insert( QStringLiteral(
"layerName" ), layerName );
655 uri = dsUri.database();
656 extension = QFileInfo( uri ).completeSuffix();
661 extension = QFileInfo( uri ).completeSuffix();
663 options.insert( QStringLiteral(
"update" ),
true );
670 providerKey = QStringLiteral(
"ogr" );
671 QRegularExpression splitRx( QStringLiteral(
"^(.*)\\.(.*?)$" ) );
672 QRegularExpressionMatch match = splitRx.match( destination );
673 if ( match.hasMatch() )
675 extension = match.captured( 2 );
679 if ( format.isEmpty() )
681 format = QStringLiteral(
"GPKG" );
682 destination = destination + QStringLiteral(
".gpkg" );
685 options.insert( QStringLiteral(
"driverName" ), format );
692 QVariantMap options = createOptions;
693 if ( !options.contains( QStringLiteral(
"fileEncoding" ) ) )
699 if ( destination.isEmpty() || destination.startsWith( QLatin1String(
"memory:" ) ) )
702 if ( destination.startsWith( QLatin1String(
"memory:" ) ) )
703 destination = destination.mid( 7 );
705 if ( destination.isEmpty() )
706 destination = QStringLiteral(
"output" );
710 if ( !layer || !layer->isValid() )
716 destination = layer->id();
719 std::unique_ptr< QgsProcessingFeatureSink > sink(
new QgsProcessingFeatureSink( layer->dataProvider(), destination, context ) );
722 return sink.release();
731 bool useWriter =
false;
732 parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter, extension );
735 if ( useWriter && providerKey == QLatin1String(
"ogr" ) )
739 QString finalFileName;
741 saveOptions.
fileEncoding = options.value( QStringLiteral(
"fileEncoding" ) ).toString();
746 if ( remappingDefinition )
750 std::unique_ptr< QgsVectorLayer > vl = qgis::make_unique< QgsVectorLayer >( destination );
755 newFields = vl->fields();
765 if ( writer->hasError() )
767 throw QgsProcessingException( QObject::tr(
"Could not create layer %1: %2" ).arg( destination, writer->errorMessage() ) );
769 destination = finalFileName;
770 if ( remappingDefinition )
772 std::unique_ptr< QgsRemappingProxyFeatureSink > remapSink = qgis::make_unique< QgsRemappingProxyFeatureSink >( *remappingDefinition, writer.release(),
true );
783 if ( remappingDefinition )
788 if ( !layerName.isEmpty() )
789 uri += QStringLiteral(
"|layername=%1" ).arg( layerName );
791 std::unique_ptr< QgsVectorLayer > layer = qgis::make_unique<QgsVectorLayer>( uri, destination, providerKey, layerOptions );
793 destination = layer->id();
794 if ( layer->isValid() )
801 std::unique_ptr< QgsRemappingProxyFeatureSink > remapSink = qgis::make_unique< QgsRemappingProxyFeatureSink >( *remappingDefinition, layer->dataProvider(),
false );
811 std::unique_ptr< QgsVectorLayerExporter > exporter = qgis::make_unique<QgsVectorLayerExporter>( uri, providerKey, newFields, geometryType,
crs,
true, options, sinkFlags );
812 if ( exporter->errorCode() )
814 throw QgsProcessingException( QObject::tr(
"Could not create layer %1: %2" ).arg( destination, exporter->errorMessage() ) );
818 if ( !layerName.isEmpty() )
819 uri += QStringLiteral(
"|layername=%1" ).arg( layerName );
820 std::unique_ptr< QgsVectorLayer > layer = qgis::make_unique<QgsVectorLayer>( uri, destination, providerKey, layerOptions );
822 destination = layer->id();
878 if ( !input.isValid() )
879 return QStringLiteral(
"memory:%1" ).arg(
id.toString() );
895 QString res = input.toString();
901 else if ( res.startsWith( QLatin1String(
"memory:" ) ) )
903 return res +
'_' +
id.toString();
909 int lastIndex = res.lastIndexOf(
'.' );
910 return res.left( lastIndex ) +
'_' +
id.toString() + res.mid( lastIndex );
921 static std::vector< std::unique_ptr< QTemporaryDir > > sTempFolders;
922 static QString sFolder;
923 static QMutex sMutex;
924 QMutexLocker locker( &sMutex );
925 const QString basePath =
QgsSettings().
value( QStringLiteral(
"Processing/Configuration/TEMP_PATH2" ) ).toString();
926 if ( basePath.isEmpty() )
929 if ( sTempFolders.empty() )
931 const QString templatePath = QStringLiteral(
"%1/processing_XXXXXX" ).arg( QDir::tempPath() );
932 std::unique_ptr< QTemporaryDir >
tempFolder = qgis::make_unique< QTemporaryDir >( templatePath );
934 sTempFolders.emplace_back( std::move(
tempFolder ) );
937 else if ( sFolder.isEmpty() || !sFolder.startsWith( basePath ) || sTempFolders.empty() )
939 if ( !QDir().exists( basePath ) )
940 QDir().mkpath( basePath );
942 const QString templatePath = QStringLiteral(
"%1/processing_XXXXXX" ).arg( basePath );
943 std::unique_ptr< QTemporaryDir >
tempFolder = qgis::make_unique< QTemporaryDir >( templatePath );
945 sTempFolders.emplace_back( std::move(
tempFolder ) );
952 QString subPath = QUuid::createUuid().toString().remove(
'-' ).remove(
'{' ).remove(
'}' );
954 if ( !QDir( path ).exists() )
957 tmpDir.mkdir( path );
964 auto getText = [map](
const QString & key )->QString
966 if ( map.contains( key ) )
967 return map.value( key ).toString();
971 QString s = QObject::tr(
"<html><body><h2>Algorithm description</h2>\n" );
972 s += QStringLiteral(
"<p>" ) + getText( QStringLiteral(
"ALG_DESC" ) ) + QStringLiteral(
"</p>\n" );
979 inputs += QStringLiteral(
"<h3>" ) + def->description() + QStringLiteral(
"</h3>\n" );
980 inputs += QStringLiteral(
"<p>" ) + getText( def->name() ) + QStringLiteral(
"</p>\n" );
982 if ( !inputs.isEmpty() )
983 s += QObject::tr(
"<h2>Input parameters</h2>\n" ) + inputs;
989 outputs += QStringLiteral(
"<h3>" ) + def->description() + QStringLiteral(
"</h3>\n" );
990 outputs += QStringLiteral(
"<p>" ) + getText( def->name() ) + QStringLiteral(
"</p>\n" );
992 if ( !outputs.isEmpty() )
993 s += QObject::tr(
"<h2>Outputs</h2>\n" ) + outputs;
995 s += QLatin1String(
"<br>" );
996 if ( !map.value( QStringLiteral(
"ALG_CREATOR" ) ).toString().isEmpty() )
997 s += QObject::tr(
"<p align=\"right\">Algorithm author: %1</p>" ).arg( getText( QStringLiteral(
"ALG_CREATOR" ) ) );
998 if ( !map.value( QStringLiteral(
"ALG_HELP_CREATOR" ) ).toString().isEmpty() )
999 s += QObject::tr(
"<p align=\"right\">Help author: %1</p>" ).arg( getText( QStringLiteral(
"ALG_HELP_CREATOR" ) ) );
1000 if ( !map.value( QStringLiteral(
"ALG_VERSION" ) ).toString().isEmpty() )
1001 s += QObject::tr(
"<p align=\"right\">Algorithm version: %1</p>" ).arg( getText( QStringLiteral(
"ALG_VERSION" ) ) );
1003 s += QStringLiteral(
"</body></html>" );
1008 long long featureLimit )
1010 bool requiresTranslation =
false;
1014 requiresTranslation = requiresTranslation || selectedFeaturesOnly;
1017 requiresTranslation = requiresTranslation || featureLimit != -1;
1022 requiresTranslation = requiresTranslation || vl->
providerType() != QLatin1String(
"ogr" );
1026 requiresTranslation = requiresTranslation || !vl->
subsetString().isEmpty();
1030 requiresTranslation = requiresTranslation || vl->
source().startsWith( QLatin1String(
"/vsi" ) );
1034 if ( !requiresTranslation )
1037 if ( parts.contains( QStringLiteral(
"path" ) ) )
1039 diskPath = parts.value( QStringLiteral(
"path" ) ).toString();
1040 QFileInfo fi( diskPath );
1041 requiresTranslation = !compatibleFormats.contains( fi.suffix(), Qt::CaseInsensitive );
1045 const QString srcLayerName = parts.value( QStringLiteral(
"layerName" ) ).toString();
1049 *layerName = srcLayerName;
1054 requiresTranslation = requiresTranslation || ( !srcLayerName.isEmpty() && srcLayerName != fi.baseName() );
1059 requiresTranslation =
true;
1063 if ( requiresTranslation )
1073 if ( featureLimit != -1 )
1075 if ( selectedFeaturesOnly )
1082 if ( selectedFeaturesOnly )
1110 return convertToCompatibleFormatInternal( layer, selectedFeaturesOnly, baseName, compatibleFormats, preferredFormat, context, feedback, &layerName, featureLimit );
1116 QSet< QString > usedNames;
1117 for (
const QgsField &f : fieldsA )
1119 usedNames.insert( f.name().toLower() );
1122 for (
const QgsField &f : fieldsB )
1125 newField.
setName( fieldsBPrefix + f.name() );
1126 if ( usedNames.contains( newField.
name().toLower() ) )
1129 QString newName = newField.
name() +
'_' + QString::number( idx );
1130 while ( usedNames.contains( newName.toLower() ) )
1133 newName = newField.
name() +
'_' + QString::number( idx );
1136 outFields.
append( newField );
1140 outFields.
append( newField );
1142 usedNames.insert( newField.
name() );
1152 if ( !fieldNames.isEmpty() )
1154 indices.reserve( fieldNames.count() );
1155 for (
const QString &f : fieldNames )
1159 indices.append( idx );
1164 indices.reserve( fields.
count() );
1165 for (
int i = 0; i < fields.
count(); ++i )
1166 indices.append( i );
1175 for (
int i : indices )
1176 fieldsSubset.
append( fields.
at( i ) );
1177 return fieldsSubset;
1183 const int setting = settings.
value( QStringLiteral(
"Processing/Configuration/DefaultOutputVectorLayerExt" ), -1 ).toInt();
1184 if ( setting == -1 )
1185 return QStringLiteral(
"gpkg" );
1192 const int setting = settings.
value( QStringLiteral(
"Processing/Configuration/DefaultOutputRasterLayerExt" ), -1 ).toInt();
1193 if ( setting == -1 )
1194 return QStringLiteral(
"tif" );
1203 : mSource( originalSource )
1204 , mOwnsSource( ownsOriginalSource )
1207 : context.invalidGeometryCheck() )
1208 , mInvalidGeometryCallback( context.invalidGeometryCallback() )
1209 , mTransformErrorCallback( context.transformErrorCallback() )
1210 , mInvalidGeometryCallbackSkip( context.defaultInvalidGeometryCallbackForCheck(
QgsFeatureRequest::GeometrySkipInvalid ) )
1211 , mInvalidGeometryCallbackAbort( context.defaultInvalidGeometryCallbackForCheck(
QgsFeatureRequest::GeometryAbortOnInvalid ) )
1212 , mFeatureLimit( featureLimit )
1234 if ( mFeatureLimit != -1 && req.
limit() != -1 )
1235 req.
setLimit( std::min(
static_cast< long long >( req.
limit() ), mFeatureLimit ) );
1236 else if ( mFeatureLimit != -1 )
1248 return sourceAvailability;
1261 if ( mFeatureLimit != -1 && req.
limit() != -1 )
1262 req.
setLimit( std::min(
static_cast< long long >( req.
limit() ), mFeatureLimit ) );
1263 else if ( mFeatureLimit != -1 )
1276 return mSource->
fields();
1286 if ( mFeatureLimit == -1 )
1289 return std::min( mFeatureLimit,
static_cast< long long >( mSource->
featureCount() ) );
1336 return expressionContextScope;
1341 mInvalidGeometryCheck = method;
1342 switch ( mInvalidGeometryCheck )
1345 mInvalidGeometryCallback =
nullptr;
1349 mInvalidGeometryCallback = mInvalidGeometryCallbackSkip;
1353 mInvalidGeometryCallback = mInvalidGeometryCallbackAbort;
1365 , mContext( context )
1366 , mSinkName( sinkName )
1367 , mOwnsSink( ownsOriginalSink )
1380 mContext.
feedback()->
reportError( QObject::tr(
"Feature could not be written to %1" ).arg( mSinkName ) );
1388 mContext.
feedback()->
reportError( QObject::tr(
"%1 feature(s) could not be written to %2" ).arg( features.count() ).arg( mSinkName ) );
1396 mContext.
feedback()->
reportError( QObject::tr(
"Features could not be written to %1" ).arg( mSinkName ) );