/* * 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 // time_t #include #include #include #include #include #include #include #include #include #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 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 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 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 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 totalSize() != 0 ? haveTotal() / static_cast(totalSize()) : 0; } 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); } time_t lastActivity() const { return getTime(DATE_ACTIVITY); } time_t lastStarted() const { return getTime(DATE_STARTED); } time_t dateAdded() const { return getTime(DATE_ADDED); } time_t dateCreated() const { return getTime(DATE_CREATED); } time_t manualAnnounceTime() const { return getTime(MANUAL_ANNOUNCE_TIME); } bool canManualAnnounceAt(time_t t) const { return isReadyToTransfer() && (manualAnnounceTime() <= t); } 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(getInt(SEED_RATIO_MODE)); } int seedIdleLimit() const { return getInt(SEED_IDLE_LIMIT); } tr_idlelimit seedIdleMode() const { return static_cast(getInt(SEED_IDLE_MODE)); } TrackerStatsList trackerStats() const { return myValues[TRACKERSTATS].value(); } QStringList trackers() const { return myValues[TRACKERS].value(); } QStringList hosts() const { return myValues[HOSTS].value(); } PeerList peers() const { return myValues[PEERS].value(); } 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(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; QIcon getIcon(int key) const; double getDouble(int key) const; qulonglong getSize(int key) const; QString getString(int key) const; time_t getTime(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 setTime(int key, time_t); 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*)