Merge pull request #7692 from m-kuhn/arrayRep

Adjust representation of arrays and maps in expressions
This commit is contained in:
Matthias Kuhn 2018-08-24 15:51:14 +02:00 committed by GitHub
commit 31fadd1c00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 72 additions and 57 deletions

View File

@ -7,6 +7,6 @@
{"arg":"value1", "syntaxOnly": true}, {"arg":"value1", "syntaxOnly": true},
{"arg":"value2", "syntaxOnly": true}, {"arg":"value2", "syntaxOnly": true},
{"arg":"value", "descOnly": true, "description":"a value"}], {"arg":"value", "descOnly": true, "description":"a value"}],
"examples": [ { "expression":"array(2,10)", "returns":"array: 2, 10"} "examples": [ { "expression":"array(2,10)", "returns":"[ 2, 10 ]"}
] ]
} }

View File

@ -4,5 +4,5 @@
"description": "Returns an array with the given value added at the end.", "description": "Returns an array with the given value added at the end.",
"arguments": [ {"arg":"array","description":"an array"}, "arguments": [ {"arg":"array","description":"an array"},
{"arg":"value","description":"the value to add"}], {"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"array_append(array(1,2,3),4)", "returns":"array: 1,2,3,4"}] "examples": [ { "expression":"array_append(array(1,2,3),4)", "returns":"[ 1, 2, 3, 4 ]"}]
} }

View File

@ -7,6 +7,6 @@
{"arg":"array1", "syntaxOnly": true}, {"arg":"array1", "syntaxOnly": true},
{"arg":"array2", "syntaxOnly": true}, {"arg":"array2", "syntaxOnly": true},
{"arg":"array", "descOnly": true, "description":"an array"}], {"arg":"array", "descOnly": true, "description":"an array"}],
"examples": [ { "expression":"array_cat(array(1,2),array(2,3))", "returns":"array: 1,2,2,3"} "examples": [ { "expression":"array_cat(array(1,2),array(2,3))", "returns":"[ 1, 2, 2, 3 ]"}
] ]
} }

View File

@ -4,6 +4,6 @@
"description": "Returns an array containing distinct values of the given array.", "description": "Returns an array containing distinct values of the given array.",
"arguments": [ "arguments": [
{"arg":"array","description":"an array"}], {"arg":"array","description":"an array"}],
"examples": [ { "expression":"array_distinct(array(1,2,3,2,1))", "returns":"array: 1,2,3"} "examples": [ { "expression":"array_distinct(array(1,2,3,2,1))", "returns":"[ 1, 2, 3 ]"}
] ]
} }

View File

@ -7,7 +7,7 @@
{"arg":"expression","description":"an expression to evaluate on each item. The variable `@element` will be replaced by the current value."} {"arg":"expression","description":"an expression to evaluate on each item. The variable `@element` will be replaced by the current value."}
], ],
"examples": [ "examples": [
{ "expression": "array_foreach(array('a','b','c'),upper(@element))", "returns":"array: 'A', 'B', 'C'"}, { "expression": "array_foreach(array('a','b','c'),upper(@element))", "returns":"[ 'A', 'B', 'C' ]"},
{ "expression": "array_foreach(array(1,2,3),@element + 10)", "returns":"array: 11, 12, 13"} { "expression": "array_foreach(array(1,2,3),@element + 10)", "returns":"[ 11, 12, 13 ]"}
] ]
} }

View File

@ -5,5 +5,5 @@
"arguments": [ {"arg":"array","description":"an array"}, "arguments": [ {"arg":"array","description":"an array"},
{"arg":"pos","description":"the position where to add (0 based)"}, {"arg":"pos","description":"the position where to add (0 based)"},
{"arg":"value","description":"the value to add"}], {"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"array_insert(array(1,2,3),1,100)", "returns":"array: 1,100,2,3"}] "examples": [ { "expression":"array_insert(array(1,2,3),1,100)", "returns":"[ 1, 100, 2, 3 ]"}]
} }

View File

@ -4,5 +4,5 @@
"description": "Returns an array with the given value added at the beginning.", "description": "Returns an array with the given value added at the beginning.",
"arguments": [ {"arg":"array","description":"an array"}, "arguments": [ {"arg":"array","description":"an array"},
{"arg":"value","description":"the value to add"}], {"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"array_prepend(array(1,2,3),0)", "returns":"array: 0,1,2,3"}] "examples": [ { "expression":"array_prepend(array(1,2,3),0)", "returns":"[ 0, 1, 2, 3 ]"}]
} }

View File

@ -4,5 +4,5 @@
"description": "Returns an array with all the entries of the given value removed.", "description": "Returns an array with all the entries of the given value removed.",
"arguments": [ {"arg":"array","description":"an array"}, "arguments": [ {"arg":"array","description":"an array"},
{"arg":"value","description":"the values to remove"}], {"arg":"value","description":"the values to remove"}],
"examples": [ { "expression":"array_remove_all(array('a','b','c','b'),'b')", "returns":"array: 'a','c'"}] "examples": [ { "expression":"array_remove_all(array('a','b','c','b'),'b')", "returns":"[ 'a', 'c' ]"}]
} }

View File

@ -4,5 +4,5 @@
"description": "Returns an array with the given index removed.", "description": "Returns an array with the given index removed.",
"arguments": [ {"arg":"array","description":"an array"}, "arguments": [ {"arg":"array","description":"an array"},
{"arg":"pos","description":"the position to remove (0 based)"}], {"arg":"pos","description":"the position to remove (0 based)"}],
"examples": [ { "expression":"array_remove_at(array(1,2,3),1)", "returns":"array: 1,3"}] "examples": [ { "expression":"array_remove_at(array(1,2,3),1)", "returns":"[ 1, 3 ]"}]
} }

View File

@ -3,5 +3,5 @@
"type": "function", "type": "function",
"description": "Returns the given array with array values in reversed order.", "description": "Returns the given array with array values in reversed order.",
"arguments": [ {"arg":"array","description":"an array"} ], "arguments": [ {"arg":"array","description":"an array"} ],
"examples": [ { "expression":"array_reverse(array(2,4,0,10))", "returns":"array: 10,0,4,2"}] "examples": [ { "expression":"array_reverse(array(2,4,0,10))", "returns":"[ 10, 0, 4, 2 ]"}]
} }

View File

@ -17,35 +17,35 @@
], ],
"examples": [{ "examples": [{
"expression": "array_slice(array(1,2,3,4,5),0,3)", "expression": "array_slice(array(1,2,3,4,5),0,3)",
"returns": "array: 1,2,3,4" "returns": "[ 1, 2, 3, 4 ]"
}, },
{ {
"expression": "array_slice(array(1,2,3,4,5),0,-1)", "expression": "array_slice(array(1,2,3,4,5),0,-1)",
"returns": "array: 1,2,3,4,5" "returns": "[ 1, 2, 3, 4, 5 ]"
}, },
{ {
"expression": "array_slice(array(1,2,3,4,5),-5,-1)", "expression": "array_slice(array(1,2,3,4,5),-5,-1)",
"returns": "array: 1,2,3,4,5" "returns": "[ 1, 2, 3, 4, 5 ]"
}, },
{ {
"expression": "array_slice(array(1,2,3,4,5),0,0)", "expression": "array_slice(array(1,2,3,4,5),0,0)",
"returns": "array: 1" "returns": "[ 1 ]"
}, },
{ {
"expression": "array_slice(array(1,2,3,4,5),-2,-1)", "expression": "array_slice(array(1,2,3,4,5),-2,-1)",
"returns": "array: 4,5" "returns": "[ 4, 5 ]"
}, },
{ {
"expression": "array_slice(array(1,2,3,4,5),-1,-1)", "expression": "array_slice(array(1,2,3,4,5),-1,-1)",
"returns": "array: 5" "returns": "[ 5 ]"
}, },
{ {
"expression": "array_slice(array('Dufour','Valmiera','Chugiak','Brighton'),1,2)", "expression": "array_slice(array('Dufour','Valmiera','Chugiak','Brighton'),1,2)",
"returns": "array: 'Valmiera','Chugiak'" "returns": "[ 'Valmiera', 'Chugiak' ]"
}, },
{ {
"expression": "array_slice(array_slice(array('Dufour','Valmiera','Chugiak','Brighton'),-2,-1)", "expression": "array_slice(array_slice(array('Dufour','Valmiera','Chugiak','Brighton'),-2,-1)",
"returns": "array: 'Chugiak','Brighton'" "returns": "[ 'Chugiak', 'Brighton' ]"
} }
] ]
} }

View File

@ -7,7 +7,7 @@
{"arg":"stop", "description":"value that ends the sequence once reached"}, {"arg":"stop", "description":"value that ends the sequence once reached"},
{"arg":"step","optional":true,"default":"1","description":"value used as the increment between values"} {"arg":"step","optional":true,"default":"1","description":"value used as the increment between values"}
], ],
"examples": [ { "expression":"generate_series('1,5)", "returns":"array: '1', '2', '3', '4', '5'"}, "examples": [ { "expression":"generate_series('1,5)", "returns":"[ 1, 2, 3, 4, 5 ]"},
{ "expression":"generate_series('5,1,-1)", "returns":"array: '5', '4', '3', '2', '1'"} { "expression":"generate_series('5,1,-1)", "returns":"[ 5, 4, 3, 2, 1 ]"}
] ]
} }

View File

@ -10,6 +10,6 @@
{"arg":"value2", "syntaxOnly": true}, {"arg":"value2", "syntaxOnly": true},
{"arg":"key", "descOnly": true, "description":"a key (string)"}, {"arg":"key", "descOnly": true, "description":"a key (string)"},
{"arg":"value", "descOnly": true, "description":"a value"}], {"arg":"value", "descOnly": true, "description":"a value"}],
"examples": [ { "expression":"map('1','one','2', 'two')", "returns":"map: 1: 'one', 2: 'two'"} "examples": [ { "expression":"map('1','one','2', 'two')", "returns":"{ '1': 'one', '2': 'two' }"}
] ]
} }

View File

@ -3,5 +3,5 @@
"type": "function", "type": "function",
"description": "Returns all the keys of a map as an array.", "description": "Returns all the keys of a map as an array.",
"arguments": [ {"arg":"map","description":"a map"}], "arguments": [ {"arg":"map","description":"a map"}],
"examples": [ { "expression":"map_akeys(map('1','one','2','two'))", "returns":"array: '1', '2'"}] "examples": [ { "expression":"map_akeys(map('1','one','2','two'))", "returns":"[ '1', '2' ]"}]
} }

View File

@ -3,5 +3,5 @@
"type": "function", "type": "function",
"description": "Returns all the values of a map as an array.", "description": "Returns all the values of a map as an array.",
"arguments": [ {"arg":"map","description":"a map"}], "arguments": [ {"arg":"map","description":"a map"}],
"examples": [ { "expression":"map_avals(map('1','one','2','two'))", "returns":"array: 'one', 'two'"}] "examples": [ { "expression":"map_avals(map('1','one','2','two'))", "returns":"[ 'one', 'two' ]"}]
} }

View File

@ -7,6 +7,6 @@
{"arg":"map1", "syntaxOnly": true}, {"arg":"map1", "syntaxOnly": true},
{"arg":"map2", "syntaxOnly": true}, {"arg":"map2", "syntaxOnly": true},
{"arg":"map", "descOnly": true, "description":"a map"}], {"arg":"map", "descOnly": true, "description":"a map"}],
"examples": [ { "expression":"map_concat(map('1','one', '2','overridden'),map('2','two', '3','three'))", "returns":"map: 1: 'one, 2: 'two', 3: 'three'"} "examples": [ { "expression":"map_concat(map('1','one', '2','overridden'),map('2','two', '3','three'))", "returns":"{ '1': 'one, '2': 'two', '3': 'three' }"}
] ]
} }

View File

@ -4,5 +4,5 @@
"description": "Returns a map with the given key and its corresponding value deleted.", "description": "Returns a map with the given key and its corresponding value deleted.",
"arguments": [ {"arg":"map","description":"a map"}, "arguments": [ {"arg":"map","description":"a map"},
{"arg":"key","description":"the key to delete"}], {"arg":"key","description":"the key to delete"}],
"examples": [ { "expression":"map_delete(map('1','one','2','two'),'2')", "returns":"map: 1: 'one'"}] "examples": [ { "expression":"map_delete(map('1','one','2','two'),'2')", "returns":"{ '1': 'one' }"}]
} }

View File

@ -5,5 +5,5 @@
"arguments": [ {"arg":"map","description":"a map"}, "arguments": [ {"arg":"map","description":"a map"},
{"arg":"key","description":"the key to add"}, {"arg":"key","description":"the key to add"},
{"arg":"value","description":"the value to add"}], {"arg":"value","description":"the value to add"}],
"examples": [ { "expression":"map_insert(map('1','one'),'3','three')", "returns":"map: 1: 'one', 3: 'three'"}] "examples": [ { "expression":"map_insert(map('1','one'),'3','three')", "returns":"{ '1': 'one', '3': 'three' }"}]
} }

View File

@ -6,7 +6,7 @@
{"arg":"string", "description":"the string to capture groups from against the regular expression"}, {"arg":"string", "description":"the string to capture groups from against the regular expression"},
{"arg":"regex","description":"the regular expression used to capture groups"}, {"arg":"regex","description":"the regular expression used to capture groups"},
{"arg":"empty_value","optional":true,"default":"''","description":"the optional string to use as replacement for empty (zero length) matches"}], {"arg":"empty_value","optional":true,"default":"''","description":"the optional string to use as replacement for empty (zero length) matches"}],
"examples": [ { "expression":"regexp_matches('QGIS=>rocks','(.*)=>(.*)')", "returns":"array: 'QGIS', 'rocks'"}, "examples": [ { "expression":"regexp_matches('QGIS=>rocks','(.*)=>(.*)')", "returns":"[ 'QGIS', 'rocks' ]"},
{ "expression":"regexp_matches('key=>','(.*)=>(.*)','empty value')", "returns":"array: 'key', 'empty value'"} { "expression":"regexp_matches('key=>','(.*)=>(.*)','empty value')", "returns":"[ 'key', 'empty value' ]"}
] ]
} }

View File

@ -6,7 +6,7 @@
{"arg":"string", "description":"the input string"}, {"arg":"string", "description":"the input string"},
{"arg":"delimiter","optional":true,"default":"','","description":"the string delimiter used to split the input string"}, {"arg":"delimiter","optional":true,"default":"','","description":"the string delimiter used to split the input string"},
{"arg":"empty_value","optional":true,"default":"''","description":"the optional string to use as replacement for empty (zero length) matches"}], {"arg":"empty_value","optional":true,"default":"''","description":"the optional string to use as replacement for empty (zero length) matches"}],
"examples": [ { "expression":"string_to_array('1,2,3',',')", "returns":"array: '1', '2', '3'"}, "examples": [ { "expression":"string_to_array('1,2,3',',')", "returns":"[ '1', '2', '3' ]"},
{ "expression":"string_to_array('1,,3',',','0')", "returns":"array: '1', '0', '3'"} { "expression":"string_to_array('1,,3',',','0')", "returns":"[ '1', '0', '3' ]"}
] ]
} }

View File

@ -903,35 +903,50 @@ QString QgsExpression::formatPreviewString( const QVariant &value )
} }
else if ( value.type() == QVariant::Map ) else if ( value.type() == QVariant::Map )
{ {
QString mapStr; QString mapStr = QStringLiteral( "{" );
const QVariantMap map = value.toMap(); const QVariantMap map = value.toMap();
QString separator;
for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it ) for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
{ {
if ( !mapStr.isEmpty() ) mapStr.append( ", " ); mapStr.append( separator );
mapStr.append( it.key() ).append( ": " ).append( formatPreviewString( it.value() ) ); if ( separator.isEmpty() )
if ( mapStr.length() > MAX_PREVIEW + 3 ) separator = QStringLiteral( "," );
mapStr.append( QStringLiteral( " '%1': %2" ).arg( it.key(), formatPreviewString( it.value() ) ) );
if ( mapStr.length() > MAX_PREVIEW - 3 )
{ {
mapStr = QString( tr( "%1…" ) ).arg( mapStr.left( MAX_PREVIEW ) ); mapStr = tr( "%1…" ).arg( mapStr.left( MAX_PREVIEW - 2 ) );
break; break;
} }
} }
return tr( "<i>&lt;map: %1&gt;</i>" ).arg( mapStr ); if ( !map.empty() )
mapStr += QStringLiteral( " " );
mapStr += QStringLiteral( "}" );
return mapStr;
} }
else if ( value.type() == QVariant::List || value.type() == QVariant::StringList ) else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
{ {
QString listStr; QString listStr = QStringLiteral( "[" );
const QVariantList list = value.toList(); const QVariantList list = value.toList();
for ( QVariantList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it ) QString separator;
for ( const QVariant &arrayValue : list )
{ {
if ( !listStr.isEmpty() ) listStr.append( ", " ); listStr.append( separator );
listStr.append( formatPreviewString( *it ) ); if ( separator.isEmpty() )
if ( listStr.length() > MAX_PREVIEW + 3 ) separator = QStringLiteral( "," );
listStr.append( " " );
listStr.append( formatPreviewString( arrayValue ) );
if ( listStr.length() > MAX_PREVIEW - 3 )
{ {
listStr = QString( tr( "%1…" ) ).arg( listStr.left( MAX_PREVIEW ) ); listStr = QString( tr( "%1…" ) ).arg( listStr.left( MAX_PREVIEW - 2 ) );
break; break;
} }
} }
return tr( "<i>&lt;array: %1&gt;</i>" ).arg( listStr ); if ( !list.empty() )
listStr += QStringLiteral( " " );
listStr += QStringLiteral( "]" );
return listStr;
} }
else else
{ {

View File

@ -279,7 +279,7 @@ void QgsExpressionBuilderWidget::btnNewFile_pressed()
bool ok; bool ok;
QString text = QInputDialog::getText( this, tr( "Enter new file name" ), QString text = QInputDialog::getText( this, tr( "Enter new file name" ),
tr( "File name:" ), QLineEdit::Normal, tr( "File name:" ), QLineEdit::Normal,
QLatin1String( "" ), &ok ); QString(), &ok );
if ( ok && !text.isEmpty() ) if ( ok && !text.isEmpty() )
{ {
newFunctionFile( text ); newFunctionFile( text );
@ -348,7 +348,7 @@ void QgsExpressionBuilderWidget::loadFieldNames( const QgsFields &fields )
{ {
QString fieldName = fields.at( i ).name(); QString fieldName = fields.at( i ).name();
fieldNames << fieldName; fieldNames << fieldName;
registerItem( QStringLiteral( "Fields and Values" ), fieldName, " \"" + fieldName + "\" ", QLatin1String( "" ), QgsExpressionItem::Field, false, i ); registerItem( QStringLiteral( "Fields and Values" ), fieldName, " \"" + fieldName + "\" ", QString(), QgsExpressionItem::Field, false, i );
} }
// highlighter->addFields( fieldNames ); // highlighter->addFields( fieldNames );
} }
@ -426,7 +426,7 @@ void QgsExpressionBuilderWidget::registerItem( const QString &group,
else else
{ {
// If the group doesn't exist yet we make it first. // If the group doesn't exist yet we make it first.
QgsExpressionItem *newgroupNode = new QgsExpressionItem( QgsExpression::group( group ), QLatin1String( "" ), QgsExpressionItem::Header ); QgsExpressionItem *newgroupNode = new QgsExpressionItem( QgsExpression::group( group ), QString(), QgsExpressionItem::Header );
newgroupNode->setData( group, Qt::UserRole ); newgroupNode->setData( group, Qt::UserRole );
//Recent group should always be last group //Recent group should always be last group
newgroupNode->setData( group.startsWith( QLatin1String( "Recent (" ) ) ? 2 : 1, QgsExpressionItem::CUSTOM_SORT_ROLE ); newgroupNode->setData( group.startsWith( QLatin1String( "Recent (" ) ) ? 2 : 1, QgsExpressionItem::CUSTOM_SORT_ROLE );
@ -628,9 +628,9 @@ void QgsExpressionBuilderWidget::txtExpressionString_textChanged()
if ( text.isEmpty() ) if ( text.isEmpty() )
{ {
lblPreview->clear(); lblPreview->clear();
lblPreview->setStyleSheet( QLatin1String( "" ) ); lblPreview->setStyleSheet( QString() );
txtExpressionString->setToolTip( QLatin1String( "" ) ); txtExpressionString->setToolTip( QString() );
lblPreview->setToolTip( QLatin1String( "" ) ); lblPreview->setToolTip( QString() );
emit expressionParsed( false ); emit expressionParsed( false );
setParserError( true ); setParserError( true );
setEvalError( true ); setEvalError( true );
@ -1064,7 +1064,7 @@ QString QgsExpressionBuilderWidget::helpStylesheet() const
QString QgsExpressionBuilderWidget::loadFunctionHelp( QgsExpressionItem *expressionItem ) QString QgsExpressionBuilderWidget::loadFunctionHelp( QgsExpressionItem *expressionItem )
{ {
if ( !expressionItem ) if ( !expressionItem )
return QLatin1String( "" ); return QString();
QString helpContents = expressionItem->getHelpText(); QString helpContents = expressionItem->getHelpText();

View File

@ -3114,24 +3114,24 @@ class TestQgsExpression: public QObject
void test_formatPreviewString() void test_formatPreviewString()
{ {
QCOMPARE( QgsExpression::formatPreviewString( QVariant( "hello" ) ), QString( "'hello'" ) ); QCOMPARE( QgsExpression::formatPreviewString( QVariant( "hello" ) ), QStringLiteral( "'hello'" ) );
QCOMPARE( QgsExpression::formatPreviewString( QVariant( QVariantMap() ) ), QString( "<i>&lt;map: &gt;</i>" ) ); QCOMPARE( QgsExpression::formatPreviewString( QVariant( QVariantMap() ) ), QStringLiteral( "{}" ) );
QVariantMap map; QVariantMap map;
map[QStringLiteral( "1" )] = "One"; map[QStringLiteral( "1" )] = "One";
map[QStringLiteral( "2" )] = "Two"; map[QStringLiteral( "2" )] = "Two";
QCOMPARE( QgsExpression::formatPreviewString( QVariant( map ) ), QString( "<i>&lt;map: 1: 'One', 2: 'Two'&gt;</i>" ) ); QCOMPARE( QgsExpression::formatPreviewString( QVariant( map ) ), QStringLiteral( "{ '1': 'One', '2': 'Two' }" ) );
map[QStringLiteral( "3" )] = "A very long string that is going to be truncated"; map[QStringLiteral( "3" )] = "A very long string that is going to be truncated";
QCOMPARE( QgsExpression::formatPreviewString( QVariant( map ) ), QString( "<i>&lt;map: 1: 'One', 2: 'Two', 3: 'A very long string that is going to …&gt;</i>" ) ); QCOMPARE( QgsExpression::formatPreviewString( QVariant( map ) ), QStringLiteral( "{ '1': 'One', '2': 'Two', '3': 'A very long string that is… }" ) );
QVariantList list; QVariantList list;
list << 1 << 2 << 3; list << 1 << 2 << 3;
QCOMPARE( QgsExpression::formatPreviewString( QVariant( list ) ), QString( "<i>&lt;array: 1, 2, 3&gt;</i>" ) ); QCOMPARE( QgsExpression::formatPreviewString( QVariant( list ) ), QStringLiteral( "[ 1, 2, 3 ]" ) );
QStringList stringList; QStringList stringList;
stringList << QStringLiteral( "One" ) << QStringLiteral( "Two" ) << QStringLiteral( "A very long string that is going to be truncated" ); stringList << QStringLiteral( "One" ) << QStringLiteral( "Two" ) << QStringLiteral( "A very long string that is going to be truncated" );
QCOMPARE( QgsExpression::formatPreviewString( QVariant( stringList ) ), QCOMPARE( QgsExpression::formatPreviewString( QVariant( stringList ) ),
QString( "<i>&lt;array: 'One', 'Two', 'A very long string that is going to be trunca…&gt;</i>" ) ); QStringLiteral( "[ 'One', 'Two', 'A very long string that is going to be tr… ]" ) );
} }
}; };