1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-02-22 14:10:34 +00:00

refactor: only update favicon when tracker changes (#1336)

* refactor: make Favicon's Key a semi-opaque type and update a Torrent's icon only when the announce_url changes.
This commit is contained in:
Charles Kerr 2020-06-24 13:28:54 -05:00 committed by GitHub
parent 33a421e97f
commit 7e1da2d8fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 101 deletions

View file

@ -74,14 +74,14 @@ void FaviconCache::ensureCacheDirHasBeenScanned()
**** ****
***/ ***/
QString FaviconCache::getDisplayName(QString const& key) QString FaviconCache::getDisplayName(Key const& key)
{ {
auto name = key; auto name = key;
name[0] = name.at(0).toTitleCase(); name[0] = name.at(0).toTitleCase();
return name; return name;
} }
QString FaviconCache::getKey(QUrl const& url) FaviconCache::Key FaviconCache::getKey(QUrl const& url)
{ {
auto host = url.host(); auto host = url.host();
@ -94,7 +94,7 @@ QString FaviconCache::getKey(QUrl const& url)
return pos < 0 ? host : host.remove(0, pos + 1); return pos < 0 ? host : host.remove(0, pos + 1);
} }
QString FaviconCache::getKey(QString const& displayName) FaviconCache::Key FaviconCache::getKey(QString const& displayName)
{ {
return displayName.toLower(); return displayName.toLower();
} }
@ -104,18 +104,18 @@ QSize FaviconCache::getIconSize()
return QSize(16, 16); return QSize(16, 16);
} }
QPixmap FaviconCache::find(QString const& key) QPixmap FaviconCache::find(Key const& key)
{ {
ensureCacheDirHasBeenScanned(); ensureCacheDirHasBeenScanned();
return pixmaps_[key]; return pixmaps_[key];
} }
QString FaviconCache::add(QUrl const& url) FaviconCache::Key FaviconCache::add(QUrl const& url)
{ {
ensureCacheDirHasBeenScanned(); ensureCacheDirHasBeenScanned();
QString const key = getKey(url); Key const key = getKey(url);
if (pixmaps_.count(key) == 0) if (pixmaps_.count(key) == 0)
{ {

View file

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <QString> #include <QString>
#include <QObject> #include <QObject>
@ -27,30 +28,32 @@ class FaviconCache : public QObject
public: public:
FaviconCache(); FaviconCache();
using Key = QString;
using Keys = std::unordered_set<Key>;
// returns a cached pixmap, or a NULL pixmap if there's no match in the cache // returns a cached pixmap, or a NULL pixmap if there's no match in the cache
QPixmap find(QString const& key); QPixmap find(Key const& key);
QPixmap find(QUrl const& url) { return find(getKey(url)); } QPixmap find(QUrl const& url) { return find(getKey(url)); }
// This will emit a signal when (if) the icon becomes ready. static Key getKey(QString const& display_name);
// Returns the key.
QString add(QUrl const& url);
static QString getDisplayName(QString const& key); // This will emit a signal when (if) the icon becomes ready.
static QString getKey(QUrl const& url); Key add(QUrl const& url);
static QString getKey(QString const& display_name);
static QString getDisplayName(Key const& key);
static QSize getIconSize(); static QSize getIconSize();
signals: signals:
void pixmapReady(QString const& key); void pixmapReady(Key const& key);
private:
QString getCacheDir();
void ensureCacheDirHasBeenScanned();
private slots: private slots:
void onRequestFinished(QNetworkReply* reply); void onRequestFinished(QNetworkReply* reply);
private: private:
static Key getKey(QUrl const& url);
QString getCacheDir();
void ensureCacheDirHasBeenScanned();
QNetworkAccessManager* nam_ = {}; QNetworkAccessManager* nam_ = {};
std::unordered_map<QString, QPixmap> pixmaps_; std::unordered_map<Key, QPixmap> pixmaps_;
}; };

View file

@ -111,35 +111,38 @@ void FilterBar::refreshTrackers()
ROW_TOTALS = 0, ROW_SEPARATOR, ROW_FIRST_TRACKER ROW_TOTALS = 0, ROW_SEPARATOR, ROW_FIRST_TRACKER
}; };
auto torrents_per_host = std::unordered_map<QString, int>{}; auto torrents_per_tracker = std::unordered_map<FaviconCache::Key, int>{};
for (auto const& tor : torrents_.torrents()) for (auto const& tor : torrents_.torrents())
{ {
for (auto const& display_name : tor->trackerDisplayNames()) for (auto const& key : tor->trackerKeys())
{ {
++torrents_per_host[display_name]; ++torrents_per_tracker[key];
} }
} }
// update the "All" row // update the "All" row
auto const num_trackers = torrents_per_host.size(); auto const num_trackers = torrents_per_tracker.size();
auto* item = tracker_model_->item(ROW_TOTALS); auto* item = tracker_model_->item(ROW_TOTALS);
item->setData(int(num_trackers), FilterBarComboBox::CountRole); item->setData(int(num_trackers), FilterBarComboBox::CountRole);
item->setData(getCountString(num_trackers), FilterBarComboBox::CountStringRole); item->setData(getCountString(num_trackers), FilterBarComboBox::CountStringRole);
auto update_tracker_item = [](QStandardItem* i, auto const& it) auto update_tracker_item = [](QStandardItem* i, auto const& it)
{ {
auto const& display_name = it->first; auto const& key = it->first;
auto const& display_name = FaviconCache::getDisplayName(key);
auto const& count = it->second; auto const& count = it->second;
auto const icon = qApp->faviconCache().find(FaviconCache::getKey(display_name)); auto const icon = qApp->faviconCache().find(key);
i->setData(display_name, Qt::DisplayRole); i->setData(display_name, Qt::DisplayRole);
i->setData(display_name, TRACKER_ROLE); i->setData(display_name, TRACKER_ROLE);
i->setData(getCountString(count), FilterBarComboBox::CountStringRole); i->setData(getCountString(count), FilterBarComboBox::CountStringRole);
i->setData(icon, Qt::DecorationRole); i->setData(icon, Qt::DecorationRole);
i->setData(int(count), FilterBarComboBox::CountRole); i->setData(int(count), FilterBarComboBox::CountRole);
return i; return i;
}; };
auto new_trackers = std::map<QString, int>(torrents_per_host.begin(), torrents_per_host.end()); auto new_trackers = std::map<FaviconCache::Key, int>(torrents_per_tracker.begin(), torrents_per_tracker.end());
auto old_it = tracker_counts_.cbegin(); auto old_it = tracker_counts_.cbegin();
auto new_it = new_trackers.cbegin(); auto new_it = new_trackers.cbegin();
auto const old_end = tracker_counts_.cend(); auto const old_end = tracker_counts_.cend();
@ -331,25 +334,8 @@ void FilterBar::onTrackerIndexChanged(int i)
{ {
if (!is_bootstrapping_) if (!is_bootstrapping_)
{ {
QString str; auto const display_name = tracker_combo_->itemData(i, TRACKER_ROLE).toString();
bool const is_tracker = !tracker_combo_->itemData(i, TRACKER_ROLE).toString().isEmpty(); prefs_.set(Prefs::FILTER_TRACKERS, display_name);
if (!is_tracker)
{
// show all
}
else
{
str = tracker_combo_->itemData(i, TRACKER_ROLE).toString();
int const pos = str.lastIndexOf(QLatin1Char('.'));
if (pos >= 0)
{
str.truncate(pos + 1);
}
}
prefs_.set(Prefs::FILTER_TRACKERS, str);
} }
} }

View file

@ -14,6 +14,7 @@
#include <QString> #include <QString>
#include <QWidget> #include <QWidget>
#include "FaviconCache.h"
#include "Torrent.h" #include "Torrent.h"
#include "Typedefs.h" #include "Typedefs.h"
@ -56,7 +57,7 @@ private:
TorrentModel const& torrents_; TorrentModel const& torrents_;
TorrentFilter const& filter_; TorrentFilter const& filter_;
std::map<QString, int> tracker_counts_; std::map<FaviconCache::Key, int> tracker_counts_;
FilterBarComboBox* activity_combo_ = {}; FilterBarComboBox* activity_combo_ = {};
FilterBarComboBox* tracker_combo_ = {}; FilterBarComboBox* tracker_combo_ = {};
QLabel* count_label_ = {}; QLabel* count_label_ = {};

View file

@ -6,8 +6,9 @@
* *
*/ */
#include <algorithm>
#include <cassert> #include <cassert>
#include <iostream> #include <iterator>
#include <QApplication> #include <QApplication>
#include <QString> #include <QString>
@ -284,10 +285,12 @@ bool change(TrackerStat& setme, tr_variant const* value)
tr_variant* child; tr_variant* child;
while (tr_variantDictChild(const_cast<tr_variant*>(value), pos++, &key, &child)) while (tr_variantDictChild(const_cast<tr_variant*>(value), pos++, &key, &child))
{ {
bool field_changed = false;
switch (key) switch (key)
{ {
#define HANDLE_KEY(key, field) case TR_KEY_ ## key: \ #define HANDLE_KEY(key, field) case TR_KEY_ ## key: \
changed = change(setme.field, child) || changed; break; field_changed = change(setme.field, child); break;
HANDLE_KEY(announce, announce) HANDLE_KEY(announce, announce)
HANDLE_KEY(announceState, announce_state) HANDLE_KEY(announceState, announce_state)
HANDLE_KEY(downloadCount, download_count) HANDLE_KEY(downloadCount, download_count)
@ -318,6 +321,16 @@ bool change(TrackerStat& setme, tr_variant const* value)
default: default:
break; break;
} }
if (field_changed)
{
if (key == TR_KEY_announce)
{
setme.favicon_key = qApp->faviconCache().add(QUrl(setme.announce));
}
changed = true;
}
} }
return changed; return changed;
@ -376,17 +389,9 @@ bool Torrent::getSeedRatio(double& setmeRatio) const
return is_limited; return is_limited;
} }
bool Torrent::hasTrackerSubstring(QString const& substr) const bool Torrent::includesTracker(FaviconCache::Key const& key) const
{ {
for (auto const& s : trackers()) return tracker_keys_.count(key) != 0;
{
if (s.contains(substr, Qt::CaseInsensitive))
{
return true;
}
}
return false;
} }
int Torrent::compareSeedRatio(Torrent const& that) const int Torrent::compareSeedRatio(Torrent const& that) const
@ -586,10 +591,6 @@ Torrent::fields_t Torrent::update(tr_quark const* keys, tr_variant const* const*
{ {
switch (key) switch (key)
{ {
case TR_KEY_editDate:
// FIXME
break;
case TR_KEY_name: case TR_KEY_name:
{ {
updateMimeIcon(); updateMimeIcon();
@ -609,28 +610,11 @@ Torrent::fields_t Torrent::update(tr_quark const* keys, tr_variant const* const*
case TR_KEY_trackers: case TR_KEY_trackers:
{ {
// rebuild trackers_ FaviconCache::Keys keys;
QStringList urls; std::transform(std::cbegin(tracker_stats_), std::cend(tracker_stats_),
urls.reserve(tracker_stats_.size()); std::inserter(keys, std::end(keys)),
for (auto const& t : tracker_stats_) [](auto const& ts) { return ts.favicon_key; });
{ std::swap(tracker_keys_, keys);
urls.append(t.announce);
}
trackers_.swap(urls);
// rebuild trackerDisplayNames
QStringList display_names;
display_names.reserve(trackers_.size());
for (auto const& tracker : trackers_)
{
auto const url = QUrl(tracker);
auto const key = qApp->faviconCache().add(url);
display_names.append(FaviconCache::getDisplayName(key));
}
display_names.removeDuplicates();
tracker_display_names_.swap(display_names);
break; break;
} }
} }
@ -706,5 +690,5 @@ QString Torrent::getError() const
QPixmap TrackerStat::getFavicon() const QPixmap TrackerStat::getFavicon() const
{ {
return qApp->faviconCache().find(QUrl(announce)); return qApp->faviconCache().find(favicon_key);
} }

View file

@ -15,11 +15,11 @@
#include <QMetaType> #include <QMetaType>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QStringList>
#include <libtransmission/transmission.h> #include <libtransmission/transmission.h>
#include <libtransmission/quark.h> #include <libtransmission/quark.h>
#include "FaviconCache.h"
#include "Speed.h" #include "Speed.h"
#ifdef ERROR #ifdef ERROR
@ -81,6 +81,7 @@ struct TrackerStat
int scrape_state; int scrape_state;
int seeder_count; int seeder_count;
int tier; int tier;
FaviconCache::Key favicon_key;
QString announce; QString announce;
QString host; QString host;
QString last_announce_result; QString last_announce_result;
@ -356,7 +357,12 @@ public:
return recheck_progress_; return recheck_progress_;
} }
bool hasTrackerSubstring(QString const& substr) const; bool includesTracker(FaviconCache::Key const& key) const;
FaviconCache::Keys const& trackerKeys() const
{
return tracker_keys_;
}
Speed uploadLimit() const Speed uploadLimit() const
{ {
@ -413,16 +419,6 @@ public:
return tracker_stats_; return tracker_stats_;
} }
QStringList const& trackers() const
{
return trackers_;
}
QStringList const& trackerDisplayNames() const
{
return tracker_display_names_;
}
PeerList const& peers() const PeerList const& peers() const
{ {
return peers_; return peers_;
@ -639,8 +635,7 @@ private:
PeerList peers_; PeerList peers_;
FileList files_; FileList files_;
QStringList trackers_; FaviconCache::Keys tracker_keys_;
QStringList tracker_display_names_;
TrackerStatsList tracker_stats_; TrackerStatsList tracker_stats_;
Speed upload_speed_; Speed upload_speed_;

View file

@ -245,8 +245,9 @@ bool TorrentFilter::filterAcceptsRow(int source_row, QModelIndex const& source_p
if (accepts) if (accepts)
{ {
auto const name = prefs_.getString(Prefs::FILTER_TRACKERS); auto const display_name = prefs_.getString(Prefs::FILTER_TRACKERS);
accepts = name.isEmpty() || tor.hasTrackerSubstring(name); auto const key = FaviconCache::getKey(display_name);
accepts = key.isEmpty() || tor.includesTracker(key);
} }
if (accepts) if (accepts)