138 if ( !lhs.isValid() )
140 return rhs.isValid() ? -1 : 0;
142 else if ( lhs.isNull() )
144 if ( !rhs.isValid() )
150 else if ( !rhs.isValid() || rhs.isNull() )
155 if ( strictTypeCheck && lhs.userType() != rhs.userType() )
157 return lhs.userType() < rhs.userType() ? -1 : 1;
161 switch ( lhs.userType() )
163 case QMetaType::Type::Int:
164 case QMetaType::Type::Char:
165 case QMetaType::Type::Short:
167 switch ( rhs.userType() )
169 case QMetaType::Type::Int:
170 case QMetaType::Type::Char:
171 case QMetaType::Type::Short:
173 const int lhsInt = lhs.toInt();
174 const int rhsInt = rhs.toInt();
175 return lhsInt < rhsInt ? -1 : ( lhsInt == rhsInt ? 0 : 1 );
178 case QMetaType::Type::Long:
179 case QMetaType::Type::LongLong:
181 const long long lhsInt = lhs.toLongLong();
182 const long long rhsInt = rhs.toLongLong();
183 return lhsInt < rhsInt ? -1 : ( lhsInt == rhsInt ? 0 : 1 );
186 case QMetaType::Type::Double:
187 case QMetaType::Type::Float:
189 const double lhsDouble =
static_cast< double >( lhs.toInt() );
190 const double rhsDouble = rhs.toDouble();
193 const bool lhsIsNan = std::isnan( lhsDouble );
194 const bool rhsIsNan = std::isnan( rhsDouble );
197 return rhsIsNan ? 0 : -1;
204 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
207 case QMetaType::Type::QString:
210 const double rhsDouble = rhs.toDouble( &ok );
213 const double lhsDouble =
static_cast< double >( lhs.toInt() );
214 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
225 case QMetaType::Type::UInt:
226 case QMetaType::Type::UChar:
227 case QMetaType::Type::UShort:
229 switch ( rhs.userType() )
231 case QMetaType::Type::UInt:
232 case QMetaType::Type::UChar:
233 case QMetaType::Type::UShort:
235 const uint lhsUInt = lhs.toUInt();
236 const uint rhsUInt = rhs.toUInt();
237 return lhsUInt < rhsUInt ? -1 : ( lhsUInt == rhsUInt ? 0 : 1 );
240 case QMetaType::Type::ULong:
241 case QMetaType::Type::ULongLong:
243 const qulonglong lhsInt = lhs.toULongLong();
244 const qulonglong rhsInt = rhs.toULongLong();
245 return lhsInt < rhsInt ? -1 : ( lhsInt == rhsInt ? 0 : 1 );
248 case QMetaType::Type::Double:
249 case QMetaType::Type::Float:
251 const double lhsDouble =
static_cast< double >( lhs.toUInt() );
252 const double rhsDouble = rhs.toDouble();
255 const bool lhsIsNan = std::isnan( lhsDouble );
256 const bool rhsIsNan = std::isnan( rhsDouble );
259 return rhsIsNan ? 0 : -1;
266 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
269 case QMetaType::Type::QString:
272 const double rhsDouble = rhs.toDouble( &ok );
275 const double lhsDouble =
static_cast< double >( lhs.toUInt() );
276 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
287 case QMetaType::Type::LongLong:
288 case QMetaType::Type::Long:
290 switch ( rhs.userType() )
292 case QMetaType::Type::Int:
293 case QMetaType::Type::Char:
294 case QMetaType::Type::Short:
295 case QMetaType::Type::LongLong:
296 case QMetaType::Type::Long:
298 const qlonglong lhsLongLong = lhs.toLongLong();
299 const qlonglong rhsLongLong = rhs.toLongLong();
300 return lhsLongLong < rhsLongLong ? -1 : ( lhsLongLong == rhsLongLong ? 0 : 1 );
303 case QMetaType::Type::Double:
304 case QMetaType::Type::Float:
306 const double lhsDouble =
static_cast< double >( lhs.toLongLong() );
307 const double rhsDouble = rhs.toDouble();
310 const bool lhsIsNan = std::isnan( lhsDouble );
311 const bool rhsIsNan = std::isnan( rhsDouble );
314 return rhsIsNan ? 0 : -1;
321 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
324 case QMetaType::Type::QString:
327 const double rhsDouble = rhs.toDouble( &ok );
330 const double lhsDouble =
static_cast< double >( lhs.toLongLong() );
331 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
342 case QMetaType::Type::ULongLong:
343 case QMetaType::Type::ULong:
345 switch ( rhs.userType() )
347 case QMetaType::Type::UInt:
348 case QMetaType::Type::UChar:
349 case QMetaType::Type::UShort:
350 case QMetaType::Type::ULongLong:
351 case QMetaType::Type::ULong:
353 const qulonglong lhsULongLong = lhs.toULongLong();
354 const qulonglong rhsULongLong = rhs.toULongLong();
355 return lhsULongLong < rhsULongLong ? -1 : ( lhsULongLong == rhsULongLong ? 0 : 1 );
364 case QMetaType::Type::Double:
366 switch ( rhs.userType() )
368 case QMetaType::Type::Int:
369 case QMetaType::Type::Char:
370 case QMetaType::Type::Short:
371 case QMetaType::Type::Double:
372 case QMetaType::Type::Float:
373 case QMetaType::Type::LongLong:
374 case QMetaType::Type::Long:
375 case QMetaType::Type::ULongLong:
376 case QMetaType::Type::ULong:
377 case QMetaType::Type::QString:
379 const double lhsDouble = lhs.toDouble();
380 bool rhsIsDoubleCompatible =
false;
381 const double rhsDouble = rhs.toDouble( &rhsIsDoubleCompatible );
382 if ( rhsIsDoubleCompatible )
385 const bool lhsIsNan = std::isnan( lhsDouble );
386 const bool rhsIsNan = std::isnan( rhsDouble );
389 return rhsIsNan ? 0 : -1;
396 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
407 case QMetaType::Type::Float:
409 switch ( rhs.userType() )
411 case QMetaType::Type::Int:
412 case QMetaType::Type::Char:
413 case QMetaType::Type::Short:
414 case QMetaType::Type::Double:
415 case QMetaType::Type::Float:
416 case QMetaType::Type::LongLong:
417 case QMetaType::Type::Long:
418 case QMetaType::Type::ULongLong:
419 case QMetaType::Type::ULong:
420 case QMetaType::Type::QString:
422 const float lhsFloat = lhs.toFloat();
423 bool rhsIsFloatCompatible =
false;
424 const float rhsFloat = rhs.toFloat( &rhsIsFloatCompatible );
425 if ( rhsIsFloatCompatible )
428 const bool lhsIsNan = std::isnan( lhsFloat );
429 const bool rhsIsNan = std::isnan( rhsFloat );
432 return rhsIsNan ? 0 : -1;
439 return lhsFloat < rhsFloat ? -1 : ( lhsFloat == rhsFloat ? 0 : 1 );
449 case QMetaType::Type::QChar:
451 if ( rhs.userType() == QMetaType::Type::QChar )
453 const QChar lhsChar = lhs.toChar();
454 const QChar rhsChar = rhs.toChar();
455 return lhsChar < rhsChar ? -1 : ( lhsChar == rhsChar ? 0 : 1 );
460 case QMetaType::Type::QDate:
462 if ( rhs.userType() == QMetaType::Type::QDate )
464 const QDate lhsDate = lhs.toDate();
465 const QDate rhsDate = rhs.toDate();
466 return lhsDate < rhsDate ? -1 : ( lhsDate == rhsDate ? 0 : 1 );
471 case QMetaType::Type::QTime:
473 if ( rhs.userType() == QMetaType::Type::QTime )
475 const QTime lhsTime = lhs.toTime();
476 const QTime rhsTime = rhs.toTime();
477 return lhsTime < rhsTime ? -1 : ( lhsTime == rhsTime ? 0 : 1 );
482 case QMetaType::Type::QDateTime:
484 if ( rhs.userType() == QMetaType::Type::QDateTime )
486 const QDateTime lhsTime = lhs.toDateTime();
487 const QDateTime rhsTime = rhs.toDateTime();
488 return lhsTime < rhsTime ? -1 : ( lhsTime == rhsTime ? 0 : 1 );
493 case QMetaType::Type::Bool:
495 if ( rhs.userType() == QMetaType::Type::Bool )
497 const bool lhsBool = lhs.toBool();
498 const bool rhsBool = rhs.toBool();
499 return lhsBool == rhsBool ? 0 : ( lhsBool ? 1 : -1 );
504 case QMetaType::Type::QVariantList:
506 if ( rhs.userType() == QMetaType::Type::QVariantList )
508 const QList<QVariant> &lhsl = lhs.toList();
509 const QList<QVariant> &rhsl = rhs.toList();
511 int i, n = std::min( lhsl.size(), rhsl.size() );
512 for ( i = 0; i < n && lhsl[i].userType() == rhsl[i].userType() &&
qgsVariantCompare( lhsl[i], rhsl[i] ) == 0; i++ )
516 return lhsl.size() < rhsl.size() ? -1 : ( lhsl.size() > rhsl.size() ? 1 : 0 );
523 case QMetaType::Type::QStringList:
525 if ( rhs.userType() == QMetaType::Type::QStringList )
527 const QStringList &lhsl = lhs.toStringList();
528 const QStringList &rhsl = rhs.toStringList();
530 int i, n = std::min( lhsl.size(), rhsl.size() );
531 for ( i = 0; i < n && lhsl[i] == rhsl[i]; i++ )
535 return lhsl.size() < rhsl.size() ? -1 : ( lhsl.size() > rhsl.size() ? 1 : 0 );
537 return lhsl[i] < rhsl[i] ? -1 : ( lhsl[i] == rhsl[i] ? 0 : 1 );
542 case QMetaType::Type::QString:
544 switch ( rhs.userType() )
546 case QMetaType::Type::Int:
547 case QMetaType::Type::Char:
548 case QMetaType::Type::Short:
549 case QMetaType::Type::Double:
550 case QMetaType::Type::Float:
551 case QMetaType::Type::LongLong:
552 case QMetaType::Type::Long:
553 case QMetaType::Type::ULongLong:
554 case QMetaType::Type::ULong:
557 bool lhsIsDoubleCompatible =
false;
558 const double lhsDouble = lhs.toDouble( &lhsIsDoubleCompatible );
559 if ( lhsIsDoubleCompatible )
561 const double rhsDouble = rhs.toDouble();
563 const bool lhsIsNan = std::isnan( lhsDouble );
564 const bool rhsIsNan = std::isnan( rhsDouble );
567 return rhsIsNan ? 0 : -1;
574 return lhsDouble < rhsDouble ? -1 : ( lhsDouble == rhsDouble ? 0 : 1 );
589 return std::clamp( QString::localeAwareCompare( lhs.toString(), rhs.toString() ), -1, 1 );