source: branches/1.5x/gtk/tr-torrent.c @ 7861

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

(1.5x gtk) #1735: .torrent files are not deleted even if you said so

  • Property svn:keywords set to Date Rev Author Id
File size: 8.5 KB
Line 
1/******************************************************************************
2 * $Id: tr-torrent.c 7861 2009-02-09 20:11:32Z 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,
166                             tr_completeness    completeness,
167                             void *             user_data )
168{
169    if( ( completeness != TR_LEECH ) && ( tr_torrentStat( tor )->sizeWhenDone != 0 ) )
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                     int          * errcode )
193{
194    tr_torrent * tor;
195    uint8_t      doTrash = FALSE;
196
197    /* let the gtk client handle the removal, since libT
198     * doesn't have any concept of the glib trash API */
199    tr_ctorGetDeleteSource( ctor, &doTrash );
200    tr_ctorSetDeleteSource( ctor, FALSE );
201    tor = tr_torrentNew( session, ctor, errcode );
202
203    if( tor && doTrash )
204    {
205        const char * config = tr_sessionGetConfigDir( session );
206        const char * source = tr_ctorGetSourceFile( ctor );
207        const int is_internal = source && ( strstr( source, config ) == source );
208
209        /* #1294: don't delete the source .torrent file if it's our internal copy */
210        if( !is_internal )
211            tr_file_trash_or_remove( source );
212    }
213
214    return tor ? maketorrent( tor ) : NULL;
215}
216
217char *
218tr_torrent_status_str( TrTorrent * gtor )
219{
220    char *          top = NULL;
221
222    const tr_stat * st = tr_torrent_stat( gtor );
223
224    const int       tpeers = MAX ( st->peersConnected, 0 );
225    const int       upeers = MAX ( st->peersGettingFromUs, 0 );
226    const int       eta = st->eta;
227
228    switch( st->activity )
229    {
230        case TR_STATUS_CHECK_WAIT:
231            top =
232                g_strdup_printf( _(
233                                     "Waiting to verify local data (%.1f%% tested)" ),
234                                 st->recheckProgress * 100.0 );
235            break;
236
237        case TR_STATUS_CHECK:
238            top =
239                g_strdup_printf( _(
240                                     "Verifying local data (%.1f%% tested)" ),
241                                 st->recheckProgress * 100.0 );
242            break;
243
244        case TR_STATUS_DOWNLOAD:
245
246            if( eta < 0 )
247                top = g_strdup_printf( _( "Remaining time unknown" ) );
248            else
249            {
250                char timestr[128];
251                tr_strltime( timestr, eta, sizeof( timestr ) );
252                /* %s is # of minutes */
253                top = g_strdup_printf( _( "%1$s remaining" ), timestr );
254            }
255            break;
256
257        case TR_STATUS_SEED:
258            top = g_strdup_printf(
259                ngettext( "Seeding to %1$'d of %2$'d connected peer",
260                          "Seeding to %1$'d of %2$'d connected peers",
261                          tpeers ),
262                upeers, tpeers );
263            break;
264
265        case TR_STATUS_STOPPED:
266            top = g_strdup( _( "Stopped" ) );
267            break;
268
269        default:
270            top = g_strdup( "???" );
271            break;
272    }
273
274    return top;
275}
276
277void
278tr_torrent_set_remove_flag( TrTorrent * gtor,
279                            gboolean    do_remove )
280{
281    if( !isDisposed( gtor ) )
282        gtor->priv->do_remove = do_remove;
283}
284
285void
286tr_torrent_delete_files( TrTorrent * gtor )
287{
288    tr_torrentDeleteLocalData( tr_torrent_handle( gtor ), tr_file_trash_or_remove );
289}
290
291void
292tr_torrent_open_folder( TrTorrent * gtor )
293{
294    tr_torrent *    tor = tr_torrent_handle( gtor );
295    const tr_info * info = tr_torrent_info( gtor );
296    char *          path = info->fileCount == 1
297                           ? g_build_filename( tr_torrentGetDownloadDir(
298                                                   tor ), NULL )
299                           : g_build_filename( tr_torrentGetDownloadDir(
300                                                   tor ), info->name, NULL );
301
302    gtr_open_file( path );
303    g_free( path );
304}
305
Note: See TracBrowser for help on using the repository browser.