source: trunk/qt/torrent.cc @ 11194

Last change on this file since 11194 was 11194, checked in by charles, 12 years ago

(trunk) revert the RPC behavior of rateUpload, rateDownload, rateToClient, and rateToPeer as discussed with Longinus00

  • Property svn:keywords set to Date Rev Author Id
File size: 21.3 KB
Line 
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.cc 11194 2010-09-03 04:30:43Z charles $
11 */
12
13#include <cassert>
14#include <iostream>
15
16#include <QApplication>
17#include <QFileIconProvider>
18#include <QFileInfo>
19#include <QSet>
20#include <QString>
21#include <QStyle>
22#include <QUrl>
23#include <QVariant>
24
25#include <libtransmission/transmission.h>
26#include <libtransmission/bencode.h>
27#include <libtransmission/utils.h> /* tr_new0, tr_strdup */
28
29#include "app.h"
30#include "prefs.h"
31#include "torrent.h"
32#include "utils.h"
33
34
35Torrent :: Torrent( Prefs& prefs, int id ):
36    magnetTorrent( false ),
37    myPrefs( prefs )
38{
39    for( int i=0; i<PROPERTY_COUNT; ++i )
40        assert( myProperties[i].id == i );
41
42    setInt( ID, id );
43    setIcon( MIME_ICON, QApplication::style()->standardIcon( QStyle::SP_FileIcon ) );
44}
45
46Torrent :: ~Torrent( )
47{
48}
49
50/***
51****
52***/
53
54Torrent :: Property
55Torrent :: myProperties[] =
56{
57    { ID, "id", QVariant::Int, INFO, },
58    { UPLOAD_SPEED, "rateUpload", QVariant::ULongLong, STAT } /* Bps */,
59    { DOWNLOAD_SPEED, "rateDownload", QVariant::ULongLong, STAT }, /* Bps */
60    { DOWNLOAD_DIR, "downloadDir", QVariant::String, STAT },
61    { ACTIVITY, "status", QVariant::Int, STAT },
62    { NAME, "name", QVariant::String, INFO },
63    { ERROR, "error", QVariant::Int, STAT },
64    { ERROR_STRING, "errorString", QVariant::String, STAT },
65    { SIZE_WHEN_DONE, "sizeWhenDone", QVariant::ULongLong, STAT },
66    { LEFT_UNTIL_DONE, "leftUntilDone", QVariant::ULongLong, STAT },
67    { HAVE_UNCHECKED, "haveUnchecked", QVariant::ULongLong, STAT },
68    { HAVE_VERIFIED, "haveValid", QVariant::ULongLong, STAT },
69    { DESIRED_AVAILABLE, "desiredAvailable", QVariant::ULongLong, STAT },
70    { TOTAL_SIZE, "totalSize", QVariant::ULongLong, INFO },
71    { PIECE_SIZE, "pieceSize", QVariant::ULongLong, INFO },
72    { PIECE_COUNT, "pieceCount", QVariant::Int, INFO },
73    { PEERS_GETTING_FROM_US, "peersGettingFromUs", QVariant::Int, STAT },
74    { PEERS_SENDING_TO_US, "peersSendingToUs", QVariant::Int, STAT },
75    { WEBSEEDS_SENDING_TO_US, "webseedsSendingToUs", QVariant::Int, STAT_EXTRA },
76    { PERCENT_DONE, "percentDone", QVariant::Double, STAT },
77    { METADATA_PERCENT_DONE, "metadataPercentComplete", QVariant::Double, STAT },
78    { PERCENT_VERIFIED, "recheckProgress", QVariant::Double, STAT },
79    { DATE_ACTIVITY, "activityDate", QVariant::DateTime, STAT_EXTRA },
80    { DATE_ADDED, "addedDate", QVariant::DateTime, INFO },
81    { DATE_STARTED, "startDate", QVariant::DateTime, STAT_EXTRA },
82    { DATE_CREATED, "dateCreated", QVariant::DateTime, INFO },
83    { PEERS_CONNECTED, "peersConnected", QVariant::Int, STAT },
84    { ETA, "eta", QVariant::Int, STAT },
85    { RATIO, "uploadRatio", QVariant::Double, STAT },
86    { DOWNLOADED_EVER, "downloadedEver", QVariant::ULongLong, STAT },
87    { UPLOADED_EVER, "uploadedEver", QVariant::ULongLong, STAT },
88    { FAILED_EVER, "corruptEver", QVariant::ULongLong, STAT_EXTRA },
89    { TRACKERS, "trackers", QVariant::StringList, STAT },
90    { TRACKERSTATS, "trackerStats", TrTypes::TrackerStatsList, STAT_EXTRA },
91    { MIME_ICON, "ccc", QVariant::Icon, DERIVED },
92    { SEED_RATIO_LIMIT, "seedRatioLimit", QVariant::Double, STAT },
93    { SEED_RATIO_MODE, "seedRatioMode", QVariant::Int, STAT },
94    { SEED_IDLE_LIMIT, "seedIdleLimit", QVariant::Int, STAT_EXTRA },
95    { SEED_IDLE_MODE, "seedIdleMode", QVariant::Int, STAT_EXTRA },
96    { DOWN_LIMIT, "downloadLimit", QVariant::Int, STAT_EXTRA }, /* KB/s */
97    { DOWN_LIMITED, "downloadLimited", QVariant::Bool, STAT_EXTRA },
98    { UP_LIMIT, "uploadLimit", QVariant::Int, STAT_EXTRA }, /* KB/s */
99    { UP_LIMITED, "uploadLimited", QVariant::Bool, STAT_EXTRA },
100    { HONORS_SESSION_LIMITS, "honorsSessionLimits", QVariant::Bool, STAT_EXTRA },
101    { PEER_LIMIT, "peer-limit", QVariant::Int, STAT_EXTRA },
102    { HASH_STRING, "hashString", QVariant::String, INFO },
103    { IS_FINISHED, "isFinished", QVariant::Bool, STAT },
104    { IS_PRIVATE, "isPrivate", QVariant::Bool, INFO },
105    { COMMENT, "comment", QVariant::String, INFO },
106    { CREATOR, "creator", QVariant::String, INFO },
107    { MANUAL_ANNOUNCE_TIME, "manualAnnounceTime", QVariant::DateTime, STAT_EXTRA },
108    { PEERS, "peers", TrTypes::PeerList, STAT_EXTRA },
109    { TORRENT_FILE, "torrentFile", QVariant::String, STAT_EXTRA },
110    { BANDWIDTH_PRIORITY, "bandwidthPriority", QVariant::Int, STAT_EXTRA }
111};
112
113Torrent :: KeyList
114Torrent :: buildKeyList( Group group )
115{
116    KeyList keys;
117
118    if( keys.empty( ) )
119        for( int i=0; i<PROPERTY_COUNT; ++i )
120            if( myProperties[i].id==ID || myProperties[i].group==group )
121                keys << myProperties[i].key;
122
123    return keys;
124}
125
126const Torrent :: KeyList&
127Torrent :: getInfoKeys( )
128{
129    static KeyList keys;
130    if( keys.isEmpty( ) )
131        keys << buildKeyList( INFO ) << "files";
132    return keys;
133}
134
135const Torrent :: KeyList&
136Torrent :: getStatKeys( )
137{
138    static KeyList keys( buildKeyList( STAT ) );
139    return keys;
140}
141
142const Torrent :: KeyList&
143Torrent :: getExtraStatKeys( )
144{
145    static KeyList keys;
146    if( keys.isEmpty( ) )
147        keys << buildKeyList( STAT_EXTRA ) << "fileStats";
148    return keys;
149}
150
151
152bool
153Torrent :: setInt( int i, int value )
154{
155    bool changed = false;
156
157    assert( 0<=i && i<PROPERTY_COUNT );
158    assert( myProperties[i].type == QVariant::Int );
159
160    if( myValues[i].isNull() || myValues[i].toInt()!=value )
161    {
162        myValues[i].setValue( value );
163        changed = true;
164    }
165
166    return changed;
167}
168
169bool
170Torrent :: setBool( int i, bool value )
171{
172    bool changed = false;
173
174    assert( 0<=i && i<PROPERTY_COUNT );
175    assert( myProperties[i].type == QVariant::Bool );
176
177    if( myValues[i].isNull() || myValues[i].toBool()!=value )
178    {
179        myValues[i].setValue( value );
180        changed = true;
181    }
182
183    return changed;
184}
185
186bool
187Torrent :: setDouble( int i, double value )
188{
189    bool changed = false;
190
191    assert( 0<=i && i<PROPERTY_COUNT );
192    assert( myProperties[i].type == QVariant::Double );
193
194    if( myValues[i].isNull() || myValues[i].toDouble()!=value )
195    {
196        myValues[i].setValue( value );
197        changed = true;
198    }
199
200    return changed;
201}
202
203bool
204Torrent :: setDateTime( int i, const QDateTime& value )
205{
206    bool changed = false;
207
208    assert( 0<=i && i<PROPERTY_COUNT );
209    assert( myProperties[i].type == QVariant::DateTime );
210
211    if( myValues[i].isNull() || myValues[i].toDateTime()!=value )
212    {
213        myValues[i].setValue( value );
214        changed = true;
215    }
216
217    return changed;
218}
219
220bool
221Torrent :: setSize( int i, qulonglong value )
222{
223    bool changed = false;
224
225    assert( 0<=i && i<PROPERTY_COUNT );
226    assert( myProperties[i].type == QVariant::ULongLong );
227
228    if( myValues[i].isNull() || myValues[i].toULongLong()!=value )
229    {
230        myValues[i].setValue( value );
231        changed = true;
232    }
233
234    return changed;
235}
236
237bool
238Torrent :: setString( int i, const char * value )
239{
240    bool changed = false;
241
242    assert( 0<=i && i<PROPERTY_COUNT );
243    assert( myProperties[i].type == QVariant::String );
244
245    if( myValues[i].isNull() || myValues[i].toString()!=value )
246    {
247        myValues[i].setValue( QString::fromUtf8( value ) );
248        changed = true;
249    }
250
251    return changed;
252}
253
254bool
255Torrent :: setIcon( int i, const QIcon& value )
256{
257    assert( 0<=i && i<PROPERTY_COUNT );
258    assert( myProperties[i].type == QVariant::Icon );
259
260    myValues[i].setValue( value );
261    return true;
262}
263
264int
265Torrent :: getInt( int i ) const
266{
267    assert( 0<=i && i<PROPERTY_COUNT );
268    assert( myProperties[i].type == QVariant::Int );
269
270    return myValues[i].toInt( );
271}
272
273QDateTime
274Torrent :: getDateTime( int i ) const
275{
276    assert( 0<=i && i<PROPERTY_COUNT );
277    assert( myProperties[i].type == QVariant::DateTime );
278
279    return myValues[i].toDateTime( );
280}
281
282bool
283Torrent :: getBool( int i ) const
284{
285    assert( 0<=i && i<PROPERTY_COUNT );
286    assert( myProperties[i].type == QVariant::Bool );
287
288    return myValues[i].toBool( );
289}
290
291qulonglong
292Torrent :: getSize( int i ) const
293{
294    assert( 0<=i && i<PROPERTY_COUNT );
295    assert( myProperties[i].type == QVariant::ULongLong );
296
297    return myValues[i].toULongLong( );
298}
299double
300Torrent :: getDouble( int i ) const
301{
302    assert( 0<=i && i<PROPERTY_COUNT );
303    assert( myProperties[i].type == QVariant::Double );
304
305    return myValues[i].toDouble( );
306}
307QString
308Torrent :: getString( int i ) const
309{
310    assert( 0<=i && i<PROPERTY_COUNT );
311    assert( myProperties[i].type == QVariant::String );
312
313    return myValues[i].toString( );
314}
315QIcon
316Torrent :: getIcon( int i ) const
317{
318    assert( 0<=i && i<PROPERTY_COUNT );
319    assert( myProperties[i].type == QVariant::Icon );
320
321    return myValues[i].value<QIcon>();
322}
323
324/***
325****
326***/
327
328bool
329Torrent :: getSeedRatio( double& ratio ) const
330{
331    bool isLimited;
332
333    switch( seedRatioMode( ) )
334    {
335        case TR_RATIOLIMIT_SINGLE:
336            isLimited = true;
337            ratio = seedRatioLimit( );
338            break;
339
340        case TR_RATIOLIMIT_GLOBAL:
341            if(( isLimited = myPrefs.getBool( Prefs :: RATIO_ENABLED )))
342                ratio = myPrefs.getDouble( Prefs :: RATIO );
343            break;
344
345        case TR_RATIOLIMIT_UNLIMITED:
346            isLimited = false;
347            break;
348    }
349
350    return isLimited;
351}
352
353bool
354Torrent :: hasFileSubstring( const QString& substr ) const
355{
356    foreach( const TrFile file, myFiles )
357        if( file.filename.contains( substr, Qt::CaseInsensitive ) )
358            return true;
359    return false;
360}
361
362bool
363Torrent :: hasTrackerSubstring( const QString& substr ) const
364{
365    foreach( QString s, myValues[TRACKERS].toStringList() )
366        if( s.contains( substr, Qt::CaseInsensitive ) )
367            return true;
368    return false;
369}
370
371int
372Torrent :: compareRatio( const Torrent& that ) const
373{
374    const double a = ratio( );
375    const double b = that.ratio( );
376    if( (int)a == TR_RATIO_INF && (int)b == TR_RATIO_INF ) return 0;
377    if( (int)a == TR_RATIO_INF ) return 1;
378    if( (int)b == TR_RATIO_INF ) return -1;
379    if( a < b ) return -1;
380    if( a > b ) return 1;
381    return 0;
382}
383
384int
385Torrent :: compareETA( const Torrent& that ) const
386{
387    const bool haveA( hasETA( ) );
388    const bool haveB( that.hasETA( ) );
389    if( haveA && haveB ) return getETA() - that.getETA();
390    if( haveA ) return 1;
391    if( haveB ) return -1;
392    return 0;
393}
394
395int
396Torrent :: compareTracker( const Torrent& that ) const
397{
398    Q_UNUSED( that );
399
400    // FIXME
401    return 0;
402}
403
404/***
405****
406***/
407
408void
409Torrent :: updateMimeIcon( )
410{
411    const FileList& files( myFiles );
412
413    QIcon icon;
414
415    if( files.size( ) > 1 )
416        icon = QFileIconProvider().icon( QFileIconProvider::Folder );
417    else if( files.size( ) == 1 )
418        icon = Utils :: guessMimeIcon( files.at(0).filename );
419    else
420        icon = QIcon( );
421
422    setIcon( MIME_ICON, icon );
423}
424
425/***
426****
427***/
428
429void
430Torrent :: notifyComplete( ) const
431{
432    // if someone wants to implement notification, here's the hook.
433}
434
435/***
436****
437***/
438
439void
440Torrent :: update( tr_benc * d )
441{
442    bool changed = false;
443
444    for( int  i=0; i<PROPERTY_COUNT; ++i )
445    {
446        tr_benc * child = tr_bencDictFind( d, myProperties[i].key );
447        if( !child )
448            continue;
449
450        switch( myProperties[i].type )
451        {
452            case QVariant :: Int: {
453                int64_t val;
454                if( tr_bencGetInt( child, &val ) )
455                    changed |= setInt( i, val );
456                break;
457            }
458
459            case QVariant :: Bool: {
460                tr_bool val;
461                if( tr_bencGetBool( child, &val ) )
462                    changed |= setBool( i, val );
463                break;
464            }
465
466            case QVariant :: String: {
467                const char * val;
468                if( tr_bencGetStr( child, &val ) )
469                    changed |= setString( i, val );
470                break;
471            }
472
473            case QVariant :: ULongLong: {
474                int64_t val;
475                if( tr_bencGetInt( child, &val ) )
476                    changed |= setSize( i, val );
477                break;
478            }
479
480            case QVariant :: Double: {
481                double val;
482                if( tr_bencGetReal( child, &val ) )
483                    changed |= setDouble( i, val );
484                break;
485            }
486
487            case QVariant :: DateTime: {
488                int64_t val;
489                if( tr_bencGetInt( child, &val ) && val )
490                    changed |= setDateTime( i, QDateTime :: fromTime_t( val ) );
491                break;
492            }
493
494            case QVariant :: StringList:
495            case TrTypes :: PeerList:
496                break;
497
498            default:
499                assert( 0 && "unhandled type" );
500        }
501    }
502
503    tr_benc * files;
504
505    if( tr_bencDictFindList( d, "files", &files ) ) {
506        const char * str;
507        int64_t intVal;
508        int i = 0;
509        myFiles.clear( );
510        tr_benc * child;
511        while(( child = tr_bencListChild( files, i ))) {
512            TrFile file;
513            file.index = i++;
514            if( tr_bencDictFindStr( child, "name", &str ) )
515                file.filename = QString::fromUtf8( str );
516            if( tr_bencDictFindInt( child, "length", &intVal ) )
517                file.size = intVal;
518            myFiles.append( file );
519        }
520        updateMimeIcon( );
521        changed = true;
522    }
523
524    if( tr_bencDictFindList( d, "fileStats", &files ) ) {
525        const int n = tr_bencListSize( files );
526        assert( n == myFiles.size( ) );
527        for( int i=0; i<n; ++i ) {
528            int64_t intVal;
529            tr_bool boolVal;
530            tr_benc * child = tr_bencListChild( files, i );
531            TrFile& file( myFiles[i] );
532            if( tr_bencDictFindInt( child, "bytesCompleted", &intVal ) )
533                file.have = intVal;
534            if( tr_bencDictFindBool( child, "wanted", &boolVal ) )
535                file.wanted = boolVal;
536            if( tr_bencDictFindInt( child, "priority", &intVal ) )
537                file.priority = intVal;
538        }
539        changed = true;
540    }
541
542    tr_benc * trackers;
543    if( tr_bencDictFindList( d, "trackers", &trackers ) ) {
544        const char * str;
545        int i = 0;
546        QStringList list;
547        tr_benc * child;
548        while(( child = tr_bencListChild( trackers, i++ ))) {
549            if( tr_bencDictFindStr( child, "announce", &str )) {
550                dynamic_cast<MyApp*>(QApplication::instance())->favicons.add( QUrl(str) );
551                list.append( QString::fromUtf8( str ) );
552            }
553        }
554        if( myValues[TRACKERS] != list ) {
555            myValues[TRACKERS].setValue( list );
556            changed = true;
557        }
558    }
559
560    tr_benc * trackerStats;
561    if( tr_bencDictFindList( d, "trackerStats", &trackerStats ) ) {
562        tr_benc * child;
563        TrackerStatsList  trackerStatsList;
564        int childNum = 0;
565        while(( child = tr_bencListChild( trackerStats, childNum++ ))) {
566            tr_bool b;
567            int64_t i;
568            const char * str;
569            TrackerStat trackerStat;
570            if( tr_bencDictFindStr( child, "announce", &str ) ) {
571                trackerStat.announce = QString::fromUtf8( str );
572                dynamic_cast<MyApp*>(QApplication::instance())->favicons.add( QUrl( trackerStat.announce ) );
573            }
574            if( tr_bencDictFindInt( child, "announceState", &i ) )
575                trackerStat.announceState = i;
576            if( tr_bencDictFindInt( child, "downloadCount", &i ) )
577                trackerStat.downloadCount = i;
578            if( tr_bencDictFindBool( child, "hasAnnounced", &b ) )
579                trackerStat.hasAnnounced = b;
580            if( tr_bencDictFindBool( child, "hasScraped", &b ) )
581                trackerStat.hasScraped = b;
582            if( tr_bencDictFindStr( child, "host", &str ) )
583                trackerStat.host = QString::fromUtf8( str );
584            if( tr_bencDictFindInt( child, "id", &i ) )
585                trackerStat.id = i;
586            if( tr_bencDictFindBool( child, "isBackup", &b ) )
587                trackerStat.isBackup = b;
588            if( tr_bencDictFindInt( child, "lastAnnouncePeerCount", &i ) )
589                trackerStat.lastAnnouncePeerCount = i;
590            if( tr_bencDictFindStr( child, "lastAnnounceResult", &str ) )
591                trackerStat.lastAnnounceResult = str;
592            if( tr_bencDictFindInt( child, "lastAnnounceStartTime", &i ) )
593                trackerStat.lastAnnounceStartTime = i;
594            if( tr_bencDictFindBool( child, "lastAnnounceSucceeded", &b ) )
595                trackerStat.lastAnnounceSucceeded = b;
596            if( tr_bencDictFindInt( child, "lastAnnounceTime", &i ) )
597                trackerStat.lastAnnounceTime = i;
598            if( tr_bencDictFindBool( child, "lastAnnounceTimedOut", &b ) )
599                trackerStat.lastAnnounceTimedOut = b;
600            if( tr_bencDictFindStr( child, "lastScrapeResult", &str ) )
601                trackerStat.lastScrapeResult = QString::fromUtf8( str );
602            if( tr_bencDictFindInt( child, "lastScrapeStartTime", &i ) )
603                trackerStat.lastScrapeStartTime = i;
604            if( tr_bencDictFindBool( child, "lastScrapeSucceeded", &b ) )
605                trackerStat.lastScrapeSucceeded = b;
606            if( tr_bencDictFindInt( child, "lastScrapeTime", &i ) )
607                trackerStat.lastScrapeTime = i;
608            if( tr_bencDictFindBool( child, "lastScrapeTimedOut", &b ) )
609                trackerStat.lastScrapeTimedOut = b;
610            if( tr_bencDictFindInt( child, "leecherCount", &i ) )
611                trackerStat.leecherCount = i;
612            if( tr_bencDictFindInt( child, "nextAnnounceTime", &i ) )
613                trackerStat.nextAnnounceTime = i;
614            if( tr_bencDictFindInt( child, "nextScrapeTime", &i ) )
615                trackerStat.nextScrapeTime = i;
616            if( tr_bencDictFindInt( child, "scrapeState", &i ) )
617                trackerStat.scrapeState = i;
618            if( tr_bencDictFindInt( child, "seederCount", &i ) )
619                trackerStat.seederCount = i;
620            if( tr_bencDictFindInt( child, "tier", &i ) )
621                trackerStat.tier = i;
622            trackerStatsList << trackerStat;
623        }
624        myValues[TRACKERSTATS].setValue( trackerStatsList );
625        changed = true;
626    }
627
628    tr_benc * peers;
629    if( tr_bencDictFindList( d, "peers", &peers ) ) {
630        tr_benc * child;
631        PeerList peerList;
632        int childNum = 0;
633        while(( child = tr_bencListChild( peers, childNum++ ))) {
634            double d;
635            tr_bool b;
636            int64_t i;
637            const char * str;
638            Peer peer;
639            if( tr_bencDictFindStr( child, "address", &str ) )
640                peer.address = QString::fromUtf8( str );
641            if( tr_bencDictFindStr( child, "clientName", &str ) )
642                peer.clientName = QString::fromUtf8( str );
643            if( tr_bencDictFindBool( child, "clientIsChoked", &b ) )
644                peer.clientIsChoked = b;
645            if( tr_bencDictFindBool( child, "clientIsInterested", &b ) )
646                peer.clientIsInterested = b;
647            if( tr_bencDictFindStr( child, "flagStr", &str ) )
648                peer.flagStr = QString::fromUtf8( str );
649            if( tr_bencDictFindBool( child, "isDownloadingFrom", &b ) )
650                peer.isDownloadingFrom = b;
651            if( tr_bencDictFindBool( child, "isEncrypted", &b ) )
652                peer.isEncrypted = b;
653            if( tr_bencDictFindBool( child, "isIncoming", &b ) )
654                peer.isIncoming = b;
655            if( tr_bencDictFindBool( child, "isUploadingTo", &b ) )
656                peer.isUploadingTo = b;
657            if( tr_bencDictFindBool( child, "peerIsChoked", &b ) )
658                peer.peerIsChoked = b;
659            if( tr_bencDictFindBool( child, "peerIsInterested", &b ) )
660                peer.peerIsInterested = b;
661            if( tr_bencDictFindInt( child, "port", &i ) )
662                peer.port = i;
663            if( tr_bencDictFindReal( child, "progress", &d ) )
664                peer.progress = d;
665            if( tr_bencDictFindInt( child, "rateToClient", &i ) )
666                peer.rateToClient = Speed::fromBps( i );
667            if( tr_bencDictFindInt( child, "rateToPeer", &i ) )
668                peer.rateToPeer = Speed::fromBps( i );
669            peerList << peer;
670        }
671        myValues[PEERS].setValue( peerList );
672        changed = true;
673    }
674
675    if( changed )
676        emit torrentChanged( id( ) );
677}
678
679QString
680Torrent :: activityString( ) const
681{
682    QString str;
683
684    switch( getActivity( ) )
685    {
686        case TR_STATUS_CHECK_WAIT: str = tr( "Waiting to verify local data" ); break;
687        case TR_STATUS_CHECK:      str = tr( "Verifying local data" ); break;
688        case TR_STATUS_DOWNLOAD:   str = tr( "Downloading" ); break;
689        case TR_STATUS_SEED:       str = tr( "Seeding" ); break;
690        case TR_STATUS_STOPPED:    str = isFinished() ? tr( "Finished" ): tr( "Paused" ); break;
691    }
692
693    return str;
694}
695
696QString
697Torrent :: getError( ) const
698{
699    QString s = getString( ERROR_STRING );
700
701    switch( getInt( ERROR ) )
702    {
703        case TR_STAT_TRACKER_WARNING: s = tr( "Tracker gave a warning: %1" ).arg( s ); break;
704        case TR_STAT_TRACKER_ERROR: s = tr( "Tracker gave an error: %1" ).arg( s ); break;
705        case TR_STAT_LOCAL_ERROR: s = tr( "Error: %1" ).arg( s ); break;
706        default: s.clear(); break;
707    }
708
709    return s;
710}
711
712QPixmap
713TrackerStat :: getFavicon( ) const
714{
715    MyApp * myApp = dynamic_cast<MyApp*>(QApplication::instance());
716    return myApp->favicons.find( QUrl( announce ) );
717}
718
Note: See TracBrowser for help on using the repository browser.