transmission/qt/Torrent.cc

1075 lines
26 KiB
C++
Raw Normal View History

2009-04-09 18:55:47 +00:00
/*
* This file Copyright (C) 2009-2015 Mnemosyne LLC
2009-04-09 18:55:47 +00:00
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
2009-04-09 18:55:47 +00:00
*
*/
#include <cassert>
#include <iostream>
#include <QApplication>
#include <QString>
#include <QUrl>
2009-04-09 18:55:47 +00:00
#include <QVariant>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> /* tr_new0, tr_strdup */
#include <libtransmission/variant.h>
2009-04-09 18:55:47 +00:00
#include "Application.h"
#include "Prefs.h"
#include "Torrent.h"
#include "Utils.h"
2009-04-09 18:55:47 +00:00
Torrent::Torrent(Prefs const& prefs, int id) :
myPrefs(prefs),
magnetTorrent(false)
2009-04-09 18:55:47 +00:00
{
#ifndef NDEBUG
for (int i = 0; i < PROPERTY_COUNT; ++i)
{
assert(myProperties[i].id == i);
}
#endif
2009-04-09 18:55:47 +00:00
setInt(ID, id);
setIcon(MIME_ICON, Utils::getFileIcon());
2009-04-09 18:55:47 +00:00
}
Torrent::~Torrent()
2009-04-09 18:55:47 +00:00
{
}
/***
****
***/
Torrent::Property Torrent::myProperties[] =
{
{ ID, TR_KEY_id, QVariant::Int, INFO },
{ UPLOAD_SPEED, TR_KEY_rateUpload, QVariant::ULongLong, STAT } /* Bps */,
{ DOWNLOAD_SPEED, TR_KEY_rateDownload, QVariant::ULongLong, STAT }, /* Bps */
{ DOWNLOAD_DIR, TR_KEY_downloadDir, QVariant::String, STAT },
{ ACTIVITY, TR_KEY_status, QVariant::Int, STAT },
{ NAME, TR_KEY_name, QVariant::String, INFO },
{ ERROR, TR_KEY_error, QVariant::Int, STAT },
{ ERROR_STRING, TR_KEY_errorString, QVariant::String, STAT },
{ SIZE_WHEN_DONE, TR_KEY_sizeWhenDone, QVariant::ULongLong, STAT },
{ LEFT_UNTIL_DONE, TR_KEY_leftUntilDone, QVariant::ULongLong, STAT },
{ HAVE_UNCHECKED, TR_KEY_haveUnchecked, QVariant::ULongLong, STAT },
{ HAVE_VERIFIED, TR_KEY_haveValid, QVariant::ULongLong, STAT },
{ DESIRED_AVAILABLE, TR_KEY_desiredAvailable, QVariant::ULongLong, STAT },
{ TOTAL_SIZE, TR_KEY_totalSize, QVariant::ULongLong, INFO },
{ PIECE_SIZE, TR_KEY_pieceSize, QVariant::ULongLong, INFO },
{ PIECE_COUNT, TR_KEY_pieceCount, QVariant::Int, INFO },
{ PEERS_GETTING_FROM_US, TR_KEY_peersGettingFromUs, QVariant::Int, STAT },
{ PEERS_SENDING_TO_US, TR_KEY_peersSendingToUs, QVariant::Int, STAT },
{ WEBSEEDS_SENDING_TO_US, TR_KEY_webseedsSendingToUs, QVariant::Int, STAT_EXTRA },
{ PERCENT_DONE, TR_KEY_percentDone, QVariant::Double, STAT },
{ METADATA_PERCENT_DONE, TR_KEY_metadataPercentComplete, QVariant::Double, STAT },
{ PERCENT_VERIFIED, TR_KEY_recheckProgress, QVariant::Double, STAT },
{ DATE_ACTIVITY, TR_KEY_activityDate, QVariant::DateTime, STAT_EXTRA },
{ DATE_ADDED, TR_KEY_addedDate, QVariant::DateTime, INFO },
{ DATE_STARTED, TR_KEY_startDate, QVariant::DateTime, STAT_EXTRA },
{ DATE_CREATED, TR_KEY_dateCreated, QVariant::DateTime, INFO },
{ PEERS_CONNECTED, TR_KEY_peersConnected, QVariant::Int, STAT },
{ ETA, TR_KEY_eta, QVariant::Int, STAT },
{ RATIO, TR_KEY_uploadRatio, QVariant::Double, STAT },
{ DOWNLOADED_EVER, TR_KEY_downloadedEver, QVariant::ULongLong, STAT },
{ UPLOADED_EVER, TR_KEY_uploadedEver, QVariant::ULongLong, STAT },
{ FAILED_EVER, TR_KEY_corruptEver, QVariant::ULongLong, STAT_EXTRA },
{ TRACKERS, TR_KEY_trackers, QVariant::StringList, STAT },
{ HOSTS, TR_KEY_NONE, QVariant::StringList, DERIVED },
{ TRACKERSTATS, TR_KEY_trackerStats, CustomVariantType::TrackerStatsList, STAT_EXTRA },
{ MIME_ICON, TR_KEY_NONE, QVariant::Icon, DERIVED },
{ SEED_RATIO_LIMIT, TR_KEY_seedRatioLimit, QVariant::Double, STAT },
{ SEED_RATIO_MODE, TR_KEY_seedRatioMode, QVariant::Int, STAT },
{ SEED_IDLE_LIMIT, TR_KEY_seedIdleLimit, QVariant::Int, STAT_EXTRA },
{ SEED_IDLE_MODE, TR_KEY_seedIdleMode, QVariant::Int, STAT_EXTRA },
{ DOWN_LIMIT, TR_KEY_downloadLimit, QVariant::Int, STAT_EXTRA }, /* KB/s */
{ DOWN_LIMITED, TR_KEY_downloadLimited, QVariant::Bool, STAT_EXTRA },
{ UP_LIMIT, TR_KEY_uploadLimit, QVariant::Int, STAT_EXTRA }, /* KB/s */
{ UP_LIMITED, TR_KEY_uploadLimited, QVariant::Bool, STAT_EXTRA },
{ HONORS_SESSION_LIMITS, TR_KEY_honorsSessionLimits, QVariant::Bool, STAT_EXTRA },
{ PEER_LIMIT, TR_KEY_peer_limit, QVariant::Int, STAT_EXTRA },
{ HASH_STRING, TR_KEY_hashString, QVariant::String, INFO },
{ IS_FINISHED, TR_KEY_isFinished, QVariant::Bool, STAT },
{ IS_PRIVATE, TR_KEY_isPrivate, QVariant::Bool, INFO },
{ IS_STALLED, TR_KEY_isStalled, QVariant::Bool, STAT },
{ COMMENT, TR_KEY_comment, QVariant::String, INFO },
{ CREATOR, TR_KEY_creator, QVariant::String, INFO },
{ MANUAL_ANNOUNCE_TIME, TR_KEY_manualAnnounceTime, QVariant::DateTime, STAT_EXTRA },
{ PEERS, TR_KEY_peers, CustomVariantType::PeerList, STAT_EXTRA },
{ BANDWIDTH_PRIORITY, TR_KEY_bandwidthPriority, QVariant::Int, STAT_EXTRA },
{ QUEUE_POSITION, TR_KEY_queuePosition, QVariant::Int, STAT },
2009-04-09 18:55:47 +00:00
};
Torrent::KeyList Torrent::buildKeyList(Group group)
2009-04-09 18:55:47 +00:00
{
KeyList keys;
2009-04-09 18:55:47 +00:00
if (keys.empty())
{
for (int i = 0; i < PROPERTY_COUNT; ++i)
{
if (myProperties[i].id == ID || myProperties[i].group == group)
{
keys << myProperties[i].key;
}
}
}
2009-04-09 18:55:47 +00:00
return keys;
2009-04-09 18:55:47 +00:00
}
Torrent::KeyList const& Torrent::getInfoKeys()
2009-04-09 18:55:47 +00:00
{
static KeyList keys;
if (keys.isEmpty())
{
keys << buildKeyList(INFO) << TR_KEY_files;
}
return keys;
2009-04-09 18:55:47 +00:00
}
Torrent::KeyList const& Torrent::getStatKeys()
2009-04-09 18:55:47 +00:00
{
static KeyList keys(buildKeyList(STAT));
return keys;
2009-04-09 18:55:47 +00:00
}
Torrent::KeyList const& Torrent::getExtraStatKeys()
2009-04-09 18:55:47 +00:00
{
static KeyList keys;
2009-04-09 18:55:47 +00:00
if (keys.isEmpty())
{
keys << buildKeyList(STAT_EXTRA) << TR_KEY_fileStats;
}
return keys;
}
2009-04-09 18:55:47 +00:00
bool Torrent::setInt(int i, int value)
2009-04-09 18:55:47 +00:00
{
bool changed = false;
2009-04-09 18:55:47 +00:00
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Int);
2009-04-09 18:55:47 +00:00
if (myValues[i].isNull() || myValues[i].toInt() != value)
2009-04-09 18:55:47 +00:00
{
myValues[i].setValue(value);
changed = true;
2009-04-09 18:55:47 +00:00
}
return changed;
2009-04-09 18:55:47 +00:00
}
bool Torrent::setBool(int i, bool value)
2009-04-09 18:55:47 +00:00
{
bool changed = false;
2009-04-09 18:55:47 +00:00
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Bool);
2009-04-09 18:55:47 +00:00
if (myValues[i].isNull() || myValues[i].toBool() != value)
2009-04-09 18:55:47 +00:00
{
myValues[i].setValue(value);
changed = true;
2009-04-09 18:55:47 +00:00
}
return changed;
2009-04-09 18:55:47 +00:00
}
bool Torrent::setDouble(int i, double value)
2009-04-09 18:55:47 +00:00
{
bool changed = false;
2009-04-09 18:55:47 +00:00
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Double);
2009-04-09 18:55:47 +00:00
if (myValues[i] != value)
2009-04-09 18:55:47 +00:00
{
myValues[i].setValue(value);
changed = true;
2009-04-09 18:55:47 +00:00
}
return changed;
2009-04-09 18:55:47 +00:00
}
bool Torrent::setTime(int i, time_t value)
2009-04-09 18:55:47 +00:00
{
bool changed = false;
2009-04-09 18:55:47 +00:00
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::DateTime);
2009-04-09 18:55:47 +00:00
auto& oldval = myValues[i];
auto const newval = qlonglong(value);
if (oldval != newval)
2009-04-09 18:55:47 +00:00
{
oldval = newval;
changed = true;
2009-04-09 18:55:47 +00:00
}
return changed;
2009-04-09 18:55:47 +00:00
}
bool Torrent::setSize(int i, qulonglong value)
2009-04-09 18:55:47 +00:00
{
bool changed = false;
2009-04-09 18:55:47 +00:00
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::ULongLong);
2009-04-09 18:55:47 +00:00
if (myValues[i].isNull() || myValues[i].toULongLong() != value)
2009-04-09 18:55:47 +00:00
{
myValues[i].setValue(value);
changed = true;
2009-04-09 18:55:47 +00:00
}
return changed;
2009-04-09 18:55:47 +00:00
}
bool Torrent::setString(int i, char const* value)
2009-04-09 18:55:47 +00:00
{
bool changed = false;
2009-04-09 18:55:47 +00:00
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::String);
2009-04-09 18:55:47 +00:00
if (myValues[i].isNull() || myValues[i].toString() != QString::fromUtf8(value))
2009-04-09 18:55:47 +00:00
{
myValues[i].setValue(QString::fromUtf8(value));
changed = true;
2009-04-09 18:55:47 +00:00
}
return changed;
2009-04-09 18:55:47 +00:00
}
bool Torrent::setIcon(int i, QIcon const& value)
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Icon);
2009-04-09 18:55:47 +00:00
myValues[i].setValue(value);
return true;
2009-04-09 18:55:47 +00:00
}
int Torrent::getInt(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Int);
2009-04-09 18:55:47 +00:00
return myValues[i].toInt();
2009-04-09 18:55:47 +00:00
}
time_t Torrent::getTime(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::DateTime);
2009-04-09 18:55:47 +00:00
return time_t(myValues[i].toLongLong());
2009-04-09 18:55:47 +00:00
}
bool Torrent::getBool(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Bool);
2009-04-09 18:55:47 +00:00
return myValues[i].toBool();
2009-04-09 18:55:47 +00:00
}
qulonglong Torrent::getSize(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::ULongLong);
2009-04-09 18:55:47 +00:00
return myValues[i].toULongLong();
2009-04-09 18:55:47 +00:00
}
2019-07-14 21:30:14 +00:00
double Torrent::getDouble(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Double);
2009-04-09 18:55:47 +00:00
return myValues[i].toDouble();
2009-04-09 18:55:47 +00:00
}
2019-07-14 21:30:14 +00:00
QString Torrent::getString(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::String);
2009-04-09 18:55:47 +00:00
return myValues[i].toString();
2009-04-09 18:55:47 +00:00
}
2019-07-14 21:30:14 +00:00
QIcon Torrent::getIcon(int i) const
2009-04-09 18:55:47 +00:00
{
assert(0 <= i && i < PROPERTY_COUNT);
assert(myProperties[i].type == QVariant::Icon);
2009-04-09 18:55:47 +00:00
return myValues[i].value<QIcon>();
2009-04-09 18:55:47 +00:00
}
/***
****
***/
bool Torrent::getSeedRatio(double& ratio) const
2009-04-09 18:55:47 +00:00
{
bool isLimited;
2009-04-09 18:55:47 +00:00
switch (seedRatioMode())
2009-04-09 18:55:47 +00:00
{
case TR_RATIOLIMIT_SINGLE:
isLimited = true;
ratio = seedRatioLimit();
break;
case TR_RATIOLIMIT_GLOBAL:
if ((isLimited = myPrefs.getBool(Prefs::RATIO_ENABLED)))
{
ratio = myPrefs.getDouble(Prefs::RATIO);
}
break;
default: // TR_RATIOLIMIT_UNLIMITED:
isLimited = false;
break;
2009-04-09 18:55:47 +00:00
}
return isLimited;
2009-04-09 18:55:47 +00:00
}
bool Torrent::hasFileSubstring(QString const& substr) const
2009-04-09 18:55:47 +00:00
{
for (TorrentFile const& file : myFiles)
{
if (file.filename.contains(substr, Qt::CaseInsensitive))
{
return true;
}
}
return false;
2009-04-09 18:55:47 +00:00
}
bool Torrent::hasTrackerSubstring(QString const& substr) const
2009-04-09 18:55:47 +00:00
{
for (QString const& s : myValues[TRACKERS].toStringList())
{
if (s.contains(substr, Qt::CaseInsensitive))
{
return true;
}
}
return false;
2009-04-09 18:55:47 +00:00
}
int Torrent::compareSeedRatio(Torrent const& that) const
{
double a;
double b;
bool const has_a = getSeedRatio(a);
bool const has_b = that.getSeedRatio(b);
if (!has_a && !has_b)
{
return 0;
}
if (!has_a || !has_b)
{
return has_a ? -1 : 1;
}
if (a < b)
{
return -1;
}
if (a > b)
{
return 1;
}
return 0;
}
int Torrent::compareRatio(Torrent const& that) const
2009-04-09 18:55:47 +00:00
{
double const a = ratio();
double const b = that.ratio();
if (static_cast<int>(a) == TR_RATIO_INF && static_cast<int>(b) == TR_RATIO_INF)
{
return 0;
}
if (static_cast<int>(a) == TR_RATIO_INF)
{
return 1;
}
if (static_cast<int>(b) == TR_RATIO_INF)
{
return -1;
}
if (a < b)
{
return -1;
}
if (a > b)
{
return 1;
}
return 0;
2009-04-09 18:55:47 +00:00
}
int Torrent::compareETA(Torrent const& that) const
2009-04-09 18:55:47 +00:00
{
bool const haveA(hasETA());
bool const haveB(that.hasETA());
if (haveA && haveB)
{
return getETA() - that.getETA();
}
if (haveA)
{
return 1;
}
if (haveB)
{
return -1;
}
return 0;
2009-04-09 18:55:47 +00:00
}
int Torrent::compareTracker(Torrent const& that) const
2009-04-09 18:55:47 +00:00
{
Q_UNUSED(that);
2009-04-09 18:55:47 +00:00
// FIXME
return 0;
2009-04-09 18:55:47 +00:00
}
/***
****
***/
void Torrent::updateMimeIcon()
2009-04-09 18:55:47 +00:00
{
FileList const& files(myFiles);
2009-04-09 18:55:47 +00:00
QIcon icon;
2009-04-09 18:55:47 +00:00
if (files.size() > 1)
{
icon = Utils::getFolderIcon();
}
else if (files.size() == 1)
{
icon = Utils::guessMimeIcon(files.at(0).filename);
}
else
{
icon = Utils::guessMimeIcon(name());
}
2009-04-09 18:55:47 +00:00
setIcon(MIME_ICON, icon);
2009-04-09 18:55:47 +00:00
}
/***
****
***/
void Torrent::notifyComplete() const
2009-04-09 18:55:47 +00:00
{
// if someone wants to implement notification, here's the hook.
}
/***
****
***/
void Torrent::update(tr_variant* d)
2009-04-09 18:55:47 +00:00
{
static bool lookup_initialized = false;
static int key_to_property_index[TR_N_KEYS];
bool changed = false;
bool const was_seed = isSeed();
uint64_t const old_verified_size = haveVerified();
if (!lookup_initialized)
{
lookup_initialized = true;
for (int i = 0; i < TR_N_KEYS; ++i)
{
key_to_property_index[i] = -1;
}
for (int i = 0; i < PROPERTY_COUNT; i++)
{
key_to_property_index[myProperties[i].key] = i;
}
}
2009-04-09 18:55:47 +00:00
tr_quark key;
tr_variant* child;
size_t pos = 0;
while (tr_variantDictChild(d, pos++, &key, &child))
2009-04-09 18:55:47 +00:00
{
int const property_index = key_to_property_index[key];
if (property_index == -1) // we're not interested in this one
{
continue;
}
2009-04-09 18:55:47 +00:00
assert(myProperties[property_index].key == key);
switch (myProperties[property_index].type)
2009-04-09 18:55:47 +00:00
{
case QVariant::Int:
{
int64_t val;
if (tr_variantGetInt(child, &val))
{
changed |= setInt(property_index, val);
}
break;
2009-04-09 18:55:47 +00:00
}
case QVariant::Bool:
{
bool val;
if (tr_variantGetBool(child, &val))
{
changed |= setBool(property_index, val);
}
break;
2009-04-09 18:55:47 +00:00
}
case QVariant::String:
{
char const* val;
if (tr_variantGetStr(child, &val, nullptr))
{
bool const field_changed = setString(property_index, val);
changed |= field_changed;
if (field_changed && key == TR_KEY_name)
{
updateMimeIcon();
}
}
break;
2009-04-09 18:55:47 +00:00
}
case QVariant::ULongLong:
{
int64_t val;
if (tr_variantGetInt(child, &val))
{
changed |= setSize(property_index, val);
}
break;
2009-04-09 18:55:47 +00:00
}
case QVariant::Double:
{
double val;
if (tr_variantGetReal(child, &val))
{
changed |= setDouble(property_index, val);
}
break;
2009-04-09 18:55:47 +00:00
}
case QVariant::DateTime:
{
int64_t val;
if (tr_variantGetInt(child, &val) && val)
{
changed |= setTime(property_index, time_t(val));
}
break;
2009-04-09 18:55:47 +00:00
}
case QVariant::StringList:
case CustomVariantType::PeerList:
// handled below
break;
2009-04-09 18:55:47 +00:00
default:
std::cerr << __FILE__ << ':' << __LINE__ << "unhandled type: " << tr_quark_get_string(key, nullptr) << std::endl;
assert(false && "unhandled type");
2009-04-09 18:55:47 +00:00
}
}
tr_variant* files;
if (tr_variantDictFindList(d, TR_KEY_files, &files))
{
char const* str;
int64_t intVal;
int i = 0;
tr_variant* child;
myFiles.clear();
myFiles.reserve(tr_variantListSize(files));
while ((child = tr_variantListChild(files, i)) != nullptr)
{
TorrentFile file;
size_t len;
file.index = i++;
if (tr_variantDictFindStr(child, TR_KEY_name, &str, &len))
{
file.filename = QString::fromUtf8(str, len);
}
if (tr_variantDictFindInt(child, TR_KEY_length, &intVal))
{
file.size = intVal;
}
myFiles.append(file);
2009-04-09 18:55:47 +00:00
}
updateMimeIcon();
changed = true;
2009-04-09 18:55:47 +00:00
}
if (tr_variantDictFindList(d, TR_KEY_fileStats, &files))
{
int const n = tr_variantListSize(files);
for (int i = 0; i < n && i < myFiles.size(); ++i)
{
int64_t intVal;
bool boolVal;
tr_variant* child = tr_variantListChild(files, i);
TorrentFile& file(myFiles[i]);
if (tr_variantDictFindInt(child, TR_KEY_bytesCompleted, &intVal))
{
file.have = intVal;
}
if (tr_variantDictFindBool(child, TR_KEY_wanted, &boolVal))
{
file.wanted = boolVal;
}
if (tr_variantDictFindInt(child, TR_KEY_priority, &intVal))
{
file.priority = intVal;
}
2009-04-09 18:55:47 +00:00
}
2009-04-09 18:55:47 +00:00
changed = true;
}
tr_variant* trackers;
if (tr_variantDictFindList(d, TR_KEY_trackers, &trackers))
{
size_t len;
char const* str;
int i = 0;
QStringList list;
tr_variant* child;
while ((child = tr_variantListChild(trackers, i++)) != nullptr)
{
if (tr_variantDictFindStr(child, TR_KEY_announce, &str, &len))
{
qApp->faviconCache().add(QUrl(QString::fromUtf8(str)));
list.append(QString::fromUtf8(str, len));
}
}
if (myValues[TRACKERS] != list)
{
QStringList hosts;
for (QString const& tracker : list)
{
QString const host = FaviconCache::getHost(QUrl(tracker));
if (!host.isEmpty())
{
hosts.append(host);
}
}
hosts.removeDuplicates();
myValues[TRACKERS].setValue(list);
myValues[HOSTS].setValue(hosts);
changed = true;
2009-04-09 18:55:47 +00:00
}
}
tr_variant* trackerStats;
if (tr_variantDictFindList(d, TR_KEY_trackerStats, &trackerStats))
{
tr_variant* child;
TrackerStatsList trackerStatsList;
int childNum = 0;
while ((child = tr_variantListChild(trackerStats, childNum++)) != nullptr)
{
bool b;
int64_t i;
size_t len;
char const* str;
TrackerStat trackerStat;
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))
{
trackerStat.announceState = i;
}
if (tr_variantDictFindInt(child, TR_KEY_downloadCount, &i))
{
trackerStat.downloadCount = i;
}
if (tr_variantDictFindBool(child, TR_KEY_hasAnnounced, &b))
{
trackerStat.hasAnnounced = b;
}
if (tr_variantDictFindBool(child, TR_KEY_hasScraped, &b))
{
trackerStat.hasScraped = b;
}
if (tr_variantDictFindStr(child, TR_KEY_host, &str, &len))
{
trackerStat.host = QString::fromUtf8(str, len);
}
if (tr_variantDictFindInt(child, TR_KEY_id, &i))
{
trackerStat.id = i;
}
if (tr_variantDictFindBool(child, TR_KEY_isBackup, &b))
{
trackerStat.isBackup = b;
}
if (tr_variantDictFindInt(child, TR_KEY_lastAnnouncePeerCount, &i))
{
trackerStat.lastAnnouncePeerCount = i;
}
if (tr_variantDictFindStr(child, TR_KEY_lastAnnounceResult, &str, &len))
{
trackerStat.lastAnnounceResult = QString::fromUtf8(str, len);
}
if (tr_variantDictFindInt(child, TR_KEY_lastAnnounceStartTime, &i))
{
trackerStat.lastAnnounceStartTime = i;
}
if (tr_variantDictFindBool(child, TR_KEY_lastAnnounceSucceeded, &b))
{
trackerStat.lastAnnounceSucceeded = b;
}
if (tr_variantDictFindInt(child, TR_KEY_lastAnnounceTime, &i))
{
trackerStat.lastAnnounceTime = i;
}
if (tr_variantDictFindBool(child, TR_KEY_lastAnnounceTimedOut, &b))
{
trackerStat.lastAnnounceTimedOut = b;
}
if (tr_variantDictFindStr(child, TR_KEY_lastScrapeResult, &str, &len))
{
trackerStat.lastScrapeResult = QString::fromUtf8(str, len);
}
if (tr_variantDictFindInt(child, TR_KEY_lastScrapeStartTime, &i))
{
trackerStat.lastScrapeStartTime = i;
}
if (tr_variantDictFindBool(child, TR_KEY_lastScrapeSucceeded, &b))
{
trackerStat.lastScrapeSucceeded = b;
}
if (tr_variantDictFindInt(child, TR_KEY_lastScrapeTime, &i))
{
trackerStat.lastScrapeTime = i;
}
if (tr_variantDictFindBool(child, TR_KEY_lastScrapeTimedOut, &b))
{
trackerStat.lastScrapeTimedOut = b;
}
if (tr_variantDictFindInt(child, TR_KEY_leecherCount, &i))
{
trackerStat.leecherCount = i;
}
if (tr_variantDictFindInt(child, TR_KEY_nextAnnounceTime, &i))
{
trackerStat.nextAnnounceTime = i;
}
if (tr_variantDictFindInt(child, TR_KEY_nextScrapeTime, &i))
{
trackerStat.nextScrapeTime = i;
}
if (tr_variantDictFindInt(child, TR_KEY_scrapeState, &i))
{
trackerStat.scrapeState = i;
}
if (tr_variantDictFindInt(child, TR_KEY_seederCount, &i))
{
trackerStat.seederCount = i;
}
if (tr_variantDictFindInt(child, TR_KEY_tier, &i))
{
trackerStat.tier = i;
}
trackerStatsList << trackerStat;
}
myValues[TRACKERSTATS].setValue(trackerStatsList);
changed = true;
}
tr_variant* peers;
if (tr_variantDictFindList(d, TR_KEY_peers, &peers))
{
tr_variant* child;
PeerList peerList;
int childNum = 0;
while ((child = tr_variantListChild(peers, childNum++)) != nullptr)
{
double d;
bool b;
int64_t i;
size_t len;
char const* str;
Peer peer;
if (tr_variantDictFindStr(child, TR_KEY_address, &str, &len))
{
peer.address = QString::fromUtf8(str, len);
}
if (tr_variantDictFindStr(child, TR_KEY_clientName, &str, &len))
{
peer.clientName = QString::fromUtf8(str, len);
}
if (tr_variantDictFindBool(child, TR_KEY_clientIsChoked, &b))
{
peer.clientIsChoked = b;
}
if (tr_variantDictFindBool(child, TR_KEY_clientIsInterested, &b))
{
peer.clientIsInterested = b;
}
if (tr_variantDictFindStr(child, TR_KEY_flagStr, &str, &len))
{
peer.flagStr = QString::fromUtf8(str, len);
}
if (tr_variantDictFindBool(child, TR_KEY_isDownloadingFrom, &b))
{
peer.isDownloadingFrom = b;
}
if (tr_variantDictFindBool(child, TR_KEY_isEncrypted, &b))
{
peer.isEncrypted = b;
}
if (tr_variantDictFindBool(child, TR_KEY_isIncoming, &b))
{
peer.isIncoming = b;
}
if (tr_variantDictFindBool(child, TR_KEY_isUploadingTo, &b))
{
peer.isUploadingTo = b;
}
if (tr_variantDictFindBool(child, TR_KEY_peerIsChoked, &b))
{
peer.peerIsChoked = b;
}
if (tr_variantDictFindBool(child, TR_KEY_peerIsInterested, &b))
{
peer.peerIsInterested = b;
}
if (tr_variantDictFindInt(child, TR_KEY_port, &i))
{
peer.port = i;
}
if (tr_variantDictFindReal(child, TR_KEY_progress, &d))
{
peer.progress = d;
}
if (tr_variantDictFindInt(child, TR_KEY_rateToClient, &i))
{
peer.rateToClient = Speed::fromBps(i);
}
if (tr_variantDictFindInt(child, TR_KEY_rateToPeer, &i))
{
peer.rateToPeer = Speed::fromBps(i);
}
peerList << peer;
2009-04-09 18:55:47 +00:00
}
myValues[PEERS].setValue(peerList);
changed = true;
2009-04-09 18:55:47 +00:00
}
if (changed)
{
emit torrentChanged(id());
}
if (!was_seed && isSeed() && old_verified_size > 0)
{
emit torrentCompleted(id());
}
2009-04-09 18:55:47 +00:00
}
QString Torrent::activityString() const
2009-04-09 18:55:47 +00:00
{
QString str;
2009-04-09 18:55:47 +00:00
switch (getActivity())
2009-04-09 18:55:47 +00:00
{
case TR_STATUS_STOPPED:
str = isFinished() ? tr("Finished") : tr("Paused");
break;
case TR_STATUS_CHECK_WAIT:
str = tr("Queued for verification");
break;
case TR_STATUS_CHECK:
str = tr("Verifying local data");
break;
case TR_STATUS_DOWNLOAD_WAIT:
str = tr("Queued for download");
break;
case TR_STATUS_DOWNLOAD:
str = tr("Downloading");
break;
case TR_STATUS_SEED_WAIT:
str = tr("Queued for seeding");
break;
case TR_STATUS_SEED:
str = tr("Seeding");
break;
2009-04-09 18:55:47 +00:00
}
return str;
2009-04-09 18:55:47 +00:00
}
QString Torrent::getError() const
{
QString s = getString(ERROR_STRING);
switch (getInt(ERROR))
{
case TR_STAT_TRACKER_WARNING:
s = tr("Tracker gave a warning: %1").arg(s);
break;
case TR_STAT_TRACKER_ERROR:
s = tr("Tracker gave an error: %1").arg(s);
break;
case TR_STAT_LOCAL_ERROR:
s = tr("Error: %1").arg(s);
break;
default:
s.clear();
break;
}
return s;
}
QPixmap TrackerStat::getFavicon() const
{
return qApp->faviconCache().find(QUrl(announce));
}