Browse Source

Merge pull request #4994 from evsh/availability-column

Add availability column to torrent contents
adaptive-webui-19844
Eugene Shalygin 7 years ago committed by GitHub
parent
commit
92a7479e2d
  1. 21
      src/base/bittorrent/torrenthandle.cpp
  2. 8
      src/base/bittorrent/torrenthandle.h
  3. 1
      src/base/unicodestrings.h
  4. 1
      src/gui/addnewtorrentdialog.cpp
  5. 1
      src/gui/properties/propertieswidget.cpp
  6. 14
      src/gui/properties/proplistdelegate.cpp
  7. 4
      src/gui/properties/proplistdelegate.h
  8. 18
      src/gui/torrentcontentmodel.cpp
  9. 52
      src/gui/torrentcontentmodel.h
  10. 53
      src/gui/torrentcontentmodelfile.cpp
  11. 17
      src/gui/torrentcontentmodelfile.h
  12. 193
      src/gui/torrentcontentmodelfolder.cpp
  13. 37
      src/gui/torrentcontentmodelfolder.h
  14. 94
      src/gui/torrentcontentmodelitem.cpp
  15. 84
      src/gui/torrentcontentmodelitem.h

21
src/base/bittorrent/torrenthandle.cpp

@ -1953,3 +1953,24 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
updateStatus(); updateStatus();
} }
QVector<qreal> TorrentHandle::availableFileFractions() const
{
QVector<int> piecesAvailability = pieceAvailability();
const auto filesCount = this->filesCount();
// libtorrent returns empty array for seeding only torrents
if (piecesAvailability.empty()) return QVector<qreal>(filesCount, -1.);
QVector<qreal> res;
res.reserve(filesCount);
TorrentInfo info = this->info();
for (int file = 0; file < filesCount; ++file) {
TorrentInfo::PieceRange filePieces = info.filePieces(file);
int availablePieces = 0;
for (int piece = filePieces.first(); piece <= filePieces.last(); ++piece) {
availablePieces += piecesAvailability[piece] > 0 ? 1 : 0;
}
res.push_back(static_cast<qreal>(availablePieces) / filePieces.size());
}
return res;
}

8
src/base/bittorrent/torrenthandle.h

@ -361,6 +361,14 @@ namespace BitTorrent
void handleAppendExtensionToggled(); void handleAppendExtensionToggled();
void saveResumeData(bool updateStatus = false); void saveResumeData(bool updateStatus = false);
/**
* @brief fraction of file pieces that are available at least from one peer
*
* This is not the same as torrrent availability, it is just a fraction of pieces
* that can be downloaded right now. It varies between 0 to 1.
*/
QVector<qreal> availableFileFractions() const;
private: private:
typedef boost::function<void ()> EventTrigger; typedef boost::function<void ()> EventTrigger;

1
src/base/unicodestrings.h

@ -39,6 +39,7 @@ const char C_NON_BREAKING_SPACE[] = " ";
const char C_UP[] = ""; const char C_UP[] = "";
const char C_DOWN[] = ""; const char C_DOWN[] = "";
const char C_COPYRIGHT[] = "©"; const char C_COPYRIGHT[] = "©";
const char C_THIN_SPACE[] = "";
const char C_UTP[] = "μTP"; const char C_UTP[] = "μTP";
const char C_LOCALE_ENGLISH[] = "English"; const char C_LOCALE_ENGLISH[] = "English";
const char C_LOCALE_ENGLISH_AUSTRALIA[] = "English(Australia)"; const char C_LOCALE_ENGLISH_AUSTRALIA[] = "English(Australia)";

1
src/gui/addnewtorrentdialog.cpp

@ -737,6 +737,7 @@ void AddNewTorrentDialog::setupTreeview()
// Hide useless columns after loading the header state // Hide useless columns after loading the header state
ui->contentTreeView->hideColumn(PROGRESS); ui->contentTreeView->hideColumn(PROGRESS);
ui->contentTreeView->hideColumn(REMAINING); ui->contentTreeView->hideColumn(REMAINING);
ui->contentTreeView->hideColumn(AVAILABILITY);
// Expand root folder // Expand root folder
ui->contentTreeView->setExpanded(m_contentModel->index(0, 0), true); ui->contentTreeView->setExpanded(m_contentModel->index(0, 0), true);

1
src/gui/properties/propertieswidget.cpp

@ -493,6 +493,7 @@ void PropertiesWidget::loadDynamicData()
qDebug("Updating priorities in files tab"); qDebug("Updating priorities in files tab");
m_ui->filesList->setUpdatesEnabled(false); m_ui->filesList->setUpdatesEnabled(false);
PropListModel->model()->updateFilesProgress(m_torrent->filesProgress()); PropListModel->model()->updateFilesProgress(m_torrent->filesProgress());
PropListModel->model()->updateFilesAvailability(m_torrent->availableFileFractions());
// XXX: We don't update file priorities regularly for performance // XXX: We don't update file priorities regularly for performance
// reasons. This means that priorities will not be updated if // reasons. This means that priorities will not be updated if
// set from the Web UI. // set from the Web UI.

14
src/gui/properties/proplistdelegate.cpp

@ -42,6 +42,7 @@
#include <QProxyStyle> #include <QProxyStyle>
#endif #endif
#include "base/unicodestrings.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/string.h" #include "base/utils/string.h"
#include "propertieswidget.h" #include "propertieswidget.h"
@ -131,6 +132,19 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
QItemDelegate::drawDisplay(painter, opt, option.rect, text); QItemDelegate::drawDisplay(painter, opt, option.rect, text);
} }
break; break;
case AVAILABILITY: {
const qreal availability = index.data().toDouble();
if (availability < 0) {
QItemDelegate::drawDisplay(painter, opt, option.rect, tr("N/A"));
}
else {
const QString value = (availability >= 1.0)
? QLatin1String("100")
: Utils::String::fromDouble(availability * 100., 1);
QItemDelegate::drawDisplay(painter, opt, option.rect, value + C_THIN_SPACE + QLatin1Char('%'));
}
}
break;
default: default:
QItemDelegate::paint(painter, option, index); QItemDelegate::paint(painter, option, index);
break; break;

4
src/gui/properties/proplistdelegate.h

@ -46,7 +46,8 @@ enum PropColumn
PCSIZE, PCSIZE,
PROGRESS, PROGRESS,
PRIORITY, PRIORITY,
REMAINING REMAINING,
AVAILABILITY
}; };
class PropListDelegate: public QItemDelegate class PropListDelegate: public QItemDelegate
@ -72,3 +73,4 @@ private:
}; };
#endif #endif

18
src/gui/torrentcontentmodel.cpp

@ -56,7 +56,7 @@ namespace
TorrentContentModel::TorrentContentModel(QObject *parent) TorrentContentModel::TorrentContentModel(QObject *parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
, m_rootItem(new TorrentContentModelFolder(QList<QVariant>({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining") }))) , m_rootItem(new TorrentContentModelFolder(QList<QVariant>({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining"), tr("Availability") })))
{ {
} }
@ -76,6 +76,7 @@ void TorrentContentModel::updateFilesProgress(const QVector<qreal> &fp)
m_filesIndex[i]->setProgress(fp[i]); m_filesIndex[i]->setProgress(fp[i]);
// Update folders progress in the tree // Update folders progress in the tree
m_rootItem->recalculateProgress(); m_rootItem->recalculateProgress();
m_rootItem->recalculateAvailability();
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }
@ -92,6 +93,20 @@ void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio)
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }
void TorrentContentModel::updateFilesAvailability(const QVector<qreal> &fa)
{
Q_ASSERT(m_filesIndex.size() == fa.size());
// XXX: Why is this necessary?
if (m_filesIndex.size() != fa.size()) return;
emit layoutAboutToBeChanged();
for (int i = 0; i < fa.size(); ++i)
m_filesIndex[i]->setAvailability(fa[i]);
// Update folders progress in the tree
m_rootItem->recalculateProgress();
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
}
QVector<int> TorrentContentModel::getFilePriorities() const QVector<int> TorrentContentModel::getFilePriorities() const
{ {
QVector<int> prio; QVector<int> prio;
@ -134,6 +149,7 @@ bool TorrentContentModel::setData(const QModelIndex& index, const QVariant& valu
item->setPriority(prio::NORMAL); item->setPriority(prio::NORMAL);
// Update folders progress in the tree // Update folders progress in the tree
m_rootItem->recalculateProgress(); m_rootItem->recalculateProgress();
m_rootItem->recalculateAvailability();
emit dataChanged(this->index(0, 0), this->index(rowCount() - 1, columnCount() - 1)); emit dataChanged(this->index(0, 0), this->index(rowCount() - 1, columnCount() - 1));
emit filteredFilesChanged(); emit filteredFilesChanged();
} }

52
src/gui/torrentcontentmodel.h

@ -41,40 +41,42 @@
class TorrentContentModelFile; class TorrentContentModelFile;
class TorrentContentModel: public QAbstractItemModel { class TorrentContentModel: public QAbstractItemModel
Q_OBJECT {
Q_OBJECT
public: public:
TorrentContentModel(QObject *parent = 0); TorrentContentModel(QObject *parent = 0);
~TorrentContentModel(); ~TorrentContentModel();
void updateFilesProgress(const QVector<qreal> &fp); void updateFilesProgress(const QVector<qreal> &fp);
void updateFilesPriorities(const QVector<int> &fprio); void updateFilesPriorities(const QVector<int> &fprio);
QVector<int> getFilePriorities() const; void updateFilesAvailability(const QVector<qreal> &fa);
bool allFiltered() const; QVector<int> getFilePriorities() const;
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const; bool allFiltered() const;
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
TorrentContentModelItem::ItemType itemType(const QModelIndex& index) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
int getFileIndex(const QModelIndex& index); TorrentContentModelItem::ItemType itemType(const QModelIndex& index) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; int getFileIndex(const QModelIndex& index);
virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; virtual Qt::ItemFlags flags(const QModelIndex& index) const;
virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual QModelIndex parent(const QModelIndex& index) const; virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex& index) const;
void clear(); virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
void setupModelData(const BitTorrent::TorrentInfo &info); void clear();
void setupModelData(const BitTorrent::TorrentInfo &info);
signals: signals:
void filteredFilesChanged(); void filteredFilesChanged();
public slots: public slots:
void selectAll(); void selectAll();
void selectNone(); void selectNone();
private: private:
TorrentContentModelFolder* m_rootItem; TorrentContentModelFolder *m_rootItem;
QVector<TorrentContentModelFile*> m_filesIndex; QVector<TorrentContentModelFile *> m_filesIndex;
}; };
#endif // TORRENTCONTENTMODEL_H #endif // TORRENTCONTENTMODEL_H

53
src/gui/torrentcontentmodelfile.cpp

@ -32,43 +32,54 @@
#include "torrentcontentmodelfolder.h" #include "torrentcontentmodelfolder.h"
TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulonglong fileSize, TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulonglong fileSize,
TorrentContentModelFolder* parent, int file_index) TorrentContentModelFolder *parent, int fileIndex)
: TorrentContentModelItem(parent) : TorrentContentModelItem(parent)
, m_fileIndex(file_index) , m_fileIndex(fileIndex)
{ {
Q_ASSERT(parent); Q_ASSERT(parent);
m_name = fileName; m_name = fileName;
// Do not display incomplete extensions // Do not display incomplete extensions
if (m_name.endsWith(".!qB")) if (m_name.endsWith(".!qB"))
m_name.chop(4); m_name.chop(4);
m_size = fileSize; m_size = fileSize;
} }
int TorrentContentModelFile::fileIndex() const int TorrentContentModelFile::fileIndex() const
{ {
return m_fileIndex; return m_fileIndex;
} }
void TorrentContentModelFile::setPriority(int new_prio, bool update_parent) void TorrentContentModelFile::setPriority(int newPriority, bool updateParent)
{ {
Q_ASSERT(new_prio != prio::MIXED); Q_ASSERT(newPriority != prio::MIXED);
if (m_priority == new_prio) if (m_priority == newPriority)
return; return;
m_priority = new_prio; m_priority = newPriority;
// Update parent // Update parent
if (update_parent) if (updateParent)
m_parentItem->updatePriority(); m_parentItem->updatePriority();
} }
void TorrentContentModelFile::setProgress(qreal progress) void TorrentContentModelFile::setProgress(qreal progress)
{ {
m_progress = progress; m_progress = progress;
m_remaining = (qulonglong)(m_size * (1.0 - m_progress)); m_remaining = static_cast<qulonglong>(m_size * (1.0 - m_progress));
Q_ASSERT(m_progress <= 1.); Q_ASSERT(m_progress <= 1.);
}
void TorrentContentModelFile::setAvailability(qreal availability)
{
m_availability = availability;
Q_ASSERT(m_availability <= 1.);
}
TorrentContentModelItem::ItemType TorrentContentModelFile::itemType() const
{
return FileType;
} }

17
src/gui/torrentcontentmodelfile.h

@ -33,19 +33,20 @@
#include "torrentcontentmodelitem.h" #include "torrentcontentmodelitem.h"
class TorrentContentModelFile : public TorrentContentModelItem class TorrentContentModelFile: public TorrentContentModelItem
{ {
public: public:
TorrentContentModelFile(const QString &fileName, qulonglong fileSize, TorrentContentModelFile(const QString &fileName, qulonglong fileSize,
TorrentContentModelFolder* parent, int file_index); TorrentContentModelFolder *parent, int fileIndex);
int fileIndex() const; int fileIndex() const;
void setPriority(int new_prio, bool update_parent = true); void setPriority(int newPriority, bool updateParent = true) override;
void setProgress(qreal progress); void setProgress(qreal progress);
ItemType itemType() const { return FileType; } void setAvailability(qreal availability);
ItemType itemType() const override;
private: private:
int m_fileIndex; int m_fileIndex;
}; };
#endif // TORRENTCONTENTMODELFILE_H #endif // TORRENTCONTENTMODELFILE_H

193
src/gui/torrentcontentmodelfolder.cpp

@ -31,136 +31,167 @@
#include <QDebug> #include <QDebug>
#include "torrentcontentmodelfolder.h" #include "torrentcontentmodelfolder.h"
TorrentContentModelFolder::TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent) TorrentContentModelFolder::TorrentContentModelFolder(const QString &name, TorrentContentModelFolder *parent)
: TorrentContentModelItem(parent) : TorrentContentModelItem(parent)
{ {
Q_ASSERT(parent); Q_ASSERT(parent);
m_name = name; m_name = name;
// Do not display incomplete extensions // Do not display incomplete extensions
if (m_name.endsWith(".!qB")) if (m_name.endsWith(".!qB"))
m_name.chop(4); m_name.chop(4);
} }
TorrentContentModelFolder::TorrentContentModelFolder(const QList<QVariant>& data) TorrentContentModelFolder::TorrentContentModelFolder(const QList<QVariant> &data)
: TorrentContentModelItem(0) : TorrentContentModelItem(0)
{ {
Q_ASSERT(data.size() == NB_COL); Q_ASSERT(data.size() == NB_COL);
m_itemData = data; m_itemData = data;
} }
TorrentContentModelFolder::~TorrentContentModelFolder() TorrentContentModelFolder::~TorrentContentModelFolder()
{ {
qDeleteAll(m_childItems); qDeleteAll(m_childItems);
}
TorrentContentModelItem::ItemType TorrentContentModelFolder::itemType() const
{
return FolderType;
} }
void TorrentContentModelFolder::deleteAllChildren() void TorrentContentModelFolder::deleteAllChildren()
{ {
Q_ASSERT(isRootItem()); Q_ASSERT(isRootItem());
qDeleteAll(m_childItems); qDeleteAll(m_childItems);
m_childItems.clear(); m_childItems.clear();
} }
const QList<TorrentContentModelItem*>& TorrentContentModelFolder::children() const const QList<TorrentContentModelItem *> &TorrentContentModelFolder::children() const
{ {
return m_childItems; return m_childItems;
} }
void TorrentContentModelFolder::appendChild(TorrentContentModelItem* item) void TorrentContentModelFolder::appendChild(TorrentContentModelItem *item)
{ {
Q_ASSERT(item); Q_ASSERT(item);
m_childItems.append(item); m_childItems.append(item);
// Update own size // Update own size
if (item->itemType() == FileType) if (item->itemType() == FileType)
increaseSize(item->size()); increaseSize(item->size());
} }
TorrentContentModelItem* TorrentContentModelFolder::child(int row) const TorrentContentModelItem *TorrentContentModelFolder::child(int row) const
{ {
return m_childItems.value(row, 0); return m_childItems.value(row, 0);
} }
TorrentContentModelFolder* TorrentContentModelFolder::childFolderWithName(const QString& name) const TorrentContentModelFolder *TorrentContentModelFolder::childFolderWithName(const QString &name) const
{ {
foreach (TorrentContentModelItem* child, m_childItems) { foreach (TorrentContentModelItem *child, m_childItems)
if (child->itemType() == FolderType && child->name() == name) if ((child->itemType() == FolderType) && (child->name() == name))
return static_cast<TorrentContentModelFolder*>(child); return static_cast<TorrentContentModelFolder *>(child);
} return 0;
return 0;
} }
int TorrentContentModelFolder::childCount() const int TorrentContentModelFolder::childCount() const
{ {
return m_childItems.count(); return m_childItems.count();
} }
// Only non-root folders use this function // Only non-root folders use this function
void TorrentContentModelFolder::updatePriority() void TorrentContentModelFolder::updatePriority()
{ {
if (isRootItem()) if (isRootItem())
return; return;
Q_ASSERT(!m_childItems.isEmpty()); Q_ASSERT(!m_childItems.isEmpty());
// If all children have the same priority // If all children have the same priority
// then the folder should have the same // then the folder should have the same
// priority // priority
const int prio = m_childItems.first()->priority(); const int prio = m_childItems.first()->priority();
for (int i=1; i<m_childItems.size(); ++i) { for (int i = 1; i < m_childItems.size(); ++i) {
if (m_childItems.at(i)->priority() != prio) { if (m_childItems.at(i)->priority() != prio) {
setPriority(prio::MIXED); setPriority(prio::MIXED);
return; return;
}
} }
} // All child items have the same priority
// All child items have the same priority // Update own if necessary
// Update own if necessary setPriority(prio);
setPriority(prio);
} }
void TorrentContentModelFolder::setPriority(int new_prio, bool update_parent) void TorrentContentModelFolder::setPriority(int newPriority, bool updateParent)
{ {
if (m_priority == new_prio) if (m_priority == newPriority)
return; return;
m_priority = new_prio; m_priority = newPriority;
// Update parent priority // Update parent priority
if (update_parent) if (updateParent)
m_parentItem->updatePriority(); m_parentItem->updatePriority();
// Update children // Update children
if (m_priority != prio::MIXED) { if (m_priority != prio::MIXED)
foreach (TorrentContentModelItem* child, m_childItems) foreach (TorrentContentModelItem *child, m_childItems)
child->setPriority(m_priority, false); child->setPriority(m_priority, false);
}
} }
void TorrentContentModelFolder::recalculateProgress() void TorrentContentModelFolder::recalculateProgress()
{ {
qreal tProgress = 0; qreal tProgress = 0;
qulonglong tSize = 0; qulonglong tSize = 0;
qulonglong tRemaining = 0; qulonglong tRemaining = 0;
foreach (TorrentContentModelItem* child, m_childItems) { foreach (TorrentContentModelItem *child, m_childItems) {
if (child->priority() != prio::IGNORED) { if (child->priority() != prio::IGNORED) {
if (child->itemType() == FolderType) if (child->itemType() == FolderType)
static_cast<TorrentContentModelFolder*>(child)->recalculateProgress(); static_cast<TorrentContentModelFolder *>(child)->recalculateProgress();
tProgress += child->progress() * child->size(); tProgress += child->progress() * child->size();
tSize += child->size(); tSize += child->size();
tRemaining += child->remaining(); tRemaining += child->remaining();
}
} }
}
if (!isRootItem() && tSize > 0) { if (!isRootItem() && (tSize > 0)) {
m_progress = tProgress / tSize; m_progress = tProgress / tSize;
m_remaining = tRemaining; m_remaining = tRemaining;
Q_ASSERT(m_progress <= 1.); Q_ASSERT(m_progress <= 1.);
} }
}
void TorrentContentModelFolder::recalculateAvailability()
{
qreal tAvailability = 0;
qulonglong tSize = 0;
bool foundAnyData = false;
foreach (TorrentContentModelItem* child, m_childItems) {
if (child->priority() == prio::IGNORED)
continue;
if (child->itemType() == FolderType)
static_cast<TorrentContentModelFolder*>(child)->recalculateAvailability();
const qreal childAvailability = child->availability();
if (childAvailability >= 0) { // -1 means "no data"
tAvailability += childAvailability * child->size();
foundAnyData = true;
}
tSize += child->size();
}
if (!isRootItem() && (tSize > 0) && foundAnyData) {
m_availability = tAvailability / tSize;
Q_ASSERT(m_availability <= 1.);
}
else {
m_availability = -1.;
}
} }
void TorrentContentModelFolder::increaseSize(qulonglong delta) void TorrentContentModelFolder::increaseSize(qulonglong delta)
{ {
if (isRootItem()) if (isRootItem())
return; return;
m_size += delta; m_size += delta;
m_parentItem->increaseSize(delta); m_parentItem->increaseSize(delta);
} }

37
src/gui/torrentcontentmodelfolder.h

@ -33,34 +33,35 @@
#include "torrentcontentmodelitem.h" #include "torrentcontentmodelitem.h"
class TorrentContentModelFolder : public TorrentContentModelItem class TorrentContentModelFolder: public TorrentContentModelItem
{ {
public: public:
// Folder constructor // Folder constructor
TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent); TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent);
// Invisible root item constructor // Invisible root item constructor
TorrentContentModelFolder(const QList<QVariant>& data); TorrentContentModelFolder(const QList<QVariant>& data);
~TorrentContentModelFolder(); ~TorrentContentModelFolder();
ItemType itemType() const { return FolderType; } ItemType itemType() const override;
void increaseSize(qulonglong delta); void increaseSize(qulonglong delta);
void recalculateProgress(); void recalculateProgress();
void updatePriority(); void recalculateAvailability();
void updatePriority();
void setPriority(int new_prio, bool update_parent = true); void setPriority(int newPriority, bool updateParent = true) override;
void deleteAllChildren(); void deleteAllChildren();
const QList<TorrentContentModelItem*>& children() const; const QList<TorrentContentModelItem*>& children() const;
void appendChild(TorrentContentModelItem* item); void appendChild(TorrentContentModelItem* item);
TorrentContentModelItem* child(int row) const; TorrentContentModelItem* child(int row) const;
TorrentContentModelFolder* childFolderWithName(const QString& name) const; TorrentContentModelFolder* childFolderWithName(const QString& name) const;
int childCount() const; int childCount() const;
private: private:
QList<TorrentContentModelItem*> m_childItems; QList<TorrentContentModelItem*> m_childItems;
}; };
#endif // TORRENTCONTENTMODELFOLDER_H #endif // TORRENTCONTENTMODELFOLDER_H

94
src/gui/torrentcontentmodelitem.cpp

@ -34,36 +34,40 @@
#include "torrentcontentmodelfolder.h" #include "torrentcontentmodelfolder.h"
#include <QDebug> #include <QDebug>
TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder* parent) TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *parent)
: m_parentItem(parent) : m_parentItem(parent)
, m_size(0) , m_size(0)
, m_remaining(0) , m_remaining(0)
, m_priority(prio::NORMAL) , m_priority(prio::NORMAL)
, m_progress(0) , m_progress(0)
, m_availability(-1.)
{ {
} }
TorrentContentModelItem::~TorrentContentModelItem() TorrentContentModelItem::~TorrentContentModelItem() = default;
bool TorrentContentModelItem::isRootItem() const
{ {
return !m_parentItem;
} }
QString TorrentContentModelItem::name() const QString TorrentContentModelItem::name() const
{ {
Q_ASSERT(!isRootItem()); Q_ASSERT(!isRootItem());
return m_name; return m_name;
} }
void TorrentContentModelItem::setName(const QString& name) void TorrentContentModelItem::setName(const QString &name)
{ {
Q_ASSERT(!isRootItem()); Q_ASSERT(!isRootItem());
m_name = name; m_name = name;
} }
qulonglong TorrentContentModelItem::size() const qulonglong TorrentContentModelItem::size() const
{ {
Q_ASSERT(!isRootItem()); Q_ASSERT(!isRootItem());
return m_size; return m_size;
} }
qreal TorrentContentModelItem::progress() const qreal TorrentContentModelItem::progress() const
@ -81,47 +85,57 @@ qulonglong TorrentContentModelItem::remaining() const
return m_remaining; return m_remaining;
} }
qreal TorrentContentModelItem::availability() const
{
Q_ASSERT(!isRootItem());
return m_size > 0 ? m_availability : 0.;
}
int TorrentContentModelItem::priority() const int TorrentContentModelItem::priority() const
{ {
Q_ASSERT(!isRootItem()); Q_ASSERT(!isRootItem());
return m_priority; return m_priority;
} }
int TorrentContentModelItem::columnCount() const int TorrentContentModelItem::columnCount() const
{ {
return NB_COL; return NB_COL;
} }
QVariant TorrentContentModelItem::data(int column) const QVariant TorrentContentModelItem::data(int column) const
{ {
if (isRootItem()) if (isRootItem())
return m_itemData.value(column); return m_itemData.value(column);
switch(column) { switch (column) {
case COL_NAME: case COL_NAME:
return m_name; return m_name;
case COL_PRIO: case COL_PRIO:
return m_priority; return m_priority;
case COL_PROGRESS: case COL_PROGRESS:
return progress(); return progress();
case COL_SIZE: case COL_SIZE:
return m_size; return m_size;
case COL_REMAINING: case COL_REMAINING:
return remaining(); return remaining();
default: case COL_AVAILABILITY:
Q_ASSERT(false); return availability();
return QVariant(); default:
} Q_ASSERT(false);
return QVariant();
}
} }
int TorrentContentModelItem::row() const int TorrentContentModelItem::row() const
{ {
if (m_parentItem) if (m_parentItem)
return m_parentItem->children().indexOf(const_cast<TorrentContentModelItem*>(this)); return m_parentItem->children().indexOf(const_cast<TorrentContentModelItem *>(this));
return 0; return 0;
} }
TorrentContentModelFolder* TorrentContentModelItem::parent() const TorrentContentModelFolder *TorrentContentModelItem::parent() const
{ {
return m_parentItem; return m_parentItem;
} }

84
src/gui/torrentcontentmodelitem.h

@ -34,48 +34,74 @@
#include <QList> #include <QList>
#include <QVariant> #include <QVariant>
namespace prio { namespace prio
enum FilePriority {IGNORED=0, NORMAL=1, HIGH=6, MAXIMUM=7, MIXED=-1}; {
enum FilePriority
{
IGNORED=0,
NORMAL=1,
HIGH=6,
MAXIMUM=7,
MIXED=-1
};
} }
class TorrentContentModelFolder; class TorrentContentModelFolder;
class TorrentContentModelItem { class TorrentContentModelItem
{
public: public:
enum TreeItemColumns {COL_NAME, COL_SIZE, COL_PROGRESS, COL_PRIO, COL_REMAINING, NB_COL}; enum TreeItemColumns
enum ItemType { FileType, FolderType }; {
COL_NAME,
COL_SIZE,
COL_PROGRESS,
COL_PRIO,
COL_REMAINING,
COL_AVAILABILITY,
NB_COL
};
TorrentContentModelItem(TorrentContentModelFolder* parent); enum ItemType
virtual ~TorrentContentModelItem(); {
FileType,
FolderType
};
inline bool isRootItem() const { return !m_parentItem; } TorrentContentModelItem(TorrentContentModelFolder *parent);
TorrentContentModelFolder* parent() const; virtual ~TorrentContentModelItem();
virtual ItemType itemType() const = 0;
QString name() const; bool isRootItem() const;
void setName(const QString& name); TorrentContentModelFolder *parent() const;
virtual ItemType itemType() const = 0;
qulonglong size() const; QString name() const;
qreal progress() const; void setName(const QString &name);
qulonglong remaining() const;
int priority() const; qulonglong size() const;
virtual void setPriority(int new_prio, bool update_parent = true) = 0; qreal progress() const;
qulonglong remaining() const;
int columnCount() const; qreal availability() const;
QVariant data(int column) const;
int row() const; int priority() const;
virtual void setPriority(int newPriority, bool updateParent = true) = 0;
int columnCount() const;
QVariant data(int column) const;
int row() const;
protected: protected:
TorrentContentModelFolder* m_parentItem; TorrentContentModelFolder *m_parentItem;
// Root item members // Root item members
QList<QVariant> m_itemData; QList<QVariant> m_itemData;
// Non-root item members // Non-root item members
QString m_name; QString m_name;
qulonglong m_size; qulonglong m_size;
qulonglong m_remaining; qulonglong m_remaining;
int m_priority; int m_priority;
qreal m_progress; qreal m_progress;
qreal m_availability;
}; };
#endif // TORRENTCONTENTMODELITEM_H #endif // TORRENTCONTENTMODELITEM_H

Loading…
Cancel
Save