Changeset 8389


Ignore:
Timestamp:
May 13, 2009, 3:54:04 PM (12 years ago)
Author:
charles
Message:

(trunk) #920: add "move data" to libT so all clients can use it

Location:
trunk
Files:
4 added
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/NEWS

    r8386 r8389  
    331.70 (2009/mm/dd)
    44<http://trac.transmissionbt.com/query?milestone=1.70&group=component&groupdesc=1&order=severity>
     5- All Platforms
     6   + Add ability to move a torrent's data and/or tell Transmission where to look for it
    57- Mac
    68   + Hold down the option key on launch to pause all transfers
  • trunk/daemon/remote.c

    r8362 r8389  
    7676    { 920, "session-info",         "Show the session's details", "si", 0, NULL },
    7777    { 'l', "list",                 "List all torrents", "l",  0, NULL },
     78    { 960, "move",                 "Move current torrent's data to a new folder", NULL, 1, "<path>" },
     79    { 961, "find",                 "Tell Transmission where to find a torrent's data", NULL, 1, "<path>" },
    7880    { 'm', "portmap",              "Enable portmapping via NAT-PMP or UPnP", "m",  0, NULL },
    7981    { 'M', "no-portmap",           "Disable portmapping", "M",  0, NULL },
     
    589591                break;
    590592
     593            case 960:
     594                tr_bencDictAddStr( &top, "method", "torrent-set-location" );
     595                tr_bencDictAddStr( args, "location", optarg );
     596                tr_bencDictAddBool( args, "move", TRUE );
     597                addIdArg( args, id );
     598                break;
     599
     600            case 961:
     601                tr_bencDictAddStr( &top, "method", "torrent-set-location" );
     602                tr_bencDictAddStr( args, "location", optarg );
     603                tr_bencDictAddBool( args, "move", FALSE );
     604                addIdArg( args, id );
     605                break;
     606
    591607            case TR_OPT_ERR:
    592608                fprintf( stderr, "invalid option\n" );
  • trunk/daemon/transmission-remote.1

    r7888 r8389  
    168168Remove the current torrent(s) and delete their downloaded data.
    169169
     170.It Fl -move
     171Move the current torrents' data from their current locations to the specified directory.
     172
     173.It Fl -find
     174Tell Transmission where to look for the current torrents' data.
     175
    170176.It Fl sr Fl -seedratio Ar ratio
    171177Let the current torrent(s) seed until a specific
  • trunk/doc/rpc-spec.txt

    r8259 r8389  
    9696   "honorsSessionLimits"             | boolean    true if session upload limits are honored
    9797   "ids"                             | array      torrent list, as described in 3.1
     98   "location"                        | string     new location of the torrent's content
    9899   "peer-limit"                      | number     maximum number of peers
    99100   "priority-high"                   | array      indices of high-priority file(s)
     
    345346
    346347
     3483.6.  Moving a Torrent
     349
     350   Method name: "torrent-set-location"
     351
     352   Request arguments:
     353
     354   string                     | value type & description
     355   ---------------------------+-------------------------------------------------
     356   "ids"                      | array      torrent list, as described in 3.1
     357   "location"                 | string     destination folder
     358   "move"                     | boolean    if true, move from previous location
     359
     360   Response arguments: none
     361
     362
    3473634.   Session Requests
    348364
     
    514530         |         |        NO | torrent-get    | removed arg "uploadLimitMode"
    515531   ------+---------+-----------+----------------+-------------------------------
    516 
    517 
     532   6     | 1.70    | yes       | torrent-set    | new arg "location"
     533   ------+---------+-----------+----------------+-------------------------------
     534
     535
  • trunk/gtk/Makefile.am

    r8238 r8389  
    5050    notify.h \
    5151    options-icon.h \
     52    relocate.h \
    5253    stats.h \
    5354    sexy-icon-entry.h \
     
    8283    msgwin.c \
    8384    notify.c \
     85    relocate.c \
    8486    sexy-icon-entry.c \
    8587    sexy-marshal.c \
  • trunk/gtk/actions.c

    r8238 r8389  
    102102};
    103103
    104 static GtkActionEntry        entries[] =
     104static GtkActionEntry entries[] =
    105105{
    106106    { "torrent-menu", NULL, N_( "_Torrent" ), NULL, NULL, NULL  },
     
    117117    { "pause-all-torrents", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause All" ), NULL, N_( "Pause all torrents" ), G_CALLBACK( action_cb ) },
    118118    { "start-all-torrents", GTK_STOCK_MEDIA_PLAY, N_( "_Start All" ), NULL, N_( "Start all torrents" ), G_CALLBACK( action_cb ) },
     119    { "relocate-torrent", NULL, N_("Set _Location" ), NULL, NULL, G_CALLBACK( action_cb ) },
    119120    { "remove-torrent", GTK_STOCK_REMOVE, NULL, "Delete", N_( "Remove torrent" ), G_CALLBACK( action_cb ) },
    120121    { "delete-torrent", GTK_STOCK_DELETE, N_( "_Delete Files and Remove" ), "<shift>Delete", NULL, G_CALLBACK( action_cb ) },
  • trunk/gtk/icons.c

    r8277 r8389  
    263263   
    264264    switch ( icon_size ) {
    265         case GTK_ICON_SIZE_INVALID:       n = 0; break;
    266         case GTK_ICON_SIZE_MENU:          n = 1; break;
    267         case GTK_ICON_SIZE_SMALL_TOOLBAR: n = 2; break;
    268         case GTK_ICON_SIZE_LARGE_TOOLBAR: n = 3; break;
    269         case GTK_ICON_SIZE_BUTTON:        n = 4; break;
    270         case GTK_ICON_SIZE_DND:           n = 5; break;
    271         case GTK_ICON_SIZE_DIALOG:        n = 6; break;
     265        case GTK_ICON_SIZE_MENU:            n = 1; break;
     266        case GTK_ICON_SIZE_SMALL_TOOLBAR:   n = 2; break;
     267        case GTK_ICON_SIZE_LARGE_TOOLBAR:   n = 3; break;
     268        case GTK_ICON_SIZE_BUTTON:          n = 4; break;
     269        case GTK_ICON_SIZE_DND:             n = 5; break;
     270        case GTK_ICON_SIZE_DIALOG:          n = 6; break;
     271        default /*GTK_ICON_SIZE_INVALID*/:  n = 0; break;
    272272    }   
    273273
  • trunk/gtk/main.c

    r8367 r8389  
    5050#include "msgwin.h"
    5151#include "notify.h"
     52#include "relocate.h"
    5253#include "stats.h"
    5354#include "tr-core.h"
     
    204205    action_sensitize( "verify-torrent", counts.totalCount != 0 );
    205206    action_sensitize( "open-torrent-folder", counts.totalCount == 1 );
     207    action_sensitize( "relocate-torrent", counts.totalCount == 1 );
    206208
    207209    canUpdate = 0;
     
    12821284}
    12831285
     1286static tr_torrent*
     1287getFirstSelectedTorrent( struct cbdata * data )
     1288{
     1289    tr_torrent * tor = NULL;
     1290    GtkTreeSelection * s = tr_window_get_selection( data->wind );
     1291    GtkTreeModel * m;
     1292    GList * l = gtk_tree_selection_get_selected_rows( s, &m );
     1293    if( l != NULL ) {
     1294        GtkTreePath * p = l->data;
     1295        GtkTreeIter i;
     1296        if( gtk_tree_model_get_iter( m, &i, p ) )
     1297            gtk_tree_model_get( m, &i, MC_TORRENT_RAW, &tor, -1 );
     1298    }
     1299    g_list_foreach( l, (GFunc)gtk_tree_path_free, NULL );
     1300    g_list_free( l );
     1301    return tor;
     1302}
     1303
    12841304void
    12851305doAction( const char * action_name, gpointer user_data )
     
    13111331    {
    13121332        startAllTorrents( data );
     1333    }
     1334    else if( !strcmp( action_name, "relocate-torrent" ) )
     1335    {
     1336        tr_torrent * tor = getFirstSelectedTorrent( data );
     1337        if( tor )
     1338        {
     1339            GtkWindow * parent = GTK_WINDOW( data->wind );
     1340            GtkWidget * w = gtr_relocate_dialog_new( parent, tor );
     1341            gtk_widget_show( w );
     1342        }
    13131343    }
    13141344    else if( !strcmp( action_name, "pause-torrent" ) )
  • trunk/gtk/torrent-cell-renderer.c

    r8004 r8389  
    5151    char *         str;
    5252    double         seedRatio;
    53     gboolean       hasSeedRatio;
     53    gboolean       hasSeedRatio = FALSE;
    5454
    5555    if( !isDone )
  • trunk/gtk/ui.h

    r7976 r8389  
    66    "      <menuitem action='new-torrent'/>\n"
    77    "      <separator/>\n"
     8    "      <menuitem action='open-torrent-folder'/>\n"
    89    "      <menuitem action='show-torrent-properties'/>\n"
    9     "      <menuitem action='open-torrent-folder'/>\n"
     10    "      <menuitem action='relocate-torrent'/>\n"
    1011    "      <separator/>\n"
    1112    "      <menuitem action='start-torrent'/>\n"
     
    6566    "\n"
    6667    "  <popup name='main-window-popup'>\n"
     68    "    <menuitem action='open-torrent-folder'/>\n"
    6769    "    <menuitem action='show-torrent-properties'/>\n"
    68     "    <menuitem action='open-torrent-folder'/>\n"
     70    "    <menuitem action='relocate-torrent'/>\n"
    6971    "    <separator/>\n"
    7072    "    <menuitem action='start-torrent'/>\n"
  • trunk/gtk/util.h

    r8282 r8389  
    100100                                       const char * mnemonic );
    101101
    102 guint       gtr_timeout_add_seconds( guint       interval,
     102guint       gtr_timeout_add_seconds( guint       seconds,
    103103                                     GSourceFunc function,
    104104                                     gpointer    data );
  • trunk/libtransmission/fdlimit.c

    r8350 r8389  
    202202}
    203203
     204tr_bool
     205tr_preallocate_file( const char * filename, uint64_t length )
     206{
     207    return preallocateFileFull( filename, length );
     208}
     209
     210int
     211tr_open_file_for_writing( const char * filename )
     212{
     213    int flags = O_WRONLY | O_CREAT;
     214#ifdef O_BINARY
     215    flags |= O_BINARY;
     216#endif
     217#ifdef O_LARGEFILE
     218    flags |= O_LARGEFILE;
     219#endif
     220    return open( filename, flags, 0666 );
     221}
     222
    204223int
    205224tr_open_file_for_scanning( const char * filename )
  • trunk/libtransmission/fdlimit.h

    r8299 r8389  
    3535int tr_open_file_for_scanning( const char * filename );
    3636
     37int tr_open_file_for_writing( const char * filename );
     38
    3739void tr_close_file( int fd );
     40
     41tr_bool tr_preallocate_file( const char * filename, uint64_t length );
    3842
    3943int64_t tr_lseek( int fd, int64_t offset, int whence );
  • trunk/libtransmission/rpcimpl.c

    r8362 r8389  
    765765}
    766766
     767static const char*
     768torrentSetLocation( tr_session               * session,
     769                    tr_benc                  * args_in,
     770                    tr_benc                  * args_out UNUSED,
     771                    struct tr_rpc_idle_data  * idle_data )
     772{
     773    const char * errmsg = NULL;
     774    const char * location = NULL;
     775
     776    assert( idle_data == NULL );
     777
     778    if( !tr_bencDictFindStr( args_in, "location", &location ) )
     779    {
     780        errmsg = "no location";
     781    }
     782    else
     783    {
     784        tr_bool move = FALSE;
     785        int i, torrentCount;
     786        tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     787
     788        tr_bencDictFindBool( args_in, "move", &move );
     789
     790        for( i=0; i<torrentCount; ++i )
     791        {
     792            tr_torrent * tor = torrents[i];
     793            tr_torrentSetLocation( tor, location, move, NULL );
     794            notify( session, TR_RPC_TORRENT_CHANGED, tor );
     795        }
     796
     797        tr_free( torrents );
     798    }
     799
     800    return errmsg;
     801}
     802
    767803/***
    768804****
     
    12021238    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, tr_sessionGetPeerPortRandomOnStart( s ) );
    12031239    tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
    1204     tr_bencDictAddInt ( d, "rpc-version", 5 );
     1240    tr_bencDictAddInt ( d, "rpc-version", 6 );
    12051241    tr_bencDictAddInt ( d, "rpc-version-minimum", 1 );
    12061242    tr_bencDictAddReal( d, "seedRatioLimit", tr_sessionGetRatioLimit( s ) );
     
    12351271methods[] =
    12361272{
    1237     { "port-test",          FALSE, portTest            },
    1238     { "blocklist-update",   FALSE, blocklistUpdate     },
    1239     { "session-get",        TRUE,  sessionGet          },
    1240     { "session-set",        TRUE,  sessionSet          },
    1241     { "session-stats",      TRUE,  sessionStats        },
    1242     { "torrent-add",        FALSE, torrentAdd          },
    1243     { "torrent-get",        TRUE,  torrentGet          },
    1244     { "torrent-remove",     TRUE,  torrentRemove       },
    1245     { "torrent-set",        TRUE,  torrentSet          },
    1246     { "torrent-start",      TRUE,  torrentStart        },
    1247     { "torrent-stop",       TRUE,  torrentStop         },
    1248     { "torrent-verify",     TRUE,  torrentVerify       },
    1249     { "torrent-reannounce", TRUE,  torrentReannounce   }
     1273    { "port-test",             FALSE, portTest            },
     1274    { "blocklist-update",      FALSE, blocklistUpdate     },
     1275    { "session-get",           TRUE,  sessionGet          },
     1276    { "session-set",           TRUE,  sessionSet          },
     1277    { "session-stats",         TRUE,  sessionStats        },
     1278    { "torrent-add",           FALSE, torrentAdd          },
     1279    { "torrent-get",           TRUE,  torrentGet          },
     1280    { "torrent-remove",        TRUE,  torrentRemove       },
     1281    { "torrent-set",           TRUE,  torrentSet          },
     1282    { "torrent-set-location",  TRUE,  torrentSetLocation  },
     1283    { "torrent-start",         TRUE,  torrentStart        },
     1284    { "torrent-stop",          TRUE,  torrentStop         },
     1285    { "torrent-verify",        TRUE,  torrentVerify       },
     1286    { "torrent-reannounce",    TRUE,  torrentReannounce   }
    12501287};
    12511288
  • trunk/libtransmission/session.c

    r8387 r8389  
    973973updateBandwidth( tr_session * session, tr_direction dir )
    974974{
    975     int limit;
     975    int limit = 0;
    976976    const tr_bool isLimited = tr_sessionGetActiveSpeedLimit( session, dir, &limit );
    977977    const tr_bool zeroCase = isLimited && !limit;
  • trunk/libtransmission/torrent-ctor.c

    r8123 r8389  
    172172
    173173    switch( priority ) {
    174         case TR_PRI_NORMAL: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
    175174        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
    176175        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
     176        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
    177177    }
    178178
  • trunk/libtransmission/torrent.c

    r8257 r8389  
    240240            break;
    241241
    242         case TR_RATIOLIMIT_UNLIMITED:
     242        default: /* TR_RATIOLIMIT_UNLIMITED */
    243243            isLimited = FALSE;
    244244            break;
     
    735735
    736736void
    737 tr_torrentSetDownloadDir( tr_torrent * tor,
    738                           const char * path )
     737tr_torrentSetDownloadDir( tr_torrent * tor, const char * path )
    739738{
    740739    assert( tr_isTorrent( tor  ) );
     
    12361235
    12371236static void
    1238 torrentStart( tr_torrent * tor,
    1239               int          reloadProgress )
     1237torrentStart( tr_torrent * tor, int reloadProgress )
    12401238{
    12411239    assert( tr_isTorrent( tor ) );
     
    12731271    assert( tr_isTorrent( tor ) );
    12741272    tr_torrentRecheckCompleteness( tor );
     1273
     1274    if( tor->startAfterVerify )
     1275    {
     1276        tor->startAfterVerify = FALSE;
     1277        tr_torrentStart( tor );
     1278    }
    12751279}
    12761280
     
    12871291{
    12881292    assert( tr_isTorrent( tor ) );
    1289 
     1293    tr_globalLock( tor->session );
     1294
     1295    /* if the torrent's already being verified, stop it */
    12901296    tr_verifyRemove( tor );
    12911297
    1292     tr_globalLock( tor->session );
    1293 
     1298    /* if the torrent's running, stop it & set the restart-after-verify flag */
     1299    if( tor->isRunning ) {
     1300        tr_torrentStop( tor );
     1301        tor->startAfterVerify = TRUE;
     1302    }
     1303
     1304    /* add the torrent to the recheck queue */
    12941305    tr_torrentUncheck( tor );
    12951306    tr_verifyAdd( tor, torrentRecheckDoneCB );
     
    13161327    evbuffer_free( buf );
    13171328}
    1318 
    13191329
    13201330static void
     
    21992209***/
    22002210
     2211struct LocationData
     2212{
     2213    tr_bool move_from_old_location;
     2214    tr_bool * setme_done;
     2215    char * location;
     2216    tr_torrent * tor;
     2217};
     2218
     2219static void
     2220setLocation( void * vdata )
     2221{
     2222    struct LocationData * data = vdata;
     2223    tr_torrent * tor = data->tor;
     2224    const tr_bool do_move = data->move_from_old_location;
     2225    const char * location = data->location;
     2226
     2227    assert( tr_isTorrent( tor ) );
     2228
     2229    if( strcmp( location, tor->downloadDir ) )
     2230    {
     2231        tr_file_index_t i;
     2232
     2233        /* bad idea to move files while they're being verified... */
     2234        tr_verifyRemove( tor );
     2235
     2236        /* if the torrent is running, stop it and set a flag to
     2237         * restart after we're done */
     2238        if( tor->isRunning )
     2239        {
     2240            tr_torrentStop( tor );
     2241            tor->startAfterVerify = TRUE;
     2242        }
     2243
     2244        /* try to move the files.
     2245         * FIXME: there are still all kinds of nasty cases, like what
     2246         * if the target directory runs out of space halfway through... */
     2247        for( i=0; i<tor->info.fileCount; ++i )
     2248        {
     2249            struct stat sb;
     2250            char * oldpath = tr_buildPath( tor->downloadDir, tor->info.files[i].name, NULL );
     2251            char * newpath = tr_buildPath( location, tor->info.files[i].name, NULL );
     2252
     2253           
     2254            if( do_move && !stat( oldpath, &sb ) )
     2255            {
     2256                tr_moveFile( oldpath, newpath );
     2257                tr_torinf( tor, "moving \"%s\" to \"%s\"", oldpath, newpath );
     2258            }
     2259            else if( !stat( newpath, &sb ) )
     2260            {
     2261                tr_torinf( tor, "found \"%s\"", newpath );
     2262            }
     2263
     2264            tr_free( newpath );
     2265            tr_free( oldpath );
     2266        }
     2267
     2268        /* blow away the leftover subdirectories in the old location */
     2269        tr_torrentDeleteLocalData( tor, unlink );
     2270
     2271        /* set the new location and reverify */
     2272        tr_torrentSetDownloadDir( tor, location );
     2273        tr_torrentVerify( tor );
     2274    }
     2275
     2276    if( data->setme_done )
     2277        *data->setme_done = TRUE;
     2278
     2279    /* cleanup */
     2280    tr_free( data->location );
     2281    tr_free( data );
     2282}
     2283
     2284void
     2285tr_torrentSetLocation( tr_torrent * tor,
     2286                       const char * location,
     2287                       tr_bool      move_from_old_location,
     2288                       tr_bool    * setme_done )
     2289{
     2290    struct LocationData * data;
     2291
     2292    assert( tr_isTorrent( tor ) );
     2293
     2294    if( setme_done )
     2295        *setme_done = FALSE;
     2296
     2297    /* run this in the libtransmission thread */
     2298    data = tr_new( struct LocationData, 1 );
     2299    data->tor = tor;
     2300    data->location = tr_strdup( location );
     2301    data->move_from_old_location = move_from_old_location;
     2302    data->setme_done = setme_done;
     2303    tr_runInEventThread( tor->session, setLocation, data );
     2304}
     2305
     2306/***
     2307****
     2308***/
     2309
    22012310void
    22022311tr_torrentCheckSeedRatio( tr_torrent * tor )
  • trunk/libtransmission/torrent.h

    r8279 r8389  
    198198    tr_bool                    isDeleting;
    199199    tr_bool                    needsSeedRatioCheck;
     200    tr_bool                    startAfterVerify;
    200201
    201202    uint16_t                   maxConnectedPeers;
  • trunk/libtransmission/transmission.h

    r8358 r8389  
    936936typedef int tr_fileFunc( const char * filename );
    937937
     938/** @brief Tell transmsision where to find this torrent's local data */
     939void tr_torrentSetLocation( tr_torrent  * torrent,
     940                            const char  * location,
     941                            tr_bool       move_from_previous_location,
     942                            tr_bool     * setme_done );
     943
    938944/**
    939945 * @brief Deletes the torrent's local data.
     
    10551061const tr_info * tr_torrentInfo( const tr_torrent * torrent );
    10561062
    1057 void tr_torrentSetDownloadDir( tr_torrent  * torrent,
    1058                                const char  * path );
     1063/* Raw function to change the torrent's downloadDir field.
     1064   This should only be used by libtransmission or to bootstrap
     1065   a newly-instantiated tr_torrent object. */
     1066void tr_torrentSetDownloadDir( tr_torrent  * torrent, const char * path );
    10591067
    10601068const char * tr_torrentGetDownloadDir( const tr_torrent * torrent );
  • trunk/libtransmission/utils.c

    r8368 r8389  
    15671567    return buf;
    15681568}
     1569
     1570/***
     1571****
     1572***/
     1573
     1574int
     1575tr_moveFile( const char * oldpath, const char * newpath )
     1576{
     1577    int in;
     1578    int out;
     1579    char * buf;
     1580    struct stat st;
     1581    size_t bytesLeft;
     1582    size_t buflen;
     1583
     1584    /* make sure the old file exists */
     1585    if( stat( oldpath, &st ) ) {
     1586        const int err = errno;
     1587        errno = err;
     1588        return -1;
     1589    }
     1590    if( !S_ISREG( st.st_mode ) ) {
     1591        errno = ENOENT;
     1592        return -1;
     1593    }
     1594    bytesLeft = st.st_size;
     1595
     1596    /* make sure the target directory exists */
     1597    {
     1598        char * newdir = tr_dirname( newpath );
     1599        int i = tr_mkdirp( newdir, 0777 );
     1600        tr_free( newdir );
     1601        if( i )
     1602            return i;
     1603    }
     1604
     1605    /* they  might be on the same filesystem... */
     1606    if( !rename( oldpath, newpath ) )
     1607        return 0;
     1608
     1609    /* copy the file */
     1610    in = tr_open_file_for_scanning( oldpath );
     1611    tr_preallocate_file( newpath, bytesLeft );
     1612    out = tr_open_file_for_writing( newpath );
     1613    buflen = stat( newpath, &st ) ? 4096 : st.st_blksize;
     1614    buf = tr_new( char, buflen );
     1615    while( bytesLeft > 0 )
     1616    {
     1617        ssize_t bytesWritten;
     1618        const size_t bytesThisPass = MIN( bytesLeft, buflen );
     1619        const int numRead = read( in, buf, bytesThisPass );
     1620        if( numRead < 0 )
     1621            break;
     1622        bytesWritten = write( out, buf, numRead );
     1623        if( bytesWritten < 0 )
     1624            break;
     1625        bytesLeft -= bytesWritten;
     1626    }
     1627
     1628    /* cleanup */
     1629    tr_free( buf );
     1630    tr_close_file( out );
     1631    tr_close_file( in );
     1632    if( bytesLeft != 0 )
     1633        return -1;
     1634
     1635    unlink( oldpath );
     1636    return 0;
     1637}
  • trunk/libtransmission/utils.h

    r8087 r8389  
    470470
    471471
     472/** on success, return 0.  on failure, return -1 and set errno */
     473int tr_moveFile( const char * oldpath, const char * newpath );
     474
    472475
    473476#ifdef __cplusplus
  • trunk/qt/mainwin.cc

    r8365 r8389  
    3636#include "prefs.h"
    3737#include "prefs-dialog.h"
     38#include "relocate.h"
    3839#include "session.h"
    3940#include "session-dialog.h"
     
    158159    connect( ui.action_Contents, SIGNAL(triggered()), this, SLOT(openHelp()));
    159160    connect( ui.action_OpenFolder, SIGNAL(triggered()), this, SLOT(openFolder()));
     161    connect( ui.action_SetLocation, SIGNAL(triggered()), this, SLOT(setLocation()));
    160162    connect( ui.action_Properties, SIGNAL(triggered()), this, SLOT(openProperties()));
    161163    connect( ui.action_SessionDialog, SIGNAL(triggered()), mySessionDialog, SLOT(show()));
    162164    connect( ui.listView, SIGNAL(activated(const QModelIndex&)), ui.action_Properties, SLOT(trigger()));
    163165
     166    QAction * sep2 = new QAction( this );
     167    sep2->setSeparator( true );
     168
    164169    // context menu
    165170    QList<QAction*> actions;
    166     actions << ui.action_Properties
    167             << ui.action_OpenFolder
    168             << sep
     171    actions << ui.action_OpenFolder
     172            << ui.action_Properties
     173            << ui.action_SetLocation
     174            << sep2
    169175            << ui.action_Start
    170176            << ui.action_Pause
     
    615621
    616622void
     623TrMainWindow :: setLocation( )
     624{
     625    const int torrentId( *getSelectedTorrents().begin() );
     626    QDialog * d = new RelocateDialog( mySession, torrentId, this );
     627    d->show( );
     628}
     629
     630void
    617631TrMainWindow :: openFolder( )
    618632{
     
    734748    const bool oneSelection( selected == 1 );
    735749    ui.action_OpenFolder->setEnabled( oneSelection && mySession.isLocal( ) );
     750    ui.action_SetLocation->setEnabled( oneSelection );
    736751
    737752    ui.action_SelectAll->setEnabled( selected < rowCount );
  • trunk/qt/mainwin.h

    r8344 r8389  
    114114        void openHelp( );
    115115        void openFolder( );
     116        void setLocation( );
    116117        void openProperties( );
    117118        void toggleSpeedMode( );
  • trunk/qt/mainwin.ui

    r8323 r8389  
    5252     <y>0</y>
    5353     <width>792</width>
    54      <height>23</height>
     54     <height>25</height>
    5555    </rect>
    5656   </property>
     
    6969    <addaction name="action_New"/>
    7070    <addaction name="separator"/>
     71    <addaction name="action_OpenFolder"/>
    7172    <addaction name="action_Properties"/>
    72     <addaction name="action_OpenFolder"/>
     73    <addaction name="action_SetLocation"/>
    7374    <addaction name="separator"/>
    7475    <addaction name="action_Start"/>
     
    532533   </property>
    533534  </action>
     535  <action name="action_SetLocation">
     536   <property name="text">
     537    <string>Set &amp;Location...</string>
     538   </property>
     539  </action>
    534540 </widget>
    535541 <resources>
  • trunk/qt/qtr.pro

    r8367 r8389  
    2525SOURCES += about.cc app.cc details.cc file-tree.cc filters.cc hig.cc \
    2626           license.cc mainwin.cc make-dialog.cc options.cc prefs.cc \
    27            prefs-dialog.cc qticonloader.cc session.cc session-dialog.cc \
    28            squeezelabel.cc stats-dialog.cc torrent.cc torrent-delegate.cc \
    29            torrent-delegate-min.cc torrent-filter.cc torrent-model.cc \
    30            triconpushbutton.cc utils.cc watchdir.cc
     27           prefs-dialog.cc qticonloader.cc relocate.cc session.cc \
     28           session-dialog.cc squeezelabel.cc stats-dialog.cc torrent.cc \
     29           torrent-delegate.cc torrent-delegate-min.cc torrent-filter.cc \
     30           torrent-model.cc triconpushbutton.cc utils.cc watchdir.cc
    3131HEADERS += $$replace(SOURCES, .cc, .h)
    3232HEADERS += speed.h types.h
  • trunk/qt/session.cc

    r8369 r8389  
    376376}
    377377
     378void
     379Session :: torrentSetLocation( const QSet<int>& ids, const QString& location, bool doMove )
     380{
     381    tr_benc top;
     382    tr_bencInitDict( &top, 2 );
     383    tr_bencDictAddStr( &top, "method", "torrent-set-location" );
     384    tr_benc * args( tr_bencDictAddDict( &top, "arguments", 3 ) );
     385    addOptionalIds( args, ids );
     386    tr_bencDictAddStr( args, "location", location.toUtf8().constData() );
     387    tr_bencDictAddBool( args, "move", doMove );
     388    exec( &top );
     389    tr_bencFree( &top );
     390}
    378391
    379392void
     
    537550    else if( !myUrl.isEmpty( ) )
    538551    {
    539         const QByteArray data( request, strlen( request ) );
    540552        static const QString path( "/transmission/rpc" );
    541553        QHttpRequestHeader header( "POST", path );
     
    544556        if( !mySessionId.isEmpty( ) )
    545557            header.setValue( TR_RPC_SESSION_ID_HEADER, mySessionId );
    546         myHttp.setProperty( "current-request", data );
    547         myHttp.request( header, data, &myBuffer );
     558        QBuffer * reqbuf = new QBuffer;
     559        reqbuf->setData( QByteArray( request ) );
     560        myHttp.request( header, reqbuf, &myBuffer );
    548561#ifdef DEBUG_HTTP
    549562        std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl;
     
    564577{
    565578    Q_UNUSED( id );
     579    QIODevice * sourceDevice = myHttp.currentSourceDevice( );
    566580
    567581    QHttpResponseHeader response = myHttp.lastResponse();
     
    580594        // update it and resubmit the request.
    581595        mySessionId = response.value( TR_RPC_SESSION_ID_HEADER );
    582         exec( myHttp.property("current-request").toByteArray().constData() );
     596        exec( qobject_cast<QBuffer*>(sourceDevice)->buffer().constData() );
    583597    }
    584598    else if( error )
  • trunk/qt/session.h

    r8358 r8389  
    9292        void torrentSet( const QSet<int>& ids, const QString& key, double val );
    9393        void torrentSet( const QSet<int>& ids, const QString& key, const QList<int>& val );
     94        void torrentSetLocation( const QSet<int>& ids, const QString& path, bool doMove );
    9495
    9596
Note: See TracChangeset for help on using the changeset viewer.