@@ -174,13 +174,28 @@ static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
174
174
return 0 ;
175
175
}
176
176
177
- static qlonglong qConvertToNumber (const QVariant::Private *d, bool *ok)
177
+ static qlonglong qConvertToNumber (const QVariant::Private *d, bool *ok, bool allowStringToBool = false )
178
178
{
179
179
*ok = true ;
180
180
181
181
switch (uint (d->type ().id ())) {
182
- case QMetaType::QString:
183
- return v_cast<QString>(d)->toLongLong (ok);
182
+ case QMetaType::QString: {
183
+ const QString *s = v_cast<QString>(d);
184
+ qlonglong l = s->toLongLong (ok);
185
+ if (*ok)
186
+ return l;
187
+ if (allowStringToBool) {
188
+ if (*s == QLatin1String (" false" ) || *s == QLatin1String (" 0" )) {
189
+ *ok = true ;
190
+ return 0 ;
191
+ }
192
+ if (*s == QLatin1String (" true" ) || *s == QLatin1String (" 1" )) {
193
+ *ok = true ;
194
+ return 1 ;
195
+ }
196
+ }
197
+ return 0 ;
198
+ }
184
199
case QMetaType::QChar:
185
200
return v_cast<QChar>(d)->unicode ();
186
201
case QMetaType::QByteArray:
@@ -238,6 +253,8 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
238
253
{
239
254
*ok = true ;
240
255
switch (uint (d->type ().id ())) {
256
+ case QMetaType::QString:
257
+ return v_cast<QString>(d)->toDouble (ok);
241
258
case QMetaType::Double:
242
259
return qreal (d->data .d );
243
260
case QMetaType::Float:
@@ -3727,21 +3744,45 @@ bool QVariant::convert(const int type, void *ptr) const
3727
3744
equal; otherwise returns \c false.
3728
3745
3729
3746
QVariant uses the equality operator of the type() it contains to
3730
- check for equality. QVariant will try to convert() \a v if its
3731
- type is not the same as this variant's type. See canConvert() for
3732
- a list of possible conversions.
3747
+ check for equality.
3748
+
3749
+ Variants of different types will always compare as not equal with a few
3750
+ exceptions:
3751
+
3752
+ \list
3753
+ \i If both types are numeric types (integers and floatins point numbers)
3754
+ Qt will compare those types using standard C++ type promotion rules.
3755
+ \i If one type is numeric and the other one a QString, Qt will try to
3756
+ convert the QString to a matching numeric type and if successful compare
3757
+ those.
3758
+ \endlist
3733
3759
*/
3734
3760
3735
3761
/* !
3736
3762
\fn bool QVariant::operator!=(const QVariant &v) const
3737
3763
3738
3764
Compares this QVariant with \a v and returns \c true if they are not
3739
3765
equal; otherwise returns \c false.
3766
+
3767
+ QVariant uses the equality operator of the type() it contains to
3768
+ check for equality.
3769
+
3770
+ Variants of different types will always compare as not equal with a few
3771
+ exceptions:
3772
+
3773
+ \list
3774
+ \i If both types are numeric types (integers and floatins point numbers)
3775
+ Qt will compare those types using standard C++ type promotion rules.
3776
+ \i If one type is numeric and the other one a QString, Qt will try to
3777
+ convert the QString to a matching numeric type and if successful compare
3778
+ those.
3779
+ \endlist
3740
3780
*/
3741
3781
3742
3782
static bool qIsNumericType (uint tp)
3743
3783
{
3744
3784
static const qulonglong numericTypeBits =
3785
+ Q_UINT64_C (1 ) << QMetaType::QString |
3745
3786
Q_UINT64_C (1 ) << QMetaType::Bool |
3746
3787
Q_UINT64_C (1 ) << QMetaType::Double |
3747
3788
Q_UINT64_C (1 ) << QMetaType::Float |
@@ -3789,6 +3830,10 @@ static int numericTypePromotion(uint t1, uint t2)
3789
3830
Q_ASSERT (qIsNumericType (t1));
3790
3831
Q_ASSERT (qIsNumericType (t2));
3791
3832
3833
+ if ((t1 == QMetaType::Bool && t2 == QMetaType::QString) ||
3834
+ (t2 == QMetaType::Bool && t1 == QMetaType::QString))
3835
+ return QMetaType::Bool;
3836
+
3792
3837
// C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
3793
3838
// bool < signed char < short < int < long < long long
3794
3839
// unsigneds have the same rank as their signed counterparts
@@ -3830,53 +3875,59 @@ static int numericTypePromotion(uint t1, uint t2)
3830
3875
return QMetaType::Int;
3831
3876
}
3832
3877
3833
- static int integralCompare (uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
3878
+ static bool integralEquals (uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
3834
3879
{
3835
3880
// use toLongLong to retrieve the data, it gets us all the bits
3836
3881
bool ok;
3837
- qlonglong l1 = qConvertToNumber (d1, &ok);
3838
- Q_ASSERT (ok);
3882
+ qlonglong l1 = qConvertToNumber (d1, &ok, promotedType == QMetaType::Bool);
3883
+ if (!ok)
3884
+ return false ;
3839
3885
3840
- qlonglong l2 = qConvertToNumber (d2, &ok);
3841
- Q_ASSERT (ok);
3886
+ qlonglong l2 = qConvertToNumber (d2, &ok, promotedType == QMetaType::Bool);
3887
+ if (!ok)
3888
+ return false ;
3842
3889
3890
+ if (promotedType == QMetaType::Bool)
3891
+ return bool (l1) == bool (l2);
3843
3892
if (promotedType == QMetaType::Int)
3844
- return int (l1) < int (l2) ? - 1 : int (l1) == int (l2) ? 0 : 1 ;
3893
+ return int (l1) == int (l2);
3845
3894
if (promotedType == QMetaType::UInt)
3846
- return uint (l1) < uint (l2) ? - 1 : uint (l1) == uint (l2) ? 0 : 1 ;
3895
+ return uint (l1) == uint (l2);
3847
3896
if (promotedType == QMetaType::LongLong)
3848
- return l1 < l2 ? - 1 : l1 == l2 ? 0 : 1 ;
3897
+ return l1 == l2;
3849
3898
if (promotedType == QMetaType::ULongLong)
3850
- return qulonglong (l1) < qulonglong (l2) ? - 1 : qulonglong (l1) == qulonglong (l2) ? 0 : 1 ;
3899
+ return qulonglong (l1) == qulonglong (l2);
3851
3900
3852
3901
Q_UNREACHABLE ();
3853
3902
return 0 ;
3854
3903
}
3855
3904
3856
- static int numericCompare (const QVariant::Private *d1, const QVariant::Private *d2)
3905
+ static bool numericEquals (const QVariant::Private *d1, const QVariant::Private *d2)
3857
3906
{
3858
3907
uint promotedType = numericTypePromotion (d1->type ().id (), d2->type ().id ());
3859
3908
if (promotedType != QMetaType::QReal)
3860
- return integralCompare (promotedType, d1, d2);
3909
+ return integralEquals (promotedType, d1, d2);
3861
3910
3862
3911
// qreal comparisons
3863
3912
bool ok;
3864
3913
qreal r1 = qConvertToRealNumber (d1, &ok);
3865
- Q_ASSERT (ok);
3914
+ if (!ok)
3915
+ return false ;
3866
3916
qreal r2 = qConvertToRealNumber (d2, &ok);
3867
- Q_ASSERT (ok);
3917
+ if (!ok)
3918
+ return false ;
3868
3919
if (r1 == r2)
3869
- return 0 ;
3920
+ return true ;
3870
3921
3871
3922
// only do fuzzy comparisons for finite, non-zero numbers
3872
3923
int c1 = qFpClassify (r1);
3873
3924
int c2 = qFpClassify (r2);
3874
3925
if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
3875
3926
if (qFuzzyCompare (r1, r2))
3876
- return 0 ;
3927
+ return true ;
3877
3928
}
3878
3929
3879
- return r1 < r2 ? - 1 : 1 ;
3930
+ return false ;
3880
3931
}
3881
3932
3882
3933
/* !
@@ -3885,26 +3936,19 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
3885
3936
bool QVariant::equals (const QVariant &v) const
3886
3937
{
3887
3938
auto metatype = d.type ();
3888
- // try numerics first, with C++ type promotion rules (no conversion)
3889
- if (qIsNumericType (metatype.id ()) && qIsNumericType (v.d .type ().id ()))
3890
- return numericCompare (&d, &v.d ) == 0 ;
3891
-
3892
- QVariant v1 = *this ;
3893
- QVariant v2 = v;
3894
- if (v2.canConvert (v1.d .type ().id ())) {
3895
- if (!v2.convert (v1.d .type ().id ()))
3896
- return false ;
3897
- } else {
3898
- // try the opposite conversion, it might work
3899
- qSwap (v1, v2);
3900
- if (!v2.convert (v1.d .type ().id ()))
3901
- return false ;
3939
+
3940
+ if (metatype != v.metaType ()) {
3941
+ // try numeric comparisons, with C++ type promotion rules (no conversion)
3942
+ if (qIsNumericType (metatype.id ()) && qIsNumericType (v.d .type ().id ()))
3943
+ return numericEquals (&d, &v.d );
3944
+ return false ;
3902
3945
}
3903
- metatype = v1. metaType ();
3946
+
3904
3947
// For historical reasons: QVariant() == QVariant()
3905
3948
if (!metatype.isValid ())
3906
3949
return true ;
3907
- return metatype.equals (QT_PREPEND_NAMESPACE (constData (v1.d )), QT_PREPEND_NAMESPACE (constData (v2.d )));
3950
+
3951
+ return metatype.equals (QT_PREPEND_NAMESPACE (constData (d)), QT_PREPEND_NAMESPACE (constData (v.d )));
3908
3952
}
3909
3953
3910
3954
/* !
0 commit comments