2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
35 #include "alertpanel.h"
36 #include "prefs_common.h"
39 #include "manage_window.h"
42 PLUGINWINDOW_NAME
, /*<! plugin name */
43 PLUGINWINDOW_DATA
, /*<! Plugin pointer */
44 PLUGINWINDOW_STYLE
, /*<! italic if error */
45 N_PLUGINWINDOW_COLUMNS
48 typedef struct _PluginWindow
51 GtkWidget
*plugin_list_view
;
52 GtkWidget
*plugin_desc
;
53 GtkWidget
*unload_btn
;
55 Plugin
*selected_plugin
;
58 static GtkListStore
* pluginwindow_create_data_store (void);
59 static GtkWidget
*pluginwindow_list_view_create (PluginWindow
*pluginwindow
);
60 static void pluginwindow_create_list_view_columns (GtkWidget
*list_view
);
61 static gboolean
pluginwindow_selected (GtkTreeSelection
*selector
,
64 gboolean currently_selected
,
67 static void close_cb(GtkButton
*button
, PluginWindow
*pluginwindow
)
69 gtk_widget_destroy(pluginwindow
->window
);
75 static void set_plugin_list(PluginWindow
*pluginwindow
)
77 GSList
*plugins
, *cur
, *unloaded
;
81 GtkTextBuffer
*textbuf
;
82 GtkTextIter start_iter
, end_iter
;
83 GtkTreeSelection
*selection
;
85 plugins
= plugin_get_list();
86 unloaded
= plugin_get_unloaded_list();
88 store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW
89 (pluginwindow
->plugin_list_view
)));
90 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store
),
91 0, GTK_SORT_ASCENDING
);
92 gtk_list_store_clear(store
);
94 textbuf
= gtk_text_view_get_buffer(GTK_TEXT_VIEW(pluginwindow
->plugin_desc
));
95 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(pluginwindow
->plugin_desc
), FALSE
);
96 gtk_text_view_set_editable(GTK_TEXT_VIEW(pluginwindow
->plugin_desc
), FALSE
);
97 gtk_text_buffer_get_start_iter(textbuf
, &start_iter
);
98 gtk_text_buffer_get_end_iter(textbuf
, &end_iter
);
99 gtk_text_buffer_delete(textbuf
, &start_iter
, &end_iter
);
100 gtk_widget_set_sensitive(pluginwindow
->unload_btn
, FALSE
);
102 for(cur
= plugins
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
103 Plugin
*plugin
= (Plugin
*) cur
->data
;
105 gtk_list_store_append(store
, &iter
);
106 text
= plugin_get_name(plugin
);
107 gtk_list_store_set(store
, &iter
,
108 PLUGINWINDOW_NAME
, text
,
109 PLUGINWINDOW_DATA
, plugin
,
110 PLUGINWINDOW_STYLE
, PANGO_STYLE_NORMAL
,
114 for(cur
= unloaded
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
115 Plugin
*plugin
= (Plugin
*) cur
->data
;
117 gtk_list_store_append(store
, &iter
);
118 text
= plugin_get_name(plugin
);
119 gtk_list_store_set(store
, &iter
,
120 PLUGINWINDOW_NAME
, text
,
121 PLUGINWINDOW_DATA
, plugin
,
122 PLUGINWINDOW_STYLE
, PANGO_STYLE_ITALIC
,
126 if (pluginwindow
->selected_plugin
== NULL
) {
127 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW
128 (pluginwindow
->plugin_list_view
));
129 gtk_tree_selection_unselect_all(selection
);
131 g_slist_free(plugins
);
134 static void select_row_cb(Plugin
*plugin
, PluginWindow
*pluginwindow
)
136 GtkTextView
*plugin_desc
= GTK_TEXT_VIEW(pluginwindow
->plugin_desc
);
137 GtkTextBuffer
*textbuf
= gtk_text_view_get_buffer(plugin_desc
);
138 GtkTextIter start_iter
, end_iter
;
141 pluginwindow
->selected_plugin
= plugin
;
143 if (pluginwindow
->selected_plugin
!= NULL
) {
144 const gchar
*desc
= plugin_get_desc(plugin
);
145 const gchar
*err
= plugin_get_error(plugin
);
146 gtk_text_buffer_get_start_iter(textbuf
, &start_iter
);
147 gtk_text_buffer_get_end_iter(textbuf
, &end_iter
);
148 gtk_text_buffer_delete(textbuf
, &start_iter
, &end_iter
);
151 text
= g_strconcat(desc
, _("\n\nVersion: "),
152 plugin_get_version(plugin
), "\n", NULL
);
154 text
= g_strconcat(_("Error: "),
155 err
, "\n", _("Plugin is not functional."),
156 "\n\n", desc
, _("\n\nVersion: "),
157 plugin_get_version(plugin
), "\n", NULL
);
158 gtk_text_buffer_insert(textbuf
, &start_iter
, text
, strlen(text
));
160 gtk_widget_set_sensitive(pluginwindow
->unload_btn
, TRUE
);
162 gtk_widget_set_sensitive(pluginwindow
->unload_btn
, FALSE
);
166 static void unselect_row_cb(Plugin
*plugin
, PluginWindow
*pluginwindow
)
168 gtk_widget_set_sensitive(pluginwindow
->unload_btn
, FALSE
);
171 static void unload_cb(GtkButton
*button
, PluginWindow
*pluginwindow
)
173 Plugin
*plugin
= pluginwindow
->selected_plugin
;
175 g_return_if_fail(plugin
!= NULL
);
176 plugin_unload(plugin
);
177 pluginwindow
->selected_plugin
= NULL
;
178 set_plugin_list(pluginwindow
);
181 static void load_cb(GtkButton
*button
, PluginWindow
*pluginwindow
)
185 file_list
= filesel_select_multiple_files_open_with_filter(
186 _("Select the Plugins to load"), get_plugin_dir(),
187 "*." G_MODULE_SUFFIX
);
192 for ( tmp
= file_list
; tmp
; tmp
= tmp
->next
) {
193 gchar
*file
, *error
= NULL
;
195 file
= (gchar
*) tmp
->data
;
197 plugin_load(file
, &error
);
199 gchar
*basename
= g_path_get_basename(file
);
201 _("The following error occured while loading %s :\n\n%s\n"),
207 /* FIXME: globally or atom-ly : ? */
208 set_plugin_list(pluginwindow
);
212 g_list_free(file_list
);
216 static gboolean
pluginwindow_key_pressed(GtkWidget
*widget
, GdkEventKey
*event
,
217 PluginWindow
*pluginwindow
)
220 switch (event
->keyval
) {
224 close_cb(NULL
, pluginwindow
);
230 load_cb(NULL
, pluginwindow
);
234 case GDK_KP_Subtract
:
236 unload_cb(NULL
, pluginwindow
);
246 *\brief Save Gtk object size to prefs dataset
248 static void pluginwindow_size_allocate_cb(GtkWidget
*widget
,
249 GtkAllocation
*allocation
)
251 g_return_if_fail(allocation
!= NULL
);
253 prefs_common
.pluginswin_width
= allocation
->width
;
254 prefs_common
.pluginswin_height
= allocation
->height
;
258 void pluginwindow_create()
260 PluginWindow
*pluginwindow
;
264 GtkWidget
*scrolledwindow2
;
265 GtkWidget
*plugin_list_view
;
269 GtkWidget
*scrolledwindow3
;
270 GtkWidget
*plugin_desc
;
271 GtkWidget
*hbuttonbox1
, *hbox3
;
274 GtkWidget
*unload_btn
;
275 GtkWidget
*close_btn
;
276 GtkWidget
*get_more_btn
;
278 static GdkGeometry geometry
;
279 GtkTooltips
*tooltips
;
281 debug_print("Creating plugins window...\n");
283 pluginwindow
= g_new0(PluginWindow
, 1);
285 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
286 gtk_container_set_border_width(GTK_CONTAINER(window
), 8);
287 gtk_window_set_title(GTK_WINDOW(window
), _("Plugins"));
288 gtk_window_set_modal(GTK_WINDOW(window
), TRUE
);
289 manage_window_set_transient(GTK_WINDOW(window
));
291 vbox1
= gtk_vbox_new(FALSE
, 4);
292 gtk_widget_show(vbox1
);
293 gtk_container_add(GTK_CONTAINER(window
), vbox1
);
294 gtk_box_set_homogeneous(GTK_BOX(vbox1
), FALSE
);
295 gtk_widget_realize(window
);
297 hbox2
= gtk_hbox_new(FALSE
, 8);
298 gtk_widget_show(hbox2
);
299 gtk_box_pack_start(GTK_BOX(vbox1
), hbox2
, TRUE
, TRUE
, 0);
301 scrolledwindow2
= gtk_scrolled_window_new(NULL
, NULL
);
302 gtk_widget_show(scrolledwindow2
);
303 gtk_box_pack_start(GTK_BOX(hbox2
), scrolledwindow2
, FALSE
, FALSE
, 0);
304 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW
305 (scrolledwindow2
), GTK_POLICY_NEVER
,
306 GTK_POLICY_AUTOMATIC
);
308 plugin_list_view
= pluginwindow_list_view_create(pluginwindow
);
309 gtk_widget_show(plugin_list_view
);
310 gtk_container_add(GTK_CONTAINER(scrolledwindow2
), plugin_list_view
);
311 gtk_widget_grab_focus(GTK_WIDGET(plugin_list_view
));
313 vbox2
= gtk_vbox_new(FALSE
, 0);
314 gtk_widget_show(vbox2
);
315 gtk_box_pack_start(GTK_BOX(hbox2
), vbox2
, TRUE
, TRUE
, 0);
317 frame2
= gtk_frame_new(NULL
);
318 gtk_widget_show(frame2
);
319 gtk_box_pack_start(GTK_BOX(vbox2
), frame2
, FALSE
, TRUE
, 0);
321 label13
= gtk_label_new(_("Description"));
322 gtk_widget_show(label13
);
323 gtk_container_add(GTK_CONTAINER(frame2
), label13
);
324 gtk_misc_set_alignment(GTK_MISC(label13
), 0, 0.5);
325 gtk_misc_set_padding(GTK_MISC(label13
), 2, 2);
327 scrolledwindow3
= gtk_scrolled_window_new(NULL
, NULL
);
328 gtk_widget_show(scrolledwindow3
);
329 gtk_box_pack_start(GTK_BOX(vbox2
), scrolledwindow3
, TRUE
, TRUE
, 0);
330 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW
331 (scrolledwindow3
), GTK_POLICY_NEVER
,
334 plugin_desc
= gtk_text_view_new();
335 gtk_widget_show(plugin_desc
);
336 gtk_container_add(GTK_CONTAINER(scrolledwindow3
), plugin_desc
);
338 desc_lbl
= gtk_label_new(_("More plugins are available from the "
339 "Claws Mail website."));
340 gtk_misc_set_alignment(GTK_MISC(desc_lbl
), 0, 0.5);
341 gtk_widget_show(desc_lbl
);
342 gtk_box_pack_start(GTK_BOX(vbox1
), desc_lbl
, FALSE
, FALSE
, 0);
344 get_more_btn
= gtkut_get_link_btn(window
, PLUGINS_URI
, _("Get more..."));
345 gtk_misc_set_alignment(GTK_MISC(GTK_BIN(get_more_btn
)->child
), 0, 0.5);
346 gtk_widget_show(get_more_btn
);
347 gtk_box_pack_start(GTK_BOX(vbox1
), get_more_btn
, FALSE
, FALSE
, 0);
349 hbox3
= gtk_hbox_new(TRUE
, 0);
350 gtk_widget_show(hbox3
);
351 gtk_box_pack_start(GTK_BOX(vbox1
), hbox3
, FALSE
, FALSE
, 0);
353 gtkut_stock_button_set_create_with_help(&hbuttonbox1
, &help_btn
,
354 &load_btn
, _("Load Plugin..."),
355 &unload_btn
, _("Unload Plugin"),
356 &close_btn
, GTK_STOCK_CLOSE
);
357 gtk_box_set_spacing(GTK_BOX(hbuttonbox1
), 6);
358 gtk_widget_show(hbuttonbox1
);
359 gtk_box_pack_end(GTK_BOX(hbox3
), hbuttonbox1
, FALSE
, FALSE
, 0);
361 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(plugin_desc
), GTK_WRAP_WORD
);
362 gtk_widget_set_sensitive(GTK_WIDGET(unload_btn
), FALSE
);
364 g_signal_connect(G_OBJECT(help_btn
), "clicked",
365 G_CALLBACK(manual_open_with_anchor_cb
),
366 MANUAL_ANCHOR_PLUGINS
);
367 g_signal_connect(G_OBJECT(load_btn
), "clicked",
368 G_CALLBACK(load_cb
), pluginwindow
);
369 g_signal_connect(G_OBJECT(unload_btn
), "clicked",
370 G_CALLBACK(unload_cb
), pluginwindow
);
371 g_signal_connect(G_OBJECT(close_btn
), "clicked",
372 G_CALLBACK(close_cb
), pluginwindow
);
373 g_signal_connect(G_OBJECT(window
), "size_allocate",
374 G_CALLBACK(pluginwindow_size_allocate_cb
), NULL
);
375 g_signal_connect(G_OBJECT(window
), "key_press_event",
376 G_CALLBACK(pluginwindow_key_pressed
), pluginwindow
);
378 tooltips
= gtk_tooltips_new();
380 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips
),
382 _("Click here to load one or more plugins"), NULL
);
384 gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips
),
386 _("Unload the selected plugin"), NULL
);
388 pluginwindow
->window
= window
;
389 pluginwindow
->plugin_list_view
= plugin_list_view
;
390 pluginwindow
->plugin_desc
= plugin_desc
;
391 pluginwindow
->unload_btn
= unload_btn
;
392 pluginwindow
->selected_plugin
= NULL
;
394 set_plugin_list(pluginwindow
);
398 if (!geometry
.min_height
) {
399 geometry
.min_width
= 480;
400 geometry
.min_height
= 300;
403 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &geometry
,
405 gtk_widget_set_size_request(window
, prefs_common
.pluginswin_width
,
406 prefs_common
.pluginswin_height
);
408 gtk_widget_show(window
);
411 static GtkListStore
* pluginwindow_create_data_store(void)
413 return gtk_list_store_new(N_PLUGINWINDOW_COLUMNS
,
420 static GtkWidget
*pluginwindow_list_view_create(PluginWindow
*pluginwindow
)
422 GtkTreeView
*list_view
;
423 GtkTreeSelection
*selector
;
426 model
= GTK_TREE_MODEL(pluginwindow_create_data_store());
427 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
428 g_object_unref(model
);
430 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
431 gtk_tree_view_set_search_column (list_view
, 0);
433 selector
= gtk_tree_view_get_selection(list_view
);
434 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
435 gtk_tree_selection_set_select_function(selector
, pluginwindow_selected
,
438 /* create the columns */
439 pluginwindow_create_list_view_columns(GTK_WIDGET(list_view
));
441 return GTK_WIDGET(list_view
);
444 static void pluginwindow_create_list_view_columns(GtkWidget
*list_view
)
446 GtkTreeViewColumn
*column
;
447 GtkCellRenderer
*renderer
;
449 renderer
= gtk_cell_renderer_text_new();
450 column
= gtk_tree_view_column_new_with_attributes
451 (_("Loaded plugins"),
453 "text", PLUGINWINDOW_NAME
,
454 "style", PLUGINWINDOW_STYLE
,
456 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
459 static gboolean
pluginwindow_selected(GtkTreeSelection
*selector
,
462 gboolean currently_selected
,
468 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
471 gtk_tree_model_get(model
, &iter
,
472 PLUGINWINDOW_DATA
, &plugin
,
475 if (currently_selected
)
476 unselect_row_cb(plugin
, data
);
478 select_row_cb(plugin
, data
);