mirror of
https://github.com/transmission/transmission.git
synced 2026-02-14 23:19:34 +00:00
refactor: add libtransmission-app (#7978)
* refactor: add libtransmission-app * refactor: add libtransmission-app/display-modes.h * refactor: use app::SortMode, app:ShowMode in Qt client * feat: add to_variant(), to_value() in serializer * refactor: use app::SortMode in GTK client * refactor: use app::ShowMode in GTK client * refactor: make naming consistent with libtransmission-app
This commit is contained in:
@@ -827,6 +827,7 @@ function(tr_install_web DST_DIR)
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(libtransmission)
|
||||
add_subdirectory(libtransmission-app)
|
||||
|
||||
set(MAC_PROJECT_DIR macosx)
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@ BasedOnStyle: InheritParentConfig
|
||||
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<libtransmission/transmission.h>'
|
||||
- Regex: '^<libtransmission-app/'
|
||||
Priority: 3
|
||||
- Regex: '^<libtransmission/transmission.h>'
|
||||
Priority: 4
|
||||
SortPriority: 3
|
||||
- Regex: '^<libtransmission/'
|
||||
Priority: 3
|
||||
Priority: 4
|
||||
SortPriority: 4
|
||||
- Regex: '^<(cairo|gdk|gio|glib|gtk|pango)mm([-./]|config)'
|
||||
Priority: 5
|
||||
|
||||
@@ -197,6 +197,7 @@ target_include_directories(${TR_NAME}-gtk SYSTEM
|
||||
|
||||
target_link_libraries(${TR_NAME}-gtk
|
||||
PRIVATE
|
||||
${TR_NAME}-app
|
||||
${TR_NAME}
|
||||
transmission::gtk_impl
|
||||
fmt::fmt-header-only
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <libtransmission/favicon-cache.h>
|
||||
#include <libtransmission-app/favicon-cache.h>
|
||||
|
||||
#include <gdkmm/pixbuf.h>
|
||||
#include <giomm/memoryinputstream.h>
|
||||
|
||||
149
gtk/FilterBar.cc
149
gtk/FilterBar.cc
@@ -13,6 +13,8 @@
|
||||
#include "TorrentFilter.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
#include <libtransmission/tr-macros.h>
|
||||
|
||||
#include <gdkmm/pixbuf.h>
|
||||
@@ -45,12 +47,13 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace transmission::app;
|
||||
|
||||
namespace
|
||||
{
|
||||
using ActivityType = TorrentFilter::Activity;
|
||||
using TrackerType = TorrentFilter::Tracker;
|
||||
|
||||
constexpr auto ActivitySeparator = static_cast<ActivityType>(-1);
|
||||
constexpr auto ShowModeSeparator = static_cast<ShowMode>(-1);
|
||||
constexpr auto TrackerSeparator = static_cast<TrackerType>(-1);
|
||||
} // namespace
|
||||
|
||||
@@ -72,18 +75,20 @@ private:
|
||||
template<typename T>
|
||||
T* get_template_child(char const* name) const;
|
||||
|
||||
void activity_combo_box_init(Gtk::ComboBox& combo);
|
||||
static void render_activity_pixbuf_func(Gtk::CellRendererPixbuf& cell_renderer, Gtk::TreeModel::const_iterator const& iter);
|
||||
void show_mode_combo_box_init(Gtk::ComboBox& combo);
|
||||
static void render_show_mode_pixbuf_func(
|
||||
Gtk::CellRendererPixbuf& cell_renderer,
|
||||
Gtk::TreeModel::const_iterator const& iter);
|
||||
|
||||
void tracker_combo_box_init(Gtk::ComboBox& combo);
|
||||
static void render_pixbuf_func(Gtk::CellRendererPixbuf& cell_renderer, Gtk::TreeModel::const_iterator const& iter);
|
||||
static void render_number_func(Gtk::CellRendererText& cell_renderer, Gtk::TreeModel::const_iterator const& iter);
|
||||
|
||||
void update_filter_activity();
|
||||
void update_filter_show_mode();
|
||||
void update_filter_tracker();
|
||||
void update_filter_text();
|
||||
|
||||
bool activity_filter_model_update();
|
||||
bool show_mode_filter_model_update();
|
||||
|
||||
bool tracker_filter_model_update();
|
||||
void favicon_ready_cb(Glib::RefPtr<Gdk::Pixbuf> const* pixbuf, Gtk::TreeModel::Path const& path);
|
||||
@@ -94,9 +99,9 @@ private:
|
||||
void update_count_label_idle();
|
||||
bool update_count_label();
|
||||
|
||||
static Glib::RefPtr<Gtk::ListStore> activity_filter_model_new();
|
||||
static Glib::RefPtr<Gtk::ListStore> show_mode_filter_model_new();
|
||||
static void status_model_update_count(Gtk::TreeModel::iterator const& iter, int n);
|
||||
static bool activity_is_it_a_separator(Gtk::TreeModel::const_iterator const& iter);
|
||||
static bool show_mode_is_it_a_separator(Gtk::TreeModel::const_iterator const& iter);
|
||||
|
||||
static Glib::RefPtr<Gtk::TreeStore> tracker_filter_model_new();
|
||||
static void tracker_model_update_count(Gtk::TreeModel::iterator const& iter, int n);
|
||||
@@ -110,10 +115,10 @@ private:
|
||||
FilterBar& widget_;
|
||||
Glib::RefPtr<Session> const core_;
|
||||
|
||||
Glib::RefPtr<Gtk::ListStore> const activity_model_;
|
||||
Glib::RefPtr<Gtk::ListStore> const show_mode_model_;
|
||||
Glib::RefPtr<Gtk::TreeStore> const tracker_model_;
|
||||
|
||||
Gtk::ComboBox* activity_ = nullptr;
|
||||
Gtk::ComboBox* show_mode_ = nullptr;
|
||||
Gtk::ComboBox* tracker_ = nullptr;
|
||||
Gtk::Entry* entry_ = nullptr;
|
||||
Gtk::Label* show_lb_ = nullptr;
|
||||
@@ -390,54 +395,50 @@ void FilterBar::Impl::tracker_combo_box_init(Gtk::ComboBox& combo)
|
||||
namespace
|
||||
{
|
||||
|
||||
/***
|
||||
****
|
||||
**** ACTIVITY
|
||||
****
|
||||
***/
|
||||
// --- Show Mode
|
||||
|
||||
class ActivityFilterModelColumns : public Gtk::TreeModelColumnRecord
|
||||
class ShowModeFilterModelColumns : public Gtk::TreeModelColumnRecord
|
||||
{
|
||||
public:
|
||||
ActivityFilterModelColumns() noexcept
|
||||
ShowModeFilterModelColumns() noexcept
|
||||
{
|
||||
add(name);
|
||||
add(count);
|
||||
add(type);
|
||||
add(show_mode);
|
||||
add(icon_name);
|
||||
}
|
||||
|
||||
Gtk::TreeModelColumn<Glib::ustring> name;
|
||||
Gtk::TreeModelColumn<int> count;
|
||||
Gtk::TreeModelColumn<ActivityType> type;
|
||||
Gtk::TreeModelColumn<ShowMode> show_mode;
|
||||
Gtk::TreeModelColumn<Glib::ustring> icon_name;
|
||||
};
|
||||
|
||||
ActivityFilterModelColumns const activity_filter_cols;
|
||||
ShowModeFilterModelColumns const show_mode_filter_cols;
|
||||
|
||||
} // namespace
|
||||
|
||||
bool FilterBar::Impl::activity_is_it_a_separator(Gtk::TreeModel::const_iterator const& iter)
|
||||
bool FilterBar::Impl::show_mode_is_it_a_separator(Gtk::TreeModel::const_iterator const& iter)
|
||||
{
|
||||
return iter->get_value(activity_filter_cols.type) == ActivitySeparator;
|
||||
return iter->get_value(show_mode_filter_cols.show_mode) == ShowModeSeparator;
|
||||
}
|
||||
|
||||
void FilterBar::Impl::status_model_update_count(Gtk::TreeModel::iterator const& iter, int n)
|
||||
{
|
||||
if (n != iter->get_value(activity_filter_cols.count))
|
||||
if (n != iter->get_value(show_mode_filter_cols.count))
|
||||
{
|
||||
iter->set_value(activity_filter_cols.count, n);
|
||||
iter->set_value(show_mode_filter_cols.count, n);
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterBar::Impl::activity_filter_model_update()
|
||||
bool FilterBar::Impl::show_mode_filter_model_update()
|
||||
{
|
||||
auto const torrents_model = core_->get_model();
|
||||
|
||||
for (auto& row : activity_model_->children())
|
||||
for (auto& row : show_mode_model_->children())
|
||||
{
|
||||
auto const type = row.get_value(activity_filter_cols.type);
|
||||
if (type == ActivitySeparator)
|
||||
auto const type = row.get_value(show_mode_filter_cols.show_mode);
|
||||
if (type == ShowModeSeparator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -447,7 +448,7 @@ bool FilterBar::Impl::activity_filter_model_update()
|
||||
for (auto i = 0U, count = torrents_model->get_n_items(); i < count; ++i)
|
||||
{
|
||||
auto const torrent = gtr_ptr_dynamic_cast<Torrent>(torrents_model->get_object(i));
|
||||
if (torrent != nullptr && TorrentFilter::match_activity(*torrent, static_cast<ActivityType>(type)))
|
||||
if (torrent != nullptr && TorrentFilter::match_mode(*torrent, static_cast<ShowMode>(type)))
|
||||
{
|
||||
++hits;
|
||||
}
|
||||
@@ -459,29 +460,29 @@ bool FilterBar::Impl::activity_filter_model_update()
|
||||
return false;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gtk::ListStore> FilterBar::Impl::activity_filter_model_new()
|
||||
Glib::RefPtr<Gtk::ListStore> FilterBar::Impl::show_mode_filter_model_new()
|
||||
{
|
||||
struct FilterTypeInfo
|
||||
{
|
||||
ActivityType type;
|
||||
ShowMode show_mode;
|
||||
char const* context;
|
||||
char const* name;
|
||||
char const* icon_name;
|
||||
};
|
||||
|
||||
static auto constexpr types = std::array<FilterTypeInfo, 9>({ {
|
||||
{ ActivityType::ALL, nullptr, N_("All"), nullptr },
|
||||
{ ActivityType{ -1 }, nullptr, nullptr, nullptr },
|
||||
{ ActivityType::ACTIVE, nullptr, N_("Active"), "system-run" },
|
||||
{ ActivityType::DOWNLOADING, "Verb", NC_("Verb", "Downloading"), "network-receive" },
|
||||
{ ActivityType::SEEDING, "Verb", NC_("Verb", "Seeding"), "network-transmit" },
|
||||
{ ActivityType::PAUSED, nullptr, N_("Paused"), "media-playback-pause" },
|
||||
{ ActivityType::FINISHED, nullptr, N_("Finished"), "media-playback-stop" },
|
||||
{ ActivityType::VERIFYING, "Verb", NC_("Verb", "Verifying"), "view-refresh" },
|
||||
{ ActivityType::ERROR, nullptr, N_("Error"), "dialog-error" },
|
||||
{ ShowMode::ShowAll, nullptr, N_("All"), nullptr },
|
||||
{ ShowMode{ -1 }, nullptr, nullptr, nullptr },
|
||||
{ ShowMode::ShowActive, nullptr, N_("Active"), "system-run" },
|
||||
{ ShowMode::ShowDownloading, "Verb", NC_("Verb", "Downloading"), "network-receive" },
|
||||
{ ShowMode::ShowSeeding, "Verb", NC_("Verb", "Seeding"), "network-transmit" },
|
||||
{ ShowMode::ShowPaused, nullptr, N_("Paused"), "media-playback-pause" },
|
||||
{ ShowMode::ShowFinished, nullptr, N_("Finished"), "media-playback-stop" },
|
||||
{ ShowMode::ShowVerifying, "Verb", NC_("Verb", "Verifying"), "view-refresh" },
|
||||
{ ShowMode::ShowError, nullptr, N_("Error"), "dialog-error" },
|
||||
} });
|
||||
|
||||
auto store = Gtk::ListStore::create(activity_filter_cols);
|
||||
auto store = Gtk::ListStore::create(show_mode_filter_cols);
|
||||
|
||||
for (auto const& type : types)
|
||||
{
|
||||
@@ -489,40 +490,40 @@ Glib::RefPtr<Gtk::ListStore> FilterBar::Impl::activity_filter_model_new()
|
||||
Glib::ustring(type.context != nullptr ? g_dpgettext2(nullptr, type.context, type.name) : _(type.name)) :
|
||||
Glib::ustring();
|
||||
auto const iter = store->append();
|
||||
iter->set_value(activity_filter_cols.name, name);
|
||||
iter->set_value(activity_filter_cols.type, type.type);
|
||||
iter->set_value(activity_filter_cols.icon_name, Glib::ustring(type.icon_name != nullptr ? type.icon_name : ""));
|
||||
iter->set_value(show_mode_filter_cols.name, name);
|
||||
iter->set_value(show_mode_filter_cols.show_mode, type.show_mode);
|
||||
iter->set_value(show_mode_filter_cols.icon_name, Glib::ustring(type.icon_name != nullptr ? type.icon_name : ""));
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
void FilterBar::Impl::render_activity_pixbuf_func(
|
||||
void FilterBar::Impl::render_show_mode_pixbuf_func(
|
||||
Gtk::CellRendererPixbuf& cell_renderer,
|
||||
Gtk::TreeModel::const_iterator const& iter)
|
||||
{
|
||||
auto const type = ActivityType{ iter->get_value(activity_filter_cols.type) };
|
||||
cell_renderer.property_width() = type == ActivityType::ALL ? 0 : 20;
|
||||
cell_renderer.property_ypad() = type == ActivityType::ALL ? 0 : 2;
|
||||
auto const type = ShowMode{ iter->get_value(show_mode_filter_cols.show_mode) };
|
||||
cell_renderer.property_width() = type == ShowMode::ShowAll ? 0 : 20;
|
||||
cell_renderer.property_ypad() = type == ShowMode::ShowAll ? 0 : 2;
|
||||
}
|
||||
|
||||
void FilterBar::Impl::activity_combo_box_init(Gtk::ComboBox& combo)
|
||||
void FilterBar::Impl::show_mode_combo_box_init(Gtk::ComboBox& combo)
|
||||
{
|
||||
combo.set_model(activity_model_);
|
||||
combo.set_row_separator_func(sigc::hide<0>(&Impl::activity_is_it_a_separator));
|
||||
combo.set_model(show_mode_model_);
|
||||
combo.set_row_separator_func(sigc::hide<0>(&Impl::show_mode_is_it_a_separator));
|
||||
combo.set_active(0);
|
||||
|
||||
{
|
||||
auto* r = Gtk::make_managed<Gtk::CellRendererPixbuf>();
|
||||
combo.pack_start(*r, false);
|
||||
combo.add_attribute(r->property_icon_name(), activity_filter_cols.icon_name);
|
||||
combo.set_cell_data_func(*r, [r](auto const& iter) { render_activity_pixbuf_func(*r, iter); });
|
||||
combo.add_attribute(r->property_icon_name(), show_mode_filter_cols.icon_name);
|
||||
combo.set_cell_data_func(*r, [r](auto const& iter) { render_show_mode_pixbuf_func(*r, iter); });
|
||||
}
|
||||
|
||||
{
|
||||
auto* r = Gtk::make_managed<Gtk::CellRendererText>();
|
||||
combo.pack_start(*r, true);
|
||||
combo.add_attribute(r->property_text(), activity_filter_cols.name);
|
||||
combo.add_attribute(r->property_text(), show_mode_filter_cols.name);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -537,16 +538,16 @@ void FilterBar::Impl::update_filter_text()
|
||||
filter_->set_text(entry_->get_text());
|
||||
}
|
||||
|
||||
void FilterBar::Impl::update_filter_activity()
|
||||
void FilterBar::Impl::update_filter_show_mode()
|
||||
{
|
||||
/* set active_activity_type_ from the activity combobox */
|
||||
if (auto const iter = activity_->get_active(); iter)
|
||||
/* set active_show_mode_type_ from the show_mode combobox */
|
||||
if (auto const iter = show_mode_->get_active(); iter)
|
||||
{
|
||||
filter_->set_activity(ActivityType{ iter->get_value(activity_filter_cols.type) });
|
||||
filter_->set_mode(ShowMode{ iter->get_value(show_mode_filter_cols.show_mode) });
|
||||
}
|
||||
else
|
||||
{
|
||||
filter_->set_activity(ActivityType::ALL);
|
||||
filter_->set_mode(ShowMode::ShowAll);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,15 +578,15 @@ bool FilterBar::Impl::update_count_label()
|
||||
trackerCount = iter->get_value(tracker_filter_cols.count);
|
||||
}
|
||||
|
||||
/* get the activity count */
|
||||
int activityCount = 0;
|
||||
if (auto const iter = activity_->get_active(); iter)
|
||||
/* get the mode count */
|
||||
int modeCount = 0;
|
||||
if (auto const iter = show_mode_->get_active(); iter)
|
||||
{
|
||||
activityCount = iter->get_value(activity_filter_cols.count);
|
||||
modeCount = iter->get_value(show_mode_filter_cols.count);
|
||||
}
|
||||
|
||||
/* set the text */
|
||||
if (auto const new_markup = visibleCount == std::min(activityCount, trackerCount) ?
|
||||
if (auto const new_markup = visibleCount == std::min(modeCount, trackerCount) ?
|
||||
_("_Show:") :
|
||||
fmt::format(fmt::runtime(_("_Show {count:L} of:")), fmt::arg("count", visibleCount));
|
||||
new_markup != show_lb_->get_label().raw())
|
||||
@@ -606,14 +607,14 @@ void FilterBar::Impl::update_count_label_idle()
|
||||
|
||||
void FilterBar::Impl::update_filter_models(Torrent::ChangeFlags changes)
|
||||
{
|
||||
static auto TR_CONSTEXPR23 activity_flags = Torrent::ChangeFlag::ACTIVE_PEERS_DOWN | Torrent::ChangeFlag::ACTIVE_PEERS_UP |
|
||||
static auto TR_CONSTEXPR23 show_mode_flags = Torrent::ChangeFlag::ACTIVE_PEERS_DOWN | Torrent::ChangeFlag::ACTIVE_PEERS_UP |
|
||||
Torrent::ChangeFlag::ACTIVE | Torrent::ChangeFlag::ACTIVITY | Torrent::ChangeFlag::ERROR_CODE |
|
||||
Torrent::ChangeFlag::FINISHED;
|
||||
static auto constexpr tracker_flags = Torrent::ChangeFlag::TRACKERS;
|
||||
|
||||
if (changes.test(activity_flags))
|
||||
if (changes.test(show_mode_flags))
|
||||
{
|
||||
activity_filter_model_update();
|
||||
show_mode_filter_model_update();
|
||||
}
|
||||
|
||||
if (changes.test(tracker_flags))
|
||||
@@ -623,7 +624,7 @@ void FilterBar::Impl::update_filter_models(Torrent::ChangeFlags changes)
|
||||
|
||||
filter_->update(changes);
|
||||
|
||||
if (changes.test(activity_flags | tracker_flags))
|
||||
if (changes.test(show_mode_flags | tracker_flags))
|
||||
{
|
||||
update_count_label_idle();
|
||||
}
|
||||
@@ -657,7 +658,7 @@ void FilterBarExtraInit::class_init(void* klass, void* /*user_data*/)
|
||||
|
||||
gtk_widget_class_set_template_from_resource(widget_klass, gtr_get_full_resource_path("FilterBar.ui").c_str());
|
||||
|
||||
gtk_widget_class_bind_template_child_full(widget_klass, "activity_combo", FALSE, 0);
|
||||
gtk_widget_class_bind_template_child_full(widget_klass, "show_mode_combo", FALSE, 0);
|
||||
gtk_widget_class_bind_template_child_full(widget_klass, "tracker_combo", FALSE, 0);
|
||||
gtk_widget_class_bind_template_child_full(widget_klass, "text_entry", FALSE, 0);
|
||||
gtk_widget_class_bind_template_child_full(widget_klass, "show_label", FALSE, 0);
|
||||
@@ -692,9 +693,9 @@ FilterBar::~FilterBar() = default;
|
||||
FilterBar::Impl::Impl(FilterBar& widget, Glib::RefPtr<Session> const& core)
|
||||
: widget_(widget)
|
||||
, core_(core)
|
||||
, activity_model_(activity_filter_model_new())
|
||||
, show_mode_model_(show_mode_filter_model_new())
|
||||
, tracker_model_(tracker_filter_model_new())
|
||||
, activity_(get_template_child<Gtk::ComboBox>("activity_combo"))
|
||||
, show_mode_(get_template_child<Gtk::ComboBox>("show_mode_combo"))
|
||||
, tracker_(get_template_child<Gtk::ComboBox>("tracker_combo"))
|
||||
, entry_(get_template_child<Gtk::Entry>("text_entry"))
|
||||
, show_lb_(get_template_child<Gtk::Label>("show_label"))
|
||||
@@ -704,10 +705,10 @@ FilterBar::Impl::Impl(FilterBar& widget, Glib::RefPtr<Session> const& core)
|
||||
update_filter_models_on_change_tag_ = core_->signal_torrents_changed().connect(
|
||||
sigc::hide<0>(sigc::mem_fun(*this, &Impl::update_filter_models_idle)));
|
||||
|
||||
activity_filter_model_update();
|
||||
show_mode_filter_model_update();
|
||||
tracker_filter_model_update();
|
||||
|
||||
activity_combo_box_init(*activity_);
|
||||
show_mode_combo_box_init(*show_mode_);
|
||||
tracker_combo_box_init(*tracker_);
|
||||
|
||||
filter_->signal_changed().connect([this](auto /*changes*/) { update_count_label_idle(); });
|
||||
@@ -715,7 +716,7 @@ FilterBar::Impl::Impl(FilterBar& widget, Glib::RefPtr<Session> const& core)
|
||||
filter_model_ = FilterListModel<Torrent>::create(core_->get_sorted_model(), filter_);
|
||||
|
||||
tracker_->signal_changed().connect(sigc::mem_fun(*this, &Impl::update_filter_tracker));
|
||||
activity_->signal_changed().connect(sigc::mem_fun(*this, &Impl::update_filter_activity));
|
||||
show_mode_->signal_changed().connect(sigc::mem_fun(*this, &Impl::update_filter_show_mode));
|
||||
|
||||
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
||||
entry_->signal_icon_release().connect([this](auto /*icon_position*/) { entry_->set_text({}); });
|
||||
|
||||
12
gtk/Prefs.cc
12
gtk/Prefs.cc
@@ -7,7 +7,10 @@
|
||||
#include "GtkCompat.h"
|
||||
#include "PrefsDialog.h"
|
||||
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/serializer.h>
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/variant.h>
|
||||
|
||||
@@ -17,6 +20,8 @@
|
||||
#include <string_view>
|
||||
|
||||
using namespace std::literals;
|
||||
using namespace transmission::app;
|
||||
using libtransmission::serializer::to_variant;
|
||||
|
||||
std::string gl_confdir;
|
||||
|
||||
@@ -71,7 +76,7 @@ namespace
|
||||
map.try_emplace(TR_KEY_show_statusbar, true);
|
||||
map.try_emplace(TR_KEY_show_toolbar, true);
|
||||
map.try_emplace(TR_KEY_show_tracker_scrapes, false);
|
||||
map.try_emplace(TR_KEY_sort_mode, "sort-by-name"sv);
|
||||
map.try_emplace(TR_KEY_sort_mode, to_variant(DefaultSortMode));
|
||||
map.try_emplace(TR_KEY_sort_reversed, false);
|
||||
map.try_emplace(TR_KEY_statusbar_stats, "total-ratio"sv);
|
||||
map.try_emplace(TR_KEY_torrent_added_notification_enabled, true);
|
||||
@@ -121,6 +126,11 @@ tr_variant& gtr_pref_get_all()
|
||||
return getPrefs();
|
||||
}
|
||||
|
||||
tr_variant::Map& gtr_pref_get_map()
|
||||
{
|
||||
return *getPrefs().get_if<tr_variant::Map>();
|
||||
}
|
||||
|
||||
int64_t gtr_pref_int_get(tr_quark const key)
|
||||
{
|
||||
int64_t i = 0;
|
||||
|
||||
13
gtk/Prefs.h
13
gtk/Prefs.h
@@ -6,12 +6,25 @@
|
||||
|
||||
#include <libtransmission/transmission.h> /* tr_variant, tr_session */
|
||||
#include <libtransmission/quark.h>
|
||||
#include <libtransmission/serializer.h>
|
||||
#include <libtransmission/variant.h>
|
||||
|
||||
#include <cstdint> // int64_t
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
[[nodiscard]] tr_variant::Map& gtr_pref_get_map();
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] std::optional<T> gtr_pref_get(tr_quark const key)
|
||||
{
|
||||
using namespace libtransmission::serializer;
|
||||
auto const& map = gtr_pref_get_map();
|
||||
auto const iter = map.find(key);
|
||||
return iter != std::end(map) ? to_value<T>(iter->second) : std::nullopt;
|
||||
}
|
||||
|
||||
void gtr_pref_init(std::string_view config_dir);
|
||||
|
||||
int64_t gtr_pref_int_get(tr_quark key);
|
||||
|
||||
@@ -478,7 +478,10 @@ void Session::Impl::on_pref_changed(tr_quark const key)
|
||||
switch (key)
|
||||
{
|
||||
case TR_KEY_sort_mode:
|
||||
sorter_->set_mode(gtr_pref_string_get(TR_KEY_sort_mode));
|
||||
if (auto const sort_mode = gtr_pref_get<SortMode>(TR_KEY_sort_mode))
|
||||
{
|
||||
sorter_->set_mode(*sort_mode);
|
||||
}
|
||||
break;
|
||||
|
||||
case TR_KEY_sort_reversed:
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
#include "GtkCompat.h"
|
||||
#include "Torrent.h"
|
||||
|
||||
#include <libtransmission-app/favicon-cache.h>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/favicon-cache.h>
|
||||
#include <libtransmission/variant.h>
|
||||
|
||||
#include <gdkmm/pixbuf.h>
|
||||
|
||||
@@ -19,24 +19,25 @@ TorrentFilter::TorrentFilter()
|
||||
{
|
||||
}
|
||||
|
||||
void TorrentFilter::set_activity(Activity type)
|
||||
void TorrentFilter::set_mode(ShowMode const mode)
|
||||
{
|
||||
if (activity_type_ == type)
|
||||
if (show_mode_ == mode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto change = Change::DIFFERENT;
|
||||
if (activity_type_ == Activity::ALL)
|
||||
|
||||
if (show_mode_ == ShowMode::ShowAll)
|
||||
{
|
||||
change = Change::MORE_STRICT;
|
||||
}
|
||||
else if (type == Activity::ALL)
|
||||
else if (mode == ShowMode::ShowAll)
|
||||
{
|
||||
change = Change::LESS_STRICT;
|
||||
}
|
||||
|
||||
activity_type_ = type;
|
||||
show_mode_ = mode;
|
||||
changed(change);
|
||||
}
|
||||
|
||||
@@ -98,9 +99,9 @@ void TorrentFilter::set_text(Glib::ustring const& text)
|
||||
changed(change);
|
||||
}
|
||||
|
||||
bool TorrentFilter::match_activity(Torrent const& torrent) const
|
||||
bool TorrentFilter::match_mode(Torrent const& torrent) const
|
||||
{
|
||||
return match_activity(torrent, activity_type_);
|
||||
return match_mode(torrent, show_mode_);
|
||||
}
|
||||
|
||||
bool TorrentFilter::match_tracker(Torrent const& torrent) const
|
||||
@@ -115,12 +116,12 @@ bool TorrentFilter::match_text(Torrent const& torrent) const
|
||||
|
||||
bool TorrentFilter::match(Torrent const& torrent) const
|
||||
{
|
||||
return match_activity(torrent) && match_tracker(torrent) && match_text(torrent);
|
||||
return match_mode(torrent) && match_tracker(torrent) && match_text(torrent);
|
||||
}
|
||||
|
||||
bool TorrentFilter::matches_all() const
|
||||
{
|
||||
return activity_type_ == Activity::ALL && tracker_type_ == Tracker::ALL && text_.empty();
|
||||
return show_mode_ == ShowMode::ShowAll && tracker_type_ == Tracker::ALL && text_.empty();
|
||||
}
|
||||
|
||||
void TorrentFilter::update(Torrent::ChangeFlags changes)
|
||||
@@ -129,23 +130,23 @@ void TorrentFilter::update(Torrent::ChangeFlags changes)
|
||||
|
||||
bool refilter_needed = false;
|
||||
|
||||
if (activity_type_ != Activity::ALL)
|
||||
if (show_mode_ != ShowMode::ShowAll)
|
||||
{
|
||||
static auto TR_CONSTEXPR23 ActivityFlags = std::array<std::pair<Activity, Torrent::ChangeFlags>, 7U>{ {
|
||||
{ Activity::DOWNLOADING, Flag::ACTIVITY },
|
||||
{ Activity::SEEDING, Flag::ACTIVITY },
|
||||
{ Activity::ACTIVE, Flag::ACTIVE_PEER_COUNT | Flag::ACTIVITY },
|
||||
{ Activity::PAUSED, Flag::ACTIVITY },
|
||||
{ Activity::FINISHED, Flag::FINISHED },
|
||||
{ Activity::VERIFYING, Flag::ACTIVITY },
|
||||
{ Activity::ERROR, Flag::ERROR_CODE },
|
||||
static auto TR_CONSTEXPR23 ShowModeFlags = std::array<std::pair<ShowMode, Torrent::ChangeFlags>, 7U>{ {
|
||||
{ ShowMode::ShowActive, Flag::ACTIVE_PEER_COUNT | Flag::ACTIVITY },
|
||||
{ ShowMode::ShowDownloading, Flag::ACTIVITY },
|
||||
{ ShowMode::ShowError, Flag::ERROR_CODE },
|
||||
{ ShowMode::ShowFinished, Flag::FINISHED },
|
||||
{ ShowMode::ShowPaused, Flag::ACTIVITY },
|
||||
{ ShowMode::ShowSeeding, Flag::ACTIVITY },
|
||||
{ ShowMode::ShowVerifying, Flag::ACTIVITY },
|
||||
} };
|
||||
|
||||
auto const iter = std::find_if(
|
||||
std::begin(ActivityFlags),
|
||||
std::end(ActivityFlags),
|
||||
[key = activity_type_](auto const& row) { return row.first == key; });
|
||||
refilter_needed = iter != std::end(ActivityFlags) && changes.test(iter->second);
|
||||
std::begin(ShowModeFlags),
|
||||
std::end(ShowModeFlags),
|
||||
[key = show_mode_](auto const& row) { return row.first == key; });
|
||||
refilter_needed = iter != std::end(ShowModeFlags) && changes.test(iter->second);
|
||||
}
|
||||
|
||||
if (!refilter_needed)
|
||||
@@ -170,43 +171,42 @@ Glib::RefPtr<TorrentFilter> TorrentFilter::create()
|
||||
return Glib::make_refptr_for_instance(new TorrentFilter());
|
||||
}
|
||||
|
||||
bool TorrentFilter::match_activity(Torrent const& torrent, Activity type)
|
||||
bool TorrentFilter::match_mode(Torrent const& torrent, ShowMode const type)
|
||||
{
|
||||
auto activity = tr_torrent_activity();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Activity::ALL:
|
||||
case ShowMode::ShowAll:
|
||||
return true;
|
||||
|
||||
case Activity::DOWNLOADING:
|
||||
case ShowMode::ShowDownloading:
|
||||
activity = torrent.get_activity();
|
||||
return activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_DOWNLOAD_WAIT;
|
||||
|
||||
case Activity::SEEDING:
|
||||
case ShowMode::ShowSeeding:
|
||||
activity = torrent.get_activity();
|
||||
return activity == TR_STATUS_SEED || activity == TR_STATUS_SEED_WAIT;
|
||||
|
||||
case Activity::ACTIVE:
|
||||
case ShowMode::ShowActive:
|
||||
return torrent.get_active_peer_count() > 0 || torrent.get_activity() == TR_STATUS_CHECK;
|
||||
|
||||
case Activity::PAUSED:
|
||||
case ShowMode::ShowPaused:
|
||||
return torrent.get_activity() == TR_STATUS_STOPPED;
|
||||
|
||||
case Activity::FINISHED:
|
||||
case ShowMode::ShowFinished:
|
||||
return torrent.get_finished();
|
||||
|
||||
case Activity::VERIFYING:
|
||||
case ShowMode::ShowVerifying:
|
||||
activity = torrent.get_activity();
|
||||
return activity == TR_STATUS_CHECK || activity == TR_STATUS_CHECK_WAIT;
|
||||
|
||||
case Activity::ERROR:
|
||||
case ShowMode::ShowError:
|
||||
return torrent.get_error_code() != 0;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
return true;
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TorrentFilter::match_tracker(Torrent const& torrent, Tracker type, Glib::ustring const& host)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "FilterBase.h"
|
||||
#include "Torrent.h"
|
||||
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
#include <glibmm/refptr.h>
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
@@ -16,17 +18,7 @@
|
||||
class TorrentFilter : public FilterBase<Torrent>
|
||||
{
|
||||
public:
|
||||
enum class Activity : int8_t
|
||||
{
|
||||
ALL,
|
||||
DOWNLOADING,
|
||||
SEEDING,
|
||||
ACTIVE,
|
||||
PAUSED,
|
||||
FINISHED,
|
||||
VERIFYING,
|
||||
ERROR,
|
||||
};
|
||||
using ShowMode = transmission::app::ShowMode;
|
||||
|
||||
enum class Tracker : int8_t
|
||||
{
|
||||
@@ -35,13 +27,13 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
void set_activity(Activity type);
|
||||
void set_mode(ShowMode mode);
|
||||
void set_tracker(Tracker type, Glib::ustring const& host);
|
||||
void set_text(Glib::ustring const& text);
|
||||
|
||||
bool match_activity(Torrent const& torrent) const;
|
||||
bool match_tracker(Torrent const& torrent) const;
|
||||
bool match_mode(Torrent const& torrent) const;
|
||||
bool match_text(Torrent const& torrent) const;
|
||||
bool match_tracker(Torrent const& torrent) const;
|
||||
|
||||
// FilterBase<Torrent>
|
||||
bool match(Torrent const& torrent) const override;
|
||||
@@ -51,7 +43,7 @@ public:
|
||||
|
||||
static Glib::RefPtr<TorrentFilter> create();
|
||||
|
||||
static bool match_activity(Torrent const& torrent, Activity type);
|
||||
static bool match_mode(Torrent const& torrent, ShowMode mode);
|
||||
static bool match_tracker(Torrent const& torrent, Tracker type, Glib::ustring const& host);
|
||||
static bool match_text(Torrent const& torrent, Glib::ustring const& text);
|
||||
|
||||
@@ -59,7 +51,7 @@ private:
|
||||
TorrentFilter();
|
||||
|
||||
private:
|
||||
Activity activity_type_ = Activity::ALL;
|
||||
ShowMode show_mode_ = transmission::app::DefaultShowMode;
|
||||
Tracker tracker_type_ = Tracker::ALL;
|
||||
Glib::ustring tracker_host_;
|
||||
Glib::ustring text_;
|
||||
|
||||
@@ -9,18 +9,24 @@
|
||||
#include "SorterBase.hh"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/tr-macros.h>
|
||||
#include <libtransmission/utils.h>
|
||||
|
||||
#include <small/map.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
using namespace transmission::app;
|
||||
|
||||
namespace
|
||||
{
|
||||
using CompareFunc = int (*)(Torrent const&, Torrent const&);
|
||||
|
||||
constexpr bool is_valid_eta(time_t value)
|
||||
{
|
||||
@@ -150,6 +156,12 @@ int compare_by_progress(Torrent const& lhs, Torrent const& rhs)
|
||||
return compare_by_ratio(lhs, rhs);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||
int compare_by_id(Torrent const& lhs, Torrent const& rhs)
|
||||
{
|
||||
return -tr_compare_3way(lhs.get_id(), rhs.get_id());
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
||||
int compare_by_eta(Torrent const& lhs, Torrent const& rhs)
|
||||
{
|
||||
@@ -171,7 +183,6 @@ int compare_by_state(Torrent const& lhs, Torrent const& rhs)
|
||||
|
||||
return compare_by_queue(lhs, rhs);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TorrentSorter::TorrentSorter()
|
||||
@@ -179,25 +190,23 @@ TorrentSorter::TorrentSorter()
|
||||
{
|
||||
}
|
||||
|
||||
void TorrentSorter::set_mode(std::string_view mode)
|
||||
void TorrentSorter::set_mode(SortMode const mode)
|
||||
{
|
||||
static auto constexpr DefaultCompareFunc = &compare_by_name;
|
||||
static auto constexpr CompareFuncs = std::array<std::pair<std::string_view, CompareFunc>, 9U>{ {
|
||||
{ "sort-by-activity"sv, &compare_by_activity },
|
||||
{ "sort-by-age"sv, &compare_by_age },
|
||||
{ "sort-by-name"sv, &compare_by_name },
|
||||
{ "sort-by-progress"sv, &compare_by_progress },
|
||||
{ "sort-by-queue"sv, &compare_by_queue },
|
||||
{ "sort-by-ratio"sv, &compare_by_ratio },
|
||||
{ "sort-by-size"sv, &compare_by_size },
|
||||
{ "sort-by-state"sv, &compare_by_state },
|
||||
{ "sort-by-time-left"sv, &compare_by_eta },
|
||||
static auto const CompareFuncs = small::max_size_map<SortMode, CompareFunc, SortModeCount>{ {
|
||||
{ SortMode::SortByActivity, &compare_by_activity },
|
||||
{ SortMode::SortByAge, &compare_by_age },
|
||||
{ SortMode::SortByEta, &compare_by_eta },
|
||||
{ SortMode::SortById, &compare_by_id },
|
||||
{ SortMode::SortByName, &compare_by_name },
|
||||
{ SortMode::SortByProgress, &compare_by_progress },
|
||||
{ SortMode::SortByQueue, &compare_by_queue },
|
||||
{ SortMode::SortByRatio, &compare_by_ratio },
|
||||
{ SortMode::SortBySize, &compare_by_size },
|
||||
{ SortMode::SortByState, &compare_by_state },
|
||||
} };
|
||||
|
||||
auto const iter = std::find_if(
|
||||
std::begin(CompareFuncs),
|
||||
std::end(CompareFuncs),
|
||||
[key = mode](auto const& row) { return row.first == key; });
|
||||
auto const iter = CompareFuncs.find(mode);
|
||||
auto const compare_func = iter != std::end(CompareFuncs) ? iter->second : DefaultCompareFunc;
|
||||
if (compare_func_ == compare_func)
|
||||
{
|
||||
|
||||
@@ -8,14 +8,18 @@
|
||||
#include "SorterBase.h"
|
||||
#include "Torrent.h"
|
||||
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
#include <glibmm/refptr.h>
|
||||
|
||||
using SortMode = transmission::app::SortMode;
|
||||
|
||||
class TorrentSorter : public SorterBase<Torrent>
|
||||
{
|
||||
using CompareFunc = int (*)(Torrent const&, Torrent const&);
|
||||
|
||||
public:
|
||||
void set_mode(std::string_view mode);
|
||||
void set_mode(SortMode mode);
|
||||
void set_reversed(bool is_reversed);
|
||||
|
||||
// SorterBase<Torrent>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "Prefs.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission-app/app.h>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/version.h>
|
||||
@@ -48,11 +50,9 @@ Glib::OptionEntry create_option_entry(Glib::ustring const& long_name, gchar shor
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
/* init libtransmission */
|
||||
tr_lib_init();
|
||||
transmission::app::init();
|
||||
|
||||
/* init i18n */
|
||||
tr_locale_set_global("");
|
||||
bindtextdomain(AppTranslationDomainName, TRANSMISSIONLOCALEDIR);
|
||||
bind_textdomain_codeset(AppTranslationDomainName, "UTF-8");
|
||||
textdomain(AppTranslationDomainName);
|
||||
|
||||
@@ -201,47 +201,47 @@
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Activity</attribute>
|
||||
<attribute name="target">sort-by-activity</attribute>
|
||||
<attribute name="target">sort_by_activity</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by A_ge</attribute>
|
||||
<attribute name="target">sort-by-age</attribute>
|
||||
<attribute name="target">sort_by_age</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Name</attribute>
|
||||
<attribute name="target">sort-by-name</attribute>
|
||||
<attribute name="target">sort_by_name</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Progress</attribute>
|
||||
<attribute name="target">sort-by-progress</attribute>
|
||||
<attribute name="target">sort_by_progress</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Queue</attribute>
|
||||
<attribute name="target">sort-by-queue</attribute>
|
||||
<attribute name="target">sort_by_queue</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Rati_o</attribute>
|
||||
<attribute name="target">sort-by-ratio</attribute>
|
||||
<attribute name="target">sort_by_ratio</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Si_ze</attribute>
|
||||
<attribute name="target">sort-by-size</attribute>
|
||||
<attribute name="target">sort_by_size</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Stat_e</attribute>
|
||||
<attribute name="target">sort-by-state</attribute>
|
||||
<attribute name="target">sort_by_state</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Time _Left</attribute>
|
||||
<attribute name="target">sort-by-time-left</attribute>
|
||||
<attribute name="target">sort_by_time_left</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
@@ -308,47 +308,47 @@
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Activity</attribute>
|
||||
<attribute name="target">sort-by-activity</attribute>
|
||||
<attribute name="target">sort_by_activity</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by A_ge</attribute>
|
||||
<attribute name="target">sort-by-age</attribute>
|
||||
<attribute name="target">sort_by_age</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Name</attribute>
|
||||
<attribute name="target">sort-by-name</attribute>
|
||||
<attribute name="target">sort_by_name</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Progress</attribute>
|
||||
<attribute name="target">sort-by-progress</attribute>
|
||||
<attribute name="target">sort_by_progress</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by _Queue</attribute>
|
||||
<attribute name="target">sort-by-queue</attribute>
|
||||
<attribute name="target">sort_by_queue</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Rati_o</attribute>
|
||||
<attribute name="target">sort-by-ratio</attribute>
|
||||
<attribute name="target">sort_by_ratio</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Si_ze</attribute>
|
||||
<attribute name="target">sort-by-size</attribute>
|
||||
<attribute name="target">sort_by_size</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Stat_e</attribute>
|
||||
<attribute name="target">sort-by-state</attribute>
|
||||
<attribute name="target">sort_by_state</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="action">win.sort-torrents</attribute>
|
||||
<attribute name="label" translatable="yes">Sort by Time _Left</attribute>
|
||||
<attribute name="target">sort-by-time-left</attribute>
|
||||
<attribute name="target">sort_by_time_left</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">_Show:</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="mnemonic-widget">activity_combo</property>
|
||||
<property name="mnemonic-widget">show_mode_combo</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
@@ -21,7 +21,7 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="activity_combo">
|
||||
<object class="GtkComboBox" id="show_mode_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-end">6</property>
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
<object class="GtkLabel" id="show_label">
|
||||
<property name="label" translatable="1">_Show:</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">activity_combo</property>
|
||||
<property name="mnemonic-widget">show_mode_combo</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="activity_combo">
|
||||
<object class="GtkComboBox" id="show_mode_combo">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="margin-end">6</property>
|
||||
</object>
|
||||
|
||||
55
libtransmission-app/.clang-tidy
Normal file
55
libtransmission-app/.clang-tidy
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
HeaderFilterRegex: .*/libtransmission/.*
|
||||
|
||||
# TODO: Enable `portability-template-virtual-member-function` after https://github.com/llvm/llvm-project/issues/139031 is fixed
|
||||
# PRs welcome to fix & re-enable any of these explicitly-disabled checks
|
||||
Checks: >
|
||||
bugprone-*,
|
||||
-bugprone-branch-clone,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-narrowing-conversions,
|
||||
cert-*,
|
||||
-cert-err58-cpp,
|
||||
-cert-int09-c,
|
||||
clang-analyzer-*,
|
||||
-clang-analyzer-optin.core.EnumCastOutOfRange,
|
||||
cppcoreguidelines-avoid-do-while,
|
||||
cppcoreguidelines-avoid-goto,
|
||||
cppcoreguidelines-avoid-reference-coroutine-parameters,
|
||||
cppcoreguidelines-init-variables,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-no-malloc,
|
||||
cppcoreguidelines-prefer-member-initializer,
|
||||
cppcoreguidelines-pro-type-cstyle-cast,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
cppcoreguidelines-slicing,
|
||||
cppcoreguidelines-special-member-functions,
|
||||
cppcoreguidelines-virtual-class-destructor,
|
||||
google-explicit-constructor,
|
||||
misc-*,
|
||||
-misc-include-cleaner,
|
||||
-misc-no-recursion,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
modernize-*,
|
||||
-modernize-use-trailing-return-type,
|
||||
performance-*,
|
||||
-performance-move-const-arg,
|
||||
portability-*,
|
||||
-portability-template-virtual-member-function,
|
||||
readability-*,
|
||||
-readability-enum-initial-value,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-identifier-length,
|
||||
-readability-magic-numbers,
|
||||
-readability-qualified-auto,
|
||||
|
||||
CheckOptions:
|
||||
- { key: cppcoreguidelines-avoid-do-while.IgnoreMacros, value: true }
|
||||
- { key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor, value: true }
|
||||
- { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase }
|
||||
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
|
||||
- { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
|
||||
- { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ }
|
||||
- { key: readability-identifier-naming.VariableCase, value: lower_case }
|
||||
- { key: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix, value: true }
|
||||
25
libtransmission-app/CMakeLists.txt
Normal file
25
libtransmission-app/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
include(CheckLibraryExists)
|
||||
include(CheckSymbolExists)
|
||||
|
||||
set(LIBNAME ${TR_NAME}-app)
|
||||
|
||||
add_library(${LIBNAME} STATIC)
|
||||
add_library(transmission::app ALIAS ${LIBNAME})
|
||||
|
||||
target_sources(${LIBNAME}
|
||||
PRIVATE
|
||||
app.cc
|
||||
app.h
|
||||
converters.cc
|
||||
converters.h
|
||||
display-modes.h
|
||||
favicon-cache.h)
|
||||
|
||||
target_include_directories(${LIBNAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||
|
||||
target_link_libraries(${LIBNAME}
|
||||
PUBLIC
|
||||
fmt::fmt-header-only)
|
||||
19
libtransmission-app/app.cc
Normal file
19
libtransmission-app/app.cc
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
#include <libtransmission/utils.h> // tr_lib_init()
|
||||
|
||||
#include "libtransmission-app/app.h"
|
||||
#include "libtransmission-app/converters.h"
|
||||
|
||||
namespace transmission::app
|
||||
{
|
||||
void init()
|
||||
{
|
||||
tr_lib_init();
|
||||
tr_locale_set_global("");
|
||||
detail::register_app_converters();
|
||||
}
|
||||
} // namespace transmission::app
|
||||
14
libtransmission-app/app.h
Normal file
14
libtransmission-app/app.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace transmission::app
|
||||
{
|
||||
|
||||
// should be called once when starting the app
|
||||
void init();
|
||||
|
||||
} // namespace transmission::app
|
||||
140
libtransmission-app/converters.cc
Normal file
140
libtransmission-app/converters.cc
Normal file
@@ -0,0 +1,140 @@
|
||||
// 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.
|
||||
|
||||
#include <array>
|
||||
#include <mutex>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "libtransmission/serializer.h"
|
||||
#include "libtransmission/variant.h"
|
||||
|
||||
#include "libtransmission-app/display-modes.h"
|
||||
#include "libtransmission-app/converters.h"
|
||||
|
||||
namespace transmission::app::detail
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template<typename T, size_t N>
|
||||
using Lookup = std::array<std::pair<std::string_view, T>, N>;
|
||||
|
||||
// ---
|
||||
|
||||
auto constexpr ShowKeys = std::array<std::pair<tr_quark, ShowMode>, ShowModeCount>{ {
|
||||
{ TR_KEY_show_active, ShowMode::ShowActive },
|
||||
{ TR_KEY_show_all, ShowMode::ShowAll },
|
||||
{ TR_KEY_show_downloading, ShowMode::ShowDownloading },
|
||||
{ TR_KEY_show_error, ShowMode::ShowError },
|
||||
{ TR_KEY_show_finished, ShowMode::ShowFinished },
|
||||
{ TR_KEY_show_paused, ShowMode::ShowPaused },
|
||||
{ TR_KEY_show_seeding, ShowMode::ShowSeeding },
|
||||
{ TR_KEY_show_verifying, ShowMode::ShowVerifying },
|
||||
} };
|
||||
|
||||
bool to_show_mode(tr_variant const& src, ShowMode* tgt)
|
||||
{
|
||||
static constexpr auto& Keys = ShowKeys;
|
||||
|
||||
if (auto const str = src.value_if<std::string_view>())
|
||||
{
|
||||
if (auto const needle = tr_quark_lookup(*str))
|
||||
{
|
||||
for (auto const& [key, val] : Keys)
|
||||
{
|
||||
if (needle == key)
|
||||
{
|
||||
*tgt = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
tr_variant from_show_mode(ShowMode const& src)
|
||||
{
|
||||
static constexpr auto& Keys = ShowKeys;
|
||||
|
||||
for (auto const& [key, val] : Keys)
|
||||
{
|
||||
if (src == val)
|
||||
{
|
||||
return tr_variant::unmanaged_string(key);
|
||||
}
|
||||
}
|
||||
|
||||
return tr_variant::unmanaged_string(TR_KEY_show_all);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
auto constexpr SortKeys = std::array<std::pair<tr_quark, SortMode>, SortModeCount>{ {
|
||||
{ TR_KEY_sort_by_activity, SortMode::SortByActivity },
|
||||
{ TR_KEY_sort_by_age, SortMode::SortByAge },
|
||||
{ TR_KEY_sort_by_eta, SortMode::SortByEta },
|
||||
{ TR_KEY_sort_by_id, SortMode::SortById },
|
||||
{ TR_KEY_sort_by_name, SortMode::SortByName },
|
||||
{ TR_KEY_sort_by_progress, SortMode::SortByProgress },
|
||||
{ TR_KEY_sort_by_queue, SortMode::SortByQueue },
|
||||
{ TR_KEY_sort_by_ratio, SortMode::SortByRatio },
|
||||
{ TR_KEY_sort_by_size, SortMode::SortBySize },
|
||||
{ TR_KEY_sort_by_state, SortMode::SortByState },
|
||||
} };
|
||||
|
||||
bool to_sort_mode(tr_variant const& src, SortMode* tgt)
|
||||
{
|
||||
static constexpr auto& Keys = SortKeys;
|
||||
|
||||
if (auto const str = src.value_if<std::string_view>())
|
||||
{
|
||||
if (auto const needle = tr_quark_lookup(*str))
|
||||
{
|
||||
for (auto const& [key, val] : Keys)
|
||||
{
|
||||
if (needle == key)
|
||||
{
|
||||
*tgt = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
tr_variant from_sort_mode(SortMode const& src)
|
||||
{
|
||||
static constexpr auto& Keys = SortKeys;
|
||||
|
||||
for (auto const& [key, val] : Keys)
|
||||
{
|
||||
if (src == val)
|
||||
{
|
||||
return tr_variant::unmanaged_string(key);
|
||||
}
|
||||
}
|
||||
|
||||
return tr_variant::unmanaged_string(TR_KEY_sort_by_name);
|
||||
}
|
||||
} // unnamed namespace
|
||||
|
||||
void register_app_converters()
|
||||
{
|
||||
static auto once = std::once_flag{};
|
||||
std::call_once(
|
||||
once,
|
||||
[]
|
||||
{
|
||||
using Converters = libtransmission::serializer::Converters;
|
||||
Converters::add(to_show_mode, from_show_mode);
|
||||
Converters::add(to_sort_mode, from_sort_mode);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace transmission::app::detail
|
||||
13
libtransmission-app/converters.h
Normal file
13
libtransmission-app/converters.h
Normal file
@@ -0,0 +1,13 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace transmission::app::detail
|
||||
{
|
||||
|
||||
void register_app_converters();
|
||||
|
||||
} // namespace transmission::app::detail
|
||||
40
libtransmission-app/display-modes.h
Normal file
40
libtransmission-app/display-modes.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace transmission::app
|
||||
{
|
||||
enum class ShowMode
|
||||
{
|
||||
ShowAll,
|
||||
ShowActive,
|
||||
ShowDownloading,
|
||||
ShowSeeding,
|
||||
ShowPaused,
|
||||
ShowFinished,
|
||||
ShowVerifying,
|
||||
ShowError,
|
||||
};
|
||||
inline auto constexpr ShowModeCount = 8U;
|
||||
inline auto constexpr DefaultShowMode = ShowMode::ShowAll;
|
||||
|
||||
enum class SortMode
|
||||
{
|
||||
SortByActivity,
|
||||
SortByAge,
|
||||
SortByEta,
|
||||
SortByName,
|
||||
SortByProgress,
|
||||
SortByQueue,
|
||||
SortByRatio,
|
||||
SortBySize,
|
||||
SortByState,
|
||||
SortById,
|
||||
};
|
||||
inline auto constexpr SortModeCount = 10U;
|
||||
inline auto constexpr DefaultSortMode = SortMode::SortByName;
|
||||
|
||||
} // namespace transmission::app
|
||||
@@ -55,7 +55,6 @@ target_sources(${TR_NAME}
|
||||
error-types.h
|
||||
error.cc
|
||||
error.h
|
||||
favicon-cache.h
|
||||
file-capacity.cc
|
||||
file-piece-map.cc
|
||||
file-piece-map.h
|
||||
@@ -307,7 +306,6 @@ if(INSTALL_LIB)
|
||||
FILES
|
||||
error-types.h
|
||||
error.h
|
||||
favicon-cache.h
|
||||
file.h
|
||||
log.h
|
||||
makemeta.h
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
@@ -213,6 +214,23 @@ private:
|
||||
static inline ConverterStorage<T> converter_storage;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] std::optional<T> to_value(tr_variant const& var)
|
||||
{
|
||||
if (auto ret = T{}; Converters::deserialize<T>(var, &ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] tr_variant to_variant(T const& val)
|
||||
{
|
||||
return Converters::serialize<T>(val);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <QTranslator>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include <libtransmission/favicon-cache.h>
|
||||
#include <libtransmission-app/favicon-cache.h>
|
||||
|
||||
#include "AddData.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
@@ -211,6 +211,7 @@ target_include_directories(${TR_NAME}-qt
|
||||
|
||||
target_link_libraries(${TR_NAME}-qt
|
||||
PRIVATE
|
||||
${TR_NAME}-app
|
||||
${TR_NAME}
|
||||
transmission::qt_impl)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
TrackerStatsList = QMetaType::User,
|
||||
PeerList,
|
||||
FileList,
|
||||
FilterModeType,
|
||||
ShowModeType,
|
||||
SortModeType
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <libtransmission/favicon-cache.h>
|
||||
#include <libtransmission-app/favicon-cache.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPixmap>
|
||||
|
||||
@@ -45,25 +45,25 @@ FilterBarComboBox* FilterBar::createActivityCombo()
|
||||
auto* model = new QStandardItemModel{ this };
|
||||
|
||||
auto* row = new QStandardItem{ tr("All") };
|
||||
row->setData(FilterMode::SHOW_ALL, ACTIVITY_ROLE);
|
||||
row->setData(QVariant::fromValue(ShowMode::ShowAll), ACTIVITY_ROLE);
|
||||
model->appendRow(row);
|
||||
|
||||
model->appendRow(new QStandardItem{}); // separator
|
||||
FilterBarComboBoxDelegate::setSeparator(model, model->index(1, 0));
|
||||
|
||||
auto add_row = [model](auto const filter_mode, QString label, std::optional<icons::Type> const type)
|
||||
auto add_row = [model](auto const show_mode, QString label, std::optional<icons::Type> const type)
|
||||
{
|
||||
auto* row = type ? new QStandardItem{ icons::icon(*type), label } : new QStandardItem{ label };
|
||||
row->setData(filter_mode, ACTIVITY_ROLE);
|
||||
model->appendRow(row);
|
||||
auto* new_row = type ? new QStandardItem{ icons::icon(*type), label } : new QStandardItem{ label };
|
||||
new_row->setData(QVariant::fromValue(show_mode), ACTIVITY_ROLE);
|
||||
model->appendRow(new_row);
|
||||
};
|
||||
add_row(FilterMode::SHOW_ACTIVE, tr("Active"), icons::Type::TorrentStateActive);
|
||||
add_row(FilterMode::SHOW_SEEDING, tr("Seeding"), icons::Type::TorrentStateSeeding);
|
||||
add_row(FilterMode::SHOW_DOWNLOADING, tr("Downloading"), icons::Type::TorrentStateDownloading);
|
||||
add_row(FilterMode::SHOW_PAUSED, tr("Paused"), icons::Type::TorrentStatePaused);
|
||||
add_row(FilterMode::SHOW_FINISHED, tr("Finished"), {});
|
||||
add_row(FilterMode::SHOW_VERIFYING, tr("Verifying"), icons::Type::TorrentStateVerifying);
|
||||
add_row(FilterMode::SHOW_ERROR, tr("Error"), icons::Type::TorrentStateError);
|
||||
add_row(ShowMode::ShowActive, tr("Active"), icons::Type::TorrentStateActive);
|
||||
add_row(ShowMode::ShowSeeding, tr("Seeding"), icons::Type::TorrentStateSeeding);
|
||||
add_row(ShowMode::ShowDownloading, tr("Downloading"), icons::Type::TorrentStateDownloading);
|
||||
add_row(ShowMode::ShowPaused, tr("Paused"), icons::Type::TorrentStatePaused);
|
||||
add_row(ShowMode::ShowFinished, tr("Finished"), {});
|
||||
add_row(ShowMode::ShowVerifying, tr("Verifying"), icons::Type::TorrentStateVerifying);
|
||||
add_row(ShowMode::ShowError, tr("Error"), icons::Type::TorrentStateError);
|
||||
|
||||
c->setModel(model);
|
||||
return c;
|
||||
@@ -97,8 +97,6 @@ Torrent::fields_t constexpr TrackerFields = {
|
||||
return name;
|
||||
}
|
||||
|
||||
auto constexpr ActivityFields = FilterMode::TorrentFields;
|
||||
|
||||
} // namespace
|
||||
|
||||
void FilterBar::refreshTrackers()
|
||||
@@ -266,9 +264,9 @@ void FilterBar::refreshPref(int key)
|
||||
{
|
||||
case Prefs::FILTER_MODE:
|
||||
{
|
||||
auto const m = prefs_.get<FilterMode>(key);
|
||||
auto const show_mode = prefs_.get<ShowMode>(key);
|
||||
QAbstractItemModel const* const model = activity_combo_->model();
|
||||
QModelIndexList indices = model->match(model->index(0, 0), ACTIVITY_ROLE, m.mode());
|
||||
QModelIndexList indices = model->match(model->index(0, 0), ACTIVITY_ROLE, QVariant::fromValue(show_mode));
|
||||
activity_combo_->setCurrentIndex(indices.isEmpty() ? 0 : indices.first().row());
|
||||
break;
|
||||
}
|
||||
@@ -308,7 +306,7 @@ void FilterBar::onTorrentsChanged(torrent_ids_t const& ids, Torrent::fields_t co
|
||||
recountTrackersSoon();
|
||||
}
|
||||
|
||||
if ((changed_fields & ActivityFields).any())
|
||||
if ((changed_fields & ShowModeFields).any())
|
||||
{
|
||||
recountActivitySoon();
|
||||
}
|
||||
@@ -335,8 +333,8 @@ void FilterBar::onActivityIndexChanged(int i)
|
||||
{
|
||||
if (!is_bootstrapping_)
|
||||
{
|
||||
auto const mode = FilterMode(activity_combo_->itemData(i, ACTIVITY_ROLE).toInt());
|
||||
prefs_.set(Prefs::FILTER_MODE, mode);
|
||||
auto const show_mode = activity_combo_->itemData(i, ACTIVITY_ROLE).value<ShowMode>();
|
||||
prefs_.set(Prefs::FILTER_MODE, show_mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,10 +367,10 @@ void FilterBar::recount()
|
||||
for (int row = 0, n = model->rowCount(); row < n; ++row)
|
||||
{
|
||||
auto const index = model->index(row, 0);
|
||||
auto const mode = index.data(ACTIVITY_ROLE).toInt();
|
||||
auto const count = torrents_per_mode[mode];
|
||||
auto const show_mode = index.data(ACTIVITY_ROLE).value<ShowMode>();
|
||||
auto const count = torrents_per_mode[static_cast<int>(show_mode)];
|
||||
model->setData(index, count, FilterBarComboBox::CountRole);
|
||||
model->setData(index, getCountString(static_cast<size_t>(count)), FilterBarComboBox::CountStringRole);
|
||||
model->setData(index, getCountString(count), FilterBarComboBox::CountStringRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,33 +5,46 @@
|
||||
|
||||
#include "Filters.h"
|
||||
|
||||
// NB: if you change this function, update TorrentFields too
|
||||
bool FilterMode::test(Torrent const& tor, int mode)
|
||||
// NOTE: `ShowModeFields` is the set of all Torrent properties
|
||||
// needed to correctly run these tests. If you change these tests,
|
||||
// then update `ShowModeFields` accordingly.
|
||||
bool should_show_torrent(Torrent const& tor, ShowMode const mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case SHOW_ACTIVE:
|
||||
case ShowMode::ShowActive:
|
||||
return tor.peersWeAreUploadingTo() > 0 || tor.peersWeAreDownloadingFrom() > 0 || tor.isVerifying();
|
||||
|
||||
case SHOW_DOWNLOADING:
|
||||
case ShowMode::ShowDownloading:
|
||||
return tor.isDownloading() || tor.isWaitingToDownload();
|
||||
|
||||
case SHOW_ERROR:
|
||||
case ShowMode::ShowError:
|
||||
return tor.hasError();
|
||||
|
||||
case SHOW_FINISHED:
|
||||
case ShowMode::ShowFinished:
|
||||
return tor.isFinished();
|
||||
|
||||
case SHOW_PAUSED:
|
||||
case ShowMode::ShowPaused:
|
||||
return tor.isPaused();
|
||||
|
||||
case SHOW_SEEDING:
|
||||
case ShowMode::ShowSeeding:
|
||||
return tor.isSeeding() || tor.isWaitingToSeed();
|
||||
|
||||
case SHOW_VERIFYING:
|
||||
case ShowMode::ShowVerifying:
|
||||
return tor.isVerifying() || tor.isWaitingToVerify();
|
||||
|
||||
default: // SHOW_ALL
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// The Torrent properties that can affect ShowMode filtering.
|
||||
// When one of these changes, it's time to refilter.
|
||||
// Update this as needed when ShowModeTests changes.
|
||||
Torrent::fields_t const ShowModeFields{
|
||||
(uint64_t{ 1 } << Torrent::TORRENT_ERROR) | //
|
||||
(uint64_t{ 1 } << Torrent::IS_FINISHED) | //
|
||||
(uint64_t{ 1 } << Torrent::PEERS_GETTING_FROM_US) | //
|
||||
(uint64_t{ 1 } << Torrent::PEERS_SENDING_TO_US) | //
|
||||
(uint64_t{ 1 } << Torrent::STATUS) //
|
||||
};
|
||||
|
||||
91
qt/Filters.h
91
qt/Filters.h
@@ -5,89 +5,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint> // uint64_t
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
#include "Torrent.h"
|
||||
|
||||
class FilterMode
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
SHOW_ALL,
|
||||
SHOW_ACTIVE,
|
||||
SHOW_DOWNLOADING,
|
||||
SHOW_SEEDING,
|
||||
SHOW_PAUSED,
|
||||
SHOW_FINISHED,
|
||||
SHOW_VERIFYING,
|
||||
SHOW_ERROR,
|
||||
NUM_MODES
|
||||
};
|
||||
// The Torrent properties that can affect ShowMode filtering.
|
||||
// When one of these changes, it's time to refilter.
|
||||
extern Torrent::fields_t const ShowModeFields;
|
||||
|
||||
explicit FilterMode(int mode = SHOW_ALL)
|
||||
: mode_{ mode }
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] int mode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
/* The Torrent properties that can affect this filter.
|
||||
When one of these changes, it's time to refilter. */
|
||||
static constexpr auto TorrentFields = Torrent::fields_t{
|
||||
(uint64_t{ 1 } << Torrent::TORRENT_ERROR) | //
|
||||
(uint64_t{ 1 } << Torrent::IS_FINISHED) | //
|
||||
(uint64_t{ 1 } << Torrent::PEERS_GETTING_FROM_US) | //
|
||||
(uint64_t{ 1 } << Torrent::PEERS_SENDING_TO_US) | //
|
||||
(uint64_t{ 1 } << Torrent::STATUS) //
|
||||
};
|
||||
|
||||
static bool test(Torrent const& tor, int mode);
|
||||
|
||||
[[nodiscard]] bool test(Torrent const& tor) const
|
||||
{
|
||||
return test(tor, mode());
|
||||
}
|
||||
|
||||
private:
|
||||
int mode_;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FilterMode)
|
||||
|
||||
class SortMode
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
SORT_BY_ACTIVITY,
|
||||
SORT_BY_AGE,
|
||||
SORT_BY_ETA,
|
||||
SORT_BY_NAME,
|
||||
SORT_BY_PROGRESS,
|
||||
SORT_BY_QUEUE,
|
||||
SORT_BY_RATIO,
|
||||
SORT_BY_SIZE,
|
||||
SORT_BY_STATE,
|
||||
SORT_BY_ID,
|
||||
NUM_MODES
|
||||
};
|
||||
|
||||
explicit SortMode(int mode = SORT_BY_ID) noexcept
|
||||
: mode_{ mode }
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto mode() const noexcept
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
private:
|
||||
int mode_ = SORT_BY_ID;
|
||||
};
|
||||
using ShowMode = transmission::app::ShowMode;
|
||||
Q_DECLARE_METATYPE(ShowMode)
|
||||
inline auto constexpr DefaultShowMode = transmission::app::DefaultShowMode;
|
||||
inline auto constexpr ShowModeCount = transmission::app::ShowModeCount;
|
||||
bool should_show_torrent(Torrent const& torrent, ShowMode);
|
||||
|
||||
using SortMode = transmission::app::SortMode;
|
||||
Q_DECLARE_METATYPE(SortMode)
|
||||
inline auto constexpr DefaultSortMode = transmission::app::DefaultSortMode;
|
||||
|
||||
@@ -156,16 +156,16 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
|
||||
ui_.listView->setModel(&filter_model_);
|
||||
connect(ui_.listView->selectionModel(), &QItemSelectionModel::selectionChanged, refresh_action_sensitivity_soon);
|
||||
|
||||
std::array<std::pair<QAction*, int>, 9> const sort_modes = { {
|
||||
{ ui_.action_SortByActivity, SortMode::SORT_BY_ACTIVITY },
|
||||
{ ui_.action_SortByAge, SortMode::SORT_BY_AGE },
|
||||
{ ui_.action_SortByETA, SortMode::SORT_BY_ETA },
|
||||
{ ui_.action_SortByName, SortMode::SORT_BY_NAME },
|
||||
{ ui_.action_SortByProgress, SortMode::SORT_BY_PROGRESS },
|
||||
{ ui_.action_SortByQueue, SortMode::SORT_BY_QUEUE },
|
||||
{ ui_.action_SortByRatio, SortMode::SORT_BY_RATIO },
|
||||
{ ui_.action_SortBySize, SortMode::SORT_BY_SIZE },
|
||||
{ ui_.action_SortByState, SortMode::SORT_BY_STATE },
|
||||
auto const sort_modes = std::array<std::pair<QAction*, SortMode>, 9U>{ {
|
||||
{ ui_.action_SortByActivity, SortMode::SortByActivity },
|
||||
{ ui_.action_SortByAge, SortMode::SortByAge },
|
||||
{ ui_.action_SortByETA, SortMode::SortByEta },
|
||||
{ ui_.action_SortByName, SortMode::SortByName },
|
||||
{ ui_.action_SortByProgress, SortMode::SortByProgress },
|
||||
{ ui_.action_SortByQueue, SortMode::SortByQueue },
|
||||
{ ui_.action_SortByRatio, SortMode::SortByRatio },
|
||||
{ ui_.action_SortBySize, SortMode::SortBySize },
|
||||
{ ui_.action_SortByState, SortMode::SortByState },
|
||||
} };
|
||||
|
||||
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
@@ -173,7 +173,7 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
|
||||
|
||||
for (auto const& [action, mode] : sort_modes)
|
||||
{
|
||||
action->setProperty(SortModeKey, mode);
|
||||
action->setProperty(SortModeKey, QVariant::fromValue(mode));
|
||||
action_group->addAction(action);
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ QMenu* MainWindow::createStatsModeMenu()
|
||||
|
||||
void MainWindow::onSortModeChanged(QAction const* action)
|
||||
{
|
||||
prefs_.set(Prefs::SORT_MODE, SortMode(action->property(SortModeKey).toInt()));
|
||||
prefs_.set(Prefs::SORT_MODE, action->property(SortModeKey));
|
||||
}
|
||||
|
||||
void MainWindow::setSortAscendingPref(bool b)
|
||||
@@ -1109,7 +1109,6 @@ void MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
void MainWindow::refreshPref(int key)
|
||||
{
|
||||
auto b = bool{};
|
||||
auto i = int{};
|
||||
auto str = QString{};
|
||||
|
||||
switch (key)
|
||||
@@ -1130,11 +1129,12 @@ void MainWindow::refreshPref(int key)
|
||||
break;
|
||||
|
||||
case Prefs::SORT_MODE:
|
||||
i = prefs_.get<SortMode>(key).mode();
|
||||
|
||||
for (auto* action : ui_.action_SortByActivity->actionGroup()->actions())
|
||||
{
|
||||
action->setChecked(i == action->property(SortModeKey).toInt());
|
||||
auto const sort_mode = prefs_.get<SortMode>(key);
|
||||
for (auto* action : ui_.action_SortByActivity->actionGroup()->actions())
|
||||
{
|
||||
action->setChecked(sort_mode == action->property(SortModeKey).value<SortMode>());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
96
qt/Prefs.cc
96
qt/Prefs.cc
@@ -21,6 +21,7 @@
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include <libtransmission/api-compat.h>
|
||||
#include <libtransmission/serializer.h>
|
||||
#include <libtransmission/variant.h>
|
||||
|
||||
#include "CustomVariantType.h"
|
||||
@@ -29,6 +30,8 @@
|
||||
#include "VariantHelpers.h"
|
||||
|
||||
namespace api_compat = libtransmission::api_compat;
|
||||
using libtransmission::serializer::to_value;
|
||||
using libtransmission::serializer::to_variant;
|
||||
using ::trqt::variant_helpers::dictAdd;
|
||||
using ::trqt::variant_helpers::getValue;
|
||||
using namespace std::string_view_literals;
|
||||
@@ -90,7 +93,7 @@ std::array<Prefs::PrefItem, Prefs::PREFS_COUNT> const Prefs::Items{
|
||||
{ MAIN_WINDOW_WIDTH, TR_KEY_main_window_width, QMetaType::Int },
|
||||
{ MAIN_WINDOW_X, TR_KEY_main_window_x, QMetaType::Int },
|
||||
{ MAIN_WINDOW_Y, TR_KEY_main_window_y, QMetaType::Int },
|
||||
{ FILTER_MODE, TR_KEY_filter_mode, CustomVariantType::FilterModeType },
|
||||
{ FILTER_MODE, TR_KEY_filter_mode, CustomVariantType::ShowModeType },
|
||||
{ FILTER_TRACKERS, TR_KEY_filter_trackers, QMetaType::QString },
|
||||
{ FILTER_TEXT, TR_KEY_filter_text, QMetaType::QString },
|
||||
{ SESSION_IS_REMOTE, TR_KEY_remote_session_enabled, QMetaType::Bool },
|
||||
@@ -164,31 +167,6 @@ std::array<Prefs::PrefItem, Prefs::PREFS_COUNT> const Prefs::Items{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
auto constexpr FilterModes = std::array<std::pair<int, std::string_view>, FilterMode::NUM_MODES>{ {
|
||||
{ FilterMode::SHOW_ALL, "show-all" },
|
||||
{ FilterMode::SHOW_ACTIVE, "show-active" },
|
||||
{ FilterMode::SHOW_DOWNLOADING, "show-downloading" },
|
||||
{ FilterMode::SHOW_SEEDING, "show-seeding" },
|
||||
{ FilterMode::SHOW_PAUSED, "show-paused" },
|
||||
{ FilterMode::SHOW_FINISHED, "show-finished" },
|
||||
{ FilterMode::SHOW_VERIFYING, "show-verifying" },
|
||||
{ FilterMode::SHOW_ERROR, "show-error" },
|
||||
} };
|
||||
|
||||
auto constexpr SortModes = std::array<std::pair<int, std::string_view>, SortMode::NUM_MODES>{ {
|
||||
{ SortMode::SORT_BY_NAME, "sort-by-name" },
|
||||
{ SortMode::SORT_BY_ACTIVITY, "sort-by-activity" },
|
||||
{ SortMode::SORT_BY_AGE, "sort-by-age" },
|
||||
{ SortMode::SORT_BY_ETA, "sort-by-eta" },
|
||||
{ SortMode::SORT_BY_PROGRESS, "sort-by-progress" },
|
||||
{ SortMode::SORT_BY_QUEUE, "sort-by-queue" },
|
||||
{ SortMode::SORT_BY_RATIO, "sort-by-ratio" },
|
||||
{ SortMode::SORT_BY_SIZE, "sort-by-size" },
|
||||
{ SortMode::SORT_BY_STATE, "sort-by-state" },
|
||||
{ SortMode::SORT_BY_ID, "sort-by-id" },
|
||||
} };
|
||||
|
||||
bool isValidUtf8(QByteArray const& byteArray)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
@@ -257,30 +235,16 @@ Prefs::Prefs(QString config_dir)
|
||||
break;
|
||||
|
||||
case CustomVariantType::SortModeType:
|
||||
if (auto const value = getValue<std::string_view>(b); value)
|
||||
if (auto const val = to_value<SortMode>(*b))
|
||||
{
|
||||
auto const test = [&value](auto const& item)
|
||||
{
|
||||
return item.second == *value;
|
||||
};
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
auto const it = std::find_if(std::cbegin(SortModes), std::cend(SortModes), test);
|
||||
auto const& [mode, mode_str] = it == std::end(SortModes) ? SortModes.front() : *it;
|
||||
values_[i] = QVariant::fromValue(SortMode{ mode });
|
||||
values_[i] = QVariant::fromValue(*val);
|
||||
}
|
||||
break;
|
||||
|
||||
case CustomVariantType::FilterModeType:
|
||||
if (auto const value = getValue<std::string_view>(b); value)
|
||||
case CustomVariantType::ShowModeType:
|
||||
if (auto const val = to_value<ShowMode>(*b))
|
||||
{
|
||||
auto const test = [&value](auto const& item)
|
||||
{
|
||||
return item.second == *value;
|
||||
};
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
auto const it = std::find_if(std::cbegin(FilterModes), std::cend(FilterModes), test);
|
||||
auto const& [mode, mode_str] = it == std::end(FilterModes) ? FilterModes.front() : *it;
|
||||
values_[i] = QVariant::fromValue(FilterMode{ mode });
|
||||
values_[i] = QVariant::fromValue(*val);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -349,32 +313,12 @@ Prefs::~Prefs()
|
||||
break;
|
||||
|
||||
case CustomVariantType::SortModeType:
|
||||
{
|
||||
auto const mode = val.value<SortMode>().mode();
|
||||
auto const test = [&mode](auto const& item)
|
||||
{
|
||||
return item.first == mode;
|
||||
};
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
auto const it = std::find_if(std::cbegin(SortModes), std::cend(SortModes), test);
|
||||
auto const& [mode_val, mode_str] = it == std::end(SortModes) ? SortModes.front() : *it;
|
||||
dictAdd(¤t_settings, key, mode_str);
|
||||
break;
|
||||
}
|
||||
*tr_variantDictAdd(¤t_settings, key) = to_variant(val.value<SortMode>());
|
||||
break;
|
||||
|
||||
case CustomVariantType::FilterModeType:
|
||||
{
|
||||
auto const mode = val.value<FilterMode>().mode();
|
||||
auto const test = [&mode](auto const& item)
|
||||
{
|
||||
return item.first == mode;
|
||||
};
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
auto const it = std::find_if(std::cbegin(FilterModes), std::cend(FilterModes), test);
|
||||
auto const& [mode_val, mode_str] = it == std::end(FilterModes) ? FilterModes.front() : *it;
|
||||
dictAdd(¤t_settings, key, mode_str);
|
||||
break;
|
||||
}
|
||||
case CustomVariantType::ShowModeType:
|
||||
*tr_variantDictAdd(¤t_settings, key) = to_variant(val.value<ShowMode>());
|
||||
break;
|
||||
|
||||
case QMetaType::QString:
|
||||
dictAdd(¤t_settings, key, val.toString());
|
||||
@@ -430,11 +374,11 @@ tr_variant Prefs::get_default_app_settings()
|
||||
settings.try_emplace(TR_KEY_blocklist_updates_enabled, true);
|
||||
settings.try_emplace(TR_KEY_compact_view, false);
|
||||
settings.try_emplace(TR_KEY_download_dir, download_dir);
|
||||
settings.try_emplace(TR_KEY_filter_mode, tr_variant::unmanaged_string("all"sv));
|
||||
settings.try_emplace(TR_KEY_filter_mode, to_variant(DefaultShowMode));
|
||||
settings.try_emplace(TR_KEY_inhibit_desktop_hibernation, false);
|
||||
settings.try_emplace(TR_KEY_main_window_height, 500);
|
||||
settings.try_emplace(TR_KEY_main_window_layout_order, tr_variant::unmanaged_string("menu,toolbar,filter,list,statusbar"sv));
|
||||
settings.try_emplace(TR_KEY_main_window_width, 300);
|
||||
settings.try_emplace(TR_KEY_main_window_width, 600);
|
||||
settings.try_emplace(TR_KEY_main_window_x, 50);
|
||||
settings.try_emplace(TR_KEY_main_window_y, 50);
|
||||
settings.try_emplace(TR_KEY_open_dialog_dir, QDir::home().absolutePath().toStdString());
|
||||
@@ -443,11 +387,11 @@ tr_variant Prefs::get_default_app_settings()
|
||||
settings.try_emplace(TR_KEY_remote_session_enabled, false);
|
||||
settings.try_emplace(TR_KEY_remote_session_host, tr_variant::unmanaged_string("localhost"sv));
|
||||
settings.try_emplace(TR_KEY_remote_session_https, false);
|
||||
settings.try_emplace(TR_KEY_remote_session_password, tr_variant::unmanaged_string(""));
|
||||
settings.try_emplace(TR_KEY_remote_session_password, tr_variant::unmanaged_string(""sv));
|
||||
settings.try_emplace(TR_KEY_remote_session_port, TrDefaultRpcPort);
|
||||
settings.try_emplace(TR_KEY_remote_session_requires_authentication, false);
|
||||
settings.try_emplace(TR_KEY_remote_session_rpc_url_path, TR_DEFAULT_RPC_URL_STR "rpc");
|
||||
settings.try_emplace(TR_KEY_remote_session_username, tr_variant::unmanaged_string(""));
|
||||
settings.try_emplace(TR_KEY_remote_session_rpc_url_path, tr_variant::unmanaged_string(TR_DEFAULT_RPC_URL_STR "rpc"));
|
||||
settings.try_emplace(TR_KEY_remote_session_username, tr_variant::unmanaged_string(""sv));
|
||||
settings.try_emplace(TR_KEY_show_backup_trackers, false);
|
||||
settings.try_emplace(TR_KEY_show_filterbar, true);
|
||||
settings.try_emplace(TR_KEY_show_notification_area_icon, false);
|
||||
@@ -455,7 +399,7 @@ tr_variant Prefs::get_default_app_settings()
|
||||
settings.try_emplace(TR_KEY_show_statusbar, true);
|
||||
settings.try_emplace(TR_KEY_show_toolbar, true);
|
||||
settings.try_emplace(TR_KEY_show_tracker_scrapes, false);
|
||||
settings.try_emplace(TR_KEY_sort_mode, tr_variant::unmanaged_string("sort-by-name"sv));
|
||||
settings.try_emplace(TR_KEY_sort_mode, to_variant(DefaultSortMode));
|
||||
settings.try_emplace(TR_KEY_sort_reversed, false);
|
||||
settings.try_emplace(TR_KEY_start_minimized, false);
|
||||
settings.try_emplace(TR_KEY_statusbar_stats, tr_variant::unmanaged_string("total-ratio"));
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <libtransmission/quark.h>
|
||||
|
||||
#include <libtransmission-app/display-modes.h>
|
||||
|
||||
class QDateTime;
|
||||
|
||||
extern "C"
|
||||
@@ -168,7 +170,7 @@ public:
|
||||
QDateTime getDateTime(int key) const;
|
||||
|
||||
template<typename T>
|
||||
T get(int key) const
|
||||
[[nodiscard]] T get(int const key) const
|
||||
{
|
||||
return values_[key].value<T>();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include <libtransmission/quark.h>
|
||||
#include <libtransmission/serializer.h>
|
||||
#include <libtransmission/session-id.h>
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/variant.h>
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
#include "AddData.h"
|
||||
#include "CustomVariantType.h"
|
||||
#include "Filters.h"
|
||||
#include "Prefs.h"
|
||||
#include "RpcQueue.h"
|
||||
#include "SessionDialog.h"
|
||||
@@ -43,10 +45,11 @@
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
using ::libtransmission::serializer::to_value;
|
||||
using ::libtransmission::serializer::to_variant;
|
||||
using ::trqt::variant_helpers::dictAdd;
|
||||
using ::trqt::variant_helpers::dictFind;
|
||||
using ::trqt::variant_helpers::getValue;
|
||||
using ::trqt::variant_helpers::to_variant;
|
||||
|
||||
/***
|
||||
****
|
||||
@@ -675,6 +678,8 @@ using TorrentProperties = Session::TorrentProperties;
|
||||
};
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
return {};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -952,8 +957,22 @@ void Session::updateInfo(tr_variant* args_dict)
|
||||
|
||||
break;
|
||||
|
||||
case CustomVariantType::FilterModeType:
|
||||
case CustomVariantType::ShowModeType:
|
||||
if (auto const val = to_value<ShowMode>(*b))
|
||||
{
|
||||
prefs_.set(i, *val);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CustomVariantType::SortModeType:
|
||||
if (auto const val = to_value<SortMode>(*b))
|
||||
{
|
||||
prefs_.set(i, *val);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case QMetaType::QString:
|
||||
if (auto const value = getValue<QString>(b); value)
|
||||
{
|
||||
|
||||
@@ -81,9 +81,9 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
auto const* a = sourceModel()->data(left, TorrentModel::TorrentRole).value<Torrent const*>();
|
||||
auto const* b = sourceModel()->data(right, TorrentModel::TorrentRole).value<Torrent const*>();
|
||||
|
||||
switch (prefs_.get<SortMode>(Prefs::SORT_MODE).mode())
|
||||
switch (prefs_.get<SortMode>(Prefs::SORT_MODE))
|
||||
{
|
||||
case SortMode::SORT_BY_QUEUE:
|
||||
case SortMode::SortByQueue:
|
||||
if (val == 0)
|
||||
{
|
||||
val = -tr_compare_3way(a->queuePosition(), b->queuePosition());
|
||||
@@ -91,7 +91,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
break;
|
||||
|
||||
case SortMode::SORT_BY_SIZE:
|
||||
case SortMode::SortBySize:
|
||||
if (val == 0)
|
||||
{
|
||||
val = tr_compare_3way(a->sizeWhenDone(), b->sizeWhenDone());
|
||||
@@ -99,7 +99,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
break;
|
||||
|
||||
case SortMode::SORT_BY_AGE:
|
||||
case SortMode::SortByAge:
|
||||
if (val == 0)
|
||||
{
|
||||
val = tr_compare_3way(a->dateAdded(), b->dateAdded());
|
||||
@@ -107,7 +107,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
break;
|
||||
|
||||
case SortMode::SORT_BY_ID:
|
||||
case SortMode::SortById:
|
||||
if (val == 0)
|
||||
{
|
||||
val = tr_compare_3way(a->id(), b->id());
|
||||
@@ -115,7 +115,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
break;
|
||||
|
||||
case SortMode::SORT_BY_ACTIVITY:
|
||||
case SortMode::SortByActivity:
|
||||
if (val == 0)
|
||||
{
|
||||
val = tr_compare_3way(a->downloadSpeed() + a->uploadSpeed(), b->downloadSpeed() + b->uploadSpeed());
|
||||
@@ -130,7 +130,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
[[fallthrough]];
|
||||
|
||||
case SortMode::SORT_BY_STATE:
|
||||
case SortMode::SortByState:
|
||||
if (val == 0)
|
||||
{
|
||||
val = -tr_compare_3way(a->isPaused(), b->isPaused());
|
||||
@@ -153,7 +153,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
[[fallthrough]];
|
||||
|
||||
case SortMode::SORT_BY_PROGRESS:
|
||||
case SortMode::SortByProgress:
|
||||
if (val == 0)
|
||||
{
|
||||
val = tr_compare_3way(a->metadataPercentDone(), b->metadataPercentDone());
|
||||
@@ -176,7 +176,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
[[fallthrough]];
|
||||
|
||||
case SortMode::SORT_BY_RATIO:
|
||||
case SortMode::SortByRatio:
|
||||
if (val == 0)
|
||||
{
|
||||
val = a->compareRatio(*b);
|
||||
@@ -184,7 +184,7 @@ bool TorrentFilter::lessThan(QModelIndex const& left, QModelIndex const& right)
|
||||
|
||||
break;
|
||||
|
||||
case SortMode::SORT_BY_ETA:
|
||||
case SortMode::SortByEta:
|
||||
if (val == 0)
|
||||
{
|
||||
val = a->compareETA(*b);
|
||||
@@ -221,8 +221,8 @@ bool TorrentFilter::filterAcceptsRow(int source_row, QModelIndex const& source_p
|
||||
|
||||
if (accepts)
|
||||
{
|
||||
auto const m = prefs_.get<FilterMode>(Prefs::FILTER_MODE);
|
||||
accepts = m.test(tor);
|
||||
auto const show_mode = prefs_.get<ShowMode>(Prefs::FILTER_MODE);
|
||||
accepts = should_show_torrent(tor, show_mode);
|
||||
}
|
||||
|
||||
if (accepts)
|
||||
@@ -241,7 +241,7 @@ bool TorrentFilter::filterAcceptsRow(int source_row, QModelIndex const& source_p
|
||||
return accepts;
|
||||
}
|
||||
|
||||
std::array<int, FilterMode::NUM_MODES> TorrentFilter::countTorrentsPerMode() const
|
||||
std::array<int, ShowModeCount> TorrentFilter::countTorrentsPerMode() const
|
||||
{
|
||||
auto* const torrent_model = dynamic_cast<TorrentModel*>(sourceModel());
|
||||
if (torrent_model == nullptr)
|
||||
@@ -249,13 +249,13 @@ std::array<int, FilterMode::NUM_MODES> TorrentFilter::countTorrentsPerMode() con
|
||||
return {};
|
||||
}
|
||||
|
||||
auto torrent_counts = std::array<int, FilterMode::NUM_MODES>{};
|
||||
auto torrent_counts = std::array<int, ShowModeCount>{};
|
||||
|
||||
for (auto const& tor : torrent_model->torrents())
|
||||
{
|
||||
for (int mode = 0; mode < FilterMode::NUM_MODES; ++mode)
|
||||
for (unsigned int mode = 0; mode < ShowModeCount; ++mode)
|
||||
{
|
||||
if (FilterMode::test(*tor, mode))
|
||||
if (should_show_torrent(*tor, static_cast<ShowMode>(mode)))
|
||||
{
|
||||
++torrent_counts[mode];
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
class QString;
|
||||
|
||||
class FilterMode;
|
||||
class Prefs;
|
||||
class Torrent;
|
||||
|
||||
@@ -36,7 +35,7 @@ public:
|
||||
TorrentFilter& operator=(TorrentFilter&&) = delete;
|
||||
TorrentFilter& operator=(TorrentFilter const&) = delete;
|
||||
|
||||
[[nodiscard]] std::array<int, FilterMode::NUM_MODES> countTorrentsPerMode() const;
|
||||
[[nodiscard]] std::array<int, ShowModeCount> countTorrentsPerMode() const;
|
||||
|
||||
protected:
|
||||
// QSortFilterProxyModel
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <libtransmission/web-utils.h>
|
||||
#include <libtransmission/favicon-cache.h>
|
||||
|
||||
#include <libtransmission-app/favicon-cache.h>
|
||||
|
||||
#include "Formatter.h"
|
||||
#include "Torrent.h"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <libtransmission/serializer.h>
|
||||
#include <libtransmission/variant.h>
|
||||
|
||||
class QByteArray;
|
||||
@@ -29,12 +28,6 @@ namespace trqt::variant_helpers
|
||||
{
|
||||
void register_qt_converters();
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] tr_variant to_variant(T const& val)
|
||||
{
|
||||
return libtransmission::serializer::Converters::serialize(val);
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if_t<std::is_same_v<T, bool>>* = nullptr>
|
||||
auto getValue(tr_variant const* variant)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/version.h>
|
||||
|
||||
#include <libtransmission-app/app.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "InteropHelper.h"
|
||||
#include "Prefs.h"
|
||||
@@ -99,8 +101,7 @@ bool tryDelegate(QStringList const& filenames)
|
||||
|
||||
int tr_main(int argc, char** argv)
|
||||
{
|
||||
tr_lib_init();
|
||||
tr_locale_set_global("");
|
||||
transmission::app::init();
|
||||
trqt::variant_helpers::register_qt_converters();
|
||||
|
||||
// parse the command-line arguments
|
||||
|
||||
Reference in New Issue
Block a user