mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
371 lines
11 KiB
C++
371 lines
11 KiB
C++
/***************************************************************************
|
|
qgsfield.cpp - Describes a field in a layer or table
|
|
--------------------------------------
|
|
Date : 01-Jan-2004
|
|
Copyright : (C) 2004 by Gary E.Sherman
|
|
email : sherman at mrcc.com
|
|
|
|
***************************************************************************
|
|
* *
|
|
* 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 "qgsfields.h"
|
|
#include "qgsfield_p.h"
|
|
#include "qgis.h"
|
|
#include "qgsapplication.h"
|
|
|
|
#include <QSettings>
|
|
#include <QDataStream>
|
|
#include <QtCore/qmath.h>
|
|
#include <QIcon>
|
|
|
|
/***************************************************************************
|
|
* This class is considered CRITICAL and any change MUST be accompanied with
|
|
* full unit tests in testqgsfield.cpp.
|
|
* See details in QEP #17
|
|
****************************************************************************/
|
|
|
|
#if 0
|
|
QgsField::QgsField( QString nam, QString typ, int len, int prec, bool num,
|
|
QString comment )
|
|
: mName( nam ), mType( typ ), mLength( len ), mPrecision( prec ), mNumeric( num )
|
|
, mComment( comment )
|
|
{
|
|
// This function used to lower case the field name since some stores
|
|
// use upper case (eg. shapefiles), but that caused problems with
|
|
// attribute actions getting confused between uppercase and
|
|
// lowercase versions of the attribute names, so just leave the
|
|
// names how they are now.
|
|
}
|
|
#endif
|
|
QgsField::QgsField( const QString& name, QVariant::Type type,
|
|
const QString& typeName, int len, int prec, const QString& comment,
|
|
QVariant::Type subType )
|
|
{
|
|
d = new QgsFieldPrivate( name, type, subType, typeName, len, prec, comment );
|
|
}
|
|
|
|
QgsField::QgsField( const QgsField &other )
|
|
: d( other.d )
|
|
{
|
|
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This class is considered CRITICAL and any change MUST be accompanied with
|
|
* full unit tests in testqgsfield.cpp.
|
|
* See details in QEP #17
|
|
****************************************************************************/
|
|
|
|
QgsField &QgsField::operator =( const QgsField & other )
|
|
{
|
|
d = other.d;
|
|
return *this;
|
|
}
|
|
|
|
QgsField::~QgsField()
|
|
{
|
|
}
|
|
|
|
bool QgsField::operator==( const QgsField& other ) const
|
|
{
|
|
return *( other.d ) == *d;
|
|
}
|
|
|
|
bool QgsField::operator!=( const QgsField& other ) const
|
|
{
|
|
return !( *this == other );
|
|
}
|
|
|
|
QString QgsField::name() const
|
|
{
|
|
return d->name;
|
|
}
|
|
|
|
QString QgsField::displayName() const
|
|
{
|
|
if ( !d->alias.isEmpty() )
|
|
return d->alias;
|
|
else
|
|
return d->name;
|
|
}
|
|
|
|
QVariant::Type QgsField::type() const
|
|
{
|
|
return d->type;
|
|
}
|
|
|
|
QVariant::Type QgsField::subType() const
|
|
{
|
|
return d->subType;
|
|
}
|
|
|
|
QString QgsField::typeName() const
|
|
{
|
|
return d->typeName;
|
|
}
|
|
|
|
int QgsField::length() const
|
|
{
|
|
return d->length;
|
|
}
|
|
|
|
int QgsField::precision() const
|
|
{
|
|
return d->precision;
|
|
}
|
|
|
|
QString QgsField::comment() const
|
|
{
|
|
return d->comment;
|
|
}
|
|
|
|
bool QgsField::isNumeric() const
|
|
{
|
|
return d->type == QVariant::Double || d->type == QVariant::Int || d->type == QVariant::UInt || d->type == QVariant::LongLong || d->type == QVariant::ULongLong;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This class is considered CRITICAL and any change MUST be accompanied with
|
|
* full unit tests in testqgsfield.cpp.
|
|
* See details in QEP #17
|
|
****************************************************************************/
|
|
|
|
void QgsField::setName( const QString& name )
|
|
{
|
|
d->name = name;
|
|
}
|
|
|
|
void QgsField::setType( QVariant::Type type )
|
|
{
|
|
d->type = type;
|
|
}
|
|
|
|
void QgsField::setSubType( QVariant::Type subType )
|
|
{
|
|
d->subType = subType;
|
|
}
|
|
|
|
void QgsField::setTypeName( const QString& typeName )
|
|
{
|
|
d->typeName = typeName;
|
|
}
|
|
|
|
void QgsField::setLength( int len )
|
|
{
|
|
d->length = len;
|
|
}
|
|
void QgsField::setPrecision( int precision )
|
|
{
|
|
d->precision = precision;
|
|
}
|
|
|
|
void QgsField::setComment( const QString& comment )
|
|
{
|
|
d->comment = comment;
|
|
}
|
|
|
|
QString QgsField::defaultValueExpression() const
|
|
{
|
|
return d->defaultValueExpression;
|
|
}
|
|
|
|
void QgsField::setDefaultValueExpression( const QString& expression )
|
|
{
|
|
d->defaultValueExpression = expression;
|
|
}
|
|
|
|
void QgsField::setConstraints( const QgsFieldConstraints& constraints )
|
|
{
|
|
d->constraints = constraints;
|
|
}
|
|
|
|
const QgsFieldConstraints& QgsField::constraints() const
|
|
{
|
|
return d->constraints;
|
|
}
|
|
|
|
QString QgsField::alias() const
|
|
{
|
|
return d->alias;
|
|
}
|
|
|
|
void QgsField::setAlias( const QString& alias )
|
|
{
|
|
d->alias = alias;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This class is considered CRITICAL and any change MUST be accompanied with
|
|
* full unit tests in testqgsfield.cpp.
|
|
* See details in QEP #17
|
|
****************************************************************************/
|
|
|
|
QString QgsField::displayString( const QVariant& v ) const
|
|
{
|
|
if ( v.isNull() )
|
|
{
|
|
QSettings settings;
|
|
return QgsApplication::nullRepresentation();
|
|
}
|
|
|
|
if ( d->type == QVariant::Double && d->precision > 0 )
|
|
return QString::number( v.toDouble(), 'f', d->precision );
|
|
|
|
return v.toString();
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This class is considered CRITICAL and any change MUST be accompanied with
|
|
* full unit tests in testqgsfield.cpp.
|
|
* See details in QEP #17
|
|
****************************************************************************/
|
|
|
|
bool QgsField::convertCompatible( QVariant& v ) const
|
|
{
|
|
if ( v.isNull() )
|
|
{
|
|
v.convert( d->type );
|
|
return true;
|
|
}
|
|
|
|
if ( d->type == QVariant::Int && v.toInt() != v.toLongLong() )
|
|
{
|
|
v = QVariant( d->type );
|
|
return false;
|
|
}
|
|
|
|
//String representations of doubles in QVariant will return false to convert( QVariant::Int )
|
|
//work around this by first converting to double, and then checking whether the double is convertible to int
|
|
if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
|
|
{
|
|
bool ok = false;
|
|
double dbl = v.toDouble( &ok );
|
|
if ( !ok )
|
|
{
|
|
//couldn't convert to number
|
|
v = QVariant( d->type );
|
|
return false;
|
|
}
|
|
|
|
double round = qgsRound( dbl );
|
|
if ( round > INT_MAX || round < -INT_MAX )
|
|
{
|
|
//double too large to fit in int
|
|
v = QVariant( d->type );
|
|
return false;
|
|
}
|
|
v = QVariant( qRound( dbl ) );
|
|
return true;
|
|
}
|
|
|
|
if ( !v.convert( d->type ) )
|
|
{
|
|
v = QVariant( d->type );
|
|
return false;
|
|
}
|
|
|
|
if ( d->type == QVariant::Double && d->precision > 0 )
|
|
{
|
|
double s = qPow( 10, d->precision );
|
|
double d = v.toDouble() * s;
|
|
v = QVariant(( d < 0 ? ceil( d - 0.5 ) : floor( d + 0.5 ) ) / s );
|
|
return true;
|
|
}
|
|
|
|
if ( d->type == QVariant::String && d->length > 0 && v.toString().length() > d->length )
|
|
{
|
|
v = v.toString().left( d->length );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void QgsField::setEditorWidgetSetup( const QgsEditorWidgetSetup& v )
|
|
{
|
|
d->editorWidgetSetup = v;
|
|
}
|
|
|
|
QgsEditorWidgetSetup QgsField::editorWidgetSetup() const
|
|
{
|
|
return d->editorWidgetSetup;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* This class is considered CRITICAL and any change MUST be accompanied with
|
|
* full unit tests in testqgsfield.cpp.
|
|
* See details in QEP #17
|
|
****************************************************************************/
|
|
|
|
QDataStream& operator<<( QDataStream& out, const QgsField& field )
|
|
{
|
|
out << field.name();
|
|
out << static_cast< quint32 >( field.type() );
|
|
out << field.typeName();
|
|
out << field.length();
|
|
out << field.precision();
|
|
out << field.comment();
|
|
out << field.alias();
|
|
out << field.defaultValueExpression();
|
|
out << field.constraints().constraints();
|
|
out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintNotNull ) );
|
|
out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintUnique ) );
|
|
out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintExpression ) );
|
|
out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
|
|
out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
|
|
out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
|
|
out << field.constraints().constraintExpression();
|
|
out << field.constraints().constraintDescription();
|
|
out << static_cast< quint32 >( field.subType() );
|
|
return out;
|
|
}
|
|
|
|
QDataStream& operator>>( QDataStream& in, QgsField& field )
|
|
{
|
|
quint32 type, subType, length, precision, constraints, originNotNull, originUnique, originExpression, strengthNotNull, strengthUnique, strengthExpression;
|
|
QString name, typeName, comment, alias, defaultValueExpression, constraintExpression, constraintDescription;
|
|
in >> name >> type >> typeName >> length >> precision >> comment >> alias
|
|
>> defaultValueExpression >> constraints >> originNotNull >> originUnique >> originExpression >> strengthNotNull >> strengthUnique >> strengthExpression >>
|
|
constraintExpression >> constraintDescription >> subType;
|
|
field.setName( name );
|
|
field.setType( static_cast< QVariant::Type >( type ) );
|
|
field.setTypeName( typeName );
|
|
field.setLength( static_cast< int >( length ) );
|
|
field.setPrecision( static_cast< int >( precision ) );
|
|
field.setComment( comment );
|
|
field.setAlias( alias );
|
|
field.setDefaultValueExpression( defaultValueExpression );
|
|
QgsFieldConstraints fieldConstraints;
|
|
if ( constraints & QgsFieldConstraints::ConstraintNotNull )
|
|
{
|
|
fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintNotNull, static_cast< QgsFieldConstraints::ConstraintOrigin>( originNotNull ) );
|
|
fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintNotNull, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthNotNull ) );
|
|
}
|
|
else
|
|
fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintNotNull );
|
|
if ( constraints & QgsFieldConstraints::ConstraintUnique )
|
|
{
|
|
fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintUnique, static_cast< QgsFieldConstraints::ConstraintOrigin>( originUnique ) );
|
|
fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintUnique, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthUnique ) );
|
|
}
|
|
else
|
|
fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintUnique );
|
|
if ( constraints & QgsFieldConstraints::ConstraintExpression )
|
|
{
|
|
fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintExpression, static_cast< QgsFieldConstraints::ConstraintOrigin>( originExpression ) );
|
|
fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintExpression, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthExpression ) );
|
|
}
|
|
else
|
|
fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintExpression );
|
|
fieldConstraints.setConstraintExpression( constraintExpression, constraintDescription );
|
|
field.setConstraints( fieldConstraints );
|
|
field.setSubType( static_cast< QVariant::Type >( subType ) );
|
|
return in;
|
|
}
|