1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
7 *
8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
9 *
10 * $Id: torrent.h 13553 2012-10-07 17:51:56Z jordan $
11 */
12
13#ifndef QTR_TORRENT_H
14#define QTR_TORRENT_H
15
16#include <QObject>
17#include <QIcon>
18#include <QMetaType>
19#include <QDateTime>
20#include <QString>
21#include <QStringList>
22#include <QList>
23#include <QTemporaryFile>
24#include <QVariant>
25
26#include <libtransmission/transmission.h>
27
28#include "speed.h"
29#include "types.h"
30
31extern "C"
32{
33    struct tr_benc;
34}
35
36class Prefs;
37class QPixmap;
38class QStyle;
39
40struct Peer
41{
42    QString address;
43    QString clientName;
44    bool clientIsChoked;
45    bool clientIsInterested;
46    QString flagStr;
47    bool isDownloadingFrom;
48    bool isEncrypted;
49    bool isIncoming;
50    bool isUploadingTo;
51    bool peerIsChoked;
52    bool peerIsInterested;
53    int port;
54    double progress;
55    Speed rateToClient;
56    Speed rateToPeer;
57};
58
59typedef QList<Peer> PeerList;
60Q_DECLARE_METATYPE(Peer)
61Q_DECLARE_METATYPE(PeerList)
62
63struct TrackerStat
64{
65    QString announce;
66    int announceState;
67    int downloadCount;
68    bool hasAnnounced;
69    bool hasScraped;
70    QString host;
71    int id;
72    bool isBackup;
73    int lastAnnouncePeerCount;
74    QString lastAnnounceResult;
75    int lastAnnounceStartTime;
76    bool lastAnnounceSucceeded;
77    int lastAnnounceTime;
78    bool lastAnnounceTimedOut;
79    QString lastScrapeResult;
80    int lastScrapeStartTime;
81    bool lastScrapeSucceeded;
82    int lastScrapeTime;
83    bool lastScrapeTimedOut;
84    int leecherCount;
85    int nextAnnounceTime;
86    int nextScrapeTime;
87    int scrapeState;
88    int seederCount;
89    int tier;
90    QPixmap getFavicon( ) const;
91};
92
93typedef QList<TrackerStat> TrackerStatsList;
94Q_DECLARE_METATYPE(TrackerStat)
95Q_DECLARE_METATYPE(TrackerStatsList)
96
97struct TrFile
98{
99    TrFile(): index(-1), priority(0), wanted(true), size(0), have(0) { }
100    int index;
101    int priority;
102    bool wanted;
103    uint64_t size;
104    uint64_t have;
105    QString filename;
106};
107
108typedef QList<TrFile> FileList;
109Q_DECLARE_METATYPE(TrFile)
110Q_DECLARE_METATYPE(FileList)
111
112
113class Torrent: public QObject
114{
115        Q_OBJECT;
116
117    public:
118
119        enum
120        {
121            ID,
122            UPLOAD_SPEED,
123            DOWNLOAD_SPEED,
124            DOWNLOAD_DIR,
125            ACTIVITY,
126            NAME,
127            ERROR,
128            ERROR_STRING,
129            SIZE_WHEN_DONE,
130            LEFT_UNTIL_DONE,
131            HAVE_UNCHECKED,
132            HAVE_VERIFIED,
133            DESIRED_AVAILABLE,
134            TOTAL_SIZE,
135            PIECE_SIZE,
136            PIECE_COUNT,
137            PEERS_GETTING_FROM_US,
138            PEERS_SENDING_TO_US,
139            WEBSEEDS_SENDING_TO_US,
140            PERCENT_DONE,
141            METADATA_PERCENT_DONE,
142            PERCENT_VERIFIED,
143            DATE_ACTIVITY,
144            DATE_ADDED,
145            DATE_STARTED,
146            DATE_CREATED,
147            PEERS_CONNECTED,
148            ETA,
149            RATIO,
150            DOWNLOADED_EVER,
151            UPLOADED_EVER,
152            FAILED_EVER,
153            TRACKERS,
154            TRACKERSTATS,
155            MIME_ICON,
156            SEED_RATIO_LIMIT,
157            SEED_RATIO_MODE,
158            SEED_IDLE_LIMIT,
159            SEED_IDLE_MODE,
160            DOWN_LIMIT,
161            DOWN_LIMITED,
162            UP_LIMIT,
163            UP_LIMITED,
164            HONORS_SESSION_LIMITS,
165            PEER_LIMIT,
166            HASH_STRING,
167            IS_FINISHED,
168            IS_PRIVATE,
169            IS_STALLED,
170            COMMENT,
171            CREATOR,
172            MANUAL_ANNOUNCE_TIME,
173            PEERS,
174            TORRENT_FILE,
175            BANDWIDTH_PRIORITY,
176            QUEUE_POSITION,
177
178            PROPERTY_COUNT
179        };
180
181    public:
182        Torrent( Prefs&, int id );
183        virtual ~Torrent( );
184
185    signals:
186        void torrentChanged( int id );
187        void torrentCompleted( int id );
188
189    private:
190
191        enum Group
192        {
193            INFO, // info fields that only need to be loaded once
194            STAT, // commonly-used stats that should be refreshed often
195            STAT_EXTRA,  // rarely used; only refresh if details dialog is open
196            DERIVED // doesn't come from RPC
197        };
198
199        struct Property
200        {
201            int id;
202            const char * key;
203            int type;
204            int group;
205        };
206
207        static Property myProperties[];
208
209        bool magnetTorrent;
210
211    public:
212        typedef QList<const char*> KeyList;
213        static const KeyList& getInfoKeys( );
214        static const KeyList& getStatKeys( );
215        static const KeyList& getExtraStatKeys( );
216
217    private:
218        static KeyList buildKeyList( Group group );
219
220    private:
221        QVariant myValues[PROPERTY_COUNT];
222
223        int getInt            ( int key ) const;
224        bool getBool          ( int key ) const;
225        QTime getTime         ( int key ) const;
226        QIcon getIcon         ( int key ) const;
227        double getDouble      ( int key ) const;
228        qulonglong getSize    ( int key ) const;
229        QString getString     ( int key ) const;
230        QDateTime getDateTime ( int key ) const;
231
232        bool setInt        ( int key, int value );
233        bool setBool       ( int key, bool value );
234        bool setIcon       ( int key, const QIcon& );
235        bool setDouble     ( int key, double );
236        bool setString     ( int key, const char * );
237        bool setSize       ( int key, qulonglong );
238        bool setDateTime   ( int key, const QDateTime& );
239
240    public:
241        int getBandwidthPriority( ) const { return getInt( BANDWIDTH_PRIORITY ); }
242        int id( ) const { return getInt( ID ); }
243        QString name( ) const { return getString( NAME ); }
244        QString creator( ) const { return getString( CREATOR ); }
245        QString comment( ) const { return getString( COMMENT ); }
246        QString getPath( ) const { return getString( DOWNLOAD_DIR ); }
247        QString getError( ) const;
248        QString hashString( ) const { return getString( HASH_STRING ); }
249        QString torrentFile( ) const { return getString( TORRENT_FILE ); }
250        bool hasError( ) const { return !getError( ).isEmpty( ); }
251        bool isDone( ) const { return getSize( LEFT_UNTIL_DONE ) == 0; }
252        bool isSeed( ) const { return haveVerified() >= totalSize(); }
253        bool isPrivate( ) const { return getBool( IS_PRIVATE ); }
254        bool getSeedRatio( double& setme ) const;
255        uint64_t haveVerified( ) const { return getSize( HAVE_VERIFIED ); }
256        uint64_t haveUnverified( ) const { return getSize( HAVE_UNCHECKED ); }
257        uint64_t desiredAvailable( ) const { return getSize( DESIRED_AVAILABLE ); }
258        uint64_t haveTotal( ) const { return haveVerified( ) + haveUnverified(); }
259        uint64_t totalSize( ) const { return getSize( TOTAL_SIZE ); }
260        uint64_t sizeWhenDone( ) const { return getSize( SIZE_WHEN_DONE ); }
261        uint64_t leftUntilDone( ) const { return getSize( LEFT_UNTIL_DONE ); }
262        uint64_t pieceSize( ) const { return getSize( PIECE_SIZE ); }
263        bool hasMetadata( ) const { return getDouble( METADATA_PERCENT_DONE ) >= 1.0; }
264        bool isMagnet( ) const { return magnetTorrent; }
265        int  pieceCount( ) const { return getInt( PIECE_COUNT ); }
266        double ratio( ) const { return getDouble( RATIO ); }
267        double percentComplete( ) const { return haveTotal() / (double)totalSize(); }
268        double percentDone( ) const { return getDouble( PERCENT_DONE ); }
269        double metadataPercentDone( ) const { return getDouble( METADATA_PERCENT_DONE ); }
270        uint64_t downloadedEver( ) const { return getSize( DOWNLOADED_EVER ); }
271        uint64_t uploadedEver( ) const { return getSize( UPLOADED_EVER ); }
272        uint64_t failedEver( ) const { return getSize( FAILED_EVER ); }
273        int compareTracker( const Torrent& ) const;
274        int compareSeedRatio( const Torrent& ) const;
275        int compareRatio( const Torrent& ) const;
276        int compareETA( const Torrent& ) const;
277        bool hasETA( ) const { return getETA( ) >= 0; }
278        int getETA( ) const { return getInt( ETA ); }
279        QDateTime lastActivity( ) const { return getDateTime( DATE_ACTIVITY ); }
280        QDateTime lastStarted( ) const { return getDateTime( DATE_STARTED ); }
281        QDateTime dateAdded( ) const { return getDateTime( DATE_ADDED ); }
282        QDateTime dateCreated( ) const { return getDateTime( DATE_CREATED ); }
283        QDateTime manualAnnounceTime( ) const { return getDateTime( MANUAL_ANNOUNCE_TIME ); }
284        bool canManualAnnounce( ) const { return isReadyToTransfer() && (manualAnnounceTime()<=QDateTime::currentDateTime()); }
285        int peersWeAreDownloadingFrom( ) const { return getInt( PEERS_SENDING_TO_US ); }
286        int webseedsWeAreDownloadingFrom( ) const { return getInt( WEBSEEDS_SENDING_TO_US ); }
287        int peersWeAreUploadingTo( ) const { return getInt( PEERS_GETTING_FROM_US ); }
288        bool isUploading( ) const { return peersWeAreUploadingTo( ) > 0; }
289        int connectedPeers( ) const { return getInt( PEERS_CONNECTED ); }
290        int connectedPeersAndWebseeds( ) const { return connectedPeers( ) + getInt( WEBSEEDS_SENDING_TO_US ); }
291        Speed downloadSpeed( ) const { return Speed::fromBps( getSize( DOWNLOAD_SPEED ) ); }
292        Speed uploadSpeed( ) const { return Speed::fromBps( getSize( UPLOAD_SPEED ) ); }
293        double getVerifyProgress( ) const { return getDouble( PERCENT_VERIFIED ); }
294        bool hasFileSubstring( const QString& substr ) const;
295        bool hasTrackerSubstring( const QString& substr ) const;
296        Speed uploadLimit( ) const { return Speed::fromKBps( getInt( UP_LIMIT ) ); }
297        Speed downloadLimit( ) const { return Speed::fromKBps( getInt( DOWN_LIMIT ) ); }
298        bool uploadIsLimited( ) const { return getBool( UP_LIMITED ); }
299        bool downloadIsLimited( ) const { return getBool( DOWN_LIMITED ); }
300        bool honorsSessionLimits( ) const { return getBool( HONORS_SESSION_LIMITS ); }
301        int peerLimit( ) const { return getInt( PEER_LIMIT ); }
302        double seedRatioLimit( ) const { return getDouble( SEED_RATIO_LIMIT ); }
303        tr_ratiolimit seedRatioMode( ) const { return (tr_ratiolimit) getInt( SEED_RATIO_MODE ); }
304        int seedIdleLimit( ) const { return getInt( SEED_IDLE_LIMIT ); }
305        tr_idlelimit seedIdleMode( ) const { return (tr_idlelimit) getInt( SEED_IDLE_MODE ); }
306        TrackerStatsList trackerStats( ) const{ return myValues[TRACKERSTATS].value<TrackerStatsList>(); }
307        QStringList trackers() const { return myValues[TRACKERS].value<QStringList>(); }
308        PeerList peers( ) const{ return myValues[PEERS].value<PeerList>(); }
309        const FileList& files( ) const { return myFiles; }
310        int queuePosition( ) const { return getInt( QUEUE_POSITION ); }
311        bool isStalled( ) const { return getBool( IS_STALLED ); }
312
313    public:
314        QString activityString( ) const;
315        tr_torrent_activity getActivity( ) const { return (tr_torrent_activity) getInt( ACTIVITY ); }
316        bool isFinished( ) const { return getBool( IS_FINISHED ); }
317        bool isPaused( ) const { return getActivity( ) == TR_STATUS_STOPPED; }
318        bool isWaitingToVerify( ) const { return getActivity( ) == TR_STATUS_CHECK_WAIT; }
319        bool isVerifying( ) const { return getActivity( ) == TR_STATUS_CHECK; }
320        bool isDownloading( ) const { return getActivity( ) == TR_STATUS_DOWNLOAD; }
321        bool isWaitingToDownload( ) const { return getActivity( ) == TR_STATUS_DOWNLOAD_WAIT; }
322        bool isSeeding( ) const { return getActivity( ) == TR_STATUS_SEED; }
323        bool isWaitingToSeed( ) const { return getActivity( ) == TR_STATUS_SEED_WAIT; }
324        bool isReadyToTransfer( ) const { return getActivity()==TR_STATUS_DOWNLOAD || getActivity()==TR_STATUS_SEED; }
325        bool isQueued( ) const { return isWaitingToDownload() || isWaitingToSeed(); }
326        void notifyComplete( ) const;
327
328    public:
329        void update( tr_benc * dict );
330        void setMagnet( bool magnet ) { magnetTorrent = magnet; }
331
332    private:
333        const char * getMimeTypeString( ) const;
334        void updateMimeIcon( );
335
336    public:
337        QIcon getMimeTypeIcon( ) const { return getIcon( MIME_ICON ); }
338
339    private:
340        Prefs& myPrefs;
341        FileList myFiles;
342};
343
344Q_DECLARE_METATYPE(const Torrent*)
345
346#endif
347
348