From 114c9a84216784f2cec9a82643fbfd65d83ba7e6 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Tue, 22 Mar 2016 16:16:03 +0100 Subject: [PATCH 1/4] Follow project coding style. Issue #2192. --- src/gui/torrentcontentmodel.h | 51 ++++---- src/gui/torrentcontentmodelfile.cpp | 47 ++++---- src/gui/torrentcontentmodelfile.h | 16 +-- src/gui/torrentcontentmodelfolder.cpp | 165 +++++++++++++------------- src/gui/torrentcontentmodelfolder.h | 36 +++--- src/gui/torrentcontentmodelitem.cpp | 83 ++++++------- src/gui/torrentcontentmodelitem.h | 80 ++++++++----- 7 files changed, 256 insertions(+), 222 deletions(-) diff --git a/src/gui/torrentcontentmodel.h b/src/gui/torrentcontentmodel.h index 547c85cfb..e7c2f8395 100644 --- a/src/gui/torrentcontentmodel.h +++ b/src/gui/torrentcontentmodel.h @@ -41,40 +41,41 @@ class TorrentContentModelFile; -class TorrentContentModel: public QAbstractItemModel { - Q_OBJECT +class TorrentContentModel: public QAbstractItemModel +{ + Q_OBJECT public: - TorrentContentModel(QObject *parent = 0); - ~TorrentContentModel(); + TorrentContentModel(QObject *parent = 0); + ~TorrentContentModel(); - void updateFilesProgress(const QVector &fp); - void updateFilesPriorities(const QVector &fprio); - QVector getFilePriorities() 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::ItemType itemType(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 BitTorrent::TorrentInfo &info); + void updateFilesProgress(const QVector &fp); + void updateFilesPriorities(const QVector &fprio); + QVector getFilePriorities() 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::ItemType itemType(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 BitTorrent::TorrentInfo &info); signals: - void filteredFilesChanged(); + void filteredFilesChanged(); public slots: - void selectAll(); - void selectNone(); + void selectAll(); + void selectNone(); private: - TorrentContentModelFolder* m_rootItem; - QVector m_filesIndex; + TorrentContentModelFolder *m_rootItem; + QVector m_filesIndex; }; #endif // TORRENTCONTENTMODEL_H diff --git a/src/gui/torrentcontentmodelfile.cpp b/src/gui/torrentcontentmodelfile.cpp index cabd8ed5c..20d3c2586 100644 --- a/src/gui/torrentcontentmodelfile.cpp +++ b/src/gui/torrentcontentmodelfile.cpp @@ -32,43 +32,48 @@ #include "torrentcontentmodelfolder.h" TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulonglong fileSize, - TorrentContentModelFolder* parent, int file_index) - : TorrentContentModelItem(parent) - , m_fileIndex(file_index) + TorrentContentModelFolder *parent, int fileIndex) + : TorrentContentModelItem(parent) + , m_fileIndex(fileIndex) { - Q_ASSERT(parent); + Q_ASSERT(parent); - m_name = fileName; + m_name = fileName; - // Do not display incomplete extensions - if (m_name.endsWith(".!qB")) - m_name.chop(4); + // Do not display incomplete extensions + if (m_name.endsWith(".!qB")) + m_name.chop(4); - m_size = fileSize; + m_size = fileSize; } 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) - return; + if (m_priority == newPriority) + return; - m_priority = new_prio; + m_priority = newPriority; - // Update parent - if (update_parent) - m_parentItem->updatePriority(); + // Update parent + if (updateParent) + m_parentItem->updatePriority(); } void TorrentContentModelFile::setProgress(qreal progress) { - m_progress = progress; - m_remaining = (qulonglong)(m_size * (1.0 - m_progress)); - Q_ASSERT(m_progress <= 1.); + m_progress = progress; + m_remaining = static_cast(m_size * (1.0 - m_progress)); + Q_ASSERT(m_progress <= 1.); +} + +TorrentContentModelItem::ItemType TorrentContentModelFile::itemType() const +{ + return FileType; } diff --git a/src/gui/torrentcontentmodelfile.h b/src/gui/torrentcontentmodelfile.h index d3861b717..234908e8d 100644 --- a/src/gui/torrentcontentmodelfile.h +++ b/src/gui/torrentcontentmodelfile.h @@ -33,19 +33,19 @@ #include "torrentcontentmodelitem.h" -class TorrentContentModelFile : public TorrentContentModelItem +class TorrentContentModelFile: public TorrentContentModelItem { public: - TorrentContentModelFile(const QString &fileName, qulonglong fileSize, - TorrentContentModelFolder* parent, int file_index); + TorrentContentModelFile(const QString &fileName, qulonglong fileSize, + TorrentContentModelFolder *parent, int fileIndex); - int fileIndex() const; - void setPriority(int new_prio, bool update_parent = true); - void setProgress(qreal progress); - ItemType itemType() const { return FileType; } + int fileIndex() const; + void setPriority(int newPriority, bool updateParent = true) override; + void setProgress(qreal progress); + ItemType itemType() const override; private: - int m_fileIndex; + int m_fileIndex; }; #endif // TORRENTCONTENTMODELFILE_H diff --git a/src/gui/torrentcontentmodelfolder.cpp b/src/gui/torrentcontentmodelfolder.cpp index 6695dbab9..ea250876a 100644 --- a/src/gui/torrentcontentmodelfolder.cpp +++ b/src/gui/torrentcontentmodelfolder.cpp @@ -31,136 +31,139 @@ #include #include "torrentcontentmodelfolder.h" -TorrentContentModelFolder::TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent) - : TorrentContentModelItem(parent) +TorrentContentModelFolder::TorrentContentModelFolder(const QString &name, TorrentContentModelFolder *parent) + : TorrentContentModelItem(parent) { - Q_ASSERT(parent); - m_name = name; - // Do not display incomplete extensions - if (m_name.endsWith(".!qB")) - m_name.chop(4); + Q_ASSERT(parent); + m_name = name; + // Do not display incomplete extensions + if (m_name.endsWith(".!qB")) + m_name.chop(4); } -TorrentContentModelFolder::TorrentContentModelFolder(const QList& data) - : TorrentContentModelItem(0) +TorrentContentModelFolder::TorrentContentModelFolder(const QList &data) + : TorrentContentModelItem(0) { - Q_ASSERT(data.size() == NB_COL); - m_itemData = data; + Q_ASSERT(data.size() == NB_COL); + m_itemData = data; } TorrentContentModelFolder::~TorrentContentModelFolder() { - qDeleteAll(m_childItems); + qDeleteAll(m_childItems); +} + +TorrentContentModelItem::ItemType TorrentContentModelFolder::itemType() const +{ + return FolderType; } void TorrentContentModelFolder::deleteAllChildren() { - Q_ASSERT(isRootItem()); - qDeleteAll(m_childItems); - m_childItems.clear(); + Q_ASSERT(isRootItem()); + qDeleteAll(m_childItems); + m_childItems.clear(); } -const QList& TorrentContentModelFolder::children() const +const QList &TorrentContentModelFolder::children() const { - return m_childItems; + return m_childItems; } -void TorrentContentModelFolder::appendChild(TorrentContentModelItem* item) +void TorrentContentModelFolder::appendChild(TorrentContentModelItem *item) { - Q_ASSERT(item); - m_childItems.append(item); - // Update own size - if (item->itemType() == FileType) - increaseSize(item->size()); + Q_ASSERT(item); + m_childItems.append(item); + // Update own size + if (item->itemType() == FileType) + 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) { - if (child->itemType() == FolderType && child->name() == name) - return static_cast(child); - } - return 0; + foreach (TorrentContentModelItem *child, m_childItems) + if ((child->itemType() == FolderType) && (child->name() == name)) + return static_cast(child); + return 0; } int TorrentContentModelFolder::childCount() const { - return m_childItems.count(); + return m_childItems.count(); } // Only non-root folders use this function void TorrentContentModelFolder::updatePriority() { - if (isRootItem()) - return; - - Q_ASSERT(!m_childItems.isEmpty()); - - // If all children have the same priority - // then the folder should have the same - // priority - const int prio = m_childItems.first()->priority(); - for (int i=1; ipriority() != prio) { - setPriority(prio::MIXED); - return; + if (isRootItem()) + return; + + Q_ASSERT(!m_childItems.isEmpty()); + + // If all children have the same priority + // then the folder should have the same + // priority + const int prio = m_childItems.first()->priority(); + for (int i = 1; i < m_childItems.size(); ++i) { + if (m_childItems.at(i)->priority() != prio) { + setPriority(prio::MIXED); + return; + } } - } - // All child items have the same priority - // Update own if necessary - setPriority(prio); + // All child items have the same priority + // Update own if necessary + setPriority(prio); } -void TorrentContentModelFolder::setPriority(int new_prio, bool update_parent) +void TorrentContentModelFolder::setPriority(int newPriority, bool updateParent) { - if (m_priority == new_prio) - return; + if (m_priority == newPriority) + return; - m_priority = new_prio; + m_priority = newPriority; - // Update parent priority - if (update_parent) - m_parentItem->updatePriority(); + // Update parent priority + if (updateParent) + m_parentItem->updatePriority(); - // Update children - if (m_priority != prio::MIXED) { - foreach (TorrentContentModelItem* child, m_childItems) - child->setPriority(m_priority, false); - } + // Update children + if (m_priority != prio::MIXED) + foreach (TorrentContentModelItem *child, m_childItems) + child->setPriority(m_priority, false); } void TorrentContentModelFolder::recalculateProgress() { - qreal tProgress = 0; - qulonglong tSize = 0; - qulonglong tRemaining = 0; - foreach (TorrentContentModelItem* child, m_childItems) { - if (child->priority() != prio::IGNORED) { - if (child->itemType() == FolderType) - static_cast(child)->recalculateProgress(); - tProgress += child->progress() * child->size(); - tSize += child->size(); - tRemaining += child->remaining(); + qreal tProgress = 0; + qulonglong tSize = 0; + qulonglong tRemaining = 0; + foreach (TorrentContentModelItem *child, m_childItems) { + if (child->priority() != prio::IGNORED) { + if (child->itemType() == FolderType) + static_cast(child)->recalculateProgress(); + tProgress += child->progress() * child->size(); + tSize += child->size(); + tRemaining += child->remaining(); + } } - } - if (!isRootItem() && tSize > 0) { - m_progress = tProgress / tSize; - m_remaining = tRemaining; - Q_ASSERT(m_progress <= 1.); - } + if (!isRootItem() && (tSize > 0)) { + m_progress = tProgress / tSize; + m_remaining = tRemaining; + Q_ASSERT(m_progress <= 1.); + } } void TorrentContentModelFolder::increaseSize(qulonglong delta) { - if (isRootItem()) - return; + if (isRootItem()) + return; - m_size += delta; - m_parentItem->increaseSize(delta); + m_size += delta; + m_parentItem->increaseSize(delta); } diff --git a/src/gui/torrentcontentmodelfolder.h b/src/gui/torrentcontentmodelfolder.h index ead57acd7..5b12ddfb5 100644 --- a/src/gui/torrentcontentmodelfolder.h +++ b/src/gui/torrentcontentmodelfolder.h @@ -33,34 +33,34 @@ #include "torrentcontentmodelitem.h" -class TorrentContentModelFolder : public TorrentContentModelItem +class TorrentContentModelFolder: public TorrentContentModelItem { public: - // Folder constructor - TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent); + // Folder constructor + TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent); - // Invisible root item constructor - TorrentContentModelFolder(const QList& data); + // Invisible root item constructor + TorrentContentModelFolder(const QList& data); - ~TorrentContentModelFolder(); + ~TorrentContentModelFolder(); - ItemType itemType() const { return FolderType; } + ItemType itemType() const override; - void increaseSize(qulonglong delta); - void recalculateProgress(); - void updatePriority(); + void increaseSize(qulonglong delta); + void recalculateProgress(); + void updatePriority(); - void setPriority(int new_prio, bool update_parent = true); + void setPriority(int newPriority, bool updateParent = true) override; - void deleteAllChildren(); - const QList& children() const; - void appendChild(TorrentContentModelItem* item); - TorrentContentModelItem* child(int row) const; - TorrentContentModelFolder* childFolderWithName(const QString& name) const; - int childCount() const; + void deleteAllChildren(); + const QList& children() const; + void appendChild(TorrentContentModelItem* item); + TorrentContentModelItem* child(int row) const; + TorrentContentModelFolder* childFolderWithName(const QString& name) const; + int childCount() const; private: - QList m_childItems; + QList m_childItems; }; #endif // TORRENTCONTENTMODELFOLDER_H diff --git a/src/gui/torrentcontentmodelitem.cpp b/src/gui/torrentcontentmodelitem.cpp index c841a0cb8..58765efba 100644 --- a/src/gui/torrentcontentmodelitem.cpp +++ b/src/gui/torrentcontentmodelitem.cpp @@ -34,36 +34,39 @@ #include "torrentcontentmodelfolder.h" #include -TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder* parent) - : m_parentItem(parent) - , m_size(0) - , m_remaining(0) - , m_priority(prio::NORMAL) - , m_progress(0) +TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *parent) + : m_parentItem(parent) + , m_size(0) + , m_remaining(0) + , m_priority(prio::NORMAL) + , m_progress(0) { } -TorrentContentModelItem::~TorrentContentModelItem() +TorrentContentModelItem::~TorrentContentModelItem() = default; + +bool TorrentContentModelItem::isRootItem() const { + return !m_parentItem; } QString TorrentContentModelItem::name() const { - Q_ASSERT(!isRootItem()); - return m_name; + Q_ASSERT(!isRootItem()); + return m_name; } -void TorrentContentModelItem::setName(const QString& name) +void TorrentContentModelItem::setName(const QString &name) { - Q_ASSERT(!isRootItem()); - m_name = name; + Q_ASSERT(!isRootItem()); + m_name = name; } qulonglong TorrentContentModelItem::size() const { - Q_ASSERT(!isRootItem()); + Q_ASSERT(!isRootItem()); - return m_size; + return m_size; } qreal TorrentContentModelItem::progress() const @@ -83,45 +86,45 @@ qulonglong TorrentContentModelItem::remaining() const int TorrentContentModelItem::priority() const { - Q_ASSERT(!isRootItem()); - return m_priority; + Q_ASSERT(!isRootItem()); + return m_priority; } int TorrentContentModelItem::columnCount() const { - return NB_COL; + return NB_COL; } QVariant TorrentContentModelItem::data(int column) const { - if (isRootItem()) - return m_itemData.value(column); - - switch(column) { - case COL_NAME: - return m_name; - case COL_PRIO: - return m_priority; - case COL_PROGRESS: - return progress(); - case COL_SIZE: - return m_size; - case COL_REMAINING: - return remaining(); - default: - Q_ASSERT(false); - return QVariant(); - } + if (isRootItem()) + return m_itemData.value(column); + + switch (column) { + case COL_NAME: + return m_name; + case COL_PRIO: + return m_priority; + case COL_PROGRESS: + return progress(); + case COL_SIZE: + return m_size; + case COL_REMAINING: + return remaining(); + default: + Q_ASSERT(false); + return QVariant(); + } } int TorrentContentModelItem::row() const { - if (m_parentItem) - return m_parentItem->children().indexOf(const_cast(this)); - return 0; + if (m_parentItem) + return m_parentItem->children().indexOf(const_cast(this)); + return 0; } -TorrentContentModelFolder* TorrentContentModelItem::parent() const +TorrentContentModelFolder *TorrentContentModelItem::parent() const { - return m_parentItem; + return m_parentItem; } diff --git a/src/gui/torrentcontentmodelitem.h b/src/gui/torrentcontentmodelitem.h index a21398f80..f67ec5a44 100644 --- a/src/gui/torrentcontentmodelitem.h +++ b/src/gui/torrentcontentmodelitem.h @@ -34,48 +34,70 @@ #include #include -namespace prio { -enum FilePriority {IGNORED=0, NORMAL=1, HIGH=6, MAXIMUM=7, MIXED=-1}; +namespace prio +{ + enum FilePriority + { + IGNORED=0, + NORMAL=1, + HIGH=6, + MAXIMUM=7, + MIXED=-1 + }; } class TorrentContentModelFolder; -class TorrentContentModelItem { +class TorrentContentModelItem +{ public: - enum TreeItemColumns {COL_NAME, COL_SIZE, COL_PROGRESS, COL_PRIO, COL_REMAINING, NB_COL}; - enum ItemType { FileType, FolderType }; + enum TreeItemColumns + { + COL_NAME, + COL_SIZE, + COL_PROGRESS, + COL_PRIO, + COL_REMAINING, + NB_COL + }; - TorrentContentModelItem(TorrentContentModelFolder* parent); - virtual ~TorrentContentModelItem(); + enum ItemType + { + FileType, + FolderType + }; - inline bool isRootItem() const { return !m_parentItem; } - TorrentContentModelFolder* parent() const; - virtual ItemType itemType() const = 0; + TorrentContentModelItem(TorrentContentModelFolder *parent); + virtual ~TorrentContentModelItem(); - QString name() const; - void setName(const QString& name); + bool isRootItem() const; + TorrentContentModelFolder *parent() const; + virtual ItemType itemType() const = 0; - qulonglong size() const; - qreal progress() const; - qulonglong remaining() const; + QString name() const; + void setName(const QString &name); - int priority() const; - virtual void setPriority(int new_prio, bool update_parent = true) = 0; + qulonglong size() const; + qreal progress() const; + qulonglong remaining() const; - int columnCount() 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: - TorrentContentModelFolder* m_parentItem; - // Root item members - QList m_itemData; - // Non-root item members - QString m_name; - qulonglong m_size; - qulonglong m_remaining; - int m_priority; - qreal m_progress; + TorrentContentModelFolder *m_parentItem; + // Root item members + QList m_itemData; + // Non-root item members + QString m_name; + qulonglong m_size; + qulonglong m_remaining; + int m_priority; + qreal m_progress; }; #endif // TORRENTCONTENTMODELITEM_H From d5af8722a6fd21fcb1119c2ba6a511c80f901114 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Tue, 22 Mar 2016 16:45:54 +0100 Subject: [PATCH 2/4] Add availability column to torrent content model --- src/gui/torrentcontentmodel.cpp | 16 +++++++++++++++ src/gui/torrentcontentmodel.h | 1 + src/gui/torrentcontentmodelfile.cpp | 6 ++++++ src/gui/torrentcontentmodelfile.h | 1 + src/gui/torrentcontentmodelfolder.cpp | 28 +++++++++++++++++++++++++++ src/gui/torrentcontentmodelfolder.h | 1 + src/gui/torrentcontentmodelitem.cpp | 11 +++++++++++ src/gui/torrentcontentmodelitem.h | 4 ++++ 8 files changed, 68 insertions(+) diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp index 528e7a7d1..53a0a4705 100644 --- a/src/gui/torrentcontentmodel.cpp +++ b/src/gui/torrentcontentmodel.cpp @@ -76,6 +76,7 @@ void TorrentContentModel::updateFilesProgress(const QVector &fp) m_filesIndex[i]->setProgress(fp[i]); // Update folders progress in the tree m_rootItem->recalculateProgress(); + m_rootItem->recalculateAvailability(); emit dataChanged(index(0, 0), index(rowCount(), columnCount())); } @@ -92,6 +93,20 @@ void TorrentContentModel::updateFilesPriorities(const QVector &fprio) emit dataChanged(index(0, 0), index(rowCount(), columnCount())); } +void TorrentContentModel::updateFilesAvailability(const QVector &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 TorrentContentModel::getFilePriorities() const { QVector prio; @@ -134,6 +149,7 @@ bool TorrentContentModel::setData(const QModelIndex& index, const QVariant& valu item->setPriority(prio::NORMAL); // Update folders progress in the tree m_rootItem->recalculateProgress(); + m_rootItem->recalculateAvailability(); emit dataChanged(this->index(0, 0), this->index(rowCount() - 1, columnCount() - 1)); emit filteredFilesChanged(); } diff --git a/src/gui/torrentcontentmodel.h b/src/gui/torrentcontentmodel.h index e7c2f8395..8fa9ac565 100644 --- a/src/gui/torrentcontentmodel.h +++ b/src/gui/torrentcontentmodel.h @@ -51,6 +51,7 @@ public: void updateFilesProgress(const QVector &fp); void updateFilesPriorities(const QVector &fprio); + void updateFilesAvailability(const QVector &fa); QVector getFilePriorities() const; bool allFiltered() const; virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; diff --git a/src/gui/torrentcontentmodelfile.cpp b/src/gui/torrentcontentmodelfile.cpp index 20d3c2586..df66cb9fc 100644 --- a/src/gui/torrentcontentmodelfile.cpp +++ b/src/gui/torrentcontentmodelfile.cpp @@ -73,6 +73,12 @@ void TorrentContentModelFile::setProgress(qreal progress) 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; diff --git a/src/gui/torrentcontentmodelfile.h b/src/gui/torrentcontentmodelfile.h index 234908e8d..f6d73e51a 100644 --- a/src/gui/torrentcontentmodelfile.h +++ b/src/gui/torrentcontentmodelfile.h @@ -42,6 +42,7 @@ public: int fileIndex() const; void setPriority(int newPriority, bool updateParent = true) override; void setProgress(qreal progress); + void setAvailability(qreal availability); ItemType itemType() const override; private: diff --git a/src/gui/torrentcontentmodelfolder.cpp b/src/gui/torrentcontentmodelfolder.cpp index ea250876a..09df1e671 100644 --- a/src/gui/torrentcontentmodelfolder.cpp +++ b/src/gui/torrentcontentmodelfolder.cpp @@ -159,6 +159,34 @@ void TorrentContentModelFolder::recalculateProgress() } } +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(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) { if (isRootItem()) diff --git a/src/gui/torrentcontentmodelfolder.h b/src/gui/torrentcontentmodelfolder.h index 5b12ddfb5..e136c9a2e 100644 --- a/src/gui/torrentcontentmodelfolder.h +++ b/src/gui/torrentcontentmodelfolder.h @@ -48,6 +48,7 @@ public: void increaseSize(qulonglong delta); void recalculateProgress(); + void recalculateAvailability(); void updatePriority(); void setPriority(int newPriority, bool updateParent = true) override; diff --git a/src/gui/torrentcontentmodelitem.cpp b/src/gui/torrentcontentmodelitem.cpp index 58765efba..15a1988db 100644 --- a/src/gui/torrentcontentmodelitem.cpp +++ b/src/gui/torrentcontentmodelitem.cpp @@ -40,6 +40,7 @@ TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *pare , m_remaining(0) , m_priority(prio::NORMAL) , m_progress(0) + , m_availability(-1.) { } @@ -84,6 +85,13 @@ qulonglong TorrentContentModelItem::remaining() const return m_remaining; } +qreal TorrentContentModelItem::availability() const +{ + Q_ASSERT(!isRootItem()); + + return m_size > 0 ? m_availability : 0.; +} + int TorrentContentModelItem::priority() const { Q_ASSERT(!isRootItem()); @@ -111,6 +119,8 @@ QVariant TorrentContentModelItem::data(int column) const return m_size; case COL_REMAINING: return remaining(); + case COL_AVAILABILITY: + return availability(); default: Q_ASSERT(false); return QVariant(); @@ -128,3 +138,4 @@ TorrentContentModelFolder *TorrentContentModelItem::parent() const { return m_parentItem; } + diff --git a/src/gui/torrentcontentmodelitem.h b/src/gui/torrentcontentmodelitem.h index f67ec5a44..115dd76c2 100644 --- a/src/gui/torrentcontentmodelitem.h +++ b/src/gui/torrentcontentmodelitem.h @@ -58,6 +58,7 @@ public: COL_PROGRESS, COL_PRIO, COL_REMAINING, + COL_AVAILABILITY, NB_COL }; @@ -81,6 +82,8 @@ public: qreal progress() const; qulonglong remaining() const; + qreal availability() const; + int priority() const; virtual void setPriority(int newPriority, bool updateParent = true) = 0; @@ -98,6 +101,7 @@ protected: qulonglong m_remaining; int m_priority; qreal m_progress; + qreal m_availability; }; #endif // TORRENTCONTENTMODELITEM_H From bc18bf1ab4f4fe11325b7255152261bf782778ed Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Tue, 22 Mar 2016 18:10:12 +0100 Subject: [PATCH 3/4] Add TorrentHandle::availableFileFractions() function The function returns list of availability values for all torrent files. The availability here is different to that one in the progress bar. Here it shows what part of the file's pieces is available (i.e. we do not count availability > 1 for a piece). --- src/base/bittorrent/torrenthandle.cpp | 21 +++++++++++++++++++++ src/base/bittorrent/torrenthandle.h | 8 ++++++++ 2 files changed, 29 insertions(+) diff --git a/src/base/bittorrent/torrenthandle.cpp b/src/base/bittorrent/torrenthandle.cpp index a6436ec34..f9ad2c697 100644 --- a/src/base/bittorrent/torrenthandle.cpp +++ b/src/base/bittorrent/torrenthandle.cpp @@ -1953,3 +1953,24 @@ void TorrentHandle::prioritizeFiles(const QVector &priorities) updateStatus(); } + +QVector TorrentHandle::availableFileFractions() const +{ + QVector piecesAvailability = pieceAvailability(); + const auto filesCount = this->filesCount(); + // libtorrent returns empty array for seeding only torrents + if (piecesAvailability.empty()) return QVector(filesCount, -1.); + + QVector 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(availablePieces) / filePieces.size()); + } + return res; +} diff --git a/src/base/bittorrent/torrenthandle.h b/src/base/bittorrent/torrenthandle.h index 8cdcfe02e..cb0c183cc 100644 --- a/src/base/bittorrent/torrenthandle.h +++ b/src/base/bittorrent/torrenthandle.h @@ -361,6 +361,14 @@ namespace BitTorrent void handleAppendExtensionToggled(); 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 availableFileFractions() const; + private: typedef boost::function EventTrigger; From 5c10a24923f39d1828af2b4b65f4724e8c82cc22 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Tue, 22 Mar 2016 19:41:43 +0100 Subject: [PATCH 4/4] Add availability column to torrent properties window --- src/base/unicodestrings.h | 1 + src/gui/addnewtorrentdialog.cpp | 1 + src/gui/properties/propertieswidget.cpp | 1 + src/gui/properties/proplistdelegate.cpp | 14 ++++++++++++++ src/gui/properties/proplistdelegate.h | 4 +++- src/gui/torrentcontentmodel.cpp | 2 +- 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/base/unicodestrings.h b/src/base/unicodestrings.h index 33e164ddb..88ffe7782 100644 --- a/src/base/unicodestrings.h +++ b/src/base/unicodestrings.h @@ -39,6 +39,7 @@ const char C_NON_BREAKING_SPACE[] = " "; const char C_UP[] = "▲"; const char C_DOWN[] = "▼"; const char C_COPYRIGHT[] = "©"; +const char C_THIN_SPACE[] = " "; const char C_UTP[] = "μTP"; const char C_LOCALE_ENGLISH[] = "English"; const char C_LOCALE_ENGLISH_AUSTRALIA[] = "English(Australia)"; diff --git a/src/gui/addnewtorrentdialog.cpp b/src/gui/addnewtorrentdialog.cpp index 5bbac7bb4..bbdb6901c 100644 --- a/src/gui/addnewtorrentdialog.cpp +++ b/src/gui/addnewtorrentdialog.cpp @@ -737,6 +737,7 @@ void AddNewTorrentDialog::setupTreeview() // Hide useless columns after loading the header state ui->contentTreeView->hideColumn(PROGRESS); ui->contentTreeView->hideColumn(REMAINING); + ui->contentTreeView->hideColumn(AVAILABILITY); // Expand root folder ui->contentTreeView->setExpanded(m_contentModel->index(0, 0), true); diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index 77466c748..5df08d842 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -493,6 +493,7 @@ void PropertiesWidget::loadDynamicData() qDebug("Updating priorities in files tab"); m_ui->filesList->setUpdatesEnabled(false); PropListModel->model()->updateFilesProgress(m_torrent->filesProgress()); + PropListModel->model()->updateFilesAvailability(m_torrent->availableFileFractions()); // XXX: We don't update file priorities regularly for performance // reasons. This means that priorities will not be updated if // set from the Web UI. diff --git a/src/gui/properties/proplistdelegate.cpp b/src/gui/properties/proplistdelegate.cpp index 2c845ba6f..b1b1b3645 100644 --- a/src/gui/properties/proplistdelegate.cpp +++ b/src/gui/properties/proplistdelegate.cpp @@ -42,6 +42,7 @@ #include #endif +#include "base/unicodestrings.h" #include "base/utils/misc.h" #include "base/utils/string.h" #include "propertieswidget.h" @@ -131,6 +132,19 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti QItemDelegate::drawDisplay(painter, opt, option.rect, text); } 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: QItemDelegate::paint(painter, option, index); break; diff --git a/src/gui/properties/proplistdelegate.h b/src/gui/properties/proplistdelegate.h index 2d5e41335..ed9035349 100644 --- a/src/gui/properties/proplistdelegate.h +++ b/src/gui/properties/proplistdelegate.h @@ -46,7 +46,8 @@ enum PropColumn PCSIZE, PROGRESS, PRIORITY, - REMAINING + REMAINING, + AVAILABILITY }; class PropListDelegate: public QItemDelegate @@ -72,3 +73,4 @@ private: }; #endif + diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp index 53a0a4705..ace9868a8 100644 --- a/src/gui/torrentcontentmodel.cpp +++ b/src/gui/torrentcontentmodel.cpp @@ -56,7 +56,7 @@ namespace TorrentContentModel::TorrentContentModel(QObject *parent) : QAbstractItemModel(parent) - , m_rootItem(new TorrentContentModelFolder(QList({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining") }))) + , m_rootItem(new TorrentContentModelFolder(QList({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining"), tr("Availability") }))) { }