|
|
|
@ -41,7 +41,6 @@ TransferListSortModel::TransferListSortModel(QObject *parent)
@@ -41,7 +41,6 @@ TransferListSortModel::TransferListSortModel(QObject *parent)
|
|
|
|
|
: QSortFilterProxyModel {parent} |
|
|
|
|
{ |
|
|
|
|
setSortRole(TransferListModel::UnderlyingDataRole); |
|
|
|
|
QMetaType::registerComparators<BitTorrent::TorrentState>(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TransferListSortModel::setStatusFilter(TorrentFilter::Type filter) |
|
|
|
@ -103,8 +102,8 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -103,8 +102,8 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
const auto hashLessThan = [this, &left, &right]() -> bool |
|
|
|
|
{ |
|
|
|
|
const TransferListModel *model = qobject_cast<TransferListModel *>(sourceModel()); |
|
|
|
|
const QString hashL = model->torrentHandle(left)->hash(); |
|
|
|
|
const QString hashR = model->torrentHandle(right)->hash(); |
|
|
|
|
const BitTorrent::InfoHash hashL = model->torrentHandle(left)->hash(); |
|
|
|
|
const BitTorrent::InfoHash hashR = model->torrentHandle(right)->hash(); |
|
|
|
|
return hashL < hashR; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -122,21 +121,21 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -122,21 +121,21 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
return (Utils::String::naturalCompare(leftValue.toString(), rightValue.toString(), Qt::CaseInsensitive) < 0); |
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_STATUS: |
|
|
|
|
// QSortFilterProxyModel::lessThan() uses the < operator only for specific QVariant types
|
|
|
|
|
// so our custom type is outside that list.
|
|
|
|
|
// In this case QSortFilterProxyModel::lessThan() converts other types to QString and
|
|
|
|
|
// sorts them.
|
|
|
|
|
// Thus we can't use the code in the default label.
|
|
|
|
|
if (leftValue != rightValue) |
|
|
|
|
return leftValue < rightValue; |
|
|
|
|
return invokeLessThanForColumn(TransferListModel::TR_QUEUE_POSITION); |
|
|
|
|
{ |
|
|
|
|
const auto stateL = leftValue.value<BitTorrent::TorrentState>(); |
|
|
|
|
const auto stateR = rightValue.value<BitTorrent::TorrentState>(); |
|
|
|
|
|
|
|
|
|
if (stateL != stateR) |
|
|
|
|
return stateL < stateR; |
|
|
|
|
return invokeLessThanForColumn(TransferListModel::TR_QUEUE_POSITION); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_ADD_DATE: |
|
|
|
|
case TransferListModel::TR_SEED_DATE: |
|
|
|
|
case TransferListModel::TR_SEEN_COMPLETE_DATE: |
|
|
|
|
{ |
|
|
|
|
const QDateTime dateL = leftValue.toDateTime(); |
|
|
|
|
const QDateTime dateR = rightValue.toDateTime(); |
|
|
|
|
{ |
|
|
|
|
const auto dateL = leftValue.toDateTime(); |
|
|
|
|
const auto dateR = rightValue.toDateTime(); |
|
|
|
|
|
|
|
|
|
if (dateL.isValid() && dateR.isValid()) |
|
|
|
|
{ |
|
|
|
@ -156,20 +155,21 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -156,20 +155,21 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_QUEUE_POSITION: |
|
|
|
|
{ |
|
|
|
|
// QVariant has comparators for all basic types
|
|
|
|
|
if ((leftValue > 0) || (rightValue > 0)) |
|
|
|
|
{ |
|
|
|
|
if ((leftValue > 0) && (rightValue > 0)) |
|
|
|
|
return leftValue < rightValue; |
|
|
|
|
{ |
|
|
|
|
const auto positionL = leftValue.toInt(); |
|
|
|
|
const auto positionR = rightValue.toInt(); |
|
|
|
|
|
|
|
|
|
return leftValue != 0; |
|
|
|
|
if ((positionL > 0) || (positionR > 0)) |
|
|
|
|
{ |
|
|
|
|
if ((positionL > 0) && (positionR > 0)) |
|
|
|
|
return positionL < positionR; |
|
|
|
|
return positionL != 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Sort according to TR_SEED_DATE
|
|
|
|
|
const QDateTime dateL = left.sibling(left.row(), TransferListModel::TR_SEED_DATE) |
|
|
|
|
const auto dateL = left.sibling(left.row(), TransferListModel::TR_SEED_DATE) |
|
|
|
|
.data(TransferListModel::UnderlyingDataRole).toDateTime(); |
|
|
|
|
const QDateTime dateR = right.sibling(right.row(), TransferListModel::TR_SEED_DATE) |
|
|
|
|
const auto dateR = right.sibling(right.row(), TransferListModel::TR_SEED_DATE) |
|
|
|
|
.data(TransferListModel::UnderlyingDataRole).toDateTime(); |
|
|
|
|
|
|
|
|
|
if (dateL.isValid() && dateR.isValid()) |
|
|
|
@ -191,22 +191,23 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -191,22 +191,23 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_SEEDS: |
|
|
|
|
case TransferListModel::TR_PEERS: |
|
|
|
|
{ |
|
|
|
|
// QVariant has comparators for all basic types
|
|
|
|
|
// Active peers/seeds take precedence over total peers/seeds.
|
|
|
|
|
if (leftValue != rightValue) |
|
|
|
|
return (leftValue < rightValue); |
|
|
|
|
|
|
|
|
|
const QVariant leftValueTotal = left.data(TransferListModel::AdditionalUnderlyingDataRole); |
|
|
|
|
const QVariant rightValueTotal = right.data(TransferListModel::AdditionalUnderlyingDataRole); |
|
|
|
|
if (leftValueTotal != rightValueTotal) |
|
|
|
|
return (leftValueTotal < rightValueTotal); |
|
|
|
|
{ |
|
|
|
|
// Active peers/seeds take precedence over total peers/seeds
|
|
|
|
|
const auto activeL = leftValue.toInt(); |
|
|
|
|
const auto activeR = rightValue.toInt(); |
|
|
|
|
if (activeL != activeR) |
|
|
|
|
return activeL < activeR; |
|
|
|
|
|
|
|
|
|
const auto totalL = left.data(TransferListModel::AdditionalUnderlyingDataRole).toInt(); |
|
|
|
|
const auto totalR = right.data(TransferListModel::AdditionalUnderlyingDataRole).toInt(); |
|
|
|
|
if (totalL != totalR) |
|
|
|
|
return totalL < totalR; |
|
|
|
|
|
|
|
|
|
return invokeLessThanForColumn(TransferListModel::TR_QUEUE_POSITION); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_ETA: |
|
|
|
|
{ |
|
|
|
|
{ |
|
|
|
|
// Sorting rules prioritized.
|
|
|
|
|
// 1. Active torrents at the top
|
|
|
|
|
// 2. Seeding torrents at the bottom
|
|
|
|
@ -221,9 +222,9 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -221,9 +222,9 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
if (isActiveL != isActiveR) |
|
|
|
|
return isActiveL; |
|
|
|
|
|
|
|
|
|
const int queuePosL = left.sibling(left.row(), TransferListModel::TR_QUEUE_POSITION) |
|
|
|
|
const auto queuePosL = left.sibling(left.row(), TransferListModel::TR_QUEUE_POSITION) |
|
|
|
|
.data(TransferListModel::UnderlyingDataRole).toInt(); |
|
|
|
|
const int queuePosR = right.sibling(right.row(), TransferListModel::TR_QUEUE_POSITION) |
|
|
|
|
const auto queuePosR = right.sibling(right.row(), TransferListModel::TR_QUEUE_POSITION) |
|
|
|
|
.data(TransferListModel::UnderlyingDataRole).toInt(); |
|
|
|
|
const bool isSeedingL = (queuePosL < 0); |
|
|
|
|
const bool isSeedingR = (queuePosR < 0); |
|
|
|
@ -236,8 +237,8 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -236,8 +237,8 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
return isAscendingOrder; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const qlonglong etaL = leftValue.toLongLong(); |
|
|
|
|
const qlonglong etaR = rightValue.toLongLong(); |
|
|
|
|
const auto etaL = leftValue.toLongLong(); |
|
|
|
|
const auto etaR = rightValue.toLongLong(); |
|
|
|
|
const bool isInvalidL = ((etaL < 0) || (etaL >= MAX_ETA)); |
|
|
|
|
const bool isInvalidR = ((etaR < 0) || (etaR >= MAX_ETA)); |
|
|
|
|
if (isInvalidL && isInvalidR) |
|
|
|
@ -255,12 +256,24 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
@@ -255,12 +256,24 @@ bool TransferListSortModel::lessThan_impl(const QModelIndex &left, const QModelI
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_LAST_ACTIVITY: |
|
|
|
|
{ |
|
|
|
|
const auto lastActivityL = leftValue.toLongLong(); |
|
|
|
|
const auto lastActivityR = rightValue.toLongLong(); |
|
|
|
|
|
|
|
|
|
if (lastActivityL < 0) return false; |
|
|
|
|
if (lastActivityR < 0) return true; |
|
|
|
|
return lastActivityL < lastActivityR; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case TransferListModel::TR_RATIO_LIMIT: |
|
|
|
|
// QVariant has comparators for all basic types
|
|
|
|
|
if (leftValue < 0) return false; |
|
|
|
|
if (rightValue < 0) return true; |
|
|
|
|
{ |
|
|
|
|
const auto ratioL = leftValue.toReal(); |
|
|
|
|
const auto ratioR = rightValue.toReal(); |
|
|
|
|
|
|
|
|
|
return (leftValue < rightValue); |
|
|
|
|
if (ratioL < 0) return false; |
|
|
|
|
if (ratioR < 0) return true; |
|
|
|
|
return ratioL < ratioR; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (leftValue != rightValue) |
|
|
|
|