mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Reorganize code from qgsexpression.cpp
This commit is contained in:
parent
82455588c8
commit
80533faaf5
@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsExpressionFunction
|
||||
{
|
||||
%Docstring
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsExpressionNode /Abstract/
|
||||
{
|
||||
%Docstring
|
||||
|
@ -7,6 +7,8 @@
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsExpressionNodeUnaryOperator : QgsExpressionNode
|
||||
{
|
||||
%Docstring
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,18 @@
|
||||
/***************************************************************************
|
||||
qgsexpressionfunction.h
|
||||
-------------------
|
||||
begin : May 2017
|
||||
copyright : (C) 2017 Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSEXPRESSIONFUNCTION_H
|
||||
#define QGSEXPRESSIONFUNCTION_H
|
||||
|
||||
@ -421,6 +436,7 @@ class QgsStaticExpressionFunction : public QgsExpressionFunction
|
||||
*/
|
||||
void setPrepareFunction( std::function < bool( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) > prepareFunc );
|
||||
|
||||
static const QList<QgsExpressionFunction *> &functions();
|
||||
|
||||
private:
|
||||
FcnEval mFnc;
|
||||
|
@ -1 +1,51 @@
|
||||
/***************************************************************************
|
||||
qgsexpressionnode.cpp
|
||||
-------------------
|
||||
begin : May 2017
|
||||
copyright : (C) 2017 Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsexpressionnode.h"
|
||||
|
||||
|
||||
QVariant QgsExpressionNode::eval( QgsExpression *parent, const QgsExpressionContext *context )
|
||||
{
|
||||
if ( mHasCachedValue )
|
||||
{
|
||||
return mCachedStaticValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
QVariant res = evalNode( parent, context );
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsExpressionNode::prepare( QgsExpression *parent, const QgsExpressionContext *context )
|
||||
{
|
||||
if ( isStatic( parent, context ) )
|
||||
{
|
||||
mCachedStaticValue = evalNode( parent, context );
|
||||
mHasCachedValue = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mHasCachedValue = false;
|
||||
return prepareNode( parent, context );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsExpressionNode::cloneTo( QgsExpressionNode *target ) const
|
||||
{
|
||||
target->mHasCachedValue = mHasCachedValue;
|
||||
target->mCachedStaticValue = mCachedStaticValue;
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/***************************************************************************
|
||||
qgsexpressionnode.h
|
||||
-------------------
|
||||
begin : May 2017
|
||||
copyright : (C) 2017 Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef QGSEXPRESSIONNODE_H
|
||||
#define QGSEXPRESSIONNODE_H
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,19 @@
|
||||
/***************************************************************************
|
||||
qgsexpressionnodeimpl.h
|
||||
-------------------
|
||||
begin : May 2017
|
||||
copyright : (C) 2017 Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef QGSEXPRESSIONNODEIMPL_H
|
||||
#define QGSEXPRESSIONNODEIMPL_H
|
||||
|
||||
|
377
src/core/expression/qgsexpressionutils.h
Normal file
377
src/core/expression/qgsexpressionutils.h
Normal file
@ -0,0 +1,377 @@
|
||||
/***************************************************************************
|
||||
qgsexpressionutils.cpp
|
||||
-------------------
|
||||
begin : May 2017
|
||||
copyright : (C) 2017 Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef QGSEXPRESSIONUTILS_H
|
||||
#define QGSEXPRESSIONUTILS_H
|
||||
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsrelationmanager.h"
|
||||
|
||||
|
||||
#define ENSURE_NO_EVAL_ERROR { if ( parent->hasEvalError() ) return QVariant(); }
|
||||
#define SET_EVAL_ERROR(x) { parent->setEvalErrorString( x ); return QVariant(); }
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// three-value logic
|
||||
|
||||
enum TVL
|
||||
{
|
||||
False,
|
||||
True,
|
||||
Unknown
|
||||
};
|
||||
|
||||
|
||||
static TVL AND[3][3] =
|
||||
{
|
||||
// false true unknown
|
||||
{ False, False, False }, // false
|
||||
{ False, True, Unknown }, // true
|
||||
{ False, Unknown, Unknown } // unknown
|
||||
};
|
||||
|
||||
static TVL OR[3][3] =
|
||||
{
|
||||
{ False, True, Unknown }, // false
|
||||
{ True, True, True }, // true
|
||||
{ Unknown, True, Unknown } // unknown
|
||||
};
|
||||
|
||||
static TVL NOT[3] = { True, False, Unknown };
|
||||
|
||||
static QVariant tvl2variant( TVL v )
|
||||
{
|
||||
switch ( v )
|
||||
{
|
||||
case False:
|
||||
return 0;
|
||||
case True:
|
||||
return 1;
|
||||
case Unknown:
|
||||
default:
|
||||
return QVariant( QVariant::Int );
|
||||
}
|
||||
}
|
||||
|
||||
#define TVL_True QVariant( true )
|
||||
#define TVL_False QVariant( false )
|
||||
#define TVL_Unknown QVariant( QVariant::Int )
|
||||
|
||||
// this handles also NULL values
|
||||
static TVL getTVLValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
// we need to convert to TVL
|
||||
if ( value.isNull() )
|
||||
return Unknown;
|
||||
|
||||
//handle some special cases
|
||||
if ( value.canConvert<QgsGeometry>() )
|
||||
{
|
||||
//geom is false if empty
|
||||
QgsGeometry geom = value.value<QgsGeometry>();
|
||||
return geom.isNull() ? False : True;
|
||||
}
|
||||
else if ( value.canConvert<QgsFeature>() )
|
||||
{
|
||||
//feat is false if non-valid
|
||||
QgsFeature feat = value.value<QgsFeature>();
|
||||
return feat.isValid() ? True : False;
|
||||
}
|
||||
|
||||
if ( value.type() == QVariant::Int )
|
||||
return value.toInt() != 0 ? True : False;
|
||||
|
||||
bool ok;
|
||||
double x = value.toDouble( &ok );
|
||||
if ( !ok )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to boolean" ).arg( value.toString() ) );
|
||||
return Unknown;
|
||||
}
|
||||
return !qgsDoubleNear( x, 0.0 ) ? True : False;
|
||||
}
|
||||
|
||||
|
||||
inline bool isIntSafe( const QVariant &v )
|
||||
{
|
||||
if ( v.type() == QVariant::Int )
|
||||
return true;
|
||||
if ( v.type() == QVariant::UInt )
|
||||
return true;
|
||||
if ( v.type() == QVariant::LongLong )
|
||||
return true;
|
||||
if ( v.type() == QVariant::ULongLong )
|
||||
return true;
|
||||
if ( v.type() == QVariant::Double )
|
||||
return false;
|
||||
if ( v.type() == QVariant::String )
|
||||
{
|
||||
bool ok;
|
||||
v.toString().toInt( &ok );
|
||||
return ok;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool isDoubleSafe( const QVariant &v )
|
||||
{
|
||||
if ( v.type() == QVariant::Double )
|
||||
return true;
|
||||
if ( v.type() == QVariant::Int )
|
||||
return true;
|
||||
if ( v.type() == QVariant::UInt )
|
||||
return true;
|
||||
if ( v.type() == QVariant::LongLong )
|
||||
return true;
|
||||
if ( v.type() == QVariant::ULongLong )
|
||||
return true;
|
||||
if ( v.type() == QVariant::String )
|
||||
{
|
||||
bool ok;
|
||||
double val = v.toString().toDouble( &ok );
|
||||
ok = ok && qIsFinite( val ) && !qIsNaN( val );
|
||||
return ok;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isDateTimeSafe( const QVariant &v )
|
||||
{
|
||||
return v.type() == QVariant::DateTime
|
||||
|| v.type() == QVariant::Date
|
||||
|| v.type() == QVariant::Time;
|
||||
}
|
||||
|
||||
inline bool isIntervalSafe( const QVariant &v )
|
||||
{
|
||||
if ( v.canConvert<QgsInterval>() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( v.type() == QVariant::String )
|
||||
{
|
||||
return QgsInterval::fromString( v.toString() ).isValid();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isNull( const QVariant &v )
|
||||
{
|
||||
return v.isNull();
|
||||
}
|
||||
|
||||
inline bool isList( const QVariant &v )
|
||||
{
|
||||
return v.type() == QVariant::List;
|
||||
}
|
||||
|
||||
// implicit conversion to string
|
||||
static QString getStringValue( const QVariant &value, QgsExpression * )
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
static double getDoubleValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
bool ok;
|
||||
double x = value.toDouble( &ok );
|
||||
if ( !ok || qIsNaN( x ) || !qIsFinite( x ) )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to double" ).arg( value.toString() ) );
|
||||
return 0;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static qlonglong getIntValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
bool ok;
|
||||
qlonglong x = value.toLongLong( &ok );
|
||||
if ( ok )
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to int" ).arg( value.toString() ) );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int getNativeIntValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
bool ok;
|
||||
qlonglong x = value.toLongLong( &ok );
|
||||
if ( ok && x >= std::numeric_limits<int>::min() && x <= std::numeric_limits<int>::max() )
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to native int" ).arg( value.toString() ) );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static QDateTime getDateTimeValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
QDateTime d = value.toDateTime();
|
||||
if ( d.isValid() )
|
||||
{
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTime t = value.toTime();
|
||||
if ( t.isValid() )
|
||||
{
|
||||
return QDateTime( QDate( 1, 1, 1 ), t );
|
||||
}
|
||||
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to DateTime" ).arg( value.toString() ) );
|
||||
return QDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
static QDate getDateValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
QDate d = value.toDate();
|
||||
if ( d.isValid() )
|
||||
{
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Date" ).arg( value.toString() ) );
|
||||
return QDate();
|
||||
}
|
||||
}
|
||||
|
||||
static QTime getTimeValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
QTime t = value.toTime();
|
||||
if ( t.isValid() )
|
||||
{
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Time" ).arg( value.toString() ) );
|
||||
return QTime();
|
||||
}
|
||||
}
|
||||
|
||||
static QgsInterval getInterval( const QVariant &value, QgsExpression *parent, bool report_error = false )
|
||||
{
|
||||
if ( value.canConvert<QgsInterval>() )
|
||||
return value.value<QgsInterval>();
|
||||
|
||||
QgsInterval inter = QgsInterval::fromString( value.toString() );
|
||||
if ( inter.isValid() )
|
||||
{
|
||||
return inter;
|
||||
}
|
||||
// If we get here then we can't convert so we just error and return invalid.
|
||||
if ( report_error )
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to Interval" ).arg( value.toString() ) );
|
||||
|
||||
return QgsInterval();
|
||||
}
|
||||
|
||||
static QgsGeometry getGeometry( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
if ( value.canConvert<QgsGeometry>() )
|
||||
return value.value<QgsGeometry>();
|
||||
|
||||
parent->setEvalErrorString( QStringLiteral( "Cannot convert to QgsGeometry" ) );
|
||||
return QgsGeometry();
|
||||
}
|
||||
|
||||
static QgsFeature getFeature( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
if ( value.canConvert<QgsFeature>() )
|
||||
return value.value<QgsFeature>();
|
||||
|
||||
parent->setEvalErrorString( QStringLiteral( "Cannot convert to QgsFeature" ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QgsExpressionNode *getNode( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
if ( value.canConvert<QgsExpressionNode *>() )
|
||||
return value.value<QgsExpressionNode *>();
|
||||
|
||||
parent->setEvalErrorString( QStringLiteral( "Cannot convert to Node" ) );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsVectorLayer *getVectorLayer( const QVariant &value, QgsExpression * )
|
||||
{
|
||||
QgsMapLayer *ml = value.value< QgsWeakMapLayerPointer >().data();
|
||||
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
|
||||
if ( !vl )
|
||||
{
|
||||
QString layerString = value.toString();
|
||||
vl = qobject_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( layerString ) ); //search by id first
|
||||
|
||||
if ( !vl )
|
||||
{
|
||||
QList<QgsMapLayer *> layersByName = QgsProject::instance()->mapLayersByName( layerString );
|
||||
if ( !layersByName.isEmpty() )
|
||||
{
|
||||
vl = qobject_cast<QgsVectorLayer *>( layersByName.at( 0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vl;
|
||||
}
|
||||
|
||||
|
||||
static QVariantList getListValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
|
||||
{
|
||||
return value.toList();
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to array" ).arg( value.toString() ) );
|
||||
return QVariantList();
|
||||
}
|
||||
}
|
||||
|
||||
static QVariantMap getMapValue( const QVariant &value, QgsExpression *parent )
|
||||
{
|
||||
if ( value.type() == QVariant::Map )
|
||||
{
|
||||
return value.toMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to map" ).arg( value.toString() ) );
|
||||
return QVariantMap();
|
||||
}
|
||||
}
|
||||
|
||||
#define FEAT_FROM_CONTEXT(c, f) if (!(c) || !(c)->hasFeature() ) return QVariant(); \
|
||||
QgsFeature f = ( c )->feature();
|
||||
|
||||
#endif // QGSEXPRESSIONUTILS_H
|
@ -23,6 +23,7 @@
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsdistancearea.h"
|
||||
#include "qgsunittypes.h"
|
||||
#include "qgsexpressionnode.h"
|
||||
|
||||
///@cond
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user