Shared folders support with a GUI.
[claws.git] / src / grouplistdialog.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2001 Hiroyuki Yamamoto
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <gdk/gdkkeysyms.h>
28 #include <gtk/gtkmain.h>
29 #include <gtk/gtkwidget.h>
30 #include <gtk/gtkdialog.h>
31 #include <gtk/gtkwindow.h>
32 #include <gtk/gtksignal.h>
33 #include <gtk/gtkvbox.h>
34 #include <gtk/gtkhbox.h>
35 #include <gtk/gtklabel.h>
36 #include <gtk/gtkentry.h>
37 #include <gtk/gtkclist.h>
38 #include <gtk/gtkscrolledwindow.h>
39 #include <gtk/gtkbutton.h>
40 #include <gtk/gtkhbbox.h>
41
42 #include "intl.h"
43 #include "grouplistdialog.h"
44 #include "manage_window.h"
45 #include "gtkutils.h"
46 #include "utils.h"
47 #include "news.h"
48 #include "folder.h"
49 #include "alertpanel.h"
50 #include "recv.h"
51 #include "socket.h"
52
53 #define GROUPLIST_DIALOG_WIDTH  420
54 #define GROUPLIST_DIALOG_HEIGHT 400
55
56 static gboolean ack;
57 static gboolean locked;
58
59 static GtkWidget *dialog;
60 static GtkWidget *entry;
61 static GtkWidget *clist;
62 static GtkWidget *status_label;
63 static GtkWidget *ok_button;
64 static GSList *group_list;
65 static Folder *news_folder;
66
67 static void grouplist_dialog_create     (void);
68 static void grouplist_dialog_set_list   (void);
69 static void grouplist_clear             (void);
70 static void grouplist_recv_func         (SockInfo       *sock,
71                                          gint            count,
72                                          gint            read_bytes,
73                                          gpointer        data);
74
75 static void ok_clicked          (GtkWidget      *widget,
76                                  gpointer        data);
77 static void cancel_clicked      (GtkWidget      *widget,
78                                  gpointer        data);
79 static void refresh_clicked     (GtkWidget      *widget,
80                                  gpointer        data);
81 static void key_pressed         (GtkWidget      *widget,
82                                  GdkEventKey    *event,
83                                  gpointer        data);
84 static void clist_selected      (GtkCList       *clist,
85                                  gint            row,
86                                  gint            column,
87                                  GdkEventButton *event,
88                                  gpointer        user_data);
89 static void entry_activated     (GtkEditable    *editable);
90
91 gchar *grouplist_dialog(Folder *folder)
92 {
93         gchar *str;
94
95         if (dialog && GTK_WIDGET_VISIBLE(dialog)) return NULL;
96
97         if (!dialog)
98                 grouplist_dialog_create();
99
100         news_folder = folder;
101
102         gtk_widget_show(dialog);
103         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
104         manage_window_set_transient(GTK_WINDOW(dialog));
105         GTK_EVENTS_FLUSH();
106
107         grouplist_dialog_set_list();
108
109         gtk_main();
110
111         manage_window_focus_out(dialog, NULL, NULL);
112         gtk_widget_hide(dialog);
113
114         if (ack) {
115                 str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
116                 if (str && *str == '\0') {
117                         g_free(str);
118                         str = NULL;
119                 }
120         } else
121                 str = NULL;
122
123         grouplist_clear();
124         GTK_EVENTS_FLUSH();
125
126         debug_print("return string = %s\n", str ? str : "(none)");
127         return str;
128 }
129
130 static void grouplist_clear(void)
131 {
132         gtk_clist_clear(GTK_CLIST(clist));
133         gtk_entry_set_text(GTK_ENTRY(entry), "");
134         slist_free_strings(group_list);
135         g_slist_free(group_list);
136 }
137
138 static void grouplist_dialog_create(void)
139 {
140         GtkWidget *vbox;
141         GtkWidget *hbox;
142         GtkWidget *msg_label;
143         GtkWidget *confirm_area;
144         GtkWidget *cancel_button;       
145         GtkWidget *refresh_button;      
146         GtkWidget *scrolledwin;
147
148         dialog = gtk_dialog_new();
149         gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, TRUE, FALSE);
150         gtk_widget_set_usize(dialog,
151                              GROUPLIST_DIALOG_WIDTH, GROUPLIST_DIALOG_HEIGHT);
152         gtk_container_set_border_width
153                 (GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 5);
154         gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
155         gtk_window_set_title(GTK_WINDOW(dialog), _("Subscribe to newsgroup"));
156         gtk_signal_connect(GTK_OBJECT(dialog), "delete_event",
157                            GTK_SIGNAL_FUNC(cancel_clicked), NULL);
158         gtk_signal_connect(GTK_OBJECT(dialog), "key_press_event",
159                            GTK_SIGNAL_FUNC(key_pressed), NULL);
160         gtk_signal_connect(GTK_OBJECT(dialog), "focus_in_event",
161                            GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
162         gtk_signal_connect(GTK_OBJECT(dialog), "focus_out_event",
163                            GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
164
165         gtk_widget_realize(dialog);
166
167         vbox = gtk_vbox_new(FALSE, 8);
168         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
169         gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
170
171         hbox = gtk_hbox_new(FALSE, 0);
172         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
173
174         msg_label = gtk_label_new(_("Input subscribing newsgroup:"));
175         gtk_box_pack_start(GTK_BOX(hbox), msg_label, FALSE, FALSE, 0);
176
177         entry = gtk_entry_new();
178         gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
179         gtk_signal_connect(GTK_OBJECT(entry), "activate",
180                            GTK_SIGNAL_FUNC(entry_activated), NULL);
181
182         scrolledwin = gtk_scrolled_window_new(NULL, NULL);
183         gtk_box_pack_start(GTK_BOX (vbox), scrolledwin, TRUE, TRUE, 0);
184         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolledwin),
185                                        GTK_POLICY_AUTOMATIC,
186                                        GTK_POLICY_AUTOMATIC);
187
188         clist = gtk_clist_new(1);
189         gtk_container_add(GTK_CONTAINER(scrolledwin), clist);
190         gtk_clist_set_column_width(GTK_CLIST(clist), 0, 80);
191         gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
192         GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[0].button,
193                                GTK_CAN_FOCUS);
194         gtk_signal_connect(GTK_OBJECT(clist), "select_row",
195                            GTK_SIGNAL_FUNC(clist_selected), NULL);
196
197         hbox = gtk_hbox_new(FALSE, 0);
198         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
199
200         status_label = gtk_label_new("");
201         gtk_box_pack_start(GTK_BOX(hbox), status_label, FALSE, FALSE, 0);
202
203         gtkut_button_set_create(&confirm_area,
204                                 &ok_button,      _("OK"),
205                                 &cancel_button,  _("Cancel"),
206                                 &refresh_button, _("Refresh"));
207         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
208                           confirm_area);
209         gtk_widget_grab_default(ok_button);
210
211         gtk_signal_connect(GTK_OBJECT(ok_button), "clicked",
212                            GTK_SIGNAL_FUNC(ok_clicked), NULL);
213         gtk_signal_connect(GTK_OBJECT(cancel_button), "clicked",
214                            GTK_SIGNAL_FUNC(cancel_clicked), NULL);
215         gtk_signal_connect(GTK_OBJECT(refresh_button), "clicked",
216                            GTK_SIGNAL_FUNC(refresh_clicked), NULL);
217
218         gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
219 }
220
221 static void grouplist_dialog_set_list(void)
222 {
223         GSList *cur;
224         gint row;
225
226         if (locked) return;
227         locked = TRUE;
228
229         recv_set_ui_func(grouplist_recv_func, NULL);
230         group_list = news_get_group_list(news_folder);
231         recv_set_ui_func(NULL, NULL);
232         if (group_list == NULL) {
233                 alertpanel_error(_("Can't retrieve newsgroup list."));
234                 locked = FALSE;
235                 return;
236         }
237
238         gtk_clist_freeze(GTK_CLIST(clist));
239         for (cur = group_list; cur != NULL ; cur = cur->next) {
240                 row = gtk_clist_append(GTK_CLIST(clist),
241                                        (gchar **)&(cur->data));
242                 gtk_clist_set_row_data(GTK_CLIST(clist), row, cur->data);
243         }
244         gtk_clist_thaw(GTK_CLIST(clist));
245
246         gtk_widget_grab_focus(ok_button);
247         gtk_widget_grab_focus(clist);
248
249         gtk_label_set_text(GTK_LABEL(status_label), _("Done."));
250
251         locked = FALSE;
252 }
253
254 static void grouplist_recv_func(SockInfo *sock, gint count, gint read_bytes,
255                                 gpointer data)
256 {
257         gchar buf[BUFFSIZE];
258
259         g_snprintf(buf, sizeof(buf),
260                    _("%d newsgroups received (%s read)"),
261                    count, to_human_readable(read_bytes));
262         gtk_label_set_text(GTK_LABEL(status_label), buf);
263         GTK_EVENTS_FLUSH();
264 }
265
266 static void ok_clicked(GtkWidget *widget, gpointer data)
267 {
268         ack = TRUE;
269         if (gtk_main_level() > 1)
270                 gtk_main_quit();
271 }
272
273 static void cancel_clicked(GtkWidget *widget, gpointer data)
274 {
275         ack = FALSE;
276         if (gtk_main_level() > 1)
277                 gtk_main_quit();
278 }
279
280 static void refresh_clicked(GtkWidget *widget, gpointer data)
281
282         if (locked) return;
283
284         grouplist_clear();
285         news_remove_group_list(news_folder);
286         grouplist_dialog_set_list();
287 }
288
289 static void key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
290 {
291         if (event && event->keyval == GDK_Escape)
292                 cancel_clicked(NULL, NULL);
293 }
294
295 static void clist_selected(GtkCList *clist, gint row, gint column,
296                            GdkEventButton *event, gpointer user_data)
297 {
298         gchar *group;
299
300         group = (gchar *)gtk_clist_get_row_data(GTK_CLIST(clist), row);
301         gtk_entry_set_text(GTK_ENTRY(entry), group ? group : "");
302 }
303
304 static void entry_activated(GtkEditable *editable)
305 {
306         ok_clicked(NULL, NULL);
307 }