Skip to content

Commit b9a69d0

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 ba99c7c commit b9a69d0

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
@@ -354,6 +354,19 @@ class QgsExpression
354354
bool handlesNull = false,
355355
bool isContextual = false );
356356

357+
/** Constructor for function which uses unnamed parameters and group list
358+
* @note added in QGIS 3.0
359+
*/
360+
Function( const QString& fnname,
361+
int params,
362+
const QStringList& groups,
363+
const QString& helpText = QString(),
364+
bool usesGeometry = false,
365+
const QStringList& referencedColumns = QStringList(),
366+
bool lazyEval = false,
367+
bool handlesNull = false,
368+
bool isContextual = false );
369+
357370
/** Constructor for function which uses named parameter list.
358371
* @note added in QGIS 2.16
359372
*/
@@ -367,6 +380,19 @@ class QgsExpression
367380
bool handlesNull = false,
368381
bool isContextual = false );
369382

383+
/** Constructor for function which uses named parameter list and group list.
384+
* @note added in QGIS 3.0
385+
*/
386+
Function( const QString& fnname,
387+
const QgsExpression::ParameterList& params,
388+
const QStringList& groups,
389+
const QString& helpText = QString(),
390+
bool usesGeometry = false,
391+
const QStringList& referencedColumns = QStringList(),
392+
bool lazyEval = false,
393+
bool handlesNull = false,
394+
bool isContextual = false );
395+
370396
virtual ~Function();
371397

372398
/** The name of the function. */
@@ -405,8 +431,23 @@ class QgsExpression
405431
*/
406432
bool isContextual() const;
407433

408-
/** The group the function belongs to. */
434+
/** Returns true if the function is deprecated and should not be presented as a valid option
435+
* to users in expression builders.
436+
* @note added in QGIS 3.0
437+
*/
438+
virtual bool isDeprecated() const;
439+
440+
/** Returns the first group which the function belongs to.
441+
* @note consider using groups() instead, as some functions naturally belong in multiple groups
442+
*/
409443
QString group() const;
444+
445+
/** Returns a list of the groups the function belongs to.
446+
* @note added in QGIS 3.0
447+
* @see group()
448+
*/
449+
QStringList groups() const;
450+
410451
/** The help text for the function. */
411452
const QString helptext() const;
412453

‎src/core/qgsexpression.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3221,7 +3221,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
32213221
<< new StaticFunction( "sqrt", ParameterList() << Parameter( "value" ), fcnSqrt, "Math" )
32223222
<< new StaticFunction( "radians", ParameterList() << Parameter( "degrees" ), fcnRadians, "Math" )
32233223
<< new StaticFunction( "degrees", ParameterList() << Parameter( "radians" ), fcnDegrees, "Math" )
3224-
<< new StaticFunction( "azimuth", ParameterList() << Parameter( "point_a" ) << Parameter( "point_b" ), fcnAzimuth, "Math" )
3224+
<< new StaticFunction( "azimuth", ParameterList() << Parameter( "point_a" ) << Parameter( "point_b" ), fcnAzimuth, QStringList() << "Math" << "GeometryGroup" )
32253225
<< new StaticFunction( "project", ParameterList() << Parameter( "point" ) << Parameter( "distance" ) << Parameter( "bearing" ), fcnProject, "GeometryGroup" )
32263226
<< new StaticFunction( "abs", ParameterList() << Parameter( "value" ), fcnAbs, "Math" )
32273227
<< new StaticFunction( "cos", ParameterList() << Parameter( "angle" ), fcnCos, "Math" )
@@ -3246,13 +3246,13 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
32463246
<< new StaticFunction( "floor", 1, fcnFloor, "Math" )
32473247
<< new StaticFunction( "ceil", 1, fcnCeil, "Math" )
32483248
<< new StaticFunction( "pi", 0, fcnPi, "Math", QString(), false, QStringList(), false, QStringList() << "$pi" )
3249-
<< new StaticFunction( "to_int", 1, fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
3250-
<< new StaticFunction( "to_real", 1, fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
3251-
<< new StaticFunction( "to_string", 1, fcnToString, "Conversions", QString(), false, QStringList(), false, QStringList() << "tostring" )
3252-
<< new StaticFunction( "to_datetime", 1, fcnToDateTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "todatetime" )
3253-
<< new StaticFunction( "to_date", 1, fcnToDate, "Conversions", QString(), false, QStringList(), false, QStringList() << "todate" )
3254-
<< new StaticFunction( "to_time", 1, fcnToTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "totime" )
3255-
<< new StaticFunction( "to_interval", 1, fcnToInterval, "Conversions", QString(), false, QStringList(), false, QStringList() << "tointerval" )
3249+
<< new StaticFunction( "to_int", ParameterList() << Parameter( "value" ), fcnToInt, "Conversions", QString(), false, QStringList(), false, QStringList() << "toint" )
3250+
<< new StaticFunction( "to_real", ParameterList() << Parameter( "value" ), fcnToReal, "Conversions", QString(), false, QStringList(), false, QStringList() << "toreal" )
3251+
<< new StaticFunction( "to_string", ParameterList() << Parameter( "value" ), fcnToString, QStringList() << "Conversions" << "String", QString(), false, QStringList(), false, QStringList() << "tostring" )
3252+
<< new StaticFunction( "to_datetime", ParameterList() << Parameter( "value" ), fcnToDateTime, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "todatetime" )
3253+
<< new StaticFunction( "to_date", ParameterList() << Parameter( "value" ), fcnToDate, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "todate" )
3254+
<< new StaticFunction( "to_time", ParameterList() << Parameter( "value" ), fcnToTime, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "totime" )
3255+
<< new StaticFunction( "to_interval", ParameterList() << Parameter( "value" ), fcnToInterval, QStringList() << "Conversions" << "Date and Time", QString(), false, QStringList(), false, QStringList() << "tointerval" )
32563256
<< new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals", QString(), false, QStringList(), false, QStringList(), true )
32573257
<< new StaticFunction( "if", 3, fcnIf, "Conditionals", QString(), False, QStringList(), true )
32583258
<< new StaticFunction( "aggregate", ParameterList() << Parameter( "layer" ) << Parameter( "aggregate" ) << Parameter( "expression" )
@@ -3279,7 +3279,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
32793279
<< new StaticFunction( "max_length", aggParams, fcnAggregateMaxLength, "Aggregates", QString(), False, QStringList(), true )
32803280
<< new StaticFunction( "concatenate", aggParams << Parameter( "concatenator", true ), fcnAggregateStringConcat, "Aggregates", QString(), False, QStringList(), true )
32813281

3282-
<< new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
3282+
<< new StaticFunction( "regexp_match", ParameterList() << Parameter( "string" ) << Parameter( "regex" ), fcnRegexpMatch, QStringList() << "Conditionals" << "String" )
32833283
<< new StaticFunction( "now", 0, fcnNow, "Date and Time", QString(), false, QStringList(), false, QStringList() << "$now" )
32843284
<< new StaticFunction( "age", 2, fcnAge, "Date and Time" )
32853285
<< new StaticFunction( "year", 1, fcnYear, "Date and Time" )
@@ -3300,7 +3300,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33003300
<< new StaticFunction( "soundex", 1, fcnSoundex, "Fuzzy Matching" )
33013301
<< new StaticFunction( "char", 1, fcnChar, "String" )
33023302
<< new StaticFunction( "wordwrap", ParameterList() << Parameter( "text" ) << Parameter( "length" ) << Parameter( "delimiter", true, " " ), fcnWordwrap, "String" )
3303-
<< new StaticFunction( "length", 1, fcnLength, "String" )
3303+
<< new StaticFunction( "length", ParameterList() << Parameter( "text", true, "" ), fcnLength, QStringList() << "String" << "GeometryGroup" )
33043304
<< new StaticFunction( "replace", 3, fcnReplace, "String" )
33053305
<< new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
33063306
<< new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
@@ -3313,7 +3313,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33133313
<< new StaticFunction( "lpad", 3, fcnLPad, "String" )
33143314
<< new StaticFunction( "format", -1, fcnFormatString, "String" )
33153315
<< new StaticFunction( "format_number", 2, fcnFormatNumber, "String" )
3316-
<< new StaticFunction( "format_date", 2, fcnFormatDate, "String" )
3316+
<< new StaticFunction( "format_date", ParameterList() << Parameter( "date" ) << Parameter( "format" ), fcnFormatDate, QStringList() << "String" << "Date and Time" )
33173317
<< new StaticFunction( "color_rgb", 3, fcnColorRgb, "Color" )
33183318
<< new StaticFunction( "color_rgba", 4, fncColorRgba, "Color" )
33193319
<< 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
@@ -497,7 +497,31 @@ class CORE_EXPORT QgsExpression
497497
: mName( fnname )
498498
, mParams( params )
499499
, mUsesGeometry( usesGeometry )
500-
, mGroup( group )
500+
, mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
501+
, mHelpText( helpText )
502+
, mReferencedColumns( referencedColumns )
503+
, mLazyEval( lazyEval )
504+
, mHandlesNull( handlesNull )
505+
, mIsContextual( isContextual )
506+
{
507+
}
508+
509+
/** Constructor for function which uses unnamed parameters and group list
510+
* @note added in QGIS 3.0
511+
*/
512+
Function( const QString& fnname,
513+
int params,
514+
const QStringList& groups,
515+
const QString& helpText = QString(),
516+
bool usesGeometry = false,
517+
const QStringList& referencedColumns = QStringList(),
518+
bool lazyEval = false,
519+
bool handlesNull = false,
520+
bool isContextual = false )
521+
: mName( fnname )
522+
, mParams( params )
523+
, mUsesGeometry( usesGeometry )
524+
, mGroups( groups )
501525
, mHelpText( helpText )
502526
, mReferencedColumns( referencedColumns )
503527
, mLazyEval( lazyEval )
@@ -522,14 +546,39 @@ class CORE_EXPORT QgsExpression
522546
, mParams( 0 )
523547
, mParameterList( params )
524548
, mUsesGeometry( usesGeometry )
525-
, mGroup( group )
549+
, mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
526550
, mHelpText( helpText )
527551
, mReferencedColumns( referencedColumns )
528552
, mLazyEval( lazyEval )
529553
, mHandlesNull( handlesNull )
530554
, mIsContextual( isContextual )
531555
{}
532556

557+
/** Constructor for function which uses named parameter list and group list.
558+
* @note added in QGIS 3.0
559+
*/
560+
Function( const QString& fnname,
561+
const ParameterList& params,
562+
const QStringList& groups,
563+
const QString& helpText = QString(),
564+
bool usesGeometry = false,
565+
const QStringList& referencedColumns = QStringList(),
566+
bool lazyEval = false,
567+
bool handlesNull = false,
568+
bool isContextual = false )
569+
: mName( fnname )
570+
, mParams( 0 )
571+
, mParameterList( params )
572+
, mUsesGeometry( usesGeometry )
573+
, mGroups( groups )
574+
, mHelpText( helpText )
575+
, mReferencedColumns( referencedColumns )
576+
, mLazyEval( lazyEval )
577+
, mHandlesNull( handlesNull )
578+
, mIsContextual( isContextual )
579+
{}
580+
581+
533582
virtual ~Function() {}
534583

535584
/** The name of the function. */
@@ -581,8 +630,23 @@ class CORE_EXPORT QgsExpression
581630
*/
582631
bool isContextual() const { return mIsContextual; }
583632

584-
/** The group the function belongs to. */
585-
QString group() const { return mGroup; }
633+
/** Returns true if the function is deprecated and should not be presented as a valid option
634+
* to users in expression builders.
635+
* @note added in QGIS 3.0
636+
*/
637+
virtual bool isDeprecated() const { return mGroups.isEmpty() ? false : mGroups.contains( "deprecated" ); }
638+
639+
/** Returns the first group which the function belongs to.
640+
* @note consider using groups() instead, as some functions naturally belong in multiple groups
641+
*/
642+
QString group() const { return mGroups.isEmpty() ? QString() : mGroups.at( 0 ); }
643+
644+
/** Returns a list of the groups the function belongs to.
645+
* @note added in QGIS 3.0
646+
* @see group()
647+
*/
648+
QStringList groups() const { return mGroups; }
649+
586650
/** The help text for the function. */
587651
//TODO QGIS 3.0 - rename to helpText()
588652
const QString helptext() const { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
@@ -615,7 +679,7 @@ class CORE_EXPORT QgsExpression
615679
int mParams;
616680
ParameterList mParameterList;
617681
bool mUsesGeometry;
618-
QString mGroup;
682+
QStringList mGroups;
619683
QString mHelpText;
620684
QStringList mReferencedColumns;
621685
bool mLazyEval;
@@ -685,6 +749,25 @@ class CORE_EXPORT QgsExpression
685749
, mAliases( aliases )
686750
{}
687751

752+
/** Static function for evaluation against a QgsExpressionContext, using a named list of parameter values and list
753+
* of groups.
754+
*/
755+
StaticFunction( const QString& fnname,
756+
const ParameterList& params,
757+
FcnEvalContext fcn,
758+
const QStringList& groups,
759+
const QString& helpText = QString(),
760+
bool usesGeometry = false,
761+
const QStringList& referencedColumns = QStringList(),
762+
bool lazyEval = false,
763+
const QStringList& aliases = QStringList(),
764+
bool handlesNull = false )
765+
: Function( fnname, params, groups, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
766+
, mFnc( nullptr )
767+
, mContextFnc( fcn )
768+
, mAliases( aliases )
769+
{}
770+
688771
//! @deprecated use QgsExpressionContext variant instead
689772
Q_DECL_DEPRECATED virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override;
690773

‎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.