Skip to content

Commit 6fc9712

Browse files
committedOct 12, 2016
Allow expression functions to appear in multiple groups (fix #15682)
Now functions which make sense for multiple contexts (eg length, to_date) can appear in more than one group. (cherry-picked from 0c4bf94)
1 parent d558077 commit 6fc9712

File tree

5 files changed

+166
-27
lines changed

5 files changed

+166
-27
lines changed
 

‎python/core/qgsexpression.sip

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,19 @@ class QgsExpression
376376
bool handlesNull = false,
377377
bool isContextual = false );
378378

379+
/** Constructor for function which uses unnamed parameters and group list
380+
* @note added in QGIS 3.0
381+
*/
382+
Function( const QString& fnname,
383+
int params,
384+
const QStringList& groups,
385+
const QString& helpText = QString(),
386+
bool usesGeometry = false,
387+
const QStringList& referencedColumns = QStringList(),
388+
bool lazyEval = false,
389+
bool handlesNull = false,
390+
bool isContextual = false );
391+
379392
/** Constructor for function which uses named parameter list.
380393
* @note added in QGIS 2.16
381394
*/
@@ -389,6 +402,19 @@ class QgsExpression
389402
bool handlesNull = false,
390403
bool isContextual = false );
391404

405+
/** Constructor for function which uses named parameter list and group list.
406+
* @note added in QGIS 3.0
407+
*/
408+
Function( const QString& fnname,
409+
const QgsExpression::ParameterList& params,
410+
const QStringList& groups,
411+
const QString& helpText = QString(),
412+
bool usesGeometry = false,
413+
const QStringList& referencedColumns = QStringList(),
414+
bool lazyEval = false,
415+
bool handlesNull = false,
416+
bool isContextual = false );
417+
392418
virtual ~Function();
393419

394420
/** The name of the function. */
@@ -427,8 +453,23 @@ class QgsExpression
427453
*/
428454
bool isContextual() const;
429455

430-
/** The group the function belongs to. */
456+
/** Returns true if the function is deprecated and should not be presented as a valid option
457+
* to users in expression builders.
458+
* @note added in QGIS 3.0
459+
*/
460+
virtual bool isDeprecated() const;
461+
462+
/** Returns the first group which the function belongs to.
463+
* @note consider using groups() instead, as some functions naturally belong in multiple groups
464+
*/
431465
QString group() const;
466+
467+
/** Returns a list of the groups the function belongs to.
468+
* @note added in QGIS 3.0
469+
* @see group()
470+
*/
471+
QStringList groups() const;
472+
432473
/** The help text for the function. */
433474
const QString helptext() const;
434475

‎src/core/qgsexpression.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3298,7 +3298,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
32983298
<< new StaticFunction( "sqrt", ParameterList() << Parameter( "value" ), fcnSqrt, "Math" )
32993299
<< new StaticFunction( "radians", ParameterList() << Parameter( "degrees" ), fcnRadians, "Math" )
33003300
<< new StaticFunction( "degrees", ParameterList() << Parameter( "radians" ), fcnDegrees, "Math" )
3301-
<< new StaticFunction( "azimuth", ParameterList() << Parameter( "point_a" ) << Parameter( "point_b" ), fcnAzimuth, "Math" )
3301+
<< new StaticFunction( "azimuth", ParameterList() << Parameter( "point_a" ) << Parameter( "point_b" ), fcnAzimuth, QStringList() << "Math" << "GeometryGroup" )
33023302
<< new StaticFunction( "project", ParameterList() << Parameter( "point" ) << Parameter( "distance" ) << Parameter( "bearing" ), fcnProject, "GeometryGroup" )
33033303
<< new StaticFunction( "abs", ParameterList() << Parameter( "value" ), fcnAbs, "Math" )
33043304
<< new StaticFunction( "cos", ParameterList() << Parameter( "angle" ), fcnCos, "Math" )
@@ -3323,13 +3323,13 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33233323
<< new StaticFunction( "floor", 1, fcnFloor, "Math" )
33243324
<< new StaticFunction( "ceil", 1, fcnCeil, "Math" )
33253325
<< new StaticFunction( "pi", 0, fcnPi, "Math", QString(), false, QStringList(), false, QStringList() << "$pi" )
3326-
<< new StaticFunction( "to_int", 1, fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
3327-
<< new StaticFunction( "to_real", 1, fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
3328-
<< new StaticFunction( "to_string", 1, fcnToString, "Conversions", QString(), false, QStringList(), false, QStringList() << "tostring" )
3329-
<< new StaticFunction( "to_datetime", 1, fcnToDateTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "todatetime" )
3330-
<< new StaticFunction( "to_date", 1, fcnToDate, "Conversions", QString(), false, QStringList(), false, QStringList() << "todate" )
3331-
<< new StaticFunction( "to_time", 1, fcnToTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "totime" )
3332-
<< new StaticFunction( "to_interval", 1, fcnToInterval, "Conversions", QString(), false, QStringList(), false, QStringList() << "tointerval" )
3326+
<< new StaticFunction( "to_int", ParameterList() << Parameter( "value" ), fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
3327+
<< new StaticFunction( "to_real", ParameterList() << Parameter( "value" ), fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
3328+
<< new StaticFunction( "to_string", ParameterList() << Parameter( "value" ), fcnToString, QStringList() << "Conversions" << "String", QString(), false, QStringList(), false, QStringList() << "tostring" )
3329+
<< new StaticFunction( "to_datetime", ParameterList() << Parameter( "value" ), fcnToDateTime, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "todatetime" )
3330+
<< new StaticFunction( "to_date", ParameterList() << Parameter( "value" ), fcnToDate, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "todate" )
3331+
<< new StaticFunction( "to_time", ParameterList() << Parameter( "value" ), fcnToTime, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "totime" )
3332+
<< new StaticFunction( "to_interval", ParameterList() << Parameter( "value" ), fcnToInterval, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "tointerval" )
33333333
<< new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals", QString(), false, QStringList(), false, QStringList(), true )
33343334
<< new StaticFunction( "if", 3, fcnIf, "Conditionals", QString(), False, QStringList(), true )
33353335
<< new StaticFunction( "aggregate", ParameterList() << Parameter( "layer" ) << Parameter( "aggregate" ) << Parameter( "expression" )
@@ -3356,7 +3356,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33563356
<< new StaticFunction( "max_length", aggParams, fcnAggregateMaxLength, "Aggregates", QString(), False, QStringList(), true )
33573357
<< new StaticFunction( "concatenate", aggParams << Parameter( "concatenator", true ), fcnAggregateStringConcat, "Aggregates", QString(), False, QStringList(), true )
33583358

3359-
<< new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
3359+
<< new StaticFunction( "regexp_match", ParameterList() << Parameter( "string" ) << Parameter( "regex" ), fcnRegexpMatch, QStringList() << "Conditionals" << "String" )
33603360
<< new StaticFunction( "now", 0, fcnNow, "Date and Time", QString(), false, QStringList(), false, QStringList() << "$now" )
33613361
<< new StaticFunction( "age", 2, fcnAge, "Date and Time" )
33623362
<< new StaticFunction( "year", 1, fcnYear, "Date and Time" )
@@ -3377,7 +3377,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33773377
<< new StaticFunction( "soundex", 1, fcnSoundex, "Fuzzy Matching" )
33783378
<< new StaticFunction( "char", 1, fcnChar, "String" )
33793379
<< new StaticFunction( "wordwrap", ParameterList() << Parameter( "text" ) << Parameter( "length" ) << Parameter( "delimiter", true, " " ), fcnWordwrap, "String" )
3380-
<< new StaticFunction( "length", 1, fcnLength, "String" )
3380+
<< new StaticFunction( "length", ParameterList() << Parameter( "text", true, "" ), fcnLength, QStringList() << "String" << "GeometryGroup" )
33813381
<< new StaticFunction( "replace", 3, fcnReplace, "String" )
33823382
<< new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
33833383
<< new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
@@ -3390,7 +3390,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33903390
<< new StaticFunction( "lpad", 3, fcnLPad, "String" )
33913391
<< new StaticFunction( "format", -1, fcnFormatString, "String" )
33923392
<< new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
3393-
<< new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
3393+
<< new StaticFunction( "format_date", ParameterList() << Parameter( "date" ) << Parameter( "format" ), fcnFormatDate, QStringList() << "String" << "Date and Time" )
33943394
<< new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
33953395
<< new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
33963396
<< new StaticFunction( "ramp_color", 2, fcnRampColor, "Color" )

‎src/core/qgsexpression.h

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,31 @@ class CORE_EXPORT QgsExpression
530530
: mName( fnname )
531531
, mParams( params )
532532
, mUsesGeometry( usesGeometry )
533-
, mGroup( group )
533+
, mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
534+
, mHelpText( helpText )
535+
, mReferencedColumns( referencedColumns )
536+
, mLazyEval( lazyEval )
537+
, mHandlesNull( handlesNull )
538+
, mIsContextual( isContextual )
539+
{
540+
}
541+
542+
/** Constructor for function which uses unnamed parameters and group list
543+
* @note added in QGIS 3.0
544+
*/
545+
Function( const QString& fnname,
546+
int params,
547+
const QStringList& groups,
548+
const QString& helpText = QString(),
549+
bool usesGeometry = false,
550+
const QStringList& referencedColumns = QStringList(),
551+
bool lazyEval = false,
552+
bool handlesNull = false,
553+
bool isContextual = false )
554+
: mName( fnname )
555+
, mParams( params )
556+
, mUsesGeometry( usesGeometry )
557+
, mGroups( groups )
534558
, mHelpText( helpText )
535559
, mReferencedColumns( referencedColumns )
536560
, mLazyEval( lazyEval )
@@ -555,14 +579,39 @@ class CORE_EXPORT QgsExpression
555579
, mParams( 0 )
556580
, mParameterList( params )
557581
, mUsesGeometry( usesGeometry )
558-
, mGroup( group )
582+
, mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
559583
, mHelpText( helpText )
560584
, mReferencedColumns( referencedColumns )
561585
, mLazyEval( lazyEval )
562586
, mHandlesNull( handlesNull )
563587
, mIsContextual( isContextual )
564588
{}
565589

590+
/** Constructor for function which uses named parameter list and group list.
591+
* @note added in QGIS 3.0
592+
*/
593+
Function( const QString& fnname,
594+
const ParameterList& params,
595+
const QStringList& groups,
596+
const QString& helpText = QString(),
597+
bool usesGeometry = false,
598+
const QStringList& referencedColumns = QStringList(),
599+
bool lazyEval = false,
600+
bool handlesNull = false,
601+
bool isContextual = false )
602+
: mName( fnname )
603+
, mParams( 0 )
604+
, mParameterList( params )
605+
, mUsesGeometry( usesGeometry )
606+
, mGroups( groups )
607+
, mHelpText( helpText )
608+
, mReferencedColumns( referencedColumns )
609+
, mLazyEval( lazyEval )
610+
, mHandlesNull( handlesNull )
611+
, mIsContextual( isContextual )
612+
{}
613+
614+
566615
virtual ~Function() {}
567616

568617
/** The name of the function. */
@@ -614,8 +663,23 @@ class CORE_EXPORT QgsExpression
614663
*/
615664
bool isContextual() const { return mIsContextual; }
616665

617-
/** The group the function belongs to. */
618-
QString group() const { return mGroup; }
666+
/** Returns true if the function is deprecated and should not be presented as a valid option
667+
* to users in expression builders.
668+
* @note added in QGIS 3.0
669+
*/
670+
virtual bool isDeprecated() const { return mGroups.isEmpty() ? false : mGroups.contains( "deprecated" ); }
671+
672+
/** Returns the first group which the function belongs to.
673+
* @note consider using groups() instead, as some functions naturally belong in multiple groups
674+
*/
675+
QString group() const { return mGroups.isEmpty() ? QString() : mGroups.at( 0 ); }
676+
677+
/** Returns a list of the groups the function belongs to.
678+
* @note added in QGIS 3.0
679+
* @see group()
680+
*/
681+
QStringList groups() const { return mGroups; }
682+
619683
/** The help text for the function. */
620684
//TODO QGIS 3.0 - rename to helpText()
621685
const QString helptext() const { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
@@ -648,7 +712,7 @@ class CORE_EXPORT QgsExpression
648712
int mParams;
649713
ParameterList mParameterList;
650714
bool mUsesGeometry;
651-
QString mGroup;
715+
QStringList mGroups;
652716
QString mHelpText;
653717
QStringList mReferencedColumns;
654718
bool mLazyEval;
@@ -718,6 +782,25 @@ class CORE_EXPORT QgsExpression
718782
, mAliases( aliases )
719783
{}
720784

785+
/** Static function for evaluation against a QgsExpressionContext, using a named list of parameter values and list
786+
* of groups.
787+
*/
788+
StaticFunction( const QString& fnname,
789+
const ParameterList& params,
790+
FcnEvalContext fcn,
791+
const QStringList& groups,
792+
const QString& helpText = QString(),
793+
bool usesGeometry = false,
794+
const QStringList& referencedColumns = QStringList(),
795+
bool lazyEval = false,
796+
const QStringList& aliases = QStringList(),
797+
bool handlesNull = false )
798+
: Function( fnname, params, groups, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
799+
, mFnc( nullptr )
800+
, mContextFnc( fcn )
801+
, mAliases( aliases )
802+
{}
803+
721804
//! @deprecated use QgsExpressionContext variant instead
722805
Q_DECL_DEPRECATED virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override;
723806

‎src/gui/qgsexpressionbuilderwidget.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
477477
QString name = func->name();
478478
if ( name.startsWith( '_' ) ) // do not display private functions
479479
continue;
480-
if ( func->group() == "deprecated" ) // don't show deprecated functions
480+
if ( func->isDeprecated() ) // don't show deprecated functions
481481
continue;
482482
if ( func->isContextual() )
483483
{
@@ -489,14 +489,7 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
489489
name += '(';
490490
else if ( !name.startsWith( '$' ) )
491491
name += "()";
492-
registerItem( func->group(), func->name(), ' ' + name + ' ', func->helptext() );
493-
}
494-
495-
QList<QgsExpression::Function*> specials = QgsExpression::specialColumns();
496-
for ( int i = 0; i < specials.size(); ++i )
497-
{
498-
QString name = specials[i]->name();
499-
registerItem( specials[i]->group(), name, ' ' + name + ' ' );
492+
registerItemForAllGroups( func->groups(), func->name(), ' ' + name + ' ', func->helptext() );
500493
}
501494

502495
loadExpressionContext();
@@ -619,7 +612,15 @@ void QgsExpressionBuilderWidget::loadExpressionContext()
619612
continue;
620613
if ( func->params() != 0 )
621614
name += '(';
622-
registerItem( func->group(), func->name(), ' ' + name + ' ', func->helptext() );
615+
registerItemForAllGroups( func->groups(), func->name(), ' ' + name + ' ', func->helptext() );
616+
}
617+
}
618+
619+
void QgsExpressionBuilderWidget::registerItemForAllGroups( const QStringList& groups, const QString& label, const QString& expressionText, const QString& helpText, QgsExpressionItem::ItemType type, bool highlightedItem, int sortOrder )
620+
{
621+
Q_FOREACH ( const QString& group, groups )
622+
{
623+
registerItem( group, label, expressionText, helpText, type, highlightedItem, sortOrder );
623624
}
624625
}
625626

‎src/gui/qgsexpressionbuilderwidget.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,20 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
278278

279279
void loadExpressionContext();
280280

281+
/** Registers a node item for the expression builder, adding multiple items when the function exists in multiple groups
282+
* @param groups The groups the item will be show in the tree view. If a group doesn't exist it will be created.
283+
* @param label The label that is show to the user for the item in the tree.
284+
* @param expressionText The text that is inserted into the expression area when the user double clicks on the item.
285+
* @param helpText The help text that the user will see when item is selected.
286+
* @param type The type of the expression item.
287+
* @param highlightedItem set to true to make the item highlighted, which inserts a bold copy of the item at the top level
288+
* @param sortOrder sort ranking for item
289+
*/
290+
void registerItemForAllGroups( const QStringList& groups, const QString& label, const QString& expressionText,
291+
const QString& helpText = "",
292+
QgsExpressionItem::ItemType type = QgsExpressionItem::ExpressionNode,
293+
bool highlightedItem = false, int sortOrder = 1 );
294+
281295
bool mAutoSave;
282296
QString mFunctionsPath;
283297
QgsVectorLayer *mLayer;

0 commit comments

Comments
 (0)
Please sign in to comment.