news selection dialog box enhanced
authorHoà Viêt Dinh <dinh.viet.hoa@free.fr>
Thu, 18 Oct 2001 18:51:14 +0000 (18:51 +0000)
committerHoà Viêt Dinh <dinh.viet.hoa@free.fr>
Thu, 18 Oct 2001 18:51:14 +0000 (18:51 +0000)
ChangeLog.claws
configure.in
src/folderview.c
src/grouplistdialog.c
src/grouplistdialog.h
src/news.c
src/news.h

index 41e5c15..8549222 100644 (file)
@@ -1,3 +1,14 @@
+2001-10-18 [hoa]        0.6.3claws23
+       * src/folderview.c
+       * src/grouplistdialog.[ch]
+               enhanced news subscription interface
+
+       * src/news.c
+       * src/news.h
+               enchanced newsgroup listing,
+               now, we can get groups informations
+               (NNTPGroupInfo)
+
 2001-10-18 [paul]      0.6.3claws22
 
        * src/summaryview.c
index 7906fed..93a2575 100644 (file)
@@ -8,7 +8,7 @@ MINOR_VERSION=6
 MICRO_VERSION=3
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws22
+EXTRA_VERSION=claws23
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl
index 647ccbf..9336837 100644 (file)
@@ -1959,6 +1959,36 @@ static void folderview_rm_imap_server_cb(FolderView *folderview, guint action,
        folder_write_list();
 }
 
+
+
+
+
+static GList *folderview_news_get_subscriptions(GtkCTree *ctree,
+                                               GtkCTreeNode *node)
+{
+       FolderItem *item;
+       GList * result;
+
+       result = NULL;
+
+       if (!node)
+               node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
+       if (!node)
+               return NULL;
+
+       node = GTK_CTREE_ROW(node)->children;
+
+       while (node) {
+               item = gtk_ctree_node_get_row_data(ctree, node);
+
+               result = g_list_append(result, item->name);
+               node = GTK_CTREE_ROW(node)->sibling;
+       }
+
+       return result;
+}
+
+
 static void folderview_new_news_group_cb(FolderView *folderview, guint action,
                                         GtkWidget *widget)
 {
@@ -1967,8 +1997,10 @@ static void folderview_new_news_group_cb(FolderView *folderview, guint action,
        GtkCTreeNode *servernode, *node;
        FolderItem *item;
        FolderItem *newitem;
-       gchar *new_group;
        const gchar *server;
+       GList * subscriptions;
+       GList * new_subscriptions;
+       GList * l;
 
        if (!folderview->selected) return;
 
@@ -1978,41 +2010,83 @@ static void folderview_new_news_group_cb(FolderView *folderview, guint action,
        g_return_if_fail(item->folder->type == F_NEWS);
        g_return_if_fail(item->folder->account != NULL);
 
-       new_group = grouplist_dialog(item->folder);
-       if (!new_group) return;
-
        if (GTK_CTREE_ROW(folderview->selected)->parent != NULL)
                servernode = GTK_CTREE_ROW(folderview->selected)->parent;
        else
                servernode = folderview->selected;
 
-       if (folderview_find_by_name(ctree, servernode, new_group)) {
-               alertpanel_error(_("The newsgroup `%s' already exists."),
-                                new_group);
-               g_free(new_group);
-               return;
-       }
+       subscriptions = folderview_news_get_subscriptions(ctree, servernode);
 
-       gtk_clist_freeze(GTK_CLIST(ctree));
+       new_subscriptions = grouplist_dialog(item->folder, subscriptions);
 
-       text[COL_FOLDER] = new_group;
-       node = gtk_ctree_insert_node(ctree, servernode, NULL, text,
-                                    FOLDER_SPACING,
-                                    folderxpm, folderxpmmask,
-                                    folderopenxpm, folderopenxpmmask,
-                                    FALSE, FALSE);
-       gtk_ctree_expand(ctree, servernode);
+       for(l = subscriptions ; l != NULL ; l = l->next) {
+         gchar * name;
+         
+         name = (gchar *) l->data;
 
-       item = gtk_ctree_node_get_row_data(ctree, servernode);
-       server = item->folder->account->nntp_server;
+         if (g_list_find_custom(new_subscriptions, name,
+                                (GCompareFunc) g_strcasecmp) == NULL) {
+           GtkCTreeNode * sel;
 
-       newitem = folder_item_new(new_group, new_group);
-       g_free(new_group);
-       folder_item_append(item, newitem);
-       gtk_ctree_node_set_row_data(ctree, node, newitem);
-       gtk_ctree_sort_node(ctree, servernode);
+           /* remove subscription */
 
-       gtk_clist_thaw(GTK_CLIST(ctree));
+           sel = folderview_find_by_name(ctree, servernode, name);
+           g_return_if_fail(sel != NULL);
+
+           item = gtk_ctree_node_get_row_data(ctree, sel);
+
+           g_return_if_fail(item != NULL);
+           g_return_if_fail(item->folder != NULL);
+           g_return_if_fail(item->folder->type == F_NEWS);
+           g_return_if_fail(item->folder->account != NULL);
+
+           if (folderview->opened == sel) {
+             summary_clear_all(folderview->summaryview);
+             folderview->opened = NULL;
+           }
+           
+           folder_item_remove(item);
+           gtk_ctree_remove_node(ctree, sel);
+
+         }
+       }
+
+       g_list_free(subscriptions);
+
+       for(l = new_subscriptions ; l != NULL ; l = l->next) {
+         gchar * name;
+         
+         name = (gchar *) l->data;
+
+         if (folderview_find_by_name(ctree, servernode, name) == NULL) {
+
+           /* add newsgroup */
+
+           gtk_clist_freeze(GTK_CLIST(ctree));
+           
+           text[COL_FOLDER] = name;
+           node = gtk_ctree_insert_node(ctree, servernode, NULL, text,
+                                        FOLDER_SPACING,
+                                        folderxpm, folderxpmmask,
+                                        folderopenxpm, folderopenxpmmask,
+                                        FALSE, FALSE);
+           gtk_ctree_expand(ctree, servernode);
+           
+           item = gtk_ctree_node_get_row_data(ctree, servernode);
+           server = item->folder->account->nntp_server;
+           
+           newitem = folder_item_new(name, name);
+           folder_item_append(item, newitem);
+           gtk_ctree_node_set_row_data(ctree, node, newitem);
+           gtk_ctree_sort_node(ctree, servernode);
+           
+           gtk_clist_thaw(GTK_CLIST(ctree));
+           
+         }
+       }
+
+       list_free_strings(new_subscriptions);
+       g_list_free(new_subscriptions);
 
        folder_write_list();
 }
index 6e7d31a..0dddd88 100644 (file)
 #include "recv.h"
 #include "socket.h"
 
-#define GROUPLIST_DIALOG_WIDTH 420
+#define GROUPLIST_DIALOG_WIDTH 500
+#define GROUPLIST_NAMES                250
 #define GROUPLIST_DIALOG_HEIGHT        400
 
+static GList * subscribed = NULL;
+gboolean dont_unsubscribed = FALSE;
+
 static gboolean ack;
 static gboolean locked;
 
@@ -63,7 +67,7 @@ static GtkWidget *entry;
 static GtkWidget *clist;
 static GtkWidget *status_label;
 static GtkWidget *ok_button;
-static GSList *group_list;
+static GSList *group_list = NULL;
 static Folder *news_folder;
 
 static void grouplist_dialog_create    (void);
@@ -88,11 +92,17 @@ static void clist_selected  (GtkCList       *clist,
                                 gint            column,
                                 GdkEventButton *event,
                                 gpointer        user_data);
+static void clist_unselected   (GtkCList       *clist,
+                                gint            row,
+                                gint            column,
+                                GdkEventButton *event,
+                                gpointer        user_data);
 static void entry_activated    (GtkEditable    *editable);
 
-gchar *grouplist_dialog(Folder *folder)
+GList *grouplist_dialog(Folder *folder, GList * cur_subscriptions)
 {
        gchar *str;
+       GList * l;
 
        if (dialog && GTK_WIDGET_VISIBLE(dialog)) return NULL;
 
@@ -106,6 +116,11 @@ gchar *grouplist_dialog(Folder *folder)
        manage_window_set_transient(GTK_WINDOW(dialog));
        GTK_EVENTS_FLUSH();
 
+       subscribed = NULL;
+
+       for(l = cur_subscriptions ; l != NULL ; l = l->next)
+         subscribed = g_list_append(subscribed, g_strdup((gchar *) l->data));
+
        grouplist_dialog_set_list(NULL);
 
        gtk_main();
@@ -113,6 +128,7 @@ gchar *grouplist_dialog(Folder *folder)
        manage_window_focus_out(dialog, NULL, NULL);
        gtk_widget_hide(dialog);
 
+       /*
        if (ack) {
                str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
                if (str && *str == '\0') {
@@ -121,19 +137,29 @@ gchar *grouplist_dialog(Folder *folder)
                }
        } else
                str = NULL;
+       */
+       if (!ack) {
+         list_free_strings(subscribed);
+         g_list_free(subscribed);
+
+         subscribed = NULL;
+         
+         for(l = cur_subscriptions ; l != NULL ; l = l->next)
+           subscribed = g_list_append(subscribed, g_strdup((gchar *) l->data));
+       }
 
        GTK_EVENTS_FLUSH();
 
        debug_print("return string = %s\n", str ? str : "(none)");
-       return str;
+       return subscribed;
 }
 
 static void grouplist_clear(void)
 {
+       dont_unsubscribed = TRUE;
        gtk_clist_clear(GTK_CLIST(clist));
        gtk_entry_set_text(GTK_ENTRY(entry), "");
-       slist_free_strings(group_list);
-       g_slist_free(group_list);
+       dont_unsubscribed = FALSE;
 }
 
 static void grouplist_dialog_create(void)
@@ -145,6 +171,9 @@ static void grouplist_dialog_create(void)
        GtkWidget *cancel_button;       
        GtkWidget *refresh_button;      
        GtkWidget *scrolledwin;
+       gchar * col_names[3] = {
+               _("name"), _("count of messages"), _("type")
+       };
 
        dialog = gtk_dialog_new();
        gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, TRUE, FALSE);
@@ -186,14 +215,15 @@ static void grouplist_dialog_create(void)
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
 
-       clist = gtk_clist_new(1);
+       clist = gtk_clist_new_with_titles(3, col_names);
        gtk_container_add(GTK_CONTAINER(scrolledwin), clist);
-       gtk_clist_set_column_width(GTK_CLIST(clist), 0, 80);
-       gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
+       gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_MULTIPLE);
        GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[0].button,
                               GTK_CAN_FOCUS);
        gtk_signal_connect(GTK_OBJECT(clist), "select_row",
                           GTK_SIGNAL_FUNC(clist_selected), NULL);
+       gtk_signal_connect(GTK_OBJECT(clist), "unselect_row",
+                          GTK_SIGNAL_FUNC(clist_unselected), NULL);
 
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
@@ -232,24 +262,68 @@ static void grouplist_dialog_set_list(gchar * pattern)
 
        grouplist_clear();
 
-       recv_set_ui_func(grouplist_recv_func, NULL);
-       group_list = news_get_group_list(news_folder);
-       recv_set_ui_func(NULL, NULL);
        if (group_list == NULL) {
-               alertpanel_error(_("Can't retrieve newsgroup list."));
-               locked = FALSE;
-               return;
+         recv_set_ui_func(grouplist_recv_func, NULL);
+         group_list = news_get_group_list(news_folder);
+         recv_set_ui_func(NULL, NULL);
+         if (group_list == NULL) {
+           alertpanel_error(_("Can't retrieve newsgroup list."));
+           locked = FALSE;
+           return;
+         }
        }
 
+       dont_unsubscribed = TRUE;
+
        gtk_clist_freeze(GTK_CLIST(clist));
        for (cur = group_list; cur != NULL ; cur = cur->next) {
-               if (fnmatch(pattern, cur->data, 0) == 0) {
-                       row = gtk_clist_append(GTK_CLIST(clist),
-                                              (gchar **)&(cur->data));
-                       gtk_clist_set_row_data(GTK_CLIST(clist), row,
-                                              cur->data);
+               struct NNTPGroupInfo * info;
+
+               info = (struct NNTPGroupInfo *) cur->data;
+
+               if (fnmatch(pattern, info->name, 0) == 0) {
+                       gchar count_str[10];
+                       gchar * cols[3];
+                       gint count;
+                       GList * l;
+
+                       count = info->last - info->first;
+                       if (count < 0)
+                               count = 0;
+                       snprintf(count_str, 10, "%i", count);
+
+                       cols[0] = info->name;
+                       cols[1] = count_str;
+                       if (info->type == 'y')
+                               cols[2] = "";
+                       else if (info->type == 'm')
+                               cols[2] = "moderated";
+                       else if (info->type == 'n')
+                               cols[2] = "readonly";
+                       else
+                               cols[2] = "unkown";
+
+                       row = gtk_clist_append(GTK_CLIST(clist), cols);
+                       gtk_clist_set_row_data(GTK_CLIST(clist), row, info);
+
+                       l = g_list_find_custom(subscribed, info->name,
+                                              (GCompareFunc) g_strcasecmp);
+                       
+                       if (l != NULL)
+                         gtk_clist_select_row(GTK_CLIST(clist), row, 0);
                }
        }
+
+       gtk_clist_moveto(GTK_CLIST(clist), 0, 0, 0, 0);
+
+       dont_unsubscribed = FALSE;
+
+       gtk_clist_set_column_width(GTK_CLIST(clist), 0, GROUPLIST_NAMES);
+       gtk_clist_set_column_justification (GTK_CLIST(clist), 1,
+                                           GTK_JUSTIFY_RIGHT);
+       gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 1, TRUE);
+       gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 2, TRUE);
+
        gtk_clist_thaw(GTK_CLIST(clist));
 
        gtk_widget_grab_focus(ok_button);
@@ -274,9 +348,26 @@ static void grouplist_recv_func(SockInfo *sock, gint count, gint read_bytes,
 
 static void ok_clicked(GtkWidget *widget, gpointer data)
 {
-       ack = TRUE;
-       if (gtk_main_level() > 1)
-               gtk_main_quit();
+       gchar * str;
+       gboolean update_list;
+
+       str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
+
+       update_list = FALSE;
+
+       if (strchr(str, '*') != NULL)
+         update_list = TRUE;
+
+       if (update_list) {
+               grouplist_dialog_set_list(str);
+               g_free(str);
+       }
+       else {
+               g_free(str);
+               ack = TRUE;
+               if (gtk_main_level() > 1)
+                       gtk_main_quit();
+       }
 }
 
 static void cancel_clicked(GtkWidget *widget, gpointer data)
@@ -292,14 +383,12 @@ static void refresh_clicked(GtkWidget *widget, gpointer data)
  
        if (locked) return;
 
-       grouplist_clear();
+       news_group_list_free(group_list);
        news_remove_group_list(news_folder);
 
        str = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
        grouplist_dialog_set_list(str);
        g_free(str);
-
-       grouplist_dialog_set_list(str);
 }
 
 static void key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
@@ -311,10 +400,34 @@ static void key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
 static void clist_selected(GtkCList *clist, gint row, gint column,
                           GdkEventButton *event, gpointer user_data)
 {
-       gchar *group;
+       struct NNTPGroupInfo * group;
+       GList * l;
+
+       group = (struct NNTPGroupInfo *)
+         gtk_clist_get_row_data(GTK_CLIST(clist), row);
+
+       if (!dont_unsubscribed) {
+               subscribed = g_list_append(subscribed, g_strdup(group->name));
+       }
+}
 
-       group = (gchar *)gtk_clist_get_row_data(GTK_CLIST(clist), row);
-       gtk_entry_set_text(GTK_ENTRY(entry), group ? group : "");
+static void clist_unselected(GtkCList *clist, gint row, gint column,
+                            GdkEventButton *event, gpointer user_data)
+{
+       struct NNTPGroupInfo * group;
+       GList * l;
+
+       group = (struct NNTPGroupInfo *)
+         gtk_clist_get_row_data(GTK_CLIST(clist), row);
+
+       if (!dont_unsubscribed) {
+               l = g_list_find_custom(subscribed, group->name,
+                                      (GCompareFunc) g_strcasecmp);
+               if (l != NULL) {
+                 g_free(l->data);
+                       subscribed = g_list_remove(subscribed, l->data);
+               }
+       }
 }
 
 static gboolean match_string(gchar * str, gchar * expr)
index 6cd0bcb..e5fd172 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "folder.h"
 
-gchar *grouplist_dialog        (Folder *folder);
+GList *grouplist_dialog(Folder *folder, GList * cur_subscriptions);
+     //gchar *grouplist_dialog (Folder *folder);
 
 #endif /* __GROUPLISTDIALOG_H__ */
index a3a8208..637a549 100644 (file)
@@ -289,6 +289,41 @@ void news_scan_group(Folder *folder, FolderItem *item)
 {
 }
 
+static struct NNTPGroupInfo * group_info_new(gchar * name,
+                                            gint first, gint last,
+                                            gchar type)
+{
+       struct NNTPGroupInfo * info;
+
+       info = g_new(struct NNTPGroupInfo, 1);
+       if (info == NULL)
+               return NULL;
+       info->name = g_strdup(name);
+       info->first = first;
+       info->last = last;
+       info->type = type;
+
+       return info;
+}
+
+static void group_info_free(struct NNTPGroupInfo * info)
+{
+  g_free(info->name);
+  g_free(info);
+}
+
+void news_group_list_free(GSList * list)
+{
+  g_slist_foreach(list, (GFunc) group_info_free, NULL);
+  g_slist_free(list);
+}
+
+gint news_group_info_compare(struct NNTPGroupInfo * info1,
+                            struct NNTPGroupInfo * info2)
+{
+  return g_strcasecmp(info1->name, info2->name);
+}
+
 GSList *news_get_group_list(Folder *folder)
 {
        gchar *path, *filename;
@@ -335,13 +370,48 @@ GSList *news_get_group_list(Folder *folder)
        }
 
        while (fgets(buf, sizeof(buf), fp) != NULL) {
-               gchar *p = buf;
-               while (*p != '\0' && *p != ' ') p++;
-               *p = '\0';
+               gchar * p;
+               gchar * cur;
+               gchar * name;
+               gint last_article;
+               gint first_article;
+               gchar type;
+               struct NNTPGroupInfo * info;
+
+               cur = buf;
+               p = strchr(cur, ' ');
+               if (p == NULL)
+                       continue;
+               * p = 0;
+
+               name = cur;
+               
+               cur = p + 1;
+               p = strchr(cur, ' ');
+               if (p == NULL)
+                       continue;
+               * p = 0;
+               last_article = atoi(cur);
+
+               cur = p + 1;
+               p = strchr(cur, ' ');
+               if (p == NULL)
+                       continue;
+               * p = 0;
+               first_article = atoi(cur);
+
+               cur = p + 1;
+               type = * cur;
+
+               info = group_info_new(name, first_article,
+                                     last_article, type);
+               if (info == NULL)
+                       continue;
+
                if (!last)
-                       last = list = g_slist_append(NULL, g_strdup(buf));
+                       last = list = g_slist_append(NULL, info);
                else {
-                       last = g_slist_append(last, g_strdup(buf));
+                       last = g_slist_append(last, info);
                        last = last->next;
                }
        }
@@ -349,7 +419,7 @@ GSList *news_get_group_list(Folder *folder)
        fclose(fp);
        g_free(filename);
 
-       list = g_slist_sort(list, (GCompareFunc)g_strcasecmp);
+       list = g_slist_sort(list, (GCompareFunc) news_group_info_compare);
 
        statusbar_pop_all();
 
index 4dfe845..d4bc34c 100644 (file)
@@ -38,6 +38,13 @@ struct _NNTPSession
        gchar *group;
 };
 
+struct NNTPGroupInfo {
+       gint first;
+       gint last;
+       gchar * name;
+       gchar type;
+};
+
 
 void news_session_destroy              (NNTPSession    *session);
 NNTPSession *news_session_get          (Folder         *folder);
@@ -52,10 +59,14 @@ gchar *news_fetch_msg                       (Folder         *folder,
 void news_scan_group                   (Folder         *folder,
                                         FolderItem     *item);
 
+void news_group_list_free               (GSList * list);
 GSList *news_get_group_list            (Folder         *folder);
 void news_remove_group_list            (Folder         *folder);
 
 gint news_post                         (Folder         *folder,
                                         const gchar    *file);
 
+gint news_group_info_compare(struct NNTPGroupInfo * info1,
+                            struct NNTPGroupInfo * info2);
+
 #endif /* __NEWS_H__ */