diff --git a/gtk/conf.h b/gtk/conf.h index dd89a1c28..8467f2a2d 100644 --- a/gtk/conf.h +++ b/gtk/conf.h @@ -56,6 +56,7 @@ cf_freestate(benc_val_t *state); #define PREF_USEUPLIMIT "use-upload-limit" #define PREF_UPLIMIT "upload-limit" #define PREF_DIR "download-directory" +#define PREF_ASKDIR "ask-download-directory" #define PREF_ADDSTD "add-behavior-standard" #define PREF_ADDIPC "add-behavior-ipc" #define PREF_MSGLEVEL "message-level" diff --git a/gtk/dialogs.c b/gtk/dialogs.c index fb81a60e0..a99fa3dd9 100644 --- a/gtk/dialogs.c +++ b/gtk/dialogs.c @@ -41,6 +41,7 @@ #define DEF_USEDOWNLIMIT FALSE #define DEF_UPLIMIT 20 #define DEF_USEUPLIMIT TRUE +#define DEF_ASKDIR FALSE #define DEF_NAT TRUE struct prefdata { @@ -52,7 +53,6 @@ struct prefdata { struct addcb { add_torrents_func_t addfunc; - GtkWindow *parent; void *data; gboolean autostart; gboolean usingaltdir; @@ -60,6 +60,14 @@ struct addcb { GtkButtonBox *altbox; }; +struct dirdata +{ + add_torrents_func_t addfunc; + void * cbdata; + GList * files; + guint flags; +}; + static void clicklimitbox(GtkWidget *widget, gpointer gdata); static void @@ -72,6 +80,8 @@ static void dirclick(GtkWidget *widget, gpointer gdata); static void addresp(GtkWidget *widget, gint resp, gpointer gdata); +static void +promptresp( GtkWidget * widget, gint resp, gpointer data ); static void setupprefwidget(GtkWidget *widget, const char *prefname, ...) { @@ -185,11 +195,13 @@ makeprefwindow(GtkWindow *parent, TrBackend *back) { GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); - const unsigned int rowcount = 9; + const unsigned int rowcount = 10; GtkWidget *table = gtk_table_new(rowcount, 2, FALSE); GtkWidget *portnum = gtk_spin_button_new_with_range(1, 0xffff, 1); GtkWidget *natcheck = gtk_check_button_new_with_mnemonic( _("Au_tomatic port mapping via NAT-PMP or UPnP")); + GtkWidget *askdir = gtk_check_button_new_with_mnemonic( + _("Al_ways prompt for download directory")); GtkWidget *dirstr = gtk_file_chooser_button_new( _("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); @@ -237,7 +249,7 @@ makeprefwindow(GtkWindow *parent, TrBackend *back) { gtk_tooltips_enable( tips ); data->prefwidgets = makeglist(portnum, lim[0].on, lim[0].num, lim[1].on, - lim[1].num, dirstr, addstd, addipc, natcheck, NULL); + lim[1].num, askdir, dirstr, addstd, addipc, natcheck, NULL); data->parent = parent; data->back = back; data->tips = tips; @@ -248,7 +260,7 @@ makeprefwindow(GtkWindow *parent, TrBackend *back) { for(ii = 0; ii < ALEN(lim); ii++) { /* limit checkbox */ setupprefwidget(lim[ii].on, lim[ii].usepref, (gboolean)lim[ii].defuse); - array = g_new(GtkWidget*, 2); + array = g_new(GtkWidget*, 3); g_signal_connect_data(lim[ii].on, "clicked", G_CALLBACK(clicklimitbox), array, (GClosureNotify)g_free, 0); gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].on, 0, 2, RN(ii*2)); @@ -264,11 +276,22 @@ makeprefwindow(GtkWindow *parent, TrBackend *back) { gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].num, 1,2,RN(ii*2+1)); array[0] = lim[ii].label; array[1] = lim[ii].num; + array[2] = GINT_TO_POINTER( TRUE ); clicklimitbox(lim[ii].on, array); gtk_tooltips_set_tip( tips, lim[ii].num, gettext( lim[ii].numtip ), "" ); } ii *= 2; + /* always ask for download dir */ + setupprefwidget( askdir, PREF_ASKDIR, ( gboolean )DEF_ASKDIR ); + array = g_new( GtkWidget *, 3 ); + g_signal_connect_data( askdir, "clicked", G_CALLBACK( clicklimitbox ), + array, ( GClosureNotify )g_free, 0 ); + gtk_table_attach_defaults(GTK_TABLE(table), askdir, 0, 2, RN(ii)); + gtk_tooltips_set_tip( tips, askdir, + _("When adding a torrent, always prompt for a directory to download data files into"), "" ); + ii++; + /* directory label and chooser */ label = gtk_label_new_with_mnemonic(_("Download di_rectory:")); gtk_label_set_mnemonic_widget(GTK_LABEL(label), dirstr); @@ -280,6 +303,10 @@ makeprefwindow(GtkWindow *parent, TrBackend *back) { event = tipbox( dirstr, tips, _("Destination directory for downloaded data files") ); gtk_table_attach_defaults(GTK_TABLE(table), event, 1, 2, RN(ii)); + array[0] = label; + array[1] = dirstr; + array[2] = GINT_TO_POINTER( FALSE ); + clicklimitbox( askdir, array ); ii++; /* port label and entry */ @@ -364,13 +391,20 @@ makeprefwindow(GtkWindow *parent, TrBackend *back) { } static void -clicklimitbox(GtkWidget *widget, gpointer gdata) { - GtkWidget **widgets = gdata; - int ii; +clicklimitbox( GtkWidget * widget, gpointer gdata ) +{ + GtkWidget ** widgets; + gboolean with, active; + int ii; - for(ii = 0; 2 > ii; ii++) - gtk_widget_set_sensitive(widgets[ii], - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); + widgets = gdata; + with = ( gboolean )GPOINTER_TO_INT( widgets[2] ); + + for(ii = 0; 2 > ii; ii++) + { + active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) ); + gtk_widget_set_sensitive( widgets[ii], ( with ? active : !active ) ); + } } static void @@ -463,7 +497,6 @@ makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata) { const char *pref; data->addfunc = addfunc; - data->parent = parent; data->data = cbdata; data->autostart = TRUE; data->usingaltdir = FALSE; @@ -541,6 +574,7 @@ addresp(GtkWidget *widget, gint resp, gpointer gdata) { freestrlist(stupidgtk); } + g_free( data ); gtk_widget_destroy(widget); } @@ -656,3 +690,53 @@ makeinfowind(GtkWindow *parent, TrTorrent *tor) { G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show_all(wind); } + +void +promptfordir( GtkWindow * parent, add_torrents_func_t addfunc, void *cbdata, + GList * files, guint flags, const char * defaultdir ) +{ + struct dirdata * stuff; + GtkWidget * wind; + + stuff = g_new( struct dirdata, 1 ); + stuff->addfunc = addfunc; + stuff->cbdata = cbdata; + stuff->files = dupstrlist( files ); + stuff->flags = flags; + + wind = gtk_file_chooser_dialog_new( _("Choose a directory"), parent, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL ); + gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( wind ), TRUE ); + gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( wind ), FALSE ); + gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ), defaultdir ); + + g_signal_connect( G_OBJECT( wind ), "response", + G_CALLBACK( promptresp ), stuff ); + + gtk_widget_show_all(wind); +} + +static void +promptresp( GtkWidget * widget, gint resp, gpointer data ) +{ + struct dirdata * stuff; + char * dir; + + stuff = data; + + if( GTK_RESPONSE_ACCEPT == resp ) + { + dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) ); + /* it seems that we will always get a directory */ + g_assert( NULL != dir ); + stuff->addfunc( stuff->cbdata, NULL, stuff->files, dir, stuff->flags ); + g_free( dir ); + } + + freestrlist( stuff->files ); + g_free( stuff ); + gtk_widget_destroy( widget ); +} diff --git a/gtk/dialogs.h b/gtk/dialogs.h index 947c6aec8..9f7b90b3c 100644 --- a/gtk/dialogs.h +++ b/gtk/dialogs.h @@ -44,4 +44,9 @@ makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata); void makeinfowind(GtkWindow *parent, TrTorrent *tor); +/* prompt for a download directory for torrents, then add them */ +void +promptfordir( GtkWindow * parent, add_torrents_func_t addfunc, void *cbdata, + GList * files, guint flags, const char * defaultdir ); + #endif /* TG_PREFS_H */ diff --git a/gtk/main.c b/gtk/main.c index d18acc81a..f5849992f 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1064,6 +1064,29 @@ doubleclick(GtkWidget *widget SHUTUP, GtkTreePath *path, } } +static const char * +defaultdir( void ) +{ + static char * wd = NULL; + const char * dir; + + dir = cf_getpref( PREF_DIR ); + if( NULL == dir ) + { + if( NULL == wd ) + { + wd = g_new( char, MAX_PATH_LENGTH + 1 ); + if( NULL == getcwd( wd, MAX_PATH_LENGTH + 1 ) ) + { + strcpy( wd, "." ); + } + } + dir = wd; + } + + return dir; +} + void addtorrents(void *vdata, void *state, GList *files, const char *dir, guint flags) { @@ -1072,7 +1095,7 @@ addtorrents(void *vdata, void *state, GList *files, char *errstr; TrTorrent *tor; GtkTreeIter iter; - char *wd; + const char * pref; errlist = NULL; torlist = NULL; @@ -1081,15 +1104,16 @@ addtorrents(void *vdata, void *state, GList *files, torlist = tr_backend_load_state(data->back, state, &errlist); if(NULL != files) { - if(NULL == dir) - dir = cf_getpref(PREF_DIR); - wd = NULL; - if(NULL == dir) { - wd = g_new(char, MAX_PATH_LENGTH + 1); - if(NULL == getcwd(wd, MAX_PATH_LENGTH + 1)) - dir = "."; - else - dir = wd; + if( NULL == dir ) + { + pref = cf_getpref( PREF_ASKDIR ); + if( NULL != pref && strbool( pref ) ) + { + promptfordir( data->wind, addtorrents, data, + files, flags, defaultdir() ); + files = NULL; + } + dir = defaultdir(); } for(ii = g_list_first(files); NULL != ii; ii = ii->next) { errstr = NULL; @@ -1100,8 +1124,6 @@ addtorrents(void *vdata, void *state, GList *files, if(NULL != errstr) errlist = g_list_append(errlist, errstr); } - if(NULL != wd) - g_free(wd); } for(ii = g_list_first(torlist); NULL != ii; ii = ii->next) { diff --git a/gtk/util.c b/gtk/util.c index 4caeab966..103499bbd 100644 --- a/gtk/util.c +++ b/gtk/util.c @@ -151,6 +151,20 @@ mkdir_p(const char *name, mode_t mode) { return TRUE; } +GList * +dupstrlist( GList * list ) +{ + GList * ii, * ret; + + ret = NULL; + for( ii = g_list_first( list ); NULL != ii; ii = ii->next ) + { + ret = g_list_append( ret, g_strdup( ii->data ) ); + } + + return ret; +} + char * joinstrlist(GList *list, char *sep) { GList *ii; diff --git a/gtk/util.h b/gtk/util.h index 5dfc0cfe6..863a67e3d 100644 --- a/gtk/util.h +++ b/gtk/util.h @@ -69,6 +69,10 @@ ratiostr(guint64 down, guint64 up); gboolean mkdir_p(const char *name, mode_t mode); +/* create a copy of a GList of strings, this dups the actual strings too */ +GList * +dupstrlist( GList * list ); + /* joins a GList of strings into one string using an optional separator */ char * joinstrlist(GList *list, char *sep);