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_description" ), QCoreApplication::translate(
"variable_help",
"Name of the coordinate reference system of the map." ) );
786 sVariableHelpTexts.insert( QStringLiteral(
"map_units" ), QCoreApplication::translate(
"variable_help",
"Units for map measurements." ) );
787 sVariableHelpTexts.insert( QStringLiteral(
"map_crs_definition" ), QCoreApplication::translate(
"variable_help",
"Coordinate reference system of map (full definition)." ) );
788 sVariableHelpTexts.insert( QStringLiteral(
"map_crs_acronym" ), QCoreApplication::translate(
"variable_help",
"Acronym of the coordinate reference system of the map." ) );
789 sVariableHelpTexts.insert( QStringLiteral(
"map_crs_ellipsoid" ), QCoreApplication::translate(
"variable_help",
"Acronym of the ellipsoid of the coordinate reference system of the map." ) );
790 sVariableHelpTexts.insert( QStringLiteral(
"map_crs_proj4" ), QCoreApplication::translate(
"variable_help",
"Proj4 definition of the coordinate reference system." ) );
791 sVariableHelpTexts.insert( QStringLiteral(
"map_crs_wkt" ), QCoreApplication::translate(
"variable_help",
"WKT definition of the coordinate reference system." ) );
792 sVariableHelpTexts.insert( QStringLiteral(
"map_layer_ids" ), QCoreApplication::translate(
"variable_help",
"List of map layer IDs visible in the map." ) );
793 sVariableHelpTexts.insert( QStringLiteral(
"map_layers" ), QCoreApplication::translate(
"variable_help",
"List of map layers visible in the map." ) );
795 sVariableHelpTexts.insert( QStringLiteral(
"row_number" ), QCoreApplication::translate(
"variable_help",
"Stores the number of the current row." ) );
796 sVariableHelpTexts.insert( QStringLiteral(
"grid_number" ), QCoreApplication::translate(
"variable_help",
"Current grid annotation value." ) );
797 sVariableHelpTexts.insert( QStringLiteral(
"grid_axis" ), QCoreApplication::translate(
"variable_help",
"Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );
800 sVariableHelpTexts.insert( QStringLiteral(
"canvas_cursor_point" ), QCoreApplication::translate(
"variable_help",
"Last cursor position on the canvas in the project's geographical coordinates." ) );
803 sVariableHelpTexts.insert( QStringLiteral(
"legend_title" ), QCoreApplication::translate(
"variable_help",
"Title of the legend." ) );
804 sVariableHelpTexts.insert( QStringLiteral(
"legend_column_count" ), QCoreApplication::translate(
"variable_help",
"Number of column in the legend." ) );
805 sVariableHelpTexts.insert( QStringLiteral(
"legend_split_layers" ), QCoreApplication::translate(
"variable_help",
"Boolean indicating if layers can be split in the legend." ) );
806 sVariableHelpTexts.insert( QStringLiteral(
"legend_wrap_string" ), QCoreApplication::translate(
"variable_help",
"Characters used to wrap the legend text." ) );
807 sVariableHelpTexts.insert( QStringLiteral(
"legend_filter_by_map" ), QCoreApplication::translate(
"variable_help",
"Boolean indicating if the content of the legend is filtered by the map." ) );
808 sVariableHelpTexts.insert( QStringLiteral(
"legend_filter_out_atlas" ), QCoreApplication::translate(
"variable_help",
"Boolean indicating if the Atlas is filtered out of the legend." ) );
812 sVariableHelpTexts.insert( QStringLiteral(
"snapping_results" ), QCoreApplication::translate(
"variable_help",
813 "<p>An array with an item for each snapped point.</p>" 814 "<p>Each item is a map with the following keys:</p>" 816 "<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>" 817 "<dt>layer</dt><dd>The layer on which the snapped feature is</dd>" 818 "<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>" 819 "<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>" 820 "<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>" 825 sVariableHelpTexts.insert( QStringLiteral(
"geometry_part_count" ), QCoreApplication::translate(
"variable_help",
"Number of parts in rendered feature's geometry." ) );
826 sVariableHelpTexts.insert( QStringLiteral(
"geometry_part_num" ), QCoreApplication::translate(
"variable_help",
"Current geometry part number for feature being rendered." ) );
827 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." ) );
828 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." ) );
830 sVariableHelpTexts.insert( QStringLiteral(
"symbol_color" ), QCoreApplication::translate(
"symbol_color",
"Color of symbol used to render the feature." ) );
831 sVariableHelpTexts.insert( QStringLiteral(
"symbol_angle" ), QCoreApplication::translate(
"symbol_angle",
"Angle of symbol used to render the feature (valid for marker symbols only)." ) );
834 sVariableHelpTexts.insert( QStringLiteral(
"cluster_color" ), QCoreApplication::translate(
"cluster_color",
"Color of symbols within a cluster, or NULL if symbols have mixed colors." ) );
835 sVariableHelpTexts.insert( QStringLiteral(
"cluster_size" ), QCoreApplication::translate(
"cluster_size",
"Number of symbols contained within a cluster." ) );
838 sVariableHelpTexts.insert( QStringLiteral(
"algorithm_id" ), QCoreApplication::translate(
"algorithm_id",
"Unique ID for algorithm." ) );
839 sVariableHelpTexts.insert( QStringLiteral(
"model_path" ), QCoreApplication::translate(
"variable_help",
"Full path (including file name) of current model (or project path if model is embedded in a project)." ) );
840 sVariableHelpTexts.insert( QStringLiteral(
"model_folder" ), QCoreApplication::translate(
"variable_help",
"Folder containing current model (or project folder if model is embedded in a project)." ) );
841 sVariableHelpTexts.insert( QStringLiteral(
"model_name" ), QCoreApplication::translate(
"variable_help",
"Name of current model." ) );
842 sVariableHelpTexts.insert( QStringLiteral(
"model_group" ), QCoreApplication::translate(
"variable_help",
"Group for current model." ) );
843 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_minx" ), QCoreApplication::translate(
"fullextent_minx",
"Minimum x-value from full canvas extent (including all layers)." ) );
844 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_miny" ), QCoreApplication::translate(
"fullextent_miny",
"Minimum y-value from full canvas extent (including all layers)." ) );
845 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_maxx" ), QCoreApplication::translate(
"fullextent_maxx",
"Maximum x-value from full canvas extent (including all layers)." ) );
846 sVariableHelpTexts.insert( QStringLiteral(
"fullextent_maxy" ), QCoreApplication::translate(
"fullextent_maxy",
"Maximum y-value from full canvas extent (including all layers)." ) );
849 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)." ) );
852 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." ) );
853 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." ) );
856 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." ) );
861 QgsExpression::initVariableHelp();
862 return sVariableHelpTexts.value( variableName, QString() );
867 QString text = !description.isEmpty() ? QStringLiteral(
"<p>%1</p>" ).arg( description ) : QString();
871 if ( !value.isValid() )
873 valueString = QCoreApplication::translate(
"variable_help",
"not set" );
879 text.append( QCoreApplication::translate(
"variable_help",
"<p>Current value: %1</p>" ).arg( valueString ) );
884 QHash<QString, QString> QgsExpression::sGroups;
888 if ( sGroups.isEmpty() )
890 sGroups.insert( QStringLiteral(
"Aggregates" ), tr(
"Aggregates" ) );
891 sGroups.insert( QStringLiteral(
"Arrays" ), tr(
"Arrays" ) );
892 sGroups.insert( QStringLiteral(
"Color" ), tr(
"Color" ) );
893 sGroups.insert( QStringLiteral(
"Conditionals" ), tr(
"Conditionals" ) );
894 sGroups.insert( QStringLiteral(
"Conversions" ), tr(
"Conversions" ) );
895 sGroups.insert( QStringLiteral(
"Date and Time" ), tr(
"Date and Time" ) );
896 sGroups.insert( QStringLiteral(
"Fields and Values" ), tr(
"Fields and Values" ) );
897 sGroups.insert( QStringLiteral(
"Files and Paths" ), tr(
"Files and Paths" ) );
898 sGroups.insert( QStringLiteral(
"Fuzzy Matching" ), tr(
"Fuzzy Matching" ) );
899 sGroups.insert( QStringLiteral(
"General" ), tr(
"General" ) );
900 sGroups.insert( QStringLiteral(
"GeometryGroup" ), tr(
"Geometry" ) );
901 sGroups.insert( QStringLiteral(
"Map Layers" ), tr(
"Map Layers" ) );
902 sGroups.insert( QStringLiteral(
"Maps" ), tr(
"Maps" ) );
903 sGroups.insert( QStringLiteral(
"Math" ), tr(
"Math" ) );
904 sGroups.insert( QStringLiteral(
"Operators" ), tr(
"Operators" ) );
905 sGroups.insert( QStringLiteral(
"Rasters" ), tr(
"Rasters" ) );
906 sGroups.insert( QStringLiteral(
"Record and Attributes" ), tr(
"Record and Attributes" ) );
907 sGroups.insert( QStringLiteral(
"String" ), tr(
"String" ) );
908 sGroups.insert( QStringLiteral(
"Variables" ), tr(
"Variables" ) );
909 sGroups.insert( QStringLiteral(
"Recent (%1)" ), tr(
"Recent (%1)" ) );
915 return sGroups.value( name, name );
920 static const int MAX_PREVIEW = 60;
922 const QString startToken = htmlOutput ? QStringLiteral(
"<i><" ) : QStringLiteral(
"<" );
923 const QString endToken = htmlOutput ? QStringLiteral(
"></i>" ) : QStringLiteral(
">" );
930 return startToken + tr(
"empty geometry" ) + endToken;
937 return startToken + tr(
"map layer" ) + endToken;
939 else if ( !value.isValid() )
941 return htmlOutput ? tr(
"<i>NULL</i>" ) : QString();
947 return startToken + tr(
"feature: %1" ).arg( feat.
id() ) + endToken;
953 return startToken + tr(
"interval: %1 days" ).arg( interval.
days() ) + endToken;
957 return startToken + tr(
"gradient ramp" ) + endToken;
959 else if ( value.type() == QVariant::Date )
961 QDate dt = value.toDate();
962 return startToken + tr(
"date: %1" ).arg( dt.toString( QStringLiteral(
"yyyy-MM-dd" ) ) ) + endToken;
964 else if ( value.type() == QVariant::Time )
966 QTime tm = value.toTime();
967 return startToken + tr(
"time: %1" ).arg( tm.toString( QStringLiteral(
"hh:mm:ss" ) ) ) + endToken;
969 else if ( value.type() == QVariant::DateTime )
971 QDateTime dt = value.toDateTime();
972 return startToken + tr(
"datetime: %1" ).arg( dt.toString( QStringLiteral(
"yyyy-MM-dd hh:mm:ss" ) ) ) + endToken;
974 else if ( value.type() == QVariant::String )
976 const QString previewString = value.toString();
977 if ( previewString.length() > MAX_PREVIEW + 3 )
979 return tr(
"'%1…'" ).arg( previewString.left( MAX_PREVIEW ) );
983 return '\'' + previewString +
'\'';
986 else if ( value.type() == QVariant::Map )
988 QString mapStr = QStringLiteral(
"{" );
989 const QVariantMap map = value.toMap();
991 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
993 mapStr.append( separator );
994 if ( separator.isEmpty() )
995 separator = QStringLiteral(
"," );
997 mapStr.append( QStringLiteral(
" '%1': %2" ).arg( it.key(),
formatPreviewString( it.value(), htmlOutput ) ) );
998 if ( mapStr.length() > MAX_PREVIEW - 3 )
1000 mapStr = tr(
"%1…" ).arg( mapStr.left( MAX_PREVIEW - 2 ) );
1005 mapStr += QStringLiteral(
" " );
1006 mapStr += QStringLiteral(
"}" );
1009 else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
1011 QString listStr = QStringLiteral(
"[" );
1012 const QVariantList list = value.toList();
1014 for (
const QVariant &arrayValue : list )
1016 listStr.append( separator );
1017 if ( separator.isEmpty() )
1018 separator = QStringLiteral(
"," );
1020 listStr.append(
" " );
1022 if ( listStr.length() > MAX_PREVIEW - 3 )
1024 listStr = QString( tr(
"%1…" ) ).arg( listStr.left( MAX_PREVIEW - 2 ) );
1028 if ( !list.empty() )
1029 listStr += QStringLiteral(
" " );
1030 listStr += QStringLiteral(
"]" );
1035 return value.toString();
1043 if ( value.isNull() )
1044 expr = QStringLiteral(
"%1 IS NULL" ).arg(
quotedColumnRef( fieldName ) );
1053 return d->mRootNode;
1063 if ( !d->mRootNode )
1064 return QList<const QgsExpressionNode *>();
1066 return d->mRootNode->nodes();
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
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 hasParserError() const
Returns true if an error occurred when parsing the input expression.
static QString formatPreviewString(const QVariant &value, bool htmlOutput=true)
Formats an expression result for friendly display to the user.
static QList< QgsExpressionFunction * > sOwnedFunctions
List of functions owned by the expression engine.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
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 operator==(const QgsExpression &other) const
Compares two expressions.
static Q_INVOKABLE AreaUnit stringToAreaUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to an areal unit.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree. ...
QVariant evaluate()
Evaluate the feature and return the result.
QgsExpression()
Create an empty expression.
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)
QString evalErrorString() const
Returns evaluation error.
Container of fields for a vector layer.
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
A geometry is the spatial representation of a feature.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QList< QgsExpression::ParserError > parserErrors() const
Returns parser error details including location of error.
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.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
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.
QString parserErrorString() const
Returns parser error.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QSet< QString > referencedVariables() const
Returns a list of all variables which are used in this expression.
static QStringList sBuiltinFunctions
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
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.
QgsUnitTypes::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g., "$area".
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.
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...
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
bool isValid() const
Checks if this expression is valid.
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.
Abstract base class for all nodes that can appear in an expression.
static QList< QgsExpressionFunction * > sFunctions
Contains information about the context in which a coordinate transform is executed.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
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.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsUnitTypes::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
QString expression() const
Returns the original, unmodified expression string.
A representation of the interval between two datetime values.
DistanceUnit
Units of distance.
double days() const
Returns the interval duration in days.
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.
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
const QgsExpressionNode * rootNode() const
Returns the root node of the 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).
bool isField() const
Checks whether an expression consists only of a single field reference.
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...
static QString helpText(QString name)
Returns the help text for a specified function.
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 ...
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QList< const QgsExpressionNode * > nodes() const
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedFunctions() const
Returns a list of the names of all functions which are used in this expression.
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...
bool isValid() const
Returns whether this CRS is correctly initialized and usable.