From 89e3500a8eef6bdd46cfb175ee7e613d01afc012 Mon Sep 17 00:00:00 2001 From: Nick Tiskov Date: Mon, 8 Jul 2013 18:31:20 +0400 Subject: [PATCH] Move number-aware comparison logic into misc class. --- src/misc.cpp | 63 +++++++++++++++++++++++++++++++++++++ src/misc.h | 4 +++ src/transferlistsortmodel.h | 59 +++------------------------------- 3 files changed, 71 insertions(+), 55 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index e12a50421..6eab2efad 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -521,3 +521,66 @@ QString misc::toQString(time_t t) return QDateTime::fromTime_t(t).toString(Qt::DefaultLocaleLongDate); } #endif + +#ifndef DISABLE_GUI +bool misc::naturalSort(QString left, QString right, bool &result) { // uses lessThan comparison + // Return value indicates if functions was successful + // result argument will contain actual comparison result if function was successful + do { + int posL = left.indexOf(QRegExp("[0-9]")); + int posR = right.indexOf(QRegExp("[0-9]")); + if (posL == -1 || posR == -1) + break; // No data + else if (posL != posR) + break; // Digit positions mismatch + else if (left.left(posL) != right.left(posR)) + break; // Strings' subsets before digit do not match + + + bool second_digit = false; + if (left.size() > posL + 1) + second_digit = left.at(posL + 1).isDigit(); + if (right.size() > posR + 1) + second_digit = second_digit ? + second_digit : + right.at(posR + 1).isDigit(); + + if (!second_digit) + break; // Single digit in both, normal sort could handle this + + QString temp; + while (posL < left.size()) { + if (left.at(posL).isDigit()) + temp += left.at(posL); + else + break; + posL++; + } + int numL = temp.toInt(); + temp.clear(); + + while (posR < right.size()) { + if (right.at(posR).isDigit()) + temp += right.at(posR); + else + break; + posR++; + } + int numR = temp.toInt(); + + if (numL != numR) { + result = (numL < numR); + return true; + } + + // Strings + digits do match and we haven't hit string end + // Do another round + left.remove(0, posL); + right.remove(0, posR); + continue; + + } while (true); + + return false; +} +#endif diff --git a/src/misc.h b/src/misc.h index e5e490f51..6d9883574 100644 --- a/src/misc.h +++ b/src/misc.h @@ -119,6 +119,10 @@ public: #else static QString toQString(time_t t); #endif + +#ifndef DISABLE_GUI + static bool naturalSort(QString left, QString right, bool& result); +#endif }; // Trick to get a portable sleep() function diff --git a/src/transferlistsortmodel.h b/src/transferlistsortmodel.h index 6f7670552..9e9565529 100644 --- a/src/transferlistsortmodel.h +++ b/src/transferlistsortmodel.h @@ -33,6 +33,7 @@ #include #include "torrentmodel.h" +#include "misc.h" class TransferListSortModel : public QSortFilterProxyModel { Q_OBJECT @@ -50,61 +51,9 @@ protected: Q_ASSERT(vL.isValid()); Q_ASSERT(vR.isValid()); - QString nameLeft = vL.toString(); - QString nameRight = vR.toString(); - - do { - int posL = nameLeft.indexOf(QRegExp("[0-9]")); - int posR = nameRight.indexOf(QRegExp("[0-9]")); - if (posL == -1 || posR == -1) - break; // No data - else if (posL != posR) - break; // Digit positions mismatch - else if (nameLeft.left(posL) != nameRight.left(posR)) - break; // Strings' subsets before digit do not match - - - bool second_digit = false; - if (nameLeft.size() > posL + 1) - second_digit = nameLeft.at(posL + 1).isDigit(); - if (nameRight.size() > posR + 1) - second_digit = second_digit ? - second_digit : - nameRight.at(posR + 1).isDigit(); - - if (!second_digit) - break; // Single digit in both, normal sort could handle this - - QString temp; - while (posL < nameLeft.size()) { - if (nameLeft.at(posL).isDigit()) - temp += nameLeft.at(posL); - else - break; - posL++; - } - int numL = temp.toInt(); - temp.clear(); - - while (posR < nameRight.size()) { - if (nameRight.at(posR).isDigit()) - temp += nameRight.at(posR); - else - break; - posR++; - } - int numR = temp.toInt(); - - if (numL != numR) - return numL < numR; - - // Strings + digits do match and we haven't hit string end - // Do another round - nameLeft.remove(0, posL); - nameRight.remove(0, posR); - continue; - - } while (true); + bool res = false; + if (misc::naturalSort(vL.toString(), vR.toString(), res)) + return res; return QSortFilterProxyModel::lessThan(left, right); }