transmission/qt/TorrentFilter.cc

267 lines
6.2 KiB
C++
Raw Normal View History

// This file Copyright © Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
2009-04-09 18:55:47 +00:00
2022-07-26 02:45:54 +00:00
#include <array>
#include <optional>
2009-04-09 18:55:47 +00:00
2023-07-16 02:55:44 +00:00
#include "libtransmission/utils.h"
#include "Filters.h"
#include "Prefs.h"
#include "Torrent.h"
#include "TorrentFilter.h"
#include "TorrentModel.h"
#include "Utils.h"
2009-04-09 18:55:47 +00:00
TorrentFilter::TorrentFilter(Prefs const& prefs)
: prefs_{ prefs }
2009-04-09 18:55:47 +00:00
{
connect(&prefs_, &Prefs::changed, this, &TorrentFilter::onPrefChanged);
connect(&refilter_timer_, &QTimer::timeout, this, &TorrentFilter::refilter);
setDynamicSortFilter(true);
refilter();
2009-04-09 18:55:47 +00:00
}
/***
****
***/
void TorrentFilter::onPrefChanged(int key)
2009-04-09 18:55:47 +00:00
{
// For refiltering nearly immediately. Used to debounce batched prefs changes.
static int const FastMSec = 50;
// For waiting a little longer. Useful when user is typing the filter text.
static int const SlowMSec = 500;
std::optional<int> msec;
switch (key)
2009-04-09 18:55:47 +00:00
{
case Prefs::FILTER_TEXT:
// special case for isEmpty: user probably hit the 'clear' button
msec = prefs_.getString(key).isEmpty() ? FastMSec : SlowMSec;
break;
case Prefs::FILTER_MODE:
case Prefs::FILTER_TRACKERS:
case Prefs::SORT_MODE:
case Prefs::SORT_REVERSED:
msec = FastMSec;
2013-09-14 22:45:04 +00:00
break;
fix: more clang-tidy warnings (#6608) * fix: readability-redundant-casting warnings in gtk * fix: bugprone-move-forwarding-reference warnings in gtk * fix: readability-redundant-casting warnings in qt * fix: bugprone-switch-missing-default-case warnings in qt * fix: readability-use-std-min-max warning in qt client * fix: readability-static-accessed-through-instance warning in qt client * fix: cppcoreguidelines-avoid-const-or-ref-data-members warning in qt client * fix: readability-avoid-nested-conditional-operator warning in qt client * fixup! fix: readability-use-std-min-max warning in qt client * fix: readability-redundant-member-init warnings in gtk client * fix: performance-avoid-endl warnings in gtk client * chore: disable readability-qualified-auto too many false warnings * chore: disable cppcoreguidelines-avoid-const-or-ref-data-members * chore: fix readability-duplicate-include warning in gtk client * chore: fix modernize-use-nodiscard warning in gtk client * chore: fix readability-convert-member-functions-to-static warning in gtk client * fixup! fix: bugprone-move-forwarding-reference warnings in gtk * chore: fix performance-enum-size warning in gtk client * fix: cppcoreguidelines-prefer-member-initializer warning in gtk client * fix: readability-identifier-naming warning in qt client * Revert "chore: fix performance-enum-size warning in gtk client" This reverts commit 5ce6b562f849c2499fa34f4d903234f1945f9c3e. * fix: readability-redundant-member-init warning in move tests * fix: readability-redundant-casting warnings in tests * fixup! fix: readability-identifier-naming warning in qt client * fixup! fix: readability-avoid-nested-conditional-operator warning in qt client * fix: readability-static-accessed-through-instance warning in qt client * fix: readability-redundant-casting warning in watchdir tests
2024-02-17 19:31:49 +00:00
default:
break;
2009-04-09 18:55:47 +00:00
}
// if this pref change affects filtering, ensure that a refilter is queued
if (msec && !refilter_timer_.isActive())
{
refilter_timer_.setSingleShot(true);
refilter_timer_.start(*msec);
}
}
void TorrentFilter::refilter()
{
invalidate();
sort(0, prefs_.getBool(Prefs::SORT_REVERSED) ? Qt::AscendingOrder : Qt::DescendingOrder);
2009-04-09 18:55:47 +00:00
}
/***
****
***/
bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right) const
2009-04-09 18:55:47 +00:00
{
int val = 0;
auto const* a = sourceModel()->data(left, TorrentModel::TorrentRole).value<Torrent const*>();
auto const* b = sourceModel()->data(right, TorrentModel::TorrentRole).value<Torrent const*>();
2009-04-09 18:55:47 +00:00
switch (prefs_.get<SortMode>(Prefs::SORT_MODE).mode())
2009-04-09 18:55:47 +00:00
{
case SortMode::SORT_BY_QUEUE:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = -tr_compare_3way(a->queuePosition(), b->queuePosition());
}
2013-09-14 22:45:04 +00:00
break;
case SortMode::SORT_BY_SIZE:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->sizeWhenDone(), b->sizeWhenDone());
}
2013-09-14 22:45:04 +00:00
break;
case SortMode::SORT_BY_AGE:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->dateAdded(), b->dateAdded());
}
2013-09-14 22:45:04 +00:00
break;
case SortMode::SORT_BY_ID:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->id(), b->id());
}
2013-09-14 22:45:04 +00:00
break;
case SortMode::SORT_BY_ACTIVITY:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->downloadSpeed() + a->uploadSpeed(), b->downloadSpeed() + b->uploadSpeed());
}
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(
a->peersWeAreUploadingTo() + a->webseedsWeAreDownloadingFrom(),
b->peersWeAreUploadingTo() + b->webseedsWeAreDownloadingFrom());
}
2013-09-14 22:45:04 +00:00
[[fallthrough]];
case SortMode::SORT_BY_STATE:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = -tr_compare_3way(a->isPaused(), b->isPaused());
}
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->getActivity(), b->getActivity());
}
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = -tr_compare_3way(a->queuePosition(), b->queuePosition());
}
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->hasError(), b->hasError());
}
[[fallthrough]];
2013-09-14 22:45:04 +00:00
case SortMode::SORT_BY_PROGRESS:
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->metadataPercentDone(), b->metadataPercentDone());
}
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->percentComplete(), b->percentComplete());
}
if (val == 0)
{
val = a->compareSeedProgress(*b);
}
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = -tr_compare_3way(a->queuePosition(), b->queuePosition());
}
2013-09-14 22:45:04 +00:00
[[fallthrough]];
case SortMode::SORT_BY_RATIO:
if (val == 0)
{
val = a->compareRatio(*b);
}
2013-09-14 22:45:04 +00:00
break;
case SortMode::SORT_BY_ETA:
if (val == 0)
{
val = a->compareETA(*b);
}
2013-09-14 22:45:04 +00:00
break;
default:
2013-09-14 22:45:04 +00:00
break;
2009-04-09 18:55:47 +00:00
}
2013-09-14 22:45:04 +00:00
if (val == 0)
{
val = -a->name().compare(b->name(), Qt::CaseInsensitive);
}
2013-09-14 22:45:04 +00:00
if (val == 0)
{
2023-07-16 02:55:44 +00:00
val = tr_compare_3way(a->hash(), b->hash());
}
2013-09-14 22:45:04 +00:00
return val < 0;
2009-04-09 18:55:47 +00:00
}
/***
****
***/
bool TorrentFilter::filterAcceptsRow(int source_row, QModelIndex const& source_parent) const
2010-07-30 22:24:48 +00:00
{
QModelIndex const child_index = sourceModel()->index(source_row, 0, source_parent);
auto const& tor = *child_index.model()->data(child_index, TorrentModel::TorrentRole).value<Torrent const*>();
bool accepts = true;
2010-07-30 22:24:48 +00:00
if (accepts)
2013-09-14 22:45:04 +00:00
{
auto const m = prefs_.get<FilterMode>(Prefs::FILTER_MODE);
accepts = m.test(tor);
2010-07-30 22:24:48 +00:00
}
if (accepts)
2013-09-14 22:45:04 +00:00
{
auto const display_name = prefs_.getString(Prefs::FILTER_TRACKERS);
accepts = display_name.isEmpty() || tor.includesTracker(display_name.toLower());
}
if (accepts)
2013-09-14 22:45:04 +00:00
{
auto const text = prefs_.getString(Prefs::FILTER_TEXT);
accepts = text.isEmpty() || tor.name().contains(text, Qt::CaseInsensitive) ||
tor.hash().toString().contains(text, Qt::CaseInsensitive);
2010-07-30 22:24:48 +00:00
}
return accepts;
}
std::array<int, FilterMode::NUM_MODES> TorrentFilter::countTorrentsPerMode() const
2010-07-30 22:24:48 +00:00
{
auto* const torrent_model = dynamic_cast<TorrentModel*>(sourceModel());
if (torrent_model == nullptr)
{
return {};
}
auto torrent_counts = std::array<int, FilterMode::NUM_MODES>{};
for (auto const& tor : torrent_model->torrents())
{
for (int mode = 0; mode < FilterMode::NUM_MODES; ++mode)
{
if (FilterMode::test(*tor, mode))
{
++torrent_counts[mode];
}
}
2010-07-30 22:24:48 +00:00
}
return torrent_counts;
2010-07-30 22:24:48 +00:00
}