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:
parent
49fdd0b430
commit
c62cb35fd4
|
@ -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);
|
||||
|
|
|
@ -22,7 +22,6 @@ class AboutDialog : public BaseDialog
|
|||
|
||||
public:
|
||||
AboutDialog(QWidget* parent = nullptr);
|
||||
virtual ~AboutDialog() = default;
|
||||
|
||||
private slots:
|
||||
void showCredits();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -106,6 +106,7 @@ set(${PROJECT_NAME}_HEADERS
|
|||
TrackerDelegate.h
|
||||
TrackerModel.h
|
||||
TrackerModelFilter.h
|
||||
Typedefs.h
|
||||
Utils.h
|
||||
WatchDir.h
|
||||
)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
190
qt/FilterBar.cc
190
qt/FilterBar.cc
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
109
qt/MainWindow.cc
109
qt/MainWindow.cc
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -433,7 +433,7 @@ void PrefsDialog::initNetworkTab()
|
|||
|
||||
void PrefsDialog::onBlocklistDialogDestroyed(QObject* o)
|
||||
{
|
||||
Q_UNUSED(o);
|
||||
Q_UNUSED(o)
|
||||
|
||||
myBlocklistDialog = nullptr;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
|
||||
#include "BaseDialog.h"
|
||||
#include "Prefs.h"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
48
qt/Session.h
48
qt/Session.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -53,5 +53,5 @@ public:
|
|||
|
||||
protected:
|
||||
// QWidget
|
||||
virtual void paintEvent(QPaintEvent* paintEvent);
|
||||
void paintEvent(QPaintEvent* paintEvent) override;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
|
|
17
qt/Torrent.h
17
qt/Torrent.h
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ signals:
|
|||
void headerDoubleClicked();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent* event);
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
class HeaderWidget;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
using torrent_ids_t = std::unordered_set<int>;
|
|
@ -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())
|
||||
|
|
23
qt/Utils.h
23
qt/Utils.h
|
@ -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
|
||||
|
|
|
@ -28,10 +28,6 @@ WatchDir::WatchDir(TorrentModel const& model) :
|
|||
{
|
||||
}
|
||||
|
||||
WatchDir::~WatchDir()
|
||||
{
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
|
|
@ -22,7 +22,6 @@ class WatchDir : public QObject
|
|||
|
||||
public:
|
||||
WatchDir(TorrentModel const&);
|
||||
virtual ~WatchDir();
|
||||
|
||||
void setPath(QString const& path, bool isEnabled);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue