source: trunk/gtk/dialogs.c @ 320

Last change on this file since 320 was 320, checked in by joshe, 16 years ago

Add support to the GTK GUI for saving private copies of torrent files.
The prefs dialog for this sucks, but it should work.

  • Property svn:keywords set to Date Rev Author Id
File size: 21.2 KB
Line 
1/*
2  $Id: dialogs.c 320 2006-06-10 06:53:20Z joshe $
3
4  Copyright (c) 2005-2006 Joshua Elsasser. All rights reserved.
5   
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions
8  are met:
9   
10   1. Redistributions of source code must retain the above copyright
11      notice, this list of conditions and the following disclaimer.
12   2. Redistributions in binary form must reproduce the above copyright
13      notice, this list of conditions and the following disclaimer in the
14      documentation and/or other materials provided with the distribution.
15   
16  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND
17  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <errno.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <gtk/gtk.h>
34#include <glib/gi18n.h>
35
36#include "conf.h"
37#include "dialogs.h"
38#include "transmission.h"
39#include "util.h"
40
41#define PREFNAME                "transmission-dialog-pref-name"
42
43/* default values for a couple prefs */
44#define DEF_DOWNLIMIT           100
45#define DEF_USEDOWNLIMIT        FALSE
46#define DEF_UPLIMIT             20
47#define DEF_USEUPLIMIT          TRUE
48
49struct prefdata {
50  GList *prefwidgets;
51  GtkWindow *parent;
52  TrBackend *back;
53};
54
55struct addcb {
56  add_torrents_func_t addfunc;
57  GtkWindow *parent;
58  void *data;
59  gboolean autostart;
60  gboolean usingaltdir;
61  GtkFileChooser *altdir;
62  GtkButtonBox *altbox;
63};
64
65static void
66windclosed(GtkWidget *widget SHUTUP, gpointer gdata);
67static void
68clicklimitbox(GtkWidget *widget, gpointer gdata);
69static void
70freedata(gpointer gdata, GClosure *closure);
71static void
72clickdialog(GtkWidget *widget, int resp, gpointer gdata);
73static void
74autoclick(GtkWidget *widget, gpointer gdata);
75static void
76dirclick(GtkWidget *widget, gpointer gdata);
77static void
78addresp(GtkWidget *widget, gint resp, gpointer gdata);
79
80static void
81setupprefwidget(GtkWidget *widget, const char *prefname, ...) {
82  const char *pref = cf_getpref(prefname);
83  GtkTreeModel *model;
84  GtkTreeIter iter;
85  guint prefsflag, modelflag;
86  va_list ap;
87
88  g_object_set_data_full(G_OBJECT(widget), PREFNAME,
89                         g_strdup(prefname), (GDestroyNotify)g_free);
90
91  va_start(ap, prefname);
92
93  if(ISA(widget, GTK_TYPE_FILE_CHOOSER)) {
94    if(NULL != pref)
95      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(widget), pref);
96  }
97  else if(ISA(widget, GTK_TYPE_SPIN_BUTTON))
98    gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
99      (NULL == pref ? va_arg(ap, long) : strtol(pref, NULL, 10)));
100  else if(ISA(widget, GTK_TYPE_TOGGLE_BUTTON))
101    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
102      (NULL == pref ? va_arg(ap, gboolean) : strbool(pref)));
103  else if(ISA(widget, GTK_TYPE_COMBO_BOX)) {
104    model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
105    prefsflag = addactionflag(pref);
106    if(gtk_tree_model_get_iter_first(model, &iter))
107      do {
108        gtk_tree_model_get(model, &iter, 1, &modelflag, -1);
109        if(modelflag == prefsflag) {
110          gtk_combo_box_set_active_iter(GTK_COMBO_BOX(widget), &iter);
111          break;
112        }
113      } while(gtk_tree_model_iter_next(model, &iter));
114  }
115  else {
116    g_assert_not_reached();
117  }
118
119  va_end(ap);
120}
121
122static void
123saveprefwidget(GtkWindow *parent, GtkWidget *widget) {
124  char *prefname;
125  const char *strval;
126  char *freeablestr;
127  GtkTreeModel *model;
128  GtkTreeIter iter;
129  guint uintval;
130
131  strval = NULL;
132  freeablestr = NULL;
133  if(ISA(widget, GTK_TYPE_FILE_CHOOSER)) {
134    strval = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
135    if(NULL != strval) {
136      if(!mkdir_p(strval, 0777)) {
137        errmsg(parent, _("Failed to create the directory %s:\n%s"),
138               strval, strerror(errno));
139        return;
140      }
141    }
142  }
143  else if(ISA(widget, GTK_TYPE_SPIN_BUTTON))
144    freeablestr = g_strdup_printf("%i",
145      gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)));
146  else if(ISA(widget, GTK_TYPE_TOGGLE_BUTTON))
147    strval = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ?
148              "yes" : "no");
149  else if(ISA(widget, GTK_TYPE_COMBO_BOX)) {
150    if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) {
151      model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
152      gtk_tree_model_get(model, &iter, 1, &uintval, -1);
153      strval = addactionname(uintval);
154    }
155  }
156  else {
157    g_assert_not_reached();
158    return;
159  }
160
161  prefname = g_object_get_data(G_OBJECT(widget), PREFNAME);
162  g_assert(NULL != prefname);
163
164  if(NULL != strval)
165    cf_setpref(prefname, strval);
166  else if(NULL != freeablestr) {
167    cf_setpref(prefname, freeablestr);
168    g_free(freeablestr);
169  }
170}
171
172void
173makeprefwindow(GtkWindow *parent, TrBackend *back, gboolean *opened) {
174  char *title = g_strdup_printf(_("%s Preferences"), g_get_application_name());
175  GtkWidget *wind = gtk_dialog_new_with_buttons(title, parent,
176   GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
177   GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
178   GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
179  const unsigned int rowcount = 9;
180  GtkWidget *table = gtk_table_new(rowcount, 2, FALSE);
181  GtkWidget *portnum = gtk_spin_button_new_with_range(1, 0xffff, 1);
182  GtkWidget *dirstr = gtk_file_chooser_button_new(
183    _("Choose a download directory"),
184    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
185  GtkWidget *addstd = gtk_combo_box_new();
186  GtkWidget *adddnd = gtk_combo_box_new();
187  GtkWidget *addipc = gtk_combo_box_new();
188  GtkWidget *label;
189  GtkWidget **array;
190  struct prefdata *data = g_new0(struct prefdata, 1);
191  struct { GtkWidget *on; GtkWidget *num; GtkWidget *label; gboolean defuse;
192    const char *usepref; const char *numpref; long def; } lim[] = {
193    { gtk_check_button_new_with_mnemonic(_("_Limit download speed")),
194      gtk_spin_button_new_with_range(0, G_MAXLONG, 1),
195      gtk_label_new_with_mnemonic(_("Maximum _download speed:")),
196      DEF_USEDOWNLIMIT, PREF_USEDOWNLIMIT, PREF_DOWNLIMIT, DEF_DOWNLIMIT, },
197    { gtk_check_button_new_with_mnemonic(_("Li_mit upload speed")),
198      gtk_spin_button_new_with_range(0, G_MAXLONG, 1),
199      gtk_label_new_with_mnemonic(_("Maximum _upload speed:")),
200      DEF_USEUPLIMIT, PREF_USEUPLIMIT, PREF_UPLIMIT, DEF_UPLIMIT, },
201  };
202  unsigned int ii;
203  GtkTreeModel *model;
204  GtkTreeIter iter;
205  GtkCellRenderer *rend;
206
207  *opened = TRUE;
208
209  g_free(title);
210  gtk_widget_set_name(wind, "TransmissionDialog");
211  gtk_table_set_col_spacings(GTK_TABLE(table), 8);
212  gtk_table_set_row_spacings(GTK_TABLE(table), 8);
213  gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_OK);
214  gtk_container_set_border_width(GTK_CONTAINER(table), 6);
215  gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
216
217  data->prefwidgets = makeglist(portnum, lim[0].on, lim[0].num, lim[1].on,
218    lim[1].num, dirstr, addstd, adddnd, addipc, NULL);
219  data->parent = parent;
220  data->back = back;
221  g_object_ref(G_OBJECT(back));
222
223#define RN(n) (n), (n) + 1
224
225  for(ii = 0; ii < ALEN(lim); ii++) {
226    /* limit checkbox */
227    setupprefwidget(lim[ii].on, lim[ii].usepref, (gboolean)lim[ii].defuse);
228    array = g_new(GtkWidget*, 2);
229    g_signal_connect_data(lim[ii].on, "clicked", G_CALLBACK(clicklimitbox),
230                          array, (GClosureNotify)g_free, 0);
231    gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].on,    0, 2, RN(ii*2));
232
233    /* limit label and entry */
234    gtk_label_set_mnemonic_widget(GTK_LABEL(lim[ii].label), lim[ii].num);
235    gtk_misc_set_alignment(GTK_MISC(lim[ii].label), 0, .5);
236    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(lim[ii].num), TRUE);
237    setupprefwidget(lim[ii].num, lim[ii].numpref, (long)lim[ii].def);
238    gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].label, 0,1,RN(ii*2+1));
239    gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].num,   1,2,RN(ii*2+1));
240    array[0] = lim[ii].label;
241    array[1] = lim[ii].num;
242    clicklimitbox(lim[ii].on, array);
243  }
244  ii *= 2;
245
246  /* directory label and chooser */
247  label = gtk_label_new_with_mnemonic(_("Download di_rectory:"));
248  gtk_label_set_mnemonic_widget(GTK_LABEL(label), dirstr);
249  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
250  setupprefwidget(dirstr, PREF_DIR);
251  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
252  gtk_table_attach_defaults(GTK_TABLE(table), dirstr,          1, 2, RN(ii));
253  ii++;
254
255  /* port label and entry */
256  label = gtk_label_new_with_mnemonic(_("Listening _port:"));
257  gtk_label_set_mnemonic_widget(GTK_LABEL(label), portnum);
258  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
259  gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(portnum), TRUE);
260  setupprefwidget(portnum, PREF_PORT, (long)TR_DEFAULT_PORT);
261  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
262  gtk_table_attach_defaults(GTK_TABLE(table), portnum,         1, 2, RN(ii));
263  ii++;
264
265  /* create the model used by the three popup menus */
266  model = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT));
267  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
268  gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, 0, 0,
269    _("Use the torrent file where it is"), -1);
270  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
271  gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, TR_TORNEW_SAVE_COPY, 0,
272    _("Keep a copy of the torrent file"), -1);
273  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
274  gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, TR_TORNEW_SAVE_MOVE, 0,
275    _("Keep a copy and remove the original"), -1);
276
277  /* std */
278  label = gtk_label_new_with_mnemonic(_("For torrents added _normally:"));
279  gtk_label_set_mnemonic_widget(GTK_LABEL(label), addstd);
280  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
281  gtk_combo_box_set_model(GTK_COMBO_BOX(addstd), model);
282  rend = gtk_cell_renderer_text_new();
283  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(addstd), rend, TRUE);
284  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(addstd), rend, "text", 0);
285  setupprefwidget(addstd, PREF_ADDSTD);
286  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
287  gtk_table_attach_defaults(GTK_TABLE(table), addstd,          1, 2, RN(ii));
288  ii++;
289
290  /* dnd */
291  label = gtk_label_new_with_mnemonic(_("For torrents dra_gged and dropped:"));
292  gtk_label_set_mnemonic_widget(GTK_LABEL(label), adddnd);
293  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
294  gtk_combo_box_set_model(GTK_COMBO_BOX(adddnd), model);
295  rend = gtk_cell_renderer_text_new();
296  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(adddnd), rend, TRUE);
297  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(adddnd), rend, "text", 0);
298  setupprefwidget(adddnd, PREF_ADDDND);
299  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
300  gtk_table_attach_defaults(GTK_TABLE(table), adddnd,          1, 2, RN(ii));
301  ii++;
302
303  /* ipc */
304  label = gtk_label_new_with_mnemonic(
305    _("For torrents added e_xternally:"));
306  gtk_label_set_mnemonic_widget(GTK_LABEL(label), addipc);
307  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
308  gtk_combo_box_set_model(GTK_COMBO_BOX(addipc), model);
309  rend = gtk_cell_renderer_text_new();
310  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(addipc), rend, TRUE);
311  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(addipc), rend, "text", 0);
312  setupprefwidget(addipc, PREF_ADDIPC);
313  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
314  gtk_table_attach_defaults(GTK_TABLE(table), addipc,          1, 2, RN(ii));
315  ii++;
316
317#undef RN
318  g_assert(rowcount == ii);
319
320  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
321  g_signal_connect_data(wind, "response", G_CALLBACK(clickdialog),
322                        data, freedata, 0);
323  g_signal_connect(wind, "destroy", G_CALLBACK(windclosed), opened);
324  gtk_widget_show_all(wind);
325}
326
327static void
328windclosed(GtkWidget *widget SHUTUP, gpointer gdata) {
329  gboolean *preachy_gcc = gdata;
330 
331  *preachy_gcc = FALSE;
332}
333
334static void
335clicklimitbox(GtkWidget *widget, gpointer gdata) {
336  GtkWidget **widgets = gdata;
337  int ii;
338
339  for(ii = 0; 2 > ii; ii++)
340    gtk_widget_set_sensitive(widgets[ii],
341      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
342}
343
344static void
345freedata(gpointer gdata, GClosure *closure SHUTUP) {
346  struct prefdata *data = gdata;
347
348  g_object_unref(G_OBJECT(data->back));
349  g_free(data);
350}
351
352static void
353clickdialog(GtkWidget *widget, int resp, gpointer gdata) {
354  struct prefdata *data = gdata;
355  char *errstr;
356  GList *ii;
357
358  if(GTK_RESPONSE_APPLY == resp || GTK_RESPONSE_OK == resp) {
359    /* save all the prefs */
360    for(ii = g_list_first(data->prefwidgets); NULL != ii; ii = ii->next)
361      saveprefwidget(data->parent, ii->data);
362
363    /* write prefs to disk */
364    cf_saveprefs(&errstr);
365    if(NULL != errstr) {
366      errmsg(data->parent, "%s", errstr);
367      g_free(errstr);
368    }
369
370    /* XXX would be nice to have errno strings, are they printed to stdout? */
371
372    tr_setBindPort(tr_backend_handle(data->back),
373                   strtol(cf_getpref(PREF_PORT), NULL, 10));
374    setlimit(data->back);
375  }
376
377  if(GTK_RESPONSE_APPLY != resp)
378    gtk_widget_destroy(widget);
379}
380
381void
382setlimit(TrBackend *back) {
383  struct { void (*func)(tr_handle_t*, int);
384    const char *use; const char *num; gboolean defuse; long def; } lim[] = {
385    {tr_setDownloadLimit, PREF_USEDOWNLIMIT, PREF_DOWNLIMIT,
386                          DEF_USEDOWNLIMIT,  DEF_DOWNLIMIT},
387    {tr_setUploadLimit,   PREF_USEUPLIMIT,   PREF_UPLIMIT,
388                          DEF_USEUPLIMIT,    DEF_UPLIMIT},
389  };
390  const char *pref;
391  unsigned int ii;
392  tr_handle_t *tr = tr_backend_handle(back);
393
394  for(ii = 0; ii < ALEN(lim); ii++) {
395    pref = cf_getpref(lim[ii].use);
396    if(!(NULL == pref ? lim[ii].defuse : strbool(pref)))
397      lim[ii].func(tr, -1);
398    else {
399      pref = cf_getpref(lim[ii].num);
400      lim[ii].func(tr, (NULL == pref ? lim[ii].def : strtol(pref, NULL, 10)));
401    }
402  }
403}
404
405void
406makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata) {
407  GtkWidget *wind = gtk_file_chooser_dialog_new(_("Add a Torrent"), parent,
408    GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
409    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
410  struct addcb *data = g_new(struct addcb, 1);
411  GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
412  GtkWidget *bbox = gtk_hbutton_box_new();
413  GtkWidget *autocheck = gtk_check_button_new_with_mnemonic(
414    _("Automatically _start torrent"));
415  GtkWidget *dircheck = gtk_check_button_new_with_mnemonic(
416    _("Use alternate _download directory"));
417  GtkFileFilter *filter = gtk_file_filter_new();
418  GtkFileFilter *unfilter = gtk_file_filter_new();
419  GtkWidget *getdir = gtk_file_chooser_button_new(
420    _("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
421  const char *pref;
422
423  data->addfunc = addfunc;
424  data->parent = parent;
425  data->data = cbdata;
426  data->autostart = TRUE;
427  data->usingaltdir = FALSE;
428  data->altdir = GTK_FILE_CHOOSER(getdir);
429  data->altbox = GTK_BUTTON_BOX(bbox);
430
431  gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_EDGE);
432  gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
433  gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
434
435  gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
436  gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
437
438  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
439  if(NULL != (pref = cf_getpref(PREF_DIR)))
440    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getdir), pref);
441
442  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
443  gtk_widget_set_sensitive(getdir, FALSE);
444
445  gtk_file_filter_set_name(filter, _("Torrent files"));
446  gtk_file_filter_add_pattern(filter, "*.torrent");
447  gtk_file_filter_set_name(unfilter, _("All files"));
448  gtk_file_filter_add_pattern(unfilter, "*");
449
450  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
451  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
452  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
453  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
454
455  g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
456  g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
457  g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
458
459  gtk_widget_show_all(wind);
460}
461
462static void
463autoclick(GtkWidget *widget, gpointer gdata) {
464  struct addcb *data = gdata;
465
466  data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
467}
468
469static void
470dirclick(GtkWidget *widget, gpointer gdata) {
471  struct addcb *data = gdata;
472
473  data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
474  gtk_widget_set_sensitive(GTK_WIDGET(data->altdir), data->usingaltdir);
475}
476
477static void
478addresp(GtkWidget *widget, gint resp, gpointer gdata) {
479  struct addcb *data = gdata;
480  GSList *files, *ii;
481  GList *stupidgtk;
482  gboolean paused;
483  char *dir;
484
485  if(GTK_RESPONSE_ACCEPT == resp) {
486    dir = NULL;
487    if(data->usingaltdir)
488      dir = gtk_file_chooser_get_filename(data->altdir);
489    files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
490    stupidgtk = NULL;
491    for(ii = files; NULL != ii; ii = ii->next)
492      stupidgtk = g_list_append(stupidgtk, ii->data);
493    paused = !data->autostart;
494    data->addfunc(data->data, NULL, stupidgtk, dir,
495                  addactionflag(cf_getpref(PREF_ADDSTD)));
496    if(NULL != dir)
497      g_free(dir);
498    g_slist_free(files);
499    freestrlist(stupidgtk);
500  }
501
502  gtk_widget_destroy(widget);
503}
504
505#define INFOLINE(tab, ii, nam, val) \
506  do { \
507    char *txt = g_markup_printf_escaped("<b>%s</b>", nam); \
508    GtkWidget *wid = gtk_label_new(NULL); \
509    gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
510    gtk_label_set_markup(GTK_LABEL(wid), txt); \
511    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 1, ii, ii + 1); \
512    wid = gtk_label_new(val); \
513    gtk_label_set_selectable(GTK_LABEL(wid), TRUE); \
514    gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
515    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 1, 2, ii, ii + 1); \
516    ii++; \
517    g_free(txt); \
518  } while(0)
519
520#define INFOLINEF(tab, ii, fmt, nam, val) \
521  do { \
522    char *buf = g_strdup_printf(fmt, val); \
523    INFOLINE(tab, ii, nam, buf); \
524    g_free(buf); \
525  } while(0)
526
527#define INFOLINEA(tab, ii, nam, val) \
528  do { \
529    char *buf = val; \
530    INFOLINE(tab, ii, nam, buf); \
531    g_free(buf); \
532  } while(0)
533
534#define INFOSEP(tab, ii) \
535  do { \
536    GtkWidget *wid = gtk_hseparator_new(); \
537    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 2, ii, ii + 1); \
538    ii++; \
539  } while(0)
540
541void
542makeinfowind(GtkWindow *parent, TrTorrent *tor) {
543  tr_stat_t *sb;
544  tr_info_t *in;
545  GtkWidget *wind, *label;
546  int ii;
547  char *str;
548  const int rowcount = 14;
549  GtkWidget *table = gtk_table_new(rowcount, 2, FALSE);
550
551  /* XXX should use model and update this window regularly */
552
553  sb = tr_torrent_stat(tor);
554  in = tr_torrent_info(tor);
555  str = g_strdup_printf(_("%s Properties"), in->name);
556  wind = gtk_dialog_new_with_buttons(str, parent,
557    GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
558    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
559  g_free(str);
560
561  gtk_widget_set_name(wind, "TransmissionDialog");
562  gtk_table_set_col_spacings(GTK_TABLE(table), 12);
563  gtk_table_set_row_spacings(GTK_TABLE(table), 12);
564  gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_ACCEPT);
565  gtk_container_set_border_width(GTK_CONTAINER(table), 6);
566  gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
567
568  label = gtk_label_new(NULL);
569  gtk_label_set_selectable(GTK_LABEL(label), TRUE);
570  str = g_markup_printf_escaped("<big>%s</big>", in->name);
571  gtk_label_set_markup(GTK_LABEL(label), str);
572  g_free(str);
573  gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 0, 1);
574
575  ii = 1;
576
577  INFOSEP(table, ii);
578
579  if(80 == in->trackerPort)
580    INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s",
581              in->trackerAddress));
582  else
583    INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s:%i",
584              in->trackerAddress, in->trackerPort));
585  INFOLINE(table, ii, _("Announce:"), in->trackerAnnounce);
586  INFOLINEA(table, ii, _("Piece Size:"), readablesize(in->pieceSize));
587  INFOLINEF(table, ii, "%i", _("Pieces:"), in->pieceCount);
588  INFOLINEA(table, ii, _("Total Size:"), readablesize(in->totalSize));
589  if(0 > sb->seeders)
590    INFOLINE(table, ii, _("Seeders:"), _("?"));
591  else
592    INFOLINEF(table, ii, "%i", _("Seeders:"), sb->seeders);
593  if(0 > sb->leechers)
594    INFOLINE(table, ii, _("Leechers:"), _("?"));
595  else
596    INFOLINEF(table, ii, "%i", _("Leechers:"), sb->leechers);
597
598  INFOSEP(table, ii);
599
600  INFOLINE(table, ii, _("Directory:"), tr_torrentGetFolder(tr_torrent_handle(tor)));
601  INFOLINEA(table, ii, _("Downloaded:"), readablesize(sb->downloaded));
602  INFOLINEA(table, ii, _("Uploaded:"), readablesize(sb->uploaded));
603
604  INFOSEP(table, ii);
605
606  g_assert(rowcount == ii);
607
608  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
609  g_signal_connect(G_OBJECT(wind), "response",
610                   G_CALLBACK(gtk_widget_destroy), NULL);
611  gtk_widget_show_all(wind);
612}
Note: See TracBrowser for help on using the repository browser.