[QGIS Commit] r14533 - in trunk/qgis: resources/context_help
src/app src/core src/ui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Mon Nov 8 07:01:58 EST 2010
Author: jef
Date: 2010-11-08 04:01:58 -0800 (Mon, 08 Nov 2010)
New Revision: 14533
Added:
trunk/qgis/resources/context_help/QgsFieldCalculator-en_US
Modified:
trunk/qgis/src/app/qgsfieldcalculator.cpp
trunk/qgis/src/app/qgsfieldcalculator.h
trunk/qgis/src/core/qgssearchstringlexer.ll
trunk/qgis/src/core/qgssearchstringparser.yy
trunk/qgis/src/core/qgssearchtreenode.cpp
trunk/qgis/src/core/qgssearchtreenode.h
trunk/qgis/src/ui/qgsfieldcalculatorbase.ui
Log:
[FEATURE] add field calculator functions (implements #3177)
- add support for functions with 2 or three arguments
- add function atan2(y,x)
- add length(string) to determine string length
- add replace(string,from,to) to do string replaces
- add substr(string,from,length) to retrieve substrings
- add (preliminary) online help to field calculator with a listing of operations.
Added: trunk/qgis/resources/context_help/QgsFieldCalculator-en_US
===================================================================
--- trunk/qgis/resources/context_help/QgsFieldCalculator-en_US (rev 0)
+++ trunk/qgis/resources/context_help/QgsFieldCalculator-en_US 2010-11-08 12:01:58 UTC (rev 14533)
@@ -0,0 +1,71 @@
+<h3>Field Calculator</h3>
+The field calculator allows you to update fields with expressions.
+
+<h4>Supported Operations</h4>
+
+<table border=1>
+<tr>
+ <th>Operation</th>
+ <th>Description</th>
+</tr>
+<tr>
+ <td>
+ <tt>column_name</tt><br>
+ <tt>"column_name"</tt>
+ </td>
+ <td>value of field <tt>column_name</tt></td>
+</tr>
+<tr><td>'string'</td><td>literal string value</td></tr>
+<tr><td><i>number</i></td><td>number</td></tr>
+<tr><td>NULL</td><td>null value</td></tr>
+<tr><td><tt>a</tt> OR <tt>b</tt></td><td><tt>a</tt> or <tt>b</tt> are true.</td></tr>
+<tr><td><tt>a</tt> AND <tt>b</tt></td><td><tt>a</tt> and <tt>b</tt> are true.</td></tr>
+<tr><td>NOT <tt>a</tt></td><td>inverted boolean value of <tt>a</tt></td></tr>
+<tr><td><tt>a</tt> IS NULL</td><td><tt>a</tt> has no value</td></tr>
+<tr><td><tt>a</tt> IS NOT NULL</td><td><tt>a</tt> has <tt>a</tt> value</td></tr>
+<tr><td><tt>a</tt> IN ( value, [, value] )</td><td><tt>a</tt> is one of the listed values</td></tr>
+<tr><td><tt>a</tt> NOT IN ( value, [, value] )</td><td><tt>a</tt> is not one of the listed values</td></tr>
+<tr><td><tt>a</tt> = <tt>b</tt></td><td><tt>a</tt> and <tt>b</tt> are equal</td><tr>
+<tr>
+ <td>
+ <tt>a</tt> != <tt>b</tt><br>
+ <tt>a</tt> <> <tt>b</tt>
+ </td>
+ <td><tt>a</tt> and <tt>b</tt> are not equal</td>
+</tr>
+<tr><td><tt>a</tt> <= <tt>b</tt></td><td><tt>a</tt> is less or equal <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> >= <tt>b</tt></td><td><tt>a</tt> is greater or equal <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> > <tt>b</tt></td><td><tt>a</tt> is greater than <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> < <tt>b</tt></td><td><tt>a</tt> is less than <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> ~ <tt>b</tt></td></td><td><tt>a</tt> matches regular expression <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> LIKE <tt>b</tt></td><td><tt>a</tt> is like <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> ILIKE <tt>b</tt></td><td><tt>a</tt> is like <tt>b</tt> (case insensitive)</td></tr>
+<tr><td>sqrt(<tt>a</tt>)</td><td>square root</td></tr>
+<tr><td>sin(<tt>a</tt>)</td><td>sinus of <tt>a</tt></td></tr>
+<tr><td>cos(<tt>a</tt>)</td><td>cosinus of <tt>b</tt></td></tr>
+<tr><td>tan(<tt>a</tt>)</td><td>tangens of <tt>a</tt></td></tr>
+<tr><td>asin(<tt>a</tt>)</td><td>arcussinus of <tt>a</tt></td></tr>
+<tr><td>acos(<tt>a</tt>)</td><td>arcuscosinus of <tt>a</tt></td></tr>
+<tr><td>atan(<tt>a</tt>)</td><td>arcustangens of <tt>a</tt></td></tr>
+<tr><td>to int(<tt>a</tt>)</td><td>convert string <tt>a</tt> to integer</td></tr>
+<tr><td>to real(<tt>a</tt>)</td><td>convert string <tt>a</tt> to real</td></tr>
+<tr><td>to string(<tt>a</tt>)</td><td>convert number <tt>a</tt> to string</td></tr>
+<tr><td>lower(<tt>a</tt>)</td><td>convert string <tt>a</tt> to lower case</td></tr>
+<tr><td>upper(<tt>a</tt>)</td><td>convert string <tt>a</tt> to upper case</td></tr>
+<tr><td>length(<tt>a</tt>)</td><td>length of string <tt>a</tt></td></tr>
+<tr><td>atan2(y,x)</td><td>arcustangens of y/x using the signs of the two arguments to determine the quadrant of the result.</td></tr>
+<tr><td>replace(<tt>a</tt>,replacethis,withthat)</td><td>replace replacethis with withthat in string <tt>a</tt></td></td>
+<tr><td>substr(<tt>a</tt>,from,len)</td><td>len characters of string <tt>a</tt> starting from from (first character index is 1)</td></td>
+<tr><td><tt>a</tt> || <tt>b</tt></td><td>concatenate strings <tt>a</tt> and <tt>b</tt></td></tr>
+<tr><td>$rownum</td><td>number current row</td></tr>
+<tr><td>$area</td><td>area of polygon</td></tr>
+<tr><td>$length</td><td>area of line</td></tr>
+<tr><td>$id</td><td>feature id</td></tr>
+<tr><td><tt>a</tt> ^ <tt>b</tt></td><td><tt>a</tt> raised to the power of <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> * <tt>b</tt></td><td><tt>a</tt> multiplied by <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> * <tt>b</tt></td><td><tt>a</tt> divided by <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> + <tt>b</tt></td><td><tt>a</tt> plus <tt>b</tt></td></tr>
+<tr><td><tt>a</tt> - <tt>b</tt></td><td><tt>a</tt> minus <tt>b</tt></td></tr>
+<tr><td>+<tt>a</tt></td><td>positive sign</td></tr>
+<tr><td>-<tt>a</tt></td><td>negative value of <tt>a</tt></td></tr>
+</table>
Modified: trunk/qgis/src/app/qgsfieldcalculator.cpp
===================================================================
--- trunk/qgis/src/app/qgsfieldcalculator.cpp 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/app/qgsfieldcalculator.cpp 2010-11-08 12:01:58 UTC (rev 14533)
@@ -36,8 +36,6 @@
mOuputFieldWidthSpinBox->setValue( 10 );
mOutputFieldPrecisionSpinBox->setValue( 3 );
-
-
//disable ok button until there is text for output field and expression
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
Modified: trunk/qgis/src/app/qgsfieldcalculator.h
===================================================================
--- trunk/qgis/src/app/qgsfieldcalculator.h 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/app/qgsfieldcalculator.h 2010-11-08 12:01:58 UTC (rev 14533)
@@ -17,6 +17,7 @@
#define QGSFIELDCALCULATOR_H
#include "ui_qgsfieldcalculatorbase.h"
+#include "qgscontexthelp.h"
class QgsVectorLayer;
@@ -61,6 +62,8 @@
void on_mExpressionTextEdit_textChanged();
void on_mOutputFieldTypeComboBox_activated( int index );
+ void on_mButtonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
+
private:
//default constructor forbidden
QgsFieldCalculator();
Modified: trunk/qgis/src/core/qgssearchstringlexer.ll
===================================================================
--- trunk/qgis/src/core/qgssearchstringlexer.ll 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/core/qgssearchstringlexer.ll 2010-11-08 12:01:58 UTC (rev 14533)
@@ -83,19 +83,25 @@
"LIKE" { yylval.op = QgsSearchTreeNode::opLike; return COMPARISON; }
"ILIKE" { yylval.op = QgsSearchTreeNode::opILike; return COMPARISON; }
-"sqrt" { yylval.op = QgsSearchTreeNode::opSQRT; return FUNCTION;}
-"sin" { yylval.op = QgsSearchTreeNode::opSIN; return FUNCTION;}
-"cos" { yylval.op = QgsSearchTreeNode::opCOS; return FUNCTION;}
-"tan" { yylval.op = QgsSearchTreeNode::opTAN; return FUNCTION;}
-"asin" { yylval.op = QgsSearchTreeNode::opASIN; return FUNCTION;}
-"acos" { yylval.op = QgsSearchTreeNode::opACOS; return FUNCTION;}
-"atan" { yylval.op = QgsSearchTreeNode::opATAN; return FUNCTION;}
-"to int" { yylval.op = QgsSearchTreeNode::opTOINT; return FUNCTION;}
-"to real" { yylval.op = QgsSearchTreeNode::opTOREAL; return FUNCTION;}
-"to string" { yylval.op = QgsSearchTreeNode::opTOSTRING; return FUNCTION;}
-"lower" { yylval.op = QgsSearchTreeNode::opLOWER; return FUNCTION;}
-"upper" { yylval.op = QgsSearchTreeNode::opUPPER; return FUNCTION;}
+"sqrt" { yylval.op = QgsSearchTreeNode::opSQRT; return FUNCTION1;}
+"sin" { yylval.op = QgsSearchTreeNode::opSIN; return FUNCTION1;}
+"cos" { yylval.op = QgsSearchTreeNode::opCOS; return FUNCTION1;}
+"tan" { yylval.op = QgsSearchTreeNode::opTAN; return FUNCTION1;}
+"asin" { yylval.op = QgsSearchTreeNode::opASIN; return FUNCTION1;}
+"acos" { yylval.op = QgsSearchTreeNode::opACOS; return FUNCTION1;}
+"atan" { yylval.op = QgsSearchTreeNode::opATAN; return FUNCTION1;}
+"to int" { yylval.op = QgsSearchTreeNode::opTOINT; return FUNCTION1;}
+"to real" { yylval.op = QgsSearchTreeNode::opTOREAL; return FUNCTION1;}
+"to string" { yylval.op = QgsSearchTreeNode::opTOSTRING; return FUNCTION1;}
+"lower" { yylval.op = QgsSearchTreeNode::opLOWER; return FUNCTION1;}
+"upper" { yylval.op = QgsSearchTreeNode::opUPPER; return FUNCTION1;}
+"length" { yylval.op = QgsSearchTreeNode::opSTRLEN; return FUNCTION1;}
+"atan2" { yylval.op = QgsSearchTreeNode::opATAN2; return FUNCTION2;}
+
+"replace" { yylval.op = QgsSearchTreeNode::opREPLACE; return FUNCTION3;}
+"substr" { yylval.op = QgsSearchTreeNode::opSUBSTR; return FUNCTION3;}
+
"||" { return CONCAT; }
[+-/*^] { return yytext[0]; }
Modified: trunk/qgis/src/core/qgssearchstringparser.yy
===================================================================
--- trunk/qgis/src/core/qgssearchstringparser.yy 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/core/qgssearchstringparser.yy 2010-11-08 12:01:58 UTC (rev 14533)
@@ -61,7 +61,9 @@
%token <number> NUMBER
%token <op> COMPARISON
-%token <op> FUNCTION
+%token <op> FUNCTION1
+%token <op> FUNCTION2
+%token <op> FUNCTION3
%token CONCAT
%token IS
%token IN
@@ -135,11 +137,28 @@
scalar_exp_list:
scalar_exp_list ',' scalar_exp { $$ = $1; $1->append($3); joinTmpNodes($1,$1,$3); }
- | scalar_exp { $$ = new QgsSearchTreeNode( QgsSearchTreeNode::tNodeList ); $$->append($1); joinTmpNodes($$,$1,0); }
+ | scalar_exp
+ {
+ $$ = new QgsSearchTreeNode( QgsSearchTreeNode::tNodeList );
+ $$->append($1);
+ joinTmpNodes($$,$1,0);
+ }
;
scalar_exp:
- FUNCTION '(' scalar_exp ')' { $$ = new QgsSearchTreeNode($1, $3, 0); joinTmpNodes($$, $3, 0);}
+ FUNCTION1 '(' scalar_exp ')' { $$ = new QgsSearchTreeNode($1, $3, 0); joinTmpNodes($$, $3, 0); }
+ | FUNCTION2 '(' scalar_exp ',' scalar_exp ')' { $$ = new QgsSearchTreeNode($1, $3, $5); joinTmpNodes($$, $3, $5); }
+ | FUNCTION3 '(' scalar_exp ',' scalar_exp ',' scalar_exp ')'
+ {
+ QgsSearchTreeNode *args = new QgsSearchTreeNode( QgsSearchTreeNode::tNodeList );
+ args->append($3);
+ args->append($5);
+ args->append($7);
+
+ $$ = new QgsSearchTreeNode($1, args, 0);
+ joinTmpNodes($$, $3, $5);
+ joinTmpNodes($$, $$, $7);
+ }
| scalar_exp '^' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPOW, $1, $3); joinTmpNodes($$,$1,$3); }
| scalar_exp '*' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opMUL, $1, $3); joinTmpNodes($$,$1,$3); }
| scalar_exp '/' scalar_exp { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opDIV, $1, $3); joinTmpNodes($$,$1,$3); }
Modified: trunk/qgis/src/core/qgssearchtreenode.cpp
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.cpp 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/core/qgssearchtreenode.cpp 2010-11-08 12:01:58 UTC (rev 14533)
@@ -115,8 +115,10 @@
else
mRight = NULL;
- foreach( QgsSearchTreeNode *lnode, node.mNodeList )
- mNodeList.append( new QgsSearchTreeNode( *lnode ) );
+ foreach( QgsSearchTreeNode * lnode, node.mNodeList )
+ {
+ mNodeList.append( new QgsSearchTreeNode( *lnode ) );
+ }
init();
}
@@ -209,7 +211,8 @@
if ( mOp == opSQRT || mOp == opSIN || mOp == opCOS || mOp == opTAN ||
mOp == opASIN || mOp == opACOS || mOp == opATAN ||
mOp == opTOINT || mOp == opTOREAL || mOp == opTOSTRING ||
- mOp == opLOWER || mOp == opUPPER )
+ mOp == opLOWER || mOp == opUPPER || mOp == opSTRLEN ||
+ mOp == opATAN2 || mOp == opREPLACE || mOp == opSUBSTR )
{
// functions
switch ( mOp )
@@ -226,6 +229,10 @@
case opTOSTRING: str += "to string"; break;
case opLOWER: str += "lower"; break;
case opUPPER: str += "upper"; break;
+ case opATAN2: str += "atan2"; break;
+ case opSTRLEN: str += "length"; break;
+ case opREPLACE: str += "replace"; break;
+ case opSUBSTR: str += "substr"; break;
default: str += "?";
}
// currently all functions take one parameter
@@ -306,7 +313,7 @@
else if ( mType == tNodeList )
{
QStringList items;
- foreach( QgsSearchTreeNode *node, mNodeList )
+ foreach( QgsSearchTreeNode * node, mNodeList )
{
items << node->makeSearchString();
}
@@ -461,7 +468,7 @@
return false;
}
- foreach( QgsSearchTreeNode *node, mRight->mNodeList )
+ foreach( QgsSearchTreeNode * node, mRight->mNodeList )
{
if ( !getValue( value2, node, fields, f ) )
{
@@ -480,7 +487,6 @@
return mOp == opNOTIN;
}
- break;
case opRegexp:
case opLike:
@@ -545,7 +551,7 @@
value = node->valueAgainst( fields, f );
if ( value.isError() )
{
- switch (( int )value.number() )
+ switch (( int ) value.number() )
{
case 1:
mError = QObject::tr( "Referenced column wasn't found: %1" ).arg( value.string() );
@@ -587,7 +593,6 @@
switch ( mType )
{
-
case tNumber:
QgsDebugMsgLevel( "number: " + QString::number( mNumber ), 2 );
return QgsSearchTreeValue( mNumber );
@@ -637,13 +642,23 @@
// arithmetic operators
case tOperator:
{
- QgsSearchTreeValue value1, value2;
+ QgsSearchTreeValue value1, value2, value3;
if ( mLeft )
{
- if ( !getValue( value1, mLeft, fields, f ) ) return value1;
+ if ( mLeft->type() != tNodeList )
+ {
+ if ( !getValue( value1, mLeft, fields, f ) ) return value1;
+ }
+ else
+ {
+ if ( mLeft->mNodeList.size() > 0 && !getValue( value1, mLeft->mNodeList[0], fields, f ) ) return value1;
+ if ( mLeft->mNodeList.size() > 1 && !getValue( value2, mLeft->mNodeList[1], fields, f ) ) return value2;
+ if ( mLeft->mNodeList.size() > 2 && !getValue( value3, mLeft->mNodeList[2], fields, f ) ) return value3;
+ }
}
if ( mRight )
{
+ Q_ASSERT( !mLeft || mLeft->type() != tNodeList );
if ( !getValue( value2, mRight, fields, f ) ) return value2;
}
@@ -716,6 +731,23 @@
}
}
+ // string operations
+ switch ( mOp )
+ {
+ case opLOWER:
+ return QgsSearchTreeValue( value1.string().toLower() );
+ case opUPPER:
+ return QgsSearchTreeValue( value1.string().toUpper() );
+ case opSTRLEN:
+ return QgsSearchTreeValue( value1.string().length() );
+ case opREPLACE:
+ return QgsSearchTreeValue( value1.string().replace( value2.string(), value3.string() ) );
+ case opSUBSTR:
+ return QgsSearchTreeValue( value1.string().mid( value2.number() - 1, value3.number() ) );
+ default:
+ break;
+ }
+
// for other operators, convert strings to numbers if needed
double val1, val2;
if ( value1.isNumeric() )
@@ -740,8 +772,6 @@
return QgsSearchTreeValue( 2, "" ); // division by zero
else
return QgsSearchTreeValue( val1 / val2 );
- default:
- return QgsSearchTreeValue( 3, QString::number( mOp ) ); // unknown operator
case opPOW:
if (( val1 == 0 && val2 < 0 ) || ( val2 < 0 && ( val2 - floor( val2 ) ) > 0 ) )
{
@@ -762,16 +792,17 @@
return QgsSearchTreeValue( acos( val1 ) );
case opATAN:
return QgsSearchTreeValue( atan( val1 ) );
+ case opATAN2:
+ return QgsSearchTreeValue( atan2( val1, val2 ) );
case opTOINT:
return QgsSearchTreeValue( int( val1 ) );
case opTOREAL:
return QgsSearchTreeValue( val1 );
case opTOSTRING:
return QgsSearchTreeValue( QString::number( val1 ) );
- case opLOWER:
- return QgsSearchTreeValue( value1.string().toLower() );
- case opUPPER:
- return QgsSearchTreeValue( value1.string().toUpper() );
+
+ default:
+ return QgsSearchTreeValue( 3, QString::number( mOp ) ); // unknown operator
}
}
@@ -806,8 +837,10 @@
void QgsSearchTreeNode::append( QList<QgsSearchTreeNode *> nodes )
{
- foreach( QgsSearchTreeNode *node, nodes )
- mNodeList.append( node );
+ foreach( QgsSearchTreeNode * node, nodes )
+ {
+ mNodeList.append( node );
+ }
}
int QgsSearchTreeValue::compare( QgsSearchTreeValue& value1, QgsSearchTreeValue& value2, Qt::CaseSensitivity cs )
Modified: trunk/qgis/src/core/qgssearchtreenode.h
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.h 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/core/qgssearchtreenode.h 2010-11-08 12:01:58 UTC (rev 14533)
@@ -74,6 +74,7 @@
opASIN,
opACOS,
opATAN,
+ opATAN2,
// conversion
opTOINT,
@@ -106,6 +107,9 @@
opCONCAT,
opLOWER,
opUPPER,
+ opREPLACE,
+ opSTRLEN,
+ opSUBSTR,
opROWNUM
};
Modified: trunk/qgis/src/ui/qgsfieldcalculatorbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsfieldcalculatorbase.ui 2010-11-08 10:57:54 UTC (rev 14532)
+++ trunk/qgis/src/ui/qgsfieldcalculatorbase.ui 2010-11-08 12:01:58 UTC (rev 14533)
@@ -305,7 +305,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
More information about the QGIS-commit
mailing list