double QgsScaleComboBox::toDouble( const QString &scaleString, bool *returnOk ) { bool ok = false; QString scaleTxt( scaleString ); double denominator = qgsPermissiveToDouble( scaleTxt, ok ); double scale = !qgsDoubleNear( denominator, 0.0 ) ? 1.0 / denominator : 0.0; if ( ok ) { // Create a text version and set that text and rescan // Idea is to get the same rounding. scaleTxt = toString( scale ); } else { // It is now either X:Y or not valid QStringList txtList = scaleTxt.split( ':' ); if ( 2 == txtList.size() ) { bool okX = false; bool okY = false; int x = qgsPermissiveToInt( txtList[ 0 ], okX ); int y = qgsPermissiveToInt( txtList[ 1 ], okY ); if ( okX && okY && x != 0 ) { // Scale is fraction of x and y scale = static_cast< double >( y ) / static_cast< double >( x ); ok = true; } } } // Set up optional return flag if ( returnOk ) { *returnOk = ok; } return scale; }
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; } // Give it a chance to convert to double since for not '.' locales // we accept both comma and dot as decimal point if ( d->type == QVariant::Double && v.type() == QVariant::String ) { QVariant tmp( v ); if ( !tmp.convert( d->type ) ) { // This might be a string with thousand separator: use locale to convert bool ok = false; double d = qgsPermissiveToDouble( v.toString(), ok ); if ( ok ) { v = QVariant( d ); return true; } // For not 'dot' locales, we also want to accept '.' if ( QLocale().decimalPoint() != '.' ) { d = QLocale( QLocale::C ).toDouble( v.toString(), &ok ); if ( ok ) { v = QVariant( d ); return true; } } } } // For string representation of an int we also might have thousand separator if ( d->type == QVariant::Int && v.type() == QVariant::String ) { QVariant tmp( v ); if ( !tmp.convert( d->type ) ) { // This might be a string with thousand separator: use locale to convert bool ok; int i = qgsPermissiveToInt( v.toString(), ok ); if ( ok ) { v = QVariant( i ); return true; } } } // For string representation of a long we also might have thousand separator if ( d->type == QVariant::LongLong && v.type() == QVariant::String ) { QVariant tmp( v ); if ( !tmp.convert( d->type ) ) { // This might be a string with thousand separator: use locale to convert bool ok; qlonglong l = qgsPermissiveToLongLong( v.toString(), ok ); if ( ok ) { v = QVariant( l ); return true; } } } //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 = std::round( dbl ); if ( round > std::numeric_limits<int>::max() || round < -std::numeric_limits<int>::max() ) { //double too large to fit in int v = QVariant( d->type ); return false; } v = QVariant( static_cast< int >( std::round( dbl ) ) ); return true; } if ( !v.convert( d->type ) ) { v = QVariant( d->type ); return false; } if ( d->type == QVariant::Double && d->precision > 0 ) { double s = std::pow( 10, d->precision ); double d = v.toDouble() * s; v = QVariant( ( d < 0 ? std::ceil( d - 0.5 ) : std::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; }