source: trunk/gtk/dialogs.c @ 327

Last change on this file since 327 was 327, checked in by joshe, 15 years ago

Remove the separate preference option for files added via drag-and-drop

and use the "standard" option.

  • Property svn:keywords set to Date Rev Author Id
File size: 20.5 KB
Line 
1/*
2  $Id: dialogs.c 327 2006-06-11 05:04:27Z 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 = 8;
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 *addipc = gtk_combo_box_new();
187  GtkWidget *label;
188  GtkWidget **array;
189  struct prefdata *data = g_new0(struct prefdata, 1);
190  struct { GtkWidget *on; GtkWidget *num; GtkWidget *label; gboolean defuse;
191    const char *usepref; const char *numpref; long def; } lim[] = {
192    { gtk_check_button_new_with_mnemonic(_("_Limit download speed")),
193      gtk_spin_button_new_with_range(0, G_MAXLONG, 1),
194      gtk_label_new_with_mnemonic(_("Maximum _download speed:")),
195      DEF_USEDOWNLIMIT, PREF_USEDOWNLIMIT, PREF_DOWNLIMIT, DEF_DOWNLIMIT, },
196    { gtk_check_button_new_with_mnemonic(_("Li_mit upload speed")),
197      gtk_spin_button_new_with_range(0, G_MAXLONG, 1),
198      gtk_label_new_with_mnemonic(_("Maximum _upload speed:")),
199      DEF_USEUPLIMIT, PREF_USEUPLIMIT, PREF_UPLIMIT, DEF_UPLIMIT, },
200  };
201  unsigned int ii;
202  GtkTreeModel *model;
203  GtkTreeIter iter;
204  GtkCellRenderer *rend;
205
206  *opened = TRUE;
207
208  g_free(title);
209  gtk_widget_set_name(wind, "TransmissionDialog");
210  gtk_table_set_col_spacings(GTK_TABLE(table), 8);
211  gtk_table_set_row_spacings(GTK_TABLE(table), 8);
212  gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_OK);
213  gtk_container_set_border_width(GTK_CONTAINER(table), 6);
214  gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
215
216  data->prefwidgets = makeglist(portnum, lim[0].on, lim[0].num, lim[1].on,
217    lim[1].num, dirstr, addstd, addipc, NULL);
218  data->parent = parent;
219  data->back = back;
220  g_object_ref(G_OBJECT(back));
221
222#define RN(n) (n), (n) + 1
223
224  for(ii = 0; ii < ALEN(lim); ii++) {
225    /* limit checkbox */
226    setupprefwidget(lim[ii].on, lim[ii].usepref, (gboolean)lim[ii].defuse);
227    array = g_new(GtkWidget*, 2);
228    g_signal_connect_data(lim[ii].on, "clicked", G_CALLBACK(clicklimitbox),
229                          array, (GClosureNotify)g_free, 0);
230    gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].on,    0, 2, RN(ii*2));
231
232    /* limit label and entry */
233    gtk_label_set_mnemonic_widget(GTK_LABEL(lim[ii].label), lim[ii].num);
234    gtk_misc_set_alignment(GTK_MISC(lim[ii].label), 0, .5);
235    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(lim[ii].num), TRUE);
236    setupprefwidget(lim[ii].num, lim[ii].numpref, (long)lim[ii].def);
237    gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].label, 0,1,RN(ii*2+1));
238    gtk_table_attach_defaults(GTK_TABLE(table), lim[ii].num,   1,2,RN(ii*2+1));
239    array[0] = lim[ii].label;
240    array[1] = lim[ii].num;
241    clicklimitbox(lim[ii].on, array);
242  }
243  ii *= 2;
244
245  /* directory label and chooser */
246  label = gtk_label_new_with_mnemonic(_("Download di_rectory:"));
247  gtk_label_set_mnemonic_widget(GTK_LABEL(label), dirstr);
248  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
249  setupprefwidget(dirstr, PREF_DIR);
250  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
251  gtk_table_attach_defaults(GTK_TABLE(table), dirstr,          1, 2, RN(ii));
252  ii++;
253
254  /* port label and entry */
255  label = gtk_label_new_with_mnemonic(_("Listening _port:"));
256  gtk_label_set_mnemonic_widget(GTK_LABEL(label), portnum);
257  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
258  gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(portnum), TRUE);
259  setupprefwidget(portnum, PREF_PORT, (long)TR_DEFAULT_PORT);
260  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
261  gtk_table_attach_defaults(GTK_TABLE(table), portnum,         1, 2, RN(ii));
262  ii++;
263
264  /* create the model used by the three popup menus */
265  model = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT));
266  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
267  gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, 0, 0,
268    _("Use the torrent file where it is"), -1);
269  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
270  gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, TR_TORNEW_SAVE_COPY, 0,
271    _("Keep a copy of the torrent file"), -1);
272  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
273  gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, TR_TORNEW_SAVE_MOVE, 0,
274    _("Keep a copy and remove the original"), -1);
275
276  /* std */
277  label = gtk_label_new_with_mnemonic(_("For torrents added _normally:"));
278  gtk_label_set_mnemonic_widget(GTK_LABEL(label), addstd);
279  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
280  gtk_combo_box_set_model(GTK_COMBO_BOX(addstd), model);
281  rend = gtk_cell_renderer_text_new();
282  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(addstd), rend, TRUE);
283  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(addstd), rend, "text", 0);
284  setupprefwidget(addstd, PREF_ADDSTD);
285  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
286  gtk_table_attach_defaults(GTK_TABLE(table), addstd,          1, 2, RN(ii));
287  ii++;
288
289  /* ipc */
290  label = gtk_label_new_with_mnemonic(
291    _("For torrents added e_xternally\n(via the command-line):"));
292  gtk_label_set_mnemonic_widget(GTK_LABEL(label), addipc);
293  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
294  gtk_combo_box_set_model(GTK_COMBO_BOX(addipc), model);
295  rend = gtk_cell_renderer_text_new();
296  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(addipc), rend, TRUE);
297  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(addipc), rend, "text", 0);
298  setupprefwidget(addipc, PREF_ADDIPC);
299  gtk_table_attach_defaults(GTK_TABLE(table), label,           0, 1, RN(ii));
300  gtk_table_attach_defaults(GTK_TABLE(table), addipc,          1, 2, RN(ii));
301  ii++;
302
303#undef RN
304  g_assert(rowcount == ii);
305
306  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
307  g_signal_connect_data(wind, "response", G_CALLBACK(clickdialog),
308                        data, freedata, 0);
309  g_signal_connect(wind, "destroy", G_CALLBACK(windclosed), opened);
310  gtk_widget_show_all(wind);
311}
312
313static void
314windclosed(GtkWidget *widget SHUTUP, gpointer gdata) {
315  gboolean *preachy_gcc = gdata;
316 
317  *preachy_gcc = FALSE;
318}
319
320static void
321clicklimitbox(GtkWidget *widget, gpointer gdata) {
322  GtkWidget **widgets = gdata;
323  int ii;
324
325  for(ii = 0; 2 > ii; ii++)
326    gtk_widget_set_sensitive(widgets[ii],
327      gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
328}
329
330static void
331freedata(gpointer gdata, GClosure *closure SHUTUP) {
332  struct prefdata *data = gdata;
333
334  g_object_unref(G_OBJECT(data->back));
335  g_free(data);
336}
337
338static void
339clickdialog(GtkWidget *widget, int resp, gpointer gdata) {
340  struct prefdata *data = gdata;
341  char *errstr;
342  GList *ii;
343
344  if(GTK_RESPONSE_APPLY == resp || GTK_RESPONSE_OK == resp) {
345    /* save all the prefs */
346    for(ii = g_list_first(data->prefwidgets); NULL != ii; ii = ii->next)
347      saveprefwidget(data->parent, ii->data);
348
349    /* write prefs to disk */
350    cf_saveprefs(&errstr);
351    if(NULL != errstr) {
352      errmsg(data->parent, "%s", errstr);
353      g_free(errstr);
354    }
355
356    /* XXX would be nice to have errno strings, are they printed to stdout? */
357
358    tr_setBindPort(tr_backend_handle(data->back),
359                   strtol(cf_getpref(PREF_PORT), NULL, 10));
360    setlimit(data->back);
361  }
362
363  if(GTK_RESPONSE_APPLY != resp)
364    gtk_widget_destroy(widget);
365}
366
367void
368setlimit(TrBackend *back) {
369  struct { void (*func)(tr_handle_t*, int);
370    const char *use; const char *num; gboolean defuse; long def; } lim[] = {
371    {tr_setDownloadLimit, PREF_USEDOWNLIMIT, PREF_DOWNLIMIT,
372                          DEF_USEDOWNLIMIT,  DEF_DOWNLIMIT},
373    {tr_setUploadLimit,   PREF_USEUPLIMIT,   PREF_UPLIMIT,
374                          DEF_USEUPLIMIT,    DEF_UPLIMIT},
375  };
376  const char *pref;
377  unsigned int ii;
378  tr_handle_t *tr = tr_backend_handle(back);
379
380  for(ii = 0; ii < ALEN(lim); ii++) {
381    pref = cf_getpref(lim[ii].use);
382    if(!(NULL == pref ? lim[ii].defuse : strbool(pref)))
383      lim[ii].func(tr, -1);
384    else {
385      pref = cf_getpref(lim[ii].num);
386      lim[ii].func(tr, (NULL == pref ? lim[ii].def : strtol(pref, NULL, 10)));
387    }
388  }
389}
390
391void
392makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata) {
393  GtkWidget *wind = gtk_file_chooser_dialog_new(_("Add a Torrent"), parent,
394    GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
395    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
396  struct addcb *data = g_new(struct addcb, 1);
397  GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
398  GtkWidget *bbox = gtk_hbutton_box_new();
399  GtkWidget *autocheck = gtk_check_button_new_with_mnemonic(
400    _("Automatically _start torrent"));
401  GtkWidget *dircheck = gtk_check_button_new_with_mnemonic(
402    _("Use alternate _download directory"));
403  GtkFileFilter *filter = gtk_file_filter_new();
404  GtkFileFilter *unfilter = gtk_file_filter_new();
405  GtkWidget *getdir = gtk_file_chooser_button_new(
406    _("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
407  const char *pref;
408
409  data->addfunc = addfunc;
410  data->parent = parent;
411  data->data = cbdata;
412  data->autostart = TRUE;
413  data->usingaltdir = FALSE;
414  data->altdir = GTK_FILE_CHOOSER(getdir);
415  data->altbox = GTK_BUTTON_BOX(bbox);
416
417  gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_EDGE);
418  gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
419  gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
420
421  gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
422  gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
423
424  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
425  if(NULL != (pref = cf_getpref(PREF_DIR)))
426    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getdir), pref);
427
428  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
429  gtk_widget_set_sensitive(getdir, FALSE);
430
431  gtk_file_filter_set_name(filter, _("Torrent files"));
432  gtk_file_filter_add_pattern(filter, "*.torrent");
433  gtk_file_filter_set_name(unfilter, _("All files"));
434  gtk_file_filter_add_pattern(unfilter, "*");
435
436  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
437  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
438  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
439  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
440
441  g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
442  g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
443  g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
444
445  gtk_widget_show_all(wind);
446}
447
448static void
449autoclick(GtkWidget *widget, gpointer gdata) {
450  struct addcb *data = gdata;
451
452  data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
453}
454
455static void
456dirclick(GtkWidget *widget, gpointer gdata) {
457  struct addcb *data = gdata;
458
459  data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
460  gtk_widget_set_sensitive(GTK_WIDGET(data->altdir), data->usingaltdir);
461}
462
463static void
464addresp(GtkWidget *widget, gint resp, gpointer gdata) {
465  struct addcb *data = gdata;
466  GSList *files, *ii;
467  GList *stupidgtk;
468  gboolean paused;
469  char *dir;
470
471  if(GTK_RESPONSE_ACCEPT == resp) {
472    dir = NULL;
473    if(data->usingaltdir)
474      dir = gtk_file_chooser_get_filename(data->altdir);
475    files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
476    stupidgtk = NULL;
477    for(ii = files; NULL != ii; ii = ii->next)
478      stupidgtk = g_list_append(stupidgtk, ii->data);
479    paused = !data->autostart;
480    data->addfunc(data->data, NULL, stupidgtk, dir,
481                  addactionflag(cf_getpref(PREF_ADDSTD)));
482    if(NULL != dir)
483      g_free(dir);
484    g_slist_free(files);
485    freestrlist(stupidgtk);
486  }
487
488  gtk_widget_destroy(widget);
489}
490
491#define INFOLINE(tab, ii, nam, val) \
492  do { \
493    char *txt = g_markup_printf_escaped("<b>%s</b>", nam); \
494    GtkWidget *wid = gtk_label_new(NULL); \
495    gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
496    gtk_label_set_markup(GTK_LABEL(wid), txt); \
497    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 1, ii, ii + 1); \
498    wid = gtk_label_new(val); \
499    gtk_label_set_selectable(GTK_LABEL(wid), TRUE); \
500    gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
501    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 1, 2, ii, ii + 1); \
502    ii++; \
503    g_free(txt); \
504  } while(0)
505
506#define INFOLINEF(tab, ii, fmt, nam, val) \
507  do { \
508    char *buf = g_strdup_printf(fmt, val); \
509    INFOLINE(tab, ii, nam, buf); \
510    g_free(buf); \
511  } while(0)
512
513#define INFOLINEA(tab, ii, nam, val) \
514  do { \
515    char *buf = val; \
516    INFOLINE(tab, ii, nam, buf); \
517    g_free(buf); \
518  } while(0)
519
520#define INFOSEP(tab, ii) \
521  do { \
522    GtkWidget *wid = gtk_hseparator_new(); \
523    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 2, ii, ii + 1); \
524    ii++; \
525  } while(0)
526
527void
528makeinfowind(GtkWindow *parent, TrTorrent *tor) {
529  tr_stat_t *sb;
530  tr_info_t *in;
531  GtkWidget *wind, *label;
532  int ii;
533  char *str;
534  const int rowcount = 14;
535  GtkWidget *table = gtk_table_new(rowcount, 2, FALSE);
536
537  /* XXX should use model and update this window regularly */
538
539  sb = tr_torrent_stat(tor);
540  in = tr_torrent_info(tor);
541  str = g_strdup_printf(_("%s Properties"), in->name);
542  wind = gtk_dialog_new_with_buttons(str, parent,
543    GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
544    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
545  g_free(str);
546
547  gtk_widget_set_name(wind, "TransmissionDialog");
548  gtk_table_set_col_spacings(GTK_TABLE(table), 12);
549  gtk_table_set_row_spacings(GTK_TABLE(table), 12);
550  gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_ACCEPT);
551  gtk_container_set_border_width(GTK_CONTAINER(table), 6);
552  gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
553
554  label = gtk_label_new(NULL);
555  gtk_label_set_selectable(GTK_LABEL(label), TRUE);
556  str = g_markup_printf_escaped("<big>%s</big>", in->name);
557  gtk_label_set_markup(GTK_LABEL(label), str);
558  g_free(str);
559  gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 0, 1);
560
561  ii = 1;
562
563  INFOSEP(table, ii);
564
565  if(80 == in->trackerPort)
566    INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s",
567              in->trackerAddress));
568  else
569    INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s:%i",
570              in->trackerAddress, in->trackerPort));
571  INFOLINE(table, ii, _("Announce:"), in->trackerAnnounce);
572  INFOLINEA(table, ii, _("Piece Size:"), readablesize(in->pieceSize));
573  INFOLINEF(table, ii, "%i", _("Pieces:"), in->pieceCount);
574  INFOLINEA(table, ii, _("Total Size:"), readablesize(in->totalSize));
575  if(0 > sb->seeders)
576    INFOLINE(table, ii, _("Seeders:"), _("?"));
577  else
578    INFOLINEF(table, ii, "%i", _("Seeders:"), sb->seeders);
579  if(0 > sb->leechers)
580    INFOLINE(table, ii, _("Leechers:"), _("?"));
581  else
582    INFOLINEF(table, ii, "%i", _("Leechers:"), sb->leechers);
583
584  INFOSEP(table, ii);
585
586  INFOLINE(table, ii, _("Directory:"), tr_torrentGetFolder(tr_torrent_handle(tor)));
587  INFOLINEA(table, ii, _("Downloaded:"), readablesize(sb->downloaded));
588  INFOLINEA(table, ii, _("Uploaded:"), readablesize(sb->uploaded));
589
590  INFOSEP(table, ii);
591
592  g_assert(rowcount == ii);
593
594  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
595  g_signal_connect(G_OBJECT(wind), "response",
596                   G_CALLBACK(gtk_widget_destroy), NULL);
597  gtk_widget_show_all(wind);
598}
Note: See TracBrowser for help on using the repository browser.