mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-22 00:06:12 -05:00
Add expression functions for arrays and maps
This commit is contained in:
parent
cd1d44be9d
commit
f622c5bf2c
2
.gitignore
vendored
2
.gitignore
vendored
@ -51,6 +51,8 @@ scripts/astyle.exe
|
||||
scripts/Debug
|
||||
scripts/qgisstyle*
|
||||
scripts/RelWithDebInfo
|
||||
src/core/qgscontexthelp_texts.cpp
|
||||
src/core/qgsexpression_texts.cpp
|
||||
tests/testdata/cache/
|
||||
tests/testdata/checker360by180.asc.aux.xml
|
||||
tests/testdata/grass/wgs84/test/.gislock
|
||||
|
12
resources/function_help/json/array
Normal file
12
resources/function_help/json/array
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "array",
|
||||
"type": "function",
|
||||
"description": "Returns an array containing all the values passed as parameter.",
|
||||
"variableLenArguments": true,
|
||||
"arguments": [
|
||||
{"arg":"value1", "syntaxOnly": true},
|
||||
{"arg":"value2", "syntaxOnly": true},
|
||||
{"arg":"value", "descOnly": true, "description":"a value"}],
|
||||
"examples": [ { "expression":"array(2,10)", "returns":"array: 2, 10"}
|
||||
]
|
||||
}
|
8
resources/function_help/json/array_append
Normal file
8
resources/function_help/json/array_append
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_append",
|
||||
"type": "function",
|
||||
"description": "Returns an array with the given value added at the end.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"value","description":"the value to add"}],
|
||||
"examples": [ { "expression":"array_append(array(1,2,3),4)", "returns":"array: 1,2,3,4"}]
|
||||
}
|
12
resources/function_help/json/array_cat
Normal file
12
resources/function_help/json/array_cat
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "array_cat",
|
||||
"type": "function",
|
||||
"description": "Returns an array containing all the given arrays concatenated.",
|
||||
"variableLenArguments": true,
|
||||
"arguments": [
|
||||
{"arg":"array1", "syntaxOnly": true},
|
||||
{"arg":"array2", "syntaxOnly": true},
|
||||
{"arg":"array", "descOnly": true, "description":"an array"}],
|
||||
"examples": [ { "expression":"array_cat(array(1,2),array(2,3))", "returns":"array: 1,2,2,3"}
|
||||
]
|
||||
}
|
8
resources/function_help/json/array_contains
Normal file
8
resources/function_help/json/array_contains
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_contains",
|
||||
"type": "function",
|
||||
"description": "Returns true if an array contains the given value.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"value","description":"the value to search"}],
|
||||
"examples": [ { "expression":"array_contains(array(1,2,3),2)", "returns":"true"}]
|
||||
}
|
8
resources/function_help/json/array_find
Normal file
8
resources/function_help/json/array_find
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_find",
|
||||
"type": "function",
|
||||
"description": "Returns the index (0 for the first one) of a value within an array. Returns -1 if the value is not found.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"value","description":"the value to search"}],
|
||||
"examples": [ { "expression":"array_find(array(1,2,3),2)", "returns":"1"}]
|
||||
}
|
8
resources/function_help/json/array_get
Normal file
8
resources/function_help/json/array_get
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_get",
|
||||
"type": "function",
|
||||
"description": "Returns the Nth value (0 for the first one) of an array.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"index","description":"the index to get (0 based)"}],
|
||||
"examples": [ { "expression":"array_get(array('a','b','c'),1)", "returns":"'b'"}]
|
||||
}
|
9
resources/function_help/json/array_insert
Normal file
9
resources/function_help/json/array_insert
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "array_insert",
|
||||
"type": "function",
|
||||
"description": "Returns an array with the given value added at the given position.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"pos","description":"the position where to add (0 based"},
|
||||
{"arg":"value","description":"the value to add"}],
|
||||
"examples": [ { "expression":"array_insert(array(1,2,3),1,100)", "returns":"array: 1,100,2,3"}]
|
||||
}
|
8
resources/function_help/json/array_intersect
Normal file
8
resources/function_help/json/array_intersect
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_intersect",
|
||||
"type": "function",
|
||||
"description": "Returns true if any element of array1 exists in array2.",
|
||||
"arguments": [ {"arg":"array1","description":"an array"},
|
||||
{"arg":"array2","description":"an other array"}],
|
||||
"examples": [ { "expression":"array_intersect(array(1,2,3,4),array(4,0,2,5))", "returns":"true"}]
|
||||
}
|
7
resources/function_help/json/array_length
Normal file
7
resources/function_help/json/array_length
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "array_length",
|
||||
"type": "function",
|
||||
"description": "Returns the number of elements of an array.",
|
||||
"arguments": [ {"arg":"array","description":"an array"}],
|
||||
"examples": [ { "expression":"array_length(array(1,2,3))", "returns":"3"}]
|
||||
}
|
8
resources/function_help/json/array_prepend
Normal file
8
resources/function_help/json/array_prepend
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_prepend",
|
||||
"type": "function",
|
||||
"description": "Returns an array with the given value added at the begining.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"value","description":"the value to add"}],
|
||||
"examples": [ { "expression":"array_prepend(array(1,2,3),0)", "returns":"array: 0,1,2,3"}]
|
||||
}
|
8
resources/function_help/json/array_remove_all
Normal file
8
resources/function_help/json/array_remove_all
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_remove_all",
|
||||
"type": "function",
|
||||
"description": "Returns an array with all the entries of the given value removed.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"value","description":"the value to add"}],
|
||||
"examples": [ { "expression":"array_remove_all(array('a','b','c','b'),'b')", "returns":"array: 'a','c'"}]
|
||||
}
|
8
resources/function_help/json/array_remove_at
Normal file
8
resources/function_help/json/array_remove_at
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "array_remove_at",
|
||||
"type": "function",
|
||||
"description": "Returns an array with the given index removed.",
|
||||
"arguments": [ {"arg":"array","description":"an array"},
|
||||
{"arg":"pos","description":"the position to remove (0 based"}],
|
||||
"examples": [ { "expression":"array_remove_at(array(1,2,3),1)", "returns":"array: 1,3"}]
|
||||
}
|
15
resources/function_help/json/map
Normal file
15
resources/function_help/json/map
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "map",
|
||||
"type": "function",
|
||||
"description": "Returns a map containing all the keys and values passed as pair of parameters.",
|
||||
"variableLenArguments": true,
|
||||
"arguments": [
|
||||
{"arg":"key1", "syntaxOnly": true},
|
||||
{"arg":"value1", "syntaxOnly": true},
|
||||
{"arg":"key2", "syntaxOnly": true},
|
||||
{"arg":"value2", "syntaxOnly": true},
|
||||
{"arg":"key", "descOnly": true, "description":"a key (string)"},
|
||||
{"arg":"value", "descOnly": true, "description":"a value"}],
|
||||
"examples": [ { "expression":"map('1','one','2', 'two')", "returns":"map: 1: 'one', 2: 'two'"}
|
||||
]
|
||||
}
|
7
resources/function_help/json/map_akeys
Normal file
7
resources/function_help/json/map_akeys
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "map_akeys",
|
||||
"type": "function",
|
||||
"description": "Returns all the keys of a map as an array.",
|
||||
"arguments": [ {"arg":"map","description":"a map"}],
|
||||
"examples": [ { "expression":"map_akeys(map('1','one','2','two'))", "returns":"array: '1', '2'"}]
|
||||
}
|
7
resources/function_help/json/map_avals
Normal file
7
resources/function_help/json/map_avals
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "map_avals",
|
||||
"type": "function",
|
||||
"description": "Returns all the values of a map as an array.",
|
||||
"arguments": [ {"arg":"map","description":"a map"}],
|
||||
"examples": [ { "expression":"map_avals(map('1','one','2','two'))", "returns":"array: 'one', 'two'"}]
|
||||
}
|
12
resources/function_help/json/map_concat
Normal file
12
resources/function_help/json/map_concat
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "map_concat",
|
||||
"type": "function",
|
||||
"description": "Returns a map containing all the entries of the given map. If two maps contain the same key, the value of the second map is taken.",
|
||||
"variableLenArguments": true,
|
||||
"arguments": [
|
||||
{"arg":"map1", "syntaxOnly": true},
|
||||
{"arg":"map2", "syntaxOnly": true},
|
||||
{"arg":"map", "descOnly": true, "description":"a map"}],
|
||||
"examples": [ { "expression":"map_concat(map('1','one', '2','overriden'),map('2','two', '3','three'))", "returns":"map: 1: 'one, 2: 'two', 3: 'three'"}
|
||||
]
|
||||
}
|
8
resources/function_help/json/map_delete
Normal file
8
resources/function_help/json/map_delete
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "map_delete",
|
||||
"type": "function",
|
||||
"description": "Returns a map with the given key and its corresponding value deleted.",
|
||||
"arguments": [ {"arg":"map","description":"a map"},
|
||||
{"arg":"key","description":"the key to delete"}],
|
||||
"examples": [ { "expression":"map_delete(map('1','one','2','two'),'2')", "returns":"map: 1: 'one'"}]
|
||||
}
|
8
resources/function_help/json/map_exist
Normal file
8
resources/function_help/json/map_exist
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "map_exist",
|
||||
"type": "function",
|
||||
"description": "Returns true if the given key exists in the map.",
|
||||
"arguments": [ {"arg":"map","description":"a map"},
|
||||
{"arg":"key","description":"the key to lookup"}],
|
||||
"examples": [ { "expression":"map_exist(map('1','one','2','two'),'3')", "returns":"false"}]
|
||||
}
|
8
resources/function_help/json/map_get
Normal file
8
resources/function_help/json/map_get
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "map_get",
|
||||
"type": "function",
|
||||
"description": "Returns the value of a map, given it's key.",
|
||||
"arguments": [ {"arg":"map","description":"a map"},
|
||||
{"arg":"key","description":"the key to lookup"}],
|
||||
"examples": [ { "expression":"map_get(map('1','one','2','two'),'2')", "returns":"'two'"}]
|
||||
}
|
9
resources/function_help/json/map_insert
Normal file
9
resources/function_help/json/map_insert
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "map_insert",
|
||||
"type": "function",
|
||||
"description": "Returns a map with an added key/value.",
|
||||
"arguments": [ {"arg":"map","description":"a map"},
|
||||
{"arg":"key","description":"the key to add"},
|
||||
{"arg":"value","description":"the value to add"}],
|
||||
"examples": [ { "expression":"map_insert(map('1','one'),'3','three')", "returns":"map: 1: 'one', 3: 'three'"}]
|
||||
}
|
@ -365,6 +365,32 @@ static TVL getTVLValue( const QVariant& value, QgsExpression* parent )
|
||||
return !qgsDoubleNear( x, 0.0 ) ? True : False;
|
||||
}
|
||||
|
||||
static QVariantList getListValue( const QVariant& value, QgsExpression* parent )
|
||||
{
|
||||
if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
|
||||
{
|
||||
return value.toList();
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to array" ).arg( value.toString() ) );
|
||||
return QVariantList();
|
||||
}
|
||||
}
|
||||
|
||||
static QVariantMap getMapValue( const QVariant& value, QgsExpression* parent )
|
||||
{
|
||||
if ( value.type() == QVariant::Map )
|
||||
{
|
||||
return value.toMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to map" ).arg( value.toString() ) );
|
||||
return QVariantMap();
|
||||
}
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
static QVariant fcnGetVariable( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent )
|
||||
@ -3156,6 +3182,150 @@ static QVariant fcnGetLayerProperty( const QVariantList& values, const QgsExpres
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
static QVariant fcnArray( const QVariantList& values, const QgsExpressionContext*, QgsExpression* )
|
||||
{
|
||||
return values;
|
||||
}
|
||||
|
||||
static QVariant fcnArrayLength( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return getListValue( values.at( 0 ), parent ).length();
|
||||
}
|
||||
|
||||
static QVariant fcnArrayContains( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return QVariant( getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayFind( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayGet( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
const QVariantList list = getListValue( values.at( 0 ), parent );
|
||||
const int pos = getIntValue( values.at( 1 ), parent );
|
||||
if ( pos < 0 || pos >= list.length() ) return QVariant();
|
||||
return list.at( pos );
|
||||
}
|
||||
|
||||
static QVariant convertToSameType( const QVariant& value, QVariant::Type type )
|
||||
{
|
||||
QVariant result = value;
|
||||
result.convert( type );
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnArrayAppend( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantList list = getListValue( values.at( 0 ), parent );
|
||||
list.append( values.at( 1 ) );
|
||||
return convertToSameType( list , values.at( 0 ).type() );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayPrepend( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantList list = getListValue( values.at( 0 ), parent );
|
||||
list.prepend( values.at( 1 ) );
|
||||
return convertToSameType( list , values.at( 0 ).type() );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayInsert( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantList list = getListValue( values.at( 0 ), parent );
|
||||
list.insert( getIntValue( values.at( 1 ), parent ), values.at( 2 ) );
|
||||
return convertToSameType( list , values.at( 0 ).type() );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayRemoveAt( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantList list = getListValue( values.at( 0 ), parent );
|
||||
list.removeAt( getIntValue( values.at( 1 ), parent ) );
|
||||
return convertToSameType( list , values.at( 0 ).type() );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayRemoveAll( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantList list = getListValue( values.at( 0 ), parent );
|
||||
list.removeAll( values.at( 1 ) );
|
||||
return convertToSameType( list , values.at( 0 ).type() );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayCat( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantList list;
|
||||
Q_FOREACH ( QVariant cur, values )
|
||||
{
|
||||
list += getListValue( cur, parent );
|
||||
}
|
||||
return convertToSameType( list , values.at( 0 ).type() );
|
||||
}
|
||||
|
||||
static QVariant fcnArrayIntersect( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
const QVariantList array1 = getListValue( values.at( 0 ), parent );
|
||||
Q_FOREACH ( QVariant cur, getListValue( values.at( 1 ), parent ) ) if ( array1.contains( cur ) ) return QVariant( true );
|
||||
return QVariant( false );
|
||||
}
|
||||
|
||||
static QVariant fcnMap( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantMap result;
|
||||
for ( int i = 0; i + 1 < values.length(); i += 2 )
|
||||
{
|
||||
result.insert( getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnMapGet( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
|
||||
}
|
||||
|
||||
static QVariant fcnMapExist( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
|
||||
}
|
||||
|
||||
static QVariant fcnMapDelete( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantMap map = getMapValue( values.at( 0 ), parent );
|
||||
map.remove( values.at( 1 ).toString() );
|
||||
return map;
|
||||
}
|
||||
|
||||
static QVariant fcnMapInsert( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantMap map = getMapValue( values.at( 0 ), parent );
|
||||
map.insert( values.at( 1 ).toString(), values.at( 2 ) );
|
||||
return map;
|
||||
}
|
||||
|
||||
static QVariant fcnMapConcat( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
QVariantMap result;
|
||||
Q_FOREACH ( QVariant cur, values )
|
||||
{
|
||||
const QVariantMap curMap = getMapValue( cur, parent );
|
||||
for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
|
||||
result.insert( it.key(), it.value() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnMapAKeys( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return QStringList( getMapValue( values.at( 0 ), parent ).keys() );
|
||||
}
|
||||
|
||||
static QVariant fcnMapAVals( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
return getMapValue( values.at( 0 ), parent ).values();
|
||||
}
|
||||
|
||||
|
||||
bool QgsExpression::registerFunction( QgsExpression::Function* function, bool transferOwnership )
|
||||
{
|
||||
int fnIdx = functionIndex( function->name() );
|
||||
@ -3491,6 +3661,30 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
||||
// feature request
|
||||
<< new StaticFunction( "eval", 1, fcnEval, "General", QString(), true, QStringList( QgsFeatureRequest::AllAttributes ) )
|
||||
<< new StaticFunction( "attribute", 2, fcnAttribute, "Record", QString(), false, QStringList( QgsFeatureRequest::AllAttributes ) )
|
||||
|
||||
// functions for arrays
|
||||
<< new StaticFunction( "array", -1, fcnArray, "Arrays" )
|
||||
<< new StaticFunction( "array_length", 1, fcnArrayLength, "Arrays" )
|
||||
<< new StaticFunction( "array_contains", ParameterList() << Parameter( "array" ) << Parameter( "value" ), fcnArrayContains, "Arrays" )
|
||||
<< new StaticFunction( "array_find", ParameterList() << Parameter( "array" ) << Parameter( "value" ), fcnArrayFind, "Arrays" )
|
||||
<< new StaticFunction( "array_get", ParameterList() << Parameter( "array" ) << Parameter( "pos" ), fcnArrayGet, "Arrays" )
|
||||
<< new StaticFunction( "array_append", ParameterList() << Parameter( "array" ) << Parameter( "value" ), fcnArrayAppend, "Arrays" )
|
||||
<< new StaticFunction( "array_prepend", ParameterList() << Parameter( "array" ) << Parameter( "value" ), fcnArrayPrepend, "Arrays" )
|
||||
<< new StaticFunction( "array_insert", ParameterList() << Parameter( "array" ) << Parameter( "pos" ) << Parameter( "value" ), fcnArrayInsert, "Arrays" )
|
||||
<< new StaticFunction( "array_remove_at", ParameterList() << Parameter( "array" ) << Parameter( "pos" ), fcnArrayRemoveAt, "Arrays" )
|
||||
<< new StaticFunction( "array_remove_all", ParameterList() << Parameter( "array" ) << Parameter( "value" ), fcnArrayRemoveAll, "Arrays" )
|
||||
<< new StaticFunction( "array_cat", -1, fcnArrayCat, "Arrays" )
|
||||
<< new StaticFunction( "array_intersect", ParameterList() << Parameter( "array1" ) << Parameter( "array2" ), fcnArrayIntersect, "Arrays" )
|
||||
|
||||
//functions for maps
|
||||
<< new StaticFunction( "map", -1, fcnMap, "Maps" )
|
||||
<< new StaticFunction( "map_get", ParameterList() << Parameter( "map" ) << Parameter( "key" ), fcnMapGet, "Maps" )
|
||||
<< new StaticFunction( "map_exist", ParameterList() << Parameter( "map" ) << Parameter( "key" ), fcnMapExist, "Maps" )
|
||||
<< new StaticFunction( "map_delete", ParameterList() << Parameter( "map" ) << Parameter( "key" ), fcnMapDelete, "Maps" )
|
||||
<< new StaticFunction( "map_insert", ParameterList() << Parameter( "map" ) << Parameter( "key" ) << Parameter( "value" ), fcnMapInsert, "Maps" )
|
||||
<< new StaticFunction( "map_concat", -1, fcnMapConcat, "Maps" )
|
||||
<< new StaticFunction( "map_akeys", ParameterList() << Parameter( "map" ), fcnMapAKeys, "Maps" )
|
||||
<< new StaticFunction( "map_avals", ParameterList() << Parameter( "map" ), fcnMapAVals, "Maps" )
|
||||
;
|
||||
|
||||
QgsExpressionContextUtils::registerContextFunctions();
|
||||
@ -5088,7 +5282,7 @@ QString QgsExpression::formatPreviewString( const QVariant& value )
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tr( "<i><list: %1></i>" ).arg( listStr );
|
||||
return tr( "<i><array: %1></i>" ).arg( listStr );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -92,5 +92,5 @@ Qt::AlignmentFlag QgsKeyValueWidgetFactory::alignmentFlag( QgsVectorLayer *vl, i
|
||||
unsigned int QgsKeyValueWidgetFactory::fieldScore( const QgsVectorLayer* vl, int fieldIdx ) const
|
||||
{
|
||||
const QgsField field = vl->fields().field( fieldIdx );
|
||||
return field.type() == QVariant::Map ? 20 : 0;
|
||||
return field.type() == QVariant::Map && field.subType() != QVariant::Invalid ? 20 : 0;
|
||||
}
|
@ -2148,6 +2148,189 @@ class TestQgsExpression: public QObject
|
||||
QCOMPARE( v4, QVariant( "test value" ) );
|
||||
}
|
||||
|
||||
void eval_string_array()
|
||||
{
|
||||
QgsFeature f( 100 );
|
||||
QgsFields fields;
|
||||
fields.append( QgsField( "col1" ) );
|
||||
fields.append( QgsField( "strings", QVariant::StringList, "string[]", 0, 0, QString(), QVariant::String ) );
|
||||
f.setFields( fields, true );
|
||||
f.setAttribute( "col1", QString( "test value" ) );
|
||||
QStringList array;
|
||||
array << "one" << "two";
|
||||
f.setAttribute( "strings", array );
|
||||
|
||||
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
|
||||
|
||||
QVariantList builderExpected;
|
||||
QCOMPARE( QgsExpression( "array()" ).evaluate( &context ), QVariant( ) );
|
||||
builderExpected << "hello";
|
||||
QCOMPARE( QgsExpression( "array('hello')" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
builderExpected << "world";
|
||||
QCOMPARE( QgsExpression( "array('hello', 'world')" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_length(\"strings\")" ).evaluate( &context ), QVariant( 2 ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_contains(\"strings\", 'two')" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "array_contains(\"strings\", 'three')" ).evaluate( &context ), QVariant( false ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_find(\"strings\", 'two')" ).evaluate( &context ), QVariant( 1 ) );
|
||||
QCOMPARE( QgsExpression( "array_find(\"strings\", 'three')" ).evaluate( &context ), QVariant( -1 ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_get(\"strings\", 1)" ).evaluate( &context ), QVariant( "two" ) );
|
||||
QCOMPARE( QgsExpression( "array_get(\"strings\", 2)" ).evaluate( &context ), QVariant() );
|
||||
QCOMPARE( QgsExpression( "array_get(\"strings\", -1)" ).evaluate( &context ), QVariant() );
|
||||
|
||||
QStringList appendExpected = array;
|
||||
appendExpected << "three";
|
||||
QCOMPARE( QgsExpression( "array_append(\"strings\", 'three')" ).evaluate( &context ), QVariant( appendExpected ) );
|
||||
|
||||
QStringList prependExpected = array;
|
||||
prependExpected.prepend( "zero" );
|
||||
QCOMPARE( QgsExpression( "array_prepend(\"strings\", 'zero')" ).evaluate( &context ), QVariant( prependExpected ) );
|
||||
|
||||
QStringList insertExpected = array;
|
||||
insertExpected.insert( 1, "one and a half" );
|
||||
QCOMPARE( QgsExpression( "array_insert(\"strings\", 1, 'one and a half')" ).evaluate( &context ), QVariant( insertExpected ) );
|
||||
|
||||
QStringList removeAtExpected = array;
|
||||
removeAtExpected.removeAt( 0 );
|
||||
QCOMPARE( QgsExpression( "array_remove_at(\"strings\", 0)" ).evaluate( &context ), QVariant( removeAtExpected ) );
|
||||
|
||||
QStringList removeAllExpected;
|
||||
removeAllExpected << "a" << "b" << "d";
|
||||
QCOMPARE( QgsExpression( "array_remove_all(array('a', 'b', 'c', 'd', 'c'), 'c')" ).evaluate( &context ), QVariant( removeAllExpected ) );
|
||||
|
||||
QStringList concatExpected = array;
|
||||
concatExpected << "a" << "b" << "c";
|
||||
QCOMPARE( QgsExpression( "array_cat(\"strings\", array('a', 'b'), array('c'))" ).evaluate( &context ), QVariant( concatExpected ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_intersect(array('1', '2', '3', '4'), array('4', '0', '2', '5'))" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "array_intersect(array('1', '2', '3', '4'), array('0', '5'))" ).evaluate( &context ), QVariant( false ) );
|
||||
}
|
||||
|
||||
void eval_int_array()
|
||||
{
|
||||
QgsFeature f( 100 );
|
||||
QgsFields fields;
|
||||
fields.append( QgsField( "col1" ) );
|
||||
fields.append( QgsField( "ints", QVariant::List, "int[]", 0, 0, QString(), QVariant::Int ) );
|
||||
f.setFields( fields, true );
|
||||
f.setAttribute( "col1", QString( "test value" ) );
|
||||
QVariantList array;
|
||||
array << 1 << -2;
|
||||
f.setAttribute( "ints", array );
|
||||
|
||||
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
|
||||
|
||||
QVariantList builderExpected;
|
||||
builderExpected << 1;
|
||||
QCOMPARE( QgsExpression( "array(1)" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
builderExpected << 2;
|
||||
QCOMPARE( QgsExpression( "array(1, 2)" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_contains(\"ints\", 1)" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "array_contains(\"ints\", 2)" ).evaluate( &context ), QVariant( false ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_find(\"ints\", -2)" ).evaluate( &context ), QVariant( 1 ) );
|
||||
QCOMPARE( QgsExpression( "array_find(\"ints\", 3)" ).evaluate( &context ), QVariant( -1 ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_get(\"ints\", 1)" ).evaluate( &context ), QVariant( -2 ) );
|
||||
QCOMPARE( QgsExpression( "array_get(\"ints\", 2)" ).evaluate( &context ), QVariant() );
|
||||
QCOMPARE( QgsExpression( "array_get(\"ints\", -1)" ).evaluate( &context ), QVariant() );
|
||||
|
||||
QVariantList appendExpected = array;
|
||||
appendExpected << 3;
|
||||
QCOMPARE( QgsExpression( "array_append(\"ints\", 3)" ).evaluate( &context ), QVariant( appendExpected ) );
|
||||
|
||||
QVariantList prependExpected = array;
|
||||
prependExpected.prepend( 0 );
|
||||
QCOMPARE( QgsExpression( "array_prepend(\"ints\", 0)" ).evaluate( &context ), QVariant( prependExpected ) );
|
||||
|
||||
QVariantList insertExpected = array;
|
||||
insertExpected.insert( 1, 2 );
|
||||
QCOMPARE( QgsExpression( "array_insert(\"ints\", 1, 2)" ).evaluate( &context ), QVariant( insertExpected ) );
|
||||
|
||||
QVariantList removeAtExpected = array;
|
||||
removeAtExpected.removeAt( 0 );
|
||||
QCOMPARE( QgsExpression( "array_remove_at(\"ints\", 0)" ).evaluate( &context ), QVariant( removeAtExpected ) );
|
||||
|
||||
QVariantList removeAllExpected;
|
||||
removeAllExpected << 1 << 2 << 4;
|
||||
QCOMPARE( QgsExpression( "array_remove_all(array(1, 2, 3, 4, 3), 3)" ).evaluate( &context ), QVariant( removeAllExpected ) );
|
||||
QCOMPARE( QgsExpression( "array_remove_all(array(1, 2, 3, 4, 3), '3')" ).evaluate( &context ), QVariant( removeAllExpected ) );
|
||||
|
||||
QVariantList concatExpected = array;
|
||||
concatExpected << 56 << 57;
|
||||
QCOMPARE( QgsExpression( "array_cat(\"ints\", array(56, 57))" ).evaluate( &context ), QVariant( concatExpected ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "array_intersect(array(1, 2, 3, 4), array(4, 0, 2, 5))" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "array_intersect(array(1, 2, 3, 4), array(0, 5))" ).evaluate( &context ), QVariant( false ) );
|
||||
|
||||
QgsExpression badArray( "array_get('not an array', 0)" );
|
||||
QCOMPARE( badArray.evaluate( &context ), QVariant() );
|
||||
QVERIFY( badArray.hasEvalError() );
|
||||
QCOMPARE( badArray.evalErrorString(), QString( "Cannot convert 'not an array' to array" ) );
|
||||
}
|
||||
|
||||
void eval_map()
|
||||
{
|
||||
QgsFeature f( 100 );
|
||||
QgsFields fields;
|
||||
fields.append( QgsField( "col1" ) );
|
||||
fields.append( QgsField( "map", QVariant::Map, "map", 0, 0, QString(), QVariant::String ) );
|
||||
f.setFields( fields, true );
|
||||
f.setAttribute( "col1", QString( "test value" ) );
|
||||
QVariantMap map;
|
||||
map["1"] = "one";
|
||||
map["2"] = "two";
|
||||
f.setAttribute( "map", map );
|
||||
|
||||
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
|
||||
|
||||
QVariantMap builderExpected;
|
||||
QCOMPARE( QgsExpression( "map()" ).evaluate( &context ), QVariant( ) );
|
||||
builderExpected["1"] = "hello";
|
||||
QCOMPARE( QgsExpression( "map('1', 'hello')" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
builderExpected["2"] = "world";
|
||||
QCOMPARE( QgsExpression( "map('1', 'hello', '2', 'world')" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
QCOMPARE( QgsExpression( "map('1', 'hello', '2', 'world', 'ignoredOddParam')" ).evaluate( &context ), QVariant( builderExpected ) );
|
||||
|
||||
QCOMPARE( QgsExpression( "map_get(\"map\", '2')" ).evaluate( &context ), QVariant( "two" ) );
|
||||
QCOMPARE( QgsExpression( "map_get(\"map\", '3')" ).evaluate( &context ), QVariant() );
|
||||
|
||||
QCOMPARE( QgsExpression( "map_exist(\"map\", '2')" ).evaluate( &context ), QVariant( true ) );
|
||||
QCOMPARE( QgsExpression( "map_exist(\"map\", '3')" ).evaluate( &context ), QVariant( false ) );
|
||||
|
||||
QVariantMap deleteExpected = map;
|
||||
deleteExpected.remove( "1" );
|
||||
QCOMPARE( QgsExpression( "map_delete(\"map\", '1')" ).evaluate( &context ), QVariant( deleteExpected ) );
|
||||
QCOMPARE( QgsExpression( "map_delete(\"map\", '3')" ).evaluate( &context ), QVariant( map ) );
|
||||
|
||||
QVariantMap insertExpected = map;
|
||||
insertExpected.insert( "3", "three" );
|
||||
QCOMPARE( QgsExpression( "map_insert(\"map\", '3', 'three')" ).evaluate( &context ), QVariant( insertExpected ) );
|
||||
|
||||
QVariantMap concatExpected;
|
||||
concatExpected["1"] = "one";
|
||||
concatExpected["2"] = "two";
|
||||
concatExpected["3"] = "three";
|
||||
QCOMPARE( QgsExpression( "map_concat(map('1', 'one', '2', 'overriden by next map'), map('2', 'two', '3', 'three'))" ).evaluate( &context ), QVariant( concatExpected ) );
|
||||
|
||||
QStringList keysExpected;
|
||||
keysExpected << "1" << "2";
|
||||
QCOMPARE( QgsExpression( "map_akeys(\"map\")" ).evaluate( &context ), QVariant( keysExpected ) );
|
||||
|
||||
QVariantList valuesExpected;
|
||||
valuesExpected << "one" << "two";
|
||||
QCOMPARE( QgsExpression( "map_avals(\"map\")" ).evaluate( &context ), QVariant( valuesExpected ) );
|
||||
|
||||
QgsExpression badMap( "map_get('not a map', '0')" );
|
||||
QCOMPARE( badMap.evaluate( &context ), QVariant() );
|
||||
QVERIFY( badMap.hasEvalError() );
|
||||
QCOMPARE( badMap.evalErrorString(), QString( "Cannot convert 'not a map' to map" ) );
|
||||
}
|
||||
|
||||
void expression_from_expression_data()
|
||||
{
|
||||
QTest::addColumn<QString>( "string" );
|
||||
@ -2346,12 +2529,12 @@ class TestQgsExpression: public QObject
|
||||
|
||||
QVariantList list;
|
||||
list << 1 << 2 << 3;
|
||||
QCOMPARE( QgsExpression::formatPreviewString( QVariant( list ) ), QString( "<i><list: 1, 2, 3></i>" ) );
|
||||
QCOMPARE( QgsExpression::formatPreviewString( QVariant( list ) ), QString( "<i><array: 1, 2, 3></i>" ) );
|
||||
|
||||
QStringList stringList;
|
||||
stringList << "One" << "Two" << "A very long string that is going to be truncated";
|
||||
QCOMPARE( QgsExpression::formatPreviewString( QVariant( stringList ) ),
|
||||
QString( "<i><list: 'One', 'Two', 'A very long string that is going to be trunca...></i>" ) );
|
||||
QString( "<i><array: 'One', 'Two', 'A very long string that is going to be trunca...></i>" ) );
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user