From bf86521d49223e25821a1fac8578d45998c8a3bb Mon Sep 17 00:00:00 2001 From: Martin Dobias Date: Sat, 2 Jun 2012 00:04:01 +0200 Subject: [PATCH] Fixes for refinement of rules. - quoting of columns (#5536 and #5542) - quoting of string - do not quote of numbers (avoids type cast during evaluation) - use at least 4 floating point digits for doubles --- python/core/qgsexpression.sip | 2 ++ src/core/qgsexpression.h | 2 ++ .../symbology-ng/qgsrulebasedrendererv2.cpp | 20 +++++++++++++++++-- .../qgsgraduatedsymbolrendererv2widget.cpp | 4 ++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/python/core/qgsexpression.sip b/python/core/qgsexpression.sip index 532dfd4dea15..f2826872195b 100644 --- a/python/core/qgsexpression.sip +++ b/python/core/qgsexpression.sip @@ -122,6 +122,8 @@ public: //! return quoted column reference (in double quotes) static QString quotedColumnRef( QString name ); + //! return quoted string (in single quotes) + static QString quotedString( QString text ); ////// diff --git a/src/core/qgsexpression.h b/src/core/qgsexpression.h index 617ae6d9d042..0fe53119c745 100644 --- a/src/core/qgsexpression.h +++ b/src/core/qgsexpression.h @@ -209,6 +209,8 @@ class CORE_EXPORT QgsExpression //! return quoted column reference (in double quotes) static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); } + //! return quoted string (in single quotes) + static QString quotedString( QString text ) { return QString( "'%1'" ).arg( text.replace( "'", "''" ) ); } ////// diff --git a/src/core/symbology-ng/qgsrulebasedrendererv2.cpp b/src/core/symbology-ng/qgsrulebasedrendererv2.cpp index d9b26cecd79e..84799cd65110 100644 --- a/src/core/symbology-ng/qgsrulebasedrendererv2.cpp +++ b/src/core/symbology-ng/qgsrulebasedrendererv2.cpp @@ -803,7 +803,18 @@ void QgsRuleBasedRendererV2::refineRuleCategories( QgsRuleBasedRendererV2::Rule* { foreach( const QgsRendererCategoryV2& cat, r->categories() ) { - QString filter = QString( "%1 = '%2'" ).arg( r->classAttribute() ).arg( cat.value().toString() ); + QString attr = QgsExpression::quotedColumnRef( r->classAttribute() ); + QString value; + // not quoting numbers saves a type cast + if ( cat.value().type() == QVariant::Int ) + value = cat.value().toString(); + else if ( cat.value().type() == QVariant::Double ) + // we loose precision here - so we may miss some categories :-( + // TODO: have a possibility to construct expressions directly as a parse tree to avoid loss of precision + value = QString::number( cat.value().toDouble(), 'f', 4 ); + else + value = QgsExpression::quotedString( cat.value().toString() ); + QString filter = QString( "%1 = %2" ).arg( attr ).arg( value ); QString label = filter; initialRule->appendChild( new Rule( cat.symbol()->clone(), 0, 0, filter, label ) ); } @@ -813,7 +824,12 @@ void QgsRuleBasedRendererV2::refineRuleRanges( QgsRuleBasedRendererV2::Rule* ini { foreach( const QgsRendererRangeV2& rng, r->ranges() ) { - QString filter = QString( "%1 >= '%2' AND %1 <= '%3'" ).arg( r->classAttribute() ).arg( rng.lowerValue() ).arg( rng.upperValue() ); + // due to the loss of precision in double->string conversion we may miss out values at the limit of the range + // TODO: have a possibility to construct expressions directly as a parse tree to avoid loss of precision + QString attr = QgsExpression::quotedColumnRef( r->classAttribute() ); + QString filter = QString( "%1 >= %2 AND %1 <= %3" ).arg( attr ) + .arg( QString::number( rng.lowerValue(), 'f', 4 ) ) + .arg( QString::number( rng.upperValue(), 'f', 4 ) ); QString label = filter; initialRule->appendChild( new Rule( rng.symbol()->clone(), 0, 0, filter, label ) ); } diff --git a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp index 1b5db8447b7e..63aabd07d934 100644 --- a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp +++ b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp @@ -325,8 +325,8 @@ void QgsGraduatedSymbolRendererV2Widget::changeRange( int rangeIdx ) QgsLUDialog dialog( this ); const QgsRendererRangeV2& range = mRenderer->ranges()[rangeIdx]; - dialog.setLowerValue( QString( "%1" ).arg( range.lowerValue() ) ); - dialog.setUpperValue( QString( "%1" ).arg( range.upperValue() ) ); + dialog.setLowerValue( QString::number( range.lowerValue(), 'f', 4 ) ); + dialog.setUpperValue( QString::number( range.upperValue(), 'f', 4 ) ); if ( dialog.exec() == QDialog::Accepted ) {