Skip to content
Permalink
Browse files

Add numeric formatter for scientific notation

  • Loading branch information
nyalldawson committed Jan 6, 2020
1 parent 8bcba47 commit d445487c0d001198b268e43ed27620e7083602ff
@@ -111,6 +111,9 @@ numberDecimalPlaces()).
.. seealso:: :py:func:`setNumberDecimalPlaces`
%End

protected:


private:
QgsBasicNumericFormat( const QgsBasicNumericFormat &other );
};
@@ -64,6 +64,7 @@ Returns the decimal separator character.
#include <qgsbearingnumericformat.h>
#include <qgsfallbacknumericformat.h>
#include <qgspercentagenumericformat.h>
#include <qgsscientificnumericformat.h>
%End

class QgsNumericFormat
@@ -90,6 +91,8 @@ This is an abstract base class and will always need to be subclassed.
sipType = sipType_QgsFallbackNumericFormat;
else if ( dynamic_cast< QgsPercentageNumericFormat * >( sipCpp ) )
sipType = sipType_QgsPercentageNumericFormat;
else if ( dynamic_cast< QgsScientificNumericFormat * >( sipCpp ) )
sipType = sipType_QgsScientificNumericFormat;
else
sipType = NULL;
%End
@@ -0,0 +1,53 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/numericformats/qgsscientificnumericformat.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/


class QgsScientificNumericFormat : QgsBasicNumericFormat
{
%Docstring
A numeric formatter which returns a scientific notation representation of a value.

.. versionadded:: 3.12
%End

%TypeHeaderCode
#include "qgsscientificnumericformat.h"
%End
public:

QgsScientificNumericFormat();
%Docstring
Default constructor
%End


virtual QString id() const;

%Docstring
QgsScientificNumericFormat cannot be copied
%End
virtual QString formatDouble( double value, const QgsNumericFormatContext &context ) const;

virtual QgsNumericFormat *clone() const /Factory/;

virtual QgsNumericFormat *create( const QVariantMap &configuration ) const /Factory/;

virtual QVariantMap configuration() const;


private:
QgsScientificNumericFormat( const QgsScientificNumericFormat &other );
};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/numericformats/qgsscientificnumericformat.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -401,6 +401,7 @@
%Include auto_generated/numericformats/qgsnumericformat.sip
%Include auto_generated/numericformats/qgsnumericformatregistry.sip
%Include auto_generated/numericformats/qgspercentagenumericformat.sip
%Include auto_generated/numericformats/qgsscientificnumericformat.sip
%Include auto_generated/processing/models/qgsprocessingmodelalgorithm.sip
%Include auto_generated/processing/models/qgsprocessingmodelchildalgorithm.sip
%Include auto_generated/processing/models/qgsprocessingmodelchildparametersource.sip
@@ -110,6 +110,7 @@ SET(QGIS_CORE_SRCS
numericformats/qgsnumericformat.cpp
numericformats/qgsnumericformatregistry.cpp
numericformats/qgspercentagenumericformat.cpp
numericformats/qgsscientificnumericformat.cpp

auth/qgsauthcertutils.cpp
auth/qgsauthconfig.cpp
@@ -1139,6 +1140,7 @@ SET(QGIS_CORE_HDRS
numericformats/qgsnumericformat.h
numericformats/qgsnumericformatregistry.h
numericformats/qgspercentagenumericformat.h
numericformats/qgsscientificnumericformat.h

processing/models/qgsprocessingmodelalgorithm.h
processing/models/qgsprocessingmodelchildalgorithm.h
@@ -56,7 +56,12 @@ QString QgsBasicNumericFormat::formatDouble( double value, const QgsNumericForma
mPrevDecimalSep = context.decimalSeparator();
}

*mOs << std::fixed << value;
if ( !mUseScientific )
*mOs << std::fixed;
else
*mOs << std::scientific;

*mOs << value;
QString res = QString::fromStdString( mOs->str() );
mOs->str( "" );
mOs->clear();
@@ -67,13 +72,25 @@ QString QgsBasicNumericFormat::formatDouble( double value, const QgsNumericForma
if ( !mShowTrailingZeros && res.contains( context.decimalSeparator() ) )
{
int trimPoint = res.length() - 1;
int ePoint = 0;
if ( mUseScientific )
{
while ( res.at( trimPoint ) != 'e' && res.at( trimPoint ) != 'E' )
trimPoint--;
ePoint = trimPoint;
trimPoint--;
}

while ( res.at( trimPoint ) == '0' )
trimPoint--;

if ( res.at( trimPoint ) == context.decimalSeparator() )
trimPoint--;

QString original = res;
res.truncate( trimPoint + 1 );
if ( mUseScientific )
res += original.mid( ePoint );
}

return res;
@@ -111,6 +111,10 @@ class CORE_EXPORT QgsBasicNumericFormat : public QgsNumericFormat
*/
void setShowTrailingZeros( bool showTrailingZeros );

protected:

bool mUseScientific = false;

private:

#ifdef SIP_RUN
@@ -90,6 +90,7 @@ class CORE_EXPORT QgsNumericFormatContext
#include <qgsbearingnumericformat.h>
#include <qgsfallbacknumericformat.h>
#include <qgspercentagenumericformat.h>
#include <qgsscientificnumericformat.h>
% End
#endif

@@ -116,6 +117,8 @@ class CORE_EXPORT QgsNumericFormat
sipType = sipType_QgsFallbackNumericFormat;
else if ( dynamic_cast< QgsPercentageNumericFormat * >( sipCpp ) )
sipType = sipType_QgsPercentageNumericFormat;
else if ( dynamic_cast< QgsScientificNumericFormat * >( sipCpp ) )
sipType = sipType_QgsScientificNumericFormat;
else
sipType = NULL;
SIP_END
@@ -19,12 +19,14 @@
#include "qgsbasicnumericformat.h"
#include "qgsbearingnumericformat.h"
#include "qgspercentagenumericformat.h"
#include "qgsscientificnumericformat.h"

QgsNumericFormatRegistry::QgsNumericFormatRegistry()
{
addFormat( new QgsBasicNumericFormat() );
addFormat( new QgsBearingNumericFormat() );
addFormat( new QgsPercentageNumericFormat() );
addFormat( new QgsScientificNumericFormat() );
}

QgsNumericFormatRegistry::~QgsNumericFormatRegistry()
@@ -0,0 +1,52 @@
/***************************************************************************
qgsscientificnumericformat.cpp
----------------------------
begin : January 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot 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 "qgsscientificnumericformat.h"
#include "qgis.h"


QgsScientificNumericFormat::QgsScientificNumericFormat()
{
mUseScientific = true;
}

QString QgsScientificNumericFormat::id() const
{
return QStringLiteral( "scientific" );
}

QString QgsScientificNumericFormat::formatDouble( double value, const QgsNumericFormatContext &context ) const
{
return QgsBasicNumericFormat::formatDouble( value, context );
}

QgsNumericFormat *QgsScientificNumericFormat::clone() const
{
return create( configuration() );
}

QgsNumericFormat *QgsScientificNumericFormat::create( const QVariantMap &configuration ) const
{
std::unique_ptr< QgsScientificNumericFormat > res = qgis::make_unique< QgsScientificNumericFormat >();
res->setConfiguration( configuration );
return res.release();
}

QVariantMap QgsScientificNumericFormat::configuration() const
{
QVariantMap res = QgsBasicNumericFormat::configuration();
return res;
}
@@ -0,0 +1,56 @@
/***************************************************************************
qgsscientificnumericformat.h
----------------------------
begin : January 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot 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. *
* *
***************************************************************************/
#ifndef QGSSCIENTIFICNUMERICFORMAT_H
#define QGSSCIENTIFICNUMERICFORMAT_H

#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsbasicnumericformat.h"

/**
* \ingroup core
* A numeric formatter which returns a scientific notation representation of a value.
*
* \since QGIS 3.12
*/
class CORE_EXPORT QgsScientificNumericFormat : public QgsBasicNumericFormat
{
public:

/**
* Default constructor
*/
QgsScientificNumericFormat();

//! QgsScientificNumericFormat cannot be copied
QgsScientificNumericFormat( const QgsScientificNumericFormat & ) = delete;
//! QgsScientificNumericFormat cannot be copied
QgsScientificNumericFormat &operator=( const QgsScientificNumericFormat & ) = delete;

QString id() const override;
QString formatDouble( double value, const QgsNumericFormatContext &context ) const override;
QgsNumericFormat *clone() const override SIP_FACTORY;
QgsNumericFormat *create( const QVariantMap &configuration ) const override SIP_FACTORY;
QVariantMap configuration() const override;

private:

#ifdef SIP_RUN
QgsScientificNumericFormat( const QgsScientificNumericFormat &other );
#endif

};

#endif // QGSSCIENTIFICNUMERICFORMAT_H
@@ -17,6 +17,7 @@
QgsNumericFormatContext,
QgsBearingNumericFormat,
QgsPercentageNumericFormat,
QgsScientificNumericFormat,
QgsNumericFormatRegistry,
QgsNumericFormat)

@@ -316,6 +317,54 @@ def testPercentageFormat(self):
self.assertEqual(f.formatDouble(5.5, context), '+550.000%')
self.assertEqual(f.formatDouble(-5.5, context), '-550.000%')

def testScientificFormat(self):
""" test scientific formatter """
f = QgsScientificNumericFormat()
context = QgsNumericFormatContext()
self.assertEqual(f.formatDouble(0, context), '0e+00')
self.assertEqual(f.formatDouble(5, context), '5e+00')
self.assertEqual(f.formatDouble(5.5, context), '5.5e+00')
self.assertEqual(f.formatDouble(-5, context), '-5e+00')
self.assertEqual(f.formatDouble(-5.5, context), '-5.5e+00')
self.assertEqual(f.formatDouble(-55555555.5, context), '-5.555556e+07')
context.setDecimalSeparator('x')
self.assertEqual(f.formatDouble(0, context), '0e+00')
self.assertEqual(f.formatDouble(-5.5, context), '-5x5e+00')
self.assertEqual(f.formatDouble(-55555555.5, context), '-5x555556e+07')
context.setDecimalSeparator('.')
f.setNumberDecimalPlaces(0)
self.assertEqual(f.formatDouble(0, context), '0e+00')
self.assertEqual(f.formatDouble(5.5, context), '6e+00')
self.assertEqual(f.formatDouble(55555555.5, context), '6e+07')
self.assertEqual(f.formatDouble(55555555.123456, context), '6e+07')
self.assertEqual(f.formatDouble(-5.5, context), '-6e+00')
self.assertEqual(f.formatDouble(-55555555.5, context), '-6e+07')
f.setNumberDecimalPlaces(3)
self.assertEqual(f.formatDouble(0, context), '0e+00')
self.assertEqual(f.formatDouble(5.5, context), '5.5e+00')
self.assertEqual(f.formatDouble(55555555.5, context), '5.556e+07')
self.assertEqual(f.formatDouble(55555555.123456, context), '5.556e+07')
self.assertEqual(f.formatDouble(-5.5, context), '-5.5e+00')
self.assertEqual(f.formatDouble(-55555555.5, context), '-5.556e+07')
f.setShowTrailingZeros(True)
self.assertEqual(f.formatDouble(0, context), '0.000e+00')
self.assertEqual(f.formatDouble(5, context), '5.000e+00')
self.assertEqual(f.formatDouble(-5, context), '-5.000e+00')
self.assertEqual(f.formatDouble(5.5, context), '5.500e+00')
self.assertEqual(f.formatDouble(55555555.5, context), '5.556e+07')
self.assertEqual(f.formatDouble(55555555.123456, context), '5.556e+07')
self.assertEqual(f.formatDouble(-5.5, context), '-5.500e+00')
self.assertEqual(f.formatDouble(-55555555.5, context), '-5.556e+07')
f.setShowPlusSign(True)
self.assertEqual(f.formatDouble(0, context), '0.000e+00')
self.assertEqual(f.formatDouble(5, context), '+5.000e+00')
self.assertEqual(f.formatDouble(-5, context), '-5.000e+00')
self.assertEqual(f.formatDouble(5.5, context), '+5.500e+00')
self.assertEqual(f.formatDouble(55555555.5, context), '+5.556e+07')
self.assertEqual(f.formatDouble(55555555.123456, context), '+5.556e+07')
self.assertEqual(f.formatDouble(-5.5, context), '-5.500e+00')
self.assertEqual(f.formatDouble(-55555555.5, context), '-5.556e+07')

def testRegistry(self):
registry = QgsNumericFormatRegistry()
self.assertTrue(registry.formats())

0 comments on commit d445487

Please sign in to comment.
You can’t perform that action at this time.