mirror of
https://github.com/transmission/transmission.git
synced 2025-12-26 13:21:44 +00:00
feat: Torrent::update() returns a bitset of changed properties (#1334)
* 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
This commit is contained in:
@@ -326,8 +326,10 @@ void DetailsDialog::onTorrentsEdited(torrent_ids_t const& ids)
|
||||
}
|
||||
}
|
||||
|
||||
void DetailsDialog::onTorrentsChanged(torrent_ids_t const& ids)
|
||||
void DetailsDialog::onTorrentsChanged(torrent_ids_t const& ids, Torrent::fields_t const& fields)
|
||||
{
|
||||
Q_UNUSED(fields)
|
||||
|
||||
if (have_pending_refresh_)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -62,7 +62,7 @@ private slots:
|
||||
void onTimer();
|
||||
|
||||
void onTorrentsEdited(torrent_ids_t const& ids);
|
||||
void onTorrentsChanged(torrent_ids_t const& ids);
|
||||
void onTorrentsChanged(torrent_ids_t const& ids, Torrent::fields_t const& fields);
|
||||
|
||||
// Tracker tab
|
||||
void onTrackerSelectionChanged();
|
||||
|
||||
@@ -232,7 +232,7 @@ FilterBar::FilterBar(Prefs& prefs, TorrentModel const& torrents, TorrentFilter c
|
||||
connect(&torrents_, SIGNAL(modelReset()), this, SLOT(recountSoon()));
|
||||
connect(&torrents_, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(recountSoon()));
|
||||
connect(&torrents_, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(recountSoon()));
|
||||
connect(&torrents_, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(recountSoon()));
|
||||
connect(&torrents_, &TorrentModel::torrentsChanged, this, &FilterBar::onTorrentsChanged);
|
||||
connect(recount_timer_, SIGNAL(timeout()), this, SLOT(recount()));
|
||||
|
||||
recountSoon();
|
||||
@@ -297,6 +297,14 @@ void FilterBar::refreshPref(int key)
|
||||
}
|
||||
}
|
||||
|
||||
void FilterBar::onTorrentsChanged(torrent_ids_t const& ids, Torrent::fields_t const& changed_fields)
|
||||
{
|
||||
Q_UNUSED(ids);
|
||||
Q_UNUSED(changed_fields);
|
||||
|
||||
recountSoon();
|
||||
}
|
||||
|
||||
void FilterBar::onTextChanged(QString const& str)
|
||||
{
|
||||
if (!is_bootstrapping_)
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Torrent.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QStandardItemModel;
|
||||
@@ -44,6 +47,7 @@ private slots:
|
||||
void onActivityIndexChanged(int index);
|
||||
void onTrackerIndexChanged(int index);
|
||||
void onTextChanged(QString const&);
|
||||
void onTorrentsChanged(torrent_ids_t const&, Torrent::fields_t const& fields);
|
||||
|
||||
private:
|
||||
Prefs& prefs_;
|
||||
|
||||
@@ -245,7 +245,7 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
|
||||
connect(&model_, &TorrentModel::modelReset, this, refresh_soon_adapter);
|
||||
connect(&model_, &TorrentModel::rowsRemoved, this, refresh_soon_adapter);
|
||||
connect(&model_, &TorrentModel::rowsInserted, this, refresh_soon_adapter);
|
||||
connect(&model_, &TorrentModel::dataChanged, this, refresh_soon_adapter);
|
||||
connect(&model_, &TorrentModel::torrentsChanged, this, refresh_soon_adapter);
|
||||
|
||||
ui_.listView->setModel(&filter_model_);
|
||||
connect(ui_.listView->selectionModel(), &QItemSelectionModel::selectionChanged, refresh_action_sensitivity_soon);
|
||||
|
||||
122
qt/Torrent.cc
122
qt/Torrent.cc
@@ -505,9 +505,9 @@ void Torrent::updateMimeIcon()
|
||||
****
|
||||
***/
|
||||
|
||||
bool Torrent::update(tr_quark const* keys, tr_variant const* const* values, size_t n)
|
||||
Torrent::fields_t Torrent::update(tr_quark const* keys, tr_variant const* const* values, size_t n)
|
||||
{
|
||||
bool changed = false;
|
||||
auto changed = fields_t{};
|
||||
|
||||
for (size_t pos = 0; pos < n; ++pos)
|
||||
{
|
||||
@@ -517,71 +517,71 @@ bool Torrent::update(tr_quark const* keys, tr_variant const* const* values, size
|
||||
|
||||
switch (key)
|
||||
{
|
||||
#define HANDLE_KEY(key, field) case TR_KEY_ ## key: \
|
||||
field_changed = change(field ## _, child); break;
|
||||
#define HANDLE_KEY(key, field, bit) case TR_KEY_ ## key: \
|
||||
field_changed = change(field ## _, child); \
|
||||
changed.set(bit, field_changed); \
|
||||
break;
|
||||
|
||||
HANDLE_KEY(activityDate, activity_date)
|
||||
HANDLE_KEY(addedDate, added_date)
|
||||
HANDLE_KEY(bandwidthPriority, bandwidth_priority)
|
||||
HANDLE_KEY(comment, comment)
|
||||
HANDLE_KEY(corruptEver, failed_ever)
|
||||
HANDLE_KEY(creator, creator)
|
||||
HANDLE_KEY(dateCreated, date_created)
|
||||
HANDLE_KEY(desiredAvailable, desired_available)
|
||||
HANDLE_KEY(downloadDir, download_dir)
|
||||
HANDLE_KEY(downloadLimit, download_limit) // KB/s
|
||||
HANDLE_KEY(downloadLimited, download_limited)
|
||||
HANDLE_KEY(downloadedEver, downloaded_ever)
|
||||
HANDLE_KEY(editDate, edit_date)
|
||||
HANDLE_KEY(error, error)
|
||||
HANDLE_KEY(errorString, error_string)
|
||||
HANDLE_KEY(eta, eta)
|
||||
HANDLE_KEY(fileStats, files)
|
||||
HANDLE_KEY(files, files)
|
||||
HANDLE_KEY(hashString, hash_string)
|
||||
HANDLE_KEY(haveUnchecked, have_unchecked)
|
||||
HANDLE_KEY(haveValid, have_verified)
|
||||
HANDLE_KEY(honorsSessionLimits, honors_session_limits)
|
||||
HANDLE_KEY(isFinished, is_finished)
|
||||
HANDLE_KEY(isPrivate, is_private)
|
||||
HANDLE_KEY(isStalled, is_stalled)
|
||||
HANDLE_KEY(leftUntilDone, left_until_done)
|
||||
HANDLE_KEY(manualAnnounceTime, manual_announce_time)
|
||||
HANDLE_KEY(metadataPercentComplete, metadata_percent_complete)
|
||||
HANDLE_KEY(name, name)
|
||||
HANDLE_KEY(peer_limit, peer_limit)
|
||||
HANDLE_KEY(peers, peers)
|
||||
HANDLE_KEY(peersConnected, peers_connected)
|
||||
HANDLE_KEY(peersGettingFromUs, peers_getting_from_us)
|
||||
HANDLE_KEY(peersSendingToUs, peers_sending_to_us)
|
||||
HANDLE_KEY(percentDone, percent_done)
|
||||
HANDLE_KEY(pieceCount, piece_count)
|
||||
HANDLE_KEY(pieceSize, piece_size)
|
||||
HANDLE_KEY(queuePosition, queue_position)
|
||||
HANDLE_KEY(rateDownload, download_speed)
|
||||
HANDLE_KEY(rateUpload, upload_speed)
|
||||
HANDLE_KEY(recheckProgress, recheck_progress)
|
||||
HANDLE_KEY(seedIdleLimit, seed_idle_limit)
|
||||
HANDLE_KEY(seedIdleMode, seed_idle_mode)
|
||||
HANDLE_KEY(seedRatioLimit, seed_ratio_limit)
|
||||
HANDLE_KEY(seedRatioMode, seed_ratio_mode)
|
||||
HANDLE_KEY(sizeWhenDone, size_when_done)
|
||||
HANDLE_KEY(startDate, start_date)
|
||||
HANDLE_KEY(status, status)
|
||||
HANDLE_KEY(totalSize, total_size)
|
||||
HANDLE_KEY(trackerStats, tracker_stats)
|
||||
HANDLE_KEY(trackers, tracker_stats)
|
||||
HANDLE_KEY(uploadLimit, upload_limit) // KB/s
|
||||
HANDLE_KEY(uploadLimited, upload_limited)
|
||||
HANDLE_KEY(uploadedEver, uploaded_ever)
|
||||
HANDLE_KEY(webseedsSendingToUs, webseeds_sending_to_us)
|
||||
HANDLE_KEY(activityDate, activity_date, ACTIVITY_DATE)
|
||||
HANDLE_KEY(addedDate, added_date, ADDED_DATE)
|
||||
HANDLE_KEY(bandwidthPriority, bandwidth_priority, BANDWIDTH_PRIORITY)
|
||||
HANDLE_KEY(comment, comment, COMMENT)
|
||||
HANDLE_KEY(corruptEver, failed_ever, FAILED_EVER)
|
||||
HANDLE_KEY(creator, creator, CREATOR)
|
||||
HANDLE_KEY(dateCreated, date_created, DATE_CREATED)
|
||||
HANDLE_KEY(desiredAvailable, desired_available, DESIRED_AVAILABLE)
|
||||
HANDLE_KEY(downloadDir, download_dir, DOWNLOAD_DIR)
|
||||
HANDLE_KEY(downloadLimit, download_limit, DOWNLOAD_LIMIT) // KB/s
|
||||
HANDLE_KEY(downloadLimited, download_limited, DOWNLOAD_LIMITED)
|
||||
HANDLE_KEY(downloadedEver, downloaded_ever, DOWNLOADED_EVER)
|
||||
HANDLE_KEY(editDate, edit_date, EDIT_DATE)
|
||||
HANDLE_KEY(error, error, ERROR)
|
||||
HANDLE_KEY(errorString, error_string, ERROR_STRING)
|
||||
HANDLE_KEY(eta, eta, ETA)
|
||||
HANDLE_KEY(fileStats, files, FILES)
|
||||
HANDLE_KEY(files, files, FILES)
|
||||
HANDLE_KEY(hashString, hash_string, HASH_STRING)
|
||||
HANDLE_KEY(haveUnchecked, have_unchecked, HAVE_UNCHECKED)
|
||||
HANDLE_KEY(haveValid, have_verified, HAVE_VERIFIED)
|
||||
HANDLE_KEY(honorsSessionLimits, honors_session_limits, HONORS_SESSION_LIMITS)
|
||||
HANDLE_KEY(isFinished, is_finished, IS_FINISHED)
|
||||
HANDLE_KEY(isPrivate, is_private, IS_PRIVATE)
|
||||
HANDLE_KEY(isStalled, is_stalled, IS_STALLED)
|
||||
HANDLE_KEY(leftUntilDone, left_until_done, LEFT_UNTIL_DONE)
|
||||
HANDLE_KEY(manualAnnounceTime, manual_announce_time, MANUAL_ANNOUNCE_TIME)
|
||||
HANDLE_KEY(metadataPercentComplete, metadata_percent_complete, METADATA_PERCENT_COMPLETE)
|
||||
HANDLE_KEY(name, name, NAME)
|
||||
HANDLE_KEY(peer_limit, peer_limit, PEER_LIMIT)
|
||||
HANDLE_KEY(peers, peers, PEERS)
|
||||
HANDLE_KEY(peersConnected, peers_connected, PEERS_CONNECTED)
|
||||
HANDLE_KEY(peersGettingFromUs, peers_getting_from_us, PEERS_GETTING_FROM_US)
|
||||
HANDLE_KEY(peersSendingToUs, peers_sending_to_us, PEERS_SENDING_TO_US)
|
||||
HANDLE_KEY(percentDone, percent_done, PERCENT_DONE)
|
||||
HANDLE_KEY(pieceCount, piece_count, PIECE_COUNT)
|
||||
HANDLE_KEY(pieceSize, piece_size, PIECE_SIZE)
|
||||
HANDLE_KEY(queuePosition, queue_position, QUEUE_POSITION)
|
||||
HANDLE_KEY(rateDownload, download_speed, DOWNLOAD_SPEED)
|
||||
HANDLE_KEY(rateUpload, upload_speed, UPLOAD_SPEED)
|
||||
HANDLE_KEY(recheckProgress, recheck_progress, RECHECK_PROGRESS)
|
||||
HANDLE_KEY(seedIdleLimit, seed_idle_limit, SEED_IDLE_LIMIT)
|
||||
HANDLE_KEY(seedIdleMode, seed_idle_mode, SEED_IDLE_MODE)
|
||||
HANDLE_KEY(seedRatioLimit, seed_ratio_limit, SEED_RATIO_LIMIT)
|
||||
HANDLE_KEY(seedRatioMode, seed_ratio_mode, SEED_RATIO_MODE)
|
||||
HANDLE_KEY(sizeWhenDone, size_when_done, SIZE_WHEN_DONE)
|
||||
HANDLE_KEY(startDate, start_date, START_DATE)
|
||||
HANDLE_KEY(status, status, STATUS)
|
||||
HANDLE_KEY(totalSize, total_size, TOTAL_SIZE)
|
||||
HANDLE_KEY(trackerStats, tracker_stats, TRACKER_STATS)
|
||||
HANDLE_KEY(trackers, tracker_stats, TRACKER_STATS)
|
||||
HANDLE_KEY(uploadLimit, upload_limit, UPLOAD_LIMIT) // KB/s
|
||||
HANDLE_KEY(uploadLimited, upload_limited, UPLOAD_LIMITED)
|
||||
HANDLE_KEY(uploadedEver, uploaded_ever, UPLOADED_EVER)
|
||||
HANDLE_KEY(webseedsSendingToUs, webseeds_sending_to_us, WEBSEEDS_SENDING_TO_US)
|
||||
#undef HANDLE_KEY
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
changed = changed || field_changed;
|
||||
|
||||
if (field_changed)
|
||||
{
|
||||
switch (key)
|
||||
|
||||
67
qt/Torrent.h
67
qt/Torrent.h
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <ctime> // time_t
|
||||
|
||||
#include <QIcon>
|
||||
@@ -499,8 +500,6 @@ public:
|
||||
return isWaitingToDownload() || isWaitingToSeed();
|
||||
}
|
||||
|
||||
bool update(tr_quark const* keys, tr_variant const* const* values, size_t n);
|
||||
|
||||
QIcon getMimeTypeIcon() const
|
||||
{
|
||||
return icon_;
|
||||
@@ -513,10 +512,72 @@ public:
|
||||
static KeyList const MainInfoKeys;
|
||||
static KeyList const MainStatKeys;
|
||||
|
||||
enum Field
|
||||
{
|
||||
ACTIVITY_DATE,
|
||||
ADDED_DATE,
|
||||
BANDWIDTH_PRIORITY,
|
||||
COMMENT,
|
||||
CREATOR,
|
||||
DATE_CREATED,
|
||||
DESIRED_AVAILABLE,
|
||||
DOWNLOADED_EVER,
|
||||
DOWNLOAD_DIR,
|
||||
DOWNLOAD_LIMIT,
|
||||
DOWNLOAD_LIMITED,
|
||||
DOWNLOAD_SPEED,
|
||||
EDIT_DATE,
|
||||
ERROR,
|
||||
ERROR_STRING,
|
||||
ETA,
|
||||
FAILED_EVER,
|
||||
FILES,
|
||||
HASH_STRING,
|
||||
HAVE_UNCHECKED,
|
||||
HAVE_VERIFIED,
|
||||
HONORS_SESSION_LIMITS,
|
||||
ICON,
|
||||
IS_FINISHED,
|
||||
IS_PRIVATE,
|
||||
IS_STALLED,
|
||||
LEFT_UNTIL_DONE,
|
||||
MANUAL_ANNOUNCE_TIME,
|
||||
METADATA_PERCENT_COMPLETE,
|
||||
NAME,
|
||||
PEERS,
|
||||
PEERS_CONNECTED,
|
||||
PEERS_GETTING_FROM_US,
|
||||
PEERS_SENDING_TO_US,
|
||||
PEER_LIMIT,
|
||||
PERCENT_DONE,
|
||||
PIECE_COUNT,
|
||||
PIECE_SIZE,
|
||||
QUEUE_POSITION,
|
||||
RECHECK_PROGRESS,
|
||||
SEED_IDLE_LIMIT,
|
||||
SEED_IDLE_MODE,
|
||||
SEED_RATIO_LIMIT,
|
||||
SEED_RATIO_MODE,
|
||||
SIZE_WHEN_DONE,
|
||||
START_DATE,
|
||||
STATUS,
|
||||
TOTAL_SIZE,
|
||||
TRACKER_STATS,
|
||||
UPLOADED_EVER,
|
||||
UPLOAD_LIMIT,
|
||||
UPLOAD_LIMITED,
|
||||
UPLOAD_SPEED,
|
||||
WEBSEEDS_SENDING_TO_US,
|
||||
|
||||
N_FIELDS
|
||||
};
|
||||
using fields_t = std::bitset<N_FIELDS>;
|
||||
|
||||
fields_t update(tr_quark const* keys, tr_variant const* const* values, size_t n);
|
||||
|
||||
private:
|
||||
void updateMimeIcon();
|
||||
|
||||
private:
|
||||
int const id_;
|
||||
|
||||
bool download_limited_ = {};
|
||||
|
||||
@@ -161,6 +161,7 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool is_complete_list)
|
||||
auto instantiated = torrents_t{};
|
||||
auto needinfo = torrent_ids_t{};
|
||||
auto processed = torrents_t{};
|
||||
auto changed_fields = Torrent::fields_t{};
|
||||
|
||||
auto const now = time(nullptr);
|
||||
auto const recently_added = [now](auto const& tor)
|
||||
@@ -248,7 +249,6 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool is_complete_list)
|
||||
}
|
||||
|
||||
Torrent* tor = getTorrentFromId(id);
|
||||
std::optional<uint64_t> left_until_done;
|
||||
bool is_new = false;
|
||||
|
||||
if (tor == nullptr)
|
||||
@@ -257,19 +257,16 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool is_complete_list)
|
||||
instantiated.push_back(tor);
|
||||
is_new = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_until_done = tor->leftUntilDone();
|
||||
}
|
||||
|
||||
auto const old_edit_date = tor->dateEdited();
|
||||
auto const fields = tor->update(keys.data(), values.data(), keys.size());
|
||||
|
||||
if (tor->update(keys.data(), values.data(), keys.size()))
|
||||
if (fields.any())
|
||||
{
|
||||
changed_fields |= fields;
|
||||
changed.insert(id);
|
||||
}
|
||||
|
||||
if (old_edit_date != tor->dateEdited())
|
||||
if (fields.test(Torrent::EDIT_DATE))
|
||||
{
|
||||
edited.insert(id);
|
||||
}
|
||||
@@ -285,7 +282,7 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool is_complete_list)
|
||||
already_added_.insert(id);
|
||||
}
|
||||
|
||||
if (left_until_done && (*left_until_done > 0) && (tor->leftUntilDone() == 0) && (tor->downloadedEver() > 0))
|
||||
if (fields.test(Torrent::LEFT_UNTIL_DONE) && (tor->leftUntilDone() == 0) && (tor->downloadedEver() > 0))
|
||||
{
|
||||
completed.insert(id);
|
||||
}
|
||||
@@ -324,7 +321,7 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool is_complete_list)
|
||||
|
||||
if (!changed.empty())
|
||||
{
|
||||
emit torrentsChanged(changed);
|
||||
emit torrentsChanged(changed, changed_fields);
|
||||
}
|
||||
|
||||
if (!completed.empty())
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
#include <vector>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
// #include <QVector>
|
||||
#include <QVector>
|
||||
|
||||
#include <Typedefs.h>
|
||||
#include "Torrent.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
class Prefs;
|
||||
class Speed;
|
||||
class Torrent;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -57,7 +57,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void torrentsAdded(torrent_ids_t const&);
|
||||
void torrentsChanged(torrent_ids_t const&);
|
||||
void torrentsChanged(torrent_ids_t const&, Torrent::fields_t const& fields);
|
||||
void torrentsCompleted(torrent_ids_t const&);
|
||||
void torrentsEdited(torrent_ids_t const&);
|
||||
void torrentsNeedInfo(torrent_ids_t const&);
|
||||
|
||||
Reference in New Issue
Block a user