34#include <QRegularExpression>
37using namespace Qt::StringLiterals;
45HelpTextHash QgsExpression::sFunctionHelpTexts;
46QRecursiveMutex QgsExpression::sFunctionsMutex;
47QMap< QString, int> QgsExpression::sFunctionIndexMap;
50HelpTextHash &QgsExpression::functionHelpTexts()
52 return sFunctionHelpTexts;
68 d->mEvalErrorString = QString();
70 d->mIsPrepared =
false;
75 if ( !d->mExp.isNull() )
83 return u
"\"%1\""_s.arg( name.replace(
'\"',
"\"\""_L1 ) );
88 text.replace(
'\'',
"''"_L1 );
89 text.replace(
'\\',
"\\\\"_L1 );
90 text.replace(
'\n',
"\\n"_L1 );
91 text.replace(
'\t',
"\\t"_L1 );
92 return u
"'%1'"_s.arg( text );
97 return quotedValue( value,
static_cast<QMetaType::Type
>( value.userType() ) );
107 case QMetaType::Type::Int:
108 case QMetaType::Type::LongLong:
109 case QMetaType::Type::Double:
110 return value.toString();
112 case QMetaType::Type::Bool:
113 return value.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
115 case QMetaType::Type::QVariantList:
116 case QMetaType::Type::QStringList:
118 QStringList quotedValues;
119 const QVariantList values = value.toList();
120 quotedValues.reserve( values.count() );
121 for (
const QVariant &v : values )
125 return u
"array( %1 )"_s.arg( quotedValues.join(
", "_L1 ) );
129 case QMetaType::Type::QString:
146 QMutexLocker locker( &sFunctionsMutex );
148 auto it = sFunctionIndexMap.constFind( name );
149 if ( it != sFunctionIndexMap.constEnd() )
156 if ( QString::compare( name, function->name(), Qt::CaseInsensitive ) == 0 )
158 sFunctionIndexMap.insert( name, i );
161 const QStringList aliases = function->aliases();
162 for (
const QString &alias : aliases )
164 if ( QString::compare( name, alias, Qt::CaseInsensitive ) == 0 )
166 sFunctionIndexMap.insert( name, i );
182 : d( new QgsExpressionPrivate )
184 d->mRootNode.reset(
::parseExpression( expr, d->mParserErrorString, d->mParserErrors ) );
186 Q_ASSERT( !d->mParserErrorString.isNull() || d->mRootNode );
197 if (
this != &other )
199 if ( !d->ref.deref() )
210QgsExpression::operator QString()
const
216 : d( new QgsExpressionPrivate )
222 if ( !d->ref.deref() )
228 return ( d == other.d || d->mExp == other.d->mExp );
233 return d->mRootNode.get();
238 return d->mParserErrors.count() > 0;
243 return d->mParserErrorString.replace(
"syntax error, unexpected end of file", tr(
"Incomplete expression. You might not have finished the full expression." ) );
248 return d->mParserErrors;
254 return QSet<QString>();
256 return d->mRootNode->referencedColumns();
262 return QSet<QString>();
264 return d->mRootNode->referencedVariables();
270 return QSet<QString>();
272 return d->mRootNode->referencedFunctions();
280 const QSet<QString> referencedFields = d->mRootNode->referencedColumns();
281 QSet<int> referencedIndexes;
283 for (
const QString &fieldName : referencedFields )
288 referencedIndexes = QSet<int>( attributesList.begin(), attributesList.end() );
294 referencedIndexes << idx;
298 return referencedIndexes;
305 return d->mRootNode->needsGeometry();
311 if ( context && !d->mCalc )
315 d->mDaEllipsoid = context->
variable( u
"project_ellipsoid"_s ).toString();
323 QString distanceUnitsStr = context->
variable( u
"project_distance_units"_s ).toString();
324 if ( !distanceUnitsStr.isEmpty() )
331 QString areaUnitsStr = context->
variable( u
"project_area_units"_s ).toString();
332 if ( !areaUnitsStr.isEmpty() )
337void QgsExpression::detach()
343 ( void ) d->ref.deref();
345 d =
new QgsExpressionPrivate( *d );
349void QgsExpression::initFunctionHelp()
351 static std::once_flag initialized;
352 std::call_once( initialized, buildFunctionHelp );
359 d->mCalc = std::make_shared<QgsDistanceArea>( *calc );
367 d->mEvalErrorString = QString();
373 d->mRootNode.reset(
::parseExpression( d->mExp, d->mParserErrorString, d->mParserErrors ) );
378 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
382 initGeomCalculator( context );
383 d->mIsPrepared =
true;
384 return d->mRootNode->prepare(
this, context );
389 d->mEvalErrorString = QString();
392 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
401 d->mEvalErrorString = QString();
404 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
408 if ( !d->mIsPrepared )
412 return d->mRootNode->eval(
this, context );
417 return !d->mEvalErrorString.isNull();
422 return d->mEvalErrorString;
427 d->mEvalErrorString = str;
435 return d->mRootNode->dump();
440 if ( !d->mCalc && d->mDaCrs && d->mDaCrs->isValid() && d->mDaTransformContext )
443 d->mCalc = std::make_shared<QgsDistanceArea>();
444 d->mCalc->setEllipsoid( d->mDaEllipsoid.isEmpty() ?
Qgis::geoNone() : d->mDaEllipsoid );
445 d->mCalc->setSourceCrs( *d->mDaCrs.get(), *d->mDaTransformContext.get() );
448 return d->mCalc.get();
453 return d->mDistanceUnit;
458 d->mDistanceUnit = unit;
476 while ( index < action.size() )
478 static const QRegularExpression sRegEx { u
"\\[%(.*?)%\\]"_s, QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption };
480 const QRegularExpressionMatch match = sRegEx.match( action, index );
481 if ( !match.hasMatch() )
484 const int pos = action.indexOf( sRegEx, index );
485 const int start = index;
486 index = pos + match.capturedLength( 0 );
487 const QString toReplace = match.captured( 1 ).trimmed();
494 expr_action += QStringView { action }.mid( start, index - start );
504 QVariant result = exp.
evaluate( context );
509 expr_action += QStringView { action }.mid( start, index - start );
513 QString resultString;
515 resultString = result.toString();
519 expr_action += action.mid( start, pos - start ) + resultString;
522 expr_action += QStringView { action }.mid( index ).toString();
528 QSet<QString> variables;
530 while ( index < text.size() )
532 const thread_local QRegularExpression rx(
"\\[%([^\\]]+)%\\]" );
533 const QRegularExpressionMatch match = rx.match( text );
534 if ( !match.hasMatch() )
537 index = match.capturedStart() + match.capturedLength();
538 QString to_replace = match.captured( 1 ).trimmed();
553 double convertedValue = QLocale().toDouble( text, &ok );
556 return convertedValue;
565 QVariant result = expr.
evaluate( &context );
566 convertedValue = result.toDouble( &ok );
569 return fallbackValue;
571 return convertedValue;
576 QgsExpression::initFunctionHelp();
578 if ( !sFunctionHelpTexts.contains( name ) )
579 return tr(
"function help for %1 missing" ).arg( name );
581 const Help &f = sFunctionHelpTexts[name];
584 if ( f.mType == tr(
"group" ) )
586 name =
group( name );
587 name = name.toLower();
590 name = name.toHtmlEscaped();
592 QString helpContents( u
"<h3>%1</h3>\n<div class=\"description\"><p>%2</p></div>"_s.arg( tr(
"%1 %2" ).arg( f.mType, name ), f.mDescription ) );
594 for (
const HelpVariant &v : std::as_const( f.mVariants ) )
596 if ( f.mVariants.size() > 1 )
598 helpContents += u
"<h3>%1</h3>\n<div class=\"description\">%2</p></div>"_s.arg( v.mName, v.mDescription );
601 if ( f.mType != tr(
"group" ) && f.mType != tr(
"expression" ) )
602 helpContents += u
"<h4>%1</h4>\n<div class=\"syntax\">\n"_s.arg( tr(
"Syntax" ) );
604 if ( f.mType == tr(
"operator" ) )
606 if ( v.mArguments.size() == 1 )
608 helpContents += u
"<code><span class=\"functionname\">%1</span> <span class=\"argument\">%2</span></code>"_s.arg( name, v.mArguments[0].mArg );
610 else if ( v.mArguments.size() == 2 )
612 helpContents += u
"<code><span class=\"argument\">%1</span> <span class=\"functionname\">%2</span> <span class=\"argument\">%3</span></code>"_s.arg( v.mArguments[0].mArg, name, v.mArguments[1].mArg );
615 else if ( f.mType != tr(
"group" ) && f.mType != tr(
"expression" ) )
617 helpContents += u
"<code><span class=\"functionname\">%1</span>"_s.arg( name );
619 bool hasOptionalArgs =
false;
621 if ( f.mType == tr(
"function" ) && ( f.mName[0] !=
'$' || !v.mArguments.isEmpty() || v.mVariableLenArguments ) )
626 for (
const HelpArg &a : std::as_const( v.mArguments ) )
632 hasOptionalArgs =
true;
633 helpContents +=
'['_L1;
636 helpContents += delim;
637 helpContents += u
"<span class=\"argument\">%2%3</span>"_s.arg( a.mArg, a.mDefaultVal.isEmpty() ? QString() :
":=" + a.mDefaultVal );
640 helpContents +=
']'_L1;
645 if ( v.mVariableLenArguments )
647 helpContents += QChar( 0x2026 );
653 helpContents +=
"</code>"_L1;
655 if ( hasOptionalArgs )
657 helpContents +=
"<br/><br/>"_L1 + tr(
"[ ] marks optional components" );
661 if ( !v.mArguments.isEmpty() )
663 helpContents += u
"<h4>%1</h4>\n<div class=\"arguments\">\n<table>"_s.arg( tr(
"Arguments" ) );
665 for (
const HelpArg &a : std::as_const( v.mArguments ) )
670 helpContents += u
"<tr><td class=\"argument\">%1</td><td>%2</td></tr>"_s.arg( a.mArg, a.mDescription );
673 helpContents +=
"</table>\n</div>\n"_L1;
676 if ( !v.mExamples.isEmpty() )
678 helpContents += u
"<h4>%1</h4>\n<div class=\"examples\">\n<ul>\n"_s.arg( tr(
"Examples" ) );
680 for (
const HelpExample &e : std::as_const( v.mExamples ) )
682 helpContents +=
"<li><code>" + e.mExpression +
"</code> → <code>" + e.mReturns +
"</code>";
684 if ( !e.mNote.isEmpty() )
685 helpContents += u
" (%1)"_s.arg( e.mNote );
687 helpContents +=
"</li>\n"_L1;
690 helpContents +=
"</ul>\n</div>\n"_L1;
693 if ( !v.mNotes.isEmpty() )
695 helpContents += u
"<h4>%1</h4>\n<div class=\"notes\"><p>%2</p></div>\n"_s.arg( tr(
"Notes" ), v.mNotes );
704 QStringList
tags = QStringList();
706 QgsExpression::initFunctionHelp();
708 if ( sFunctionHelpTexts.contains( name ) )
710 const Help &f = sFunctionHelpTexts[name];
712 for (
const HelpVariant &v : std::as_const( f.mVariants ) )
721void QgsExpression::initVariableHelp()
723 static std::once_flag initialized;
724 std::call_once( initialized, buildVariableHelp );
727void QgsExpression::buildVariableHelp()
730 sVariableHelpTexts()->insert( u
"qgis_version"_s, QCoreApplication::translate(
"variable_help",
"Current QGIS version string." ) );
731 sVariableHelpTexts()->insert( u
"qgis_version_no"_s, QCoreApplication::translate(
"variable_help",
"Current QGIS version number." ) );
732 sVariableHelpTexts()->insert( u
"qgis_release_name"_s, QCoreApplication::translate(
"variable_help",
"Current QGIS release name." ) );
733 sVariableHelpTexts()->insert( u
"qgis_short_version"_s, QCoreApplication::translate(
"variable_help",
"Short QGIS version string." ) );
734 sVariableHelpTexts()->insert( u
"qgis_os_name"_s, QCoreApplication::translate(
"variable_help",
"Operating system name, e.g., 'windows', 'linux' or 'osx'." ) );
735 sVariableHelpTexts()->insert( u
"qgis_platform"_s, QCoreApplication::translate(
"variable_help",
"QGIS platform, e.g., 'desktop' or 'server'." ) );
736 sVariableHelpTexts()->insert( u
"qgis_locale"_s, QCoreApplication::translate(
"variable_help",
"Two letter identifier for current QGIS locale." ) );
737 sVariableHelpTexts()->insert( u
"user_account_name"_s, QCoreApplication::translate(
"variable_help",
"Current user's operating system account name." ) );
738 sVariableHelpTexts()->insert( u
"user_full_name"_s, QCoreApplication::translate(
"variable_help",
"Current user's operating system user name (if available)." ) );
741 sVariableHelpTexts()->insert( u
"project_title"_s, QCoreApplication::translate(
"variable_help",
"Title of current project." ) );
742 sVariableHelpTexts()->insert( u
"project_path"_s, QCoreApplication::translate(
"variable_help",
"Full path (including file name) of current project." ) );
743 sVariableHelpTexts()->insert( u
"project_folder"_s, QCoreApplication::translate(
"variable_help",
"Folder for current project." ) );
744 sVariableHelpTexts()->insert( u
"project_filename"_s, QCoreApplication::translate(
"variable_help",
"Filename of current project." ) );
745 sVariableHelpTexts()->insert( u
"project_basename"_s, QCoreApplication::translate(
"variable_help",
"Base name of current project's filename (without path and extension)." ) );
746 sVariableHelpTexts()->insert( u
"project_home"_s, QCoreApplication::translate(
"variable_help",
"Home path of current project." ) );
747 sVariableHelpTexts()->insert( u
"project_crs"_s, QCoreApplication::translate(
"variable_help",
"Identifier for the coordinate reference system of project (e.g., 'EPSG:4326')." ) );
748 sVariableHelpTexts()->insert( u
"project_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Coordinate reference system of project (full definition)." ) );
749 sVariableHelpTexts()->insert( u
"project_units"_s, QCoreApplication::translate(
"variable_help",
"Unit of the project's CRS." ) );
750 sVariableHelpTexts()->insert( u
"project_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the coordinate reference system of the project." ) );
751 sVariableHelpTexts()->insert( u
"project_crs_acronym"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the coordinate reference system of the project." ) );
752 sVariableHelpTexts()->insert( u
"project_crs_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the ellipsoid of the coordinate reference system of the project." ) );
753 sVariableHelpTexts()->insert( u
"project_crs_proj4"_s, QCoreApplication::translate(
"variable_help",
"Proj4 definition of the coordinate reference system of the project." ) );
754 sVariableHelpTexts()->insert( u
"project_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the coordinate reference system of the project." ) );
756 sVariableHelpTexts()->insert( u
"project_vertical_crs"_s, QCoreApplication::translate(
"variable_help",
"Identifier for the vertical coordinate reference system of the project (e.g., 'EPSG:5703')." ) );
757 sVariableHelpTexts()->insert( u
"project_vertical_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Vertical coordinate reference system of project (full definition)." ) );
758 sVariableHelpTexts()->insert( u
"project_vertical_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the vertical coordinate reference system of the project." ) );
759 sVariableHelpTexts()->insert( u
"project_vertical_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the vertical coordinate reference system of the project." ) );
761 sVariableHelpTexts()->insert( u
"project_author"_s, QCoreApplication::translate(
"variable_help",
"Project author, taken from project metadata." ) );
762 sVariableHelpTexts()->insert( u
"project_abstract"_s, QCoreApplication::translate(
"variable_help",
"Project abstract, taken from project metadata." ) );
763 sVariableHelpTexts()->insert( u
"project_creation_date"_s, QCoreApplication::translate(
"variable_help",
"Project creation date, taken from project metadata." ) );
764 sVariableHelpTexts()->insert( u
"project_identifier"_s, QCoreApplication::translate(
"variable_help",
"Project identifier, taken from project metadata." ) );
765 sVariableHelpTexts()->insert( u
"project_last_saved"_s, QCoreApplication::translate(
"variable_help",
"Date/time when project was last saved." ) );
766 sVariableHelpTexts()->insert( u
"project_keywords"_s, QCoreApplication::translate(
"variable_help",
"Project keywords, taken from project metadata." ) );
767 sVariableHelpTexts()->insert( u
"project_area_units"_s, QCoreApplication::translate(
"variable_help",
"Area unit for current project, used when calculating areas of geometries." ) );
768 sVariableHelpTexts()->insert( u
"project_distance_units"_s, QCoreApplication::translate(
"variable_help",
"Distance unit for current project, used when calculating lengths of geometries." ) );
769 sVariableHelpTexts()->insert( u
"project_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Name of ellipsoid of current project, used when calculating geodetic areas and lengths of geometries." ) );
770 sVariableHelpTexts()->insert( u
"layer_ids"_s, QCoreApplication::translate(
"variable_help",
"List of all map layer IDs from the current project." ) );
771 sVariableHelpTexts()->insert( u
"layers"_s, QCoreApplication::translate(
"variable_help",
"List of all map layers from the current project." ) );
774 sVariableHelpTexts()->insert( u
"layer_name"_s, QCoreApplication::translate(
"variable_help",
"Name of current layer." ) );
775 sVariableHelpTexts()->insert( u
"layer_id"_s, QCoreApplication::translate(
"variable_help",
"ID of current layer." ) );
776 sVariableHelpTexts()->insert( u
"layer_crs"_s, QCoreApplication::translate(
"variable_help",
"CRS Authority ID of current layer." ) );
777 sVariableHelpTexts()->insert( u
"layer"_s, QCoreApplication::translate(
"variable_help",
"The current layer." ) );
778 sVariableHelpTexts()->insert( u
"layer_crs_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Ellipsoid acronym of current layer CRS." ) );
780 sVariableHelpTexts()->insert( u
"layer_vertical_crs"_s, QCoreApplication::translate(
"variable_help",
"Identifier for the vertical coordinate reference system of the layer (e.g., 'EPSG:5703')." ) );
781 sVariableHelpTexts()->insert( u
"layer_vertical_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Vertical coordinate reference system of layer (full definition)." ) );
782 sVariableHelpTexts()->insert( u
"layer_vertical_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the vertical coordinate reference system of the layer." ) );
783 sVariableHelpTexts()->insert( u
"layer_vertical_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the vertical coordinate reference system of the layer." ) );
787 ->insert( u
"feature"_s, QCoreApplication::translate(
"variable_help",
"The current feature being evaluated. This can be used with the 'attribute' function to evaluate attribute values from the current feature." ) );
788 sVariableHelpTexts()->insert( u
"id"_s, QCoreApplication::translate(
"variable_help",
"The ID of the current feature being evaluated." ) );
789 sVariableHelpTexts()->insert( u
"geometry"_s, QCoreApplication::translate(
"variable_help",
"The geometry of the current feature being evaluated." ) );
792 sVariableHelpTexts()->insert( u
"layout_name"_s, QCoreApplication::translate(
"variable_help",
"Name of composition." ) );
793 sVariableHelpTexts()->insert( u
"layout_numpages"_s, QCoreApplication::translate(
"variable_help",
"Number of pages in composition." ) );
794 sVariableHelpTexts()->insert( u
"layout_page"_s, QCoreApplication::translate(
"variable_help",
"Current page number in composition." ) );
795 sVariableHelpTexts()->insert( u
"layout_pageheight"_s, QCoreApplication::translate(
"variable_help",
"Composition page height in mm (or specified custom units)." ) );
796 sVariableHelpTexts()->insert( u
"layout_pagewidth"_s, QCoreApplication::translate(
"variable_help",
"Composition page width in mm (or specified custom units)." ) );
797 sVariableHelpTexts()->insert( u
"layout_pageoffsets"_s, QCoreApplication::translate(
"variable_help",
"Array of Y coordinate of the top of each page." ) );
798 sVariableHelpTexts()->insert( u
"layout_dpi"_s, QCoreApplication::translate(
"variable_help",
"Composition resolution (DPI)." ) );
801 sVariableHelpTexts()->insert( u
"atlas_layerid"_s, QCoreApplication::translate(
"variable_help",
"Current atlas coverage layer ID." ) );
802 sVariableHelpTexts()->insert( u
"atlas_layername"_s, QCoreApplication::translate(
"variable_help",
"Current atlas coverage layer name." ) );
803 sVariableHelpTexts()->insert( u
"atlas_totalfeatures"_s, QCoreApplication::translate(
"variable_help",
"Total number of features in atlas." ) );
804 sVariableHelpTexts()->insert( u
"atlas_featurenumber"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature number." ) );
805 sVariableHelpTexts()->insert( u
"atlas_filename"_s, QCoreApplication::translate(
"variable_help",
"Current atlas file name." ) );
806 sVariableHelpTexts()->insert( u
"atlas_pagename"_s, QCoreApplication::translate(
"variable_help",
"Current atlas page name." ) );
807 sVariableHelpTexts()->insert( u
"atlas_feature"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature (as feature object)." ) );
808 sVariableHelpTexts()->insert( u
"atlas_featureid"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature ID." ) );
809 sVariableHelpTexts()->insert( u
"atlas_geometry"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature geometry." ) );
812 sVariableHelpTexts()->insert( u
"item_id"_s, QCoreApplication::translate(
"variable_help",
"Layout item user-assigned ID (not necessarily unique)." ) );
813 sVariableHelpTexts()->insert( u
"item_uuid"_s, QCoreApplication::translate(
"variable_help",
"layout item unique ID." ) );
814 sVariableHelpTexts()->insert( u
"item_left"_s, QCoreApplication::translate(
"variable_help",
"Left position of layout item (in mm)." ) );
815 sVariableHelpTexts()->insert( u
"item_top"_s, QCoreApplication::translate(
"variable_help",
"Top position of layout item (in mm)." ) );
816 sVariableHelpTexts()->insert( u
"item_width"_s, QCoreApplication::translate(
"variable_help",
"Width of layout item (in mm)." ) );
817 sVariableHelpTexts()->insert( u
"item_height"_s, QCoreApplication::translate(
"variable_help",
"Height of layout item (in mm)." ) );
820 sVariableHelpTexts()->insert( u
"map_id"_s, QCoreApplication::translate(
"variable_help",
"ID of current map destination. This will be 'canvas' for canvas renders, and the item ID for layout map renders." ) );
821 sVariableHelpTexts()->insert( u
"map_rotation"_s, QCoreApplication::translate(
"variable_help",
"Current rotation of map." ) );
822 sVariableHelpTexts()->insert( u
"map_scale"_s, QCoreApplication::translate(
"variable_help",
"Current scale of map." ) );
823 sVariableHelpTexts()->insert( u
"map_extent"_s, QCoreApplication::translate(
"variable_help",
"Geometry representing the current extent of the map." ) );
824 sVariableHelpTexts()->insert( u
"map_extent_center"_s, QCoreApplication::translate(
"variable_help",
"Center of map." ) );
825 sVariableHelpTexts()->insert( u
"map_extent_width"_s, QCoreApplication::translate(
"variable_help",
"Width of map." ) );
826 sVariableHelpTexts()->insert( u
"map_extent_height"_s, QCoreApplication::translate(
"variable_help",
"Height of map." ) );
827 sVariableHelpTexts()->insert( u
"map_crs"_s, QCoreApplication::translate(
"variable_help",
"Coordinate reference system of map (e.g., 'EPSG:4326')." ) );
828 sVariableHelpTexts()->insert( u
"map_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the coordinate reference system of the map." ) );
829 sVariableHelpTexts()->insert( u
"map_units"_s, QCoreApplication::translate(
"variable_help",
"Units for map measurements." ) );
830 sVariableHelpTexts()->insert( u
"map_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Coordinate reference system of the map (full definition)." ) );
831 sVariableHelpTexts()->insert( u
"map_crs_acronym"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the coordinate reference system of the map." ) );
832 sVariableHelpTexts()->insert( u
"map_crs_projection"_s, QCoreApplication::translate(
"variable_help",
"Projection method used by the coordinate reference system of the map." ) );
833 sVariableHelpTexts()->insert( u
"map_crs_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the ellipsoid of the coordinate reference system of the map." ) );
834 sVariableHelpTexts()->insert( u
"map_crs_proj4"_s, QCoreApplication::translate(
"variable_help",
"Proj4 definition of the coordinate reference system of the map." ) );
835 sVariableHelpTexts()->insert( u
"map_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the coordinate reference system of the map." ) );
836 sVariableHelpTexts()->insert( u
"map_layer_ids"_s, QCoreApplication::translate(
"variable_help",
"List of map layer IDs visible in the map." ) );
837 sVariableHelpTexts()->insert( u
"map_layers"_s, QCoreApplication::translate(
"variable_help",
"List of map layers visible in the map." ) );
839 sVariableHelpTexts()->insert( u
"map_start_time"_s, QCoreApplication::translate(
"variable_help",
"Start of the map's temporal time range (as a datetime value)" ) );
840 sVariableHelpTexts()->insert( u
"map_end_time"_s, QCoreApplication::translate(
"variable_help",
"End of the map's temporal time range (as a datetime value)" ) );
841 sVariableHelpTexts()->insert( u
"map_interval"_s, QCoreApplication::translate(
"variable_help",
"Duration of the map's temporal time range (as an interval value)" ) );
842 sVariableHelpTexts()->insert( u
"map_z_range_lower"_s, QCoreApplication::translate(
"variable_help",
"Lower elevation of the map's elevation range" ) );
843 sVariableHelpTexts()->insert( u
"map_z_range_upper"_s, QCoreApplication::translate(
"variable_help",
"Upper elevation of the map's elevation range" ) );
845 sVariableHelpTexts()->insert( u
"frame_rate"_s, QCoreApplication::translate(
"variable_help",
"Number of frames per second during animation playback" ) );
846 sVariableHelpTexts()->insert( u
"frame_number"_s, QCoreApplication::translate(
"variable_help",
"Current frame number during animation playback" ) );
847 sVariableHelpTexts()->insert( u
"frame_duration"_s, QCoreApplication::translate(
"variable_help",
"Temporal duration of each animation frame (as an interval value)" ) );
848 sVariableHelpTexts()->insert( u
"frame_timestep"_s, QCoreApplication::translate(
"variable_help",
"Frame time step during animation playback" ) );
849 sVariableHelpTexts()->insert( u
"frame_timestep_unit"_s, QCoreApplication::translate(
"variable_help",
"Unit value of the frame time step during animation playback" ) );
850 sVariableHelpTexts()->insert( u
"frame_timestep_units"_s, QCoreApplication::translate(
"variable_help",
"String representation of the frame time step unit during animation playback" ) );
851 sVariableHelpTexts()->insert( u
"animation_start_time"_s, QCoreApplication::translate(
"variable_help",
"Start of the animation's overall temporal time range (as a datetime value)" ) );
852 sVariableHelpTexts()->insert( u
"animation_end_time"_s, QCoreApplication::translate(
"variable_help",
"End of the animation's overall temporal time range (as a datetime value)" ) );
853 sVariableHelpTexts()->insert( u
"animation_interval"_s, QCoreApplication::translate(
"variable_help",
"Duration of the animation's overall temporal time range (as an interval value)" ) );
857 ->insert( u
"zoom_level"_s, QCoreApplication::translate(
"variable_help",
"Vector tile zoom level of the map that is being rendered (derived from the current map scale). Normally in interval [0, 20]." ) );
859 ->insert( u
"vector_tile_zoom"_s, QCoreApplication::translate(
"variable_help",
"Exact vector tile zoom level of the map that is being rendered (derived from the current map scale). Normally in interval [0, 20]. Unlike @zoom_level, this variable is a floating point value which can be used to interpolate values between two integer zoom levels." ) );
861 sVariableHelpTexts()->insert(
863 QCoreApplication::translate(
"variable_help",
"Stores the number of the current row." )
865 + QCoreApplication::translate(
"variable_help",
"When used for calculations within the attribute table the row number will respect the original order of features from the underlying data source." )
867 + QCoreApplication::translate(
"variable_help",
"When used from the field calculator the row numbering starts at 1, otherwise (e.g. from Processing tools) the row numbering starts from 0." )
869 sVariableHelpTexts()->insert( u
"grid_number"_s, QCoreApplication::translate(
"variable_help",
"Current grid annotation value." ) );
870 sVariableHelpTexts()->insert( u
"grid_axis"_s, QCoreApplication::translate(
"variable_help",
"Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );
871 sVariableHelpTexts()->insert( u
"grid_count"_s, QCoreApplication::translate(
"variable_help",
"Total number of visible grid lines for the current grid axis." ) );
873 ->insert( u
"grid_index"_s, QCoreApplication::translate(
"variable_help",
"The index of the grid line currently being drawn (starting at 1 for the first grid line). The index is specific to the current grid axis." ) );
874 sVariableHelpTexts()->insert( u
"column_number"_s, QCoreApplication::translate(
"variable_help",
"Stores the number of the current column." ) );
877 sVariableHelpTexts()->insert( u
"canvas_cursor_point"_s, QCoreApplication::translate(
"variable_help",
"Last cursor position on the canvas in the project's geographical coordinates." ) );
879 ->insert( u
"layer_cursor_point"_s, QCoreApplication::translate(
"variable_help",
"Last cursor position on the canvas in the current layers's geographical coordinates. QGIS Server: When used in a maptip expression for a raster layer, this variable holds the GetFeatureInfo position." ) );
882 sVariableHelpTexts()->insert( u
"legend_title"_s, QCoreApplication::translate(
"variable_help",
"Title of the legend." ) );
883 sVariableHelpTexts()->insert( u
"legend_column_count"_s, QCoreApplication::translate(
"variable_help",
"Number of column in the legend." ) );
884 sVariableHelpTexts()->insert( u
"legend_split_layers"_s, QCoreApplication::translate(
"variable_help",
"Boolean indicating if layers can be split in the legend." ) );
885 sVariableHelpTexts()->insert( u
"legend_wrap_string"_s, QCoreApplication::translate(
"variable_help",
"Characters used to wrap the legend text." ) );
886 sVariableHelpTexts()->insert( u
"legend_filter_by_map"_s, QCoreApplication::translate(
"variable_help",
"Boolean indicating if the content of the legend is filtered by the map." ) );
887 sVariableHelpTexts()->insert( u
"legend_filter_out_atlas"_s, QCoreApplication::translate(
"variable_help",
"Boolean indicating if the Atlas is filtered out of the legend." ) );
890 sVariableHelpTexts()->insert( u
"scale_value"_s, QCoreApplication::translate(
"variable_help",
"Current scale bar distance value." ) );
893 sVariableHelpTexts()->insert(
894 u
"snapping_results"_s,
895 QCoreApplication::translate(
897 "<p>An array with an item for each snapped point.</p>"
898 "<p>Each item is a map with the following keys:</p>"
900 "<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>"
901 "<dt>layer</dt><dd>The layer on which the snapped feature is</dd>"
902 "<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>"
903 "<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>"
904 "<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>"
911 sVariableHelpTexts()->insert( u
"geometry_part_count"_s, QCoreApplication::translate(
"variable_help",
"Number of parts in rendered feature's geometry." ) );
912 sVariableHelpTexts()->insert( u
"geometry_part_num"_s, QCoreApplication::translate(
"variable_help",
"Current geometry part number for feature being rendered." ) );
914 ->insert( u
"geometry_ring_num"_s, QCoreApplication::translate(
"variable_help",
"Current geometry ring number for feature being rendered (for polygon features only). The exterior ring has a value of 0." ) );
916 ->insert( u
"geometry_point_count"_s, 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." ) );
918 ->insert( u
"geometry_point_num"_s, 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." ) );
920 sVariableHelpTexts()->insert( u
"symbol_color"_s, QCoreApplication::translate(
"symbol_color",
"Color of symbol used to render the feature." ) );
921 sVariableHelpTexts()->insert( u
"symbol_angle"_s, QCoreApplication::translate(
"symbol_angle",
"Angle of symbol used to render the feature (valid for marker symbols only)." ) );
922 sVariableHelpTexts()->insert( u
"symbol_layer_count"_s, QCoreApplication::translate(
"symbol_layer_count",
"Total number of symbol layers in the symbol." ) );
923 sVariableHelpTexts()->insert( u
"symbol_layer_index"_s, QCoreApplication::translate(
"symbol_layer_index",
"Current symbol layer index." ) );
924 sVariableHelpTexts()->insert( u
"symbol_marker_row"_s, QCoreApplication::translate(
"symbol_marker_row",
"Row number for marker (valid for point pattern fills only)." ) );
925 sVariableHelpTexts()->insert( u
"symbol_marker_column"_s, QCoreApplication::translate(
"symbol_marker_column",
"Column number for marker (valid for point pattern fills only)." ) );
926 sVariableHelpTexts()->insert( u
"symbol_frame"_s, QCoreApplication::translate(
"symbol_frame",
"Frame number (for animated symbols only)." ) );
928 sVariableHelpTexts()->insert( u
"symbol_label"_s, QCoreApplication::translate(
"symbol_label",
"Label for the symbol (either a user defined label or the default autogenerated label)." ) );
929 sVariableHelpTexts()->insert( u
"symbol_id"_s, QCoreApplication::translate(
"symbol_id",
"Internal ID of the symbol." ) );
930 sVariableHelpTexts()->insert( u
"symbol_count"_s, QCoreApplication::translate(
"symbol_count",
"Total number of features represented by the symbol." ) );
933 sVariableHelpTexts()->insert( u
"cluster_color"_s, QCoreApplication::translate(
"cluster_color",
"Color of symbols within a cluster, or NULL if symbols have mixed colors." ) );
934 sVariableHelpTexts()->insert( u
"cluster_size"_s, QCoreApplication::translate(
"cluster_size",
"Number of symbols contained within a cluster." ) );
937 sVariableHelpTexts()->insert( u
"algorithm_id"_s, QCoreApplication::translate(
"algorithm_id",
"Unique ID for algorithm." ) );
938 sVariableHelpTexts()->insert( u
"model_path"_s, QCoreApplication::translate(
"variable_help",
"Full path (including file name) of current model (or project path if model is embedded in a project)." ) );
939 sVariableHelpTexts()->insert( u
"model_folder"_s, QCoreApplication::translate(
"variable_help",
"Folder containing current model (or project folder if model is embedded in a project)." ) );
940 sVariableHelpTexts()->insert( u
"model_name"_s, QCoreApplication::translate(
"variable_help",
"Name of current model." ) );
941 sVariableHelpTexts()->insert( u
"model_group"_s, QCoreApplication::translate(
"variable_help",
"Group for current model." ) );
942 sVariableHelpTexts()->insert( u
"fullextent_minx"_s, QCoreApplication::translate(
"fullextent_minx",
"Minimum x-value from full canvas extent (including all layers)." ) );
943 sVariableHelpTexts()->insert( u
"fullextent_miny"_s, QCoreApplication::translate(
"fullextent_miny",
"Minimum y-value from full canvas extent (including all layers)." ) );
944 sVariableHelpTexts()->insert( u
"fullextent_maxx"_s, QCoreApplication::translate(
"fullextent_maxx",
"Maximum x-value from full canvas extent (including all layers)." ) );
945 sVariableHelpTexts()->insert( u
"fullextent_maxy"_s, QCoreApplication::translate(
"fullextent_maxy",
"Maximum y-value from full canvas extent (including all layers)." ) );
949 ->insert( u
"notification_message"_s, QCoreApplication::translate(
"notification_message",
"Content of the notification message sent by the provider (available only for actions triggered by provider notifications)." ) );
953 ->insert( u
"current_geometry"_s, 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." ) );
955 ->insert( u
"current_feature"_s, 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." ) );
958 sVariableHelpTexts()->insert(
959 u
"current_parent_geometry"_s,
960 QCoreApplication::translate(
961 "current_parent_geometry",
962 "Only usable in an embedded form context, "
963 "represents the geometry of the feature currently being edited in the parent form.\n"
964 "Can be used in a form/row context to filter the related features using a value "
965 "from the feature currently edited in the parent form, to make sure that the filter "
966 "still works with standalone forms it is recommended to wrap this variable in a "
970 sVariableHelpTexts()->insert(
971 u
"current_parent_feature"_s,
972 QCoreApplication::translate(
973 "current_parent_feature",
974 "Only usable in an embedded form context, "
975 "represents the feature currently being edited in the parent form.\n"
976 "Can be used in a form/row context to filter the related features using a value "
977 "from the feature currently edited in the parent form, to make sure that the filter "
978 "still works with standalone forms it is recommended to wrap this variable in a "
985 ->insert( u
"form_mode"_s, QCoreApplication::translate(
"form_mode",
"What the form is used for, like AddFeatureMode, SingleEditMode, MultiEditMode, SearchMode, AggregateSearchMode or IdentifyMode as string." ) );
988 sVariableHelpTexts()->insert( u
"plot_axis"_s, QCoreApplication::translate(
"plot_axis",
"The associated plot axis, e.g. 'x' or 'y'." ) );
989 sVariableHelpTexts()->insert( u
"plot_axis_value"_s, QCoreApplication::translate(
"plot_axis_value",
"The current value for the plot axis grid line." ) );
990 sVariableHelpTexts()->insert( u
"chart_category"_s, QCoreApplication::translate(
"chart_category",
"The chart item category, e.g. 'fruit' or 'june'." ) );
991 sVariableHelpTexts()->insert( u
"chart_value"_s, QCoreApplication::translate(
"chart_value",
"The chart item value." ) );
992 sVariableHelpTexts()->insert( u
"chart_series_name"_s, QCoreApplication::translate(
"chart_series_name",
"The chart item's series name, e.g. 'Series 1'." ) );
997 QgsExpression::initVariableHelp();
998 if ( sVariableHelpTexts()->contains( name ) )
1002 sVariableHelpTexts()->insert( name, description );
1008 QgsExpression::initVariableHelp();
1009 return sVariableHelpTexts()->value( variableName, QString() );
1014 QString text = !description.isEmpty() ? u
"<p>%1</p>"_s.arg( description ) : QString();
1017 QString valueString;
1018 if ( !value.isValid() )
1020 valueString = QCoreApplication::translate(
"variable_help",
"not set" );
1026 text.append( QCoreApplication::translate(
"variable_help",
"<p>Current value: %1</p>" ).arg( valueString ) );
1033 if ( sGroups()->isEmpty() )
1035 sGroups()->insert( u
"Aggregates"_s, tr(
"Aggregates" ) );
1036 sGroups()->insert( u
"Arrays"_s, tr(
"Arrays" ) );
1037 sGroups()->insert( u
"Color"_s, tr(
"Color" ) );
1038 sGroups()->insert( u
"Conditionals"_s, tr(
"Conditionals" ) );
1039 sGroups()->insert( u
"Conversions"_s, tr(
"Conversions" ) );
1040 sGroups()->insert( u
"Date and Time"_s, tr(
"Date and Time" ) );
1041 sGroups()->insert( u
"Fields and Values"_s, tr(
"Fields and Values" ) );
1042 sGroups()->insert( u
"Files and Paths"_s, tr(
"Files and Paths" ) );
1043 sGroups()->insert( u
"Fuzzy Matching"_s, tr(
"Fuzzy Matching" ) );
1044 sGroups()->insert( u
"General"_s, tr(
"General" ) );
1045 sGroups()->insert( u
"GeometryGroup"_s, tr(
"Geometry" ) );
1046 sGroups()->insert( u
"Map Layers"_s, tr(
"Map Layers" ) );
1047 sGroups()->insert( u
"Maps"_s, tr(
"Maps" ) );
1048 sGroups()->insert( u
"Math"_s, tr(
"Math" ) );
1049 sGroups()->insert( u
"Operators"_s, tr(
"Operators" ) );
1050 sGroups()->insert( u
"Rasters"_s, tr(
"Rasters" ) );
1051 sGroups()->insert( u
"Record and Attributes"_s, tr(
"Record and Attributes" ) );
1052 sGroups()->insert( u
"String"_s, tr(
"String" ) );
1053 sGroups()->insert( u
"MagneticModels"_s, tr(
"Magnetic Models" ) );
1054 sGroups()->insert( u
"Variables"_s, tr(
"Variables" ) );
1055 sGroups()->insert( u
"Recent (%1)"_s, tr(
"Recent (%1)" ) );
1056 sGroups()->insert( u
"UserGroup"_s, tr(
"User expressions" ) );
1062 return sGroups()->value( name, name );
1067 const QString startToken = htmlOutput ? u
"<i><"_s : u
"<"_s;
1068 const QString endToken = htmlOutput ? u
"></i>"_s : u
">"_s;
1070 QgsGeometry geom = QgsExpressionUtils::getGeometry( value,
nullptr );
1075 return startToken + tr(
"empty geometry" ) + endToken;
1081 return startToken + tr(
"map layer" ) + endToken;
1083 else if ( !value.isValid() )
1085 return htmlOutput ? tr(
"<i>NULL</i>" ) : QString();
1087 else if ( value.userType() == qMetaTypeId< QgsFeature>() )
1091 return startToken + tr(
"feature: %1" ).arg( feat.
id() ) + endToken;
1093 else if ( value.userType() == qMetaTypeId< QgsCoordinateReferenceSystem>() )
1098 else if ( value.userType() == qMetaTypeId< QTimeZone>() )
1100 const QTimeZone tz = value.value<QTimeZone>();
1101#if QT_FEATURE_timezone > 0
1102 return startToken + tr(
"time zone: %1" ).arg( tz.isValid() ? tz.displayName( QTimeZone::GenericTime, QTimeZone::ShortName ) : tr(
"invalid" ) ) + endToken;
1104 QgsDebugError( u
"Qt is built without Qt timezone support, timezone preview not available"_s );
1107 else if ( value.userType() == qMetaTypeId< QgsInterval>() )
1110 if ( interval.
days() > 1 )
1112 return startToken + tr(
"interval: %1 days" ).arg( interval.
days() ) + endToken;
1114 else if ( interval.
hours() > 1 )
1116 return startToken + tr(
"interval: %1 hours" ).arg( interval.
hours() ) + endToken;
1118 else if ( interval.
minutes() > 1 )
1120 return startToken + tr(
"interval: %1 minutes" ).arg( interval.
minutes() ) + endToken;
1124 return startToken + tr(
"interval: %1 seconds" ).arg( interval.
seconds() ) + endToken;
1127 else if ( value.userType() == qMetaTypeId< QgsGradientColorRamp>() )
1129 return startToken + tr(
"gradient ramp" ) + endToken;
1131 else if ( value.userType() == QMetaType::Type::QDate )
1133 const QDate dt = value.toDate();
1134 return startToken + tr(
"date: %1" ).arg( dt.toString( u
"yyyy-MM-dd"_s ) ) + endToken;
1136 else if ( value.userType() == QMetaType::Type::QTime )
1138 const QTime tm = value.toTime();
1139 return startToken + tr(
"time: %1" ).arg( tm.toString( u
"hh:mm:ss"_s ) ) + endToken;
1141 else if ( value.userType() == QMetaType::Type::QDateTime )
1143 const QDateTime dt = value.toDateTime();
1144 return startToken + tr(
"datetime: %1 (%2)" ).arg( dt.toString( u
"yyyy-MM-dd hh:mm:ss"_s ), dt.timeZoneAbbreviation() ) + endToken;
1146 else if ( value.userType() == QMetaType::Type::QString )
1148 const QString previewString = value.toString();
1149 if ( previewString.length() > maximumPreviewLength + 3 )
1151 return tr(
"'%1…'" ).arg( previewString.left( maximumPreviewLength ) );
1155 return '\'' + previewString +
'\'';
1158 else if ( value.userType() == QMetaType::Type::QVariantMap )
1160 QString mapStr = u
"{"_s;
1161 const QVariantMap map = value.toMap();
1163 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1165 mapStr.append( separator );
1166 if ( separator.isEmpty() )
1169 mapStr.append( u
" '%1': %2"_s.arg( it.key(),
formatPreviewString( it.value(), htmlOutput ) ) );
1170 if ( mapStr.length() > maximumPreviewLength - 3 )
1172 mapStr = tr(
"%1…" ).arg( mapStr.left( maximumPreviewLength - 2 ) );
1181 else if ( value.userType() == QMetaType::Type::QVariantList || value.userType() == QMetaType::Type::QStringList )
1183 QString listStr = u
"["_s;
1184 const QVariantList list = value.toList();
1186 for (
const QVariant &arrayValue : list )
1188 listStr.append( separator );
1189 if ( separator.isEmpty() )
1192 listStr.append(
" " );
1194 if ( listStr.length() > maximumPreviewLength - 3 )
1196 listStr = QString( tr(
"%1…" ) ).arg( listStr.left( maximumPreviewLength - 2 ) );
1200 if ( !list.empty() )
1205 else if ( value.type() == QVariant::Color )
1207 const QColor color = value.value<QColor>();
1209 if ( !color.isValid() )
1211 return tr(
"<i>Invalid</i>" );
1214 switch ( color.spec() )
1216 case QColor::Spec::Cmyk:
1217 return u
"CMYKA: %1,%2,%3,%4,%5"_s.arg( color.cyanF(), 0,
'f', 2 ).arg( color.magentaF(), 0,
'f', 2 ).arg( color.yellowF(), 0,
'f', 2 ).arg( color.blackF(), 0,
'f', 2 ).arg( color.alphaF(), 0,
'f', 2 );
1219 case QColor::Spec::Hsv:
1220 return u
"HSVA: %1,%2,%3,%4"_s.arg( color.hsvHueF(), 0,
'f', 2 ).arg( color.hsvSaturationF(), 0,
'f', 2 ).arg( color.valueF(), 0,
'f', 2 ).arg( color.alphaF(), 0,
'f', 2 );
1222 case QColor::Spec::Hsl:
1223 return u
"HSLA: %1,%2,%3,%4"_s.arg( color.hslHueF(), 0,
'f', 2 ).arg( color.hslSaturationF(), 0,
'f', 2 ).arg( color.lightnessF(), 0,
'f', 2 ).arg( color.alphaF(), 0,
'f', 2 );
1225 case QColor::Spec::Rgb:
1226 case QColor::Spec::ExtendedRgb:
1227 return u
"RGBA: %1,%2,%3,%4"_s.arg( color.redF(), 0,
'f', 2 ).arg( color.greenF(), 0,
'f', 2 ).arg( color.blueF(), 0,
'f', 2 ).arg( color.alphaF(), 0,
'f', 2 );
1229 case QColor::Spec::Invalid:
1230 return tr(
"<i>Invalid</i>" );
1232 QgsDebugError( u
"Unknown color format: %1"_s.arg( color.spec() ) );
1233 return tr(
"<i>Unknown color format: %1</i>" ).arg( color.spec() );
1235 else if ( value.userType() == QMetaType::Type::Int
1236 || value.userType() == QMetaType::Type::UInt
1237 || value.userType() == QMetaType::Type::LongLong
1238 || value.userType() == QMetaType::Type::ULongLong
1239 || value.userType() == QMetaType::Type::Double
1242 value.userType() ==
static_cast<QMetaType::Type
>( QMetaType::Float ) )
1244 return QgsExpressionUtils::toLocalizedString( value );
1248 QString str { value.toString() };
1249 if ( str.length() > maximumPreviewLength - 3 )
1251 str = tr(
"%1…" ).arg( str.left( maximumPreviewLength - 2 ) );
1263 else if ( fieldType == QMetaType::Type::UnknownType )
1289 if ( columnRef && literal )
1291 field = columnRef->
name();
1292 value = literal->
value();
1302 if ( expressions.empty() )
1308 for (
const QString &
expression : expressions )
1319 else if ( field != inField )
1335 if ( inOp->isNotIn() )
1344 inField = columnRef->
name();
1347 else if ( columnRef->
name() != inField )
1354 const QList<QgsExpressionNode *>
nodes = nodeList->list();
1370 QStringList orParts;
1375 orParts.append( collectOrs( leftOrOp->opLeft(), leftOrOp->opRight() ) );
1379 orParts.append( leftOrOp->dump() );
1384 orParts.append( leftInOp->dump() );
1395 orParts.append( collectOrs( rightOrOp->opLeft(), rightOrOp->opRight() ) );
1399 orParts.append( rightOrOp->dump() );
1404 orParts.append( rightInOp->dump() );
1417 const QStringList orParts = collectOrs( orOp->opLeft(), orOp->opRight() );
1418 if ( orParts.isEmpty() )
1424 QString orPartsResult;
1441 const QString innerInfield { inOpInner->node()->referencedColumns().values().first() };
1445 inField = innerInfield;
1449 if ( innerInfield != inField )
1455 const auto constInnerValuesList { inOpInner->list()->list() };
1456 for (
const auto &innerInValueNode : std::as_const( constInnerValuesList ) )
1458 values.append( innerInValueNode->dump() );
1484 result = u
"%1 IN (%2)"_s.arg(
quotedColumnRef( inField ), values.join(
',' ) );
1490 return d->mRootNode.get();
1505 if ( attrIndex >= 0 )
1512 const QString fieldName = qgis::down_cast<const QgsExpressionNodeColumnRef *>( candidate.
rootNode() )->name();
1524 if ( !
expression.contains(
'\"' ) && fieldIndex != -1 )
1537 if ( !d->mRootNode )
1538 return QList<const QgsExpressionNode *>();
1540 return d->mRootNode->nodes();
DistanceUnit
Units of distance.
@ Unknown
Unknown distance unit.
@ Unknown
Unknown areal unit.
static QString geoNone()
Constant that holds the string representation for "No ellipse/No CRS".
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
Represents a coordinate reference system (CRS).
QString userFriendlyIdentifier(Qgis::CrsIdentifierType type=Qgis::CrsIdentifierType::MediumString) const
Returns a user friendly identifier for the CRS.
Contains information about the context in which a coordinate transform is executed.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
An abstract base class for defining QgsExpression functions.
A binary expression operator, which operates on two values.
An expression node which takes its value from a feature's field.
QString name() const
The name of the column.
An expression node for value IN or NOT IN clauses.
An expression node for literal values.
QVariant value() const
The value of the literal.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QgsExpression & operator=(const QgsExpression &other)
Create a copy of this expression.
QString expression() const
Returns the original, unmodified expression string.
Qgis::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static double evaluateToDouble(const QString &text, double fallbackValue)
Attempts to evaluate a text string as an expression to a resultant double value.
static QString quoteFieldExpression(const QString &expression, const QgsVectorLayer *layer)
Validate if the expression is a field in the layer and ensure it is quoted.
static int functionCount()
Returns the number of functions defined in the parser.
QList< const QgsExpressionNode * > nodes() const
Returns a list of all nodes which are used in this expression.
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes).
QSet< QString > referencedVariables() const
Returns a list of all variables which are used in this expression.
static bool isFunctionName(const QString &name)
tells whether the identifier is a name of existing function
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
static QString variableHelpText(const QString &variableName)
Returns the help text for a specified variable.
QList< QgsExpression::ParserError > parserErrors() const
Returns parser error details including location of error.
QString evalErrorString() const
Returns evaluation error.
bool operator==(const QgsExpression &other) const
Compares two expressions.
QString parserErrorString() const
Returns parser error.
static QString formatPreviewString(const QVariant &value, bool htmlOutput=true, int maximumPreviewLength=60)
Formats an expression result for friendly display to the user.
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...
static QStringList tags(const QString &name)
Returns a string list of search tags for a specified function.
bool isField() const
Checks whether an expression consists only of a single field reference.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
QgsExpression()
Create an empty expression.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
void setDistanceUnits(Qgis::DistanceUnit unit)
Sets the desired distance units for calculations involving geomCalculator(), e.g.,...
void setAreaUnits(Qgis::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
static bool isFieldEqualityExpression(const QString &expression, QString &field, QVariant &value)
Returns true if the given expression is a simple "field=value" type expression.
Qgis::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
QSet< QString > referencedFunctions() const
Returns a list of the names of all functions which are used in this expression.
static QString group(const QString &group)
Returns the translated name for a function group.
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions).
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
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 hasEvalError() const
Returns true if an error occurred when evaluating last input.
static QString formatVariableHelp(const QString &description, bool showValue=true, const QVariant &value=QVariant())
Returns formatted help text for a variable.
QgsExpression(const QString &expr)
Creates a new expression based on the provided string.
static int expressionToLayerFieldIndex(const QString &expression, const QgsVectorLayer *layer)
Attempts to resolve an expression to a field index from the given layer.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
static bool attemptReduceToInClause(const QStringList &expressions, QString &result)
Attempts to reduce a list of expressions to a single "field IN (val1, val2, ... )" type expression.
bool isValid() const
Checks if this expression is valid.
static bool addVariableHelpText(const QString name, const QString &description)
Adds a help string for a custom variable.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
static bool checkExpression(const QString &text, const QgsExpressionContext *context, QString &errorMessage)
Tests whether a string is a valid expression.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Container of fields for a vector layer.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
A representation of the interval between two datetime values.
double days() const
Returns the interval duration in days.
double seconds() const
Returns the interval duration in seconds.
double hours() const
Returns the interval duration in hours.
double minutes() const
Returns the interval duration in minutes.
static QgsProject * instance()
Returns the QgsProject singleton instance.
static Q_INVOKABLE Qgis::DistanceUnit stringToDistanceUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to a distance unit.
static Q_INVOKABLE Qgis::AreaUnit stringToAreaUnit(const QString &string, bool *ok=nullptr)
Converts a translated string to an areal unit.
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based dataset.
static Q_INVOKABLE QString displayString(Qgis::WkbType type)
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
QMap< QString, QString > QgsStringMap
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
QgsExpressionNode * parseExpression(const QString &str, QString &parserErrorMsg, QList< QgsExpression::ParserError > &parserErrors)
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.