34#include <QRegularExpression>
37using namespace Qt::StringLiterals;
45HelpTextHash QgsExpression::sFunctionHelpTexts;
46QMutex QgsExpression::sFunctionWriteMutex;
47#if defined( __clang__ )
50std::atomic<QgsExpression::FunctionListSnapshot> QgsExpression::sFunctions;
53QStringList QgsExpression::sBuiltinFunctionNames;
56HelpTextHash &QgsExpression::functionHelpTexts()
58 return sFunctionHelpTexts;
74 d->mEvalErrorString = QString();
76 d->mIsPrepared =
false;
81 if ( !d->mExp.isNull() )
89 return u
"\"%1\""_s.arg( name.replace(
'\"',
"\"\""_L1 ) );
94 text.replace(
'\'',
"''"_L1 );
95 text.replace(
'\\',
"\\\\"_L1 );
96 text.replace(
'\n',
"\\n"_L1 );
97 text.replace(
'\t',
"\\t"_L1 );
98 return u
"'%1'"_s.arg( text );
103 return quotedValue( value,
static_cast<QMetaType::Type
>( value.userType() ) );
113 case QMetaType::Type::Int:
114 case QMetaType::Type::LongLong:
115 case QMetaType::Type::Double:
116 return value.toString();
118 case QMetaType::Type::Bool:
119 return value.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
121 case QMetaType::Type::QVariantList:
122 case QMetaType::Type::QStringList:
124 QStringList quotedValues;
125 const QVariantList values = value.toList();
126 quotedValues.reserve( values.count() );
127 for (
const QVariant &v : values )
131 return u
"array( %1 )"_s.arg( quotedValues.join(
", "_L1 ) );
135 case QMetaType::Type::QString:
148 const int fnIndex = functions->functionIndex( name );
149 return fnIndex != -1;
155 return functions->functionIndex( name );
160 return mFunctionIndexMap.value( name.toLower(), -1 );
166 mFunctionIndexMap.clear();
169 mFunctionIndexMap.insert( function->name().toLower(), i );
170 const QStringList aliases = function->aliases();
171 for (
const QString &alias : aliases )
173 mFunctionIndexMap.insert( alias.toLower(), i );
181 return ( *
this )[index];
187 return functions->size();
191 : d( new QgsExpressionPrivate )
193 d->mRootNode.reset(
::parseExpression( expr, d->mParserErrorString, d->mParserErrors ) );
195 Q_ASSERT( !d->mParserErrorString.isNull() || d->mRootNode );
206 if (
this != &other )
208 if ( !d->ref.deref() )
219QgsExpression::operator QString()
const
225 : d( new QgsExpressionPrivate )
231 if ( !d->ref.deref() )
237 return ( d == other.d || d->mExp == other.d->mExp );
242 return d->mRootNode.get();
247 return d->mParserErrors.count() > 0;
252 return d->mParserErrorString.replace(
"syntax error, unexpected end of file", tr(
"Incomplete expression. You might not have finished the full expression." ) );
257 return d->mParserErrors;
263 return QSet<QString>();
265 return d->mRootNode->referencedColumns();
271 return QSet<QString>();
273 return d->mRootNode->referencedVariables();
279 return QSet<QString>();
281 return d->mRootNode->referencedFunctions();
289 const QSet<QString> referencedFields = d->mRootNode->referencedColumns();
290 QSet<int> referencedIndexes;
292 for (
const QString &fieldName : referencedFields )
297 referencedIndexes = QSet<int>( attributesList.begin(), attributesList.end() );
303 referencedIndexes << idx;
307 return referencedIndexes;
314 return d->mRootNode->needsGeometry();
320 if ( context && !d->mCalc )
324 d->mDaEllipsoid = context->
variable( u
"project_ellipsoid"_s ).toString();
332 QString distanceUnitsStr = context->
variable( u
"project_distance_units"_s ).toString();
333 if ( !distanceUnitsStr.isEmpty() )
340 QString areaUnitsStr = context->
variable( u
"project_area_units"_s ).toString();
341 if ( !areaUnitsStr.isEmpty() )
346void QgsExpression::detach()
352 ( void ) d->ref.deref();
354 d =
new QgsExpressionPrivate( *d );
358void QgsExpression::initFunctionHelp()
360 static std::once_flag initialized;
361 std::call_once( initialized, buildFunctionHelp );
368 d->mCalc = std::make_shared<QgsDistanceArea>( *calc );
376 d->mEvalErrorString = QString();
382 d->mRootNode.reset(
::parseExpression( d->mExp, d->mParserErrorString, d->mParserErrors ) );
387 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
391 initGeomCalculator( context );
392 d->mIsPrepared =
true;
393 return d->mRootNode->prepare(
this, context );
398 d->mEvalErrorString = QString();
401 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
410 d->mEvalErrorString = QString();
413 d->mEvalErrorString = tr(
"No root node! Parsing failed?" );
417 if ( !d->mIsPrepared )
421 return d->mRootNode->eval(
this, context );
426 return !d->mEvalErrorString.isNull();
431 return d->mEvalErrorString;
436 d->mEvalErrorString = str;
444 return d->mRootNode->dump();
449 if ( !d->mCalc && d->mDaCrs && d->mDaCrs->isValid() && d->mDaTransformContext )
452 d->mCalc = std::make_shared<QgsDistanceArea>();
453 d->mCalc->setEllipsoid( d->mDaEllipsoid.isEmpty() ?
Qgis::geoNone() : d->mDaEllipsoid );
454 d->mCalc->setSourceCrs( *d->mDaCrs.get(), *d->mDaTransformContext.get() );
457 return d->mCalc.get();
462 return d->mDistanceUnit;
467 d->mDistanceUnit = unit;
485 while ( index < action.size() )
487 const thread_local QRegularExpression sRegEx { u
"\\[%(.*?)%\\]"_s, QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption };
489 const QRegularExpressionMatch match = sRegEx.match( action, index );
490 if ( !match.hasMatch() )
493 const int pos = action.indexOf( sRegEx, index );
494 const int start = index;
495 index = pos + match.capturedLength( 0 );
496 const QString toReplace = match.captured( 1 ).trimmed();
503 expr_action += QStringView { action }.mid( start, index - start );
513 QVariant result = exp.
evaluate( context );
518 expr_action += QStringView { action }.mid( start, index - start );
522 QString resultString;
524 resultString = result.toString();
528 expr_action += action.mid( start, pos - start ) + resultString;
531 expr_action += QStringView { action }.mid( index ).toString();
537 QSet<QString> variables;
539 while ( index < text.size() )
541 const thread_local QRegularExpression rx(
"\\[%([^\\]]+)%\\]" );
542 const QRegularExpressionMatch match = rx.match( text );
543 if ( !match.hasMatch() )
546 index = match.capturedStart() + match.capturedLength();
547 QString to_replace = match.captured( 1 ).trimmed();
569 double convertedValue = QLocale().toDouble( text, &ok );
572 return convertedValue;
578 QVariant result = expr.
evaluate( context );
579 convertedValue = result.toDouble( &ok );
582 return fallbackValue;
584 return convertedValue;
590 QList<QgsExpressionFunction *> res;
596 res.append( it.get() );
603 QgsExpression::initFunctionHelp();
605 if ( !sFunctionHelpTexts.contains( name ) )
606 return tr(
"function help for %1 missing" ).arg( name );
608 const Help &f = sFunctionHelpTexts[name];
611 if ( f.mType == tr(
"group" ) )
613 name =
group( name );
614 name = name.toLower();
617 name = name.toHtmlEscaped();
619 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 ) );
621 for (
const HelpVariant &v : std::as_const( f.mVariants ) )
623 if ( f.mVariants.size() > 1 )
625 helpContents += u
"<h3>%1</h3>\n<div class=\"description\">%2</p></div>"_s.arg( v.mName, v.mDescription );
628 if ( f.mType != tr(
"group" ) && f.mType != tr(
"expression" ) )
629 helpContents += u
"<h4>%1</h4>\n<div class=\"syntax\">\n"_s.arg( tr(
"Syntax" ) );
631 if ( f.mType == tr(
"operator" ) )
633 if ( v.mArguments.size() == 1 )
635 helpContents += u
"<code><span class=\"functionname\">%1</span> <span class=\"argument\">%2</span></code>"_s.arg( name, v.mArguments[0].mArg );
637 else if ( v.mArguments.size() == 2 )
639 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 );
642 else if ( f.mType != tr(
"group" ) && f.mType != tr(
"expression" ) )
644 helpContents += u
"<code><span class=\"functionname\">%1</span>"_s.arg( name );
646 bool hasOptionalArgs =
false;
648 if ( f.mType == tr(
"function" ) && ( f.mName[0] !=
'$' || !v.mArguments.isEmpty() || v.mVariableLenArguments ) )
653 for (
const HelpArg &a : std::as_const( v.mArguments ) )
659 hasOptionalArgs =
true;
660 helpContents +=
'['_L1;
663 helpContents += delim;
664 helpContents += u
"<span class=\"argument\">%2%3</span>"_s.arg( a.mArg, a.mDefaultVal.isEmpty() ? QString() :
":=" + a.mDefaultVal );
667 helpContents +=
']'_L1;
672 if ( v.mVariableLenArguments )
674 helpContents += QChar( 0x2026 );
680 helpContents +=
"</code>"_L1;
682 if ( hasOptionalArgs )
684 helpContents +=
"<br/><br/>"_L1 + tr(
"[ ] marks optional components" );
688 if ( !v.mArguments.isEmpty() )
690 helpContents += u
"<h4>%1</h4>\n<div class=\"arguments\">\n<table>"_s.arg( tr(
"Arguments" ) );
692 for (
const HelpArg &a : std::as_const( v.mArguments ) )
697 helpContents += u
"<tr><td class=\"argument\">%1</td><td>%2</td></tr>"_s.arg( a.mArg, a.mDescription );
700 helpContents +=
"</table>\n</div>\n"_L1;
703 if ( !v.mExamples.isEmpty() )
705 helpContents += u
"<h4>%1</h4>\n<div class=\"examples\">\n<ul>\n"_s.arg( tr(
"Examples" ) );
707 for (
const HelpExample &e : std::as_const( v.mExamples ) )
709 helpContents +=
"<li><code>" + e.mExpression +
"</code> → <code>" + e.mReturns +
"</code>";
711 if ( !e.mNote.isEmpty() )
712 helpContents += u
" (%1)"_s.arg( e.mNote );
714 helpContents +=
"</li>\n"_L1;
717 helpContents +=
"</ul>\n</div>\n"_L1;
720 if ( !v.mNotes.isEmpty() )
722 helpContents += u
"<h4>%1</h4>\n<div class=\"notes\"><p>%2</p></div>\n"_s.arg( tr(
"Notes" ), v.mNotes );
731 QStringList
tags = QStringList();
733 QgsExpression::initFunctionHelp();
735 if ( sFunctionHelpTexts.contains( name ) )
737 const Help &f = sFunctionHelpTexts[name];
739 for (
const HelpVariant &v : std::as_const( f.mVariants ) )
748void QgsExpression::initVariableHelp()
750 static std::once_flag initialized;
751 std::call_once( initialized, buildVariableHelp );
754void QgsExpression::buildVariableHelp()
757 sVariableHelpTexts()->insert( u
"qgis_version"_s, QCoreApplication::translate(
"variable_help",
"Current QGIS version string." ) );
758 sVariableHelpTexts()->insert( u
"qgis_version_no"_s, QCoreApplication::translate(
"variable_help",
"Current QGIS version number." ) );
759 sVariableHelpTexts()->insert( u
"qgis_release_name"_s, QCoreApplication::translate(
"variable_help",
"Current QGIS release name." ) );
760 sVariableHelpTexts()->insert( u
"qgis_short_version"_s, QCoreApplication::translate(
"variable_help",
"Short QGIS version string." ) );
761 sVariableHelpTexts()->insert( u
"qgis_os_name"_s, QCoreApplication::translate(
"variable_help",
"Operating system name, e.g., 'windows', 'linux' or 'osx'." ) );
762 sVariableHelpTexts()->insert( u
"qgis_platform"_s, QCoreApplication::translate(
"variable_help",
"QGIS platform, e.g., 'desktop' or 'server'." ) );
763 sVariableHelpTexts()->insert( u
"qgis_locale"_s, QCoreApplication::translate(
"variable_help",
"Two letter identifier for current QGIS locale." ) );
764 sVariableHelpTexts()->insert( u
"user_account_name"_s, QCoreApplication::translate(
"variable_help",
"Current user's operating system account name." ) );
765 sVariableHelpTexts()->insert( u
"user_full_name"_s, QCoreApplication::translate(
"variable_help",
"Current user's operating system user name (if available)." ) );
768 sVariableHelpTexts()->insert( u
"project_title"_s, QCoreApplication::translate(
"variable_help",
"Title of current project." ) );
769 sVariableHelpTexts()->insert( u
"project_path"_s, QCoreApplication::translate(
"variable_help",
"Full path (including file name) of current project." ) );
770 sVariableHelpTexts()->insert( u
"project_folder"_s, QCoreApplication::translate(
"variable_help",
"Folder for current project." ) );
771 sVariableHelpTexts()->insert( u
"project_filename"_s, QCoreApplication::translate(
"variable_help",
"Filename of current project." ) );
772 sVariableHelpTexts()->insert( u
"project_basename"_s, QCoreApplication::translate(
"variable_help",
"Base name of current project's filename (without path and extension)." ) );
773 sVariableHelpTexts()->insert( u
"project_home"_s, QCoreApplication::translate(
"variable_help",
"Home path of current project." ) );
774 sVariableHelpTexts()->insert( u
"project_crs"_s, QCoreApplication::translate(
"variable_help",
"Identifier for the coordinate reference system of project (e.g., 'EPSG:4326')." ) );
775 sVariableHelpTexts()->insert( u
"project_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Coordinate reference system of project (full definition)." ) );
776 sVariableHelpTexts()->insert( u
"project_units"_s, QCoreApplication::translate(
"variable_help",
"Unit of the project's CRS." ) );
777 sVariableHelpTexts()->insert( u
"project_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the coordinate reference system of the project." ) );
778 sVariableHelpTexts()->insert( u
"project_crs_acronym"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the coordinate reference system of the project." ) );
779 sVariableHelpTexts()->insert( u
"project_crs_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the ellipsoid of the coordinate reference system of the project." ) );
780 sVariableHelpTexts()->insert( u
"project_crs_proj4"_s, QCoreApplication::translate(
"variable_help",
"Proj4 definition of the coordinate reference system of the project." ) );
781 sVariableHelpTexts()->insert( u
"project_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the coordinate reference system of the project." ) );
783 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')." ) );
784 sVariableHelpTexts()->insert( u
"project_vertical_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Vertical coordinate reference system of project (full definition)." ) );
785 sVariableHelpTexts()->insert( u
"project_vertical_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the vertical coordinate reference system of the project." ) );
786 sVariableHelpTexts()->insert( u
"project_vertical_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the vertical coordinate reference system of the project." ) );
788 sVariableHelpTexts()->insert( u
"project_author"_s, QCoreApplication::translate(
"variable_help",
"Project author, taken from project metadata." ) );
789 sVariableHelpTexts()->insert( u
"project_abstract"_s, QCoreApplication::translate(
"variable_help",
"Project abstract, taken from project metadata." ) );
790 sVariableHelpTexts()->insert( u
"project_creation_date"_s, QCoreApplication::translate(
"variable_help",
"Project creation date, taken from project metadata." ) );
791 sVariableHelpTexts()->insert( u
"project_identifier"_s, QCoreApplication::translate(
"variable_help",
"Project identifier, taken from project metadata." ) );
792 sVariableHelpTexts()->insert( u
"project_last_saved"_s, QCoreApplication::translate(
"variable_help",
"Date/time when project was last saved." ) );
793 sVariableHelpTexts()->insert( u
"project_keywords"_s, QCoreApplication::translate(
"variable_help",
"Project keywords, taken from project metadata." ) );
794 sVariableHelpTexts()->insert( u
"project_area_units"_s, QCoreApplication::translate(
"variable_help",
"Area unit for current project, used when calculating areas of geometries." ) );
795 sVariableHelpTexts()->insert( u
"project_distance_units"_s, QCoreApplication::translate(
"variable_help",
"Distance unit for current project, used when calculating lengths of geometries." ) );
796 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." ) );
797 sVariableHelpTexts()->insert( u
"layer_ids"_s, QCoreApplication::translate(
"variable_help",
"List of all map layer IDs from the current project." ) );
798 sVariableHelpTexts()->insert( u
"layers"_s, QCoreApplication::translate(
"variable_help",
"List of all map layers from the current project." ) );
801 sVariableHelpTexts()->insert( u
"layer_name"_s, QCoreApplication::translate(
"variable_help",
"Name of current layer." ) );
802 sVariableHelpTexts()->insert( u
"layer_id"_s, QCoreApplication::translate(
"variable_help",
"ID of current layer." ) );
803 sVariableHelpTexts()->insert( u
"layer_crs"_s, QCoreApplication::translate(
"variable_help",
"CRS Authority ID of current layer." ) );
804 sVariableHelpTexts()->insert( u
"layer"_s, QCoreApplication::translate(
"variable_help",
"The current layer." ) );
805 sVariableHelpTexts()->insert( u
"layer_crs_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Ellipsoid acronym of current layer CRS." ) );
807 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')." ) );
808 sVariableHelpTexts()->insert( u
"layer_vertical_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Vertical coordinate reference system of layer (full definition)." ) );
809 sVariableHelpTexts()->insert( u
"layer_vertical_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the vertical coordinate reference system of the layer." ) );
810 sVariableHelpTexts()->insert( u
"layer_vertical_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the vertical coordinate reference system of the layer." ) );
814 ->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." ) );
815 sVariableHelpTexts()->insert( u
"id"_s, QCoreApplication::translate(
"variable_help",
"The ID of the current feature being evaluated." ) );
816 sVariableHelpTexts()->insert( u
"geometry"_s, QCoreApplication::translate(
"variable_help",
"The geometry of the current feature being evaluated." ) );
819 sVariableHelpTexts()->insert( u
"layout_name"_s, QCoreApplication::translate(
"variable_help",
"Name of composition." ) );
820 sVariableHelpTexts()->insert( u
"layout_numpages"_s, QCoreApplication::translate(
"variable_help",
"Number of pages in composition." ) );
821 sVariableHelpTexts()->insert( u
"layout_page"_s, QCoreApplication::translate(
"variable_help",
"Current page number in composition." ) );
822 sVariableHelpTexts()->insert( u
"layout_pageheight"_s, QCoreApplication::translate(
"variable_help",
"Composition page height in mm (or specified custom units)." ) );
823 sVariableHelpTexts()->insert( u
"layout_pagewidth"_s, QCoreApplication::translate(
"variable_help",
"Composition page width in mm (or specified custom units)." ) );
824 sVariableHelpTexts()->insert( u
"layout_pageoffsets"_s, QCoreApplication::translate(
"variable_help",
"Array of Y coordinate of the top of each page." ) );
825 sVariableHelpTexts()->insert( u
"layout_dpi"_s, QCoreApplication::translate(
"variable_help",
"Composition resolution (DPI)." ) );
828 sVariableHelpTexts()->insert( u
"atlas_layerid"_s, QCoreApplication::translate(
"variable_help",
"Current atlas coverage layer ID." ) );
829 sVariableHelpTexts()->insert( u
"atlas_layername"_s, QCoreApplication::translate(
"variable_help",
"Current atlas coverage layer name." ) );
830 sVariableHelpTexts()->insert( u
"atlas_totalfeatures"_s, QCoreApplication::translate(
"variable_help",
"Total number of features in atlas." ) );
831 sVariableHelpTexts()->insert( u
"atlas_featurenumber"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature number." ) );
832 sVariableHelpTexts()->insert( u
"atlas_filename"_s, QCoreApplication::translate(
"variable_help",
"Current atlas file name." ) );
833 sVariableHelpTexts()->insert( u
"atlas_pagename"_s, QCoreApplication::translate(
"variable_help",
"Current atlas page name." ) );
834 sVariableHelpTexts()->insert( u
"atlas_feature"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature (as feature object)." ) );
835 sVariableHelpTexts()->insert( u
"atlas_featureid"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature ID." ) );
836 sVariableHelpTexts()->insert( u
"atlas_geometry"_s, QCoreApplication::translate(
"variable_help",
"Current atlas feature geometry." ) );
839 sVariableHelpTexts()->insert( u
"item_id"_s, QCoreApplication::translate(
"variable_help",
"Layout item user-assigned ID (not necessarily unique)." ) );
840 sVariableHelpTexts()->insert( u
"item_uuid"_s, QCoreApplication::translate(
"variable_help",
"layout item unique ID." ) );
841 sVariableHelpTexts()->insert( u
"item_left"_s, QCoreApplication::translate(
"variable_help",
"Left position of layout item (in mm)." ) );
842 sVariableHelpTexts()->insert( u
"item_top"_s, QCoreApplication::translate(
"variable_help",
"Top position of layout item (in mm)." ) );
843 sVariableHelpTexts()->insert( u
"item_width"_s, QCoreApplication::translate(
"variable_help",
"Width of layout item (in mm)." ) );
844 sVariableHelpTexts()->insert( u
"item_height"_s, QCoreApplication::translate(
"variable_help",
"Height of layout item (in mm)." ) );
847 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." ) );
848 sVariableHelpTexts()->insert( u
"map_rotation"_s, QCoreApplication::translate(
"variable_help",
"Current rotation of map." ) );
849 sVariableHelpTexts()->insert( u
"map_scale"_s, QCoreApplication::translate(
"variable_help",
"Current scale of map." ) );
850 sVariableHelpTexts()->insert( u
"map_extent"_s, QCoreApplication::translate(
"variable_help",
"Geometry representing the current extent of the map." ) );
851 sVariableHelpTexts()->insert( u
"map_extent_center"_s, QCoreApplication::translate(
"variable_help",
"Center of map." ) );
852 sVariableHelpTexts()->insert( u
"map_extent_width"_s, QCoreApplication::translate(
"variable_help",
"Width of map." ) );
853 sVariableHelpTexts()->insert( u
"map_extent_height"_s, QCoreApplication::translate(
"variable_help",
"Height of map." ) );
854 sVariableHelpTexts()->insert( u
"map_crs"_s, QCoreApplication::translate(
"variable_help",
"Coordinate reference system of map (e.g., 'EPSG:4326')." ) );
855 sVariableHelpTexts()->insert( u
"map_crs_description"_s, QCoreApplication::translate(
"variable_help",
"Name of the coordinate reference system of the map." ) );
856 sVariableHelpTexts()->insert( u
"map_units"_s, QCoreApplication::translate(
"variable_help",
"Units for map measurements." ) );
857 sVariableHelpTexts()->insert( u
"map_crs_definition"_s, QCoreApplication::translate(
"variable_help",
"Coordinate reference system of the map (full definition)." ) );
858 sVariableHelpTexts()->insert( u
"map_crs_acronym"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the coordinate reference system of the map." ) );
859 sVariableHelpTexts()->insert( u
"map_crs_projection"_s, QCoreApplication::translate(
"variable_help",
"Projection method used by the coordinate reference system of the map." ) );
860 sVariableHelpTexts()->insert( u
"map_crs_ellipsoid"_s, QCoreApplication::translate(
"variable_help",
"Acronym of the ellipsoid of the coordinate reference system of the map." ) );
861 sVariableHelpTexts()->insert( u
"map_crs_proj4"_s, QCoreApplication::translate(
"variable_help",
"Proj4 definition of the coordinate reference system of the map." ) );
862 sVariableHelpTexts()->insert( u
"map_crs_wkt"_s, QCoreApplication::translate(
"variable_help",
"WKT definition of the coordinate reference system of the map." ) );
863 sVariableHelpTexts()->insert( u
"map_layer_ids"_s, QCoreApplication::translate(
"variable_help",
"List of map layer IDs visible in the map." ) );
864 sVariableHelpTexts()->insert( u
"map_layers"_s, QCoreApplication::translate(
"variable_help",
"List of map layers visible in the map." ) );
866 sVariableHelpTexts()->insert( u
"map_start_time"_s, QCoreApplication::translate(
"variable_help",
"Start of the map's temporal time range (as a datetime value)" ) );
867 sVariableHelpTexts()->insert( u
"map_end_time"_s, QCoreApplication::translate(
"variable_help",
"End of the map's temporal time range (as a datetime value)" ) );
868 sVariableHelpTexts()->insert( u
"map_interval"_s, QCoreApplication::translate(
"variable_help",
"Duration of the map's temporal time range (as an interval value)" ) );
869 sVariableHelpTexts()->insert( u
"map_z_range_lower"_s, QCoreApplication::translate(
"variable_help",
"Lower elevation of the map's elevation range" ) );
870 sVariableHelpTexts()->insert( u
"map_z_range_upper"_s, QCoreApplication::translate(
"variable_help",
"Upper elevation of the map's elevation range" ) );
872 sVariableHelpTexts()->insert( u
"frame_rate"_s, QCoreApplication::translate(
"variable_help",
"Number of frames per second during animation playback" ) );
873 sVariableHelpTexts()->insert( u
"frame_number"_s, QCoreApplication::translate(
"variable_help",
"Current frame number during animation playback" ) );
874 sVariableHelpTexts()->insert( u
"frame_duration"_s, QCoreApplication::translate(
"variable_help",
"Temporal duration of each animation frame (as an interval value)" ) );
875 sVariableHelpTexts()->insert( u
"frame_timestep"_s, QCoreApplication::translate(
"variable_help",
"Frame time step during animation playback" ) );
876 sVariableHelpTexts()->insert( u
"frame_timestep_unit"_s, QCoreApplication::translate(
"variable_help",
"Unit value of the frame time step during animation playback" ) );
877 sVariableHelpTexts()->insert( u
"frame_timestep_units"_s, QCoreApplication::translate(
"variable_help",
"String representation of the frame time step unit during animation playback" ) );
878 sVariableHelpTexts()->insert( u
"animation_start_time"_s, QCoreApplication::translate(
"variable_help",
"Start of the animation's overall temporal time range (as a datetime value)" ) );
879 sVariableHelpTexts()->insert( u
"animation_end_time"_s, QCoreApplication::translate(
"variable_help",
"End of the animation's overall temporal time range (as a datetime value)" ) );
880 sVariableHelpTexts()->insert( u
"animation_interval"_s, QCoreApplication::translate(
"variable_help",
"Duration of the animation's overall temporal time range (as an interval value)" ) );
884 ->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]." ) );
886 ->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." ) );
888 sVariableHelpTexts()->insert(
890 QCoreApplication::translate(
"variable_help",
"Stores the number of the current row." )
892 + 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." )
894 + 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." )
896 sVariableHelpTexts()->insert( u
"grid_number"_s, QCoreApplication::translate(
"variable_help",
"Current grid annotation value." ) );
897 sVariableHelpTexts()->insert( u
"grid_axis"_s, QCoreApplication::translate(
"variable_help",
"Current grid annotation axis (e.g., 'x' for longitude, 'y' for latitude)." ) );
898 sVariableHelpTexts()->insert( u
"grid_count"_s, QCoreApplication::translate(
"variable_help",
"Total number of visible grid lines for the current grid axis." ) );
900 ->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." ) );
901 sVariableHelpTexts()->insert( u
"column_number"_s, QCoreApplication::translate(
"variable_help",
"Stores the number of the current column." ) );
904 sVariableHelpTexts()->insert( u
"canvas_cursor_point"_s, QCoreApplication::translate(
"variable_help",
"Last cursor position on the canvas in the project's geographical coordinates." ) );
906 ->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." ) );
909 sVariableHelpTexts()->insert( u
"legend_title"_s, QCoreApplication::translate(
"variable_help",
"Title of the legend." ) );
910 sVariableHelpTexts()->insert( u
"legend_column_count"_s, QCoreApplication::translate(
"variable_help",
"Number of column in the legend." ) );
911 sVariableHelpTexts()->insert( u
"legend_split_layers"_s, QCoreApplication::translate(
"variable_help",
"Boolean indicating if layers can be split in the legend." ) );
912 sVariableHelpTexts()->insert( u
"legend_wrap_string"_s, QCoreApplication::translate(
"variable_help",
"Characters used to wrap the legend text." ) );
913 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." ) );
914 sVariableHelpTexts()->insert( u
"legend_filter_out_atlas"_s, QCoreApplication::translate(
"variable_help",
"Boolean indicating if the Atlas is filtered out of the legend." ) );
917 sVariableHelpTexts()->insert( u
"scale_value"_s, QCoreApplication::translate(
"variable_help",
"Current scale bar distance value." ) );
920 sVariableHelpTexts()->insert(
921 u
"snapping_results"_s,
922 QCoreApplication::translate(
924 "<p>An array with an item for each snapped point.</p>"
925 "<p>Each item is a map with the following keys:</p>"
927 "<dt>valid</dt><dd>Boolean that indicates if the snapping result is valid</dd>"
928 "<dt>layer</dt><dd>The layer on which the snapped feature is</dd>"
929 "<dt>feature_id</dt><dd>The feature id of the snapped feature</dd>"
930 "<dt>vertex_index</dt><dd>The index of the snapped vertex</dd>"
931 "<dt>distance</dt><dd>The distance between the mouse cursor and the snapped point at the time of snapping</dd>"
938 sVariableHelpTexts()->insert( u
"geometry_part_count"_s, QCoreApplication::translate(
"variable_help",
"Number of parts in rendered feature's geometry." ) );
939 sVariableHelpTexts()->insert( u
"geometry_part_num"_s, QCoreApplication::translate(
"variable_help",
"Current geometry part number for feature being rendered." ) );
941 ->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." ) );
943 ->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." ) );
945 ->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." ) );
947 sVariableHelpTexts()->insert( u
"symbol_color"_s, QCoreApplication::translate(
"symbol_color",
"Color of symbol used to render the feature." ) );
948 sVariableHelpTexts()->insert( u
"symbol_angle"_s, QCoreApplication::translate(
"symbol_angle",
"Angle of symbol used to render the feature (valid for marker symbols only)." ) );
949 sVariableHelpTexts()->insert( u
"symbol_layer_count"_s, QCoreApplication::translate(
"symbol_layer_count",
"Total number of symbol layers in the symbol." ) );
950 sVariableHelpTexts()->insert( u
"symbol_layer_index"_s, QCoreApplication::translate(
"symbol_layer_index",
"Current symbol layer index." ) );
951 sVariableHelpTexts()->insert( u
"symbol_marker_row"_s, QCoreApplication::translate(
"symbol_marker_row",
"Row number for marker (valid for point pattern fills only)." ) );
952 sVariableHelpTexts()->insert( u
"symbol_marker_column"_s, QCoreApplication::translate(
"symbol_marker_column",
"Column number for marker (valid for point pattern fills only)." ) );
953 sVariableHelpTexts()->insert( u
"symbol_frame"_s, QCoreApplication::translate(
"symbol_frame",
"Frame number (for animated symbols only)." ) );
955 sVariableHelpTexts()->insert( u
"symbol_label"_s, QCoreApplication::translate(
"symbol_label",
"Label for the symbol (either a user defined label or the default autogenerated label)." ) );
956 sVariableHelpTexts()->insert( u
"symbol_id"_s, QCoreApplication::translate(
"symbol_id",
"Internal ID of the symbol." ) );
957 sVariableHelpTexts()->insert( u
"symbol_count"_s, QCoreApplication::translate(
"symbol_count",
"Total number of features represented by the symbol." ) );
960 sVariableHelpTexts()->insert( u
"cluster_color"_s, QCoreApplication::translate(
"cluster_color",
"Color of symbols within a cluster, or NULL if symbols have mixed colors." ) );
961 sVariableHelpTexts()->insert( u
"cluster_size"_s, QCoreApplication::translate(
"cluster_size",
"Number of symbols contained within a cluster." ) );
964 sVariableHelpTexts()->insert( u
"algorithm_id"_s, QCoreApplication::translate(
"algorithm_id",
"Unique ID for algorithm." ) );
965 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)." ) );
966 sVariableHelpTexts()->insert( u
"model_folder"_s, QCoreApplication::translate(
"variable_help",
"Folder containing current model (or project folder if model is embedded in a project)." ) );
967 sVariableHelpTexts()->insert( u
"model_name"_s, QCoreApplication::translate(
"variable_help",
"Name of current model." ) );
968 sVariableHelpTexts()->insert( u
"model_group"_s, QCoreApplication::translate(
"variable_help",
"Group for current model." ) );
969 sVariableHelpTexts()->insert( u
"fullextent_minx"_s, QCoreApplication::translate(
"fullextent_minx",
"Minimum x-value from full canvas extent (including all layers)." ) );
970 sVariableHelpTexts()->insert( u
"fullextent_miny"_s, QCoreApplication::translate(
"fullextent_miny",
"Minimum y-value from full canvas extent (including all layers)." ) );
971 sVariableHelpTexts()->insert( u
"fullextent_maxx"_s, QCoreApplication::translate(
"fullextent_maxx",
"Maximum x-value from full canvas extent (including all layers)." ) );
972 sVariableHelpTexts()->insert( u
"fullextent_maxy"_s, QCoreApplication::translate(
"fullextent_maxy",
"Maximum y-value from full canvas extent (including all layers)." ) );
976 ->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)." ) );
980 ->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." ) );
982 ->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." ) );
985 sVariableHelpTexts()->insert(
986 u
"current_parent_geometry"_s,
987 QCoreApplication::translate(
988 "current_parent_geometry",
989 "Only usable in an embedded form context, "
990 "represents the geometry of the feature currently being edited in the parent form.\n"
991 "Can be used in a form/row context to filter the related features using a value "
992 "from the feature currently edited in the parent form, to make sure that the filter "
993 "still works with standalone forms it is recommended to wrap this variable in a "
997 sVariableHelpTexts()->insert(
998 u
"current_parent_feature"_s,
999 QCoreApplication::translate(
1000 "current_parent_feature",
1001 "Only usable in an embedded form context, "
1002 "represents the feature currently being edited in the parent form.\n"
1003 "Can be used in a form/row context to filter the related features using a value "
1004 "from the feature currently edited in the parent form, to make sure that the filter "
1005 "still works with standalone forms it is recommended to wrap this variable in a "
1011 sVariableHelpTexts()
1012 ->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." ) );
1015 sVariableHelpTexts()->insert( u
"plot_axis"_s, QCoreApplication::translate(
"plot_axis",
"The associated plot axis, e.g. 'x' or 'y'." ) );
1016 sVariableHelpTexts()->insert( u
"plot_axis_value"_s, QCoreApplication::translate(
"plot_axis_value",
"The current value for the plot axis grid line." ) );
1017 sVariableHelpTexts()->insert( u
"chart_category"_s, QCoreApplication::translate(
"chart_category",
"The chart item category, e.g. 'fruit' or 'june'." ) );
1018 sVariableHelpTexts()->insert( u
"chart_value"_s, QCoreApplication::translate(
"chart_value",
"The chart item value." ) );
1019 sVariableHelpTexts()->insert( u
"chart_series_name"_s, QCoreApplication::translate(
"chart_series_name",
"The chart item's series name, e.g. 'Series 1'." ) );
1024 QgsExpression::initVariableHelp();
1025 if ( sVariableHelpTexts()->contains( name ) )
1029 sVariableHelpTexts()->insert( name, description );
1035 QgsExpression::initVariableHelp();
1036 return sVariableHelpTexts()->value( variableName, QString() );
1041 QString text = !description.isEmpty() ? u
"<p>%1</p>"_s.arg( description ) : QString();
1044 QString valueString;
1045 if ( !value.isValid() )
1047 valueString = QCoreApplication::translate(
"variable_help",
"not set" );
1053 text.append( QCoreApplication::translate(
"variable_help",
"<p>Current value: %1</p>" ).arg( valueString ) );
1060 if ( sGroups()->isEmpty() )
1062 sGroups()->insert( u
"Aggregates"_s, tr(
"Aggregates" ) );
1063 sGroups()->insert( u
"Arrays"_s, tr(
"Arrays" ) );
1064 sGroups()->insert( u
"Color"_s, tr(
"Color" ) );
1065 sGroups()->insert( u
"Conditionals"_s, tr(
"Conditionals" ) );
1066 sGroups()->insert( u
"Conversions"_s, tr(
"Conversions" ) );
1067 sGroups()->insert( u
"Date and Time"_s, tr(
"Date and Time" ) );
1068 sGroups()->insert( u
"Fields and Values"_s, tr(
"Fields and Values" ) );
1069 sGroups()->insert( u
"Files and Paths"_s, tr(
"Files and Paths" ) );
1070 sGroups()->insert( u
"Fuzzy Matching"_s, tr(
"Fuzzy Matching" ) );
1071 sGroups()->insert( u
"General"_s, tr(
"General" ) );
1072 sGroups()->insert( u
"GeometryGroup"_s, tr(
"Geometry" ) );
1073 sGroups()->insert( u
"Map Layers"_s, tr(
"Map Layers" ) );
1074 sGroups()->insert( u
"Maps"_s, tr(
"Maps" ) );
1075 sGroups()->insert( u
"Math"_s, tr(
"Math" ) );
1076 sGroups()->insert( u
"Operators"_s, tr(
"Operators" ) );
1077 sGroups()->insert( u
"Rasters"_s, tr(
"Rasters" ) );
1078 sGroups()->insert( u
"Record and Attributes"_s, tr(
"Record and Attributes" ) );
1079 sGroups()->insert( u
"String"_s, tr(
"String" ) );
1080 sGroups()->insert( u
"MagneticModels"_s, tr(
"Magnetic Models" ) );
1081 sGroups()->insert( u
"Variables"_s, tr(
"Variables" ) );
1082 sGroups()->insert( u
"Recent (%1)"_s, tr(
"Recent (%1)" ) );
1083 sGroups()->insert( u
"UserGroup"_s, tr(
"User expressions" ) );
1089 return sGroups()->value( name, name );
1094 const QString startToken = htmlOutput ? u
"<i><"_s : u
"<"_s;
1095 const QString endToken = htmlOutput ? u
"></i>"_s : u
">"_s;
1097 QgsGeometry geom = QgsExpressionUtils::getGeometry( value,
nullptr );
1102 return startToken + tr(
"empty geometry" ) + endToken;
1108 return startToken + tr(
"map layer" ) + endToken;
1110 else if ( !value.isValid() )
1112 return htmlOutput ? tr(
"<i>NULL</i>" ) : QString();
1114 else if ( value.userType() == qMetaTypeId< QgsFeature>() )
1118 return startToken + tr(
"feature: %1" ).arg( feat.
id() ) + endToken;
1120 else if ( value.userType() == qMetaTypeId< QgsCoordinateReferenceSystem>() )
1125 else if ( value.userType() == qMetaTypeId< QTimeZone>() )
1127 const QTimeZone tz = value.value<QTimeZone>();
1128#if QT_FEATURE_timezone > 0
1129 return startToken + tr(
"time zone: %1" ).arg( tz.isValid() ? tz.displayName( QTimeZone::GenericTime, QTimeZone::ShortName ) : tr(
"invalid" ) ) + endToken;
1131 QgsDebugError( u
"Qt is built without Qt timezone support, timezone preview not available"_s );
1134 else if ( value.userType() == qMetaTypeId< QgsInterval>() )
1137 if ( interval.
days() > 1 )
1139 return startToken + tr(
"interval: %1 days" ).arg( interval.
days() ) + endToken;
1141 else if ( interval.
hours() > 1 )
1143 return startToken + tr(
"interval: %1 hours" ).arg( interval.
hours() ) + endToken;
1145 else if ( interval.
minutes() > 1 )
1147 return startToken + tr(
"interval: %1 minutes" ).arg( interval.
minutes() ) + endToken;
1151 return startToken + tr(
"interval: %1 seconds" ).arg( interval.
seconds() ) + endToken;
1154 else if ( value.userType() == qMetaTypeId< QgsGradientColorRamp>() )
1156 return startToken + tr(
"gradient ramp" ) + endToken;
1158 else if ( value.userType() == QMetaType::Type::QDate )
1160 const QDate dt = value.toDate();
1161 return startToken + tr(
"date: %1" ).arg( dt.toString( u
"yyyy-MM-dd"_s ) ) + endToken;
1163 else if ( value.userType() == QMetaType::Type::QTime )
1165 const QTime tm = value.toTime();
1166 return startToken + tr(
"time: %1" ).arg( tm.toString( u
"hh:mm:ss"_s ) ) + endToken;
1168 else if ( value.userType() == QMetaType::Type::QDateTime )
1170 const QDateTime dt = value.toDateTime();
1171 return startToken + tr(
"datetime: %1 (%2)" ).arg( dt.toString( u
"yyyy-MM-dd hh:mm:ss"_s ), dt.timeZoneAbbreviation() ) + endToken;
1173 else if ( value.userType() == QMetaType::Type::QString )
1175 const QString previewString = value.toString();
1176 if ( previewString.length() > maximumPreviewLength + 3 )
1178 return tr(
"'%1…'" ).arg( previewString.left( maximumPreviewLength ) );
1182 return '\'' + previewString +
'\'';
1185 else if ( value.userType() == QMetaType::Type::QVariantMap )
1187 QString mapStr = u
"{"_s;
1188 const QVariantMap map = value.toMap();
1190 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1192 mapStr.append( separator );
1193 if ( separator.isEmpty() )
1196 mapStr.append( u
" '%1': %2"_s.arg( it.key(),
formatPreviewString( it.value(), htmlOutput ) ) );
1197 if ( mapStr.length() > maximumPreviewLength - 3 )
1199 mapStr = tr(
"%1…" ).arg( mapStr.left( maximumPreviewLength - 2 ) );
1208 else if ( value.userType() == QMetaType::Type::QVariantList || value.userType() == QMetaType::Type::QStringList )
1210 QString listStr = u
"["_s;
1211 const QVariantList list = value.toList();
1213 for (
const QVariant &arrayValue : list )
1215 listStr.append( separator );
1216 if ( separator.isEmpty() )
1219 listStr.append(
" " );
1221 if ( listStr.length() > maximumPreviewLength - 3 )
1223 listStr = QString( tr(
"%1…" ) ).arg( listStr.left( maximumPreviewLength - 2 ) );
1227 if ( !list.empty() )
1232 else if ( value.type() == QVariant::Color )
1234 const QColor color = value.value<QColor>();
1236 if ( !color.isValid() )
1238 return tr(
"<i>Invalid</i>" );
1241 switch ( color.spec() )
1243 case QColor::Spec::Cmyk:
1244 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 );
1246 case QColor::Spec::Hsv:
1247 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 );
1249 case QColor::Spec::Hsl:
1250 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 );
1252 case QColor::Spec::Rgb:
1253 case QColor::Spec::ExtendedRgb:
1254 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 );
1256 case QColor::Spec::Invalid:
1257 return tr(
"<i>Invalid</i>" );
1259 QgsDebugError( u
"Unknown color format: %1"_s.arg( color.spec() ) );
1260 return tr(
"<i>Unknown color format: %1</i>" ).arg( color.spec() );
1262 else if ( value.userType() == QMetaType::Type::Int
1263 || value.userType() == QMetaType::Type::UInt
1264 || value.userType() == QMetaType::Type::LongLong
1265 || value.userType() == QMetaType::Type::ULongLong
1266 || value.userType() == QMetaType::Type::Double
1269 value.userType() ==
static_cast<QMetaType::Type
>( QMetaType::Float ) )
1271 return QgsExpressionUtils::toLocalizedString( value );
1275 QString str { value.toString() };
1276 if ( str.length() > maximumPreviewLength - 3 )
1278 str = tr(
"%1…" ).arg( str.left( maximumPreviewLength - 2 ) );
1290 else if ( fieldType == QMetaType::Type::UnknownType )
1316 if ( columnRef && literal )
1318 field = columnRef->
name();
1319 value = literal->
value();
1329 if ( expressions.empty() )
1335 for (
const QString &
expression : expressions )
1346 else if ( field != inField )
1362 if ( inOp->isNotIn() )
1371 inField = columnRef->
name();
1374 else if ( columnRef->
name() != inField )
1381 const QList<QgsExpressionNode *>
nodes = nodeList->list();
1397 QStringList orParts;
1402 orParts.append( collectOrs( leftOrOp->opLeft(), leftOrOp->opRight() ) );
1406 orParts.append( leftOrOp->dump() );
1411 orParts.append( leftInOp->dump() );
1422 orParts.append( collectOrs( rightOrOp->opLeft(), rightOrOp->opRight() ) );
1426 orParts.append( rightOrOp->dump() );
1431 orParts.append( rightInOp->dump() );
1444 const QStringList orParts = collectOrs( orOp->opLeft(), orOp->opRight() );
1445 if ( orParts.isEmpty() )
1451 QString orPartsResult;
1468 const QString innerInfield { inOpInner->node()->referencedColumns().values().first() };
1472 inField = innerInfield;
1476 if ( innerInfield != inField )
1482 const auto constInnerValuesList { inOpInner->list()->list() };
1483 for (
const auto &innerInValueNode : std::as_const( constInnerValuesList ) )
1485 values.append( innerInValueNode->dump() );
1511 result = u
"%1 IN (%2)"_s.arg(
quotedColumnRef( inField ), values.join(
',' ) );
1517 if ( !d->mRootNode )
1522 res.d->mRootNode.reset( d->mRootNode->simplifiedNode() );
1528 return d->mRootNode.get();
1543 if ( attrIndex >= 0 )
1550 const QString fieldName = qgis::down_cast<const QgsExpressionNodeColumnRef *>( candidate.
rootNode() )->name();
1562 if ( !
expression.contains(
'\"' ) && fieldIndex != -1 )
1575 if ( !d->mRootNode )
1576 return QList<const QgsExpressionNode *>();
1578 return d->mRootNode->nodes();
An atomic shared_ptr, for use in LLVM/clang builds (temporarily, until LLVM adds support for c++20 at...
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 std::unique_ptr< QgsExpressionContextScope > globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
static std::unique_ptr< QgsExpressionContextScope > projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
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.
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.
int functionIndex(const QString &name) const
Returns the index of the function in the list.
void updateFunctionNameMap()
Updates the map of function names to indices.
SharedFunctionPtr getFunction(int index) const
Returns a shared pointer for the function with the specified index.
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
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 Q_DECL_DEPRECATED int functionIndex(const QString &name)
Returns index of the function in Functions array.
static Q_DECL_DEPRECATED 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.
std::shared_ptr< const SharedFunctionPtrList > FunctionListSnapshot
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.
static const FunctionListSnapshot getFunctionsSnapshot()
Returns a thread-safe snapshot of all registered functions.
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.
static Q_DECL_DEPRECATED QList< QgsExpressionFunction * > Functions()
Returns a list of all registered functions.
QgsExpression simplified() const
Returns an expression which is the simplest direct equivalent of this 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.
std::shared_ptr< QgsExpressionFunction > SharedFunctionPtr
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.