From fa091495d6a96f812de877fe5b6716a10df11393 Mon Sep 17 00:00:00 2001 From: Mike Gelfand Date: Sun, 8 Jan 2023 18:31:03 +0300 Subject: [PATCH] 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) --- gtk/CMakeLists.txt | 8 ++++ gtk/FilterBar.cc | 26 +++--------- gtk/FilterBase.h | 53 +++++++++++++++++++++++ gtk/FilterBase.hh | 67 +++++++++++++++++++++++++++++ gtk/FilterListModel.h | 54 ++++++++++++++++++++++++ gtk/FilterListModel.hh | 96 ++++++++++++++++++++++++++++++++++++++++++ gtk/Session.cc | 24 +++-------- gtk/SortListModel.h | 43 +++++++++++++++++++ gtk/SortListModel.hh | 71 +++++++++++++++++++++++++++++++ gtk/SorterBase.h | 51 ++++++++++++++++++++++ gtk/SorterBase.hh | 49 +++++++++++++++++++++ gtk/TorrentFilter.cc | 51 ++++++---------------- gtk/TorrentFilter.h | 40 +++--------------- gtk/TorrentSorter.cc | 49 +++------------------ gtk/TorrentSorter.h | 40 +++--------------- 15 files changed, 532 insertions(+), 190 deletions(-) create mode 100644 gtk/FilterBase.h create mode 100644 gtk/FilterBase.hh create mode 100644 gtk/FilterListModel.h create mode 100644 gtk/FilterListModel.hh create mode 100644 gtk/SortListModel.h create mode 100644 gtk/SortListModel.hh create mode 100644 gtk/SorterBase.h create mode 100644 gtk/SorterBase.hh diff --git a/gtk/CMakeLists.txt b/gtk/CMakeLists.txt index 54c4ab6c4..e81269ab0 100644 --- a/gtk/CMakeLists.txt +++ b/gtk/CMakeLists.txt @@ -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 diff --git a/gtk/FilterBar.cc b/gtk/FilterBar.cc index 67de4b8ba..85a88b57c 100644 --- a/gtk/FilterBar.cc +++ b/gtk/FilterBar.cc @@ -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 filter_ = TorrentFilter::create(); - Glib::RefPtr filter_model_; + Glib::RefPtr> 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(filter_model_->IF_GTKMM4(get_n_items(), children().size())); + auto const visibleCount = static_cast(filter_model_->get_n_items()); /* get the tracker count */ int trackerCount = 0; @@ -701,22 +700,9 @@ FilterBar::Impl::Impl(FilterBar& widget, Glib::RefPtr 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::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::get_filter_model() const diff --git a/gtk/FilterBase.h b/gtk/FilterBase.h new file mode 100644 index 000000000..050907d45 --- /dev/null +++ b/gtk/FilterBase.h @@ -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 +#else +#include +#endif + +template +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& signal_changed(); +#endif + +protected: +#if GTKMM_CHECK_VERSION(4, 0, 0) + // Gtk::Filter + bool match_vfunc(Glib::RefPtr const& object) override; + Match get_strictness_vfunc() override; +#else + void changed(Change change); +#endif + +private: +#if !GTKMM_CHECK_VERSION(4, 0, 0) + sigc::signal signal_changed_; +#endif +}; diff --git a/gtk/FilterBase.hh b/gtk/FilterBase.hh new file mode 100644 index 000000000..fde9764d2 --- /dev/null +++ b/gtk/FilterBase.hh @@ -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 +bool FilterBase::matches_all() const +{ + return false; +} + +template +bool FilterBase::matches_none() const +{ + return false; +} + +#if GTKMM_CHECK_VERSION(4, 0, 0) + +template +bool FilterBase::match_vfunc(Glib::RefPtr const& object) +{ + auto const concrete_object = gtr_ptr_dynamic_cast(object); + g_return_val_if_fail(concrete_object != nullptr, false); + + return match(*concrete_object); +} + +template +typename FilterBase::Match FilterBase::get_strictness_vfunc() +{ + if (matches_all()) + { + return Match::ALL; + } + + if (matches_none()) + { + return Match::NONE; + } + + return Match::SOME; +} + +#else + +template +sigc::signal::Change)>& FilterBase::signal_changed() +{ + return signal_changed_; +} + +template +void FilterBase::changed(Change change) +{ + signal_changed_.emit(change); +} + +#endif diff --git a/gtk/FilterListModel.h b/gtk/FilterListModel.h new file mode 100644 index 000000000..03797374b --- /dev/null +++ b/gtk/FilterListModel.h @@ -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 + +#if GTKMM_CHECK_VERSION(4, 0, 0) +#include +#else +#include +#include +#endif + +template +class FilterBase; + +template +class FilterListModel : public IF_GTKMM4(Gtk::FilterListModel, Gtk::TreeModelFilter) +{ +public: + using FilterType = FilterBase; + +public: + FilterListModel(Glib::RefPtr const& model, Glib::RefPtr const& filter); + +#if !GTKMM_CHECK_VERSION(4, 0, 0) + FilterListModel(Glib::RefPtr const& model, Glib::RefPtr const& filter); + ~FilterListModel() override; + + guint get_n_items() const; + + sigc::signal& signal_items_changed(); +#endif + + template + static Glib::RefPtr> create( + Glib::RefPtr const& model, + Glib::RefPtr const& filter); + +private: +#if !GTKMM_CHECK_VERSION(4, 0, 0) + bool matches_all_ = false; + bool matches_none_ = false; + + sigc::signal signal_items_changed_; + + sigc::connection signal_changed_tag_; +#endif +}; diff --git a/gtk/FilterListModel.hh b/gtk/FilterListModel.hh new file mode 100644 index 000000000..219a5e03b --- /dev/null +++ b/gtk/FilterListModel.hh @@ -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 +FilterListModel::FilterListModel(Glib::RefPtr const& model, Glib::RefPtr const& filter) +#if GTKMM_CHECK_VERSION(4, 0, 0) + : Gtk::FilterListModel(model, filter) +#else + : FilterListModel(gtr_ptr_static_cast(ListModelAdapter::create(model)), filter) +#endif +{ +} + +#if !GTKMM_CHECK_VERSION(4, 0, 0) + +template +FilterListModel::FilterListModel(Glib::RefPtr const& model, Glib::RefPtr 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 +FilterListModel::~FilterListModel() +{ + signal_changed_tag_.disconnect(); +} + +template +guint FilterListModel::get_n_items() const +{ + return children().size(); +} + +template +sigc::signal& FilterListModel::signal_items_changed() +{ + return signal_items_changed_; +} + +#endif + +template +template +Glib::RefPtr> FilterListModel::create( + Glib::RefPtr const& model, + Glib::RefPtr const& filter) +{ + return Glib::make_refptr_for_instance(new FilterListModel(model, filter)); +} diff --git a/gtk/Session.cc b/gtk/Session.cc index 0db0ca5a3..ca4bb64c5 100644 --- a/gtk/Session.cc +++ b/gtk/Session.cc @@ -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> get_raw_model() const; - Glib::RefPtr get_model(); + Glib::RefPtr> get_model(); tr_session* get_session() const; std::pair, 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> raw_model_; - Glib::RefPtr sorted_model_; + Glib::RefPtr> sorted_model_; Glib::RefPtr sorter_ = TorrentSorter::create(); tr_session* session_ = nullptr; }; @@ -237,7 +236,7 @@ Glib::RefPtr Session::get_sorted_model() const return impl_->get_model(); } -Glib::RefPtr Session::Impl::get_model() +Glib::RefPtr> Session::Impl::get_model() { return sorted_model_; } @@ -537,20 +536,7 @@ Session::Impl::Impl(Session& core, tr_session* session) { raw_model_ = Gio::ListStore::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(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::create(gtr_ptr_static_cast(raw_model_), sorter_); /* init from prefs & listen to pref changes */ on_pref_changed(TR_KEY_sort_mode); diff --git a/gtk/SortListModel.h b/gtk/SortListModel.h new file mode 100644 index 000000000..ecf252ab1 --- /dev/null +++ b/gtk/SortListModel.h @@ -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 + +#if GTKMM_CHECK_VERSION(4, 0, 0) +#include +#else +#include +#include +#endif + +template +class SorterBase; + +template +class SortListModel : public IF_GTKMM4(Gtk::SortListModel, Gtk::TreeModelSort) +{ +public: + using SorterType = SorterBase; + +public: + SortListModel(Glib::RefPtr const& model, Glib::RefPtr const& sorter); + +#if !GTKMM_CHECK_VERSION(4, 0, 0) + SortListModel(Glib::RefPtr const& model, Glib::RefPtr const& sorter); + ~SortListModel() override; +#endif + + template + static Glib::RefPtr> create(Glib::RefPtr const& model, Glib::RefPtr const& sorter); + +private: +#if !GTKMM_CHECK_VERSION(4, 0, 0) + sigc::connection signal_changed_tag_; +#endif +}; diff --git a/gtk/SortListModel.hh b/gtk/SortListModel.hh new file mode 100644 index 000000000..bb1cbf579 --- /dev/null +++ b/gtk/SortListModel.hh @@ -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 +SortListModel::SortListModel(Glib::RefPtr const& model, Glib::RefPtr const& sorter) +#if GTKMM_CHECK_VERSION(4, 0, 0) + : Gtk::SortListModel(model, sorter) +#else + : SortListModel(gtr_ptr_static_cast(ListModelAdapter::create(model)), sorter) +#endif +{ +} + +#if !GTKMM_CHECK_VERSION(4, 0, 0) + +template +SortListModel::SortListModel(Glib::RefPtr const& model, Glib::RefPtr 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 +SortListModel::~SortListModel() +{ + signal_changed_tag_.disconnect(); +} + +#endif + +template +template +Glib::RefPtr> SortListModel::create( + Glib::RefPtr const& model, + Glib::RefPtr const& sorter) +{ + return Glib::make_refptr_for_instance(new SortListModel(model, sorter)); +} diff --git a/gtk/SorterBase.h b/gtk/SorterBase.h new file mode 100644 index 000000000..fdc56ae72 --- /dev/null +++ b/gtk/SorterBase.h @@ -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 +#else +#include +#endif + +template +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& 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 signal_changed_; +#endif +}; diff --git a/gtk/SorterBase.hh b/gtk/SorterBase.hh new file mode 100644 index 000000000..1c72f5303 --- /dev/null +++ b/gtk/SorterBase.hh @@ -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 +Gtk::Ordering SorterBase::compare_vfunc(gpointer lhs, gpointer rhs) +{ + auto const* const concrete_lhs = dynamic_cast(Glib::wrap_auto(static_cast(lhs))); + auto const* const concrete_rhs = dynamic_cast(Glib::wrap_auto(static_cast(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 +Gtk::Sorter::Order SorterBase::get_order_vfunc() +{ + return Gtk::Sorter::Order::PARTIAL; +} + +#else + +template +sigc::signal::Change)>& SorterBase::signal_changed() +{ + return signal_changed_; +} + +template +void SorterBase::changed(Change change) +{ + signal_changed_.emit(change); +} + +#endif diff --git a/gtk/TorrentFilter.cc b/gtk/TorrentFilter.cc index 7d86de4a6..6cbee17a0 100644 --- a/gtk/TorrentFilter.cc +++ b/gtk/TorrentFilter.cc @@ -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 +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& TorrentFilter::signal_changed() -{ - return signal_changed_; -} - -#endif - Glib::RefPtr 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 const& item) -{ - auto const torrent = gtr_ptr_dynamic_cast(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)) -{ -} diff --git a/gtk/TorrentFilter.h b/gtk/TorrentFilter.h index 35b6a731b..66719ee2e 100644 --- a/gtk/TorrentFilter.h +++ b/gtk/TorrentFilter.h @@ -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 #include -#if GTKMM_CHECK_VERSION(4, 0, 0) -#include -#else -#include -#endif - -class TorrentFilter : public IF_GTKMM4(Gtk::Filter, Glib::Object) +class TorrentFilter : public FilterBase { -#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 + 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& signal_changed(); -#endif - static Glib::RefPtr 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 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 signal_changed_; -#endif }; diff --git a/gtk/TorrentSorter.cc b/gtk/TorrentSorter.cc index 4e35b32cf..ca8b9b040 100644 --- a/gtk/TorrentSorter.cc +++ b/gtk/TorrentSorter.cc @@ -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 @@ -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({ @@ -253,49 +259,8 @@ void TorrentSorter::update(Torrent::ChangeFlags changes) } } -#if !GTKMM_CHECK_VERSION(4, 0, 0) - -sigc::signal& TorrentSorter::signal_changed() -{ - return signal_changed_; -} - -#endif - Glib::RefPtr 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(Glib::wrap_auto(static_cast(lhs))); - g_return_val_if_fail(lhs_torrent != nullptr, Gtk::Ordering::SMALLER); - - auto const* const rhs_torrent = dynamic_cast(Glib::wrap_auto(static_cast(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)) -{ -} diff --git a/gtk/TorrentSorter.h b/gtk/TorrentSorter.h index 98bf4f4b0..37cade431 100644 --- a/gtk/TorrentSorter.h +++ b/gtk/TorrentSorter.h @@ -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 -#if GTKMM_CHECK_VERSION(4, 0, 0) -#include -#else -#include -#endif - -class TorrentSorter : public IF_GTKMM4(Gtk::Sorter, Glib::Object) +class TorrentSorter : public SorterBase { 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 + int compare(Torrent const& lhs, Torrent const& rhs) const override; void update(Torrent::ChangeFlags changes); -#if !GTKMM_CHECK_VERSION(4, 0, 0) - sigc::signal& signal_changed(); -#endif - static Glib::RefPtr 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 signal_changed_; -#endif };