Browse Source

Merge pull request #2142 from sorokin/repaint

Misc changes in TorrentModel and TransferListWidget
adaptive-webui-19844
sledgehammer999 10 years ago
parent
commit
21139f9d29
  1. 7
      src/qtlibtorrent/torrentmodel.cpp
  2. 3
      src/qtlibtorrent/torrentmodel.h
  3. 3
      src/src.pro
  4. 90
      src/statussortfilterproxymodel.cpp
  5. 52
      src/statussortfilterproxymodel.h
  6. 6
      src/transferlistfilterswidget.cpp
  7. 255
      src/transferlistsortmodel.cpp
  8. 146
      src/transferlistsortmodel.h
  9. 42
      src/transferlistwidget.cpp
  10. 4
      src/transferlistwidget.h

7
src/qtlibtorrent/torrentmodel.cpp

@ -508,7 +508,6 @@ void TorrentModel::setRefreshInterval(int refreshInterval)
void TorrentModel::forceModelRefresh() void TorrentModel::forceModelRefresh()
{ {
emit dataChanged(index(0, 0), index(rowCount()-1, columnCount()-1));
QBtSession::instance()->postTorrentUpdate(); QBtSession::instance()->postTorrentUpdate();
} }
@ -591,9 +590,13 @@ void TorrentModel::stateUpdated(const std::vector<libtorrent::torrent_status> &s
libtorrent::torrent_status const& status = *i; libtorrent::torrent_status const& status = *i;
const int row = torrentRow(misc::toQString(status.info_hash)); const int row = torrentRow(misc::toQString(status.info_hash));
if (row >= 0) if (row >= 0) {
m_torrents[row]->refreshStatus(status); m_torrents[row]->refreshStatus(status);
notifyTorrentChanged(row);
} }
}
emit modelRefreshed();
} }
bool TorrentModel::inhibitSystem() bool TorrentModel::inhibitSystem()

3
src/qtlibtorrent/torrentmodel.h

@ -57,7 +57,7 @@ public:
inline int columnCount() const { return NB_COLUMNS; } inline int columnCount() const { return NB_COLUMNS; }
QVariant data(int column, int role = Qt::DisplayRole) const; QVariant data(int column, int role = Qt::DisplayRole) const;
bool setData(int column, const QVariant &value, int role = Qt::DisplayRole); bool setData(int column, const QVariant &value, int role = Qt::DisplayRole);
inline QString hash() const { return m_hash; } inline QString const& hash() const { return m_hash; }
State state() const; State state() const;
signals: signals:
@ -101,6 +101,7 @@ signals:
void torrentAdded(TorrentModelItem *torrentItem); void torrentAdded(TorrentModelItem *torrentItem);
void torrentAboutToBeRemoved(TorrentModelItem *torrentItem); void torrentAboutToBeRemoved(TorrentModelItem *torrentItem);
void torrentChangedLabel(TorrentModelItem *torrentItem, QString previous, QString current); void torrentChangedLabel(TorrentModelItem *torrentItem, QString previous, QString current);
void modelRefreshed();
private slots: private slots:
void addTorrent(const QTorrentHandle& h); void addTorrent(const QTorrentHandle& h);

3
src/src.pro

@ -154,12 +154,12 @@ nox {
autoexpandabledialog.h \ autoexpandabledialog.h \
statsdialog.h \ statsdialog.h \
messageboxraised.h \ messageboxraised.h \
statussortfilterproxymodel.h \
torrentfilterenum.h torrentfilterenum.h
SOURCES += mainwindow.cpp \ SOURCES += mainwindow.cpp \
ico.cpp \ ico.cpp \
transferlistwidget.cpp \ transferlistwidget.cpp \
transferlistsortmodel.cpp \
transferlistdelegate.cpp \ transferlistdelegate.cpp \
transferlistfilterswidget.cpp \ transferlistfilterswidget.cpp \
torrentcontentmodel.cpp \ torrentcontentmodel.cpp \
@ -178,7 +178,6 @@ nox {
autoexpandabledialog.cpp \ autoexpandabledialog.cpp \
statsdialog.cpp \ statsdialog.cpp \
messageboxraised.cpp \ messageboxraised.cpp \
statussortfilterproxymodel.cpp \
statusbar.cpp \ statusbar.cpp \
trackerlogin.cpp trackerlogin.cpp

90
src/statussortfilterproxymodel.cpp

@ -1,90 +0,0 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2014 sledgehammer999
*
* 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 the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : hammered999@gmail.com
*/
#include "statussortfilterproxymodel.h"
#include "torrentmodel.h"
StatusSortFilterProxyModel::StatusSortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), filter0(TorrentFilter::ALL)
{
}
void StatusSortFilterProxyModel::setFilterStatus(const TorrentFilter::TorrentFilter &filter) {
if (filter != filter0) {
filter0 = filter;
invalidateFilter();
}
}
TorrentFilter::TorrentFilter StatusSortFilterProxyModel::getFilterStatus() const {
return filter0;
}
bool StatusSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
if (filter0 == TorrentFilter::ALL)
return true;
QAbstractItemModel *model = sourceModel();
if (!model) return false;
QModelIndex index = model->index(sourceRow, TorrentModelItem::TR_STATUS, sourceParent);
TorrentModelItem::State state = (TorrentModelItem::State)index.data().toInt();
switch (filter0) {
case TorrentFilter::DOWNLOADING:
return (state == TorrentModelItem::STATE_DOWNLOADING || state == TorrentModelItem::STATE_STALLED_DL
|| state == TorrentModelItem::STATE_PAUSED_DL || state == TorrentModelItem::STATE_CHECKING_DL
|| state == TorrentModelItem::STATE_QUEUED_DL || state == TorrentModelItem::STATE_DOWNLOADING_META);
case TorrentFilter::COMPLETED:
return (state == TorrentModelItem::STATE_SEEDING || state == TorrentModelItem::STATE_STALLED_UP
|| state == TorrentModelItem::STATE_PAUSED_UP || state == TorrentModelItem::STATE_CHECKING_UP
|| state == TorrentModelItem::STATE_QUEUED_UP);
case TorrentFilter::PAUSED:
return (state == TorrentModelItem::STATE_PAUSED_UP || state == TorrentModelItem::STATE_PAUSED_DL);
case TorrentFilter::ACTIVE:
if (state == TorrentModelItem::STATE_STALLED_DL) {
const qulonglong up_speed = model->index(sourceRow, TorrentModelItem::TR_UPSPEED, sourceParent).data().toULongLong();
return (up_speed > 0);
}
return (state == TorrentModelItem::STATE_DOWNLOADING || state == TorrentModelItem::STATE_SEEDING);
case TorrentFilter::INACTIVE:
if (state == TorrentModelItem::STATE_STALLED_DL) {
const qulonglong up_speed = model->index(sourceRow, TorrentModelItem::TR_UPSPEED, sourceParent).data().toULongLong();
return !(up_speed > 0);
}
return (state != TorrentModelItem::STATE_DOWNLOADING && state != TorrentModelItem::STATE_SEEDING);
default:
return false;
}
}

52
src/statussortfilterproxymodel.h

@ -1,52 +0,0 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2014 sledgehammer999
*
* 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 the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : hammered999@gmail.com
*/
#ifndef STATUSSORTFILTERPROXYMODEL_H
#define STATUSSORTFILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
#include "torrentfilterenum.h"
class StatusSortFilterProxyModel : public QSortFilterProxyModel {
Q_OBJECT
public:
StatusSortFilterProxyModel(QObject *parent = 0);
void setFilterStatus(const TorrentFilter::TorrentFilter &filter);
TorrentFilter::TorrentFilter getFilterStatus() const;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private:
TorrentFilter::TorrentFilter filter0;
};
#endif // STATUSSORTFILTERPROXYMODEL_H

6
src/transferlistfilterswidget.cpp

@ -203,7 +203,7 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
// SIGNAL/SLOT // SIGNAL/SLOT
connect(statusFilters, SIGNAL(currentRowChanged(int)), transferList, SLOT(applyStatusFilter(int))); connect(statusFilters, SIGNAL(currentRowChanged(int)), transferList, SLOT(applyStatusFilter(int)));
connect(transferList->getSourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(updateTorrentNumbers())); connect(transferList->getSourceModel(), SIGNAL(modelRefreshed()), SLOT(updateTorrentNumbers()));
connect(transferList->getSourceModel(), SIGNAL(torrentAdded(TorrentModelItem*)), SLOT(handleNewTorrent(TorrentModelItem*))); connect(transferList->getSourceModel(), SIGNAL(torrentAdded(TorrentModelItem*)), SLOT(handleNewTorrent(TorrentModelItem*)));
connect(labelFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyLabelFilter(int))); connect(labelFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyLabelFilter(int)));
connect(labelFilters, SIGNAL(torrentDropped(int)), this, SLOT(torrentDropped(int))); connect(labelFilters, SIGNAL(torrentDropped(int)), this, SLOT(torrentDropped(int)));
@ -359,10 +359,10 @@ void TransferListFiltersWidget::removeSelectedLabel() {
void TransferListFiltersWidget::applyLabelFilter(int row) { void TransferListFiltersWidget::applyLabelFilter(int row) {
switch(row) { switch(row) {
case 0: case 0:
transferList->applyLabelFilter("all"); transferList->applyLabelFilterAll();
break; break;
case 1: case 1:
transferList->applyLabelFilter("none"); transferList->applyLabelFilter(QString());
break; break;
default: default:
transferList->applyLabelFilter(labelFilters->labelFromRow(row)); transferList->applyLabelFilter(labelFilters->labelFromRow(row));

255
src/transferlistsortmodel.cpp

@ -0,0 +1,255 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2013 Nick Tiskov
*
* 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 the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : daymansmail@gmail.com
*/
#include "transferlistsortmodel.h"
#include "torrentmodel.h"
#include "misc.h"
TransferListSortModel::TransferListSortModel(QObject *parent)
: QSortFilterProxyModel(parent)
, filter0(TorrentFilter::ALL)
{}
void TransferListSortModel::setStatusFilter(const TorrentFilter::TorrentFilter &filter) {
if (filter != filter0) {
filter0 = filter;
invalidateFilter();
}
}
void TransferListSortModel::setLabelFilter(QString const& label) {
if (!labelFilterEnabled || labelFilter != label) {
labelFilterEnabled = true;
labelFilter = label;
invalidateFilter();
}
}
void TransferListSortModel::disableLabelFilter() {
if (labelFilterEnabled) {
labelFilterEnabled = false;
labelFilter = QString();
invalidateFilter();
}
}
bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const {
const int column = sortColumn();
if (column == TorrentModelItem::TR_NAME) {
QVariant vL = left.data();
QVariant vR = right.data();
if (!(vL.isValid() && vR.isValid()))
return QSortFilterProxyModel::lessThan(left, right);
Q_ASSERT(vL.isValid());
Q_ASSERT(vR.isValid());
bool res = false;
if (misc::naturalSort(vL.toString(), vR.toString(), res))
return res;
return QSortFilterProxyModel::lessThan(left, right);
}
else if (column == TorrentModelItem::TR_ADD_DATE || column == TorrentModelItem::TR_SEED_DATE || column == TorrentModelItem::TR_SEEN_COMPLETE_DATE) {
QDateTime vL = left.data().toDateTime();
QDateTime vR = right.data().toDateTime();
//not valid dates should be sorted at the bottom.
if (!vL.isValid()) return false;
if (!vR.isValid()) return true;
return vL < vR;
}
else if (column == TorrentModelItem::TR_PRIORITY) {
const int vL = left.data().toInt();
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) {
int left_active = left.data().toInt();
int left_total = left.data(Qt::UserRole).toInt();
int right_active = right.data().toInt();
int right_total = right.data(Qt::UserRole).toInt();
// Active peers/seeds take precedence over total peers/seeds.
if (left_active == right_active)
return (left_total < right_total);
else return (left_active < right_active);
}
else if (column == TorrentModelItem::TR_ETA) {
const QAbstractItemModel *model = sourceModel();
const int prioL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int prioR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const qlonglong etaL = left.data().toLongLong();
const qlonglong etaR = right.data().toLongLong();
const bool ascend = (sortOrder() == Qt::AscendingOrder);
const bool invalidL = (etaL < 0 || etaL >= MAX_ETA);
const bool invalidR = (etaR < 0 || etaR >= MAX_ETA);
const bool seedingL = (prioL < 0);
const bool seedingR = (prioR < 0);
bool activeL;
bool activeR;
switch (model->data(model->index(left.row(), TorrentModelItem::TR_STATUS)).toInt()) {
case TorrentModelItem::STATE_DOWNLOADING:
case TorrentModelItem::STATE_DOWNLOADING_META:
case TorrentModelItem::STATE_STALLED_DL:
case TorrentModelItem::STATE_SEEDING:
case TorrentModelItem::STATE_STALLED_UP:
activeL = true;
break;
default:
activeL = false;
}
switch (model->data(model->index(right.row(), TorrentModelItem::TR_STATUS)).toInt()) {
case TorrentModelItem::STATE_DOWNLOADING:
case TorrentModelItem::STATE_DOWNLOADING_META:
case TorrentModelItem::STATE_STALLED_DL:
case TorrentModelItem::STATE_SEEDING:
case TorrentModelItem::STATE_STALLED_UP:
activeR = true;
break;
default:
activeR = false;
}
// Sorting rules prioritized.
// 1. Active torrents at the top
// 2. Seeding torrents at the bottom
// 3. Torrents with invalid ETAs at the bottom
if (activeL != activeR) return activeL;
if (seedingL != seedingR) {
if (seedingL) return !ascend;
else return ascend;
}
if (invalidL && invalidR) {
if (seedingL) { //Both seeding
QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
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;
}
else
return prioL < prioR;
}
else if ((invalidL == false) && (invalidR == false))
return QSortFilterProxyModel::lessThan(left, right);
else
return !invalidL;
}
return QSortFilterProxyModel::lessThan(left, right);
}
bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
return matchStatusFilter(sourceRow, sourceParent)
&& matchLabelFilter(sourceRow, sourceParent)
&& QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
bool TransferListSortModel::matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const {
if (filter0 == TorrentFilter::ALL)
return true;
QAbstractItemModel *model = sourceModel();
if (!model) return false;
QModelIndex index = model->index(sourceRow, TorrentModelItem::TR_STATUS, sourceParent);
TorrentModelItem::State state = (TorrentModelItem::State)index.data().toInt();
switch (filter0) {
case TorrentFilter::DOWNLOADING:
return (state == TorrentModelItem::STATE_DOWNLOADING || state == TorrentModelItem::STATE_STALLED_DL
|| state == TorrentModelItem::STATE_PAUSED_DL || state == TorrentModelItem::STATE_CHECKING_DL
|| state == TorrentModelItem::STATE_QUEUED_DL || state == TorrentModelItem::STATE_DOWNLOADING_META);
case TorrentFilter::COMPLETED:
return (state == TorrentModelItem::STATE_SEEDING || state == TorrentModelItem::STATE_STALLED_UP
|| state == TorrentModelItem::STATE_PAUSED_UP || state == TorrentModelItem::STATE_CHECKING_UP
|| state == TorrentModelItem::STATE_QUEUED_UP);
case TorrentFilter::PAUSED:
return (state == TorrentModelItem::STATE_PAUSED_UP || state == TorrentModelItem::STATE_PAUSED_DL);
case TorrentFilter::ACTIVE:
if (state == TorrentModelItem::STATE_STALLED_DL) {
const qulonglong up_speed = model->index(sourceRow, TorrentModelItem::TR_UPSPEED, sourceParent).data().toULongLong();
return (up_speed > 0);
}
return (state == TorrentModelItem::STATE_DOWNLOADING || state == TorrentModelItem::STATE_SEEDING);
case TorrentFilter::INACTIVE:
if (state == TorrentModelItem::STATE_STALLED_DL) {
const qulonglong up_speed = model->index(sourceRow, TorrentModelItem::TR_UPSPEED, sourceParent).data().toULongLong();
return !(up_speed > 0);
}
return (state != TorrentModelItem::STATE_DOWNLOADING && state != TorrentModelItem::STATE_SEEDING);
default:
return false;
}
}
bool TransferListSortModel::matchLabelFilter(int sourceRow, const QModelIndex &sourceParent) const {
if (!labelFilterEnabled)
return true;
QAbstractItemModel *model = sourceModel();
if (!model)
return false;
return model->index(sourceRow, TorrentModelItem::TR_LABEL, sourceParent).data().toString() == labelFilter;
}

146
src/transferlistsortmodel.h

@ -32,148 +32,30 @@
#define TRANSFERLISTSORTMODEL_H #define TRANSFERLISTSORTMODEL_H
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include "torrentmodel.h" #include "torrentfilterenum.h"
#include "misc.h"
class TransferListSortModel : public QSortFilterProxyModel { class TransferListSortModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
public: public:
TransferListSortModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {} TransferListSortModel(QObject *parent = 0);
protected: void setStatusFilter(const TorrentFilter::TorrentFilter &filter);
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const { void setLabelFilter(QString const& label);
const int column = sortColumn(); void disableLabelFilter();
if (column == TorrentModelItem::TR_NAME) { private:
QVariant vL = left.data(); bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
QVariant vR = right.data(); bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
if (!(vL.isValid() && vR.isValid()))
return QSortFilterProxyModel::lessThan(left, right);
Q_ASSERT(vL.isValid());
Q_ASSERT(vR.isValid());
bool res = false; bool matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const;
if (misc::naturalSort(vL.toString(), vR.toString(), res)) bool matchLabelFilter(int sourceRow, const QModelIndex &sourceParent) const;
return res;
return QSortFilterProxyModel::lessThan(left, right); private:
} TorrentFilter::TorrentFilter filter0;
else if (column == TorrentModelItem::TR_ADD_DATE || column == TorrentModelItem::TR_SEED_DATE || column == TorrentModelItem::TR_SEEN_COMPLETE_DATE) {
QDateTime vL = left.data().toDateTime();
QDateTime vR = right.data().toDateTime();
//not valid dates should be sorted at the bottom. bool labelFilterEnabled;
if (!vL.isValid()) return false; QString labelFilter;
if (!vR.isValid()) return true;
return vL < vR;
}
else if (column == TorrentModelItem::TR_PRIORITY) {
const int vL = left.data().toInt();
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) {
int left_active = left.data().toInt();
int left_total = left.data(Qt::UserRole).toInt();
int right_active = right.data().toInt();
int right_total = right.data(Qt::UserRole).toInt();
// Active peers/seeds take precedence over total peers/seeds.
if (left_active == right_active)
return (left_total < right_total);
else return (left_active < right_active);
}
else if (column == TorrentModelItem::TR_ETA) {
const QAbstractItemModel *model = sourceModel();
const int prioL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int prioR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const qlonglong etaL = left.data().toLongLong();
const qlonglong etaR = right.data().toLongLong();
const bool ascend = (sortOrder() == Qt::AscendingOrder);
const bool invalidL = (etaL < 0 || etaL >= MAX_ETA);
const bool invalidR = (etaR < 0 || etaR >= MAX_ETA);
const bool seedingL = (prioL < 0);
const bool seedingR = (prioR < 0);
bool activeL;
bool activeR;
switch (model->data(model->index(left.row(), TorrentModelItem::TR_STATUS)).toInt()) {
case TorrentModelItem::STATE_DOWNLOADING:
case TorrentModelItem::STATE_DOWNLOADING_META:
case TorrentModelItem::STATE_STALLED_DL:
case TorrentModelItem::STATE_SEEDING:
case TorrentModelItem::STATE_STALLED_UP:
activeL = true;
break;
default:
activeL = false;
}
switch (model->data(model->index(right.row(), TorrentModelItem::TR_STATUS)).toInt()) {
case TorrentModelItem::STATE_DOWNLOADING:
case TorrentModelItem::STATE_DOWNLOADING_META:
case TorrentModelItem::STATE_STALLED_DL:
case TorrentModelItem::STATE_SEEDING:
case TorrentModelItem::STATE_STALLED_UP:
activeR = true;
break;
default:
activeR = false;
}
// Sorting rules prioritized.
// 1. Active torrents at the top
// 2. Seeding torrents at the bottom
// 3. Torrents with invalid ETAs at the bottom
if (activeL != activeR) return activeL;
if (seedingL != seedingR) {
if (seedingL) return !ascend;
else return ascend;
}
if (invalidL && invalidR) {
if (seedingL) { //Both seeding
QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
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;
}
else
return prioL < prioR;
}
else if ((invalidL == false) && (invalidR == false))
return QSortFilterProxyModel::lessThan(left, right);
else
return !invalidL;
}
return QSortFilterProxyModel::lessThan(left, right);
}
}; };
#endif // TRANSFERLISTSORTMODEL_H #endif // TRANSFERLISTSORTMODEL_H

42
src/transferlistwidget.cpp

@ -63,7 +63,6 @@
#include "iconprovider.h" #include "iconprovider.h"
#include "fs_utils.h" #include "fs_utils.h"
#include "autoexpandabledialog.h" #include "autoexpandabledialog.h"
#include "statussortfilterproxymodel.h"
#include "transferlistsortmodel.h" #include "transferlistsortmodel.h"
using namespace libtorrent; using namespace libtorrent;
@ -82,20 +81,9 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window,
// Create transfer list model // Create transfer list model
listModel = new TorrentModel(this); listModel = new TorrentModel(this);
// Set Sort/Filter proxy
labelFilterModel = new QSortFilterProxyModel();
labelFilterModel->setDynamicSortFilter(true);
labelFilterModel->setSourceModel(listModel);
labelFilterModel->setFilterKeyColumn(TorrentModelItem::TR_LABEL);
labelFilterModel->setFilterRole(Qt::DisplayRole);
statusFilterModel = new StatusSortFilterProxyModel();
statusFilterModel->setDynamicSortFilter(true);
statusFilterModel->setSourceModel(labelFilterModel);
nameFilterModel = new TransferListSortModel(); nameFilterModel = new TransferListSortModel();
nameFilterModel->setDynamicSortFilter(true); nameFilterModel->setDynamicSortFilter(true);
nameFilterModel->setSourceModel(statusFilterModel); nameFilterModel->setSourceModel(listModel);
nameFilterModel->setFilterKeyColumn(TorrentModelItem::TR_NAME); nameFilterModel->setFilterKeyColumn(TorrentModelItem::TR_NAME);
nameFilterModel->setFilterRole(Qt::DisplayRole); nameFilterModel->setFilterRole(Qt::DisplayRole);
nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive); nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
@ -170,8 +158,6 @@ TransferListWidget::~TransferListWidget() {
// Save settings // Save settings
saveSettings(); saveSettings();
// Clean up // Clean up
delete labelFilterModel;
delete statusFilterModel;
delete nameFilterModel; delete nameFilterModel;
delete listModel; delete listModel;
delete listDelegate; delete listDelegate;
@ -204,16 +190,14 @@ inline QString TransferListWidget::getHashFromRow(int row) const {
inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const { inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const {
Q_ASSERT(index.isValid()); Q_ASSERT(index.isValid());
if (index.model() == nameFilterModel) if (index.model() == nameFilterModel)
return labelFilterModel->mapToSource(statusFilterModel->mapToSource(nameFilterModel->mapToSource(index))); return nameFilterModel->mapToSource(index);
if (index.model() == statusFilterModel) return index;
return labelFilterModel->mapToSource(statusFilterModel->mapToSource(index));
return labelFilterModel->mapToSource(index);
} }
inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const { inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const {
Q_ASSERT(index.isValid()); Q_ASSERT(index.isValid());
Q_ASSERT(index.model() == labelFilterModel); Q_ASSERT(index.model() == nameFilterModel);
return nameFilterModel->mapFromSource(statusFilterModel->mapFromSource(labelFilterModel->mapFromSource(index))); return nameFilterModel->mapFromSource(index);
} }
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) { void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) {
@ -901,17 +885,13 @@ void TransferListWidget::currentChanged(const QModelIndex& current, const QModel
emit currentTorrentChanged(h); emit currentTorrentChanged(h);
} }
void TransferListWidget::applyLabelFilterAll() {
nameFilterModel->disableLabelFilter();
}
void TransferListWidget::applyLabelFilter(QString label) { void TransferListWidget::applyLabelFilter(QString label) {
if (label == "all") {
labelFilterModel->setFilterRegExp(QRegExp());
return;
}
if (label == "none") {
labelFilterModel->setFilterRegExp(QRegExp("^$"));
return;
}
qDebug("Applying Label filter: %s", qPrintable(label)); qDebug("Applying Label filter: %s", qPrintable(label));
labelFilterModel->setFilterRegExp(QRegExp("^" + QRegExp::escape(label) + "$", Qt::CaseSensitive)); nameFilterModel->setLabelFilter(label);
} }
void TransferListWidget::applyNameFilter(const QString& name) { void TransferListWidget::applyNameFilter(const QString& name) {
@ -919,7 +899,7 @@ void TransferListWidget::applyNameFilter(const QString& name) {
} }
void TransferListWidget::applyStatusFilter(int f) { void TransferListWidget::applyStatusFilter(int f) {
statusFilterModel->setFilterStatus((TorrentFilter::TorrentFilter)f); nameFilterModel->setStatusFilter((TorrentFilter::TorrentFilter)f);
// Select first item if nothing is selected // Select first item if nothing is selected
if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) { if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) {
qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModelItem::TR_NAME).data().toString())); qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModelItem::TR_NAME).data().toString()));

4
src/transferlistwidget.h

@ -40,7 +40,6 @@ class MainWindow;
class TransferListDelegate; class TransferListDelegate;
class TransferListSortModel; class TransferListSortModel;
class TorrentModel; class TorrentModel;
class StatusSortFilterProxyModel;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QShortcut; class QShortcut;
@ -81,6 +80,7 @@ public slots:
void displayDLHoSMenu(const QPoint&); void displayDLHoSMenu(const QPoint&);
void applyNameFilter(const QString& name); void applyNameFilter(const QString& name);
void applyStatusFilter(int f); void applyStatusFilter(int f);
void applyLabelFilterAll();
void applyLabelFilter(QString label); void applyLabelFilter(QString label);
void previewFile(QString filePath); void previewFile(QString filePath);
void removeLabelFromRows(QString label); void removeLabelFromRows(QString label);
@ -114,8 +114,6 @@ private:
TransferListDelegate *listDelegate; TransferListDelegate *listDelegate;
TorrentModel *listModel; TorrentModel *listModel;
TransferListSortModel *nameFilterModel; TransferListSortModel *nameFilterModel;
StatusSortFilterProxyModel *statusFilterModel;
QSortFilterProxyModel *labelFilterModel;
QBtSession* BTSession; QBtSession* BTSession;
MainWindow *main_window; MainWindow *main_window;
QShortcut *editHotkey; QShortcut *editHotkey;

Loading…
Cancel
Save