Merge StatusSortFilterProxyModel into TransferListSortModel

I thought merging all 3 sort-filter proxy models into one should
speedup dataChanged() signal. As turned out this is not the case. The
time difference is within inaccuracy range, so this doesn't affect
performance.

But I still think it is good to merge them into one proxy model as it
simplifies code.
This commit is contained in:
Ivan Sorokin 2014-11-09 01:58:01 +03:00
parent cf2cb29826
commit 8bafc5e216
7 changed files with 71 additions and 160 deletions

View file

@ -154,7 +154,6 @@ 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 \
@ -179,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

View file

@ -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;
}
}

View file

@ -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

View file

@ -35,8 +35,16 @@
TransferListSortModel::TransferListSortModel(QObject *parent) TransferListSortModel::TransferListSortModel(QObject *parent)
: QSortFilterProxyModel(parent) : QSortFilterProxyModel(parent)
, filter0(TorrentFilter::ALL)
{} {}
void TransferListSortModel::setStatusFilter(const TorrentFilter::TorrentFilter &filter) {
if (filter != filter0) {
filter0 = filter;
invalidateFilter();
}
}
bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const {
const int column = sortColumn(); const int column = sortColumn();
@ -169,3 +177,51 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return QSortFilterProxyModel::lessThan(left, right); return QSortFilterProxyModel::lessThan(left, right);
} }
bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
return matchStatusFilter(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;
}
}

View file

@ -32,6 +32,7 @@
#define TRANSFERLISTSORTMODEL_H #define TRANSFERLISTSORTMODEL_H
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include "torrentfilterenum.h"
class TransferListSortModel : public QSortFilterProxyModel { class TransferListSortModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
@ -39,8 +40,16 @@ class TransferListSortModel : public QSortFilterProxyModel {
public: public:
TransferListSortModel(QObject *parent = 0); TransferListSortModel(QObject *parent = 0);
protected: void setStatusFilter(const TorrentFilter::TorrentFilter &filter);
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
private:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const;
private:
TorrentFilter::TorrentFilter filter0;
}; };
#endif // TRANSFERLISTSORTMODEL_H #endif // TRANSFERLISTSORTMODEL_H

View file

@ -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;
@ -89,13 +88,9 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window,
labelFilterModel->setFilterKeyColumn(TorrentModelItem::TR_LABEL); labelFilterModel->setFilterKeyColumn(TorrentModelItem::TR_LABEL);
labelFilterModel->setFilterRole(Qt::DisplayRole); 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(labelFilterModel);
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);
@ -171,7 +166,6 @@ TransferListWidget::~TransferListWidget() {
saveSettings(); saveSettings();
// Clean up // Clean up
delete labelFilterModel; delete labelFilterModel;
delete statusFilterModel;
delete nameFilterModel; delete nameFilterModel;
delete listModel; delete listModel;
delete listDelegate; delete listDelegate;
@ -204,16 +198,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 labelFilterModel->mapToSource(nameFilterModel->mapToSource(index));
if (index.model() == statusFilterModel)
return labelFilterModel->mapToSource(statusFilterModel->mapToSource(index));
return labelFilterModel->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() == labelFilterModel);
return nameFilterModel->mapFromSource(statusFilterModel->mapFromSource(labelFilterModel->mapFromSource(index))); return nameFilterModel->mapFromSource(labelFilterModel->mapFromSource(index));
} }
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) { void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) {
@ -919,7 +911,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()));

View file

@ -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;
@ -114,7 +113,6 @@ private:
TransferListDelegate *listDelegate; TransferListDelegate *listDelegate;
TorrentModel *listModel; TorrentModel *listModel;
TransferListSortModel *nameFilterModel; TransferListSortModel *nameFilterModel;
StatusSortFilterProxyModel *statusFilterModel;
QSortFilterProxyModel *labelFilterModel; QSortFilterProxyModel *labelFilterModel;
QBtSession* BTSession; QBtSession* BTSession;
MainWindow *main_window; MainWindow *main_window;