* refactor: use a vector for FavIcon cache keys
Third of three PRs focused on small memory wins in transmission-qt.
This one saves 1-2 M off RES in my 15K torrent testbed. Not a major
improvement, but nice enough.
Previously we held the torrent's tracker keys in an unordered_set.
That container type is overkill for this field: the list is usually
short and almost never changes, so we don't need fast insertion time.
We can keep the same log N lookup by using a sorted vector and avoid
the excess container size & memory allocations of an unordered_set.
* refactor: intern repeated strings e.g. downloadDir
Add an app-wide interned QString cache for commonly-repeated
strings. Currently used for download_dir, announce_url, comment,
creator, error_string.
* refactor: keep torrent hash in std::array<char,20>
This replaces the hashString QString allocation with a compile-time
array that's included in sizeof the Torrent struct that owns it.
* refactor: omit unnecessary #include
* refactor: make the onDuplicatesTimer slot private.
* feat: show dupe torrents in dialog's detailText
* fix: a stupid bug that I introduced.
* If you accidentally try to add a lot of duplicates -- for example, by
starting up with a lot of duplicate torrents in the watchdir -- then
coalesce all of them into a single error dialog instead of spamming
the desktop with a different dialog for every duplicate.
* Make the duplicate torrent dialog's error message slightly terser to
make it accommodate a long list of torrents: omit the ".torrent" file
suffixes and show an abbreviated form of the existing torrent's hash.
* Support searching by torrent hash in the filterbar's text entry.
This is useful when copy/pasting the hash from the duplicate torrent
error dialog and is also consistent with the GTK client behavior.
* Copy the GTK client's behavior of appending ".added" to the end of
.torrent files after they've been added to the session.
* refactor: speed up FaviconCache::add() again.
Another iteration on FaviconCache::add() since it's still showing up so
high in my perf tests. add()'s url argument is now a QString instead of
a QUrl, and the class has a private unordered_map that maps QString urls
into Keys. Basically, QUrl generation is so expensive that it's worth
caching the result to avoid constructing the intermediate QUrl object.
Also, ensure that the network reply's `deleteLater()` method is called
so that they don't leak, and add 'svg' to the icon list since it's now
supported on all major browsers.
Minor optimization: since we don't actually change our request headers
very often, we can lazy-build the request once and reuse that instead of
having to rebuild it each time.
Explicitly delete the implied function to ensure we don't get bitten by
this again in the future.
Mark the string_views constexpr where possible so that we can avoid some
strlen() calls at runtime.
* refactor: make variant_headers reusable to qt app.
Torrent.cc's `change()` template methods are generically useful to deal
with tr_variant wrangling, but previously were only used in Torrent.cc.
This PR moves them into a new API `VariantHelpers.h` for use by Prefs,
Session, TorrentModel, etc.
* refactor: Torrent::update() returns a delta bitset
Setting up for followup PRs where, instead of doing expensive work every
time there is a change, we can be more fine-grained and do the work only
if the relevant Torrent properties changed.
* chore: make uncrustify happy
* refactor: update filterbar counts more selectively
Only rebuild the activity and tracker combobox models when the model's
size changes or when the relevant Torrent properties change.
Previously, rebuild would happen on any Torrent property change even if
the properties were unrelated to activity or trackers.
* chore: remove redundant "private:" key
* refactor: Torrent::update() returns a delta bitset
Setting up for followup PRs where, instead of doing expensive work every
time there is a change, we can be more fine-grained and do the work only
if the relevant Torrent properties changed.
* chore: make uncrustify happy
* chore: fix #includes
* refactor: faster action sensitivity updates
Currently we walk through every row in the model and pump its TorrentRole data, which can be expensive for long lists. However since we're only interested in the selected rows, let's save some traversal overhead by getting that list directly and walking it instead.
edit-date got added to the backend in 3.00, but I never finished adding
it properly to the Qt client. This PR rectifies that. When a torrent is
edited, the Application and DetailsDialogs will re-query the backend to
update the torrent properties that are needed.
* refactor: use snake_case field naming in qt client
* fix: some missed symbols
* chore: make uncrustify happy
* fixup! refactor: use snake_case field naming in qt client
* chore: remove qvariants from torrent class
* chore: remove unused Q_DECLARE macro calls
* refactor: remove unused includes from Torrent.h
* chore: make clang-tidy and linter happy
* refactor: rename 'setValue()' to 'change()'
* refactor: make tr_variant function paramters const
* chore: remove devel scaffolding
* refactor: rename peer_limit_ to peerLimit_
* refactor: do not use bitwise logic on booleans
GTK client: none.
Qt client: Finnish.
Mac client: none (there're suitable languages, but they're lacking XIB files
and we haven't switched to base localization yet).
GTK client: none.
Qt client: Japanese.
Mac client: none (there're suitable languages, but they're lacking XIB files
and we haven't switched to base localization yet).
* perf: lazy-update actions enabled on change events
Actions' sensitivity was being lazy-updated in response to other events
but accidentally were doing immediate updates in response to torrentsChanged
signals being emitted from TorrentModel. This commit makes that path a
lazy-update as well.
* chore: uncrustify
* refactor: make the idle updater a lambda again
* Add EDIT_DATE torrent property declaration (Qt client)
Switch to static assertion to help avoid similar issues in the future.
* Only declare std::hash<QString> for Qt < 5.14
* Pass main window as context when connecting lambdas to torrents model signals (Qt client)
This helps to automatically disconnect from signals on main window
destruction. If not done, use after free is possible since main window is
destroyed before torrents model.
Fixes: #1106
* feat: add tr_stat.infoDate to note tr_info changes
The last time during this session that any tr_info field changed
(e.g. trackers/filenames edited or magnet torrent got metadata).
RPC clients can monitor this to know when to reload fields which
don't usually change.
* faster updating of trackers combobox.
* generate trackerDisplayNames just once per torrent
* refactor: cache torrent delegate's warning emblem
* refactor: change mainwin refresh debounce to 200ms
* refactor: do not store trackers, hosts in QVariant
* refactor: don't use `virtual` when it's not needed
* refactor: faster counting torrents-matching-filter
* refactor: faster tracker handling in filterbar
* refactor: improve json parser's prealloc heuristic
* refactor: make Torrent::hasError() faster
* refactor: remove redundant speed stats collection
* refactor: remove unnecessary tor->isQueued() calls
* refactor: use unordered containers where possible
* scale favicons only once, when adding to the cache
* feat: add optional "format" arg to torrent-get RPC
If the "format" request was "objects" (default), "torrents" will be an
array of objects, each of which contains the key/value pairs matching
the request's "fields" arg. This is unchanged from previous versions.
If the format was "table", then "torrents" will be an array of arrays.
The first row holds the keys and each remaining row holds a torrent's
values for those keys. This format is more efficient in terms of JSON
generation and JSON parsing.
refractor: simplify torrent model signal emissions
The Torrent->Application signal connections make up for about 5% of the
app's memory use. Move this to the TorrentModel so that there are only a
handful of signal connections.
Moving signals to TorrentModel means batch change signals can be emitted
instead of per-change-per-torrent emissions and can be handled that way.
* refactor: debounce TorrentFilter prefs refiltering
When filter settings change, add a slight delay before refiltering. This
prevents the UI from freezing when the user is typing in the filterbar's
textfield.
Also fixes a long-standing wart that caused the model to be sorted twice
instead of just once whenever the filter text changed.
* refactor: keep torrent's time properties as time_t
Comparing QDateTimes is expensive. Keep the torrents' time properties in
the time_t form that we got them from RPG in; difftime() is cheaper.
* refactor: don't load the same stock more than once
Some actions share an icon -- for example, "start all", "start now", and
"start" each use "media-playback-start". When this happens, get the icon
once and cache it to avoid hitting the disk more often than necessary.
In addition, the statusbar's network transfer icon was being reloaded in
a periodic upkeep timer, reloading with QIcon::fromTheme each time. Only
give icons are needed, so load them once and cache them.
* refactor: better lookup of torrent mime-type icons
filename-to-mime-type and mime-type-to-icon lookups are both expensive,
so do a better job of detecting top-level folders and caching the icons
based on file suffixes.
This also lets find a good mime icon even if the torrent doesn't have
its 'files' property populated yet from RPC.
* fix: __attribute__(__printf__) warnings
* fix: implicit fallthrough warning
* fixup! fix: implicit fallthrough warning
* fix: disable warnings for 3rd party code
Since we want to leave upstream code as-is
* fixup! fix: disable warnings for 3rd party code
* fixup! fix: disable warnings for 3rd party code
* silence spurious alignment warning
Xrefs
Discussion: https://stackoverflow.com/a/35554349
Macro inspiration: 90ac46f710/f/src/util/util_safealign.h (_35)
* fixup! fix: disable warnings for 3rd party code
* fixup! fix: implicit fallthrough warning
* make uncrustify happy
* remove uncrustify-test.sh
that's probably off-topic for this PR
* fixup! fix: __attribute__(__printf__) warnings
* Update libtransmission/CMakeLists.txt
Co-Authored-By: ckerr <ckerr@github.com>
* fixup! silence spurious alignment warning
* use -w for DISABLE_WARNINGS in Clang
* refactor: fix libtransmission deprecation warnings
* fix: pthread_create's start_routine's return value
This was defined as `void` on non-Windows but should have been `void*`
* chore: uncrustify
* fix: add DISABLE_WARNINGS option for SunPro Studio
* fix "unused in lambda capture" warnings by clang++
* fix 'increases required alignment' warning
Caused from storing int16_t's in a char array.
* fix net.c 'increases required alignment' warning
The code passes in a `struct sockaddr_storage*` which is a padded struct
large enough for the necessary alignment. Unfortunately it was recast as
a `struct sockaddr*` which has less padding and a smaller alignment. The
warning occrred because of these differing alignments.
* make building quieter so warnings are more visible
* fixup! fix 'increases required alignment' warning
* Fix -Wcast-function-type warnings in GTK+ app code
https://gitlab.gnome.org/GNOME/gnome-terminal/issues/96 talks about both
the issue and its solution.
GCC 8's -Wcast-function-type, enabled by -Wextra, is problematic in glib
applications because it's idiomatic there to recast function signatures,
e.g. `g_slist_free(list, (GFunc)g_free, NULL);`.
Disabling the warning with pragmas causes "unrecognized pragma" warnings
on clang and older versions of gcc, and disabling the warning could miss
actual bugs. GCC defines `void (*)(void)` as a special case that matches
anything so we can silence warnings by double-casting through GCallback.
In the previous example, the warning is silenced by changing the code to
read `g_slist_free(list, (GFunc)(GCallback)g_free, NULL);`).
* fixup! fix "unused in lambda capture" warnings by clang++
* fixup! fix "unused in lambda capture" warnings by clang++
* fix two more libtransmission compiler warnings
* fix: in watchdir, use TR_ENABLE_ASSERTS not NDEBUG
In compact torrents view, use BAR_WIDTH as groove area width instead of
total progress bar width, to improve the appearance in case progress text
is drawn outside of the groove area (because of style settings).
Initial patch provided by dubhater.
Fixes: #491
An assertion failure happens shortly after opening the
"Torrent properties" dialog if the torrent's root folder has
a one-letter name, e. g.
A/
A/Some Linux distro.iso
A/Some other Linux distro.iso
Off by one errors are great, eh?
This fixes https://trac.transmissionbt.com/ticket/6141
Magnet transfers caused the by-progress sorting to become non-stable, as their
percentComplete() could return NaN. This patch fixes this by preferring active
downloads over magnet transfers, then sorting them by percentComplete().
This way all the qualifiers (`const`, `volatile`, `mutable`) are grouped
together, e.g. `T const* const x` vs. `const T* const x`. Also helps reading
types right-to-left, e.g. "constant pointer to constant T" vs. "constant
pointer to T which is constant".
There're places where manual intervention is still required as uncrustify
is not ideal (unfortunately), but at least one may rely on it to do the
right thing most of the time (e.g. when sending in a patch).
The style itself is quite different from what we had before but making it
uniform across all the codebase is the key. I also hope that it'll make the
code more readable (YMMV) and less sensitive to further changes.