Skip to content
Permalink
Browse files
Fix multiple localization issues with vector renderers
Fix #45582
  • Loading branch information
elpaso committed Oct 22, 2021
1 parent b89cda5 commit 51be34ee5d91b006104c70c71c59d30da521fbfc
@@ -456,6 +456,20 @@ configuration.
.. versionadded:: 3.6
%End

static QString displayString( const QVariant &value, int precision = -1 );
%Docstring
Returns a localized representation of ``value`` with the given ``precision``,
if precision is -1 then precision is guessed from the default QVariant.toString
output.

.. note::

Precision is ignored for integers.

.. versionadded:: 3.21
%End


protected:


@@ -18,8 +18,22 @@ class QgsLUDialog: QDialog
public:
QgsLUDialog( QWidget *parent /TransferThis/ = 0, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
QString lowerValue() const;

double lowerValueDouble() const;
%Docstring
Returns the lower value.

.. versionadded:: 3.21
%End
void setLowerValue( const QString &val );
QString upperValue() const;

double upperValueDouble() const;
%Docstring
Returns the upper value.

.. versionadded:: 3.21
%End
void setUpperValue( const QString &val );
};

@@ -343,5 +343,5 @@ QString QgsClassificationMethod::labelForRange( const double lowerValue, const d
const QString lowerLabel = valueToLabel( lowerValue );
const QString upperLabel = valueToLabel( upperValue );

return labelFormat().arg( lowerLabel ).arg( upperLabel );
return labelFormat().arg( lowerLabel, upperLabel );
}
@@ -865,6 +865,111 @@ QgsLegendSymbolList QgsCategorizedSymbolRenderer::baseLegendSymbolItems() const
return lst;
}

QString QgsCategorizedSymbolRenderer::displayString( const QVariant &v, int precision )
{
if ( v.isNull() )
{
return QgsApplication::nullRepresentation();
}

const bool isNumeric {v.type() == QVariant::Double || v.type() == QVariant::Int || v.type() == QVariant::UInt || v.type() == QVariant::LongLong || v.type() == QVariant::ULongLong};

// Special treatment for numeric types if group separator is set or decimalPoint is not a dot
if ( v.type() == QVariant::Double )
{
// if value doesn't contain a double (a default value expression for instance),
// apply no transformation
bool ok;
v.toDouble( &ok );
if ( !ok )
return v.toString();

// Locales with decimal point != '.' or that require group separator: use QLocale
if ( QLocale().decimalPoint() != '.' ||
!( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
{
if ( precision > 0 )
{
if ( -1 < v.toDouble() && v.toDouble() < 1 )
{
return QLocale().toString( v.toDouble(), 'g', precision );
}
else
{
return QLocale().toString( v.toDouble(), 'f', precision );
}
}
else
{
// Precision is not set, let's guess it from the
// standard conversion to string
const QString s( v.toString() );
const int dotPosition( s.indexOf( '.' ) );
int precision;
if ( dotPosition < 0 && s.indexOf( 'e' ) < 0 )
{
precision = 0;
return QLocale().toString( v.toDouble(), 'f', precision );
}
else
{
if ( dotPosition < 0 ) precision = 0;
else precision = s.length() - dotPosition - 1;

if ( -1 < v.toDouble() && v.toDouble() < 1 )
{
return QLocale().toString( v.toDouble(), 'g', precision );
}
else
{
return QLocale().toString( v.toDouble(), 'f', precision );
}
}
}
}
// Default for doubles with precision
else if ( precision > 0 )
{
if ( -1 < v.toDouble() && v.toDouble() < 1 )
{
return QString::number( v.toDouble(), 'g', precision );
}
else
{
return QString::number( v.toDouble(), 'f', precision );
}
}
}
// Other numeric types than doubles
else if ( isNumeric &&
!( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
{
bool ok;
const qlonglong converted( v.toLongLong( &ok ) );
if ( ok )
return QLocale().toString( converted );
}
else if ( v.type() == QVariant::ByteArray )
{
return QObject::tr( "BLOB" );
}
else if ( v.type() == QVariant::StringList || v.type() == QVariant::List )
{
QString result;
const QVariantList list = v.toList();
for ( const QVariant &var : list )
{
if ( !result.isEmpty() )
result.append( QStringLiteral( ", " ) );
result.append( var.toString() );
}
return result;
}

// Fallback if special rules do not apply
return v.toString();
}

QgsLegendSymbolList QgsCategorizedSymbolRenderer::legendSymbolItems() const
{
if ( mDataDefinedSizeLegend && mSourceSymbol && mSourceSymbol->type() == Qgis::SymbolType::Marker )
@@ -1209,8 +1314,8 @@ QgsCategoryList QgsCategorizedSymbolRenderer::createCategories( const QList<QVar
QgsSymbol *newSymbol = symbol->clone();
if ( !value.isNull() )
{
int fieldIdx = fields.lookupField( attributeName );
QString categoryName = value.toString();
const int fieldIdx = fields.lookupField( attributeName );
QString categoryName = displayString( value );
if ( fieldIdx != -1 )
{
const QgsField field = fields.at( fieldIdx );
@@ -441,6 +441,18 @@ class CORE_EXPORT QgsCategorizedSymbolRenderer : public QgsFeatureRenderer
*/
static QgsCategoryList createCategories( const QVariantList &values, const QgsSymbol *symbol, QgsVectorLayer *layer = nullptr, const QString &fieldName = QString() );

/**
* Returns a localized representation of \a value with the given \a precision,
* if precision is -1 then precision is guessed from the default QVariant::toString
* output.
*
* \note Precision is ignored for integers.
*
* \since QGIS 3.21
*/
static QString displayString( const QVariant &value, int precision = -1 );


protected:
QString mAttrName;
QgsCategoryList mCategories;
@@ -498,6 +510,7 @@ class CORE_EXPORT QgsCategorizedSymbolRenderer : public QgsFeatureRenderer

//! Returns list of legend symbol items from individual categories
QgsLegendSymbolList baseLegendSymbolItems() const;

};

#endif // QGSCATEGORIZEDSYMBOLRENDERER_H
@@ -29,17 +29,27 @@ QString QgsLUDialog::lowerValue() const
return mLowerEdit->text();
}

double QgsLUDialog::lowerValueDouble() const
{
return mLowerEdit->value();
}

QString QgsLUDialog::upperValue() const
{
return mUpperEdit->text();
}

double QgsLUDialog::upperValueDouble() const
{
return mUpperEdit->value();
}

void QgsLUDialog::setLowerValue( const QString &val )
{
mLowerEdit->setText( val );
mLowerEdit->setValue( QLocale().toDouble( val ) );
}

void QgsLUDialog::setUpperValue( const QString &val )
{
mUpperEdit->setText( val );
mUpperEdit->setValue( QLocale().toDouble( val ) );
}
@@ -33,8 +33,20 @@ class GUI_EXPORT QgsLUDialog: public QDialog, private Ui::QgsLUDialogBase
public:
QgsLUDialog( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
QString lowerValue() const;

/**
* Returns the lower value.
* \since QGIS 3.21
*/
double lowerValueDouble() const;
void setLowerValue( const QString &val );
QString upperValue() const;

/**
* Returns the upper value.
* \since QGIS 3.21
*/
double upperValueDouble() const;
void setUpperValue( const QString &val );
};

@@ -162,7 +162,7 @@ QVariant QgsCategorizedSymbolRendererModel::data( const QModelIndex &index, int
const QVariantList list = category.value().toList();
res.reserve( list.size() );
for ( const QVariant &v : list )
res << v.toString();
res << QgsCategorizedSymbolRenderer::displayString( v );

if ( role == Qt::DisplayRole )
return res.join( ';' );
@@ -175,7 +175,7 @@ QVariant QgsCategorizedSymbolRendererModel::data( const QModelIndex &index, int
}
else
{
return category.value().toString();
return QgsCategorizedSymbolRenderer::displayString( category.value() );
}
}
case 2:
@@ -1212,27 +1212,20 @@ void QgsGraduatedSymbolRendererWidget::changeRange( int rangeIdx )

if ( dialog.exec() == QDialog::Accepted )
{
bool ok = false;
double lowerValue = qgsPermissiveToDouble( dialog.lowerValue(), ok );
if ( ! ok )
lowerValue = 0.0;
double upperValue = qgsPermissiveToDouble( dialog.upperValue(), ok );
if ( ! ok )
upperValue = 0.0;
mRenderer->updateRangeUpperValue( rangeIdx, upperValue );
mRenderer->updateRangeLowerValue( rangeIdx, lowerValue );
mRenderer->updateRangeUpperValue( rangeIdx, dialog.upperValueDouble() );
mRenderer->updateRangeLowerValue( rangeIdx, dialog.lowerValueDouble() );

//If the boundaries have to stay linked, we update the ranges above and below, as well as their label if needed
if ( cbxLinkBoundaries->isChecked() )
{
if ( rangeIdx > 0 )
{
mRenderer->updateRangeUpperValue( rangeIdx - 1, lowerValue );
mRenderer->updateRangeUpperValue( rangeIdx - 1, dialog.lowerValueDouble() );
}

if ( rangeIdx < mRenderer->ranges().size() - 1 )
{
mRenderer->updateRangeLowerValue( rangeIdx + 1, upperValue );
mRenderer->updateRangeLowerValue( rangeIdx + 1, dialog.upperValueDouble() );
}
}
}
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>227</width>
<width>302</width>
<height>122</height>
</rect>
</property>
@@ -22,27 +22,15 @@
<property name="text">
<string>Lower value</string>
</property>
<property name="buddy">
<cstring>mLowerEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mLowerEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mUpperLabel">
<property name="text">
<string>Upper value</string>
</property>
<property name="buddy">
<cstring>mUpperEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mUpperEdit"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
@@ -63,9 +51,36 @@
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QgsDoubleSpinBox" name="mLowerEdit">
<property name="minimum">
<double>-1000000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsDoubleSpinBox" name="mUpperEdit">
<property name="minimum">
<double>-1000000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>

0 comments on commit 51be34e

Please sign in to comment.