refactor: use fmt to build the GTK client's user-visible strings (#2788)

Co-authored-by: Mike Gelfand <mikedld@mikedld.com>
This commit is contained in:
Charles Kerr 2022-03-21 09:15:48 -05:00 committed by GitHub
parent 44e30bf092
commit fcc1510ecb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 512 additions and 437 deletions

View File

@ -107,7 +107,7 @@ static auto constexpr Options = std::array<tr_option, 45>{
{ { 'a', "allowed", "Allowed IP addresses. (Default: " TR_DEFAULT_RPC_WHITELIST ")", "a", true, "<list>" },
{ 'b', "blocklist", "Enable peer blocklists", "b", false, nullptr },
{ 'B', "no-blocklist", "Disable peer blocklists", "B", false, nullptr },
{ 'c', "watch-dir", "Where to watch for new .torrent files", "c", true, "<directory>" },
{ 'c', "watch-dir", "Where to watch for new torrent files", "c", true, "<directory>" },
{ 'C', "no-watch-dir", "Disable the watch-dir", "C", false, nullptr },
{ 941, "incomplete-dir", "Where to store new torrents until they're complete", nullptr, true, "<directory>" },
{ 942, "no-incomplete-dir", "Don't store incomplete torrents in a different location", nullptr, false, nullptr },
@ -243,7 +243,7 @@ static auto onFileAdded(tr_watchdir_t dir, char const* name, void* vsession)
if (tr_torrentNew(ctor, nullptr) == nullptr)
{
tr_logAddError(fmt::format(_("Couldn't add .torrent file '{path}'"), fmt::arg("path", name)));
tr_logAddError(fmt::format(_("Couldn't add torrent file '{path}'"), fmt::arg("path", name)));
}
else
{
@ -254,7 +254,7 @@ static auto onFileAdded(tr_watchdir_t dir, char const* name, void* vsession)
{
tr_error* error = nullptr;
tr_logAddInfo(fmt::format(_("Removing .torrent file '{path}'"), fmt::arg("path", name)));
tr_logAddInfo(fmt::format(_("Removing torrent file '{path}'"), fmt::arg("path", name)));
if (!tr_sys_path_remove(filename.c_str(), &error))
{
@ -761,7 +761,7 @@ static int daemon_start(void* varg, [[maybe_unused]] bool foreground)
(void)tr_variantDictFindStrView(settings, TR_KEY_watch_dir, &dir);
if (!std::empty(dir))
{
tr_logAddInfo(fmt::format(_("Watching '{path}' for new .torrent files"), fmt::arg("path", dir)));
tr_logAddInfo(fmt::format(_("Watching '{path}' for new torrent files"), fmt::arg("path", dir)));
watchdir = tr_watchdir_new(dir, &onFileAdded, mySession, ev_base, force_generic);
if (watchdir == nullptr)

View File

@ -351,7 +351,7 @@ void register_magnet_link_handler()
auto const msg = fmt::format(
_("Couldn't register Transmission as a {content_type} handler: {error} ({error_code})"),
fmt::arg("content_type", content_type),
fmt::arg("error", e.what().raw()),
fmt::arg("error", e.what()),
fmt::arg("error_code", e.code()));
g_warning("%s", msg.c_str());
}

View File

@ -17,6 +17,10 @@
#include <glibmm/i18n.h>
#include <fmt/core.h>
#include <fmt/chrono.h>
#include <fmt/format.h>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> /* tr_free */
#include <libtransmission/web-utils.h>
@ -464,7 +468,7 @@ Gtk::Widget* DetailsDialog::Impl::options_page_new()
[this]() { torrent_set_bool(TR_KEY_honorsSessionLimits, honor_limits_check_->get_active()); });
down_limited_check_ = Gtk::make_managed<Gtk::CheckButton>(
gtr_sprintf(_("Limit _download speed (%s):"), _(speed_K_str)),
fmt::format(_("Limit _download speed ({speed_units}):"), fmt::arg("speed_units", speed_K_str)),
true);
down_limited_check_->set_active(false);
down_limited_check_tag_ = down_limited_check_->signal_toggled().connect(
@ -475,7 +479,9 @@ Gtk::Widget* DetailsDialog::Impl::options_page_new()
[this]() { torrent_set_int(TR_KEY_downloadLimit, down_limit_spin_->get_value_as_int()); });
t->add_row_w(row, *down_limited_check_, *down_limit_spin_);
up_limited_check_ = Gtk::make_managed<Gtk::CheckButton>(gtr_sprintf(_("Limit _upload speed (%s):"), _(speed_K_str)), true);
up_limited_check_ = Gtk::make_managed<Gtk::CheckButton>(
fmt::format(_("Limit _upload speed ({speed_units}):"), fmt::arg("speed_units", speed_K_str)),
true);
up_limited_check_tag_ = up_limited_check_->signal_toggled().connect(
[this]() { torrent_set_bool(TR_KEY_uploadLimited, up_limited_check_->get_active()); });
@ -593,19 +599,16 @@ void gtr_text_buffer_set_text(Glib::RefPtr<Gtk::TextBuffer> const& b, Glib::ustr
}
}
Glib::ustring get_short_date_string(time_t t)
std::string get_date_string(time_t t)
{
char buf[64];
struct tm tm;
if (t == 0)
{
return _("N/A");
}
struct tm tm;
tr_localtime_r(&t, &tm);
strftime(buf, sizeof(buf), "%d %b %Y", &tm);
return Glib::locale_to_utf8(buf);
return fmt::format("{:%x}", tm);
}
} // namespace
@ -660,9 +663,9 @@ void DetailsDialog::Impl::refreshInfo(std::vector<tr_torrent*> const& torrents)
}
else
{
auto const creator = Glib::ustring(infos.front().creator != nullptr ? infos.front().creator : "");
auto const creator = tr_strvStrip(infos.front().creator != nullptr ? infos.front().creator : "");
auto const date = infos.front().date_created;
auto const datestr = get_short_date_string(date);
auto const datestr = get_date_string(date);
bool const mixed_creator = std::any_of(
infos.begin(),
infos.end(),
@ -672,31 +675,28 @@ void DetailsDialog::Impl::refreshInfo(std::vector<tr_torrent*> const& torrents)
infos.end(),
[date](auto const& info) { return date != info.date_created; });
bool const empty_creator = creator.empty();
bool const empty_creator = std::empty(creator);
bool const empty_date = date == 0;
if (mixed_date || mixed_creator)
if (mixed_creator || mixed_date)
{
str = mixed;
}
else if (empty_date && empty_creator)
else if (!empty_creator && !empty_date)
{
str = _("N/A");
str = fmt::format(_("Created by {creator} on {date}"), fmt::arg("creator", creator), fmt::arg("date", datestr));
}
else if (!empty_creator)
{
str = fmt::format(_("Created by {creator}"), fmt::arg("creator", creator));
}
else if (!empty_date)
{
str = fmt::format(_("Created on {date}"), fmt::arg("date", datestr));
}
else
{
if (empty_date && !empty_creator)
{
str = gtr_sprintf(_("Created by %1$s"), creator);
}
else if (empty_creator && !empty_date)
{
str = gtr_sprintf(_("Created on %1$s"), datestr);
}
else
{
str = gtr_sprintf(_("Created by %1$s on %2$s"), creator, datestr);
}
str = _("N/A");
}
}
@ -845,15 +845,21 @@ void DetailsDialog::Impl::refreshInfo(std::vector<tr_torrent*> const& torrents)
}
else if (pieceSize >= 0)
{
str = gtr_sprintf(
ngettext("%1$s (%2$'d piece @ %3$s)", "%1$s (%2$'d pieces @ %3$s)", pieces),
sizebuf,
pieces,
tr_formatter_mem_B(pieceSize));
str = fmt::format(
ngettext(
"{file_size} ({piece_count} piece @ {piece_size})",
"{file_size} ({piece_count} pieces @ {piece_size})",
pieces),
fmt::arg("file_size", sizebuf),
fmt::arg("piece_count", pieces),
fmt::arg("piece_size", tr_formatter_mem_B(pieceSize)));
}
else
{
str = gtr_sprintf(ngettext("%1$s (%2$'d piece)", "%1$s (%2$'d pieces)", pieces), sizebuf, pieces);
str = fmt::format(
ngettext("{file_size} ({piece_count} piece)", "{file_size} ({piece_count} pieces)", pieces),
fmt::arg("file_size", sizebuf),
fmt::arg("piece_count", pieces));
}
size_lb_->set_text(str);
@ -891,47 +897,62 @@ void DetailsDialog::Impl::refreshInfo(std::vector<tr_torrent*> const& torrents)
if (haveUnchecked == 0 && leftUntilDone == 0)
{
str = gtr_sprintf(_("%1$s (%2$s%%)"), total, buf2);
str = fmt::format(
_("{current_size} ({percent_done}%)"),
fmt::arg("current_size", total),
fmt::arg("percent_done", buf2));
}
else if (haveUnchecked == 0)
{
str = gtr_sprintf(_("%1$s (%2$s%% of %3$s%% Available)"), total, buf2, avail);
str = fmt::format(
_("{current_size} ({percent_done}% of {percent_available}% available"),
fmt::arg("current_size", total),
fmt::arg("percent_done", buf2),
fmt::arg("percent_available", avail));
}
else
{
str = gtr_sprintf(_("%1$s (%2$s%% of %3$s%% Available); %4$s Unverified"), total, buf2, avail, unver);
str = fmt::format(
_("{current_size} ({percent_done}% of {percent_available}% available; {unverified_size} unverified)"),
fmt::arg("current_size", total),
fmt::arg("percent_done", buf2),
fmt::arg("percent_available", avail),
fmt::arg("unverified_size", unver));
}
}
}
have_lb_->set_text(str);
/* dl_lb */
// dl_lb
if (stats.empty())
{
str = no_torrent;
}
else
{
uint64_t d = 0;
uint64_t f = 0;
auto const downloaded_str = tr_strlsize(std::accumulate(
std::begin(stats),
std::end(stats),
uint64_t{ 0 },
[](auto sum, auto const* st) { return sum + st->downloadedEver; }));
for (auto const* const st : stats)
auto const failed = std::accumulate(
std::begin(stats),
std::end(stats),
uint64_t{ 0 },
[](auto sum, auto const* st) { return sum + st->corruptEver; });
if (failed != 0)
{
d += st->downloadedEver;
f += st->corruptEver;
}
auto const dbuf = tr_strlsize(d);
auto const fbuf = tr_strlsize(f);
if (f != 0)
{
str = gtr_sprintf(_("%1$s (+%2$s discarded after failed checksum)"), dbuf, fbuf);
str = fmt::format(
_("{downloaded_size} (+{discarded_size} discarded after failed checksum)"),
fmt::arg("downloaded_size", downloaded_str),
fmt::arg("discarded_size", tr_strlsize(failed)));
}
else
{
str = dbuf;
str = downloaded_str;
}
}
@ -954,7 +975,10 @@ void DetailsDialog::Impl::refreshInfo(std::vector<tr_torrent*> const& torrents)
std::end(stats),
uint64_t{},
[](auto sum, auto const* st) { return sum + st->sizeWhenDone; });
str = gtr_sprintf(_("%s (Ratio: %s)"), tr_strlsize(uploaded), tr_strlratio(tr_getRatio(uploaded, denominator)));
str = fmt::format(
_("{uploaded_size} (Ratio: {ratio})"),
fmt::arg("uploaded_size", tr_strlsize(uploaded)),
fmt::arg("ratio", tr_strlratio(tr_getRatio(uploaded, denominator))));
}
ul_lb_->set_text(str);
@ -1025,7 +1049,8 @@ void DetailsDialog::Impl::refreshInfo(std::vector<tr_torrent*> const& torrents)
}
else
{
str = gtr_sprintf(_("%1$s ago"), tr_strltime(period));
// e.g. 5 minutes ago
str = fmt::format(_("{time_span} ago"), fmt::arg("time_span", tr_strltime(period)));
}
}
}
@ -1355,6 +1380,11 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
row[peer_cols.was_updated] = false;
}
auto make_key = [](tr_torrent const* tor, tr_peer_stat const* ps)
{
return fmt::format("{}.{}", tr_torrentId(tor), ps->addr);
};
/* step 3: add any new peers */
for (size_t i = 0; i < torrents.size(); ++i)
{
@ -1363,7 +1393,7 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
for (int j = 0; j < peerCount[i]; ++j)
{
auto const* s = &peers.at(i)[j];
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), s->addr);
auto const key = make_key(tor, s);
if (hash.find(key) == hash.end())
{
@ -1382,7 +1412,7 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
for (int j = 0; j < peerCount[i]; ++j)
{
auto const* s = &peers.at(i)[j];
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), s->addr);
auto const key = make_key(tor, s);
refreshPeerRow(store->get_iter(hash.at(key).get_path()), s);
}
}
@ -1418,6 +1448,11 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
auto& hash = webseed_hash_;
auto& store = webseed_store_;
auto make_key = [](tr_torrent const* tor, char const* url)
{
return fmt::format("{}.{}", tr_torrentId(tor), url);
};
/* step 1: mark all webseeds as not-updated */
for (auto const& row : store->children())
{
@ -1432,7 +1467,7 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
has_any_webseeds = true;
auto const* const url = tr_torrentWebseed(tor, j).url;
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), url);
auto const key = make_key(tor, url);
if (hash.find(key) == hash.end())
{
@ -1450,7 +1485,7 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
for (size_t j = 0, n = tr_torrentWebseedCount(tor); j < n; ++j)
{
auto const webseed = tr_torrentWebseed(tor, j);
auto const key = gtr_sprintf("%d.%s", tr_torrentId(tor), webseed.url);
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;
@ -1649,6 +1684,7 @@ void setPeerViewColumns(Gtk::TreeView* peer_view)
else if (*col == peer_cols.progress)
{
auto* r = Gtk::make_managed<Gtk::CellRendererProgress>();
// % is percent done
c = Gtk::make_managed<Gtk::TreeViewColumn>(_("%"), *r);
c->add_attribute(r->property_text(), *col);
}
@ -1837,12 +1873,12 @@ Gtk::Widget* DetailsDialog::Impl::peer_page_new()
namespace
{
char const err_markup_begin[] = "<span color=\"red\">";
char const err_markup_end[] = "</span>";
char const timeout_markup_begin[] = "<span color=\"#246\">";
char const timeout_markup_end[] = "</span>";
char const success_markup_begin[] = "<span color=\"#080\">";
char const success_markup_end[] = "</span>";
auto constexpr ErrMarkupBegin = "<span color=\"red\">"sv;
auto constexpr ErrMarkupEnd = "</span>"sv;
auto constexpr TimeoutMarkupBegin = "<span color=\"#246\">"sv;
auto constexpr TimeoutMarkupEnd = "</span>"sv;
auto constexpr SuccessMarkupBegin = "<span color=\"#080\">"sv;
auto constexpr SuccessMarkupEnd = "</span>"sv;
std::array<std::string_view, 3> const text_dir_mark = { ""sv, "\u200E"sv, "\u200F"sv };
@ -1867,29 +1903,35 @@ void appendAnnounceInfo(tr_tracker_view const& tracker, time_t const now, Gtk::T
if (tracker.lastAnnounceSucceeded)
{
gstr << gtr_sprintf(
_("Got a list of %1$s%2$'d peers%3$s %4$s ago"),
success_markup_begin,
tracker.lastAnnouncePeerCount,
success_markup_end,
timebuf);
gstr << fmt::format(
// {markup_begin} and {markup_end} should surround the peer text
ngettext(
"Got a list of {markup_begin}{peer_count} peer{markup_end} {time_span} ago",
"Got a list of {markup_begin}{peer_count} peers{markup_end} {time_span} ago",
tracker.lastAnnouncePeerCount),
fmt::arg("markup_begin", SuccessMarkupBegin),
fmt::arg("peer_count", tracker.lastAnnouncePeerCount),
fmt::arg("markup_end", SuccessMarkupEnd),
fmt::arg("time_span", timebuf));
}
else if (tracker.lastAnnounceTimedOut)
{
gstr << gtr_sprintf(
_("Peer list request %1$stimed out%2$s %3$s ago; will retry"),
timeout_markup_begin,
timeout_markup_end,
timebuf);
gstr << fmt::format(
// {markup_begin} and {markup_end} should surround the time_span
_("Peer list request {markup_begin}timed out {time_span} ago{markup_end}; will retry"),
fmt::arg("markup_begin", TimeoutMarkupBegin),
fmt::arg("time_span", timebuf),
fmt::arg("markup_end", TimeoutMarkupEnd));
}
else
{
gstr << gtr_sprintf(
_("Got an error %1$s\"%2$s\"%3$s %4$s ago"),
err_markup_begin,
tracker.lastAnnounceResult,
err_markup_end,
timebuf);
gstr << fmt::format(
// {markup_begin} and {markup_end} should surround the error
_("Got an error '{markup_begin}{error}{markup_end}' {time_span} ago"),
fmt::arg("markup_begin", ErrMarkupBegin),
fmt::arg("error", Glib::Markup::escape_text(tracker.lastAnnounceResult)),
fmt::arg("markup_end", ErrMarkupEnd),
fmt::arg("time_span", timebuf));
}
}
@ -1904,7 +1946,9 @@ void appendAnnounceInfo(tr_tracker_view const& tracker, time_t const now, Gtk::T
case TR_TRACKER_WAITING:
gstr << '\n';
gstr << text_dir_mark[direction];
gstr << gtr_sprintf(_("Asking for more peers in %s"), tr_strltime_rounded(tracker.nextAnnounceTime - now));
gstr << fmt::format(
_("Asking for more peers in {time_span}"),
fmt::arg("time_span", tr_strltime_rounded(tracker.nextAnnounceTime - now)));
break;
case TR_TRACKER_QUEUED:
@ -1916,9 +1960,12 @@ void appendAnnounceInfo(tr_tracker_view const& tracker, time_t const now, Gtk::T
case TR_TRACKER_ACTIVE:
gstr << '\n';
gstr << text_dir_mark[direction];
gstr << gtr_sprintf(
_("Asking for more peers now… <small>%s</small>"),
tr_strltime_rounded(now - tracker.lastAnnounceStartTime));
gstr << fmt::format(
// {markup_begin} and {markup_end} should surround the time_span
_("Asking for more peers now… {markup_begin}{time_span}{markup_end}"),
fmt::arg("markup_begin", "<small>"),
fmt::arg("time_span", tr_strltime_rounded(now - tracker.lastAnnounceStartTime)),
fmt::arg("markup_end", "</small>"));
break;
default:
@ -1936,22 +1983,26 @@ void appendScrapeInfo(tr_tracker_view const& tracker, time_t const now, Gtk::Tex
if (tracker.lastScrapeSucceeded)
{
gstr << gtr_sprintf(
_("Tracker had %s%'d seeders and %'d leechers%s %s ago"),
success_markup_begin,
tracker.seederCount,
tracker.leecherCount,
success_markup_end,
timebuf);
gstr << fmt::format(
// {markup_begin} and {markup_end} should surround the seeder/leecher text
_("Tracker had {markup_begin}{seeder_count} {seeder_or_seeders} and {leecher_count} {leecher_or_leechers}{markup_end} {time_span} ago"),
fmt::arg("seeder_count", tracker.seederCount),
fmt::arg("seeder_or_seeders", ngettext("seeder", "seeders", tracker.seederCount)),
fmt::arg("leecher_count", tracker.leecherCount),
fmt::arg("leecher_or_leechers", ngettext("leecher", "leechers", tracker.leecherCount)),
fmt::arg("time_span", timebuf),
fmt::arg("markup_begin", SuccessMarkupBegin),
fmt::arg("markup_end", SuccessMarkupEnd));
}
else
{
gstr << gtr_sprintf(
_("Got a scrape error \"%s%s%s\" %s ago"),
err_markup_begin,
tracker.lastScrapeResult,
err_markup_end,
timebuf);
gstr << fmt::format(
// {markup_begin} and {markup_end} should surround the error text
_("Got a scrape error '{markup_begin}{error}{markup_end}' {time_span} ago"),
fmt::arg("error", Glib::Markup::escape_text(tracker.lastScrapeResult)),
fmt::arg("time_span", timebuf),
fmt::arg("markup_begin", ErrMarkupBegin),
fmt::arg("markup_end", ErrMarkupEnd));
}
}
@ -1963,7 +2014,9 @@ void appendScrapeInfo(tr_tracker_view const& tracker, time_t const now, Gtk::Tex
case TR_TRACKER_WAITING:
gstr << '\n';
gstr << text_dir_mark[direction];
gstr << gtr_sprintf(_("Asking for peer counts in %s"), tr_strltime_rounded(tracker.nextScrapeTime - now));
gstr << fmt::format(
_("Asking for peer counts in {time_span}"),
fmt::arg("time_span", tr_strltime_rounded(tracker.nextScrapeTime - now)));
break;
case TR_TRACKER_QUEUED:
@ -1975,9 +2028,11 @@ void appendScrapeInfo(tr_tracker_view const& tracker, time_t const now, Gtk::Tex
case TR_TRACKER_ACTIVE:
gstr << '\n';
gstr << text_dir_mark[direction];
gstr << gtr_sprintf(
_("Asking for peer counts now… <small>%s</small>"),
tr_strltime_rounded(now - tracker.lastScrapeStartTime));
gstr << fmt::format(
_("Asking for peer counts now… {markup_begin}{time_span}{markup_end}"),
fmt::arg("markup_begin", "<small>"),
fmt::arg("time_span", tr_strltime_rounded(now - tracker.lastScrapeStartTime)),
fmt::arg("markup_end", "</small>"));
break;
default:
@ -1995,7 +2050,7 @@ void buildTrackerSummary(
// hostname
gstr << text_dir_mark[direction];
gstr << (tracker.isBackup ? "<i>" : "<b>");
gstr << Glib::Markup::escape_text(!key.empty() ? gtr_sprintf("%s - %s", tracker.host, key) : tracker.host);
gstr << Glib::Markup::escape_text(!key.empty() ? fmt::format("{} - {}", tracker.host, key) : tracker.host);
gstr << (tracker.isBackup ? "</i>" : "</b>");
if (!tracker.isBackup)
@ -2261,7 +2316,7 @@ void DetailsDialog::Impl::on_edit_trackers()
int const torrent_id = tr_torrentId(tor);
auto d = std::make_shared<Gtk::Dialog>(
gtr_sprintf(_("%s - Edit Trackers"), tr_torrentName(tor)),
fmt::format(_("{torrent_name} - Edit Trackers"), fmt::arg("torrent_name", tr_torrentName(tor))),
dialog_,
Gtk::DIALOG_MODAL | Gtk::DIALOG_DESTROY_WITH_PARENT);
d->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
@ -2371,7 +2426,7 @@ void DetailsDialog::Impl::on_tracker_list_add_button_clicked()
guint row;
auto w = std::make_shared<Gtk::Dialog>(
gtr_sprintf(_("%s - Add Tracker"), tr_torrentName(tor)),
fmt::format(_("{torrent_name} - Add Tracker"), fmt::arg("torrent_name", tr_torrentName(tor))),
dialog_,
Gtk::DIALOG_DESTROY_WITH_PARENT);
w->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
@ -2611,7 +2666,7 @@ void DetailsDialog::Impl::set_torrents(std::vector<int> const& ids)
{
int const id = ids.front();
auto const* tor = core_->find_torrent(id);
title = gtr_sprintf(_("%s Properties"), tr_torrentName(tor));
title = fmt::format(_("{torrent_name} Properties"), fmt::arg("torrent_name", tr_torrentName(tor)));
file_list_->set_torrent(id);
file_list_->show();
@ -2619,10 +2674,13 @@ void DetailsDialog::Impl::set_torrents(std::vector<int> const& ids)
}
else
{
title = fmt::format(
ngettext("Properties - {count} Torrent", "Properties - {count} Torrents", len),
fmt::arg("count", len));
file_list_->clear();
file_list_->hide();
file_label_->show();
title = gtr_sprintf(_("%'d Torrent Properties"), len);
}
dialog_.set_title(title);

View File

@ -745,8 +745,8 @@ bool FileList::Impl::on_rename_done_idle(Glib::ustring const& path_string, Glib:
*static_cast<Gtk::Window*>(widget_.get_toplevel()),
fmt::format(
_("Couldn't rename '{old_path}' as '{path}': {error} ({error_code})"),
fmt::arg("old_path", path_string.raw()),
fmt::arg("path", newname.raw()),
fmt::arg("old_path", path_string),
fmt::arg("path", newname),
fmt::arg("error", tr_strerror(error)),
fmt::arg("error_code", error)),
false,

View File

@ -711,7 +711,9 @@ bool FilterBar::Impl::update_count_label()
/* set the text */
show_lb_->set_markup_with_mnemonic(
visibleCount == std::min(activityCount, trackerCount) ? _("_Show:") : gtr_sprintf(_("_Show %'d of:"), visibleCount));
visibleCount == std::min(activityCount, trackerCount) ?
_("_Show:") :
fmt::format(_("_Show {count:L} of:"), fmt::arg("count", visibleCount)));
show_lb_->steal_data(DIRTY_KEY);
return false;

View File

@ -8,6 +8,8 @@
#include <glibmm/i18n.h>
#include <fmt/core.h>
#include <libtransmission/utils.h>
#include "FreeSpaceLabel.h"
@ -47,9 +49,8 @@ bool FreeSpaceLabel::Impl::on_freespace_timer()
}
auto const bytes = tr_dirSpace(dir_).free;
auto const text = bytes < 0 ? _("Error") : gtr_sprintf(_("%s free"), tr_strlsize(bytes));
auto const markup = gtr_sprintf("<i>%s</i>", text);
label_.set_markup(markup);
auto const text = bytes < 0 ? _("Error") : fmt::format(_("{disk_space} free"), fmt::arg("disk_space", tr_strlsize(bytes)));
label_.set_markup(fmt::format("<i>{}</i>", text));
return true;
}

View File

@ -220,17 +220,15 @@ void MainWindow::Impl::syncAltSpeedButton()
bool const b = gtr_pref_flag_get(TR_KEY_alt_speed_enabled);
char const* const stock = b ? "alt-speed-on" : "alt-speed-off";
auto const u = tr_formatter_speed_KBps(gtr_pref_int_get(TR_KEY_alt_speed_up));
auto const d = tr_formatter_speed_KBps(gtr_pref_int_get(TR_KEY_alt_speed_down));
auto const str = b ? gtr_sprintf(_("Click to disable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u) :
gtr_sprintf(_("Click to enable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u);
alt_speed_button_->set_active(b);
alt_speed_image_->set_from_icon_name(stock, Gtk::BuiltinIconSize::ICON_SIZE_MENU);
alt_speed_button_->set_halign(Gtk::ALIGN_CENTER);
alt_speed_button_->set_valign(Gtk::ALIGN_CENTER);
alt_speed_button_->set_tooltip_text(str);
alt_speed_button_->set_tooltip_text(fmt::format(
b ? _("Click to disable Alternative Speed Limits\n ({download_speed} down, {upload_speed} up)") :
_("Click to enable Alternative Speed Limits\n ({download_speed} down, {upload_speed} up)"),
fmt::arg("download_speed", tr_formatter_speed_KBps(gtr_pref_int_get(TR_KEY_alt_speed_down))),
fmt::arg("upload_speed", tr_formatter_speed_KBps(gtr_pref_int_get(TR_KEY_alt_speed_up)))));
}
void MainWindow::Impl::alt_speed_toggled_cb()
@ -381,7 +379,7 @@ void MainWindow::Impl::onOptionsClicked(Gtk::Button* button)
gtr_label_set_text(
*static_cast<Gtk::Label*>(ratio_on_item_->get_child()),
gtr_sprintf(_("Stop at Ratio (%s)"), tr_strlratio(gtr_pref_double_get(TR_KEY_ratio_limit))));
fmt::format(_("Stop at Ratio ({ratio})"), fmt::arg("ratio", tr_strlratio(gtr_pref_double_get(TR_KEY_ratio_limit)))));
(gtr_pref_flag_get(TR_KEY_ratio_limit_enabled) ? ratio_on_item_ : ratio_off_item_)->set_active(true);
@ -589,31 +587,28 @@ void MainWindow::Impl::updateStats()
if (auto const pch = gtr_pref_string_get(TR_KEY_statusbar_stats); pch == "session-ratio")
{
tr_sessionGetStats(session, &stats);
buf = gtr_sprintf(_("Ratio: %s"), tr_strlratio(stats.ratio));
buf = fmt::format(_("Ratio: {ratio}"), tr_strlratio(stats.ratio));
}
else if (pch == "session-transfer")
{
tr_sessionGetStats(session, &stats);
/* Translators: "size|" is here for disambiguation. Please remove it from your translation.
%1$s is the size of the data we've downloaded
%2$s is the size of the data we've uploaded */
buf = gtr_sprintf(Q_("Down: %1$s, Up: %2$s"), tr_strlsize(stats.downloadedBytes), tr_strlsize(stats.uploadedBytes));
buf = fmt::format(
C_("current session totals", "Down: {downloaded_size}, Up: {uploaded_size}"),
fmt::arg("downloaded_size", tr_strlsize(stats.downloadedBytes)),
fmt::arg("uploaded_size", tr_strlsize(stats.uploadedBytes)));
}
else if (pch == "total-transfer")
{
tr_sessionGetCumulativeStats(session, &stats);
/* Translators: "size|" is here for disambiguation. Please remove it from your translation.
%1$s is the size of the data we've downloaded
%2$s is the size of the data we've uploaded */
buf = gtr_sprintf(
Q_("size|Down: %1$s, Up: %2$s"),
tr_strlsize(stats.downloadedBytes),
tr_strlsize(stats.uploadedBytes));
buf = fmt::format(
C_("all-time totals", "Down: {downloaded_size}, Up: {uploaded_size}"),
fmt::arg("downloaded_size", tr_strlsize(stats.downloadedBytes)),
fmt::arg("uploaded_size", tr_strlsize(stats.uploadedBytes)));
}
else /* default is total-ratio */
{
tr_sessionGetCumulativeStats(session, &stats);
buf = gtr_sprintf(_("Ratio: %s"), tr_strlratio(stats.ratio));
buf = fmt::format(_("Ratio: {ratio}"), fmt::arg("ratio", tr_strlratio(stats.ratio)));
}
stats_lb_->set_text(buf);
@ -625,25 +620,25 @@ void MainWindow::Impl::updateSpeeds()
if (session != nullptr)
{
double upSpeed = 0;
double downSpeed = 0;
int upCount = 0;
int downCount = 0;
auto const model = core_->get_model();
auto dn_count = int{};
auto dn_speed = double{};
auto up_count = int{};
auto up_speed = double{};
auto const model = core_->get_model();
for (auto const& row : model->children())
{
upSpeed += row.get_value(torrent_cols.speed_up);
upCount += row.get_value(torrent_cols.active_peers_up);
downSpeed += row.get_value(torrent_cols.speed_down);
downCount += row.get_value(torrent_cols.active_peers_down);
dn_count += row.get_value(torrent_cols.active_peers_down);
dn_speed += row.get_value(torrent_cols.speed_down);
up_count += row.get_value(torrent_cols.active_peers_up);
up_speed += row.get_value(torrent_cols.speed_up);
}
dl_lb_->set_text(gtr_sprintf("%s %s", tr_formatter_speed_KBps(downSpeed), gtr_get_unicode_string(GtrUnicode::Down)));
dl_lb_->set_visible(downCount > 0);
dl_lb_->set_text(fmt::format(_("{download_speed} ▼"), fmt::arg("download_speed", dn_speed)));
dl_lb_->set_visible(dn_count > 0);
ul_lb_->set_text(gtr_sprintf("%s %s", tr_formatter_speed_KBps(upSpeed), gtr_get_unicode_string(GtrUnicode::Up)));
ul_lb_->set_visible(downCount > 0 || upCount > 0);
ul_lb_->set_text(fmt::format(_("{upload_speed} ▲"), fmt::arg("upload_speed", up_speed)));
ul_lb_->set_visible(dn_count > 0 || up_count > 0);
}
}

View File

@ -111,11 +111,11 @@ bool MakeProgressDialog::onProgressDialogRefresh()
/* progress label */
if (!builder_.isDone)
{
str = gtr_sprintf(_("Creating \"%s\""), base);
str = fmt::format(_("Creating '{path}'"), fmt::arg("path", base));
}
else if (builder_.result == TrMakemetaResult::OK)
{
str = gtr_sprintf(_("Created \"%s\"!"), base);
str = fmt::format(_("Created '{path}'"), fmt::arg("path", base));
}
else if (builder_.result == TrMakemetaResult::CANCELLED)
{
@ -130,7 +130,7 @@ bool MakeProgressDialog::onProgressDialogRefresh()
str = fmt::format(
_("Couldn't read '{path}': {error} ({error_code})"),
fmt::arg("path", builder_.errfile),
fmt::arg("error", Glib::strerror(builder_.my_errno).raw()),
fmt::arg("error", Glib::strerror(builder_.my_errno)),
fmt::arg("error_code", builder_.my_errno));
}
else if (builder_.result == TrMakemetaResult::ERR_IO_WRITE)
@ -138,7 +138,7 @@ bool MakeProgressDialog::onProgressDialogRefresh()
str = fmt::format(
_("Couldn't save '{path}': {error} ({error_code})"),
fmt::arg("path", builder_.errfile),
fmt::arg("error", Glib::strerror(builder_.my_errno).raw()),
fmt::arg("error", Glib::strerror(builder_.my_errno)),
fmt::arg("error_code", builder_.my_errno));
}
else
@ -158,7 +158,7 @@ bool MakeProgressDialog::onProgressDialogRefresh()
/* how much data we've scanned through to generate checksums */
str = fmt::format(
_("Scanned {file_size}"),
fmt::arg("file_size", tr_strlsize((uint64_t)builder_.pieceIndex * (uint64_t)builder_.pieceSize).raw()));
fmt::arg("file_size", tr_strlsize((uint64_t)builder_.pieceIndex * (uint64_t)builder_.pieceSize)));
}
progress_bar_->set_fraction(fraction);
@ -276,7 +276,7 @@ void MakeDialog::Impl::onResponse(int response)
/* destination file */
auto const dir = destination_chooser_->get_filename();
auto const base = Glib::path_get_basename(builder_->top);
auto const target = gtr_sprintf("%s/%s.torrent", dir, base).raw();
auto const target = gtr_sprintf("%s/%s.torrent", dir, base);
/* build the array of trackers */
auto const tracker_text = announce_text_buffer_->get_text(false);
@ -498,9 +498,8 @@ MakeDialog::Impl::Impl(MakeDialog& dialog, Glib::RefPtr<Session> const& core)
fr->add(*sw);
v->pack_start(*fr, true, true, 0);
auto* l = Gtk::make_managed<Gtk::Label>();
l->set_markup(
_("To add a backup URL, add it on the line after the primary URL.\n"
"To add another primary URL, add it after a blank line."));
l->set_markup(_(
"To add a backup URL, add it on the next line after a primary URL.\nTo add a new primary URL, add it after a blank line."));
l->set_justify(Gtk::JUSTIFY_LEFT);
l->set_halign(Gtk::ALIGN_START);
l->set_valign(Gtk::ALIGN_CENTER);

View File

@ -188,7 +188,7 @@ void MessageLogWindow::Impl::doSave(Gtk::Window& parent, Glib::ustring const& fi
parent,
fmt::format(
_("Couldn't save '{path}': {error} ({error_code})"),
fmt::arg("path", filename.raw()),
fmt::arg("path", filename),
fmt::arg("error", g_strerror(errcode)),
fmt::arg("error_code", errcode)),
false,

View File

@ -171,7 +171,7 @@ void OptionsDialog::Impl::updateTorrent()
}
/**
* When the source .torrent file is deleted
* When the source torrent file is deleted
* (such as, if it was a temp file that a web browser passed to us),
* gtk invokes this callback and `filename' will be nullptr.
* The `filename' tests here are to prevent us from losing the current
@ -292,7 +292,7 @@ OptionsDialog::Impl::Impl(
filename_ = tr_ctorGetSourceFile(ctor_.get()) != nullptr ? tr_ctorGetSourceFile(ctor_.get()) : "";
downloadDir_ = str;
file_list_ = Gtk::make_managed<FileList>(core_, 0);
trash_check_ = Gtk::make_managed<Gtk::CheckButton>(_("Mo_ve .torrent file to the trash"), true);
trash_check_ = Gtk::make_managed<Gtk::CheckButton>(_("Mo_ve torrent file to the trash"), true);
run_check_ = Gtk::make_managed<Gtk::CheckButton>(_("_Start when added"), true);
priority_combo_ = gtr_priority_combo_new();
@ -376,7 +376,7 @@ OptionsDialog::Impl::Impl(
run_check_->set_active(!flag);
grid->attach(*run_check_, 0, row, 2, 1);
/* "trash .torrent file" row */
/* "trash torrent file" row */
row++;
if (!tr_ctorGetDeleteSource(ctor_.get(), &flag))

View File

@ -254,7 +254,7 @@ Gtk::Widget* PrefsDialog::Impl::downloadingPage()
t->add_section_title(row, C_("Gerund", "Adding"));
{
auto* l = new_check_button(_("Automatically add .torrent files _from:"), TR_KEY_watch_dir_enabled, core_);
auto* l = new_check_button(_("Automatically add torrent files _from:"), TR_KEY_watch_dir_enabled, core_);
auto* w = new_path_chooser_button(TR_KEY_watch_dir, core_);
w->set_sensitive(gtr_pref_flag_get(TR_KEY_watch_dir_enabled));
l->signal_toggled().connect([l, w]() { target_cb(l, w); });
@ -267,7 +267,7 @@ Gtk::Widget* PrefsDialog::Impl::downloadingPage()
t->add_wide_control(
row,
*new_check_button(_("Mo_ve .torrent file to the trash"), TR_KEY_trash_original_torrent_files, core_));
*new_check_button(_("Mo_ve torrent file to the trash"), TR_KEY_trash_original_torrent_files, core_));
t->add_row(row, _("Save to _Location:"), *new_path_chooser_button(TR_KEY_download_dir, core_));
@ -415,7 +415,7 @@ void updateBlocklistText(Gtk::Label* w, Glib::RefPtr<Session> const& core)
auto const msg = fmt::format(
ngettext("Blocklist has {count} entry", "Blocklist has {count} entries", n),
fmt::arg("count", n));
w->set_markup(gtr_sprintf("<i>%s</i>", msg.c_str()));
w->set_markup(fmt::format("<i>{}</i>", msg));
}
/* prefs dialog is being destroyed, so stop listening to blocklist updates */
@ -887,7 +887,11 @@ Gtk::Widget* PrefsDialog::Impl::speedPage()
t->add_section_title(row, _("Speed Limits"));
{
auto* w = new_check_button(gtr_sprintf(_("_Upload (%s):"), _(speed_K_str)), TR_KEY_speed_limit_up_enabled, core_);
auto* w = new_check_button(
// checkbox to limit upload speed
fmt::format(_("_Upload ({speed_units}):"), fmt::arg("speed_units", speed_K_str)),
TR_KEY_speed_limit_up_enabled,
core_);
auto* w2 = new_spin_button(TR_KEY_speed_limit_up, core_, 0, INT_MAX, 5);
w2->set_sensitive(gtr_pref_flag_get(TR_KEY_speed_limit_up_enabled));
w->signal_toggled().connect([w, w2]() { target_cb(w, w2); });
@ -895,7 +899,11 @@ Gtk::Widget* PrefsDialog::Impl::speedPage()
}
{
auto* w = new_check_button(gtr_sprintf(_("_Download (%s):"), _(speed_K_str)), TR_KEY_speed_limit_down_enabled, core_);
auto* w = new_check_button(
// checkbox to limit download speed
fmt::format(_("_Download ({speed_units}):"), fmt::arg("speed_units", speed_K_str)),
TR_KEY_speed_limit_down_enabled,
core_);
auto* w2 = new_spin_button(TR_KEY_speed_limit_down, core_, 0, INT_MAX, 5);
w2->set_sensitive(gtr_pref_flag_get(TR_KEY_speed_limit_down_enabled));
w->signal_toggled().connect([w, w2]() { target_cb(w, w2); });
@ -906,7 +914,7 @@ Gtk::Widget* PrefsDialog::Impl::speedPage()
{
auto* h = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL, GUI_PAD);
auto* w = Gtk::make_managed<Gtk::Label>(gtr_sprintf("<b>%s</b>", _("Alternative Speed Limits")));
auto* w = Gtk::make_managed<Gtk::Label>(fmt::format("<b>{}</b>", _("Alternative Speed Limits")));
w->set_halign(Gtk::ALIGN_START);
w->set_valign(Gtk::ALIGN_CENTER);
w->set_use_markup(true);
@ -917,7 +925,7 @@ Gtk::Widget* PrefsDialog::Impl::speedPage()
{
auto* w = Gtk::make_managed<Gtk::Label>(
gtr_sprintf("<small>%s</small>", _("Override normal speed limits manually or at scheduled times")));
fmt::format("<small>{}</small>", _("Override normal speed limits manually or at scheduled times")));
w->set_use_markup(true);
w->set_halign(Gtk::ALIGN_START);
w->set_valign(Gtk::ALIGN_CENTER);
@ -926,12 +934,14 @@ Gtk::Widget* PrefsDialog::Impl::speedPage()
t->add_row(
row,
gtr_sprintf(_("U_pload (%s):"), _(speed_K_str)),
// labels a spinbutton for alternate upload speed limits
fmt::format(_("U_pload ({speed_units}):"), fmt::arg("speed_units", speed_K_str)),
*new_spin_button(TR_KEY_alt_speed_up, core_, 0, INT_MAX, 5));
t->add_row(
row,
gtr_sprintf(_("Do_wnload (%s):"), _(speed_K_str)),
// labels a spinbutton for alternate download speed limits
fmt::format(_("Do_wnload ({speed_units}):"), fmt::arg("speed_units", speed_K_str)),
*new_spin_button(TR_KEY_alt_speed_down, core_, 0, INT_MAX, 5));
{
@ -939,6 +949,7 @@ Gtk::Widget* PrefsDialog::Impl::speedPage()
auto* start_combo = new_time_combo(core_, TR_KEY_alt_speed_time_begin);
page->sched_widgets.push_back(start_combo);
h->pack_start(*start_combo, true, true, 0);
// label goes between two time selectors, e.g. "limit speeds from [time] to [time]"
auto* to_label = Gtk::make_managed<Gtk::Label>(_(" _to "), true);
page->sched_widgets.push_back(to_label);
h->pack_start(*to_label, false, false, 0);
@ -1006,7 +1017,10 @@ network_page_data::~network_page_data()
void onPortTested(bool isOpen, network_page_data* data)
{
data->portLabel->set_markup(isOpen ? _("Port is <b>open</b>") : _("Port is <b>closed</b>"));
data->portLabel->set_markup(fmt::format(
isOpen ? _("Port is {markup_begin}open{markup_end}") : _("Port is {markup_begin}closed{markup_end}"),
fmt::arg("markup_begin", "<b>"),
fmt::arg("markup_end", "</b>")));
data->portButton->set_sensitive(true);
data->portSpin->set_sensitive(true);
}

View File

@ -10,6 +10,8 @@
#include <glibmm.h>
#include <glibmm/i18n.h>
#include <fmt/core.h>
#include <libtransmission/transmission.h>
#include "HigWorkarea.h"
@ -72,7 +74,9 @@ void RelocateDialog::Impl::startMovingNextTorrent()
torrent_ids_.pop_back();
message_dialog_->set_message(gtr_sprintf(_("Moving \"%s\""), tr_torrentName(tor)), true);
message_dialog_->set_message(
fmt::format(_("Moving '{torrent_name}'"), fmt::arg("torrent_name", tr_torrentName(tor))),
true);
}
/* every once in awhile, check to see if the move is done.

View File

@ -3,9 +3,10 @@
// A copy of this license can be found in licenses/ .
#include <algorithm>
#include <cmath> /* pow() */
#include <cmath> // pow()
#include <cstring> // strstr
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <string>
@ -617,9 +618,9 @@ void rename_torrent(Glib::RefPtr<Gio::File> const& file)
{
auto const errmsg = fmt::format(
_("Couldn't rename '{old_path}' as '{path}': {error} ({error_code})"),
fmt::arg("old_path", old_name.raw()),
fmt::arg("path", new_name.raw()),
fmt::arg("error", e.what().raw()),
fmt::arg("old_path", old_name),
fmt::arg("path", new_name),
fmt::arg("error", e.what()),
fmt::arg("error_code", e.code()));
g_message("%s", errmsg.c_str());
}
@ -1037,7 +1038,7 @@ int Session::Impl::add_ctor(tr_ctor* ctor, bool do_prompt, bool do_notify)
if (tr_torrentFindFromMetainfo(get_session(), metainfo) != nullptr)
{
/* don't complain about .torrent files in the watch directory
/* don't complain about torrent files in the watch directory
* that have already been added... that gets annoying and we
* don't want to be nagging users to clean up their watch dirs */
if (tr_ctorGetSourceFile(ctor) == nullptr || !adding_from_watch_dir_)
@ -1115,7 +1116,7 @@ void Session::Impl::add_file_async_callback(
{
if (!file->load_contents_finish(result, contents, length))
{
auto const errmsg = fmt::format(_("Couldn't read '{path}'"), fmt::arg("path", file->get_parse_name().raw()));
auto const errmsg = fmt::format(_("Couldn't read '{path}'"), fmt::arg("path", file->get_parse_name()));
g_message("%s", errmsg.c_str());
}
else if (tr_ctorSetMetainfo(ctor, contents, length, nullptr))
@ -1131,8 +1132,8 @@ void Session::Impl::add_file_async_callback(
{
auto const errmsg = fmt::format(
_("Couldn't read '{path}': {error} ({error_code})"),
fmt::arg("path", file->get_parse_name().raw()),
fmt::arg("error", e.what().raw()),
fmt::arg("path", file->get_parse_name()),
fmt::arg("error", e.what()),
fmt::arg("error_code", e.code()));
g_message("%s", errmsg.c_str());
}
@ -1182,7 +1183,8 @@ bool Session::Impl::add_file(Glib::RefPtr<Gio::File> const& file, bool do_start,
else
{
tr_ctorFree(ctor);
g_message(_("Skipping unknown torrent \"%s\""), file->get_parse_name().c_str());
std::cerr << fmt::format(_("Couldn't add torrent file '{path}'"), fmt::arg("path", file->get_parse_name()))
<< std::endl;
}
return handled;
@ -1457,7 +1459,7 @@ bool gtr_inhibit_hibernation(guint32& cookie)
}
catch (Glib::Error const& e)
{
tr_logAddError(fmt::format(_("Couldn't inhibit desktop hibernation: {error}"), fmt::arg("error", e.what().raw())));
tr_logAddError(fmt::format(_("Couldn't inhibit desktop hibernation: {error}"), fmt::arg("error", e.what())));
}
return success;
@ -1482,7 +1484,7 @@ void gtr_uninhibit_hibernation(guint inhibit_cookie)
}
catch (Glib::Error const& e)
{
tr_logAddError(fmt::format(_("Couldn't inhibit desktop hibernation: {error}"), fmt::arg("error", e.what().raw())));
tr_logAddError(fmt::format(_("Couldn't inhibit desktop hibernation: {error}"), fmt::arg("error", e.what())));
}
}

View File

@ -8,6 +8,8 @@
#include <glibmm.h>
#include <glibmm/i18n.h>
#include <fmt/core.h>
#include "HigWorkarea.h"
#include "PrefsDialog.h"
#include "Session.h"
@ -60,6 +62,11 @@ void setLabelFromRatio(Gtk::Label* l, double d)
setLabel(l, tr_strlratio(d));
}
auto startedTimesText(uint64_t n)
{
return fmt::format(ngettext("Started {count:L} time", "Started {count:L} times", n), fmt::arg("count", n));
}
} // namespace
bool StatsDialog::Impl::updateStats()
@ -75,10 +82,7 @@ bool StatsDialog::Impl::updateStats()
setLabel(one_time_lb_, tr_strltime(one.secondsActive));
setLabelFromRatio(one_ratio_lb_, one.ratio);
setLabel(
all_sessions_lb_,
gtr_sprintf(ngettext("Started %'d time", "Started %'d times", (int)all.sessionCount), (int)all.sessionCount));
setLabel(all_sessions_lb_, startedTimesText(all.sessionCount));
setLabel(all_up_lb_, tr_strlsize(all.uploadedBytes));
setLabel(all_down_lb_, tr_strlsize(all.downloadedBytes));
setLabel(all_time_lb_, tr_strltime(all.secondsActive));
@ -158,7 +162,7 @@ StatsDialog::Impl::Impl(StatsDialog& dialog, Glib::RefPtr<Session> const& core)
t->add_section_divider(row);
t->add_section_title(row, _("Total"));
all_sessions_lb_ = Gtk::make_managed<Gtk::Label>(_("Started %'d time"));
all_sessions_lb_ = Gtk::make_managed<Gtk::Label>(startedTimesText(1));
all_sessions_lb_->set_single_line_mode(true);
t->add_label_w(row, *all_sessions_lb_);
++row;

View File

@ -6,10 +6,13 @@
#include <climits> /* INT_MAX */
#include <cstring> // strchr()
#include <memory>
#include <optional>
#include <glibmm.h>
#include <glibmm/i18n.h>
#include <fmt/core.h>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> /* tr_truncd() */
@ -33,7 +36,7 @@ auto const SmallScale = 0.9;
auto const CompactIconSize = Gtk::ICON_SIZE_MENU;
auto const FullIconSize = Gtk::ICON_SIZE_DND;
Glib::ustring getProgressString(tr_torrent const* tor, uint64_t total_size, tr_stat const* st)
auto getProgressString(tr_torrent const* tor, uint64_t total_size, tr_stat const* st)
{
Glib::ustring gstr;
@ -43,81 +46,56 @@ Glib::ustring getProgressString(tr_torrent const* tor, uint64_t total_size, tr_s
double seedRatio;
bool const hasSeedRatio = tr_torrentGetSeedRatio(tor, &seedRatio);
if (!isDone) /* downloading */
if (!isDone) // downloading
{
gstr += gtr_sprintf(
/* %1$s is how much we've got,
%2$s is how much we'll have when done,
%3$s%% is a percentage of the two */
_("%1$s of %2$s (%3$s%%)"),
tr_strlsize(haveTotal),
tr_strlsize(st->sizeWhenDone),
tr_strlpercent(st->percentDone * 100.0));
// 50 MB of 200 MB (25%)
gstr += fmt::format(
_("{current_size} of {complete_size} ({percent_done}%)"),
fmt::arg("current_size", tr_strlsize(haveTotal)),
fmt::arg("complete_size", tr_strlsize(st->sizeWhenDone)),
fmt::arg("percent_done", tr_strlpercent(st->percentDone * 100.0)));
}
else if (!isSeed) /* partial seeds */
else if (!isSeed && hasSeedRatio) // partial seed, seed ratio
{
if (hasSeedRatio)
{
gstr += gtr_sprintf(
/* %1$s is how much we've got,
%2$s is the torrent's total size,
%3$s%% is a percentage of the two,
%4$s is how much we've uploaded,
%5$s is our upload-to-download ratio,
%6$s is the ratio we want to reach before we stop uploading */
_("%1$s of %2$s (%3$s%%), uploaded %4$s (Ratio: %5$s Goal: %6$s)"),
tr_strlsize(haveTotal),
tr_strlsize(total_size),
tr_strlpercent(st->percentComplete * 100.0),
tr_strlsize(st->uploadedEver),
tr_strlratio(st->ratio),
tr_strlratio(seedRatio));
}
else
{
gstr += gtr_sprintf(
/* %1$s is how much we've got,
%2$s is the torrent's total size,
%3$s%% is a percentage of the two,
%4$s is how much we've uploaded,
%5$s is our upload-to-download ratio */
_("%1$s of %2$s (%3$s%%), uploaded %4$s (Ratio: %5$s)"),
tr_strlsize(haveTotal),
tr_strlsize(total_size),
tr_strlpercent(st->percentComplete * 100.0),
tr_strlsize(st->uploadedEver),
tr_strlratio(st->ratio));
}
// 50 MB of 200 MB (25%), uploaded 30 MB (Ratio: X%, Goal: Y%)
gstr += fmt::format(
_("{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(total_size)),
fmt::arg("percent_done", tr_strlpercent(st->percentComplete * 100.0)),
fmt::arg("uploaded_size", tr_strlsize(st->uploadedEver)),
fmt::arg("ratio", tr_strlratio(st->ratio)),
fmt::arg("seed_ratio", tr_strlratio(seedRatio)));
}
else /* seeding */
else if (!isSeed) // partial seed, no seed ratio
{
if (hasSeedRatio)
{
gstr += gtr_sprintf(
/* %1$s is the torrent's total size,
%2$s is how much we've uploaded,
%3$s is our upload-to-download ratio,
%4$s is the ratio we want to reach before we stop uploading */
_("%1$s, uploaded %2$s (Ratio: %3$s Goal: %4$s)"),
tr_strlsize(total_size),
tr_strlsize(st->uploadedEver),
tr_strlratio(st->ratio),
tr_strlratio(seedRatio));
}
else /* seeding w/o a ratio */
{
gstr += gtr_sprintf(
/* %1$s is the torrent's total size,
%2$s is how much we've uploaded,
%3$s is our upload-to-download ratio */
_("%1$s, uploaded %2$s (Ratio: %3$s)"),
tr_strlsize(total_size),
tr_strlsize(st->uploadedEver),
tr_strlratio(st->ratio));
}
gstr += fmt::format(
_("{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(total_size)),
fmt::arg("percent_complete", tr_strlpercent(st->percentComplete * 100.0)),
fmt::arg("uploaded_size", tr_strlsize(st->uploadedEver)),
fmt::arg("ratio", tr_strlratio(st->ratio)));
}
else if (hasSeedRatio) // seed, seed ratio
{
gstr += fmt::format(
_("{complete_size}, uploaded {uploaded_size} (Ratio: {ratio}, Goal: {seed_ratio})"),
fmt::arg("complete_size", tr_strlsize(total_size)),
fmt::arg("uploaded_size", tr_strlsize(st->uploadedEver)),
fmt::arg("ratio", tr_strlratio(st->ratio)),
fmt::arg("seed_ratio", tr_strlratio(seedRatio)));
}
else // seed, no seed ratio
{
gstr += fmt::format(
_("{complete_size}, uploaded {uploaded_size} (Ratio: {ratio})"),
fmt::arg("complete_size", tr_strlsize(total_size)),
fmt::arg("uploaded_size", tr_strlsize(st->uploadedEver)),
fmt::arg("ratio", tr_strlratio(st->ratio)));
}
/* add time when downloading */
// add time remaining when applicable
if (st->activity == TR_STATUS_DOWNLOAD || (hasSeedRatio && st->activity == TR_STATUS_SEED))
{
int const eta = st->eta;
@ -129,37 +107,32 @@ Glib::ustring getProgressString(tr_torrent const* tor, uint64_t total_size, tr_s
}
else
{
/* time remaining */
gstr += gtr_sprintf(_("%s remaining"), tr_strltime(eta));
gstr += fmt::format(_("{time_span} remaining"), fmt::arg("time_span", tr_strltime(eta)));
}
}
return gstr;
}
Glib::ustring getShortTransferString(
tr_torrent const* tor,
tr_stat const* st,
std::string getShortTransferString(
tr_torrent const* const tor,
tr_stat const* const st,
double uploadSpeed_KBps,
double downloadSpeed_KBps)
{
bool const haveMeta = tr_torrentHasMetadata(tor);
bool const have_meta = tr_torrentHasMetadata(tor);
if (bool const haveDown = haveMeta && (st->peersSendingToUs > 0 || st->webseedsSendingToUs > 0); haveDown)
if (bool const have_down = have_meta && (st->peersSendingToUs > 0 || st->webseedsSendingToUs > 0); have_down)
{
/* down speed, down symbol, up speed, up symbol */
return gtr_sprintf(
_("%1$s %2$s %3$s %4$s"),
return fmt::format(
_("{upload_speed} ▲ {download_speed} ▼"),
tr_formatter_speed_KBps(downloadSpeed_KBps),
gtr_get_unicode_string(GtrUnicode::Down),
tr_formatter_speed_KBps(uploadSpeed_KBps),
gtr_get_unicode_string(GtrUnicode::Up));
tr_formatter_speed_KBps(uploadSpeed_KBps));
}
if (bool const haveUp = haveMeta && st->peersGettingFromUs > 0; haveUp)
if (bool const have_up = have_meta && st->peersGettingFromUs > 0; have_up)
{
/* up speed, up symbol */
return gtr_sprintf(_("%1$s %2$s"), tr_formatter_speed_KBps(uploadSpeed_KBps), gtr_get_unicode_string(GtrUnicode::Up));
return fmt::format(_("{upload_speed} ▲"), tr_formatter_speed_KBps(downloadSpeed_KBps));
}
if (st->isStalled)
@ -170,151 +143,161 @@ Glib::ustring getShortTransferString(
return {};
}
Glib::ustring getShortStatusString(tr_torrent const* tor, tr_stat const* st, double uploadSpeed_KBps, double downloadSpeed_KBps)
std::string getShortStatusString(
tr_torrent const* const tor,
tr_stat const* const st,
double uploadSpeed_KBps,
double downloadSpeed_KBps)
{
Glib::ustring gstr;
switch (st->activity)
{
case TR_STATUS_STOPPED:
gstr += st->finished ? _("Finished") : _("Paused");
break;
return st->finished ? _("Finished") : _("Paused");
case TR_STATUS_CHECK_WAIT:
gstr += _("Queued for verification");
break;
return _("Queued for verification");
case TR_STATUS_DOWNLOAD_WAIT:
gstr += _("Queued for download");
break;
return _("Queued for download");
case TR_STATUS_SEED_WAIT:
gstr += _("Queued for seeding");
break;
return _("Queued for seeding");
case TR_STATUS_CHECK:
gstr += gtr_sprintf(_("Verifying local data (%.1f%% tested)"), tr_truncd(st->recheckProgress * 100.0, 1));
break;
return fmt::format(
_("Verifying local data ({percent_done:.1}% tested)"),
fmt::arg("percent_done", tr_truncd(st->recheckProgress * 100.0, 1)));
case TR_STATUS_DOWNLOAD:
case TR_STATUS_SEED:
{
/* download/upload speed, ratio */
gstr += gtr_sprintf("%s ", getShortTransferString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps));
gstr += gtr_sprintf(_("Ratio: %s"), tr_strlratio(st->ratio));
break;
}
return fmt::format(
"{} {}",
getShortTransferString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps),
fmt::format(_("Ratio: {ratio}"), fmt::arg("ratio", tr_strlratio(st->ratio))));
default:
break;
return {};
}
return gstr;
}
Glib::ustring getStatusString(
static std::optional<std::string> getErrorString(tr_stat const* st)
{
switch (st->error)
{
case TR_STAT_TRACKER_WARNING:
return fmt::format(_("Tracker warning: '{warning}'"), fmt::arg("warning", st->errorString));
break;
case TR_STAT_TRACKER_ERROR:
return fmt::format(_("Tracker Error: '{error}'"), fmt::arg("error", st->errorString));
break;
case TR_STAT_LOCAL_ERROR:
return fmt::format(_("Local error: '{error}'"), fmt::arg("error", st->errorString));
default:
return std::nullopt;
}
}
static auto getActivityString(
tr_torrent const* const tor,
tr_stat const* const st,
double const uploadSpeed_KBps,
double const downloadSpeed_KBps)
{
switch (st->activity)
{
case TR_STATUS_STOPPED:
case TR_STATUS_CHECK_WAIT:
case TR_STATUS_CHECK:
case TR_STATUS_DOWNLOAD_WAIT:
case TR_STATUS_SEED_WAIT:
return getShortStatusString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps);
case TR_STATUS_DOWNLOAD:
if (!tr_torrentHasMetadata(tor))
{
return fmt::format(
ngettext(
"Downloading metadata from {active_count} connected peer ({percent_done:d}% done)",
"Downloading metadata from {active_count} connected peers ({percent_done:d}% done)",
st->peersConnected),
fmt::arg("active_count", st->peersConnected),
fmt::arg("percent_done", 100.0 * st->metadataPercentComplete));
}
if (st->peersSendingToUs != 0 && st->webseedsSendingToUs != 0)
{
return fmt::format(
ngettext(
"Downloading from {active_count} of {connected_count} connected peer and webseed",
"Downloading from {active_count} of {connected_count} connected peers and webseeds",
st->peersConnected + st->webseedsSendingToUs),
fmt::arg("active_count", st->peersSendingToUs + st->webseedsSendingToUs),
fmt::arg("connected_count", st->peersConnected + st->webseedsSendingToUs));
}
if (st->webseedsSendingToUs != 0)
{
return fmt::format(
ngettext(
"Downloading from {active_count} webseed",
"Downloading from {active_count} webseeds",
st->webseedsSendingToUs),
fmt::arg("active_count", st->webseedsSendingToUs));
}
return fmt::format(
ngettext(
"Downloading from {active_count} of {connected_count} connected peer",
"Downloading from {active_count} of {connected_count} connected peers",
st->peersConnected),
fmt::arg("active_count", st->peersSendingToUs),
fmt::arg("connected_count", st->peersConnected));
case TR_STATUS_SEED:
return fmt::format(
ngettext(
"Seeding to {active_count} of {connected_count} connected peer",
"Seeding to {active_count} of {connected_count} connected peers",
st->peersConnected),
fmt::arg("active_count", st->peersGettingFromUs),
fmt::arg("connected_count", st->peersConnected));
default:
g_assert_not_reached();
return std::string{};
}
}
std::string getStatusString(
tr_torrent const* tor,
tr_stat const* st,
double const uploadSpeed_KBps,
double const downloadSpeed_KBps)
{
Glib::ustring gstr;
auto status_str = std::string{};
if (st->error != 0)
if (auto error_string = getErrorString(st); error_string)
{
char const* fmt[] = {
nullptr,
N_("Tracker gave a warning: \"%s\""),
N_("Tracker gave an error: \"%s\""),
N_("Error: %s"),
};
gstr += gtr_sprintf(_(fmt[st->error]), st->errorString);
status_str = *error_string;
}
else
{
switch (st->activity)
{
case TR_STATUS_STOPPED:
case TR_STATUS_CHECK_WAIT:
case TR_STATUS_CHECK:
case TR_STATUS_DOWNLOAD_WAIT:
case TR_STATUS_SEED_WAIT:
{
gstr += getShortStatusString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps);
break;
}
case TR_STATUS_DOWNLOAD:
{
if (!tr_torrentHasMetadata(tor))
{
/* Downloading metadata from 2 peer (s)(50% done) */
gstr += gtr_sprintf(
_("Downloading metadata from %1$'d %2$s (%3$d%% done)"),
st->peersConnected,
ngettext("peer", "peers", st->peersConnected),
(int)(100.0 * st->metadataPercentComplete));
}
else if (st->peersSendingToUs != 0 && st->webseedsSendingToUs != 0)
{
/* Downloading from 2 of 3 peer (s) and 2 webseed (s) */
gstr += gtr_sprintf(
_("Downloading from %1$'d of %2$'d %3$s and %4$'d %5$s"),
st->peersSendingToUs,
st->peersConnected,
ngettext("peer", "peers", st->peersConnected),
st->webseedsSendingToUs,
ngettext("web seed", "web seeds", st->webseedsSendingToUs));
}
else if (st->webseedsSendingToUs != 0)
{
/* Downloading from 3 web seed (s) */
gstr += gtr_sprintf(
_("Downloading from %1$'d %2$s"),
st->webseedsSendingToUs,
ngettext("web seed", "web seeds", st->webseedsSendingToUs));
}
else
{
/* Downloading from 2 of 3 peer (s) */
gstr += gtr_sprintf(
_("Downloading from %1$'d of %2$'d %3$s"),
st->peersSendingToUs,
st->peersConnected,
ngettext("peer", "peers", st->peersConnected));
}
break;
}
case TR_STATUS_SEED:
gstr += gtr_sprintf(
ngettext(
"Seeding to %1$'d of %2$'d connected peer",
"Seeding to %1$'d of %2$'d connected peers",
st->peersConnected),
st->peersGettingFromUs,
st->peersConnected);
break;
default:
g_assert_not_reached();
}
status_str = getActivityString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps);
}
if (st->activity != TR_STATUS_CHECK_WAIT && st->activity != TR_STATUS_CHECK && st->activity != TR_STATUS_DOWNLOAD_WAIT &&
st->activity != TR_STATUS_SEED_WAIT && st->activity != TR_STATUS_STOPPED)
{
auto const buf = getShortTransferString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps);
if (!buf.empty())
if (auto const buf = getShortTransferString(tor, st, uploadSpeed_KBps, downloadSpeed_KBps); !std::empty(buf))
{
gstr += gtr_sprintf(" - %s", buf);
status_str += fmt::format(" - {}", buf);
}
}
return gstr;
return status_str;
}
} // namespace

View File

@ -100,31 +100,29 @@ Glib::ustring tr_strltime(time_t seconds)
}
auto const days = (int)(seconds / 86400);
auto const d = fmt::format(ngettext("{days} day", "{days} days", days), fmt::arg("days", days));
int const hours = (seconds % 86400) / 3600;
int const minutes = (seconds % 3600) / 60;
seconds = (seconds % 3600) % 60;
auto const d = gtr_sprintf(ngettext("%'d day", "%'d days", days), days);
auto const h = gtr_sprintf(ngettext("%'d hour", "%'d hours", hours), hours);
auto const m = gtr_sprintf(ngettext("%'d minute", "%'d minutes", minutes), minutes);
auto const s = gtr_sprintf(ngettext("%'d second", "%'d seconds", (int)seconds), (int)seconds);
auto const h = fmt::format(ngettext("{hours} hour", "{hours} hours", hours), fmt::arg("hours", hours));
if (days != 0)
{
return (days >= 4 || hours == 0) ? d : gtr_sprintf("%s, %s", d, h);
return (days >= 4 || hours == 0) ? d : fmt::format("{}, {}", d, h);
}
else if (hours != 0)
int const minutes = (seconds % 3600) / 60;
auto const m = fmt::format(ngettext("{minutes} minute", "{minutes} minutes", minutes), fmt::arg("minutes", minutes));
if (hours != 0)
{
return (hours >= 4 || minutes == 0) ? h : gtr_sprintf("%s, %s", h, m);
return (hours >= 4 || minutes == 0) ? h : fmt::format("{}, {}", h, m);
}
else if (minutes != 0)
seconds = (seconds % 3600) % 60;
auto const s = fmt::format(ngettext("{seconds} second", "{seconds} seconds", seconds), fmt::arg("seconds", seconds));
if (minutes != 0)
{
return (minutes >= 4 || seconds == 0) ? m : gtr_sprintf("%s, %s", m, s);
}
else
{
return s;
return (minutes >= 4 || seconds == 0) ? m : fmt::format("{}, {}", m, s);
}
return s;
}
namespace
@ -154,14 +152,14 @@ void gtr_add_torrent_error_dialog(Gtk::Widget& child, tr_torrent* duplicate_torr
if (duplicate_torrent != nullptr)
{
secondary = gtr_sprintf(
_("The torrent file \"%s\" is already in use by \"%s.\""),
filename,
tr_torrentName(duplicate_torrent));
secondary = fmt::format(
_("The torrent file '{path}' is already in use by '{torrent_name}'."),
fmt::arg("path", filename),
fmt::arg("torrent_name", tr_torrentName(duplicate_torrent)));
}
else
{
secondary = gtr_sprintf(_("Unable to add torrent file \"%s\"."), filename);
secondary = fmt::format(_("Couldn't add torrent file '{path}'"), fmt::arg("path", filename));
}
auto w = std::make_shared<Gtk::MessageDialog>(
@ -452,13 +450,13 @@ void gtr_unrecognized_url_dialog(Gtk::Widget& parent, Glib::ustring const& url)
auto w = std::make_shared<Gtk::MessageDialog>(
*window,
fmt::format(_("Unsupported URL: '{url}'"), fmt::arg("url", url.raw())),
fmt::format(_("Unsupported URL: '{url}'"), fmt::arg("url", url)),
false /*use markup*/,
Gtk::MESSAGE_ERROR,
Gtk::BUTTONS_CLOSE,
true /*modal*/);
gstr += gtr_sprintf(_("Transmission doesn't know how to use \"%s\""), url);
gstr += fmt::format(_("Transmission doesn't know how to use '{url}'"), fmt::arg("url", url));
if (tr_magnet_metainfo{}.parseMagnet(url.raw()))
{

View File

@ -14,6 +14,9 @@
#include <glibmm.h>
#include <gtkmm.h>
#include <fmt/core.h>
#include <fmt/format.h>
#include <libtransmission/transmission.h>
#include <libtransmission/tr-macros.h>
@ -204,6 +207,16 @@ struct std::hash<Glib::ustring>
}
};
template<>
struct fmt::formatter<Glib::ustring> : formatter<std::string>
{
template<typename FormatContext>
auto format(Glib::ustring const& ustr, FormatContext& ctx) const
{
return formatter<std::string>::format(ustr.raw(), ctx);
}
};
namespace Glib
{

View File

@ -225,7 +225,7 @@ bool tr_announce_list::canAdd(tr_url_parsed_t const& announce)
bool tr_announce_list::save(std::string const& torrent_file, tr_error** error) const
{
// load the .torrent file
// load the torrent file
auto metainfo = tr_variant{};
if (!tr_variantFromFile(&metainfo, TR_VARIANT_PARSE_BENC, std::string{ torrent_file }, error))
{

View File

@ -101,7 +101,7 @@ bool tr_metaInfoBuilderSetPieceSize(tr_metainfo_builder* builder, uint32_t bytes
void tr_metaInfoBuilderFree(tr_metainfo_builder*);
/**
* @brief create a new .torrent file
* @brief create a new torrent file
*
* This is actually done in a worker thread, not the main thread!
* Otherwise the client's interface would lock up while this runs.

View File

@ -27,7 +27,7 @@ struct tr_session;
*/
void tr_setConfigDir(tr_session* session, std::string_view config_dir);
/** @brief return the directory where .torrent files are stored */
/** @brief return the directory where torrent files are stored */
char const* tr_getTorrentDir(tr_session const*);
/** @brief return the directory where the Web Client's web ui files are kept */

View File

@ -257,7 +257,7 @@ static bool useNewMetainfo(tr_torrent* tor, tr_incomplete_metadata const* m, tr_
return false;
}
// yay we have an info dict. Let's make a .torrent file
// yay we have an info dict. Let's make a torrent file
auto top_v = tr_variant{};
tr_buildMetainfoExceptInfoDict(tor->metainfo_, &top_v);
tr_variantMergeDicts(tr_variantDictAddDict(&top_v, TR_KEY_info, 0), &info_dict_v);
@ -265,7 +265,7 @@ static bool useNewMetainfo(tr_torrent* tor, tr_incomplete_metadata const* m, tr_
tr_variantFree(&top_v);
tr_variantFree(&info_dict_v);
// does this synthetic .torrent file parse?
// does this synthetic torrent file parse?
auto metainfo = tr_torrent_metainfo{};
if (!metainfo.parseBenc(benc))
{

View File

@ -234,7 +234,7 @@ void tr_sessionClose(tr_session*);
/**
* @brief Return the session's configuration directory.
*
* This is where transmission stores its .torrent files, .resume files,
* This is where transmission stores its torrent files, .resume files,
* blocklists, etc. It's set in tr_transmissionInit() and is immutable
* during the session.
*/
@ -780,7 +780,7 @@ char const* tr_blocklistGetURL(tr_session const*);
/** @} */
/**
* Instantiating tr_torrents and wrangling .torrent file metadata
* Instantiating tr_torrents and wrangling torrent file metadata
*
* 1. Torrent metadata is handled in the tr_torrent_metadata class.
*
@ -803,7 +803,7 @@ tr_ctor* tr_ctorNew(tr_session const* session);
/** @brief Free a torrent constructor object */
void tr_ctorFree(tr_ctor* ctor);
/** @brief Set whether or not to delete the source .torrent file
/** @brief Set whether or not to delete the source torrent file
when the torrent is added. (Default: False) */
void tr_ctorSetDeleteSource(tr_ctor* ctor, bool doDelete);
@ -813,7 +813,7 @@ bool tr_ctorSetMetainfoFromMagnetLink(tr_ctor* ctor, char const* magnet, tr_erro
/** @brief Set the constructor's metainfo from a raw benc already in memory */
bool tr_ctorSetMetainfo(tr_ctor* ctor, char const* metainfo, size_t len, tr_error** error);
/** @brief Set the constructor's metainfo from a local .torrent file */
/** @brief Set the constructor's metainfo from a local torrent file */
bool tr_ctorSetMetainfoFromFile(tr_ctor* ctor, char const* filename, tr_error** error);
tr_torrent_metainfo const* tr_ctorGetMetainfo(tr_ctor const* ctor);
@ -859,10 +859,10 @@ bool tr_ctorGetPaused(tr_ctor const* ctor, tr_ctorMode mode, bool* setmeIsPaused
/** @brief Get the download path from this peer constructor */
bool tr_ctorGetDownloadDir(tr_ctor const* ctor, tr_ctorMode mode, char const** setmeDownloadDir);
/** @brief Get the "delete .torrent file" flag from this peer constructor */
/** @brief Get the "delete torrent file" flag from this peer constructor */
bool tr_ctorGetDeleteSource(tr_ctor const* ctor, bool* setmeDoDelete);
/** @brief Get the .torrent file that this ctor's metainfo came from,
/** @brief Get the torrent file that this ctor's metainfo came from,
or nullptr if tr_ctorSetMetainfoFromFile() wasn't used */
char const* tr_ctorGetSourceFile(tr_ctor const* ctor);
@ -897,7 +897,7 @@ tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of);
using tr_fileFunc = bool (*)(char const* filename, struct tr_error** error);
/** @brief Removes our .torrent and .resume files for this torrent */
/** @brief Removes our torrent and .resume files for this torrent */
void tr_torrentRemove(tr_torrent* torrent, bool removeLocalData, tr_fileFunc removeFunc);
/** @brief Start a torrent */
@ -1443,7 +1443,7 @@ struct tr_torrent_view
struct tr_torrent_view tr_torrentView(tr_torrent const* tor);
/*
* Get the filename of Transmission's internal copy of the .torrent file.
* Get the filename of Transmission's internal copy of the torrent file.
* This is a duplicate that must be freed with tr_free() when done.
*/
char* tr_torrentFilename(tr_torrent const* tor);
@ -1538,7 +1538,7 @@ struct tr_stat
float percentComplete;
/** How much of the metadata the torrent has.
For torrents added from a .torrent this will always be 1.
For torrents added from a torrent this will always be 1.
For magnet links, this number will from from 0 to 1 as the metadata is downloaded.
Range is [0..1] */
float metadataPercentComplete;

View File

@ -158,7 +158,7 @@ static void tr_watchdir_on_retry_timer(evutil_socket_t /*fd*/, short /*type*/, v
return;
}
tr_logAddWarn(fmt::format(_("Couldn't add .torrent file '{path}'"), fmt::arg("path", retry->name)));
tr_logAddWarn(fmt::format(_("Couldn't add torrent file '{path}'"), fmt::arg("path", retry->name)));
}
tr_watchdir_retries_remove(&handle->active_retries, retry);

View File

@ -69,7 +69,7 @@ void WatchDir::setPath(QString const& path, bool is_enabled)
{
watcher_ = std::make_unique<QFileSystemWatcher>(QStringList{ path });
connect(watcher_.get(), &QFileSystemWatcher::directoryChanged, this, &WatchDir::watcherActivated);
// trigger the watchdir for .torrent files in there already
// trigger the watchdir for torrent files in there already
QTimer::singleShot(0, this, SLOT(rescanAllWatchedDirectories()));
}
}
@ -86,7 +86,7 @@ void WatchDir::watcherActivated(QString const& path)
files.insert(str);
}
// try to add any new files which end in .torrent
// try to add any new files which end in torrent
auto const new_files = files - watch_dir_files_;
auto const torrent_suffix = QStringLiteral(".torrent");
@ -107,7 +107,7 @@ void WatchDir::watcherActivated(QString const& path)
case ERROR:
{
// give the .torrent a few seconds to finish downloading
// give the torrent a few seconds to finish downloading
auto* t = new QTimer(this);
t->setObjectName(dir.absoluteFilePath(name));
t->setSingleShot(true);

View File

@ -338,7 +338,7 @@ TEST_F(AnnounceListTest, save)
};
auto constexpr Tiers = std::array<tr_tracker_tier_t, 3>{ 0, 1, 2 };
// first, set up a scratch .torrent
// first, set up a scratch torrent
auto constexpr* const OriginalFile = LIBTRANSMISSION_TEST_ASSETS_DIR "/Android-x86 8.1 r6 iso.torrent";
auto original_content = std::vector<char>{};
auto const test_file = tr_strvJoin(::testing::TempDir(), "transmission-announce-list-test.torrent"sv);
@ -354,13 +354,13 @@ TEST_F(AnnounceListTest, save)
EXPECT_TRUE(announce_list.add(Urls[1], Tiers[1]));
EXPECT_TRUE(announce_list.add(Urls[2], Tiers[2]));
// try saving to a nonexistent .torrent file
// try saving to a nonexistent torrent file
EXPECT_FALSE(announce_list.save("/this/path/does/not/exist", &error));
EXPECT_NE(nullptr, error);
EXPECT_NE(0, error->code);
tr_error_clear(&error);
// now save to a real .torrent fi le
// now save to a real torrent file
EXPECT_TRUE(announce_list.save(test_file, &error));
EXPECT_EQ(nullptr, error);

View File

@ -56,8 +56,8 @@ protected:
EXPECT_FALSE(builder->isFolder);
EXPECT_FALSE(builder->abortFlag);
// have tr_makeMetaInfo() build the .torrent file
auto const torrent_file = tr_strvJoin(input_file, ".torrent");
// have tr_makeMetaInfo() build the torrent file
auto const torrent_file = tr_strvJoin(input_file, ".torrent"sv);
tr_makeMetaInfo(
builder,
torrent_file.c_str(),
@ -80,7 +80,7 @@ protected:
}
sync();
// now let's check our work: parse the .torrent file
// now let's check our work: parse the torrent file
EXPECT_TRUE(metainfo.parseTorrentFile(torrent_file));
// quick check of some of the parsed metainfo
@ -147,7 +147,7 @@ protected:
EXPECT_EQ(payload_sizes[i], builder->files[i].size);
}
// build the .torrent file
// build the torrent file
auto torrent_file = tr_strvJoin(top, ".torrent"sv);
tr_makeMetaInfo(
builder,
@ -171,7 +171,7 @@ protected:
EXPECT_TRUE(waitFor(test, 5000));
sync();
// now let's check our work: parse the .torrent file
// now let's check our work: parse the torrent file
auto metainfo = tr_torrent_metainfo{};
EXPECT_TRUE(metainfo.parseTorrentFile(torrent_file));

View File

@ -38,6 +38,8 @@ protected:
SessionTest::SetUp();
}
static auto constexpr MaxWaitMsec = 3000;
};
TEST_P(IncompleteDirTest, incompleteDir)
@ -110,7 +112,7 @@ TEST_P(IncompleteDirTest, incompleteDir)
{
return data.done;
};
EXPECT_TRUE(waitFor(test, 1000));
EXPECT_TRUE(waitFor(test, MaxWaitMsec));
}
evbuffer_free(data.buf);

View File

@ -199,7 +199,7 @@ TEST_F(RenameTest, singleFilenameTorrent)
EXPECT_STREQ("foobar", tr_torrentName(tor)); // confirm the torrent's name is now 'foobar'
EXPECT_STREQ("foobar", tr_torrentFile(tor, 0).name); // confirm the file's name is now 'foobar'
char* const torrent_filename = tr_torrentFilename(tor);
EXPECT_STREQ(nullptr, strstr(torrent_filename, "foobar")); // confirm .torrent file hasn't changed
EXPECT_STREQ(nullptr, strstr(torrent_filename, "foobar")); // confirm torrent file hasn't changed
tr_free(torrent_filename);
tmpstr = tr_strvPath(tor->currentDir().sv(), "foobar");
EXPECT_TRUE(tr_sys_path_exists(tmpstr.c_str(), nullptr)); // confirm the file's name is now 'foobar' on the disk

View File

@ -36,7 +36,7 @@ namespace
auto constexpr TimeoutSecs = long{ 30 };
char constexpr MyName[] = "transmission-show";
char constexpr Usage[] = "Usage: transmission-show [options] <.torrent file>";
char constexpr Usage[] = "Usage: transmission-show [options] <torrent-file>";
char constexpr UserAgent[] = "transmission-show/" LONG_VERSION_STRING;
auto options = std::array<tr_option, 5>{
@ -328,13 +328,13 @@ int tr_main(int argc, char* argv[])
/* make sure the user specified a filename */
if (std::empty(opts.filename))
{
fprintf(stderr, "ERROR: No .torrent file specified.\n");
fprintf(stderr, "ERROR: No torrent file specified.\n");
tr_getopt_usage(MyName, Usage, std::data(options));
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
/* try to parse the .torrent file */
/* try to parse the torrent file */
auto metainfo = tr_torrent_metainfo{};
tr_error* error = nullptr;
auto const parsed = metainfo.parseTorrentFile(opts.filename, nullptr, &error);
@ -342,7 +342,7 @@ int tr_main(int argc, char* argv[])
{
fprintf(
stderr,
"Error parsing .torrent file \"%" TR_PRIsv "\": %s (%d)\n",
"Error parsing torrent file \"%" TR_PRIsv "\": %s (%d)\n",
TR_PRIsv_ARG(opts.filename),
error->message,
error->code);