50 if ( transferOwnership )
102 d->mRootNode =
::parseExpression( expression, d->mParserErrorString, d->mParserErrors );
103 d->mEvalErrorString = QString();
105 d->mIsPrepared =
false;
110 if ( !d->mExp.isNull() )
118 return QStringLiteral(
"\"%1\"" ).arg( name.replace(
'\"', QLatin1String(
"\"\"" ) ) );
123 text.replace(
'\'', QLatin1String(
"''" ) );
124 text.replace(
'\\', QLatin1String(
"\\\\" ) );
125 text.replace(
'\n', QLatin1String(
"\\n" ) );
126 text.replace(
'\t', QLatin1String(
"\\t" ) );
127 return QStringLiteral(
"'%1'" ).arg( text );
137 if ( value.isNull() )
138 return QStringLiteral(
"NULL" );
143 case QVariant::LongLong:
144 case QVariant::Double:
145 return value.toString();
148 return value.toBool() ? QStringLiteral(
"TRUE" ) : QStringLiteral(
"FALSE" );
152 QStringList quotedValues;
153 const QVariantList values = value.toList();
154 quotedValues.reserve( values.count() );
155 for (
const QVariant &v : values )
159 return QStringLiteral(
"array( %1 )" ).arg( quotedValues.join( QStringLiteral(
", " ) ) );
163 case QVariant::String:
177 for (
int i = 0; i < count; i++ )
182 for (
const QString &alias : aliases )
184 if ( QString::compare( name, alias, Qt::CaseInsensitive ) == 0 )
198 : d( new QgsExpressionPrivate )
200 d->mRootNode =
::parseExpression( expr, d->mParserErrorString, d->mParserErrors );
202 Q_ASSERT( !d->mParserErrorString.isNull() || d->mRootNode );
213 if ( !d->ref.deref() )
223 QgsExpression::operator QString()
const 229 : d( new QgsExpressionPrivate )
236 if ( !d->ref.deref() )
242 return ( d == other.d || d->mExp == other.d->mExp );
252 return d->mParserErrors.count() > 0;
257 return d->mParserErrorString;
262 return d->mParserErrors;
268 return QSet<QString>();
270 return d->mRootNode->referencedColumns();
276 return QSet<QString>();
278 return d->mRootNode->referencedVariables();
284 return QSet<QString>();
286 return d->mRootNode->referencedFunctions();
294 const QSet<QString> referencedFields = d->mRootNode->referencedColumns();
295 QSet<int> referencedIndexes;
297 for (
const QString &fieldName : referencedFields )
304 referencedIndexes << fields.
lookupField( fieldName );
307 return referencedIndexes;
314 return d->mRootNode->needsGeometry();
320 if ( context && ! d->mCalc )
322 QString ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
328 d->mCalc->setEllipsoid( ellipsoid.isEmpty() ?
GEO_NONE : ellipsoid );
329 d->mCalc->setSourceCrs( crs, tContext );
336 QString distanceUnitsStr = context->
variable( QStringLiteral(
"project_distance_units" ) ).toString();
337 if ( ! distanceUnitsStr.isEmpty() )
344 QString areaUnitsStr = context->
variable( QStringLiteral(
"project_area_units" ) ).toString();
345 if ( ! areaUnitsStr.isEmpty() )
350 void QgsExpression::detach()
356 ( void )d->ref.deref();
358 d =
new QgsExpressionPrivate( *d );
366 d->mCalc = std::shared_ptr<QgsDistanceArea>(
new QgsDistanceArea( *calc ) );
374 d->mEvalErrorString = QString();
380 d->mRootNode =
::parseExpression( d->mExp, d->mParserErrorString, d->mParserErrors );
385 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
389 initGeomCalculator( context );
390 d->mIsPrepared =
true;
391 return d->mRootNode->prepare(
this, context );
396 d->mEvalErrorString = QString();
399 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
403 return d->mRootNode->eval(
this, static_cast<const QgsExpressionContext *>(
nullptr ) );
408 d->mEvalErrorString = QString();
411 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
415 if ( ! d->mIsPrepared )
419 return d->mRootNode->eval(
this, context );
424 return !d->mEvalErrorString.isNull();
429 return d->mEvalErrorString;
434 d->mEvalErrorString = str;
442 return d->mRootNode->dump();
447 return d->mCalc.get();
452 return d->mDistanceUnit;
457 d->mDistanceUnit = unit;
475 while ( index < action.size() )
477 static const QRegularExpression sRegEx{ QStringLiteral(
"\\[%(.*?)%\\]" ), QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption };
479 const QRegularExpressionMatch match = sRegEx.match( action, index );
480 if ( !match.hasMatch() )
483 const int pos = action.indexOf( sRegEx, index );
484 const int start = index;
485 index = pos + match.capturedLength( 0 );
486 const QString toReplace = match.captured( 1 ).trimmed();
493 expr_action += action.midRef( start, index - start );
503 QVariant result = exp.
evaluate( context );
508 expr_action += action.midRef( start, index - start );
512 QgsDebugMsg(
"Expression result is: " + result.toString() );
513 expr_action += action.mid( start, pos - start ) + result.toString();
516 expr_action += action.midRef( index );
523 QSet<QString> variables;
525 while ( index < text.size() )
527 QRegExp rx = QRegExp(
"\\[%([^\\]]+)%\\]" );
529 int pos = rx.indexIn( text, index );
533 index = pos + rx.matchedLength();
534 QString to_replace = rx.cap( 1 ).trimmed();
549 double convertedValue = QLocale().toDouble( text, &ok );
552 return convertedValue;
562 QVariant result = expr.
evaluate( &context );
563 convertedValue = result.toDouble( &ok );
566 return fallbackValue;
568 return convertedValue;
575 QgsExpression::initFunctionHelp();
577 if ( !sFunctionHelpTexts.contains( name ) )
578 return tr(
"function help for %1 missing" ).arg( name );
580 const Help &f = sFunctionHelpTexts[ name ];
583 if ( f.mType == tr(
"group" ) )
585 name =
group( name );
586 name = name.toLower();
589 name = name.toHtmlEscaped();
591 QString helpContents( QStringLiteral(
"<h3>%1</h3>\n<div class=\"description\"><p>%2</p></div>" )
592 .arg( tr(
"%1 %2" ).arg( f.mType, name ),
595 for (
const HelpVariant &v : qgis::as_const( f.mVariants ) )
597 if ( f.mVariants.size() > 1 )
599 helpContents += QStringLiteral(
"<h3>%1</h3>\n<div class=\"description\">%2</p></div>" ).arg( v.mName, v.mDescription );
602 if ( f.mType != tr(
"group" ) && f.mType != tr(
"expression" ) )
603 helpContents += QStringLiteral(
"<h4>%1</h4>\n<div class=\"syntax\">\n" ).arg( tr(
"Syntax" ) );
605 if ( f.mType == tr(
"operator" ) )
607 if ( v.mArguments.size() == 1 )
609 helpContents += QStringLiteral(
"<code><span class=\"functionname\">%1</span> <span class=\"argument\">%2</span></code>" )
610 .arg( name, v.mArguments[0].mArg );
612 else if ( v.mArguments.size() == 2 )
614 helpContents += QStringLiteral(
"<code><span class=\"argument\">%1</span> <span class=\"functionname\">%2</span> <span class=\"argument\">%3</span></code>" )
615 .arg( v.mArguments[0].mArg, name, v.mArguments[1].mArg );
618 else if ( f.mType != tr(
"group" ) && f.mType != tr(
"expression" ) )
620 helpContents += QStringLiteral(
"<code><span class=\"functionname\">%1</span>" ).arg( name );
622 bool hasOptionalArgs =
false;
624 if ( f.mType == tr(
"function" ) && ( f.mName[0] !=
'$' || !v.mArguments.isEmpty() || v.mVariableLenArguments ) )
629 for (
const HelpArg &a : qgis::as_const( v.mArguments ) )
635 hasOptionalArgs =
true;
636 helpContents += QStringLiteral(
"[" );
639 helpContents += delim;
640 helpContents += QStringLiteral(
"<span class=\"argument\">%2%3</span>" ).arg(
642 a.mDefaultVal.isEmpty() ? QString() :
'=' + a.mDefaultVal
646 helpContents += QStringLiteral(
"]" );
648 delim = QStringLiteral(
"," );
651 if ( v.mVariableLenArguments )
653 helpContents += QChar( 0x2026 );
659 helpContents += QLatin1String(
"</code>" );
661 if ( hasOptionalArgs )
663 helpContents += QLatin1String(
"<br/><br/>" ) + tr(
"[ ] marks optional components" );
667 if ( !v.mArguments.isEmpty() )
669 helpContents += QStringLiteral(
"<h4>%1</h4>\n<div class=\"arguments\">\n<table>" ).arg( tr(
"Arguments" ) );
671 for (
const HelpArg &a : qgis::as_const( v.mArguments ) )
676 helpContents += QStringLiteral(
"<tr><td class=\"argument\">%1</td><td>%2</td></tr>" ).arg( a.mArg, a.mDescription );
679 helpContents += QLatin1String(
"</table>\n</div>\n" );
682 if ( !v.mExamples.isEmpty() )
684 helpContents += QStringLiteral(
"<h4>%1</h4>\n<div class=\"examples\">\n<ul>\n" ).arg( tr(
"Examples" ) );
686 for (
const HelpExample &e : qgis::as_const( v.mExamples ) )
688 helpContents +=
"<li><code>" + e.mExpression +
"</code> → <code>" + e.mReturns +
"</code>";
690 if ( !e.mNote.isEmpty() )
691 helpContents += QStringLiteral(
" (%1)" ).arg( e.mNote );
693 helpContents += QLatin1String(
"</li>\n" );
696 helpContents += QLatin1String(
"</ul>\n</div>\n" );
699 if ( !v.mNotes.isEmpty() )
701 helpContents += QStringLiteral(
"<h4>%1</h4>\n<div class=\"notes\"><p>%2</p></div>\n" ).arg( tr(
"Notes" ), v.mNotes );
708 QHash<QString, QString> QgsExpression::sVariableHelpTexts;
710 void QgsExpression::initVariableHelp()
712 if ( !sVariableHelpTexts.isEmpty() )
716 sVariableHelpTexts.insert( QStringLiteral(
"qgis_version" ), QCoreApplication::translate(
"variable_help",
"Current QGIS version string." ) );
717 sVariableHelpTexts.insert( QStringLiteral(
"qgis_version_no" ), QCoreApplication::translate(
"variable_help",
"Current QGIS version number." ) );
718 sVariableHelpTexts.insert( QStringLiteral(
"qgis_release_name" ), QCoreApplication::translate(
"variable_help",
"Current QGIS release name." ) );
719 sVariableHelpTexts.insert( QStringLiteral(
"qgis_short_version" ), QCoreApplication::translate(
"variable_help",
"Short QGIS version string." ) );
720 sVariableHelpTexts.insert( QStringLiteral(
"qgis_os_name" ), QCoreApplication::translate(
"variable_help",
"Operating system name, e.g., 'windows', 'linux' or 'osx'." ) );
721 sVariableHelpTexts.insert( QStringLiteral(
"qgis_platform" ), QCoreApplication::translate(
"variable_help",
"QGIS platform, e.g., 'desktop' or 'server'." ) );
722 sVariableHelpTexts.insert( QStringLiteral(
"qgis_locale" ), QCoreApplication::translate(
"variable_help",
"Two letter identifier for current QGIS locale." ) );
723 sVariableHelpTexts.insert( QStringLiteral(
"user_account_name" ), QCoreApplication::translate(
"variable_help",
"Current user's operating system account name." ) );
724 sVariableHelpTexts.insert( QStringLiteral(
"user_full_name" ), QCoreApplication::translate(
"variable_help",
"Current user's operating system user name (if available)." ) );
727 sVariableHelpTexts.insert( QStringLiteral(
"project_title" ), QCoreApplication::translate(
"variable_help",
"Title of current project." ) );
728 sVariableHelpTexts.insert( QStringLiteral(
"project_path" ), QCoreApplication::translate(
"variable_help",
"Full path (including file name) of current project." ) );
729 sVariableHelpTexts.insert( QStringLiteral(
"project_folder" ), QCoreApplication::translate(
"variable_help",
"Folder for current project." ) );
730 sVariableHelpTexts.insert( QStringLiteral(
"project_filename" ), QCoreApplication::translate(
"variable_help",
"Filename of current project." ) );
731 sVariableHelpTexts.insert( QStringLiteral(
"project_basename" ), QCoreApplication::translate(
"variable_help",
"Base name of current project's filename (without path and extension)." ) );
732 sVariableHelpTexts.insert( QStringLiteral(
"project_home" ), QCoreApplication::translate(
"variable_help",
"Home path of current project." ) );
733 sVariableHelpTexts.insert( QStringLiteral(
"project_crs" ), QCoreApplication::translate(
"variable_help",
"Coordinate reference system of project (e.g., 'EPSG:4326')." ) );
734 sVariableHelpTexts.insert( QStringLiteral(
"project_crs_definition" ), QCoreApplication::translate(
"variable_help",
"Coordinate reference system of project (full definition)." ) );
735 sVariableHelpTexts.insert( QStringLiteral(
"project_author" ), QCoreApplication::translate(
"variable_help",
"Project author, taken from project metadata." ) );
736 sVariableHelpTexts.insert( QStringLiteral(
"project_abstract" ), QCoreApplication::translate(
"variable_help",
"Project abstract, taken from project metadata." ) );
737 sVariableHelpTexts.insert( QStringLiteral(
"project_creation_date" ), QCoreApplication::translate(
"variable_help",
"Project creation date, taken from project metadata." ) );
738 sVariableHelpTexts.insert( QStringLiteral(
"project_identifier" ), QCoreApplication::translate(
"variable_help",
"Project identifier, taken from project metadata." ) );
739 sVariableHelpTexts.insert( QStringLiteral(
"project_keywords" ), QCoreApplication::translate(
"variable_help",
"Project keywords, taken from project metadata." ) );
740 sVariableHelpTexts.insert( QStringLiteral(
"project_area_units" ), QCoreApplication::translate(
"variable_help",
"Area unit for current project, used when calculating areas of geometries." ) );
741 sVariableHelpTexts.insert( QStringLiteral(
"project_distance_units" ), QCoreApplication::translate(
"variable_help",
"Distance unit for current project, used when calculating lengths of geometries." ) );
742 sVariableHelpTexts.insert( QStringLiteral(
"project_ellipsoid" ), QCoreApplication::translate(
"variable_help",
"Name of ellipsoid of current project, used when calculating geodetic areas and lengths of geometries." ) );
745 sVariableHelpTexts.insert( QStringLiteral(
"layer_name" ), QCoreApplication::translate(
"variable_help",
"Name of current layer." ) );
746 sVariableHelpTexts.insert( QStringLiteral(
"layer_id" ), QCoreApplication::translate(
"variable_help",
"ID of current layer." ) );
747 sVariableHelpTexts.insert( QStringLiteral(
"layer" ), QCoreApplication::translate(
"variable_help",
"The current layer." ) );
750 sVariableHelpTexts.insert( QStringLiteral(
"layout_name" ), QCoreApplication::translate(
"variable_help",
"Name of composition." ) );
751 sVariableHelpTexts.insert( QStringLiteral(
"layout_numpages" ), QCoreApplication::translate(
"variable_help",
"Number of pages in composition." ) );
752 sVariableHelpTexts.insert( QStringLiteral(
"layout_page" ), QCoreApplication::translate(
"variable_help",
"Current page number in composition." ) );
753 sVariableHelpTexts.insert( QStringLiteral(
"layout_pageheight" ), QCoreApplication::translate(
"variable_help",
"Composition page height in mm." ) );
754 sVariableHelpTexts.insert( QStringLiteral(
"layout_pagewidth" ), QCoreApplication::translate(
"variable_help",
"Composition page width in mm." ) );
755 sVariableHelpTexts.insert( QStringLiteral(
"layout_dpi" ), QCoreApplication::translate(
"variable_help",
"Composition resolution (DPI)." ) );
758 sVariableHelpTexts.insert( QStringLiteral(
"atlas_layerid" ), QCoreApplication::translate(
"variable_help",
"Current atlas coverage layer ID." ) );
759 sVariableHelpTexts.insert( QStringLiteral(
"atlas_layername" ), QCoreApplication::translate(
"variable_help",
"Current atlas coverage layer name." ) );
760 sVariableHelpTexts.insert( QStringLiteral(
"atlas_totalfeatures" ), QCoreApplication::translate(
"variable_help",
"Total number of features in atlas." ) );
761 sVariableHelpTexts.insert( QStringLiteral(
"atlas_featurenumber" ), QCoreApplication::translate(
"variable_help",
"Current atlas feature number." ) );
762 sVariableHelpTexts.insert( QStringLiteral(
"atlas_filename" ), QCoreApplication::translate(
"variable_help",
"Current atlas file name." ) );
763 sVariableHelpTexts.insert( QStringLiteral(
"atlas_pagename" ), QCoreApplication::translate(
"variable_help",
"Current atlas page name." ) );
764 sVariableHelpTexts.insert( QStringLiteral(
"atlas_feature" ), QCoreApplication::translate(
"variable_help",
"Current atlas feature (as feature object)." ) );
765 sVariableHelpTexts.insert( QStringLiteral(
"atlas_featureid" ), QCoreApplication::translate(
"variable_help",
"Current atlas feature ID." ) );
766 sVariableHelpTexts.insert( QStringLiteral(
"atlas_geometry" ), QCoreApplication::translate(
"variable_help",
"Current atlas feature geometry." ) );
769 sVariableHelpTexts.insert( QStringLiteral(
"item_id" ), QCoreApplication::translate(
"variable_help",
"Layout item user ID (not necessarily unique)." ) );
770 sVariableHelpTexts.insert( QStringLiteral(
"item_uuid" ), QCoreApplication::translate(
"variable_help",
"layout item unique ID." ) );
771 sVariableHelpTexts.insert( QStringLiteral(
"item_left" ), QCoreApplication::translate(
"variable_help",
"Left position of layout item (in mm)." ) );
772 sVariableHelpTexts.insert( QStringLiteral(
"item_top" ), QCoreApplication::translate(
"variable_help",
"Top position of layout item (in mm)." ) );
773 sVariableHelpTexts.insert( QStringLiteral(
"item_width" ), QCoreApplication::translate(
"variable_help",
"Width of layout item (in mm)." ) );
774 sVariableHelpTexts.insert( QStringLiteral(
"item_height" ), QCoreApplication::translate(
"variable_help",
"Height of layout item (in mm)." ) );
777 sVariableHelpTexts.insert( QStringLiteral(
"map_id" ), QCoreApplication::translate(
"variable_help",
"ID of current map destination. This will be 'canvas' for canvas renders, and the item ID for layout map renders." ) );
778 sVariableHelpTexts.insert( QStringLiteral(
"map_rotation" ), QCoreApplication::translate(
"variable_help",
"Current rotation of map." ) );
779 sVariableHelpTexts.insert( QStringLiteral(
"map_scale" ), QCoreApplication::translate(
"variable_help",
"Current scale of map." ) );
780 sVariableHelpTexts.insert( QStringLiteral(
"map_extent" ), QCoreApplication::translate(
"variable_help",
"Geometry representing the current extent of the map." ) );
781 sVariableHelpTexts.insert( QStringLiteral(
"map_extent_center" ), QCoreApplication::translate(
"variable_help",
"Center of map." ) );
782 sVariableHelpTexts.insert( QStringLiteral(
"map_extent_width" ), QCoreApplication::translate(
"variable_help",
"Width of map." ) );
783 sVariableHelpTexts.insert( QStringLiteral(
"map_extent_height" ), QCoreApplication::translate(
"variable_help",
"Height of map." ) );
784 sVariableHelpTexts.insert( QStringLiteral(
"map_crs" ), QCoreApplication::translate(
"variable_help",
"Coordinate reference system of map (e.g., 'EPSG:4326')." ) );
785 sVariableHelpTexts.insert( QStringLiteral(
"map_crs_definition" ), QCoreApplication::translate(
"variable_help",
"Coordinate reference system of map (full definition)." ) );
786 sVariableHelpTexts.insert( QStringLiteral(
"map_units" ), QCoreApplication::translate(
"variable_help",
"Units for map measurements." ) );
787 sVariableHelpTexts.insert( QStringLiteral(
"map_layer_ids" ), QCoreApplication::translate(
"variable_help",
"List of map layer IDs visible in the map." ) );
788 sVariableHelpTexts.insert( QStringLiteral(
"map_layers" ), QCoreApplication::translate(
"variable_help",
"List of map layers visible in the map." ) );
790 sVariableHelpTexts.insert( QStringLiteral(
"row_number" ), QCoreApplication::translate(
"variable_help",
"Stores the number of the current row." ) );
791 sVariableHelpTexts.insert( QStringLiteral(
"grid_number" ), QCoreApplication::translate(
"variable_help",
"Current grid annotation value." ) );
792 sVariableHelpTexts.insert( QStringLiteral(
"grid_axis" ), QCoreApplication::translate(
"variable_help",
"Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );
795 sVariableHelpTexts.insert( QStringLiteral(
"canvas_cursor_point" ), QCoreApplication::translate(
"variable_help",
"Last cursor position on the canvas in the project's geographical coordinates." ) );
798 sVariableHelpTexts.insert( QStringLiteral(
"snapping_results" ), QCoreApplication::translate(
"variable_help",
799 "<p>An array with an item for each snapped point.</p>" 800 "<p>Each item is a map with the following keys:</p>" 802 "<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>" 803 "<dt>layer</dt><dd>The layer on which the snapped feature is</dd>" 804 "<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>" 805 "<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>" 806 "<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>" 811 sVariableHelpTexts.insert( QStringLiteral(
"geometry_part_count" ), QCoreApplication::translate(
"variable_help",
"Number of parts in rendered feature's geometry." ) );
812 sVariableHelpTexts.insert( QStringLiteral(
"geometry_part_num" ), QCoreApplication::translate(
"variable_help",
"Current geometry part number for feature being rendered." ) );
813 sVariableHelpTexts.insert( QStringLiteral(
"geometry_point_count" ), QCoreApplication::translate(
"variable_help",
"Number of points in the rendered geometry's part. It is only meaningful for line geometries and for symbol layers that set this variable." ) );
814 sVariableHelpTexts.insert( QStringLiteral(
"geometry_point_num" ), QCoreApplication::translate(
"variable_help",
"Current point number in the rendered geometry's part. It is only meaningful for line geometries and for symbol layers that set this variable." ) );
816 sVariableHelpTexts.insert( QStringLiteral(
"symbol_color" ), QCoreApplication::translate(
"symbol_color",
"Color of symbol used to render the feature." ) );
817 sVariableHelpTexts.insert( QStringLiteral(
"symbol_angle" ), QCoreApplication::translate(
"symbol_angle",
"Angle of symbol used to render the feature (valid for marker symbols only)." ) );
820 sVariableHelpTexts.insert( QStringLiteral(
"cluster_color" ), QCoreApplication::translate(
"cluster_color",
"Color of symbols within a cluster, or NULL if symbols have mixed colors." ) );
821 sVariableHelpTexts.insert( QStringLiteral(
"cluster_size" ), QCoreApplication::translate(
"cluster_size",
"Number of symbols contained within a cluster." ) );
824 sVariableHelpTexts.insert( QStringLiteral(
"algorithm_id" ), QCoreApplication::translate(
"algorithm_id",
"Unique ID for algorithm." ) );
825 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_minx" ), QCoreApplication::translate(
"fullextent_minx",
"Minimum x-value from full canvas extent (including all layers)." ) );
826 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_miny" ), QCoreApplication::translate(
"fullextent_miny",
"Minimum y-value from full canvas extent (including all layers)." ) );
827 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_maxx" ), QCoreApplication::translate(
"fullextent_maxx",
"Maximum x-value from full canvas extent (including all layers)." ) );
828 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_maxy" ), QCoreApplication::translate(
"fullextent_maxy",
"Maximum y-value from full canvas extent (including all layers)." ) );
831 sVariableHelpTexts.insert( QStringLiteral(
"notification_message" ), QCoreApplication::translate(
"notification_message",
"Content of the notification message sent by the provider (available only for actions triggered by provider notifications)." ) );
834 sVariableHelpTexts.insert( QStringLiteral(
"current_geometry" ), QCoreApplication::translate(
"current_geometry",
"Represents the geometry of the feature currently being edited in the form or the table row. Can be used in a form/row context to filter the related features." ) );
835 sVariableHelpTexts.insert( QStringLiteral(
"current_feature" ), QCoreApplication::translate(
"current_feature",
"Represents the feature currently being edited in the form or the table row. Can be used in a form/row context to filter the related features." ) );
838 sVariableHelpTexts.insert( QStringLiteral(
"form_mode" ), QCoreApplication::translate(
"form_mode",
"What the form is used for, like AddFeatureMode, SingleEditMode, MultiEditMode, SearchMode, AggregateSearchMode or IdentifyMode as string." ) );
843 QgsExpression::initVariableHelp();
844 return sVariableHelpTexts.value( variableName, QString() );
849 QString text = !description.isEmpty() ? QStringLiteral(
"<p>%1</p>" ).arg( description ) : QString();
853 if ( !value.isValid() )
855 valueString = QCoreApplication::translate(
"variable_help",
"not set" );
861 text.append( QCoreApplication::translate(
"variable_help",
"<p>Current value: %1</p>" ).arg( valueString ) );
866 QHash<QString, QString> QgsExpression::sGroups;
870 if ( sGroups.isEmpty() )
872 sGroups.insert( QStringLiteral(
"Aggregates" ), tr(
"Aggregates" ) );
873 sGroups.insert( QStringLiteral(
"Arrays" ), tr(
"Arrays" ) );
874 sGroups.insert( QStringLiteral(
"General" ), tr(
"General" ) );
875 sGroups.insert( QStringLiteral(
"Operators" ), tr(
"Operators" ) );
876 sGroups.insert( QStringLiteral(
"Conditionals" ), tr(
"Conditionals" ) );
877 sGroups.insert( QStringLiteral(
"Fields and Values" ), tr(
"Fields and Values" ) );
878 sGroups.insert( QStringLiteral(
"Map Layers" ), tr(
"Map Layers" ) );
879 sGroups.insert( QStringLiteral(
"Maps" ), tr(
"Maps" ) );
880 sGroups.insert( QStringLiteral(
"Math" ), tr(
"Math" ) );
881 sGroups.insert( QStringLiteral(
"Conversions" ), tr(
"Conversions" ) );
882 sGroups.insert( QStringLiteral(
"Date and Time" ), tr(
"Date and Time" ) );
883 sGroups.insert( QStringLiteral(
"String" ), tr(
"String" ) );
884 sGroups.insert( QStringLiteral(
"Color" ), tr(
"Color" ) );
885 sGroups.insert( QStringLiteral(
"GeometryGroup" ), tr(
"Geometry" ) );
886 sGroups.insert( QStringLiteral(
"Rasters" ), tr(
"Rasters" ) );
887 sGroups.insert( QStringLiteral(
"Record and Attributes" ), tr(
"Record and Attributes" ) );
888 sGroups.insert( QStringLiteral(
"Variables" ), tr(
"Variables" ) );
889 sGroups.insert( QStringLiteral(
"Fuzzy Matching" ), tr(
"Fuzzy Matching" ) );
890 sGroups.insert( QStringLiteral(
"Recent (%1)" ), tr(
"Recent (%1)" ) );
896 return sGroups.value( name, name );
901 static const int MAX_PREVIEW = 60;
903 const QString startToken = htmlOutput ? QStringLiteral(
"<i><" ) : QStringLiteral(
"<" );
904 const QString endToken = htmlOutput ? QStringLiteral(
"></i>" ) : QStringLiteral(
">" );
911 return startToken + tr(
"empty geometry" ) + endToken;
918 return startToken + tr(
"map layer" ) + endToken;
920 else if ( !value.isValid() )
922 return htmlOutput ? tr(
"<i>NULL</i>" ) : QString();
928 return startToken + tr(
"feature: %1" ).arg( feat.
id() ) + endToken;
934 return startToken + tr(
"interval: %1 days" ).arg( interval.
days() ) + endToken;
938 return startToken + tr(
"gradient ramp" ) + endToken;
940 else if ( value.type() == QVariant::Date )
942 QDate dt = value.toDate();
943 return startToken + tr(
"date: %1" ).arg( dt.toString( QStringLiteral(
"yyyy-MM-dd" ) ) ) + endToken;
945 else if ( value.type() == QVariant::Time )
947 QTime tm = value.toTime();
948 return startToken + tr(
"time: %1" ).arg( tm.toString( QStringLiteral(
"hh:mm:ss" ) ) ) + endToken;
950 else if ( value.type() == QVariant::DateTime )
952 QDateTime dt = value.toDateTime();
953 return startToken + tr(
"datetime: %1" ).arg( dt.toString( QStringLiteral(
"yyyy-MM-dd hh:mm:ss" ) ) ) + endToken;
955 else if ( value.type() == QVariant::String )
957 const QString previewString = value.toString();
958 if ( previewString.length() > MAX_PREVIEW + 3 )
960 return tr(
"'%1…'" ).arg( previewString.left( MAX_PREVIEW ) );
964 return '\'' + previewString +
'\'';
967 else if ( value.type() == QVariant::Map )
969 QString mapStr = QStringLiteral(
"{" );
970 const QVariantMap map = value.toMap();
972 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
974 mapStr.append( separator );
975 if ( separator.isEmpty() )
976 separator = QStringLiteral(
"," );
978 mapStr.append( QStringLiteral(
" '%1': %2" ).arg( it.key(),
formatPreviewString( it.value(), htmlOutput ) ) );
979 if ( mapStr.length() > MAX_PREVIEW - 3 )
981 mapStr = tr(
"%1…" ).arg( mapStr.left( MAX_PREVIEW - 2 ) );
986 mapStr += QStringLiteral(
" " );
987 mapStr += QStringLiteral(
"}" );
990 else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
992 QString listStr = QStringLiteral(
"[" );
993 const QVariantList list = value.toList();
995 for (
const QVariant &arrayValue : list )
997 listStr.append( separator );
998 if ( separator.isEmpty() )
999 separator = QStringLiteral(
"," );
1001 listStr.append(
" " );
1003 if ( listStr.length() > MAX_PREVIEW - 3 )
1005 listStr = QString( tr(
"%1…" ) ).arg( listStr.left( MAX_PREVIEW - 2 ) );
1009 if ( !list.empty() )
1010 listStr += QStringLiteral(
" " );
1011 listStr += QStringLiteral(
"]" );
1016 return value.toString();
1024 if ( value.isNull() )
1025 expr = QStringLiteral(
"%1 IS NULL" ).arg(
quotedColumnRef( fieldName ) );
1034 return d->mRootNode;
1044 if ( !d->mRootNode )
1045 return QList<const QgsExpressionNode *>();
1047 return d->mRootNode->nodes();
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
static bool isFunctionName(const QString &name)
tells whether the identifier is a name of existing function
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
static QString formatPreviewString(const QVariant &value, bool htmlOutput=true)
Formats an expression result for friendly display to the user.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
static QList< QgsExpressionFunction * > sOwnedFunctions
List of functions owned by the expression engine.
QSet< QString > referencedVariables() const
Returns a list of all variables which are used in this expression.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static QString group(const QString &group)
Returns the translated name for a function group.
bool isValid() const
Checks if this expression is valid.
static Q_INVOKABLE AreaUnit stringToAreaUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to an areal unit.
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
QVariant evaluate()
Evaluate the feature and return the result.
QgsExpression()
Create an empty expression.
bool operator==(const QgsExpression &other) const
Compares two expressions.
static double evaluateToDouble(const QString &text, double fallbackValue)
Attempts to evaluate a text string as an expression to a resultant double value.
QgsExpressionNode * parseExpression(const QString &str, QString &parserErrorMsg, QList< QgsExpression::ParserError > &parserErrors)
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree. ...
QSet< QString > referencedFunctions() const
Returns a list of the names of all functions which are used in this expression.
static QString variableHelpText(const QString &variableName)
Returns the help text for a specified variable.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
const QgsCoordinateReferenceSystem & crs
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
static QStringList sBuiltinFunctions
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
static const QStringList & BuiltinFunctions()
static bool unregisterFunction(const QString &name)
Unregisters a function from the expression engine.
double days() const
Returns the interval duration in days.
static int functionCount()
Returns the number of functions defined in the parser.
static bool checkExpression(const QString &text, const QgsExpressionContext *context, QString &errorMessage)
Tests whether a string is a valid expression.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine...
QgsExpression & operator=(const QgsExpression &other)
Create a copy of this expression.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
bool isField() const
Checks whether an expression consists only of a single field reference.
Abstract base class for all nodes that can appear in an expression.
QList< QgsExpression::ParserError > parserErrors() const
Returns parser error details including location of error.
static QList< QgsExpressionFunction * > sFunctions
QgsUnitTypes::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g., "$area".
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Contains information about the context in which a coordinate transform is executed.
static const QList< QgsExpressionFunction * > & Functions()
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
static QString formatVariableHelp(const QString &description, bool showValue=true, const QVariant &value=QVariant())
Returns formatted help text for a variable.
QgsUnitTypes::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
A representation of the interval between two datetime values.
DistanceUnit
Units of distance.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations...
static Q_INVOKABLE QgsUnitTypes::DistanceUnit stringToDistanceUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to a distance unit.
A abstract base class for defining QgsExpression functions.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
QList< const QgsExpressionNode * > nodes() const
Returns a list of all nodes which are used in this expression.
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
void setDistanceUnits(QgsUnitTypes::DistanceUnit unit)
Sets the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
static QgsProject * instance()
Returns the QgsProject singleton instance.
This class represents a coordinate reference system (CRS).
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
const QgsExpressionNode * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
static QString helpText(QString name)
Returns the help text for a specified function.
QString expression() const
Returns the original, unmodified expression string.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required...
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
QString parserErrorString() const
Returns parser error.
QString evalErrorString() const
Returns evaluation error.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...