mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-03-10 12:21:12 +00:00
Clean up and refactor torrent content model code
This commit is contained in:
parent
8f4c4e8c40
commit
a5452d04ae
@ -46,7 +46,8 @@
|
||||
#include "torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include "proplistdelegate.h"
|
||||
#include "torrentfilesmodel.h"
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "peerlistwidget.h"
|
||||
#include "trackerlist.h"
|
||||
#include "mainwindow.h"
|
||||
@ -73,7 +74,7 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow* main_window, Tra
|
||||
setEnabled(false);
|
||||
|
||||
// Set Properties list model
|
||||
PropListModel = new TorrentFilesFilterModel();
|
||||
PropListModel = new TorrentContentFilterModel();
|
||||
filesList->setModel(PropListModel);
|
||||
PropDelegate = new PropListDelegate(this);
|
||||
filesList->setItemDelegate(PropDelegate);
|
||||
@ -414,7 +415,7 @@ void PropertiesWidget::loadUrlSeeds() {
|
||||
void PropertiesWidget::openDoubleClickedFile(QModelIndex index) {
|
||||
if (!index.isValid()) return;
|
||||
if (!h.is_valid() || !h.has_metadata()) return;
|
||||
if (PropListModel->getType(index) == TorrentFileItem::TFILE) {
|
||||
if (PropListModel->getType(index) == TorrentContentModelItem::TFILE) {
|
||||
int i = PropListModel->getFileIndex(index);
|
||||
const QDir saveDir(h.save_path());
|
||||
const QString filename = h.filepath_at(i);
|
||||
@ -516,7 +517,7 @@ void PropertiesWidget::renameSelectedFile() {
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (PropListModel->getType(index) == TorrentFileItem::TFILE) {
|
||||
if (PropListModel->getType(index) == TorrentContentModelItem::TFILE) {
|
||||
// File renaming
|
||||
const int file_index = PropListModel->getFileIndex(index);
|
||||
if (!h.is_valid() || !h.has_metadata()) return;
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
|
||||
class TransferListWidget;
|
||||
class TorrentFilesFilterModel;
|
||||
class TorrentContentFilterModel;
|
||||
class PropListDelegate;
|
||||
class torrent_file;
|
||||
class PeerListWidget;
|
||||
@ -101,7 +101,7 @@ private:
|
||||
QTorrentHandle h;
|
||||
QTimer *refreshTimer;
|
||||
SlideState state;
|
||||
TorrentFilesFilterModel *PropListModel;
|
||||
TorrentContentFilterModel *PropListModel;
|
||||
PropListDelegate *PropDelegate;
|
||||
PeerListWidget *peersList;
|
||||
TrackerList *trackerList;
|
||||
|
@ -119,7 +119,9 @@ nox {
|
||||
transferlistwidget.h \
|
||||
transferlistdelegate.h \
|
||||
transferlistfilterswidget.h \
|
||||
torrentfilesmodel.h \
|
||||
torrentcontentmodel.h \
|
||||
torrentcontentmodelitem.h \
|
||||
torrentcontentfiltermodel.h \
|
||||
deletionconfirmationdlg.h \
|
||||
statusbar.h \
|
||||
reverseresolution.h \
|
||||
@ -142,6 +144,9 @@ nox {
|
||||
SOURCES += mainwindow.cpp \
|
||||
ico.cpp \
|
||||
transferlistwidget.cpp \
|
||||
torrentcontentmodel.cpp \
|
||||
torrentcontentmodelitem.cpp \
|
||||
torrentcontentfiltermodel.cpp \
|
||||
torrentadditiondlg.cpp \
|
||||
sessionapplication.cpp \
|
||||
torrentimportdlg.cpp \
|
||||
|
@ -45,7 +45,8 @@
|
||||
#include <libtorrent/bencode.hpp>
|
||||
|
||||
#include "qbtsession.h"
|
||||
#include "torrentfilesmodel.h"
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "preferences.h"
|
||||
#include "transferlistwidget.h"
|
||||
#include "qinisettings.h"
|
||||
@ -67,7 +68,7 @@ torrentAdditionDialog::torrentAdditionDialog(QWidget *parent) :
|
||||
CancelButton->setIcon(IconProvider::instance()->getIcon("dialog-cancel"));
|
||||
OkButton->setIcon(IconProvider::instance()->getIcon("list-add"));
|
||||
// Set Properties list model
|
||||
PropListModel = new TorrentFilesFilterModel(this);
|
||||
PropListModel = new TorrentContentFilterModel(this);
|
||||
connect(PropListModel, SIGNAL(filteredFilesChanged()), SLOT(updateDiskSpaceLabels()));
|
||||
torrentContentList->setModel(PropListModel);
|
||||
torrentContentList->hideColumn(PROGRESS);
|
||||
@ -407,7 +408,7 @@ void torrentAdditionDialog::renameSelectedFile() {
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (PropListModel->getType(index) == TorrentFileItem::TFILE) {
|
||||
if (PropListModel->getType(index) == TorrentContentModelItem::TFILE) {
|
||||
// File renaming
|
||||
const uint file_index = PropListModel->getFileIndex(index);
|
||||
QString old_name = files_path.at(file_index);
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
class TorrentFilesFilterModel;
|
||||
class TorrentContentFilterModel;
|
||||
class PropListDelegate;
|
||||
|
||||
class torrentAdditionDialog : public QDialog, private Ui_addTorrentDialog{
|
||||
@ -83,7 +83,7 @@ private:
|
||||
QString defaultSavePath;
|
||||
QString old_label;
|
||||
bool appendLabelToSavePath;
|
||||
TorrentFilesFilterModel *PropListModel;
|
||||
TorrentContentFilterModel *PropListModel;
|
||||
PropListDelegate *PropDelegate;
|
||||
unsigned int nbFiles;
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> t;
|
||||
|
98
src/torrentcontentfiltermodel.cpp
Normal file
98
src/torrentcontentfiltermodel.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006-2012 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "torrentcontentfiltermodel.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
|
||||
TorrentContentFilterModel::TorrentContentFilterModel(QObject *parent):
|
||||
QSortFilterProxyModel(parent), m_model(new TorrentContentModel(this))
|
||||
{
|
||||
connect(m_model, SIGNAL(filteredFilesChanged()), this, SIGNAL(filteredFilesChanged()));
|
||||
setSourceModel(m_model);
|
||||
// Filter settings
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setFilterKeyColumn(TorrentContentModelItem::COL_NAME);
|
||||
setFilterRole(Qt::DisplayRole);
|
||||
setDynamicSortFilter(true);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
TorrentContentFilterModel::~TorrentContentFilterModel()
|
||||
{
|
||||
delete m_model;
|
||||
}
|
||||
|
||||
TorrentContentModel* TorrentContentFilterModel::model() const
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
TorrentContentModelItem::FileType TorrentContentFilterModel::getType(const QModelIndex& index) const
|
||||
{
|
||||
return m_model->getType(mapToSource(index));
|
||||
}
|
||||
|
||||
int TorrentContentFilterModel::getFileIndex(const QModelIndex& index) const
|
||||
{
|
||||
return m_model->getFileIndex(mapToSource(index));
|
||||
}
|
||||
|
||||
QModelIndex TorrentContentFilterModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
if (!child.isValid()) return QModelIndex();
|
||||
QModelIndex sourceParent = m_model->parent(mapToSource(child));
|
||||
if (!sourceParent.isValid()) return QModelIndex();
|
||||
return mapFromSource(sourceParent);
|
||||
}
|
||||
|
||||
bool TorrentContentFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
|
||||
{
|
||||
if (m_model->getType(m_model->index(source_row, 0, source_parent)) == TorrentContentModelItem::FOLDER) {
|
||||
// always accept folders, since we want to filter their children
|
||||
return true;
|
||||
}
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
void TorrentContentFilterModel::selectAll()
|
||||
{
|
||||
for (int i=0; i<rowCount(); ++i) {
|
||||
setData(index(i, 0), Qt::Checked, Qt::CheckStateRole);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void TorrentContentFilterModel::selectNone()
|
||||
{
|
||||
for (int i=0; i<rowCount(); ++i) {
|
||||
setData(index(i, 0), Qt::Unchecked, Qt::CheckStateRole);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
65
src/torrentcontentfiltermodel.h
Normal file
65
src/torrentcontentfiltermodel.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006-2012 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef TORRENTCONTENTFILTERMODEL_H
|
||||
#define TORRENTCONTENTFILTERMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include "torrentcontentmodelitem.h"
|
||||
|
||||
class TorrentContentModel;
|
||||
|
||||
class TorrentContentFilterModel: public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TorrentContentFilterModel(QObject *parent = 0);
|
||||
virtual ~TorrentContentFilterModel();
|
||||
|
||||
TorrentContentModel* model() const;
|
||||
TorrentContentModelItem::FileType getType(const QModelIndex& index) const;
|
||||
int getFileIndex(const QModelIndex& index) const;
|
||||
virtual QModelIndex parent(const QModelIndex& child) const;
|
||||
|
||||
signals:
|
||||
void filteredFilesChanged();
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
|
||||
|
||||
public slots:
|
||||
void selectAll();
|
||||
void selectNone();
|
||||
|
||||
private:
|
||||
TorrentContentModel *m_model;
|
||||
};
|
||||
|
||||
#endif // TORRENTCONTENTFILTERMODEL_H
|
325
src/torrentcontentmodel.cpp
Normal file
325
src/torrentcontentmodel.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006-2012 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "iconprovider.h"
|
||||
#include "misc.h"
|
||||
#include "torrentcontentmodel.h"
|
||||
#include "torrentcontentmodelitem.h"
|
||||
#include <QDir>
|
||||
|
||||
TorrentContentModel::TorrentContentModel(QObject *parent):
|
||||
QAbstractItemModel(parent), files_index(0)
|
||||
{
|
||||
QList<QVariant> rootData;
|
||||
rootData << tr("Name") << tr("Size") << tr("Progress") << tr("Priority");
|
||||
rootItem = new TorrentContentModelItem(rootData);
|
||||
}
|
||||
|
||||
TorrentContentModel::~TorrentContentModel()
|
||||
{
|
||||
if (files_index)
|
||||
delete [] files_index;
|
||||
delete rootItem;
|
||||
}
|
||||
|
||||
void TorrentContentModel::updateFilesProgress(const std::vector<libtorrent::size_type>& fp)
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
for (unsigned int i=0; i<fp.size(); ++i) {
|
||||
Q_ASSERT(fp[i] >= 0);
|
||||
files_index[i]->setProgress(fp[i]);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void TorrentContentModel::updateFilesPriorities(const std::vector<int> &fprio)
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
for (unsigned int i=0; i<fprio.size(); ++i) {
|
||||
//qDebug("Called updateFilesPriorities with %d", fprio[i]);
|
||||
files_index[i]->setPriority(fprio[i]);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
std::vector<int> TorrentContentModel::getFilesPriorities(unsigned int nbFiles) const
|
||||
{
|
||||
std::vector<int> prio;
|
||||
for (unsigned int i=0; i<nbFiles; ++i) {
|
||||
//qDebug("Called getFilesPriorities: %d", files_index[i]->getPriority());
|
||||
prio.push_back(files_index[i]->getPriority());
|
||||
}
|
||||
return prio;
|
||||
}
|
||||
|
||||
bool TorrentContentModel::allFiltered() const
|
||||
{
|
||||
for (int i=0; i<rootItem->childCount(); ++i) {
|
||||
if (rootItem->child(i)->getPriority() != prio::IGNORED)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int TorrentContentModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return static_cast<TorrentContentModelItem*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
|
||||
bool TorrentContentModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||
TorrentContentModelItem *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
||||
qDebug("setData(%s, %d", qPrintable(item->getName()), value.toInt());
|
||||
if (item->getPriority() != value.toInt()) {
|
||||
if (value.toInt() == Qt::PartiallyChecked)
|
||||
item->setPriority(prio::PARTIAL);
|
||||
else if (value.toInt() == Qt::Unchecked)
|
||||
item->setPriority(prio::IGNORED);
|
||||
else
|
||||
item->setPriority(prio::NORMAL);
|
||||
emit dataChanged(this->index(0,0), this->index(rowCount(), columnCount()));
|
||||
emit filteredFilesChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (role == Qt::EditRole) {
|
||||
TorrentContentModelItem *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
||||
switch(index.column()) {
|
||||
case TorrentContentModelItem::COL_NAME:
|
||||
item->setName(value.toString());
|
||||
break;
|
||||
case TorrentContentModelItem::COL_SIZE:
|
||||
item->setSize(value.toULongLong());
|
||||
break;
|
||||
case TorrentContentModelItem::COL_PROGRESS:
|
||||
item->setProgress(value.toDouble());
|
||||
break;
|
||||
case TorrentContentModelItem::COL_PRIO:
|
||||
item->setPriority(value.toInt());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TorrentContentModelItem::FileType TorrentContentModel::getType(const QModelIndex& index) const
|
||||
{
|
||||
const TorrentContentModelItem *item = static_cast<const TorrentContentModelItem*>(index.internalPointer());
|
||||
return item->getType();
|
||||
}
|
||||
|
||||
int TorrentContentModel::getFileIndex(const QModelIndex& index)
|
||||
{
|
||||
TorrentContentModelItem *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
||||
return item->getFileIndex();
|
||||
}
|
||||
|
||||
QVariant TorrentContentModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
TorrentContentModelItem *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
||||
if (index.column() == 0 && role == Qt::DecorationRole) {
|
||||
if (item->isFolder())
|
||||
return IconProvider::instance()->getIcon("inode-directory");
|
||||
else
|
||||
return IconProvider::instance()->getIcon("text-plain");
|
||||
}
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == prio::IGNORED)
|
||||
return Qt::Unchecked;
|
||||
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == prio::PARTIAL)
|
||||
return Qt::PartiallyChecked;
|
||||
return Qt::Checked;
|
||||
}
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
Qt::ItemFlags TorrentContentModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
if (getType(index) == TorrentContentModelItem::FOLDER)
|
||||
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
|
||||
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
||||
QVariant TorrentContentModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex TorrentContentModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid() && parent.column() != 0)
|
||||
return QModelIndex();
|
||||
|
||||
if (column >= TorrentContentModelItem::NB_COL)
|
||||
return QModelIndex();
|
||||
|
||||
TorrentContentModelItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TorrentContentModelItem*>(parent.internalPointer());
|
||||
Q_ASSERT(parentItem);
|
||||
if (row >= parentItem->childCount())
|
||||
return QModelIndex();
|
||||
|
||||
TorrentContentModelItem *childItem = parentItem->child(row);
|
||||
if (childItem) {
|
||||
return createIndex(row, column, childItem);
|
||||
} else {
|
||||
return QModelIndex();
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex TorrentContentModel::parent(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TorrentContentModelItem *childItem = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
||||
if (!childItem) return QModelIndex();
|
||||
TorrentContentModelItem *parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == rootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
int TorrentContentModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
TorrentContentModelItem *parentItem;
|
||||
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TorrentContentModelItem*>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
void TorrentContentModel::clear()
|
||||
{
|
||||
qDebug("clear called");
|
||||
beginResetModel();
|
||||
if (files_index) {
|
||||
delete [] files_index;
|
||||
files_index = 0;
|
||||
}
|
||||
rootItem->deleteAllChildren();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void TorrentContentModel::setupModelData(const libtorrent::torrent_info &t)
|
||||
{
|
||||
qDebug("setup model data called");
|
||||
if (t.num_files() == 0)
|
||||
return;
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
// Initialize files_index array
|
||||
qDebug("Torrent contains %d files", t.num_files());
|
||||
files_index = new TorrentContentModelItem*[t.num_files()];
|
||||
|
||||
TorrentContentModelItem *parent = this->rootItem;
|
||||
TorrentContentModelItem *root_folder = parent;
|
||||
TorrentContentModelItem *current_parent;
|
||||
|
||||
// Iterate over files
|
||||
for (int i=0; i<t.num_files(); ++i) {
|
||||
libtorrent::file_entry fentry = t.file_at(i);
|
||||
current_parent = root_folder;
|
||||
#if LIBTORRENT_VERSION_MINOR >= 16
|
||||
QString path = QDir::cleanPath(misc::toQStringU(fentry.path)).replace("\\", "/");
|
||||
#else
|
||||
QString path = QDir::cleanPath(misc::toQStringU(fentry.path.string())).replace("\\", "/");
|
||||
#endif
|
||||
// Iterate of parts of the path to create necessary folders
|
||||
QStringList pathFolders = path.split("/");
|
||||
pathFolders.removeAll(".unwanted");
|
||||
pathFolders.takeLast();
|
||||
foreach (const QString &pathPart, pathFolders) {
|
||||
TorrentContentModelItem *new_parent = current_parent->childWithName(pathPart);
|
||||
if (!new_parent) {
|
||||
new_parent = new TorrentContentModelItem(pathPart, current_parent);
|
||||
}
|
||||
current_parent = new_parent;
|
||||
}
|
||||
// Actually create the file
|
||||
TorrentContentModelItem *f = new TorrentContentModelItem(t, fentry, current_parent, i);
|
||||
files_index[i] = f;
|
||||
}
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
void TorrentContentModel::selectAll()
|
||||
{
|
||||
for (int i=0; i<rootItem->childCount(); ++i) {
|
||||
TorrentContentModelItem *child = rootItem->child(i);
|
||||
if (child->getPriority() == prio::IGNORED)
|
||||
child->setPriority(prio::NORMAL);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void TorrentContentModel::selectNone()
|
||||
{
|
||||
for (int i=0; i<rootItem->childCount(); ++i) {
|
||||
rootItem->child(i)->setPriority(prio::IGNORED);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
76
src/torrentcontentmodel.h
Normal file
76
src/torrentcontentmodel.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006-2012 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef TORRENTCONTENTMODEL_H
|
||||
#define TORRENTCONTENTMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include "torrentcontentmodelitem.h"
|
||||
|
||||
class TorrentContentModel: public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
TorrentContentModelItem *rootItem;
|
||||
TorrentContentModelItem **files_index;
|
||||
|
||||
public:
|
||||
TorrentContentModel(QObject *parent = 0);
|
||||
~TorrentContentModel();
|
||||
|
||||
void updateFilesProgress(const std::vector<libtorrent::size_type>& fp);
|
||||
void updateFilesPriorities(const std::vector<int> &fprio);
|
||||
std::vector<int> getFilesPriorities(unsigned int nbFiles) const;
|
||||
bool allFiltered() const;
|
||||
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
|
||||
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
||||
TorrentContentModelItem::FileType getType(const QModelIndex& index) const;
|
||||
int getFileIndex(const QModelIndex& index);
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
||||
virtual QModelIndex parent(const QModelIndex& index) const;
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
void clear();
|
||||
void setupModelData(const libtorrent::torrent_info& t);
|
||||
|
||||
signals:
|
||||
void filteredFilesChanged();
|
||||
|
||||
public slots:
|
||||
void selectAll();
|
||||
void selectNone();
|
||||
};
|
||||
|
||||
#endif // TORRENTCONTENTMODEL_H
|
320
src/torrentcontentmodelitem.cpp
Normal file
320
src/torrentcontentmodelitem.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006-2012 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "torrentcontentmodelitem.h"
|
||||
#include <QDebug>
|
||||
|
||||
TorrentContentModelItem::TorrentContentModelItem(const libtorrent::torrent_info &t,
|
||||
const libtorrent::file_entry &f,
|
||||
TorrentContentModelItem *parent,
|
||||
int file_index):
|
||||
m_parentItem(parent), m_type(TFILE), m_fileIndex(file_index), m_totalDone(0)
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
|
||||
#if LIBTORRENT_VERSION_MINOR >= 16
|
||||
QString name = misc::fileName(misc::toQStringU(t.files().file_path(f)));
|
||||
#else
|
||||
Q_UNUSED(t);
|
||||
QString name = misc::toQStringU(f.path.filename());
|
||||
#endif
|
||||
// Do not display incomplete extensions
|
||||
if (name.endsWith(".!qB"))
|
||||
name.chop(4);
|
||||
|
||||
m_itemData << name
|
||||
<< QVariant((qulonglong)f.size)
|
||||
<< 0.
|
||||
<< prio::NORMAL;
|
||||
|
||||
/* Update parent */
|
||||
m_parentItem->appendChild(this);
|
||||
m_parentItem->updateSize();
|
||||
}
|
||||
|
||||
TorrentContentModelItem::TorrentContentModelItem(QString name, TorrentContentModelItem *parent):
|
||||
m_parentItem(parent), m_type(FOLDER), m_totalDone(0)
|
||||
{
|
||||
// Do not display incomplete extensions
|
||||
if (name.endsWith(".!qB"))
|
||||
name.chop(4);
|
||||
m_itemData << name
|
||||
<< 0.
|
||||
<< 0.
|
||||
<< prio::NORMAL;
|
||||
|
||||
/* Update parent */
|
||||
m_parentItem->appendChild(this);
|
||||
}
|
||||
|
||||
TorrentContentModelItem::TorrentContentModelItem(const QList<QVariant>& data):
|
||||
m_parentItem(0), m_type(ROOT), m_itemData(data), m_totalDone(0)
|
||||
{
|
||||
Q_ASSERT(data.size() == 4);
|
||||
}
|
||||
|
||||
TorrentContentModelItem::~TorrentContentModelItem()
|
||||
{
|
||||
qDeleteAll(m_childItems);
|
||||
}
|
||||
|
||||
TorrentContentModelItem::FileType TorrentContentModelItem::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
int TorrentContentModelItem::getFileIndex() const
|
||||
{
|
||||
Q_ASSERT(m_type == TFILE);
|
||||
return m_fileIndex;
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::deleteAllChildren()
|
||||
{
|
||||
Q_ASSERT(m_type == ROOT);
|
||||
qDeleteAll(m_childItems);
|
||||
m_childItems.clear();
|
||||
}
|
||||
|
||||
const QList<TorrentContentModelItem*>& TorrentContentModelItem::children() const
|
||||
{
|
||||
return m_childItems;
|
||||
}
|
||||
|
||||
QString TorrentContentModelItem::getName() const
|
||||
{
|
||||
return m_itemData.at(COL_NAME).toString();
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::setName(const QString& name)
|
||||
{
|
||||
Q_ASSERT(m_type != ROOT);
|
||||
m_itemData.replace(COL_NAME, name);
|
||||
}
|
||||
|
||||
qulonglong TorrentContentModelItem::getSize() const
|
||||
{
|
||||
return m_itemData.value(COL_SIZE).toULongLong();
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::setSize(qulonglong size)
|
||||
{
|
||||
Q_ASSERT (m_type != ROOT);
|
||||
if (getSize() == size)
|
||||
return;
|
||||
m_itemData.replace(COL_SIZE, (qulonglong)size);
|
||||
m_parentItem->updateSize();
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::updateSize()
|
||||
{
|
||||
if (m_type == ROOT)
|
||||
return;
|
||||
Q_ASSERT(m_type == FOLDER);
|
||||
qulonglong size = 0;
|
||||
foreach (TorrentContentModelItem* child, m_childItems) {
|
||||
if (child->getPriority() != prio::IGNORED)
|
||||
size += child->getSize();
|
||||
}
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::setProgress(qulonglong done)
|
||||
{
|
||||
Q_ASSERT (m_type != ROOT);
|
||||
if (getPriority() == 0) return;
|
||||
m_totalDone = done;
|
||||
qulonglong size = getSize();
|
||||
Q_ASSERT(m_totalDone <= size);
|
||||
qreal progress;
|
||||
if (size > 0)
|
||||
progress = m_totalDone/(float)size;
|
||||
else
|
||||
progress = 1.;
|
||||
Q_ASSERT(progress >= 0. && progress <= 1.);
|
||||
m_itemData.replace(COL_PROGRESS, progress);
|
||||
m_parentItem->updateProgress();
|
||||
}
|
||||
|
||||
qulonglong TorrentContentModelItem::getTotalDone() const
|
||||
{
|
||||
return m_totalDone;
|
||||
}
|
||||
|
||||
float TorrentContentModelItem::getProgress() const
|
||||
{
|
||||
Q_ASSERT (m_type != ROOT);
|
||||
if (getPriority() == 0)
|
||||
return -1;
|
||||
qulonglong size = getSize();
|
||||
if (size > 0)
|
||||
return m_totalDone / (float) getSize();
|
||||
return 1.;
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::updateProgress()
|
||||
{
|
||||
if (m_type == ROOT) return;
|
||||
Q_ASSERT(m_type == FOLDER);
|
||||
m_totalDone = 0;
|
||||
foreach (TorrentContentModelItem* child, m_childItems) {
|
||||
if (child->getPriority() > 0)
|
||||
m_totalDone += child->getTotalDone();
|
||||
}
|
||||
//qDebug("Folder: total_done: %llu/%llu", total_done, getSize());
|
||||
Q_ASSERT(m_totalDone <= getSize());
|
||||
setProgress(m_totalDone);
|
||||
}
|
||||
|
||||
int TorrentContentModelItem::getPriority() const
|
||||
{
|
||||
return m_itemData.value(COL_PRIO).toInt();
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::setPriority(int new_prio, bool update_parent)
|
||||
{
|
||||
Q_ASSERT(new_prio != prio::PARTIAL || m_type == FOLDER); // PARTIAL only applies to folders
|
||||
const int old_prio = getPriority();
|
||||
if (old_prio == new_prio) return;
|
||||
qDebug("setPriority(%s, %d)", qPrintable(getName()), new_prio);
|
||||
// Reset progress if priority is 0
|
||||
if (new_prio == 0) {
|
||||
setProgress(0);
|
||||
}
|
||||
|
||||
m_itemData.replace(COL_PRIO, new_prio);
|
||||
|
||||
// Update parent
|
||||
if (update_parent && m_parentItem) {
|
||||
qDebug("Updating parent item");
|
||||
m_parentItem->updateSize();
|
||||
m_parentItem->updateProgress();
|
||||
m_parentItem->updatePriority();
|
||||
}
|
||||
|
||||
// Update children
|
||||
if (new_prio != prio::PARTIAL && !m_childItems.empty()) {
|
||||
qDebug("Updating children items");
|
||||
foreach (TorrentContentModelItem* child, m_childItems) {
|
||||
// Do not update the parent since
|
||||
// the parent is causing the update
|
||||
child->setPriority(new_prio, false);
|
||||
}
|
||||
}
|
||||
if (m_type == FOLDER) {
|
||||
updateSize();
|
||||
updateProgress();
|
||||
}
|
||||
}
|
||||
|
||||
// Only non-root folders use this function
|
||||
void TorrentContentModelItem::updatePriority()
|
||||
{
|
||||
if (m_type == ROOT) return;
|
||||
Q_ASSERT(m_type == FOLDER);
|
||||
if (m_childItems.isEmpty()) return;
|
||||
// If all children have the same priority
|
||||
// then the folder should have the same
|
||||
// priority
|
||||
const int prio = m_childItems.first()->getPriority();
|
||||
for (int i=1; i<m_childItems.size(); ++i) {
|
||||
if (m_childItems.at(i)->getPriority() != prio) {
|
||||
setPriority(prio::PARTIAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// All child items have the same priorrity
|
||||
// Update mine if necessary
|
||||
if (prio != getPriority())
|
||||
setPriority(prio);
|
||||
}
|
||||
|
||||
TorrentContentModelItem* TorrentContentModelItem::childWithName(const QString& name) const
|
||||
{
|
||||
foreach (TorrentContentModelItem *child, m_childItems) {
|
||||
if (child->getName() == name)
|
||||
return child;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TorrentContentModelItem::isFolder() const
|
||||
{
|
||||
return (m_type==FOLDER);
|
||||
}
|
||||
|
||||
void TorrentContentModelItem::appendChild(TorrentContentModelItem *item)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
Q_ASSERT(m_type != TFILE);
|
||||
int i=0;
|
||||
for (i=0; i<m_childItems.size(); ++i) {
|
||||
QString newchild_name = item->getName();
|
||||
if (QString::localeAwareCompare(newchild_name, m_childItems.at(i)->getName()) < 0)
|
||||
break;
|
||||
}
|
||||
m_childItems.insert(i, item);
|
||||
}
|
||||
|
||||
TorrentContentModelItem* TorrentContentModelItem::child(int row)
|
||||
{
|
||||
//Q_ASSERT(row >= 0 && row < childItems.size());
|
||||
return m_childItems.value(row, 0);
|
||||
}
|
||||
|
||||
int TorrentContentModelItem::childCount() const
|
||||
{
|
||||
return m_childItems.count();
|
||||
}
|
||||
|
||||
int TorrentContentModelItem::columnCount() const
|
||||
{
|
||||
return m_itemData.count();
|
||||
}
|
||||
|
||||
QVariant TorrentContentModelItem::data(int column) const
|
||||
{
|
||||
if (column == COL_PROGRESS && m_type != ROOT)
|
||||
return getProgress();
|
||||
return m_itemData.value(column);
|
||||
}
|
||||
|
||||
int TorrentContentModelItem::row() const
|
||||
{
|
||||
if (m_parentItem)
|
||||
return m_parentItem->children().indexOf(const_cast<TorrentContentModelItem*>(this));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TorrentContentModelItem* TorrentContentModelItem::parent()
|
||||
{
|
||||
return m_parentItem;
|
||||
}
|
102
src/torrentcontentmodelitem.h
Normal file
102
src/torrentcontentmodelitem.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006-2012 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef TORRENTCONTENTMODELITEM_H
|
||||
#define TORRENTCONTENTMODELITEM_H
|
||||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
namespace prio {
|
||||
enum FilePriority {IGNORED=0, NORMAL=1, HIGH=2, MAXIMUM=7, PARTIAL=-1};
|
||||
}
|
||||
|
||||
class TorrentContentModelItem {
|
||||
public:
|
||||
enum TreeItemColumns {COL_NAME, COL_SIZE, COL_PROGRESS, COL_PRIO, NB_COL};
|
||||
enum FileType {TFILE, FOLDER, ROOT};
|
||||
|
||||
// File Construction
|
||||
TorrentContentModelItem(const libtorrent::torrent_info &t,
|
||||
const libtorrent::file_entry &f,
|
||||
TorrentContentModelItem *parent,
|
||||
int file_index);
|
||||
// Folder constructor
|
||||
TorrentContentModelItem(QString name, TorrentContentModelItem *parent = 0);
|
||||
// Invisible root item constructor
|
||||
TorrentContentModelItem(const QList<QVariant>& data);
|
||||
|
||||
~TorrentContentModelItem();
|
||||
|
||||
FileType getType() const;
|
||||
|
||||
int getFileIndex() const;
|
||||
|
||||
QString getName() const;
|
||||
void setName(const QString& name);
|
||||
|
||||
qulonglong getSize() const;
|
||||
void setSize(qulonglong size);
|
||||
void updateSize();
|
||||
qulonglong getTotalDone() const;
|
||||
|
||||
void setProgress(qulonglong done);
|
||||
float getProgress() const;
|
||||
void updateProgress();
|
||||
|
||||
int getPriority() const;
|
||||
void setPriority(int new_prio, bool update_parent=true);
|
||||
void updatePriority();
|
||||
|
||||
TorrentContentModelItem* childWithName(const QString& name) const;
|
||||
bool isFolder() const;
|
||||
|
||||
void appendChild(TorrentContentModelItem *item);
|
||||
TorrentContentModelItem *child(int row);
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QVariant data(int column) const;
|
||||
int row() const;
|
||||
|
||||
TorrentContentModelItem *parent();
|
||||
void deleteAllChildren();
|
||||
const QList<TorrentContentModelItem*>& children() const;
|
||||
|
||||
private:
|
||||
TorrentContentModelItem *m_parentItem;
|
||||
FileType m_type;
|
||||
QList<TorrentContentModelItem*> m_childItems;
|
||||
QList<QVariant> m_itemData;
|
||||
int m_fileIndex;
|
||||
qulonglong m_totalDone;
|
||||
};
|
||||
|
||||
#endif // TORRENTCONTENTMODELITEM_H
|
@ -1,684 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef TORRENTFILESMODEL_H
|
||||
#define TORRENTFILESMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include "proplistdelegate.h"
|
||||
#include "iconprovider.h"
|
||||
|
||||
namespace prio {
|
||||
enum FilePriority {IGNORED=0, NORMAL=1, HIGH=2, MAXIMUM=7, PARTIAL=-1};
|
||||
}
|
||||
|
||||
class TorrentFileItem {
|
||||
|
||||
public:
|
||||
enum TreeItemColumns {COL_NAME, COL_SIZE, COL_PROGRESS, COL_PRIO, NB_COL};
|
||||
enum FileType {TFILE, FOLDER, ROOT};
|
||||
|
||||
private:
|
||||
QList<TorrentFileItem*> childItems;
|
||||
QList<QVariant> itemData;
|
||||
TorrentFileItem *parentItem;
|
||||
FileType m_type;
|
||||
qulonglong total_done;
|
||||
int file_index;
|
||||
|
||||
public:
|
||||
// File Construction
|
||||
TorrentFileItem(const libtorrent::torrent_info &t, const libtorrent::file_entry &f, TorrentFileItem *parent, int _file_index) {
|
||||
Q_ASSERT(parent);
|
||||
parentItem = parent;
|
||||
m_type = TFILE;
|
||||
file_index = _file_index;
|
||||
#if LIBTORRENT_VERSION_MINOR >= 16
|
||||
QString name = misc::fileName(misc::toQStringU(t.files().file_path(f)));
|
||||
#else
|
||||
Q_UNUSED(t);
|
||||
QString name = misc::toQStringU(f.path.filename());
|
||||
#endif
|
||||
// Do not display incomplete extensions
|
||||
if (name.endsWith(".!qB"))
|
||||
name.chop(4);
|
||||
itemData << name;
|
||||
//qDebug("Created a TreeItem file with name %s", qPrintable(getName()));
|
||||
//qDebug("parent is %s", qPrintable(parent->getName()));
|
||||
itemData << QVariant((qulonglong)f.size);
|
||||
total_done = 0;
|
||||
itemData << 0.; // Progress;
|
||||
itemData << prio::NORMAL; // Priority
|
||||
if (parent) {
|
||||
parent->appendChild(this);
|
||||
parent->updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
// Folder constructor
|
||||
TorrentFileItem(QString name, TorrentFileItem *parent=0) {
|
||||
parentItem = parent;
|
||||
m_type = FOLDER;
|
||||
// Do not display incomplete extensions
|
||||
if (name.endsWith(".!qB"))
|
||||
name.chop(4);
|
||||
itemData << name;
|
||||
itemData << 0.; // Size
|
||||
itemData << 0.; // Progress;
|
||||
total_done = 0;
|
||||
itemData << prio::NORMAL; // Priority
|
||||
if (parent) {
|
||||
parent->appendChild(this);
|
||||
}
|
||||
}
|
||||
|
||||
TorrentFileItem(const QList<QVariant>& data) {
|
||||
parentItem = 0;
|
||||
m_type = ROOT;
|
||||
Q_ASSERT(data.size() == 4);
|
||||
itemData = data;
|
||||
total_done = 0;
|
||||
}
|
||||
|
||||
~TorrentFileItem() {
|
||||
qDebug("Deleting item: %s", qPrintable(getName()));
|
||||
qDeleteAll(childItems);
|
||||
}
|
||||
|
||||
FileType getType() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
int getFileIndex() const {
|
||||
Q_ASSERT(m_type ==TFILE);
|
||||
return file_index;
|
||||
}
|
||||
|
||||
void deleteAllChildren() {
|
||||
Q_ASSERT(m_type==ROOT);
|
||||
qDeleteAll(childItems);
|
||||
childItems.clear();
|
||||
Q_ASSERT(childItems.empty());
|
||||
}
|
||||
|
||||
QList<TorrentFileItem*> children() const {
|
||||
return childItems;
|
||||
}
|
||||
|
||||
QString getName() const {
|
||||
//Q_ASSERT(type != ROOT);
|
||||
return itemData.at(COL_NAME).toString();
|
||||
}
|
||||
|
||||
void setName(QString name) {
|
||||
Q_ASSERT(m_type != ROOT);
|
||||
itemData.replace(COL_NAME, name);
|
||||
}
|
||||
|
||||
qulonglong getSize() const {
|
||||
return itemData.value(COL_SIZE).toULongLong();
|
||||
}
|
||||
|
||||
void setSize(qulonglong size) {
|
||||
if (getSize() == size) return;
|
||||
itemData.replace(COL_SIZE, (qulonglong)size);
|
||||
if (parentItem)
|
||||
parentItem->updateSize();
|
||||
}
|
||||
|
||||
void updateSize() {
|
||||
if (m_type == ROOT) return;
|
||||
Q_ASSERT(m_type == FOLDER);
|
||||
qulonglong size = 0;
|
||||
foreach (TorrentFileItem* child, childItems) {
|
||||
if (child->getPriority() != prio::IGNORED)
|
||||
size += child->getSize();
|
||||
}
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
void setProgress(qulonglong done) {
|
||||
Q_ASSERT (m_type != ROOT);
|
||||
if (getPriority() == 0) return;
|
||||
total_done = done;
|
||||
qulonglong size = getSize();
|
||||
Q_ASSERT(total_done <= size);
|
||||
qreal progress;
|
||||
if (size > 0)
|
||||
progress = total_done/(float)size;
|
||||
else
|
||||
progress = 1.;
|
||||
Q_ASSERT(progress >= 0. && progress <= 1.);
|
||||
itemData.replace(COL_PROGRESS, progress);
|
||||
parentItem->updateProgress();
|
||||
}
|
||||
|
||||
qulonglong getTotalDone() const {
|
||||
return total_done;
|
||||
}
|
||||
|
||||
qreal getProgress() const {
|
||||
Q_ASSERT (m_type != ROOT);
|
||||
if (getPriority() == 0)
|
||||
return -1;
|
||||
qulonglong size = getSize();
|
||||
if (size > 0)
|
||||
return total_done/(float)getSize();
|
||||
return 1.;
|
||||
}
|
||||
|
||||
void updateProgress() {
|
||||
if (m_type == ROOT) return;
|
||||
Q_ASSERT(m_type == FOLDER);
|
||||
total_done = 0;
|
||||
foreach (TorrentFileItem* child, childItems) {
|
||||
if (child->getPriority() > 0)
|
||||
total_done += child->getTotalDone();
|
||||
}
|
||||
//qDebug("Folder: total_done: %llu/%llu", total_done, getSize());
|
||||
Q_ASSERT(total_done <= getSize());
|
||||
setProgress(total_done);
|
||||
}
|
||||
|
||||
int getPriority() const {
|
||||
return itemData.value(COL_PRIO).toInt();
|
||||
}
|
||||
|
||||
void setPriority(int new_prio, bool update_parent=true) {
|
||||
Q_ASSERT(new_prio != prio::PARTIAL || m_type == FOLDER); // PARTIAL only applies to folders
|
||||
const int old_prio = getPriority();
|
||||
if (old_prio == new_prio) return;
|
||||
qDebug("setPriority(%s, %d)", qPrintable(getName()), new_prio);
|
||||
// Reset progress if priority is 0
|
||||
if (new_prio == 0) {
|
||||
setProgress(0);
|
||||
}
|
||||
|
||||
itemData.replace(COL_PRIO, new_prio);
|
||||
|
||||
// Update parent
|
||||
if (update_parent && parentItem) {
|
||||
qDebug("Updating parent item");
|
||||
parentItem->updateSize();
|
||||
parentItem->updateProgress();
|
||||
parentItem->updatePriority();
|
||||
}
|
||||
|
||||
// Update children
|
||||
if (new_prio != prio::PARTIAL && !childItems.empty()) {
|
||||
qDebug("Updating children items");
|
||||
foreach (TorrentFileItem* child, childItems) {
|
||||
// Do not update the parent since
|
||||
// the parent is causing the update
|
||||
child->setPriority(new_prio, false);
|
||||
}
|
||||
}
|
||||
if (m_type == FOLDER) {
|
||||
updateSize();
|
||||
updateProgress();
|
||||
}
|
||||
}
|
||||
|
||||
// Only non-root folders use this function
|
||||
void updatePriority() {
|
||||
if (m_type == ROOT) return;
|
||||
Q_ASSERT(m_type == FOLDER);
|
||||
if (childItems.isEmpty()) return;
|
||||
// If all children have the same priority
|
||||
// then the folder should have the same
|
||||
// priority
|
||||
const int prio = childItems.first()->getPriority();
|
||||
for (int i=1; i<childItems.size(); ++i) {
|
||||
if (childItems.at(i)->getPriority() != prio) {
|
||||
setPriority(prio::PARTIAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// All child items have the same priorrity
|
||||
// Update mine if necessary
|
||||
if (prio != getPriority())
|
||||
setPriority(prio);
|
||||
}
|
||||
|
||||
TorrentFileItem* childWithName(QString name) const {
|
||||
foreach (TorrentFileItem *child, childItems) {
|
||||
if (child->getName() == name) return child;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isFolder() const {
|
||||
return (m_type==FOLDER);
|
||||
}
|
||||
|
||||
void appendChild(TorrentFileItem *item) {
|
||||
Q_ASSERT(item);
|
||||
//Q_ASSERT(!childWithName(item->getName()));
|
||||
Q_ASSERT(m_type != TFILE);
|
||||
int i=0;
|
||||
for (i=0; i<childItems.size(); ++i) {
|
||||
QString newchild_name = item->getName();
|
||||
if (QString::localeAwareCompare(newchild_name, childItems.at(i)->getName()) < 0) break;
|
||||
}
|
||||
childItems.insert(i, item);
|
||||
//childItems.append(item);
|
||||
//Q_ASSERT(type != ROOT || childItems.size() == 1);
|
||||
}
|
||||
|
||||
TorrentFileItem *child(int row) {
|
||||
//Q_ASSERT(row >= 0 && row < childItems.size());
|
||||
return childItems.value(row, 0);
|
||||
}
|
||||
|
||||
int childCount() const {
|
||||
return childItems.count();
|
||||
}
|
||||
|
||||
int columnCount() const {
|
||||
return itemData.count();
|
||||
}
|
||||
|
||||
QVariant data(int column) const {
|
||||
if (column == COL_PROGRESS && m_type != ROOT)
|
||||
return getProgress();
|
||||
return itemData.value(column);
|
||||
}
|
||||
|
||||
int row() const {
|
||||
if (parentItem) {
|
||||
return parentItem->children().indexOf(const_cast<TorrentFileItem*>(this));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TorrentFileItem *parent() {
|
||||
return parentItem;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TorrentFilesModel: public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
TorrentFileItem *rootItem;
|
||||
TorrentFileItem **files_index;
|
||||
|
||||
public:
|
||||
TorrentFilesModel(QObject *parent=0): QAbstractItemModel(parent) {
|
||||
files_index = 0;
|
||||
QList<QVariant> rootData;
|
||||
rootData << tr("Name") << tr("Size") << tr("Progress") << tr("Priority");
|
||||
rootItem = new TorrentFileItem(rootData);
|
||||
}
|
||||
|
||||
~TorrentFilesModel() {
|
||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||
delete [] files_index;
|
||||
delete rootItem;
|
||||
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||
}
|
||||
|
||||
void updateFilesProgress(std::vector<libtorrent::size_type> fp) {
|
||||
emit layoutAboutToBeChanged();
|
||||
for (unsigned int i=0; i<fp.size(); ++i) {
|
||||
Q_ASSERT(fp[i] >= 0);
|
||||
files_index[i]->setProgress(fp[i]);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void updateFilesPriorities(const std::vector<int> &fprio) {
|
||||
emit layoutAboutToBeChanged();
|
||||
for (unsigned int i=0; i<fprio.size(); ++i) {
|
||||
//qDebug("Called updateFilesPriorities with %d", fprio[i]);
|
||||
files_index[i]->setPriority(fprio[i]);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
std::vector<int> getFilesPriorities(unsigned int nbFiles) const {
|
||||
std::vector<int> prio;
|
||||
for (unsigned int i=0; i<nbFiles; ++i) {
|
||||
//qDebug("Called getFilesPriorities: %d", files_index[i]->getPriority());
|
||||
prio.push_back(files_index[i]->getPriority());
|
||||
}
|
||||
return prio;
|
||||
}
|
||||
|
||||
bool allFiltered() const {
|
||||
for (int i=0; i<rootItem->childCount(); ++i) {
|
||||
if (rootItem->child(i)->getPriority() != prio::IGNORED)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int columnCount(const QModelIndex &parent=QModelIndex()) const {
|
||||
if (parent.isValid())
|
||||
return static_cast<TorrentFileItem*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
|
||||
bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) {
|
||||
if (!index.isValid()) return false;
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||
TorrentFileItem *item = static_cast<TorrentFileItem*>(index.internalPointer());
|
||||
qDebug("setData(%s, %d", qPrintable(item->getName()), value.toInt());
|
||||
if (item->getPriority() != value.toInt()) {
|
||||
if (value.toInt() == Qt::PartiallyChecked)
|
||||
item->setPriority(prio::PARTIAL);
|
||||
else if (value.toInt() == Qt::Unchecked)
|
||||
item->setPriority(prio::IGNORED);
|
||||
else
|
||||
item->setPriority(prio::NORMAL);
|
||||
emit dataChanged(this->index(0,0), this->index(rowCount(), columnCount()));
|
||||
emit filteredFilesChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (role == Qt::EditRole) {
|
||||
TorrentFileItem *item = static_cast<TorrentFileItem*>(index.internalPointer());
|
||||
switch(index.column()) {
|
||||
case TorrentFileItem::COL_NAME:
|
||||
item->setName(value.toString());
|
||||
break;
|
||||
case TorrentFileItem::COL_SIZE:
|
||||
item->setSize(value.toULongLong());
|
||||
break;
|
||||
case TorrentFileItem::COL_PROGRESS:
|
||||
item->setProgress(value.toDouble());
|
||||
break;
|
||||
case TorrentFileItem::COL_PRIO:
|
||||
item->setPriority(value.toInt());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TorrentFileItem::FileType getType(const QModelIndex &index) const {
|
||||
const TorrentFileItem *item = static_cast<const TorrentFileItem*>(index.internalPointer());
|
||||
return item->getType();
|
||||
}
|
||||
|
||||
int getFileIndex(const QModelIndex &index) {
|
||||
TorrentFileItem *item = static_cast<TorrentFileItem*>(index.internalPointer());
|
||||
return item->getFileIndex();
|
||||
}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
TorrentFileItem *item = static_cast<TorrentFileItem*>(index.internalPointer());
|
||||
if (index.column() == 0 && role == Qt::DecorationRole) {
|
||||
if (item->isFolder())
|
||||
return IconProvider::instance()->getIcon("inode-directory");
|
||||
else
|
||||
return IconProvider::instance()->getIcon("text-plain");
|
||||
}
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole) {
|
||||
if (item->data(TorrentFileItem::COL_PRIO).toInt() == prio::IGNORED)
|
||||
return Qt::Unchecked;
|
||||
if (item->data(TorrentFileItem::COL_PRIO).toInt() == prio::PARTIAL)
|
||||
return Qt::PartiallyChecked;
|
||||
return Qt::Checked;
|
||||
}
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
if (getType(index) == TorrentFileItem::FOLDER)
|
||||
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
|
||||
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const {
|
||||
if (parent.isValid() && parent.column() != 0)
|
||||
return QModelIndex();
|
||||
if (column >= TorrentFileItem::NB_COL)
|
||||
return QModelIndex();
|
||||
|
||||
TorrentFileItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TorrentFileItem*>(parent.internalPointer());
|
||||
Q_ASSERT(parentItem);
|
||||
if (row >= parentItem->childCount())
|
||||
return QModelIndex();
|
||||
|
||||
TorrentFileItem *childItem = parentItem->child(row);
|
||||
if (childItem) {
|
||||
return createIndex(row, column, childItem);
|
||||
} else {
|
||||
return QModelIndex();
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex parent(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TorrentFileItem *childItem = static_cast<TorrentFileItem*>(index.internalPointer());
|
||||
if (!childItem) return QModelIndex();
|
||||
TorrentFileItem *parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == rootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent=QModelIndex()) const {
|
||||
TorrentFileItem *parentItem;
|
||||
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<TorrentFileItem*>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
qDebug("clear called");
|
||||
beginResetModel();
|
||||
if (files_index) {
|
||||
delete [] files_index;
|
||||
files_index = 0;
|
||||
}
|
||||
rootItem->deleteAllChildren();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void setupModelData(const libtorrent::torrent_info &t) {
|
||||
qDebug("setup model data called");
|
||||
if (t.num_files() == 0) return;
|
||||
emit layoutAboutToBeChanged();
|
||||
// Initialize files_index array
|
||||
qDebug("Torrent contains %d files", t.num_files());
|
||||
files_index = new TorrentFileItem*[t.num_files()];
|
||||
|
||||
TorrentFileItem *parent = this->rootItem;
|
||||
TorrentFileItem *root_folder = parent;
|
||||
TorrentFileItem *current_parent;
|
||||
|
||||
// Iterate over files
|
||||
for (int i=0; i<t.num_files(); ++i) {
|
||||
libtorrent::file_entry fentry = t.file_at(i);
|
||||
current_parent = root_folder;
|
||||
#if LIBTORRENT_VERSION_MINOR >= 16
|
||||
QString path = QDir::cleanPath(misc::toQStringU(fentry.path)).replace("\\", "/");
|
||||
#else
|
||||
QString path = QDir::cleanPath(misc::toQStringU(fentry.path.string())).replace("\\", "/");
|
||||
#endif
|
||||
// Iterate of parts of the path to create necessary folders
|
||||
QStringList pathFolders = path.split("/");
|
||||
pathFolders.removeAll(".unwanted");
|
||||
pathFolders.takeLast();
|
||||
foreach (const QString &pathPart, pathFolders) {
|
||||
TorrentFileItem *new_parent = current_parent->childWithName(pathPart);
|
||||
if (!new_parent) {
|
||||
new_parent = new TorrentFileItem(pathPart, current_parent);
|
||||
}
|
||||
current_parent = new_parent;
|
||||
}
|
||||
// Actually create the file
|
||||
TorrentFileItem *f = new TorrentFileItem(t, fentry, current_parent, i);
|
||||
files_index[i] = f;
|
||||
}
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void selectAll() {
|
||||
for (int i=0; i<rootItem->childCount(); ++i) {
|
||||
TorrentFileItem *child = rootItem->child(i);
|
||||
if (child->getPriority() == prio::IGNORED)
|
||||
child->setPriority(prio::NORMAL);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void selectNone() {
|
||||
for (int i=0; i<rootItem->childCount(); ++i) {
|
||||
rootItem->child(i)->setPriority(prio::IGNORED);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
signals:
|
||||
void filteredFilesChanged();
|
||||
};
|
||||
|
||||
class TorrentFilesFilterModel: public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TorrentFilesFilterModel(QObject *parent = 0): QSortFilterProxyModel(parent) {
|
||||
m_model = new TorrentFilesModel(this);
|
||||
connect(m_model, SIGNAL(filteredFilesChanged()), this, SIGNAL(filteredFilesChanged()));
|
||||
setSourceModel(m_model);
|
||||
// Filter settings
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setFilterKeyColumn(TorrentFileItem::COL_NAME);
|
||||
setFilterRole(Qt::DisplayRole);
|
||||
setDynamicSortFilter(true);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
~TorrentFilesFilterModel() {
|
||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||
delete m_model;
|
||||
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||
}
|
||||
|
||||
TorrentFilesModel* model() const {
|
||||
return m_model;
|
||||
}
|
||||
|
||||
TorrentFileItem::FileType getType(const QModelIndex &index) const {
|
||||
return m_model->getType(mapToSource(index));
|
||||
}
|
||||
|
||||
int getFileIndex(const QModelIndex &index) {
|
||||
return m_model->getFileIndex(mapToSource(index));
|
||||
}
|
||||
|
||||
QModelIndex parent(const QModelIndex & child) const {
|
||||
if (!child.isValid()) return QModelIndex();
|
||||
QModelIndex sourceParent = m_model->parent(mapToSource(child));
|
||||
if (!sourceParent.isValid()) return QModelIndex();
|
||||
return mapFromSource(sourceParent);
|
||||
}
|
||||
|
||||
signals:
|
||||
void filteredFilesChanged();
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
|
||||
if (m_model->getType(m_model->index(source_row, 0, source_parent)) == TorrentFileItem::FOLDER) {
|
||||
// always accept folders, since we want to filter their children
|
||||
return true;
|
||||
}
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void selectAll() {
|
||||
for (int i=0; i<rowCount(); ++i) {
|
||||
setData(index(i, 0), Qt::Checked, Qt::CheckStateRole);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
void selectNone() {
|
||||
for (int i=0; i<rowCount(); ++i) {
|
||||
setData(index(i, 0), Qt::Unchecked, Qt::CheckStateRole);
|
||||
}
|
||||
emit dataChanged(index(0,0), index(rowCount(), columnCount()));
|
||||
}
|
||||
|
||||
private:
|
||||
TorrentFilesModel *m_model;
|
||||
};
|
||||
|
||||
|
||||
#endif // TORRENTFILESMODEL_H
|
Loading…
x
Reference in New Issue
Block a user