Skip to content
Permalink
Browse files

[FEATURE]: possibility to use feature length, feature area, string co…

…ncatenation and type conversions in field calculator

git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@11856 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent
mhugent committed Oct 27, 2009
1 parent 8b47b5d commit 96ce43c69c3e6fdd00e6ae3ca3eae190406795ff
@@ -558,7 +558,7 @@ void QgsAttributeTableDialog::revert()
void QgsAttributeTableDialog::on_mOpenFieldCalculator_clicked()
{
QgsFieldCalculator calc( mLayer );
if ( calc.exec() )
if ( calc.exec() == QDialog::Accepted )
{
// update model - a field has been added or updated
mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
@@ -43,6 +43,15 @@ QgsFieldCalculator::QgsFieldCalculator( QgsVectorLayer* vl ): QDialog(), mVector
mNewFieldGroupBox->setEnabled( false );
mNewFieldGroupBox->setTitle( mNewFieldGroupBox->title() + tr( " (not supported by provider)" ) );
}

if ( vl->geometryType() != QGis::Polygon )
{
mAreaButton->setEnabled( false );
}
if ( vl->geometryType() != QGis::Line )
{
mLengthButton->setEnabled( false );
}
}

QgsFieldCalculator::~QgsFieldCalculator()
@@ -133,7 +142,9 @@ void QgsFieldCalculator::accept()
// block layerModified signals (that would trigger table update)
mVectorLayer->blockSignals( true );

mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
bool useGeometry = calcString.contains( "$area" ) || calcString.contains( "$length" );

mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), QgsRectangle(), useGeometry, false );
while ( mVectorLayer->nextFeature( feature ) )
{
if ( onlySelected )
@@ -144,7 +155,15 @@ void QgsFieldCalculator::accept()
}
}

QgsSearchTreeValue value = searchTree->valueAgainst( mVectorLayer->pendingFields(), feature.attributeMap() );
QgsSearchTreeValue value;
if ( useGeometry )
{
searchTree->getValue( value, searchTree, mVectorLayer->pendingFields(), feature.attributeMap(), feature.geometry() );
}
else
{
searchTree->getValue( value, searchTree, mVectorLayer->pendingFields(), feature.attributeMap() );
}
if ( value.isError() )
{
calculationSuccess = false;
@@ -332,6 +351,31 @@ void QgsFieldCalculator::on_mCloseBracketPushButton_clicked()
mExpressionTextEdit->insertPlainText( " ) " );
}

void QgsFieldCalculator::on_mToRealButton_clicked()
{
mExpressionTextEdit->insertPlainText( " to real ( " );
}

void QgsFieldCalculator::on_mToIntButton_clicked()
{
mExpressionTextEdit->insertPlainText( " to int ( " );
}

void QgsFieldCalculator::on_mToStringButton_clicked()
{
mExpressionTextEdit->insertPlainText( " to string ( " );
}

void QgsFieldCalculator::on_mLengthButton_clicked()
{
mExpressionTextEdit->insertPlainText( "$length" );
}

void QgsFieldCalculator::on_mAreaButton_clicked()
{
mExpressionTextEdit->insertPlainText( "$area" );
}

void QgsFieldCalculator::on_mSamplePushButton_clicked()
{
getFieldValues( 25 );
@@ -48,6 +48,11 @@ class QgsFieldCalculator: public QDialog, private Ui::QgsFieldCalculatorBase
void on_mATanButton_clicked();
void on_mOpenBracketPushButton_clicked();
void on_mCloseBracketPushButton_clicked();
void on_mToRealButton_clicked();
void on_mToIntButton_clicked();
void on_mToStringButton_clicked();
void on_mLengthButton_clicked();
void on_mAreaButton_clicked();
void on_mSamplePushButton_clicked();
void on_mAllPushButton_clicked();
void on_mOutputFieldNameLineEdit_textChanged( const QString& text );
@@ -52,6 +52,7 @@ number {num1}|{num2}
str_char ('')|(\\.)|[^'\\]
string "'"{str_char}*"'"


%%

"NOT" { return NOT; }
@@ -75,6 +76,9 @@ string "'"{str_char}*"'"
"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;}

[+-/*^] { return yytext[0]; }

@@ -84,6 +88,9 @@ string "'"{str_char}*"'"

{string} { return STRING; }

"$area" { return AREA; }
"$length" { return LENGTH; }

{column_ref} { return COLUMN_REF; }

{white} /* skip blanks and tabs */
@@ -61,6 +61,8 @@ void addToTmpNodes(QgsSearchTreeNode* node);
%token <number> NUMBER
%token <op> COMPARISON
%token <op> FUNCTION
%token AREA
%token LENGTH

%token STRING
%token COLUMN_REF
@@ -126,10 +128,12 @@ scalar_exp:
| '(' scalar_exp ')' { $$ = $2; }
| '+' scalar_exp %prec UMINUS { $$ = $2; }
| '-' scalar_exp %prec UMINUS { $$ = $2; if ($$->type() == QgsSearchTreeNode::tNumber) $$->setNumber(- $$->number()); }
| AREA { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opAREA, 0, 0); addToTmpNodes($$); }
| LENGTH { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opLENGTH, 0, 0); addToTmpNodes($$); }
| NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); }
| STRING { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 0); addToTmpNodes($$); }
| COLUMN_REF { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 1); addToTmpNodes($$); }
;
;

%%

@@ -19,9 +19,11 @@

#include "qgslogger.h"
#include "qgsfield.h"
#include "qgsgeometry.h"
#include "qgssearchtreenode.h"
#include <QRegExp>
#include <QObject>
#include <QSettings>
#include <iostream>

#ifndef Q_OS_MACX
@@ -50,6 +52,15 @@ QgsSearchTreeNode::QgsSearchTreeNode( Operator op, QgsSearchTreeNode* left,
mOp = op;
mLeft = left;
mRight = right;

if ( mOp == opLENGTH || mOp == opAREA )
{
//initialize QgsDistanceArea
mCalc.setProjectionsEnabled( false );
QSettings settings;
QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString();
mCalc.setEllipsoid( ellipsoid );
}
}


@@ -138,7 +149,10 @@ QString QgsSearchTreeNode::makeSearchString()
str += "(";
if ( mOp != opNOT )
{
str += mLeft->makeSearchString();
if ( mLeft )
{
str += mLeft->makeSearchString();
}
switch ( mOp )
{
case opAND: str += " AND "; break;
@@ -284,9 +298,9 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
}
}

bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node, const QgsFieldMap& fields, const QgsAttributeMap& attributes )
bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node, const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
{
value = node->valueAgainst( fields, attributes );
value = node->valueAgainst( fields, attributes, geom );
if ( value.isError() )
{
switch (( int )value.number() )
@@ -316,7 +330,7 @@ bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode*
return true;
}

QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes )
QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
{
QgsDebugMsgLevel( "valueAgainst: " + makeSearchString(), 2 );

@@ -370,14 +384,55 @@ QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, c
QgsSearchTreeValue value1, value2;
if ( mLeft )
{
if ( !getValue( value1, mLeft, fields, attributes ) ) return value1;
if ( !getValue( value1, mLeft, fields, attributes, geom ) ) return value1;
}
if ( mRight )
{
if ( !getValue( value2, mRight, fields, attributes ) ) return value2;
if ( !getValue( value2, mRight, fields, attributes, geom ) ) return value2;
}

if ( mOp == opLENGTH || mOp == opAREA )
{
if ( !geom )
{
return QgsSearchTreeValue( 2, "Geometry is 0" );
}

//check that we don't use area for lines or length for polygons
if ( mOp == opLENGTH && geom->type() != QGis::Line )
{
return QgsSearchTreeValue( 0 );
}
if ( mOp == opAREA && geom->type() != QGis::Polygon )
{
return QgsSearchTreeValue( 0 );
}
return QgsSearchTreeValue( mCalc.measure( geom ) );
}

//string operations with one argument
if ( !mRight && !value1.isNumeric() )
{
if ( mOp == opTOINT )
{
return QgsSearchTreeValue( value1.string().toInt() );
}
else if ( mOp == opTOREAL )
{
return QgsSearchTreeValue( value1.string().toDouble() );
}
}

//don't convert to numbers in case of string concatenation
if ( mLeft && mRight && !value1.isNumeric() && !value2.isNumeric() )
{
if ( mOp == opPLUS )
{
return QgsSearchTreeValue( value1.string() + value2.string() );
}
}

// convert to numbers if needed
// for other operators, convert strings to numbers if needed
double val1, val2;
if ( value1.isNumeric() )
val1 = value1.number();
@@ -423,6 +478,12 @@ QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, c
return QgsSearchTreeValue( acos( val1 ) );
case opATAN:
return QgsSearchTreeValue( atan( val1 ) );
case opTOINT:
return QgsSearchTreeValue( int( val1 ) );
case opTOREAL:
return QgsSearchTreeValue( val1 );
case opTOSTRING:
return QgsSearchTreeValue( QString::number( val1 ) );
}
}

@@ -24,6 +24,7 @@
#include <QString>
#include <QVariant>

#include <qgsdistancearea.h>
#include <qgsfield.h>
#include <qgsfeature.h>

@@ -70,6 +71,11 @@ class CORE_EXPORT QgsSearchTreeNode
opASIN,
opACOS,
opATAN,
opTOINT,
opTOREAL,
opTOSTRING,
opLENGTH,
opAREA,

// comparison
opEQ, // =
@@ -126,13 +132,15 @@ class CORE_EXPORT QgsSearchTreeNode
//! returns error message
const QString& errorMsg() { return mError; }

//! returns scalar value of node
QgsSearchTreeValue valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes );

protected:
//! wrapper around valueAgainst()
bool getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node,
const QgsFieldMap& fields, const QgsAttributeMap& attributes );
const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom = 0 );

protected:


//! returns scalar value of node
QgsSearchTreeValue valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom = 0 );

//! strips mText when node is of string type
void stripText();
@@ -152,6 +160,9 @@ class CORE_EXPORT QgsSearchTreeNode
//! children
QgsSearchTreeNode* mLeft;
QgsSearchTreeNode* mRight;

/**For length() and area() functions*/
QgsDistanceArea mCalc;
};

// TODO: poslat do zvlast suboru

0 comments on commit 96ce43c

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