Skip to content

Commit

Permalink
Merge pull request #40022 from qgis-bot/backport-39778-to-release-3_16
Browse files Browse the repository at this point in the history
[Backport release-3_16] Bugfix gh39757 shared locale sort
  • Loading branch information
elpaso committed Nov 13, 2020
2 parents 0c16716 + e345bb3 commit 03393a5
Show file tree
Hide file tree
Showing 25 changed files with 557 additions and 133 deletions.
1 change: 1 addition & 0 deletions python/core/auto_additions/qgis.py
@@ -1,2 +1,3 @@
# The following has been generated automatically from src/core/qgis.h
Qgis.DataType.baseClass = Qgis
Qgis.PythonMacroMode.baseClass = Qgis
16 changes: 16 additions & 0 deletions python/core/auto_generated/raster/qgsrastershaderfunction.sip.in
Expand Up @@ -113,11 +113,27 @@ Returns the minimum value for the raster shader.
virtual void legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems /Out/ ) const;
%Docstring
Returns legend symbology items if provided by renderer.
%End

int labelPrecision() const;
%Docstring
Returns label precision

.. versionadded:: 3.16
%End

void setLabelPrecision( int labelPrecision );
%Docstring
Sets label precision to ``labelPrecision``

.. versionadded:: 3.16
%End

protected:




};
/************************************************************************
* This file has been generated automatically from *
Expand Down
12 changes: 11 additions & 1 deletion python/gui/auto_generated/qgsdoublevalidator.sip.in
Expand Up @@ -52,9 +52,19 @@ Constructor for QgsDoubleValidator.

:param bottom: the minimal range limit accepted by the validator
:param top: the maximal range limit accepted by the validator
:param decimal: the number of decimal accepted by the validator
:param decimal: the number of decimals accepted by the validator
:param parent: parent object
%End

QgsDoubleValidator( int decimal, QObject *parent );
%Docstring
Constructor for QgsDoubleValidator.

:param decimal: the number of decimals accepted by the validator
:param parent: parent object

.. versionadded:: 3.16
%End


QValidator::State validate( QString &input ) const;
Expand Down
Expand Up @@ -10,6 +10,7 @@




class QgsColorRampShaderWidget: QWidget, protected Ui::QgsColorRampShaderWidgetBase
{
%Docstring
Expand Down Expand Up @@ -111,6 +112,7 @@ Loads min and max values from color ramp tree
%End

protected:

void populateColormapTreeWidget( const QList<QgsColorRampShader::ColorRampItem> &colorRampItems );
%Docstring
Populates color ramp tree from ramp items
Expand Down
1 change: 1 addition & 0 deletions src/core/qgis.h
Expand Up @@ -115,6 +115,7 @@ class CORE_EXPORT Qgis
ARGB32 = 12, //!< Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32
ARGB32_Premultiplied = 13 //!< Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied
};
Q_ENUM( DataType )

/**
* Authorisation to run Python Macros
Expand Down
2 changes: 2 additions & 0 deletions src/core/raster/qgscolorrampshader.cpp
Expand Up @@ -507,6 +507,7 @@ QDomElement QgsColorRampShader::writeXml( QDomDocument &doc ) const
colorRampShaderElem.setAttribute( QStringLiteral( "clip" ), clip() );
colorRampShaderElem.setAttribute( QStringLiteral( "minimumValue" ), mMinimumValue );
colorRampShaderElem.setAttribute( QStringLiteral( "maximumValue" ), mMaximumValue );
colorRampShaderElem.setAttribute( QStringLiteral( "labelPrecision" ), mLabelPrecision );

// save source color ramp
if ( sourceColorRamp() )
Expand Down Expand Up @@ -544,6 +545,7 @@ void QgsColorRampShader::readXml( const QDomElement &colorRampShaderElem )
setClip( colorRampShaderElem.attribute( QStringLiteral( "clip" ), QStringLiteral( "0" ) ) == QLatin1String( "1" ) );
setMinimumValue( colorRampShaderElem.attribute( QStringLiteral( "minimumValue" ) ).toDouble() );
setMaximumValue( colorRampShaderElem.attribute( QStringLiteral( "maximumValue" ) ).toDouble() );
setLabelPrecision( colorRampShaderElem.attribute( QStringLiteral( "labelPrecision" ), QStringLiteral( "6" ) ).toDouble() );

QList<QgsColorRampShader::ColorRampItem> itemList;
QDomElement itemElem;
Expand Down
1 change: 1 addition & 0 deletions src/core/raster/qgscolorrampshader.h
Expand Up @@ -229,6 +229,7 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction

//! Do not render values out of range
bool mClip = false;

};

#endif
9 changes: 3 additions & 6 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Expand Up @@ -67,7 +67,7 @@ QgsRasterRenderer *QgsPalettedRasterRenderer::create( const QDomElement &elem, Q
QDomNodeList paletteEntries = paletteElem.elementsByTagName( QStringLiteral( "paletteEntry" ) );

QDomElement entryElem;
int value;
double value;

for ( int i = 0; i < paletteEntries.size(); ++i )
{
Expand Down Expand Up @@ -353,8 +353,7 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::colorTableToClas
QgsPalettedRasterRenderer::ClassData classes;
for ( ; colorIt != table.constEnd(); ++colorIt )
{
int idx = ( int )( colorIt->value );
classes << QgsPalettedRasterRenderer::Class( idx, colorIt->color, colorIt->label );
classes << QgsPalettedRasterRenderer::Class( colorIt->value, colorIt->color, colorIt->label );
}
return classes;
}
Expand Down Expand Up @@ -499,7 +498,7 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromRas
QgsRasterIterator iter( raster );
iter.startRasterRead( bandNumber, raster->xSize(), raster->ySize(), raster->extent(), feedback );

int nbBlocksWidth = static_cast< int >( std::ceil( 1.0 * raster->ySize() / maxWidth ) );
int nbBlocksWidth = static_cast< int >( std::ceil( 1.0 * raster->xSize() / maxWidth ) );
int nbBlocksHeight = static_cast< int >( std::ceil( 1.0 * raster->ySize() / maxHeight ) );
int nbBlocks = nbBlocksWidth * nbBlocksHeight;

Expand Down Expand Up @@ -609,11 +608,9 @@ QgsPalettedRasterRenderer::ClassData QgsPalettedRasterRenderer::classDataFromRas
void QgsPalettedRasterRenderer::updateArrays()
{
mColors.clear();
int i = 0;
ClassData::const_iterator it = mClassData.constBegin();
for ( ; it != mClassData.constEnd(); ++it )
{
mColors[it->value] = qPremultiply( it->color.rgba() );
i++;
}
}
1 change: 1 addition & 0 deletions src/core/raster/qgsrastershader.cpp
Expand Up @@ -115,3 +115,4 @@ void QgsRasterShader::readXml( const QDomElement &elem )
setRasterShaderFunction( colorRampShader );
}
}

11 changes: 11 additions & 0 deletions src/core/raster/qgsrastershaderfunction.cpp
Expand Up @@ -69,3 +69,14 @@ bool QgsRasterShaderFunction::shade( double redValue, double greenValue, double

return false;
}


int QgsRasterShaderFunction::labelPrecision() const
{
return mLabelPrecision;
}

void QgsRasterShaderFunction::setLabelPrecision( int labelPrecision )
{
mLabelPrecision = labelPrecision;
}
16 changes: 16 additions & 0 deletions src/core/raster/qgsrastershaderfunction.h
Expand Up @@ -123,6 +123,18 @@ class CORE_EXPORT QgsRasterShaderFunction
*/
virtual void legendSymbologyItems( QList< QPair< QString, QColor > > &symbolItems SIP_OUT ) const { Q_UNUSED( symbolItems ) }

/**
* Returns label precision
* \since QGIS 3.16
*/
int labelPrecision() const;

/**
* Sets label precision to \a labelPrecision
* \since QGIS 3.16
*/
void setLabelPrecision( int labelPrecision );

protected:
//! \brief User defineable maximum value for the shading function
double mMaximumValue;
Expand All @@ -132,5 +144,9 @@ class CORE_EXPORT QgsRasterShaderFunction

//! \brief Minimum maximum range for the shading function
double mMinimumMaximumRange;

//! \brief Label precision
int mLabelPrecision = 6;

};
#endif
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -465,6 +465,7 @@ set(QGIS_GUI_SRCS
qgslegendpatchshapebutton.cpp
qgslegendpatchshapewidget.cpp
qgslimitedrandomcolorrampdialog.cpp
qgslocaleawarenumericlineeditdelegate.cpp
qgsratiolockbutton.cpp
qgsludialog.cpp
qgsmanageconnectionsdialog.cpp
Expand Down
1 change: 0 additions & 1 deletion src/gui/mesh/qgsmeshrenderermeshsettingswidget.cpp
Expand Up @@ -20,7 +20,6 @@
#include "qgsmapcanvas.h"
#include "qgsmeshlayer.h"
#include "qgsrasterlayer.h"
#include "raster/qgscolorrampshaderwidget.h"
#include "raster/qgsrasterminmaxwidget.h"
#include "qgsrasterminmaxorigin.h"
#include "qgsmessagelog.h"
Expand Down
12 changes: 11 additions & 1 deletion src/gui/qgsdoublevalidator.cpp
Expand Up @@ -28,7 +28,7 @@ const QString PERMISSIVE_DOUBLE = R"(-?[\d]{0,1000}([\.%1][\d]{0,1000})?(e[+-]?[

QgsDoubleValidator::QgsDoubleValidator( QObject *parent )
: QRegularExpressionValidator( parent )
, mMinimum( std::numeric_limits<qreal>::min() )
, mMinimum( std::numeric_limits<qreal>::lowest() )
, mMaximum( std::numeric_limits<qreal>::max() )
{
// The regular expression accept double with point as decimal point but also the locale decimal point
Expand Down Expand Up @@ -64,6 +64,16 @@ QgsDoubleValidator::QgsDoubleValidator( double bottom, double top, int decimal,
setRegularExpression( reg );
}

QgsDoubleValidator::QgsDoubleValidator( int decimal, QObject *parent )
: QRegularExpressionValidator( parent )
, mMinimum( std::numeric_limits<qreal>::lowest() )
, mMaximum( std::numeric_limits<qreal>::max() )
{
// The regular expression accept double with point as decimal point but also the locale decimal point
QRegularExpression reg( PERMISSIVE_DOUBLE.arg( locale().decimalPoint() ).arg( QString::number( decimal ) ) );
setRegularExpression( reg );
}

QValidator::State QgsDoubleValidator::validate( QString &input, int & ) const
{
if ( input.isEmpty() )
Expand Down
11 changes: 10 additions & 1 deletion src/gui/qgsdoublevalidator.h
Expand Up @@ -67,10 +67,19 @@ class GUI_EXPORT QgsDoubleValidator : public QRegularExpressionValidator
*
* \param bottom the minimal range limit accepted by the validator
* \param top the maximal range limit accepted by the validator
* \param decimal the number of decimal accepted by the validator
* \param decimal the number of decimals accepted by the validator
* \param parent parent object
*/
QgsDoubleValidator( double bottom, double top, int decimal, QObject *parent );

/**
* Constructor for QgsDoubleValidator.
*
* \param decimal the number of decimals accepted by the validator
* \param parent parent object
* \since QGIS 3.16
*/
QgsDoubleValidator( int decimal, QObject *parent );

QValidator::State validate( QString &input, int & ) const override SIP_SKIP;

Expand Down
21 changes: 17 additions & 4 deletions src/gui/qgsguiutils.cpp
Expand Up @@ -24,6 +24,7 @@
#include <QImageWriter>
#include <QFontDialog>
#include <QApplication>
#include <QRegularExpression>


namespace QgsGuiUtils
Expand Down Expand Up @@ -275,11 +276,23 @@ namespace QgsGuiUtils
return QSize( adjustedSize, adjustedSize );
}

QString displayValueWithMaximumDecimals( const Qgis::DataType rasterDataType, const double value )
QString displayValueWithMaximumDecimals( const Qgis::DataType dataType, const double value, bool displayTrailingZeroes )
{
const int precision { significantDigits( rasterDataType ) };
// Reduce
return QLocale().toString( value, 'f', precision );
const int precision { significantDigits( dataType ) };
QString result { QLocale().toString( value, 'f', precision ) };
if ( ! displayTrailingZeroes )
{
const QRegularExpression zeroesRe { QStringLiteral( R"raw(\%1\d*?(0+$))raw" ).arg( QLocale().decimalPoint() ) };
if ( zeroesRe.match( result ).hasMatch() )
{
result.truncate( zeroesRe.match( result ).capturedStart( 1 ) );
if ( result.endsWith( QLocale().decimalPoint( ) ) )
{
result.chop( 1 );
}
}
}
return result;
}

int significantDigits( const Qgis::DataType rasterDataType )
Expand Down
7 changes: 4 additions & 3 deletions src/gui/qgsguiutils.h
Expand Up @@ -193,19 +193,20 @@ namespace QgsGuiUtils

/**
* Returns a localized string representation of the \a value with the appropriate number of
* decimals supported by the \a rasterDataType.
* decimals supported by the \a dataType. Traling zeroes after decimal separator are not
* show unless \a displayTrailingZeroes is set.
* Note that for floating point types the number of decimals may exceed the actual internal
* precision because the precision is always calculated on the mantissa and the conversion to
* string interprets the precision as decimal places.
* \since QGIS 3.16
*/
QString displayValueWithMaximumDecimals( const Qgis::DataType rasterDataType, const double value );
QString GUI_EXPORT displayValueWithMaximumDecimals( const Qgis::DataType dataType, const double value, bool displayTrailingZeroes = false );

/**
* Returns the maximum number of significant digits a for the given \a rasterDataType.
* \since QGIS 3.16
*/
int significantDigits( const Qgis::DataType rasterDataType );
int GUI_EXPORT significantDigits( const Qgis::DataType rasterDataType );

}

Expand Down
73 changes: 73 additions & 0 deletions src/gui/qgslocaleawarenumericlineeditdelegate.cpp
@@ -0,0 +1,73 @@
/***************************************************************************
qgslocaleawarenumericlineeditdelegate.cpp - QgsLocaleAwareNumericLineEditDelegate
---------------------
begin : 5.11.2020
copyright : (C) 2020 by Alessandro Pasotti
email : elpaso at itopen dot it
***************************************************************************
* *
* 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 <QLineEdit>

#include "qgslocaleawarenumericlineeditdelegate.h"
#include "qgsdoublevalidator.h"
#include "qgsguiutils.h"

/// @cond PRIVATE

QgsLocaleAwareNumericLineEditDelegate::QgsLocaleAwareNumericLineEditDelegate( Qgis::DataType dataType, QWidget *parent )
: QStyledItemDelegate( parent )
, mDataType( dataType )
{
}

QWidget *QgsLocaleAwareNumericLineEditDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
Q_UNUSED( option )
Q_UNUSED( index )
auto editor = new QLineEdit{ parent };
editor->setValidator( new QgsDoubleValidator( QgsGuiUtils::significantDigits( mDataType ), editor ) );
return editor;
}

void QgsLocaleAwareNumericLineEditDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
{
QLineEdit *lineEdit { qobject_cast<QLineEdit *>( editor ) };
if ( ! lineEdit )
{
QStyledItemDelegate::setEditorData( editor, index );
}

const QVariant value { index.data( ) };
return lineEdit->setText( displayText( value, QLocale() ) );
}

void QgsLocaleAwareNumericLineEditDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
QLineEdit *lineEdit { qobject_cast<QLineEdit *>( editor ) };
if ( ! editor )
{
QStyledItemDelegate::setModelData( editor, model, index );
}
const double value { QgsDoubleValidator::toDouble( lineEdit->text() ) };
model->setData( index, value );
}

QString QgsLocaleAwareNumericLineEditDelegate::displayText( const QVariant &value, const QLocale & ) const
{
return QgsGuiUtils::displayValueWithMaximumDecimals( mDataType, value.toDouble( ) );
}

void QgsLocaleAwareNumericLineEditDelegate::setDataType( const Qgis::DataType &dataType )
{
mDataType = dataType;
}

///@endcond

0 comments on commit 03393a5

Please sign in to comment.