Statistics
| Revision:

root / src / grouplistdialog.c @ 333

History | View | Annotate | Download (15.1 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 31 hiro
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 1 hiro
 *
5 1 hiro
 * This program is free software; you can redistribute it and/or modify
6 1 hiro
 * it under the terms of the GNU General Public License as published by
7 1 hiro
 * the Free Software Foundation; either version 2 of the License, or
8 1 hiro
 * (at your option) any later version.
9 1 hiro
 *
10 1 hiro
 * This program is distributed in the hope that it will be useful,
11 1 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 1 hiro
 * GNU General Public License for more details.
14 1 hiro
 *
15 1 hiro
 * You should have received a copy of the GNU General Public License
16 1 hiro
 * along with this program; if not, write to the Free Software
17 1 hiro
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 1 hiro
 */
19 1 hiro
20 1 hiro
#ifdef HAVE_CONFIG_H
21 1 hiro
#  include "config.h"
22 1 hiro
#endif
23 1 hiro
24 1 hiro
#include "defs.h"
25 1 hiro
26 1 hiro
#include <glib.h>
27 92 hiro
#include <glib/gi18n.h>
28 1 hiro
#include <gdk/gdkkeysyms.h>
29 1 hiro
#include <gtk/gtkmain.h>
30 1 hiro
#include <gtk/gtkwidget.h>
31 1 hiro
#include <gtk/gtkdialog.h>
32 1 hiro
#include <gtk/gtkwindow.h>
33 1 hiro
#include <gtk/gtksignal.h>
34 1 hiro
#include <gtk/gtkvbox.h>
35 1 hiro
#include <gtk/gtkhbox.h>
36 1 hiro
#include <gtk/gtklabel.h>
37 1 hiro
#include <gtk/gtkentry.h>
38 1 hiro
#include <gtk/gtkctree.h>
39 1 hiro
#include <gtk/gtkscrolledwindow.h>
40 1 hiro
#include <gtk/gtkbutton.h>
41 1 hiro
#include <gtk/gtkhbbox.h>
42 31 hiro
#include <gtk/gtkstock.h>
43 1 hiro
#include <string.h>
44 1 hiro
45 1 hiro
#include "grouplistdialog.h"
46 1 hiro
#include "manage_window.h"
47 1 hiro
#include "gtkutils.h"
48 1 hiro
#include "utils.h"
49 1 hiro
#include "news.h"
50 1 hiro
#include "folder.h"
51 1 hiro
#include "alertpanel.h"
52 1 hiro
#include "recv.h"
53 1 hiro
#include "socket.h"
54 1 hiro
55 1 hiro
#define GROUPLIST_DIALOG_WIDTH                450
56 1 hiro
#define GROUPLIST_DIALOG_HEIGHT                400
57 1 hiro
#define GROUPLIST_COL_NAME_WIDTH        250
58 1 hiro
59 1 hiro
static gboolean ack;
60 1 hiro
static gboolean locked;
61 1 hiro
62 1 hiro
static GtkWidget *dialog;
63 1 hiro
static GtkWidget *entry;
64 1 hiro
static GtkWidget *ctree;
65 1 hiro
static GtkWidget *status_label;
66 1 hiro
static GtkWidget *ok_button;
67 1 hiro
static GSList *group_list;
68 1 hiro
static Folder *news_folder;
69 1 hiro
70 1 hiro
static GSList *subscribed;
71 1 hiro
72 1 hiro
static void grouplist_dialog_create        (void);
73 1 hiro
static void grouplist_dialog_set_list        (const gchar        *pattern,
74 1 hiro
                                         gboolean         refresh);
75 1 hiro
static void grouplist_search                (void);
76 1 hiro
static void grouplist_clear                (void);
77 1 hiro
static gboolean grouplist_recv_func        (SockInfo        *sock,
78 1 hiro
                                         gint                 count,
79 1 hiro
                                         gint                 read_bytes,
80 1 hiro
                                         gpointer         data);
81 1 hiro
82 1 hiro
static gint window_deleted        (GtkWidget        *widget,
83 1 hiro
                                 GdkEventAny        *event,
84 1 hiro
                                 gpointer         data);
85 1 hiro
static void ok_clicked                (GtkWidget        *widget,
86 1 hiro
                                 gpointer         data);
87 1 hiro
static void cancel_clicked        (GtkWidget        *widget,
88 1 hiro
                                 gpointer         data);
89 1 hiro
static void refresh_clicked        (GtkWidget        *widget,
90 1 hiro
                                 gpointer         data);
91 1 hiro
static gboolean key_pressed        (GtkWidget        *widget,
92 1 hiro
                                 GdkEventKey        *event,
93 1 hiro
                                 gpointer         data);
94 1 hiro
static void ctree_selected        (GtkCTree        *ctree,
95 1 hiro
                                 GtkCTreeNode        *node,
96 1 hiro
                                 gint                 column,
97 1 hiro
                                 gpointer         data);
98 1 hiro
static void ctree_unselected        (GtkCTree        *ctree,
99 1 hiro
                                 GtkCTreeNode        *node,
100 1 hiro
                                 gint                 column,
101 1 hiro
                                 gpointer         data);
102 1 hiro
static void entry_activated        (GtkEditable        *editable);
103 1 hiro
static void search_clicked        (GtkWidget        *widget,
104 1 hiro
                                 gpointer         data);
105 1 hiro
106 1 hiro
GSList *grouplist_dialog(Folder *folder)
107 1 hiro
{
108 1 hiro
        GNode *node;
109 1 hiro
        FolderItem *item;
110 1 hiro
111 1 hiro
        if (dialog && GTK_WIDGET_VISIBLE(dialog)) return NULL;
112 1 hiro
113 1 hiro
        if (!dialog)
114 1 hiro
                grouplist_dialog_create();
115 1 hiro
116 1 hiro
        news_folder = folder;
117 1 hiro
118 1 hiro
        gtk_widget_show(dialog);
119 1 hiro
        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
120 1 hiro
        manage_window_set_transient(GTK_WINDOW(dialog));
121 1 hiro
        gtk_widget_grab_focus(ok_button);
122 1 hiro
        gtk_widget_grab_focus(ctree);
123 1 hiro
        GTK_EVENTS_FLUSH();
124 1 hiro
125 1 hiro
        subscribed = NULL;
126 1 hiro
        for (node = folder->node->children; node != NULL; node = node->next) {
127 1 hiro
                item = FOLDER_ITEM(node->data);
128 1 hiro
                subscribed = g_slist_append(subscribed, g_strdup(item->path));
129 1 hiro
        }
130 1 hiro
131 1 hiro
        grouplist_dialog_set_list(NULL, TRUE);
132 1 hiro
133 1 hiro
        if (ack) gtk_main();
134 1 hiro
135 1 hiro
        manage_window_focus_out(dialog, NULL, NULL);
136 1 hiro
        gtk_widget_hide(dialog);
137 1 hiro
138 1 hiro
        if (!ack) {
139 1 hiro
                slist_free_strings(subscribed);
140 1 hiro
                g_slist_free(subscribed);
141 1 hiro
                subscribed = NULL;
142 1 hiro
143 1 hiro
                for (node = folder->node->children; node != NULL;
144 1 hiro
                     node = node->next) {
145 1 hiro
                        item = FOLDER_ITEM(node->data);
146 1 hiro
                        subscribed = g_slist_append(subscribed,
147 1 hiro
                                                    g_strdup(item->path));
148 1 hiro
                }
149 1 hiro
        }
150 1 hiro
151 1 hiro
        grouplist_clear();
152 1 hiro
153 1 hiro
        return subscribed;
154 1 hiro
}
155 1 hiro
156 1 hiro
static void grouplist_dialog_create(void)
157 1 hiro
{
158 1 hiro
        GtkWidget *vbox;
159 1 hiro
        GtkWidget *hbox;
160 1 hiro
        GtkWidget *msg_label;
161 1 hiro
        GtkWidget *search_button;
162 1 hiro
        GtkWidget *confirm_area;
163 1 hiro
        GtkWidget *cancel_button;
164 1 hiro
        GtkWidget *refresh_button;
165 1 hiro
        GtkWidget *scrolledwin;
166 1 hiro
        gchar *titles[3];
167 1 hiro
        gint i;
168 1 hiro
169 1 hiro
        dialog = gtk_dialog_new();
170 1 hiro
        gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, TRUE, FALSE);
171 1 hiro
        gtk_widget_set_size_request(dialog,
172 1 hiro
                                    GROUPLIST_DIALOG_WIDTH,
173 1 hiro
                                    GROUPLIST_DIALOG_HEIGHT);
174 1 hiro
        gtk_container_set_border_width
175 1 hiro
                (GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 5);
176 1 hiro
        gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
177 1 hiro
        gtk_window_set_title(GTK_WINDOW(dialog), _("Subscribe to newsgroup"));
178 1 hiro
        g_signal_connect(G_OBJECT(dialog), "delete_event",
179 1 hiro
                         G_CALLBACK(window_deleted), NULL);
180 1 hiro
        g_signal_connect(G_OBJECT(dialog), "key_press_event",
181 1 hiro
                         G_CALLBACK(key_pressed), NULL);
182 1 hiro
        MANAGE_WINDOW_SIGNALS_CONNECT(dialog);
183 1 hiro
184 1 hiro
        gtk_widget_realize(dialog);
185 1 hiro
186 1 hiro
        vbox = gtk_vbox_new(FALSE, 8);
187 1 hiro
        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
188 1 hiro
        gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
189 1 hiro
190 1 hiro
        hbox = gtk_hbox_new(FALSE, 0);
191 1 hiro
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
192 1 hiro
193 1 hiro
        msg_label = gtk_label_new(_("Select newsgroups to subscribe."));
194 1 hiro
        gtk_box_pack_start(GTK_BOX(hbox), msg_label, FALSE, FALSE, 0);
195 1 hiro
196 1 hiro
        hbox = gtk_hbox_new(FALSE, 8);
197 1 hiro
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
198 1 hiro
199 1 hiro
        msg_label = gtk_label_new(_("Find groups:"));
200 1 hiro
        gtk_box_pack_start(GTK_BOX(hbox), msg_label, FALSE, FALSE, 0);
201 1 hiro
202 1 hiro
        entry = gtk_entry_new();
203 1 hiro
        gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
204 1 hiro
        g_signal_connect(G_OBJECT(entry), "activate",
205 1 hiro
                         G_CALLBACK(entry_activated), NULL);
206 1 hiro
207 1 hiro
        search_button = gtk_button_new_with_label(_(" Search "));
208 1 hiro
        gtk_box_pack_start(GTK_BOX(hbox), search_button, FALSE, FALSE, 0);
209 1 hiro
210 1 hiro
        g_signal_connect(G_OBJECT(search_button), "clicked",
211 1 hiro
                         G_CALLBACK(search_clicked), NULL);
212 1 hiro
213 1 hiro
        scrolledwin = gtk_scrolled_window_new(NULL, NULL);
214 1 hiro
        gtk_box_pack_start(GTK_BOX (vbox), scrolledwin, TRUE, TRUE, 0);
215 1 hiro
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolledwin),
216 1 hiro
                                       GTK_POLICY_AUTOMATIC,
217 1 hiro
                                       GTK_POLICY_AUTOMATIC);
218 1 hiro
219 1 hiro
        titles[0] = _("Newsgroup name");
220 1 hiro
        titles[1] = _("Messages");
221 1 hiro
        titles[2] = _("Type");
222 1 hiro
        ctree = gtk_ctree_new_with_titles(3, 0, titles);
223 1 hiro
        gtk_container_add(GTK_CONTAINER(scrolledwin), ctree);
224 1 hiro
        gtk_clist_set_column_width
225 1 hiro
                (GTK_CLIST(ctree), 0, GROUPLIST_COL_NAME_WIDTH);
226 1 hiro
        gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_MULTIPLE);
227 1 hiro
        gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
228 1 hiro
        gtk_ctree_set_expander_style(GTK_CTREE(ctree),
229 1 hiro
                                     GTK_CTREE_EXPANDER_SQUARE);
230 1 hiro
        for (i = 0; i < 3; i++)
231 1 hiro
                GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(ctree)->column[i].button,
232 1 hiro
                                       GTK_CAN_FOCUS);
233 1 hiro
        g_signal_connect(G_OBJECT(ctree), "tree_select_row",
234 1 hiro
                         G_CALLBACK(ctree_selected), NULL);
235 1 hiro
        g_signal_connect(G_OBJECT(ctree), "tree_unselect_row",
236 1 hiro
                         G_CALLBACK(ctree_unselected), NULL);
237 1 hiro
238 1 hiro
        hbox = gtk_hbox_new(FALSE, 0);
239 1 hiro
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
240 1 hiro
241 1 hiro
        status_label = gtk_label_new("");
242 1 hiro
        gtk_box_pack_start(GTK_BOX(hbox), status_label, FALSE, FALSE, 0);
243 1 hiro
244 31 hiro
        gtkut_stock_button_set_create(&confirm_area,
245 31 hiro
                                      &ok_button, GTK_STOCK_OK,
246 31 hiro
                                      &cancel_button, GTK_STOCK_CANCEL,
247 31 hiro
                                      &refresh_button, GTK_STOCK_REFRESH);
248 1 hiro
        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
249 1 hiro
                          confirm_area);
250 1 hiro
        gtk_widget_grab_default(ok_button);
251 1 hiro
252 1 hiro
        g_signal_connect(G_OBJECT(ok_button), "clicked",
253 1 hiro
                         G_CALLBACK(ok_clicked), NULL);
254 1 hiro
        g_signal_connect(G_OBJECT(cancel_button), "clicked",
255 1 hiro
                         G_CALLBACK(cancel_clicked), NULL);
256 1 hiro
        g_signal_connect(G_OBJECT(refresh_button), "clicked",
257 1 hiro
                         G_CALLBACK(refresh_clicked), NULL);
258 1 hiro
259 1 hiro
        gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
260 1 hiro
}
261 1 hiro
262 1 hiro
static GHashTable *branch_node_table;
263 1 hiro
264 1 hiro
static void grouplist_hash_init(void)
265 1 hiro
{
266 1 hiro
        branch_node_table = g_hash_table_new(g_str_hash, g_str_equal);
267 1 hiro
}
268 1 hiro
269 1 hiro
static void grouplist_hash_done(void)
270 1 hiro
{
271 1 hiro
        hash_free_strings(branch_node_table);
272 1 hiro
        g_hash_table_destroy(branch_node_table);
273 1 hiro
}
274 1 hiro
275 1 hiro
static GtkCTreeNode *grouplist_hash_get_branch_node(const gchar *name)
276 1 hiro
{
277 1 hiro
        return g_hash_table_lookup(branch_node_table, name);
278 1 hiro
}
279 1 hiro
280 1 hiro
static void grouplist_hash_set_branch_node(const gchar *name,
281 1 hiro
                                           GtkCTreeNode *node)
282 1 hiro
{
283 1 hiro
        g_hash_table_insert(branch_node_table, g_strdup(name), node);
284 1 hiro
}
285 1 hiro
286 1 hiro
static gchar *grouplist_get_parent_name(const gchar *name)
287 1 hiro
{
288 1 hiro
        gchar *p;
289 1 hiro
290 1 hiro
        p = strrchr(name, '.');
291 1 hiro
        if (!p)
292 1 hiro
                return g_strdup("");
293 1 hiro
        return g_strndup(name, p - name);
294 1 hiro
}
295 1 hiro
296 1 hiro
static GtkCTreeNode *grouplist_create_parent(const gchar *name,
297 1 hiro
                                             const gchar *pattern)
298 1 hiro
{
299 1 hiro
        GtkCTreeNode *parent;
300 1 hiro
        GtkCTreeNode *node;
301 1 hiro
        gchar *cols[3];
302 1 hiro
        gchar *parent_name;
303 1 hiro
304 1 hiro
        if (*name == '\0') return NULL;
305 1 hiro
        node = grouplist_hash_get_branch_node(name);
306 1 hiro
        if (node != NULL) return node;
307 1 hiro
308 1 hiro
        cols[0] = (gchar *)name;
309 1 hiro
        cols[1] = cols[2] = "";
310 1 hiro
311 1 hiro
        parent_name = grouplist_get_parent_name(name);
312 1 hiro
        parent = grouplist_create_parent(parent_name, pattern);
313 1 hiro
314 1 hiro
        node = parent ? GTK_CTREE_ROW(parent)->children
315 1 hiro
                : GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
316 1 hiro
        node = gtk_ctree_insert_node(GTK_CTREE(ctree), parent, node,
317 1 hiro
                                     cols, 0, NULL, NULL, NULL, NULL,
318 1 hiro
                                     FALSE, FALSE);
319 32 hiro
        if (parent && g_pattern_match_simple(pattern, parent_name) == FALSE)
320 1 hiro
                gtk_ctree_expand(GTK_CTREE(ctree), parent);
321 1 hiro
        gtk_ctree_node_set_selectable(GTK_CTREE(ctree), node, FALSE);
322 1 hiro
323 1 hiro
        grouplist_hash_set_branch_node(name, node);
324 1 hiro
325 1 hiro
        g_free(parent_name);
326 1 hiro
327 1 hiro
        return node;
328 1 hiro
}
329 1 hiro
330 1 hiro
static GtkCTreeNode *grouplist_create_branch(NewsGroupInfo *ginfo,
331 1 hiro
                                             const gchar *pattern)
332 1 hiro
{
333 1 hiro
        GtkCTreeNode *node;
334 1 hiro
        GtkCTreeNode *parent;
335 1 hiro
        gchar *name = (gchar *)ginfo->name;
336 1 hiro
        gchar *parent_name;
337 1 hiro
        gchar *count_str;
338 1 hiro
        gchar *cols[3];
339 1 hiro
        gint count;
340 1 hiro
341 1 hiro
        count = ginfo->last - ginfo->first;
342 1 hiro
        if (count < 0)
343 1 hiro
                count = 0;
344 1 hiro
        count_str = itos(count);
345 1 hiro
346 1 hiro
        cols[0] = ginfo->name;
347 1 hiro
        cols[1] = count_str;
348 1 hiro
        if (ginfo->type == 'y')
349 1 hiro
                cols[2] = "";
350 1 hiro
        else if (ginfo->type == 'm')
351 1 hiro
                cols[2] = _("moderated");
352 1 hiro
        else if (ginfo->type == 'n')
353 1 hiro
                cols[2] = _("readonly");
354 1 hiro
        else
355 1 hiro
                cols[2] = _("unknown");
356 1 hiro
357 1 hiro
        parent_name = grouplist_get_parent_name(name);
358 1 hiro
        parent = grouplist_create_parent(parent_name, pattern);
359 1 hiro
        node = grouplist_hash_get_branch_node(name);
360 1 hiro
        if (node) {
361 1 hiro
                gtk_ctree_set_node_info(GTK_CTREE(ctree), node, cols[0], 0,
362 1 hiro
                                        NULL, NULL, NULL, NULL, FALSE, FALSE);
363 1 hiro
                gtk_ctree_node_set_text(GTK_CTREE(ctree), node, 1, cols[1]);
364 1 hiro
                gtk_ctree_node_set_text(GTK_CTREE(ctree), node, 2, cols[2]);
365 1 hiro
        } else {
366 1 hiro
                node = parent ? GTK_CTREE_ROW(parent)->children
367 1 hiro
                        : GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
368 1 hiro
                node = gtk_ctree_insert_node(GTK_CTREE(ctree), parent, node,
369 1 hiro
                                             cols, 0, NULL, NULL, NULL, NULL,
370 1 hiro
                                             TRUE, FALSE);
371 32 hiro
                if (parent &&
372 32 hiro
                    g_pattern_match_simple(pattern, parent_name) == FALSE)
373 1 hiro
                        gtk_ctree_expand(GTK_CTREE(ctree), parent);
374 1 hiro
        }
375 1 hiro
        gtk_ctree_node_set_selectable(GTK_CTREE(ctree), node, TRUE);
376 1 hiro
        if (node)
377 1 hiro
                gtk_ctree_node_set_row_data(GTK_CTREE(ctree), node, ginfo);
378 1 hiro
379 1 hiro
        g_free(parent_name);
380 1 hiro
381 1 hiro
        return node;
382 1 hiro
}
383 1 hiro
384 1 hiro
static void grouplist_dialog_set_list(const gchar *pattern, gboolean refresh)
385 1 hiro
{
386 1 hiro
        GSList *cur;
387 1 hiro
        GtkCTreeNode *node;
388 32 hiro
        GPatternSpec *pspec;
389 1 hiro
390 1 hiro
        if (locked) return;
391 1 hiro
        locked = TRUE;
392 1 hiro
393 1 hiro
        if (!pattern || *pattern == '\0')
394 1 hiro
                pattern = "*";
395 1 hiro
396 1 hiro
        if (refresh) {
397 1 hiro
                ack = TRUE;
398 1 hiro
                grouplist_clear();
399 1 hiro
                recv_set_ui_func(grouplist_recv_func, NULL);
400 1 hiro
                group_list = news_get_group_list(news_folder);
401 1 hiro
                group_list = g_slist_reverse(group_list);
402 1 hiro
                recv_set_ui_func(NULL, NULL);
403 1 hiro
                if (group_list == NULL && ack == TRUE) {
404 1 hiro
                        alertpanel_error(_("Can't retrieve newsgroup list."));
405 1 hiro
                        locked = FALSE;
406 1 hiro
                        return;
407 1 hiro
                }
408 1 hiro
        } else {
409 1 hiro
                g_signal_handlers_block_by_func
410 1 hiro
                        (G_OBJECT(ctree), G_CALLBACK(ctree_unselected),
411 1 hiro
                         NULL);
412 1 hiro
                gtk_clist_clear(GTK_CLIST(ctree));
413 1 hiro
                g_signal_handlers_unblock_by_func
414 1 hiro
                        (G_OBJECT(ctree), G_CALLBACK(ctree_unselected),
415 1 hiro
                         NULL);
416 1 hiro
        }
417 1 hiro
        gtk_entry_set_text(GTK_ENTRY(entry), pattern);
418 1 hiro
419 1 hiro
        grouplist_hash_init();
420 1 hiro
421 1 hiro
        gtk_clist_freeze(GTK_CLIST(ctree));
422 1 hiro
423 1 hiro
        g_signal_handlers_block_by_func(G_OBJECT(ctree),
424 1 hiro
                                        G_CALLBACK(ctree_selected), NULL);
425 1 hiro
426 32 hiro
        pspec = g_pattern_spec_new(pattern);
427 32 hiro
428 1 hiro
        for (cur = group_list; cur != NULL ; cur = cur->next) {
429 1 hiro
                NewsGroupInfo *ginfo = (NewsGroupInfo *)cur->data;
430 1 hiro
431 32 hiro
                if (g_pattern_match_string(pspec, ginfo->name)) {
432 1 hiro
                        node = grouplist_create_branch(ginfo, pattern);
433 333 hiro
                        if (g_slist_find_custom
434 333 hiro
                                (subscribed, ginfo->name,
435 333 hiro
                                 (GCompareFunc)g_ascii_strcasecmp)
436 1 hiro
                            != NULL)
437 1 hiro
                                gtk_ctree_select(GTK_CTREE(ctree), node);
438 1 hiro
                }
439 1 hiro
        }
440 1 hiro
441 32 hiro
        g_pattern_spec_free(pspec);
442 32 hiro
443 1 hiro
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
444 1 hiro
                                          G_CALLBACK(ctree_selected), NULL);
445 1 hiro
446 1 hiro
        gtk_clist_thaw(GTK_CLIST(ctree));
447 1 hiro
448 1 hiro
        grouplist_hash_done();
449 1 hiro
450 1 hiro
        gtk_label_set_text(GTK_LABEL(status_label), _("Done."));
451 1 hiro
452 1 hiro
        locked = FALSE;
453 1 hiro
}
454 1 hiro
455 1 hiro
static void grouplist_search(void)
456 1 hiro
{
457 1 hiro
        gchar *str;
458 1 hiro
459 1 hiro
        if (locked) return;
460 1 hiro
461 1 hiro
        str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
462 1 hiro
        grouplist_dialog_set_list(str, FALSE);
463 1 hiro
        g_free(str);
464 1 hiro
}
465 1 hiro
466 1 hiro
static void grouplist_clear(void)
467 1 hiro
{
468 1 hiro
        g_signal_handlers_block_by_func(G_OBJECT(ctree),
469 1 hiro
                                        G_CALLBACK(ctree_unselected), NULL);
470 1 hiro
        gtk_clist_clear(GTK_CLIST(ctree));
471 1 hiro
        gtk_entry_set_text(GTK_ENTRY(entry), "");
472 1 hiro
        news_group_list_free(group_list);
473 1 hiro
        group_list = NULL;
474 1 hiro
        g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
475 1 hiro
                                          G_CALLBACK(ctree_unselected), NULL);
476 1 hiro
}
477 1 hiro
478 1 hiro
static gboolean grouplist_recv_func(SockInfo *sock, gint count, gint read_bytes,
479 1 hiro
                                    gpointer data)
480 1 hiro
{
481 1 hiro
        gchar buf[BUFFSIZE];
482 1 hiro
483 1 hiro
        g_snprintf(buf, sizeof(buf),
484 1 hiro
                   _("%d newsgroups received (%s read)"),
485 1 hiro
                   count, to_human_readable(read_bytes));
486 1 hiro
        gtk_label_set_text(GTK_LABEL(status_label), buf);
487 1 hiro
        GTK_EVENTS_FLUSH();
488 1 hiro
        if (ack == FALSE)
489 1 hiro
                return FALSE;
490 1 hiro
        else
491 1 hiro
                return TRUE;
492 1 hiro
}
493 1 hiro
494 1 hiro
static gint window_deleted(GtkWidget *widget, GdkEventAny *event, gpointer data)
495 1 hiro
{
496 1 hiro
        ack = FALSE;
497 1 hiro
        if (gtk_main_level() > 1)
498 1 hiro
                gtk_main_quit();
499 1 hiro
500 1 hiro
        return TRUE;
501 1 hiro
}
502 1 hiro
503 1 hiro
static void ok_clicked(GtkWidget *widget, gpointer data)
504 1 hiro
{
505 1 hiro
        ack = TRUE;
506 1 hiro
        if (gtk_main_level() > 1)
507 1 hiro
                gtk_main_quit();
508 1 hiro
}
509 1 hiro
510 1 hiro
static void cancel_clicked(GtkWidget *widget, gpointer data)
511 1 hiro
{
512 1 hiro
        ack = FALSE;
513 1 hiro
        if (gtk_main_level() > 1)
514 1 hiro
                gtk_main_quit();
515 1 hiro
}
516 1 hiro
517 1 hiro
static void refresh_clicked(GtkWidget *widget, gpointer data)
518 1 hiro
{
519 1 hiro
        gchar *str;
520 1 hiro
521 1 hiro
        if (locked) return;
522 1 hiro
523 1 hiro
        news_remove_group_list_cache(news_folder);
524 1 hiro
525 1 hiro
        str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
526 1 hiro
        grouplist_dialog_set_list(str, TRUE);
527 1 hiro
        g_free(str);
528 1 hiro
}
529 1 hiro
530 1 hiro
static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event,
531 1 hiro
                            gpointer data)
532 1 hiro
{
533 1 hiro
        if (event && event->keyval == GDK_Escape)
534 1 hiro
                cancel_clicked(NULL, NULL);
535 1 hiro
        return FALSE;
536 1 hiro
}
537 1 hiro
538 1 hiro
static void ctree_selected(GtkCTree *ctree, GtkCTreeNode *node, gint column,
539 1 hiro
                           gpointer data)
540 1 hiro
{
541 1 hiro
        NewsGroupInfo *ginfo;
542 1 hiro
543 1 hiro
        ginfo = gtk_ctree_node_get_row_data(ctree, node);
544 1 hiro
        if (!ginfo) return;
545 1 hiro
546 1 hiro
        subscribed = g_slist_append(subscribed, g_strdup(ginfo->name));
547 1 hiro
}
548 1 hiro
549 1 hiro
static void ctree_unselected(GtkCTree *ctree, GtkCTreeNode *node, gint column,
550 1 hiro
                             gpointer data)
551 1 hiro
{
552 1 hiro
        NewsGroupInfo *ginfo;
553 1 hiro
        GSList *list;
554 1 hiro
555 1 hiro
        ginfo = gtk_ctree_node_get_row_data(ctree, node);
556 1 hiro
        if (!ginfo) return;
557 1 hiro
558 1 hiro
        list = g_slist_find_custom(subscribed, ginfo->name,
559 333 hiro
                                   (GCompareFunc)g_ascii_strcasecmp);
560 1 hiro
        if (list) {
561 1 hiro
                g_free(list->data);
562 1 hiro
                subscribed = g_slist_remove(subscribed, list->data);
563 1 hiro
        }
564 1 hiro
}
565 1 hiro
566 1 hiro
static void entry_activated(GtkEditable *editable)
567 1 hiro
{
568 1 hiro
        grouplist_search();
569 1 hiro
}
570 1 hiro
571 1 hiro
static void search_clicked(GtkWidget *widget, gpointer data)
572 1 hiro
{
573 1 hiro
        grouplist_search();
574 1 hiro
}