Skip to content

Commit

Permalink
Convert values to target field format
Browse files Browse the repository at this point in the history
For the field calculator and virtual fields.

Fix #11000
Fix #10995
Fix #10993
  • Loading branch information
m-kuhn committed Oct 6, 2014
1 parent 11e3044 commit 7318c73
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
59 changes: 59 additions & 0 deletions python/core/qgsfield.sip
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,65 @@ public:

/**Formats string for display*/
QString displayString( const QVariant& v ) const;


/**
* Converts the provided variant to a compatible format
*
* @param v The value to convert
*
* @return True if the conversion was successful
*/
QVariant convertCompatible( QVariant& v ) const;
%MethodCode
PyObject *sipParseErr = NULL;

{
QVariant * a0;
int a0State = 0;
const QgsField *sipCpp;

if (sipParseArgs(&sipParseErr, sipArgs, "BJ1", &sipSelf, sipType_QgsField, &sipCpp, sipType_QVariant,&a0, &a0State))
{
bool sipRes;

Py_BEGIN_ALLOW_THREADS
try
{
QgsDebugMsg( a0->toString() );
sipRes = sipCpp->convertCompatible(*a0);
QgsDebugMsg( a0->toString() );
}
catch (...)
{
Py_BLOCK_THREADS

sipReleaseType(a0,sipType_QVariant,a0State);
sipRaiseUnknownException();
return NULL;
}

Py_END_ALLOW_THREADS

PyObject* res = sipConvertFromType( a0, sipType_QVariant, NULL );
sipReleaseType(a0,sipType_QVariant,a0State);

if ( !sipRes )
{
PyErr_SetString(PyExc_ValueError,
QString( "Value %1 (%2) could not be converted to field type %3." ).arg( a0->toString() ).arg ( a0->typeName() ).arg( sipCpp->type() ).toUtf8().constData() );
sipError = sipErrorFail;
}

return res;
}
}

/* Raise an exception if the arguments couldn't be parsed. */
sipNoMethod(sipParseErr, sipName_QgsField, sipName_convertCompatible, doc_QgsField_convertCompatible);

return NULL;
%End
}; // class QgsField


Expand Down
6 changes: 4 additions & 2 deletions src/app/qgsfieldcalculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ void QgsFieldCalculator::accept()
return;
}

const QgsField& field = mVectorLayer->pendingFields()[mAttributeId];

QApplication::setOverrideCursor( Qt::WaitCursor );

mVectorLayer->beginEditCommand( "Field calculator" );
Expand Down Expand Up @@ -198,7 +200,7 @@ void QgsFieldCalculator::accept()
bool newField = !mUpdateExistingGroupBox->isChecked();
QVariant emptyAttribute;
if ( newField )
emptyAttribute = QVariant( mVectorLayer->pendingFields()[mAttributeId].type() );
emptyAttribute = QVariant( field.type() );

QgsFeatureIterator fit = mVectorLayer->getFeatures( QgsFeatureRequest().setFlags( useGeometry ? QgsFeatureRequest::NoFlags : QgsFeatureRequest::NoGeometry ) );
while ( fit.nextFeature( feature ) )
Expand All @@ -210,9 +212,9 @@ void QgsFieldCalculator::accept()
continue;
}
}

exp.setCurrentRowNumber( rownum );
QVariant value = exp.evaluate( &feature );
field.convertCompatible( value );
if ( exp.hasEvalError() )
{
calculationSuccess = false;
Expand Down
22 changes: 22 additions & 0 deletions src/core/qgsfield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "qgsfield.h"

#include <QSettings>
#include <QtCore/qmath.h>

#if 0
QgsField::QgsField( QString nam, QString typ, int len, int prec, bool num,
Expand Down Expand Up @@ -128,6 +129,27 @@ QString QgsField::displayString( const QVariant& v ) const
return v.toString();
}

bool QgsField::convertCompatible( QVariant& v ) const
{
if ( v.isNull() )
{
v.convert( mType );
return true;
}

if ( !v.convert( mType ) )
{
return false;
}

if ( mType == QVariant::Double && mPrecision > 0 )
{
v = qRound64( v.toDouble() * qPow( 10, mPrecision ) ) / qPow( 10, mPrecision );
return true;
}

return true;
}

////////////////////////////////////////////////////////////////////////////

Expand Down
9 changes: 9 additions & 0 deletions src/core/qgsfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ class CORE_EXPORT QgsField
/** Formats string for display*/
QString displayString( const QVariant& v ) const;

/**
* Converts the provided variant to a compatible format
*
* @param v The value to convert
*
* @return True if the conversion was successful
*/
bool convertCompatible( QVariant& v ) const;

private:

//! Name
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsvectorlayerfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ void QgsVectorLayerFeatureIterator::addVirtualAttributes( QgsFeature& f )
{
QgsExpression* exp = it.value();
QVariant val = exp->evaluate( f );
mSource->mFields.at( it.key() ).convertCompatible( val );;
f.setAttribute( it.key(), val );
}
}
Expand Down

0 comments on commit 7318c73

Please sign in to comment.