Skip to content

Commit

Permalink
Merge pull request #8082 from elpaso/qvariant-equal
Browse files Browse the repository at this point in the history
Add qgsVariantEqual for null-aware comparison
  • Loading branch information
elpaso committed Oct 1, 2018
2 parents fecf2eb + 5ed02a7 commit ff41882
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 7 deletions.
11 changes: 11 additions & 0 deletions python/core/auto_generated/qgis.sip.in
Expand Up @@ -187,6 +187,17 @@ QVariant data types (such as strings, numeric values, dates and times)
.. seealso:: :py:func:`qgsVariantGreaterThan`
%End

bool qgsVariantEqual( const QVariant &lhs, const QVariant &rhs );
%Docstring
Compares two QVariant values and returns whether they are equal, NULL values are treated as equal.

:param lhs: first value
:param rhs: second value

:return: true if values are equal
%End


bool qgsVariantGreaterThan( const QVariant &lhs, const QVariant &rhs );
%Docstring
Compares two QVariant values and returns whether the first is greater than the second.
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgis.cpp
Expand Up @@ -189,7 +189,7 @@ bool qgsVariantLessThan( const QVariant &lhs, const QVariant &rhs )
const QList<QVariant> &rhsl = rhs.toList();

int i, n = std::min( lhsl.size(), rhsl.size() );
for ( i = 0; i < n && lhsl[i].type() == rhsl[i].type() && lhsl[i].isNull() == rhsl[i].isNull() && lhsl[i] == rhsl[i]; i++ )
for ( i = 0; i < n && lhsl[i].type() == rhsl[i].type() && qgsVariantEqual( lhsl[i], rhsl[i] ); i++ )
;

if ( i == n )
Expand Down Expand Up @@ -306,3 +306,8 @@ uint qHash( const QVariant &variant )

return std::numeric_limits<uint>::max();
}

bool qgsVariantEqual( const QVariant &lhs, const QVariant &rhs )
{
return lhs.isNull() == rhs.isNull() && lhs == rhs;
}
10 changes: 10 additions & 0 deletions src/core/qgis.h
Expand Up @@ -448,6 +448,16 @@ CORE_EXPORT qlonglong qgsPermissiveToLongLong( QString string, bool &ok );
*/
CORE_EXPORT bool qgsVariantLessThan( const QVariant &lhs, const QVariant &rhs );

/**
* Compares two QVariant values and returns whether they are equal, NULL values are treated as equal.
*
* \param lhs first value
* \param rhs second value
* \return true if values are equal
*/
CORE_EXPORT bool qgsVariantEqual( const QVariant &lhs, const QVariant &rhs );


/**
* Compares two QVariant values and returns whether the first is greater than the second.
* Useful for sorting lists of variants, correctly handling sorting of the various
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsfeaturefiltermodel.cpp
Expand Up @@ -533,7 +533,7 @@ QVariant QgsFeatureFilterModel::extraIdentifierValue() const

void QgsFeatureFilterModel::setExtraIdentifierValue( const QVariant &extraIdentifierValue )
{
if ( extraIdentifierValue == mExtraIdentifierValue && extraIdentifierValue.isNull() == mExtraIdentifierValue.isNull() && mExtraIdentifierValue.isValid() )
if ( qgsVariantEqual( extraIdentifierValue, mExtraIdentifierValue ) && mExtraIdentifierValue.isValid() )
return;

if ( mIsSettingExtraIdentifierValue )
Expand Down
2 changes: 1 addition & 1 deletion src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp
Expand Up @@ -185,7 +185,7 @@ void QgsValueRelationWidgetWrapper::setValue( const QVariant &value )
for ( int i = 0; i < mComboBox->count(); i++ )
{
QVariant v( mComboBox->itemData( i ) );
if ( v.isNull() == value.isNull() && v == value )
if ( qgsVariantEqual( v, value ) )
{
idx = i;
break;
Expand Down
6 changes: 3 additions & 3 deletions src/gui/qgsattributeform.cpp
Expand Up @@ -357,9 +357,9 @@ bool QgsAttributeForm::saveEdits()
int n = 0;
for ( int i = 0; i < dst.count(); ++i )
{
if ( ( dst.at( i ) == src.at( i ) && dst.at( i ).isNull() == src.at( i ).isNull() ) // If field is not changed...
|| !dst.at( i ).isValid() // or the widget returns invalid (== do not change)
|| !fieldIsEditable( i ) ) // or the field cannot be edited ...
if ( qgsVariantEqual( dst.at( i ), src.at( i ) ) // If field is not changed...
|| !dst.at( i ).isValid() // or the widget returns invalid (== do not change)
|| !fieldIsEditable( i ) ) // or the field cannot be edited ...
{
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -2118,7 +2118,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist, Flags flags )

if ( i == flist.size() )
{
if ( v == defVal && defVal.isNull() == v.isNull() )
if ( qgsVariantEqual( v, defVal ) )
{
if ( defVal.isNull() )
{
Expand Down
30 changes: 30 additions & 0 deletions tests/src/core/testqgis.cpp
Expand Up @@ -45,6 +45,7 @@ class TestQgis : public QObject
void qVariantCompare();
void testQgsAsConst();
void testQgsRound();
void testQgsVariantEqual();

private:
QString mReport;
Expand Down Expand Up @@ -359,6 +360,35 @@ void TestQgis::testQgsRound()
QGSCOMPARENEAR( qgsRound( 9999999.87654321987654321, 14 ), 9999999.876543219876543, 0.00000000000001 );
}

void TestQgis::testQgsVariantEqual()
{

// Invalid
QVERIFY( qgsVariantEqual( QVariant(), QVariant() ) );
QVERIFY( QVariant() == QVariant() );

// Zero
QVERIFY( qgsVariantEqual( QVariant( 0 ), QVariant( 0.0f ) ) );
QVERIFY( QVariant( 0 ) == QVariant( 0.0f ) );

// Double
QVERIFY( qgsVariantEqual( QVariant( 1.234 ), QVariant( 1.234 ) ) );

// This is what we actually wanted to fix with qgsVariantEqual
// zero != NULL
QVERIFY( ! qgsVariantEqual( QVariant( 0 ), QVariant( QVariant::Int ) ) );
QVERIFY( ! qgsVariantEqual( QVariant( 0 ), QVariant( QVariant::Double ) ) );
QVERIFY( ! qgsVariantEqual( QVariant( 0.0f ), QVariant( QVariant::Int ) ) );
QVERIFY( ! qgsVariantEqual( QVariant( 0.0f ), QVariant( QVariant::Double ) ) );
QVERIFY( QVariant( 0 ) == QVariant( QVariant::Int ) );

// NULL identities
QVERIFY( qgsVariantEqual( QVariant( QVariant::Int ), QVariant( QVariant::Int ) ) );
QVERIFY( qgsVariantEqual( QVariant( QVariant::Double ), QVariant( QVariant::Double ) ) );


}


QGSTEST_MAIN( TestQgis )
#include "testqgis.moc"

0 comments on commit ff41882

Please sign in to comment.