source: trunk/qt/session.cc @ 8221

Last change on this file since 8221 was 8221, checked in by charles, 13 years ago

(trunk qt) first stab at getting the properties dialog's "options" controls operational.

File size: 23.6 KB
Line 
1/*
2 * This file Copyright (C) 2009 Charles Kerr <charles@transmissionbt.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id:$
11 */
12
13#include <cassert>
14#include <iostream>
15
16#include <QApplication>
17#include <QByteArray>
18#include <QCoreApplication>
19#include <QDesktopServices>
20#include <QMessageBox>
21#include <QSet>
22#include <QStyle>
23#include <QTextStream>
24
25#include <libtransmission/transmission.h>
26#include <libtransmission/bencode.h>
27#include <libtransmission/rpcimpl.h>
28#include <libtransmission/utils.h> /* tr_free */
29#include <libtransmission/version.h> /* LONG_VERSION */
30
31#include "prefs.h"
32#include "qticonloader.h"
33#include "session.h"
34#include "torrent.h"
35
36// #define DEBUG_HTTP
37
38namespace
39{
40    enum
41    {
42        TAG_SOME_TORRENTS,
43        TAG_ALL_TORRENTS,
44        TAG_SESSION_STATS,
45        TAG_SESSION_INFO,
46        TAG_BLOCKLIST_UPDATE,
47        TAG_ADD_TORRENT,
48        TAG_PORT_TEST
49    };
50}
51
52/***
53****
54***/
55
56namespace
57{
58    typedef Torrent::KeyList KeyList;
59    const KeyList& getInfoKeys( ) { return Torrent::getInfoKeys( ); }
60    const KeyList& getStatKeys( ) { return Torrent::getStatKeys( ); }
61    const KeyList& getExtraStatKeys( ) { return Torrent::getExtraStatKeys( ); }
62
63    void
64    addList( tr_benc * list, const KeyList& strings )
65    {
66        tr_bencListReserve( list, strings.size( ) );
67        foreach( const char * str, strings )
68            tr_bencListAddStr( list, str );
69    }
70}
71
72/***
73****
74***/
75
76void
77Session :: sessionSet( const char * key, const QVariant& value )
78{
79    tr_benc top;
80    tr_bencInitDict( &top, 2 );
81    tr_bencDictAddStr( &top, "method", "session-set" );
82    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 1 ) );
83    switch( value.type( ) ) {
84        case QVariant::Bool:   tr_bencDictAddBool ( args, key, value.toBool() ); break;
85        case QVariant::Int:    tr_bencDictAddInt  ( args, key, value.toInt() ); break;
86        case QVariant::Double: tr_bencDictAddReal ( args, key, value.toDouble() ); break;
87        case QVariant::String: tr_bencDictAddStr  ( args, key, value.toString().toUtf8() ); break;
88        default: assert( "unknown type" );
89    }
90std::cerr << tr_bencToJSON(&top) << std::endl;
91    exec( &top );
92    tr_bencFree( &top );
93}
94
95void
96Session :: portTest( )
97{
98    tr_benc top;
99    tr_bencInitDict( &top, 2 );
100    tr_bencDictAddStr( &top, "method", "port-test" );
101    tr_bencDictAddInt( &top, "tag", TAG_PORT_TEST );
102    exec( &top );
103    tr_bencFree( &top );
104}
105
106void
107Session :: updatePref( int key )
108{
109    if( myPrefs.isCore( key ) ) switch( key )
110    {
111        case Prefs :: ALT_SPEED_LIMIT_UP:
112        case Prefs :: ALT_SPEED_LIMIT_DOWN:
113        case Prefs :: ALT_SPEED_LIMIT_ENABLED:
114        case Prefs :: ALT_SPEED_LIMIT_TIME_BEGIN:
115        case Prefs :: ALT_SPEED_LIMIT_TIME_END:
116        case Prefs :: ALT_SPEED_LIMIT_TIME_ENABLED:
117        case Prefs :: ALT_SPEED_LIMIT_TIME_DAY:
118        case Prefs :: BLOCKLIST_ENABLED:
119        case Prefs :: BLOCKLIST_DATE:
120        case Prefs :: DOWNLOAD_DIR:
121        case Prefs :: PEER_LIMIT_GLOBAL:
122        case Prefs :: PEER_LIMIT_TORRENT:
123        case Prefs :: SEED_RATIO_LIMIT:
124        case Prefs :: SEED_RATIO_LIMITED:
125        case Prefs :: USPEED_ENABLED:
126        case Prefs :: USPEED:
127        case Prefs :: DSPEED_ENABLED:
128        case Prefs :: DSPEED:
129        case Prefs :: PEX_ENABLED:
130        case Prefs :: PORT_FORWARDING:
131        case Prefs :: PEER_PORT:
132        case Prefs :: PEER_PORT_RANDOM_ON_START:
133            sessionSet( myPrefs.keyStr(key), myPrefs.variant(key) );
134            break;
135
136        case Prefs :: RPC_AUTH_REQUIRED:
137            if( mySession )
138                tr_sessionSetRPCEnabled( mySession, myPrefs.getBool(key) );
139            break;
140        case Prefs :: RPC_ENABLED:
141            if( mySession )
142                tr_sessionSetRPCEnabled( mySession, myPrefs.getBool(key) );
143            break;
144        case Prefs :: RPC_PASSWORD:
145            if( mySession )
146                tr_sessionSetRPCPassword( mySession, myPrefs.getString(key).toUtf8().constData() );
147            break;
148        case Prefs :: RPC_PORT:
149            if( mySession )
150                tr_sessionSetRPCPort( mySession, myPrefs.getInt(key) );
151            break;
152        case Prefs :: RPC_USERNAME:
153            if( mySession )
154                tr_sessionSetRPCUsername( mySession, myPrefs.getString(key).toUtf8().constData() );
155            break;
156        case Prefs :: RPC_WHITELIST_ENABLED:
157            if( mySession )
158                tr_sessionSetRPCWhitelistEnabled( mySession, myPrefs.getBool(key) );
159            break;
160        case Prefs :: RPC_WHITELIST:
161            if( mySession )
162                tr_sessionSetRPCWhitelist( mySession, myPrefs.getString(key).toUtf8().constData() );
163            break;
164
165        default:
166            std::cerr << "unhandled pref: " << key << std::endl;
167    }
168}
169
170/***
171****
172***/
173
174Session :: Session( const char * configDir, Prefs& prefs, const char * url, bool paused ):
175    myBlocklistSize( -1 ),
176    myPrefs( prefs ),
177    mySession( 0 ),
178    myUrl( url )
179{
180    myStats.ratio = TR_RATIO_NA;
181    myStats.uploadedBytes = 0;
182    myStats.downloadedBytes = 0;
183    myStats.filesAdded = 0;
184    myStats.sessionCount = 0;
185    myStats.secondsActive = 0;
186    myCumulativeStats = myStats;
187
188    if( url != 0 )
189    {
190        connect( &myHttp, SIGNAL(requestStarted(int)), this, SLOT(onRequestStarted(int)));
191        connect( &myHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool)));
192        connect( &myHttp, SIGNAL(dataReadProgress(int,int)), this, SIGNAL(dataReadProgress()));
193        connect( &myHttp, SIGNAL(dataSendProgress(int,int)), this, SIGNAL(dataSendProgress()));
194        myHttp.setHost( myUrl.host( ), myUrl.port( ) );
195        myHttp.setUser( myUrl.userName( ), myUrl.password( ) );
196        myBuffer.open( QIODevice::ReadWrite );
197
198        if( paused )
199            exec( "{ \"method\": \"torrent-stop\" }" );
200    }
201    else
202    {
203        tr_benc settings;
204        tr_bencInitDict( &settings, 0 );
205        tr_sessionGetDefaultSettings( &settings );
206        tr_sessionLoadSettings( &settings, configDir, "qt" );
207        mySession = tr_sessionInit( "qt", configDir, true, &settings );
208        tr_bencFree( &settings );
209
210        tr_ctor * ctor = tr_ctorNew( mySession );
211        if( paused )
212            tr_ctorSetPaused( ctor, TR_FORCE, TRUE );
213        int torrentCount;
214        tr_torrent ** torrents = tr_sessionLoadTorrents( mySession, ctor, &torrentCount );
215        tr_free( torrents );
216        tr_ctorFree( ctor );
217    }
218
219    connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
220}
221
222Session :: ~Session( )
223{
224    if( mySession )
225        tr_sessionClose( mySession );
226}
227
228bool
229Session :: isServer( ) const
230{
231    return mySession != 0;
232}
233
234bool
235Session :: isLocal( ) const
236{
237    if( mySession != 0 )
238        return true;
239
240    if( myUrl.host() == "127.0.0.1" )
241        return true;
242
243    if( !myUrl.host().compare( "localhost", Qt::CaseInsensitive ) )
244        return true;
245
246    return false;
247}
248
249/***
250****
251***/
252
253namespace
254{
255    tr_benc *
256    buildRequest( const char * method, tr_benc& top, int tag=-1 )
257    {
258        tr_bencInitDict( &top, 3 );
259        tr_bencDictAddStr( &top, "method", method );
260        if( tag >= 0 )
261            tr_bencDictAddInt( &top, "tag", tag );
262        return tr_bencDictAddDict( &top, "arguments", 0 );
263    }
264
265    void
266    addOptionalIds( tr_benc * args, const QSet<int>& ids )
267    {
268        if( !ids.isEmpty( ) )
269        {
270            tr_benc * idList( tr_bencDictAddList( args, "ids", ids.size( ) ) );
271            foreach( int i, ids )
272                tr_bencListAddInt( idList, i );
273        }
274    }
275}
276
277const int Session :: ADD_TORRENT_TAG = TAG_ADD_TORRENT;
278
279void
280Session :: torrentSet( int id, const QString& key, double value )
281{
282    QString s;
283    QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<value<<" } }";
284std::cerr << qPrintable(s) << std::endl;
285    exec( s.toUtf8().constData() );
286    refreshExtraStats( id );
287}
288
289void
290Session :: torrentSet( int id, const QString& key, int value )
291{
292    QString s;
293    QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<value<<" } }";
294std::cerr << qPrintable(s) << std::endl;
295    exec( s.toUtf8().constData() );
296    refreshExtraStats( id );
297}
298
299void
300Session :: torrentSet( int id, const QString& key, bool value )
301{
302    QString s;
303    QTextStream( &s ) << "{ \"method\": \"torrent-set\", \"arguments\": { \"ids\": "<<id<<", \""<<key<<"\": "<<(value?"true":"false")<<" } }";
304std::cerr << qPrintable(s) << std::endl;
305    exec( s.toUtf8().constData() );
306    refreshExtraStats( id );
307}
308
309void
310Session :: torrentSet( int id, const QString& key, const QList<int>& value )
311{
312    tr_benc top;
313    tr_bencInitDict( &top, 2 );
314    tr_bencDictAddStr( &top, "method", "torrent-set" );
315    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
316    tr_bencListAddInt( tr_bencDictAddList( args, "ids", 1 ), id );
317    tr_benc * list( tr_bencDictAddList( args, key.toUtf8().constData(), value.size( ) ) );
318    foreach( int i, value )
319        tr_bencListAddInt( list, i );
320    exec( &top );
321    tr_bencFree( &top );
322    refreshExtraStats( id );
323}
324
325
326void
327Session :: refreshTorrents( const QSet<int>& ids )
328{
329    if( ids.empty( ) )
330    {
331        refreshAllTorrents( );
332    }
333    else
334    {
335        tr_benc top;
336        tr_bencInitDict( &top, 3 );
337        tr_bencDictAddStr( &top, "method", "torrent-get" );
338        tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
339        tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
340        addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) );
341        addOptionalIds( args, ids );
342        exec( &top );
343        tr_bencFree( &top );
344    }
345}
346
347void
348Session :: refreshExtraStats( int id )
349{
350    tr_benc top;
351    tr_bencInitDict( &top, 3 );
352    tr_bencDictAddStr( &top, "method", "torrent-get" );
353    tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
354    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
355    tr_bencListAddInt( tr_bencDictAddList( args, "ids", 1 ), id );
356    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) + getExtraStatKeys( ));
357    exec( &top );
358    tr_bencFree( &top );
359}
360
361void
362Session :: sendTorrentRequest( const char * request, const QSet<int>& ids )
363{
364    tr_benc top;
365    tr_benc * args( buildRequest( request, top ) );
366    addOptionalIds( args, ids );
367    exec( &top );
368    tr_bencFree( &top );
369
370    refreshTorrents( ids );
371}
372
373void
374Session :: pause( const QSet<int>& ids )
375{
376    sendTorrentRequest( "torrent-stop", ids );
377}
378
379void
380Session :: start( const QSet<int>& ids )
381{
382    sendTorrentRequest( "torrent-start", ids );
383}
384
385void
386Session :: refreshActiveTorrents( )
387{
388    tr_benc top;
389    tr_bencInitDict( &top, 3 );
390    tr_bencDictAddStr( &top, "method", "torrent-get" );
391    tr_bencDictAddInt( &top, "tag", TAG_SOME_TORRENTS );
392    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 2 ) );
393    tr_bencDictAddStr( args, "ids", "recently-active" );
394    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) );
395    exec( &top );
396    tr_bencFree( &top );
397}
398
399void
400Session :: refreshAllTorrents( )
401{
402    tr_benc top;
403    tr_bencInitDict( &top, 3 );
404    tr_bencDictAddStr( &top, "method", "torrent-get" );
405    tr_bencDictAddInt( &top, "tag", TAG_ALL_TORRENTS );
406    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 1 ) );
407    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys( ) );
408    exec( &top );
409    tr_bencFree( &top );
410}
411
412void
413Session :: initTorrents( const QSet<int>& ids )
414{
415    tr_benc top;
416    const int tag( ids.isEmpty() ? TAG_ALL_TORRENTS : TAG_SOME_TORRENTS );
417    tr_benc * args( buildRequest( "torrent-get", top, tag ) );
418    addOptionalIds( args, ids );
419    addList( tr_bencDictAddList( args, "fields", 0 ), getStatKeys()+getInfoKeys() );
420    exec( &top );
421    tr_bencFree( &top );
422}
423
424void
425Session :: refreshSessionStats( )
426{
427    tr_benc top;
428    tr_bencInitDict( &top, 2 );
429    tr_bencDictAddStr( &top, "method", "session-stats" );
430    tr_bencDictAddInt( &top, "tag", TAG_SESSION_STATS );
431    exec( &top );
432    tr_bencFree( &top );
433}
434
435void
436Session :: refreshSessionInfo( )
437{
438    tr_benc top;
439    tr_bencInitDict( &top, 2 );
440    tr_bencDictAddStr( &top, "method", "session-get" );
441    tr_bencDictAddInt( &top, "tag", TAG_SESSION_INFO );
442    exec( &top );
443    tr_bencFree( &top );
444}
445
446void
447Session :: updateBlocklist( )
448{
449    tr_benc top;
450    tr_bencInitDict( &top, 2 );
451    tr_bencDictAddStr( &top, "method", "blocklist-update" );
452    tr_bencDictAddInt( &top, "tag", TAG_BLOCKLIST_UPDATE );
453    exec( &top );
454    tr_bencFree( &top );
455}
456
457/***
458****
459***/
460
461void
462Session :: exec( const tr_benc * request )
463{
464    char * str( tr_bencToJSON( request ) );
465    exec( str );
466    tr_free( str );
467}
468
469void
470Session :: localSessionCallback( tr_session * session, const char * json, size_t len, void * self )
471{
472    Q_UNUSED( session );
473
474    ((Session*)self)->parseResponse( json, len );
475}
476
477void
478Session :: exec( const char * request )
479{
480    if( mySession  )
481    {
482        tr_rpc_request_exec_json( mySession, request, strlen( request ), localSessionCallback, this );
483    }
484    else
485    {
486        const QByteArray data( request, strlen( request ) );
487        static const QString path( "/transmission/rpc" );
488        QHttpRequestHeader header( "POST", path );
489        header.setValue( "User-Agent", QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING );
490        header.setValue( "Content-Type", "application/json; charset=UTF-8" );
491        myHttp.request( header, data, &myBuffer );
492#ifdef DEBUG_HTTP
493        std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl;
494#endif
495    }
496}
497
498void
499Session :: onRequestStarted( int id )
500{
501    Q_UNUSED( id );
502
503    assert( myBuffer.atEnd( ) );
504}
505
506void
507Session :: onRequestFinished( int id, bool error )
508{
509    Q_UNUSED( id );
510
511#ifdef DEBUG_HTTP
512    std::cerr << "http request " << id << " ended.. response header: "
513              << qPrintable( myHttp.lastResponse().toString() )
514              << std::endl
515              << "json: " << myBuffer.buffer( ).constData( )
516              << std::endl;
517#endif
518
519    if( error )
520        std::cerr << "http error: " << qPrintable(myHttp.errorString()) << std::endl;
521    else {
522        const QByteArray& response( myBuffer.buffer( ) );
523        const char * json( response.constData( ) );
524        int jsonLength( response.size( ) );
525        if( json[jsonLength-1] == '\n' ) --jsonLength;
526
527        parseResponse( json, jsonLength );
528    }
529
530    myBuffer.buffer( ).clear( );
531    myBuffer.reset( );
532    assert( myBuffer.bytesAvailable( ) < 1 );
533}
534
535void
536Session :: parseResponse( const char * json, size_t jsonLength )
537{
538    tr_benc top;
539    const uint8_t * end( 0 );
540    const int err( tr_jsonParse( json, jsonLength, &top, &end ) );
541    if( !err )
542    {
543        int64_t tag;
544        const char * str;
545        tr_benc *args, *torrents;
546        if( tr_bencDictFindInt( &top, "tag", &tag ) )
547        {
548            switch( tag )
549            {
550                case TAG_SOME_TORRENTS:
551                case TAG_ALL_TORRENTS:
552                    if( tr_bencDictFindDict( &top, "arguments", &args ) ) {
553                        if( tr_bencDictFindList( args, "torrents", &torrents ) )
554                            emit torrentsUpdated( torrents, tag==TAG_ALL_TORRENTS );
555                        if( tr_bencDictFindList( args, "removed", &torrents ) )
556                            emit torrentsRemoved( torrents );
557                    }
558                    break;
559
560                case TAG_SESSION_STATS:
561                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
562                        updateStats( args );
563                    break;
564
565                case TAG_SESSION_INFO:
566                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
567                        updateInfo( args );
568                    break;
569
570                case TAG_BLOCKLIST_UPDATE: {
571                    int64_t intVal = 0;
572                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
573                        if( tr_bencDictFindInt( args, "blocklist-size", &intVal ) )
574                            setBlocklistSize( intVal );
575                    break;
576                }
577
578                case TAG_PORT_TEST: {
579                    tr_bool isOpen = 0;
580                    if( tr_bencDictFindDict( &top, "arguments", &args ) )
581                        tr_bencDictFindBool( args, "port-is-open", &isOpen );
582                    emit portTested( (bool)isOpen );
583                }
584
585                case TAG_ADD_TORRENT:
586                    str = "";
587                    if( tr_bencDictFindStr( &top, "result", &str ) && strcmp( str, "success" ) ) {
588                        QMessageBox * d = new QMessageBox( QMessageBox::Information,
589                                                           tr( "Add Torrent" ),
590                                                           QString::fromUtf8(str),
591                                                           QMessageBox::Close,
592                                                           QApplication::activeWindow());
593                        QPixmap pixmap; 
594                        QIcon icon = QtIconLoader :: icon( "dialog-information" );
595                        if( !icon.isNull( ) ) {
596                            const int size = QApplication::style()->pixelMetric( QStyle::PM_LargeIconSize );
597                            d->setIconPixmap( icon.pixmap( size, size ) );
598                        }
599                        connect( d, SIGNAL(rejected()), d, SLOT(deleteLater()) );
600                        d->show( );
601                    }
602                    break;
603
604                default:
605                    break;
606            }
607        }
608        tr_bencFree( &top );
609    }
610}
611
612void
613Session :: updateStats( tr_benc * d, struct tr_session_stats * stats )
614{
615    int64_t i;
616
617    if( tr_bencDictFindInt( d, "uploadedBytes", &i ) )
618        stats->uploadedBytes = i;
619    if( tr_bencDictFindInt( d, "downloadedBytes", &i ) )
620        stats->downloadedBytes = i;
621    if( tr_bencDictFindInt( d, "filesAdded", &i ) )
622        stats->filesAdded = i;
623    if( tr_bencDictFindInt( d, "sessionCount", &i ) )
624        stats->sessionCount = i;
625    if( tr_bencDictFindInt( d, "secondsActive", &i ) )
626        stats->secondsActive = i;
627
628    stats->ratio = tr_getRatio( stats->uploadedBytes, stats->downloadedBytes );
629
630}
631
632void
633Session :: updateStats( tr_benc * d )
634{
635    tr_benc * c;
636
637    if( tr_bencDictFindDict( d, "current-stats", &c ) )
638        updateStats( c, &myStats );
639
640    if( tr_bencDictFindDict( d, "cumulative-stats", &c ) )
641        updateStats( c, &myCumulativeStats );
642
643    emit statsUpdated( );
644}
645
646void
647Session :: updateInfo( tr_benc * d )
648{
649    int64_t i;
650    const char * str;
651    disconnect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
652
653    for( int i=Prefs::FIRST_CORE_PREF; i<=Prefs::LAST_CORE_PREF; ++i )
654    {
655        const tr_benc * b( tr_bencDictFind( d, myPrefs.keyStr( i ) ) );
656
657        if( !b )
658            continue;
659
660        switch( myPrefs.type( i ) )
661        {
662            case QVariant :: Int: {
663                int64_t val;
664                if( tr_bencGetInt( b, &val ) )
665                    myPrefs.set( i, (int)val );
666                break;
667            }
668            case QVariant :: Double: {
669                double val;
670                if( tr_bencGetReal( b, &val ) )
671                    myPrefs.set( i, val );
672                break;
673            }
674            case QVariant :: Bool: {
675                tr_bool val;
676                if( tr_bencGetBool( b, &val ) )
677                    myPrefs.set( i, (bool)val );
678                break;
679            }
680            case TrTypes :: FilterModeType:
681            case TrTypes :: SortModeType:
682            case QVariant :: String: {
683                const char * val;
684                if( tr_bencGetStr( b, &val ) )
685                    myPrefs.set( i, QString(val) );
686                break;
687            }
688            default:
689                break;
690        }
691    }
692
693    /* Use the C API to get settings that, for security reasons, aren't supported by RPC */
694    if( mySession != 0 )
695    {
696        myPrefs.set( Prefs::RPC_ENABLED,           tr_sessionIsRPCEnabled           ( mySession ) );
697        myPrefs.set( Prefs::RPC_AUTH_REQUIRED,     tr_sessionIsRPCPasswordEnabled   ( mySession ) );
698        myPrefs.set( Prefs::RPC_PASSWORD,          tr_sessionGetRPCPassword         ( mySession ) );
699        myPrefs.set( Prefs::RPC_PORT,              tr_sessionGetRPCPort             ( mySession ) );
700        myPrefs.set( Prefs::RPC_USERNAME,          tr_sessionGetRPCUsername         ( mySession ) );
701        myPrefs.set( Prefs::RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled ( mySession ) );
702        myPrefs.set( Prefs::RPC_WHITELIST,         tr_sessionGetRPCWhitelist        ( mySession ) );
703    }
704
705    if( tr_bencDictFindInt( d, "blocklist-size", &i ) && i!=blocklistSize( ) )
706        setBlocklistSize( i );
707
708    if( tr_bencDictFindStr( d, "version", &str ) && ( mySessionVersion != str ) )
709        mySessionVersion = str;
710
711    //std::cerr << "Session :: updateInfo end" << std::endl;
712    connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(updatePref(int)) );
713
714    emit sessionUpdated( );
715}
716
717void
718Session :: setBlocklistSize( int64_t i )
719{
720    myBlocklistSize = i;
721
722    emit blocklistUpdated( i );
723}
724
725void
726Session :: addTorrent( QString filename )
727{
728    QFile file( filename );
729    file.open( QIODevice::ReadOnly );
730    QByteArray raw( file.readAll( ) );
731    file.close( );
732
733    if( !raw.isEmpty( ) )
734    {
735        int b64len = 0;
736        char * b64 = tr_base64_encode( raw.constData(), raw.size(), &b64len );
737
738        tr_benc top, *args;
739        tr_bencInitDict( &top, 2 );
740        tr_bencDictAddStr( &top, "method", "torrent-add" );
741        args = tr_bencDictAddDict( &top, "arguments", 3 );
742        tr_bencDictAddStr( args, "download-dir", qPrintable(myPrefs.getString(Prefs::DOWNLOAD_DIR)) );
743        tr_bencDictAddRaw( args, "metainfo", b64, b64len  );
744        tr_bencDictAddInt( args, "paused", !myPrefs.getBool( Prefs::START ) );
745        exec( &top );
746
747        tr_free( b64 );
748        tr_bencFree( &top );
749    }
750}
751
752void
753Session :: removeTorrents( const QSet<int>& ids, bool deleteFiles )
754{
755    if( !ids.isEmpty( ) )
756    {
757        tr_benc top, *args;
758        tr_bencInitDict( &top, 2 );
759        tr_bencDictAddStr( &top, "method", "torrent-remove" );
760        args = tr_bencDictAddDict( &top, "arguments", 2 );
761        addOptionalIds( args, ids );
762        tr_bencDictAddInt( args, "delete-local-data", deleteFiles );
763        exec( &top );
764        tr_bencFree( &top );
765    }
766}
767
768void
769Session :: verifyTorrents( const QSet<int>& ids )
770{
771    if( !ids.isEmpty( ) )
772    {
773        tr_benc top, *args;
774        tr_bencInitDict( &top, 2 );
775        tr_bencDictAddStr( &top, "method", "torrent-verify" );
776        args = tr_bencDictAddDict( &top, "arguments", 1 );
777        addOptionalIds( args, ids );
778        exec( &top );
779        tr_bencFree( &top );
780    }
781}
782
783void
784Session :: reannounceTorrents( const QSet<int>& ids )
785{
786    if( !ids.isEmpty( ) )
787    {
788        tr_benc top, *args;
789        tr_bencInitDict( &top, 2 );
790        tr_bencDictAddStr( &top, "method", "torrent-reannounce" );
791        args = tr_bencDictAddDict( &top, "arguments", 1 );
792        addOptionalIds( args, ids );
793        exec( &top );
794        tr_bencFree( &top );
795    }
796}
797
798/***
799****
800***/
801
802void
803Session :: launchWebInterface( )
804{
805    QUrl url;
806    if( !mySession) // remote session
807        url = myUrl;
808    else { // local session
809        url.setHost( "localhost" );
810        url.setPort( myPrefs.getInt( Prefs::RPC_PORT ) );
811    }
812    std::cerr << qPrintable(url.toString()) << std::endl;
813    QDesktopServices :: openUrl( url );
814}
Note: See TracBrowser for help on using the repository browser.