From 3780f90ef554e21504e5ac2ddfe79ff4b602c68c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 20 Feb 2022 21:25:49 -0600 Subject: [PATCH] perf: skip some excess announce list rebuilds --- libtransmission/announce-list.h | 10 ++++++ libtransmission/announcer.cc | 4 +-- libtransmission/session.cc | 18 ++++++++-- libtransmission/transmission.h | 2 +- qt/PrefsDialog.cc | 60 ++++++++++++++++++++++----------- qt/PrefsDialog.h | 2 +- 6 files changed, 71 insertions(+), 25 deletions(-) diff --git a/libtransmission/announce-list.h b/libtransmission/announce-list.h index 9049a163e..ffb994e98 100644 --- a/libtransmission/announce-list.h +++ b/libtransmission/announce-list.h @@ -92,6 +92,16 @@ public: [[nodiscard]] tr_tracker_tier_t nextTier() const; + [[nodiscard]] bool operator==(tr_announce_list const& that) const + { + return trackers_ == that.trackers_; + } + + [[nodiscard]] bool operator!=(tr_announce_list const& that) const + { + return trackers_ != that.trackers_; + } + bool add(std::string_view announce_url_sv) { return add(announce_url_sv, this->nextTier()); diff --git a/libtransmission/announcer.cc b/libtransmission/announcer.cc index 8f27553f9..73b74c154 100644 --- a/libtransmission/announcer.cc +++ b/libtransmission/announcer.cc @@ -581,8 +581,8 @@ private: { auto announce_list = tor->announceList(); - // if it's a public torrent, inject the default trackers - if (!tor->isPrivate()) + // if it's a public torrent, add the default trackers + if (tor->isPublic()) { announce_list.add(tor->session->defaultTrackers()); } diff --git a/libtransmission/session.cc b/libtransmission/session.cc index d4abeb760..3d96b107b 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -2253,8 +2253,22 @@ int tr_sessionGetCacheLimit_MB(tr_session const* session) void tr_session::setDefaultTrackers(std::string_view trackers) { - this->default_trackers_str_ = trackers; - this->default_trackers_.parse(trackers); + auto const oldval = default_trackers_; + + default_trackers_str_ = trackers; + default_trackers_.parse(trackers); + + // if the list changed, update all the public torrents + if (default_trackers_ != oldval) + { + for (auto* tor : torrents) + { + if (tor->isPublic()) + { + tr_announcerResetTorrent(announcer, tor); + } + } + } } void tr_sessionSetDefaultTrackers(tr_session* session, char const* trackers) diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index fd887a244..9898f2a72 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -1195,7 +1195,7 @@ char* tr_torrentGetMagnetLink(tr_torrent const* tor); * along with tr_torrentSetTrackerList(), is intended for import/export * and user editing. It does *not* include the "default trackers" that * are applied to all public torrents. If you want a full display of all - * trackers, use tr_torrentTracker() and tr_torrentTackerCount() + * trackers, use tr_torrentTracker() and tr_torrentTrackerCount() */ char* tr_torrentGetTrackerList(tr_torrent const* tor); diff --git a/qt/PrefsDialog.cc b/qt/PrefsDialog.cc index 981b1d875..dfe651ee8 100644 --- a/qt/PrefsDialog.cc +++ b/qt/PrefsDialog.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -239,12 +240,47 @@ void PrefsDialog::linkWidgetToPref(QWidget* widget, int pref_key) connect(spin_box, &QAbstractSpinBox::editingFinished, this, &PrefsDialog::spinBoxEditingFinished); return; } +} - if (auto const* edit = qobject_cast(widget); edit != nullptr) +static bool isDescendantOf(QObject const* descendant, QObject const* ancestor) +{ + if (ancestor == nullptr) { - connect(edit, &QPlainTextEdit::textChanged, this, &PrefsDialog::plainTextChanged); - return; + return false; } + while (descendant != nullptr) + { + if (descendant == ancestor) + { + return true; + } + + descendant = descendant->parent(); + } + return false; +} + +void PrefsDialog::focusChanged(QWidget* old, QWidget* cur) +{ + // We don't want to change the preference every time there's a keystroke + // in a QPlainTextEdit, so instead of connecting to the textChanged signal, + // only update the pref when the text changed AND focus was lost. + char const constexpr* const StartValue = "StartValue"; + + if (auto* const edit = qobject_cast(cur); isDescendantOf(edit, this)) + { + edit->setProperty(StartValue, edit->toPlainText()); + } + + if (auto const* const edit = qobject_cast(old); isDescendantOf(edit, this)) + { + if (auto const val = edit->toPlainText(); val != edit->property(StartValue).toString()) + { + setPref(PreferenceWidget{ old }.getPrefKey(), val); + } + } + + // (TODO: we probably want to do this for single-line text entries too?) } void PrefsDialog::checkBoxToggled(bool checked) @@ -306,22 +342,6 @@ void PrefsDialog::pathChanged(QString const& path) } } -void PrefsDialog::plainTextChanged() -{ - PreferenceWidget const pref_widget(sender()); - - if (pref_widget.is()) - { - auto const* const plain_text_edit = pref_widget.as(); - - if (plain_text_edit->document()->isModified()) - { - prefs_.set(pref_widget.getPrefKey(), plain_text_edit->toPlainText()); - // we avoid using setPref() because the included refreshPref() call would reset the cursor while we're editing - } - } -} - /*** **** ***/ @@ -704,6 +724,8 @@ PrefsDialog::PrefsDialog(Session& session, Prefs& prefs, QWidget* parent) } adjustSize(); + + connect(qApp, &QApplication::focusChanged, this, &PrefsDialog::focusChanged); } void PrefsDialog::setPref(int key, QVariant const& v) diff --git a/qt/PrefsDialog.h b/qt/PrefsDialog.h index df8e823b8..1a82f6d8a 100644 --- a/qt/PrefsDialog.h +++ b/qt/PrefsDialog.h @@ -29,12 +29,12 @@ public: PrefsDialog(Session&, Prefs&, QWidget* parent = nullptr); private slots: + void focusChanged(QWidget* old, QWidget* now); void checkBoxToggled(bool checked); void spinBoxEditingFinished(); void timeEditingFinished(); void lineEditingFinished(); void pathChanged(QString const& path); - void plainTextChanged(); void refreshPref(int key); void encryptionEdited(int); void altSpeedDaysEdited(int);