From f4742a98c5dc67edd44140785bdb59ed439de5a1 Mon Sep 17 00:00:00 2001 From: FranciscoPombal Date: Mon, 13 Jan 2020 11:41:37 +0000 Subject: [PATCH 1/2] Add stalled filters to GUI and Web API/UI `/api/v2/torrents/info` can now take the following new values for the`filter` parameter: `stalled`, `stalled_uploading` and `stalled_downloading`. Requires Web API version bump. Closes #11787 --- src/base/torrentfilter.cpp | 16 ++++++++++++++ src/base/torrentfilter.h | 6 ++++++ src/gui/transferlistfilterswidget.cpp | 21 +++++++++++++++++++ src/icons/icons.qrc | 1 + src/icons/skin/filterstalled.svg | 3 +++ src/webui/api/torrentscontroller.cpp | 2 +- src/webui/www/private/scripts/client.js | 6 ++++++ src/webui/www/private/scripts/dynamicTable.js | 12 +++++++++++ src/webui/www/private/views/filters.html | 3 +++ 9 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/icons/skin/filterstalled.svg diff --git a/src/base/torrentfilter.cpp b/src/base/torrentfilter.cpp index 9d9242f87..e8fe74498 100644 --- a/src/base/torrentfilter.cpp +++ b/src/base/torrentfilter.cpp @@ -41,6 +41,9 @@ const TorrentFilter TorrentFilter::PausedTorrent(TorrentFilter::Paused); const TorrentFilter TorrentFilter::ResumedTorrent(TorrentFilter::Resumed); const TorrentFilter TorrentFilter::ActiveTorrent(TorrentFilter::Active); const TorrentFilter TorrentFilter::InactiveTorrent(TorrentFilter::Inactive); +const TorrentFilter TorrentFilter::StalledTorrent(TorrentFilter::Stalled); +const TorrentFilter TorrentFilter::StalledUploadingTorrent(TorrentFilter::StalledUploading); +const TorrentFilter TorrentFilter::StalledDownloadingTorrent(TorrentFilter::StalledDownloading); const TorrentFilter TorrentFilter::ErroredTorrent(TorrentFilter::Errored); using BitTorrent::TorrentHandle; @@ -95,6 +98,12 @@ bool TorrentFilter::setTypeByName(const QString &filter) type = Active; else if (filter == "inactive") type = Inactive; + else if (filter == "stalled") + type = Stalled; + else if (filter == "stalled_uploading") + type = StalledUploading; + else if (filter == "stalled_downloading") + type = StalledDownloading; else if (filter == "errored") type = Errored; @@ -163,6 +172,13 @@ bool TorrentFilter::matchState(const BitTorrent::TorrentHandle *const torrent) c return torrent->isActive(); case Inactive: return torrent->isInactive(); + case Stalled: + return (torrent->state() == BitTorrent::TorrentState::StalledUploading) + || (torrent->state() == BitTorrent::TorrentState::StalledDownloading); + case StalledUploading: + return torrent->state() == BitTorrent::TorrentState::StalledUploading; + case StalledDownloading: + return torrent->state() == BitTorrent::TorrentState::StalledDownloading; case Errored: return torrent->isErrored(); default: // All diff --git a/src/base/torrentfilter.h b/src/base/torrentfilter.h index 350e3f7a7..49344cff7 100644 --- a/src/base/torrentfilter.h +++ b/src/base/torrentfilter.h @@ -52,6 +52,9 @@ public: Paused, Active, Inactive, + Stalled, + StalledUploading, + StalledDownloading, Errored }; @@ -67,6 +70,9 @@ public: static const TorrentFilter ResumedTorrent; static const TorrentFilter ActiveTorrent; static const TorrentFilter InactiveTorrent; + static const TorrentFilter StalledTorrent; + static const TorrentFilter StalledUploadingTorrent; + static const TorrentFilter StalledDownloadingTorrent; static const TorrentFilter ErroredTorrent; TorrentFilter(); diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp index bb593a5a2..2966b6478 100644 --- a/src/gui/transferlistfilterswidget.cpp +++ b/src/gui/transferlistfilterswidget.cpp @@ -186,6 +186,15 @@ StatusFilterWidget::StatusFilterWidget(QWidget *parent, TransferListWidget *tran auto *inactive = new QListWidgetItem(this); inactive->setData(Qt::DisplayRole, tr("Inactive (0)")); inactive->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterinactive.svg")); + auto *stalled = new QListWidgetItem(this); + stalled->setData(Qt::DisplayRole, tr("Stalled (0)")); + stalled->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterstalled.svg")); + auto *stalledUploading = new QListWidgetItem(this); + stalledUploading->setData(Qt::DisplayRole, tr("Stalled Uploading (0)")); + stalledUploading->setData(Qt::DecorationRole, QIcon(":/icons/skin/stalledUP.svg")); + auto *stalledDownloading = new QListWidgetItem(this); + stalledDownloading->setData(Qt::DisplayRole, tr("Stalled Downloading (0)")); + stalledDownloading->setData(Qt::DecorationRole, QIcon(":/icons/skin/stalledDL.svg")); auto *errored = new QListWidgetItem(this); errored->setData(Qt::DisplayRole, tr("Errored (0)")); errored->setData(Qt::DecorationRole, QIcon(":/icons/skin/error.svg")); @@ -209,6 +218,9 @@ void StatusFilterWidget::updateTorrentNumbers() int nbPaused = 0; int nbActive = 0; int nbInactive = 0; + int nbStalled = 0; + int nbStalledUploading = 0; + int nbStalledDownloading = 0; int nbErrored = 0; const QHash torrents = BitTorrent::Session::instance()->torrents(); @@ -227,10 +239,16 @@ void StatusFilterWidget::updateTorrentNumbers() ++nbActive; if (torrent->isInactive()) ++nbInactive; + if (torrent->state() == BitTorrent::TorrentState::StalledUploading) + ++nbStalledUploading; + if (torrent->state() == BitTorrent::TorrentState::StalledDownloading) + ++nbStalledDownloading; if (torrent->isErrored()) ++nbErrored; } + nbStalled = nbStalledUploading + nbStalledDownloading; + item(TorrentFilter::All)->setData(Qt::DisplayRole, tr("All (%1)").arg(torrents.count())); item(TorrentFilter::Downloading)->setData(Qt::DisplayRole, tr("Downloading (%1)").arg(nbDownloading)); item(TorrentFilter::Seeding)->setData(Qt::DisplayRole, tr("Seeding (%1)").arg(nbSeeding)); @@ -239,6 +257,9 @@ void StatusFilterWidget::updateTorrentNumbers() item(TorrentFilter::Paused)->setData(Qt::DisplayRole, tr("Paused (%1)").arg(nbPaused)); item(TorrentFilter::Active)->setData(Qt::DisplayRole, tr("Active (%1)").arg(nbActive)); item(TorrentFilter::Inactive)->setData(Qt::DisplayRole, tr("Inactive (%1)").arg(nbInactive)); + item(TorrentFilter::Stalled)->setData(Qt::DisplayRole, tr("Stalled (%1)").arg(nbStalled)); + item(TorrentFilter::StalledUploading)->setData(Qt::DisplayRole, tr("Stalled Uploading (%1)").arg(nbStalledUploading)); + item(TorrentFilter::StalledDownloading)->setData(Qt::DisplayRole, tr("Stalled Downloading (%1)").arg(nbStalledDownloading)); item(TorrentFilter::Errored)->setData(Qt::DisplayRole, tr("Errored (%1)").arg(nbErrored)); } diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index fd9291a9c..341d1f5d8 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -349,6 +349,7 @@ skin/filteractive.svg skin/filterall.svg skin/filterinactive.svg + skin/filterstalled.svg skin/firewalled.svg skin/handle-icon-horizontal.gif skin/handle-icon.gif diff --git a/src/icons/skin/filterstalled.svg b/src/icons/skin/filterstalled.svg new file mode 100644 index 000000000..a15a2f842 --- /dev/null +++ b/src/icons/skin/filterstalled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index c21a1ecca..e3684e124 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -231,7 +231,7 @@ namespace // - "force_start": Torrent force start state // - "category": Torrent category // GET params: -// - filter (string): all, downloading, seeding, completed, paused, resumed, active, inactive +// - filter (string): all, downloading, seeding, completed, paused, resumed, active, inactive, stalled, stalled_uploading, stalled_downloading // - category (string): torrent category for filtering by it (empty string means "uncategorized"; no "category" param presented means "any category") // - hashes (string): filter by hashes, can contain multiple hashes separated by | // - sort (string): name of column for sorting by its value diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index 174713fbd..9c01f233e 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -184,6 +184,9 @@ window.addEvent('load', function() { $("resumed_filter").removeClass("selectedFilter"); $("active_filter").removeClass("selectedFilter"); $("inactive_filter").removeClass("selectedFilter"); + $("stalled_filter").removeClass("selectedFilter"); + $("stalled_uploading_filter").removeClass("selectedFilter"); + $("stalled_downloading_filter").removeClass("selectedFilter"); $("errored_filter").removeClass("selectedFilter"); $(f + "_filter").addClass("selectedFilter"); selected_filter = f; @@ -344,6 +347,9 @@ window.addEvent('load', function() { updateFilter('paused', 'QBT_TR(Paused (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); updateFilter('active', 'QBT_TR(Active (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); updateFilter('inactive', 'QBT_TR(Inactive (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); + updateFilter('stalled', 'QBT_TR(Stalled (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); + updateFilter('stalled_uploading', 'QBT_TR(Stalled Uploading (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); + updateFilter('stalled_downloading', 'QBT_TR(Stalled Downloading (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); updateFilter('errored', 'QBT_TR(Errored (%1))QBT_TR[CONTEXT=StatusFilterWidget]'); }; diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index bb673e0e6..99914def4 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -1225,6 +1225,18 @@ window.qBittorrent.DynamicTable = (function() { if (~state.indexOf('paused')) return false; break; + case 'stalled': + if ((state != 'stalledUP') && (state != 'stalledDL')) + return false; + break; + case 'stalled_uploading': + if (state != 'stalledUP') + return false; + break; + case 'stalled_downloading': + if (state != 'stalledDL') + return false; + break; case 'inactive': inactive = true; // fallthrough diff --git a/src/webui/www/private/views/filters.html b/src/webui/www/private/views/filters.html index 34f234397..86cc858ed 100644 --- a/src/webui/www/private/views/filters.html +++ b/src/webui/www/private/views/filters.html @@ -11,6 +11,9 @@
  • PausedQBT_TR(Paused (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • ActiveQBT_TR(Active (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • InactiveQBT_TR(Inactive (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • +
  • StalledQBT_TR(Stalled (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • +
  • Stalled UploadingQBT_TR(Stalled Uploading (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • +
  • Stalled DownloadingQBT_TR(Stalled Downloading (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • ErroredQBT_TR(Errored (0))QBT_TR[CONTEXT=StatusFilterWidget]
  • From df2fbb1edcbb072e85944cedab3bc15453f308e2 Mon Sep 17 00:00:00 2001 From: FranciscoPombal Date: Mon, 13 Jan 2020 11:41:59 +0000 Subject: [PATCH 2/2] Bump Web API version --- src/webui/webapplication.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index cc716cb43..7bdf14f47 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -43,7 +43,7 @@ #include "base/utils/net.h" #include "base/utils/version.h" -constexpr Utils::Version API_VERSION {2, 4, 0}; +constexpr Utils::Version API_VERSION {2, 4, 1}; class APIController; class WebApplication;