From 02f19bfbee1a1529a8dae5106f98c909d82c1932 Mon Sep 17 00:00:00 2001 From: jagannatharjun Date: Sat, 24 Oct 2020 12:57:46 +0530 Subject: [PATCH] Use ProgressbarDelegate for drawing progressbar in PropListDelegate Also directly provide display data from model rather then generating it in delegate --- src/gui/properties/proplistdelegate.cpp | 109 ++++-------------------- src/gui/properties/proplistdelegate.h | 7 +- src/gui/torrentcontentfiltermodel.cpp | 2 +- src/gui/torrentcontentmodel.cpp | 43 ++++++---- src/gui/torrentcontentmodel.h | 5 ++ src/gui/torrentcontentmodelfolder.cpp | 2 +- src/gui/torrentcontentmodelfolder.h | 2 +- src/gui/torrentcontentmodelitem.cpp | 55 +++++++++++- src/gui/torrentcontentmodelitem.h | 8 +- 9 files changed, 113 insertions(+), 120 deletions(-) diff --git a/src/gui/properties/proplistdelegate.cpp b/src/gui/properties/proplistdelegate.cpp index bfb7bf0fa..b3382ade6 100644 --- a/src/gui/properties/proplistdelegate.cpp +++ b/src/gui/properties/proplistdelegate.cpp @@ -42,9 +42,7 @@ #include "base/bittorrent/downloadpriority.h" #include "base/bittorrent/torrenthandle.h" -#include "base/unicodestrings.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" +#include "gui/torrentcontentmodel.h" #include "propertieswidget.h" namespace @@ -64,107 +62,31 @@ namespace } PropListDelegate::PropListDelegate(PropertiesWidget *properties) - : QStyledItemDelegate(properties) + : ProgressBarDelegate {PROGRESS, TorrentContentModel::UnderlyingDataRole, properties} , m_properties(properties) { } -void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +void PropListDelegate::initProgressStyleOption(QStyleOptionProgressBar &option, const QModelIndex &index) const { - painter->save(); - - const QStyle *style = option.widget ? option.widget->style() : QApplication::style(); - QStyleOptionViewItem opt = option; - QStyledItemDelegate::initStyleOption(&opt, index); - - switch (index.column()) { - case PCSIZE: - case REMAINING: - opt.text = Utils::Misc::friendlyUnit(index.data().toLongLong()); - style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); - break; - - case PROGRESS: { - const qreal progress = (index.data().toReal() * 100); - if (progress < 0) - break; - - QStyleOptionProgressBar newopt; - newopt.rect = opt.rect; - newopt.text = (progress == 100) ? QString("100%") : (Utils::String::fromDouble(progress, 1) + '%'); - newopt.progress = static_cast(progress); - newopt.maximum = 100; - newopt.minimum = 0; - newopt.textVisible = true; - if (index.sibling(index.row(), PRIORITY).data().toInt() == static_cast(BitTorrent::DownloadPriority::Ignored)) { - newopt.state &= ~QStyle::State_Enabled; - newopt.palette = progressBarDisabledPalette(); - } - else { - newopt.state |= QStyle::State_Enabled; - } - -#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) - // XXX: To avoid having the progress text on the right of the bar - QProxyStyle("fusion").drawControl(QStyle::CE_ProgressBar, &newopt, painter, 0); -#else - QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter); -#endif - } - break; - - case PRIORITY: { - QString text = ""; - switch (static_cast(index.data().toInt())) { - case BitTorrent::DownloadPriority::Mixed: - text = tr("Mixed", "Mixed (priorities"); - break; - case BitTorrent::DownloadPriority::Ignored: - text = tr("Not downloaded"); - break; - case BitTorrent::DownloadPriority::High: - text = tr("High", "High (priority)"); - break; - case BitTorrent::DownloadPriority::Maximum: - text = tr("Maximum", "Maximum (priority)"); - break; - default: - text = tr("Normal", "Normal (priority)"); - break; - } - opt.text = text; - style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); - } - break; - - case AVAILABILITY: { - const qreal availability = index.data().toReal(); - if (availability < 0) { - opt.text = tr("N/A"); - } - else { - const QString value = (availability >= 1.0) - ? QLatin1String("100") - : Utils::String::fromDouble(availability * 100, 1); - opt.text = (value + C_THIN_SPACE + QLatin1Char('%')); - } - style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); - } - break; - - default: - QStyledItemDelegate::paint(painter, option, index); - break; + ProgressBarDelegate::initProgressStyleOption(option, index); + const int priority + = index.sibling(index.row(), PRIORITY).data(TorrentContentModel::UnderlyingDataRole).toInt(); + if (static_cast(priority) == BitTorrent::DownloadPriority::Ignored) { + option.state &= ~QStyle::State_Enabled; + option.palette = progressBarDisabledPalette(); + } + else { + option.state |= QStyle::State_Enabled; } - - painter->restore(); } void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { auto *combobox = static_cast(editor); // Set combobox index - switch (static_cast(index.data().toInt())) { + const int priority = index.data(TorrentContentModel::UnderlyingDataRole).toInt(); + switch (static_cast(priority)) { case BitTorrent::DownloadPriority::Ignored: combobox->setCurrentIndex(0); break; @@ -190,7 +112,8 @@ QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewI return nullptr; } - if (index.data().toInt() == static_cast(BitTorrent::DownloadPriority::Mixed)) + const int priority = index.data(TorrentContentModel::UnderlyingDataRole).toInt(); + if (static_cast(priority) == BitTorrent::DownloadPriority::Mixed) return nullptr; auto *editor = new QComboBox(parent); diff --git a/src/gui/properties/proplistdelegate.h b/src/gui/properties/proplistdelegate.h index 4af03b0e6..563c77bc5 100644 --- a/src/gui/properties/proplistdelegate.h +++ b/src/gui/properties/proplistdelegate.h @@ -29,7 +29,7 @@ #ifndef PROPLISTDELEGATE_H #define PROPLISTDELEGATE_H -#include +#include "gui/progressbardelegate.h" class QAbstractItemModel; class QModelIndex; @@ -49,14 +49,13 @@ enum PropColumn AVAILABILITY }; -class PropListDelegate final : public QStyledItemDelegate +class PropListDelegate final : public ProgressBarDelegate { Q_OBJECT public: explicit PropListDelegate(PropertiesWidget *properties); - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */, const QModelIndex &index) const override; @@ -68,6 +67,8 @@ signals: void filteredFilesChanged() const; private: + void initProgressStyleOption(QStyleOptionProgressBar &option, const QModelIndex &index) const override; + PropertiesWidget *m_properties; }; diff --git a/src/gui/torrentcontentfiltermodel.cpp b/src/gui/torrentcontentfiltermodel.cpp index 8f91b0711..f28b3a1fa 100644 --- a/src/gui/torrentcontentfiltermodel.cpp +++ b/src/gui/torrentcontentfiltermodel.cpp @@ -39,7 +39,7 @@ TorrentContentFilterModel::TorrentContentFilterModel(QObject *parent) setSourceModel(m_model); // Filter settings setFilterKeyColumn(TorrentContentModelItem::COL_NAME); - setFilterRole(Qt::DisplayRole); + setFilterRole(TorrentContentModel::UnderlyingDataRole); setDynamicSortFilter(true); setSortCaseSensitivity(Qt::CaseInsensitive); } diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp index 7462f44ab..a71013a7f 100644 --- a/src/gui/torrentcontentmodel.cpp +++ b/src/gui/torrentcontentmodel.cpp @@ -180,7 +180,7 @@ namespace TorrentContentModel::TorrentContentModel(QObject *parent) : QAbstractItemModel(parent) - , m_rootItem(new TorrentContentModelFolder(QVector({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining"), tr("Availability") }))) + , m_rootItem(new TorrentContentModelFolder(QVector({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining"), tr("Availability") }))) { #if defined(Q_OS_WIN) m_fileIconProvider = new WinShellFileIconProvider(); @@ -332,25 +332,34 @@ QVariant TorrentContentModel::data(const QModelIndex &index, int role) const auto *item = static_cast(index.internalPointer()); - if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::DecorationRole)) { - if (item->itemType() == TorrentContentModelItem::FolderType) - return m_fileIconProvider->icon(QFileIconProvider::Folder); + switch (role) { + case Qt::DecorationRole: { + if (index.column() != TorrentContentModelItem::COL_NAME) + return {}; - return m_fileIconProvider->icon(QFileInfo(item->name())); - } + if (item->itemType() == TorrentContentModelItem::FolderType) + return m_fileIconProvider->icon(QFileIconProvider::Folder); + return m_fileIconProvider->icon(QFileInfo(item->name())); + } + case Qt::CheckStateRole: { + if (index.column() != TorrentContentModelItem::COL_NAME) + return {}; - if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) { - if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast(BitTorrent::DownloadPriority::Ignored)) - return Qt::Unchecked; - if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast(BitTorrent::DownloadPriority::Mixed)) - return Qt::PartiallyChecked; - return Qt::Checked; - } + if (item->priority() == BitTorrent::DownloadPriority::Ignored) + return Qt::Unchecked; + if (item->priority() == BitTorrent::DownloadPriority::Mixed) + return Qt::PartiallyChecked; + return Qt::Checked; + } + case Qt::DisplayRole: + return item->displayData(index.column()); - if (role == Qt::DisplayRole) - return item->data(index.column()); + case Roles::UnderlyingDataRole: + return item->underlyingData(index.column()); - return {}; + default: + return {}; + } } Qt::ItemFlags TorrentContentModel::flags(const QModelIndex &index) const @@ -367,7 +376,7 @@ Qt::ItemFlags TorrentContentModel::flags(const QModelIndex &index) const QVariant TorrentContentModel::headerData(int section, Qt::Orientation orientation, int role) const { if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) - return m_rootItem->data(section); + return m_rootItem->displayData(section); return {}; } diff --git a/src/gui/torrentcontentmodel.h b/src/gui/torrentcontentmodel.h index 779f82a4e..90bf9ba8c 100644 --- a/src/gui/torrentcontentmodel.h +++ b/src/gui/torrentcontentmodel.h @@ -51,6 +51,11 @@ class TorrentContentModel final : public QAbstractItemModel Q_DISABLE_COPY(TorrentContentModel) public: + enum Roles + { + UnderlyingDataRole = Qt::UserRole + }; + TorrentContentModel(QObject *parent = nullptr); ~TorrentContentModel() override; diff --git a/src/gui/torrentcontentmodelfolder.cpp b/src/gui/torrentcontentmodelfolder.cpp index 5e0627a43..d20fa86d8 100644 --- a/src/gui/torrentcontentmodelfolder.cpp +++ b/src/gui/torrentcontentmodelfolder.cpp @@ -43,7 +43,7 @@ TorrentContentModelFolder::TorrentContentModelFolder(const QString &name, Torren m_name.chop(4); } -TorrentContentModelFolder::TorrentContentModelFolder(const QVector &data) +TorrentContentModelFolder::TorrentContentModelFolder(const QVector &data) : TorrentContentModelItem(nullptr) { Q_ASSERT(data.size() == NB_COL); diff --git a/src/gui/torrentcontentmodelfolder.h b/src/gui/torrentcontentmodelfolder.h index a99f89999..3654c21fd 100644 --- a/src/gui/torrentcontentmodelfolder.h +++ b/src/gui/torrentcontentmodelfolder.h @@ -43,7 +43,7 @@ public: TorrentContentModelFolder(const QString &name, TorrentContentModelFolder *parent); // Invisible root item constructor - explicit TorrentContentModelFolder(const QVector &data); + explicit TorrentContentModelFolder(const QVector &data); ~TorrentContentModelFolder() override; diff --git a/src/gui/torrentcontentmodelitem.cpp b/src/gui/torrentcontentmodelitem.cpp index 48a8828aa..ba5216f8e 100644 --- a/src/gui/torrentcontentmodelitem.cpp +++ b/src/gui/torrentcontentmodelitem.cpp @@ -30,6 +30,9 @@ #include +#include "base/unicodestrings.h" +#include "base/utils/misc.h" +#include "base/utils/string.h" #include "torrentcontentmodelfolder.h" TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *parent) @@ -99,7 +102,55 @@ int TorrentContentModelItem::columnCount() const return NB_COL; } -QVariant TorrentContentModelItem::data(int column) const +QString TorrentContentModelItem::displayData(const int column) const +{ + if (isRootItem()) + return m_itemData.value(column); + + switch (column) { + case COL_NAME: + return m_name; + case COL_PRIO: { + switch (m_priority) { + case BitTorrent::DownloadPriority::Mixed: + return tr("Mixed", "Mixed (priorities"); + case BitTorrent::DownloadPriority::Ignored: + return tr("Not downloaded"); + case BitTorrent::DownloadPriority::High: + return tr("High", "High (priority)"); + case BitTorrent::DownloadPriority::Maximum: + return tr("Maximum", "Maximum (priority)"); + default: + return tr("Normal", "Normal (priority)"); + } + } + case COL_PROGRESS: { + const qreal progress = m_progress * 100; + return (static_cast(progress) == 100) + ? QString::fromLatin1("100%") + : (Utils::String::fromDouble(progress, 1) + QLatin1Char('%')); + } + case COL_SIZE: + return Utils::Misc::friendlyUnit(m_size); + case COL_REMAINING: + return Utils::Misc::friendlyUnit(remaining()); + case COL_AVAILABILITY: { + const int avail = availability(); + if (avail < 0) + return tr("N/A"); + + const QString value = (avail >= 1.0) + ? QString::fromLatin1("100") + : Utils::String::fromDouble((avail * 100), 1); + return QString {value + C_THIN_SPACE + QLatin1Char('%')}; + } + default: + Q_ASSERT(false); + return {}; + } +} + +QVariant TorrentContentModelItem::underlyingData(const int column) const { if (isRootItem()) return m_itemData.value(column); @@ -110,7 +161,7 @@ QVariant TorrentContentModelItem::data(int column) const case COL_PRIO: return static_cast(m_priority); case COL_PROGRESS: - return progress(); + return progress() * 100; case COL_SIZE: return m_size; case COL_REMAINING: diff --git a/src/gui/torrentcontentmodelitem.h b/src/gui/torrentcontentmodelitem.h index c0a532ce2..077f1b790 100644 --- a/src/gui/torrentcontentmodelitem.h +++ b/src/gui/torrentcontentmodelitem.h @@ -29,6 +29,7 @@ #ifndef TORRENTCONTENTMODELITEM_H #define TORRENTCONTENTMODELITEM_H +#include #include #include "base/bittorrent/downloadpriority.h" @@ -39,6 +40,8 @@ class TorrentContentModelFolder; class TorrentContentModelItem { + Q_DECLARE_TR_FUNCTIONS(TorrentContentModelItem); + public: enum TreeItemColumns { @@ -77,13 +80,14 @@ public: virtual void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) = 0; int columnCount() const; - QVariant data(int column) const; + QString displayData(int column) const; + QVariant underlyingData(int column) const; int row() const; protected: TorrentContentModelFolder *m_parentItem; // Root item members - QVector m_itemData; + QVector m_itemData; // Non-root item members QString m_name; qulonglong m_size;