653 lines
12 KiB
C++
653 lines
12 KiB
C++
/*
|
|
* This file Copyright (C) 2009-2015 Mnemosyne LLC
|
|
*
|
|
* It may be used under the GNU GPL versions 2 or 3
|
|
* or any future license endorsed by Mnemosyne LLC.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <QObject>
|
|
#include <QIcon>
|
|
#include <QMetaType>
|
|
#include <QDateTime>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
#include <QList>
|
|
#include <QVariant>
|
|
|
|
#include <libtransmission/transmission.h>
|
|
#include <libtransmission/quark.h>
|
|
|
|
#include "CustomVariantType.h"
|
|
#include "Speed.h"
|
|
|
|
#ifdef ERROR
|
|
#undef ERROR
|
|
#endif
|
|
|
|
class QPixmap;
|
|
|
|
class Prefs;
|
|
|
|
extern "C"
|
|
{
|
|
struct tr_variant;
|
|
}
|
|
|
|
struct Peer
|
|
{
|
|
bool clientIsChoked;
|
|
bool clientIsInterested;
|
|
bool isDownloadingFrom;
|
|
bool isEncrypted;
|
|
bool isIncoming;
|
|
bool isUploadingTo;
|
|
bool peerIsChoked;
|
|
bool peerIsInterested;
|
|
QString address;
|
|
QString clientName;
|
|
QString flagStr;
|
|
int port;
|
|
Speed rateToClient;
|
|
Speed rateToPeer;
|
|
double progress;
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(Peer)
|
|
|
|
typedef QList<Peer> PeerList;
|
|
Q_DECLARE_METATYPE(PeerList)
|
|
|
|
struct TrackerStat
|
|
{
|
|
QPixmap getFavicon() const;
|
|
|
|
bool hasAnnounced;
|
|
bool hasScraped;
|
|
bool isBackup;
|
|
bool lastAnnounceSucceeded;
|
|
bool lastAnnounceTimedOut;
|
|
bool lastScrapeSucceeded;
|
|
bool lastScrapeTimedOut;
|
|
int announceState;
|
|
int downloadCount;
|
|
int id;
|
|
int lastAnnouncePeerCount;
|
|
int lastAnnounceStartTime;
|
|
int lastAnnounceTime;
|
|
int lastScrapeStartTime;
|
|
int lastScrapeTime;
|
|
int leecherCount;
|
|
int nextAnnounceTime;
|
|
int nextScrapeTime;
|
|
int scrapeState;
|
|
int seederCount;
|
|
int tier;
|
|
QString announce;
|
|
QString host;
|
|
QString lastAnnounceResult;
|
|
QString lastScrapeResult;
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(TrackerStat)
|
|
|
|
typedef QList<TrackerStat> TrackerStatsList;
|
|
Q_DECLARE_METATYPE(TrackerStatsList)
|
|
|
|
struct TorrentFile
|
|
{
|
|
TorrentFile() :
|
|
wanted(true),
|
|
index(-1),
|
|
priority(0),
|
|
size(0),
|
|
have(0)
|
|
{
|
|
}
|
|
|
|
bool wanted;
|
|
int index;
|
|
int priority;
|
|
QString filename;
|
|
uint64_t size;
|
|
uint64_t have;
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(TorrentFile)
|
|
|
|
typedef QList<TorrentFile> FileList;
|
|
Q_DECLARE_METATYPE(FileList)
|
|
|
|
class Torrent : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
enum
|
|
{
|
|
ID,
|
|
UPLOAD_SPEED,
|
|
DOWNLOAD_SPEED,
|
|
DOWNLOAD_DIR,
|
|
ACTIVITY,
|
|
NAME,
|
|
ERROR,
|
|
ERROR_STRING,
|
|
SIZE_WHEN_DONE,
|
|
LEFT_UNTIL_DONE,
|
|
HAVE_UNCHECKED,
|
|
HAVE_VERIFIED,
|
|
DESIRED_AVAILABLE,
|
|
TOTAL_SIZE,
|
|
PIECE_SIZE,
|
|
PIECE_COUNT,
|
|
PEERS_GETTING_FROM_US,
|
|
PEERS_SENDING_TO_US,
|
|
WEBSEEDS_SENDING_TO_US,
|
|
PERCENT_DONE,
|
|
METADATA_PERCENT_DONE,
|
|
PERCENT_VERIFIED,
|
|
DATE_ACTIVITY,
|
|
DATE_ADDED,
|
|
DATE_STARTED,
|
|
DATE_CREATED,
|
|
PEERS_CONNECTED,
|
|
ETA,
|
|
RATIO,
|
|
DOWNLOADED_EVER,
|
|
UPLOADED_EVER,
|
|
FAILED_EVER,
|
|
TRACKERS,
|
|
HOSTS,
|
|
TRACKERSTATS,
|
|
MIME_ICON,
|
|
SEED_RATIO_LIMIT,
|
|
SEED_RATIO_MODE,
|
|
SEED_IDLE_LIMIT,
|
|
SEED_IDLE_MODE,
|
|
DOWN_LIMIT,
|
|
DOWN_LIMITED,
|
|
UP_LIMIT,
|
|
UP_LIMITED,
|
|
HONORS_SESSION_LIMITS,
|
|
PEER_LIMIT,
|
|
HASH_STRING,
|
|
IS_FINISHED,
|
|
IS_PRIVATE,
|
|
IS_STALLED,
|
|
COMMENT,
|
|
CREATOR,
|
|
MANUAL_ANNOUNCE_TIME,
|
|
PEERS,
|
|
BANDWIDTH_PRIORITY,
|
|
QUEUE_POSITION,
|
|
//
|
|
PROPERTY_COUNT
|
|
};
|
|
|
|
typedef QList<tr_quark> KeyList;
|
|
|
|
public:
|
|
Torrent(Prefs const&, int id);
|
|
virtual ~Torrent();
|
|
|
|
int getBandwidthPriority() const
|
|
{
|
|
return getInt(BANDWIDTH_PRIORITY);
|
|
}
|
|
|
|
int id() const
|
|
{
|
|
return getInt(ID);
|
|
}
|
|
|
|
QString name() const
|
|
{
|
|
return getString(NAME);
|
|
}
|
|
|
|
QString creator() const
|
|
{
|
|
return getString(CREATOR);
|
|
}
|
|
|
|
QString comment() const
|
|
{
|
|
return getString(COMMENT);
|
|
}
|
|
|
|
QString getPath() const
|
|
{
|
|
return getString(DOWNLOAD_DIR);
|
|
}
|
|
|
|
QString getError() const;
|
|
|
|
QString hashString() const
|
|
{
|
|
return getString(HASH_STRING);
|
|
}
|
|
|
|
bool hasError() const
|
|
{
|
|
return !getError().isEmpty();
|
|
}
|
|
|
|
bool isDone() const
|
|
{
|
|
return getSize(LEFT_UNTIL_DONE) == 0;
|
|
}
|
|
|
|
bool isSeed() const
|
|
{
|
|
return haveVerified() >= totalSize();
|
|
}
|
|
|
|
bool isPrivate() const
|
|
{
|
|
return getBool(IS_PRIVATE);
|
|
}
|
|
|
|
bool getSeedRatio(double& setme) const;
|
|
|
|
uint64_t haveVerified() const
|
|
{
|
|
return getSize(HAVE_VERIFIED);
|
|
}
|
|
|
|
uint64_t haveUnverified() const
|
|
{
|
|
return getSize(HAVE_UNCHECKED);
|
|
}
|
|
|
|
uint64_t desiredAvailable() const
|
|
{
|
|
return getSize(DESIRED_AVAILABLE);
|
|
}
|
|
|
|
uint64_t haveTotal() const
|
|
{
|
|
return haveVerified() + haveUnverified();
|
|
}
|
|
|
|
uint64_t totalSize() const
|
|
{
|
|
return getSize(TOTAL_SIZE);
|
|
}
|
|
|
|
uint64_t sizeWhenDone() const
|
|
{
|
|
return getSize(SIZE_WHEN_DONE);
|
|
}
|
|
|
|
uint64_t leftUntilDone() const
|
|
{
|
|
return getSize(LEFT_UNTIL_DONE);
|
|
}
|
|
|
|
uint64_t pieceSize() const
|
|
{
|
|
return getSize(PIECE_SIZE);
|
|
}
|
|
|
|
bool hasMetadata() const
|
|
{
|
|
return getDouble(METADATA_PERCENT_DONE) >= 1.0;
|
|
}
|
|
|
|
bool isMagnet() const
|
|
{
|
|
return magnetTorrent;
|
|
}
|
|
|
|
int pieceCount() const
|
|
{
|
|
return getInt(PIECE_COUNT);
|
|
}
|
|
|
|
double ratio() const
|
|
{
|
|
return getDouble(RATIO);
|
|
}
|
|
|
|
double percentComplete() const
|
|
{
|
|
return haveTotal() / static_cast<double>(totalSize());
|
|
}
|
|
|
|
double percentDone() const
|
|
{
|
|
return getDouble(PERCENT_DONE);
|
|
}
|
|
|
|
double metadataPercentDone() const
|
|
{
|
|
return getDouble(METADATA_PERCENT_DONE);
|
|
}
|
|
|
|
uint64_t downloadedEver() const
|
|
{
|
|
return getSize(DOWNLOADED_EVER);
|
|
}
|
|
|
|
uint64_t uploadedEver() const
|
|
{
|
|
return getSize(UPLOADED_EVER);
|
|
}
|
|
|
|
uint64_t failedEver() const
|
|
{
|
|
return getSize(FAILED_EVER);
|
|
}
|
|
|
|
int compareTracker(Torrent const&) const;
|
|
int compareSeedRatio(Torrent const&) const;
|
|
int compareRatio(Torrent const&) const;
|
|
int compareETA(Torrent const&) const;
|
|
|
|
bool hasETA() const
|
|
{
|
|
return getETA() >= 0;
|
|
}
|
|
|
|
int getETA() const
|
|
{
|
|
return getInt(ETA);
|
|
}
|
|
|
|
QDateTime lastActivity() const
|
|
{
|
|
return getDateTime(DATE_ACTIVITY);
|
|
}
|
|
|
|
QDateTime lastStarted() const
|
|
{
|
|
return getDateTime(DATE_STARTED);
|
|
}
|
|
|
|
QDateTime dateAdded() const
|
|
{
|
|
return getDateTime(DATE_ADDED);
|
|
}
|
|
|
|
QDateTime dateCreated() const
|
|
{
|
|
return getDateTime(DATE_CREATED);
|
|
}
|
|
|
|
QDateTime manualAnnounceTime() const
|
|
{
|
|
return getDateTime(MANUAL_ANNOUNCE_TIME);
|
|
}
|
|
|
|
bool canManualAnnounce() const
|
|
{
|
|
return isReadyToTransfer() && (manualAnnounceTime() <= QDateTime::currentDateTime());
|
|
}
|
|
|
|
int peersWeAreDownloadingFrom() const
|
|
{
|
|
return getInt(PEERS_SENDING_TO_US);
|
|
}
|
|
|
|
int webseedsWeAreDownloadingFrom() const
|
|
{
|
|
return getInt(WEBSEEDS_SENDING_TO_US);
|
|
}
|
|
|
|
int peersWeAreUploadingTo() const
|
|
{
|
|
return getInt(PEERS_GETTING_FROM_US);
|
|
}
|
|
|
|
bool isUploading() const
|
|
{
|
|
return peersWeAreUploadingTo() > 0;
|
|
}
|
|
|
|
int connectedPeers() const
|
|
{
|
|
return getInt(PEERS_CONNECTED);
|
|
}
|
|
|
|
int connectedPeersAndWebseeds() const
|
|
{
|
|
return connectedPeers() + getInt(WEBSEEDS_SENDING_TO_US);
|
|
}
|
|
|
|
Speed downloadSpeed() const
|
|
{
|
|
return Speed::fromBps(getSize(DOWNLOAD_SPEED));
|
|
}
|
|
|
|
Speed uploadSpeed() const
|
|
{
|
|
return Speed::fromBps(getSize(UPLOAD_SPEED));
|
|
}
|
|
|
|
double getVerifyProgress() const
|
|
{
|
|
return getDouble(PERCENT_VERIFIED);
|
|
}
|
|
|
|
bool hasFileSubstring(QString const& substr) const;
|
|
bool hasTrackerSubstring(QString const& substr) const;
|
|
|
|
Speed uploadLimit() const
|
|
{
|
|
return Speed::fromKBps(getInt(UP_LIMIT));
|
|
}
|
|
|
|
Speed downloadLimit() const
|
|
{
|
|
return Speed::fromKBps(getInt(DOWN_LIMIT));
|
|
}
|
|
|
|
bool uploadIsLimited() const
|
|
{
|
|
return getBool(UP_LIMITED);
|
|
}
|
|
|
|
bool downloadIsLimited() const
|
|
{
|
|
return getBool(DOWN_LIMITED);
|
|
}
|
|
|
|
bool honorsSessionLimits() const
|
|
{
|
|
return getBool(HONORS_SESSION_LIMITS);
|
|
}
|
|
|
|
int peerLimit() const
|
|
{
|
|
return getInt(PEER_LIMIT);
|
|
}
|
|
|
|
double seedRatioLimit() const
|
|
{
|
|
return getDouble(SEED_RATIO_LIMIT);
|
|
}
|
|
|
|
tr_ratiolimit seedRatioMode() const
|
|
{
|
|
return static_cast<tr_ratiolimit>(getInt(SEED_RATIO_MODE));
|
|
}
|
|
|
|
int seedIdleLimit() const
|
|
{
|
|
return getInt(SEED_IDLE_LIMIT);
|
|
}
|
|
|
|
tr_idlelimit seedIdleMode() const
|
|
{
|
|
return static_cast<tr_idlelimit>(getInt(SEED_IDLE_MODE));
|
|
}
|
|
|
|
TrackerStatsList trackerStats() const
|
|
{
|
|
return myValues[TRACKERSTATS].value<TrackerStatsList>();
|
|
}
|
|
|
|
QStringList trackers() const
|
|
{
|
|
return myValues[TRACKERS].value<QStringList>();
|
|
}
|
|
|
|
QStringList hosts() const
|
|
{
|
|
return myValues[HOSTS].value<QStringList>();
|
|
}
|
|
|
|
PeerList peers() const
|
|
{
|
|
return myValues[PEERS].value<PeerList>();
|
|
}
|
|
|
|
FileList const& files() const
|
|
{
|
|
return myFiles;
|
|
}
|
|
|
|
int queuePosition() const
|
|
{
|
|
return getInt(QUEUE_POSITION);
|
|
}
|
|
|
|
bool isStalled() const
|
|
{
|
|
return getBool(IS_STALLED);
|
|
}
|
|
|
|
QString activityString() const;
|
|
|
|
tr_torrent_activity getActivity() const
|
|
{
|
|
return static_cast<tr_torrent_activity>(getInt(ACTIVITY));
|
|
}
|
|
|
|
bool isFinished() const
|
|
{
|
|
return getBool(IS_FINISHED);
|
|
}
|
|
|
|
bool isPaused() const
|
|
{
|
|
return getActivity() == TR_STATUS_STOPPED;
|
|
}
|
|
|
|
bool isWaitingToVerify() const
|
|
{
|
|
return getActivity() == TR_STATUS_CHECK_WAIT;
|
|
}
|
|
|
|
bool isVerifying() const
|
|
{
|
|
return getActivity() == TR_STATUS_CHECK;
|
|
}
|
|
|
|
bool isDownloading() const
|
|
{
|
|
return getActivity() == TR_STATUS_DOWNLOAD;
|
|
}
|
|
|
|
bool isWaitingToDownload() const
|
|
{
|
|
return getActivity() == TR_STATUS_DOWNLOAD_WAIT;
|
|
}
|
|
|
|
bool isSeeding() const
|
|
{
|
|
return getActivity() == TR_STATUS_SEED;
|
|
}
|
|
|
|
bool isWaitingToSeed() const
|
|
{
|
|
return getActivity() == TR_STATUS_SEED_WAIT;
|
|
}
|
|
|
|
bool isReadyToTransfer() const
|
|
{
|
|
return getActivity() == TR_STATUS_DOWNLOAD || getActivity() == TR_STATUS_SEED;
|
|
}
|
|
|
|
bool isQueued() const
|
|
{
|
|
return isWaitingToDownload() || isWaitingToSeed();
|
|
}
|
|
|
|
void notifyComplete() const;
|
|
|
|
void update(tr_variant* dict);
|
|
|
|
void setMagnet(bool magnet)
|
|
{
|
|
magnetTorrent = magnet;
|
|
}
|
|
|
|
QIcon getMimeTypeIcon() const
|
|
{
|
|
return getIcon(MIME_ICON);
|
|
}
|
|
|
|
static KeyList const& getInfoKeys();
|
|
static KeyList const& getStatKeys();
|
|
static KeyList const& getExtraStatKeys();
|
|
|
|
signals:
|
|
void torrentChanged(int id);
|
|
void torrentCompleted(int id);
|
|
|
|
private:
|
|
enum Group
|
|
{
|
|
INFO, // info fields that only need to be loaded once
|
|
STAT, // commonly-used stats that should be refreshed often
|
|
STAT_EXTRA, // rarely used; only refresh if details dialog is open
|
|
DERIVED // doesn't come from RPC
|
|
};
|
|
|
|
struct Property
|
|
{
|
|
int id;
|
|
tr_quark key;
|
|
int type;
|
|
int group;
|
|
};
|
|
|
|
private:
|
|
int getInt(int key) const;
|
|
bool getBool(int key) const;
|
|
QTime getTime(int key) const;
|
|
QIcon getIcon(int key) const;
|
|
double getDouble(int key) const;
|
|
qulonglong getSize(int key) const;
|
|
QString getString(int key) const;
|
|
QDateTime getDateTime(int key) const;
|
|
|
|
bool setInt(int key, int value);
|
|
bool setBool(int key, bool value);
|
|
bool setIcon(int key, QIcon const&);
|
|
bool setDouble(int key, double);
|
|
bool setString(int key, char const*);
|
|
bool setSize(int key, qulonglong);
|
|
bool setDateTime(int key, QDateTime const&);
|
|
|
|
char const* getMimeTypeString() const;
|
|
void updateMimeIcon();
|
|
|
|
static KeyList buildKeyList(Group group);
|
|
|
|
private:
|
|
Prefs const& myPrefs;
|
|
|
|
QVariant myValues[PROPERTY_COUNT];
|
|
bool magnetTorrent;
|
|
FileList myFiles;
|
|
|
|
static Property myProperties[];
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(Torrent const*)
|