source: trunk/gtk/prefs.c @ 18

Last change on this file since 18 was 18, checked in by root, 16 years ago

Update 2005-12-19

File size: 10.5 KB
Line 
1/*
2  Copyright (c) 2005 Joshua Elsasser. All rights reserved.
3   
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions
6  are met:
7   
8   1. Redistributions of source code must retain the above copyright
9      notice, this list of conditions and the following disclaimer.
10   2. Redistributions in binary form must reproduce the above copyright
11      notice, this list of conditions and the following disclaimer in the
12      documentation and/or other materials provided with the distribution.
13   
14  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND
15  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  POSSIBILITY OF SUCH DAMAGE.
25*/
26
27#include <errno.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include <gtk/gtk.h>
32
33#include "conf.h"
34#include "prefs.h"
35#include "transmission.h"
36#include "util.h"
37
38struct prefdata {
39  GtkSpinButton *port;
40  GtkCheckButton *uselimit;
41  GtkSpinButton *limit;
42  GtkEntry *dir;
43  GtkWindow *parent;
44  tr_handle_t *tr;
45};
46
47struct addcb {
48  add_torrent_func_t addfunc;
49  GtkWindow *parent;
50  tr_handle_t *tr;
51  torrents_added_func_t donefunc;
52  void *donedata;
53  gboolean autostart;
54  gboolean usingaltdir;
55  GtkFileChooser *altdir;
56  GtkButtonBox *altbox;
57};
58
59static void
60clicklimitbox(GtkWidget *widget, gpointer gdata);
61static void
62clickdialog(GtkWidget *widget, int resp, gpointer gdata);
63static void
64autoclick(GtkWidget *widget, gpointer gdata);
65static void
66dirclick(GtkWidget *widget, gpointer gdata);
67static void
68addresp(GtkWidget *widget, gint resp, gpointer gdata);
69
70void
71makeprefwindow(GtkWindow *parent, tr_handle_t *tr) {
72  GtkWidget *wind = gtk_dialog_new_with_buttons("Preferences", parent,
73    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK,
74    GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
75  GtkWidget *table = gtk_table_new(4, 2, FALSE);
76  GtkWidget *portnum = gtk_spin_button_new_with_range(1, 0xffff, 1);
77  GtkWidget *limitbox = gtk_check_button_new_with_label("Limit upload speed");
78  GtkWidget *limitnum = gtk_spin_button_new_with_range(0, G_MAXLONG, 1);
79  GtkWidget *dirstr = gtk_entry_new();
80  GtkWidget *label;
81  const char *pref;
82  struct prefdata *data = g_new0(struct prefdata, 1);
83
84  data->port = GTK_SPIN_BUTTON(portnum);
85  data->uselimit = GTK_CHECK_BUTTON(limitbox);
86  data->limit = GTK_SPIN_BUTTON(limitnum);
87  data->dir = GTK_ENTRY(dirstr);
88  data->parent = parent;
89  data->tr = tr;
90
91  /* port label and entry */
92  label = gtk_label_new("Listening port");
93  if(NULL != (pref = cf_getpref(PREF_PORT)))
94    gtk_spin_button_set_value(GTK_SPIN_BUTTON(portnum), strtol(pref,NULL,10));
95  else
96    gtk_spin_button_set_value(GTK_SPIN_BUTTON(portnum), TR_DEFAULT_PORT);
97  gtk_table_attach_defaults(GTK_TABLE(table), label,            0, 1, 0, 1);
98  gtk_table_attach_defaults(GTK_TABLE(table), portnum,          1, 2, 0, 1);
99
100  /* limit checkbox */
101  pref = cf_getpref(PREF_USELIMIT);
102  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(limitbox),
103    (NULL == pref ? TRUE : strbool(pref)));
104  gtk_widget_set_sensitive(limitnum,
105    gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(limitbox)));
106  g_signal_connect(G_OBJECT(limitbox), "clicked",
107                   G_CALLBACK(clicklimitbox), limitnum);
108  gtk_table_attach_defaults(GTK_TABLE(table), limitbox,         0, 2, 1, 2);
109
110  /* limit label and entry */
111  label = gtk_label_new("Maximum upload speed");
112  pref = cf_getpref(PREF_LIMIT);
113  gtk_spin_button_set_value(GTK_SPIN_BUTTON(limitnum),
114    (NULL == pref ? DEFAULT_UPLIMIT : strtol(pref,NULL,10)));
115  gtk_table_attach_defaults(GTK_TABLE(table), label,            0, 1, 2, 3);
116  gtk_table_attach_defaults(GTK_TABLE(table), limitnum,         1, 2, 2, 3);
117
118  /* directory label and entry */
119  label = gtk_label_new("Download directory");
120  if(NULL != (pref = cf_getpref(PREF_DIR)))
121    gtk_entry_set_text(GTK_ENTRY(dirstr), pref);
122  gtk_table_attach_defaults(GTK_TABLE(table), label,            0, 1, 3, 4);
123  gtk_table_attach_defaults(GTK_TABLE(table), dirstr,           1, 2, 3, 4);
124
125  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
126  g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(clickdialog), data);
127  gtk_widget_show_all(wind);
128}
129
130static void
131clicklimitbox(GtkWidget *widget, gpointer gdata) {
132  GtkWidget *entry = gdata;
133
134  gtk_widget_set_sensitive(entry,
135    gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
136}
137
138static void
139clickdialog(GtkWidget *widget, int resp, gpointer gdata) {
140  struct prefdata *data = gdata;
141  int intval;
142  const char *strval;
143  char *strnum, *errstr;
144  gboolean boolval;
145
146  if(GTK_RESPONSE_OK == resp) {
147    /* check directory */
148    strval = gtk_entry_get_text(data->dir);
149    if('\0' != strval[0] &&!mkdir_p(strval, 0777)) {
150      errmsg(data->parent, "Failed to create directory %s:\n%s",
151             strval, strerror(errno));
152      return;
153    }
154
155    /* save dir pref */
156    cf_setpref(PREF_DIR, gtk_entry_get_text(data->dir), NULL);
157
158    /* save port pref */
159    strnum = g_strdup_printf("%i",
160      gtk_spin_button_get_value_as_int(data->port));
161    cf_setpref(PREF_PORT, strnum, NULL);
162    g_free(strnum);
163    /* XXX should I change the port here?  is it even possible? */
164
165    /* save uselimit pref */
166    boolval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->uselimit));
167    cf_setpref(PREF_USELIMIT, (boolval ? "yes" : "no"), NULL);
168
169    /* save limit pref */
170    intval = gtk_spin_button_get_value_as_int(data->limit);
171    strnum = g_strdup_printf("%i", intval);
172    /*
173      note that prefs aren't written to disk unless we pass a pointer
174      to an error string, so do this for the last call to cf_setpref()
175    */
176    if(!cf_setpref(PREF_LIMIT, strnum, &errstr)) {
177      errmsg(data->parent, "%s", errstr);
178      g_free(strnum);
179      g_free(errstr);
180    }
181
182    setlimit(data->tr);
183  }
184
185  gtk_widget_destroy(widget);
186  g_free(data);
187}
188
189void
190setlimit(tr_handle_t *tr) {
191  const char *pref;
192
193  if(NULL != (pref = cf_getpref(PREF_USELIMIT)) && !strbool(pref))
194    tr_setUploadLimit(tr, -1);
195  else if(NULL != (pref = cf_getpref(PREF_LIMIT)))
196    tr_setUploadLimit(tr, strtol(pref, NULL, 10));
197  else
198    tr_setUploadLimit(tr, DEFAULT_UPLIMIT);
199}
200
201void
202makeaddwind(add_torrent_func_t addfunc, GtkWindow *parent, tr_handle_t *tr,
203            torrents_added_func_t donefunc, void *donedata) {
204  GtkWidget *wind = gtk_file_chooser_dialog_new("Add a Torrent", parent,
205    GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
206    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
207  struct addcb *data = g_new(struct addcb, 1);
208  GtkWidget *vbox = gtk_vbox_new(FALSE, 5);
209  GtkWidget *bbox = gtk_hbutton_box_new();
210  GtkWidget *autocheck = gtk_check_button_new_with_label(
211    "Automatically start torrent");
212  GtkWidget *dircheck = gtk_check_button_new_with_label(
213    "Use alternate download directory");
214  GtkFileFilter *filter = gtk_file_filter_new();
215  GtkFileFilter *unfilter = gtk_file_filter_new();
216  GtkWidget *getdir = gtk_file_chooser_button_new(
217    "Choose a download directory", GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
218  const char *pref;
219
220  data->addfunc = addfunc;
221  data->parent = parent;
222  data->tr = tr;
223  data->donefunc = donefunc;
224  data->donedata = donedata;
225  data->autostart = TRUE;
226  data->usingaltdir = FALSE;
227  data->altdir = GTK_FILE_CHOOSER(getdir);
228  data->altbox = GTK_BUTTON_BOX(bbox);
229
230  gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
231  gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
232  gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
233
234  gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
235  gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
236
237  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
238  if(NULL != (pref = cf_getpref(PREF_DIR)))
239    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getdir), pref);
240  else {
241    pref = g_get_current_dir();
242    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(getdir), pref);
243    g_free((char*)pref);
244  }
245
246  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
247
248  gtk_file_filter_set_name(filter, "Torrent files");
249  gtk_file_filter_add_pattern(filter, "*.torrent");
250  gtk_file_filter_set_name(unfilter, "All files");
251  gtk_file_filter_add_pattern(unfilter, "*");
252
253  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
254  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
255  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
256  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
257
258  g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
259  g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
260  g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
261
262  gtk_widget_show_all(wind);
263  gtk_widget_hide(getdir);
264}
265
266static void
267autoclick(GtkWidget *widget, gpointer gdata) {
268  struct addcb *data = gdata;
269
270  data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
271}
272
273static void
274dirclick(GtkWidget *widget, gpointer gdata) {
275  struct addcb *data = gdata;
276
277  data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
278  gtk_button_box_set_layout(data->altbox,
279    (data->usingaltdir ? GTK_BUTTONBOX_EDGE : GTK_BUTTONBOX_START));
280  if(data->usingaltdir)
281    gtk_widget_show(GTK_WIDGET(data->altdir));
282  else
283    gtk_widget_hide(GTK_WIDGET(data->altdir));
284}
285
286static void
287addresp(GtkWidget *widget, gint resp, gpointer gdata) {
288  struct addcb *data = gdata;
289  GSList *files, *ii;
290  gboolean added = FALSE;
291  char *dir = NULL;
292
293  if(GTK_RESPONSE_ACCEPT == resp) {
294    if(data->usingaltdir)
295      dir = gtk_file_chooser_get_filename(data->altdir);
296    files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
297    for(ii = files; NULL != ii; ii = ii->next)
298      if(data->addfunc(data->tr, data->parent, ii->data, dir,
299                       !data->autostart))
300        added = TRUE;
301    if(added)
302      data->donefunc(data->donedata);
303    if(NULL != dir)
304      g_free(dir);
305  }
306
307  gtk_widget_destroy(widget);
308}
Note: See TracBrowser for help on using the repository browser.