source: trunk/gtk/tr-torrent.c @ 7473

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

(trunk) #1029: When removing local data only remove data from the torrent

  • Property svn:keywords set to Date Rev Author Id
File size: 9.2 KB
Line 
1/******************************************************************************
2 * $Id: tr-torrent.c 7473 2008-12-23 16:04:11Z charles $
3 *
4 * Copyright (c) 2006-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <string.h>
26#include <unistd.h>
27
28#include <gtk/gtk.h>
29#include <glib/gi18n.h>
30
31#include <libtransmission/transmission.h>
32
33#include "tr-prefs.h"
34#include "tr-torrent.h"
35#include "conf.h"
36#include "notify.h"
37#include "util.h"
38
39struct TrTorrentPrivate
40{
41    tr_torrent *  handle;
42    gboolean      do_remove;
43};
44
45
46static void
47tr_torrent_init( GTypeInstance *  instance,
48                 gpointer g_class UNUSED )
49{
50    TrTorrent *               self = TR_TORRENT( instance );
51    struct TrTorrentPrivate * p;
52
53    p = self->priv = G_TYPE_INSTANCE_GET_PRIVATE( self,
54                                                  TR_TORRENT_TYPE,
55                                                  struct TrTorrentPrivate );
56    p->handle = NULL;
57
58#ifdef REFDBG
59    g_message( "torrent %p init", self );
60#endif
61}
62
63static int
64isDisposed( const TrTorrent * tor )
65{
66    return !tor || !TR_IS_TORRENT( tor ) || !tor->priv;
67}
68
69static void
70tr_torrent_dispose( GObject * o )
71{
72    GObjectClass * parent;
73    TrTorrent *    self = TR_TORRENT( o );
74
75    if( !isDisposed( self ) )
76    {
77        if( self->priv->handle )
78        {
79            if( self->priv->do_remove )
80                tr_torrentRemove( self->priv->handle );
81            else
82                tr_torrentFree( self->priv->handle );
83        }
84
85        self->priv = NULL;
86    }
87
88    parent = g_type_class_peek( g_type_parent( TR_TORRENT_TYPE ) );
89    parent->dispose( o );
90}
91
92void
93tr_torrent_clear( TrTorrent * tor )
94{
95    g_return_if_fail( tor );
96    g_return_if_fail( tor->priv );
97
98    tor->priv->handle = NULL;
99}
100
101static void
102tr_torrent_class_init( gpointer              g_class,
103                       gpointer g_class_data UNUSED )
104{
105    GObjectClass *gobject_class = G_OBJECT_CLASS( g_class );
106
107    gobject_class->dispose = tr_torrent_dispose;
108    g_type_class_add_private( g_class, sizeof( struct TrTorrentPrivate ) );
109}
110
111GType
112tr_torrent_get_type( void )
113{
114    static GType type = 0;
115
116    if( !type )
117    {
118        static const GTypeInfo info = {
119            sizeof ( TrTorrentClass ),
120            NULL,                     /* base_init */
121            NULL,                     /* base_finalize */
122            tr_torrent_class_init,    /* class_init */
123            NULL,                     /* class_finalize */
124            NULL,                     /* class_data */
125            sizeof ( TrTorrent ),
126            0,                        /* n_preallocs */
127            tr_torrent_init,          /* instance_init */
128            NULL,
129        };
130        type = g_type_register_static( G_TYPE_OBJECT, "TrTorrent", &info, 0 );
131    }
132    return type;
133}
134
135tr_torrent *
136tr_torrent_handle( TrTorrent *tor )
137{
138    return isDisposed( tor ) ? NULL : tor->priv->handle;
139}
140
141const tr_stat *
142tr_torrent_stat( TrTorrent *tor )
143{
144    tr_torrent * handle = tr_torrent_handle( tor );
145
146    return handle ? tr_torrentStatCached( handle ) : NULL;
147}
148
149const tr_info *
150tr_torrent_info( TrTorrent * tor )
151{
152    tr_torrent * handle = tr_torrent_handle( tor );
153
154    return handle ? tr_torrentInfo( handle ) : NULL;
155}
156
157static gboolean
158notifyInMainThread( gpointer user_data )
159{
160    tr_notify_send( TR_TORRENT( user_data ) );
161    return FALSE;
162}
163
164static void
165completenessChangedCallback( tr_torrent       * tor UNUSED,
166                             tr_completeness    completeness,
167                             void *             user_data )
168{
169    if( completeness != TR_LEECH )
170        g_idle_add( notifyInMainThread, user_data );
171}
172
173static TrTorrent *
174maketorrent( tr_torrent * tor )
175{
176    TrTorrent * gtor = g_object_new( TR_TORRENT_TYPE, NULL );
177
178    gtor->priv->handle = tor;
179    tr_torrentSetCompletenessCallback( tor, completenessChangedCallback, gtor );
180    return gtor;
181}
182
183TrTorrent*
184tr_torrent_new_preexisting( tr_torrent * tor )
185{
186    return maketorrent( tor );
187}
188
189TrTorrent *
190tr_torrent_new_ctor( tr_session   * session,
191                     tr_ctor      * ctor,
192                     char        ** err )
193{
194    tr_torrent * tor;
195    int          errcode;
196    uint8_t      doTrash = FALSE;
197
198    errcode = -1;
199    *err = NULL;
200
201    /* let the gtk client handle the removal, since libT
202     * doesn't have any concept of the glib trash API */
203    tr_ctorGetDeleteSource( ctor, &doTrash );
204    tr_ctorSetDeleteSource( ctor, FALSE );
205    tor = tr_torrentNew( session, ctor, &errcode );
206
207    if( tor && doTrash )
208    {
209        const char * config = tr_sessionGetConfigDir( session );
210        const char * source = tr_ctorGetSourceFile( ctor );
211        const int is_internal = source && ( strstr( source, config ) == source );
212
213        /* #1294: don't delete the source .torrent file if it's our internal copy */
214        if( !is_internal )
215            tr_file_trash_or_unlink( source );
216    }
217
218    if( !tor )
219    {
220        const char * filename = tr_ctorGetSourceFile( ctor );
221        if( !filename )
222            filename = "(null)";
223
224        switch( errcode )
225        {
226            case TR_EINVALID:
227                *err =
228                    g_strdup_printf( _(
229                                         "File \"%s\" isn't a valid torrent" ),
230                                     filename );
231                break;
232
233            case TR_EDUPLICATE:
234                *err = g_strdup_printf( _(
235                                            "File \"%s\" is already open" ),
236                                        filename );
237                break;
238
239            default:
240                *err = g_strdup( filename );
241                break;
242        }
243
244        return NULL;
245    }
246
247    return maketorrent( tor );
248}
249
250char *
251tr_torrent_status_str( TrTorrent * gtor )
252{
253    char *          top = NULL;
254
255    const tr_stat * st = tr_torrent_stat( gtor );
256
257    const int       tpeers = MAX ( st->peersConnected, 0 );
258    const int       upeers = MAX ( st->peersGettingFromUs, 0 );
259    const int       eta = st->eta;
260
261    switch( st->activity )
262    {
263        case TR_STATUS_CHECK_WAIT:
264            top =
265                g_strdup_printf( _(
266                                     "Waiting to verify local data (%.1f%% tested)" ),
267                                 st->recheckProgress * 100.0 );
268            break;
269
270        case TR_STATUS_CHECK:
271            top =
272                g_strdup_printf( _(
273                                     "Verifying local data (%.1f%% tested)" ),
274                                 st->recheckProgress * 100.0 );
275            break;
276
277        case TR_STATUS_DOWNLOAD:
278
279            if( eta < 0 )
280                top = g_strdup_printf( _( "Remaining time unknown" ) );
281            else
282            {
283                char timestr[128];
284                tr_strltime( timestr, eta, sizeof( timestr ) );
285                /* %s is # of minutes */
286                top = g_strdup_printf( _( "%1$s remaining" ), timestr );
287            }
288            break;
289
290        case TR_STATUS_SEED:
291            top = g_strdup_printf(
292                ngettext( "Seeding to %1$'d of %2$'d connected peer",
293                          "Seeding to %1$'d of %2$'d connected peers",
294                          tpeers ),
295                upeers, tpeers );
296            break;
297
298        case TR_STATUS_STOPPED:
299            top = g_strdup( _( "Stopped" ) );
300            break;
301
302        default:
303            top = g_strdup( "???" );
304            break;
305    }
306
307    return top;
308}
309
310void
311tr_torrent_set_remove_flag( TrTorrent * gtor,
312                            gboolean    do_remove )
313{
314    if( !isDisposed( gtor ) )
315        gtor->priv->do_remove = do_remove;
316}
317
318void
319tr_torrent_delete_files( TrTorrent * gtor )
320{
321    tr_torrentDeleteLocalData( tr_torrent_handle( gtor ), tr_file_trash_or_unlink );
322}
323
324void
325tr_torrent_open_folder( TrTorrent * gtor )
326{
327    tr_torrent *    tor = tr_torrent_handle( gtor );
328    const tr_info * info = tr_torrent_info( gtor );
329    char *          path = info->fileCount == 1
330                           ? g_build_filename( tr_torrentGetDownloadDir(
331                                                   tor ), NULL )
332                           : g_build_filename( tr_torrentGetDownloadDir(
333                                                   tor ), info->name, NULL );
334
335    gtr_open_file( path );
336    g_free( path );
337}
338
Note: See TracBrowser for help on using the repository browser.