diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 391a44fb6..5bc4fc7f5 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -187,7 +187,7 @@ jobs: - name: Get Dependencies run: | brew update - brew install cmake gettext libdeflate libevent libnatpmp libpsl miniupnpc ninja node + brew install cmake gettext libdeflate libevent libnatpmp libpsl miniupnpc ninja node pkg-config - name: Get Dependencies (GTK) if: ${{ needs.what-to-make.outputs.make-gtk == 'true' }} run: brew install gtkmm3 libjpeg @@ -462,7 +462,7 @@ jobs: - name: Get Dependencies run: | brew update - brew install cmake gettext libdeflate libevent libnatpmp libpsl miniupnpc ninja node + brew install cmake gettext libdeflate libevent libnatpmp libpsl miniupnpc ninja node pkg-config - name: Get Dependencies (GTK) if: ${{ needs.what-to-make.outputs.make-gtk == 'true' }} run: brew install gtkmm3 libjpeg diff --git a/gtk/CMakeLists.txt b/gtk/CMakeLists.txt index e81269ab0..0d2499f59 100644 --- a/gtk/CMakeLists.txt +++ b/gtk/CMakeLists.txt @@ -44,6 +44,8 @@ target_sources(${TR_NAME}-gtk OptionsDialog.h PathButton.cc PathButton.h + Percents.cc + Percents.h Prefs.cc Prefs.h PrefsDialog.cc diff --git a/gtk/Percents.cc b/gtk/Percents.cc new file mode 100644 index 000000000..786a71f5b --- /dev/null +++ b/gtk/Percents.cc @@ -0,0 +1,9 @@ +#include "Percents.h" + +#include +#include + +std::string Percents::to_string() const +{ + return tr_strpercent(raw_value_ / 100.); +} diff --git a/gtk/Percents.h b/gtk/Percents.h new file mode 100644 index 000000000..d5f126500 --- /dev/null +++ b/gtk/Percents.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +class Percents +{ +public: + Percents() = default; + + explicit Percents(int value) noexcept + : raw_value_(value * 100) + { + } + + explicit Percents(float value) noexcept + : raw_value_(std::round(value * 10000)) + { + } + + [[nodiscard]] constexpr int to_int() const noexcept + { + return raw_value_ / 100; + } + + [[nodiscard]] std::string to_string() const; + + constexpr bool operator==(Percents const& rhs) const noexcept + { + return raw_value_ == rhs.raw_value_; + } + + constexpr bool operator<(Percents const& rhs) const noexcept + { + return raw_value_ < rhs.raw_value_; + } + +private: + int raw_value_ = 0; +}; diff --git a/gtk/Torrent.cc b/gtk/Torrent.cc index 52d44c164..715898707 100644 --- a/gtk/Torrent.cc +++ b/gtk/Torrent.cc @@ -6,6 +6,7 @@ #include "Torrent.h" #include "IconCache.h" +#include "Percents.h" #include "Utils.h" #include @@ -18,6 +19,7 @@ #include #include +#include using namespace std::string_view_literals; @@ -33,6 +35,8 @@ Glib::Value& column_value_cast(Glib::ValueBase& value, Gtk::TreeModelColumn>> void update_cache_value(T& value, U&& new_value, Torrent::ChangeFlags& changes, Torrent::ChangeFlag flag) { + using std::rel_ops::operator!=; + if (value != new_value) { value = std::forward(new_value); @@ -123,19 +127,20 @@ public: int active_peers_up = {}; int error_code = {}; + Percents activity_percent_done = {}; + Percents metadata_percent_complete = {}; + Percents percent_complete = {}; + Percents percent_done = {}; + Percents recheck_progress = {}; + Percents seed_ratio_percent_done = {}; + uint16_t peers_connected = {}; uint16_t peers_getting_from_us = {}; uint16_t peers_sending_to_us = {}; uint16_t webseeds_sending_to_us = {}; - float activity_percent_done = {}; - float metadata_percent_complete = {}; - float percent_complete = {}; - float percent_done = {}; float ratio = {}; - float recheck_progress = {}; float seed_ratio = {}; - float seed_ratio_percent_done = {}; float speed_down = {}; float speed_up = {}; @@ -213,7 +218,7 @@ Torrent::ChangeFlags Torrent::Impl::update_cache() stats->peersSendingToUs + stats->webseedsSendingToUs, result, ChangeFlag::ACTIVE_PEERS_DOWN); - update_cache_value(cache_.recheck_progress, stats->recheckProgress, 0.01F, result, ChangeFlag::RECHECK_PROGRESS); + update_cache_value(cache_.recheck_progress, Percents(stats->recheckProgress), result, ChangeFlag::RECHECK_PROGRESS); update_cache_value( cache_.active, stats->peersSendingToUs > 0 || stats->peersGettingFromUs > 0 || stats->activity == TR_STATUS_CHECK, @@ -222,11 +227,10 @@ Torrent::ChangeFlags Torrent::Impl::update_cache() update_cache_value(cache_.activity, stats->activity, result, ChangeFlag::ACTIVITY); update_cache_value( cache_.activity_percent_done, - std::clamp( + Percents(std::clamp( stats->activity == TR_STATUS_SEED && has_seed_ratio ? stats->seedRatioPercentDone : stats->percentDone, 0.0F, - 1.0F), - 0.01F, + 1.0F)), result, ChangeFlag::PERCENT_DONE); update_cache_value(cache_.finished, stats->finished, result, ChangeFlag::FINISHED); @@ -247,11 +251,10 @@ Torrent::ChangeFlags Torrent::Impl::update_cache() update_cache_value(cache_.added_date, stats->addedDate, result, ChangeFlag::ADDED_DATE); update_cache_value(cache_.eta, stats->eta, result, ChangeFlag::ETA); - update_cache_value(cache_.percent_complete, stats->percentComplete, 0.01F, result, ChangeFlag::PERCENT_COMPLETE); + update_cache_value(cache_.percent_complete, Percents(stats->percentComplete), result, ChangeFlag::PERCENT_COMPLETE); update_cache_value( cache_.seed_ratio_percent_done, - stats->seedRatioPercentDone, - 0.01F, + Percents(stats->seedRatioPercentDone), result, ChangeFlag::SEED_RATIO_PERCENT_DONE); update_cache_value(cache_.total_size, tr_torrentTotalSize(raw_torrent_), result, ChangeFlag::TOTAL_SIZE); @@ -260,15 +263,14 @@ Torrent::ChangeFlags Torrent::Impl::update_cache() 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_.percent_done, stats->percentDone, 0.01F, 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_.metadata_percent_complete, - stats->metadataPercentComplete, - 0.01F, + Percents(stats->metadataPercentComplete), result, ChangeFlag::LONG_STATUS); update_cache_value(cache_.peers_connected, stats->peersConnected, result, ChangeFlag::LONG_STATUS); @@ -334,7 +336,7 @@ Glib::ustring Torrent::Impl::get_short_status_text() const return fmt::format( // xgettext:no-c-format _("Verifying local data ({percent_done}% tested)"), - fmt::arg("percent_done", tr_truncd(cache_.recheck_progress * 100.0, 1))); + fmt::arg("percent_done", cache_.recheck_progress.to_string())); case TR_STATUS_DOWNLOAD: case TR_STATUS_SEED: @@ -363,7 +365,7 @@ Glib::ustring Torrent::Impl::get_long_progress_text() const _("{current_size} of {complete_size} ({percent_done}%)"), fmt::arg("current_size", tr_strlsize(haveTotal)), fmt::arg("complete_size", tr_strlsize(cache_.size_when_done)), - fmt::arg("percent_done", tr_strpercent(cache_.percent_done * 100.0))); + fmt::arg("percent_done", cache_.percent_done.to_string())); } else if (!isSeed && cache_.has_seed_ratio) // partial seed, seed ratio { @@ -373,7 +375,7 @@ Glib::ustring Torrent::Impl::get_long_progress_text() const _("{current_size} of {complete_size} ({percent_complete}%), uploaded {uploaded_size} (Ratio: {ratio}, Goal: {seed_ratio})"), fmt::arg("current_size", tr_strlsize(haveTotal)), fmt::arg("complete_size", tr_strlsize(cache_.total_size)), - fmt::arg("percent_complete", tr_strpercent(cache_.percent_complete * 100.0)), + fmt::arg("percent_complete", cache_.percent_complete.to_string()), fmt::arg("uploaded_size", tr_strlsize(cache_.uploaded_ever)), fmt::arg("ratio", tr_strlratio(cache_.ratio)), fmt::arg("seed_ratio", tr_strlratio(cache_.seed_ratio))); @@ -385,7 +387,7 @@ Glib::ustring Torrent::Impl::get_long_progress_text() const _("{current_size} of {complete_size} ({percent_complete}%), uploaded {uploaded_size} (Ratio: {ratio})"), fmt::arg("current_size", tr_strlsize(haveTotal)), fmt::arg("complete_size", tr_strlsize(cache_.total_size)), - fmt::arg("percent_complete", tr_strpercent(cache_.percent_complete * 100.0)), + fmt::arg("percent_complete", cache_.percent_complete.to_string()), fmt::arg("uploaded_size", tr_strlsize(cache_.uploaded_ever)), fmt::arg("ratio", tr_strlratio(cache_.ratio))); } @@ -514,7 +516,7 @@ Glib::ustring Torrent::Impl::get_activity_text() const "Downloading metadata from {active_count} connected peers ({percent_done}% done)", cache_.peers_connected), fmt::arg("active_count", cache_.peers_connected), - fmt::arg("percent_done", tr_strpercent(cache_.metadata_percent_complete * 100.0))); + fmt::arg("percent_done", cache_.metadata_percent_complete.to_string())); } if (cache_.peers_sending_to_us != 0 && cache_.webseeds_sending_to_us != 0) @@ -608,7 +610,7 @@ int Torrent::get_active_peers_down() const return impl_->get_cache().active_peers_down; } -float Torrent::get_recheck_progress() const +Percents Torrent::get_recheck_progress() const { return impl_->get_cache().recheck_progress; } @@ -678,12 +680,12 @@ time_t Torrent::get_added_date() const return impl_->get_cache().added_date; } -float Torrent::get_percent_complete() const +Percents Torrent::get_percent_complete() const { return impl_->get_cache().percent_complete; } -float Torrent::get_seed_ratio_percent_done() const +Percents Torrent::get_seed_ratio_percent_done() const { return impl_->get_cache().seed_ratio_percent_done; } @@ -698,7 +700,7 @@ Glib::ustring Torrent::get_name() const return impl_->get_cache().name; } -float Torrent::get_percent_done() const +Percents Torrent::get_percent_done() const { return impl_->get_cache().activity_percent_done; } diff --git a/gtk/Torrent.h b/gtk/Torrent.h index 18ddcf568..8ad015939 100644 --- a/gtk/Torrent.h +++ b/gtk/Torrent.h @@ -21,6 +21,8 @@ #include #include +class Percents; + class Torrent : public Glib::Object { public: @@ -80,13 +82,13 @@ public: tr_torrent_id_t get_id() const; Glib::ustring const& get_name_collated() const; Glib::ustring get_name() const; - float get_percent_complete() const; - float get_percent_done() const; + Percents get_percent_complete() const; + Percents get_percent_done() const; tr_priority_t get_priority() const; size_t get_queue_position() const; float get_ratio() const; - float get_recheck_progress() const; - float get_seed_ratio_percent_done() const; + Percents get_recheck_progress() const; + Percents get_seed_ratio_percent_done() const; float get_speed_down() const; float get_speed_up() const; tr_torrent& get_underlying() const; diff --git a/gtk/TorrentCellRenderer.cc b/gtk/TorrentCellRenderer.cc index ad9ef3ae2..d91b64979 100644 --- a/gtk/TorrentCellRenderer.cc +++ b/gtk/TorrentCellRenderer.cc @@ -6,6 +6,7 @@ #include "TorrentCellRenderer.h" #include "HigWorkarea.h" // GUI_PAD, GUI_PAD_SMALL +#include "Percents.h" #include "Torrent.h" #include @@ -370,7 +371,7 @@ void TorrentCellRenderer::Impl::render_compact( int width = 0; auto const& torrent = *property_torrent_.get_value(); - auto const percent_done = static_cast(torrent.get_percent_done() * 100); + auto const percent_done = torrent.get_percent_done().to_int(); bool const sensitive = torrent.get_sensitive(); if (torrent.get_error_code() != 0 && (flags & TR_GTK_CELL_RENDERER_STATE(SELECTED)) == Gtk::CellRendererState{}) @@ -464,7 +465,7 @@ void TorrentCellRenderer::Impl::render_full( Gtk::Requisition size; auto const& torrent = *property_torrent_.get_value(); - auto const percent_done = static_cast(torrent.get_percent_done() * 100); + auto const percent_done = torrent.get_percent_done().to_int(); bool const sensitive = torrent.get_sensitive(); if (torrent.get_error_code() != 0 && (flags & TR_GTK_CELL_RENDERER_STATE(SELECTED)) == Gtk::CellRendererState{}) diff --git a/gtk/TorrentSorter.cc b/gtk/TorrentSorter.cc index ca8b9b040..72fbecc0e 100644 --- a/gtk/TorrentSorter.cc +++ b/gtk/TorrentSorter.cc @@ -5,6 +5,7 @@ #include "TorrentSorter.h" +#include "Percents.h" #include "SorterBase.hh" #include "Utils.h" diff --git a/gtk/Utils.h b/gtk/Utils.h index 91b11d72a..4f340739a 100644 --- a/gtk/Utils.h +++ b/gtk/Utils.h @@ -177,6 +177,8 @@ template // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) constexpr int gtr_compare_generic(T const& lhs, T const& rhs) { + using std::rel_ops::operator>; + if (lhs < rhs) { return -1;