1 /***************************************************************************
2 qgsprocessingparameters.cpp
3 ---------------------------
4 begin : April 2017
5 copyright : (C) 2017 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 "qgsprocessingparameters.h"
19 #include "qgsprocessingprovider.h"
20 #include "qgsprocessingcontext.h"
21 #include "qgsprocessingutils.h"
22 #include "qgsprocessingalgorithm.h"
23 #include "qgsvectorlayerfeatureiterator.h"
24 #include "qgsprocessingoutputs.h"
25 #include "qgssettings.h"
26 #include "qgsvectorfilewriter.h"
27 #include "qgsreferencedgeometry.h"
28 #include "qgsprocessingregistry.h"
29 #include "qgsprocessingparametertype.h"
30 #include "qgsrasterfilewriter.h"
31 #include "qgsvectorlayer.h"
32 #include "qgsmeshlayer.h"
33 #include "qgsapplication.h"
34 #include "qgslayoutmanager.h"
35 #include "qgsprintlayout.h"
36 #include "qgssymbollayerutils.h"
37 #include "qgsfileutils.h"
38 #include "qgsproviderregistry.h"
39 #include <functional>
40
41
toVariant() const42 QVariant QgsProcessingFeatureSourceDefinition::toVariant() const
43 {
44 QVariantMap map;
45 map.insert( QStringLiteral( "source" ), source.toVariant() );
46 map.insert( QStringLiteral( "selected_only" ), selectedFeaturesOnly );
47 map.insert( QStringLiteral( "feature_limit" ), featureLimit );
48 map.insert( QStringLiteral( "flags" ), static_cast< int >( flags ) );
49 map.insert( QStringLiteral( "geometry_check" ), static_cast< int >( geometryCheck ) );
50 return map;
51 }
52
loadVariant(const QVariantMap & map)53 bool QgsProcessingFeatureSourceDefinition::loadVariant( const QVariantMap &map )
54 {
55 source.loadVariant( map.value( QStringLiteral( "source" ) ) );
56 selectedFeaturesOnly = map.value( QStringLiteral( "selected_only" ), false ).toBool();
57 featureLimit = map.value( QStringLiteral( "feature_limit" ), -1 ).toLongLong();
58 flags = static_cast< Flags >( map.value( QStringLiteral( "flags" ), 0 ).toInt() );
59 geometryCheck = static_cast< QgsFeatureRequest::InvalidGeometryCheck >( map.value( QStringLiteral( "geometry_check" ), QgsFeatureRequest::GeometryAbortOnInvalid ).toInt() );
60 return true;
61 }
62
63
64 //
65 // QgsProcessingOutputLayerDefinition
66 //
67
setRemappingDefinition(const QgsRemappingSinkDefinition & definition)68 void QgsProcessingOutputLayerDefinition::setRemappingDefinition( const QgsRemappingSinkDefinition &definition )
69 {
70 mUseRemapping = true;
71 mRemappingDefinition = definition;
72 }
73
toVariant() const74 QVariant QgsProcessingOutputLayerDefinition::toVariant() const
75 {
76 QVariantMap map;
77 map.insert( QStringLiteral( "sink" ), sink.toVariant() );
78 map.insert( QStringLiteral( "create_options" ), createOptions );
79 if ( mUseRemapping )
80 map.insert( QStringLiteral( "remapping" ), QVariant::fromValue( mRemappingDefinition ) );
81 return map;
82 }
83
loadVariant(const QVariantMap & map)84 bool QgsProcessingOutputLayerDefinition::loadVariant( const QVariantMap &map )
85 {
86 sink.loadVariant( map.value( QStringLiteral( "sink" ) ) );
87 createOptions = map.value( QStringLiteral( "create_options" ) ).toMap();
88 if ( map.contains( QStringLiteral( "remapping" ) ) )
89 {
90 mUseRemapping = true;
91 mRemappingDefinition = map.value( QStringLiteral( "remapping" ) ).value< QgsRemappingSinkDefinition >();
92 }
93 else
94 {
95 mUseRemapping = false;
96 }
97 return true;
98 }
99
operator ==(const QgsProcessingOutputLayerDefinition & other) const100 bool QgsProcessingOutputLayerDefinition::operator==( const QgsProcessingOutputLayerDefinition &other ) const
101 {
102 return sink == other.sink && destinationProject == other.destinationProject && destinationName == other.destinationName && createOptions == other.createOptions
103 && mUseRemapping == other.mUseRemapping && mRemappingDefinition == other.mRemappingDefinition;
104 }
105
operator !=(const QgsProcessingOutputLayerDefinition & other) const106 bool QgsProcessingOutputLayerDefinition::operator!=( const QgsProcessingOutputLayerDefinition &other ) const
107 {
108 return !( *this == other );
109 }
110
isDynamic(const QVariantMap & parameters,const QString & name)111 bool QgsProcessingParameters::isDynamic( const QVariantMap ¶meters, const QString &name )
112 {
113 QVariant val = parameters.value( name );
114 if ( val.canConvert<QgsProperty>() )
115 return val.value< QgsProperty >().propertyType() != QgsProperty::StaticProperty;
116 else
117 return false;
118 }
119
parameterAsString(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)120 QString QgsProcessingParameters::parameterAsString( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
121 {
122 if ( !definition )
123 return QString();
124
125 return parameterAsString( definition, parameters.value( definition->name() ), context );
126 }
127
parameterAsString(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)128 QString QgsProcessingParameters::parameterAsString( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
129 {
130 if ( !definition )
131 return QString();
132
133 QVariant val = value;
134 if ( val.canConvert<QgsProperty>() )
135 return val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
136
137 if ( !val.isValid() )
138 {
139 // fall back to default
140 val = definition->defaultValue();
141 }
142
143 if ( val == QgsProcessing::TEMPORARY_OUTPUT )
144 {
145 if ( const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( definition ) )
146 return destParam->generateTemporaryDestination();
147 }
148
149 return val.toString();
150 }
151
parameterAsExpression(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)152 QString QgsProcessingParameters::parameterAsExpression( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
153 {
154 if ( !definition )
155 return QString();
156
157 return parameterAsExpression( definition, parameters.value( definition->name() ), context );
158 }
159
parameterAsExpression(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)160 QString QgsProcessingParameters::parameterAsExpression( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
161 {
162 if ( !definition )
163 return QString();
164
165 QVariant val = value;
166 if ( val.canConvert<QgsProperty>() )
167 return val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
168
169 if ( val.isValid() && !val.toString().isEmpty() )
170 {
171 QgsExpression e( val.toString() );
172 if ( e.isValid() )
173 return val.toString();
174 }
175
176 // fall back to default
177 return definition->defaultValue().toString();
178 }
179
parameterAsDouble(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)180 double QgsProcessingParameters::parameterAsDouble( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
181 {
182 if ( !definition )
183 return 0;
184
185 return parameterAsDouble( definition, parameters.value( definition->name() ), context );
186 }
187
parameterAsDouble(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)188 double QgsProcessingParameters::parameterAsDouble( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
189 {
190 if ( !definition )
191 return 0;
192
193 QVariant val = value;
194 if ( val.canConvert<QgsProperty>() )
195 return val.value< QgsProperty >().valueAsDouble( context.expressionContext(), definition->defaultValue().toDouble() );
196
197 bool ok = false;
198 double res = val.toDouble( &ok );
199 if ( ok )
200 return res;
201
202 // fall back to default
203 val = definition->defaultValue();
204 return val.toDouble();
205 }
206
parameterAsInt(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)207 int QgsProcessingParameters::parameterAsInt( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
208 {
209 if ( !definition )
210 return 0;
211
212 return parameterAsInt( definition, parameters.value( definition->name() ), context );
213 }
214
parameterAsInt(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)215 int QgsProcessingParameters::parameterAsInt( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
216 {
217 if ( !definition )
218 return 0;
219
220 QVariant val = value;
221 if ( val.canConvert<QgsProperty>() )
222 return val.value< QgsProperty >().valueAsInt( context.expressionContext(), definition->defaultValue().toInt() );
223
224 bool ok = false;
225 double dbl = val.toDouble( &ok );
226 if ( !ok )
227 {
228 // fall back to default
229 val = definition->defaultValue();
230 dbl = val.toDouble( &ok );
231 }
232
233 //String representations of doubles in QVariant will not convert to int
234 //work around this by first converting to double, and then checking whether the double is convertible to int
235 if ( ok )
236 {
237 double round = std::round( dbl );
238 if ( round > std::numeric_limits<int>::max() || round < -std::numeric_limits<int>::max() )
239 {
240 //double too large to fit in int
241 return 0;
242 }
243 return static_cast< int >( std::round( dbl ) );
244 }
245
246 return val.toInt();
247 }
248
parameterAsInts(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)249 QList< int > QgsProcessingParameters::parameterAsInts( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
250 {
251 if ( !definition )
252 return QList< int >();
253
254 return parameterAsInts( definition, parameters.value( definition->name() ), context );
255 }
256
parameterAsInts(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)257 QList< int > QgsProcessingParameters::parameterAsInts( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
258 {
259 if ( !definition )
260 return QList< int >();
261
262 QList< int > resultList;
263 QVariant val = value;
264 if ( val.isValid() )
265 {
266 if ( val.canConvert<QgsProperty>() )
267 resultList << val.value< QgsProperty >().valueAsInt( context.expressionContext(), definition->defaultValue().toInt() );
268 else if ( val.type() == QVariant::List )
269 {
270 QVariantList list = val.toList();
271 for ( auto it = list.constBegin(); it != list.constEnd(); ++it )
272 resultList << it->toInt();
273 }
274 else
275 {
276 QStringList parts = val.toString().split( ';' );
277 for ( auto it = parts.constBegin(); it != parts.constEnd(); ++it )
278 resultList << it->toInt();
279 }
280 }
281
282 if ( ( resultList.isEmpty() || resultList.at( 0 ) == 0 ) )
283 {
284 resultList.clear();
285 // check default
286 if ( definition->defaultValue().isValid() )
287 {
288 if ( definition->defaultValue().type() == QVariant::List )
289 {
290 QVariantList list = definition->defaultValue().toList();
291 for ( auto it = list.constBegin(); it != list.constEnd(); ++it )
292 resultList << it->toInt();
293 }
294 else
295 {
296 QStringList parts = definition->defaultValue().toString().split( ';' );
297 for ( auto it = parts.constBegin(); it != parts.constEnd(); ++it )
298 resultList << it->toInt();
299 }
300 }
301 }
302
303 return resultList;
304 }
305
parameterAsDateTime(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)306 QDateTime QgsProcessingParameters::parameterAsDateTime( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
307 {
308 if ( !definition )
309 return QDateTime();
310
311 return parameterAsDateTime( definition, parameters.value( definition->name() ), context );
312 }
313
parameterAsDateTime(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)314 QDateTime QgsProcessingParameters::parameterAsDateTime( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
315 {
316 if ( !definition )
317 return QDateTime();
318
319 QVariant val = value;
320 if ( val.canConvert<QgsProperty>() )
321 val = val.value< QgsProperty >().value( context.expressionContext(), definition->defaultValue() );
322
323 QDateTime d = val.toDateTime();
324 if ( !d.isValid() && val.type() == QVariant::String )
325 {
326 d = QDateTime::fromString( val.toString() );
327 }
328
329 if ( !d.isValid() )
330 {
331 // fall back to default
332 val = definition->defaultValue();
333 d = val.toDateTime();
334 }
335 if ( !d.isValid() && val.type() == QVariant::String )
336 {
337 d = QDateTime::fromString( val.toString() );
338 }
339
340 return d;
341 }
342
parameterAsDate(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)343 QDate QgsProcessingParameters::parameterAsDate( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
344 {
345 if ( !definition )
346 return QDate();
347
348 return parameterAsDate( definition, parameters.value( definition->name() ), context );
349 }
350
parameterAsDate(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)351 QDate QgsProcessingParameters::parameterAsDate( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
352 {
353 if ( !definition )
354 return QDate();
355
356 QVariant val = value;
357 if ( val.canConvert<QgsProperty>() )
358 val = val.value< QgsProperty >().value( context.expressionContext(), definition->defaultValue() );
359
360 QDate d = val.toDate();
361 if ( !d.isValid() && val.type() == QVariant::String )
362 {
363 d = QDate::fromString( val.toString() );
364 }
365
366 if ( !d.isValid() )
367 {
368 // fall back to default
369 val = definition->defaultValue();
370 d = val.toDate();
371 }
372 if ( !d.isValid() && val.type() == QVariant::String )
373 {
374 d = QDate::fromString( val.toString() );
375 }
376
377 return d;
378 }
379
parameterAsTime(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)380 QTime QgsProcessingParameters::parameterAsTime( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
381 {
382 if ( !definition )
383 return QTime();
384
385 return parameterAsTime( definition, parameters.value( definition->name() ), context );
386 }
387
parameterAsTime(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)388 QTime QgsProcessingParameters::parameterAsTime( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
389 {
390 if ( !definition )
391 return QTime();
392
393 QVariant val = value;
394 if ( val.canConvert<QgsProperty>() )
395 val = val.value< QgsProperty >().value( context.expressionContext(), definition->defaultValue() );
396
397 QTime d;
398
399 if ( val.type() == QVariant::DateTime )
400 d = val.toDateTime().time();
401 else
402 d = val.toTime();
403
404 if ( !d.isValid() && val.type() == QVariant::String )
405 {
406 d = QTime::fromString( val.toString() );
407 }
408
409 if ( !d.isValid() )
410 {
411 // fall back to default
412 val = definition->defaultValue();
413 d = val.toTime();
414 }
415 if ( !d.isValid() && val.type() == QVariant::String )
416 {
417 d = QTime::fromString( val.toString() );
418 }
419
420 return d;
421 }
422
parameterAsEnum(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)423 int QgsProcessingParameters::parameterAsEnum( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
424 {
425 if ( !definition )
426 return 0;
427
428 return parameterAsEnum( definition, parameters.value( definition->name() ), context );
429 }
430
parameterAsEnum(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)431 int QgsProcessingParameters::parameterAsEnum( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
432 {
433 if ( !definition )
434 return 0;
435
436 int val = parameterAsInt( definition, value, context );
437 const QgsProcessingParameterEnum *enumDef = dynamic_cast< const QgsProcessingParameterEnum *>( definition );
438 if ( enumDef && val >= enumDef->options().size() )
439 {
440 return enumDef->defaultValue().toInt();
441 }
442 return val;
443 }
444
parameterAsEnums(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)445 QList<int> QgsProcessingParameters::parameterAsEnums( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
446 {
447 if ( !definition )
448 return QList<int>();
449
450 return parameterAsEnums( definition, parameters.value( definition->name() ), context );
451 }
452
parameterAsEnums(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)453 QList<int> QgsProcessingParameters::parameterAsEnums( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
454 {
455 if ( !definition )
456 return QList<int>();
457
458 QVariantList resultList;
459 QVariant val = value;
460 if ( val.canConvert<QgsProperty>() )
461 resultList << val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
462 else if ( val.type() == QVariant::List )
463 {
464 const auto constToList = val.toList();
465 for ( const QVariant &var : constToList )
466 resultList << var;
467 }
468 else if ( val.type() == QVariant::String )
469 {
470 const auto constSplit = val.toString().split( ',' );
471 for ( const QString &var : constSplit )
472 resultList << var;
473 }
474 else
475 resultList << val;
476
477 if ( resultList.isEmpty() )
478 return QList< int >();
479
480 if ( ( !val.isValid() || !resultList.at( 0 ).isValid() ) && definition )
481 {
482 resultList.clear();
483 // check default
484 if ( definition->defaultValue().type() == QVariant::List )
485 {
486 const auto constToList = definition->defaultValue().toList();
487 for ( const QVariant &var : constToList )
488 resultList << var;
489 }
490 else if ( definition->defaultValue().type() == QVariant::String )
491 {
492 const auto constSplit = definition->defaultValue().toString().split( ',' );
493 for ( const QString &var : constSplit )
494 resultList << var;
495 }
496 else
497 resultList << definition->defaultValue();
498 }
499
500 QList< int > result;
501 const QgsProcessingParameterEnum *enumDef = dynamic_cast< const QgsProcessingParameterEnum *>( definition );
502 const auto constResultList = resultList;
503 for ( const QVariant &var : constResultList )
504 {
505 int resInt = var.toInt();
506 if ( !enumDef || resInt < enumDef->options().size() )
507 {
508 result << resInt;
509 }
510 }
511 return result;
512 }
513
parameterAsBool(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)514 bool QgsProcessingParameters::parameterAsBool( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
515 {
516 if ( !definition )
517 return false;
518
519 return parameterAsBool( definition, parameters.value( definition->name() ), context );
520 }
521
parameterAsBoolean(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)522 bool QgsProcessingParameters::parameterAsBoolean( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
523 {
524 if ( !definition )
525 return false;
526
527 return parameterAsBoolean( definition, parameters.value( definition->name() ), context );
528 }
529
parameterAsBool(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)530 bool QgsProcessingParameters::parameterAsBool( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
531 {
532 if ( !definition )
533 return false;
534
535 QVariant def = definition->defaultValue();
536
537 QVariant val = value;
538 if ( val.canConvert<QgsProperty>() )
539 return val.value< QgsProperty >().valueAsBool( context.expressionContext(), def.toBool() );
540 else if ( val.isValid() )
541 return val.toBool();
542 else
543 return def.toBool();
544 }
545
parameterAsBoolean(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)546 bool QgsProcessingParameters::parameterAsBoolean( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
547 {
548 if ( !definition )
549 return false;
550
551 QVariant def = definition->defaultValue();
552
553 QVariant val = value;
554 if ( val.canConvert<QgsProperty>() )
555 return val.value< QgsProperty >().valueAsBool( context.expressionContext(), def.toBool() );
556 else if ( val.isValid() )
557 return val.toBool();
558 else
559 return def.toBool();
560 }
561
parameterAsSink(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsFields & fields,QgsWkbTypes::Type geometryType,const QgsCoordinateReferenceSystem & crs,QgsProcessingContext & context,QString & destinationIdentifier,QgsFeatureSink::SinkFlags sinkFlags,const QVariantMap & createOptions,const QStringList & datasourceOptions,const QStringList & layerOptions)562 QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsFields &fields,
563 QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs,
564 QgsProcessingContext &context, QString &destinationIdentifier, QgsFeatureSink::SinkFlags sinkFlags,
565 const QVariantMap &createOptions, const QStringList &datasourceOptions, const QStringList &layerOptions )
566 {
567 QVariant val;
568 if ( definition )
569 {
570 val = parameters.value( definition->name() );
571 }
572
573 return parameterAsSink( definition, val, fields, geometryType, crs, context, destinationIdentifier, sinkFlags, createOptions, datasourceOptions, layerOptions );
574 }
575
parameterAsSink(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsFields & fields,QgsWkbTypes::Type geometryType,const QgsCoordinateReferenceSystem & crs,QgsProcessingContext & context,QString & destinationIdentifier,QgsFeatureSink::SinkFlags sinkFlags,const QVariantMap & createOptions,const QStringList & datasourceOptions,const QStringList & layerOptions)576 QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsProcessingContext &context, QString &destinationIdentifier, QgsFeatureSink::SinkFlags sinkFlags, const QVariantMap &createOptions, const QStringList &datasourceOptions, const QStringList &layerOptions )
577 {
578 QVariantMap options = createOptions;
579 QVariant val = value;
580
581 QgsProject *destinationProject = nullptr;
582 QString destName;
583 QgsRemappingSinkDefinition remapDefinition;
584 bool useRemapDefinition = false;
585 if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
586 {
587 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
588 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
589 destinationProject = fromVar.destinationProject;
590 options = fromVar.createOptions;
591
592 val = fromVar.sink;
593 destName = fromVar.destinationName;
594 if ( fromVar.useRemapping() )
595 {
596 useRemapDefinition = true;
597 remapDefinition = fromVar.remappingDefinition();
598 }
599 }
600
601 QString dest;
602 if ( definition && val.canConvert<QgsProperty>() )
603 {
604 dest = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
605 }
606 else if ( !val.isValid() || val.toString().isEmpty() )
607 {
608 if ( definition && definition->flags() & QgsProcessingParameterDefinition::FlagOptional && !definition->defaultValue().isValid() )
609 {
610 // unset, optional sink, no default => no sink
611 return nullptr;
612 }
613 // fall back to default
614 if ( !definition )
615 {
616 throw QgsProcessingException( QObject::tr( "No parameter definition for the sink" ) );
617 }
618 dest = definition->defaultValue().toString();
619 }
620 else
621 {
622 dest = val.toString();
623 }
624 if ( dest == QgsProcessing::TEMPORARY_OUTPUT )
625 {
626 if ( const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( definition ) )
627 dest = destParam->generateTemporaryDestination();
628 }
629
630 if ( dest.isEmpty() )
631 return nullptr;
632
633 std::unique_ptr< QgsFeatureSink > sink( QgsProcessingUtils::createFeatureSink( dest, context, fields, geometryType, crs, options, datasourceOptions, layerOptions, sinkFlags, useRemapDefinition ? &remapDefinition : nullptr ) );
634 destinationIdentifier = dest;
635
636 if ( destinationProject )
637 {
638 if ( destName.isEmpty() && definition )
639 {
640 destName = definition->description();
641 }
642 QString outputName;
643 if ( definition )
644 outputName = definition->name();
645 context.addLayerToLoadOnCompletion( destinationIdentifier, QgsProcessingContext::LayerDetails( destName, destinationProject, outputName, QgsProcessingUtils::LayerHint::Vector ) );
646 }
647
648 return sink.release();
649 }
650
parameterAsSource(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)651 QgsProcessingFeatureSource *QgsProcessingParameters::parameterAsSource( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
652 {
653 if ( !definition )
654 return nullptr;
655
656 return parameterAsSource( definition, parameters.value( definition->name() ), context );
657 }
658
parameterAsSource(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)659 QgsProcessingFeatureSource *QgsProcessingParameters::parameterAsSource( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
660 {
661 if ( !definition )
662 return nullptr;
663
664 return QgsProcessingUtils::variantToSource( value, context, definition->defaultValue() );
665 }
666
parameterAsCompatibleSourceLayerPathInternal(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QStringList & compatibleFormats,const QString & preferredFormat,QgsProcessingFeedback * feedback,QString * layerName)667 QString parameterAsCompatibleSourceLayerPathInternal( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback, QString *layerName )
668 {
669 if ( !definition )
670 return QString();
671
672 QVariant val = parameters.value( definition->name() );
673
674 bool selectedFeaturesOnly = false;
675 long long featureLimit = -1;
676 if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
677 {
678 // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
679 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
680 selectedFeaturesOnly = fromVar.selectedFeaturesOnly;
681 featureLimit = fromVar.featureLimit;
682 val = fromVar.source;
683 }
684 else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
685 {
686 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
687 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
688 val = fromVar.sink;
689 }
690
691 if ( val.canConvert<QgsProperty>() )
692 {
693 val = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
694 }
695
696 QgsVectorLayer *vl = nullptr;
697 vl = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( val ) );
698
699 if ( !vl )
700 {
701 QString layerRef;
702 if ( val.canConvert<QgsProperty>() )
703 {
704 layerRef = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
705 }
706 else if ( !val.isValid() || val.toString().isEmpty() )
707 {
708 // fall back to default
709 val = definition->defaultValue();
710
711 // default value may be a vector layer
712 vl = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( val ) );
713 if ( !vl )
714 layerRef = definition->defaultValue().toString();
715 }
716 else
717 {
718 layerRef = val.toString();
719 }
720
721 if ( !vl )
722 {
723 if ( layerRef.isEmpty() )
724 return QString();
725
726 vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context, true, QgsProcessingUtils::LayerHint::Vector ) );
727 }
728 }
729
730 if ( !vl )
731 return QString();
732
733 if ( layerName )
734 return QgsProcessingUtils::convertToCompatibleFormatAndLayerName( vl, selectedFeaturesOnly, definition->name(),
735 compatibleFormats, preferredFormat, context, feedback, *layerName, featureLimit );
736 else
737 return QgsProcessingUtils::convertToCompatibleFormat( vl, selectedFeaturesOnly, definition->name(),
738 compatibleFormats, preferredFormat, context, feedback, featureLimit );
739 }
740
parameterAsCompatibleSourceLayerPath(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QStringList & compatibleFormats,const QString & preferredFormat,QgsProcessingFeedback * feedback)741 QString QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback )
742 {
743 return parameterAsCompatibleSourceLayerPathInternal( definition, parameters, context, compatibleFormats, preferredFormat, feedback, nullptr );
744 }
745
parameterAsCompatibleSourceLayerPathAndLayerName(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QStringList & compatibleFormats,const QString & preferredFormat,QgsProcessingFeedback * feedback,QString * layerName)746 QString QgsProcessingParameters::parameterAsCompatibleSourceLayerPathAndLayerName( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback, QString *layerName )
747 {
748 QString *destLayer = layerName;
749 QString tmp;
750 if ( destLayer )
751 destLayer->clear();
752 else
753 destLayer = &tmp;
754
755 return parameterAsCompatibleSourceLayerPathInternal( definition, parameters, context, compatibleFormats, preferredFormat, feedback, destLayer );
756 }
757
758
parameterAsLayer(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,QgsProcessingUtils::LayerHint layerHint)759 QgsMapLayer *QgsProcessingParameters::parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingUtils::LayerHint layerHint )
760 {
761 if ( !definition )
762 return nullptr;
763
764 return parameterAsLayer( definition, parameters.value( definition->name() ), context, layerHint );
765 }
766
parameterAsLayer(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context,QgsProcessingUtils::LayerHint layerHint)767 QgsMapLayer *QgsProcessingParameters::parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, QgsProcessingUtils::LayerHint layerHint )
768 {
769 if ( !definition )
770 return nullptr;
771
772 QVariant val = value;
773 if ( val.canConvert<QgsProperty>() )
774 {
775 val = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
776 }
777
778 if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) ) )
779 {
780 return layer;
781 }
782
783 if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
784 {
785 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
786 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
787 val = fromVar.sink;
788 }
789
790 if ( val.canConvert<QgsProperty>() && val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
791 {
792 val = val.value< QgsProperty >().staticValue();
793 }
794
795 if ( !val.isValid() || val.toString().isEmpty() )
796 {
797 // fall back to default
798 val = definition->defaultValue();
799 }
800
801 if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) ) )
802 {
803 return layer;
804 }
805
806 QString layerRef = val.toString();
807 if ( layerRef.isEmpty() )
808 layerRef = definition->defaultValue().toString();
809
810 if ( layerRef.isEmpty() )
811 return nullptr;
812
813 return QgsProcessingUtils::mapLayerFromString( layerRef, context, true, layerHint );
814 }
815
parameterAsRasterLayer(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)816 QgsRasterLayer *QgsProcessingParameters::parameterAsRasterLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
817 {
818 return qobject_cast< QgsRasterLayer *>( parameterAsLayer( definition, parameters, context, QgsProcessingUtils::LayerHint::Raster ) );
819 }
820
parameterAsRasterLayer(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)821 QgsRasterLayer *QgsProcessingParameters::parameterAsRasterLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
822 {
823 return qobject_cast< QgsRasterLayer *>( parameterAsLayer( definition, value, context, QgsProcessingUtils::LayerHint::Raster ) );
824 }
825
parameterAsMeshLayer(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)826 QgsMeshLayer *QgsProcessingParameters::parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
827 {
828 return qobject_cast< QgsMeshLayer *>( parameterAsLayer( definition, parameters, context, QgsProcessingUtils::LayerHint::Mesh ) );
829 }
830
parameterAsMeshLayer(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)831 QgsMeshLayer *QgsProcessingParameters::parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
832 {
833 return qobject_cast< QgsMeshLayer *>( parameterAsLayer( definition, value, context, QgsProcessingUtils::LayerHint::Mesh ) );
834 }
835
parameterAsOutputLayer(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)836 QString QgsProcessingParameters::parameterAsOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
837 {
838 QVariant val;
839 if ( definition )
840 {
841 val = parameters.value( definition->name() );
842 }
843 return parameterAsOutputLayer( definition, val, context );
844 }
845
parameterAsOutputLayer(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)846 QString QgsProcessingParameters::parameterAsOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
847 {
848 QVariant val = value;
849
850 QgsProject *destinationProject = nullptr;
851 QString destName;
852 if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
853 {
854 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
855 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
856 destinationProject = fromVar.destinationProject;
857 val = fromVar.sink;
858 destName = fromVar.destinationName;
859 }
860
861 QString dest;
862 if ( definition && val.canConvert<QgsProperty>() )
863 {
864 dest = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
865 }
866 else if ( definition && ( !val.isValid() || val.toString().isEmpty() ) )
867 {
868 // fall back to default
869 dest = definition->defaultValue().toString();
870 }
871 else
872 {
873 dest = val.toString();
874 }
875 if ( dest == QgsProcessing::TEMPORARY_OUTPUT )
876 {
877 if ( const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( definition ) )
878 dest = destParam->generateTemporaryDestination();
879 }
880
881 if ( destinationProject )
882 {
883 QString outputName;
884 if ( destName.isEmpty() && definition )
885 {
886 destName = definition->description();
887 }
888 if ( definition )
889 outputName = definition->name();
890
891 QgsProcessingUtils::LayerHint layerTypeHint = QgsProcessingUtils::LayerHint::UnknownType;
892 if ( definition && definition->type() == QgsProcessingParameterVectorDestination::typeName() )
893 layerTypeHint = QgsProcessingUtils::LayerHint::Vector;
894 else if ( definition && definition->type() == QgsProcessingParameterRasterDestination::typeName() )
895 layerTypeHint = QgsProcessingUtils::LayerHint::Raster;
896
897 context.addLayerToLoadOnCompletion( dest, QgsProcessingContext::LayerDetails( destName, destinationProject, outputName, layerTypeHint ) );
898 }
899
900 return dest;
901 }
902
parameterAsFileOutput(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)903 QString QgsProcessingParameters::parameterAsFileOutput( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
904 {
905 QVariant val;
906 if ( definition )
907 {
908 val = parameters.value( definition->name() );
909 }
910 return parameterAsFileOutput( definition, val, context );
911 }
912
parameterAsFileOutput(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)913 QString QgsProcessingParameters::parameterAsFileOutput( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
914 {
915 QVariant val = value;
916
917 if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
918 {
919 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
920 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
921 val = fromVar.sink;
922 }
923
924 QString dest;
925 if ( definition && val.canConvert<QgsProperty>() )
926 {
927 dest = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
928 }
929 else if ( definition && ( !val.isValid() || val.toString().isEmpty() ) )
930 {
931 // fall back to default
932 dest = definition->defaultValue().toString();
933 }
934 else
935 {
936 dest = val.toString();
937 }
938 if ( dest == QgsProcessing::TEMPORARY_OUTPUT )
939 {
940 if ( const QgsProcessingDestinationParameter *destParam = dynamic_cast< const QgsProcessingDestinationParameter * >( definition ) )
941 dest = destParam->generateTemporaryDestination();
942 }
943 return dest;
944 }
945
parameterAsVectorLayer(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)946 QgsVectorLayer *QgsProcessingParameters::parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
947 {
948 return qobject_cast< QgsVectorLayer *>( parameterAsLayer( definition, parameters, context, QgsProcessingUtils::LayerHint::Vector ) );
949 }
950
parameterAsVectorLayer(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)951 QgsVectorLayer *QgsProcessingParameters::parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
952 {
953 return qobject_cast< QgsVectorLayer *>( parameterAsLayer( definition, value, context, QgsProcessingUtils::LayerHint::Vector ) );
954 }
955
parameterAsCrs(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)956 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
957 {
958 if ( !definition )
959 return QgsCoordinateReferenceSystem();
960
961 return parameterAsCrs( definition, parameters.value( definition->name() ), context );
962 }
963
parameterAsCrs(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)964 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsCrs( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
965 {
966 if ( !definition )
967 return QgsCoordinateReferenceSystem();
968
969 return QgsProcessingUtils::variantToCrs( value, context, definition->defaultValue() );
970 }
971
parameterAsExtent(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)972 QgsRectangle QgsProcessingParameters::parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context,
973 const QgsCoordinateReferenceSystem &crs )
974 {
975 if ( !definition )
976 return QgsRectangle();
977
978 return parameterAsExtent( definition, parameters.value( definition->name() ), context, crs );
979 }
980
parameterAsExtent(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)981 QgsRectangle QgsProcessingParameters::parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
982 {
983 if ( !definition )
984 return QgsRectangle();
985
986 QVariant val = value;
987
988 if ( val.canConvert< QgsRectangle >() )
989 {
990 return val.value<QgsRectangle>();
991 }
992 if ( val.canConvert< QgsGeometry >() )
993 {
994 const QgsGeometry geom = val.value<QgsGeometry>();
995 if ( !geom.isNull() )
996 return geom.boundingBox();
997 }
998 if ( val.canConvert< QgsReferencedRectangle >() )
999 {
1000 QgsReferencedRectangle rr = val.value<QgsReferencedRectangle>();
1001 if ( crs.isValid() && rr.crs().isValid() && crs != rr.crs() )
1002 {
1003 QgsCoordinateTransform ct( rr.crs(), crs, context.project() );
1004 try
1005 {
1006 return ct.transformBoundingBox( rr );
1007 }
1008 catch ( QgsCsException & )
1009 {
1010 QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
1011 }
1012 }
1013 return rr;
1014 }
1015
1016 if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
1017 {
1018 // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
1019 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
1020 val = fromVar.source;
1021 }
1022 else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
1023 {
1024 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
1025 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
1026 val = fromVar.sink;
1027 }
1028
1029 if ( val.canConvert<QgsProperty>() && val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
1030 {
1031 val = val.value< QgsProperty >().staticValue();
1032 }
1033
1034 // maybe parameter is a direct layer value?
1035 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) );
1036
1037 QString rectText;
1038 if ( val.canConvert<QgsProperty>() )
1039 rectText = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
1040 else
1041 rectText = val.toString();
1042
1043 if ( rectText.isEmpty() && !layer )
1044 return QgsRectangle();
1045
1046 QRegularExpression rx( QStringLiteral( "^(.*?)\\s*,\\s*(.*?),\\s*(.*?),\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*$" ) );
1047 QRegularExpressionMatch match = rx.match( rectText );
1048 if ( match.hasMatch() )
1049 {
1050 bool xMinOk = false;
1051 double xMin = match.captured( 1 ).toDouble( &xMinOk );
1052 bool xMaxOk = false;
1053 double xMax = match.captured( 2 ).toDouble( &xMaxOk );
1054 bool yMinOk = false;
1055 double yMin = match.captured( 3 ).toDouble( &yMinOk );
1056 bool yMaxOk = false;
1057 double yMax = match.captured( 4 ).toDouble( &yMaxOk );
1058 if ( xMinOk && xMaxOk && yMinOk && yMaxOk )
1059 {
1060 QgsRectangle rect( xMin, yMin, xMax, yMax );
1061 QgsCoordinateReferenceSystem rectCrs( match.captured( 5 ) );
1062 if ( crs.isValid() && rectCrs.isValid() && crs != rectCrs )
1063 {
1064 QgsCoordinateTransform ct( rectCrs, crs, context.project() );
1065 try
1066 {
1067 return ct.transformBoundingBox( rect );
1068 }
1069 catch ( QgsCsException & )
1070 {
1071 QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
1072 }
1073 }
1074 return rect;
1075 }
1076 }
1077
1078 // try as layer extent
1079 if ( !layer )
1080 layer = QgsProcessingUtils::mapLayerFromString( rectText, context );
1081
1082 if ( layer )
1083 {
1084 QgsRectangle rect = layer->extent();
1085 if ( crs.isValid() && layer->crs().isValid() && crs != layer->crs() )
1086 {
1087 QgsCoordinateTransform ct( layer->crs(), crs, context.project() );
1088 try
1089 {
1090 return ct.transformBoundingBox( rect );
1091 }
1092 catch ( QgsCsException & )
1093 {
1094 QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
1095 }
1096 }
1097 return rect;
1098 }
1099 return QgsRectangle();
1100 }
1101
parameterAsExtentGeometry(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)1102 QgsGeometry QgsProcessingParameters::parameterAsExtentGeometry( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
1103 {
1104 if ( !definition )
1105 return QgsGeometry();
1106
1107 QVariant val = parameters.value( definition->name() );
1108
1109 if ( val.canConvert< QgsReferencedRectangle >() )
1110 {
1111 QgsReferencedRectangle rr = val.value<QgsReferencedRectangle>();
1112 QgsGeometry g = QgsGeometry::fromRect( rr );
1113 if ( crs.isValid() && rr.crs().isValid() && crs != rr.crs() )
1114 {
1115 g = g.densifyByCount( 20 );
1116 QgsCoordinateTransform ct( rr.crs(), crs, context.project() );
1117 try
1118 {
1119 g.transform( ct );
1120 }
1121 catch ( QgsCsException & )
1122 {
1123 QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
1124 }
1125 return g;
1126 }
1127 }
1128
1129 if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
1130 {
1131 // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
1132 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
1133 val = fromVar.source;
1134 }
1135 else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
1136 {
1137 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
1138 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
1139 val = fromVar.sink;
1140 }
1141
1142 if ( val.canConvert<QgsProperty>() && val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
1143 {
1144 val = val.value< QgsProperty >().staticValue();
1145 }
1146
1147 QString rectText;
1148 if ( val.canConvert<QgsProperty>() )
1149 rectText = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
1150 else
1151 rectText = val.toString();
1152
1153 if ( !rectText.isEmpty() )
1154 {
1155 QRegularExpression rx( QStringLiteral( "^(.*?)\\s*,\\s*(.*?),\\s*(.*?),\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*$" ) );
1156 QRegularExpressionMatch match = rx.match( rectText );
1157 if ( match.hasMatch() )
1158 {
1159 bool xMinOk = false;
1160 double xMin = match.captured( 1 ).toDouble( &xMinOk );
1161 bool xMaxOk = false;
1162 double xMax = match.captured( 2 ).toDouble( &xMaxOk );
1163 bool yMinOk = false;
1164 double yMin = match.captured( 3 ).toDouble( &yMinOk );
1165 bool yMaxOk = false;
1166 double yMax = match.captured( 4 ).toDouble( &yMaxOk );
1167 if ( xMinOk && xMaxOk && yMinOk && yMaxOk )
1168 {
1169 QgsRectangle rect( xMin, yMin, xMax, yMax );
1170 QgsCoordinateReferenceSystem rectCrs( match.captured( 5 ) );
1171 QgsGeometry g = QgsGeometry::fromRect( rect );
1172 if ( crs.isValid() && rectCrs.isValid() && crs != rectCrs )
1173 {
1174 g = g.densifyByCount( 20 );
1175 QgsCoordinateTransform ct( rectCrs, crs, context.project() );
1176 try
1177 {
1178 g.transform( ct );
1179 }
1180 catch ( QgsCsException & )
1181 {
1182 QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
1183 }
1184 return g;
1185 }
1186 }
1187 }
1188 }
1189
1190 // try as layer extent
1191
1192 // maybe parameter is a direct layer value?
1193 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) );
1194 if ( !layer )
1195 layer = QgsProcessingUtils::mapLayerFromString( rectText, context );
1196
1197 if ( layer )
1198 {
1199 QgsRectangle rect = layer->extent();
1200 QgsGeometry g = QgsGeometry::fromRect( rect );
1201 if ( crs.isValid() && layer->crs().isValid() && crs != layer->crs() )
1202 {
1203 g = g.densifyByCount( 20 );
1204 QgsCoordinateTransform ct( layer->crs(), crs, context.project() );
1205 try
1206 {
1207 g.transform( ct );
1208 }
1209 catch ( QgsCsException & )
1210 {
1211 QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
1212 }
1213 }
1214 return g;
1215 }
1216
1217 return QgsGeometry::fromRect( parameterAsExtent( definition, parameters, context, crs ) );
1218 }
1219
parameterAsExtentCrs(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1220 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsExtentCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1221 {
1222 QVariant val = parameters.value( definition->name() );
1223 return parameterAsExtentCrs( definition, val, context );
1224 }
1225
parameterAsExtentCrs(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1226 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsExtentCrs( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1227 {
1228 QVariant val = value;
1229 if ( val.canConvert< QgsReferencedRectangle >() )
1230 {
1231 QgsReferencedRectangle rr = val.value<QgsReferencedRectangle>();
1232 if ( rr.crs().isValid() )
1233 {
1234 return rr.crs();
1235 }
1236 }
1237
1238 if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
1239 {
1240 // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
1241 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
1242 val = fromVar.source;
1243 }
1244 else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
1245 {
1246 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
1247 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
1248 val = fromVar.sink;
1249 }
1250
1251 if ( val.canConvert<QgsProperty>() && val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
1252 {
1253 val = val.value< QgsProperty >().staticValue();
1254 }
1255
1256 QString valueAsString;
1257 if ( val.canConvert<QgsProperty>() )
1258 valueAsString = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
1259 else
1260 valueAsString = val.toString();
1261
1262 QRegularExpression rx( QStringLiteral( "^(.*?)\\s*,\\s*(.*?),\\s*(.*?),\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*$" ) );
1263
1264 QRegularExpressionMatch match = rx.match( valueAsString );
1265 if ( match.hasMatch() )
1266 {
1267 QgsCoordinateReferenceSystem crs( match.captured( 5 ) );
1268 if ( crs.isValid() )
1269 return crs;
1270 }
1271
1272 if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
1273 {
1274 // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it
1275 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
1276 val = fromVar.source;
1277 }
1278 else if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
1279 {
1280 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
1281 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
1282 val = fromVar.sink;
1283 }
1284
1285 if ( val.canConvert<QgsProperty>() && val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
1286 {
1287 val = val.value< QgsProperty >().staticValue();
1288 }
1289
1290 // try as layer crs
1291 if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) ) )
1292 return layer->crs();
1293 else if ( QgsMapLayer *layer = QgsProcessingUtils::mapLayerFromString( valueAsString, context ) )
1294 return layer->crs();
1295
1296 if ( auto *lProject = context.project() )
1297 return lProject->crs();
1298 else
1299 return QgsCoordinateReferenceSystem();
1300 }
1301
parameterAsPoint(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)1302 QgsPointXY QgsProcessingParameters::parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
1303 {
1304 if ( !definition )
1305 return QgsPointXY();
1306
1307 return parameterAsPoint( definition, parameters.value( definition->name() ), context, crs );
1308 }
1309
parameterAsPoint(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)1310 QgsPointXY QgsProcessingParameters::parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
1311 {
1312 if ( !definition )
1313 return QgsPointXY();
1314
1315 QVariant val = value;
1316 if ( val.canConvert< QgsPointXY >() )
1317 {
1318 return val.value<QgsPointXY>();
1319 }
1320 if ( val.canConvert< QgsGeometry >() )
1321 {
1322 const QgsGeometry geom = val.value<QgsGeometry>();
1323 if ( !geom.isNull() )
1324 return geom.centroid().asPoint();
1325 }
1326 if ( val.canConvert< QgsReferencedPointXY >() )
1327 {
1328 QgsReferencedPointXY rp = val.value<QgsReferencedPointXY>();
1329 if ( crs.isValid() && rp.crs().isValid() && crs != rp.crs() )
1330 {
1331 QgsCoordinateTransform ct( rp.crs(), crs, context.project() );
1332 try
1333 {
1334 return ct.transform( rp );
1335 }
1336 catch ( QgsCsException & )
1337 {
1338 QgsMessageLog::logMessage( QObject::tr( "Error transforming point geometry" ) );
1339 }
1340 }
1341 return rp;
1342 }
1343
1344 QString pointText = parameterAsString( definition, value, context );
1345 if ( pointText.isEmpty() )
1346 pointText = definition->defaultValue().toString();
1347
1348 if ( pointText.isEmpty() )
1349 return QgsPointXY();
1350
1351 QRegularExpression rx( QStringLiteral( "^\\s*\\(?\\s*(.*?)\\s*,\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*\\)?\\s*$" ) );
1352
1353 QString valueAsString = parameterAsString( definition, value, context );
1354 QRegularExpressionMatch match = rx.match( valueAsString );
1355 if ( match.hasMatch() )
1356 {
1357 bool xOk = false;
1358 double x = match.captured( 1 ).toDouble( &xOk );
1359 bool yOk = false;
1360 double y = match.captured( 2 ).toDouble( &yOk );
1361
1362 if ( xOk && yOk )
1363 {
1364 QgsPointXY pt( x, y );
1365
1366 QgsCoordinateReferenceSystem pointCrs( match.captured( 3 ) );
1367 if ( crs.isValid() && pointCrs.isValid() && crs != pointCrs )
1368 {
1369 QgsCoordinateTransform ct( pointCrs, crs, context.project() );
1370 try
1371 {
1372 return ct.transform( pt );
1373 }
1374 catch ( QgsCsException & )
1375 {
1376 QgsMessageLog::logMessage( QObject::tr( "Error transforming point geometry" ) );
1377 }
1378 }
1379 return pt;
1380 }
1381 }
1382
1383 return QgsPointXY();
1384 }
1385
parameterAsPointCrs(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1386 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsPointCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1387 {
1388 QVariant val = parameters.value( definition->name() );
1389 return parameterAsPointCrs( definition, val, context );
1390 }
1391
parameterAsPointCrs(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1392 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsPointCrs( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1393 {
1394 if ( value.canConvert< QgsReferencedPointXY >() )
1395 {
1396 QgsReferencedPointXY rr = value.value<QgsReferencedPointXY>();
1397 if ( rr.crs().isValid() )
1398 {
1399 return rr.crs();
1400 }
1401 }
1402
1403 QRegularExpression rx( QStringLiteral( "^\\s*\\(?\\s*(.*?)\\s*,\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*\\)?\\s*$" ) );
1404
1405 QString valueAsString = parameterAsString( definition, value, context );
1406 QRegularExpressionMatch match = rx.match( valueAsString );
1407 if ( match.hasMatch() )
1408 {
1409 QgsCoordinateReferenceSystem crs( match.captured( 3 ) );
1410 if ( crs.isValid() )
1411 return crs;
1412 }
1413
1414 if ( auto *lProject = context.project() )
1415 return lProject->crs();
1416 else
1417 return QgsCoordinateReferenceSystem();
1418 }
1419
parameterAsGeometry(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)1420 QgsGeometry QgsProcessingParameters::parameterAsGeometry( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
1421 {
1422 if ( !definition )
1423 return QgsGeometry();
1424
1425 return parameterAsGeometry( definition, parameters.value( definition->name() ), context, crs );
1426 }
1427
parameterAsGeometry(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context,const QgsCoordinateReferenceSystem & crs)1428 QgsGeometry QgsProcessingParameters::parameterAsGeometry( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
1429 {
1430 if ( !definition )
1431 return QgsGeometry();
1432
1433 QVariant val = value;
1434 if ( val.canConvert< QgsGeometry >() )
1435 {
1436 return val.value<QgsGeometry>();
1437 }
1438
1439 if ( val.canConvert< QgsPointXY >() )
1440 {
1441 return QgsGeometry::fromPointXY( val.value<QgsPointXY>() );
1442 }
1443
1444 if ( val.canConvert< QgsRectangle >() )
1445 {
1446 return QgsGeometry::fromRect( val.value<QgsRectangle>() );
1447 }
1448
1449 if ( val.canConvert< QgsReferencedPointXY >() )
1450 {
1451 QgsReferencedPointXY rp = val.value<QgsReferencedPointXY>();
1452 if ( crs.isValid() && rp.crs().isValid() && crs != rp.crs() )
1453 {
1454 QgsCoordinateTransform ct( rp.crs(), crs, context.project() );
1455 try
1456 {
1457 return QgsGeometry::fromPointXY( ct.transform( rp ) );
1458 }
1459 catch ( QgsCsException & )
1460 {
1461 QgsMessageLog::logMessage( QObject::tr( "Error transforming point geometry" ) );
1462 }
1463 }
1464 return QgsGeometry::fromPointXY( rp );
1465 }
1466
1467 if ( val.canConvert< QgsReferencedRectangle >() )
1468 {
1469 QgsReferencedRectangle rr = val.value<QgsReferencedRectangle>();
1470 QgsGeometry g = QgsGeometry::fromRect( rr );
1471 if ( crs.isValid() && rr.crs().isValid() && crs != rr.crs() )
1472 {
1473 g = g.densifyByCount( 20 );
1474 QgsCoordinateTransform ct( rr.crs(), crs, context.project() );
1475 try
1476 {
1477 g.transform( ct );
1478 }
1479 catch ( QgsCsException & )
1480 {
1481 QgsMessageLog::logMessage( QObject::tr( "Error transforming rectangle geometry" ) );
1482 }
1483 }
1484 return g;
1485 }
1486
1487 if ( val.canConvert< QgsReferencedGeometry >() )
1488 {
1489 QgsReferencedGeometry rg = val.value<QgsReferencedGeometry>();
1490 if ( crs.isValid() && rg.crs().isValid() && crs != rg.crs() )
1491 {
1492 QgsCoordinateTransform ct( rg.crs(), crs, context.project() );
1493 try
1494 {
1495 rg.transform( ct );
1496 }
1497 catch ( QgsCsException & )
1498 {
1499 QgsMessageLog::logMessage( QObject::tr( "Error transforming geometry" ) );
1500 }
1501 }
1502 return rg;
1503 }
1504
1505 QString valueAsString = parameterAsString( definition, value, context );
1506 if ( valueAsString.isEmpty() )
1507 valueAsString = definition->defaultValue().toString();
1508
1509 if ( valueAsString.isEmpty() )
1510 return QgsGeometry();
1511
1512 QRegularExpression rx( QStringLiteral( "^\\s*(?:CRS=(.*);)?(.*?)$" ) );
1513
1514 QRegularExpressionMatch match = rx.match( valueAsString );
1515 if ( match.hasMatch() )
1516 {
1517 QgsGeometry g = QgsGeometry::fromWkt( match.captured( 2 ) );
1518 if ( !g.isNull() )
1519 {
1520 QgsCoordinateReferenceSystem geomCrs( match.captured( 1 ) );
1521 if ( crs.isValid() && geomCrs.isValid() && crs != geomCrs )
1522 {
1523 QgsCoordinateTransform ct( geomCrs, crs, context.project() );
1524 try
1525 {
1526 g.transform( ct );
1527 }
1528 catch ( QgsCsException & )
1529 {
1530 QgsMessageLog::logMessage( QObject::tr( "Error transforming geometry" ) );
1531 }
1532 }
1533 return g;
1534 }
1535 }
1536
1537 return QgsGeometry();
1538 }
1539
1540
parameterAsGeometryCrs(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1541 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsGeometryCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1542 {
1543 QVariant val = parameters.value( definition->name() );
1544 return parameterAsGeometryCrs( definition, val, context );
1545 }
1546
parameterAsGeometryCrs(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1547 QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsGeometryCrs( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1548 {
1549 if ( value.canConvert< QgsReferencedGeometry >() )
1550 {
1551 QgsReferencedGeometry rg = value.value<QgsReferencedGeometry>();
1552 if ( rg.crs().isValid() )
1553 {
1554 return rg.crs();
1555 }
1556 }
1557
1558 if ( value.canConvert< QgsReferencedPointXY >() )
1559 {
1560 QgsReferencedPointXY rp = value.value<QgsReferencedPointXY>();
1561 if ( rp.crs().isValid() )
1562 {
1563 return rp.crs();
1564 }
1565 }
1566
1567 if ( value.canConvert< QgsReferencedRectangle >() )
1568 {
1569 QgsReferencedRectangle rr = value.value<QgsReferencedRectangle>();
1570 if ( rr.crs().isValid() )
1571 {
1572 return rr.crs();
1573 }
1574 }
1575
1576 // Match against EWKT
1577 QRegularExpression rx( QStringLiteral( "^\\s*(?:CRS=(.*);)?(.*?)$" ) );
1578
1579 QString valueAsString = parameterAsString( definition, value, context );
1580 QRegularExpressionMatch match = rx.match( valueAsString );
1581 if ( match.hasMatch() )
1582 {
1583 QgsCoordinateReferenceSystem crs( match.captured( 1 ) );
1584 if ( crs.isValid() )
1585 return crs;
1586 }
1587
1588 if ( auto *lProject = context.project() )
1589 return lProject->crs();
1590 else
1591 return QgsCoordinateReferenceSystem();
1592 }
1593
1594
1595
1596
parameterAsFile(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1597 QString QgsProcessingParameters::parameterAsFile( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1598 {
1599 if ( !definition )
1600 return QString();
1601
1602 QString fileText = parameterAsString( definition, parameters, context );
1603 if ( fileText.isEmpty() )
1604 fileText = definition->defaultValue().toString();
1605 return fileText;
1606 }
1607
parameterAsFile(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1608 QString QgsProcessingParameters::parameterAsFile( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1609 {
1610 if ( !definition )
1611 return QString();
1612
1613 QString fileText = parameterAsString( definition, value, context );
1614 if ( fileText.isEmpty() )
1615 fileText = definition->defaultValue().toString();
1616 return fileText;
1617 }
1618
parameterAsMatrix(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1619 QVariantList QgsProcessingParameters::parameterAsMatrix( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1620 {
1621 if ( !definition )
1622 return QVariantList();
1623
1624 return parameterAsMatrix( definition, parameters.value( definition->name() ), context );
1625 }
1626
parameterAsMatrix(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1627 QVariantList QgsProcessingParameters::parameterAsMatrix( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1628 {
1629 if ( !definition )
1630 return QVariantList();
1631
1632 QString resultString;
1633 QVariant val = value;
1634 if ( val.canConvert<QgsProperty>() )
1635 resultString = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
1636 else if ( val.type() == QVariant::List )
1637 return val.toList();
1638 else
1639 resultString = val.toString();
1640
1641 if ( resultString.isEmpty() )
1642 {
1643 // check default
1644 if ( definition->defaultValue().type() == QVariant::List )
1645 return definition->defaultValue().toList();
1646 else
1647 resultString = definition->defaultValue().toString();
1648 }
1649
1650 QVariantList result;
1651 const auto constSplit = resultString.split( ',' );
1652 bool ok;
1653 double number;
1654 for ( const QString &s : constSplit )
1655 {
1656 number = s.toDouble( &ok );
1657 result << ( ok ? QVariant( number ) : s );
1658 }
1659
1660 return result;
1661 }
1662
parameterAsLayerList(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1663 QList<QgsMapLayer *> QgsProcessingParameters::parameterAsLayerList( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1664 {
1665 if ( !definition )
1666 return QList<QgsMapLayer *>();
1667
1668 return parameterAsLayerList( definition, parameters.value( definition->name() ), context );
1669 }
1670
parameterAsLayerList(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1671 QList<QgsMapLayer *> QgsProcessingParameters::parameterAsLayerList( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1672 {
1673 if ( !definition )
1674 return QList<QgsMapLayer *>();
1675
1676 QVariant val = value;
1677 if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( val ) ) )
1678 {
1679 return QList<QgsMapLayer *>() << layer;
1680 }
1681
1682 QList<QgsMapLayer *> layers;
1683
1684 std::function< void( const QVariant &var ) > processVariant;
1685 processVariant = [ &layers, &context, &definition, &processVariant ]( const QVariant & var )
1686 {
1687 if ( var.type() == QVariant::List )
1688 {
1689 const auto constToList = var.toList();
1690 for ( const QVariant &listVar : constToList )
1691 {
1692 processVariant( listVar );
1693 }
1694 }
1695 else if ( var.type() == QVariant::StringList )
1696 {
1697 const auto constToStringList = var.toStringList();
1698 for ( const QString &s : constToStringList )
1699 {
1700 processVariant( s );
1701 }
1702 }
1703 else if ( var.canConvert<QgsProperty>() )
1704 processVariant( var.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() ) );
1705 else if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
1706 {
1707 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
1708 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
1709 QVariant sink = fromVar.sink;
1710 if ( sink.canConvert<QgsProperty>() )
1711 {
1712 processVariant( sink.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() ) );
1713 }
1714 }
1715 else if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( var ) ) )
1716 {
1717 layers << layer;
1718 }
1719 else
1720 {
1721 QgsMapLayer *alayer = QgsProcessingUtils::mapLayerFromString( var.toString(), context );
1722 if ( alayer )
1723 layers << alayer;
1724 }
1725 };
1726
1727 processVariant( val );
1728
1729 if ( layers.isEmpty() )
1730 {
1731 // check default
1732 if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( definition->defaultValue() ) ) )
1733 {
1734 layers << layer;
1735 }
1736 else if ( definition->defaultValue().type() == QVariant::List )
1737 {
1738 const auto constToList = definition->defaultValue().toList();
1739 for ( const QVariant &var : constToList )
1740 {
1741 if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( var ) ) )
1742 {
1743 layers << layer;
1744 }
1745 else
1746 {
1747 processVariant( var );
1748 }
1749 }
1750 }
1751 else
1752 processVariant( definition->defaultValue() );
1753 }
1754
1755 return layers;
1756 }
1757
parameterAsFileList(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1758 QStringList QgsProcessingParameters::parameterAsFileList( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1759 {
1760 if ( !definition )
1761 return QStringList();
1762
1763 QVariant val = value;
1764
1765 QStringList files;
1766
1767 std::function< void( const QVariant &var ) > processVariant;
1768 processVariant = [ &files, &context, &definition, &processVariant ]( const QVariant & var )
1769 {
1770 if ( var.type() == QVariant::List )
1771 {
1772 const auto constToList = var.toList();
1773 for ( const QVariant &listVar : constToList )
1774 {
1775 processVariant( listVar );
1776 }
1777 }
1778 else if ( var.type() == QVariant::StringList )
1779 {
1780 const auto constToStringList = var.toStringList();
1781 for ( const QString &s : constToStringList )
1782 {
1783 processVariant( s );
1784 }
1785 }
1786 else if ( var.canConvert<QgsProperty>() )
1787 processVariant( var.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() ) );
1788 else
1789 {
1790 files << var.toString();
1791 }
1792 };
1793
1794 processVariant( val );
1795
1796 if ( files.isEmpty() )
1797 {
1798 processVariant( definition->defaultValue() );
1799 }
1800
1801 return files;
1802 }
1803
parameterAsFileList(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1804 QStringList QgsProcessingParameters::parameterAsFileList( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1805 {
1806 if ( !definition )
1807 return QStringList();
1808
1809 return parameterAsFileList( definition, parameters.value( definition->name() ), context );
1810 }
1811
parameterAsRange(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1812 QList<double> QgsProcessingParameters::parameterAsRange( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1813 {
1814 if ( !definition )
1815 return QList<double>();
1816
1817 return parameterAsRange( definition, parameters.value( definition->name() ), context );
1818 }
1819
parameterAsRange(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1820 QList<double> QgsProcessingParameters::parameterAsRange( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1821 {
1822 if ( !definition )
1823 return QList<double>();
1824
1825 QStringList resultStringList;
1826 QVariant val = value;
1827
1828 if ( val.canConvert<QgsProperty>() )
1829 resultStringList << val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
1830 else if ( val.type() == QVariant::List )
1831 {
1832 const auto constToList = val.toList();
1833 for ( const QVariant &var : constToList )
1834 resultStringList << var.toString();
1835 }
1836 else
1837 resultStringList << val.toString();
1838
1839 if ( ( resultStringList.isEmpty() || ( resultStringList.size() == 1 && resultStringList.at( 0 ).isEmpty() ) ) )
1840 {
1841 resultStringList.clear();
1842 // check default
1843 if ( definition->defaultValue().type() == QVariant::List )
1844 {
1845 const auto constToList = definition->defaultValue().toList();
1846 for ( const QVariant &var : constToList )
1847 resultStringList << var.toString();
1848 }
1849 else
1850 resultStringList << definition->defaultValue().toString();
1851 }
1852
1853 if ( resultStringList.size() == 1 )
1854 {
1855 resultStringList = resultStringList.at( 0 ).split( ',' );
1856 }
1857
1858 if ( resultStringList.size() < 2 )
1859 return QList< double >() << std::numeric_limits<double>::quiet_NaN() << std::numeric_limits<double>::quiet_NaN() ;
1860
1861 QList< double > result;
1862 bool ok = false;
1863 double n = resultStringList.at( 0 ).toDouble( &ok );
1864 if ( ok )
1865 result << n;
1866 else
1867 result << std::numeric_limits<double>::quiet_NaN() ;
1868 ok = false;
1869 n = resultStringList.at( 1 ).toDouble( &ok );
1870 if ( ok )
1871 result << n;
1872 else
1873 result << std::numeric_limits<double>::quiet_NaN() ;
1874
1875 return result;
1876 }
1877
parameterAsFields(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1878 QStringList QgsProcessingParameters::parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1879 {
1880 if ( !definition )
1881 return QStringList();
1882
1883 QStringList resultStringList;
1884 return parameterAsFields( definition, parameters.value( definition->name() ), context );
1885 }
1886
parameterAsFields(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1887 QStringList QgsProcessingParameters::parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1888 {
1889 if ( !definition )
1890 return QStringList();
1891
1892 QStringList resultStringList;
1893 QVariant val = value;
1894 if ( val.isValid() )
1895 {
1896 if ( val.canConvert<QgsProperty>() )
1897 resultStringList << val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
1898 else if ( val.type() == QVariant::List )
1899 {
1900 const auto constToList = val.toList();
1901 for ( const QVariant &var : constToList )
1902 resultStringList << var.toString();
1903 }
1904 else if ( val.type() == QVariant::StringList )
1905 {
1906 resultStringList = val.toStringList();
1907 }
1908 else
1909 resultStringList.append( val.toString().split( ';' ) );
1910 }
1911
1912 if ( ( resultStringList.isEmpty() || resultStringList.at( 0 ).isEmpty() ) )
1913 {
1914 resultStringList.clear();
1915 // check default
1916 if ( definition->defaultValue().isValid() )
1917 {
1918 if ( definition->defaultValue().type() == QVariant::List )
1919 {
1920 const auto constToList = definition->defaultValue().toList();
1921 for ( const QVariant &var : constToList )
1922 resultStringList << var.toString();
1923 }
1924 else if ( definition->defaultValue().type() == QVariant::StringList )
1925 {
1926 resultStringList = definition->defaultValue().toStringList();
1927 }
1928 else
1929 resultStringList.append( definition->defaultValue().toString().split( ';' ) );
1930 }
1931 }
1932
1933 return resultStringList;
1934 }
1935
parameterAsLayout(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1936 QgsPrintLayout *QgsProcessingParameters::parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1937 {
1938 if ( !definition )
1939 return nullptr;
1940
1941 return parameterAsLayout( definition, parameters.value( definition->name() ), context );
1942 }
1943
parameterAsLayout(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1944 QgsPrintLayout *QgsProcessingParameters::parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1945 {
1946 const QString layoutName = parameterAsString( definition, value, context );
1947 if ( layoutName.isEmpty() )
1948 return nullptr;
1949
1950 if ( !context.project() )
1951 return nullptr;
1952
1953 QgsMasterLayoutInterface *l = context.project()->layoutManager()->layoutByName( layoutName );
1954 if ( l && l->layoutType() == QgsMasterLayoutInterface::PrintLayout )
1955 return static_cast< QgsPrintLayout * >( l );
1956 else
1957 return nullptr;
1958 }
1959
parameterAsLayoutItem(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context,QgsPrintLayout * layout)1960 QgsLayoutItem *QgsProcessingParameters::parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, QgsPrintLayout *layout )
1961 {
1962 if ( !definition )
1963 return nullptr;
1964
1965 return parameterAsLayoutItem( definition, parameters.value( definition->name() ), context, layout );
1966 }
1967
parameterAsLayoutItem(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context,QgsPrintLayout * layout)1968 QgsLayoutItem *QgsProcessingParameters::parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, QgsPrintLayout *layout )
1969 {
1970 if ( !layout )
1971 return nullptr;
1972
1973 const QString id = parameterAsString( definition, value, context );
1974 if ( id.isEmpty() )
1975 return nullptr;
1976
1977 // prefer matching by uuid, since it's guaranteed to be unique.
1978 if ( QgsLayoutItem *item = layout->itemByUuid( id ) )
1979 return item;
1980 else if ( QgsLayoutItem *item = layout->itemById( id ) )
1981 return item;
1982 else
1983 return nullptr;
1984 }
1985
parameterAsColor(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,QgsProcessingContext & context)1986 QColor QgsProcessingParameters::parameterAsColor( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context )
1987 {
1988 if ( !definition )
1989 return QColor();
1990
1991 return parameterAsColor( definition, parameters.value( definition->name() ), context );
1992 }
1993
parameterAsColor(const QgsProcessingParameterDefinition * definition,const QVariant & value,QgsProcessingContext & context)1994 QColor QgsProcessingParameters::parameterAsColor( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
1995 {
1996 if ( !definition )
1997 return QColor();
1998
1999 QVariant val = value;
2000 if ( val.canConvert<QgsProperty>() )
2001 {
2002 val = val.value< QgsProperty >().value( context.expressionContext(), definition->defaultValue() );
2003 }
2004 if ( val.type() == QVariant::Color )
2005 {
2006 QColor c = val.value< QColor >();
2007 if ( const QgsProcessingParameterColor *colorParam = dynamic_cast< const QgsProcessingParameterColor * >( definition ) )
2008 if ( !colorParam->opacityEnabled() )
2009 c.setAlpha( 255 );
2010 return c;
2011 }
2012
2013 QString colorText = parameterAsString( definition, value, context );
2014 if ( colorText.isEmpty() && !( definition->flags() & QgsProcessingParameterDefinition::FlagOptional ) )
2015 {
2016 if ( definition->defaultValue().type() == QVariant::Color )
2017 return definition->defaultValue().value< QColor >();
2018 else
2019 colorText = definition->defaultValue().toString();
2020 }
2021
2022 if ( colorText.isEmpty() )
2023 return QColor();
2024
2025 bool containsAlpha = false;
2026 QColor c = QgsSymbolLayerUtils::parseColorWithAlpha( colorText, containsAlpha );
2027 if ( const QgsProcessingParameterColor *colorParam = dynamic_cast< const QgsProcessingParameterColor * >( definition ) )
2028 if ( c.isValid() && !colorParam->opacityEnabled() )
2029 c.setAlpha( 255 );
2030 return c;
2031 }
2032
parameterAsConnectionName(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)2033 QString QgsProcessingParameters::parameterAsConnectionName( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
2034 {
2035 if ( !definition )
2036 return QString();
2037
2038 return parameterAsConnectionName( definition, parameters.value( definition->name() ), context );
2039 }
2040
parameterAsConnectionName(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)2041 QString QgsProcessingParameters::parameterAsConnectionName( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
2042 {
2043 // for now it's just treated identical to strings, but in future we may want flexibility to amend this
2044 // (hence the new method)
2045 return parameterAsString( definition, value, context );
2046 }
2047
parameterAsSchema(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)2048 QString QgsProcessingParameters::parameterAsSchema( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
2049 {
2050 if ( !definition )
2051 return QString();
2052
2053 return parameterAsSchema( definition, parameters.value( definition->name() ), context );
2054 }
2055
parameterAsSchema(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)2056 QString QgsProcessingParameters::parameterAsSchema( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
2057 {
2058 // for now it's just treated identical to strings, but in future we may want flexibility to amend this (e.g. if we want to embed connection details into the schema
2059 // parameter values, such as via a delimiter separated string)
2060 return parameterAsString( definition, value, context );
2061 }
2062
parameterAsDatabaseTableName(const QgsProcessingParameterDefinition * definition,const QVariantMap & parameters,const QgsProcessingContext & context)2063 QString QgsProcessingParameters::parameterAsDatabaseTableName( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, const QgsProcessingContext &context )
2064 {
2065 if ( !definition )
2066 return QString();
2067
2068 return parameterAsDatabaseTableName( definition, parameters.value( definition->name() ), context );
2069 }
2070
parameterAsDatabaseTableName(const QgsProcessingParameterDefinition * definition,const QVariant & value,const QgsProcessingContext & context)2071 QString QgsProcessingParameters::parameterAsDatabaseTableName( const QgsProcessingParameterDefinition *definition, const QVariant &value, const QgsProcessingContext &context )
2072 {
2073 // for now it's just treated identical to strings, but in future we may want flexibility to amend this (e.g. if we want to embed connection details into the table name
2074 // parameter values, such as via a delimiter separated string)
2075 return parameterAsString( definition, value, context );
2076 }
2077
parameterFromVariantMap(const QVariantMap & map)2078 QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantMap( const QVariantMap &map )
2079 {
2080 QString type = map.value( QStringLiteral( "parameter_type" ) ).toString();
2081 QString name = map.value( QStringLiteral( "name" ) ).toString();
2082 std::unique_ptr< QgsProcessingParameterDefinition > def;
2083
2084 // probably all these hardcoded values aren't required anymore, and we could
2085 // always resort to the registry lookup...
2086 // TODO: confirm
2087 if ( type == QgsProcessingParameterBoolean::typeName() )
2088 def.reset( new QgsProcessingParameterBoolean( name ) );
2089 else if ( type == QgsProcessingParameterCrs::typeName() )
2090 def.reset( new QgsProcessingParameterCrs( name ) );
2091 else if ( type == QgsProcessingParameterMapLayer::typeName() )
2092 def.reset( new QgsProcessingParameterMapLayer( name ) );
2093 else if ( type == QgsProcessingParameterExtent::typeName() )
2094 def.reset( new QgsProcessingParameterExtent( name ) );
2095 else if ( type == QgsProcessingParameterPoint::typeName() )
2096 def.reset( new QgsProcessingParameterPoint( name ) );
2097 else if ( type == QgsProcessingParameterFile::typeName() )
2098 def.reset( new QgsProcessingParameterFile( name ) );
2099 else if ( type == QgsProcessingParameterMatrix::typeName() )
2100 def.reset( new QgsProcessingParameterMatrix( name ) );
2101 else if ( type == QgsProcessingParameterMultipleLayers::typeName() )
2102 def.reset( new QgsProcessingParameterMultipleLayers( name ) );
2103 else if ( type == QgsProcessingParameterNumber::typeName() )
2104 def.reset( new QgsProcessingParameterNumber( name ) );
2105 else if ( type == QgsProcessingParameterRange::typeName() )
2106 def.reset( new QgsProcessingParameterRange( name ) );
2107 else if ( type == QgsProcessingParameterRasterLayer::typeName() )
2108 def.reset( new QgsProcessingParameterRasterLayer( name ) );
2109 else if ( type == QgsProcessingParameterEnum::typeName() )
2110 def.reset( new QgsProcessingParameterEnum( name ) );
2111 else if ( type == QgsProcessingParameterString::typeName() )
2112 def.reset( new QgsProcessingParameterString( name ) );
2113 else if ( type == QgsProcessingParameterAuthConfig::typeName() )
2114 def.reset( new QgsProcessingParameterAuthConfig( name ) );
2115 else if ( type == QgsProcessingParameterExpression::typeName() )
2116 def.reset( new QgsProcessingParameterExpression( name ) );
2117 else if ( type == QgsProcessingParameterVectorLayer::typeName() )
2118 def.reset( new QgsProcessingParameterVectorLayer( name ) );
2119 else if ( type == QgsProcessingParameterField::typeName() )
2120 def.reset( new QgsProcessingParameterField( name ) );
2121 else if ( type == QgsProcessingParameterFeatureSource::typeName() )
2122 def.reset( new QgsProcessingParameterFeatureSource( name ) );
2123 else if ( type == QgsProcessingParameterFeatureSink::typeName() )
2124 def.reset( new QgsProcessingParameterFeatureSink( name ) );
2125 else if ( type == QgsProcessingParameterVectorDestination::typeName() )
2126 def.reset( new QgsProcessingParameterVectorDestination( name ) );
2127 else if ( type == QgsProcessingParameterRasterDestination::typeName() )
2128 def.reset( new QgsProcessingParameterRasterDestination( name ) );
2129 else if ( type == QgsProcessingParameterFileDestination::typeName() )
2130 def.reset( new QgsProcessingParameterFileDestination( name ) );
2131 else if ( type == QgsProcessingParameterFolderDestination::typeName() )
2132 def.reset( new QgsProcessingParameterFolderDestination( name ) );
2133 else if ( type == QgsProcessingParameterBand::typeName() )
2134 def.reset( new QgsProcessingParameterBand( name ) );
2135 else if ( type == QgsProcessingParameterMeshLayer::typeName() )
2136 def.reset( new QgsProcessingParameterMeshLayer( name ) );
2137 else if ( type == QgsProcessingParameterLayout::typeName() )
2138 def.reset( new QgsProcessingParameterLayout( name ) );
2139 else if ( type == QgsProcessingParameterLayoutItem::typeName() )
2140 def.reset( new QgsProcessingParameterLayoutItem( name ) );
2141 else if ( type == QgsProcessingParameterColor::typeName() )
2142 def.reset( new QgsProcessingParameterColor( name ) );
2143 else if ( type == QgsProcessingParameterCoordinateOperation::typeName() )
2144 def.reset( new QgsProcessingParameterCoordinateOperation( name ) );
2145 else
2146 {
2147 QgsProcessingParameterType *paramType = QgsApplication::instance()->processingRegistry()->parameterType( type );
2148 if ( paramType )
2149 def.reset( paramType->create( name ) );
2150 }
2151
2152 if ( !def )
2153 return nullptr;
2154
2155 def->fromVariantMap( map );
2156 return def.release();
2157 }
2158
descriptionFromName(const QString & name)2159 QString QgsProcessingParameters::descriptionFromName( const QString &name )
2160 {
2161 QString desc = name;
2162 desc.replace( '_', ' ' );
2163 return desc;
2164 }
2165
parameterFromScriptCode(const QString & code)2166 QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromScriptCode( const QString &code )
2167 {
2168 bool isOptional = false;
2169 QString name;
2170 QString definition;
2171 QString type;
2172 if ( !parseScriptCodeParameterOptions( code, isOptional, name, type, definition ) )
2173 return nullptr;
2174
2175 QString description = descriptionFromName( name );
2176
2177 if ( type == QLatin1String( "boolean" ) )
2178 return QgsProcessingParameterBoolean::fromScriptCode( name, description, isOptional, definition );
2179 else if ( type == QLatin1String( "crs" ) )
2180 return QgsProcessingParameterCrs::fromScriptCode( name, description, isOptional, definition );
2181 else if ( type == QLatin1String( "layer" ) )
2182 return QgsProcessingParameterMapLayer::fromScriptCode( name, description, isOptional, definition );
2183 else if ( type == QLatin1String( "extent" ) )
2184 return QgsProcessingParameterExtent::fromScriptCode( name, description, isOptional, definition );
2185 else if ( type == QLatin1String( "point" ) )
2186 return QgsProcessingParameterPoint::fromScriptCode( name, description, isOptional, definition );
2187 else if ( type == QLatin1String( "geometry" ) )
2188 return QgsProcessingParameterGeometry::fromScriptCode( name, description, isOptional, definition );
2189 else if ( type == QLatin1String( "file" ) )
2190 return QgsProcessingParameterFile::fromScriptCode( name, description, isOptional, definition, QgsProcessingParameterFile::File );
2191 else if ( type == QLatin1String( "folder" ) )
2192 return QgsProcessingParameterFile::fromScriptCode( name, description, isOptional, definition, QgsProcessingParameterFile::Folder );
2193 else if ( type == QLatin1String( "matrix" ) )
2194 return QgsProcessingParameterMatrix::fromScriptCode( name, description, isOptional, definition );
2195 else if ( type == QLatin1String( "multiple" ) )
2196 return QgsProcessingParameterMultipleLayers::fromScriptCode( name, description, isOptional, definition );
2197 else if ( type == QLatin1String( "number" ) )
2198 return QgsProcessingParameterNumber::fromScriptCode( name, description, isOptional, definition );
2199 else if ( type == QLatin1String( "distance" ) )
2200 return QgsProcessingParameterDistance::fromScriptCode( name, description, isOptional, definition );
2201 else if ( type == QLatin1String( "scale" ) )
2202 return QgsProcessingParameterScale::fromScriptCode( name, description, isOptional, definition );
2203 else if ( type == QLatin1String( "range" ) )
2204 return QgsProcessingParameterRange::fromScriptCode( name, description, isOptional, definition );
2205 else if ( type == QLatin1String( "raster" ) )
2206 return QgsProcessingParameterRasterLayer::fromScriptCode( name, description, isOptional, definition );
2207 else if ( type == QLatin1String( "enum" ) )
2208 return QgsProcessingParameterEnum::fromScriptCode( name, description, isOptional, definition );
2209 else if ( type == QLatin1String( "string" ) )
2210 return QgsProcessingParameterString::fromScriptCode( name, description, isOptional, definition );
2211 else if ( type == QLatin1String( "authcfg" ) )
2212 return QgsProcessingParameterAuthConfig::fromScriptCode( name, description, isOptional, definition );
2213 else if ( type == QLatin1String( "expression" ) )
2214 return QgsProcessingParameterExpression::fromScriptCode( name, description, isOptional, definition );
2215 else if ( type == QLatin1String( "field" ) )
2216 return QgsProcessingParameterField::fromScriptCode( name, description, isOptional, definition );
2217 else if ( type == QLatin1String( "vector" ) )
2218 return QgsProcessingParameterVectorLayer::fromScriptCode( name, description, isOptional, definition );
2219 else if ( type == QLatin1String( "source" ) )
2220 return QgsProcessingParameterFeatureSource::fromScriptCode( name, description, isOptional, definition );
2221 else if ( type == QLatin1String( "sink" ) )
2222 return QgsProcessingParameterFeatureSink::fromScriptCode( name, description, isOptional, definition );
2223 else if ( type == QLatin1String( "vectordestination" ) )
2224 return QgsProcessingParameterVectorDestination::fromScriptCode( name, description, isOptional, definition );
2225 else if ( type == QLatin1String( "rasterdestination" ) )
2226 return QgsProcessingParameterRasterDestination::fromScriptCode( name, description, isOptional, definition );
2227 else if ( type == QLatin1String( "filedestination" ) )
2228 return QgsProcessingParameterFileDestination::fromScriptCode( name, description, isOptional, definition );
2229 else if ( type == QLatin1String( "folderdestination" ) )
2230 return QgsProcessingParameterFolderDestination::fromScriptCode( name, description, isOptional, definition );
2231 else if ( type == QLatin1String( "band" ) )
2232 return QgsProcessingParameterBand::fromScriptCode( name, description, isOptional, definition );
2233 else if ( type == QLatin1String( "mesh" ) )
2234 return QgsProcessingParameterMeshLayer::fromScriptCode( name, description, isOptional, definition );
2235 else if ( type == QLatin1String( "layout" ) )
2236 return QgsProcessingParameterLayout::fromScriptCode( name, description, isOptional, definition );
2237 else if ( type == QLatin1String( "layoutitem" ) )
2238 return QgsProcessingParameterLayoutItem::fromScriptCode( name, description, isOptional, definition );
2239 else if ( type == QLatin1String( "color" ) )
2240 return QgsProcessingParameterColor::fromScriptCode( name, description, isOptional, definition );
2241 else if ( type == QLatin1String( "coordinateoperation" ) )
2242 return QgsProcessingParameterCoordinateOperation::fromScriptCode( name, description, isOptional, definition );
2243 else if ( type == QLatin1String( "maptheme" ) )
2244 return QgsProcessingParameterMapTheme::fromScriptCode( name, description, isOptional, definition );
2245 else if ( type == QLatin1String( "datetime" ) )
2246 return QgsProcessingParameterDateTime::fromScriptCode( name, description, isOptional, definition );
2247 else if ( type == QLatin1String( "providerconnection" ) )
2248 return QgsProcessingParameterProviderConnection::fromScriptCode( name, description, isOptional, definition );
2249 else if ( type == QLatin1String( "databaseschema" ) )
2250 return QgsProcessingParameterDatabaseSchema::fromScriptCode( name, description, isOptional, definition );
2251 else if ( type == QLatin1String( "databasetable" ) )
2252 return QgsProcessingParameterDatabaseTable::fromScriptCode( name, description, isOptional, definition );
2253
2254 return nullptr;
2255 }
2256
parseScriptCodeParameterOptions(const QString & code,bool & isOptional,QString & name,QString & type,QString & definition)2257 bool QgsProcessingParameters::parseScriptCodeParameterOptions( const QString &code, bool &isOptional, QString &name, QString &type, QString &definition )
2258 {
2259 QRegularExpression re( QStringLiteral( "(?:#*)(.*?)=\\s*(.*)" ) );
2260 QRegularExpressionMatch m = re.match( code );
2261 if ( !m.hasMatch() )
2262 return false;
2263
2264 name = m.captured( 1 );
2265 QString tokens = m.captured( 2 );
2266 if ( tokens.startsWith( QLatin1String( "optional" ), Qt::CaseInsensitive ) )
2267 {
2268 isOptional = true;
2269 tokens.remove( 0, 8 ); // length "optional" = 8
2270 }
2271 else
2272 {
2273 isOptional = false;
2274 }
2275
2276 tokens = tokens.trimmed();
2277
2278 QRegularExpression re2( QStringLiteral( "(.*?)\\s+(.*)" ) );
2279 m = re2.match( tokens );
2280 if ( !m.hasMatch() )
2281 {
2282 type = tokens.toLower().trimmed();
2283 definition.clear();
2284 }
2285 else
2286 {
2287 type = m.captured( 1 ).toLower().trimmed();
2288 definition = m.captured( 2 );
2289 }
2290 return true;
2291 }
2292
2293 //
2294 // QgsProcessingParameterDefinition
2295 //
2296
QgsProcessingParameterDefinition(const QString & name,const QString & description,const QVariant & defaultValue,bool optional,const QString & help)2297 QgsProcessingParameterDefinition::QgsProcessingParameterDefinition( const QString &name, const QString &description, const QVariant &defaultValue, bool optional, const QString &help )
2298 : mName( name )
2299 , mDescription( description )
2300 , mHelp( help )
2301 , mDefault( defaultValue )
2302 , mFlags( optional ? FlagOptional : 0 )
2303 {}
2304
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const2305 bool QgsProcessingParameterDefinition::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
2306 {
2307 if ( !input.isValid() && !mDefault.isValid() )
2308 return mFlags & FlagOptional;
2309
2310 if ( ( input.type() == QVariant::String && input.toString().isEmpty() )
2311 || ( !input.isValid() && mDefault.type() == QVariant::String && mDefault.toString().isEmpty() ) )
2312 return mFlags & FlagOptional;
2313
2314 return true;
2315 }
2316
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const2317 QString QgsProcessingParameterDefinition::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
2318 {
2319 if ( !value.isValid() )
2320 return QStringLiteral( "None" );
2321
2322 if ( value.canConvert<QgsProperty>() )
2323 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
2324
2325 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
2326 }
2327
asScriptCode() const2328 QString QgsProcessingParameterDefinition::asScriptCode() const
2329 {
2330 QString code = QStringLiteral( "##%1=" ).arg( mName );
2331 if ( mFlags & FlagOptional )
2332 code += QLatin1String( "optional " );
2333 code += type() + ' ';
2334 code += mDefault.toString();
2335 return code.trimmed();
2336 }
2337
asPythonString(const QgsProcessing::PythonOutputType outputType) const2338 QString QgsProcessingParameterDefinition::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
2339 {
2340 // base class method is probably not much use
2341 if ( QgsProcessingParameterType *t = QgsApplication::processingRegistry()->parameterType( type() ) )
2342 {
2343 switch ( outputType )
2344 {
2345 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
2346 {
2347 QString code = t->className() + QStringLiteral( "('%1', '%2'" ).arg( name(), description() );
2348 if ( mFlags & FlagOptional )
2349 code += QLatin1String( ", optional=True" );
2350
2351 QgsProcessingContext c;
2352 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
2353 return code;
2354 }
2355 }
2356 }
2357
2358 // oh well, we tried
2359 return QString();
2360 }
2361
toVariantMap() const2362 QVariantMap QgsProcessingParameterDefinition::toVariantMap() const
2363 {
2364 QVariantMap map;
2365 map.insert( QStringLiteral( "parameter_type" ), type() );
2366 map.insert( QStringLiteral( "name" ), mName );
2367 map.insert( QStringLiteral( "description" ), mDescription );
2368 map.insert( QStringLiteral( "help" ), mHelp );
2369 map.insert( QStringLiteral( "default" ), mDefault );
2370 map.insert( QStringLiteral( "defaultGui" ), mGuiDefault );
2371 map.insert( QStringLiteral( "flags" ), static_cast< int >( mFlags ) );
2372 map.insert( QStringLiteral( "metadata" ), mMetadata );
2373 return map;
2374 }
2375
fromVariantMap(const QVariantMap & map)2376 bool QgsProcessingParameterDefinition::fromVariantMap( const QVariantMap &map )
2377 {
2378 mName = map.value( QStringLiteral( "name" ) ).toString();
2379 mDescription = map.value( QStringLiteral( "description" ) ).toString();
2380 mHelp = map.value( QStringLiteral( "help" ) ).toString();
2381 mDefault = map.value( QStringLiteral( "default" ) );
2382 mGuiDefault = map.value( QStringLiteral( "defaultGui" ) );
2383 mFlags = static_cast< Flags >( map.value( QStringLiteral( "flags" ) ).toInt() );
2384 mMetadata = map.value( QStringLiteral( "metadata" ) ).toMap();
2385 return true;
2386 }
2387
algorithm() const2388 QgsProcessingAlgorithm *QgsProcessingParameterDefinition::algorithm() const
2389 {
2390 return mAlgorithm;
2391 }
2392
provider() const2393 QgsProcessingProvider *QgsProcessingParameterDefinition::provider() const
2394 {
2395 return mAlgorithm ? mAlgorithm->provider() : nullptr;
2396 }
2397
toolTip() const2398 QString QgsProcessingParameterDefinition::toolTip() const
2399 {
2400 QString text = QStringLiteral( "<p><b>%1</b></p>" ).arg( description() );
2401 if ( !help().isEmpty() )
2402 {
2403 text += QStringLiteral( "<p>%1</p>" ).arg( help() );
2404 }
2405 text += QStringLiteral( "<p>%1</p>" ).arg( QObject::tr( "Python identifier: ‘%1’" ).arg( QStringLiteral( "<i>%1</i>" ).arg( name() ) ) );
2406 return text;
2407 }
2408
QgsProcessingParameterBoolean(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)2409 QgsProcessingParameterBoolean::QgsProcessingParameterBoolean( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
2410 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
2411 {}
2412
clone() const2413 QgsProcessingParameterDefinition *QgsProcessingParameterBoolean::clone() const
2414 {
2415 return new QgsProcessingParameterBoolean( *this );
2416 }
2417
valueAsPythonString(const QVariant & val,QgsProcessingContext &) const2418 QString QgsProcessingParameterBoolean::valueAsPythonString( const QVariant &val, QgsProcessingContext & ) const
2419 {
2420 if ( !val.isValid() )
2421 return QStringLiteral( "None" );
2422
2423 if ( val.canConvert<QgsProperty>() )
2424 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );
2425 return val.toBool() ? QStringLiteral( "True" ) : QStringLiteral( "False" );
2426 }
2427
asScriptCode() const2428 QString QgsProcessingParameterBoolean::asScriptCode() const
2429 {
2430 QString code = QStringLiteral( "##%1=" ).arg( mName );
2431 if ( mFlags & FlagOptional )
2432 code += QLatin1String( "optional " );
2433 code += type() + ' ';
2434 code += mDefault.toBool() ? QStringLiteral( "true" ) : QStringLiteral( "false" );
2435 return code.trimmed();
2436 }
2437
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)2438 QgsProcessingParameterBoolean *QgsProcessingParameterBoolean::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
2439 {
2440 return new QgsProcessingParameterBoolean( name, description, definition.toLower().trimmed() != QStringLiteral( "false" ), isOptional );
2441 }
2442
QgsProcessingParameterCrs(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)2443 QgsProcessingParameterCrs::QgsProcessingParameterCrs( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
2444 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
2445 {
2446
2447 }
2448
clone() const2449 QgsProcessingParameterDefinition *QgsProcessingParameterCrs::clone() const
2450 {
2451 return new QgsProcessingParameterCrs( *this );
2452 }
2453
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const2454 bool QgsProcessingParameterCrs::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
2455 {
2456 if ( !input.isValid() )
2457 return mFlags & FlagOptional;
2458
2459 if ( input.canConvert<QgsCoordinateReferenceSystem>() )
2460 {
2461 return true;
2462 }
2463 else if ( input.canConvert<QgsProcessingFeatureSourceDefinition>() )
2464 {
2465 return true;
2466 }
2467 else if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
2468 {
2469 return true;
2470 }
2471
2472 if ( input.canConvert<QgsProperty>() )
2473 {
2474 return true;
2475 }
2476
2477 // direct map layer value
2478 if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( input ) ) )
2479 return true;
2480
2481 if ( input.type() != QVariant::String || input.toString().isEmpty() )
2482 return mFlags & FlagOptional;
2483
2484 return true;
2485 }
2486
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const2487 QString QgsProcessingParameterCrs::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
2488 {
2489 if ( !value.isValid() )
2490 return QStringLiteral( "None" );
2491
2492 if ( value.canConvert<QgsCoordinateReferenceSystem>() )
2493 {
2494 if ( !value.value< QgsCoordinateReferenceSystem >().isValid() )
2495 return QStringLiteral( "QgsCoordinateReferenceSystem()" );
2496 else
2497 return QStringLiteral( "QgsCoordinateReferenceSystem('%1')" ).arg( value.value< QgsCoordinateReferenceSystem >().authid() );
2498 }
2499
2500 if ( value.canConvert<QgsProperty>() )
2501 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
2502
2503 QVariantMap p;
2504 p.insert( name(), value );
2505 QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( this, p, context );
2506 if ( layer )
2507 return QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) );
2508
2509 return QgsProcessingParameterDefinition::valueAsPythonString( value, context );
2510 }
2511
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)2512 QgsProcessingParameterCrs *QgsProcessingParameterCrs::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
2513 {
2514 return new QgsProcessingParameterCrs( name, description, definition.compare( QLatin1String( "none" ), Qt::CaseInsensitive ) == 0 ? QVariant() : definition, isOptional );
2515 }
2516
QgsProcessingParameterMapLayer(const QString & name,const QString & description,const QVariant & defaultValue,bool optional,const QList<int> & types)2517 QgsProcessingParameterMapLayer::QgsProcessingParameterMapLayer( const QString &name, const QString &description, const QVariant &defaultValue, bool optional, const QList<int> &types )
2518 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
2519 , QgsProcessingParameterLimitedDataTypes( types )
2520 {
2521
2522 }
2523
clone() const2524 QgsProcessingParameterDefinition *QgsProcessingParameterMapLayer::clone() const
2525 {
2526 return new QgsProcessingParameterMapLayer( *this );
2527 }
2528
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext * context) const2529 bool QgsProcessingParameterMapLayer::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context ) const
2530 {
2531 if ( !input.isValid() )
2532 return mFlags & FlagOptional;
2533
2534 if ( input.canConvert<QgsProperty>() )
2535 {
2536 return true;
2537 }
2538
2539 if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( input ) ) )
2540 {
2541 return true;
2542 }
2543
2544 if ( input.type() != QVariant::String || input.toString().isEmpty() )
2545 return mFlags & FlagOptional;
2546
2547 if ( !context )
2548 {
2549 // that's as far as we can get without a context
2550 return true;
2551 }
2552
2553 // try to load as layer
2554 if ( QgsProcessingUtils::mapLayerFromString( input.toString(), *context ) )
2555 return true;
2556
2557 return false;
2558 }
2559
valueAsPythonString(const QVariant & val,QgsProcessingContext & context) const2560 QString QgsProcessingParameterMapLayer::valueAsPythonString( const QVariant &val, QgsProcessingContext &context ) const
2561 {
2562 if ( !val.isValid() )
2563 return QStringLiteral( "None" );
2564
2565 if ( val.canConvert<QgsProperty>() )
2566 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );
2567
2568 QVariantMap p;
2569 p.insert( name(), val );
2570 QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( this, p, context );
2571 return layer ? QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) )
2572 : QgsProcessingUtils::stringToPythonLiteral( val.toString() );
2573 }
2574
createAllMapLayerFileFilter()2575 QString createAllMapLayerFileFilter()
2576 {
2577 QStringList vectors = QgsProviderRegistry::instance()->fileVectorFilters().split( QStringLiteral( ";;" ) );
2578 QStringList rasters = QgsProviderRegistry::instance()->fileRasterFilters().split( QStringLiteral( ";;" ) );
2579 for ( const QString &raster : rasters )
2580 {
2581 if ( !vectors.contains( raster ) )
2582 vectors << raster;
2583 }
2584 QStringList meshFilters = QgsProviderRegistry::instance()->fileMeshFilters().split( QStringLiteral( ";;" ) );
2585 for ( const QString &mesh : meshFilters )
2586 {
2587 if ( !vectors.contains( mesh ) )
2588 vectors << mesh;
2589 }
2590 vectors.removeAll( QObject::tr( "All files (*.*)" ) );
2591 std::sort( vectors.begin(), vectors.end() );
2592
2593 return QObject::tr( "All files (*.*)" ) + QStringLiteral( ";;" ) + vectors.join( QLatin1String( ";;" ) );
2594 }
2595
createFileFilter() const2596 QString QgsProcessingParameterMapLayer::createFileFilter() const
2597 {
2598 return createAllMapLayerFileFilter();
2599 }
2600
asScriptCode() const2601 QString QgsProcessingParameterMapLayer::asScriptCode() const
2602 {
2603 QString code = QStringLiteral( "##%1=" ).arg( mName );
2604 if ( mFlags & FlagOptional )
2605 code += QLatin1String( "optional " );
2606 code += QLatin1String( "layer " );
2607
2608 for ( int type : mDataTypes )
2609 {
2610 switch ( type )
2611 {
2612 case QgsProcessing::TypeVectorAnyGeometry:
2613 code += QLatin1String( "hasgeometry " );
2614 break;
2615
2616 case QgsProcessing::TypeVectorPoint:
2617 code += QLatin1String( "point " );
2618 break;
2619
2620 case QgsProcessing::TypeVectorLine:
2621 code += QLatin1String( "line " );
2622 break;
2623
2624 case QgsProcessing::TypeVectorPolygon:
2625 code += QLatin1String( "polygon " );
2626 break;
2627
2628 case QgsProcessing::TypeRaster:
2629 code += QLatin1String( "raster " );
2630 break;
2631
2632 case QgsProcessing::TypeMesh:
2633 code += QLatin1String( "mesh " );
2634 break;
2635 }
2636 }
2637
2638 code += mDefault.toString();
2639 return code.trimmed();
2640 }
2641
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)2642 QgsProcessingParameterMapLayer *QgsProcessingParameterMapLayer::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
2643 {
2644 QList< int > types;
2645 QString def = definition;
2646 while ( true )
2647 {
2648 if ( def.startsWith( QLatin1String( "hasgeometry" ), Qt::CaseInsensitive ) )
2649 {
2650 types << QgsProcessing::TypeVectorAnyGeometry;
2651 def = def.mid( 12 );
2652 continue;
2653 }
2654 else if ( def.startsWith( QLatin1String( "point" ), Qt::CaseInsensitive ) )
2655 {
2656 types << QgsProcessing::TypeVectorPoint;
2657 def = def.mid( 6 );
2658 continue;
2659 }
2660 else if ( def.startsWith( QLatin1String( "line" ), Qt::CaseInsensitive ) )
2661 {
2662 types << QgsProcessing::TypeVectorLine;
2663 def = def.mid( 5 );
2664 continue;
2665 }
2666 else if ( def.startsWith( QLatin1String( "polygon" ), Qt::CaseInsensitive ) )
2667 {
2668 types << QgsProcessing::TypeVectorPolygon;
2669 def = def.mid( 8 );
2670 continue;
2671 }
2672 else if ( def.startsWith( QLatin1String( "raster" ), Qt::CaseInsensitive ) )
2673 {
2674 types << QgsProcessing::TypeRaster;
2675 def = def.mid( 7 );
2676 continue;
2677 }
2678 else if ( def.startsWith( QLatin1String( "mesh" ), Qt::CaseInsensitive ) )
2679 {
2680 types << QgsProcessing::TypeMesh;
2681 def = def.mid( 5 );
2682 continue;
2683 }
2684 break;
2685 }
2686
2687 return new QgsProcessingParameterMapLayer( name, description, def, isOptional, types );
2688 }
2689
asPythonString(const QgsProcessing::PythonOutputType outputType) const2690 QString QgsProcessingParameterMapLayer::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
2691 {
2692 switch ( outputType )
2693 {
2694 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
2695 {
2696 QString code = QStringLiteral( "QgsProcessingParameterMapLayer('%1', '%2'" ).arg( name(), description() );
2697 if ( mFlags & FlagOptional )
2698 code += QLatin1String( ", optional=True" );
2699
2700 QgsProcessingContext c;
2701 code += QStringLiteral( ", defaultValue=%1" ).arg( valueAsPythonString( mDefault, c ) );
2702
2703 if ( !mDataTypes.empty() )
2704 {
2705 QStringList options;
2706 options.reserve( mDataTypes.size() );
2707 for ( int t : mDataTypes )
2708 options << QStringLiteral( "QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( static_cast< QgsProcessing::SourceType >( t ) ) );
2709 code += QStringLiteral( ", types=[%1])" ).arg( options.join( ',' ) );
2710 }
2711 else
2712 {
2713 code += QLatin1Char( ')' );
2714 }
2715
2716 return code;
2717 }
2718 }
2719 return QString();
2720 }
2721
toVariantMap() const2722 QVariantMap QgsProcessingParameterMapLayer::toVariantMap() const
2723 {
2724 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
2725 QVariantList types;
2726 for ( int type : mDataTypes )
2727 {
2728 types << type;
2729 }
2730 map.insert( QStringLiteral( "data_types" ), types );
2731 return map;
2732 }
2733
fromVariantMap(const QVariantMap & map)2734 bool QgsProcessingParameterMapLayer::fromVariantMap( const QVariantMap &map )
2735 {
2736 QgsProcessingParameterDefinition::fromVariantMap( map );
2737 mDataTypes.clear();
2738 const QVariantList values = map.value( QStringLiteral( "data_types" ) ).toList();
2739 for ( const QVariant &val : values )
2740 {
2741 mDataTypes << val.toInt();
2742 }
2743 return true;
2744 }
2745
QgsProcessingParameterExtent(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)2746 QgsProcessingParameterExtent::QgsProcessingParameterExtent( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
2747 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
2748 {
2749
2750 }
2751
clone() const2752 QgsProcessingParameterDefinition *QgsProcessingParameterExtent::clone() const
2753 {
2754 return new QgsProcessingParameterExtent( *this );
2755 }
2756
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext * context) const2757 bool QgsProcessingParameterExtent::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context ) const
2758 {
2759 if ( !input.isValid() )
2760 return mFlags & FlagOptional;
2761
2762 if ( input.canConvert<QgsProcessingFeatureSourceDefinition>() )
2763 {
2764 return true;
2765 }
2766 else if ( input.canConvert<QgsProcessingOutputLayerDefinition>() )
2767 {
2768 return true;
2769 }
2770
2771 if ( input.canConvert<QgsProperty>() )
2772 {
2773 return true;
2774 }
2775
2776 if ( input.canConvert< QgsRectangle >() )
2777 {
2778 QgsRectangle r = input.value<QgsRectangle>();
2779 return !r.isNull();
2780 }
2781 if ( input.canConvert< QgsGeometry >() )
2782 {
2783 return true;
2784 }
2785 if ( input.canConvert< QgsReferencedRectangle >() )
2786 {
2787 QgsReferencedRectangle r = input.value<QgsReferencedRectangle>();
2788 return !r.isNull();
2789 }
2790
2791 // direct map layer value
2792 if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( input ) ) )
2793 return true;
2794
2795 if ( input.type() != QVariant::String || input.toString().isEmpty() )
2796 return mFlags & FlagOptional;
2797
2798 if ( !context )
2799 {
2800 // that's as far as we can get without a context
2801 return true;
2802 }
2803
2804 QRegularExpression rx( QStringLiteral( "^(.*?)\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*$" ) );
2805 QRegularExpressionMatch match = rx.match( input.toString() );
2806 if ( match.hasMatch() )
2807 {
2808 bool xMinOk = false;
2809 ( void )match.captured( 1 ).toDouble( &xMinOk );
2810 bool xMaxOk = false;
2811 ( void )match.captured( 2 ).toDouble( &xMaxOk );
2812 bool yMinOk = false;
2813 ( void )match.captured( 3 ).toDouble( &yMinOk );
2814 bool yMaxOk = false;
2815 ( void )match.captured( 4 ).toDouble( &yMaxOk );
2816 if ( xMinOk && xMaxOk && yMinOk && yMaxOk )
2817 return true;
2818 }
2819
2820 // try as layer extent
2821 return QgsProcessingUtils::mapLayerFromString( input.toString(), *context );
2822 }
2823
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const2824 QString QgsProcessingParameterExtent::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
2825 {
2826 if ( !value.isValid() )
2827 return QStringLiteral( "None" );
2828
2829 if ( value.canConvert<QgsProperty>() )
2830 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
2831
2832 if ( value.canConvert< QgsRectangle >() )
2833 {
2834 QgsRectangle r = value.value<QgsRectangle>();
2835 return QStringLiteral( "'%1, %3, %2, %4'" ).arg( qgsDoubleToString( r.xMinimum() ),
2836 qgsDoubleToString( r.yMinimum() ),
2837 qgsDoubleToString( r.xMaximum() ),
2838 qgsDoubleToString( r.yMaximum() ) );
2839 }
2840 else if ( value.canConvert< QgsReferencedRectangle >() )
2841 {
2842 QgsReferencedRectangle r = value.value<QgsReferencedRectangle>();
2843 return QStringLiteral( "'%1, %3, %2, %4 [%5]'" ).arg( qgsDoubleToString( r.xMinimum() ),
2844 qgsDoubleToString( r.yMinimum() ),
2845 qgsDoubleToString( r.xMaximum() ),
2846 qgsDoubleToString( r.yMaximum() ), r.crs().authid() );
2847 }
2848 else if ( value.canConvert< QgsGeometry >() )
2849 {
2850 const QgsGeometry g = value.value<QgsGeometry>();
2851 if ( !g.isNull() )
2852 {
2853 const QString wkt = g.asWkt();
2854 return QStringLiteral( "QgsGeometry.fromWkt('%1')" ).arg( wkt );
2855 }
2856 }
2857
2858 QVariantMap p;
2859 p.insert( name(), value );
2860 QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( this, p, context );
2861 if ( layer )
2862 return QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) );
2863
2864 return QgsProcessingParameterDefinition::valueAsPythonString( value, context );
2865 }
2866
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)2867 QgsProcessingParameterExtent *QgsProcessingParameterExtent::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
2868 {
2869 return new QgsProcessingParameterExtent( name, description, definition, isOptional );
2870 }
2871
QgsProcessingParameterPoint(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)2872 QgsProcessingParameterPoint::QgsProcessingParameterPoint( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
2873 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
2874 {
2875
2876 }
2877
clone() const2878 QgsProcessingParameterDefinition *QgsProcessingParameterPoint::clone() const
2879 {
2880 return new QgsProcessingParameterPoint( *this );
2881 }
2882
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const2883 bool QgsProcessingParameterPoint::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
2884 {
2885 if ( !input.isValid() )
2886 return mFlags & FlagOptional;
2887
2888 if ( input.canConvert<QgsProperty>() )
2889 {
2890 return true;
2891 }
2892
2893 if ( input.canConvert< QgsPointXY >() )
2894 {
2895 return true;
2896 }
2897 if ( input.canConvert< QgsReferencedPointXY >() )
2898 {
2899 return true;
2900 }
2901 if ( input.canConvert< QgsGeometry >() )
2902 {
2903 return true;
2904 }
2905
2906 if ( input.type() == QVariant::String )
2907 {
2908 if ( input.toString().isEmpty() )
2909 return mFlags & FlagOptional;
2910 }
2911
2912 QRegularExpression rx( QStringLiteral( "^\\s*\\(?\\s*(.*?)\\s*,\\s*(.*?)\\s*(?:\\[(.*)\\])?\\s*\\)?\\s*$" ) );
2913
2914 QRegularExpressionMatch match = rx.match( input.toString() );
2915 if ( match.hasMatch() )
2916 {
2917 bool xOk = false;
2918 ( void )match.captured( 1 ).toDouble( &xOk );
2919 bool yOk = false;
2920 ( void )match.captured( 2 ).toDouble( &yOk );
2921 return xOk && yOk;
2922 }
2923 else
2924 return false;
2925 }
2926
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const2927 QString QgsProcessingParameterPoint::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
2928 {
2929 if ( !value.isValid() )
2930 return QStringLiteral( "None" );
2931
2932 if ( value.canConvert<QgsProperty>() )
2933 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
2934
2935 if ( value.canConvert< QgsPointXY >() )
2936 {
2937 QgsPointXY r = value.value<QgsPointXY>();
2938 return QStringLiteral( "'%1,%2'" ).arg( qgsDoubleToString( r.x() ),
2939 qgsDoubleToString( r.y() ) );
2940 }
2941 else if ( value.canConvert< QgsReferencedPointXY >() )
2942 {
2943 QgsReferencedPointXY r = value.value<QgsReferencedPointXY>();
2944 return QStringLiteral( "'%1,%2 [%3]'" ).arg( qgsDoubleToString( r.x() ),
2945 qgsDoubleToString( r.y() ),
2946 r.crs().authid() );
2947 }
2948 else if ( value.canConvert< QgsGeometry >() )
2949 {
2950 const QgsGeometry g = value.value<QgsGeometry>();
2951 if ( !g.isNull() )
2952 {
2953 const QString wkt = g.asWkt();
2954 return QStringLiteral( "QgsGeometry.fromWkt('%1')" ).arg( wkt );
2955 }
2956 }
2957
2958 return QgsProcessingParameterDefinition::valueAsPythonString( value, context );
2959 }
2960
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)2961 QgsProcessingParameterPoint *QgsProcessingParameterPoint::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
2962 {
2963 return new QgsProcessingParameterPoint( name, description, definition, isOptional );
2964 }
2965
QgsProcessingParameterGeometry(const QString & name,const QString & description,const QVariant & defaultValue,bool optional,const QList<int> & geometryTypes,bool allowMultipart)2966 QgsProcessingParameterGeometry::QgsProcessingParameterGeometry( const QString &name, const QString &description,
2967 const QVariant &defaultValue, bool optional, const QList<int> &geometryTypes, bool allowMultipart )
2968 : QgsProcessingParameterDefinition( name, description, defaultValue, optional ),
2969 mGeomTypes( geometryTypes ),
2970 mAllowMultipart( allowMultipart )
2971 {
2972
2973 }
2974
clone() const2975 QgsProcessingParameterDefinition *QgsProcessingParameterGeometry::clone() const
2976 {
2977 return new QgsProcessingParameterGeometry( *this );
2978 }
2979
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const2980 bool QgsProcessingParameterGeometry::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
2981 {
2982 if ( !input.isValid() )
2983 return mFlags & FlagOptional;
2984
2985 if ( input.canConvert<QgsProperty>() )
2986 {
2987 return true;
2988 }
2989
2990 bool anyTypeAllowed = mGeomTypes.isEmpty() || mGeomTypes.contains( QgsWkbTypes::UnknownGeometry );
2991
2992 if ( input.canConvert< QgsGeometry >() )
2993 {
2994 return ( anyTypeAllowed || mGeomTypes.contains( input.value<QgsGeometry>().type() ) ) &&
2995 ( mAllowMultipart || !input.value<QgsGeometry>().isMultipart() );
2996 }
2997
2998 if ( input.canConvert< QgsReferencedGeometry >() )
2999 {
3000 return ( anyTypeAllowed || mGeomTypes.contains( input.value<QgsReferencedGeometry>().type() ) ) &&
3001 ( mAllowMultipart || !input.value<QgsReferencedGeometry>().isMultipart() );
3002 }
3003
3004 if ( input.canConvert< QgsPointXY >() )
3005 {
3006 return anyTypeAllowed || mGeomTypes.contains( QgsWkbTypes::PointGeometry );
3007 }
3008
3009 if ( input.canConvert< QgsRectangle >() )
3010 {
3011 return anyTypeAllowed || mGeomTypes.contains( QgsWkbTypes::PolygonGeometry );
3012 }
3013
3014 if ( input.canConvert< QgsReferencedPointXY >() )
3015 {
3016 return anyTypeAllowed || mGeomTypes.contains( QgsWkbTypes::PointGeometry );
3017 }
3018
3019 if ( input.canConvert< QgsReferencedRectangle >() )
3020 {
3021 return anyTypeAllowed || mGeomTypes.contains( QgsWkbTypes::PolygonGeometry );
3022 }
3023
3024 if ( input.type() == QVariant::String )
3025 {
3026 if ( input.toString().isEmpty() )
3027 return mFlags & FlagOptional;
3028 }
3029
3030 // Match against EWKT
3031 QRegularExpression rx( QStringLiteral( "^\\s*(?:CRS=(.*);)?(.*?)$" ) );
3032
3033 QRegularExpressionMatch match = rx.match( input.toString() );
3034 if ( match.hasMatch() )
3035 {
3036 QgsGeometry g = QgsGeometry::fromWkt( match.captured( 2 ) );
3037 if ( ! g.isNull() )
3038 {
3039 return ( anyTypeAllowed || mGeomTypes.contains( g.type() ) ) && ( mAllowMultipart || !g.isMultipart() );
3040 }
3041 else
3042 {
3043 QgsMessageLog::logMessage( QObject::tr( "Error creating geometry: \"%1\"" ).arg( g.lastError() ), QObject::tr( "Processing" ) );
3044 }
3045 }
3046 return false;
3047 }
3048
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const3049 QString QgsProcessingParameterGeometry::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
3050 {
3051 auto asPythonString = []( const QgsGeometry & g, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() )
3052 {
3053 if ( !crs.isValid() )
3054 return QgsProcessingUtils::stringToPythonLiteral( g.asWkt() );
3055 else
3056 return QgsProcessingUtils::stringToPythonLiteral( QStringLiteral( "CRS=%1;%2" ).arg( crs.authid().isEmpty() ? crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) : crs.authid(), g.asWkt() ) );
3057 };
3058
3059 if ( !value.isValid() )
3060 return QStringLiteral( "None" );
3061
3062 if ( value.canConvert<QgsProperty>() )
3063 return QStringLiteral( "QgsProperty.fromExpression(%1)" ).arg( QgsProcessingUtils::stringToPythonLiteral( value.value< QgsProperty >().asExpression() ) );
3064
3065 if ( value.canConvert< QgsGeometry >() )
3066 {
3067 const QgsGeometry g = value.value<QgsGeometry>();
3068 if ( !g.isNull() )
3069 return asPythonString( g );
3070 }
3071
3072 if ( value.canConvert< QgsReferencedGeometry >() )
3073 {
3074 const QgsReferencedGeometry g = value.value<QgsReferencedGeometry>();
3075 if ( !g.isNull() )
3076 return asPythonString( g, g.crs() );
3077 }
3078
3079 if ( value.canConvert< QgsPointXY >() )
3080 {
3081 const QgsGeometry g = QgsGeometry::fromPointXY( value.value<QgsPointXY>() );
3082 if ( !g.isNull() )
3083 return asPythonString( g );
3084 }
3085
3086 if ( value.canConvert< QgsReferencedPointXY >() )
3087 {
3088 const QgsReferencedGeometry g = QgsReferencedGeometry::fromReferencedPointXY( value.value<QgsReferencedPointXY>() );
3089 if ( !g.isNull() )
3090 return asPythonString( g, g.crs() );
3091 }
3092
3093 if ( value.canConvert< QgsRectangle >() )
3094 {
3095 const QgsGeometry g = QgsGeometry::fromRect( value.value<QgsRectangle>() );
3096 if ( !g.isNull() )
3097 return asPythonString( g );
3098 }
3099
3100 if ( value.canConvert< QgsReferencedRectangle >() )
3101 {
3102 const QgsReferencedGeometry g = QgsReferencedGeometry::fromReferencedRect( value.value<QgsReferencedRectangle>() );
3103 if ( !g.isNull() )
3104 return asPythonString( g, g.crs() );
3105 }
3106
3107 return QgsProcessingParameterDefinition::valueAsPythonString( value, context );
3108 }
3109
asScriptCode() const3110 QString QgsProcessingParameterGeometry::asScriptCode() const
3111 {
3112 QString code = QStringLiteral( "##%1=" ).arg( mName );
3113 if ( mFlags & FlagOptional )
3114 code += QLatin1String( "optional " );
3115 code += type() + ' ';
3116
3117 for ( int type : mGeomTypes )
3118 {
3119 switch ( static_cast<QgsWkbTypes::GeometryType>( type ) )
3120 {
3121 case QgsWkbTypes::PointGeometry:
3122 code += QLatin1String( "point " );
3123 break;
3124
3125 case QgsWkbTypes::LineGeometry:
3126 code += QLatin1String( "line " );
3127 break;
3128
3129 case QgsWkbTypes::PolygonGeometry:
3130 code += QLatin1String( "polygon " );
3131 break;
3132
3133 default:
3134 code += QLatin1String( "unknown " );
3135 break;
3136 }
3137 }
3138
3139 code += mDefault.toString();
3140 return code.trimmed();
3141 }
3142
asPythonString(const QgsProcessing::PythonOutputType outputType) const3143 QString QgsProcessingParameterGeometry::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
3144 {
3145 switch ( outputType )
3146 {
3147 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
3148 {
3149 QString code = QStringLiteral( "QgsProcessingParameterGeometry('%1', '%2'" ).arg( name(), description() );
3150 if ( mFlags & FlagOptional )
3151 code += QLatin1String( ", optional=True" );
3152
3153 if ( !mGeomTypes.empty() )
3154 {
3155 auto geomTypeToString = []( QgsWkbTypes::GeometryType t ) -> QString
3156 {
3157 switch ( t )
3158 {
3159 case QgsWkbTypes::PointGeometry:
3160 return QStringLiteral( "PointGeometry" );
3161
3162 case QgsWkbTypes::LineGeometry:
3163 return QStringLiteral( "LineGeometry" );
3164
3165 case QgsWkbTypes::PolygonGeometry:
3166 return QStringLiteral( "PolygonGeometry" );
3167
3168 case QgsWkbTypes::UnknownGeometry:
3169 return QStringLiteral( "UnknownGeometry" );
3170
3171 case QgsWkbTypes::NullGeometry:
3172 return QStringLiteral( "NullGeometry" );
3173 }
3174 return QString();
3175 };
3176
3177 QStringList options;
3178 options.reserve( mGeomTypes.size() );
3179 for ( int type : mGeomTypes )
3180 {
3181 options << QStringLiteral( " QgsWkbTypes.%1" ).arg( geomTypeToString( static_cast<QgsWkbTypes::GeometryType>( type ) ) );
3182 }
3183 code += QStringLiteral( ", geometryTypes=[%1 ]" ).arg( options.join( ',' ) );
3184 }
3185
3186 if ( ! mAllowMultipart )
3187 {
3188 code += QStringLiteral( ", allowMultipart=False" );
3189 }
3190
3191 QgsProcessingContext c;
3192 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
3193 return code;
3194 }
3195 }
3196 return QString();
3197 }
3198
toVariantMap() const3199 QVariantMap QgsProcessingParameterGeometry::toVariantMap() const
3200 {
3201 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
3202 QVariantList types;
3203 for ( int type : mGeomTypes )
3204 {
3205 types << type;
3206 }
3207 map.insert( QStringLiteral( "geometrytypes" ), types );
3208 map.insert( QStringLiteral( "multipart" ), mAllowMultipart );
3209 return map;
3210 }
3211
fromVariantMap(const QVariantMap & map)3212 bool QgsProcessingParameterGeometry::fromVariantMap( const QVariantMap &map )
3213 {
3214 QgsProcessingParameterDefinition::fromVariantMap( map );
3215 mGeomTypes.clear();
3216 const QVariantList values = map.value( QStringLiteral( "geometrytypes" ) ).toList();
3217 for ( const QVariant &val : values )
3218 {
3219 mGeomTypes << val.toInt();
3220 }
3221 mAllowMultipart = map.value( QStringLiteral( "multipart" ) ).toBool();
3222 return true;
3223 }
3224
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)3225 QgsProcessingParameterGeometry *QgsProcessingParameterGeometry::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
3226 {
3227 return new QgsProcessingParameterGeometry( name, description, definition, isOptional );
3228 }
3229
QgsProcessingParameterFile(const QString & name,const QString & description,Behavior behavior,const QString & extension,const QVariant & defaultValue,bool optional,const QString & fileFilter)3230 QgsProcessingParameterFile::QgsProcessingParameterFile( const QString &name, const QString &description, Behavior behavior, const QString &extension, const QVariant &defaultValue, bool optional, const QString &fileFilter )
3231 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
3232 , mBehavior( behavior )
3233 , mExtension( fileFilter.isEmpty() ? extension : QString() )
3234 , mFileFilter( fileFilter.isEmpty() && extension.isEmpty() ? QObject::tr( "All files (*.*)" ) : fileFilter )
3235 {
3236
3237 }
3238
clone() const3239 QgsProcessingParameterDefinition *QgsProcessingParameterFile::clone() const
3240 {
3241 return new QgsProcessingParameterFile( *this );
3242 }
3243
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const3244 bool QgsProcessingParameterFile::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
3245 {
3246 if ( !input.isValid() )
3247 return mFlags & FlagOptional;
3248
3249 if ( input.canConvert<QgsProperty>() )
3250 {
3251 return true;
3252 }
3253
3254 QString string = input.toString().trimmed();
3255
3256 if ( input.type() != QVariant::String || string.isEmpty() )
3257 return mFlags & FlagOptional;
3258
3259 switch ( mBehavior )
3260 {
3261 case File:
3262 {
3263 if ( !mExtension.isEmpty() )
3264 {
3265 return string.endsWith( mExtension, Qt::CaseInsensitive );
3266 }
3267 else if ( !mFileFilter.isEmpty() )
3268 {
3269 const QString test = QgsFileUtils::addExtensionFromFilter( string, mFileFilter );
3270 return test == string;
3271 }
3272 else
3273 {
3274 return true;
3275 }
3276 }
3277
3278 case Folder:
3279 return true;
3280 }
3281 return true;
3282 }
3283
asScriptCode() const3284 QString QgsProcessingParameterFile::asScriptCode() const
3285 {
3286 QString code = QStringLiteral( "##%1=" ).arg( mName );
3287 if ( mFlags & FlagOptional )
3288 code += QLatin1String( "optional " );
3289 code += ( mBehavior == File ? QStringLiteral( "file" ) : QStringLiteral( "folder" ) ) + ' ';
3290 code += mDefault.toString();
3291 return code.trimmed();
3292 }
3293
asPythonString(const QgsProcessing::PythonOutputType outputType) const3294 QString QgsProcessingParameterFile::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
3295 {
3296 switch ( outputType )
3297 {
3298 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
3299 {
3300
3301 QString code = QStringLiteral( "QgsProcessingParameterFile('%1', '%2'" ).arg( name(), description() );
3302 if ( mFlags & FlagOptional )
3303 code += QLatin1String( ", optional=True" );
3304 code += QStringLiteral( ", behavior=%1" ).arg( mBehavior == File ? QStringLiteral( "QgsProcessingParameterFile.File" ) : QStringLiteral( "QgsProcessingParameterFile.Folder" ) );
3305 if ( !mExtension.isEmpty() )
3306 code += QStringLiteral( ", extension='%1'" ).arg( mExtension );
3307 if ( !mFileFilter.isEmpty() )
3308 code += QStringLiteral( ", fileFilter='%1'" ).arg( mFileFilter );
3309 QgsProcessingContext c;
3310 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
3311 return code;
3312 }
3313 }
3314 return QString();
3315 }
3316
createFileFilter() const3317 QString QgsProcessingParameterFile::createFileFilter() const
3318 {
3319 switch ( mBehavior )
3320 {
3321 case File:
3322 {
3323 if ( !mFileFilter.isEmpty() )
3324 return mFileFilter != QObject::tr( "All files (*.*)" ) ? mFileFilter + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" ) : mFileFilter;
3325 else if ( !mExtension.isEmpty() )
3326 return QObject::tr( "%1 files" ).arg( mExtension.toUpper() ) + QStringLiteral( " (*." ) + mExtension.toLower() + QStringLiteral( ");;" ) + QObject::tr( "All files (*.*)" );
3327 else
3328 return QObject::tr( "All files (*.*)" );
3329 }
3330
3331 case Folder:
3332 return QString();
3333 }
3334 return QString();
3335 }
3336
setExtension(const QString & extension)3337 void QgsProcessingParameterFile::setExtension( const QString &extension )
3338 {
3339 mExtension = extension;
3340 mFileFilter.clear();
3341 }
3342
fileFilter() const3343 QString QgsProcessingParameterFile::fileFilter() const
3344 {
3345 return mFileFilter;
3346 }
3347
setFileFilter(const QString & filter)3348 void QgsProcessingParameterFile::setFileFilter( const QString &filter )
3349 {
3350 mFileFilter = filter;
3351 mExtension.clear();
3352 }
3353
toVariantMap() const3354 QVariantMap QgsProcessingParameterFile::toVariantMap() const
3355 {
3356 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
3357 map.insert( QStringLiteral( "behavior" ), mBehavior );
3358 map.insert( QStringLiteral( "extension" ), mExtension );
3359 map.insert( QStringLiteral( "filefilter" ), mFileFilter );
3360 return map;
3361 }
3362
fromVariantMap(const QVariantMap & map)3363 bool QgsProcessingParameterFile::fromVariantMap( const QVariantMap &map )
3364 {
3365 QgsProcessingParameterDefinition::fromVariantMap( map );
3366 mBehavior = static_cast< Behavior >( map.value( QStringLiteral( "behavior" ) ).toInt() );
3367 mExtension = map.value( QStringLiteral( "extension" ) ).toString();
3368 mFileFilter = map.value( QStringLiteral( "filefilter" ) ).toString();
3369 return true;
3370 }
3371
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition,QgsProcessingParameterFile::Behavior behavior)3372 QgsProcessingParameterFile *QgsProcessingParameterFile::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition, QgsProcessingParameterFile::Behavior behavior )
3373 {
3374 return new QgsProcessingParameterFile( name, description, behavior, QString(), definition, isOptional );
3375 }
3376
QgsProcessingParameterMatrix(const QString & name,const QString & description,int numberRows,bool fixedNumberRows,const QStringList & headers,const QVariant & defaultValue,bool optional)3377 QgsProcessingParameterMatrix::QgsProcessingParameterMatrix( const QString &name, const QString &description, int numberRows, bool fixedNumberRows, const QStringList &headers, const QVariant &defaultValue, bool optional )
3378 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
3379 , mHeaders( headers )
3380 , mNumberRows( numberRows )
3381 , mFixedNumberRows( fixedNumberRows )
3382 {
3383
3384 }
3385
clone() const3386 QgsProcessingParameterDefinition *QgsProcessingParameterMatrix::clone() const
3387 {
3388 return new QgsProcessingParameterMatrix( *this );
3389 }
3390
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const3391 bool QgsProcessingParameterMatrix::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
3392 {
3393 if ( !input.isValid() )
3394 return mFlags & FlagOptional;
3395
3396 if ( input.type() == QVariant::String )
3397 {
3398 if ( input.toString().isEmpty() )
3399 return mFlags & FlagOptional;
3400 return true;
3401 }
3402 else if ( input.type() == QVariant::List )
3403 {
3404 if ( input.toList().isEmpty() )
3405 return mFlags & FlagOptional;
3406 return true;
3407 }
3408 else if ( input.type() == QVariant::Double || input.type() == QVariant::Int )
3409 {
3410 return true;
3411 }
3412
3413 return false;
3414 }
3415
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const3416 QString QgsProcessingParameterMatrix::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
3417 {
3418 if ( !value.isValid() )
3419 return QStringLiteral( "None" );
3420
3421 if ( value.canConvert<QgsProperty>() )
3422 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
3423
3424 QVariantMap p;
3425 p.insert( name(), value );
3426 QVariantList list = QgsProcessingParameters::parameterAsMatrix( this, p, context );
3427
3428 return QgsProcessingUtils::variantToPythonLiteral( list );
3429 }
3430
asPythonString(const QgsProcessing::PythonOutputType outputType) const3431 QString QgsProcessingParameterMatrix::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
3432 {
3433 switch ( outputType )
3434 {
3435 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
3436 {
3437 QString code = QStringLiteral( "QgsProcessingParameterMatrix('%1', '%2'" ).arg( name(), description() );
3438 if ( mFlags & FlagOptional )
3439 code += QLatin1String( ", optional=True" );
3440 code += QStringLiteral( ", numberRows=%1" ).arg( mNumberRows );
3441 code += QStringLiteral( ", hasFixedNumberRows=%1" ).arg( mFixedNumberRows ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
3442
3443 QStringList headers;
3444 headers.reserve( mHeaders.size() );
3445 for ( const QString &h : mHeaders )
3446 headers << QgsProcessingUtils::stringToPythonLiteral( h );
3447 code += QStringLiteral( ", headers=[%1]" ).arg( headers.join( ',' ) );
3448
3449 QgsProcessingContext c;
3450 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
3451 return code;
3452 }
3453 }
3454 return QString();
3455 }
3456
headers() const3457 QStringList QgsProcessingParameterMatrix::headers() const
3458 {
3459 return mHeaders;
3460 }
3461
setHeaders(const QStringList & headers)3462 void QgsProcessingParameterMatrix::setHeaders( const QStringList &headers )
3463 {
3464 mHeaders = headers;
3465 }
3466
numberRows() const3467 int QgsProcessingParameterMatrix::numberRows() const
3468 {
3469 return mNumberRows;
3470 }
3471
setNumberRows(int numberRows)3472 void QgsProcessingParameterMatrix::setNumberRows( int numberRows )
3473 {
3474 mNumberRows = numberRows;
3475 }
3476
hasFixedNumberRows() const3477 bool QgsProcessingParameterMatrix::hasFixedNumberRows() const
3478 {
3479 return mFixedNumberRows;
3480 }
3481
setHasFixedNumberRows(bool fixedNumberRows)3482 void QgsProcessingParameterMatrix::setHasFixedNumberRows( bool fixedNumberRows )
3483 {
3484 mFixedNumberRows = fixedNumberRows;
3485 }
3486
toVariantMap() const3487 QVariantMap QgsProcessingParameterMatrix::toVariantMap() const
3488 {
3489 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
3490 map.insert( QStringLiteral( "headers" ), mHeaders );
3491 map.insert( QStringLiteral( "rows" ), mNumberRows );
3492 map.insert( QStringLiteral( "fixed_number_rows" ), mFixedNumberRows );
3493 return map;
3494 }
3495
fromVariantMap(const QVariantMap & map)3496 bool QgsProcessingParameterMatrix::fromVariantMap( const QVariantMap &map )
3497 {
3498 QgsProcessingParameterDefinition::fromVariantMap( map );
3499 mHeaders = map.value( QStringLiteral( "headers" ) ).toStringList();
3500 mNumberRows = map.value( QStringLiteral( "rows" ) ).toInt();
3501 mFixedNumberRows = map.value( QStringLiteral( "fixed_number_rows" ) ).toBool();
3502 return true;
3503 }
3504
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)3505 QgsProcessingParameterMatrix *QgsProcessingParameterMatrix::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
3506 {
3507 return new QgsProcessingParameterMatrix( name, description, 0, false, QStringList(), definition.isEmpty() ? QVariant() : definition, isOptional );
3508 }
3509
QgsProcessingParameterMultipleLayers(const QString & name,const QString & description,QgsProcessing::SourceType layerType,const QVariant & defaultValue,bool optional)3510 QgsProcessingParameterMultipleLayers::QgsProcessingParameterMultipleLayers( const QString &name, const QString &description, QgsProcessing::SourceType layerType, const QVariant &defaultValue, bool optional )
3511 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
3512 , mLayerType( layerType )
3513 {
3514
3515 }
3516
clone() const3517 QgsProcessingParameterDefinition *QgsProcessingParameterMultipleLayers::clone() const
3518 {
3519 return new QgsProcessingParameterMultipleLayers( *this );
3520 }
3521
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext * context) const3522 bool QgsProcessingParameterMultipleLayers::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context ) const
3523 {
3524 if ( !input.isValid() )
3525 return mFlags & FlagOptional;
3526
3527 if ( mLayerType != QgsProcessing::TypeFile )
3528 {
3529 if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( input ) ) )
3530 {
3531 return true;
3532 }
3533 }
3534
3535 if ( input.type() == QVariant::String )
3536 {
3537 if ( input.toString().isEmpty() )
3538 return mFlags & FlagOptional;
3539
3540 if ( mMinimumNumberInputs > 1 )
3541 return false;
3542
3543 if ( !context )
3544 return true;
3545
3546 if ( mLayerType != QgsProcessing::TypeFile )
3547 return QgsProcessingUtils::mapLayerFromString( input.toString(), *context );
3548 else
3549 return true;
3550 }
3551 else if ( input.type() == QVariant::List )
3552 {
3553 if ( input.toList().count() < mMinimumNumberInputs )
3554 return mFlags & FlagOptional;
3555
3556 if ( mMinimumNumberInputs > input.toList().count() )
3557 return false;
3558
3559 if ( !context )
3560 return true;
3561
3562 if ( mLayerType != QgsProcessing::TypeFile )
3563 {
3564 const auto constToList = input.toList();
3565 for ( const QVariant &v : constToList )
3566 {
3567 if ( qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( v ) ) )
3568 continue;
3569
3570 if ( !QgsProcessingUtils::mapLayerFromString( v.toString(), *context ) )
3571 return false;
3572 }
3573 }
3574 return true;
3575 }
3576 else if ( input.type() == QVariant::StringList )
3577 {
3578 if ( input.toStringList().count() < mMinimumNumberInputs )
3579 return mFlags & FlagOptional;
3580
3581 if ( mMinimumNumberInputs > input.toStringList().count() )
3582 return false;
3583
3584 if ( !context )
3585 return true;
3586
3587 if ( mLayerType != QgsProcessing::TypeFile )
3588 {
3589 const auto constToStringList = input.toStringList();
3590 for ( const QString &v : constToStringList )
3591 {
3592 if ( !QgsProcessingUtils::mapLayerFromString( v, *context ) )
3593 return false;
3594 }
3595 }
3596 return true;
3597 }
3598 return false;
3599 }
3600
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const3601 QString QgsProcessingParameterMultipleLayers::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
3602 {
3603 if ( !value.isValid() )
3604 return QStringLiteral( "None" );
3605
3606 if ( value.canConvert<QgsProperty>() )
3607 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
3608
3609 if ( mLayerType == QgsProcessing::TypeFile )
3610 {
3611 QStringList parts;
3612 if ( value.type() == QVariant::StringList )
3613 {
3614 const QStringList list = value.toStringList();
3615 parts.reserve( list.count() );
3616 for ( const QString &v : list )
3617 parts << QgsProcessingUtils::stringToPythonLiteral( v );
3618 }
3619 else if ( value.type() == QVariant::List )
3620 {
3621 const QVariantList list = value.toList();
3622 parts.reserve( list.count() );
3623 for ( const QVariant &v : list )
3624 parts << QgsProcessingUtils::stringToPythonLiteral( v.toString() );
3625 }
3626 if ( !parts.isEmpty() )
3627 return parts.join( ',' ).prepend( '[' ).append( ']' );
3628 }
3629 else
3630 {
3631 QVariantMap p;
3632 p.insert( name(), value );
3633 const QList<QgsMapLayer *> list = QgsProcessingParameters::parameterAsLayerList( this, p, context );
3634 if ( !list.isEmpty() )
3635 {
3636 QStringList parts;
3637 parts.reserve( list.count() );
3638 for ( const QgsMapLayer *layer : list )
3639 {
3640 parts << QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) );
3641 }
3642 return parts.join( ',' ).prepend( '[' ).append( ']' );
3643 }
3644 }
3645
3646 return QgsProcessingParameterDefinition::valueAsPythonString( value, context );
3647 }
3648
asScriptCode() const3649 QString QgsProcessingParameterMultipleLayers::asScriptCode() const
3650 {
3651 QString code = QStringLiteral( "##%1=" ).arg( mName );
3652 if ( mFlags & FlagOptional )
3653 code += QLatin1String( "optional " );
3654 switch ( mLayerType )
3655 {
3656 case QgsProcessing::TypeRaster:
3657 code += QLatin1String( "multiple raster" );
3658 break;
3659
3660 case QgsProcessing::TypeFile:
3661 code += QLatin1String( "multiple file" );
3662 break;
3663
3664 default:
3665 code += QLatin1String( "multiple vector" );
3666 break;
3667 }
3668 code += ' ';
3669 if ( mDefault.type() == QVariant::List )
3670 {
3671 QStringList parts;
3672 const auto constToList = mDefault.toList();
3673 for ( const QVariant &var : constToList )
3674 {
3675 parts << var.toString();
3676 }
3677 code += parts.join( ',' );
3678 }
3679 else if ( mDefault.type() == QVariant::StringList )
3680 {
3681 code += mDefault.toStringList().join( ',' );
3682 }
3683 else
3684 {
3685 code += mDefault.toString();
3686 }
3687 return code.trimmed();
3688 }
3689
asPythonString(const QgsProcessing::PythonOutputType outputType) const3690 QString QgsProcessingParameterMultipleLayers::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
3691 {
3692 switch ( outputType )
3693 {
3694 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
3695 {
3696 QString code = QStringLiteral( "QgsProcessingParameterMultipleLayers('%1', '%2'" ).arg( name(), description() );
3697 if ( mFlags & FlagOptional )
3698 code += QLatin1String( ", optional=True" );
3699
3700 QString layerType = QStringLiteral( "QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( mLayerType ) );
3701
3702 code += QStringLiteral( ", layerType=%1" ).arg( layerType );
3703 QgsProcessingContext c;
3704 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
3705 return code;
3706 }
3707 }
3708 return QString();
3709 }
3710
createFileFilter() const3711 QString QgsProcessingParameterMultipleLayers::createFileFilter() const
3712 {
3713 QStringList exts;
3714 switch ( mLayerType )
3715 {
3716 case QgsProcessing::TypeFile:
3717 return QObject::tr( "All files (*.*)" );
3718
3719 case QgsProcessing::TypeRaster:
3720 return QgsProviderRegistry::instance()->fileRasterFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
3721
3722 case QgsProcessing::TypeVector:
3723 case QgsProcessing::TypeVectorAnyGeometry:
3724 case QgsProcessing::TypeVectorPoint:
3725 case QgsProcessing::TypeVectorLine:
3726 case QgsProcessing::TypeVectorPolygon:
3727 return QgsProviderRegistry::instance()->fileVectorFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
3728
3729 case QgsProcessing::TypeMesh:
3730 return QgsProviderRegistry::instance()->fileMeshFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
3731
3732 case QgsProcessing::TypeMapLayer:
3733 return createAllMapLayerFileFilter();
3734 }
3735 return QString();
3736 }
3737
layerType() const3738 QgsProcessing::SourceType QgsProcessingParameterMultipleLayers::layerType() const
3739 {
3740 return mLayerType;
3741 }
3742
setLayerType(QgsProcessing::SourceType type)3743 void QgsProcessingParameterMultipleLayers::setLayerType( QgsProcessing::SourceType type )
3744 {
3745 mLayerType = type;
3746 }
3747
minimumNumberInputs() const3748 int QgsProcessingParameterMultipleLayers::minimumNumberInputs() const
3749 {
3750 return mMinimumNumberInputs;
3751 }
3752
setMinimumNumberInputs(int minimumNumberInputs)3753 void QgsProcessingParameterMultipleLayers::setMinimumNumberInputs( int minimumNumberInputs )
3754 {
3755 if ( mMinimumNumberInputs >= 1 || !( flags() & QgsProcessingParameterDefinition::FlagOptional ) )
3756 mMinimumNumberInputs = minimumNumberInputs;
3757 }
3758
toVariantMap() const3759 QVariantMap QgsProcessingParameterMultipleLayers::toVariantMap() const
3760 {
3761 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
3762 map.insert( QStringLiteral( "layer_type" ), mLayerType );
3763 map.insert( QStringLiteral( "min_inputs" ), mMinimumNumberInputs );
3764 return map;
3765 }
3766
fromVariantMap(const QVariantMap & map)3767 bool QgsProcessingParameterMultipleLayers::fromVariantMap( const QVariantMap &map )
3768 {
3769 QgsProcessingParameterDefinition::fromVariantMap( map );
3770 mLayerType = static_cast< QgsProcessing::SourceType >( map.value( QStringLiteral( "layer_type" ) ).toInt() );
3771 mMinimumNumberInputs = map.value( QStringLiteral( "min_inputs" ) ).toInt();
3772 return true;
3773 }
3774
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)3775 QgsProcessingParameterMultipleLayers *QgsProcessingParameterMultipleLayers::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
3776 {
3777 QString type = definition;
3778 QString defaultVal;
3779 QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*)" ) );
3780 QRegularExpressionMatch m = re.match( definition );
3781 if ( m.hasMatch() )
3782 {
3783 type = m.captured( 1 ).toLower().trimmed();
3784 defaultVal = m.captured( 2 );
3785 }
3786 QgsProcessing::SourceType layerType = QgsProcessing::TypeVectorAnyGeometry;
3787 if ( type == QLatin1String( "vector" ) )
3788 layerType = QgsProcessing::TypeVectorAnyGeometry;
3789 else if ( type == QLatin1String( "raster" ) )
3790 layerType = QgsProcessing::TypeRaster;
3791 else if ( type == QLatin1String( "file" ) )
3792 layerType = QgsProcessing::TypeFile;
3793 return new QgsProcessingParameterMultipleLayers( name, description, layerType, defaultVal.isEmpty() ? QVariant() : defaultVal, isOptional );
3794 }
3795
QgsProcessingParameterNumber(const QString & name,const QString & description,Type type,const QVariant & defaultValue,bool optional,double minValue,double maxValue)3796 QgsProcessingParameterNumber::QgsProcessingParameterNumber( const QString &name, const QString &description, Type type, const QVariant &defaultValue, bool optional, double minValue, double maxValue )
3797 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
3798 , mMin( minValue )
3799 , mMax( maxValue )
3800 , mDataType( type )
3801 {
3802 if ( mMin >= mMax )
3803 {
3804 QgsMessageLog::logMessage( QObject::tr( "Invalid number parameter \"%1\": min value %2 is >= max value %3!" ).arg( name ).arg( mMin ).arg( mMax ), QObject::tr( "Processing" ) );
3805 }
3806 }
3807
clone() const3808 QgsProcessingParameterDefinition *QgsProcessingParameterNumber::clone() const
3809 {
3810 return new QgsProcessingParameterNumber( *this );
3811 }
3812
checkValueIsAcceptable(const QVariant & value,QgsProcessingContext *) const3813 bool QgsProcessingParameterNumber::checkValueIsAcceptable( const QVariant &value, QgsProcessingContext * ) const
3814 {
3815 QVariant input = value;
3816 if ( !input.isValid() )
3817 {
3818 if ( !defaultValue().isValid() )
3819 return mFlags & FlagOptional;
3820
3821 input = defaultValue();
3822 }
3823
3824 if ( input.canConvert<QgsProperty>() )
3825 {
3826 return true;
3827 }
3828
3829 bool ok = false;
3830 double res = input.toDouble( &ok );
3831 if ( !ok )
3832 return mFlags & FlagOptional;
3833
3834 return !( res < mMin || res > mMax );
3835 }
3836
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const3837 QString QgsProcessingParameterNumber::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
3838 {
3839 if ( !value.isValid() )
3840 return QStringLiteral( "None" );
3841
3842 if ( value.canConvert<QgsProperty>() )
3843 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
3844
3845 return value.toString();
3846 }
3847
toolTip() const3848 QString QgsProcessingParameterNumber::toolTip() const
3849 {
3850 QString text = QgsProcessingParameterDefinition::toolTip();
3851 QStringList parts;
3852 if ( mMin > std::numeric_limits<double>::lowest() + 1 )
3853 parts << QObject::tr( "Minimum value: %1" ).arg( mMin );
3854 if ( mMax < std::numeric_limits<double>::max() )
3855 parts << QObject::tr( "Maximum value: %1" ).arg( mMax );
3856 if ( mDefault.isValid() )
3857 parts << QObject::tr( "Default value: %1" ).arg( mDataType == Integer ? mDefault.toInt() : mDefault.toDouble() );
3858 QString extra = parts.join( QLatin1String( "<br />" ) );
3859 if ( !extra.isEmpty() )
3860 text += QStringLiteral( "<p>%1</p>" ).arg( extra );
3861 return text;
3862 }
3863
asPythonString(const QgsProcessing::PythonOutputType outputType) const3864 QString QgsProcessingParameterNumber::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
3865 {
3866 switch ( outputType )
3867 {
3868 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
3869 {
3870 QString code = QStringLiteral( "QgsProcessingParameterNumber('%1', '%2'" ).arg( name(), description() );
3871 if ( mFlags & FlagOptional )
3872 code += QLatin1String( ", optional=True" );
3873
3874 code += QStringLiteral( ", type=%1" ).arg( mDataType == Integer ? QStringLiteral( "QgsProcessingParameterNumber.Integer" ) : QStringLiteral( "QgsProcessingParameterNumber.Double" ) );
3875
3876 if ( mMin != std::numeric_limits<double>::lowest() + 1 )
3877 code += QStringLiteral( ", minValue=%1" ).arg( mMin );
3878 if ( mMax != std::numeric_limits<double>::max() )
3879 code += QStringLiteral( ", maxValue=%1" ).arg( mMax );
3880 QgsProcessingContext c;
3881 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
3882 return code;
3883 }
3884 }
3885 return QString();
3886 }
3887
minimum() const3888 double QgsProcessingParameterNumber::minimum() const
3889 {
3890 return mMin;
3891 }
3892
setMinimum(double min)3893 void QgsProcessingParameterNumber::setMinimum( double min )
3894 {
3895 mMin = min;
3896 }
3897
maximum() const3898 double QgsProcessingParameterNumber::maximum() const
3899 {
3900 return mMax;
3901 }
3902
setMaximum(double max)3903 void QgsProcessingParameterNumber::setMaximum( double max )
3904 {
3905 mMax = max;
3906 }
3907
dataType() const3908 QgsProcessingParameterNumber::Type QgsProcessingParameterNumber::dataType() const
3909 {
3910 return mDataType;
3911 }
3912
setDataType(Type dataType)3913 void QgsProcessingParameterNumber::setDataType( Type dataType )
3914 {
3915 mDataType = dataType;
3916 }
3917
toVariantMap() const3918 QVariantMap QgsProcessingParameterNumber::toVariantMap() const
3919 {
3920 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
3921 map.insert( QStringLiteral( "min" ), mMin );
3922 map.insert( QStringLiteral( "max" ), mMax );
3923 map.insert( QStringLiteral( "data_type" ), mDataType );
3924 return map;
3925 }
3926
fromVariantMap(const QVariantMap & map)3927 bool QgsProcessingParameterNumber::fromVariantMap( const QVariantMap &map )
3928 {
3929 QgsProcessingParameterDefinition::fromVariantMap( map );
3930 mMin = map.value( QStringLiteral( "min" ) ).toDouble();
3931 mMax = map.value( QStringLiteral( "max" ) ).toDouble();
3932 mDataType = static_cast< Type >( map.value( QStringLiteral( "data_type" ) ).toInt() );
3933 return true;
3934 }
3935
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)3936 QgsProcessingParameterNumber *QgsProcessingParameterNumber::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
3937 {
3938 return new QgsProcessingParameterNumber( name, description, Double, definition.isEmpty() ? QVariant()
3939 : ( definition.toLower().trimmed() == QLatin1String( "none" ) ? QVariant() : definition ), isOptional );
3940 }
3941
QgsProcessingParameterRange(const QString & name,const QString & description,QgsProcessingParameterNumber::Type type,const QVariant & defaultValue,bool optional)3942 QgsProcessingParameterRange::QgsProcessingParameterRange( const QString &name, const QString &description, QgsProcessingParameterNumber::Type type, const QVariant &defaultValue, bool optional )
3943 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
3944 , mDataType( type )
3945 {
3946
3947 }
3948
clone() const3949 QgsProcessingParameterDefinition *QgsProcessingParameterRange::clone() const
3950 {
3951 return new QgsProcessingParameterRange( *this );
3952 }
3953
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const3954 bool QgsProcessingParameterRange::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
3955 {
3956 if ( !input.isValid() )
3957 return mFlags & FlagOptional;
3958
3959 if ( input.canConvert<QgsProperty>() )
3960 {
3961 return true;
3962 }
3963
3964 if ( input.type() == QVariant::String )
3965 {
3966 QStringList list = input.toString().split( ',' );
3967 if ( list.count() != 2 )
3968 return mFlags & FlagOptional;
3969 bool ok = false;
3970 list.at( 0 ).toDouble( &ok );
3971 bool ok2 = false;
3972 list.at( 1 ).toDouble( &ok2 );
3973 if ( !ok || !ok2 )
3974 return mFlags & FlagOptional;
3975 return true;
3976 }
3977 else if ( input.type() == QVariant::List )
3978 {
3979 if ( input.toList().count() != 2 )
3980 return mFlags & FlagOptional;
3981
3982 bool ok = false;
3983 input.toList().at( 0 ).toDouble( &ok );
3984 bool ok2 = false;
3985 input.toList().at( 1 ).toDouble( &ok2 );
3986 if ( !ok || !ok2 )
3987 return mFlags & FlagOptional;
3988 return true;
3989 }
3990
3991 return false;
3992 }
3993
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const3994 QString QgsProcessingParameterRange::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
3995 {
3996 if ( !value.isValid() )
3997 return QStringLiteral( "None" );
3998
3999 if ( value.canConvert<QgsProperty>() )
4000 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
4001
4002 QVariantMap p;
4003 p.insert( name(), value );
4004 QList< double > parts = QgsProcessingParameters::parameterAsRange( this, p, context );
4005
4006 QStringList stringParts;
4007 const auto constParts = parts;
4008 for ( double v : constParts )
4009 {
4010 stringParts << QString::number( v );
4011 }
4012 return stringParts.join( ',' ).prepend( '[' ).append( ']' );
4013 }
4014
asPythonString(const QgsProcessing::PythonOutputType outputType) const4015 QString QgsProcessingParameterRange::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
4016 {
4017 switch ( outputType )
4018 {
4019 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
4020 {
4021 QString code = QStringLiteral( "QgsProcessingParameterRange('%1', '%2'" ).arg( name(), description() );
4022 if ( mFlags & FlagOptional )
4023 code += QLatin1String( ", optional=True" );
4024
4025 code += QStringLiteral( ", type=%1" ).arg( mDataType == QgsProcessingParameterNumber::Integer ? QStringLiteral( "QgsProcessingParameterNumber.Integer" ) : QStringLiteral( "QgsProcessingParameterNumber.Double" ) );
4026
4027 QgsProcessingContext c;
4028 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
4029 return code;
4030 }
4031 }
4032 return QString();
4033 }
4034
dataType() const4035 QgsProcessingParameterNumber::Type QgsProcessingParameterRange::dataType() const
4036 {
4037 return mDataType;
4038 }
4039
setDataType(QgsProcessingParameterNumber::Type dataType)4040 void QgsProcessingParameterRange::setDataType( QgsProcessingParameterNumber::Type dataType )
4041 {
4042 mDataType = dataType;
4043 }
4044
toVariantMap() const4045 QVariantMap QgsProcessingParameterRange::toVariantMap() const
4046 {
4047 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
4048 map.insert( QStringLiteral( "data_type" ), mDataType );
4049 return map;
4050 }
4051
fromVariantMap(const QVariantMap & map)4052 bool QgsProcessingParameterRange::fromVariantMap( const QVariantMap &map )
4053 {
4054 QgsProcessingParameterDefinition::fromVariantMap( map );
4055 mDataType = static_cast< QgsProcessingParameterNumber::Type >( map.value( QStringLiteral( "data_type" ) ).toInt() );
4056 return true;
4057 }
4058
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4059 QgsProcessingParameterRange *QgsProcessingParameterRange::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4060 {
4061 return new QgsProcessingParameterRange( name, description, QgsProcessingParameterNumber::Double, definition.isEmpty() ? QVariant()
4062 : ( definition.toLower().trimmed() == QLatin1String( "none" ) ? QVariant() : definition ), isOptional );
4063 }
4064
QgsProcessingParameterRasterLayer(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)4065 QgsProcessingParameterRasterLayer::QgsProcessingParameterRasterLayer( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
4066 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4067 {
4068
4069 }
4070
clone() const4071 QgsProcessingParameterDefinition *QgsProcessingParameterRasterLayer::clone() const
4072 {
4073 return new QgsProcessingParameterRasterLayer( *this );
4074 }
4075
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext * context) const4076 bool QgsProcessingParameterRasterLayer::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context ) const
4077 {
4078 if ( !input.isValid() )
4079 return mFlags & FlagOptional;
4080
4081 if ( input.canConvert<QgsProperty>() )
4082 {
4083 return true;
4084 }
4085
4086 if ( qobject_cast< QgsRasterLayer * >( qvariant_cast<QObject *>( input ) ) )
4087 return true;
4088
4089 if ( input.type() != QVariant::String || input.toString().isEmpty() )
4090 return mFlags & FlagOptional;
4091
4092 if ( !context )
4093 {
4094 // that's as far as we can get without a context
4095 return true;
4096 }
4097
4098 // try to load as layer
4099 if ( QgsProcessingUtils::mapLayerFromString( input.toString(), *context, true, QgsProcessingUtils::LayerHint::Raster ) )
4100 return true;
4101
4102 return false;
4103 }
4104
valueAsPythonString(const QVariant & val,QgsProcessingContext & context) const4105 QString QgsProcessingParameterRasterLayer::valueAsPythonString( const QVariant &val, QgsProcessingContext &context ) const
4106 {
4107 if ( !val.isValid() )
4108 return QStringLiteral( "None" );
4109
4110 if ( val.canConvert<QgsProperty>() )
4111 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );
4112
4113 QVariantMap p;
4114 p.insert( name(), val );
4115 QgsRasterLayer *layer = QgsProcessingParameters::parameterAsRasterLayer( this, p, context );
4116 return layer ? QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) )
4117 : QgsProcessingUtils::stringToPythonLiteral( val.toString() );
4118 }
4119
createFileFilter() const4120 QString QgsProcessingParameterRasterLayer::createFileFilter() const
4121 {
4122 return QgsProviderRegistry::instance()->fileRasterFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
4123 }
4124
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4125 QgsProcessingParameterRasterLayer *QgsProcessingParameterRasterLayer::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4126 {
4127 return new QgsProcessingParameterRasterLayer( name, description, definition.isEmpty() ? QVariant() : definition, isOptional );
4128 }
4129
QgsProcessingParameterEnum(const QString & name,const QString & description,const QStringList & options,bool allowMultiple,const QVariant & defaultValue,bool optional)4130 QgsProcessingParameterEnum::QgsProcessingParameterEnum( const QString &name, const QString &description, const QStringList &options, bool allowMultiple, const QVariant &defaultValue, bool optional )
4131 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4132 , mOptions( options )
4133 , mAllowMultiple( allowMultiple )
4134 {
4135
4136 }
4137
clone() const4138 QgsProcessingParameterDefinition *QgsProcessingParameterEnum::clone() const
4139 {
4140 return new QgsProcessingParameterEnum( *this );
4141 }
4142
checkValueIsAcceptable(const QVariant & value,QgsProcessingContext *) const4143 bool QgsProcessingParameterEnum::checkValueIsAcceptable( const QVariant &value, QgsProcessingContext * ) const
4144 {
4145 QVariant input = value;
4146 if ( !input.isValid() )
4147 {
4148 if ( !defaultValue().isValid() )
4149 return mFlags & FlagOptional;
4150
4151 input = defaultValue();
4152 }
4153
4154 if ( input.canConvert<QgsProperty>() )
4155 {
4156 return true;
4157 }
4158
4159 if ( input.type() == QVariant::List )
4160 {
4161 if ( !mAllowMultiple )
4162 return false;
4163
4164 const QVariantList values = input.toList();
4165 if ( values.empty() && !( mFlags & FlagOptional ) )
4166 return false;
4167
4168 for ( const QVariant &val : values )
4169 {
4170 bool ok = false;
4171 int res = val.toInt( &ok );
4172 if ( !ok )
4173 return false;
4174 else if ( res < 0 || res >= mOptions.count() )
4175 return false;
4176 }
4177
4178 return true;
4179 }
4180 else if ( input.type() == QVariant::String )
4181 {
4182 QStringList parts = input.toString().split( ',' );
4183 if ( parts.count() > 1 && !mAllowMultiple )
4184 return false;
4185
4186 const auto constParts = parts;
4187 for ( const QString &part : constParts )
4188 {
4189 bool ok = false;
4190 int res = part.toInt( &ok );
4191 if ( !ok )
4192 return false;
4193 else if ( res < 0 || res >= mOptions.count() )
4194 return false;
4195 }
4196 return true;
4197 }
4198 else if ( input.type() == QVariant::Int || input.type() == QVariant::Double )
4199 {
4200 bool ok = false;
4201 int res = input.toInt( &ok );
4202 if ( !ok )
4203 return false;
4204 else if ( res >= 0 && res < mOptions.count() )
4205 return true;
4206 }
4207 return false;
4208 }
4209
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const4210 QString QgsProcessingParameterEnum::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
4211 {
4212 if ( !value.isValid() )
4213 return QStringLiteral( "None" );
4214
4215 if ( value.canConvert<QgsProperty>() )
4216 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
4217
4218 if ( value.type() == QVariant::List )
4219 {
4220 QStringList parts;
4221 const auto constToList = value.toList();
4222 for ( const QVariant &val : constToList )
4223 {
4224 parts << QString::number( static_cast< int >( val.toDouble() ) );
4225 }
4226 return parts.join( ',' ).prepend( '[' ).append( ']' );
4227 }
4228 else if ( value.type() == QVariant::String )
4229 {
4230 QStringList parts = value.toString().split( ',' );
4231 if ( parts.count() > 1 )
4232 {
4233 return parts.join( ',' ).prepend( '[' ).append( ']' );
4234 }
4235 }
4236
4237 return QString::number( static_cast< int >( value.toDouble() ) );
4238 }
4239
asScriptCode() const4240 QString QgsProcessingParameterEnum::asScriptCode() const
4241 {
4242 QString code = QStringLiteral( "##%1=" ).arg( mName );
4243 if ( mFlags & FlagOptional )
4244 code += QLatin1String( "optional " );
4245 code += QLatin1String( "enum " );
4246
4247 if ( mAllowMultiple )
4248 code += QLatin1String( "multiple " );
4249
4250 code += mOptions.join( ';' ) + ' ';
4251
4252 code += mDefault.toString();
4253 return code.trimmed();
4254 }
4255
asPythonString(const QgsProcessing::PythonOutputType outputType) const4256 QString QgsProcessingParameterEnum::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
4257 {
4258 switch ( outputType )
4259 {
4260 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
4261 {
4262 QString code = QStringLiteral( "QgsProcessingParameterEnum('%1', '%2'" ).arg( name(), description() );
4263 if ( mFlags & FlagOptional )
4264 code += QLatin1String( ", optional=True" );
4265
4266 QStringList options;
4267 options.reserve( mOptions.size() );
4268 for ( const QString &o : mOptions )
4269 options << QgsProcessingUtils::stringToPythonLiteral( o );
4270 code += QStringLiteral( ", options=[%1]" ).arg( options.join( ',' ) );
4271
4272 code += QStringLiteral( ", allowMultiple=%1" ).arg( mAllowMultiple ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
4273
4274 QgsProcessingContext c;
4275 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
4276 return code;
4277 }
4278 }
4279 return QString();
4280 }
4281
options() const4282 QStringList QgsProcessingParameterEnum::options() const
4283 {
4284 return mOptions;
4285 }
4286
setOptions(const QStringList & options)4287 void QgsProcessingParameterEnum::setOptions( const QStringList &options )
4288 {
4289 mOptions = options;
4290 }
4291
allowMultiple() const4292 bool QgsProcessingParameterEnum::allowMultiple() const
4293 {
4294 return mAllowMultiple;
4295 }
4296
setAllowMultiple(bool allowMultiple)4297 void QgsProcessingParameterEnum::setAllowMultiple( bool allowMultiple )
4298 {
4299 mAllowMultiple = allowMultiple;
4300 }
4301
toVariantMap() const4302 QVariantMap QgsProcessingParameterEnum::toVariantMap() const
4303 {
4304 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
4305 map.insert( QStringLiteral( "options" ), mOptions );
4306 map.insert( QStringLiteral( "allow_multiple" ), mAllowMultiple );
4307 return map;
4308 }
4309
fromVariantMap(const QVariantMap & map)4310 bool QgsProcessingParameterEnum::fromVariantMap( const QVariantMap &map )
4311 {
4312 QgsProcessingParameterDefinition::fromVariantMap( map );
4313 mOptions = map.value( QStringLiteral( "options" ) ).toStringList();
4314 mAllowMultiple = map.value( QStringLiteral( "allow_multiple" ) ).toBool();
4315 return true;
4316 }
4317
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4318 QgsProcessingParameterEnum *QgsProcessingParameterEnum::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4319 {
4320 QString defaultVal;
4321 bool multiple = false;
4322 QString def = definition;
4323 if ( def.startsWith( QLatin1String( "multiple" ), Qt::CaseInsensitive ) )
4324 {
4325 multiple = true;
4326 def = def.mid( 9 );
4327 }
4328
4329 QRegularExpression re( QStringLiteral( "(.*)\\s+(.*?)$" ) );
4330 QRegularExpressionMatch m = re.match( def );
4331 QString values = def;
4332 if ( m.hasMatch() )
4333 {
4334 values = m.captured( 1 ).trimmed();
4335 defaultVal = m.captured( 2 );
4336 }
4337
4338 return new QgsProcessingParameterEnum( name, description, values.split( ';' ), multiple, defaultVal.isEmpty() ? QVariant() : defaultVal, isOptional );
4339 }
4340
QgsProcessingParameterString(const QString & name,const QString & description,const QVariant & defaultValue,bool multiLine,bool optional)4341 QgsProcessingParameterString::QgsProcessingParameterString( const QString &name, const QString &description, const QVariant &defaultValue, bool multiLine, bool optional )
4342 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4343 , mMultiLine( multiLine )
4344 {
4345
4346 }
4347
clone() const4348 QgsProcessingParameterDefinition *QgsProcessingParameterString::clone() const
4349 {
4350 return new QgsProcessingParameterString( *this );
4351 }
4352
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const4353 QString QgsProcessingParameterString::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
4354 {
4355 if ( !value.isValid() || value.isNull() )
4356 return QStringLiteral( "None" );
4357
4358 if ( value.canConvert<QgsProperty>() )
4359 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
4360
4361 QString s = value.toString();
4362 return QgsProcessingUtils::stringToPythonLiteral( s );
4363 }
4364
asScriptCode() const4365 QString QgsProcessingParameterString::asScriptCode() const
4366 {
4367 QString code = QStringLiteral( "##%1=" ).arg( mName );
4368 if ( mFlags & FlagOptional )
4369 code += QLatin1String( "optional " );
4370 code += QLatin1String( "string " );
4371
4372 if ( mMultiLine )
4373 code += QLatin1String( "long " );
4374
4375 code += mDefault.toString();
4376 return code.trimmed();
4377 }
4378
asPythonString(const QgsProcessing::PythonOutputType outputType) const4379 QString QgsProcessingParameterString::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
4380 {
4381 switch ( outputType )
4382 {
4383 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
4384 {
4385 QString code = QStringLiteral( "QgsProcessingParameterString('%1', '%2'" ).arg( name(), description() );
4386 if ( mFlags & FlagOptional )
4387 code += QLatin1String( ", optional=True" );
4388 code += QStringLiteral( ", multiLine=%1" ).arg( mMultiLine ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
4389
4390 QgsProcessingContext c;
4391 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
4392 return code;
4393 }
4394 }
4395 return QString();
4396 }
4397
multiLine() const4398 bool QgsProcessingParameterString::multiLine() const
4399 {
4400 return mMultiLine;
4401 }
4402
setMultiLine(bool multiLine)4403 void QgsProcessingParameterString::setMultiLine( bool multiLine )
4404 {
4405 mMultiLine = multiLine;
4406 }
4407
toVariantMap() const4408 QVariantMap QgsProcessingParameterString::toVariantMap() const
4409 {
4410 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
4411 map.insert( QStringLiteral( "multiline" ), mMultiLine );
4412 return map;
4413 }
4414
fromVariantMap(const QVariantMap & map)4415 bool QgsProcessingParameterString::fromVariantMap( const QVariantMap &map )
4416 {
4417 QgsProcessingParameterDefinition::fromVariantMap( map );
4418 mMultiLine = map.value( QStringLiteral( "multiline" ) ).toBool();
4419 return true;
4420 }
4421
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4422 QgsProcessingParameterString *QgsProcessingParameterString::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4423 {
4424 QString def = definition;
4425 bool multiLine = false;
4426 if ( def.startsWith( QLatin1String( "long" ), Qt::CaseInsensitive ) )
4427 {
4428 multiLine = true;
4429 def = def.mid( 5 );
4430 }
4431
4432 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
4433 def = def.mid( 1 );
4434 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
4435 def.chop( 1 );
4436
4437 QVariant defaultValue = def;
4438 if ( def == QLatin1String( "None" ) )
4439 defaultValue = QVariant();
4440
4441 return new QgsProcessingParameterString( name, description, defaultValue, multiLine, isOptional );
4442 }
4443
4444 //
4445 // QgsProcessingParameterAuthConfig
4446 //
4447
QgsProcessingParameterAuthConfig(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)4448 QgsProcessingParameterAuthConfig::QgsProcessingParameterAuthConfig( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
4449 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4450 {
4451
4452 }
4453
clone() const4454 QgsProcessingParameterDefinition *QgsProcessingParameterAuthConfig::clone() const
4455 {
4456 return new QgsProcessingParameterAuthConfig( *this );
4457 }
4458
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const4459 QString QgsProcessingParameterAuthConfig::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
4460 {
4461 if ( !value.isValid() )
4462 return QStringLiteral( "None" );
4463
4464 QString s = value.toString();
4465 return QgsProcessingUtils::stringToPythonLiteral( s );
4466 }
4467
asScriptCode() const4468 QString QgsProcessingParameterAuthConfig::asScriptCode() const
4469 {
4470 QString code = QStringLiteral( "##%1=" ).arg( mName );
4471 if ( mFlags & FlagOptional )
4472 code += QLatin1String( "optional " );
4473 code += QLatin1String( "authcfg " );
4474
4475 code += mDefault.toString();
4476 return code.trimmed();
4477 }
4478
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4479 QgsProcessingParameterAuthConfig *QgsProcessingParameterAuthConfig::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4480 {
4481 QString def = definition;
4482
4483 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
4484 def = def.mid( 1 );
4485 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
4486 def.chop( 1 );
4487
4488 QVariant defaultValue = def;
4489 if ( def == QLatin1String( "None" ) )
4490 defaultValue = QVariant();
4491
4492 return new QgsProcessingParameterAuthConfig( name, description, defaultValue, isOptional );
4493 }
4494
4495
4496 //
4497 // QgsProcessingParameterExpression
4498 //
4499
QgsProcessingParameterExpression(const QString & name,const QString & description,const QVariant & defaultValue,const QString & parentLayerParameterName,bool optional)4500 QgsProcessingParameterExpression::QgsProcessingParameterExpression( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, bool optional )
4501 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4502 , mParentLayerParameterName( parentLayerParameterName )
4503 {
4504
4505 }
4506
clone() const4507 QgsProcessingParameterDefinition *QgsProcessingParameterExpression::clone() const
4508 {
4509 return new QgsProcessingParameterExpression( *this );
4510 }
4511
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const4512 QString QgsProcessingParameterExpression::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
4513 {
4514 if ( !value.isValid() )
4515 return QStringLiteral( "None" );
4516
4517 if ( value.canConvert<QgsProperty>() )
4518 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
4519
4520 QString s = value.toString();
4521 return QgsProcessingUtils::stringToPythonLiteral( s );
4522 }
4523
dependsOnOtherParameters() const4524 QStringList QgsProcessingParameterExpression::dependsOnOtherParameters() const
4525 {
4526 QStringList depends;
4527 if ( !mParentLayerParameterName.isEmpty() )
4528 depends << mParentLayerParameterName;
4529 return depends;
4530 }
4531
asPythonString(const QgsProcessing::PythonOutputType outputType) const4532 QString QgsProcessingParameterExpression::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
4533 {
4534 switch ( outputType )
4535 {
4536 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
4537 {
4538 QString code = QStringLiteral( "QgsProcessingParameterExpression('%1', '%2'" ).arg( name(), description() );
4539 if ( mFlags & FlagOptional )
4540 code += QLatin1String( ", optional=True" );
4541
4542 code += QStringLiteral( ", parentLayerParameterName='%1'" ).arg( mParentLayerParameterName );
4543
4544 QgsProcessingContext c;
4545 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
4546 return code;
4547 }
4548 }
4549 return QString();
4550 }
4551
parentLayerParameterName() const4552 QString QgsProcessingParameterExpression::parentLayerParameterName() const
4553 {
4554 return mParentLayerParameterName;
4555 }
4556
setParentLayerParameterName(const QString & parentLayerParameterName)4557 void QgsProcessingParameterExpression::setParentLayerParameterName( const QString &parentLayerParameterName )
4558 {
4559 mParentLayerParameterName = parentLayerParameterName;
4560 }
4561
toVariantMap() const4562 QVariantMap QgsProcessingParameterExpression::toVariantMap() const
4563 {
4564 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
4565 map.insert( QStringLiteral( "parent_layer" ), mParentLayerParameterName );
4566 return map;
4567 }
4568
fromVariantMap(const QVariantMap & map)4569 bool QgsProcessingParameterExpression::fromVariantMap( const QVariantMap &map )
4570 {
4571 QgsProcessingParameterDefinition::fromVariantMap( map );
4572 mParentLayerParameterName = map.value( QStringLiteral( "parent_layer" ) ).toString();
4573 return true;
4574 }
4575
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4576 QgsProcessingParameterExpression *QgsProcessingParameterExpression::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4577 {
4578 return new QgsProcessingParameterExpression( name, description, definition, QString(), isOptional );
4579 }
4580
QgsProcessingParameterVectorLayer(const QString & name,const QString & description,const QList<int> & types,const QVariant & defaultValue,bool optional)4581 QgsProcessingParameterVectorLayer::QgsProcessingParameterVectorLayer( const QString &name, const QString &description, const QList<int> &types, const QVariant &defaultValue, bool optional )
4582 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4583 , QgsProcessingParameterLimitedDataTypes( types )
4584 {
4585
4586 }
4587
clone() const4588 QgsProcessingParameterDefinition *QgsProcessingParameterVectorLayer::clone() const
4589 {
4590 return new QgsProcessingParameterVectorLayer( *this );
4591 }
4592
checkValueIsAcceptable(const QVariant & v,QgsProcessingContext * context) const4593 bool QgsProcessingParameterVectorLayer::checkValueIsAcceptable( const QVariant &v, QgsProcessingContext *context ) const
4594 {
4595 if ( !v.isValid() )
4596 return mFlags & FlagOptional;
4597
4598 QVariant var = v;
4599
4600 if ( var.canConvert<QgsProperty>() )
4601 {
4602 QgsProperty p = var.value< QgsProperty >();
4603 if ( p.propertyType() == QgsProperty::StaticProperty )
4604 {
4605 var = p.staticValue();
4606 }
4607 else
4608 {
4609 return true;
4610 }
4611 }
4612
4613 if ( qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( var ) ) )
4614 return true;
4615
4616 if ( var.type() != QVariant::String || var.toString().isEmpty() )
4617 return mFlags & FlagOptional;
4618
4619 if ( !context )
4620 {
4621 // that's as far as we can get without a context
4622 return true;
4623 }
4624
4625 // try to load as layer
4626 if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context, true, QgsProcessingUtils::LayerHint::Vector ) )
4627 return true;
4628
4629 return false;
4630 }
4631
valueAsPythonString(const QVariant & val,QgsProcessingContext & context) const4632 QString QgsProcessingParameterVectorLayer::valueAsPythonString( const QVariant &val, QgsProcessingContext &context ) const
4633 {
4634 if ( !val.isValid() )
4635 return QStringLiteral( "None" );
4636
4637 if ( val.canConvert<QgsProperty>() )
4638 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );
4639
4640 QVariantMap p;
4641 p.insert( name(), val );
4642 QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( this, p, context );
4643 return layer ? QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) )
4644 : QgsProcessingUtils::stringToPythonLiteral( val.toString() );
4645 }
4646
asPythonString(const QgsProcessing::PythonOutputType outputType) const4647 QString QgsProcessingParameterVectorLayer::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
4648 {
4649 switch ( outputType )
4650 {
4651 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
4652 {
4653 QString code = QStringLiteral( "QgsProcessingParameterVectorLayer('%1', '%2'" ).arg( name(), description() );
4654 if ( mFlags & FlagOptional )
4655 code += QLatin1String( ", optional=True" );
4656
4657 if ( !mDataTypes.empty() )
4658 {
4659 QStringList options;
4660 for ( int t : mDataTypes )
4661 options << QStringLiteral( "QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( static_cast< QgsProcessing::SourceType >( t ) ) );
4662 code += QStringLiteral( ", types=[%1]" ).arg( options.join( ',' ) );
4663 }
4664
4665 QgsProcessingContext c;
4666 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
4667 return code;
4668 }
4669 }
4670 return QString();
4671 }
4672
createFileFilter() const4673 QString QgsProcessingParameterVectorLayer::createFileFilter() const
4674 {
4675 return QgsProviderRegistry::instance()->fileVectorFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
4676 }
4677
dataTypes() const4678 QList<int> QgsProcessingParameterLimitedDataTypes::dataTypes() const
4679 {
4680 return mDataTypes;
4681 }
4682
setDataTypes(const QList<int> & types)4683 void QgsProcessingParameterLimitedDataTypes::setDataTypes( const QList<int> &types )
4684 {
4685 mDataTypes = types;
4686 }
4687
toVariantMap() const4688 QVariantMap QgsProcessingParameterVectorLayer::toVariantMap() const
4689 {
4690 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
4691 QVariantList types;
4692 for ( int type : mDataTypes )
4693 {
4694 types << type;
4695 }
4696 map.insert( QStringLiteral( "data_types" ), types );
4697 return map;
4698 }
4699
fromVariantMap(const QVariantMap & map)4700 bool QgsProcessingParameterVectorLayer::fromVariantMap( const QVariantMap &map )
4701 {
4702 QgsProcessingParameterDefinition::fromVariantMap( map );
4703 mDataTypes.clear();
4704 const QVariantList values = map.value( QStringLiteral( "data_types" ) ).toList();
4705 for ( const QVariant &val : values )
4706 {
4707 mDataTypes << val.toInt();
4708 }
4709 return true;
4710 }
4711
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4712 QgsProcessingParameterVectorLayer *QgsProcessingParameterVectorLayer::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4713 {
4714 return new QgsProcessingParameterVectorLayer( name, description, QList< int>(), definition.isEmpty() ? QVariant() : definition, isOptional );
4715 }
4716
QgsProcessingParameterMeshLayer(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)4717 QgsProcessingParameterMeshLayer::QgsProcessingParameterMeshLayer( const QString &name,
4718 const QString &description,
4719 const QVariant &defaultValue,
4720 bool optional )
4721 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4722 {
4723
4724 }
4725
clone() const4726 QgsProcessingParameterDefinition *QgsProcessingParameterMeshLayer::clone() const
4727 {
4728 return new QgsProcessingParameterMeshLayer( *this );
4729 }
4730
checkValueIsAcceptable(const QVariant & v,QgsProcessingContext * context) const4731 bool QgsProcessingParameterMeshLayer::checkValueIsAcceptable( const QVariant &v, QgsProcessingContext *context ) const
4732 {
4733 if ( !v.isValid() )
4734 return mFlags & FlagOptional;
4735
4736 QVariant var = v;
4737
4738 if ( var.canConvert<QgsProperty>() )
4739 {
4740 QgsProperty p = var.value< QgsProperty >();
4741 if ( p.propertyType() == QgsProperty::StaticProperty )
4742 {
4743 var = p.staticValue();
4744 }
4745 else
4746 {
4747 return true;
4748 }
4749 }
4750
4751 if ( qobject_cast< QgsMeshLayer * >( qvariant_cast<QObject *>( var ) ) )
4752 return true;
4753
4754 if ( var.type() != QVariant::String || var.toString().isEmpty() )
4755 return mFlags & FlagOptional;
4756
4757 if ( !context )
4758 {
4759 // that's as far as we can get without a context
4760 return true;
4761 }
4762
4763 // try to load as layer
4764 if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context, true, QgsProcessingUtils::LayerHint::Mesh ) )
4765 return true;
4766
4767 return false;
4768 }
4769
valueAsPythonString(const QVariant & val,QgsProcessingContext & context) const4770 QString QgsProcessingParameterMeshLayer::valueAsPythonString( const QVariant &val, QgsProcessingContext &context ) const
4771 {
4772 if ( !val.isValid() )
4773 return QStringLiteral( "None" );
4774
4775 if ( val.canConvert<QgsProperty>() )
4776 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );
4777
4778 QVariantMap p;
4779 p.insert( name(), val );
4780 QgsMeshLayer *layer = QgsProcessingParameters::parameterAsMeshLayer( this, p, context );
4781 return layer ? QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) )
4782 : QgsProcessingUtils::stringToPythonLiteral( val.toString() );
4783 }
4784
createFileFilter() const4785 QString QgsProcessingParameterMeshLayer::createFileFilter() const
4786 {
4787 return QgsProviderRegistry::instance()->fileMeshFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
4788 }
4789
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)4790 QgsProcessingParameterMeshLayer *QgsProcessingParameterMeshLayer::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
4791 {
4792 return new QgsProcessingParameterMeshLayer( name, description, definition.isEmpty() ? QVariant() : definition, isOptional );
4793 }
4794
QgsProcessingParameterField(const QString & name,const QString & description,const QVariant & defaultValue,const QString & parentLayerParameterName,DataType type,bool allowMultiple,bool optional,bool defaultToAllFields)4795 QgsProcessingParameterField::QgsProcessingParameterField( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, DataType type, bool allowMultiple, bool optional, bool defaultToAllFields )
4796 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
4797 , mParentLayerParameterName( parentLayerParameterName )
4798 , mDataType( type )
4799 , mAllowMultiple( allowMultiple )
4800 , mDefaultToAllFields( defaultToAllFields )
4801 {
4802
4803 }
4804
4805
clone() const4806 QgsProcessingParameterDefinition *QgsProcessingParameterField::clone() const
4807 {
4808 return new QgsProcessingParameterField( *this );
4809 }
4810
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const4811 bool QgsProcessingParameterField::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
4812 {
4813 if ( !input.isValid() )
4814 return mFlags & FlagOptional;
4815
4816 if ( input.canConvert<QgsProperty>() )
4817 {
4818 return true;
4819 }
4820
4821 if ( input.type() == QVariant::List || input.type() == QVariant::StringList )
4822 {
4823 if ( !mAllowMultiple )
4824 return false;
4825
4826 if ( input.toList().isEmpty() && !( mFlags & FlagOptional ) )
4827 return false;
4828 }
4829 else if ( input.type() == QVariant::String )
4830 {
4831 if ( input.toString().isEmpty() )
4832 return mFlags & FlagOptional;
4833
4834 QStringList parts = input.toString().split( ';' );
4835 if ( parts.count() > 1 && !mAllowMultiple )
4836 return false;
4837 }
4838 else
4839 {
4840 if ( input.toString().isEmpty() )
4841 return mFlags & FlagOptional;
4842 }
4843 return true;
4844 }
4845
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const4846 QString QgsProcessingParameterField::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
4847 {
4848 if ( !value.isValid() )
4849 return QStringLiteral( "None" );
4850
4851 if ( value.canConvert<QgsProperty>() )
4852 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
4853
4854 if ( value.type() == QVariant::List )
4855 {
4856 QStringList parts;
4857 const auto constToList = value.toList();
4858 for ( const QVariant &val : constToList )
4859 {
4860 parts << QgsProcessingUtils::stringToPythonLiteral( val.toString() );
4861 }
4862 return parts.join( ',' ).prepend( '[' ).append( ']' );
4863 }
4864 else if ( value.type() == QVariant::StringList )
4865 {
4866 QStringList parts;
4867 const auto constToStringList = value.toStringList();
4868 for ( QString s : constToStringList )
4869 {
4870 parts << QgsProcessingUtils::stringToPythonLiteral( s );
4871 }
4872 return parts.join( ',' ).prepend( '[' ).append( ']' );
4873 }
4874
4875 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
4876 }
4877
asScriptCode() const4878 QString QgsProcessingParameterField::asScriptCode() const
4879 {
4880 QString code = QStringLiteral( "##%1=" ).arg( mName );
4881 if ( mFlags & FlagOptional )
4882 code += QLatin1String( "optional " );
4883 code += QLatin1String( "field " );
4884
4885 switch ( mDataType )
4886 {
4887 case Numeric:
4888 code += QLatin1String( "numeric " );
4889 break;
4890
4891 case String:
4892 code += QLatin1String( "string " );
4893 break;
4894
4895 case DateTime:
4896 code += QLatin1String( "datetime " );
4897 break;
4898
4899 case Any:
4900 break;
4901 }
4902
4903 if ( mAllowMultiple )
4904 code += QLatin1String( "multiple " );
4905
4906 if ( mDefaultToAllFields )
4907 code += QLatin1String( "default_to_all_fields " );
4908
4909 code += mParentLayerParameterName + ' ';
4910
4911 code += mDefault.toString();
4912 return code.trimmed();
4913 }
4914
asPythonString(const QgsProcessing::PythonOutputType outputType) const4915 QString QgsProcessingParameterField::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
4916 {
4917 switch ( outputType )
4918 {
4919 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
4920 {
4921 QString code = QStringLiteral( "QgsProcessingParameterField('%1', '%2'" ).arg( name(), description() );
4922 if ( mFlags & FlagOptional )
4923 code += QLatin1String( ", optional=True" );
4924
4925 QString dataType;
4926 switch ( mDataType )
4927 {
4928 case Any:
4929 dataType = QStringLiteral( "QgsProcessingParameterField.Any" );
4930 break;
4931
4932 case Numeric:
4933 dataType = QStringLiteral( "QgsProcessingParameterField.Numeric" );
4934 break;
4935
4936 case String:
4937 dataType = QStringLiteral( "QgsProcessingParameterField.String" );
4938 break;
4939
4940 case DateTime:
4941 dataType = QStringLiteral( "QgsProcessingParameterField.DateTime" );
4942 break;
4943 }
4944 code += QStringLiteral( ", type=%1" ).arg( dataType );
4945
4946 code += QStringLiteral( ", parentLayerParameterName='%1'" ).arg( mParentLayerParameterName );
4947 code += QStringLiteral( ", allowMultiple=%1" ).arg( mAllowMultiple ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
4948 QgsProcessingContext c;
4949 code += QStringLiteral( ", defaultValue=%1" ).arg( valueAsPythonString( mDefault, c ) );
4950
4951 if ( mDefaultToAllFields )
4952 code += QLatin1String( ", defaultToAllFields=True" );
4953
4954 code += ')';
4955
4956 return code;
4957 }
4958 }
4959 return QString();
4960 }
4961
dependsOnOtherParameters() const4962 QStringList QgsProcessingParameterField::dependsOnOtherParameters() const
4963 {
4964 QStringList depends;
4965 if ( !mParentLayerParameterName.isEmpty() )
4966 depends << mParentLayerParameterName;
4967 return depends;
4968 }
4969
parentLayerParameterName() const4970 QString QgsProcessingParameterField::parentLayerParameterName() const
4971 {
4972 return mParentLayerParameterName;
4973 }
4974
setParentLayerParameterName(const QString & parentLayerParameterName)4975 void QgsProcessingParameterField::setParentLayerParameterName( const QString &parentLayerParameterName )
4976 {
4977 mParentLayerParameterName = parentLayerParameterName;
4978 }
4979
dataType() const4980 QgsProcessingParameterField::DataType QgsProcessingParameterField::dataType() const
4981 {
4982 return mDataType;
4983 }
4984
setDataType(DataType dataType)4985 void QgsProcessingParameterField::setDataType( DataType dataType )
4986 {
4987 mDataType = dataType;
4988 }
4989
allowMultiple() const4990 bool QgsProcessingParameterField::allowMultiple() const
4991 {
4992 return mAllowMultiple;
4993 }
4994
setAllowMultiple(bool allowMultiple)4995 void QgsProcessingParameterField::setAllowMultiple( bool allowMultiple )
4996 {
4997 mAllowMultiple = allowMultiple;
4998 }
4999
defaultToAllFields() const5000 bool QgsProcessingParameterField::defaultToAllFields() const
5001 {
5002 return mDefaultToAllFields;
5003 }
5004
setDefaultToAllFields(bool enabled)5005 void QgsProcessingParameterField::setDefaultToAllFields( bool enabled )
5006 {
5007 mDefaultToAllFields = enabled;
5008 }
5009
toVariantMap() const5010 QVariantMap QgsProcessingParameterField::toVariantMap() const
5011 {
5012 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
5013 map.insert( QStringLiteral( "parent_layer" ), mParentLayerParameterName );
5014 map.insert( QStringLiteral( "data_type" ), mDataType );
5015 map.insert( QStringLiteral( "allow_multiple" ), mAllowMultiple );
5016 map.insert( QStringLiteral( "default_to_all_fields" ), mDefaultToAllFields );
5017 return map;
5018 }
5019
fromVariantMap(const QVariantMap & map)5020 bool QgsProcessingParameterField::fromVariantMap( const QVariantMap &map )
5021 {
5022 QgsProcessingParameterDefinition::fromVariantMap( map );
5023 mParentLayerParameterName = map.value( QStringLiteral( "parent_layer" ) ).toString();
5024 mDataType = static_cast< DataType >( map.value( QStringLiteral( "data_type" ) ).toInt() );
5025 mAllowMultiple = map.value( QStringLiteral( "allow_multiple" ) ).toBool();
5026 mDefaultToAllFields = map.value( QStringLiteral( "default_to_all_fields" ) ).toBool();
5027 return true;
5028 }
5029
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)5030 QgsProcessingParameterField *QgsProcessingParameterField::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
5031 {
5032 QString parent;
5033 DataType type = Any;
5034 bool allowMultiple = false;
5035 bool defaultToAllFields = false;
5036 QString def = definition;
5037
5038 if ( def.startsWith( QLatin1String( "numeric " ), Qt::CaseInsensitive ) )
5039 {
5040 type = Numeric;
5041 def = def.mid( 8 );
5042 }
5043 else if ( def.startsWith( QLatin1String( "string " ), Qt::CaseInsensitive ) )
5044 {
5045 type = String;
5046 def = def.mid( 7 );
5047 }
5048 else if ( def.startsWith( QLatin1String( "datetime " ), Qt::CaseInsensitive ) )
5049 {
5050 type = DateTime;
5051 def = def.mid( 9 );
5052 }
5053
5054 if ( def.startsWith( QLatin1String( "multiple" ), Qt::CaseInsensitive ) )
5055 {
5056 allowMultiple = true;
5057 def = def.mid( 8 ).trimmed();
5058 }
5059
5060 if ( def.startsWith( QLatin1String( "default_to_all_fields" ), Qt::CaseInsensitive ) )
5061 {
5062 defaultToAllFields = true;
5063 def = def.mid( 21 ).trimmed();
5064 }
5065
5066 QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*)$" ) );
5067 QRegularExpressionMatch m = re.match( def );
5068 if ( m.hasMatch() )
5069 {
5070 parent = m.captured( 1 ).trimmed();
5071 def = m.captured( 2 );
5072 }
5073 else
5074 {
5075 parent = def;
5076 def.clear();
5077 }
5078
5079 return new QgsProcessingParameterField( name, description, def.isEmpty() ? QVariant() : def, parent, type, allowMultiple, isOptional, defaultToAllFields );
5080 }
5081
QgsProcessingParameterFeatureSource(const QString & name,const QString & description,const QList<int> & types,const QVariant & defaultValue,bool optional)5082 QgsProcessingParameterFeatureSource::QgsProcessingParameterFeatureSource( const QString &name, const QString &description, const QList<int> &types, const QVariant &defaultValue, bool optional )
5083 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
5084 , QgsProcessingParameterLimitedDataTypes( types )
5085 {
5086
5087 }
5088
clone() const5089 QgsProcessingParameterDefinition *QgsProcessingParameterFeatureSource::clone() const
5090 {
5091 return new QgsProcessingParameterFeatureSource( *this );
5092 }
5093
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext * context) const5094 bool QgsProcessingParameterFeatureSource::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context ) const
5095 {
5096 QVariant var = input;
5097 if ( !var.isValid() )
5098 return mFlags & FlagOptional;
5099
5100 if ( var.canConvert<QgsProcessingFeatureSourceDefinition>() )
5101 {
5102 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( var );
5103 var = fromVar.source;
5104 }
5105 else if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
5106 {
5107 // input is a QgsProcessingOutputLayerDefinition - get extra properties from it
5108 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
5109 var = fromVar.sink;
5110 }
5111
5112 if ( var.canConvert<QgsProperty>() )
5113 {
5114 QgsProperty p = var.value< QgsProperty >();
5115 if ( p.propertyType() == QgsProperty::StaticProperty )
5116 {
5117 var = p.staticValue();
5118 }
5119 else
5120 {
5121 return true;
5122 }
5123 }
5124 if ( qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( input ) ) )
5125 {
5126 return true;
5127 }
5128
5129 if ( var.type() != QVariant::String || var.toString().isEmpty() )
5130 return mFlags & FlagOptional;
5131
5132 if ( !context )
5133 {
5134 // that's as far as we can get without a context
5135 return true;
5136 }
5137
5138 // try to load as layer
5139 if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context, true, QgsProcessingUtils::LayerHint::Vector ) )
5140 return true;
5141
5142 return false;
5143 }
5144
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const5145 QString QgsProcessingParameterFeatureSource::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
5146 {
5147 if ( !value.isValid() )
5148 return QStringLiteral( "None" );
5149
5150 if ( value.canConvert<QgsProperty>() )
5151 return QStringLiteral( "QgsProperty.fromExpression(%1)" ).arg( QgsProcessingUtils::stringToPythonLiteral( value.value< QgsProperty >().asExpression() ) );
5152
5153 if ( value.canConvert<QgsProcessingFeatureSourceDefinition>() )
5154 {
5155 QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
5156 QString geometryCheckString;
5157 switch ( fromVar.geometryCheck )
5158 {
5159 case QgsFeatureRequest::GeometryNoCheck:
5160 geometryCheckString = QStringLiteral( "QgsFeatureRequest.GeometryNoCheck" );
5161 break;
5162
5163 case QgsFeatureRequest::GeometrySkipInvalid:
5164 geometryCheckString = QStringLiteral( "QgsFeatureRequest.GeometrySkipInvalid" );
5165 break;
5166
5167 case QgsFeatureRequest::GeometryAbortOnInvalid:
5168 geometryCheckString = QStringLiteral( "QgsFeatureRequest.GeometryAbortOnInvalid" );
5169 break;
5170 }
5171
5172 QStringList flags;
5173 QString flagString;
5174 if ( fromVar.flags & QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck )
5175 flags << QStringLiteral( "QgsProcessingFeatureSourceDefinition.FlagOverrideDefaultGeometryCheck" );
5176 if ( fromVar.flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature )
5177 flags << QStringLiteral( "QgsProcessingFeatureSourceDefinition.FlagCreateIndividualOutputPerInputFeature" );
5178 if ( !flags.empty() )
5179 flagString = flags.join( QLatin1String( " | " ) );
5180
5181 if ( fromVar.source.propertyType() == QgsProperty::StaticProperty )
5182 {
5183 QString layerString = fromVar.source.staticValue().toString();
5184 // prefer to use layer source instead of id if possible (since it's persistent)
5185 if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerString, context, true, QgsProcessingUtils::LayerHint::Vector ) ) )
5186 layerString = layer->source();
5187
5188 if ( fromVar.selectedFeaturesOnly || fromVar.featureLimit != -1 || fromVar.flags )
5189 {
5190 return QStringLiteral( "QgsProcessingFeatureSourceDefinition(%1, selectedFeaturesOnly=%2, featureLimit=%3%4, geometryCheck=%5)" ).arg( QgsProcessingUtils::stringToPythonLiteral( layerString ),
5191 fromVar.selectedFeaturesOnly ? QStringLiteral( "True" ) : QStringLiteral( "False" ),
5192 QString::number( fromVar.featureLimit ),
5193 flagString.isEmpty() ? QString() : ( QStringLiteral( ", flags=%1" ).arg( flagString ) ),
5194 geometryCheckString );
5195 }
5196 else
5197 {
5198 return QgsProcessingUtils::stringToPythonLiteral( layerString );
5199 }
5200 }
5201 else
5202 {
5203 if ( fromVar.selectedFeaturesOnly || fromVar.featureLimit != -1 || fromVar.flags )
5204 {
5205 return QStringLiteral( "QgsProcessingFeatureSourceDefinition(QgsProperty.fromExpression(%1), selectedFeaturesOnly=%2, featureLimit=%3%4, geometryCheck=%5)" )
5206 .arg( QgsProcessingUtils::stringToPythonLiteral( fromVar.source.asExpression() ),
5207 fromVar.selectedFeaturesOnly ? QStringLiteral( "True" ) : QStringLiteral( "False" ),
5208 QString::number( fromVar.featureLimit ),
5209 flagString.isEmpty() ? QString() : ( QStringLiteral( ", flags=%1" ).arg( flagString ) ),
5210 geometryCheckString );
5211 }
5212 else
5213 {
5214 return QStringLiteral( "QgsProperty.fromExpression(%1)" ).arg( QgsProcessingUtils::stringToPythonLiteral( fromVar.source.asExpression() ) );
5215 }
5216 }
5217 }
5218 else if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
5219 {
5220 return QgsProcessingUtils::stringToPythonLiteral( layer->source() );
5221 }
5222
5223 QString layerString = value.toString();
5224
5225 // prefer to use layer source if possible (since it's persistent)
5226 if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerString, context, true, QgsProcessingUtils::LayerHint::Vector ) ) )
5227 layerString = layer->providerType() != QLatin1String( "ogr" ) && layer->providerType() != QLatin1String( "gdal" ) && layer->providerType() != QLatin1String( "mdal" ) ? QgsProcessingUtils::encodeProviderKeyAndUri( layer->providerType(), layer->source() ) : layer->source();
5228
5229 return QgsProcessingUtils::stringToPythonLiteral( layerString );
5230 }
5231
asScriptCode() const5232 QString QgsProcessingParameterFeatureSource::asScriptCode() const
5233 {
5234 QString code = QStringLiteral( "##%1=" ).arg( mName );
5235 if ( mFlags & FlagOptional )
5236 code += QLatin1String( "optional " );
5237 code += QLatin1String( "source " );
5238
5239 for ( int type : mDataTypes )
5240 {
5241 switch ( type )
5242 {
5243 case QgsProcessing::TypeVectorPoint:
5244 code += QLatin1String( "point " );
5245 break;
5246
5247 case QgsProcessing::TypeVectorLine:
5248 code += QLatin1String( "line " );
5249 break;
5250
5251 case QgsProcessing::TypeVectorPolygon:
5252 code += QLatin1String( "polygon " );
5253 break;
5254
5255 }
5256 }
5257
5258 code += mDefault.toString();
5259 return code.trimmed();
5260 }
5261
asPythonString(const QgsProcessing::PythonOutputType outputType) const5262 QString QgsProcessingParameterFeatureSource::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
5263 {
5264 switch ( outputType )
5265 {
5266 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
5267 {
5268 QString code = QStringLiteral( "QgsProcessingParameterFeatureSource('%1', '%2'" ).arg( name(), description() );
5269 if ( mFlags & FlagOptional )
5270 code += QLatin1String( ", optional=True" );
5271
5272 if ( !mDataTypes.empty() )
5273 {
5274 QStringList options;
5275 options.reserve( mDataTypes.size() );
5276 for ( int t : mDataTypes )
5277 options << QStringLiteral( "QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( static_cast< QgsProcessing::SourceType >( t ) ) );
5278 code += QStringLiteral( ", types=[%1]" ).arg( options.join( ',' ) );
5279 }
5280
5281 QgsProcessingContext c;
5282 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
5283 return code;
5284 }
5285 }
5286 return QString();
5287 }
5288
createFileFilter() const5289 QString QgsProcessingParameterFeatureSource::createFileFilter() const
5290 {
5291 return QgsProviderRegistry::instance()->fileVectorFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
5292 }
5293
QgsProcessingParameterLimitedDataTypes(const QList<int> & types)5294 QgsProcessingParameterLimitedDataTypes::QgsProcessingParameterLimitedDataTypes( const QList<int> &types )
5295 : mDataTypes( types )
5296 {
5297
5298 }
5299
toVariantMap() const5300 QVariantMap QgsProcessingParameterFeatureSource::toVariantMap() const
5301 {
5302 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
5303 QVariantList types;
5304 for ( int type : mDataTypes )
5305 {
5306 types << type;
5307 }
5308 map.insert( QStringLiteral( "data_types" ), types );
5309 return map;
5310 }
5311
fromVariantMap(const QVariantMap & map)5312 bool QgsProcessingParameterFeatureSource::fromVariantMap( const QVariantMap &map )
5313 {
5314 QgsProcessingParameterDefinition::fromVariantMap( map );
5315 mDataTypes.clear();
5316 const QVariantList values = map.value( QStringLiteral( "data_types" ) ).toList();
5317 for ( const QVariant &val : values )
5318 {
5319 mDataTypes << val.toInt();
5320 }
5321 return true;
5322 }
5323
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)5324 QgsProcessingParameterFeatureSource *QgsProcessingParameterFeatureSource::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
5325 {
5326 QList< int > types;
5327 QString def = definition;
5328 while ( true )
5329 {
5330 if ( def.startsWith( QLatin1String( "point" ), Qt::CaseInsensitive ) )
5331 {
5332 types << QgsProcessing::TypeVectorPoint;
5333 def = def.mid( 6 );
5334 continue;
5335 }
5336 else if ( def.startsWith( QLatin1String( "line" ), Qt::CaseInsensitive ) )
5337 {
5338 types << QgsProcessing::TypeVectorLine;
5339 def = def.mid( 5 );
5340 continue;
5341 }
5342 else if ( def.startsWith( QLatin1String( "polygon" ), Qt::CaseInsensitive ) )
5343 {
5344 types << QgsProcessing::TypeVectorPolygon;
5345 def = def.mid( 8 );
5346 continue;
5347 }
5348 break;
5349 }
5350
5351 return new QgsProcessingParameterFeatureSource( name, description, types, def, isOptional );
5352 }
5353
QgsProcessingParameterFeatureSink(const QString & name,const QString & description,QgsProcessing::SourceType type,const QVariant & defaultValue,bool optional,bool createByDefault,bool supportsAppend)5354 QgsProcessingParameterFeatureSink::QgsProcessingParameterFeatureSink( const QString &name, const QString &description, QgsProcessing::SourceType type, const QVariant &defaultValue, bool optional, bool createByDefault, bool supportsAppend )
5355 : QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
5356 , mDataType( type )
5357 , mSupportsAppend( supportsAppend )
5358 {
5359 }
5360
clone() const5361 QgsProcessingParameterDefinition *QgsProcessingParameterFeatureSink::clone() const
5362 {
5363 return new QgsProcessingParameterFeatureSink( *this );
5364 }
5365
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const5366 bool QgsProcessingParameterFeatureSink::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
5367 {
5368 QVariant var = input;
5369 if ( !var.isValid() )
5370 return mFlags & FlagOptional;
5371
5372 if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
5373 {
5374 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
5375 var = fromVar.sink;
5376 }
5377
5378 if ( var.canConvert<QgsProperty>() )
5379 {
5380 QgsProperty p = var.value< QgsProperty >();
5381 if ( p.propertyType() == QgsProperty::StaticProperty )
5382 {
5383 var = p.staticValue();
5384 }
5385 else
5386 {
5387 return true;
5388 }
5389 }
5390
5391 if ( var.type() != QVariant::String )
5392 return false;
5393
5394 if ( var.toString().isEmpty() )
5395 return mFlags & FlagOptional;
5396
5397 return true;
5398 }
5399
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const5400 QString QgsProcessingParameterFeatureSink::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
5401 {
5402 if ( !value.isValid() )
5403 return QStringLiteral( "None" );
5404
5405 if ( value.canConvert<QgsProperty>() )
5406 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
5407
5408 if ( value.canConvert<QgsProcessingOutputLayerDefinition>() )
5409 {
5410 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
5411 if ( fromVar.sink.propertyType() == QgsProperty::StaticProperty )
5412 {
5413 return QgsProcessingUtils::stringToPythonLiteral( fromVar.sink.staticValue().toString() );
5414 }
5415 else
5416 {
5417 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( fromVar.sink.asExpression() );
5418 }
5419 }
5420
5421 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
5422 }
5423
asScriptCode() const5424 QString QgsProcessingParameterFeatureSink::asScriptCode() const
5425 {
5426 QString code = QStringLiteral( "##%1=" ).arg( mName );
5427 if ( mFlags & FlagOptional )
5428 code += QLatin1String( "optional " );
5429 code += QLatin1String( "sink " );
5430
5431 switch ( mDataType )
5432 {
5433 case QgsProcessing::TypeVectorPoint:
5434 code += QLatin1String( "point " );
5435 break;
5436
5437 case QgsProcessing::TypeVectorLine:
5438 code += QLatin1String( "line " );
5439 break;
5440
5441 case QgsProcessing::TypeVectorPolygon:
5442 code += QLatin1String( "polygon " );
5443 break;
5444
5445 case QgsProcessing::TypeVector:
5446 code += QLatin1String( "table " );
5447 break;
5448
5449 default:
5450 break;
5451 }
5452
5453 code += mDefault.toString();
5454 return code.trimmed();
5455 }
5456
toOutputDefinition() const5457 QgsProcessingOutputDefinition *QgsProcessingParameterFeatureSink::toOutputDefinition() const
5458 {
5459 return new QgsProcessingOutputVectorLayer( name(), description(), mDataType );
5460 }
5461
defaultFileExtension() const5462 QString QgsProcessingParameterFeatureSink::defaultFileExtension() const
5463 {
5464 if ( auto *lOriginalProvider = originalProvider() )
5465 {
5466 return lOriginalProvider->defaultVectorFileExtension( hasGeometry() );
5467 }
5468 else if ( QgsProcessingProvider *p = provider() )
5469 {
5470 return p->defaultVectorFileExtension( hasGeometry() );
5471 }
5472 else
5473 {
5474 if ( hasGeometry() )
5475 {
5476 return QgsProcessingUtils::defaultVectorExtension();
5477 }
5478 else
5479 {
5480 return QStringLiteral( "dbf" );
5481 }
5482 }
5483 }
5484
asPythonString(const QgsProcessing::PythonOutputType outputType) const5485 QString QgsProcessingParameterFeatureSink::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
5486 {
5487 switch ( outputType )
5488 {
5489 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
5490 {
5491 QString code = QStringLiteral( "QgsProcessingParameterFeatureSink('%1', '%2'" ).arg( name(), description() );
5492 if ( mFlags & FlagOptional )
5493 code += QLatin1String( ", optional=True" );
5494
5495 code += QStringLiteral( ", type=QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( mDataType ) );
5496
5497 code += QStringLiteral( ", createByDefault=%1" ).arg( createByDefault() ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
5498 if ( mSupportsAppend )
5499 code += QLatin1String( ", supportsAppend=True" );
5500
5501 QgsProcessingContext c;
5502 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
5503 return code;
5504 }
5505 }
5506 return QString();
5507 }
5508
createFileFilter() const5509 QString QgsProcessingParameterFeatureSink::createFileFilter() const
5510 {
5511 const QStringList exts = supportedOutputVectorLayerExtensions();
5512 QStringList filters;
5513 for ( const QString &ext : exts )
5514 {
5515 filters << QObject::tr( "%1 files (*.%2)" ).arg( ext.toUpper(), ext.toLower() );
5516 }
5517 return filters.join( QLatin1String( ";;" ) ) + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
5518
5519 }
5520
supportedOutputVectorLayerExtensions() const5521 QStringList QgsProcessingParameterFeatureSink::supportedOutputVectorLayerExtensions() const
5522 {
5523 if ( auto *lOriginalProvider = originalProvider() )
5524 {
5525 if ( hasGeometry() )
5526 return lOriginalProvider->supportedOutputVectorLayerExtensions();
5527 else
5528 return lOriginalProvider->supportedOutputTableExtensions();
5529 }
5530 else if ( QgsProcessingProvider *p = provider() )
5531 {
5532 if ( hasGeometry() )
5533 return p->supportedOutputVectorLayerExtensions();
5534 else
5535 return p->supportedOutputTableExtensions();
5536 }
5537 else
5538 {
5539 return QgsVectorFileWriter::supportedFormatExtensions();
5540 }
5541 }
5542
dataType() const5543 QgsProcessing::SourceType QgsProcessingParameterFeatureSink::dataType() const
5544 {
5545 return mDataType;
5546 }
5547
hasGeometry() const5548 bool QgsProcessingParameterFeatureSink::hasGeometry() const
5549 {
5550 switch ( mDataType )
5551 {
5552 case QgsProcessing::TypeMapLayer:
5553 case QgsProcessing::TypeVectorAnyGeometry:
5554 case QgsProcessing::TypeVectorPoint:
5555 case QgsProcessing::TypeVectorLine:
5556 case QgsProcessing::TypeVectorPolygon:
5557 return true;
5558
5559 case QgsProcessing::TypeRaster:
5560 case QgsProcessing::TypeFile:
5561 case QgsProcessing::TypeVector:
5562 case QgsProcessing::TypeMesh:
5563 return false;
5564 }
5565 return true;
5566 }
5567
setDataType(QgsProcessing::SourceType type)5568 void QgsProcessingParameterFeatureSink::setDataType( QgsProcessing::SourceType type )
5569 {
5570 mDataType = type;
5571 }
5572
toVariantMap() const5573 QVariantMap QgsProcessingParameterFeatureSink::toVariantMap() const
5574 {
5575 QVariantMap map = QgsProcessingDestinationParameter::toVariantMap();
5576 map.insert( QStringLiteral( "data_type" ), mDataType );
5577 map.insert( QStringLiteral( "supports_append" ), mSupportsAppend );
5578 return map;
5579 }
5580
fromVariantMap(const QVariantMap & map)5581 bool QgsProcessingParameterFeatureSink::fromVariantMap( const QVariantMap &map )
5582 {
5583 QgsProcessingDestinationParameter::fromVariantMap( map );
5584 mDataType = static_cast< QgsProcessing::SourceType >( map.value( QStringLiteral( "data_type" ) ).toInt() );
5585 mSupportsAppend = map.value( QStringLiteral( "supports_append" ), false ).toBool();
5586 return true;
5587 }
5588
generateTemporaryDestination() const5589 QString QgsProcessingParameterFeatureSink::generateTemporaryDestination() const
5590 {
5591 if ( supportsNonFileBasedOutput() )
5592 return QStringLiteral( "memory:%1" ).arg( description() );
5593 else
5594 return QgsProcessingDestinationParameter::generateTemporaryDestination();
5595 }
5596
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)5597 QgsProcessingParameterFeatureSink *QgsProcessingParameterFeatureSink::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
5598 {
5599 QgsProcessing::SourceType type = QgsProcessing::TypeVectorAnyGeometry;
5600 QString def = definition;
5601 if ( def.startsWith( QLatin1String( "point" ), Qt::CaseInsensitive ) )
5602 {
5603 type = QgsProcessing::TypeVectorPoint;
5604 def = def.mid( 6 );
5605 }
5606 else if ( def.startsWith( QLatin1String( "line" ), Qt::CaseInsensitive ) )
5607 {
5608 type = QgsProcessing::TypeVectorLine;
5609 def = def.mid( 5 );
5610 }
5611 else if ( def.startsWith( QLatin1String( "polygon" ), Qt::CaseInsensitive ) )
5612 {
5613 type = QgsProcessing::TypeVectorPolygon;
5614 def = def.mid( 8 );
5615 }
5616 else if ( def.startsWith( QLatin1String( "table" ), Qt::CaseInsensitive ) )
5617 {
5618 type = QgsProcessing::TypeVector;
5619 def = def.mid( 6 );
5620 }
5621
5622 return new QgsProcessingParameterFeatureSink( name, description, type, definition, isOptional );
5623 }
5624
supportsAppend() const5625 bool QgsProcessingParameterFeatureSink::supportsAppend() const
5626 {
5627 return mSupportsAppend;
5628 }
5629
setSupportsAppend(bool supportsAppend)5630 void QgsProcessingParameterFeatureSink::setSupportsAppend( bool supportsAppend )
5631 {
5632 mSupportsAppend = supportsAppend;
5633 }
5634
QgsProcessingParameterRasterDestination(const QString & name,const QString & description,const QVariant & defaultValue,bool optional,bool createByDefault)5635 QgsProcessingParameterRasterDestination::QgsProcessingParameterRasterDestination( const QString &name, const QString &description, const QVariant &defaultValue, bool optional, bool createByDefault )
5636 : QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
5637 {
5638 }
5639
clone() const5640 QgsProcessingParameterDefinition *QgsProcessingParameterRasterDestination::clone() const
5641 {
5642 return new QgsProcessingParameterRasterDestination( *this );
5643 }
5644
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const5645 bool QgsProcessingParameterRasterDestination::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
5646 {
5647 QVariant var = input;
5648 if ( !var.isValid() )
5649 return mFlags & FlagOptional;
5650
5651 if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
5652 {
5653 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
5654 var = fromVar.sink;
5655 }
5656
5657 if ( var.canConvert<QgsProperty>() )
5658 {
5659 QgsProperty p = var.value< QgsProperty >();
5660 if ( p.propertyType() == QgsProperty::StaticProperty )
5661 {
5662 var = p.staticValue();
5663 }
5664 else
5665 {
5666 return true;
5667 }
5668 }
5669
5670 if ( var.type() != QVariant::String )
5671 return false;
5672
5673 if ( var.toString().isEmpty() )
5674 return mFlags & FlagOptional;
5675
5676 return true;
5677 }
5678
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const5679 QString QgsProcessingParameterRasterDestination::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
5680 {
5681 if ( !value.isValid() )
5682 return QStringLiteral( "None" );
5683
5684 if ( value.canConvert<QgsProperty>() )
5685 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
5686
5687 if ( value.canConvert<QgsProcessingOutputLayerDefinition>() )
5688 {
5689 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
5690 if ( fromVar.sink.propertyType() == QgsProperty::StaticProperty )
5691 {
5692 return QgsProcessingUtils::stringToPythonLiteral( fromVar.sink.staticValue().toString() );
5693 }
5694 else
5695 {
5696 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( fromVar.sink.asExpression() );
5697 }
5698 }
5699
5700 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
5701 }
5702
toOutputDefinition() const5703 QgsProcessingOutputDefinition *QgsProcessingParameterRasterDestination::toOutputDefinition() const
5704 {
5705 return new QgsProcessingOutputRasterLayer( name(), description() );
5706 }
5707
defaultFileExtension() const5708 QString QgsProcessingParameterRasterDestination::defaultFileExtension() const
5709 {
5710 if ( auto *lOriginalProvider = originalProvider() )
5711 {
5712 return lOriginalProvider->defaultRasterFileExtension();
5713 }
5714 else if ( QgsProcessingProvider *p = provider() )
5715 {
5716 return p->defaultRasterFileExtension();
5717 }
5718 else
5719 {
5720 return QgsProcessingUtils::defaultRasterExtension();
5721 }
5722 }
5723
createFileFilter() const5724 QString QgsProcessingParameterRasterDestination::createFileFilter() const
5725 {
5726 const QStringList exts = supportedOutputRasterLayerExtensions();
5727 QStringList filters;
5728 for ( const QString &ext : exts )
5729 {
5730 filters << QObject::tr( "%1 files (*.%2)" ).arg( ext.toUpper(), ext.toLower() );
5731 }
5732 return filters.join( QLatin1String( ";;" ) ) + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
5733 }
5734
supportedOutputRasterLayerExtensions() const5735 QStringList QgsProcessingParameterRasterDestination::supportedOutputRasterLayerExtensions() const
5736 {
5737 if ( auto *lOriginalProvider = originalProvider() )
5738 {
5739 return lOriginalProvider->supportedOutputRasterLayerExtensions();
5740 }
5741 else if ( QgsProcessingProvider *p = provider() )
5742 {
5743 return p->supportedOutputRasterLayerExtensions();
5744 }
5745 else
5746 {
5747 return QgsRasterFileWriter::supportedFormatExtensions();
5748 }
5749 }
5750
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)5751 QgsProcessingParameterRasterDestination *QgsProcessingParameterRasterDestination::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
5752 {
5753 return new QgsProcessingParameterRasterDestination( name, description, definition.isEmpty() ? QVariant() : definition, isOptional );
5754 }
5755
5756
QgsProcessingParameterFileDestination(const QString & name,const QString & description,const QString & fileFilter,const QVariant & defaultValue,bool optional,bool createByDefault)5757 QgsProcessingParameterFileDestination::QgsProcessingParameterFileDestination( const QString &name, const QString &description, const QString &fileFilter, const QVariant &defaultValue, bool optional, bool createByDefault )
5758 : QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
5759 , mFileFilter( fileFilter.isEmpty() ? QObject::tr( "All files (*.*)" ) : fileFilter )
5760 {
5761
5762 }
5763
clone() const5764 QgsProcessingParameterDefinition *QgsProcessingParameterFileDestination::clone() const
5765 {
5766 return new QgsProcessingParameterFileDestination( *this );
5767 }
5768
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const5769 bool QgsProcessingParameterFileDestination::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
5770 {
5771 QVariant var = input;
5772 if ( !var.isValid() )
5773 return mFlags & FlagOptional;
5774
5775 if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
5776 {
5777 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
5778 var = fromVar.sink;
5779 }
5780
5781 if ( var.canConvert<QgsProperty>() )
5782 {
5783 QgsProperty p = var.value< QgsProperty >();
5784 if ( p.propertyType() == QgsProperty::StaticProperty )
5785 {
5786 var = p.staticValue();
5787 }
5788 else
5789 {
5790 return true;
5791 }
5792 }
5793
5794 if ( var.type() != QVariant::String )
5795 return false;
5796
5797 if ( var.toString().isEmpty() )
5798 return mFlags & FlagOptional;
5799
5800 // possible enhancement - check that value is compatible with file filter?
5801
5802 return true;
5803 }
5804
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const5805 QString QgsProcessingParameterFileDestination::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
5806 {
5807 if ( !value.isValid() )
5808 return QStringLiteral( "None" );
5809
5810 if ( value.canConvert<QgsProperty>() )
5811 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
5812
5813 if ( value.canConvert<QgsProcessingOutputLayerDefinition>() )
5814 {
5815 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
5816 if ( fromVar.sink.propertyType() == QgsProperty::StaticProperty )
5817 {
5818 return QgsProcessingUtils::stringToPythonLiteral( fromVar.sink.staticValue().toString() );
5819 }
5820 else
5821 {
5822 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( fromVar.sink.asExpression() );
5823 }
5824 }
5825
5826 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
5827 }
5828
toOutputDefinition() const5829 QgsProcessingOutputDefinition *QgsProcessingParameterFileDestination::toOutputDefinition() const
5830 {
5831 if ( !mFileFilter.isEmpty() && mFileFilter.contains( QStringLiteral( "htm" ), Qt::CaseInsensitive ) )
5832 {
5833 return new QgsProcessingOutputHtml( name(), description() );
5834 }
5835 else
5836 {
5837 return new QgsProcessingOutputFile( name(), description() );
5838 }
5839 }
5840
defaultFileExtension() const5841 QString QgsProcessingParameterFileDestination::defaultFileExtension() const
5842 {
5843 if ( mFileFilter.isEmpty() || mFileFilter == QObject::tr( "All files (*.*)" ) )
5844 return QStringLiteral( "file" );
5845
5846 // get first extension from filter
5847 QRegularExpression rx( QStringLiteral( ".*?\\(\\*\\.([a-zA-Z0-9._]+).*" ) );
5848 QRegularExpressionMatch match = rx.match( mFileFilter );
5849 if ( !match.hasMatch() )
5850 return QStringLiteral( "file" );
5851
5852 return match.captured( 1 );
5853 }
5854
asPythonString(const QgsProcessing::PythonOutputType outputType) const5855 QString QgsProcessingParameterFileDestination::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
5856 {
5857 switch ( outputType )
5858 {
5859 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
5860 {
5861 QString code = QStringLiteral( "QgsProcessingParameterFileDestination('%1', '%2'" ).arg( name(), description() );
5862 if ( mFlags & FlagOptional )
5863 code += QLatin1String( ", optional=True" );
5864
5865 code += QStringLiteral( ", fileFilter=%1" ).arg( QgsProcessingUtils::stringToPythonLiteral( mFileFilter ) );
5866
5867 code += QStringLiteral( ", createByDefault=%1" ).arg( createByDefault() ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
5868
5869 QgsProcessingContext c;
5870 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
5871 return code;
5872 }
5873 }
5874 return QString();
5875 }
5876
createFileFilter() const5877 QString QgsProcessingParameterFileDestination::createFileFilter() const
5878 {
5879 return ( fileFilter().isEmpty() ? QString() : fileFilter() + QStringLiteral( ";;" ) ) + QObject::tr( "All files (*.*)" );
5880 }
5881
fileFilter() const5882 QString QgsProcessingParameterFileDestination::fileFilter() const
5883 {
5884 return mFileFilter;
5885 }
5886
setFileFilter(const QString & fileFilter)5887 void QgsProcessingParameterFileDestination::setFileFilter( const QString &fileFilter )
5888 {
5889 mFileFilter = fileFilter;
5890 }
5891
toVariantMap() const5892 QVariantMap QgsProcessingParameterFileDestination::toVariantMap() const
5893 {
5894 QVariantMap map = QgsProcessingDestinationParameter::toVariantMap();
5895 map.insert( QStringLiteral( "file_filter" ), mFileFilter );
5896 return map;
5897 }
5898
fromVariantMap(const QVariantMap & map)5899 bool QgsProcessingParameterFileDestination::fromVariantMap( const QVariantMap &map )
5900 {
5901 QgsProcessingDestinationParameter::fromVariantMap( map );
5902 mFileFilter = map.value( QStringLiteral( "file_filter" ) ).toString();
5903 return true;
5904
5905 }
5906
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)5907 QgsProcessingParameterFileDestination *QgsProcessingParameterFileDestination::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
5908 {
5909 return new QgsProcessingParameterFileDestination( name, description, QString(), definition.isEmpty() ? QVariant() : definition, isOptional );
5910 }
5911
QgsProcessingParameterFolderDestination(const QString & name,const QString & description,const QVariant & defaultValue,bool optional,bool createByDefault)5912 QgsProcessingParameterFolderDestination::QgsProcessingParameterFolderDestination( const QString &name, const QString &description, const QVariant &defaultValue, bool optional, bool createByDefault )
5913 : QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
5914 {}
5915
clone() const5916 QgsProcessingParameterDefinition *QgsProcessingParameterFolderDestination::clone() const
5917 {
5918 return new QgsProcessingParameterFolderDestination( *this );
5919 }
5920
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const5921 bool QgsProcessingParameterFolderDestination::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
5922 {
5923 QVariant var = input;
5924 if ( !var.isValid() )
5925 return mFlags & FlagOptional;
5926
5927 if ( var.canConvert<QgsProperty>() )
5928 {
5929 QgsProperty p = var.value< QgsProperty >();
5930 if ( p.propertyType() == QgsProperty::StaticProperty )
5931 {
5932 var = p.staticValue();
5933 }
5934 else
5935 {
5936 return true;
5937 }
5938 }
5939
5940 if ( var.type() != QVariant::String )
5941 return false;
5942
5943 if ( var.toString().isEmpty() )
5944 return mFlags & FlagOptional;
5945
5946 return true;
5947 }
5948
toOutputDefinition() const5949 QgsProcessingOutputDefinition *QgsProcessingParameterFolderDestination::toOutputDefinition() const
5950 {
5951 return new QgsProcessingOutputFolder( name(), description() );
5952 }
5953
defaultFileExtension() const5954 QString QgsProcessingParameterFolderDestination::defaultFileExtension() const
5955 {
5956 return QString();
5957 }
5958
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)5959 QgsProcessingParameterFolderDestination *QgsProcessingParameterFolderDestination::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
5960 {
5961 return new QgsProcessingParameterFolderDestination( name, description, definition.isEmpty() ? QVariant() : definition, isOptional );
5962 }
5963
QgsProcessingDestinationParameter(const QString & name,const QString & description,const QVariant & defaultValue,bool optional,bool createByDefault)5964 QgsProcessingDestinationParameter::QgsProcessingDestinationParameter( const QString &name, const QString &description, const QVariant &defaultValue, bool optional, bool createByDefault )
5965 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
5966 , mCreateByDefault( createByDefault )
5967 {
5968
5969 }
5970
toVariantMap() const5971 QVariantMap QgsProcessingDestinationParameter::toVariantMap() const
5972 {
5973 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
5974 map.insert( QStringLiteral( "supports_non_file_outputs" ), mSupportsNonFileBasedOutputs );
5975 map.insert( QStringLiteral( "create_by_default" ), mCreateByDefault );
5976 return map;
5977 }
5978
fromVariantMap(const QVariantMap & map)5979 bool QgsProcessingDestinationParameter::fromVariantMap( const QVariantMap &map )
5980 {
5981 QgsProcessingParameterDefinition::fromVariantMap( map );
5982 mSupportsNonFileBasedOutputs = map.value( QStringLiteral( "supports_non_file_outputs" ) ).toBool();
5983 mCreateByDefault = map.value( QStringLiteral( "create_by_default" ), QStringLiteral( "1" ) ).toBool();
5984 return true;
5985 }
5986
asPythonString(const QgsProcessing::PythonOutputType outputType) const5987 QString QgsProcessingDestinationParameter::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
5988 {
5989 switch ( outputType )
5990 {
5991 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
5992 {
5993 // base class method is probably not much use
5994 if ( QgsProcessingParameterType *t = QgsApplication::processingRegistry()->parameterType( type() ) )
5995 {
5996 QString code = t->className() + QStringLiteral( "('%1', '%2'" ).arg( name(), description() );
5997 if ( mFlags & FlagOptional )
5998 code += QLatin1String( ", optional=True" );
5999
6000 code += QStringLiteral( ", createByDefault=%1" ).arg( mCreateByDefault ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
6001
6002 QgsProcessingContext c;
6003 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6004 return code;
6005 }
6006 break;
6007 }
6008 }
6009 // oh well, we tried
6010 return QString();
6011 }
6012
createFileFilter() const6013 QString QgsProcessingDestinationParameter::createFileFilter() const
6014 {
6015 return QObject::tr( "Default extension" ) + QStringLiteral( " (*." ) + defaultFileExtension() + ')';
6016 }
6017
generateTemporaryDestination() const6018 QString QgsProcessingDestinationParameter::generateTemporaryDestination() const
6019 {
6020 // sanitize name to avoid multiple . in the filename. E.g. when name() contain
6021 // backend command name having a "." inside as in case of grass commands
6022 QRegularExpression rx( QStringLiteral( "[.]" ) );
6023 QString sanitizedName = name();
6024 sanitizedName.replace( rx, QStringLiteral( "_" ) );
6025
6026 if ( defaultFileExtension().isEmpty() )
6027 {
6028 return QgsProcessingUtils::generateTempFilename( sanitizedName );
6029 }
6030 else
6031 {
6032 return QgsProcessingUtils::generateTempFilename( sanitizedName + '.' + defaultFileExtension() );
6033 }
6034 }
6035
isSupportedOutputValue(const QVariant & value,QgsProcessingContext & context,QString & error) const6036 bool QgsProcessingDestinationParameter::isSupportedOutputValue( const QVariant &value, QgsProcessingContext &context, QString &error ) const
6037 {
6038 if ( auto *lOriginalProvider = originalProvider() )
6039 return lOriginalProvider->isSupportedOutputValue( value, this, context, error );
6040 else if ( provider() )
6041 return provider()->isSupportedOutputValue( value, this, context, error );
6042
6043 return true;
6044 }
6045
createByDefault() const6046 bool QgsProcessingDestinationParameter::createByDefault() const
6047 {
6048 return mCreateByDefault;
6049 }
6050
setCreateByDefault(bool createByDefault)6051 void QgsProcessingDestinationParameter::setCreateByDefault( bool createByDefault )
6052 {
6053 mCreateByDefault = createByDefault;
6054 }
6055
QgsProcessingParameterVectorDestination(const QString & name,const QString & description,QgsProcessing::SourceType type,const QVariant & defaultValue,bool optional,bool createByDefault)6056 QgsProcessingParameterVectorDestination::QgsProcessingParameterVectorDestination( const QString &name, const QString &description, QgsProcessing::SourceType type, const QVariant &defaultValue, bool optional, bool createByDefault )
6057 : QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
6058 , mDataType( type )
6059 {
6060
6061 }
6062
clone() const6063 QgsProcessingParameterDefinition *QgsProcessingParameterVectorDestination::clone() const
6064 {
6065 return new QgsProcessingParameterVectorDestination( *this );
6066 }
6067
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const6068 bool QgsProcessingParameterVectorDestination::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
6069 {
6070 QVariant var = input;
6071 if ( !var.isValid() )
6072 return mFlags & FlagOptional;
6073
6074 if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
6075 {
6076 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
6077 var = fromVar.sink;
6078 }
6079
6080 if ( var.canConvert<QgsProperty>() )
6081 {
6082 QgsProperty p = var.value< QgsProperty >();
6083 if ( p.propertyType() == QgsProperty::StaticProperty )
6084 {
6085 var = p.staticValue();
6086 }
6087 else
6088 {
6089 return true;
6090 }
6091 }
6092
6093 if ( var.type() != QVariant::String )
6094 return false;
6095
6096 if ( var.toString().isEmpty() )
6097 return mFlags & FlagOptional;
6098
6099 return true;
6100 }
6101
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const6102 QString QgsProcessingParameterVectorDestination::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
6103 {
6104 if ( !value.isValid() )
6105 return QStringLiteral( "None" );
6106
6107 if ( value.canConvert<QgsProperty>() )
6108 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
6109
6110 if ( value.canConvert<QgsProcessingOutputLayerDefinition>() )
6111 {
6112 QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
6113 if ( fromVar.sink.propertyType() == QgsProperty::StaticProperty )
6114 {
6115 return QgsProcessingUtils::stringToPythonLiteral( fromVar.sink.staticValue().toString() );
6116 }
6117 else
6118 {
6119 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( fromVar.sink.asExpression() );
6120 }
6121 }
6122
6123 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
6124 }
6125
asScriptCode() const6126 QString QgsProcessingParameterVectorDestination::asScriptCode() const
6127 {
6128 QString code = QStringLiteral( "##%1=" ).arg( mName );
6129 if ( mFlags & FlagOptional )
6130 code += QLatin1String( "optional " );
6131 code += QLatin1String( "vectorDestination " );
6132
6133 switch ( mDataType )
6134 {
6135 case QgsProcessing::TypeVectorPoint:
6136 code += QLatin1String( "point " );
6137 break;
6138
6139 case QgsProcessing::TypeVectorLine:
6140 code += QLatin1String( "line " );
6141 break;
6142
6143 case QgsProcessing::TypeVectorPolygon:
6144 code += QLatin1String( "polygon " );
6145 break;
6146
6147 default:
6148 break;
6149 }
6150
6151 code += mDefault.toString();
6152 return code.trimmed();
6153 }
6154
toOutputDefinition() const6155 QgsProcessingOutputDefinition *QgsProcessingParameterVectorDestination::toOutputDefinition() const
6156 {
6157 return new QgsProcessingOutputVectorLayer( name(), description(), mDataType );
6158 }
6159
defaultFileExtension() const6160 QString QgsProcessingParameterVectorDestination::defaultFileExtension() const
6161 {
6162 if ( auto *lOriginalProvider = originalProvider() )
6163 {
6164 return lOriginalProvider->defaultVectorFileExtension( hasGeometry() );
6165 }
6166 else if ( QgsProcessingProvider *p = provider() )
6167 {
6168 return p->defaultVectorFileExtension( hasGeometry() );
6169 }
6170 else
6171 {
6172 if ( hasGeometry() )
6173 {
6174 return QgsProcessingUtils::defaultVectorExtension();
6175 }
6176 else
6177 {
6178 return QStringLiteral( "dbf" );
6179 }
6180 }
6181 }
6182
asPythonString(const QgsProcessing::PythonOutputType outputType) const6183 QString QgsProcessingParameterVectorDestination::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
6184 {
6185 switch ( outputType )
6186 {
6187 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6188 {
6189 QString code = QStringLiteral( "QgsProcessingParameterVectorDestination('%1', '%2'" ).arg( name(), description() );
6190 if ( mFlags & FlagOptional )
6191 code += QLatin1String( ", optional=True" );
6192
6193 code += QStringLiteral( ", type=QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( mDataType ) );
6194
6195 code += QStringLiteral( ", createByDefault=%1" ).arg( createByDefault() ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
6196
6197 QgsProcessingContext c;
6198 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6199 return code;
6200 }
6201 }
6202 return QString();
6203 }
6204
createFileFilter() const6205 QString QgsProcessingParameterVectorDestination::createFileFilter() const
6206 {
6207 const QStringList exts = supportedOutputVectorLayerExtensions();
6208 QStringList filters;
6209 for ( const QString &ext : exts )
6210 {
6211 filters << QObject::tr( "%1 files (*.%2)" ).arg( ext.toUpper(), ext.toLower() );
6212 }
6213 return filters.join( QLatin1String( ";;" ) ) + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );
6214 }
6215
supportedOutputVectorLayerExtensions() const6216 QStringList QgsProcessingParameterVectorDestination::supportedOutputVectorLayerExtensions() const
6217 {
6218 if ( auto *lOriginalProvider = originalProvider() )
6219 {
6220 if ( hasGeometry() )
6221 return lOriginalProvider->supportedOutputVectorLayerExtensions();
6222 else
6223 return lOriginalProvider->supportedOutputTableExtensions();
6224 }
6225 else if ( QgsProcessingProvider *p = provider() )
6226 {
6227 if ( hasGeometry() )
6228 return p->supportedOutputVectorLayerExtensions();
6229 else
6230 return p->supportedOutputTableExtensions();
6231 }
6232 else
6233 {
6234 return QgsVectorFileWriter::supportedFormatExtensions();
6235 }
6236 }
6237
dataType() const6238 QgsProcessing::SourceType QgsProcessingParameterVectorDestination::dataType() const
6239 {
6240 return mDataType;
6241 }
6242
hasGeometry() const6243 bool QgsProcessingParameterVectorDestination::hasGeometry() const
6244 {
6245 switch ( mDataType )
6246 {
6247 case QgsProcessing::TypeMapLayer:
6248 case QgsProcessing::TypeVectorAnyGeometry:
6249 case QgsProcessing::TypeVectorPoint:
6250 case QgsProcessing::TypeVectorLine:
6251 case QgsProcessing::TypeVectorPolygon:
6252 return true;
6253
6254 case QgsProcessing::TypeRaster:
6255 case QgsProcessing::TypeFile:
6256 case QgsProcessing::TypeVector:
6257 case QgsProcessing::TypeMesh:
6258 return false;
6259 }
6260 return true;
6261 }
6262
setDataType(QgsProcessing::SourceType type)6263 void QgsProcessingParameterVectorDestination::setDataType( QgsProcessing::SourceType type )
6264 {
6265 mDataType = type;
6266 }
6267
toVariantMap() const6268 QVariantMap QgsProcessingParameterVectorDestination::toVariantMap() const
6269 {
6270 QVariantMap map = QgsProcessingDestinationParameter::toVariantMap();
6271 map.insert( QStringLiteral( "data_type" ), mDataType );
6272 return map;
6273 }
6274
fromVariantMap(const QVariantMap & map)6275 bool QgsProcessingParameterVectorDestination::fromVariantMap( const QVariantMap &map )
6276 {
6277 QgsProcessingDestinationParameter::fromVariantMap( map );
6278 mDataType = static_cast< QgsProcessing::SourceType >( map.value( QStringLiteral( "data_type" ) ).toInt() );
6279 return true;
6280 }
6281
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)6282 QgsProcessingParameterVectorDestination *QgsProcessingParameterVectorDestination::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
6283 {
6284 QgsProcessing::SourceType type = QgsProcessing::TypeVectorAnyGeometry;
6285 QString def = definition;
6286 if ( def.startsWith( QLatin1String( "point" ), Qt::CaseInsensitive ) )
6287 {
6288 type = QgsProcessing::TypeVectorPoint;
6289 def = def.mid( 6 );
6290 }
6291 else if ( def.startsWith( QLatin1String( "line" ), Qt::CaseInsensitive ) )
6292 {
6293 type = QgsProcessing::TypeVectorLine;
6294 def = def.mid( 5 );
6295 }
6296 else if ( def.startsWith( QLatin1String( "polygon" ), Qt::CaseInsensitive ) )
6297 {
6298 type = QgsProcessing::TypeVectorPolygon;
6299 def = def.mid( 8 );
6300 }
6301
6302 return new QgsProcessingParameterVectorDestination( name, description, type, definition, isOptional );
6303 }
6304
QgsProcessingParameterBand(const QString & name,const QString & description,const QVariant & defaultValue,const QString & parentLayerParameterName,bool optional,bool allowMultiple)6305 QgsProcessingParameterBand::QgsProcessingParameterBand( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, bool optional, bool allowMultiple )
6306 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
6307 , mParentLayerParameterName( parentLayerParameterName )
6308 , mAllowMultiple( allowMultiple )
6309 {
6310
6311 }
6312
clone() const6313 QgsProcessingParameterDefinition *QgsProcessingParameterBand::clone() const
6314 {
6315 return new QgsProcessingParameterBand( *this );
6316 }
6317
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const6318 bool QgsProcessingParameterBand::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
6319 {
6320 if ( !input.isValid() )
6321 return mFlags & FlagOptional;
6322
6323 if ( input.canConvert<QgsProperty>() )
6324 {
6325 return true;
6326 }
6327
6328 if ( input.type() == QVariant::List || input.type() == QVariant::StringList )
6329 {
6330 if ( !mAllowMultiple )
6331 return false;
6332
6333 if ( input.toList().isEmpty() && !( mFlags & FlagOptional ) )
6334 return false;
6335 }
6336 else
6337 {
6338 bool ok = false;
6339 double res = input.toInt( &ok );
6340 Q_UNUSED( res )
6341 if ( !ok )
6342 return mFlags & FlagOptional;
6343 }
6344 return true;
6345 }
6346
allowMultiple() const6347 bool QgsProcessingParameterBand::allowMultiple() const
6348 {
6349 return mAllowMultiple;
6350 }
6351
setAllowMultiple(bool allowMultiple)6352 void QgsProcessingParameterBand::setAllowMultiple( bool allowMultiple )
6353 {
6354 mAllowMultiple = allowMultiple;
6355 }
6356
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const6357 QString QgsProcessingParameterBand::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
6358 {
6359 if ( !value.isValid() )
6360 return QStringLiteral( "None" );
6361
6362 if ( value.canConvert<QgsProperty>() )
6363 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
6364
6365 if ( value.type() == QVariant::List )
6366 {
6367 QStringList parts;
6368 QVariantList values = value.toList();
6369 for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
6370 {
6371 parts << QString::number( static_cast< int >( it->toDouble() ) );
6372 }
6373 return parts.join( ',' ).prepend( '[' ).append( ']' );
6374 }
6375 else if ( value.type() == QVariant::StringList )
6376 {
6377 QStringList parts;
6378 QStringList values = value.toStringList();
6379 for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
6380 {
6381 parts << QString::number( static_cast< int >( it->toDouble() ) );
6382 }
6383 return parts.join( ',' ).prepend( '[' ).append( ']' );
6384 }
6385
6386 return value.toString();
6387 }
6388
asScriptCode() const6389 QString QgsProcessingParameterBand::asScriptCode() const
6390 {
6391 QString code = QStringLiteral( "##%1=" ).arg( mName );
6392 if ( mFlags & FlagOptional )
6393 code += QLatin1String( "optional " );
6394 code += QLatin1String( "band " );
6395
6396 if ( mAllowMultiple )
6397 code += QLatin1String( "multiple " );
6398
6399 code += mParentLayerParameterName + ' ';
6400
6401 code += mDefault.toString();
6402 return code.trimmed();
6403 }
6404
dependsOnOtherParameters() const6405 QStringList QgsProcessingParameterBand::dependsOnOtherParameters() const
6406 {
6407 QStringList depends;
6408 if ( !mParentLayerParameterName.isEmpty() )
6409 depends << mParentLayerParameterName;
6410 return depends;
6411 }
6412
asPythonString(const QgsProcessing::PythonOutputType outputType) const6413 QString QgsProcessingParameterBand::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
6414 {
6415 switch ( outputType )
6416 {
6417 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6418 {
6419 QString code = QStringLiteral( "QgsProcessingParameterBand('%1', '%2'" ).arg( name(), description() );
6420 if ( mFlags & FlagOptional )
6421 code += QLatin1String( ", optional=True" );
6422
6423 code += QStringLiteral( ", parentLayerParameterName='%1'" ).arg( mParentLayerParameterName );
6424 code += QStringLiteral( ", allowMultiple=%1" ).arg( mAllowMultiple ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
6425
6426 QgsProcessingContext c;
6427 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6428 return code;
6429 }
6430 }
6431 return QString();
6432 }
6433
parentLayerParameterName() const6434 QString QgsProcessingParameterBand::parentLayerParameterName() const
6435 {
6436 return mParentLayerParameterName;
6437 }
6438
setParentLayerParameterName(const QString & parentLayerParameterName)6439 void QgsProcessingParameterBand::setParentLayerParameterName( const QString &parentLayerParameterName )
6440 {
6441 mParentLayerParameterName = parentLayerParameterName;
6442 }
6443
toVariantMap() const6444 QVariantMap QgsProcessingParameterBand::toVariantMap() const
6445 {
6446 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
6447 map.insert( QStringLiteral( "parent_layer" ), mParentLayerParameterName );
6448 map.insert( QStringLiteral( "allow_multiple" ), mAllowMultiple );
6449 return map;
6450 }
6451
fromVariantMap(const QVariantMap & map)6452 bool QgsProcessingParameterBand::fromVariantMap( const QVariantMap &map )
6453 {
6454 QgsProcessingParameterDefinition::fromVariantMap( map );
6455 mParentLayerParameterName = map.value( QStringLiteral( "parent_layer" ) ).toString();
6456 mAllowMultiple = map.value( QStringLiteral( "allow_multiple" ) ).toBool();
6457 return true;
6458 }
6459
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)6460 QgsProcessingParameterBand *QgsProcessingParameterBand::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
6461 {
6462 QString parent;
6463 QString def = definition;
6464 bool allowMultiple = false;
6465
6466 if ( def.startsWith( QLatin1String( "multiple" ), Qt::CaseInsensitive ) )
6467 {
6468 allowMultiple = true;
6469 def = def.mid( 8 ).trimmed();
6470 }
6471
6472 QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*)$" ) );
6473 QRegularExpressionMatch m = re.match( def );
6474 if ( m.hasMatch() )
6475 {
6476 parent = m.captured( 1 ).trimmed();
6477 def = m.captured( 2 );
6478 }
6479 else
6480 {
6481 parent = def;
6482 def.clear();
6483 }
6484
6485 return new QgsProcessingParameterBand( name, description, def.isEmpty() ? QVariant() : def, parent, isOptional, allowMultiple );
6486 }
6487
6488 //
6489 // QgsProcessingParameterDistance
6490 //
6491
QgsProcessingParameterDistance(const QString & name,const QString & description,const QVariant & defaultValue,const QString & parentParameterName,bool optional,double minValue,double maxValue)6492 QgsProcessingParameterDistance::QgsProcessingParameterDistance( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentParameterName, bool optional, double minValue, double maxValue )
6493 : QgsProcessingParameterNumber( name, description, Double, defaultValue, optional, minValue, maxValue )
6494 , mParentParameterName( parentParameterName )
6495 {
6496
6497 }
6498
clone() const6499 QgsProcessingParameterDistance *QgsProcessingParameterDistance::clone() const
6500 {
6501 return new QgsProcessingParameterDistance( *this );
6502 }
6503
type() const6504 QString QgsProcessingParameterDistance::type() const
6505 {
6506 return typeName();
6507 }
6508
dependsOnOtherParameters() const6509 QStringList QgsProcessingParameterDistance::dependsOnOtherParameters() const
6510 {
6511 QStringList depends;
6512 if ( !mParentParameterName.isEmpty() )
6513 depends << mParentParameterName;
6514 return depends;
6515 }
6516
asPythonString(const QgsProcessing::PythonOutputType outputType) const6517 QString QgsProcessingParameterDistance::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
6518 {
6519 switch ( outputType )
6520 {
6521 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6522 {
6523 QString code = QStringLiteral( "QgsProcessingParameterDistance('%1', '%2'" ).arg( name(), description() );
6524 if ( mFlags & FlagOptional )
6525 code += QLatin1String( ", optional=True" );
6526
6527 code += QStringLiteral( ", parentParameterName='%1'" ).arg( mParentParameterName );
6528
6529 if ( minimum() != std::numeric_limits<double>::lowest() + 1 )
6530 code += QStringLiteral( ", minValue=%1" ).arg( minimum() );
6531 if ( maximum() != std::numeric_limits<double>::max() )
6532 code += QStringLiteral( ", maxValue=%1" ).arg( maximum() );
6533 QgsProcessingContext c;
6534 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6535 return code;
6536 }
6537 }
6538 return QString();
6539 }
6540
parentParameterName() const6541 QString QgsProcessingParameterDistance::parentParameterName() const
6542 {
6543 return mParentParameterName;
6544 }
6545
setParentParameterName(const QString & parentParameterName)6546 void QgsProcessingParameterDistance::setParentParameterName( const QString &parentParameterName )
6547 {
6548 mParentParameterName = parentParameterName;
6549 }
6550
toVariantMap() const6551 QVariantMap QgsProcessingParameterDistance::toVariantMap() const
6552 {
6553 QVariantMap map = QgsProcessingParameterNumber::toVariantMap();
6554 map.insert( QStringLiteral( "parent" ), mParentParameterName );
6555 map.insert( QStringLiteral( "default_unit" ), static_cast< int >( mDefaultUnit ) );
6556 return map;
6557 }
6558
fromVariantMap(const QVariantMap & map)6559 bool QgsProcessingParameterDistance::fromVariantMap( const QVariantMap &map )
6560 {
6561 QgsProcessingParameterNumber::fromVariantMap( map );
6562 mParentParameterName = map.value( QStringLiteral( "parent" ) ).toString();
6563 mDefaultUnit = static_cast< QgsUnitTypes::DistanceUnit>( map.value( QStringLiteral( "default_unit" ), QgsUnitTypes::DistanceUnknownUnit ).toInt() );
6564 return true;
6565 }
6566
6567
6568 //
6569 // QgsProcessingParameterScale
6570 //
6571
QgsProcessingParameterScale(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)6572 QgsProcessingParameterScale::QgsProcessingParameterScale( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
6573 : QgsProcessingParameterNumber( name, description, Double, defaultValue, optional )
6574 {
6575
6576 }
6577
clone() const6578 QgsProcessingParameterScale *QgsProcessingParameterScale::clone() const
6579 {
6580 return new QgsProcessingParameterScale( *this );
6581 }
6582
type() const6583 QString QgsProcessingParameterScale::type() const
6584 {
6585 return typeName();
6586 }
6587
asPythonString(const QgsProcessing::PythonOutputType outputType) const6588 QString QgsProcessingParameterScale::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
6589 {
6590 switch ( outputType )
6591 {
6592 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6593 {
6594 QString code = QStringLiteral( "QgsProcessingParameterScale('%1', '%2'" ).arg( name(), description() );
6595 if ( mFlags & FlagOptional )
6596 code += QLatin1String( ", optional=True" );
6597 QgsProcessingContext c;
6598 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6599 return code;
6600 }
6601 }
6602 return QString();
6603 }
6604
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)6605 QgsProcessingParameterScale *QgsProcessingParameterScale::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
6606 {
6607 return new QgsProcessingParameterScale( name, description, definition.isEmpty() ? QVariant()
6608 : ( definition.toLower().trimmed() == QLatin1String( "none" ) ? QVariant() : definition ), isOptional );
6609 }
6610
6611
6612 //
6613 // QgsProcessingParameterLayout
6614 //
6615
QgsProcessingParameterLayout(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)6616 QgsProcessingParameterLayout::QgsProcessingParameterLayout( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
6617 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
6618 {}
6619
clone() const6620 QgsProcessingParameterDefinition *QgsProcessingParameterLayout::clone() const
6621 {
6622 return new QgsProcessingParameterLayout( *this );
6623 }
6624
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const6625 QString QgsProcessingParameterLayout::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
6626 {
6627 if ( !value.isValid() || value.isNull() )
6628 return QStringLiteral( "None" );
6629
6630 if ( value.canConvert<QgsProperty>() )
6631 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
6632
6633 QString s = value.toString();
6634 return QgsProcessingUtils::stringToPythonLiteral( s );
6635 }
6636
asScriptCode() const6637 QString QgsProcessingParameterLayout::asScriptCode() const
6638 {
6639 QString code = QStringLiteral( "##%1=" ).arg( mName );
6640 if ( mFlags & FlagOptional )
6641 code += QLatin1String( "optional " );
6642 code += QLatin1String( "layout " );
6643
6644 code += mDefault.toString();
6645 return code.trimmed();
6646 }
6647
asPythonString(const QgsProcessing::PythonOutputType outputType) const6648 QString QgsProcessingParameterLayout::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
6649 {
6650 switch ( outputType )
6651 {
6652 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6653 {
6654 QString code = QStringLiteral( "QgsProcessingParameterLayout('%1', '%2'" ).arg( name(), description() );
6655 if ( mFlags & FlagOptional )
6656 code += QLatin1String( ", optional=True" );
6657 QgsProcessingContext c;
6658 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6659 return code;
6660 }
6661 }
6662 return QString();
6663 }
6664
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)6665 QgsProcessingParameterLayout *QgsProcessingParameterLayout::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
6666 {
6667 QString def = definition;
6668
6669 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
6670 def = def.mid( 1 );
6671 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
6672 def.chop( 1 );
6673
6674 QVariant defaultValue = def;
6675 if ( def == QLatin1String( "None" ) )
6676 defaultValue = QVariant();
6677
6678 return new QgsProcessingParameterLayout( name, description, defaultValue, isOptional );
6679 }
6680
6681
6682 //
6683 // QString mParentLayerParameterName;
6684 //
6685
QgsProcessingParameterLayoutItem(const QString & name,const QString & description,const QVariant & defaultValue,const QString & parentLayoutParameterName,int itemType,bool optional)6686 QgsProcessingParameterLayoutItem::QgsProcessingParameterLayoutItem( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayoutParameterName, int itemType, bool optional )
6687 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
6688 , mParentLayoutParameterName( parentLayoutParameterName )
6689 , mItemType( itemType )
6690 {
6691
6692 }
6693
clone() const6694 QgsProcessingParameterDefinition *QgsProcessingParameterLayoutItem::clone() const
6695 {
6696 return new QgsProcessingParameterLayoutItem( *this );
6697 }
6698
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const6699 QString QgsProcessingParameterLayoutItem::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
6700 {
6701 if ( !value.isValid() || value.isNull() )
6702 return QStringLiteral( "None" );
6703
6704 if ( value.canConvert<QgsProperty>() )
6705 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
6706
6707 QString s = value.toString();
6708 return QgsProcessingUtils::stringToPythonLiteral( s );
6709 }
6710
asScriptCode() const6711 QString QgsProcessingParameterLayoutItem::asScriptCode() const
6712 {
6713 QString code = QStringLiteral( "##%1=" ).arg( mName );
6714 if ( mFlags & FlagOptional )
6715 code += QLatin1String( "optional " );
6716 code += QLatin1String( "layoutitem " );
6717 if ( mItemType >= 0 )
6718 code += QString::number( mItemType ) + ' ';
6719
6720 code += mParentLayoutParameterName + ' ';
6721
6722 code += mDefault.toString();
6723 return code.trimmed();
6724 }
6725
asPythonString(QgsProcessing::PythonOutputType outputType) const6726 QString QgsProcessingParameterLayoutItem::asPythonString( QgsProcessing::PythonOutputType outputType ) const
6727 {
6728 switch ( outputType )
6729 {
6730 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6731 {
6732 QString code = QStringLiteral( "QgsProcessingParameterLayoutItem('%1', '%2'" ).arg( name(), description() );
6733 if ( mFlags & FlagOptional )
6734 code += QLatin1String( ", optional=True" );
6735
6736 if ( mItemType >= 0 )
6737 code += QStringLiteral( ", itemType=%1" ).arg( mItemType );
6738
6739 code += QStringLiteral( ", parentLayoutParameterName='%1'" ).arg( mParentLayoutParameterName );
6740
6741 QgsProcessingContext c;
6742 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6743 return code;
6744 }
6745 }
6746 return QString();
6747 }
6748
toVariantMap() const6749 QVariantMap QgsProcessingParameterLayoutItem::toVariantMap() const
6750 {
6751 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
6752 map.insert( QStringLiteral( "parent_layout" ), mParentLayoutParameterName );
6753 map.insert( QStringLiteral( "item_type" ), mItemType );
6754 return map;
6755 }
6756
fromVariantMap(const QVariantMap & map)6757 bool QgsProcessingParameterLayoutItem::fromVariantMap( const QVariantMap &map )
6758 {
6759 QgsProcessingParameterDefinition::fromVariantMap( map );
6760 mParentLayoutParameterName = map.value( QStringLiteral( "parent_layout" ) ).toString();
6761 mItemType = map.value( QStringLiteral( "item_type" ) ).toInt();
6762 return true;
6763 }
6764
dependsOnOtherParameters() const6765 QStringList QgsProcessingParameterLayoutItem::dependsOnOtherParameters() const
6766 {
6767 QStringList depends;
6768 if ( !mParentLayoutParameterName.isEmpty() )
6769 depends << mParentLayoutParameterName;
6770 return depends;
6771 }
6772
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)6773 QgsProcessingParameterLayoutItem *QgsProcessingParameterLayoutItem::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
6774 {
6775 QString parent;
6776 QString def = definition;
6777 int itemType = -1;
6778 QRegularExpression re( QStringLiteral( "(\\d+)?\\s*(.*?)\\s+(.*)$" ) );
6779 QRegularExpressionMatch m = re.match( def );
6780 if ( m.hasMatch() )
6781 {
6782 itemType = m.captured( 1 ).trimmed().isEmpty() ? -1 : m.captured( 1 ).trimmed().toInt();
6783 parent = m.captured( 2 ).trimmed().isEmpty() ? m.captured( 3 ).trimmed() : m.captured( 2 ).trimmed();
6784 def = !m.captured( 2 ).trimmed().isEmpty() ? m.captured( 3 ) : QString();
6785 }
6786 else
6787 {
6788 parent = def;
6789 def.clear();
6790 }
6791
6792 return new QgsProcessingParameterLayoutItem( name, description, def.isEmpty() ? QVariant() : def, parent, itemType, isOptional );
6793 }
6794
parentLayoutParameterName() const6795 QString QgsProcessingParameterLayoutItem::parentLayoutParameterName() const
6796 {
6797 return mParentLayoutParameterName;
6798 }
6799
setParentLayoutParameterName(const QString & name)6800 void QgsProcessingParameterLayoutItem::setParentLayoutParameterName( const QString &name )
6801 {
6802 mParentLayoutParameterName = name;
6803 }
6804
itemType() const6805 int QgsProcessingParameterLayoutItem::itemType() const
6806 {
6807 return mItemType;
6808 }
6809
setItemType(int type)6810 void QgsProcessingParameterLayoutItem::setItemType( int type )
6811 {
6812 mItemType = type;
6813 }
6814
6815 //
6816 // QgsProcessingParameterColor
6817 //
6818
QgsProcessingParameterColor(const QString & name,const QString & description,const QVariant & defaultValue,bool opacityEnabled,bool optional)6819 QgsProcessingParameterColor::QgsProcessingParameterColor( const QString &name, const QString &description, const QVariant &defaultValue, bool opacityEnabled, bool optional )
6820 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
6821 , mAllowOpacity( opacityEnabled )
6822 {
6823
6824 }
6825
clone() const6826 QgsProcessingParameterDefinition *QgsProcessingParameterColor::clone() const
6827 {
6828 return new QgsProcessingParameterColor( *this );
6829 }
6830
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const6831 QString QgsProcessingParameterColor::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
6832 {
6833 if ( !value.isValid() || value.isNull() )
6834 return QStringLiteral( "None" );
6835
6836 if ( value.canConvert<QgsProperty>() )
6837 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
6838
6839 if ( value.canConvert< QColor >() && !value.value< QColor >().isValid() )
6840 return QStringLiteral( "QColor()" );
6841
6842 if ( value.canConvert< QColor >() )
6843 {
6844 QColor c = value.value< QColor >();
6845 if ( !mAllowOpacity || c.alpha() == 255 )
6846 return QStringLiteral( "QColor(%1, %2, %3)" ).arg( c.red() ).arg( c.green() ).arg( c.blue() );
6847 else
6848 return QStringLiteral( "QColor(%1, %2, %3, %4)" ).arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() );
6849 }
6850
6851 QString s = value.toString();
6852 return QgsProcessingUtils::stringToPythonLiteral( s );
6853 }
6854
asScriptCode() const6855 QString QgsProcessingParameterColor::asScriptCode() const
6856 {
6857 QString code = QStringLiteral( "##%1=" ).arg( mName );
6858 if ( mFlags & FlagOptional )
6859 code += QLatin1String( "optional " );
6860 code += QLatin1String( "color " );
6861
6862 if ( mAllowOpacity )
6863 code += QLatin1String( "withopacity " );
6864
6865 code += mDefault.toString();
6866 return code.trimmed();
6867 }
6868
asPythonString(const QgsProcessing::PythonOutputType outputType) const6869 QString QgsProcessingParameterColor::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
6870 {
6871 switch ( outputType )
6872 {
6873 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
6874 {
6875 QString code = QStringLiteral( "QgsProcessingParameterColor('%1', '%2'" ).arg( name(), description() );
6876 if ( mFlags & FlagOptional )
6877 code += QLatin1String( ", optional=True" );
6878
6879 code += QStringLiteral( ", opacityEnabled=%1" ).arg( mAllowOpacity ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
6880
6881 QgsProcessingContext c;
6882 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
6883 return code;
6884 }
6885 }
6886 return QString();
6887 }
6888
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const6889 bool QgsProcessingParameterColor::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
6890 {
6891 if ( !input.isValid() && ( mDefault.isValid() && ( !mDefault.toString().isEmpty() || mDefault.value< QColor >().isValid() ) ) )
6892 return true;
6893
6894 if ( !input.isValid() )
6895 return mFlags & FlagOptional;
6896
6897 if ( input.type() == QVariant::Color )
6898 {
6899 return true;
6900 }
6901 else if ( input.canConvert<QgsProperty>() )
6902 {
6903 return true;
6904 }
6905
6906 if ( input.type() != QVariant::String || input.toString().isEmpty() )
6907 return mFlags & FlagOptional;
6908
6909 bool containsAlpha = false;
6910 return QgsSymbolLayerUtils::parseColorWithAlpha( input.toString(), containsAlpha ).isValid();
6911 }
6912
toVariantMap() const6913 QVariantMap QgsProcessingParameterColor::toVariantMap() const
6914 {
6915 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
6916 map.insert( QStringLiteral( "opacityEnabled" ), mAllowOpacity );
6917 return map;
6918 }
6919
fromVariantMap(const QVariantMap & map)6920 bool QgsProcessingParameterColor::fromVariantMap( const QVariantMap &map )
6921 {
6922 QgsProcessingParameterDefinition::fromVariantMap( map );
6923 mAllowOpacity = map.value( QStringLiteral( "opacityEnabled" ) ).toBool();
6924 return true;
6925 }
6926
opacityEnabled() const6927 bool QgsProcessingParameterColor::opacityEnabled() const
6928 {
6929 return mAllowOpacity;
6930 }
6931
setOpacityEnabled(bool enabled)6932 void QgsProcessingParameterColor::setOpacityEnabled( bool enabled )
6933 {
6934 mAllowOpacity = enabled;
6935 }
6936
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)6937 QgsProcessingParameterColor *QgsProcessingParameterColor::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
6938 {
6939 QString def = definition;
6940
6941 bool allowOpacity = false;
6942 if ( def.startsWith( QLatin1String( "withopacity" ), Qt::CaseInsensitive ) )
6943 {
6944 allowOpacity = true;
6945 def = def.mid( 12 );
6946 }
6947
6948 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
6949 def = def.mid( 1 );
6950 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
6951 def.chop( 1 );
6952
6953 QVariant defaultValue = def;
6954 if ( def == QLatin1String( "None" ) )
6955 defaultValue = QVariant();
6956
6957 return new QgsProcessingParameterColor( name, description, defaultValue, allowOpacity, isOptional );
6958 }
6959
6960 //
6961 // QgsProcessingParameterCoordinateOperation
6962 //
QgsProcessingParameterCoordinateOperation(const QString & name,const QString & description,const QVariant & defaultValue,const QString & sourceCrsParameterName,const QString & destinationCrsParameterName,const QVariant & staticSourceCrs,const QVariant & staticDestinationCrs,bool optional)6963 QgsProcessingParameterCoordinateOperation::QgsProcessingParameterCoordinateOperation( const QString &name, const QString &description, const QVariant &defaultValue, const QString &sourceCrsParameterName, const QString &destinationCrsParameterName, const QVariant &staticSourceCrs, const QVariant &staticDestinationCrs, bool optional )
6964 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
6965 , mSourceParameterName( sourceCrsParameterName )
6966 , mDestParameterName( destinationCrsParameterName )
6967 , mSourceCrs( staticSourceCrs )
6968 , mDestCrs( staticDestinationCrs )
6969 {
6970
6971 }
6972
clone() const6973 QgsProcessingParameterDefinition *QgsProcessingParameterCoordinateOperation::clone() const
6974 {
6975 return new QgsProcessingParameterCoordinateOperation( * this );
6976 }
6977
valueAsPythonString(const QVariant & value,QgsProcessingContext & context) const6978 QString QgsProcessingParameterCoordinateOperation::valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const
6979 {
6980 if ( !value.isValid() || value.isNull() )
6981 return QStringLiteral( "None" );
6982
6983 if ( value.canConvert<QgsCoordinateReferenceSystem>() )
6984 {
6985 if ( !value.value< QgsCoordinateReferenceSystem >().isValid() )
6986 return QStringLiteral( "QgsCoordinateReferenceSystem()" );
6987 else
6988 return QStringLiteral( "QgsCoordinateReferenceSystem('%1')" ).arg( value.value< QgsCoordinateReferenceSystem >().authid() );
6989 }
6990
6991 if ( value.canConvert<QgsProperty>() )
6992 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
6993
6994 QVariantMap p;
6995 p.insert( name(), value );
6996 QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( this, p, context );
6997 if ( layer )
6998 return QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) );
6999
7000 QString s = value.toString();
7001 return QgsProcessingUtils::stringToPythonLiteral( s );
7002 }
7003
asScriptCode() const7004 QString QgsProcessingParameterCoordinateOperation::asScriptCode() const
7005 {
7006 QString code = QStringLiteral( "##%1=" ).arg( mName );
7007 if ( mFlags & FlagOptional )
7008 code += QLatin1String( "optional " );
7009 code += QLatin1String( "coordinateoperation " );
7010
7011 code += mDefault.toString();
7012 return code.trimmed();
7013 }
7014
asPythonString(QgsProcessing::PythonOutputType outputType) const7015 QString QgsProcessingParameterCoordinateOperation::asPythonString( QgsProcessing::PythonOutputType outputType ) const
7016 {
7017 switch ( outputType )
7018 {
7019 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
7020 {
7021 QgsProcessingContext c;
7022 QString code = QStringLiteral( "QgsProcessingParameterCoordinateOperation('%1', '%2'" ).arg( name(), description() );
7023 if ( mFlags & FlagOptional )
7024 code += QLatin1String( ", optional=True" );
7025 if ( !mSourceParameterName.isEmpty() )
7026 code += QStringLiteral( ", sourceCrsParameterName=%1" ).arg( valueAsPythonString( mSourceParameterName, c ) );
7027 if ( !mDestParameterName.isEmpty() )
7028 code += QStringLiteral( ", destinationCrsParameterName=%1" ).arg( valueAsPythonString( mDestParameterName, c ) );
7029
7030 if ( mSourceCrs.isValid() )
7031 code += QStringLiteral( ", staticSourceCrs=%1" ).arg( valueAsPythonString( mSourceCrs, c ) );
7032 if ( mDestCrs.isValid() )
7033 code += QStringLiteral( ", staticDestinationCrs=%1" ).arg( valueAsPythonString( mDestCrs, c ) );
7034
7035 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
7036 return code;
7037 }
7038 }
7039 return QString();
7040 }
7041
dependsOnOtherParameters() const7042 QStringList QgsProcessingParameterCoordinateOperation::dependsOnOtherParameters() const
7043 {
7044 QStringList res;
7045 if ( !mSourceParameterName.isEmpty() )
7046 res << mSourceParameterName;
7047 if ( !mDestParameterName.isEmpty() )
7048 res << mDestParameterName;
7049 return res;
7050 }
7051
toVariantMap() const7052 QVariantMap QgsProcessingParameterCoordinateOperation::toVariantMap() const
7053 {
7054 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
7055 map.insert( QStringLiteral( "source_crs_parameter_name" ), mSourceParameterName );
7056 map.insert( QStringLiteral( "dest_crs_parameter_name" ), mDestParameterName );
7057 map.insert( QStringLiteral( "static_source_crs" ), mSourceCrs );
7058 map.insert( QStringLiteral( "static_dest_crs" ), mDestCrs );
7059 return map;
7060 }
7061
fromVariantMap(const QVariantMap & map)7062 bool QgsProcessingParameterCoordinateOperation::fromVariantMap( const QVariantMap &map )
7063 {
7064 QgsProcessingParameterDefinition::fromVariantMap( map );
7065 mSourceParameterName = map.value( QStringLiteral( "source_crs_parameter_name" ) ).toString();
7066 mDestParameterName = map.value( QStringLiteral( "dest_crs_parameter_name" ) ).toString();
7067 mSourceCrs = map.value( QStringLiteral( "static_source_crs" ) );
7068 mDestCrs = map.value( QStringLiteral( "static_dest_crs" ) );
7069 return true;
7070 }
7071
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)7072 QgsProcessingParameterCoordinateOperation *QgsProcessingParameterCoordinateOperation::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
7073 {
7074 QString def = definition;
7075
7076 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
7077 def = def.mid( 1 );
7078 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
7079 def.chop( 1 );
7080
7081 QVariant defaultValue = def;
7082 if ( def == QLatin1String( "None" ) )
7083 defaultValue = QVariant();
7084
7085 return new QgsProcessingParameterCoordinateOperation( name, description, defaultValue, QString(), QString(), QVariant(), QVariant(), isOptional );
7086 }
7087
7088
7089 //
7090 // QgsProcessingParameterMapTheme
7091 //
7092
QgsProcessingParameterMapTheme(const QString & name,const QString & description,const QVariant & defaultValue,bool optional)7093 QgsProcessingParameterMapTheme::QgsProcessingParameterMapTheme( const QString &name, const QString &description, const QVariant &defaultValue, bool optional )
7094 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
7095 {
7096
7097 }
7098
7099
clone() const7100 QgsProcessingParameterDefinition *QgsProcessingParameterMapTheme::clone() const
7101 {
7102 return new QgsProcessingParameterMapTheme( *this );
7103 }
7104
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const7105 bool QgsProcessingParameterMapTheme::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
7106 {
7107 if ( !input.isValid() && !mDefault.isValid() )
7108 return mFlags & FlagOptional;
7109
7110 if ( ( input.type() == QVariant::String && input.toString().isEmpty() )
7111 || ( !input.isValid() && mDefault.type() == QVariant::String && mDefault.toString().isEmpty() ) )
7112 return mFlags & FlagOptional;
7113
7114 return true;
7115 }
7116
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const7117 QString QgsProcessingParameterMapTheme::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
7118 {
7119 if ( !value.isValid() )
7120 return QStringLiteral( "None" );
7121
7122 if ( value.canConvert<QgsProperty>() )
7123 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
7124
7125 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
7126 }
7127
asScriptCode() const7128 QString QgsProcessingParameterMapTheme::asScriptCode() const
7129 {
7130 QString code = QStringLiteral( "##%1=" ).arg( mName );
7131 if ( mFlags & FlagOptional )
7132 code += QLatin1String( "optional " );
7133 code += QLatin1String( "maptheme " );
7134
7135 code += mDefault.toString();
7136 return code.trimmed();
7137 }
7138
asPythonString(const QgsProcessing::PythonOutputType outputType) const7139 QString QgsProcessingParameterMapTheme::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
7140 {
7141 switch ( outputType )
7142 {
7143 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
7144 {
7145 QString code = QStringLiteral( "QgsProcessingParameterMapTheme('%1', '%2'" ).arg( name(), description() );
7146 if ( mFlags & FlagOptional )
7147 code += QLatin1String( ", optional=True" );
7148
7149 QgsProcessingContext c;
7150 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
7151
7152 return code;
7153 }
7154 }
7155 return QString();
7156 }
7157
toVariantMap() const7158 QVariantMap QgsProcessingParameterMapTheme::toVariantMap() const
7159 {
7160 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
7161 return map;
7162 }
7163
fromVariantMap(const QVariantMap & map)7164 bool QgsProcessingParameterMapTheme::fromVariantMap( const QVariantMap &map )
7165 {
7166 QgsProcessingParameterDefinition::fromVariantMap( map );
7167 return true;
7168 }
7169
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)7170 QgsProcessingParameterMapTheme *QgsProcessingParameterMapTheme::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
7171 {
7172 QString parent;
7173
7174 QString def = definition;
7175 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
7176 def = def.mid( 1 );
7177 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
7178 def.chop( 1 );
7179
7180 QVariant defaultValue = def;
7181
7182 if ( defaultValue == QLatin1String( "None" ) || defaultValue.toString().isEmpty() )
7183 defaultValue = QVariant();
7184
7185 return new QgsProcessingParameterMapTheme( name, description, defaultValue, isOptional );
7186 }
7187
7188
7189 //
7190 // QgsProcessingParameterDateTime
7191 //
7192
QgsProcessingParameterDateTime(const QString & name,const QString & description,Type type,const QVariant & defaultValue,bool optional,const QDateTime & minValue,const QDateTime & maxValue)7193 QgsProcessingParameterDateTime::QgsProcessingParameterDateTime( const QString &name, const QString &description, Type type, const QVariant &defaultValue, bool optional, const QDateTime &minValue, const QDateTime &maxValue )
7194 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
7195 , mMin( minValue )
7196 , mMax( maxValue )
7197 , mDataType( type )
7198 {
7199 if ( mMin.isValid() && mMax.isValid() && mMin >= mMax )
7200 {
7201 QgsMessageLog::logMessage( QObject::tr( "Invalid datetime parameter \"%1\": min value %2 is >= max value %3!" ).arg( name, mMin.toString(), mMax.toString() ), QObject::tr( "Processing" ) );
7202 }
7203 }
7204
clone() const7205 QgsProcessingParameterDefinition *QgsProcessingParameterDateTime::clone() const
7206 {
7207 return new QgsProcessingParameterDateTime( *this );
7208 }
7209
checkValueIsAcceptable(const QVariant & value,QgsProcessingContext *) const7210 bool QgsProcessingParameterDateTime::checkValueIsAcceptable( const QVariant &value, QgsProcessingContext * ) const
7211 {
7212 QVariant input = value;
7213 if ( !input.isValid() )
7214 {
7215 if ( !defaultValue().isValid() )
7216 return mFlags & FlagOptional;
7217
7218 input = defaultValue();
7219 }
7220
7221 if ( input.canConvert<QgsProperty>() )
7222 {
7223 return true;
7224 }
7225
7226 if ( input.type() != QVariant::DateTime && input.type() != QVariant::Date && input.type() != QVariant::Time && input.type() != QVariant::String )
7227 return false;
7228
7229 if ( ( input.type() == QVariant::DateTime || input.type() == QVariant::Date ) && mDataType == Time )
7230 return false;
7231
7232 if ( input.type() == QVariant::String )
7233 {
7234 QString s = input.toString();
7235 if ( s.isEmpty() )
7236 return mFlags & FlagOptional;
7237
7238 input = QDateTime::fromString( s, Qt::ISODate );
7239 if ( mDataType == Time )
7240 {
7241 if ( !input.toDateTime().isValid() )
7242 input = QTime::fromString( s );
7243 else
7244 input = input.toDateTime().time();
7245 }
7246 }
7247
7248 if ( mDataType != Time )
7249 {
7250 QDateTime res = input.toDateTime();
7251 return res.isValid() && ( res >= mMin || !mMin.isValid() ) && ( res <= mMax || !mMax.isValid() );
7252 }
7253 else
7254 {
7255 QTime res = input.toTime();
7256 return res.isValid() && ( res >= mMin.time() || !mMin.isValid() ) && ( res <= mMax.time() || !mMax.isValid() );
7257 }
7258 }
7259
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const7260 QString QgsProcessingParameterDateTime::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
7261 {
7262 if ( !value.isValid() )
7263 return QStringLiteral( "None" );
7264
7265 if ( value.canConvert<QgsProperty>() )
7266 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
7267
7268 if ( value.type() == QVariant::DateTime )
7269 {
7270 const QDateTime dt = value.toDateTime();
7271 if ( !dt.isValid() )
7272 return QStringLiteral( "QDateTime()" );
7273 else
7274 return QStringLiteral( "QDateTime(QDate(%1, %2, %3), QTime(%4, %5, %6))" ).arg( dt.date().year() )
7275 .arg( dt.date().month() )
7276 .arg( dt.date().day() )
7277 .arg( dt.time().hour() )
7278 .arg( dt.time().minute() )
7279 .arg( dt.time().second() );
7280 }
7281 else if ( value.type() == QVariant::Date )
7282 {
7283 const QDate dt = value.toDate();
7284 if ( !dt.isValid() )
7285 return QStringLiteral( "QDate()" );
7286 else
7287 return QStringLiteral( "QDate(%1, %2, %3)" ).arg( dt.year() )
7288 .arg( dt.month() )
7289 .arg( dt.day() );
7290 }
7291 else if ( value.type() == QVariant::Time )
7292 {
7293 const QTime dt = value.toTime();
7294 if ( !dt.isValid() )
7295 return QStringLiteral( "QTime()" );
7296 else
7297 return QStringLiteral( "QTime(%4, %5, %6)" )
7298 .arg( dt.hour() )
7299 .arg( dt.minute() )
7300 .arg( dt.second() );
7301 }
7302 return value.toString();
7303 }
7304
toolTip() const7305 QString QgsProcessingParameterDateTime::toolTip() const
7306 {
7307 QString text = QgsProcessingParameterDefinition::toolTip();
7308 QStringList parts;
7309 if ( mMin.isValid() )
7310 parts << QObject::tr( "Minimum value: %1" ).arg( mMin.toString( Qt::ISODate ) );
7311 if ( mMax.isValid() )
7312 parts << QObject::tr( "Maximum value: %1" ).arg( mMax.toString( Qt::ISODate ) );
7313 if ( mDefault.isValid() )
7314 parts << QObject::tr( "Default value: %1" ).arg( mDataType == DateTime ? mDefault.toDateTime().toString( Qt::ISODate ) :
7315 ( mDataType == Date ? mDefault.toDate().toString( Qt::ISODate ) : mDefault.toTime( ).toString() ) );
7316 QString extra = parts.join( QLatin1String( "<br />" ) );
7317 if ( !extra.isEmpty() )
7318 text += QStringLiteral( "<p>%1</p>" ).arg( extra );
7319 return text;
7320 }
7321
asPythonString(const QgsProcessing::PythonOutputType outputType) const7322 QString QgsProcessingParameterDateTime::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
7323 {
7324 switch ( outputType )
7325 {
7326 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
7327 {
7328 QString code = QStringLiteral( "QgsProcessingParameterDateTime('%1', '%2'" ).arg( name(), description() );
7329 if ( mFlags & FlagOptional )
7330 code += QLatin1String( ", optional=True" );
7331
7332 code += QStringLiteral( ", type=%1" ).arg( mDataType == DateTime ? QStringLiteral( "QgsProcessingParameterDateTime.DateTime" )
7333 : mDataType == Date ? QStringLiteral( "QgsProcessingParameterDateTime.Date" )
7334 : QStringLiteral( "QgsProcessingParameterDateTime.Time" ) );
7335
7336 QgsProcessingContext c;
7337 if ( mMin.isValid() )
7338 code += QStringLiteral( ", minValue=%1" ).arg( valueAsPythonString( mMin, c ) );
7339 if ( mMax.isValid() )
7340 code += QStringLiteral( ", maxValue=%1" ).arg( valueAsPythonString( mMax, c ) );
7341 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
7342 return code;
7343 }
7344 }
7345 return QString();
7346 }
7347
minimum() const7348 QDateTime QgsProcessingParameterDateTime::minimum() const
7349 {
7350 return mMin;
7351 }
7352
setMinimum(const QDateTime & min)7353 void QgsProcessingParameterDateTime::setMinimum( const QDateTime &min )
7354 {
7355 mMin = min;
7356 }
7357
maximum() const7358 QDateTime QgsProcessingParameterDateTime::maximum() const
7359 {
7360 return mMax;
7361 }
7362
setMaximum(const QDateTime & max)7363 void QgsProcessingParameterDateTime::setMaximum( const QDateTime &max )
7364 {
7365 mMax = max;
7366 }
7367
dataType() const7368 QgsProcessingParameterDateTime::Type QgsProcessingParameterDateTime::dataType() const
7369 {
7370 return mDataType;
7371 }
7372
setDataType(Type dataType)7373 void QgsProcessingParameterDateTime::setDataType( Type dataType )
7374 {
7375 mDataType = dataType;
7376 }
7377
toVariantMap() const7378 QVariantMap QgsProcessingParameterDateTime::toVariantMap() const
7379 {
7380 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
7381 map.insert( QStringLiteral( "min" ), mMin );
7382 map.insert( QStringLiteral( "max" ), mMax );
7383 map.insert( QStringLiteral( "data_type" ), mDataType );
7384 return map;
7385 }
7386
fromVariantMap(const QVariantMap & map)7387 bool QgsProcessingParameterDateTime::fromVariantMap( const QVariantMap &map )
7388 {
7389 QgsProcessingParameterDefinition::fromVariantMap( map );
7390 mMin = map.value( QStringLiteral( "min" ) ).toDateTime();
7391 mMax = map.value( QStringLiteral( "max" ) ).toDateTime();
7392 mDataType = static_cast< Type >( map.value( QStringLiteral( "data_type" ) ).toInt() );
7393 return true;
7394 }
7395
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)7396 QgsProcessingParameterDateTime *QgsProcessingParameterDateTime::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
7397 {
7398 return new QgsProcessingParameterDateTime( name, description, DateTime, definition.isEmpty() ? QVariant()
7399 : ( definition.toLower().trimmed() == QLatin1String( "none" ) ? QVariant() : definition ), isOptional );
7400 }
7401
7402
7403
7404 //
7405 // QgsProcessingParameterProviderConnection
7406 //
7407
QgsProcessingParameterProviderConnection(const QString & name,const QString & description,const QString & provider,const QVariant & defaultValue,bool optional)7408 QgsProcessingParameterProviderConnection::QgsProcessingParameterProviderConnection( const QString &name, const QString &description, const QString &provider, const QVariant &defaultValue, bool optional )
7409 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
7410 , mProviderId( provider )
7411 {
7412
7413 }
7414
7415
clone() const7416 QgsProcessingParameterDefinition *QgsProcessingParameterProviderConnection::clone() const
7417 {
7418 return new QgsProcessingParameterProviderConnection( *this );
7419 }
7420
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const7421 bool QgsProcessingParameterProviderConnection::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
7422 {
7423 if ( !input.isValid() && !mDefault.isValid() )
7424 return mFlags & FlagOptional;
7425
7426 if ( ( input.type() == QVariant::String && input.toString().isEmpty() )
7427 || ( !input.isValid() && mDefault.type() == QVariant::String && mDefault.toString().isEmpty() ) )
7428 return mFlags & FlagOptional;
7429
7430 return true;
7431 }
7432
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const7433 QString QgsProcessingParameterProviderConnection::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
7434 {
7435 if ( !value.isValid() )
7436 return QStringLiteral( "None" );
7437
7438 if ( value.canConvert<QgsProperty>() )
7439 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
7440
7441 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
7442 }
7443
asScriptCode() const7444 QString QgsProcessingParameterProviderConnection::asScriptCode() const
7445 {
7446 QString code = QStringLiteral( "##%1=" ).arg( mName );
7447 if ( mFlags & FlagOptional )
7448 code += QLatin1String( "optional " );
7449 code += QLatin1String( "providerconnection " );
7450 code += mProviderId + ' ';
7451
7452 code += mDefault.toString();
7453 return code.trimmed();
7454 }
7455
asPythonString(const QgsProcessing::PythonOutputType outputType) const7456 QString QgsProcessingParameterProviderConnection::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
7457 {
7458 switch ( outputType )
7459 {
7460 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
7461 {
7462 QString code = QStringLiteral( "QgsProcessingParameterProviderConnection('%1', '%2', '%3'" ).arg( name(), description(), mProviderId );
7463 if ( mFlags & FlagOptional )
7464 code += QLatin1String( ", optional=True" );
7465
7466 QgsProcessingContext c;
7467 code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
7468
7469 return code;
7470 }
7471 }
7472 return QString();
7473 }
7474
toVariantMap() const7475 QVariantMap QgsProcessingParameterProviderConnection::toVariantMap() const
7476 {
7477 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
7478 map.insert( QStringLiteral( "provider" ), mProviderId );
7479 return map;
7480 }
7481
fromVariantMap(const QVariantMap & map)7482 bool QgsProcessingParameterProviderConnection::fromVariantMap( const QVariantMap &map )
7483 {
7484 QgsProcessingParameterDefinition::fromVariantMap( map );
7485 mProviderId = map.value( QStringLiteral( "provider" ) ).toString();
7486 return true;
7487 }
7488
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)7489 QgsProcessingParameterProviderConnection *QgsProcessingParameterProviderConnection::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
7490 {
7491 QString parent;
7492
7493 QString def = definition;
7494 QString provider;
7495 if ( def.contains( ' ' ) )
7496 {
7497 provider = def.left( def.indexOf( ' ' ) );
7498 def = def.mid( def.indexOf( ' ' ) + 1 );
7499 }
7500 else
7501 {
7502 provider = def;
7503 def.clear();
7504 }
7505
7506 if ( def.startsWith( '"' ) || def.startsWith( '\'' ) )
7507 def = def.mid( 1 );
7508 if ( def.endsWith( '"' ) || def.endsWith( '\'' ) )
7509 def.chop( 1 );
7510
7511 QVariant defaultValue = def;
7512
7513 if ( defaultValue == QLatin1String( "None" ) || defaultValue.toString().isEmpty() )
7514 defaultValue = QVariant();
7515
7516 return new QgsProcessingParameterProviderConnection( name, description, provider, defaultValue, isOptional );
7517 }
7518
7519
7520 //
7521 // QgsProcessingParameterDatabaseSchema
7522 //
7523
QgsProcessingParameterDatabaseSchema(const QString & name,const QString & description,const QString & parentLayerParameterName,const QVariant & defaultValue,bool optional)7524 QgsProcessingParameterDatabaseSchema::QgsProcessingParameterDatabaseSchema( const QString &name, const QString &description, const QString &parentLayerParameterName, const QVariant &defaultValue, bool optional )
7525 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
7526 , mParentConnectionParameterName( parentLayerParameterName )
7527 {
7528
7529 }
7530
7531
clone() const7532 QgsProcessingParameterDefinition *QgsProcessingParameterDatabaseSchema::clone() const
7533 {
7534 return new QgsProcessingParameterDatabaseSchema( *this );
7535 }
7536
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const7537 bool QgsProcessingParameterDatabaseSchema::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
7538 {
7539 if ( !input.isValid() && !mDefault.isValid() )
7540 return mFlags & FlagOptional;
7541
7542 if ( ( input.type() == QVariant::String && input.toString().isEmpty() )
7543 || ( !input.isValid() && mDefault.type() == QVariant::String && mDefault.toString().isEmpty() ) )
7544 return mFlags & FlagOptional;
7545
7546 return true;
7547 }
7548
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const7549 QString QgsProcessingParameterDatabaseSchema::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
7550 {
7551 if ( !value.isValid() )
7552 return QStringLiteral( "None" );
7553
7554 if ( value.canConvert<QgsProperty>() )
7555 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
7556
7557 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
7558 }
7559
asScriptCode() const7560 QString QgsProcessingParameterDatabaseSchema::asScriptCode() const
7561 {
7562 QString code = QStringLiteral( "##%1=" ).arg( mName );
7563 if ( mFlags & FlagOptional )
7564 code += QLatin1String( "optional " );
7565 code += QLatin1String( "databaseschema " );
7566
7567 code += mParentConnectionParameterName + ' ';
7568
7569 code += mDefault.toString();
7570 return code.trimmed();
7571 }
7572
asPythonString(const QgsProcessing::PythonOutputType outputType) const7573 QString QgsProcessingParameterDatabaseSchema::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
7574 {
7575 switch ( outputType )
7576 {
7577 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
7578 {
7579 QString code = QStringLiteral( "QgsProcessingParameterDatabaseSchema('%1', '%2'" ).arg( name(), description() );
7580 if ( mFlags & FlagOptional )
7581 code += QLatin1String( ", optional=True" );
7582
7583 code += QStringLiteral( ", connectionParameterName='%1'" ).arg( mParentConnectionParameterName );
7584 QgsProcessingContext c;
7585 code += QStringLiteral( ", defaultValue=%1" ).arg( valueAsPythonString( mDefault, c ) );
7586
7587 code += ')';
7588
7589 return code;
7590 }
7591 }
7592 return QString();
7593 }
7594
dependsOnOtherParameters() const7595 QStringList QgsProcessingParameterDatabaseSchema::dependsOnOtherParameters() const
7596 {
7597 QStringList depends;
7598 if ( !mParentConnectionParameterName.isEmpty() )
7599 depends << mParentConnectionParameterName;
7600 return depends;
7601 }
7602
parentConnectionParameterName() const7603 QString QgsProcessingParameterDatabaseSchema::parentConnectionParameterName() const
7604 {
7605 return mParentConnectionParameterName;
7606 }
7607
setParentConnectionParameterName(const QString & name)7608 void QgsProcessingParameterDatabaseSchema::setParentConnectionParameterName( const QString &name )
7609 {
7610 mParentConnectionParameterName = name;
7611 }
7612
toVariantMap() const7613 QVariantMap QgsProcessingParameterDatabaseSchema::toVariantMap() const
7614 {
7615 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
7616 map.insert( QStringLiteral( "mParentConnectionParameterName" ), mParentConnectionParameterName );
7617 return map;
7618 }
7619
fromVariantMap(const QVariantMap & map)7620 bool QgsProcessingParameterDatabaseSchema::fromVariantMap( const QVariantMap &map )
7621 {
7622 QgsProcessingParameterDefinition::fromVariantMap( map );
7623 mParentConnectionParameterName = map.value( QStringLiteral( "mParentConnectionParameterName" ) ).toString();
7624 return true;
7625 }
7626
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)7627 QgsProcessingParameterDatabaseSchema *QgsProcessingParameterDatabaseSchema::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
7628 {
7629 QString parent;
7630 QString def = definition;
7631
7632 QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*)$" ) );
7633 QRegularExpressionMatch m = re.match( def );
7634 if ( m.hasMatch() )
7635 {
7636 parent = m.captured( 1 ).trimmed();
7637 def = m.captured( 2 );
7638 }
7639 else
7640 {
7641 parent = def;
7642 def.clear();
7643 }
7644
7645 return new QgsProcessingParameterDatabaseSchema( name, description, parent, def.isEmpty() ? QVariant() : def, isOptional );
7646 }
7647
7648 //
7649 // QgsProcessingParameterDatabaseTable
7650 //
7651
QgsProcessingParameterDatabaseTable(const QString & name,const QString & description,const QString & connectionParameterName,const QString & schemaParameterName,const QVariant & defaultValue,bool optional,bool allowNewTableNames)7652 QgsProcessingParameterDatabaseTable::QgsProcessingParameterDatabaseTable( const QString &name, const QString &description,
7653 const QString &connectionParameterName,
7654 const QString &schemaParameterName,
7655 const QVariant &defaultValue, bool optional, bool allowNewTableNames )
7656 : QgsProcessingParameterDefinition( name, description, defaultValue, optional )
7657 , mParentConnectionParameterName( connectionParameterName )
7658 , mParentSchemaParameterName( schemaParameterName )
7659 , mAllowNewTableNames( allowNewTableNames )
7660 {
7661
7662 }
7663
7664
clone() const7665 QgsProcessingParameterDefinition *QgsProcessingParameterDatabaseTable::clone() const
7666 {
7667 return new QgsProcessingParameterDatabaseTable( *this );
7668 }
7669
checkValueIsAcceptable(const QVariant & input,QgsProcessingContext *) const7670 bool QgsProcessingParameterDatabaseTable::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
7671 {
7672 if ( !input.isValid() && !mDefault.isValid() )
7673 return mFlags & FlagOptional;
7674
7675 if ( ( input.type() == QVariant::String && input.toString().isEmpty() )
7676 || ( !input.isValid() && mDefault.type() == QVariant::String && mDefault.toString().isEmpty() ) )
7677 return mFlags & FlagOptional;
7678
7679 return true;
7680 }
7681
valueAsPythonString(const QVariant & value,QgsProcessingContext &) const7682 QString QgsProcessingParameterDatabaseTable::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
7683 {
7684 if ( !value.isValid() )
7685 return QStringLiteral( "None" );
7686
7687 if ( value.canConvert<QgsProperty>() )
7688 return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
7689
7690 return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
7691 }
7692
asScriptCode() const7693 QString QgsProcessingParameterDatabaseTable::asScriptCode() const
7694 {
7695 QString code = QStringLiteral( "##%1=" ).arg( mName );
7696 if ( mFlags & FlagOptional )
7697 code += QLatin1String( "optional " );
7698 code += QLatin1String( "databasetable " );
7699
7700 code += ( mParentConnectionParameterName.isEmpty() ? QStringLiteral( "none" ) : mParentConnectionParameterName ) + ' ';
7701 code += ( mParentSchemaParameterName.isEmpty() ? QStringLiteral( "none" ) : mParentSchemaParameterName ) + ' ';
7702
7703 code += mDefault.toString();
7704 return code.trimmed();
7705 }
7706
asPythonString(const QgsProcessing::PythonOutputType outputType) const7707 QString QgsProcessingParameterDatabaseTable::asPythonString( const QgsProcessing::PythonOutputType outputType ) const
7708 {
7709 switch ( outputType )
7710 {
7711 case QgsProcessing::PythonQgsProcessingAlgorithmSubclass:
7712 {
7713 QString code = QStringLiteral( "QgsProcessingParameterDatabaseTable('%1', '%2'" ).arg( name(), description() );
7714 if ( mFlags & FlagOptional )
7715 code += QLatin1String( ", optional=True" );
7716
7717 if ( mAllowNewTableNames )
7718 code += QLatin1String( ", allowNewTableNames=True" );
7719
7720 code += QStringLiteral( ", connectionParameterName='%1'" ).arg( mParentConnectionParameterName );
7721 code += QStringLiteral( ", schemaParameterName='%1'" ).arg( mParentSchemaParameterName );
7722 QgsProcessingContext c;
7723 code += QStringLiteral( ", defaultValue=%1" ).arg( valueAsPythonString( mDefault, c ) );
7724
7725 code += ')';
7726
7727 return code;
7728 }
7729 }
7730 return QString();
7731 }
7732
dependsOnOtherParameters() const7733 QStringList QgsProcessingParameterDatabaseTable::dependsOnOtherParameters() const
7734 {
7735 QStringList depends;
7736 if ( !mParentConnectionParameterName.isEmpty() )
7737 depends << mParentConnectionParameterName;
7738 if ( !mParentSchemaParameterName.isEmpty() )
7739 depends << mParentSchemaParameterName;
7740 return depends;
7741 }
7742
parentConnectionParameterName() const7743 QString QgsProcessingParameterDatabaseTable::parentConnectionParameterName() const
7744 {
7745 return mParentConnectionParameterName;
7746 }
7747
setParentConnectionParameterName(const QString & name)7748 void QgsProcessingParameterDatabaseTable::setParentConnectionParameterName( const QString &name )
7749 {
7750 mParentConnectionParameterName = name;
7751 }
7752
parentSchemaParameterName() const7753 QString QgsProcessingParameterDatabaseTable::parentSchemaParameterName() const
7754 {
7755 return mParentSchemaParameterName;
7756 }
7757
setParentSchemaParameterName(const QString & name)7758 void QgsProcessingParameterDatabaseTable::setParentSchemaParameterName( const QString &name )
7759 {
7760 mParentSchemaParameterName = name;
7761 }
7762
toVariantMap() const7763 QVariantMap QgsProcessingParameterDatabaseTable::toVariantMap() const
7764 {
7765 QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
7766 map.insert( QStringLiteral( "mParentConnectionParameterName" ), mParentConnectionParameterName );
7767 map.insert( QStringLiteral( "mParentSchemaParameterName" ), mParentSchemaParameterName );
7768 map.insert( QStringLiteral( "mAllowNewTableNames" ), mAllowNewTableNames );
7769 return map;
7770 }
7771
fromVariantMap(const QVariantMap & map)7772 bool QgsProcessingParameterDatabaseTable::fromVariantMap( const QVariantMap &map )
7773 {
7774 QgsProcessingParameterDefinition::fromVariantMap( map );
7775 mParentConnectionParameterName = map.value( QStringLiteral( "mParentConnectionParameterName" ) ).toString();
7776 mParentSchemaParameterName = map.value( QStringLiteral( "mParentSchemaParameterName" ) ).toString();
7777 mAllowNewTableNames = map.value( QStringLiteral( "mAllowNewTableNames" ), false ).toBool();
7778 return true;
7779 }
7780
fromScriptCode(const QString & name,const QString & description,bool isOptional,const QString & definition)7781 QgsProcessingParameterDatabaseTable *QgsProcessingParameterDatabaseTable::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
7782 {
7783 QString connection;
7784 QString schema;
7785 QString def = definition;
7786
7787 QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*+)\\b\\s*(.*)$" ) );
7788 QRegularExpressionMatch m = re.match( def );
7789 if ( m.hasMatch() )
7790 {
7791 connection = m.captured( 1 ).trimmed();
7792 if ( connection == QLatin1String( "none" ) )
7793 connection.clear();
7794 schema = m.captured( 2 ).trimmed();
7795 if ( schema == QLatin1String( "none" ) )
7796 schema.clear();
7797 def = m.captured( 3 );
7798 }
7799
7800 return new QgsProcessingParameterDatabaseTable( name, description, connection, schema, def.isEmpty() ? QVariant() : def, isOptional );
7801 }
7802
allowNewTableNames() const7803 bool QgsProcessingParameterDatabaseTable::allowNewTableNames() const
7804 {
7805 return mAllowNewTableNames;
7806 }
7807
setAllowNewTableNames(bool allowNewTableNames)7808 void QgsProcessingParameterDatabaseTable::setAllowNewTableNames( bool allowNewTableNames )
7809 {
7810 mAllowNewTableNames = allowNewTableNames;
7811 }
7812