1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-26 01:27:28 +00:00
transmission/gtk/dialogs.c

743 lines
26 KiB
C
Raw Normal View History

/******************************************************************************
* $Id$
*
* Copyright (c) 2005-2006 Transmission authors and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
2006-07-16 19:39:23 +00:00
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "conf.h"
#include "dialogs.h"
#include "transmission.h"
#include "util.h"
#define PREFNAME "transmission-dialog-pref-name"
/* default values for a couple prefs */
#define DEF_DOWNLIMIT 100
#define DEF_USEDOWNLIMIT FALSE
#define DEF_UPLIMIT 20
#define DEF_USEUPLIMIT TRUE
#define DEF_ASKDIR FALSE
2006-09-25 18:37:45 +00:00
#define DEF_NAT TRUE
2006-07-16 19:39:23 +00:00
struct prefdata {
GList *prefwidgets;
GtkWindow *parent;
TrBackend *back;
GtkTooltips * tips;
2006-07-16 19:39:23 +00:00
};
struct addcb {
add_torrents_func_t addfunc;
void *data;
gboolean autostart;
gboolean usingaltdir;
GtkFileChooser *altdir;
GtkButtonBox *altbox;
};
struct dirdata
{
add_torrents_func_t addfunc;
void * cbdata;
GList * files;
guint flags;
};
2006-07-16 19:39:23 +00:00
static void
clicklimitbox(GtkWidget *widget, gpointer gdata);
static void
freedata(gpointer gdata, GClosure *closure);
static void
clickdialog(GtkWidget *widget, int resp, gpointer gdata);
static void
autoclick(GtkWidget *widget, gpointer gdata);
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 );
2006-07-16 19:39:23 +00:00
static void
setupprefwidget(GtkWidget *widget, const char *prefname, ...) {
const char *pref = cf_getpref(prefname);
GtkTreeModel *model;
GtkTreeIter iter;
guint prefsflag, modelflag;
va_list ap;
g_object_set_data_full(G_OBJECT(widget), PREFNAME,
g_strdup(prefname), (GDestroyNotify)g_free);
va_start(ap, prefname);
if(ISA(widget, GTK_TYPE_FILE_CHOOSER)) {
if(NULL != pref)
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(widget), pref);
}
else if(ISA(widget, GTK_TYPE_SPIN_BUTTON))
gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
(NULL == pref ? va_arg(ap, long) : strtol(pref, NULL, 10)));
else if(ISA(widget, GTK_TYPE_TOGGLE_BUTTON))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
(NULL == pref ? va_arg(ap, gboolean) : strbool(pref)));
else if(ISA(widget, GTK_TYPE_COMBO_BOX)) {
model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
prefsflag = addactionflag(pref);
if(gtk_tree_model_get_iter_first(model, &iter))
do {
gtk_tree_model_get(model, &iter, 1, &modelflag, -1);
if(modelflag == prefsflag) {
gtk_combo_box_set_active_iter(GTK_COMBO_BOX(widget), &iter);
break;
}
} while(gtk_tree_model_iter_next(model, &iter));
}
else {
g_assert_not_reached();
}
va_end(ap);
}
static void
saveprefwidget(GtkWindow *parent, GtkWidget *widget) {
char *prefname;
const char *strval;
char *freeablestr;
GtkTreeModel *model;
GtkTreeIter iter;
guint uintval;
strval = NULL;
freeablestr = NULL;
if(ISA(widget, GTK_TYPE_FILE_CHOOSER)) {
strval = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
if(NULL != strval) {
if(!mkdir_p(strval, 0777)) {
errmsg(parent, _("Failed to create the directory %s:\n%s"),
strval, strerror(errno));
return;
}
}
}
else if(ISA(widget, GTK_TYPE_SPIN_BUTTON))
freeablestr = g_strdup_printf("%i",
gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)));
else if(ISA(widget, GTK_TYPE_TOGGLE_BUTTON))
strval = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ?
"yes" : "no");
else if(ISA(widget, GTK_TYPE_COMBO_BOX)) {
if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) {
model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
gtk_tree_model_get(model, &iter, 1, &uintval, -1);
strval = addactionname(uintval);
}
}
else {
g_assert_not_reached();
return;
}
prefname = g_object_get_data(G_OBJECT(widget), PREFNAME);
g_assert(NULL != prefname);
if(NULL != strval)
cf_setpref(prefname, strval);
else if(NULL != freeablestr) {
cf_setpref(prefname, freeablestr);
g_free(freeablestr);
}
}
/* wrap a widget in an event box with a tooltip */
static GtkWidget *
tipbox( GtkWidget * widget, GtkTooltips * tips, const char * tip )
{
GtkWidget * box;
box = gtk_event_box_new();
gtk_container_add( GTK_CONTAINER( box ), widget );
gtk_tooltips_set_tip( tips, box, tip, "" );
return box;
}
2006-08-20 22:45:29 +00:00
GtkWidget *
makeprefwindow(GtkWindow *parent, TrBackend *back) {
2006-07-16 19:39:23 +00:00
char *title = g_strdup_printf(_("%s Preferences"), g_get_application_name());
GtkWidget *wind = gtk_dialog_new_with_buttons(title, parent,
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 = 10;
2006-07-16 19:39:23 +00:00
GtkWidget *table = gtk_table_new(rowcount, 2, FALSE);
GtkWidget *portnum = gtk_spin_button_new_with_range(1, 0xffff, 1);
2006-09-25 18:37:45 +00:00
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"));
2006-07-16 19:39:23 +00:00
GtkWidget *dirstr = gtk_file_chooser_button_new(
_("Choose a download directory"),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
GtkWidget *addstd = gtk_combo_box_new();
GtkWidget *addipc = gtk_combo_box_new();
GtkWidget *label;
GtkWidget **array;
struct prefdata *data = g_new0(struct prefdata, 1);
struct { GtkWidget *on; GtkWidget *num; GtkWidget *label; gboolean defuse;
const char *usepref; const char *numpref; long def;
const char *ontip; const char *numtip; } lim[] = {
2006-07-16 19:39:23 +00:00
{ gtk_check_button_new_with_mnemonic(_("_Limit download speed")),
gtk_spin_button_new_with_range(0, G_MAXLONG, 1),
gtk_label_new_with_mnemonic(_("Maximum _download speed:")),
DEF_USEDOWNLIMIT, PREF_USEDOWNLIMIT, PREF_DOWNLIMIT, DEF_DOWNLIMIT,
N_("Restrict the download rate"),
N_("Speed in KiB/sec for restricted download rate")},
2006-07-16 19:39:23 +00:00
{ gtk_check_button_new_with_mnemonic(_("Li_mit upload speed")),
gtk_spin_button_new_with_range(0, G_MAXLONG, 1),
gtk_label_new_with_mnemonic(_("Maximum _upload speed:")),
DEF_USEUPLIMIT, PREF_USEUPLIMIT, PREF_UPLIMIT, DEF_UPLIMIT,
N_("Restrict the upload rate"),
N_("Speed in KiB/sec for restricted upload rate")},
2006-07-16 19:39:23 +00:00
};
unsigned int ii;
GtkTreeModel *model;
GtkTreeIter iter;
GtkCellRenderer *rend;
2006-09-25 18:37:45 +00:00
gboolean boolval;
int intval;
GtkTooltips * tips;
GtkWidget * event;
2006-07-16 19:39:23 +00:00
g_free(title);
gtk_widget_set_name(wind, "TransmissionDialog");
gtk_table_set_col_spacings(GTK_TABLE(table), 8);
gtk_table_set_row_spacings(GTK_TABLE(table), 8);
gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_OK);
gtk_container_set_border_width(GTK_CONTAINER(table), 6);
gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
tips = gtk_tooltips_new();
g_object_ref( tips );
gtk_object_sink( GTK_OBJECT( tips ) );
gtk_tooltips_enable( tips );
2006-07-16 19:39:23 +00:00
data->prefwidgets = makeglist(portnum, lim[0].on, lim[0].num, lim[1].on,
lim[1].num, askdir, dirstr, addstd, addipc, natcheck, NULL);
2006-07-16 19:39:23 +00:00
data->parent = parent;
data->back = back;
data->tips = tips;
2006-07-16 19:39:23 +00:00
g_object_ref(G_OBJECT(back));
#define RN(n) (n), (n) + 1
for(ii = 0; ii < ALEN(lim); ii++) {
/* limit checkbox */
setupprefwidget(lim[ii].on, lim[ii].usepref, (gboolean)lim[ii].defuse);
array = g_new(GtkWidget*, 3);
2006-07-16 19:39:23 +00:00
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));
gtk_tooltips_set_tip( tips, lim[ii].on, gettext( lim[ii].ontip ), "" );
2006-07-16 19:39:23 +00:00
/* limit label and entry */
gtk_label_set_mnemonic_widget(GTK_LABEL(lim[ii].label), lim[ii].num);
gtk_misc_set_alignment(GTK_MISC(lim[ii].label), 0, .5);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(lim[ii].num), TRUE);
setupprefwidget(lim[ii].num, lim[ii].numpref, (long)lim[ii].def);
event = tipbox( lim[ii].label, tips, gettext( lim[ii].numtip ) );
gtk_table_attach_defaults(GTK_TABLE(table), event, 0,1,RN(ii*2+1));
2006-07-16 19:39:23 +00:00
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 );
2006-07-16 19:39:23 +00:00
clicklimitbox(lim[ii].on, array);
gtk_tooltips_set_tip( tips, lim[ii].num, gettext( lim[ii].numtip ), "" );
2006-07-16 19:39:23 +00:00
}
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++;
2006-07-16 19:39:23 +00:00
/* directory label and chooser */
label = gtk_label_new_with_mnemonic(_("Download di_rectory:"));
gtk_label_set_mnemonic_widget(GTK_LABEL(label), dirstr);
gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
setupprefwidget(dirstr, PREF_DIR);
event = tipbox( label, tips,
_("Destination directory for downloaded data files") );
gtk_table_attach_defaults(GTK_TABLE(table), event, 0, 1, RN(ii));
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 );
2006-07-16 19:39:23 +00:00
ii++;
/* port label and entry */
label = gtk_label_new_with_mnemonic(_("Listening _port:"));
gtk_label_set_mnemonic_widget(GTK_LABEL(label), portnum);
gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(portnum), TRUE);
setupprefwidget(portnum, PREF_PORT, (long)TR_DEFAULT_PORT);
event = tipbox( label, tips,
_("TCP port number to listen for peer connections") );
gtk_table_attach_defaults(GTK_TABLE(table), event, 0, 1, RN(ii));
2006-07-16 19:39:23 +00:00
gtk_table_attach_defaults(GTK_TABLE(table), portnum, 1, 2, RN(ii));
gtk_tooltips_set_tip( tips, portnum,
_("TCP port number to listen for peer connections"), "" );
2006-07-16 19:39:23 +00:00
ii++;
2006-09-25 18:37:45 +00:00
/* NAT traversal checkbox */
intval = tr_handleStatus(tr_backend_handle(back))->natTraversalStatus;
2006-09-25 18:37:45 +00:00
boolval = !TR_NAT_TRAVERSAL_IS_DISABLED( intval );
setupprefwidget(natcheck, PREF_NAT, boolval);
gtk_table_attach_defaults(GTK_TABLE(table), natcheck, 0, 2, RN(ii));
gtk_tooltips_set_tip( tips, natcheck,
_("Attempt to bypass NAT or firewall to allow incoming peer connections"), "" );
2006-09-25 18:37:45 +00:00
ii++;
/* create the model used by the two popup menus */
2006-07-16 19:39:23 +00:00
model = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT));
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, 0, 0,
_("Use the torrent file where it is"), -1);
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, TR_TORNEW_SAVE_COPY, 0,
_("Keep a copy of the torrent file"), -1);
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, TR_TORNEW_SAVE_MOVE, 0,
_("Keep a copy and remove the original"), -1);
/* std */
label = gtk_label_new_with_mnemonic(_("For torrents added _normally:"));
gtk_label_set_mnemonic_widget(GTK_LABEL(label), addstd);
gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
gtk_combo_box_set_model(GTK_COMBO_BOX(addstd), model);
rend = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(addstd), rend, TRUE);
gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(addstd), rend, "text", 0);
setupprefwidget(addstd, PREF_ADDSTD);
event = tipbox( label, tips,
_("Torrent files added via the toolbar, popup menu, and drag-and-drop") );
gtk_table_attach_defaults(GTK_TABLE(table), event, 0, 1, RN(ii));
event = tipbox( addstd, tips,
_("Torrent files added via the toolbar, popup menu, and drag-and-drop") );
gtk_table_attach_defaults(GTK_TABLE(table), event, 1, 2, RN(ii));
2006-07-16 19:39:23 +00:00
ii++;
/* ipc */
label = gtk_label_new_with_mnemonic(
_("For torrents added e_xternally\n(via the command-line):"));
gtk_label_set_mnemonic_widget(GTK_LABEL(label), addipc);
gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
gtk_combo_box_set_model(GTK_COMBO_BOX(addipc), model);
rend = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(addipc), rend, TRUE);
gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(addipc), rend, "text", 0);
setupprefwidget(addipc, PREF_ADDIPC);
event = tipbox( label, tips,
_("For torrents added via the command-line only") );
gtk_table_attach_defaults(GTK_TABLE(table), event, 0, 1, RN(ii));
event = tipbox( addipc, tips,
_("For torrents added via the command-line only") );
gtk_table_attach_defaults(GTK_TABLE(table), event, 1, 2, RN(ii));
2006-07-16 19:39:23 +00:00
ii++;
#undef RN
g_assert(rowcount == ii);
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
g_signal_connect_data(wind, "response", G_CALLBACK(clickdialog),
data, freedata, 0);
gtk_widget_show_all(wind);
2006-08-20 22:45:29 +00:00
return wind;
2006-07-16 19:39:23 +00:00
}
static void
clicklimitbox( GtkWidget * widget, gpointer gdata )
{
GtkWidget ** widgets;
gboolean with, active;
int ii;
2006-07-16 19:39:23 +00:00
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 ) );
}
2006-07-16 19:39:23 +00:00
}
static void
freedata(gpointer gdata, GClosure *closure SHUTUP) {
struct prefdata *data = gdata;
g_list_free(data->prefwidgets);
g_object_unref(G_OBJECT(data->back));
g_object_unref( data->tips );
2006-07-16 19:39:23 +00:00
g_free(data);
}
static void
clickdialog(GtkWidget *widget, int resp, gpointer gdata) {
struct prefdata *data = gdata;
char *errstr;
GList *ii;
if(GTK_RESPONSE_APPLY == resp || GTK_RESPONSE_OK == resp) {
/* save all the prefs */
for(ii = g_list_first(data->prefwidgets); NULL != ii; ii = ii->next)
saveprefwidget(data->parent, ii->data);
/* write prefs to disk */
cf_saveprefs(&errstr);
if(NULL != errstr) {
errmsg(data->parent, "%s", errstr);
g_free(errstr);
}
2006-09-25 18:37:45 +00:00
applyprefs(data->back);
2006-07-16 19:39:23 +00:00
/* XXX would be nice to have errno strings, are they printed to stdout? */
}
if(GTK_RESPONSE_APPLY != resp)
gtk_widget_destroy(widget);
}
void
2006-09-25 18:37:45 +00:00
applyprefs(TrBackend *back) {
2006-07-16 19:39:23 +00:00
struct { void (*func)(tr_handle_t*, int);
const char *use; const char *num; gboolean defuse; long def; } lim[] = {
2006-12-27 00:33:22 +00:00
{tr_setGlobalDownloadLimit, PREF_USEDOWNLIMIT, PREF_DOWNLIMIT,
DEF_USEDOWNLIMIT, DEF_DOWNLIMIT},
{tr_setGlobalUploadLimit, PREF_USEUPLIMIT, PREF_UPLIMIT,
DEF_USEUPLIMIT, DEF_UPLIMIT},
2006-07-16 19:39:23 +00:00
};
const char *pref;
2006-09-25 18:37:45 +00:00
int ii;
2006-07-16 19:39:23 +00:00
tr_handle_t *tr = tr_backend_handle(back);
2006-09-25 18:37:45 +00:00
gboolean boolval;
2006-07-16 19:39:23 +00:00
2006-09-25 18:37:45 +00:00
/* set upload and download limits */
for(ii = 0; ii < (int)ALEN(lim); ii++) {
2006-07-16 19:39:23 +00:00
pref = cf_getpref(lim[ii].use);
if(!(NULL == pref ? lim[ii].defuse : strbool(pref)))
lim[ii].func(tr, -1);
else {
pref = cf_getpref(lim[ii].num);
lim[ii].func(tr, (NULL == pref ? lim[ii].def : strtol(pref, NULL, 10)));
}
}
2006-09-25 18:37:45 +00:00
/* set the listening port */
if(NULL != (pref = cf_getpref(PREF_PORT)) &&
0 < (ii = strtol(pref, NULL, 10)) && 0xffff >= ii)
tr_setBindPort(tr, ii);
/* enable/disable NAT traversal */
boolval = (NULL == (pref = cf_getpref(PREF_NAT)) ? DEF_NAT : strbool(pref));
tr_natTraversalEnable(tr, boolval);
2006-07-16 19:39:23 +00:00
}
void
makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata) {
GtkWidget *wind = gtk_file_chooser_dialog_new(_("Add a Torrent"), parent,
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
struct addcb *data = g_new(struct addcb, 1);
GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
GtkWidget *bbox = gtk_hbutton_box_new();
GtkWidget *autocheck = gtk_check_button_new_with_mnemonic(
_("Automatically _start torrent"));
GtkWidget *dircheck = gtk_check_button_new_with_mnemonic(
_("Use alternate _download directory"));
GtkFileFilter *filter = gtk_file_filter_new();
GtkFileFilter *unfilter = gtk_file_filter_new();
GtkWidget *getdir = gtk_file_chooser_button_new(
_("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
const char *pref;
data->addfunc = addfunc;
data->data = cbdata;
data->autostart = TRUE;
data->usingaltdir = FALSE;
data->altdir = GTK_FILE_CHOOSER(getdir);
data->altbox = GTK_BUTTON_BOX(bbox);
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_EDGE);
gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
if(NULL != (pref = cf_getpref(PREF_DIR)))
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getdir), pref);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
gtk_widget_set_sensitive(getdir, FALSE);
gtk_file_filter_set_name(filter, _("Torrent files"));
gtk_file_filter_add_pattern(filter, "*.torrent");
gtk_file_filter_set_name(unfilter, _("All files"));
gtk_file_filter_add_pattern(unfilter, "*");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
gtk_widget_show_all(wind);
}
static void
autoclick(GtkWidget *widget, gpointer gdata) {
struct addcb *data = gdata;
data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
}
static void
dirclick(GtkWidget *widget, gpointer gdata) {
struct addcb *data = gdata;
data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
gtk_widget_set_sensitive(GTK_WIDGET(data->altdir), data->usingaltdir);
}
static void
addresp(GtkWidget *widget, gint resp, gpointer gdata) {
struct addcb *data = gdata;
GSList *files, *ii;
GList *stupidgtk;
int flags;
2006-07-16 19:39:23 +00:00
char *dir;
if(GTK_RESPONSE_ACCEPT == resp) {
dir = NULL;
if(data->usingaltdir)
dir = gtk_file_chooser_get_filename(data->altdir);
files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
stupidgtk = NULL;
for(ii = files; NULL != ii; ii = ii->next)
stupidgtk = g_list_append(stupidgtk, ii->data);
flags = ( data->autostart ? TR_TORNEW_RUNNING : TR_TORNEW_PAUSED );
flags |= addactionflag( cf_getpref( PREF_ADDSTD ) );
data->addfunc( data->data, NULL, stupidgtk, dir, flags );
2006-07-16 19:39:23 +00:00
if(NULL != dir)
g_free(dir);
g_slist_free(files);
freestrlist(stupidgtk);
}
g_free( data );
2006-07-16 19:39:23 +00:00
gtk_widget_destroy(widget);
}
#define INFOLINE(tab, ii, nam, val) \
do { \
char *txt = g_markup_printf_escaped("<b>%s</b>", nam); \
GtkWidget *wid = gtk_label_new(NULL); \
gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
gtk_label_set_markup(GTK_LABEL(wid), txt); \
gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 1, ii, ii + 1); \
wid = gtk_label_new(val); \
gtk_label_set_selectable(GTK_LABEL(wid), TRUE); \
gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
gtk_table_attach_defaults(GTK_TABLE(tab), wid, 1, 2, ii, ii + 1); \
ii++; \
g_free(txt); \
} while(0)
#define INFOLINEF(tab, ii, fmt, nam, val) \
do { \
char *buf = g_strdup_printf(fmt, val); \
INFOLINE(tab, ii, nam, buf); \
g_free(buf); \
} while(0)
#define INFOLINEA(tab, ii, nam, val) \
do { \
char *buf = val; \
INFOLINE(tab, ii, nam, buf); \
g_free(buf); \
} while(0)
#define INFOSEP(tab, ii) \
do { \
GtkWidget *wid = gtk_hseparator_new(); \
gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 2, ii, ii + 1); \
ii++; \
} while(0)
void
makeinfowind(GtkWindow *parent, TrTorrent *tor) {
tr_stat_t *sb;
tr_info_t *in;
GtkWidget *wind, *label;
int ii;
char *str;
const int rowcount = 15;
2006-07-16 19:39:23 +00:00
GtkWidget *table = gtk_table_new(rowcount, 2, FALSE);
/* XXX should use model and update this window regularly */
sb = tr_torrent_stat(tor);
in = tr_torrent_info(tor);
str = g_strdup_printf(_("%s Properties"), in->name);
wind = gtk_dialog_new_with_buttons(str, parent,
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
g_free(str);
gtk_widget_set_name(wind, "TransmissionDialog");
gtk_table_set_col_spacings(GTK_TABLE(table), 12);
gtk_table_set_row_spacings(GTK_TABLE(table), 12);
gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_ACCEPT);
gtk_container_set_border_width(GTK_CONTAINER(table), 6);
gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
label = gtk_label_new(NULL);
gtk_label_set_selectable(GTK_LABEL(label), TRUE);
str = g_markup_printf_escaped("<big>%s</big>", in->name);
gtk_label_set_markup(GTK_LABEL(label), str);
g_free(str);
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 0, 1);
ii = 1;
INFOSEP(table, ii);
if(80 == sb->trackerPort)
2006-07-16 19:39:23 +00:00
INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s",
sb->trackerAddress));
2006-07-16 19:39:23 +00:00
else
INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s:%i",
sb->trackerAddress, sb->trackerPort));
INFOLINE(table, ii, _("Announce:"), sb->trackerAnnounce);
2006-07-16 19:39:23 +00:00
INFOLINEA(table, ii, _("Piece Size:"), readablesize(in->pieceSize));
INFOLINEF(table, ii, "%i", _("Pieces:"), in->pieceCount);
INFOLINEA(table, ii, _("Total Size:"), readablesize(in->totalSize));
if(0 > sb->seeders)
INFOLINE(table, ii, _("Seeders:"), _("?"));
else
INFOLINEF(table, ii, "%i", _("Seeders:"), sb->seeders);
if(0 > sb->leechers)
INFOLINE(table, ii, _("Leechers:"), _("?"));
else
INFOLINEF(table, ii, "%i", _("Leechers:"), sb->leechers);
if(0 > sb->completedFromTracker)
INFOLINE(table, ii, _("Completed:"), _("?"));
else
INFOLINEF(table, ii, "%i", _("Completed:"), sb->completedFromTracker);
2006-07-16 19:39:23 +00:00
INFOSEP(table, ii);
INFOLINE(table, ii, _("Directory:"), tr_torrentGetFolder(tr_torrent_handle(tor)));
INFOLINEA(table, ii, _("Downloaded:"), readablesize(sb->downloaded));
INFOLINEA(table, ii, _("Uploaded:"), readablesize(sb->uploaded));
INFOSEP(table, ii);
g_assert(rowcount == ii);
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
g_signal_connect(G_OBJECT(wind), "response",
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 );
}