Browse Source

Don't reorder the torrents in the transfer list if not necessary

The current sorting algorithm is not stable and causes undesidered
rearrangements of the transfer list when different torrents have same
values in respect to the current sorting criterion. Fix this by using
the priority, the seed date and the hash of the torrents as fallback
values to determine the order.

Closes #2158.
Closes #2526.
adaptive-webui-19844
Gabriele 10 years ago
parent
commit
1f77a03eb6
  1. 74
      src/gui/transferlistsortmodel.cpp
  2. 1
      src/gui/transferlistsortmodel.h

74
src/gui/transferlistsortmodel.cpp

@ -93,10 +93,13 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
QVariant vL = left.data(); QVariant vL = left.data();
QVariant vR = right.data(); QVariant vR = right.data();
if (!(vL.isValid() && vR.isValid())) if (!(vL.isValid() && vR.isValid()))
return QSortFilterProxyModel::lessThan(left, right); return lowerPositionThan(left, right);
Q_ASSERT(vL.isValid()); Q_ASSERT(vL.isValid());
Q_ASSERT(vR.isValid()); Q_ASSERT(vR.isValid());
if (vL == vR)
return lowerPositionThan(left, right);
bool res = false; bool res = false;
if (misc::naturalSort(vL.toString(), vR.toString(), res)) if (misc::naturalSort(vL.toString(), vR.toString(), res))
return res; return res;
@ -114,26 +117,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return vL < vR; return vL < vR;
} }
else if (column == TorrentModelItem::TR_PRIORITY) { else if (column == TorrentModelItem::TR_PRIORITY) {
const int vL = left.data().toInt(); return lowerPositionThan(left, right);
const int vR = right.data().toInt();
// Seeding torrents should be sorted by their completed date instead.
if (vL == -1 && vR == -1) {
QAbstractItemModel *model = sourceModel();
const QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
const QDateTime dateR = model->data(model->index(right.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
//not valid dates should be sorted at the bottom.
if (!dateL.isValid()) return false;
if (!dateR.isValid()) return true;
return dateL < dateR;
}
// Seeding torrents should be at the bottom
if (vL == -1) return false;
if (vR == -1) return true;
return vL < vR;
} }
else if (column == TorrentModelItem::TR_PEERS || column == TorrentModelItem::TR_SEEDS) { else if (column == TorrentModelItem::TR_PEERS || column == TorrentModelItem::TR_SEEDS) {
int left_active = left.data().toInt(); int left_active = left.data().toInt();
@ -142,9 +126,14 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
int right_total = right.data(Qt::UserRole).toInt(); int right_total = right.data(Qt::UserRole).toInt();
// Active peers/seeds take precedence over total peers/seeds. // Active peers/seeds take precedence over total peers/seeds.
if (left_active == right_active) if (left_active == right_active) {
if (left_total == right_total)
return lowerPositionThan(left, right);
return (left_total < right_total); return (left_total < right_total);
else return (left_active < right_active); }
else {
return (left_active < right_active);
}
} }
else if (column == TorrentModelItem::TR_ETA) { else if (column == TorrentModelItem::TR_ETA) {
const QAbstractItemModel *model = sourceModel(); const QAbstractItemModel *model = sourceModel();
@ -212,7 +201,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
} }
} }
else if ((invalidL == false) && (invalidR == false)) { else if ((invalidL == false) && (invalidR == false)) {
return QSortFilterProxyModel::lessThan(left, right); return lowerPositionThan(left, right);
} }
else { else {
return !invalidL; return !invalidL;
@ -237,9 +226,46 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return vL < vR; return vL < vR;
} }
if (left.data() == right.data())
return lowerPositionThan(left, right);
return QSortFilterProxyModel::lessThan(left, right); return QSortFilterProxyModel::lessThan(left, right);
} }
bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QModelIndex &right) const
{
const TorrentModel *model = dynamic_cast<TorrentModel*>(sourceModel());
// Sort according to TR_PRIORITY
const int queueL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int queueR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
if (!(queueL < 0 && queueR < 0)) {
if (queueL > 0 && queueR > 0)
return queueL < queueR;
else if (queueL < 0)
return false;
else
return true;
}
// Sort according to TR_SEED_DATE
const QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
const QDateTime dateR = model->data(model->index(right.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
if (dateL.isValid() && dateR.isValid()) {
if (dateL != dateR)
return dateL < dateR;
}
else if (dateL.isValid())
return false;
else if (dateR.isValid())
return true;
// Finally, sort by hash
const QString hashL(model->torrentHash(left.row()));
const QString hashR(model->torrentHash(right.row()));
return hashL < hashR;
}
bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{ {
return matchStatusFilter(sourceRow, sourceParent) return matchStatusFilter(sourceRow, sourceParent)

1
src/gui/transferlistsortmodel.h

@ -50,6 +50,7 @@ public:
private: private:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const; bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
bool lowerPositionThan(const QModelIndex &left, const QModelIndex &right) const;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const; bool matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const;

Loading…
Cancel
Save