qt client speedups

* 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
This commit is contained in:
Charles Kerr 2019-11-11 19:37:05 -06:00 committed by GitHub
parent 49fdd0b430
commit c62cb35fd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 504 additions and 531 deletions

View File

@ -45,6 +45,12 @@ struct json_wrapper_data
struct evbuffer* strbuf;
char const* source;
tr_ptrArray stack;
/* A very common pattern is for a container's children to be similar,
* e.g. they may all be objects with the same set of keys. So when
* a container is popped off the stack, remember its size to use as
* a preallocation heuristic for the next container at that depth. */
size_t preallocGuess[MAX_DEPTH];
};
static tr_variant* get_node(struct jsonsl_st* jsn)
@ -103,25 +109,22 @@ static void action_callback_PUSH(jsonsl_t jsn, jsonsl_action_t action UNUSED, st
tr_variant* node;
struct json_wrapper_data* data = jsn->data;
switch (state->type)
if ((state->type == JSONSL_T_LIST) || (state->type == JSONSL_T_OBJECT))
{
case JSONSL_T_LIST:
data->has_content = true;
node = get_node(jsn);
tr_variantInitList(node, 0);
tr_ptrArrayAppend(&data->stack, node);
break;
case JSONSL_T_OBJECT:
data->has_content = true;
node = get_node(jsn);
tr_variantInitDict(node, 0);
tr_ptrArrayAppend(&data->stack, node);
break;
default:
/* nothing else interesting on push */
break;
int const depth = tr_ptrArraySize(&data->stack);
size_t const n = depth < MAX_DEPTH ? data->preallocGuess[depth] : 0;
if (state->type == JSONSL_T_LIST)
{
tr_variantInitList(node, n);
}
else
{
tr_variantInitDict(node, n);
}
}
}
@ -318,7 +321,12 @@ static void action_callback_POP(jsonsl_t jsn, jsonsl_action_t action UNUSED, str
}
else if (state->type == JSONSL_T_LIST || state->type == JSONSL_T_OBJECT)
{
tr_ptrArrayPop(&data->stack);
int const depth = tr_ptrArraySize(&data->stack);
tr_variant const* v = tr_ptrArrayPop(&data->stack);
if (depth < MAX_DEPTH)
{
data->preallocGuess[depth] = v->val.l.count;
}
}
else if (state->type == JSONSL_T_SPECIAL)
{
@ -369,6 +377,10 @@ int tr_jsonParse(char const* source, void const* vbuf, size_t len, tr_variant* s
data.source = source;
data.keybuf = evbuffer_new();
data.strbuf = evbuffer_new();
for (int i = 0; i < MAX_DEPTH; ++i)
{
data.preallocGuess[i] = 0;
}
/* parse it */
jsonsl_feed(jsn, vbuf, len);

View File

@ -22,7 +22,6 @@ class AboutDialog : public BaseDialog
public:
AboutDialog(QWidget* parent = nullptr);
virtual ~AboutDialog() = default;
private slots:
void showCredits();

View File

@ -399,7 +399,7 @@ void Application::quitLater()
QTimer::singleShot(0, this, SLOT(quit()));
}
QStringList Application::getNames(QSet<int> const& ids) const
QStringList Application::getNames(torrent_ids_t const& ids) const
{
QStringList names;
for (auto const& id : ids)
@ -411,7 +411,7 @@ QStringList Application::getNames(QSet<int> const& ids) const
return names;
}
void Application::onTorrentsAdded(QSet<int> const& ids)
void Application::onTorrentsAdded(torrent_ids_t const& ids)
{
if (myPrefs->getBool(Prefs::SHOW_NOTIFICATION_ON_ADD))
{
@ -421,7 +421,7 @@ void Application::onTorrentsAdded(QSet<int> const& ids)
}
}
void Application::onTorrentsCompleted(QSet<int> const& ids)
void Application::onTorrentsCompleted(torrent_ids_t const& ids)
{
if (myPrefs->getBool(Prefs::SHOW_NOTIFICATION_ON_COMPLETE))
{
@ -440,9 +440,9 @@ void Application::onTorrentsCompleted(QSet<int> const& ids)
}
}
void Application::onTorrentsNeedInfo(QSet<int> const& ids)
void Application::onTorrentsNeedInfo(torrent_ids_t const& ids)
{
if (!ids.isEmpty())
if (!ids.empty())
{
mySession->initTorrents(ids);
}

View File

@ -9,11 +9,11 @@
#pragma once
#include <QApplication>
#include <QSet>
#include <QTimer>
#include <QTranslator>
#include "FaviconCache.h"
#include "Typedefs.h"
class AddData;
class Prefs;
@ -43,14 +43,14 @@ private slots:
void onSessionSourceChanged();
void refreshPref(int key);
void refreshTorrents();
void onTorrentsAdded(QSet<int> const& torrents);
void onTorrentsCompleted(QSet<int> const& torrents);
void onTorrentsNeedInfo(QSet<int> const& torrents);
void onTorrentsAdded(torrent_ids_t const& torrents);
void onTorrentsCompleted(torrent_ids_t const& torrents);
void onTorrentsNeedInfo(torrent_ids_t const& torrents);
private:
void maybeUpdateBlocklist();
void loadTranslations();
QStringList getNames(QSet<int> const& ids) const;
QStringList getNames(torrent_ids_t const& ids) const;
void quitLater();
private:

View File

@ -106,6 +106,7 @@ set(${PROJECT_NAME}_HEADERS
TrackerDelegate.h
TrackerModel.h
TrackerModelFilter.h
Typedefs.h
Utils.h
WatchDir.h
)

View File

@ -24,7 +24,7 @@ public:
void addLayout(QGridLayout* layout);
// QObject
virtual bool eventFilter(QObject* object, QEvent* event);
bool eventFilter(QObject* object, QEvent* event) override;
public slots:
void update();

View File

@ -6,6 +6,7 @@
*
*/
#include <algorithm> // std::any_of
#include <cassert>
#include <climits> /* INT_MAX */
#include <ctime>
@ -249,7 +250,7 @@ DetailsDialog::~DetailsDialog()
myTrackerModel->deleteLater();
}
void DetailsDialog::setIds(QSet<int> const& ids)
void DetailsDialog::setIds(torrent_ids_t const& ids)
{
if (ids != myIds)
{
@ -309,15 +310,20 @@ void DetailsDialog::getNewData()
}
}
void DetailsDialog::onTorrentsChanged(QSet<int> const& ids)
void DetailsDialog::onTorrentsChanged(torrent_ids_t const& ids)
{
auto const interesting = ids & myIds;
if (!interesting.isEmpty() && !myHavePendingRefresh)
if (myHavePendingRefresh)
{
myHavePendingRefresh = true;
QTimer::singleShot(100, this, SLOT(refresh()));
return;
}
if (!std::any_of(ids.begin(), ids.end(), [this](auto const& id) { return myIds.count(id) != 0; }))
{
return;
}
myHavePendingRefresh = true;
QTimer::singleShot(100, this, SLOT(refresh()));
}
namespace
@ -1290,7 +1296,7 @@ void DetailsDialog::onAddTrackerClicked()
}
else
{
QSet<int> ids;
torrent_ids_t ids;
for (int const id : myIds)
{
@ -1336,8 +1342,7 @@ void DetailsDialog::onEditTrackerClicked()
}
else
{
QSet<int> ids;
ids << trackerInfo.torrentId;
torrent_ids_t ids{ trackerInfo.torrentId };
QPair<int, QString> const idUrl = qMakePair(trackerInfo.st.id, newval);
@ -1362,8 +1367,7 @@ void DetailsDialog::onRemoveTrackerClicked()
// batch all of a tracker's torrents into one command
for (int const id : torrentId_to_trackerIds.uniqueKeys())
{
QSet<int> ids;
ids << id;
torrent_ids_t const ids{ id };
mySession.torrentSet(ids, TR_KEY_trackerRemove, torrentId_to_trackerIds.values(id));
}

View File

@ -14,6 +14,7 @@
#include <QTimer>
#include "BaseDialog.h"
#include "Typedefs.h"
#include "ui_DetailsDialog.h"
@ -35,10 +36,10 @@ public:
DetailsDialog(Session&, Prefs&, TorrentModel const&, QWidget* parent = nullptr);
virtual ~DetailsDialog();
void setIds(QSet<int> const& ids);
void setIds(torrent_ids_t const& ids);
// QWidget
virtual QSize sizeHint() const
QSize sizeHint() const override
{
return QSize(440, 460);
}
@ -59,7 +60,7 @@ private slots:
void refresh();
void refreshPref(int key);
void onTorrentsChanged(QSet<int> const& ids);
void onTorrentsChanged(torrent_ids_t const& ids);
void onTimer();
// Tracker tab
@ -93,7 +94,7 @@ private:
Ui::DetailsDialog ui;
QSet<int> myIds;
torrent_ids_t myIds;
QTimer myTimer;
bool myChangedTorrents;
bool myHavePendingRefresh;

View File

@ -40,6 +40,15 @@ QString FaviconCache::getCacheDir()
return QDir(base).absoluteFilePath(QLatin1String("favicons"));
}
namespace
{
QPixmap scale(QPixmap pixmap)
{
return pixmap.scaled(FaviconCache::getIconSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
}
void FaviconCache::ensureCacheDirHasBeenScanned()
{
static bool hasBeenScanned = false;
@ -60,24 +69,44 @@ void FaviconCache::ensureCacheDirHasBeenScanned()
if (!pixmap.isNull())
{
myPixmaps.insert(file, pixmap);
myPixmaps[file] = scale(pixmap);
}
}
}
}
QString FaviconCache::getHost(QUrl const& url)
/***
****
***/
QString FaviconCache::getDisplayName(QUrl const& url)
{
QString host = url.host();
int const first_dot = host.indexOf(QLatin1Char('.'));
int const last_dot = host.lastIndexOf(QLatin1Char('.'));
return getDisplayName(getKey(url));
}
if (first_dot != -1 && last_dot != -1 && first_dot != last_dot)
{
host.remove(0, first_dot + 1);
}
QString FaviconCache::getDisplayName(QString const& key)
{
auto name = key;
name[0] = name.at(0).toTitleCase();
return name;
}
return host;
QString FaviconCache::getKey(QUrl const& url)
{
auto host = url.host();
// remove tld
auto const suffix = url.topLevelDomain();
host.truncate(host.size() - suffix.size());
// remove subdomain
auto const pos = host.indexOf(QLatin1Char('.'));
return pos < 0 ? host : host.remove(0, pos + 1);
}
QString FaviconCache::getKey(QString const& displayName)
{
return displayName.toLower();
}
QSize FaviconCache::getIconSize()
@ -85,31 +114,26 @@ QSize FaviconCache::getIconSize()
return QSize(16, 16);
}
QPixmap FaviconCache::find(QUrl const& url)
{
return findFromHost(getHost(url));
}
QPixmap FaviconCache::findFromHost(QString const& host)
QPixmap FaviconCache::find(QString const& key)
{
ensureCacheDirHasBeenScanned();
return myPixmaps[host];
return myPixmaps[key];
}
void FaviconCache::add(QUrl const& url)
QString FaviconCache::add(QUrl const& url)
{
ensureCacheDirHasBeenScanned();
QString const host = getHost(url);
QString const key = getKey(url);
if (!myPixmaps.contains(host))
if (myPixmaps.count(key) == 0)
{
// add a placholder s.t. we only ping the server once per session
myPixmaps.insert(host, QPixmap());
myPixmaps[key] = QPixmap();
// try to download the favicon
QString const path = QLatin1String("http://") + host + QLatin1String("/favicon.");
QString const path = QLatin1String("http://") + url.host() + QLatin1String("/favicon.");
QStringList suffixes;
suffixes << QLatin1String("ico") << QLatin1String("png") << QLatin1String("gif") << QLatin1String("jpg");
@ -118,11 +142,13 @@ void FaviconCache::add(QUrl const& url)
myNAM->get(QNetworkRequest(path + suffix));
}
}
return key;
}
void FaviconCache::onRequestFinished(QNetworkReply* reply)
{
QString const host = reply->url().host();
auto const key = getKey(reply->url());
QPixmap pixmap;
@ -136,17 +162,17 @@ void FaviconCache::onRequestFinished(QNetworkReply* reply)
if (!pixmap.isNull())
{
// save it in memory...
myPixmaps.insert(host, pixmap);
myPixmaps[key] = scale(pixmap);
// save it on disk...
QDir cacheDir(getCacheDir());
cacheDir.mkpath(cacheDir.absolutePath());
QFile file(cacheDir.absoluteFilePath(host));
QFile file(cacheDir.absoluteFilePath(key));
file.open(QIODevice::WriteOnly);
file.write(content);
file.close();
// notify listeners
emit pixmapReady(host);
emit pixmapReady(key);
}
}

View File

@ -8,11 +8,14 @@
#pragma once
#include <QMap>
#include <unordered_map>
#include <QString>
#include <QObject>
#include <QPixmap>
#include <Utils.h> // std::hash<QString>
class QNetworkAccessManager;
class QNetworkReply;
class QUrl;
@ -26,19 +29,21 @@ public:
virtual ~FaviconCache();
// returns a cached pixmap, or a NULL pixmap if there's no match in the cache
QPixmap find(QUrl const& url);
QPixmap find(QString const& key);
QPixmap find(QUrl const& url) { return find(getKey(url)); }
// returns a cached pixmap, or a NULL pixmap if there's no match in the cache
QPixmap findFromHost(QString const& host);
// This will emit a signal when (if) the icon becomes ready.
// Returns the key.
QString add(QUrl const& url);
// this will emit a signal when (if) the icon becomes ready
void add(QUrl const& url);
static QString getHost(QUrl const& url);
static QString getDisplayName(QUrl const& url);
static QString getDisplayName(QString const& key);
static QString getKey(QUrl const& url);
static QString getKey(QString const& displayName);
static QSize getIconSize();
signals:
void pixmapReady(QString const& host);
void pixmapReady(QString const& key);
private:
QString getCacheDir();
@ -49,5 +54,5 @@ private slots:
private:
QNetworkAccessManager* myNAM;
QMap<QString, QPixmap> myPixmaps;
std::unordered_map<QString, QPixmap> myPixmaps;
};

View File

@ -20,12 +20,8 @@ public:
{
}
virtual ~FileTreeDelegate()
{
}
public:
// QAbstractItemDelegate
virtual QSize sizeHint(QStyleOptionViewItem const&, QModelIndex const&) const;
virtual void paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const;
QSize sizeHint(QStyleOptionViewItem const&, QModelIndex const&) const override;
void paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const override;
};

View File

@ -292,7 +292,7 @@ int FileTreeModel::rowCount(QModelIndex const& parent) const
int FileTreeModel::columnCount(QModelIndex const& parent) const
{
Q_UNUSED(parent);
Q_UNUSED(parent)
return NUM_COLUMNS;
}

View File

@ -43,7 +43,7 @@ public:
public:
FileTreeModel(QObject* parent = nullptr, bool isEditable = true);
virtual ~FileTreeModel();
~FileTreeModel();
void setEditable(bool editable);
@ -62,14 +62,14 @@ public:
QModelIndex parent(QModelIndex const& child, int column) const;
// QAbstractItemModel
virtual QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(QModelIndex const& index) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual QModelIndex index(int row, int column, QModelIndex const& parent = QModelIndex()) const;
virtual QModelIndex parent(QModelIndex const& child) const;
virtual int rowCount(QModelIndex const& parent = QModelIndex()) const;
virtual int columnCount(QModelIndex const& parent = QModelIndex()) const;
virtual bool setData(QModelIndex const& index, QVariant const& value, int role = Qt::EditRole);
QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(QModelIndex const& index) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, QModelIndex const& parent = QModelIndex()) const override;
QModelIndex parent(QModelIndex const& child) const override;
int rowCount(QModelIndex const& parent = QModelIndex()) const override;
int columnCount(QModelIndex const& parent = QModelIndex()) const override;
bool setData(QModelIndex const& index, QVariant const& value, int role = Qt::EditRole) override;
signals:
void priorityChanged(QSet<int> const& fileIndices, int);

View File

@ -40,13 +40,13 @@ signals:
protected:
// QWidget
virtual void resizeEvent(QResizeEvent* event);
virtual void keyPressEvent(QKeyEvent* event);
virtual void mouseDoubleClickEvent(QMouseEvent* event);
virtual void contextMenuEvent(QContextMenuEvent* event);
void resizeEvent(QResizeEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
void contextMenuEvent(QContextMenuEvent* event) override;
// QAbstractItemView
virtual bool edit(QModelIndex const& index, EditTrigger trigger, QEvent* event);
bool edit(QModelIndex const& index, EditTrigger trigger, QEvent* event) override;
private slots:
void onClicked(QModelIndex const& index);

View File

@ -6,6 +6,9 @@
*
*/
#include <map>
#include <unordered_map>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
@ -21,6 +24,7 @@
#include "Torrent.h"
#include "TorrentFilter.h"
#include "TorrentModel.h"
#include "Utils.h"
enum
{
@ -28,30 +32,6 @@ enum
TrackerRole
};
namespace
{
QString readableHostName(QString const& host)
{
// get the readable name...
QString name = host;
int const pos = name.lastIndexOf(QLatin1Char('.'));
if (pos >= 0)
{
name.truncate(pos);
}
if (!name.isEmpty())
{
name[0] = name[0].toUpper();
}
return name;
}
} // namespace
/***
****
***/
@ -107,122 +87,88 @@ FilterBarComboBox* FilterBar::createActivityCombo()
****
***/
namespace
{
QString getCountString(int n)
{
return QString::fromLatin1("%L1").arg(n);
}
} // namespace
void FilterBar::refreshTrackers()
{
FaviconCache& favicons = qApp->faviconCache();
int const firstTrackerRow = 2; // skip over the "All" and separator...
// pull info from the tracker model...
QSet<QString> oldHosts;
for (int row = firstTrackerRow;; ++row)
enum
{
QModelIndex index = myTrackerModel->index(row, 0);
ROW_TOTALS = 0, ROW_SEPARATOR, ROW_FIRST_TRACKER
};
if (!index.isValid())
{
break;
}
oldHosts << index.data(TrackerRole).toString();
}
// pull the new stats from the torrent model...
QSet<QString> newHosts;
QMap<QString, int> torrentsPerHost;
for (int row = 0;; ++row)
auto torrentsPerHost = std::unordered_map<QString, int>{};
for (auto const& tor : myTorrents.torrents())
{
QModelIndex index = myTorrents.index(row, 0);
if (!index.isValid())
for (auto const& displayName : tor->trackerDisplayNames())
{
break;
}
Torrent const* tor = index.data(TorrentModel::TorrentRole).value<Torrent const*>();
QSet<QString> torrentNames;
for (QString const& host : tor->hosts())
{
newHosts.insert(host);
torrentNames.insert(readableHostName(host));
}
for (QString const& name : torrentNames)
{
++torrentsPerHost[name];
++torrentsPerHost[displayName];
}
}
// update the "All" row
myTrackerModel->setData(myTrackerModel->index(0, 0), myTorrents.rowCount(), FilterBarComboBox::CountRole);
myTrackerModel->setData(myTrackerModel->index(0, 0), getCountString(myTorrents.rowCount()),
FilterBarComboBox::CountStringRole);
auto const num_trackers = torrentsPerHost.size();
auto item = myTrackerModel->item(ROW_TOTALS);
item->setData(int(num_trackers), FilterBarComboBox::CountRole);
item->setData(getCountString(num_trackers), FilterBarComboBox::CountStringRole);
// rows to update
for (QString const& host : oldHosts & newHosts)
{
QString const name = readableHostName(host);
QStandardItem* row = myTrackerModel->findItems(name).front();
int const count = torrentsPerHost[name];
row->setData(count, FilterBarComboBox::CountRole);
row->setData(getCountString(count), FilterBarComboBox::CountStringRole);
row->setData(QIcon(favicons.findFromHost(host)), Qt::DecorationRole);
}
// rows to remove
for (QString const& host : oldHosts - newHosts)
{
QString const name = readableHostName(host);
QStandardItem* item = myTrackerModel->findItems(name).front();
if (!item->data(TrackerRole).toString().isEmpty()) // don't remove "All"
auto updateTrackerItem = [](QStandardItem* i, auto const& it)
{
myTrackerModel->removeRows(item->row(), 1);
}
}
auto const& displayName = it->first;
auto const& count = it->second;
auto const icon = qApp->faviconCache().find(FaviconCache::getKey(displayName));
i->setData(displayName, Qt::DisplayRole);
i->setData(displayName, TrackerRole);
i->setData(getCountString(count), FilterBarComboBox::CountStringRole);
i->setData(icon, Qt::DecorationRole);
i->setData(int(count), FilterBarComboBox::CountRole);
return i;
};
// rows to add
auto newTrackers = std::map<QString, int>(torrentsPerHost.begin(), torrentsPerHost.end());
auto old_it = myTrackerCounts.cbegin();
auto new_it = newTrackers.cbegin();
auto const old_end = myTrackerCounts.cend();
auto const new_end = newTrackers.cend();
bool anyAdded = false;
int row = ROW_FIRST_TRACKER;
for (QString const& host : newHosts - oldHosts)
while ((old_it != old_end) || (new_it != new_end))
{
QString const name = readableHostName(host);
if (!myTrackerModel->findItems(name).isEmpty())
if ((old_it == old_end) || ((new_it != new_end) && (old_it->first > new_it->first)))
{
continue;
myTrackerModel->insertRow(row, updateTrackerItem(new QStandardItem(1), new_it));
anyAdded = true;
++new_it;
++row;
}
// find the sorted position to add this row
int i = firstTrackerRow;
for (int n = myTrackerModel->rowCount(); i < n; ++i)
else if ((new_it == new_end) || ((old_it != old_end) && (old_it->first < new_it->first)))
{
QString const rowName = myTrackerModel->index(i, 0).data(Qt::DisplayRole).toString();
if (rowName >= name)
{
break;
}
myTrackerModel->removeRow(row);
++old_it;
}
else // update
{
updateTrackerItem(myTrackerModel->item(row), new_it);
++old_it;
++new_it;
++row;
}
// add the row
QStandardItem* row = new QStandardItem(favicons.findFromHost(host), name);
int const count = torrentsPerHost[host];
row->setData(count, FilterBarComboBox::CountRole);
row->setData(getCountString(count), FilterBarComboBox::CountStringRole);
row->setData(QIcon(favicons.findFromHost(host)), Qt::DecorationRole);
row->setData(host, TrackerRole);
myTrackerModel->insertRow(i, row);
anyAdded = true;
}
if (anyAdded) // the one added might match our filter...
{
refreshPref(Prefs::FILTER_TRACKERS);
}
myTrackerCounts.swap(newTrackers);
}
FilterBarComboBox* FilterBar::createTrackerCombo(QStandardItemModel* model)
@ -294,10 +240,7 @@ FilterBar::FilterBar(Prefs& prefs, TorrentModel const& torrents, TorrentFilter c
myIsBootstrapping = false;
// initialize our state
QList<int> initKeys;
initKeys << Prefs::FILTER_MODE << Prefs::FILTER_TRACKERS;
for (int const key : initKeys)
for (int const key : { Prefs::FILTER_MODE, Prefs::FILTER_TRACKERS })
{
refreshPref(key);
}
@ -338,10 +281,8 @@ void FilterBar::refreshPref(int key)
case Prefs::FILTER_TRACKERS:
{
QString const tracker = myPrefs.getString(key);
QString const name = readableHostName(tracker);
QList<QStandardItem*> rows = myTrackerModel->findItems(name);
auto const displayName = myPrefs.getString(key);
auto rows = myTrackerModel->findItems(displayName);
if (!rows.isEmpty())
{
myTrackerCombo->setCurrentIndex(rows.front()->row());
@ -435,8 +376,3 @@ void FilterBar::recount()
refreshTrackers();
}
QString FilterBar::getCountString(int n) const
{
return QString::fromLatin1("%L1").arg(n);
}

View File

@ -8,6 +8,8 @@
#pragma once
#include <unordered_map>
#include <QWidget>
class QLabel;
@ -35,7 +37,6 @@ private:
FilterBarComboBox* createTrackerCombo(QStandardItemModel*);
FilterBarComboBox* createActivityCombo();
void refreshTrackers();
QString getCountString(int n) const;
private slots:
void recountSoon();
@ -57,4 +58,5 @@ private:
QTimer* myRecountTimer;
bool myIsBootstrapping;
QLineEdit* myLineEdit;
std::map<QString, int> myTrackerCounts;
};

View File

@ -89,7 +89,7 @@ QSize FilterBarComboBox::calculateSize(QSize const& textSize, QSize const& count
void FilterBarComboBox::paintEvent(QPaintEvent* e)
{
Q_UNUSED(e);
Q_UNUSED(e)
QStylePainter painter(this);
painter.setPen(palette().color(QPalette::Text));

View File

@ -28,12 +28,12 @@ public:
int currentCount() const;
// QWidget
virtual QSize minimumSizeHint() const;
virtual QSize sizeHint() const;
QSize minimumSizeHint() const override;
QSize sizeHint() const override;
protected:
// QWidget
virtual void paintEvent(QPaintEvent* e);
void paintEvent(QPaintEvent* e) override;
private:
QSize calculateSize(QSize const& textSize, QSize const& countSize) const;

View File

@ -25,8 +25,8 @@ public:
protected:
// QAbstractItemDelegate
virtual void paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const;
virtual QSize sizeHint(QStyleOptionViewItem const&, QModelIndex const&) const;
void paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const override;
QSize sizeHint(QStyleOptionViewItem const&, QModelIndex const&) const override;
private:
QComboBox* const myCombo;

View File

@ -18,9 +18,9 @@ public:
IconToolButton(QWidget* parent = nullptr);
// QWidget
virtual QSize sizeHint() const;
QSize sizeHint() const override;
protected:
// QWidget
virtual void paintEvent(QPaintEvent* event);
void paintEvent(QPaintEvent* event) override;
};

View File

@ -8,14 +8,14 @@
#include <cassert>
#include <QtGui>
#include <QCheckBox>
#include <QFileDialog>
#include <QIcon>
#include <QLabel>
#include <QMessageBox>
#include <QPainter>
#include <QProxyStyle>
#include <QLabel>
#include <QFileDialog>
#include <QMessageBox>
#include <QtGui>
#include <libtransmission/transmission.h>
#include <libtransmission/version.h>
@ -330,8 +330,9 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
refreshPref(key);
}
auto refreshStatusSoon = [this]() { refreshSoon(REFRESH_STATUS_BAR); };
connect(&mySession, SIGNAL(sourceChanged()), this, SLOT(onSessionSourceChanged()));
connect(&mySession, SIGNAL(statsUpdated()), this, SLOT(refreshStatusBar()));
connect(&mySession, &Session::statsUpdated, refreshStatusSoon);
connect(&mySession, SIGNAL(dataReadProgress()), this, SLOT(dataReadProgress()));
connect(&mySession, SIGNAL(dataSendProgress()), this, SLOT(dataSendProgress()));
connect(&mySession, SIGNAL(httpAuthenticationRequired()), this, SLOT(wrongAuthentication()));
@ -518,7 +519,7 @@ void MainWindow::setSortAscendingPref(bool b)
void MainWindow::showEvent(QShowEvent* event)
{
Q_UNUSED(event);
Q_UNUSED(event)
ui.action_ShowMainWindow->setChecked(true);
}
@ -529,7 +530,7 @@ void MainWindow::showEvent(QShowEvent* event)
void MainWindow::hideEvent(QHideEvent* event)
{
Q_UNUSED(event);
Q_UNUSED(event)
if (!isVisible())
{
@ -610,7 +611,7 @@ static void openSelect(QString const& path)
void MainWindow::openFolder()
{
QSet<int> const selectedTorrents = getSelectedTorrents();
auto const selectedTorrents = getSelectedTorrents();
if (selectedTorrents.size() != 1)
{
@ -692,10 +693,26 @@ void MainWindow::refreshSoon(int fields)
if (!myRefreshTimer.isActive())
{
myRefreshTimer.setSingleShot(true);
myRefreshTimer.start(100);
myRefreshTimer.start(200);
}
}
MainWindow::TransferStats MainWindow::getTransferStats() const
{
TransferStats stats;
for (auto const& tor : myModel.torrents())
{
stats.speedUp += tor->uploadSpeed();
stats.speedDown += tor->downloadSpeed();
stats.peersSending += tor->webseedsWeAreDownloadingFrom();
stats.peersSending += tor->peersWeAreDownloadingFrom();
stats.peersReceiving += tor->peersWeAreUploadingTo();
}
return stats;
}
void MainWindow::onRefreshTimer()
{
int fields = 0;
@ -706,14 +723,19 @@ void MainWindow::onRefreshTimer()
refreshTitle();
}
if (fields & REFRESH_STATUS_BAR)
if (fields & (REFRESH_TRAY_ICON | REFRESH_STATUS_BAR))
{
refreshStatusBar();
}
auto const stats = getTransferStats();
if (fields & REFRESH_TRAY_ICON)
{
refreshTrayIcon();
if (fields & REFRESH_TRAY_ICON)
{
refreshTrayIcon(stats);
}
if (fields & REFRESH_STATUS_BAR)
{
refreshStatusBar(stats);
}
}
if (fields & REFRESH_TORRENT_VIEW_HEADER)
@ -742,48 +764,37 @@ void MainWindow::refreshTitle()
setWindowTitle(title);
}
void MainWindow::refreshTrayIcon()
void MainWindow::refreshTrayIcon(TransferStats const& stats)
{
Speed upSpeed;
Speed downSpeed;
size_t upCount;
size_t downCount;
QString tip;
myModel.getTransferSpeed(upSpeed, upCount, downSpeed, downCount);
if (myNetworkError)
{
tip = tr("Network Error");
}
else if (upCount == 0 && downCount == 0)
else if (stats.peersSending == 0 && stats.peersReceiving == 0)
{
tip = tr("Idle");
}
else if (downCount != 0)
else if (stats.peersSending != 0)
{
tip = Formatter::downloadSpeedToString(downSpeed) + QLatin1String(" ") + Formatter::uploadSpeedToString(upSpeed);
tip = Formatter::downloadSpeedToString(stats.speedDown) + QLatin1String(" ") + Formatter::uploadSpeedToString(
stats.speedUp);
}
else if (upCount != 0)
else if (stats.peersReceiving != 0)
{
tip = Formatter::uploadSpeedToString(upSpeed);
tip = Formatter::uploadSpeedToString(stats.speedUp);
}
myTrayIcon.setToolTip(tip);
}
void MainWindow::refreshStatusBar()
void MainWindow::refreshStatusBar(TransferStats const& stats)
{
Speed upSpeed;
Speed downSpeed;
size_t upCount;
size_t downCount;
myModel.getTransferSpeed(upSpeed, upCount, downSpeed, downCount);
ui.uploadSpeedLabel->setText(Formatter::uploadSpeedToString(upSpeed));
ui.uploadSpeedLabel->setVisible(downCount || upCount);
ui.downloadSpeedLabel->setText(Formatter::downloadSpeedToString(downSpeed));
ui.downloadSpeedLabel->setVisible(downCount);
ui.uploadSpeedLabel->setText(Formatter::uploadSpeedToString(stats.speedUp));
ui.uploadSpeedLabel->setVisible(stats.peersSending || stats.peersReceiving);
ui.downloadSpeedLabel->setText(Formatter::downloadSpeedToString(stats.speedDown));
ui.downloadSpeedLabel->setVisible(stats.peersSending);
ui.networkLabel->setVisible(!mySession.isServer());
@ -833,7 +844,6 @@ void MainWindow::refreshTorrentViewHeader()
void MainWindow::refreshActionSensitivity()
{
int paused(0);
int queued(0);
int selected(0);
int selectedAndCanAnnounce(0);
int selectedAndPaused(0);
@ -848,19 +858,12 @@ void MainWindow::refreshActionSensitivity()
for (int row = 0; row < rowCount; ++row)
{
QModelIndex const modelIndex(model->index(row, 0));
assert(model == modelIndex.model());
Torrent const* tor(model->data(modelIndex, TorrentModel::TorrentRole).value<Torrent const*>());
auto const& tor = model->data(modelIndex, TorrentModel::TorrentRole).value<Torrent const*>();
if (tor != nullptr)
{
bool const isSelected(selectionModel->isSelected(modelIndex));
bool const isPaused(tor->isPaused());
bool const isQueued(tor->isQueued());
if (isQueued)
{
++queued;
}
if (isPaused)
{
@ -876,7 +879,7 @@ void MainWindow::refreshActionSensitivity()
++selectedAndPaused;
}
if (isQueued)
if (tor->isQueued())
{
++selectedAndQueued;
}
@ -936,9 +939,9 @@ void MainWindow::clearSelection()
ui.action_DeselectAll->trigger();
}
QSet<int> MainWindow::getSelectedTorrents(bool withMetadataOnly) const
torrent_ids_t MainWindow::getSelectedTorrents(bool withMetadataOnly) const
{
QSet<int> ids;
torrent_ids_t ids;
for (QModelIndex const& index : ui.listView->selectionModel()->selectedRows())
{
@ -1120,7 +1123,7 @@ void MainWindow::refreshPref(int key)
action->setChecked(str == action->property(STATS_MODE_KEY).toString());
}
refreshStatusBar();
refreshSoon(REFRESH_STATUS_BAR);
break;
case Prefs::SORT_REVERSED:
@ -1340,7 +1343,7 @@ void MainWindow::addTorrent(AddData const& addMe, bool showOptions)
void MainWindow::removeTorrents(bool const deleteFiles)
{
QSet<int> ids;
torrent_ids_t ids;
QMessageBox msgBox(this);
QString primary_text;
QString secondary_text;
@ -1364,7 +1367,7 @@ void MainWindow::removeTorrents(bool const deleteFiles)
}
}
if (ids.isEmpty())
if (ids.empty())
{
return;
}

View File

@ -13,13 +13,15 @@
#include <QMainWindow>
#include <QNetworkReply>
#include <QPointer>
#include <QSet>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QWidgetList>
#include "Filters.h"
#include "Speed.h"
#include "TorrentFilter.h"
#include "Typedefs.h"
#include "ui_MainWindow.h"
class QAction;
@ -84,15 +86,15 @@ public slots:
protected:
// QWidget
virtual void contextMenuEvent(QContextMenuEvent*);
virtual void dragEnterEvent(QDragEnterEvent*);
virtual void dropEvent(QDropEvent*);
void contextMenuEvent(QContextMenuEvent*) override;
void dragEnterEvent(QDragEnterEvent*) override;
void dropEvent(QDropEvent*) override;
private:
QIcon getStockIcon(QString const&, int fallback = -1);
QIcon addEmblem(QIcon icon, QStringList const& emblemNames);
QSet<int> getSelectedTorrents(bool withMetadataOnly = false) const;
torrent_ids_t getSelectedTorrents(bool withMetadataOnly = false) const;
void updateNetworkIcon();
QMenu* createOptionsMenu();
@ -103,8 +105,8 @@ private:
void addTorrent(AddData const& addMe, bool showOptions);
// QWidget
virtual void hideEvent(QHideEvent* event);
virtual void showEvent(QShowEvent* event);
void hideEvent(QHideEvent* event) override;
void showEvent(QShowEvent* event) override;
private slots:
void addTorrents(QStringList const& filenames);
@ -130,7 +132,6 @@ private slots:
void openURL();
void refreshPref(int key);
void refreshSoon(int fields = ~0);
void refreshStatusBar();
void removeTorrents(bool const deleteFiles);
void setLocation();
void setSortAscendingPref(bool);
@ -176,6 +177,15 @@ private:
QAction* myAltSpeedAction;
QString myErrorMessage;
struct TransferStats
{
Speed speedUp;
Speed speedDown;
size_t peersSending = 0;
size_t peersReceiving = 0;
};
TransferStats getTransferStats() const;
enum
{
REFRESH_TITLE = (1 << 0),
@ -187,6 +197,7 @@ private:
int myRefreshFields = 0;
QTimer myRefreshTimer;
void refreshTitle();
void refreshTrayIcon();
void refreshTrayIcon(TransferStats const&);
void refreshStatusBar(TransferStats const&);
void refreshTorrentViewHeader();
};

View File

@ -33,8 +33,8 @@ public:
protected:
// QWidget
virtual void dragEnterEvent(QDragEnterEvent*);
virtual void dropEvent(QDropEvent*);
void dragEnterEvent(QDragEnterEvent*) override;
void dropEvent(QDropEvent*) override;
private:
QString getSource() const;

View File

@ -32,14 +32,14 @@ public:
QString const& path() const;
// QWidget
virtual QSize sizeHint() const;
QSize sizeHint() const override;
signals:
void pathChanged(QString const& path);
protected:
// QWidget
virtual void paintEvent(QPaintEvent* event);
void paintEvent(QPaintEvent* event) override;
private:
void updateAppearance();

View File

@ -433,7 +433,7 @@ void PrefsDialog::initNetworkTab()
void PrefsDialog::onBlocklistDialogDestroyed(QObject* o)
{
Q_UNUSED(o);
Q_UNUSED(o)
myBlocklistDialog = nullptr;
}

View File

@ -9,7 +9,6 @@
#pragma once
#include <QMap>
#include <QSet>
#include "BaseDialog.h"
#include "Prefs.h"

View File

@ -26,7 +26,7 @@ void RelocateDialog::onMoveToggled(bool b)
myMoveFlag = b;
}
RelocateDialog::RelocateDialog(Session& session, TorrentModel const& model, QSet<int> const& ids, QWidget* parent) :
RelocateDialog::RelocateDialog(Session& session, TorrentModel const& model, torrent_ids_t const& ids, QWidget* parent) :
BaseDialog(parent),
mySession(session),
myIds(ids)

View File

@ -8,9 +8,8 @@
#pragma once
#include <QSet>
#include "BaseDialog.h"
#include "Typedefs.h"
#include "ui_RelocateDialog.h"
@ -22,7 +21,7 @@ class RelocateDialog : public BaseDialog
Q_OBJECT
public:
RelocateDialog(Session&, TorrentModel const&, QSet<int> const& ids, QWidget* parent = nullptr);
RelocateDialog(Session&, TorrentModel const&, torrent_ids_t const& ids, QWidget* parent = nullptr);
virtual ~RelocateDialog()
{
@ -37,7 +36,7 @@ private slots:
private:
Session& mySession;
QSet<int> const myIds;
torrent_ids_t const myIds;
Ui::RelocateDialog ui;

View File

@ -204,7 +204,7 @@ QNetworkAccessManager* RpcClient::networkAccessManager()
void RpcClient::localSessionCallback(tr_session* s, tr_variant* response, void* vself)
{
Q_UNUSED(s);
Q_UNUSED(s)
RpcClient* self = static_cast<RpcClient*>(vself);

View File

@ -42,7 +42,7 @@ struct RpcResponse
QNetworkReply::NetworkError networkError = QNetworkReply::NoError;
};
Q_DECLARE_METATYPE(QFutureInterface<RpcResponse>);
Q_DECLARE_METATYPE(QFutureInterface<RpcResponse>)
// The response future -- the RPC engine returns one for each request made.
typedef QFuture<RpcResponse> RpcResponseFuture;

View File

@ -54,10 +54,10 @@ void addList(tr_variant* list, KeyList const& keys)
}
// If this object is passed as "ids" (compared by address), then recently active torrents are queried.
QSet<int> const recentlyActiveIds = QSet<int>() << -1;
auto const recentlyActiveIds = torrent_ids_t{ -1 };
// If this object is passed as "ids" (compared by being empty), then all torrents are queried.
QSet<int> const allIds;
auto const allIds = torrent_ids_t{};
} // namespace
@ -405,13 +405,13 @@ bool Session::isLocal() const
namespace
{
void addOptionalIds(tr_variant* args, QSet<int> const& ids)
void addOptionalIds(tr_variant* args, torrent_ids_t const& ids)
{
if (&ids == &recentlyActiveIds)
{
tr_variantDictAddStr(args, TR_KEY_ids, "recently-active");
}
else if (!ids.isEmpty())
else if (!ids.empty())
{
tr_variant* idList(tr_variantDictAddList(args, TR_KEY_ids, ids.size()));
@ -424,7 +424,7 @@ void addOptionalIds(tr_variant* args, QSet<int> const& ids)
} // namespace
void Session::torrentSet(QSet<int> const& ids, tr_quark const key, double value)
void Session::torrentSet(torrent_ids_t const& ids, tr_quark const key, double value)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -434,7 +434,7 @@ void Session::torrentSet(QSet<int> const& ids, tr_quark const key, double value)
exec(TR_KEY_torrent_set, &args);
}
void Session::torrentSet(QSet<int> const& ids, tr_quark const key, int value)
void Session::torrentSet(torrent_ids_t const& ids, tr_quark const key, int value)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -444,7 +444,7 @@ void Session::torrentSet(QSet<int> const& ids, tr_quark const key, int value)
exec(TR_KEY_torrent_set, &args);
}
void Session::torrentSet(QSet<int> const& ids, tr_quark const key, bool value)
void Session::torrentSet(torrent_ids_t const& ids, tr_quark const key, bool value)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -454,7 +454,7 @@ void Session::torrentSet(QSet<int> const& ids, tr_quark const key, bool value)
exec(TR_KEY_torrent_set, &args);
}
void Session::torrentSet(QSet<int> const& ids, tr_quark const key, QStringList const& value)
void Session::torrentSet(torrent_ids_t const& ids, tr_quark const key, QStringList const& value)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -469,7 +469,7 @@ void Session::torrentSet(QSet<int> const& ids, tr_quark const key, QStringList c
exec(TR_KEY_torrent_set, &args);
}
void Session::torrentSet(QSet<int> const& ids, tr_quark const key, QList<int> const& value)
void Session::torrentSet(torrent_ids_t const& ids, tr_quark const key, QList<int> const& value)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -484,7 +484,7 @@ void Session::torrentSet(QSet<int> const& ids, tr_quark const key, QList<int> co
exec(TR_KEY_torrent_set, &args);
}
void Session::torrentSet(QSet<int> const& ids, tr_quark const key, QPair<int, QString> const& value)
void Session::torrentSet(torrent_ids_t const& ids, tr_quark const key, QPair<int, QString> const& value)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -496,7 +496,7 @@ void Session::torrentSet(QSet<int> const& ids, tr_quark const key, QPair<int, QS
exec(TR_KEY_torrent_set, &args);
}
void Session::torrentSetLocation(QSet<int> const& ids, QString const& location, bool doMove)
void Session::torrentSetLocation(torrent_ids_t const& ids, QString const& location, bool doMove)
{
tr_variant args;
tr_variantInitDict(&args, 3);
@ -507,7 +507,7 @@ void Session::torrentSetLocation(QSet<int> const& ids, QString const& location,
exec(TR_KEY_torrent_set_location, &args);
}
void Session::torrentRenamePath(QSet<int> const& ids, QString const& oldpath, QString const& newname)
void Session::torrentRenamePath(torrent_ids_t const& ids, QString const& oldpath, QString const& newname)
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -536,20 +536,15 @@ void Session::torrentRenamePath(QSet<int> const& ids, QString const& oldpath, QS
d->show();
});
q->add([this](RpcResponse const& r)
q->add([this, ids](RpcResponse const& /*r*/)
{
int64_t id = 0;
if (tr_variantDictFindInt(r.args.get(), TR_KEY_id, &id) && id != 0)
{
refreshTorrents(QSet<int>() << id, KeyList() << TR_KEY_fileStats << TR_KEY_files << TR_KEY_id << TR_KEY_name);
}
refreshTorrents(ids, { TR_KEY_fileStats, TR_KEY_files, TR_KEY_id, TR_KEY_name });
});
q->run();
}
void Session::refreshTorrents(QSet<int> const& ids, KeyList const& keys)
void Session::refreshTorrents(torrent_ids_t const& ids, KeyList const& keys)
{
tr_variant args;
tr_variantInitDict(&args, 3);
@ -584,17 +579,17 @@ void Session::refreshTorrents(QSet<int> const& ids, KeyList const& keys)
q->run();
}
void Session::refreshDetailInfo(QSet<int> const& ids)
void Session::refreshDetailInfo(torrent_ids_t const& ids)
{
refreshTorrents(ids, Torrent::detailInfoKeys);
}
void Session::refreshExtraStats(QSet<int> const& ids)
void Session::refreshExtraStats(torrent_ids_t const& ids)
{
refreshTorrents(ids, Torrent::mainStatKeys + Torrent::detailStatKeys);
}
void Session::sendTorrentRequest(char const* request, QSet<int> const& ids)
void Session::sendTorrentRequest(char const* request, torrent_ids_t const& ids)
{
tr_variant args;
tr_variantInitDict(&args, 1);
@ -615,37 +610,37 @@ void Session::sendTorrentRequest(char const* request, QSet<int> const& ids)
q->run();
}
void Session::pauseTorrents(QSet<int> const& ids)
void Session::pauseTorrents(torrent_ids_t const& ids)
{
sendTorrentRequest("torrent-stop", ids);
}
void Session::startTorrents(QSet<int> const& ids)
void Session::startTorrents(torrent_ids_t const& ids)
{
sendTorrentRequest("torrent-start", ids);
}
void Session::startTorrentsNow(QSet<int> const& ids)
void Session::startTorrentsNow(torrent_ids_t const& ids)
{
sendTorrentRequest("torrent-start-now", ids);
}
void Session::queueMoveTop(QSet<int> const& ids)
void Session::queueMoveTop(torrent_ids_t const& ids)
{
sendTorrentRequest("queue-move-top", ids);
}
void Session::queueMoveUp(QSet<int> const& ids)
void Session::queueMoveUp(torrent_ids_t const& ids)
{
sendTorrentRequest("queue-move-up", ids);
}
void Session::queueMoveDown(QSet<int> const& ids)
void Session::queueMoveDown(torrent_ids_t const& ids)
{
sendTorrentRequest("queue-move-down", ids);
}
void Session::queueMoveBottom(QSet<int> const& ids)
void Session::queueMoveBottom(torrent_ids_t const& ids)
{
sendTorrentRequest("queue-move-bottom", ids);
}
@ -660,7 +655,7 @@ void Session::refreshAllTorrents()
refreshTorrents(allIds, Torrent::mainStatKeys);
}
void Session::initTorrents(QSet<int> const& ids)
void Session::initTorrents(torrent_ids_t const& ids)
{
refreshTorrents(ids, Torrent::allMainKeys);
}
@ -1047,9 +1042,9 @@ void Session::addNewlyCreatedTorrent(QString const& filename, QString const& loc
exec("torrent-add", &args);
}
void Session::removeTorrents(QSet<int> const& ids, bool deleteFiles)
void Session::removeTorrents(torrent_ids_t const& ids, bool deleteFiles)
{
if (!ids.isEmpty())
if (!ids.empty())
{
tr_variant args;
tr_variantInitDict(&args, 2);
@ -1060,9 +1055,9 @@ void Session::removeTorrents(QSet<int> const& ids, bool deleteFiles)
}
}
void Session::verifyTorrents(QSet<int> const& ids)
void Session::verifyTorrents(torrent_ids_t const& ids)
{
if (!ids.isEmpty())
if (!ids.empty())
{
tr_variant args;
tr_variantInitDict(&args, 1);
@ -1072,9 +1067,9 @@ void Session::verifyTorrents(QSet<int> const& ids)
}
}
void Session::reannounceTorrents(QSet<int> const& ids)
void Session::reannounceTorrents(torrent_ids_t const& ids)
{
if (!ids.isEmpty())
if (!ids.empty())
{
tr_variant args;
tr_variantInitDict(&args, 1);

View File

@ -9,7 +9,6 @@
#pragma once
#include <QObject>
#include <QSet>
#include <QString>
#include <QStringList>
@ -18,6 +17,7 @@
#include "RpcClient.h"
#include "Torrent.h"
#include "Typedefs.h"
class AddData;
class Prefs;
@ -77,37 +77,37 @@ public:
RpcResponseFuture exec(tr_quark method, tr_variant* args);
RpcResponseFuture exec(char const* method, tr_variant* args);
void torrentSet(QSet<int> const& ids, tr_quark const key, bool val);
void torrentSet(QSet<int> const& ids, tr_quark const key, int val);
void torrentSet(QSet<int> const& ids, tr_quark const key, double val);
void torrentSet(QSet<int> const& ids, tr_quark const key, QList<int> const& val);
void torrentSet(QSet<int> const& ids, tr_quark const key, QStringList const& val);
void torrentSet(QSet<int> const& ids, tr_quark const key, QPair<int, QString> const& val);
void torrentSetLocation(QSet<int> const& ids, QString const& path, bool doMove);
void torrentRenamePath(QSet<int> const& ids, QString const& oldpath, QString const& newname);
void torrentSet(torrent_ids_t const& ids, tr_quark const key, bool val);
void torrentSet(torrent_ids_t const& ids, tr_quark const key, int val);
void torrentSet(torrent_ids_t const& ids, tr_quark const key, double val);
void torrentSet(torrent_ids_t const& ids, tr_quark const key, QList<int> const& val);
void torrentSet(torrent_ids_t const& ids, tr_quark const key, QStringList const& val);
void torrentSet(torrent_ids_t const& ids, tr_quark const key, QPair<int, QString> const& val);
void torrentSetLocation(torrent_ids_t const& ids, QString const& path, bool doMove);
void torrentRenamePath(torrent_ids_t const& ids, QString const& oldpath, QString const& newname);
void addTorrent(AddData const& addme, tr_variant* top, bool trashOriginal);
void initTorrents(QSet<int> const& ids = QSet<int>());
void pauseTorrents(QSet<int> const& torrentIds = QSet<int>());
void startTorrents(QSet<int> const& torrentIds = QSet<int>());
void startTorrentsNow(QSet<int> const& torrentIds = QSet<int>());
void refreshDetailInfo(QSet<int> const& torrentIds);
void initTorrents(torrent_ids_t const& ids = {});
void pauseTorrents(torrent_ids_t const& torrentIds = {});
void startTorrents(torrent_ids_t const& torrentIds = {});
void startTorrentsNow(torrent_ids_t const& torrentIds = {});
void refreshDetailInfo(torrent_ids_t const& torrentIds);
void refreshActiveTorrents();
void refreshAllTorrents();
void addNewlyCreatedTorrent(QString const& filename, QString const& localPath);
void verifyTorrents(QSet<int> const& torrentIds);
void reannounceTorrents(QSet<int> const& torrentIds);
void refreshExtraStats(QSet<int> const& ids);
void verifyTorrents(torrent_ids_t const& torrentIds);
void reannounceTorrents(torrent_ids_t const& torrentIds);
void refreshExtraStats(torrent_ids_t const& ids);
public slots:
void addTorrent(AddData const& addme);
void launchWebInterface();
void queueMoveBottom(QSet<int> const& torrentIds = QSet<int>());
void queueMoveDown(QSet<int> const& torrentIds = QSet<int>());
void queueMoveTop(QSet<int> const& torrentIds = QSet<int>());
void queueMoveUp(QSet<int> const& torrentIds = QSet<int>());
void queueMoveBottom(torrent_ids_t const& torrentIds = {});
void queueMoveDown(torrent_ids_t const& torrentIds = {});
void queueMoveTop(torrent_ids_t const& torrentIds = {});
void queueMoveUp(torrent_ids_t const& torrentIds = {});
void refreshSessionInfo();
void refreshSessionStats();
void removeTorrents(QSet<int> const& torrentIds, bool deleteFiles = false);
void removeTorrents(torrent_ids_t const& torrentIds, bool deleteFiles = false);
void updatePref(int key);
signals:
@ -131,8 +131,8 @@ private:
void sessionSet(tr_quark const key, QVariant const& variant);
void pumpRequests();
void sendTorrentRequest(char const* request, QSet<int> const& torrentIds);
void refreshTorrents(QSet<int> const& torrentIds, Torrent::KeyList const& keys);
void sendTorrentRequest(char const* request, torrent_ids_t const& torrentIds);
void refreshTorrents(torrent_ids_t const& torrentIds, Torrent::KeyList const& keys);
static void updateStats(tr_variant* d, tr_session_stats* stats);

View File

@ -24,13 +24,9 @@ class SessionDialog : public BaseDialog
public:
SessionDialog(Session& session, Prefs& prefs, QWidget* parent = nullptr);
virtual ~SessionDialog()
{
}
public slots:
// QDialog
virtual void accept();
void accept() override;
private slots:
void resensitize();

View File

@ -53,5 +53,5 @@ public:
protected:
// QWidget
virtual void paintEvent(QPaintEvent* paintEvent);
void paintEvent(QPaintEvent* paintEvent) override;
};

View File

@ -22,10 +22,10 @@ class StatsDialog : public BaseDialog
public:
StatsDialog(Session&, QWidget* parent = nullptr);
~StatsDialog();
~StatsDialog() override;
// QWidget
virtual void setVisible(bool visible);
void setVisible(bool visible) override;
private slots:
void updateStats();

View File

@ -75,8 +75,6 @@ Torrent::Property Torrent::myProperties[] =
{ DOWNLOADED_EVER, TR_KEY_downloadedEver, QVariant::ULongLong },
{ UPLOADED_EVER, TR_KEY_uploadedEver, QVariant::ULongLong },
{ FAILED_EVER, TR_KEY_corruptEver, QVariant::ULongLong },
{ TRACKERS, TR_KEY_trackers, QVariant::StringList },
{ HOSTS, TR_KEY_NONE, QVariant::StringList },
{ TRACKERSTATS, TR_KEY_trackerStats, CustomVariantType::TrackerStatsList },
{ MIME_ICON, TR_KEY_NONE, QVariant::Icon },
{ SEED_RATIO_LIMIT, TR_KEY_seedRatioLimit, QVariant::Double },
@ -406,7 +404,7 @@ bool Torrent::hasFileSubstring(QString const& substr) const
bool Torrent::hasTrackerSubstring(QString const& substr) const
{
for (QString const& s : myValues[TRACKERS].toStringList())
for (auto const& s : trackers())
{
if (s.contains(substr, Qt::CaseInsensitive))
{
@ -505,7 +503,7 @@ int Torrent::compareETA(Torrent const& that) const
int Torrent::compareTracker(Torrent const& that) const
{
Q_UNUSED(that);
Q_UNUSED(that)
// FIXME
return 0;
@ -657,7 +655,6 @@ bool Torrent::update(tr_quark const* keys, tr_variant** values, size_t n)
break;
}
case QVariant::StringList:
case CustomVariantType::PeerList:
// handled below
break;
@ -756,21 +753,21 @@ bool Torrent::update(tr_quark const* keys, tr_variant** values, size_t n)
}
// update the trackers
if (myValues[TRACKERS] != trackers)
if (trackers_ != trackers)
{
QStringList hosts;
QStringList displayNames;
displayNames.reserve(trackers.size());
for (auto const& tracker : trackers)
{
auto const url = QUrl(tracker);
qApp->faviconCache().add(url);
hosts.append(FaviconCache::getHost(url));
auto const key = qApp->faviconCache().add(url);
displayNames.append(FaviconCache::getDisplayName(key));
}
hosts.removeDuplicates();
hosts.removeOne(QString());
displayNames.removeDuplicates();
myValues[TRACKERS].setValue(trackers);
myValues[HOSTS].setValue(hosts);
trackers_.swap(trackers);
trackerDisplayNames_.swap(displayNames);
changed = true;
}
}
@ -794,7 +791,6 @@ bool Torrent::update(tr_quark const* keys, tr_variant** values, size_t n)
if (tr_variantDictFindStr(child, TR_KEY_announce, &str, &len))
{
trackerStat.announce = QString::fromUtf8(str, len);
qApp->faviconCache().add(QUrl(trackerStat.announce));
}
if (tr_variantDictFindInt(child, TR_KEY_announceState, &i))

View File

@ -158,8 +158,6 @@ public:
DOWNLOADED_EVER,
UPLOADED_EVER,
FAILED_EVER,
TRACKERS,
HOSTS,
TRACKERSTATS,
MIME_ICON,
SEED_RATIO_LIMIT,
@ -188,8 +186,6 @@ public:
public:
Torrent(Prefs const&, int id);
virtual ~Torrent() = default;
;
int getBandwidthPriority() const
{
@ -235,7 +231,7 @@ public:
bool hasError() const
{
return !getError().isEmpty();
return getInt(ERROR) != TR_STAT_OK;
}
bool isDone() const
@ -493,14 +489,14 @@ public:
return myValues[TRACKERSTATS].value<TrackerStatsList>();
}
QStringList trackers() const
QStringList const& trackers() const
{
return myValues[TRACKERS].value<QStringList>();
return trackers_;
}
QStringList hosts() const
QStringList const& trackerDisplayNames() const
{
return myValues[HOSTS].value<QStringList>();
return trackerDisplayNames_;
}
PeerList peers() const
@ -619,6 +615,9 @@ private:
bool setSize(int key, qulonglong);
bool setTime(int key, time_t);
QStringList trackers_;
QStringList trackerDisplayNames_;
char const* getMimeTypeString() const;
void updateMimeIcon();

View File

@ -155,7 +155,7 @@ TorrentDelegate::~TorrentDelegate()
QSize TorrentDelegate::margin(QStyle const& style) const
{
Q_UNUSED(style);
Q_UNUSED(style)
return QSize(4, 4);
}
@ -420,6 +420,23 @@ QSize TorrentDelegate::sizeHint(QStyleOptionViewItem const& option, QModelIndex
return QSize(option.rect.width(), *myHeightHint);
}
QIcon& TorrentDelegate::getWarningEmblem() const
{
auto& icon = myWarningEmblem;
if (icon.isNull())
{
icon = QIcon::fromTheme(QLatin1String("emblem-important"));
}
if (icon.isNull())
{
icon = qApp->style()->standardIcon(QStyle::SP_MessageBoxWarning);
}
return icon;
}
void TorrentDelegate::paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const
{
Torrent const* tor(index.data(TorrentModel::TorrentRole).value<Torrent const*>());
@ -531,8 +548,7 @@ void TorrentDelegate::drawTorrent(QPainter* painter, QStyleOptionViewItem const&
progressBarState |= QStyle::State_Small;
QIcon::Mode const emblemIm = isItemSelected ? QIcon::Selected : QIcon::Normal;
QIcon const emblemIcon = tor.hasError() ? QIcon::fromTheme(QLatin1String("emblem-important"),
style->standardIcon(QStyle::SP_MessageBoxWarning)) : QIcon();
QIcon const emblemIcon = tor.hasError() ? getWarningEmblem() : QIcon();
// layout
QSize const m(margin(*style));

View File

@ -26,12 +26,13 @@ public:
virtual ~TorrentDelegate();
// QAbstractItemDelegate
virtual QSize sizeHint(QStyleOptionViewItem const& option, QModelIndex const& index) const;
virtual void paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const;
QSize sizeHint(QStyleOptionViewItem const& option, QModelIndex const& index) const override;
void paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const override;
protected:
QSize margin(QStyle const& style) const;
void setProgressBarPercentDone(QStyleOptionViewItem const& option, Torrent const&) const;
QIcon& getWarningEmblem() const;
// Our own overridables
virtual QSize sizeHint(QStyleOptionViewItem const&, Torrent const&) const;
@ -55,4 +56,5 @@ protected:
private:
mutable std::optional<int> myHeightHint;
mutable QFont myHeightFont;
mutable QIcon myWarningEmblem;
};

View File

@ -221,8 +221,7 @@ void TorrentDelegateMin::drawTorrent(QPainter* painter, QStyleOptionViewItem con
progressBarState |= QStyle::State_Small;
QIcon::Mode const emblemIm = isItemSelected ? QIcon::Selected : QIcon::Normal;
QIcon const emblemIcon = tor.hasError() ? QIcon::fromTheme(QLatin1String("emblem-important"),
style->standardIcon(QStyle::SP_MessageBoxWarning)) : QIcon();
QIcon const emblemIcon = tor.hasError() ? getWarningEmblem() : QIcon();
// layout
QSize const m(margin(*style));

View File

@ -20,12 +20,8 @@ public:
{
}
virtual ~TorrentDelegateMin()
{
}
protected:
// TorrentDelegate
virtual QSize sizeHint(QStyleOptionViewItem const&, Torrent const&) const;
virtual void drawTorrent(QPainter* painter, QStyleOptionViewItem const& option, Torrent const&) const;
QSize sizeHint(QStyleOptionViewItem const&, Torrent const&) const override;
void drawTorrent(QPainter* painter, QStyleOptionViewItem const& option, Torrent const&) const override;
};

View File

@ -322,18 +322,9 @@ void TorrentFilter::countTorrentsPerMode(int* setmeCounts) const
{
std::fill_n(setmeCounts, static_cast<std::size_t>(FilterMode::NUM_MODES), 0);
for (int row(0);; ++row)
for (auto const& tor : dynamic_cast<TorrentModel*>(sourceModel())->torrents())
{
QModelIndex index(sourceModel()->index(row, 0));
if (!index.isValid())
{
break;
}
Torrent const* tor(index.data(TorrentModel::TorrentRole).value<Torrent const*>());
for (int mode(0); mode < FilterMode::NUM_MODES; ++mode)
for (int mode = 0; mode < FilterMode::NUM_MODES; ++mode)
{
if (activityFilterAcceptsTorrent(tor, mode))
{

View File

@ -39,8 +39,8 @@ public:
protected:
// QSortFilterProxyModel
virtual bool filterAcceptsRow(int, QModelIndex const&) const;
virtual bool lessThan(QModelIndex const&, QModelIndex const&) const;
bool filterAcceptsRow(int, QModelIndex const&) const override;
bool lessThan(QModelIndex const&, QModelIndex const&) const override;
private:
bool activityFilterAcceptsTorrent(Torrent const* tor, FilterMode const& mode) const;

View File

@ -44,9 +44,9 @@ struct TorrentIdLessThan
};
template<typename Iter>
QSet<int> getIds(Iter it, Iter end)
auto getIds(Iter it, Iter end)
{
QSet<int> ids;
torrent_ids_t ids;
for ( ; it != end; ++it)
{
@ -82,7 +82,7 @@ void TorrentModel::clear()
int TorrentModel::rowCount(QModelIndex const& parent) const
{
Q_UNUSED(parent);
Q_UNUSED(parent)
return myTorrents.size();
}
@ -124,10 +124,11 @@ QVariant TorrentModel::data(QModelIndex const& index, int role) const
void TorrentModel::removeTorrents(tr_variant* list)
{
torrents_t torrents;
torrents.reserve(tr_variantListSize(list));
int i = 0;
tr_variant* child;
QSet<Torrent*> torrents;
while ((child = tr_variantListChild(list, i++)) != nullptr)
{
int64_t id;
@ -140,11 +141,11 @@ void TorrentModel::removeTorrents(tr_variant* list)
if (torrent != nullptr)
{
torrents.insert(torrent);
torrents.push_back(torrent);
}
}
if (!torrents.isEmpty())
if (!torrents.empty())
{
rowsRemove(torrents);
}
@ -152,13 +153,13 @@ void TorrentModel::removeTorrents(tr_variant* list)
void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
{
auto const old = QSet<Torrent*>::fromList(myTorrents.toList());
auto added = QSet<int>{};
auto changed = QSet<int>{};
auto completed = QSet<int>{};
auto const old = isCompleteList ? myTorrents : torrents_t{};
auto added = torrent_ids_t{};
auto changed = torrent_ids_t{};
auto completed = torrent_ids_t{};
auto instantiated = torrents_t{};
auto needinfo = QSet<int>{};
auto processed = QSet<Torrent*>{};
auto needinfo = torrent_ids_t{};
auto processed = torrents_t{};
auto const now = time(nullptr);
auto const recently_added = [now](auto const& tor)
@ -179,6 +180,7 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
char const* str;
size_t len;
size_t i = 0;
keys.reserve(tr_variantListSize(firstChild));
while (tr_variantGetStr(tr_variantListChild(firstChild, i++), &str, &len))
{
keys.push_back(tr_quark_new(str, len));
@ -210,6 +212,7 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
values.reserve(keys.size());
size_t tor_index = table ? 1 : 0;
tr_variant* v;
processed.reserve(tr_variantListSize(torrents));
while ((v = tr_variantListChild(torrents, tor_index++)))
{
// Build an array of values
@ -245,11 +248,13 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
Torrent* tor = getTorrentFromId(id);
std::optional<uint64_t> leftUntilDone;
bool is_new = false;
if (tor == nullptr)
{
tor = new Torrent(myPrefs, id);
instantiated.push_back(tor);
is_new = true;
}
else
{
@ -261,12 +266,12 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
changed.insert(id);
}
if (!tor->hasName() && !old.contains(tor))
if (is_new && !tor->hasName())
{
needinfo.insert(id);
}
if (recently_added(tor) && tor->hasName() && !myAlreadyAdded.contains(id))
if (recently_added(tor) && tor->hasName() && !myAlreadyAdded.count(id))
{
added.insert(id);
myAlreadyAdded.insert(id);
@ -277,39 +282,39 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
completed.insert(id);
}
processed.insert(tor);
processed.push_back(tor);
}
// model upkeep
if (!instantiated.isEmpty())
if (!instantiated.empty())
{
rowsAdd(instantiated);
}
if (!changed.isEmpty())
if (!changed.empty())
{
rowsEmitChanged(changed);
}
// emit signals
if (!added.isEmpty())
if (!added.empty())
{
emit torrentsAdded(added);
}
if (!needinfo.isEmpty())
if (!needinfo.empty())
{
emit torrentsNeedInfo(needinfo);
}
if (!changed.isEmpty())
if (!changed.empty())
{
emit torrentsChanged(changed);
}
if (!completed.isEmpty())
if (!completed.empty())
{
emit torrentsCompleted(completed);
}
@ -318,11 +323,11 @@ void TorrentModel::updateTorrents(tr_variant* torrents, bool isCompleteList)
if (isCompleteList)
{
auto const removed = old - processed;
if (!removed.isEmpty())
{
rowsRemove(removed);
}
std::sort(processed.begin(), processed.end(), TorrentIdLessThan());
torrents_t removed;
removed.reserve(old.size());
std::set_difference(old.begin(), old.end(), processed.begin(), processed.end(), std::back_inserter(removed));
rowsRemove(removed);
}
}
@ -365,7 +370,7 @@ Torrent const* TorrentModel::getTorrentFromId(int id) const
****
***/
std::vector<TorrentModel::span_t> TorrentModel::getSpans(QSet<int> const& ids) const
std::vector<TorrentModel::span_t> TorrentModel::getSpans(torrent_ids_t const& ids) const
{
// ids -> rows
std::vector<int> rows;
@ -420,7 +425,7 @@ std::vector<TorrentModel::span_t> TorrentModel::getSpans(QSet<int> const& ids) c
****
***/
void TorrentModel::rowsEmitChanged(QSet<int> const& ids)
void TorrentModel::rowsEmitChanged(torrent_ids_t const& ids)
{
for (auto const& span : getSpans(ids))
{
@ -432,7 +437,7 @@ void TorrentModel::rowsAdd(torrents_t const& torrents)
{
auto const compare = TorrentIdLessThan();
if (myTorrents.isEmpty())
if (myTorrents.empty())
{
beginInsertRows(QModelIndex(), 0, torrents.size() - 1);
myTorrents = torrents;
@ -453,7 +458,7 @@ void TorrentModel::rowsAdd(torrents_t const& torrents)
}
}
void TorrentModel::rowsRemove(QSet<Torrent*> const& torrents)
void TorrentModel::rowsRemove(torrents_t const& torrents)
{
// must walk in reverse to avoid invalidating row numbers
auto const& spans = getSpans(getIds(torrents.begin(), torrents.end()));
@ -474,29 +479,6 @@ void TorrentModel::rowsRemove(QSet<Torrent*> const& torrents)
****
***/
void TorrentModel::getTransferSpeed(Speed& uploadSpeed, size_t& uploadPeerCount, Speed& downloadSpeed,
size_t& downloadPeerCount) const
{
Speed upSpeed;
Speed downSpeed;
size_t upCount = 0;
size_t downCount = 0;
for (Torrent const* const tor : myTorrents)
{
upSpeed += tor->uploadSpeed();
upCount += tor->peersWeAreUploadingTo();
downSpeed += tor->downloadSpeed();
downCount += tor->webseedsWeAreDownloadingFrom();
downCount += tor->peersWeAreDownloadingFrom();
}
uploadSpeed = upSpeed;
uploadPeerCount = upCount;
downloadSpeed = downSpeed;
downloadPeerCount = downCount;
}
bool TorrentModel::hasTorrent(QString const& hashString) const
{
auto test = [hashString](auto const& tor) { return tor->hashString() == hashString; };

View File

@ -9,10 +9,12 @@
#pragma once
#include <optional>
#include <vector>
#include <QAbstractListModel>
#include <QSet>
#include <QVector>
// #include <QVector>
#include <Typedefs.h>
class Prefs;
class Speed;
@ -34,7 +36,7 @@ public:
};
explicit TorrentModel(Prefs const& prefs);
virtual ~TorrentModel();
virtual ~TorrentModel() override;
void clear();
bool hasTorrent(QString const& hashString) const;
@ -42,7 +44,8 @@ public:
Torrent* getTorrentFromId(int id);
Torrent const* getTorrentFromId(int id) const;
void getTransferSpeed(Speed& uploadSpeed, size_t& uploadPeerCount, Speed& downloadSpeed, size_t& downloadPeerCount) const;
using torrents_t = QVector<Torrent*>;
torrents_t const& torrents() const { return myTorrents; }
// QAbstractItemModel
int rowCount(QModelIndex const& parent = QModelIndex()) const override;
@ -53,23 +56,22 @@ public slots:
void removeTorrents(tr_variant* torrentList);
signals:
void torrentsAdded(QSet<int>);
void torrentsChanged(QSet<int>);
void torrentsCompleted(QSet<int>);
void torrentsNeedInfo(QSet<int>);
void torrentsAdded(torrent_ids_t const&);
void torrentsChanged(torrent_ids_t const&);
void torrentsCompleted(torrent_ids_t const&);
void torrentsNeedInfo(torrent_ids_t const&);
private:
using torrents_t = QVector<Torrent*>;
void rowsAdd(torrents_t const& torrents);
void rowsRemove(QSet<Torrent*> const& torrents);
void rowsEmitChanged(QSet<int> const& ids);
void rowsRemove(torrents_t const& torrents);
void rowsEmitChanged(torrent_ids_t const& ids);
std::optional<int> getRow(int id) const;
std::optional<int> getRow(Torrent const* tor) const;
using span_t = std::pair<int, int>;
std::vector<span_t> getSpans(QSet<int> const& ids) const;
std::vector<span_t> getSpans(torrent_ids_t const& ids) const;
Prefs const& myPrefs;
torrent_ids_t myAlreadyAdded;
torrents_t myTorrents;
QSet<int> myAlreadyAdded;
};

View File

@ -24,7 +24,7 @@ signals:
void headerDoubleClicked();
protected:
virtual void resizeEvent(QResizeEvent* event);
void resizeEvent(QResizeEvent* event) override;
private:
class HeaderWidget;

View File

@ -88,7 +88,7 @@ ItemLayout::ItemLayout(QString const& text, bool suppressColors, Qt::LayoutDirec
QSize TrackerDelegate::margin(QStyle const& style) const
{
Q_UNUSED(style);
Q_UNUSED(style)
return myMargin;
}

View File

@ -26,15 +26,11 @@ public:
{
}
virtual ~TrackerDelegate()
{
}
void setShowMore(bool b);
// QAbstractItemDelegate
virtual QSize sizeHint(QStyleOptionViewItem const& option, QModelIndex const& index) const;
virtual void paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const;
QSize sizeHint(QStyleOptionViewItem const& option, QModelIndex const& index) const override;
void paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const override;
protected:
QString getText(TrackerInfo const&) const;

View File

@ -16,7 +16,7 @@
int TrackerModel::rowCount(QModelIndex const& parent) const
{
Q_UNUSED(parent);
Q_UNUSED(parent)
return parent.isValid() ? 0 : myRows.size();
}
@ -80,7 +80,7 @@ struct CompareTrackers
}
};
void TrackerModel::refresh(TorrentModel const& torrentModel, QSet<int> const& ids)
void TrackerModel::refresh(TorrentModel const& torrentModel, torrent_ids_t const& ids)
{
// build a list of the TrackerInfos
QVector<TrackerInfo> trackers;

View File

@ -9,10 +9,10 @@
#pragma once
#include <QAbstractListModel>
#include <QSet>
#include <QVector>
#include "Torrent.h"
#include "Typedefs.h"
class TorrentModel;
@ -35,20 +35,14 @@ public:
};
public:
TrackerModel()
{
}
TrackerModel() = default;
virtual ~TrackerModel()
{
}
void refresh(TorrentModel const&, QSet<int> const& ids);
void refresh(TorrentModel const&, torrent_ids_t const& ids);
int find(int torrentId, QString const& url) const;
// QAbstractItemModel
virtual int rowCount(QModelIndex const& parent = QModelIndex()) const;
virtual QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const;
int rowCount(QModelIndex const& parent = QModelIndex()) const override;
QVariant data(QModelIndex const& index, int role = Qt::DisplayRole) const override;
private:
typedef QVector<TrackerInfo> rows_t;

5
qt/Typedefs.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <unordered_set>
using torrent_ids_t = std::unordered_set<int>;

View File

@ -6,8 +6,9 @@
*
*/
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#ifdef _WIN32
#include <windows.h>
@ -109,12 +110,13 @@ QIcon fileIcon()
return icon;
}
std::map<QString, QIcon> iconCache;
std::unordered_map<QString, QIcon> iconCache;
QIcon const getMimeIcon(QString const& filename)
{
// If the suffix doesn't match a mime type, treat it as a folder.
// This heuristic is fast and yields good results for torrent names.
static std::set<QString> suffixes;
static std::unordered_set<QString> suffixes;
if (suffixes.empty())
{
for (auto const& type : QMimeDatabase().allMimeTypes())

View File

@ -80,7 +80,7 @@ public:
return false;
}
for (QChar const ch : s)
for (auto const& ch : s)
{
if (!isxdigit(ch.unicode()))
{
@ -93,9 +93,22 @@ public:
static bool isUriWithSupportedScheme(QString const& s)
{
static QString const ftp = QString::fromUtf8("ftp://");
static QString const http = QString::fromUtf8("http://");
static QString const https = QString::fromUtf8("https://");
return s.startsWith(http) || s.startsWith(https) || s.startsWith(ftp);
return s.startsWith(QStringLiteral("ftp://")) ||
s.startsWith(QStringLiteral("http://")) ||
s.startsWith(QStringLiteral("https://"));
}
};
namespace std
{
template<>
struct hash<QString>
{
std::size_t operator ()(QString const& s) const
{
return qHash(s);
}
};
} // namespace std

View File

@ -28,10 +28,6 @@ WatchDir::WatchDir(TorrentModel const& model) :
{
}
WatchDir::~WatchDir()
{
}
/***
****
***/

View File

@ -22,7 +22,6 @@ class WatchDir : public QObject
public:
WatchDir(TorrentModel const&);
virtual ~WatchDir();
void setPath(QString const& path, bool isEnabled);

View File

@ -121,6 +121,6 @@ SOURCES += AboutDialog.cc \
Utils.cc \
WatchDir.cc
HEADERS += $$replace(SOURCES, .cc, .h)
HEADERS += BaseDialog.h CustomVariantType.h Speed.h
HEADERS += BaseDialog.h CustomVariantType.h Speed.h Typedefs.h
win32:RC_FILE = qtr.rc