From 66bab2e3b0582b5cd446d4c983b9529cbbb3816f Mon Sep 17 00:00:00 2001 From: Alexander Barthel Date: Mon, 13 Nov 2023 16:20:18 +0100 Subject: [PATCH] Corrected broken sort order of numerical columns when using distance search #1060 --- src/search/sqlmodel.cpp | 5 +++++ src/search/sqlmodel.h | 5 ++++- src/search/sqlproxymodel.cpp | 23 ++++++++++++++++++++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/search/sqlmodel.cpp b/src/search/sqlmodel.cpp index d45a94472..08e4ab84f 100644 --- a/src/search/sqlmodel.cpp +++ b/src/search/sqlmodel.cpp @@ -672,6 +672,11 @@ QVariant SqlModel::defaultDataHandler(int, int, const Column *, const QVariant&, return QVariant(); } +QVariant SqlModel::rawData(const QModelIndex& index) const +{ + return index.isValid() ? QSqlQueryModel::data(index, Qt::DisplayRole) : QVariant(); +} + QVariant SqlModel::data(const QModelIndex& index, int role) const { if(!index.isValid()) diff --git a/src/search/sqlmodel.h b/src/search/sqlmodel.h index a592e82b5..501fd401e 100644 --- a/src/search/sqlmodel.h +++ b/src/search/sqlmodel.h @@ -1,5 +1,5 @@ /***************************************************************************** -* Copyright 2015-2020 Alexander Barthel alex@littlenavmap.org +* Copyright 2015-2023 Alexander Barthel alex@littlenavmap.org * * 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 @@ -144,6 +144,9 @@ class SqlModel : /* Fetch and format data for display */ virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + /* Fetch data without any converts for display role */ + QVariant rawData(const QModelIndex& index) const; + /* * Sets a data callback that is called for each table cell and the given item data roles. * @param func callback function or method. Use std::bind to create callbacks to non static methods. diff --git a/src/search/sqlproxymodel.cpp b/src/search/sqlproxymodel.cpp index 7562a516a..0ca96080f 100644 --- a/src/search/sqlproxymodel.cpp +++ b/src/search/sqlproxymodel.cpp @@ -1,5 +1,5 @@ /***************************************************************************** -* Copyright 2015-2020 Alexander Barthel alex@littlenavmap.org +* Copyright 2015-2023 Alexander Barthel alex@littlenavmap.org * * 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 @@ -123,6 +123,10 @@ QVariant SqlProxyModel::headerData(int section, Qt::Orientation orientation, int /* Defines greater and lower than for sorting of the two columns distance and heading */ bool SqlProxyModel::lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight) const { + // These types can be converted to long long and compared + const static QSet NUMERIC_TYPES({QVariant::Bool, QVariant::Int, QVariant::UInt, QVariant::LongLong, QVariant::ULongLong, + QVariant::Date, QVariant::Time, QVariant::DateTime}); + QString leftCol = sourceSqlModel->getColumnName(sourceLeft.column()); QString rightCol = sourceSqlModel->getColumnName(sourceRight.column()); @@ -141,8 +145,21 @@ bool SqlProxyModel::lessThan(const QModelIndex& sourceLeft, const QModelIndex& s return headingLeft < headingRight; } else - // Let the model do the sorting for other columns - return QSortFilterProxyModel::lessThan(sourceLeft, sourceRight); + { + // Get unmodified (converted to strings) raw data + QVariant leftData = sourceSqlModel->rawData(sourceLeft); + QVariant rightData = sourceSqlModel->rawData(sourceRight); + + if(leftData.type() == QVariant::Double && rightData.type() == QVariant::Double) + // Compare float and double numerically + return leftData.toDouble() < rightData.toDouble(); + else if(NUMERIC_TYPES.contains(leftData.type()) && NUMERIC_TYPES.contains(rightData.type())) + // Compare bool, int to long long numerically + return leftData.toLongLong() < rightData.toLongLong(); + else + // Let the model do the sorting for other columns + return QSortFilterProxyModel::lessThan(sourceLeft, sourceRight); + } } /* Returns the formatted data for the "distance" and "heading" column */