Changeset 5015


Ignore:
Timestamp:
Feb 13, 2008, 3:00:21 AM (14 years ago)
Author:
charles
Message:

(gtk) new "add torrent" popup to let users choose which files to download, file priority, add paused, delete source .torrent, etc

Location:
trunk
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/Makefile.am

    r5003 r5015  
    2424    makemeta-ui.h \
    2525    msgwin.h \
     26    open.h \
    2627    stats.h \
    2728    sexy-icon-entry.h \
     
    4950    makemeta-ui.c \
    5051    msgwin.c \
     52    open.c \
    5153    sexy-icon-entry.c \
    5254    stats.c \
  • trunk/gtk/dialogs.c

    r4848 r5015  
    2323 *****************************************************************************/
    2424
    25 #include <errno.h>
    26 #include <stdio.h>
    27 #include <stdlib.h>
    28 #include <string.h>
    29 
    3025#include <gtk/gtk.h>
    3126#include <glib/gi18n.h>
     
    3732#include "hig.h"
    3833#include "tr_core.h"
    39 #include "tr_icon.h"
    4034#include "tr_prefs.h"
    41 #include "util.h"
    42 
    43 #define UPDATE_INTERVAL         1000
    44 #define PREFNAME                "transmission-dialog-pref-name"
    45 #define FILESWIND_EXTRA_INDENT  4
    46 
    47 #define STRIPROOT( path )                                                     \
    48     ( g_path_is_absolute( (path) ) ? g_path_skip_root( (path) ) : (path) )
    49 
    50 struct addcb
    51 {
    52   GtkWidget * widget;
    53   TrCore * core;
    54   gboolean autostart;
    55   gboolean usingaltdir;
    56   GtkFileChooser *altdir;
    57   GtkButtonBox *altbox;
     35
     36struct dirdata
     37{
     38    GtkWidget  * widget;
     39    TrCore     * core;
     40    GList      * files;
     41    tr_ctor    * ctor;
    5842};
    5943
    60 struct dirdata
    61 {
    62     GtkWidget             * widget;
    63     TrCore                * core;
    64     GList                 * files;
    65     uint8_t               * data;
    66     size_t                  size;
    67     enum tr_torrent_action  action;
    68     gboolean                paused;
    69 };
    70 
    71 static void
    72 addwindnocore( gpointer gdata, GObject * core );
    73 static void
    74 autoclick(GtkWidget *widget, gpointer gdata);
    75 static void
    76 dirclick(GtkWidget *widget, gpointer gdata);
    77 static void
    78 addresp(GtkWidget *widget, gint resp, gpointer gdata);
    79 static void
    80 promptdirnocore( gpointer gdata, GObject * core );
    81 static void
    82 promptresp( GtkWidget * widget, gint resp, gpointer data );
    83 
    84 void
    85 makeaddwind( GtkWindow * parent, TrCore * core )
    86 {
    87   GtkWidget *wind = gtk_file_chooser_dialog_new(_("Open Torrent"), parent,
    88     GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    89     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
    90   struct addcb *data = g_new(struct addcb, 1);
    91   GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
    92   GtkWidget *bbox = gtk_hbutton_box_new();
    93   GtkWidget *autocheck = gtk_check_button_new_with_mnemonic(
    94     _("Automatically _start torrent"));
    95   GtkWidget *dircheck = gtk_check_button_new_with_mnemonic(
    96     _("Use alternate _download directory"));
    97   GtkFileFilter *filter = gtk_file_filter_new();
    98   GtkFileFilter *unfilter = gtk_file_filter_new();
    99   GtkWidget *getdir = gtk_file_chooser_button_new(
    100     _("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
    101   char * pref;
    102 
    103   data->widget = wind;
    104   data->core = core;
    105   data->autostart = TRUE;
    106   data->usingaltdir = FALSE;
    107   data->altdir = GTK_FILE_CHOOSER(getdir);
    108   data->altbox = GTK_BUTTON_BOX(bbox);
    109 
    110   g_object_weak_ref( G_OBJECT( core ), addwindnocore, data );
    111 
    112   gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_EDGE);
    113   gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
    114   gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
    115 
    116   gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
    117   gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
    118 
    119   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
    120   pref = pref_string_get( PREF_KEY_DIR_DEFAULT );
    121   if( pref != NULL ) {
    122       gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( wind ), pref );
    123       g_free( pref );
    124   }
    125 
    126   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
    127   gtk_widget_set_sensitive(getdir, FALSE);
    128 
    129   gtk_file_filter_set_name(filter, _("Torrent files"));
    130   gtk_file_filter_add_pattern(filter, "*.torrent");
    131   gtk_file_filter_set_name(unfilter, _("All files"));
    132   gtk_file_filter_add_pattern(unfilter, "*");
    133 
    134   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
    135   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
    136   gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
    137   gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
    138 
    139   g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
    140   g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
    141   g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
    142 
    143   gtk_widget_show_all(wind);
    144 }
    145 
    146 void
    147 addwindnocore( gpointer gdata, GObject * core UNUSED )
    148 {
    149     struct addcb * data = gdata;
     44static void
     45promptdirnocore( gpointer gdata, GObject * core UNUSED )
     46{
     47    struct dirdata * stuff = gdata;
    15048
    15149    /* prevent the response callback from trying to remove the weak
    15250       reference which no longer exists */
    153     data->core = NULL;
    154 
    155     gtk_dialog_response( GTK_DIALOG( data->widget ), GTK_RESPONSE_NONE );
    156 }
    157 
    158 static void
    159 autoclick(GtkWidget *widget, gpointer gdata) {
    160   struct addcb *data = gdata;
    161 
    162   data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
    163 }
    164 
    165 static void
    166 dirclick(GtkWidget *widget, gpointer gdata) {
    167   struct addcb *data = gdata;
    168 
    169   data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
    170   gtk_widget_set_sensitive(GTK_WIDGET(data->altdir), data->usingaltdir);
    171 }
    172 
    173 static void
    174 addresp(GtkWidget *widget, gint resp, gpointer gdata) {
    175   struct addcb *data = gdata;
    176   GSList *files, *ii;
    177   GList *stupidgtk;
    178   char *dir;
    179   enum tr_torrent_action action;
    180 
    181   if(GTK_RESPONSE_ACCEPT == resp) {
    182     dir = NULL;
    183     if(data->usingaltdir)
    184       dir = gtk_file_chooser_get_filename(data->altdir);
    185     files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
    186     action = tr_prefs_get_action( PREF_KEY_ADDSTD );
    187 
    188     if( NULL == dir )
     51    stuff->core = NULL;
     52
     53    gtk_dialog_response( GTK_DIALOG( stuff->widget ), GTK_RESPONSE_NONE );
     54}
     55
     56static void
     57promptresp( GtkWidget * widget, gint resp, gpointer data )
     58{
     59    struct dirdata * stuff;
     60
     61    stuff = data;
     62
     63    if( GTK_RESPONSE_ACCEPT == resp )
    18964    {
    190         stupidgtk = NULL;
    191         for( ii = files; NULL != ii; ii = ii->next )
    192         {
    193             stupidgtk = g_list_append( stupidgtk, ii->data );
    194         }
    195         tr_core_add_list( data->core, stupidgtk, action, !data->autostart );
    196         freestrlist(stupidgtk);
    197     }
    198     else
    199     {
    200         for( ii = files; NULL != ii; ii = ii->next )
    201         {
    202             tr_core_add_dir( data->core, ii->data, dir,
    203                              action, !data->autostart );
    204             g_free( ii->data );
    205         }
     65        char * dir;
     66        GList * l;
     67
     68        /* update the destination */
     69        dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
     70        tr_ctorSetDestination( stuff->ctor, TR_FORCE, dir );
    20671        g_free( dir );
    207     }
    208     tr_core_torrents_added( data->core );
    209     g_slist_free(files);
    210   }
    211 
    212   if( NULL != data->core )
    213   {
    214       g_object_weak_unref( G_OBJECT( data->core ), addwindnocore, data );
    215   }
    216 
    217   g_free( data );
    218   gtk_widget_destroy(widget);
     72
     73        /* if there's metainfo in the ctor already, use it */
     74        if( !tr_ctorGetMetainfo( stuff->ctor, NULL ) )
     75            tr_core_add_ctor( stuff->core, stuff->ctor );
     76
     77        /* if there's a list of files, use them too */
     78        for( l=stuff->files; l!=NULL; l=l->next )
     79            if( !tr_ctorSetMetainfoFromFile( stuff->ctor, l->data ) )
     80                tr_core_add_ctor( stuff->core, stuff->ctor );
     81    }
     82
     83    if( stuff->core )
     84        g_object_weak_unref( G_OBJECT( stuff->core ), promptdirnocore, stuff );
     85
     86    gtk_widget_destroy( widget );
     87    freestrlist( stuff->files );
     88    tr_ctorFree( stuff->ctor );
     89    g_free( stuff );
    21990}
    22091
     
    235106}
    236107
     108static void
     109deleteToggled( GtkToggleButton * tb, gpointer ctor )
     110{
     111    tr_ctorSetDeleteSource( ctor, gtk_toggle_button_get_active( tb ) );
     112}
     113
     114static void
     115startToggled( GtkToggleButton * tb, gpointer ctor )
     116{
     117    tr_ctorSetPaused( ctor, TR_FORCE, !gtk_toggle_button_get_active( tb ) );
     118}
     119
    237120void
    238 promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
    239               size_t size, enum tr_torrent_action act, gboolean paused )
    240 {
    241     char * path;
     121promptfordir( GtkWindow * parent, TrCore * core, GList * files, tr_ctor * ctor )
     122{
     123    uint8_t          flag = 0;
     124    const char     * str;
    242125    struct dirdata * stuff;
    243126    GtkWidget      * wind;
     127    GtkWidget      * v;
     128    GtkWidget      * w;
    244129
    245130    stuff = g_new0( struct dirdata, 1 );
    246     stuff->core    = core;
    247     if( NULL != files )
    248     {
    249         stuff->files = dupstrlist( files );
    250     }
    251     if( NULL != data )
    252     {
    253         stuff->data = g_new( uint8_t, size );
    254         memcpy( stuff->data, data, size );
    255         stuff->size = size;
    256     }
    257     stuff->action  = act;
    258     stuff->paused  = paused;
     131    stuff->core   = core;
     132    stuff->ctor   = ctor;
     133    stuff->files  = dupstrlist( files );
    259134
    260135    g_object_weak_ref( G_OBJECT( core ), promptdirnocore, stuff );
     
    267142    gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( wind ), TRUE );
    268143    gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( wind ), FALSE );
    269     path = getdownloaddir( );
    270     gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ), path );
    271     g_free( path );
     144    tr_ctorGetDestination( ctor, TR_FORCE, &str );
     145    gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( wind ), str );
     146
     147    v = gtk_vbox_new( FALSE, GUI_PAD );
     148
     149        w = gtk_check_button_new_with_mnemonic( _( "_Delete original torrent file" ) );
     150        g_signal_connect( w, "toggled", G_CALLBACK( deleteToggled ), ctor );
     151        tr_ctorGetDeleteSource( ctor, &flag );
     152        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), flag );
     153        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
     154
     155        w = gtk_check_button_new_with_mnemonic( _( "_Start when added" ) );
     156        g_signal_connect( w, "toggled", G_CALLBACK( startToggled ), ctor );
     157        tr_ctorGetPaused( ctor, TR_FORCE, &flag );
     158        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), !flag );
     159        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
     160
     161    gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( wind ), v );
    272162
    273163    stuff->widget = wind;
     
    277167
    278168    gtk_widget_show_all(wind);
    279 }
    280 
    281 void
    282 promptdirnocore( gpointer gdata, GObject * core UNUSED )
    283 {
    284     struct dirdata * stuff = gdata;
    285 
    286     /* prevent the response callback from trying to remove the weak
    287        reference which no longer exists */
    288     stuff->core = NULL;
    289 
    290     gtk_dialog_response( GTK_DIALOG( stuff->widget ), GTK_RESPONSE_NONE );
    291 }
    292 
    293 static void
    294 promptresp( GtkWidget * widget, gint resp, gpointer data )
    295 {
    296     struct dirdata * stuff;
    297     char           * dir;
    298     GList          * ii;
    299 
    300     stuff = data;
    301 
    302     if( GTK_RESPONSE_ACCEPT == resp )
    303     {
    304         dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
    305         /* it seems that we will always get a directory */
    306         g_assert( NULL != dir );
    307         for( ii = g_list_first( stuff->files ); NULL != ii; ii = ii->next )
    308         {
    309             tr_core_add_dir( stuff->core, ii->data, dir,
    310                              stuff->action, stuff->paused );
    311         }
    312         if( NULL != stuff->data )
    313         {
    314             tr_core_add_data_dir( stuff->core, stuff->data, stuff->size, dir,
    315                                   stuff->paused );
    316         }
    317         tr_core_torrents_added( stuff->core );
    318         g_free( dir );
    319     }
    320 
    321     if( NULL != stuff->core )
    322     {
    323         g_object_weak_unref( G_OBJECT( stuff->core ), promptdirnocore, stuff );
    324     }
    325 
    326     freestrlist( stuff->files );
    327     g_free( stuff->data );
    328     g_free( stuff );
    329     gtk_widget_destroy( widget );
    330169}
    331170
     
    346185{
    347186    struct quitdata * stuff = data;
    348 
    349     pref_flag_set( PREF_KEY_ASKQUIT,
    350                    !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(stuff->dontask) ) );
     187    GtkToggleButton * tb = GTK_TOGGLE_BUTTON( stuff->dontask );
     188
     189    tr_core_set_pref_bool( stuff->core,
     190                           PREF_KEY_ASKQUIT,
     191                           !gtk_toggle_button_get_active( tb ) );
    351192
    352193    if( response == GTK_RESPONSE_ACCEPT )
  • trunk/gtk/dialogs.h

    r4404 r5015  
    3030#include "util.h"
    3131
    32 /* show the "add a torrent" dialog */
    33 void
    34 makeaddwind( GtkWindow * parent, TrCore * core );
    35 
    3632/* prompt for a download directory for torrents, then add them */
    37 void
    38 promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
    39               size_t size, enum tr_torrent_action act, gboolean paused );
     33void promptfordir( GtkWindow* parent, TrCore*, GList* filenames, tr_ctor* );
    4034
    4135/* prompt if the user wants to quit, calls func with cbdata if they do */
    42 void
    43 askquit( TrCore*, GtkWindow* parent, callbackfunc_t func, void * cbdata );
     36void askquit( TrCore*, GtkWindow* parent, callbackfunc_t func, void* cbdata );
    4437
    4538#endif /* TG_PREFS_H */
  • trunk/gtk/file-list.c

    r5009 r5015  
    375375{
    376376    FileData * data = gdata;
     377
     378    g_object_weak_unref( G_OBJECT( data->gtor ), torrentDestroyed, data );
     379
    377380    file_list_set_torrent( data->top, NULL );
    378381}
  • trunk/gtk/ipc.c

    r4876 r5015  
    580580    struct constate      * con = arg;
    581581    struct constate_serv * srv = &con->u.serv;
    582     enum tr_torrent_action action;
    583582    benc_val_t           * path;
    584583    int                    ii;
     584    tr_ctor              * ctor;
     585    GList                * list = NULL;
    585586
    586587    if( NULL == val || TYPE_LIST != val->type )
     
    590591    }
    591592
    592     action = tr_prefs_get_action( PREF_KEY_ADDIPC );
     593    ctor = tr_ctorNew( srv->core );
     594
    593595    for( ii = 0; ii < val->val.l.count; ii++ )
    594596    {
     
    598600            g_utf8_validate( path->val.s.s, path->val.s.i, NULL ) )
    599601        {
    600             tr_core_add( TR_CORE( srv->core ), path->val.s.s, action, FALSE );
    601         }
    602     }
    603     tr_core_torrents_added( TR_CORE( srv->core ) );
     602            list = g_list_append( list, g_strndup( path->val.s.s, path->val.s.i ) );
     603        }
     604    }
     605
     606    if( list ) {
     607        tr_core_add_list( srv->core, list, ctor );
     608        tr_core_torrents_added( TR_CORE( srv->core ) );
     609    }
    604610
    605611    /* XXX should send info response back with torrent ids */
     
    613619    struct constate      * con = arg;
    614620    struct constate_serv * srv = &con->u.serv;
    615     enum tr_torrent_action action;
    616621    benc_val_t           * file, * data, * dir, * start;
    617     gboolean               paused;
     622    tr_ctor              * ctor;
    618623
    619624    if( NULL == val || TYPE_DICT != val->type )
     
    637642    }
    638643
    639     action = tr_prefs_get_action( PREF_KEY_ADDIPC );
    640     paused = ( NULL == start || start->val.i ? FALSE : TRUE );
    641     if( NULL != file )
    642     {
    643         if( NULL == dir )
    644         {
    645             tr_core_add( srv->core, file->val.s.s, action, paused );
    646         }
    647         else
    648         {
    649             tr_core_add_dir( srv->core, file->val.s.s, dir->val.s.s,
    650                              action, paused );
    651         }
    652     }
    653     else
    654     {
    655         if( NULL == dir )
    656         {
    657             tr_core_add_data( srv->core, (uint8_t *) data->val.s.s,
    658                               data->val.s.i, paused );
    659         }
    660         else
    661         {
    662             tr_core_add_data_dir( srv->core, (uint8_t *) data->val.s.s,
    663                                   data->val.s.i, dir->val.s.s, paused );
    664         }
    665     }
     644    ctor = tr_ctorNew( tr_core_handle( srv->core ) );
     645    if( dir )
     646        tr_ctorSetDestination( ctor, TR_FORCE, dir->val.s.s );
     647    if( file )
     648        tr_ctorSetMetainfoFromFile( ctor, file->val.s.s );
     649    if( data )
     650        tr_ctorSetMetainfo( ctor, (uint8_t*)data->val.s.s, data->val.s.i );
     651    if( start )
     652        tr_ctorSetPaused( ctor, TR_FORCE, !start->val.i );
     653
     654    tr_core_add_ctor( TR_CORE( srv->core ), ctor );
     655
    666656    tr_core_torrents_added( TR_CORE( srv->core ) );
    667657
     
    999989        case IPC_MSG_GETDIR:
    1000990            /* XXX sending back "" when we're prompting is kind of bogus */
    1001             pref = pref_flag_get( PREF_KEY_DIR_ASK ) ? "" : getdownloaddir();
     991            pref = pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) ? "" : getdownloaddir();
    1002992            buf = ipc_mkstr( con->ipc, &size, IPC_MSG_DIR, tag, pref );
    1003993            break;
  • trunk/gtk/main.c

    r4982 r5015  
    4848#include "makemeta-ui.h"
    4949#include "msgwin.h"
     50#include "open.h"
    5051#include "stats.h"
    5152#include "torrent-inspector.h"
     
    147148         gpointer gdata );
    148149static void
    149 coreprompt( TrCore *, GList *, enum tr_torrent_action, gboolean, gpointer );
    150 static void
    151 corepromptdata( TrCore *, uint8_t *, size_t, gboolean, gpointer );
     150coreprompt( TrCore *, GList *, gpointer, gpointer );
    152151static void
    153152initializeFromPrefs( struct cbdata * cbdata );
     
    330329appsetup( TrWindow * wind, GList * args,
    331330          struct cbdata * cbdata,
    332           gboolean paused, gboolean minimized )
    333 {
    334     enum tr_torrent_action action;
    335 
     331          gboolean forcepause, gboolean minimized )
     332{
    336333    /* fill out cbdata */
    337334    cbdata->wind       = NULL;
     
    350347    g_signal_connect( cbdata->core, "directory-prompt",
    351348                      G_CALLBACK( coreprompt ), cbdata );
    352     g_signal_connect( cbdata->core, "directory-prompt-data",
    353                       G_CALLBACK( corepromptdata ), cbdata );
    354349    g_signal_connect_swapped( cbdata->core, "quit",
    355350                              G_CALLBACK( wannaquit ), cbdata );
     
    364359
    365360    /* add torrents from command-line and saved state */
    366     tr_core_load( cbdata->core, paused );
     361    tr_core_load( cbdata->core, forcepause );
    367362
    368363    if( NULL != args )
    369364    {
    370         action = tr_prefs_get_action( PREF_KEY_ADDIPC );
    371         tr_core_add_list( cbdata->core, args, action, paused );
     365        tr_ctor * ctor = tr_ctorNew( tr_core_handle( cbdata->core ) );
     366        if( forcepause )
     367            tr_ctorSetPaused( ctor, TR_FORCE, TRUE );
     368        tr_core_add_list( cbdata->core, args, ctor );
    372369    }
    373370    tr_core_torrents_added( cbdata->core );
     
    626623    GList * freeme = NULL;
    627624
    628 #ifdef DND_DEBUG
     625#if 0
     626    int i;
    629627    char *sele = gdk_atom_name(sel->selection);
    630628    char *targ = gdk_atom_name(sel->target);
     
    684682        if( paths != NULL )
    685683        {
    686             enum tr_torrent_action action = tr_prefs_get_action( PREF_KEY_ADDSTD );
     684            tr_ctor * ctor = tr_ctorNew( tr_core_handle( data->core ) );
    687685            paths = g_list_reverse( paths );
    688             tr_core_add_list( data->core, paths, action, FALSE );
     686            tr_core_add_list( data->core, paths, ctor );
    689687            tr_core_torrents_added( data->core );
    690688            g_list_free( paths );
     
    749747}
    750748
    751 void
    752 coreprompt( TrCore * core, GList * paths, enum tr_torrent_action act,
    753             gboolean paused, gpointer gdata )
     749static void
     750coreprompt( TrCore                 * core,
     751            GList                  * paths,
     752            gpointer                 ctor,
     753            gpointer                 gdata )
    754754{
    755755    struct cbdata * cbdata = gdata;
    756756
    757     promptfordir( cbdata->wind, core, paths, NULL, 0, act, paused );
    758 }
    759 
    760 void
    761 corepromptdata( TrCore * core, uint8_t * data, size_t size,
    762                 gboolean paused, gpointer gdata )
    763 {
    764     struct cbdata * cbdata = gdata;
    765 
    766     promptfordir( cbdata->wind, core, NULL, data, size, TR_TOR_LEAVE, paused );
     757    if( g_list_length( paths ) != 1 )
     758        promptfordir( cbdata->wind, core, paths, ctor );
     759    else {
     760        tr_ctorSetMetainfoFromFile( ctor, paths->data );
     761        makeaddwind( cbdata->wind, core, ctor );
     762    }
    767763}
    768764
     
    10141010    if ( !strcmp (action_name, "open-torrent-menu") || !strcmp( action_name, "open-torrent-toolbar" ))
    10151011    {
    1016         makeaddwind( data->wind, data->core );
     1012        makeaddwind( data->wind, data->core, tr_ctorNew( tr_core_handle( data->core ) ) );
    10171013    }
    10181014    else if (!strcmp (action_name, "show-stats"))
  • trunk/gtk/my-valgrind.sh

    r3160 r5015  
    33export G_DEBUG=gc-friendly
    44export GLIBCXX_FORCE_NEW=1
    5 valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=64 --log-file=x-valgrind --show-reachable=yes ./transmission
     5valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=64 --log-file=x-valgrind --show-reachable=yes ./transmission ~/Desktop/*torrent
  • trunk/gtk/tr_core.c

    r5005 r5015  
    7878                        gpointer marshal )
    7979{
    80     typedef void (*TRMarshalPrompt)
    81         ( gpointer, GList *, enum tr_torrent_action, gboolean, gpointer );
     80    typedef void (*TRMarshalPrompt)( gpointer, GList *, gpointer, gpointer );
    8281    TRMarshalPrompt        callback;
    8382    GCClosure            * cclosure = (GCClosure*) closure;
    8483    GList                * paths;
    85     enum tr_torrent_action action;
    86     gboolean               paused;
     84    gpointer               ctor;
    8785    gpointer               inst, gdata;
    8886
    89     g_return_if_fail( 4 == count );
    90 
    91     inst    = g_value_peek_pointer( vals );
    92     paths   = g_value_get_pointer( vals + 1 );
    93     action  = g_value_get_int( vals + 2 );
    94     paused  = g_value_get_boolean( vals + 3 );
    95     gdata   = closure->data;
     87    g_return_if_fail( 3 == count );
     88
     89    inst      = g_value_peek_pointer( vals );
     90    paths     = g_value_get_pointer( vals + 1 );
     91    ctor      = g_value_get_pointer( vals + 2 );
     92    gdata     = closure->data;
    9693
    9794    callback = (TRMarshalPrompt) ( NULL == marshal ?
    9895                                   cclosure->callback : marshal );
    99     callback( inst, paths, action, paused, gdata );
    100 }
    101 
    102 static void
    103 tr_core_marshal_data( GClosure * closure, GValue * ret UNUSED, guint count,
    104                       const GValue * vals, gpointer hint UNUSED,
    105                       gpointer marshal )
    106 {
    107     typedef void (*TRMarshalPrompt)
    108         ( gpointer, uint8_t *, size_t, gboolean, gpointer );
    109     TRMarshalPrompt        callback;
    110     GCClosure            * cclosure = (GCClosure*) closure;
    111     uint8_t              * data;
    112     size_t                 size;
    113     gboolean               paused;
    114     gpointer               inst, gdata;
    115 
    116     g_return_if_fail( 4 == count );
    117 
    118     inst    = g_value_peek_pointer( vals );
    119     data    = (uint8_t *) g_value_get_string( vals + 1 );
    120     size    = g_value_get_uint( vals + 2 );
    121     paused  = g_value_get_boolean( vals + 3 );
    122     gdata   = closure->data;
    123 
    124     callback = (TRMarshalPrompt) ( NULL == marshal ?
    125                                    cclosure->callback : marshal );
    126     callback( inst, data, size, paused, gdata );
     96    callback( inst, paths, ctor, gdata );
    12797}
    12898
     
    172142                                          G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    173143                                          tr_core_marshal_prompt, G_TYPE_NONE,
    174                                           3, G_TYPE_POINTER, G_TYPE_INT,
    175                                           G_TYPE_BOOLEAN );
    176     core_class->promptdatasig = g_signal_new( "directory-prompt-data",
    177                                               G_TYPE_FROM_CLASS( g_class ),
    178                                               G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    179                                               tr_core_marshal_data,
    180                                               G_TYPE_NONE, 3, G_TYPE_STRING,
    181                                               G_TYPE_UINT, G_TYPE_BOOLEAN );
     144                                          2, G_TYPE_POINTER, G_TYPE_POINTER );
    182145    core_class->quitsig = g_signal_new( "quit", G_TYPE_FROM_CLASS( g_class ),
    183146                                        G_SIGNAL_RUN_LAST, 0, NULL, NULL,
     
    487450}
    488451
    489 static void
    490 tr_core_insert( TrCore * self, TrTorrent * tor )
     452void
     453tr_core_add_torrent( TrCore * self, TrTorrent * tor )
    491454{
    492455    const tr_info * inf = tr_torrent_info( tor );
     
    495458    GtkListStore * store = GTK_LIST_STORE( tr_core_model( self ) );
    496459    GtkTreeIter unused;
     460
    497461    gtk_list_store_insert_with_values( store, &unused, 0,
    498462                                       MC_NAME,          inf->name,
     
    504468                                       MC_ID,            self->priv->nextid,
    505469                                       -1);
    506     self->priv->nextid++;
    507     g_object_unref( tor );
     470    ++self->priv->nextid;
     471
     472    /* cleanup */
     473    g_object_unref( G_OBJECT( tor ) );
    508474    g_free( collated );
    509475}
     
    530496    torrents = tr_loadTorrents ( tr_core_handle( self ), ctor, &count );
    531497    for( i=0; i<count; ++i )
    532         tr_core_insert( self, tr_torrent_new_preexisting( torrents[i] ) );
     498        tr_core_add_torrent( self, tr_torrent_new_preexisting( torrents[i] ) );
    533499
    534500    tr_free( torrents );
     
    539505}
    540506
    541 gboolean
    542 tr_core_add( TrCore * self, const char * path, enum tr_torrent_action act,
    543              gboolean paused )
    544 {
    545     GList * list;
    546     int     ret;
    547 
    548     TR_IS_CORE( self );
    549 
    550     list = g_list_append( NULL, (void *) path );
    551     ret  = tr_core_add_list( self, list, act, paused );
    552     g_list_free( list );
    553 
    554     return 1 == ret;
    555 }
    556 
    557507static void
    558508tr_core_errsig( TrCore * self, enum tr_core_err type, const char * msg )
     
    564514}
    565515
    566 gboolean
    567 tr_core_add_dir( TrCore * self, const char * path, const char * dir,
    568                  enum tr_torrent_action act, gboolean paused )
     516static void
     517tr_core_apply_defaults( tr_ctor * ctor )
     518{
     519    if( tr_ctorGetPaused( ctor, TR_FORCE, NULL ) )
     520        tr_ctorSetPaused( ctor, TR_FORCE, !pref_flag_get( PREF_KEY_START ) );
     521
     522    if( tr_ctorGetDeleteSource( ctor, NULL ) )
     523        tr_ctorSetDeleteSource( ctor, pref_flag_get( PREF_KEY_DELETE_ORIGINAL ) );
     524
     525    if( tr_ctorGetMaxConnectedPeers( ctor, TR_FORCE, NULL ) )
     526        tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
     527
     528    if( tr_ctorGetDestination( ctor, TR_FORCE, NULL ) ) {
     529        char * path = pref_string_get( PREF_KEY_DIR_DEFAULT );
     530        tr_ctorSetDestination( ctor, TR_FORCE, path );
     531        g_free( path );
     532    }
     533}
     534
     535void
     536tr_core_add_ctor( TrCore * self, tr_ctor * ctor )
    569537{
    570538    TrTorrent * tor;
    571539    char      * errstr;
    572540
    573     TR_IS_CORE( self );
    574 
    575541    errstr = NULL;
    576     tor = tr_torrent_new( tr_core_handle( self ), path, dir, act, paused, &errstr );
    577     if( NULL == tor )
     542
     543    tr_core_apply_defaults( ctor );
     544    tor = tr_torrent_new_ctor( tr_core_handle( self ), ctor, &errstr );
     545    if( !tor )
    578546    {
    579547        tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
    580548        g_free( errstr );
    581         return FALSE;
    582     }
    583     g_assert( NULL == errstr );
    584 
    585     tr_core_insert( self, tor );
    586 
    587     return TRUE;
    588 }
    589 
    590 int
    591 tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
    592                   gboolean paused )
    593 {
    594     char * dir;
    595     int count;
    596 
    597     TR_IS_CORE( self );
    598 
    599     if( pref_flag_get( PREF_KEY_DIR_ASK ) )
     549        errstr = NULL;
     550    }
     551    else
     552    {
     553        g_assert( !errstr );
     554        tr_core_add_torrent( self, tor );
     555    }
     556}
     557
     558void
     559tr_core_add_list( TrCore   * self,
     560                  GList    * paths,
     561                  tr_ctor  * ctor )
     562{
     563    tr_core_apply_defaults( ctor );
     564
     565    if( pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) )
    600566    {
    601567        TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
    602         g_signal_emit( self, class->promptsig, 0, paths, act, paused );
    603         return 0;
    604     }
    605 
    606     dir = getdownloaddir();
    607     count = 0;
    608     for( ; paths; paths=paths->next )
    609         if( tr_core_add_dir( self, paths->data, dir, act, paused ) )
    610             count++;
    611 
    612     g_free( dir );
    613     return count;
    614 }
    615 
    616 gboolean
    617 tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused )
    618 {
    619     gboolean ret;
    620     char * path;
    621     TR_IS_CORE( self );
    622 
    623     if( pref_flag_get( PREF_KEY_DIR_ASK ) )
    624     {
    625         TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
    626         g_signal_emit( self, class->promptdatasig, 0, data, size, paused );
    627         return FALSE;
    628     }
    629 
    630     path = getdownloaddir( );
    631     ret = tr_core_add_data_dir( self, data, size, path, paused );
    632     g_free( path );
    633     return ret;
    634 }
    635 
    636 gboolean
    637 tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
    638                       const char * dir, gboolean paused )
    639 {
    640     TrTorrent * tor;
    641     char      * errstr = NULL;
    642 
    643     TR_IS_CORE( self );
    644 
    645     tor = tr_torrent_new_with_data( tr_core_handle( self ), data, size, dir,
    646                                     paused, &errstr );
    647     if( NULL == tor )
    648     {
    649         tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
    650         g_free( errstr );
    651         return FALSE;
    652     }
    653     g_assert( NULL == errstr );
    654 
    655     tr_core_insert( self, tor );
    656 
    657     return TRUE;
     568        g_signal_emit( self, class->promptsig, 0, paths, ctor );
     569    }
     570    else
     571    {
     572        for( ; paths; paths=paths->next )
     573            if( !tr_ctorSetMetainfoFromFile( ctor, paths->data ) )
     574                tr_core_add_ctor( self, ctor );
     575        tr_ctorFree( ctor );
     576    }
    658577}
    659578
     
    661580tr_core_torrents_added( TrCore * self )
    662581{
    663     TR_IS_CORE( self );
    664 
    665582    tr_core_update( self );
    666583    tr_core_errsig( self, TR_CORE_ERR_NO_MORE_TORRENTS, NULL );
     
    672589    TrTorrent * tor;
    673590    GtkTreeModel * model = tr_core_model( self );
    674 
    675     TR_IS_CORE( self );
    676591
    677592    gtk_tree_model_get( model, iter, MC_TORRENT, &tor, -1 );
     
    747662tr_core_quit( TrCore * self )
    748663{
    749     TrCoreClass * class;
    750 
    751     TR_IS_CORE( self );
    752 
    753     class = g_type_class_peek( TR_CORE_TYPE );
     664    TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
    754665    g_signal_emit( self, class->quitsig, 0 );
    755666}
  • trunk/gtk/tr_core.h

    r4998 r5015  
    3131#include <gtk/gtk.h>
    3232
    33 #include <libtransmission/bencode.h>
    3433#include <libtransmission/transmission.h>
    3534
     35#include "tr_torrent.h"
    3636#include "util.h"
    3737
    38 #define TR_CORE_TYPE            ( tr_core_get_type() )
    39 
    40 #define TR_CORE( obj )                                                        \
    41   ( G_TYPE_CHECK_INSTANCE_CAST( (obj),   TR_CORE_TYPE, TrCore ) )
    42 
    43 #define TR_CORE_CLASS( class )                                                \
    44   ( G_TYPE_CHECK_CLASS_CAST(    (class), TR_CORE_TYPE, TrCoreClass ) )
    45 
    46 #define TR_IS_CORE( obj )                                                     \
    47   ( G_TYPE_CHECK_INSTANCE_TYPE( (obj),   TR_CORE_TYPE ) )
    48 
    49 #define TR_IS_CORE_CLASS( class )                                             \
    50   ( G_TYPE_CHECK_CLASS_TYPE(    (class), TR_CORE_TYPE ) )
    51 
    52 #define TR_CORE_GET_CLASS( obj )                                              \
    53   ( G_TYPE_INSTANCE_GET_CLASS(  (obj),   TR_CORE_TYPE, TrCoreClass ) )
    54 
     38#define TR_CORE_TYPE (tr_core_get_type())
     39#define TR_CORE(o) G_TYPE_CHECK_INSTANCE_CAST((o),TR_CORE_TYPE,TrCore)
     40#define TR_IS_CORE(o) G_TYPE_CHECK_INSTANCE_TYPE((o),TR_CORE_TYPE)
     41#define TR_CORE_CLASS(k) G_TYPE_CHECK_CLASS_CAST((k),TR_CORE_TYPE,TrCoreClass)
     42#define TR_IS_CORE_CLASS(k) G_TYPE_CHECK_CLASS_TYPE((k),TR_CORE_TYPE)
     43#define TR_CORE_GET_CLASS(o) G_TYPE_INSTANCE_GET_CLASS((o),TR_CORE_TYPE,TrCoreClass)
    5544
    5645struct core_stats
     
    6251};
    6352
    64 /* treat the contents of this structure as private */
    6553typedef struct TrCore
    6654{
     
    7967
    8068    /* "directory-prompt" signal:
    81        void handler( TrCore *, GList *, enum tr_torrent_action, gboolean, gpointer ) */
     69       void handler( TrCore *, GList *, gpointer ctor, gpointer userData ) */
    8270    int promptsig;
    83 
    84     /* "directory-prompt-data" signal:
    85        void handler( TrCore *, uint8_t *, size_t, gboolean, gpointer ) */
    86     int promptdatasig;
    8771
    8872    /* "quit" signal:
     
    121105tr_core_get_stats( const TrCore * self );
    122106
    123 /* Load saved state, return number of torrents added. May trigger one
    124    or more "error" signals with TR_CORE_ERR_ADD_TORRENT */
    125 int
    126 tr_core_load( TrCore * self, gboolean forcepaused );
     107/******
     108*******
     109******/
    127110
    128 /* Any the tr_core_add functions below may trigger an "error" signal
    129    with TR_CORE_ERR_ADD_TORRENT */
     111/**
     112 * Load saved state and return number of torrents added.
     113 * May trigger one or more "error" signals with TR_CORE_ERR_ADD_TORRENT
     114 */
     115int tr_core_load( TrCore * self, gboolean forcepaused );
    130116
    131 /* Add the torrent at the given path */
    132 gboolean
    133 tr_core_add( TrCore * self, const char * path, enum tr_torrent_action act,
    134              gboolean paused );
     117/**
     118 * Add a torrent.
     119 * May trigger an "error" signal with TR_CORE_ERR_ADD_TORRENT
     120 * Caller must free the ctor.
     121 */
     122void tr_core_add_ctor( TrCore * self, tr_ctor * ctor );
    135123
    136 /* Add the torrent at the given path with the given download directory */
    137 gboolean
    138 tr_core_add_dir( TrCore * self, const char * path, const char * dir,
    139                  enum tr_torrent_action act, gboolean paused );
     124/**
     125 * Add a list of torrents.
     126 * May trigger one or more "error" signals with TR_CORE_ERR_ADD_TORRENT
     127 */
     128void tr_core_add_list( TrCore   * self,
     129                       GList    * torrentFiles,
     130                       tr_ctor  * ctor );
    140131
    141 /* Add a list of torrents with the given paths */
    142 int
    143 tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
    144                   gboolean paused );
     132/**
     133 * Add a torrent.
     134 */
     135void tr_core_add_torrent( TrCore*, TrTorrent* );
    145136
    146 /* Add the torrent data in the given buffer */
    147 gboolean
    148 tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused );
     137/**
     138 * Notifies listeners that torrents have been added.
     139 * This should be called after one or more tr_core_add*() calls.
     140 */
     141void tr_core_torrents_added( TrCore * self );
    149142
    150 /* Add the torrent data in the given buffer with the given download directory */
    151 gboolean
    152 tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
    153                       const char * dir, gboolean paused );
    154 
    155 /* Save state, update model, and signal the end of a torrent cluster */
    156 void
    157 tr_core_torrents_added( TrCore * self );
     143/******
     144*******
     145******/
    158146
    159147/* remove a torrent, waiting for it to pause if necessary */
  • trunk/gtk/tr_prefs.c

    r5007 r5015  
    4343    pref_int_set_default    ( PREF_KEY_UL_LIMIT, 50 );
    4444
    45     pref_flag_set_default   ( PREF_KEY_DIR_ASK, FALSE );
     45    pref_flag_set_default   ( PREF_KEY_OPTIONS_PROMPT, TRUE );
    4646    pref_string_set_default ( PREF_KEY_DIR_DEFAULT, g_get_home_dir() );
    4747
     
    5454    pref_flag_set_default   ( PREF_KEY_ENCRYPTED_ONLY, FALSE );
    5555
    56     pref_string_set_default ( PREF_KEY_ADDSTD, toractionname(TR_TOR_COPY) );
    57     pref_string_set_default ( PREF_KEY_ADDIPC, toractionname(TR_TOR_COPY) );
    58 
    5956    pref_int_set_default    ( PREF_KEY_MSGLEVEL, TR_MSG_INF );
    6057
     
    6360    pref_flag_set_default   ( PREF_KEY_MINIMAL_VIEW, FALSE );
    6461
     62    pref_flag_set_default   ( PREF_KEY_START, TRUE );
     63    pref_flag_set_default   ( PREF_KEY_DELETE_ORIGINAL, FALSE );
     64
    6565    pref_save( NULL );
    66 }
    67 
    68 /**
    69 ***
    70 **/
    71 
    72 int
    73 tr_prefs_get_action( const char * key )
    74 {
    75     char * val = pref_string_get( key );
    76     const int ret = toraddaction( val );
    77     g_free( val );
    78     return ret;
    79 }
    80 
    81 void
    82 tr_prefs_set_action( const char * key, int action )
    83 {
    84     pref_string_set( key, toractionname(action) );
    8566}
    8667
     
    156137
    157138static void
    158 action_cb( GtkComboBox * w, gpointer core )
    159 {
    160     const char * key = g_object_get_data( G_OBJECT(w), PREFS_KEY );
    161     GtkTreeIter iter;
    162     if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(w), &iter ) )
    163     {
    164         int action;
    165         GtkTreeModel * model = gtk_combo_box_get_model( GTK_COMBO_BOX(w) );
    166         gtk_tree_model_get( model, &iter, 1, &action, -1 );
    167         tr_core_set_pref( core, key, toractionname(action) );
    168     }
    169 }
    170 
    171 static GtkWidget*
    172 new_action_combo( const char * key, gpointer core )
    173 {
    174     const char * s;
    175     GtkTreeIter iter;
    176     GtkCellRenderer * rend;
    177     GtkListStore * model;
    178     GtkWidget * w;
    179 
    180     model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
    181 
    182     s = _("Use the torrent file where it is");
    183     gtk_list_store_append( model, &iter );
    184     gtk_list_store_set( model, &iter, 1, TR_TOR_LEAVE, 0, s, -1 );
    185 
    186     s = _("Keep a copy of the torrent file");
    187     gtk_list_store_append( model, &iter );
    188     gtk_list_store_set( model, &iter, 1, TR_TOR_COPY, 0, s, -1 );
    189 
    190     s = _("Keep a copy and remove the original");
    191     gtk_list_store_append( model, &iter );
    192     gtk_list_store_set( model, &iter, 1, TR_TOR_MOVE, 0, s, -1 );
    193 
    194     w = gtk_combo_box_new_with_model( GTK_TREE_MODEL(model) );
    195     gtk_combo_box_set_active( GTK_COMBO_BOX(w), tr_prefs_get_action(key) );
    196     g_object_set_data_full( G_OBJECT(w), PREFS_KEY, g_strdup(key), g_free );
    197     rend = gtk_cell_renderer_text_new( );
    198     gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(w), rend, TRUE );
    199     gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(w), rend, "text", 0 );
    200     g_signal_connect( w, "changed", G_CALLBACK(action_cb), core );
    201 
    202     return w;
    203 }
    204 
    205 static void
    206139target_cb( GtkWidget * widget, gpointer target )
    207140{
    208141    gtk_widget_set_sensitive( GTK_WIDGET(target), gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ) );
    209 }
    210 
    211 static void
    212 target_invert_cb( GtkWidget * widget, gpointer target )
    213 {
    214     gtk_widget_set_sensitive( GTK_WIDGET(target), !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ) );
    215142}
    216143
     
    268195}
    269196
    270 GtkWidget *
    271 tr_prefs_dialog_new( GObject * core, GtkWindow * parent )
     197static GtkWidget*
     198generalPage( GObject * core )
     199{
     200    int row = 0;
     201    const char * s;
     202    GtkWidget * t;
     203    GtkWidget * w;
     204
     205    t = hig_workarea_create ();
     206
     207    hig_workarea_add_section_title (t, &row, _("Windows"));
     208       
     209        s = _("Show an icon in the system _tray");
     210        w = new_check_button( s, PREF_KEY_SYSTRAY, core );
     211        hig_workarea_add_wide_control( t, &row, w );
     212       
     213        s = _("Confirm _quit");
     214        w = new_check_button( s, PREF_KEY_ASKQUIT, core );
     215        hig_workarea_add_wide_control( t, &row, w );
     216
     217    hig_workarea_finish (t, &row);
     218    return t;
     219}
     220
     221static GtkWidget*
     222torrentPage( GObject * core )
     223{
     224    int row = 0;
     225    const char * s;
     226    GtkWidget * t;
     227    GtkWidget * w;
     228
     229    t = hig_workarea_create ();
     230
     231    hig_workarea_add_section_title( t, &row, _( "Location" ) );
     232
     233        w = new_path_chooser_button( PREF_KEY_DIR_DEFAULT, core );
     234        hig_workarea_add_row( t, &row, _( "Default download location:" ), w, NULL );
     235
     236    hig_workarea_add_section_divider( t, &row );
     237    hig_workarea_add_section_title( t, &row, _( "Adding Torrents" ) );
     238
     239        s = _( "Show _options window" );
     240        w = new_check_button( s, PREF_KEY_OPTIONS_PROMPT, core );
     241        hig_workarea_add_wide_control( t, &row, w );
     242
     243        s = _( "_Start transfers when added" );
     244        w = new_check_button( s, PREF_KEY_START, core );
     245        hig_workarea_add_wide_control( t, &row, w );
     246
     247        s = _( "_Delete original torrent file" );
     248        w = new_check_button( s, PREF_KEY_DELETE_ORIGINAL, core );
     249        hig_workarea_add_wide_control( t, &row, w );
     250
     251    hig_workarea_finish (t, &row);
     252    return t;
     253}
     254
     255static GtkWidget*
     256peerPage( GObject * core )
     257{
     258    int row = 0;
     259    const char * s;
     260    GtkWidget * t;
     261    GtkWidget * w;
     262
     263    t = hig_workarea_create ();
     264    hig_workarea_add_section_title (t, &row, _("Options"));
     265       
     266        s = _("Use peer _exchange if possible");
     267        w = new_check_button( s, PREF_KEY_PEX, core );
     268        hig_workarea_add_wide_control( t, &row, w );
     269       
     270        s = _("_Ignore unencrypted peers");
     271        w = new_check_button( s, PREF_KEY_ENCRYPTED_ONLY, core );
     272        hig_workarea_add_wide_control( t, &row, w );
     273
     274    hig_workarea_add_section_divider( t, &row );
     275    hig_workarea_add_section_title( t, &row, _( "Limits" ) );
     276 
     277        w = new_spin_button( PREF_KEY_MAX_PEERS_GLOBAL, core, 1, 3000, 5 );
     278        hig_workarea_add_row( t, &row, _( "Total max peers:" ), w, NULL );
     279        w = new_spin_button( PREF_KEY_MAX_PEERS_PER_TORRENT, core, 1, 300, 5 );
     280        hig_workarea_add_row( t, &row, _( "Per-torrent max peers:" ), w, NULL );
     281
     282    hig_workarea_finish (t, &row);
     283    return t;
     284}
     285
     286static GtkWidget*
     287bandwidthPage( GObject * core )
     288{
     289    int row = 0;
     290    const char * s;
     291    GtkWidget * t;
     292    GtkWidget * w, * w2;
     293
     294    t = hig_workarea_create ();
     295
     296    hig_workarea_add_section_title (t, &row, _("Speed Limits"));
     297
     298        s = _("_Limit upload speed (KiB/s)");
     299        w = new_check_button( s, PREF_KEY_UL_LIMIT_ENABLED, core );
     300        w2 = new_spin_button( PREF_KEY_UL_LIMIT, core, 0, INT_MAX, 5 );
     301        gtk_widget_set_sensitive( GTK_WIDGET(w2), pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED ) );
     302        g_signal_connect( w, "toggled", G_CALLBACK(target_cb), w2 );
     303        hig_workarea_add_row_w( t, &row, w, w2, NULL );
     304
     305        s = _("Li_mit download speed (KiB/s)");
     306        w = new_check_button( s, PREF_KEY_DL_LIMIT_ENABLED, core );
     307        w2 = new_spin_button( PREF_KEY_DL_LIMIT, core, 0, INT_MAX, 5 );
     308        gtk_widget_set_sensitive( GTK_WIDGET(w2), pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED ) );
     309        g_signal_connect( w, "toggled", G_CALLBACK(target_cb), w2 );
     310        hig_workarea_add_row_w( t, &row, w, w2, NULL );
     311
     312    hig_workarea_finish (t, &row);
     313    return t;
     314}
     315
     316static GtkWidget*
     317networkPage( GObject * core, gpointer alive )
    272318{
    273319    int row = 0;
     
    277323    GtkWidget * l;
    278324    GtkWidget * h;
     325    GtkTooltips * tips;
     326
     327    tips = gtk_tooltips_new( );
     328
     329    t = hig_workarea_create ();
     330    hig_workarea_add_section_title (t, &row, _("Network"));
     331       
     332        s = _("_Automatically map port" );
     333        w = new_check_button( s, PREF_KEY_NAT, core );
     334        hig_workarea_add_wide_control( t, &row, w );
     335        gtk_tooltips_set_tip( GTK_TOOLTIPS( tips ), w, _( "NAT traversal uses either NAT-PMP or UPnP" ), NULL );
     336
     337        h = gtk_hbox_new( FALSE, GUI_PAD );
     338        w2 = new_spin_button( PREF_KEY_PORT, core, 1, INT_MAX, 1 );
     339        gtk_box_pack_start( GTK_BOX(h), w2, FALSE, FALSE, 0 );
     340        l = gtk_label_new( NULL );
     341        gtk_misc_set_alignment( GTK_MISC(l), 0.0f, 0.5f );
     342        gtk_box_pack_start( GTK_BOX(h), l, FALSE, FALSE, 0 );
     343        hig_workarea_add_row( t, &row, _("Incoming TCP _Port"), h, w );
     344
     345        g_object_set_data( G_OBJECT(l), "tr-port-spin", w2 );
     346        g_object_set_data( G_OBJECT(l), "alive", alive );
     347        testing_port_cb( NULL, l );
     348
     349        g_signal_connect( w, "toggled", G_CALLBACK(toggled_cb), l );
     350        g_signal_connect( w2, "value-changed", G_CALLBACK(testing_port_cb), l );
     351
     352    hig_workarea_finish (t, &row);
     353    return t;
     354}
     355
     356GtkWidget *
     357tr_prefs_dialog_new( GObject * core, GtkWindow * parent )
     358{
    279359    GtkWidget * d;
    280     GtkTooltips * tips;
     360    GtkWidget * n;
     361    GtkWidget * w;
    281362    gboolean * alive;
    282363
    283364    alive = g_new( gboolean, 1 );
    284365    *alive = TRUE;
    285 
    286     tips = gtk_tooltips_new( );
    287366
    288367    d = gtk_dialog_new_with_buttons( _("Preferences"), parent,
     
    295374    g_object_weak_ref( G_OBJECT( d ), dialogDestroyed, alive );
    296375
     376    n = gtk_notebook_new( );
     377
     378    w = torrentPage( core );
     379    gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Torrents")) );
     380    w = peerPage( core );
     381    gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Peers")) );
     382    w = bandwidthPage( core );
     383    gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Bandwidth")) );
     384    w = networkPage( core, alive );
     385    gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Network")) );
     386    w = generalPage( core );
     387    gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("General")) );
     388
     389
    297390    g_signal_connect( d, "response", G_CALLBACK(response_cb), core );
    298 
    299     t = hig_workarea_create ();
    300 
    301     hig_workarea_add_section_title (t, &row, _("Speed Limits"));
    302 
    303         s = _("_Limit upload speed (KiB/s)");
    304         w = new_check_button( s, PREF_KEY_UL_LIMIT_ENABLED, core );
    305         w2 = new_spin_button( PREF_KEY_UL_LIMIT, core, 0, INT_MAX, 5 );
    306         gtk_widget_set_sensitive( GTK_WIDGET(w2), pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED ) );
    307         g_signal_connect( w, "toggled", G_CALLBACK(target_cb), w2 );
    308         hig_workarea_add_row_w( t, &row, w, w2, NULL );
    309 
    310         s = _("Li_mit download speed (KiB/s)");
    311         w = new_check_button( s, PREF_KEY_DL_LIMIT_ENABLED, core );
    312         w2 = new_spin_button( PREF_KEY_DL_LIMIT, core, 0, INT_MAX, 5 );
    313         gtk_widget_set_sensitive( GTK_WIDGET(w2), pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED ) );
    314         g_signal_connect( w, "toggled", G_CALLBACK(target_cb), w2 );
    315         hig_workarea_add_row_w( t, &row, w, w2, NULL );
    316 
    317     hig_workarea_add_section_divider( t, &row );
    318     hig_workarea_add_section_title (t, &row, _("Downloads"));
    319 
    320         s = _("P_rompt for download directory");
    321         w = new_check_button( s, PREF_KEY_DIR_ASK, core );
    322         w2 = new_path_chooser_button( PREF_KEY_DIR_DEFAULT, core );
    323         gtk_widget_set_sensitive( GTK_WIDGET(w2), !pref_flag_get( PREF_KEY_DIR_ASK ) );
    324         g_signal_connect( w, "toggled", G_CALLBACK(target_invert_cb), w2 );
    325         hig_workarea_add_row_w( t, &row, w, w2, NULL );
    326 
    327         w = new_action_combo( PREF_KEY_ADDSTD, core );
    328         s = _("For torrents added _normally:");
    329         l = hig_workarea_add_row( t, &row, s, w, NULL );
    330 
    331         w = new_action_combo( PREF_KEY_ADDIPC, core );
    332         s = _("For torrents added from _command-line:");
    333         l = hig_workarea_add_row( t, &row, s, w, NULL );
    334 
    335     hig_workarea_add_section_divider( t, &row );
    336     hig_workarea_add_section_title( t, &row, _( "Peer Connections" ) );
    337  
    338         w = new_spin_button( PREF_KEY_MAX_PEERS_GLOBAL, core, 1, 3000, 5 );
    339         hig_workarea_add_row( t, &row, _( "Global maximum connected peers:" ), w, NULL );
    340         w = new_spin_button( PREF_KEY_MAX_PEERS_PER_TORRENT, core, 1, 300, 5 );
    341         hig_workarea_add_row( t, &row, _( "Maximum connected peers for new torrents:" ), w, NULL );
    342 
    343     hig_workarea_add_section_divider( t, &row );
    344     hig_workarea_add_section_title (t, &row, _("Network"));
    345        
    346         s = _("_Automatically map port" );
    347         w = new_check_button( s, PREF_KEY_NAT, core );
    348         hig_workarea_add_wide_control( t, &row, w );
    349         gtk_tooltips_set_tip( GTK_TOOLTIPS( tips ), w, _( "NAT traversal uses either NAT-PMP or UPnP" ), NULL );
    350 
    351         h = gtk_hbox_new( FALSE, GUI_PAD );
    352         w2 = new_spin_button( PREF_KEY_PORT, core, 1, INT_MAX, 1 );
    353         gtk_box_pack_start( GTK_BOX(h), w2, FALSE, FALSE, 0 );
    354         l = gtk_label_new( NULL );
    355         gtk_misc_set_alignment( GTK_MISC(l), 0.0f, 0.5f );
    356         gtk_box_pack_start( GTK_BOX(h), l, FALSE, FALSE, 0 );
    357         hig_workarea_add_row( t, &row, _("Incoming TCP _Port"), h, w );
    358 
    359         g_object_set_data( G_OBJECT(l), "tr-port-spin", w2 );
    360         g_object_set_data( G_OBJECT(l), "alive", alive );
    361         testing_port_cb( NULL, l );
    362 
    363         g_signal_connect( w, "toggled", G_CALLBACK(toggled_cb), l );
    364         g_signal_connect( w2, "value-changed", G_CALLBACK(testing_port_cb), l );
    365 
    366     hig_workarea_add_section_divider( t, &row );
    367     hig_workarea_add_section_title (t, &row, _("Options"));
    368        
    369         s = _("Use peer _exchange if possible");
    370         w = new_check_button( s, PREF_KEY_PEX, core );
    371         hig_workarea_add_wide_control( t, &row, w );
    372        
    373         s = _("_Ignore unencrypted peers");
    374         w = new_check_button( s, PREF_KEY_ENCRYPTED_ONLY, core );
    375         hig_workarea_add_wide_control( t, &row, w );
    376        
    377         s = _("Show an icon in the system _tray");
    378         w = new_check_button( s, PREF_KEY_SYSTRAY, core );
    379         hig_workarea_add_wide_control( t, &row, w );
    380        
    381         s = _("Confirm _quit");
    382         w = new_check_button( s, PREF_KEY_ASKQUIT, core );
    383         hig_workarea_add_wide_control( t, &row, w );
    384 
    385     hig_workarea_finish (t, &row);
    386     gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(d)->vbox), t );
     391    gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(d)->vbox), n );
    387392    gtk_widget_show_all( GTK_DIALOG(d)->vbox );
    388393    return d;
  • trunk/gtk/tr_prefs.h

    r4404 r5015  
    2525#define PREF_KEY_UL_LIMIT_ENABLED       "upload-limit-enabled"
    2626#define PREF_KEY_UL_LIMIT               "upload-limit"
    27 #define PREF_KEY_DIR_ASK                "prompt-for-download-directory"
     27#define PREF_KEY_OPTIONS_PROMPT         "show-options-window"
    2828#define PREF_KEY_DIR_DEFAULT            "default-download-directory"
    29 #define PREF_KEY_ADDSTD                 "add-behavior-standard"
    30 #define PREF_KEY_ADDIPC                 "add-behavior-ipc"
     29#define PREF_KEY_START                  "start-added-torrents"
     30#define PREF_KEY_DELETE_ORIGINAL        "delete-original-torrent-files"
    3131#define PREF_KEY_PORT                   "listening-port"
    3232#define PREF_KEY_NAT                    "nat-traversal-enabled"
     
    4949void tr_prefs_init_global( void );
    5050
    51 int  tr_prefs_get_action( const char * key );
    52 void tr_prefs_set_action( const char * key, int action );
    53 
    5451#endif
  • trunk/gtk/tr_torrent.c

    r5005 r5015  
    3939{
    4040   tr_torrent * handle;
    41    char * delfile;
    4241   gboolean seeding_cap_enabled;
    4342   gdouble seeding_cap; /* ratio to stop seeding at */
     
    5554                                                  struct TrTorrentPrivate );
    5655    p->handle = NULL;
    57     p->delfile = NULL;
    5856    p->seeding_cap = 2.0;
    5957
     
    7270tr_torrent_dispose( GObject * o )
    7371{
    74     GObjectClass * parent = g_type_class_peek(g_type_parent(TR_TORRENT_TYPE));
     72    GObjectClass * parent;
    7573    TrTorrent * self = TR_TORRENT( o );
    7674
     
    7977        if( self->priv->handle )
    8078            tr_torrentClose( self->priv->handle );
    81         g_free( self->priv->delfile );
    8279        self->priv = NULL;
    8380    }
    8481
    85     /* chain up to the parent class */
     82    parent = g_type_class_peek(g_type_parent(TR_TORRENT_TYPE));
    8683    parent->dispose( o );
    8784}
    8885
    8986static void
    90 tr_torrent_class_init(gpointer g_class, gpointer g_class_data UNUSED )
     87tr_torrent_class_init( gpointer g_class, gpointer g_class_data UNUSED )
    9188{
    9289    GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
    9390    gobject_class->dispose = tr_torrent_dispose;
    94     g_type_class_add_private( g_class, sizeof(struct TrTorrentPrivate) );
     91    g_type_class_add_private( g_class, sizeof( struct TrTorrentPrivate ) );
    9592}
    9693
    9794GType
    98 tr_torrent_get_type(void)
     95tr_torrent_get_type( void )
    9996{
    10097  static GType type = 0;
    10198
    102   if(0 == type) {
     99  if( !type )
     100  {
    103101    static const GTypeInfo info = {
    104102      sizeof (TrTorrentClass),
     
    171169
    172170TrTorrent *
    173 tr_torrent_new( tr_handle               * handle,
    174                 const char              * metainfo_filename,
    175                 const char              * destination,
    176                 enum tr_torrent_action    act,
    177                 gboolean                  paused,
    178                 char                   ** err )
    179 {
    180   TrTorrent * ret;
    181   tr_torrent * tor;
    182   tr_ctor * ctor;
    183   int errcode = -1;
    184 
    185   g_assert( destination );
    186 
    187   *err = NULL;
    188 
    189   ctor = tr_ctorNew( handle );
    190   tr_ctorSetMetainfoFromFile( ctor, metainfo_filename );
    191   tr_ctorSetDestination( ctor, TR_FORCE, destination );
    192   tr_ctorSetPaused( ctor, TR_FORCE, paused );
    193   tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
    194   tor = tr_torrentNew( handle, ctor, &errcode );
    195   tr_ctorFree( ctor );
     171tr_torrent_new_ctor( tr_handle  * handle,
     172                     tr_ctor    * ctor,
     173                     char      ** err )
     174{
     175    tr_torrent * tor;
     176    int errcode;
     177
     178    errcode = -1;
     179    *err = NULL;
     180
     181    tor = tr_torrentNew( handle, ctor, &errcode );
    196182 
    197   if( tor == NULL ) {
    198     switch( errcode ) {
    199       case TR_EINVALID:
    200         *err = g_strdup_printf(_("%s: not a valid torrent file"), metainfo_filename );
    201         break;
    202       case TR_EDUPLICATE:
    203         *err = g_strdup_printf(_("%s: torrent is already open"), metainfo_filename );
    204         break;
    205       default:
    206         *err = g_strdup( metainfo_filename );
    207         break;
     183    if( !tor )
     184    {
     185        const char * filename = tr_ctorGetSourceFile( ctor );
     186        if( !filename )
     187            filename = "(null)";
     188
     189        switch( errcode )
     190        {
     191            case TR_EINVALID:
     192                *err = g_strdup_printf( _("%s: not a valid torrent file"), filename );
     193                 break;
     194            case TR_EDUPLICATE:
     195                *err = g_strdup_printf( _("%s: torrent is already open"), filename );
     196                break;
     197            default:
     198                *err = g_strdup( filename );
     199                break;
     200        }
     201
     202        return NULL;
    208203    }
    209     return NULL;
    210   }
    211 
    212   ret = maketorrent( tor );
    213   if( TR_TOR_MOVE == act )
    214     ret->priv->delfile = g_strdup( metainfo_filename );
    215   return ret;
    216 }
    217 
    218 TrTorrent *
    219 tr_torrent_new_with_data( tr_handle    * handle,
    220                           uint8_t      * metainfo,
    221                           size_t         size,
    222                           const char   * destination,
    223                           gboolean       paused,
    224                           char        ** err )
    225 {
    226   tr_torrent * tor;
    227   tr_ctor * ctor;
    228   int errcode = -1; 
    229 
    230   g_assert( destination );
    231 
    232   *err = NULL;
    233 
    234   ctor = tr_ctorNew( handle );
    235   tr_ctorSetMetainfo( ctor, metainfo, size );
    236   tr_ctorSetDestination( ctor, TR_FORCE, destination );
    237   tr_ctorSetPaused( ctor, TR_FORCE, paused );
    238   tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
    239   tor = tr_torrentNew( handle, ctor, &errcode );
    240  
    241   if( tor == NULL ) {
    242     switch( errcode ) {
    243       case TR_EINVALID:
    244         *err = g_strdup( _("not a valid torrent file") );
    245         break;
    246       case TR_EDUPLICATE:
    247         *err = g_strdup( _("torrent is already open") );
    248         break;
    249       default:
    250         *err = g_strdup( "" );
    251         break;
    252     }
    253     return NULL;
    254   }
    255 
    256   return maketorrent( tor );
     204
     205    return maketorrent( tor );
    257206}
    258207
  • trunk/gtk/tr_torrent.h

    r5005 r5015  
    8888
    8989TrTorrent *
    90 tr_torrent_new( tr_handle * handle, const char * path, const char * dir,
    91                 enum tr_torrent_action act, gboolean paused, char ** err);
    92 
    93 TrTorrent *
    94 tr_torrent_new_with_data( tr_handle * handle, uint8_t * data, size_t size,
    95                           const char * dir, gboolean paused, char ** err );
     90tr_torrent_new_ctor( tr_handle * handle, tr_ctor * ctor, char ** err );
    9691
    9792#endif
  • trunk/gtk/util.c

    r4759 r5015  
    223223}
    224224
    225 enum tr_torrent_action
    226 toraddaction( const char * action )
    227 {
    228     if( !action || !strcmp( "copy", action ) )
    229         return TR_TOR_COPY;
    230 
    231     if( !strcmp( "move", action ) )
    232         return TR_TOR_MOVE;
    233 
    234     return TR_TOR_LEAVE;
    235 }
    236 
    237 const char *
    238 toractionname( enum tr_torrent_action action )
    239 {
    240     switch( action )
    241     {
    242         case TR_TOR_COPY:
    243             return "copy";
    244 
    245         case TR_TOR_MOVE:
    246             return "move";
    247 
    248         default:
    249             return "leave";
    250     }
    251 }
    252 
    253225char *
    254226getdownloaddir( void )
  • trunk/gtk/util.h

    r4759 r5015  
    3434/* NULL-safe version of strcmp */
    3535int tr_strcmp( const char*, const char * );
    36 
    37 /* XXX this shouldn't be here */
    38 enum tr_torrent_action { TR_TOR_LEAVE, TR_TOR_COPY, TR_TOR_MOVE };
    3936
    4037/* return number of items in array */
     
    8279GList *
    8380checkfilenames( int argc, char ** argv );
    84 
    85 /* returns the flag for an action string */
    86 enum tr_torrent_action
    87 toraddaction( const char * action );
    88 
    89 /* returns the action string for a flag */
    90 const char *
    91 toractionname( enum tr_torrent_action action );
    9281
    9382/* retrieve the global download directory */
  • trunk/po/POTFILES.in

    r4344 r5015  
    44gtk/conf.c
    55gtk/dialogs.c
     6gtk/file-list.c
    67gtk/hig.c
    78gtk/io.c
     
    1011gtk/makemeta-ui.c
    1112gtk/msgwin.c
     13gtk/open.c
    1214gtk/stats.c
    1315gtk/torrent-cell-renderer.c
Note: See TracChangeset for help on using the changeset viewer.