Refactor sorting and filtering compatibility code (GTK client) (#4558)

* Refactor sorting and filtering compatibility code

Factor out parts of `TorrentFilter` and `TorrentSorter` classes into
reusable `FilterBase<>` and `SorterBase<>` templates.

Factor out filter and sort models setup from `FilterBar` and `Session`
classes into reusable `FilterListModel<>` and `SortListModel<>`
templates.

* Remove unused lambda capture (Clang build failure)
This commit is contained in:
Mike Gelfand
2023-01-08 18:31:03 +03:00
committed by GitHub
parent d9278bd167
commit fa091495d6
15 changed files with 532 additions and 190 deletions

View File

@@ -18,6 +18,10 @@ target_sources(${TR_NAME}-gtk
FileList.h
FilterBar.cc
FilterBar.h
FilterBase.h
FilterBase.hh
FilterListModel.h
FilterListModel.hh
Flags.h
FreeSpaceLabel.cc
FreeSpaceLabel.h
@@ -48,6 +52,10 @@ target_sources(${TR_NAME}-gtk
RelocateDialog.h
Session.cc
Session.h
SorterBase.h
SorterBase.hh
SortListModel.h
SortListModel.hh
StatsDialog.cc
StatsDialog.h
SystemTrayIcon.cc

View File

@@ -1,4 +1,4 @@
// This file Copyright © 2012-2022 Mnemosyne LLC.
// This file Copyright © 2012-2023 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.
@@ -6,6 +6,7 @@
#include "FilterBar.h"
#include "FaviconCache.h" // gtr_get_favicon()
#include "FilterListModel.hh"
#include "HigWorkarea.h" // GUI_PAD
#include "ListModelAdapter.h"
#include "Session.h" // torrent_cols
@@ -110,11 +111,9 @@ private:
Gtk::Entry* entry_ = nullptr;
Gtk::Label* show_lb_ = nullptr;
Glib::RefPtr<TorrentFilter> filter_ = TorrentFilter::create();
Glib::RefPtr<FilterModel> filter_model_;
Glib::RefPtr<FilterListModel<Torrent>> filter_model_;
#if GTKMM_CHECK_VERSION(4, 0, 0)
sigc::connection filter_model_items_changed_tag_;
#endif
sigc::connection update_count_label_tag_;
sigc::connection update_filter_models_tag_;
sigc::connection update_filter_models_on_add_remove_tag_;
@@ -567,7 +566,7 @@ void FilterBar::Impl::update_filter_tracker()
bool FilterBar::Impl::update_count_label()
{
/* get the visible count */
auto const visibleCount = static_cast<int>(filter_model_->IF_GTKMM4(get_n_items(), children().size()));
auto const visibleCount = static_cast<int>(filter_model_->get_n_items());
/* get the tracker count */
int trackerCount = 0;
@@ -701,22 +700,9 @@ FilterBar::Impl::Impl(FilterBar& widget, Glib::RefPtr<Session> const& core)
activity_combo_box_init(*activity_);
tracker_combo_box_init(*tracker_);
#if GTKMM_CHECK_VERSION(4, 0, 0)
filter_model_ = Gtk::FilterListModel::create(core_->get_sorted_model(), filter_);
filter_model_ = FilterListModel<Torrent>::create(core_->get_sorted_model(), filter_);
filter_model_items_changed_tag_ = filter_model_->signal_items_changed().connect(
[this](guint /*position*/, guint /*removed*/, guint /*added*/) { update_count_label_idle(); });
#else
static auto const& self_col = Torrent::get_columns().self;
auto const filter_func = [this](FilterModel::const_iterator const& iter)
{
return filter_->match(*iter->get_value(self_col));
};
filter_model_ = Gtk::TreeModelFilter::create(core_->get_sorted_model());
filter_model_->set_visible_func(filter_func);
filter_->signal_changed().connect([this]() { filter_model_->refilter(); });
#endif
tracker_->signal_changed().connect(sigc::mem_fun(*this, &Impl::update_filter_tracker));
activity_->signal_changed().connect(sigc::mem_fun(*this, &Impl::update_filter_activity));
@@ -735,9 +721,7 @@ FilterBar::Impl::~Impl()
update_filter_models_on_add_remove_tag_.disconnect();
update_filter_models_tag_.disconnect();
update_count_label_tag_.disconnect();
#if GTKMM_CHECK_VERSION(4, 0, 0)
filter_model_items_changed_tag_.disconnect();
#endif
}
Glib::RefPtr<FilterBar::Model> FilterBar::get_filter_model() const

53
gtk/FilterBase.h Normal file
View File

@@ -0,0 +1,53 @@
// This file Copyright © 2022-2023 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.
#pragma once
#include "GtkCompat.h"
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include <gtkmm/filter.h>
#else
#include <glibmm/object.h>
#endif
template<typename T>
class FilterBase : public IF_GTKMM4(Gtk::Filter, Glib::Object)
{
public:
#if !GTKMM_CHECK_VERSION(4, 0, 0)
enum class Change{
DIFFERENT,
LESS_STRICT,
MORE_STRICT,
};
#endif
public:
~FilterBase() override = default;
virtual bool match(T const& item) const = 0;
virtual bool matches_all() const;
virtual bool matches_none() const;
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void(Change)>& signal_changed();
#endif
protected:
#if GTKMM_CHECK_VERSION(4, 0, 0)
// Gtk::Filter
bool match_vfunc(Glib::RefPtr<Glib::ObjectBase> const& object) override;
Match get_strictness_vfunc() override;
#else
void changed(Change change);
#endif
private:
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void(Change)> signal_changed_;
#endif
};

67
gtk/FilterBase.hh Normal file
View File

@@ -0,0 +1,67 @@
// This file Copyright © 2022-2023 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.
#pragma once
#include "FilterBase.h"
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include "Utils.h"
#endif
template<typename T>
bool FilterBase<T>::matches_all() const
{
return false;
}
template<typename T>
bool FilterBase<T>::matches_none() const
{
return false;
}
#if GTKMM_CHECK_VERSION(4, 0, 0)
template<typename T>
bool FilterBase<T>::match_vfunc(Glib::RefPtr<Glib::ObjectBase> const& object)
{
auto const concrete_object = gtr_ptr_dynamic_cast<T>(object);
g_return_val_if_fail(concrete_object != nullptr, false);
return match(*concrete_object);
}
template<typename T>
typename FilterBase<T>::Match FilterBase<T>::get_strictness_vfunc()
{
if (matches_all())
{
return Match::ALL;
}
if (matches_none())
{
return Match::NONE;
}
return Match::SOME;
}
#else
template<typename T>
sigc::signal<void(typename FilterBase<T>::Change)>& FilterBase<T>::signal_changed()
{
return signal_changed_;
}
template<typename T>
void FilterBase<T>::changed(Change change)
{
signal_changed_.emit(change);
}
#endif

54
gtk/FilterListModel.h Normal file
View File

@@ -0,0 +1,54 @@
// This file Copyright © 2023 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.
#pragma once
#include "GtkCompat.h"
#include <giomm/listmodel.h>
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include <gtkmm/filterlistmodel.h>
#else
#include <gtkmm/treemodel.h>
#include <gtkmm/treemodelfilter.h>
#endif
template<typename ItemT>
class FilterBase;
template<typename ItemT>
class FilterListModel : public IF_GTKMM4(Gtk::FilterListModel, Gtk::TreeModelFilter)
{
public:
using FilterType = FilterBase<ItemT>;
public:
FilterListModel(Glib::RefPtr<Gio::ListModel> const& model, Glib::RefPtr<FilterType> const& filter);
#if !GTKMM_CHECK_VERSION(4, 0, 0)
FilterListModel(Glib::RefPtr<Gtk::TreeModel> const& model, Glib::RefPtr<FilterType> const& filter);
~FilterListModel() override;
guint get_n_items() const;
sigc::signal<void(guint, guint, guint)>& signal_items_changed();
#endif
template<typename ModelT>
static Glib::RefPtr<FilterListModel<ItemT>> create(
Glib::RefPtr<ModelT> const& model,
Glib::RefPtr<FilterType> const& filter);
private:
#if !GTKMM_CHECK_VERSION(4, 0, 0)
bool matches_all_ = false;
bool matches_none_ = false;
sigc::signal<void(guint, guint, guint)> signal_items_changed_;
sigc::connection signal_changed_tag_;
#endif
};

96
gtk/FilterListModel.hh Normal file
View File

@@ -0,0 +1,96 @@
// This file Copyright © 2023 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.
#pragma once
#include "FilterBase.hh"
#include "FilterListModel.h"
#if !GTKMM_CHECK_VERSION(4, 0, 0)
#include "ListModelAdapter.h"
#include "Utils.h"
#endif
template<typename ItemT>
FilterListModel<ItemT>::FilterListModel(Glib::RefPtr<Gio::ListModel> const& model, Glib::RefPtr<FilterType> const& filter)
#if GTKMM_CHECK_VERSION(4, 0, 0)
: Gtk::FilterListModel(model, filter)
#else
: FilterListModel(gtr_ptr_static_cast<Gtk::TreeModel>(ListModelAdapter::create<ItemT>(model)), filter)
#endif
{
}
#if !GTKMM_CHECK_VERSION(4, 0, 0)
template<typename ItemT>
FilterListModel<ItemT>::FilterListModel(Glib::RefPtr<Gtk::TreeModel> const& model, Glib::RefPtr<FilterType> const& filter)
: Gtk::TreeModelFilter(model)
, matches_all_(filter->matches_all())
, matches_none_(filter->matches_none())
{
static auto const& self_col = ItemT::get_columns().self;
auto const filter_func = [this, filter](const_iterator const& iter)
{
if (matches_all_)
{
return true;
}
if (matches_none_)
{
return false;
}
auto const* const self = iter->get_value(self_col);
g_return_val_if_fail(self != nullptr, false);
return filter->match(*self);
};
set_visible_func(filter_func);
signal_changed_tag_ = filter->signal_changed().connect(
[this, filter](auto /*changes*/)
{
matches_all_ = filter->matches_all();
matches_none_ = filter->matches_none();
refilter();
});
signal_row_inserted().connect([this](auto const& path, auto const& /*iter*/)
{ signal_items_changed_.emit(path.front(), 0, 1); });
signal_row_deleted().connect([this](auto const& path) { signal_items_changed_.emit(path.front(), 1, 0); });
}
template<typename ItemT>
FilterListModel<ItemT>::~FilterListModel()
{
signal_changed_tag_.disconnect();
}
template<typename ItemT>
guint FilterListModel<ItemT>::get_n_items() const
{
return children().size();
}
template<typename ItemT>
sigc::signal<void(guint, guint, guint)>& FilterListModel<ItemT>::signal_items_changed()
{
return signal_items_changed_;
}
#endif
template<typename ItemT>
template<typename ModelT>
Glib::RefPtr<FilterListModel<ItemT>> FilterListModel<ItemT>::create(
Glib::RefPtr<ModelT> const& model,
Glib::RefPtr<FilterType> const& filter)
{
return Glib::make_refptr_for_instance(new FilterListModel(model, filter));
}

View File

@@ -9,6 +9,7 @@
#include "Notify.h"
#include "Prefs.h"
#include "PrefsDialog.h"
#include "SortListModel.hh"
#include "Torrent.h"
#include "TorrentSorter.h"
#include "Utils.h"
@@ -83,8 +84,6 @@ TrVariantPtr create_variant(tr_variant& other)
class Session::Impl
{
using SortModel = IF_GTKMM4(Gtk::SortListModel, Gtk::TreeModelSort);
public:
Impl(Session& core, tr_session* session);
~Impl();
@@ -94,7 +93,7 @@ public:
tr_session* close();
Glib::RefPtr<Gio::ListStore<Torrent>> get_raw_model() const;
Glib::RefPtr<SortModel> get_model();
Glib::RefPtr<SortListModel<Torrent>> get_model();
tr_session* get_session() const;
std::pair<Glib::RefPtr<Torrent>, guint> find_torrent_by_id(tr_torrent_id_t torrent_id) const;
@@ -207,7 +206,7 @@ private:
guint inhibit_cookie_ = 0;
gint busy_count_ = 0;
Glib::RefPtr<Gio::ListStore<Torrent>> raw_model_;
Glib::RefPtr<SortModel> sorted_model_;
Glib::RefPtr<SortListModel<Torrent>> sorted_model_;
Glib::RefPtr<TorrentSorter> sorter_ = TorrentSorter::create();
tr_session* session_ = nullptr;
};
@@ -237,7 +236,7 @@ Glib::RefPtr<Session::Model> Session::get_sorted_model() const
return impl_->get_model();
}
Glib::RefPtr<Session::Impl::SortModel> Session::Impl::get_model()
Glib::RefPtr<SortListModel<Torrent>> Session::Impl::get_model()
{
return sorted_model_;
}
@@ -537,20 +536,7 @@ Session::Impl::Impl(Session& core, tr_session* session)
{
raw_model_ = Gio::ListStore<Torrent>::create();
signal_torrents_changed_.connect(sigc::hide<0>(sigc::mem_fun(*sorter_.get(), &TorrentSorter::update)));
#if GTKMM_CHECK_VERSION(4, 0, 0)
sorted_model_ = Gtk::SortListModel::create(raw_model_, sorter_);
#else
static auto const& self_col = Torrent::get_columns().self;
auto const sort_func = [this](SortModel::const_iterator const& lhs, SortModel::const_iterator const& rhs)
{
return sorter_->compare(*lhs->get_value(self_col), *rhs->get_value(self_col));
};
sorted_model_ = Gtk::TreeModelSort::create(ListModelAdapter::create<Torrent>(raw_model_));
sorted_model_->set_default_sort_func(sort_func);
sorter_->signal_changed().connect([this, sort_func]() { sorted_model_->set_default_sort_func(sort_func); });
#endif
sorted_model_ = SortListModel<Torrent>::create(gtr_ptr_static_cast<Gio::ListModel>(raw_model_), sorter_);
/* init from prefs & listen to pref changes */
on_pref_changed(TR_KEY_sort_mode);

43
gtk/SortListModel.h Normal file
View File

@@ -0,0 +1,43 @@
// This file Copyright © 2023 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.
#pragma once
#include "GtkCompat.h"
#include <giomm/listmodel.h>
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include <gtkmm/sortlistmodel.h>
#else
#include <gtkmm/treemodel.h>
#include <gtkmm/treemodelsort.h>
#endif
template<typename ItemT>
class SorterBase;
template<typename ItemT>
class SortListModel : public IF_GTKMM4(Gtk::SortListModel, Gtk::TreeModelSort)
{
public:
using SorterType = SorterBase<ItemT>;
public:
SortListModel(Glib::RefPtr<Gio::ListModel> const& model, Glib::RefPtr<SorterType> const& sorter);
#if !GTKMM_CHECK_VERSION(4, 0, 0)
SortListModel(Glib::RefPtr<Gtk::TreeModel> const& model, Glib::RefPtr<SorterType> const& sorter);
~SortListModel() override;
#endif
template<typename ModelT>
static Glib::RefPtr<SortListModel<ItemT>> create(Glib::RefPtr<ModelT> const& model, Glib::RefPtr<SorterType> const& sorter);
private:
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::connection signal_changed_tag_;
#endif
};

71
gtk/SortListModel.hh Normal file
View File

@@ -0,0 +1,71 @@
// This file Copyright © 2023 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.
#pragma once
#include "SorterBase.hh"
#include "SortListModel.h"
#if !GTKMM_CHECK_VERSION(4, 0, 0)
#include "ListModelAdapter.h"
#include "Utils.h"
#endif
template<typename ItemT>
SortListModel<ItemT>::SortListModel(Glib::RefPtr<Gio::ListModel> const& model, Glib::RefPtr<SorterType> const& sorter)
#if GTKMM_CHECK_VERSION(4, 0, 0)
: Gtk::SortListModel(model, sorter)
#else
: SortListModel(gtr_ptr_static_cast<Gtk::TreeModel>(ListModelAdapter::create<ItemT>(model)), sorter)
#endif
{
}
#if !GTKMM_CHECK_VERSION(4, 0, 0)
template<typename ItemT>
SortListModel<ItemT>::SortListModel(Glib::RefPtr<Gtk::TreeModel> const& model, Glib::RefPtr<SorterType> const& sorter)
: Gtk::TreeModelSort(model)
{
static auto const& self_col = ItemT::get_columns().self;
auto const sort_func = [sorter](const_iterator const& lhs, const_iterator const& rhs)
{
auto const* const lhs_self = lhs->get_value(self_col);
auto const* const rhs_self = rhs->get_value(self_col);
if (lhs_self == nullptr && rhs_self == nullptr)
{
g_return_val_if_reached(0);
}
g_return_val_if_fail(lhs_self != nullptr, -1);
g_return_val_if_fail(rhs_self != nullptr, 1);
return sorter->compare(*lhs_self, *rhs_self);
};
set_default_sort_func(sort_func);
signal_changed_tag_ = sorter->signal_changed().connect([this, sort_func](auto /*changes*/)
{ set_default_sort_func(sort_func); });
}
template<typename ItemT>
SortListModel<ItemT>::~SortListModel()
{
signal_changed_tag_.disconnect();
}
#endif
template<typename ItemT>
template<typename ModelT>
Glib::RefPtr<SortListModel<ItemT>> SortListModel<ItemT>::create(
Glib::RefPtr<ModelT> const& model,
Glib::RefPtr<SorterType> const& sorter)
{
return Glib::make_refptr_for_instance(new SortListModel(model, sorter));
}

51
gtk/SorterBase.h Normal file
View File

@@ -0,0 +1,51 @@
// This file Copyright © 2022-2023 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.
#pragma once
#include "GtkCompat.h"
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include <gtkmm/sorter.h>
#else
#include <glibmm/object.h>
#endif
template<typename T>
class SorterBase : public IF_GTKMM4(Gtk::Sorter, Glib::Object)
{
public:
#if !GTKMM_CHECK_VERSION(4, 0, 0)
enum class Change{
DIFFERENT,
INVERTED,
LESS_STRICT,
MORE_STRICT,
};
#endif
public:
~SorterBase() override = default;
virtual int compare(T const& lhs, T const& rhs) const = 0;
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void(Change)>& signal_changed();
#endif
protected:
#if GTKMM_CHECK_VERSION(4, 0, 0)
// Gtk::Sorter
Gtk::Ordering compare_vfunc(gpointer lhs, gpointer rhs) override;
Order get_order_vfunc() override;
#else
void changed(Change change);
#endif
private:
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void(Change)> signal_changed_;
#endif
};

49
gtk/SorterBase.hh Normal file
View File

@@ -0,0 +1,49 @@
// This file Copyright © 2022-2023 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.
#pragma once
#include "SorterBase.h"
#if GTKMM_CHECK_VERSION(4, 0, 0)
template<typename T>
Gtk::Ordering SorterBase<T>::compare_vfunc(gpointer lhs, gpointer rhs)
{
auto const* const concrete_lhs = dynamic_cast<T const*>(Glib::wrap_auto(static_cast<GObject*>(lhs)));
auto const* const concrete_rhs = dynamic_cast<T const*>(Glib::wrap_auto(static_cast<GObject*>(rhs)));
if (concrete_lhs == nullptr && concrete_lhs == nullptr)
{
g_return_val_if_reached(Gtk::Ordering::EQUAL);
}
g_return_val_if_fail(concrete_lhs != nullptr, Gtk::Ordering::SMALLER);
g_return_val_if_fail(concrete_rhs != nullptr, Gtk::Ordering::LARGER);
return Gtk::Ordering{ compare(*concrete_lhs, *concrete_rhs) };
}
template<typename T>
Gtk::Sorter::Order SorterBase<T>::get_order_vfunc()
{
return Gtk::Sorter::Order::PARTIAL;
}
#else
template<typename T>
sigc::signal<void(typename SorterBase<T>::Change)>& SorterBase<T>::signal_changed()
{
return signal_changed_;
}
template<typename T>
void SorterBase<T>::changed(Change change)
{
signal_changed_.emit(change);
}
#endif

View File

@@ -1,14 +1,20 @@
// This file Copyright © 2022 Mnemosyne LLC.
// This file Copyright © 2022-2023 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.
#include "TorrentFilter.h"
#include "FilterBase.hh"
#include "Utils.h"
#include <libtransmission/transmission.h>
TorrentFilter::TorrentFilter()
: Glib::ObjectBase(typeid(TorrentFilter))
{
}
void TorrentFilter::set_activity(Activity type)
{
if (activity_type_ == type)
@@ -108,6 +114,11 @@ bool TorrentFilter::match(Torrent const& torrent) const
return match_activity(torrent) && match_tracker(torrent) && match_text(torrent);
}
bool TorrentFilter::matches_all() const
{
return activity_type_ == Activity::ALL && tracker_type_ == Tracker::ALL && text_.empty();
}
void TorrentFilter::update(Torrent::ChangeFlags changes)
{
using Flag = Torrent::ChangeFlag;
@@ -146,15 +157,6 @@ void TorrentFilter::update(Torrent::ChangeFlags changes)
}
}
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void()>& TorrentFilter::signal_changed()
{
return signal_changed_;
}
#endif
Glib::RefPtr<TorrentFilter> TorrentFilter::create()
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
@@ -246,32 +248,3 @@ bool TorrentFilter::match_text(Torrent const& torrent, Glib::ustring const& text
return ret;
}
#if GTKMM_CHECK_VERSION(4, 0, 0)
bool TorrentFilter::match_vfunc(Glib::RefPtr<Glib::ObjectBase> const& item)
{
auto const torrent = gtr_ptr_dynamic_cast<Torrent>(item);
g_return_val_if_fail(torrent != nullptr, false);
return match(*torrent);
}
TorrentFilter::Match TorrentFilter::get_strictness_vfunc()
{
return activity_type_ == Activity::ALL && tracker_type_ == Tracker::ALL && text_.empty() ? Match::ALL : Match::SOME;
}
#else
void TorrentFilter::changed(Change /*change*/)
{
signal_changed_.emit();
}
#endif
TorrentFilter::TorrentFilter()
: Glib::ObjectBase(typeid(TorrentFilter))
{
}

View File

@@ -1,32 +1,18 @@
// This file Copyright © 2022 Mnemosyne LLC.
// This file Copyright © 2022-2023 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.
#pragma once
#include "GtkCompat.h"
#include "FilterBase.h"
#include "Torrent.h"
#include <glibmm/refptr.h>
#include <glibmm/ustring.h>
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include <gtkmm/filter.h>
#else
#include <glibmm/object.h>
#endif
class TorrentFilter : public IF_GTKMM4(Gtk::Filter, Glib::Object)
class TorrentFilter : public FilterBase<Torrent>
{
#if !GTKMM_CHECK_VERSION(4, 0, 0)
enum class Change{
DIFFERENT,
LESS_STRICT,
MORE_STRICT,
};
#endif
public:
enum class Activity
{
@@ -55,28 +41,18 @@ public:
bool match_tracker(Torrent const& torrent) const;
bool match_text(Torrent const& torrent) const;
bool match(Torrent const& torrent) const;
// FilterBase<Torrent>
bool match(Torrent const& torrent) const override;
bool matches_all() const override;
void update(Torrent::ChangeFlags changes);
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void()>& signal_changed();
#endif
static Glib::RefPtr<TorrentFilter> create();
static bool match_activity(Torrent const& torrent, Activity type);
static bool match_tracker(Torrent const& torrent, Tracker type, Glib::ustring const& host);
static bool match_text(Torrent const& torrent, Glib::ustring const& text);
protected:
#if GTKMM_CHECK_VERSION(4, 0, 0)
bool match_vfunc(Glib::RefPtr<Glib::ObjectBase> const& item) override;
Match get_strictness_vfunc() override;
#else
void changed(Change change);
#endif
private:
TorrentFilter();
@@ -85,8 +61,4 @@ private:
Tracker tracker_type_ = Tracker::ALL;
Glib::ustring tracker_host_;
Glib::ustring text_;
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void()> signal_changed_;
#endif
};

View File

@@ -1,10 +1,11 @@
// This file Copyright © 2022 Mnemosyne LLC.
// This file Copyright © 2022-2023 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.
#include "TorrentSorter.h"
#include "SorterBase.hh"
#include "Utils.h"
#include <libtransmission/transmission.h>
@@ -185,6 +186,11 @@ int compare_by_state(Torrent const& lhs, Torrent const& rhs)
} // namespace
TorrentSorter::TorrentSorter()
: Glib::ObjectBase(typeid(TorrentSorter))
{
}
void TorrentSorter::set_mode(std::string_view mode)
{
static auto const compare_funcs = std::map<std::string_view, CompareFunc>({
@@ -253,49 +259,8 @@ void TorrentSorter::update(Torrent::ChangeFlags changes)
}
}
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void()>& TorrentSorter::signal_changed()
{
return signal_changed_;
}
#endif
Glib::RefPtr<TorrentSorter> TorrentSorter::create()
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return Glib::make_refptr_for_instance(new TorrentSorter());
}
#if GTKMM_CHECK_VERSION(4, 0, 0)
Gtk::Ordering TorrentSorter::compare_vfunc(gpointer lhs, gpointer rhs)
{
auto const* const lhs_torrent = dynamic_cast<Torrent const*>(Glib::wrap_auto(static_cast<GObject*>(lhs)));
g_return_val_if_fail(lhs_torrent != nullptr, Gtk::Ordering::SMALLER);
auto const* const rhs_torrent = dynamic_cast<Torrent const*>(Glib::wrap_auto(static_cast<GObject*>(rhs)));
g_return_val_if_fail(rhs_torrent != nullptr, Gtk::Ordering::LARGER);
return Gtk::Ordering{ compare(*lhs_torrent, *rhs_torrent) };
}
Gtk::Sorter::Order TorrentSorter::get_order_vfunc()
{
return Gtk::Sorter::Order::PARTIAL;
}
#else
void TorrentSorter::changed(Change /*change*/)
{
signal_changed_.emit();
}
#endif
TorrentSorter::TorrentSorter()
: Glib::ObjectBase(typeid(TorrentSorter))
{
}

View File

@@ -1,64 +1,34 @@
// This file Copyright © 2022 Mnemosyne LLC.
// This file Copyright © 2022-2023 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.
#pragma once
#include "GtkCompat.h"
#include "SorterBase.h"
#include "Torrent.h"
#include <glibmm/refptr.h>
#if GTKMM_CHECK_VERSION(4, 0, 0)
#include <gtkmm/sorter.h>
#else
#include <glibmm/object.h>
#endif
class TorrentSorter : public IF_GTKMM4(Gtk::Sorter, Glib::Object)
class TorrentSorter : public SorterBase<Torrent>
{
using CompareFunc = int (*)(Torrent const&, Torrent const&);
#if !GTKMM_CHECK_VERSION(4, 0, 0)
enum class Change{
DIFFERENT,
INVERTED,
LESS_STRICT,
MORE_STRICT,
};
#endif
public:
void set_mode(std::string_view mode);
void set_reversed(bool is_reversed);
int compare(Torrent const& lhs, Torrent const& rhs) const;
// SorterBase<Torrent>
int compare(Torrent const& lhs, Torrent const& rhs) const override;
void update(Torrent::ChangeFlags changes);
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void()>& signal_changed();
#endif
static Glib::RefPtr<TorrentSorter> create();
protected:
#if GTKMM_CHECK_VERSION(4, 0, 0)
Gtk::Ordering compare_vfunc(gpointer lhs, gpointer rhs) override;
Order get_order_vfunc() override;
#else
void changed(Change change);
#endif
private:
TorrentSorter();
private:
CompareFunc compare_func_ = nullptr;
bool is_reversed_ = false;
#if !GTKMM_CHECK_VERSION(4, 0, 0)
sigc::signal<void()> signal_changed_;
#endif
};