From 76521a1751fb8b7638f524299943106c9c0917f2 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 15 Nov 2023 22:15:40 -0600 Subject: [PATCH] refactor: Values pt. 7 - remove tr_formatter_init methods (#6258) * refactor: initialize libtransmission::Values units in Application::initUnits() * refactor: use libtransmission::Values instead of Formatter::unitStr() * refactor: remove Formatter::Size, Formatter:Type * refactor: use Values::Config to init units in transmission-qt * refactor: use Values::Config to init units in transmission-mac * chore: remove unused tr_formatter_foo_init() functions * chore: make Value::operator+() const * use Values::Speed, Values::Storage in GTK client * chore: use snake_case for Formatter methods * refactor: use Values::Speed in GTK client details dialog * feat: add Values::Value::is_zero() * refactor: remove unnecessary UTF8String calls --- gtk/DetailsDialog.cc | 83 +++++++++++++--------------- gtk/MainWindow.cc | 11 ++-- gtk/PrefsDialog.cc | 12 ++-- gtk/Torrent.cc | 79 +++++++++++++++++--------- gtk/Torrent.h | 10 +++- gtk/Utils.cc | 29 ++-------- gtk/Utils.h | 24 +------- gtk/main.cc | 11 ++-- libtransmission/torrent.h | 4 +- libtransmission/utils.cc | 48 ++++------------ libtransmission/utils.h | 7 --- libtransmission/values.h | 16 +++++- macosx/Controller.mm | 65 ++++++++++++---------- qt/Application.cc | 16 ++++++ qt/Application.h | 1 + qt/DetailsDialog.cc | 48 ++++++++-------- qt/FileTreeItem.cc | 2 +- qt/FileTreeView.cc | 13 +++-- qt/Formatter.cc | 55 ++---------------- qt/Formatter.h | 42 +++----------- qt/FreeSpaceLabel.cc | 2 +- qt/MainWindow.cc | 25 +++++---- qt/MakeDialog.cc | 4 +- qt/PrefsDialog.cc | 10 ++-- qt/Speed.h | 11 ++-- qt/StatsDialog.cc | 16 +++--- qt/TorrentDelegate.cc | 53 +++++++++--------- qt/TrackerDelegate.cc | 11 ++-- tests/libtransmission/values-test.cc | 13 +++-- 29 files changed, 321 insertions(+), 400 deletions(-) diff --git a/gtk/DetailsDialog.cc b/gtk/DetailsDialog.cc index d30899bc5..477e04c5d 100644 --- a/gtk/DetailsDialog.cc +++ b/gtk/DetailsDialog.cc @@ -487,10 +487,13 @@ void DetailsDialog::Impl::torrent_set_real(tr_quark key, double value) void DetailsDialog::Impl::options_page_init(Glib::RefPtr const& /*builder*/) { + auto const speed_units_kbyps_str = Speed::units().display_name(Speed::Units::KByps); + honor_limits_check_tag_ = honor_limits_check_->signal_toggled().connect( [this]() { torrent_set_bool(TR_KEY_honorsSessionLimits, honor_limits_check_->get_active()); }); - down_limited_check_->set_label(fmt::format(down_limited_check_->get_label().raw(), fmt::arg("speed_units", speed_K_str))); + down_limited_check_->set_label( + fmt::format(fmt::runtime(down_limited_check_->get_label().raw()), fmt::arg("speed_units", speed_units_kbyps_str))); down_limited_check_tag_ = down_limited_check_->signal_toggled().connect( [this]() { torrent_set_bool(TR_KEY_downloadLimited, down_limited_check_->get_active()); }); @@ -498,7 +501,8 @@ void DetailsDialog::Impl::options_page_init(Glib::RefPtr const& /* down_limit_spin_tag_ = down_limit_spin_->signal_value_changed().connect( [this]() { torrent_set_int(TR_KEY_downloadLimit, down_limit_spin_->get_value_as_int()); }); - up_limited_check_->set_label(fmt::format(up_limited_check_->get_label().raw(), fmt::arg("speed_units", speed_K_str))); + up_limited_check_->set_label( + fmt::format(fmt::runtime(up_limited_check_->get_label().raw()), fmt::arg("speed_units", speed_units_kbyps_str))); up_limited_check_tag_ = up_limited_check_->signal_toggled().connect( [this]() { torrent_set_bool(TR_KEY_uploadLimited, up_limited_check_->get_active()); }); @@ -1108,14 +1112,14 @@ public: add(key); add(was_updated); add(url); - add(download_rate_double); + add(download_rate_speed); add(download_rate_string); } Gtk::TreeModelColumn key; Gtk::TreeModelColumn was_updated; Gtk::TreeModelColumn url; - Gtk::TreeModelColumn download_rate_double; + Gtk::TreeModelColumn download_rate_speed; Gtk::TreeModelColumn download_rate_string; }; @@ -1130,9 +1134,9 @@ public: add(was_updated); add(address); add(address_collated); - add(download_rate_double); + add(download_rate_speed); add(download_rate_string); - add(upload_rate_double); + add(upload_rate_speed); add(upload_rate_string); add(client); add(progress); @@ -1157,9 +1161,9 @@ public: Gtk::TreeModelColumn was_updated; Gtk::TreeModelColumn address; Gtk::TreeModelColumn address_collated; - Gtk::TreeModelColumn download_rate_double; + Gtk::TreeModelColumn download_rate_speed; Gtk::TreeModelColumn download_rate_string; - Gtk::TreeModelColumn upload_rate_double; + Gtk::TreeModelColumn upload_rate_speed; Gtk::TreeModelColumn upload_rate_string; Gtk::TreeModelColumn client; Gtk::TreeModelColumn progress; @@ -1219,25 +1223,28 @@ void initPeerRow( void refreshPeerRow(Gtk::TreeModel::iterator const& iter, tr_peer_stat const* peer) { - std::string up_speed; - std::string down_speed; - std::string up_count; - std::string down_count; - std::string blocks_to_peer; - std::string blocks_to_client; - std::string cancelled_by_peer; - std::string cancelled_by_client; - g_return_if_fail(peer != nullptr); + auto const down_speed = Speed{ peer->rateToClient_KBps, Speed::Units::KByps }; + auto const up_speed = Speed{ peer->rateToPeer_KBps, Speed::Units::KByps }; + + auto blocks_to_client = std::string{}; + auto blocks_to_peer = std::string{}; + auto cancelled_by_client = std::string{}; + auto cancelled_by_peer = std::string{}; + auto down_count = std::string{}; + auto down_speed_string = std::string{}; + auto up_count = std::string{}; + auto up_speed_string = std::string{}; + if (peer->rateToPeer_KBps > 0.01) { - up_speed = Speed{ peer->rateToPeer_KBps, Speed::Units::KByps }.to_string(); + up_speed_string = up_speed.to_string(); } if (peer->rateToClient_KBps > 0) { - down_speed = Speed{ peer->rateToClient_KBps, Speed::Units::KByps }.to_string(); + down_speed_string = down_speed.to_string(); } if (peer->activeReqsToPeer > 0) @@ -1275,10 +1282,10 @@ void refreshPeerRow(Gtk::TreeModel::iterator const& iter, tr_peer_stat const* pe (*iter)[peer_cols.upload_request_count_string] = up_count; (*iter)[peer_cols.download_request_count_number] = peer->activeReqsToPeer; (*iter)[peer_cols.download_request_count_string] = down_count; - (*iter)[peer_cols.download_rate_double] = peer->rateToClient_KBps; - (*iter)[peer_cols.download_rate_string] = down_speed; - (*iter)[peer_cols.upload_rate_double] = peer->rateToPeer_KBps; - (*iter)[peer_cols.upload_rate_string] = up_speed; + (*iter)[peer_cols.download_rate_speed] = down_speed; + (*iter)[peer_cols.download_rate_string] = down_speed_string; + (*iter)[peer_cols.upload_rate_speed] = up_speed; + (*iter)[peer_cols.upload_rate_string] = up_speed_string; (*iter)[peer_cols.flags] = std::data(peer->flagStr); (*iter)[peer_cols.was_updated] = true; (*iter)[peer_cols.blocks_downloaded_count_number] = peer->blocksToClient; @@ -1425,11 +1432,11 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector const& tor auto const key = make_key(tor, webseed.url); auto const iter = store->get_iter(hash.at(key).get_path()); - auto const KBps = double(webseed.download_bytes_per_second) / speed_K; - auto const buf = webseed.is_downloading ? Speed{ KBps, Speed::Units::KByps }.to_string() : std::string{}; + auto const speed = Speed{ webseed.download_bytes_per_second, Speed::Units::Byps }; + auto const speed_string = webseed.is_downloading ? speed.to_string() : std::string{}; - (*iter)[webseed_cols.download_rate_double] = KBps; - (*iter)[webseed_cols.download_rate_string] = buf; + (*iter)[webseed_cols.download_rate_speed] = speed; + (*iter)[webseed_cols.download_rate_string] = speed_string; (*iter)[webseed_cols.was_updated] = true; } } @@ -1577,25 +1584,9 @@ void setPeerViewColumns(Gtk::TreeView* peer_view) if (more) { view_columns.push_back(&peer_cols.download_request_count_string); - } - - if (more) - { view_columns.push_back(&peer_cols.blocks_downloaded_count_string); - } - - if (more) - { view_columns.push_back(&peer_cols.blocks_uploaded_count_string); - } - - if (more) - { view_columns.push_back(&peer_cols.reqs_cancelled_by_client_count_string); - } - - if (more) - { view_columns.push_back(&peer_cols.reqs_cancelled_by_peer_count_string); } @@ -1683,7 +1674,7 @@ void setPeerViewColumns(Gtk::TreeView* peer_view) r->property_xalign() = 1.0F; c = Gtk::make_managed(_("Down"), *r); c->add_attribute(r->property_text(), *col); - sort_col = &peer_cols.download_rate_double; + sort_col = &peer_cols.download_rate_speed; } else if (*col == peer_cols.upload_rate_string) { @@ -1691,7 +1682,7 @@ void setPeerViewColumns(Gtk::TreeView* peer_view) r->property_xalign() = 1.0F; c = Gtk::make_managed(_("Up"), *r); c->add_attribute(r->property_text(), *col); - sort_col = &peer_cols.upload_rate_double; + sort_col = &peer_cols.upload_rate_speed; } else if (*col == peer_cols.client) { @@ -1761,7 +1752,7 @@ void DetailsDialog::Impl::peer_page_init(Glib::RefPtr const& build auto* r = Gtk::make_managed(); auto* c = Gtk::make_managed(_("Down"), *r); c->add_attribute(r->property_text(), webseed_cols.download_rate_string); - c->set_sort_column(webseed_cols.download_rate_double); + c->set_sort_column(webseed_cols.download_rate_speed); v->append_column(*c); } diff --git a/gtk/MainWindow.cc b/gtk/MainWindow.cc index c6bdf4cc5..5ac237249 100644 --- a/gtk/MainWindow.cc +++ b/gtk/MainWindow.cc @@ -792,9 +792,9 @@ void MainWindow::Impl::updateSpeeds() if (session != nullptr) { auto dn_count = int{}; - auto dn_speed = double{}; + auto dn_speed = Speed{}; auto up_count = int{}; - auto up_speed = double{}; + auto up_speed = Speed{}; auto const model = core_->get_model(); for (auto i = 0U, count = model->get_n_items(); i < count; ++i) @@ -806,13 +806,10 @@ void MainWindow::Impl::updateSpeeds() up_speed += torrent->get_speed_up(); } - dl_lb_->set_text(fmt::format( - _("{download_speed} ▼"), - fmt::arg("download_speed", Speed{ dn_speed, Speed::Units::KByps }.to_string()))); + dl_lb_->set_text(fmt::format(fmt::runtime(_("{download_speed} ▼")), fmt::arg("download_speed", dn_speed.to_string()))); dl_lb_->set_visible(dn_count > 0); - ul_lb_->set_text( - fmt::format(_("{upload_speed} ▲"), fmt::arg("upload_speed", Speed{ up_speed, Speed::Units::KByps }.to_string()))); + ul_lb_->set_text(fmt::format(fmt::runtime(_("{upload_speed} ▲")), fmt::arg("upload_speed", up_speed.to_string()))); ul_lb_->set_visible(dn_count > 0 || up_count > 0); } } diff --git a/gtk/PrefsDialog.cc b/gtk/PrefsDialog.cc index 66ea89f59..780c6e68f 100644 --- a/gtk/PrefsDialog.cc +++ b/gtk/PrefsDialog.cc @@ -49,6 +49,8 @@ #include #include +using namespace libtransmission::Values; + /** *** **/ @@ -840,20 +842,22 @@ public: SpeedPage::SpeedPage(BaseObjectType* cast_item, Glib::RefPtr const& builder, Glib::RefPtr const& core) : PageBase(cast_item, builder, core) { + auto const speed_units_kbyps_str = Speed::units().display_name(Speed::Units::KByps); + localize_label( *init_check_button("upload_limit_check", TR_KEY_speed_limit_up_enabled), - fmt::arg("speed_units", speed_K_str)); + fmt::arg("speed_units", speed_units_kbyps_str)); init_spin_button("upload_limit_spin", TR_KEY_speed_limit_up, 0, std::numeric_limits::max(), 5); localize_label( *init_check_button("download_limit_check", TR_KEY_speed_limit_down_enabled), - fmt::arg("speed_units", speed_K_str)); + fmt::arg("speed_units", speed_units_kbyps_str)); init_spin_button("download_limit_spin", TR_KEY_speed_limit_down, 0, std::numeric_limits::max(), 5); - localize_label(*get_widget("alt_upload_limit_label"), fmt::arg("speed_units", speed_K_str)); + localize_label(*get_widget("alt_upload_limit_label"), fmt::arg("speed_units", speed_units_kbyps_str)); init_spin_button("alt_upload_limit_spin", TR_KEY_alt_speed_up, 0, std::numeric_limits::max(), 5); - localize_label(*get_widget("alt_download_limit_label"), fmt::arg("speed_units", speed_K_str)); + localize_label(*get_widget("alt_download_limit_label"), fmt::arg("speed_units", speed_units_kbyps_str)); init_spin_button("alt_download_limit_spin", TR_KEY_alt_speed_down, 0, std::numeric_limits::max(), 5); init_time_combo("alt_speed_start_time_combo", TR_KEY_alt_speed_time_begin); diff --git a/gtk/Torrent.cc b/gtk/Torrent.cc index ea3919537..6f6eb07a1 100644 --- a/gtk/Torrent.cc +++ b/gtk/Torrent.cc @@ -140,12 +140,15 @@ public: std::string_view mime_type; - uint64_t have_unchecked = {}; - uint64_t have_valid = {}; - uint64_t left_until_done = {}; - uint64_t size_when_done = {}; - uint64_t total_size = {}; - uint64_t uploaded_ever = {}; + Storage have_unchecked = {}; + Storage have_valid = {}; + Storage left_until_done = {}; + Storage size_when_done = {}; + Storage total_size = {}; + Storage uploaded_ever = {}; + + Speed speed_down = {}; + Speed speed_up = {}; size_t queue_position = {}; @@ -174,8 +177,6 @@ public: float ratio = {}; float seed_ratio = {}; - float speed_down = {}; - float speed_up = {}; tr_priority_t priority = {}; @@ -247,8 +248,16 @@ Torrent::ChangeFlags Torrent::Impl::update_cache() auto const view = tr_torrentView(raw_torrent_); update_cache_value(cache_.name, view.name, result, ChangeFlag::NAME); - update_cache_value(cache_.speed_up, stats->pieceUploadSpeed_KBps, 0.01F, result, ChangeFlag::SPEED_UP); - update_cache_value(cache_.speed_down, stats->pieceDownloadSpeed_KBps, 0.01F, result, ChangeFlag::SPEED_DOWN); + update_cache_value( + cache_.speed_up, + Speed{ stats->pieceUploadSpeed_KBps, Speed::Units::KByps }, + result, + ChangeFlag::SPEED_UP); + update_cache_value( + cache_.speed_down, + Speed{ stats->pieceDownloadSpeed_KBps, Speed::Units::KByps }, + result, + ChangeFlag::SPEED_DOWN); update_cache_value(cache_.active_peers_up, stats->peersGettingFromUs, result, ChangeFlag::ACTIVE_PEERS_UP); update_cache_value( cache_.active_peers_down, @@ -294,16 +303,36 @@ Torrent::ChangeFlags Torrent::Impl::update_cache() Percents(stats->seedRatioPercentDone), result, ChangeFlag::SEED_RATIO_PERCENT_DONE); - update_cache_value(cache_.total_size, view.total_size, result, ChangeFlag::TOTAL_SIZE); + update_cache_value(cache_.total_size, Storage{ view.total_size, Storage::Units::Bytes }, result, ChangeFlag::TOTAL_SIZE); update_cache_value(cache_.has_seed_ratio, has_seed_ratio, result, ChangeFlag::LONG_PROGRESS); - update_cache_value(cache_.have_unchecked, stats->haveUnchecked, result, ChangeFlag::LONG_PROGRESS); - update_cache_value(cache_.have_valid, stats->haveValid, result, ChangeFlag::LONG_PROGRESS); - update_cache_value(cache_.left_until_done, stats->leftUntilDone, result, ChangeFlag::LONG_PROGRESS); + update_cache_value( + cache_.have_unchecked, + Storage{ stats->haveUnchecked, Storage::Units::Bytes }, + result, + ChangeFlag::LONG_PROGRESS); + update_cache_value( + cache_.have_valid, + Storage{ stats->haveValid, Storage::Units::Bytes }, + result, + ChangeFlag::LONG_PROGRESS); + update_cache_value( + cache_.left_until_done, + Storage{ stats->leftUntilDone, Storage::Units::Bytes }, + result, + ChangeFlag::LONG_PROGRESS); update_cache_value(cache_.percent_done, Percents(stats->percentDone), result, ChangeFlag::LONG_PROGRESS); update_cache_value(cache_.seed_ratio, static_cast(seed_ratio), 0.01F, result, ChangeFlag::LONG_PROGRESS); - update_cache_value(cache_.size_when_done, stats->sizeWhenDone, result, ChangeFlag::LONG_PROGRESS); - update_cache_value(cache_.uploaded_ever, stats->uploadedEver, result, ChangeFlag::LONG_PROGRESS); + update_cache_value( + cache_.size_when_done, + Storage{ stats->sizeWhenDone, Storage::Units::Bytes }, + result, + ChangeFlag::LONG_PROGRESS); + update_cache_value( + cache_.uploaded_ever, + Storage{ stats->uploadedEver, Storage::Units::Bytes }, + result, + ChangeFlag::LONG_PROGRESS); update_cache_value( cache_.metadata_percent_complete, @@ -426,7 +455,7 @@ Glib::ustring Torrent::Impl::get_long_progress_text() const { Glib::ustring gstr; - bool const isDone = cache_.left_until_done == 0; + bool const isDone = cache_.left_until_done.is_zero(); auto const haveTotal = cache_.have_unchecked + cache_.have_valid; bool const isSeed = cache_.have_valid >= cache_.total_size; @@ -585,16 +614,14 @@ Glib::ustring Torrent::Impl::get_short_transfer_text() const if (cache_.has_metadata && cache_.active_peers_down > 0) { return fmt::format( - _("{download_speed} ▼ {upload_speed} ▲"), - fmt::arg("upload_speed", Speed{ cache_.speed_up, Speed::Units::KByps }.to_string()), - fmt::arg("download_speed", Speed{ cache_.speed_down, Speed::Units::KByps }.to_string())); + fmt::runtime(_("{download_speed} ▼ {upload_speed} ▲")), + fmt::arg("upload_speed", cache_.speed_up.to_string()), + fmt::arg("download_speed", cache_.speed_down.to_string())); } if (cache_.has_metadata && cache_.active_peers_up > 0) { - return fmt::format( - _("{upload_speed} ▲"), - fmt::arg("upload_speed", Speed{ cache_.speed_up, Speed::Units::KByps }.to_string())); + return fmt::format(fmt::runtime(_("{upload_speed} ▲")), fmt::arg("upload_speed", cache_.speed_up.to_string())); } if (cache_.stalled) @@ -720,12 +747,12 @@ tr_torrent& Torrent::get_underlying() const return *impl_->get_raw_torrent(); } -float Torrent::get_speed_up() const +Speed Torrent::get_speed_up() const { return impl_->get_cache().speed_up; } -float Torrent::get_speed_down() const +Speed Torrent::get_speed_down() const { return impl_->get_cache().speed_down; } @@ -790,7 +817,7 @@ int Torrent::get_active_peer_count() const return impl_->get_cache().active_peer_count; } -uint64_t Torrent::get_total_size() const +Storage Torrent::get_total_size() const { return impl_->get_cache().total_size; } diff --git a/gtk/Torrent.h b/gtk/Torrent.h index c98fc18fc..17c04de16 100644 --- a/gtk/Torrent.h +++ b/gtk/Torrent.h @@ -8,6 +8,7 @@ #include "Flags.h" #include +#include #include #include @@ -71,6 +72,9 @@ public: using ChangeFlags = Flags; public: + using Speed = libtransmission::Values::Speed; + using Storage = libtransmission::Values::Storage; + int get_active_peer_count() const; int get_active_peers_down() const; int get_active_peers_up() const; @@ -92,10 +96,10 @@ public: float get_ratio() const; Percents get_recheck_progress() const; Percents get_seed_ratio_percent_done() const; - float get_speed_down() const; - float get_speed_up() const; + Speed get_speed_down() const; + Speed get_speed_up() const; tr_torrent& get_underlying() const; - uint64_t get_total_size() const; + Storage get_total_size() const; unsigned int get_trackers() const; Glib::RefPtr get_icon() const; diff --git a/gtk/Utils.cc b/gtk/Utils.cc index 7aba70ee3..f877a4816 100644 --- a/gtk/Utils.cc +++ b/gtk/Utils.cc @@ -61,28 +61,6 @@ using namespace std::literals; using namespace libtransmission::Values; -/*** -**** UNITS -***/ - -int const mem_K = 1024; -char const* const mem_K_str = N_("KiB"); -char const* const mem_M_str = N_("MiB"); -char const* const mem_G_str = N_("GiB"); -char const* const mem_T_str = N_("TiB"); - -int const disk_K = 1000; -char const* const disk_K_str = N_("kB"); -char const* const disk_M_str = N_("MB"); -char const* const disk_G_str = N_("GB"); -char const* const disk_T_str = N_("TB"); - -int const speed_K = 1000; -char const* const speed_K_str = N_("kB/s"); -char const* const speed_M_str = N_("MB/s"); -char const* const speed_G_str = N_("GB/s"); -char const* const speed_T_str = N_("TB/s"); - /*** **** ***/ @@ -135,9 +113,14 @@ Glib::ustring tr_strlratio(double ratio) return tr_strratio(ratio, gtr_get_unicode_string(GtrUnicode::Inf).c_str()); } +Glib::ustring tr_strlsize(libtransmission::Values::Storage const& storage) +{ + return storage.is_zero() ? Q_("None") : storage.to_string(); +} + Glib::ustring tr_strlsize(guint64 n_bytes) { - return n_bytes == 0 ? Q_("None") : Storage{ n_bytes, Storage::Units::Bytes }.to_string(); + return tr_strlsize(Storage{ n_bytes, Storage::Units::Bytes }); } namespace diff --git a/gtk/Utils.h b/gtk/Utils.h index e6749dd45..980d1218f 100644 --- a/gtk/Utils.h +++ b/gtk/Utils.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -43,28 +44,6 @@ **** ***/ -extern int const mem_K; -extern char const* const mem_K_str; -extern char const* const mem_M_str; -extern char const* const mem_G_str; -extern char const* const mem_T_str; - -extern int const disk_K; -extern char const* const disk_K_str; -extern char const* const disk_M_str; -extern char const* const disk_G_str; -extern char const* const disk_T_str; - -extern int const speed_K; -extern char const* const speed_K_str; -extern char const* const speed_M_str; -extern char const* const speed_G_str; -extern char const* const speed_T_str; - -/*** -**** -***/ - void gtr_message(std::string const& message); void gtr_warning(std::string const& message); void gtr_error(std::string const& message); @@ -85,6 +64,7 @@ Glib::ustring gtr_get_unicode_string(GtrUnicode uni); /* return a human-readable string for the size given in bytes. */ Glib::ustring tr_strlsize(guint64 size_in_bytes); +Glib::ustring tr_strlsize(libtransmission::Values::Storage const& storage); /* return a human-readable string for the given ratio. */ Glib::ustring tr_strlratio(double ratio); diff --git a/gtk/main.cc b/gtk/main.cc index 03d5097d8..1b529eabb 100644 --- a/gtk/main.cc +++ b/gtk/main.cc @@ -32,7 +32,6 @@ namespace { - auto const* const AppConfigDirName = "transmission"; auto const* const AppTranslationDomainName = "transmission-gtk"; auto const* const AppName = "transmission-gtk"; @@ -45,7 +44,6 @@ Glib::OptionEntry create_option_entry(Glib::ustring const& long_name, gchar shor entry.set_description(description); return entry; } - } // namespace int main(int argc, char** argv) @@ -117,10 +115,11 @@ int main(int argc, char** argv) return 0; } - /* init the unit formatters */ - tr_formatter_mem_init(mem_K, _(mem_K_str), _(mem_M_str), _(mem_G_str), _(mem_T_str)); - tr_formatter_size_init(disk_K, _(disk_K_str), _(disk_M_str), _(disk_G_str), _(disk_T_str)); - tr_formatter_speed_init(speed_K, _(speed_K_str), _(speed_M_str), _(speed_G_str), _(speed_T_str)); + // init the unit formatters + using Config = libtransmission::Values::Config; + Config::Speed = { Config::Base::Kilo, _("B/s"), _("kB/s"), _("MB/s"), _("GB/s"), _("TB/s") }; + Config::Memory = { Config::Base::Kibi, _("B"), _("KiB"), _("MiB"), _("GiB"), _("TiB") }; + Config::Storage = { Config::Base::Kilo, _("B"), _("kB"), _("MB"), _("GB"), _("TB") }; /* set up the config dir */ if (std::empty(config_dir)) diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index ce6e2afe2..bd2ff3e80 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -1172,14 +1172,14 @@ private: [[nodiscard]] constexpr bool is_piece_transfer_allowed(tr_direction direction) const noexcept { - if (uses_speed_limit(direction) && speed_limit(direction).base_quantity() == 0U) + if (uses_speed_limit(direction) && speed_limit(direction).is_zero()) { return false; } if (uses_session_limits()) { - if (auto const limit = session->active_speed_limit(direction); limit && limit->base_quantity() == 0U) + if (auto const limit = session->active_speed_limit(direction); limit && limit->is_zero()) { return false; } diff --git a/libtransmission/utils.cc b/libtransmission/utils.cc index 2817b70d9..c00d768df 100644 --- a/libtransmission/utils.cc +++ b/libtransmission/utils.cc @@ -64,6 +64,18 @@ time_t libtransmission::detail::tr_time::current_time = {}; // --- +namespace libtransmission::Values +{ + +// default values; can be overridden by client apps +Config::Units Config::Memory{ Config::Base::Kibi, "B"sv, "KiB"sv, "MiB"sv, "GiB"sv, "TiB"sv }; +Config::Units Config::Speed{ Config::Base::Kilo, "B/s"sv, "kB/s"sv, "MB/s"sv, "GB/s"sv, "TB/s"sv }; +Config::Units Config::Storage{ Config::Base::Kilo, "B"sv, "kB"sv, "MB"sv, "GB"sv, "TB"sv }; + +} // namespace libtransmission::Values + +// --- + std::optional tr_locale_set_global(char const* locale_name) noexcept { try @@ -666,42 +678,6 @@ uint64_t tr_ntohll(uint64_t netlonglong) #endif } -// --- VALUES / FORMATTER - -namespace libtransmission::Values -{ - -// default values; can be overridden by client apps -Config::Units Config::Memory{ Config::Base::Kibi, "B"sv, "KiB"sv, "MiB"sv, "GiB"sv, "TiB"sv }; -Config::Units Config::Speed{ Config::Base::Kilo, "B/s"sv, "kB/s"sv, "MB/s"sv, "GB/s"sv, "TB/s"sv }; -Config::Units Config::Storage{ Config::Base::Kilo, "B"sv, "kB"sv, "MB"sv, "GB"sv, "TB"sv }; - -} // namespace libtransmission::Values - -void tr_formatter_size_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb) -{ - namespace Values = libtransmission::Values; - - auto const kval = base == 1000U ? Values::Config::Base::Kilo : Values::Config::Base::Kibi; - Values::Config::Storage = { kval, "B", kb, mb, gb, tb }; -} - -void tr_formatter_speed_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb) -{ - namespace Values = libtransmission::Values; - - auto const kval = base == 1000U ? Values::Config::Base::Kilo : Values::Config::Base::Kibi; - Values::Config::Speed = { kval, "B/s", kb, mb, gb, tb }; -} - -void tr_formatter_mem_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb) -{ - namespace Values = libtransmission::Values; - - auto const kval = base == 1000U ? Values::Config::Base::Kilo : Values::Config::Base::Kibi; - Values::Config::Memory = { kval, "B", kb, mb, gb, tb }; -} - // --- ENVIRONMENT bool tr_env_key_exists(char const* key) diff --git a/libtransmission/utils.h b/libtransmission/utils.h index 34647b8d1..3f571679a 100644 --- a/libtransmission/utils.h +++ b/libtransmission/utils.h @@ -300,13 +300,6 @@ constexpr void tr_timeUpdate(time_t now) noexcept // --- -/* example: tr_formatter_size_init(1024, _("KiB"), _("MiB"), _("GiB"), _("TiB")); */ -void tr_formatter_size_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb); -void tr_formatter_speed_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb); -void tr_formatter_mem_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb); - -// --- - /** @brief Check if environment variable exists. */ [[nodiscard]] bool tr_env_key_exists(char const* key); diff --git a/libtransmission/values.h b/libtransmission/values.h index 116d4c556..f8bbad46a 100644 --- a/libtransmission/values.h +++ b/libtransmission/values.h @@ -65,6 +65,11 @@ struct Config return std::string_view{ units < std::size(display_names_) ? std::data(display_names_[units]) : "" }; } + [[nodiscard]] constexpr auto display_name(UnitsEnum multiplier) const noexcept + { + return display_name(static_cast(multiplier)); + } + [[nodiscard]] constexpr auto multiplier(UnitsEnum multiplier) const noexcept { return multipliers_[static_cast(multiplier)]; @@ -122,6 +127,11 @@ public: return base_quantity_; } + [[nodiscard]] constexpr auto is_zero() const noexcept + { + return base_quantity_ == 0U; + } + [[nodiscard]] constexpr auto count(Units tgt) const noexcept { return base_quantity_ / (1.0 * units_.multiplier(tgt)); @@ -133,7 +143,7 @@ public: return *this; } - [[nodiscard]] constexpr auto operator+(Value const& that) noexcept + [[nodiscard]] constexpr auto operator+(Value const& that) const noexcept { auto ret = *this; return ret += that; @@ -145,7 +155,7 @@ public: return *this; } - [[nodiscard]] constexpr auto operator*(uint64_t mult) noexcept + [[nodiscard]] constexpr auto operator*(uint64_t mult) const noexcept { auto ret = *this; return ret *= mult; @@ -157,7 +167,7 @@ public: return *this; } - [[nodiscard]] constexpr auto operator/(uint64_t mult) noexcept + [[nodiscard]] constexpr auto operator/(uint64_t mult) const noexcept { auto ret = *this; return ret /= mult; diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 7c83e7477..6acc4fde7 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -16,6 +16,7 @@ #include #include #include +#include #include #import "VDKQueue.h" @@ -126,6 +127,41 @@ static NSString* const kDonateURL = @"https://transmissionbt.com/donate/"; static NSTimeInterval const kDonateNagTime = 60 * 60 * 24 * 7; +static void initUnits() +{ + using Config = libtransmission::Values::Config; + + // use a random value to avoid possible pluralization issues with 1 or 0 (an example is if we use 1 for bytes, + // we'd get "byte" when we'd want "bytes" for the generic libtransmission value at least) + int const ArbitraryPluralNumber = 17; + + NSByteCountFormatter* unitFormatter = [[NSByteCountFormatter alloc] init]; + unitFormatter.includesCount = NO; + unitFormatter.allowsNonnumericFormatting = NO; + unitFormatter.allowedUnits = NSByteCountFormatterUseBytes; + NSString* b_str = [unitFormatter stringFromByteCount:ArbitraryPluralNumber]; + unitFormatter.allowedUnits = NSByteCountFormatterUseKB; + NSString* k_str = [unitFormatter stringFromByteCount:ArbitraryPluralNumber]; + unitFormatter.allowedUnits = NSByteCountFormatterUseMB; + NSString* m_str = [unitFormatter stringFromByteCount:ArbitraryPluralNumber]; + unitFormatter.allowedUnits = NSByteCountFormatterUseGB; + NSString* g_str = [unitFormatter stringFromByteCount:ArbitraryPluralNumber]; + unitFormatter.allowedUnits = NSByteCountFormatterUseTB; + NSString* t_str = [unitFormatter stringFromByteCount:ArbitraryPluralNumber]; + Config::Memory = { Config::Base::Kilo, b_str.UTF8String, k_str.UTF8String, + m_str.UTF8String, g_str.UTF8String, t_str.UTF8String }; + Config::Storage = { Config::Base::Kilo, b_str.UTF8String, k_str.UTF8String, + m_str.UTF8String, g_str.UTF8String, t_str.UTF8String }; + + b_str = NSLocalizedString(@"B/s", "Transfer speed (bytes per second)"); + k_str = NSLocalizedString(@"KB/s", "Transfer speed (kilobytes per second)"); + m_str = NSLocalizedString(@"MB/s", "Transfer speed (megabytes per second)"); + g_str = NSLocalizedString(@"GB/s", "Transfer speed (gigabytes per second)"); + t_str = NSLocalizedString(@"TB/s", "Transfer speed (terabytes per second)"); + Config::Speed = { Config::Base::Kilo, b_str.UTF8String, k_str.UTF8String, + m_str.UTF8String, g_str.UTF8String, t_str.UTF8String }; +} + static void altSpeedToggledCallback([[maybe_unused]] tr_session* handle, bool active, bool byUser, void* controller) { NSDictionary* dict = @{@"Active" : @(active), @"ByUser" : @(byUser)}; @@ -514,34 +550,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool tr_variantDictAddStr(&settings, TR_KEY_rpc_host_whitelist, [_fDefaults stringForKey:@"RPCHostWhitelist"].UTF8String); } - NSByteCountFormatter* unitFormatter = [[NSByteCountFormatter alloc] init]; - unitFormatter.includesCount = NO; - unitFormatter.allowsNonnumericFormatting = NO; - - unitFormatter.allowedUnits = NSByteCountFormatterUseKB; - // use a random value to avoid possible pluralization issues with 1 or 0 (an example is if we use 1 for bytes, - // we'd get "byte" when we'd want "bytes" for the generic libtransmission value at least) - NSString* kbString = [unitFormatter stringFromByteCount:17]; - - unitFormatter.allowedUnits = NSByteCountFormatterUseMB; - NSString* mbString = [unitFormatter stringFromByteCount:17]; - - unitFormatter.allowedUnits = NSByteCountFormatterUseGB; - NSString* gbString = [unitFormatter stringFromByteCount:17]; - - unitFormatter.allowedUnits = NSByteCountFormatterUseTB; - NSString* tbString = [unitFormatter stringFromByteCount:17]; - - tr_formatter_size_init(1000, kbString.UTF8String, mbString.UTF8String, gbString.UTF8String, tbString.UTF8String); - - tr_formatter_speed_init( - 1000, - NSLocalizedString(@"KB/s", "Transfer speed (kilobytes per second)").UTF8String, - NSLocalizedString(@"MB/s", "Transfer speed (megabytes per second)").UTF8String, - NSLocalizedString(@"GB/s", "Transfer speed (gigabytes per second)").UTF8String, - NSLocalizedString(@"TB/s", "Transfer speed (terabytes per second)").UTF8String); //why not? - - tr_formatter_mem_init(1000, kbString.UTF8String, mbString.UTF8String, gbString.UTF8String, tbString.UTF8String); + initUnits(); auto const default_config_dir = tr_getDefaultConfigDir("Transmission"); _fLib = tr_sessionInit(default_config_dir.c_str(), YES, settings); diff --git a/qt/Application.cc b/qt/Application.cc index 7fb866564..506378e93 100644 --- a/qt/Application.cc +++ b/qt/Application.cc @@ -29,6 +29,7 @@ #include #include +#include #include #include "AddData.h" @@ -99,6 +100,7 @@ Application::Application(int& argc, char** argv) { setApplicationName(config_name_); loadTranslations(); + initUnits(); #if defined(_WIN32) || defined(__APPLE__) @@ -403,6 +405,20 @@ void Application::loadTranslations() } } +void Application::initUnits() +{ + using Config = libtransmission::Values::Config; + + Config::Speed = { Config::Base::Kilo, tr("B/s").toStdString(), tr("kB/s").toStdString(), + tr("MB/s").toStdString(), tr("GB/s").toStdString(), tr("TB/s").toStdString() }; + + Config::Memory = { Config::Base::Kibi, tr("B").toStdString(), tr("KiB").toStdString(), + tr("MiB").toStdString(), tr("GiB").toStdString(), tr("TiB").toStdString() }; + + Config::Storage = { Config::Base::Kilo, tr("B").toStdString(), tr("kB").toStdString(), + tr("MB").toStdString(), tr("GB").toStdString(), tr("TB").toStdString() }; +} + void Application::quitLater() const { QTimer::singleShot(0, this, SLOT(quit())); diff --git a/qt/Application.h b/qt/Application.h index 144de6ee1..a5bbd08fe 100644 --- a/qt/Application.h +++ b/qt/Application.h @@ -92,6 +92,7 @@ private slots: private: void maybeUpdateBlocklist() const; void loadTranslations(); + void initUnits(); QStringList getNames(torrent_ids_t const& ids) const; void quitLater() const; void notifyTorrentAdded(Torrent const*) const; diff --git a/qt/DetailsDialog.cc b/qt/DetailsDialog.cc index e00284f79..eb5440e90 100644 --- a/qt/DetailsDialog.cc +++ b/qt/DetailsDialog.cc @@ -430,7 +430,6 @@ void DetailsDialog::refreshUI() auto const mixed = tr("Mixed"); auto const unknown = tr("Unknown"); auto const now = time(nullptr); - auto const& fmt = Formatter::get(); // build a list of torrents auto torrents = QList{}; @@ -532,14 +531,14 @@ void DetailsDialog::refreshUI() double const d = size_when_done == 0 ? 100.0 : 100.0 * static_cast(size_when_done - left_until_done) / static_cast(size_when_done); - auto const pct = fmt.percentToString(d); - auto const size_when_done_str = fmt.sizeToString(size_when_done); + auto const pct = Formatter::percent_to_string(d); + auto const size_when_done_str = Formatter::storage_to_string(size_when_done); if (have_unverified == 0 && left_until_done == 0) { //: Text following the "Have:" label in torrent properties dialog; //: %1 is amount of downloaded and verified data - string = tr("%1 (100%)").arg(fmt.sizeToString(have_verified)); + string = tr("%1 (100%)").arg(Formatter::storage_to_string(have_verified)); } else if (have_unverified == 0) { @@ -547,7 +546,7 @@ void DetailsDialog::refreshUI() //: %1 is amount of downloaded and verified data, //: %2 is overall size of torrent data, //: %3 is percentage (%1/%2*100) - string = tr("%1 of %2 (%3%)").arg(fmt.sizeToString(have_verified)).arg(size_when_done_str).arg(pct); + string = tr("%1 of %2 (%3%)").arg(Formatter::storage_to_string(have_verified)).arg(size_when_done_str).arg(pct); } else { @@ -557,10 +556,10 @@ void DetailsDialog::refreshUI() //: %3 is percentage (%1/%2*100), //: %4 is amount of downloaded but not yet verified data string = tr("%1 of %2 (%3%), %4 Unverified") - .arg(fmt.sizeToString(have_verified + have_unverified)) + .arg(Formatter::storage_to_string(have_verified + have_unverified)) .arg(size_when_done_str) .arg(pct) - .arg(fmt.sizeToString(have_unverified)); + .arg(Formatter::storage_to_string(have_unverified)); } } @@ -574,7 +573,7 @@ void DetailsDialog::refreshUI() else { auto const percent = 100.0 * static_cast(available) / static_cast(size_when_done); - string = QStringLiteral("%1%").arg(fmt.percentToString(percent)); + string = QStringLiteral("%1%").arg(Formatter::percent_to_string(percent)); } ui_.availabilityValueLabel->setText(string); @@ -595,8 +594,8 @@ void DetailsDialog::refreshUI() f += t->failedEver(); } - QString const dstr = fmt.sizeToString(d); - QString const fstr = fmt.sizeToString(f); + auto const dstr = Formatter::storage_to_string(d); + auto const fstr = Formatter::storage_to_string(f); if (f != 0) { @@ -627,8 +626,8 @@ void DetailsDialog::refreshUI() } string = tr("%1 (Ratio: %2)") - .arg(fmt.sizeToString(uploaded)) - .arg(fmt.ratioToString(tr_getRatio(uploaded, denominator))); + .arg(Formatter::storage_to_string(uploaded)) + .arg(Formatter::ratio_to_string(tr_getRatio(uploaded, denominator))); } ui_.uploadedValueLabel->setText(string); @@ -667,7 +666,7 @@ void DetailsDialog::refreshUI() else { auto const seconds = static_cast(std::difftime(now, baseline)); - string = fmt.timeToString(seconds); + string = Formatter::time_to_string(seconds); } } @@ -701,7 +700,7 @@ void DetailsDialog::refreshUI() } else { - string = fmt.timeToString(baseline); + string = Formatter::time_to_string(baseline); } } } @@ -739,7 +738,7 @@ void DetailsDialog::refreshUI() } else { - string = tr("%1 ago").arg(fmt.timeToString(seconds)); + string = tr("%1 ago").arg(Formatter::time_to_string(seconds)); } } @@ -802,11 +801,13 @@ void DetailsDialog::refreshUI() } else if (piece_size > 0) { - string = tr("%1 (%Ln pieces @ %2)", "", pieces).arg(fmt.sizeToString(size)).arg(fmt.memToString(piece_size)); + string = tr("%1 (%Ln pieces @ %2)", "", pieces) + .arg(Formatter::storage_to_string(size)) + .arg(Formatter::memory_to_string(piece_size)); } else { - string = tr("%1 (%Ln pieces)", "", pieces).arg(fmt.sizeToString(size)); + string = tr("%1 (%Ln pieces)", "", pieces).arg(Formatter::storage_to_string(size)); } } @@ -1449,10 +1450,9 @@ void DetailsDialog::onRemoveTrackerClicked() void DetailsDialog::initOptionsTab() { - auto const speed_unit_str = Formatter::get().unitStr(Formatter::SPEED, Formatter::KB); - - ui_.singleDownSpin->setSuffix(QStringLiteral(" %1").arg(speed_unit_str)); - ui_.singleUpSpin->setSuffix(QStringLiteral(" %1").arg(speed_unit_str)); + auto const speed_unit_suffix = QStringLiteral(" %1").arg(Speed::display_name(Speed::Units::KByps)); + ui_.singleDownSpin->setSuffix(speed_unit_suffix); + ui_.singleUpSpin->setSuffix(speed_unit_suffix); ui_.singleDownSpin->setProperty(PrefKey, TR_KEY_downloadLimit); ui_.singleUpSpin->setProperty(PrefKey, TR_KEY_uploadLimit); @@ -1545,12 +1545,14 @@ void DetailsDialog::initTrackerTab() void DetailsDialog::initPeersTab() { + auto const speed_width_str = Speed{ 1024U, Speed::Units::MByps }.to_qstring(); + ui_.peersView->setHeaderLabels({ QString{}, tr("Up"), tr("Down"), tr("%"), tr("Status"), tr("Address"), tr("Client") }); ui_.peersView->sortByColumn(COL_ADDRESS, Qt::AscendingOrder); ui_.peersView->setColumnWidth(COL_LOCK, 20); - ui_.peersView->setColumnWidth(COL_UP, measureViewItem(ui_.peersView, COL_UP, QStringLiteral("1024 MiB/s"))); - ui_.peersView->setColumnWidth(COL_DOWN, measureViewItem(ui_.peersView, COL_DOWN, QStringLiteral("1024 MiB/s"))); + ui_.peersView->setColumnWidth(COL_UP, measureViewItem(ui_.peersView, COL_UP, speed_width_str)); + ui_.peersView->setColumnWidth(COL_DOWN, measureViewItem(ui_.peersView, COL_DOWN, speed_width_str)); ui_.peersView->setColumnWidth(COL_PERCENT, measureViewItem(ui_.peersView, COL_PERCENT, QStringLiteral("100%"))); ui_.peersView->setColumnWidth(COL_STATUS, measureViewItem(ui_.peersView, COL_STATUS, QStringLiteral("ODUK?EXI"))); ui_.peersView->setColumnWidth(COL_ADDRESS, measureViewItem(ui_.peersView, COL_ADDRESS, QStringLiteral("888.888.888.888"))); diff --git a/qt/FileTreeItem.cc b/qt/FileTreeItem.cc index c2d2bcc95..a4aad3c69 100644 --- a/qt/FileTreeItem.cc +++ b/qt/FileTreeItem.cc @@ -220,7 +220,7 @@ double FileTreeItem::progress() const QString FileTreeItem::sizeString() const { - return Formatter::get().sizeToString(size()); + return Formatter::storage_to_string(size()); } uint64_t FileTreeItem::size() const diff --git a/qt/FileTreeView.cc b/qt/FileTreeView.cc index 07668faad..6dea4abd6 100644 --- a/qt/FileTreeView.cc +++ b/qt/FileTreeView.cc @@ -22,6 +22,8 @@ #include "Formatter.h" #include "Utils.h" +using namespace libtransmission::Values; + namespace { @@ -89,12 +91,11 @@ void FileTreeView::resizeEvent(QResizeEvent* event) switch (column) { case FileTreeModel::COL_SIZE: - for (int s = Formatter::get().B; s <= Formatter::get().TB; ++s) - { - item_texts - << (QStringLiteral("999.9 ") + Formatter::get().unitStr(Formatter::MEM, static_cast(s))); - } - + item_texts << QString::fromStdString(Memory{ 999.9, Memory::Units::Bytes }.to_string()) + << QString::fromStdString(Memory{ 999.9, Memory::Units::KBytes }.to_string()) + << QString::fromStdString(Memory{ 999.9, Memory::Units::MBytes }.to_string()) + << QString::fromStdString(Memory{ 999.9, Memory::Units::GBytes }.to_string()) + << QString::fromStdString(Memory{ 999.9, Memory::Units::TBytes }.to_string()); break; case FileTreeModel::COL_PROGRESS: diff --git a/qt/Formatter.cc b/qt/Formatter.cc index 636eef731..cda61b447 100644 --- a/qt/Formatter.cc +++ b/qt/Formatter.cc @@ -8,58 +8,13 @@ #include #include "Formatter.h" -#include "Speed.h" #include using namespace std::literals; - using namespace libtransmission::Values; -Formatter& Formatter::get() -{ - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - static auto& singleton = *new Formatter(); - return singleton; -} - -Formatter::Formatter() - : UnitStrings{ { - { tr("B/s"), tr("kB/s"), tr("MB/s"), tr("GB/s"), tr("TB/s") }, // SPEED - { tr("B"), tr("kB"), tr("MB"), tr("GB"), tr("TB") }, // SIZE - { tr("B"), tr("KiB"), tr("MiB"), tr("GiB"), tr("TiB") } // MEM - } } -{ - namespace Values = libtransmission::Values; - - auto const& speed = UnitStrings[SPEED]; - Values::Config::Speed = { Values::Config::Base::Kilo, "B"sv, - speed[KB].toStdString(), speed[MB].toStdString(), - speed[GB].toStdString(), speed[TB].toStdString() }; - - auto const& size = UnitStrings[SIZE]; - tr_formatter_size_init( - SizeBase, - size[KB].toUtf8().constData(), - size[MB].toUtf8().constData(), - size[GB].toUtf8().constData(), - size[TB].toUtf8().constData()); - - auto const& mem = UnitStrings[MEM]; - tr_formatter_mem_init( - MemBase, - mem[KB].toUtf8().constData(), - mem[MB].toUtf8().constData(), - mem[GB].toUtf8().constData(), - mem[TB].toUtf8().constData()); -} - -QString Formatter::unitStr(Type t, Size s) const -{ - return UnitStrings[t][s]; -} - -QString Formatter::memToString(int64_t bytes) const +QString Formatter::memory_to_string(int64_t const bytes) { if (bytes < 0) { @@ -74,7 +29,7 @@ QString Formatter::memToString(int64_t bytes) const return QString::fromStdString(Memory{ bytes, Memory::Units::Bytes }.to_string()); } -QString Formatter::sizeToString(uint64_t bytes) const +QString Formatter::storage_to_string(uint64_t const bytes) { if (bytes == 0) { @@ -84,17 +39,17 @@ QString Formatter::sizeToString(uint64_t bytes) const return QString::fromStdString(Storage{ bytes, Storage::Units::Bytes }.to_string()); } -QString Formatter::sizeToString(int64_t bytes) const +QString Formatter::storage_to_string(int64_t const bytes) { if (bytes < 0) { return tr("Unknown"); } - return Formatter::sizeToString(static_cast(bytes)); + return storage_to_string(static_cast(bytes)); } -QString Formatter::timeToString(int seconds) const +QString Formatter::time_to_string(int seconds) { seconds = std::max(seconds, 0); diff --git a/qt/Formatter.h b/qt/Formatter.h index a3b24c9bd..c001e46a3 100644 --- a/qt/Formatter.h +++ b/qt/Formatter.h @@ -20,52 +20,24 @@ class Formatter Q_DECLARE_TR_FUNCTIONS(Formatter) public: - enum Size - { - B, - KB, - MB, - GB, - TB, + Formatter() = delete; - NUM_SIZES - }; + [[nodiscard]] static QString memory_to_string(int64_t bytes); - enum Type - { - SPEED, - SIZE, - MEM, - - NUM_TYPES - }; - - static constexpr int SizeBase = 1000; - static constexpr int MemBase = 1024; - - [[nodiscard]] static Formatter& get(); - - [[nodiscard]] QString memToString(int64_t bytes) const; - [[nodiscard]] QString sizeToString(int64_t bytes) const; - [[nodiscard]] QString sizeToString(uint64_t bytes) const; - [[nodiscard]] QString timeToString(int seconds) const; - [[nodiscard]] QString unitStr(Type t, Size s) const; - - [[nodiscard]] auto percentToString(double x) const + [[nodiscard]] static auto percent_to_string(double x) { return QString::fromStdString(tr_strpercent(x)); } - [[nodiscard]] auto ratioToString(double ratio) const + [[nodiscard]] static auto ratio_to_string(double ratio) { static auto constexpr InfinitySymbol = "\xE2\x88\x9E"; return QString::fromStdString(tr_strratio(ratio, InfinitySymbol)); } -protected: - Formatter(); + [[nodiscard]] static QString storage_to_string(int64_t bytes); + [[nodiscard]] static QString storage_to_string(uint64_t bytes); -private: - std::array, Formatter::NUM_TYPES> const UnitStrings; + [[nodiscard]] static QString time_to_string(int seconds); }; diff --git a/qt/FreeSpaceLabel.cc b/qt/FreeSpaceLabel.cc index b3ad7544a..14f5e9a23 100644 --- a/qt/FreeSpaceLabel.cc +++ b/qt/FreeSpaceLabel.cc @@ -78,7 +78,7 @@ void FreeSpaceLabel::onTimer() // update the label if (auto const bytes = dictFind(r.args.get(), TR_KEY_size_bytes); bytes && *bytes > 1) { - setText(tr("%1 free").arg(Formatter::get().sizeToString(*bytes))); + setText(tr("%1 free").arg(Formatter::storage_to_string(*bytes))); } else { diff --git a/qt/MainWindow.cc b/qt/MainWindow.cc index 5df5c36ba..34a7d68e9 100644 --- a/qt/MainWindow.cc +++ b/qt/MainWindow.cc @@ -446,7 +446,7 @@ QMenu* MainWindow::createOptionsMenu() action_group->addAction(off_action); connect(off_action, &QAction::triggered, this, qOverload(&MainWindow::onSetPrefs)); - on_action = menu->addAction(tr("Stop at Ratio (%1)").arg(Formatter::get().ratioToString(current_value))); + on_action = menu->addAction(tr("Stop at Ratio (%1)").arg(Formatter::ratio_to_string(current_value))); on_action->setCheckable(true); on_action->setProperty(PrefVariantsKey, QVariantList{ pref, current_value, enabled_pref, true }); action_group->addAction(on_action); @@ -456,7 +456,7 @@ QMenu* MainWindow::createOptionsMenu() for (double const i : StockRatios) { - QAction* action = menu->addAction(Formatter::get().ratioToString(i)); + QAction* action = menu->addAction(Formatter::ratio_to_string(i)); action->setProperty(PrefVariantsKey, QVariantList{ pref, i, enabled_pref, true }); connect(action, &QAction::triggered, this, qOverload<>(&MainWindow::onSetPrefs)); } @@ -824,7 +824,6 @@ void MainWindow::refreshTrayIcon(TransferStats const& stats) void MainWindow::refreshStatusBar(TransferStats const& stats) { - auto const& fmt = Formatter::get(); ui_.uploadSpeedLabel->setText(stats.speed_up.to_upload_qstring()); ui_.uploadSpeedLabel->setVisible(stats.peers_sending || stats.peers_receiving); ui_.downloadSpeedLabel->setText(stats.speed_down.to_download_qstring()); @@ -837,22 +836,26 @@ void MainWindow::refreshStatusBar(TransferStats const& stats) if (mode == session_ratio_stats_mode_name_) { - str = tr("Ratio: %1").arg(fmt.ratioToString(session_.getStats().ratio)); + str = tr("Ratio: %1").arg(Formatter::ratio_to_string(session_.getStats().ratio)); } else if (mode == session_transfer_stats_mode_name_) { auto const& st = session_.getStats(); - str = tr("Down: %1, Up: %2").arg(fmt.sizeToString(st.downloadedBytes)).arg(fmt.sizeToString(st.uploadedBytes)); + str = tr("Down: %1, Up: %2") + .arg(Formatter::storage_to_string(st.downloadedBytes)) + .arg(Formatter::storage_to_string(st.uploadedBytes)); } else if (mode == total_transfer_stats_mode_name_) { auto const& st = session_.getCumulativeStats(); - str = tr("Down: %1, Up: %2").arg(fmt.sizeToString(st.downloadedBytes)).arg(fmt.sizeToString(st.uploadedBytes)); + str = tr("Down: %1, Up: %2") + .arg(Formatter::storage_to_string(st.downloadedBytes)) + .arg(Formatter::storage_to_string(st.uploadedBytes)); } else // default is "total-ratio" { assert(mode == total_ratio_stats_mode_name_); - str = tr("Ratio: %1").arg(fmt.ratioToString(session_.getCumulativeStats().ratio)); + str = tr("Ratio: %1").arg(Formatter::ratio_to_string(session_.getCumulativeStats().ratio)); } ui_.statsLabel->setText(str); @@ -1188,7 +1191,7 @@ void MainWindow::refreshPref(int key) break; case Prefs::RATIO: - ratio_on_action_->setText(tr("Stop at Ratio (%1)").arg(Formatter::get().ratioToString(prefs_.get(key)))); + ratio_on_action_->setText(tr("Stop at Ratio (%1)").arg(Formatter::ratio_to_string(prefs_.get(key)))); break; case Prefs::FILTERBAR: @@ -1241,8 +1244,8 @@ void MainWindow::refreshPref(int key) b = prefs_.getBool(Prefs::ALT_SPEED_LIMIT_ENABLED); alt_speed_action_->setChecked(b); ui_.altSpeedButton->setChecked(b); - QString const fmt = b ? tr("Click to disable Temporary Speed Limits\n (%1 down, %2 up)") : - tr("Click to enable Temporary Speed Limits\n (%1 down, %2 up)"); + auto const fmt = b ? tr("Click to disable Temporary Speed Limits\n (%1 down, %2 up)") : + tr("Click to enable Temporary Speed Limits\n (%1 down, %2 up)"); auto const d = Speed{ prefs_.get(Prefs::ALT_SPEED_LIMIT_DOWN), Speed::Units::KByps }; auto const u = Speed{ prefs_.get(Prefs::ALT_SPEED_LIMIT_UP), Speed::Units::KByps }; ui_.altSpeedButton->setToolTip(fmt.arg(d.to_qstring()).arg(u.to_qstring())); @@ -1495,7 +1498,7 @@ void MainWindow::updateNetworkIcon() } else if (seconds_since_last_read < 120) { - tip = tr("%1 last responded %2 ago").arg(url).arg(Formatter::get().timeToString(seconds_since_last_read)); + tip = tr("%1 last responded %2 ago").arg(url).arg(Formatter::time_to_string(seconds_since_last_read)); } else { diff --git a/qt/MakeDialog.cc b/qt/MakeDialog.cc index ab253c0d6..c386336c4 100644 --- a/qt/MakeDialog.cc +++ b/qt/MakeDialog.cc @@ -309,10 +309,10 @@ void MakeDialog::updatePiecesLabel() auto const files = tr("%Ln File(s)", nullptr, builder_->file_count()); auto const pieces = tr("%Ln Piece(s)", nullptr, builder_->piece_count()); text = tr("%1 in %2; %3 @ %4") - .arg(Formatter::get().sizeToString(builder_->total_size())) + .arg(Formatter::storage_to_string(builder_->total_size())) .arg(files) .arg(pieces) - .arg(Formatter::get().memToString(static_cast(builder_->piece_size()))); + .arg(Formatter::memory_to_string(static_cast(builder_->piece_size()))); ui_.pieceSizeSlider->setEnabled(true); } diff --git a/qt/PrefsDialog.cc b/qt/PrefsDialog.cc index a6c53dff6..eb38ea13e 100644 --- a/qt/PrefsDialog.cc +++ b/qt/PrefsDialog.cc @@ -36,9 +36,7 @@ #include "Session.h" #include "Utils.h" -/*** -**** -***/ +// --- namespace { @@ -370,9 +368,9 @@ void PrefsDialog::altSpeedDaysEdited(int i) void PrefsDialog::initSpeedTab() { - QString const speed_unit_str = Formatter::get().unitStr(Formatter::get().SPEED, Formatter::get().KB); - auto const suffix = QStringLiteral(" %1").arg(speed_unit_str); - QLocale const locale; + auto const suffix = QStringLiteral(" %1").arg(Speed::display_name(Speed::Units::KByps)); + + auto const locale = QLocale{}; ui_.uploadSpeedLimitSpin->setSuffix(suffix); ui_.downloadSpeedLimitSpin->setSuffix(suffix); diff --git a/qt/Speed.h b/qt/Speed.h index 809cfe602..f9a469ffb 100644 --- a/qt/Speed.h +++ b/qt/Speed.h @@ -29,11 +29,6 @@ public: { } - [[nodiscard]] auto constexpr is_zero() const noexcept - { - return base_quantity() == 0U; - } - [[nodiscard]] auto to_qstring() const noexcept { return QString::fromStdString(to_string()); @@ -55,4 +50,10 @@ public: { return Speed{ base_quantity() + other.base_quantity(), Speed::Units::Byps }; } + + [[nodiscard]] static auto display_name(Speed::Units const units) + { + auto const speed_unit_sv = Speed::units().display_name(units); + return QString::fromUtf8(std::data(speed_unit_sv), std::size(speed_unit_sv)); + } }; diff --git a/qt/StatsDialog.cc b/qt/StatsDialog.cc index 51c36e854..3422c98af 100644 --- a/qt/StatsDialog.cc +++ b/qt/StatsDialog.cc @@ -50,15 +50,15 @@ void StatsDialog::updateStats() tr_session_stats const& current(session_.getStats()); tr_session_stats const& total(session_.getCumulativeStats()); - ui_.currentUploadedValueLabel->setText(Formatter::get().sizeToString(current.uploadedBytes)); - ui_.currentDownloadedValueLabel->setText(Formatter::get().sizeToString(current.downloadedBytes)); - ui_.currentRatioValueLabel->setText(Formatter::get().ratioToString(current.ratio)); - ui_.currentDurationValueLabel->setText(Formatter::get().timeToString(current.secondsActive)); + ui_.currentUploadedValueLabel->setText(Formatter::storage_to_string(current.uploadedBytes)); + ui_.currentDownloadedValueLabel->setText(Formatter::storage_to_string(current.downloadedBytes)); + ui_.currentRatioValueLabel->setText(Formatter::ratio_to_string(current.ratio)); + ui_.currentDurationValueLabel->setText(Formatter::time_to_string(current.secondsActive)); - ui_.totalUploadedValueLabel->setText(Formatter::get().sizeToString(total.uploadedBytes)); - ui_.totalDownloadedValueLabel->setText(Formatter::get().sizeToString(total.downloadedBytes)); - ui_.totalRatioValueLabel->setText(Formatter::get().ratioToString(total.ratio)); - ui_.totalDurationValueLabel->setText(Formatter::get().timeToString(total.secondsActive)); + ui_.totalUploadedValueLabel->setText(Formatter::storage_to_string(total.uploadedBytes)); + ui_.totalDownloadedValueLabel->setText(Formatter::storage_to_string(total.downloadedBytes)); + ui_.totalRatioValueLabel->setText(Formatter::ratio_to_string(total.ratio)); + ui_.totalDurationValueLabel->setText(Formatter::time_to_string(total.secondsActive)); ui_.startCountLabel->setText(tr("Started %Ln time(s)", nullptr, total.sessionCount)); } diff --git a/qt/TorrentDelegate.cc b/qt/TorrentDelegate.cc index 50fb0e9af..0bdea3e70 100644 --- a/qt/TorrentDelegate.cc +++ b/qt/TorrentDelegate.cc @@ -172,7 +172,7 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: First part of torrent progress string, //: %1 is the percentage of torrent metadata downloaded str = tr("Magnetized transfer - retrieving metadata (%1%)") - .arg(Formatter::get().percentToString(tor.metadataPercentDone() * 100.0)); + .arg(Formatter::percent_to_string(tor.metadataPercentDone() * 100.0)); } else if (!is_done) // downloading { @@ -181,9 +181,9 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: %2 is how much we'll have when done, //: %3 is a percentage of the two str = tr("%1 of %2 (%3%)") - .arg(Formatter::get().sizeToString(have_total)) - .arg(Formatter::get().sizeToString(tor.sizeWhenDone())) - .arg(Formatter::get().percentToString(tor.percentDone() * 100.0)); + .arg(Formatter::storage_to_string(have_total)) + .arg(Formatter::storage_to_string(tor.sizeWhenDone())) + .arg(Formatter::percent_to_string(tor.percentDone() * 100.0)); } else if (!is_seed) // partial seed { @@ -197,12 +197,12 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: %5 is our upload-to-download ratio, //: %6 is the ratio we want to reach before we stop uploading str = tr("%1 of %2 (%3%), uploaded %4 (Ratio: %5 Goal: %6)") - .arg(Formatter::get().sizeToString(have_total)) - .arg(Formatter::get().sizeToString(tor.totalSize())) - .arg(Formatter::get().percentToString(tor.percentComplete() * 100.0)) - .arg(Formatter::get().sizeToString(tor.uploadedEver())) - .arg(Formatter::get().ratioToString(tor.ratio())) - .arg(Formatter::get().ratioToString(*seed_ratio_limit)); + .arg(Formatter::storage_to_string(have_total)) + .arg(Formatter::storage_to_string(tor.totalSize())) + .arg(Formatter::percent_to_string(tor.percentComplete() * 100.0)) + .arg(Formatter::storage_to_string(tor.uploadedEver())) + .arg(Formatter::ratio_to_string(tor.ratio())) + .arg(Formatter::ratio_to_string(*seed_ratio_limit)); } else { @@ -213,11 +213,11 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: %4 is how much we've uploaded, //: %5 is our upload-to-download ratio str = tr("%1 of %2 (%3%), uploaded %4 (Ratio: %5)") - .arg(Formatter::get().sizeToString(have_total)) - .arg(Formatter::get().sizeToString(tor.totalSize())) - .arg(Formatter::get().percentToString(tor.percentComplete() * 100.0)) - .arg(Formatter::get().sizeToString(tor.uploadedEver())) - .arg(Formatter::get().ratioToString(tor.ratio())); + .arg(Formatter::storage_to_string(have_total)) + .arg(Formatter::storage_to_string(tor.totalSize())) + .arg(Formatter::percent_to_string(tor.percentComplete() * 100.0)) + .arg(Formatter::storage_to_string(tor.uploadedEver())) + .arg(Formatter::ratio_to_string(tor.ratio())); } } else // seeding @@ -230,10 +230,10 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: %3 is our upload-to-download ratio, //: %4 is the ratio we want to reach before we stop uploading str = tr("%1, uploaded %2 (Ratio: %3 Goal: %4)") - .arg(Formatter::get().sizeToString(have_total)) - .arg(Formatter::get().sizeToString(tor.uploadedEver())) - .arg(Formatter::get().ratioToString(tor.ratio())) - .arg(Formatter::get().ratioToString(*seed_ratio_limit)); + .arg(Formatter::storage_to_string(have_total)) + .arg(Formatter::storage_to_string(tor.uploadedEver())) + .arg(Formatter::ratio_to_string(tor.ratio())) + .arg(Formatter::ratio_to_string(*seed_ratio_limit)); } else // seeding w/o a ratio { @@ -242,9 +242,9 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: %2 is how much we've uploaded, //: %3 is our upload-to-download ratio str = tr("%1, uploaded %2 (Ratio: %3)") - .arg(Formatter::get().sizeToString(have_total)) - .arg(Formatter::get().sizeToString(tor.uploadedEver())) - .arg(Formatter::get().ratioToString(tor.ratio())); + .arg(Formatter::storage_to_string(have_total)) + .arg(Formatter::storage_to_string(tor.uploadedEver())) + .arg(Formatter::ratio_to_string(tor.ratio())); } } @@ -256,7 +256,7 @@ QString TorrentDelegate::progressString(Torrent const& tor) //: Second (optional) part of torrent progress string, //: %1 is duration, //: notice that leading space (before the dash) is included here - str += tr(" - %1 left").arg(Formatter::get().timeToString(tor.getETA())); + str += tr(" - %1 left").arg(Formatter::time_to_string(tor.getETA())); } else { @@ -295,13 +295,12 @@ QString TorrentDelegate::shortStatusString(Torrent const& tor) switch (tor.getActivity()) { case TR_STATUS_CHECK: - str = tr("Verifying local data (%1% tested)").arg(Formatter::get().percentToString(tor.getVerifyProgress() * 100.0)); + str = tr("Verifying local data (%1% tested)").arg(Formatter::percent_to_string(tor.getVerifyProgress() * 100.0)); break; case TR_STATUS_DOWNLOAD: case TR_STATUS_SEED: - str = shortTransferString(tor) + QStringLiteral(" ") + - tr("Ratio: %1").arg(Formatter::get().ratioToString(tor.ratio())); + str = shortTransferString(tor) + QStringLiteral(" ") + tr("Ratio: %1").arg(Formatter::ratio_to_string(tor.ratio())); break; default: @@ -336,7 +335,7 @@ QString TorrentDelegate::statusString(Torrent const& tor) if (!tor.hasMetadata()) { str = tr("Downloading metadata from %Ln peer(s) (%1% done)", nullptr, tor.peersWeAreDownloadingFrom()) - .arg(Formatter::get().percentToString(100.0 * tor.metadataPercentDone())); + .arg(Formatter::percent_to_string(100.0 * tor.metadataPercentDone())); } else { diff --git a/qt/TrackerDelegate.cc b/qt/TrackerDelegate.cc index eba3136cb..6c2ac12e8 100644 --- a/qt/TrackerDelegate.cc +++ b/qt/TrackerDelegate.cc @@ -24,7 +24,6 @@ namespace { - auto constexpr Spacing = int{ 6 }; auto constexpr Margin = QSize{ 10, 10 }; @@ -158,17 +157,15 @@ void TrackerDelegate::setShowMore(bool b) namespace { - -QString timeToStringRounded(int seconds) +QString timeToRoundedString(int seconds) { if (seconds > 60) { seconds -= seconds % 60; } - return Formatter::get().timeToString(seconds); + return Formatter::time_to_string(seconds); } - } // namespace QString TrackerDelegate::getText(TrackerInfo const& inf) const @@ -184,11 +181,11 @@ QString TrackerDelegate::getText(TrackerInfo const& inf) const auto const now = time(nullptr); auto const time_until = [&now](auto t) { - return timeToStringRounded(static_cast(t - now)); + return timeToRoundedString(static_cast(t - now)); }; auto const time_since = [&now](auto t) { - return timeToStringRounded(static_cast(now - t)); + return timeToRoundedString(static_cast(now - t)); }; // hostname diff --git a/tests/libtransmission/values-test.cc b/tests/libtransmission/values-test.cc index 2bae5f49c..76ad235fa 100644 --- a/tests/libtransmission/values-test.cc +++ b/tests/libtransmission/values-test.cc @@ -50,11 +50,14 @@ TEST_F(ValuesTest, toString) EXPECT_EQ("999.2 kB/s", val.to_string()); } -TEST_F(ValuesTest, valueHonorsFormatterInit) +TEST_F(ValuesTest, isZero) { - tr_formatter_speed_init(1024, "KayBeePerEss", "EmmBeePerEss", "GeeBeePerEss", "TeeBeePerEss"); + auto val = Speed{}; + EXPECT_TRUE(val.is_zero()); - auto const val = Speed{ 1, Speed::Units::MByps }; - EXPECT_EQ("1 EmmBeePerEss", val.to_string()); - EXPECT_EQ(1048576U, val.base_quantity()); + val = Speed{ 0, Speed::Units::Byps }; + EXPECT_TRUE(val.is_zero()); + + val = Speed{ 1, Speed::Units::Byps }; + EXPECT_FALSE(val.is_zero()); }