/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "defs.h"
#include <glib.h>
+#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkwidget.h>
#include <gtk/gtkscrolledwindow.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkhbbox.h>
+#include <gtk/gtkstock.h>
#include <string.h>
-#include <fnmatch.h>
-#include "intl.h"
#include "grouplistdialog.h"
#include "manage_window.h"
#include "gtkutils.h"
gint read_bytes,
gpointer data);
+static gint window_deleted (GtkWidget *widget,
+ GdkEventAny *event,
+ gpointer data);
static void ok_clicked (GtkWidget *widget,
gpointer data);
static void cancel_clicked (GtkWidget *widget,
static gboolean key_pressed (GtkWidget *widget,
GdkEventKey *event,
gpointer data);
-static void ctree_selected (GtkCTree *ctree,
- GtkCTreeNode *node,
- gint column,
- gpointer data);
-static void ctree_unselected (GtkCTree *ctree,
- GtkCTreeNode *node,
- gint column,
+static gboolean button_press_cb (GtkCTree *ctree,
+ GdkEventButton *button,
gpointer data);
static void entry_activated (GtkEditable *editable);
static void search_clicked (GtkWidget *widget,
gint i;
dialog = gtk_dialog_new();
- gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, TRUE, FALSE);
+ gtk_window_set_resizable(GTK_WINDOW(dialog), TRUE);
gtk_widget_set_size_request(dialog,
- GROUPLIST_DIALOG_WIDTH, GROUPLIST_DIALOG_HEIGHT);
+ GROUPLIST_DIALOG_WIDTH,
+ GROUPLIST_DIALOG_HEIGHT);
gtk_container_set_border_width
(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 5);
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(dialog), _("Newsgroup subscription"));
g_signal_connect(G_OBJECT(dialog), "delete_event",
- G_CALLBACK(cancel_clicked), NULL);
+ G_CALLBACK(window_deleted), NULL);
g_signal_connect(G_OBJECT(dialog), "key_press_event",
G_CALLBACK(key_pressed), NULL);
MANAGE_WINDOW_SIGNALS_CONNECT(dialog);
scrolledwin = gtk_scrolled_window_new(NULL, NULL);
gtk_box_pack_start(GTK_BOX (vbox), scrolledwin, TRUE, TRUE, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolledwin),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
+ GTK_POLICY_ALWAYS,
+ GTK_POLICY_ALWAYS);
titles[0] = _("Newsgroup name");
titles[1] = _("Messages");
gtk_container_add(GTK_CONTAINER(scrolledwin), ctree);
gtk_clist_set_column_width
(GTK_CLIST(ctree), 0, GROUPLIST_COL_NAME_WIDTH);
+ gtk_clist_set_column_auto_resize(GTK_CLIST(ctree), 0, TRUE);
gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_MULTIPLE);
gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
gtk_ctree_set_expander_style(GTK_CTREE(ctree),
for (i = 0; i < 3; i++)
GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(ctree)->column[i].button,
GTK_CAN_FOCUS);
- g_signal_connect(G_OBJECT(ctree), "tree_select_row",
- G_CALLBACK(ctree_selected), NULL);
- g_signal_connect(G_OBJECT(ctree), "tree_unselect_row",
- G_CALLBACK(ctree_unselected), NULL);
+ g_signal_connect(G_OBJECT(ctree), "button-press-event",
+ G_CALLBACK(button_press_cb), NULL);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
status_label = gtk_label_new("");
gtk_box_pack_start(GTK_BOX(hbox), status_label, FALSE, FALSE, 0);
- gtkut_button_set_create(&confirm_area,
- &ok_button, _("OK"),
- &cancel_button, _("Cancel"),
- &refresh_button, _("Refresh"));
+ gtkut_stock_button_set_create(&confirm_area,
+ &ok_button, GTK_STOCK_OK,
+ &cancel_button, GTK_STOCK_CANCEL,
+ &refresh_button, GTK_STOCK_REFRESH);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
confirm_area);
gtk_widget_grab_default(ok_button);
node = gtk_ctree_insert_node(GTK_CTREE(ctree), parent, node,
cols, 0, NULL, NULL, NULL, NULL,
FALSE, FALSE);
- if (parent && fnmatch(pattern, parent_name, 0) != 0)
+ if (parent && g_pattern_match_simple(pattern, parent_name) == FALSE)
gtk_ctree_expand(GTK_CTREE(ctree), parent);
gtk_ctree_node_set_selectable(GTK_CTREE(ctree), node, FALSE);
node = gtk_ctree_insert_node(GTK_CTREE(ctree), parent, node,
cols, 0, NULL, NULL, NULL, NULL,
TRUE, FALSE);
- if (parent && fnmatch(pattern, parent_name, 0) != 0)
+ if (parent &&
+ g_pattern_match_simple(pattern, parent_name) == FALSE)
gtk_ctree_expand(GTK_CTREE(ctree), parent);
}
gtk_ctree_node_set_selectable(GTK_CTREE(ctree), node, TRUE);
return node;
}
+static void grouplist_expand_upwards(GtkCTree *ctree, const gchar *name) {
+ const gchar *ptr;
+ gchar *newname=g_malloc0(strlen(name));
+
+ for (ptr=name; *ptr; ptr++) {
+ if (*ptr == '.')
+ gtk_ctree_expand(ctree,
+ grouplist_hash_get_branch_node(newname));
+ newname[ptr-name] = *ptr;
+ }
+ g_free(newname);
+}
+
static void grouplist_dialog_set_list(const gchar *pattern, gboolean refresh)
{
GSList *cur;
GtkCTreeNode *node;
+ GPatternSpec *pspec;
if (locked) return;
locked = TRUE;
locked = FALSE;
return;
}
- } else {
- g_signal_handlers_block_by_func
- (G_OBJECT(ctree), G_CALLBACK(ctree_unselected),
- NULL);
+ } else
gtk_clist_clear(GTK_CLIST(ctree));
- g_signal_handlers_unblock_by_func
- (G_OBJECT(ctree), G_CALLBACK(ctree_unselected),
- NULL);
- }
+
gtk_entry_set_text(GTK_ENTRY(entry), pattern);
grouplist_hash_init();
gtk_clist_freeze(GTK_CLIST(ctree));
- g_signal_handlers_block_by_func(G_OBJECT(ctree),
- G_CALLBACK(ctree_selected),
- NULL);
+ pspec = g_pattern_spec_new(pattern);
for (cur = group_list; cur != NULL ; cur = cur->next) {
NewsGroupInfo *ginfo = (NewsGroupInfo *)cur->data;
- if (fnmatch(pattern, ginfo->name, 0) == 0) {
+ if (g_pattern_match_string(pspec, ginfo->name)) {
node = grouplist_create_branch(ginfo, pattern);
if (g_slist_find_custom(subscribed, ginfo->name,
(GCompareFunc)g_strcasecmp)
gtk_ctree_select(GTK_CTREE(ctree), node);
}
}
+ for (cur = subscribed; cur; cur = g_slist_next(cur))
+ grouplist_expand_upwards(GTK_CTREE(ctree), (gchar *)cur->data);
- g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
- G_CALLBACK(ctree_selected),
- NULL);
+ g_pattern_spec_free(pspec);
gtk_clist_thaw(GTK_CLIST(ctree));
static void grouplist_clear(void)
{
- g_signal_handlers_block_by_func(G_OBJECT(ctree),
- G_CALLBACK(ctree_unselected),
- NULL);
gtk_clist_clear(GTK_CLIST(ctree));
gtk_entry_set_text(GTK_ENTRY(entry), "");
news_group_list_free(group_list);
group_list = NULL;
- g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
- G_CALLBACK(ctree_unselected),
- NULL);
}
static gboolean grouplist_recv_func(SockInfo *sock, gint count, gint read_bytes,
return TRUE;
}
+static gint window_deleted(GtkWidget *widget, GdkEventAny *event, gpointer data)
+{
+ ack = FALSE;
+ if (gtk_main_level() > 1)
+ gtk_main_quit();
+
+ return TRUE;
+}
+
static void ok_clicked(GtkWidget *widget, gpointer data)
{
ack = TRUE;
return FALSE;
}
-static void ctree_selected(GtkCTree *ctree, GtkCTreeNode *node, gint column,
- gpointer data)
+/* clist/ctree clear old selection on click (gtk2 only)
+ * - intercept all button clicks (always return TRUE)
+ * - only allow left button single click
+ * - handle click on expander
+ * - update "subscribed" list and un-/select row
+ */
+static gboolean button_press_cb(GtkCTree *ctree, GdkEventButton *button,
+ gpointer data)
{
+ gint row, col;
+ GtkCTreeNode *node;
NewsGroupInfo *ginfo;
+ GSList *list;
- ginfo = gtk_ctree_node_get_row_data(ctree, node);
- if (!ginfo) return;
+ if (button->type != GDK_BUTTON_PRESS) return TRUE;
+ if (button->button != 1) return TRUE;
- subscribed = g_slist_append(subscribed, g_strdup(ginfo->name));
-}
+ gtk_clist_get_selection_info(GTK_CLIST(ctree),
+ button->x, button->y, &row, &col);
+ node = gtk_ctree_node_nth(ctree, row);
+ if (!node) return TRUE;
-static void ctree_unselected(GtkCTree *ctree, GtkCTreeNode *node, gint column,
- gpointer data)
-{
- NewsGroupInfo *ginfo;
- GSList *list;
+ if (gtk_ctree_is_hot_spot(ctree, button->x, button->y)) {
+ gtk_ctree_toggle_expansion(ctree, node);
+ return TRUE;
+ }
ginfo = gtk_ctree_node_get_row_data(ctree, node);
- if (!ginfo) return;
+ if (!ginfo) return TRUE;
list = g_slist_find_custom(subscribed, ginfo->name,
- (GCompareFunc)g_strcasecmp);
+ (GCompareFunc)g_ascii_strcasecmp);
if (list) {
g_free(list->data);
subscribed = g_slist_remove(subscribed, list->data);
+ gtk_clist_unselect_row(GTK_CLIST(ctree), row, 0);
+ } else {
+ subscribed = g_slist_append(subscribed, g_strdup(ginfo->name));
+ gtk_clist_select_row(GTK_CLIST(ctree), row, 0);
}
+
+ return TRUE;
}
static void entry_activated(GtkEditable *editable)