Skip to content
Permalink
Browse files

Merge pull request #1208 from nirvn/expression_wordwrap3

[expression] implement a wordwrap function (fix #9412)
  • Loading branch information
NathanW2 committed Mar 4, 2014
2 parents 86ea4bf + a7cb2b2 commit 9b71d081f1deb26193eca483ad9e7287bdc7af6b
Showing with 89 additions and 1 deletion.
  1. +16 −0 resources/function_help/wordwrap
  2. +68 −1 src/core/qgsexpression.cpp
  3. +5 −0 tests/src/core/testqgsexpression.cpp
@@ -0,0 +1,16 @@
<h3>wordwrap() function</h3>
Returns a string wrapped to a maximum/minimum number of characters.

<p><h4>Syntax</h4>
replace(<i>string,wrap_length[,delimiter_string]</i>)</p>

<p><h4>Arguments</h4>
<!-- List args for functions here-->
<i> string</i> &rarr; is string. The string to be wrapped.<br>
<i> wrap_length</i> &rarr; is number. If positive, the number represents the ideal maximum number of characters to wrap; if negative, the number represents the minimum number of characters to wrap.<br>
<i> delimiter_string</i> &rarr; is string. The delimiter string to wrap to a new line (<u>optional</u>).<br></p>

<p><h4>Example</h4>
<!-- Show example of function.-->
wordwrap('UNIVERSITY OF QGIS',13) &rarr; 'UNIVERSITY OF\nQGIS'<br>
wordwrap('UNIVERSITY OF QGIS',-3) &rarr; 'UNIVERSITY\nOF QGIS'</p>
@@ -631,6 +631,72 @@ static QVariant fcnTrim( const QVariantList& values, const QgsFeature* , QgsExpr
return QVariant( str.trimmed() );
}

static QVariant fcnWordwrap( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
{
if ( values.length() == 2 || values.length() == 3 )
{
QString str = getStringValue( values.at( 0 ), parent );
int wrap = getIntValue( values.at( 1 ), parent );

if ( !str.isEmpty() && wrap != 0 )
{
QString newstr;
QString delimiterstr;
if ( values.length() == 3 ) delimiterstr = getStringValue( values.at( 2 ), parent );
if ( delimiterstr.isEmpty() ) delimiterstr = " ";
int delimiterlength = delimiterstr.length();

QStringList lines = str.split( "\n" );
int strlength, strcurrent, strhit, lasthit;

for ( int i = 0; i < lines.size(); i++ )
{
strlength = lines[i].length();
strcurrent = 0;
strhit = 0;
lasthit = 0;

while ( strcurrent < strlength )
{
// positive wrap value = desired maximum line width to wrap
// negative wrap value = desired minimum line width before wrap
if ( wrap > 0 )
{
//first try to locate delimiter backwards
strhit = lines[i].lastIndexOf( delimiterstr, strcurrent + wrap );
if ( strhit == lasthit || strhit == -1 )
{
//if no new backward delimiter found, try to locate forward
strhit = lines[i].indexOf( delimiterstr, strcurrent + qAbs( wrap ) );
}
lasthit = strhit;
}
else
{
strhit = lines[i].indexOf( delimiterstr, strcurrent + qAbs( wrap ) );
}
if ( strhit > -1 )
{
newstr.append( lines[i].midRef( strcurrent , strhit - strcurrent ) );
newstr.append( "\n" );
strcurrent = strhit + delimiterlength;
}
else
{
newstr.append( lines[i].midRef( strcurrent ) );
strcurrent = strlength;
}
}
if ( i < lines.size() - 1 ) newstr.append( "\n" );
}

return QVariant( newstr );
}
}

return QVariant();
}

static QVariant fcnLength( const QVariantList& values, const QgsFeature* , QgsExpression* parent )
{
QString str = getStringValue( values.at( 0 ), parent );
@@ -1416,7 +1482,7 @@ const QStringList &QgsExpression::BuiltinFunctions()
<< "coalesce" << "regexp_match" << "$now" << "age" << "year"
<< "month" << "week" << "day" << "hour"
<< "minute" << "second" << "lower" << "upper"
<< "title" << "length" << "replace" << "trim"
<< "title" << "length" << "replace" << "trim" << "wordwrap"
<< "regexp_replace" << "regexp_substr"
<< "substr" << "concat" << "strpos" << "left"
<< "right" << "rpad" << "lpad"
@@ -1484,6 +1550,7 @@ const QList<QgsExpression::Function*> &QgsExpression::Functions()
<< new StaticFunction( "upper", 1, fcnUpper, "String" )
<< new StaticFunction( "title", 1, fcnTitle, "String" )
<< new StaticFunction( "trim", 1, fcnTrim, "String" )
<< new StaticFunction( "wordwrap", -1, fcnWordwrap, "String" )
<< new StaticFunction( "length", 1, fcnLength, "String" )
<< new StaticFunction( "replace", 3, fcnReplace, "String" )
<< new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
@@ -315,6 +315,11 @@ class TestQgsExpression: public QObject
QTest::newRow( "title" ) << "title(' HeLlO WORLD ')" << false << QVariant( " Hello World " );
QTest::newRow( "trim" ) << "trim(' Test String ')" << false << QVariant( "Test String" );
QTest::newRow( "trim empty string" ) << "trim('')" << false << QVariant( "" );
QTest::newRow( "wordwrap" ) << "wordwrap('university of qgis',13)" << false << QVariant( "university of\nqgis" );
QTest::newRow( "wordwrap" ) << "wordwrap('university of qgis',13,' ')" << false << QVariant( "university of\nqgis" );
QTest::newRow( "wordwrap" ) << "wordwrap('university of qgis',-3)" << false << QVariant( "university\nof qgis" );
QTest::newRow( "wordwrap" ) << "wordwrap('university of qgis',-3,' ')" << false << QVariant( "university\nof qgis" );
QTest::newRow( "wordwrap" ) << "wordwrap('university of qgis\nsupports many multiline',-5,' ')" << false << QVariant( "university\nof qgis\nsupports\nmany multiline" );
QTest::newRow( "format" ) << "format('%1 %2 %3 %1', 'One', 'Two', 'Three')" << false << QVariant( "One Two Three One" );

// implicit conversions

0 comments on commit 9b71d08

Please sign in to comment.
You can’t perform that action at this time.