2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Colin Leroy <colin@colino.net> and
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "claws-features.h"
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <sys/types.h>
32 #include "manage_window.h"
34 #include "mainwindow.h"
36 #include "alertpanel.h"
39 #include "prefs_common.h"
48 static struct URIOpener
51 GtkWidget
*hbox_scroll
;
56 GtkWidget
*scrolledwin
;
63 static void uri_opener_load_uris (void);
64 static void uri_opener_open_cb (GtkWidget
*widget
, gpointer data
);
65 static void uri_opener_close_cb (GtkWidget
*widget
, gpointer data
);
66 static void uri_opener_select_all_cb (GtkWidget
*widget
, gpointer data
);
67 static gboolean
key_pressed (GtkWidget
*widget
, GdkEventKey
*event
,
69 static void uri_opener_double_clicked(GtkTreeView
*list_view
,
71 GtkTreeViewColumn
*column
,
73 static void uri_opener_create(void);
74 void uri_opener_open(MessageView
*msgview
, GSList
*uris
)
76 cm_return_if_fail(msgview
);
77 cm_return_if_fail(msgview
->mimeview
);
78 cm_return_if_fail(msgview
->mimeview
->textview
);
79 cm_return_if_fail(msgview
);
83 manage_window_set_transient(GTK_WINDOW(opener
.window
));
84 gtk_widget_grab_focus(opener
.close_btn
);
87 alertpanel_notice(_("There are no URLs in this email."));
91 opener
.msgview
= msgview
;
92 opener
.uris
= g_slist_copy(uris
);
93 uri_opener_load_uris();
95 gtk_widget_show(opener
.window
);
96 gtk_widget_grab_focus(opener
.urilist
);
97 gtk_window_set_modal(GTK_WINDOW(opener
.window
), TRUE
);
100 static GtkListStore
* uri_opener_create_data_store(void)
102 return gtk_list_store_new(N_URI_OPENER_COLUMNS
,
108 static void uri_opener_create_list_view_columns(GtkWidget
*list_view
)
110 GtkTreeViewColumn
*column
;
111 GtkCellRenderer
*renderer
;
113 renderer
= gtk_cell_renderer_text_new();
114 column
= gtk_tree_view_column_new_with_attributes
115 (_("Available URLs:"),
117 "markup", URI_OPENER_URL
,
119 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
122 static GtkWidget
*uri_opener_list_view_create (void)
124 GtkTreeView
*list_view
;
125 GtkTreeSelection
*selector
;
128 model
= GTK_TREE_MODEL(uri_opener_create_data_store());
129 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
130 g_object_unref(model
);
132 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
134 selector
= gtk_tree_view_get_selection(list_view
);
135 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_MULTIPLE
);
137 g_signal_connect(G_OBJECT(list_view
), "row_activated",
138 G_CALLBACK(uri_opener_double_clicked
),
141 /* create the columns */
142 uri_opener_create_list_view_columns(GTK_WIDGET(list_view
));
144 return GTK_WIDGET(list_view
);
148 static GtkWidget
*uri_opener_scrolled_win_create(void)
150 GtkWidget
*scrolledwin
;
152 scrolledwin
= gtk_scrolled_window_new(NULL
, NULL
);
153 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin
),
154 GTK_SHADOW_ETCHED_IN
);
155 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin
),
156 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
158 gtk_widget_set_size_request(scrolledwin
, 200, 250);
159 gtk_widget_show(scrolledwin
);
164 static void uri_opener_size_allocate_cb(GtkWidget
*widget
, GtkAllocation
*allocation
)
166 cm_return_if_fail(allocation
!= NULL
);
168 prefs_common
.uriopenerwin_width
= allocation
->width
;
169 prefs_common
.uriopenerwin_height
= allocation
->height
;
172 static void uri_opener_create(void)
175 GtkWidget
*hbox_scroll
;
181 GtkWidget
*select_all_btn
;
183 GtkWidget
*close_btn
;
184 GtkWidget
*scrolledwin
;
185 static GdkGeometry geometry
;
187 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "uri_opener");
188 gtk_window_set_title (GTK_WINDOW(window
),
189 C_("Dialog title", "Open URLs"));
191 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
192 gtk_window_set_position (GTK_WINDOW (window
), GTK_WIN_POS_CENTER
);
193 gtk_window_set_resizable(GTK_WINDOW (window
), TRUE
);
194 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
195 g_signal_connect(G_OBJECT(window
), "delete_event",
196 G_CALLBACK(uri_opener_close_cb
), NULL
);
197 g_signal_connect (G_OBJECT(window
), "size_allocate",
198 G_CALLBACK (uri_opener_size_allocate_cb
), NULL
);
199 g_signal_connect(G_OBJECT(window
), "key_press_event",
200 G_CALLBACK(key_pressed
), NULL
);
201 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
203 vbox1
= gtk_vbox_new(FALSE
, 6);
204 gtkut_stock_button_set_create(&hbox1
,
205 &open_btn
, GTK_STOCK_OPEN
,
206 &close_btn
, GTK_STOCK_CLOSE
,
209 g_signal_connect(G_OBJECT(open_btn
), "clicked",
210 G_CALLBACK(uri_opener_open_cb
), NULL
);
212 g_signal_connect(G_OBJECT(close_btn
), "clicked",
213 G_CALLBACK(uri_opener_close_cb
), NULL
);
215 urilist
= uri_opener_list_view_create();
217 label
= gtk_label_new(_("Please select the URL to open."));
218 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0.5);
219 gtk_box_pack_start(GTK_BOX(vbox1
), label
, FALSE
, TRUE
, 0);
221 scrolledwin
= uri_opener_scrolled_win_create();
222 hbox_scroll
= gtk_hbox_new(FALSE
, 0);
223 gtk_box_pack_start(GTK_BOX(hbox_scroll
), scrolledwin
, TRUE
, TRUE
, 0);
225 select_all_btn
= gtk_button_new_with_label(_("Select All"));
226 g_signal_connect(G_OBJECT(select_all_btn
), "clicked",
227 G_CALLBACK(uri_opener_select_all_cb
), NULL
);
229 hbox
= gtk_hbox_new(FALSE
, 0);
230 gtk_box_pack_start(GTK_BOX(hbox
), select_all_btn
, FALSE
, FALSE
, 0);
231 gtk_box_pack_start(GTK_BOX(hbox
), gtk_label_new(""), TRUE
, TRUE
, 0);
233 gtk_container_add(GTK_CONTAINER(scrolledwin
), urilist
);
234 gtk_box_pack_start(GTK_BOX(vbox1
), hbox_scroll
, TRUE
, TRUE
, 0);
235 gtk_box_pack_start(GTK_BOX(vbox1
), hbox
, FALSE
, FALSE
, 0);
236 gtk_box_pack_start(GTK_BOX(vbox1
), hbox1
, FALSE
, FALSE
, 0);
238 gtk_widget_show_all(vbox1
);
239 gtk_container_add(GTK_CONTAINER (window
), vbox1
);
241 if (!geometry
.min_height
) {
242 geometry
.min_width
= 450;
243 geometry
.min_height
= 300;
246 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
248 gtk_widget_set_size_request(window
, prefs_common
.uriopenerwin_width
,
249 prefs_common
.uriopenerwin_height
);
251 opener
.window
= window
;
252 opener
.hbox_scroll
= hbox_scroll
;
253 opener
.hbox1
= hbox1
;
254 opener
.vbox1
= vbox1
;
255 opener
.label
= label
;
256 opener
.urilist
= urilist
;
257 opener
.scrolledwin
= scrolledwin
;
258 opener
.open_btn
= open_btn
;
259 opener
.close_btn
= close_btn
;
263 static void uri_opener_list_view_insert_uri(GtkWidget
*list_view
,
264 GtkTreeIter
*row_iter
,
268 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model
269 (GTK_TREE_VIEW(list_view
)));
270 gchar
*visible
= textview_get_visible_uri(opener
.msgview
->mimeview
->textview
, uri
);
274 if (visible
&& strcmp(visible
, uri
->uri
))
275 label
= g_markup_printf_escaped("<b>%s</b>\n%s", visible
, uri
->uri
);
277 label
= g_markup_printf_escaped("\n%s", uri
->uri
);
279 if (row_iter
== NULL
) {
281 gtk_list_store_append(list_store
, &iter
);
282 gtk_list_store_set(list_store
, &iter
,
283 URI_OPENER_URL
, label
,
284 URI_OPENER_DATA
, uri
,
287 gtk_list_store_set(list_store
, row_iter
,
288 URI_OPENER_URL
, label
,
289 URI_OPENER_DATA
, uri
,
296 static void uri_opener_list_view_clear_uris(GtkWidget
*list_view
)
298 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model
299 (GTK_TREE_VIEW(list_view
)));
300 gtk_list_store_clear(list_store
);
303 static void uri_opener_load_uris (void)
305 GSList
*cur
= opener
.uris
;
307 GtkTreeSelection
*selection
;
310 uri_opener_list_view_clear_uris(opener
.urilist
);
311 for (; cur
; cur
= cur
->next
) {
312 ClickableText
*uri
= (ClickableText
*)cur
->data
;
313 uri_opener_list_view_insert_uri(opener
.urilist
, NULL
, uri
);
316 g_object_ref(opener
.urilist
);
317 gtk_container_remove(GTK_CONTAINER(opener
.scrolledwin
), opener
.urilist
);
318 gtk_widget_destroy(opener
.scrolledwin
);
320 opener
.scrolledwin
= uri_opener_scrolled_win_create();
321 gtk_container_add(GTK_CONTAINER(opener
.scrolledwin
), opener
.urilist
);
322 gtk_box_pack_start(GTK_BOX(opener
.hbox_scroll
),
323 opener
.scrolledwin
, TRUE
, TRUE
, 0);
324 g_object_unref(opener
.urilist
);
326 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(opener
.urilist
));
327 if (!gtk_tree_model_get_iter_first(model
, &iter
))
329 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(opener
.urilist
));
330 gtk_tree_selection_select_iter(selection
, &iter
);
333 static void uri_opener_close(void)
335 g_slist_free(opener
.uris
);
337 gtk_window_set_modal(GTK_WINDOW(opener
.window
), FALSE
);
338 gtk_widget_hide(opener
.window
);
341 static void uri_opener_close_cb(GtkWidget
*widget
,
347 static gboolean
key_pressed(GtkWidget
*widget
, GdkEventKey
*event
, gpointer data
)
349 if (event
&& event
->keyval
== GDK_KEY_Escape
)
354 static void uri_opener_double_clicked(GtkTreeView
*list_view
,
356 GtkTreeViewColumn
*column
,
361 GtkTreeModel
*model
= gtk_tree_view_get_model(list_view
);
363 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
366 gtk_tree_model_get(model
, &iter
,
367 URI_OPENER_DATA
, &uri
,
373 if (textview_uri_security_check(opener
.msgview
->mimeview
->textview
, uri
) == TRUE
)
375 prefs_common_get_uri_cmd());
378 static void uri_opener_open_cb(GtkWidget
*widget
,
384 GtkTreeSelection
*selection
;
385 GList
*selected
, *cur
;
387 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(opener
.urilist
));
388 selected
= gtk_tree_selection_get_selected_rows(selection
, &model
);
389 cm_return_if_fail(selected
);
391 for(cur
= selected
; cur
!= NULL
; cur
= g_list_next(cur
))
393 if(!gtk_tree_model_get_iter(model
, &sel
, (GtkTreePath
*)cur
->data
))
396 gtk_tree_model_get(model
, &sel
,
397 URI_OPENER_DATA
, &uri
,
402 if (textview_uri_security_check(opener
.msgview
->mimeview
->textview
, uri
) == TRUE
)
404 prefs_common_get_uri_cmd());
407 g_list_foreach(selected
, (GFunc
)gtk_tree_path_free
, NULL
);
408 g_list_free(selected
);
411 static void uri_opener_select_all_cb(GtkWidget
*widget
,
414 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(
415 GTK_TREE_VIEW(opener
.urilist
));
416 gtk_tree_selection_select_all(selection
);