fix bug 4239, 'Preferences: Text Options Header Display modal is not modal' (sic)
[claws.git] / src / uri_opener.c
index a0f83259a704e98c1c3d9118eac8d3265087a9c0..4b2506fff8e96a5074f60ddc0a9ff575a67dffa7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and 
+ * Copyright (C) 1999-2012 Colin Leroy <colin@colino.net> and 
  * the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  */
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
-#include <gtk/gtkwidget.h>
+#include <gtk/gtk.h>
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
@@ -34,7 +35,7 @@
 #include "gtkutils.h"
 #include "alertpanel.h"
 #include "textview.h"
-#include "prefs_common.h"
+#include "mimeview.h"
 #include "prefs_common.h"
 
 enum {
@@ -47,12 +48,13 @@ enum {
 static struct URIOpener
 {
        GtkWidget *window;
+       GtkWidget *hbox_scroll;
        GtkWidget *hbox1;
        GtkWidget *vbox1;
        GtkWidget *label;
        GtkWidget *urilist;
+       GtkWidget *scrolledwin;
        GtkWidget *open_btn;
-       GtkWidget *open_all_btn;
        GtkWidget *close_btn;
        MessageView *msgview;
        GSList    *uris;
@@ -60,7 +62,8 @@ static struct URIOpener
 
 static void uri_opener_load_uris (void);
 static void uri_opener_open_cb         (GtkWidget *widget, gpointer data);
-static void uri_opener_close_cb        (GtkWidget *widget, gpointer data);
+static void uri_opener_close_cb                (GtkWidget *widget, gpointer data);
+static void uri_opener_select_all_cb   (GtkWidget *widget, gpointer data);
 static gboolean key_pressed            (GtkWidget *widget, GdkEventKey *event,
                                         gpointer data);
 static void uri_opener_double_clicked(GtkTreeView              *list_view,
@@ -70,10 +73,10 @@ static void uri_opener_double_clicked(GtkTreeView           *list_view,
 static void uri_opener_create(void);
 void uri_opener_open(MessageView *msgview, GSList *uris)
 {
-       g_return_if_fail(msgview);
-       g_return_if_fail(msgview->mimeview);
-       g_return_if_fail(msgview->mimeview->textview);
-       g_return_if_fail(msgview);
+       cm_return_if_fail(msgview);
+       cm_return_if_fail(msgview->mimeview);
+       cm_return_if_fail(msgview->mimeview->textview);
+       cm_return_if_fail(msgview);
        if (!opener.window)
                uri_opener_create();
 
@@ -111,7 +114,7 @@ static void uri_opener_create_list_view_columns(GtkWidget *list_view)
        column = gtk_tree_view_column_new_with_attributes
                (_("Available URLs:"),
                 renderer,
-                "text", URI_OPENER_URL,
+                "markup", URI_OPENER_URL,
                 NULL);
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
 }
@@ -129,7 +132,7 @@ static GtkWidget *uri_opener_list_view_create       (void)
        gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
        
        selector = gtk_tree_view_get_selection(list_view);
-       gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
+       gtk_tree_selection_set_mode(selector, GTK_SELECTION_MULTIPLE);
 
        g_signal_connect(G_OBJECT(list_view), "row_activated",
                         G_CALLBACK(uri_opener_double_clicked),
@@ -142,42 +145,69 @@ static GtkWidget *uri_opener_list_view_create     (void)
 
 }
 
+static GtkWidget *uri_opener_scrolled_win_create(void)
+{
+       GtkWidget *scrolledwin;
+
+       scrolledwin = gtk_scrolled_window_new(NULL, NULL);
+       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
+                                           GTK_SHADOW_ETCHED_IN);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
+                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+                                      
+       gtk_widget_set_size_request(scrolledwin, 200, 250);
+       gtk_widget_show(scrolledwin);
+       
+       return scrolledwin;
+}
+
+static void uri_opener_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation)
+{
+       cm_return_if_fail(allocation != NULL);
+
+       prefs_common.uriopenerwin_width = allocation->width;
+       prefs_common.uriopenerwin_height = allocation->height;
+}
+
 static void uri_opener_create(void) 
 {
        GtkWidget *window;
+       GtkWidget *hbox_scroll;
+       GtkWidget *hbox;
        GtkWidget *hbox1;
        GtkWidget *vbox1;
        GtkWidget *label;
        GtkWidget *urilist;
+       GtkWidget *select_all_btn;
        GtkWidget *open_btn;
-       GtkWidget *open_all_btn;
        GtkWidget *close_btn;
        GtkWidget *scrolledwin;
+       static GdkGeometry geometry;
 
        window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "uri_opener");
        gtk_window_set_title (GTK_WINDOW(window),
-                             Q_("Dialog title|Open URLs"));
+                             C_("Dialog title", "Open URLs"));
 
        gtk_container_set_border_width (GTK_CONTAINER (window), 8);
        gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
        gtk_window_set_resizable(GTK_WINDOW (window), TRUE);
+       gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
        g_signal_connect(G_OBJECT(window), "delete_event",
                         G_CALLBACK(uri_opener_close_cb), NULL);
+       g_signal_connect (G_OBJECT(window), "size_allocate",
+                        G_CALLBACK (uri_opener_size_allocate_cb), NULL);
        g_signal_connect(G_OBJECT(window), "key_press_event",
                         G_CALLBACK(key_pressed), NULL);
        MANAGE_WINDOW_SIGNALS_CONNECT (window);
 
        vbox1 = gtk_vbox_new(FALSE, 6);
        gtkut_stock_button_set_create(&hbox1, 
+                                     &open_btn, GTK_STOCK_OPEN,
                                      &close_btn, GTK_STOCK_CLOSE,
-                                     &open_all_btn, _("Open _All"),
-                                     &open_btn, GTK_STOCK_OPEN);
+                                     NULL, NULL);
 
        g_signal_connect(G_OBJECT(open_btn), "clicked",
-                        G_CALLBACK(uri_opener_open_cb), GINT_TO_POINTER(FALSE));
-
-       g_signal_connect(G_OBJECT(open_all_btn), "clicked",
-                        G_CALLBACK(uri_opener_open_cb), GINT_TO_POINTER(TRUE));
+                        G_CALLBACK(uri_opener_open_cb), NULL);
 
        g_signal_connect(G_OBJECT(close_btn), "clicked",
                         G_CALLBACK(uri_opener_close_cb), NULL);
@@ -188,33 +218,44 @@ static void uri_opener_create(void)
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
        gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, TRUE, 0);
        
-       scrolledwin = gtk_scrolled_window_new(NULL, NULL);
-       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
-                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-                                      
-       gtk_widget_set_size_request(scrolledwin, 500, 250);
+       scrolledwin = uri_opener_scrolled_win_create();
+       hbox_scroll = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox_scroll), scrolledwin, TRUE, TRUE, 0);
+       
+       select_all_btn = gtk_button_new_with_label(_("Select All"));
+       g_signal_connect(G_OBJECT(select_all_btn), "clicked",
+                        G_CALLBACK(uri_opener_select_all_cb), NULL);   
 
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox), select_all_btn, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(""), TRUE, TRUE, 0);
+       
        gtk_container_add(GTK_CONTAINER(scrolledwin), urilist);
-       gtk_box_pack_start(GTK_BOX(vbox1), scrolledwin, TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox1), hbox_scroll, TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
        
-       gtk_widget_show(label);
-       gtk_widget_show(scrolledwin);
-       gtk_widget_show(urilist);
-       gtk_widget_show(hbox1);
-       gtk_widget_show(vbox1);
-       gtk_widget_show(close_btn);
-       gtk_widget_show(open_btn);
-       gtk_widget_show(open_all_btn);
+       gtk_widget_show_all(vbox1);
        gtk_container_add(GTK_CONTAINER (window), vbox1);
 
+       if (!geometry.min_height) {
+               geometry.min_width = 450;
+               geometry.min_height = 300;
+       }
+
+       gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
+                                     GDK_HINT_MIN_SIZE);
+       gtk_widget_set_size_request(window, prefs_common.uriopenerwin_width,
+                                   prefs_common.uriopenerwin_height);
+
        opener.window = window;
+       opener.hbox_scroll = hbox_scroll;
        opener.hbox1 = hbox1;
        opener.vbox1 = vbox1;
        opener.label = label;
        opener.urilist = urilist;
+       opener.scrolledwin = scrolledwin;
        opener.open_btn = open_btn;
-       opener.open_all_btn = open_all_btn;
        opener.close_btn = close_btn;
 
 }
@@ -228,20 +269,28 @@ static void uri_opener_list_view_insert_uri(GtkWidget *list_view,
                                        (GTK_TREE_VIEW(list_view)));
        gchar *visible = textview_get_visible_uri(opener.msgview->mimeview->textview, uri);
        
+       gchar *label = NULL;
+       
+       if (visible && strcmp(visible, uri->uri))
+               label = g_markup_printf_escaped("<b>%s</b>\n%s", visible, uri->uri);
+       else
+               label = g_markup_printf_escaped("\n%s", uri->uri);
+
        if (row_iter == NULL) {
                /* append new */
                gtk_list_store_append(list_store, &iter);
                gtk_list_store_set(list_store, &iter,
-                                  URI_OPENER_URL, visible?visible:uri->uri,
+                                  URI_OPENER_URL, label,
                                   URI_OPENER_DATA, uri,
                                   -1);
        } else {
                gtk_list_store_set(list_store, row_iter,
-                                  URI_OPENER_URL, visible?visible:uri->uri,
+                                  URI_OPENER_URL, label,
                                   URI_OPENER_DATA, uri,
                                   -1);
        }
        g_free(visible);
+       g_free(label);
 }
 
 static void uri_opener_list_view_clear_uris(GtkWidget *list_view)
@@ -254,18 +303,38 @@ static void uri_opener_list_view_clear_uris(GtkWidget *list_view)
 static void uri_opener_load_uris (void) 
 {
        GSList *cur = opener.uris;
+       GtkTreeModel *model;
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
        
        uri_opener_list_view_clear_uris(opener.urilist);
        for (; cur; cur = cur->next) {
                ClickableText *uri = (ClickableText *)cur->data;
                uri_opener_list_view_insert_uri(opener.urilist, NULL, uri);
        }
+       
+       g_object_ref(opener.urilist);
+       gtk_container_remove(GTK_CONTAINER(opener.scrolledwin), opener.urilist);
+       gtk_widget_destroy(opener.scrolledwin);
+       
+       opener.scrolledwin = uri_opener_scrolled_win_create();
+       gtk_container_add(GTK_CONTAINER(opener.scrolledwin), opener.urilist);
+       gtk_box_pack_start(GTK_BOX(opener.hbox_scroll),
+                          opener.scrolledwin, TRUE, TRUE, 0);
+       g_object_unref(opener.urilist);
+       
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(opener.urilist));
+       if (!gtk_tree_model_get_iter_first(model, &iter))
+               return;
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(opener.urilist));
+       gtk_tree_selection_select_iter(selection, &iter);
 }
 
 static void uri_opener_close(void) 
 {
        g_slist_free(opener.uris);
        opener.uris = NULL;
+       gtk_window_set_modal(GTK_WINDOW(opener.window), FALSE);
        gtk_widget_hide(opener.window);
 }
 
@@ -277,7 +346,7 @@ static void uri_opener_close_cb(GtkWidget *widget,
 
 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
-       if (event && event->keyval == GDK_Escape)
+       if (event && event->keyval == GDK_KEY_Escape)
                uri_opener_close();
        return FALSE;
 }
@@ -306,40 +375,43 @@ static void uri_opener_double_clicked(GtkTreeView         *list_view,
                         prefs_common_get_uri_cmd());
 }
 
-
-
-
 static void uri_opener_open_cb(GtkWidget *widget, 
                                gpointer data) 
 {
        ClickableText *uri;
        GtkTreeIter sel;
        GtkTreeModel *model;
-       gboolean all = GPOINTER_TO_INT(data);
-
-       if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection
-                               (GTK_TREE_VIEW(opener.urilist)),
-                               &model, &sel))
-               return;
-       
-       if (!all) {
+       GtkTreeSelection *selection;
+       GList *selected, *cur;
+
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(opener.urilist));
+       selected  = gtk_tree_selection_get_selected_rows(selection, &model);
+       cm_return_if_fail(selected);
+               
+       for(cur = selected; cur != NULL; cur = g_list_next(cur))
+       { 
+               if(!gtk_tree_model_get_iter(model, &sel, (GtkTreePath *)cur->data))
+                       continue;
+               
                gtk_tree_model_get(model, &sel,
                           URI_OPENER_DATA, &uri,
                           -1);
                if (!uri)
-                       return;
+                       continue;
 
                if (textview_uri_security_check(opener.msgview->mimeview->textview, uri) == TRUE) 
                        open_uri(uri->uri,
                                 prefs_common_get_uri_cmd());
-       } else {
-               GSList *cur = opener.uris;
-
-               for (; cur; cur = cur->next) {
-                       uri = (ClickableText *)cur->data;
-                       if (textview_uri_security_check(opener.msgview->mimeview->textview, uri) == TRUE) 
-                               open_uri(uri->uri,
-                                        prefs_common_get_uri_cmd());
-               }
        }
+       
+       g_list_foreach(selected, (GFunc)gtk_tree_path_free, NULL);
+       g_list_free(selected);
+}
+
+static void uri_opener_select_all_cb(GtkWidget *widget, 
+                                    gpointer data)
+{
+       GtkTreeSelection *selection = gtk_tree_view_get_selection(
+                                               GTK_TREE_VIEW(opener.urilist));
+       gtk_tree_selection_select_all(selection);
 }