1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * heavily based on code from Gedit
5 * Copyright (C) 2002 Paolo Maggi and James Willcox
6 * Copyright (C) 2003-2005 Paolo Maggi
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
30 #include <glib/gi18n.h>
31 #include <glade/glade-xml.h>
33 #include "rb-plugin-manager.h"
34 #include "rb-plugins-engine.h"
35 #include "rb-plugin.h"
37 #include "rb-glade-helpers.h"
47 #define PLUGIN_MANAGER_NAME_TITLE _("Plugin")
48 #define PLUGIN_MANAGER_ACTIVE_TITLE _("Enabled")
50 #define RB_PLUGIN_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), RB_TYPE_PLUGIN_MANAGER, RBPluginManagerPrivate))
52 struct _RBPluginManagerPrivate
56 GtkTreeModel
*plugin_model
;
58 GtkWidget
*configure_button
;
59 GtkWidget
*site_label
;
60 GtkWidget
*copyright_label
;
61 GtkWidget
*authors_label
;
62 GtkWidget
*description_label
;
63 GtkWidget
*plugin_icon
;
65 GtkWidget
*copyright_text
;
66 GtkWidget
*authors_text
;
67 GtkWidget
*description_text
;
68 GtkWidget
*plugin_title
;
71 G_DEFINE_TYPE(RBPluginManager
, rb_plugin_manager
, GTK_TYPE_VBOX
)
73 static void rb_plugin_manager_finalize (GObject
*o
);
74 static RBPluginInfo
*plugin_manager_get_selected_plugin (RBPluginManager
*pm
);
75 static void plugin_manager_toggle_active (GtkTreeIter
*iter
, GtkTreeModel
*model
, RBPluginManager
*pm
);
76 static void plugin_manager_toggle_all (RBPluginManager
*pm
);
79 rb_plugin_manager_class_init (RBPluginManagerClass
*klass
)
81 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
83 object_class
->finalize
= rb_plugin_manager_finalize
;
85 g_type_class_add_private (object_class
, sizeof (RBPluginManagerPrivate
));
89 configure_button_cb (GtkWidget
*button
,
95 info
= plugin_manager_get_selected_plugin (pm
);
97 g_return_if_fail (info
!= NULL
);
99 rb_debug ("Configuring: %s", rb_plugins_engine_get_plugin_name (info
));
101 toplevel
= GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (pm
)));
103 rb_plugins_engine_configure_plugin (info
, toplevel
);
105 rb_debug ("Done configuring plugin");
109 plugin_manager_view_cell_cb (GtkTreeViewColumn
*tree_column
,
110 GtkCellRenderer
*cell
,
111 GtkTreeModel
*tree_model
,
117 g_return_if_fail (tree_model
!= NULL
);
118 g_return_if_fail (tree_column
!= NULL
);
120 gtk_tree_model_get (tree_model
, iter
, INFO_COLUMN
, &info
, -1);
125 g_object_set (G_OBJECT (cell
),
127 rb_plugins_engine_get_plugin_name (info
),
132 active_toggled_cb (GtkCellRendererToggle
*cell
,
140 path
= gtk_tree_path_new_from_string (path_str
);
142 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
143 g_return_if_fail (model
!= NULL
);
145 if (gtk_tree_model_get_iter (model
, &iter
, path
))
146 plugin_manager_toggle_active (&iter
, model
, pm
);
148 gtk_tree_path_free (path
);
152 cursor_changed_cb (GtkTreeSelection
*selection
,
155 RBPluginManager
*pm
= data
;
160 view
= gtk_tree_selection_get_tree_view (selection
);
161 info
= plugin_manager_get_selected_plugin (pm
);
163 /* update info widgets */
164 string
= g_strdup_printf ("<span size=\"x-large\">%s</span>",
165 rb_plugins_engine_get_plugin_name (info
));
166 gtk_label_set_markup (GTK_LABEL (pm
->priv
->plugin_title
), string
);
168 gtk_label_set_text (GTK_LABEL (pm
->priv
->description_text
),
169 rb_plugins_engine_get_plugin_description (info
));
170 gtk_label_set_text (GTK_LABEL (pm
->priv
->copyright_text
),
171 rb_plugins_engine_get_plugin_copyright (info
));
172 gtk_label_set_text (GTK_LABEL (pm
->priv
->site_text
),
173 rb_plugins_engine_get_plugin_website (info
));
175 string
= g_strjoinv ("\n", (gchar
**)rb_plugins_engine_get_plugin_authors (info
));
176 gtk_label_set_text (GTK_LABEL (pm
->priv
->authors_text
), string
);
179 gtk_image_set_from_pixbuf (GTK_IMAGE (pm
->priv
->plugin_icon
),
180 rb_plugins_engine_get_plugin_icon (info
));
182 gtk_widget_set_sensitive (GTK_WIDGET (pm
->priv
->configure_button
),
184 rb_plugins_engine_plugin_is_configurable (info
));
188 row_activated_cb (GtkTreeView
*tree_view
,
190 GtkTreeViewColumn
*column
,
193 RBPluginManager
*pm
= data
;
198 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
199 g_return_if_fail (model
!= NULL
);
201 found
= gtk_tree_model_get_iter (model
, &iter
, path
);
202 g_return_if_fail (found
);
204 plugin_manager_toggle_active (&iter
, model
, pm
);
208 column_clicked_cb (GtkTreeViewColumn
*tree_column
,
211 RBPluginManager
*pm
= RB_PLUGIN_MANAGER (data
);
213 plugin_manager_toggle_all (pm
);
217 plugin_manager_populate_lists (RBPluginManager
*pm
)
223 for (p
= pm
->priv
->plugins
; p
!= NULL
; p
= g_list_next (p
)) {
225 info
= (RBPluginInfo
*)p
->data
;
227 gtk_list_store_append (GTK_LIST_STORE (pm
->priv
->plugin_model
), &iter
);
228 gtk_list_store_set (GTK_LIST_STORE (pm
->priv
->plugin_model
), &iter
,
229 ACTIVE_COLUMN
, rb_plugins_engine_plugin_is_active (info
),
230 VISIBLE_COLUMN
, rb_plugins_engine_plugin_is_visible (info
),
235 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
236 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model
), &iter
)) {
237 GtkTreeSelection
*selection
;
239 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
));
240 g_return_if_fail (selection
!= NULL
);
242 gtk_tree_selection_select_iter (selection
, &iter
);
247 plugin_manager_set_active (GtkTreeIter
*iter
,
253 GtkTreeIter child_iter
;
255 gtk_tree_model_get (model
, iter
, INFO_COLUMN
, &info
, -1);
257 g_return_if_fail (info
!= NULL
);
260 /* activate the plugin */
261 if (!rb_plugins_engine_activate_plugin (info
)) {
262 rb_debug ("Could not activate %s.", rb_plugins_engine_get_plugin_name (info
));
266 /* deactivate the plugin */
267 if (!rb_plugins_engine_deactivate_plugin (info
)) {
268 rb_debug ("Could not deactivate %s.", rb_plugins_engine_get_plugin_name (info
));
274 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model
),
276 gtk_list_store_set (GTK_LIST_STORE (pm
->priv
->plugin_model
),
279 rb_plugins_engine_plugin_is_active (info
),
282 /* cause the configure button sensitivity to be updated */
283 cursor_changed_cb (gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
)), pm
);
287 plugin_manager_toggle_active (GtkTreeIter
*iter
,
291 gboolean active
, visible
;
293 gtk_tree_model_get (model
, iter
,
294 ACTIVE_COLUMN
, &active
,
295 VISIBLE_COLUMN
, &visible
,
300 plugin_manager_set_active (iter
, model
, active
, pm
);
304 static RBPluginInfo
*
305 plugin_manager_get_selected_plugin (RBPluginManager
*pm
)
307 RBPluginInfo
*info
= NULL
;
310 GtkTreeSelection
*selection
;
312 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
313 g_return_val_if_fail (model
!= NULL
, NULL
);
315 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
));
316 g_return_val_if_fail (selection
!= NULL
, NULL
);
318 if (gtk_tree_selection_get_selected (selection
, NULL
, &iter
)) {
319 gtk_tree_model_get (model
, &iter
, INFO_COLUMN
, &info
, -1);
326 plugin_manager_toggle_all (RBPluginManager
*pm
)
330 static gboolean active
;
334 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
336 g_return_if_fail (model
!= NULL
);
338 if (gtk_tree_model_get_iter_first (model
, &iter
)) {
340 plugin_manager_set_active (&iter
, model
, active
, pm
);
341 } while (gtk_tree_model_iter_next (model
, &iter
));
345 /* Callback used as the interactive search comparison function */
347 name_search_cb (GtkTreeModel
*model
,
354 gchar
*normalized_string
;
355 gchar
*normalized_key
;
356 gchar
*case_normalized_string
;
357 gchar
*case_normalized_key
;
361 gtk_tree_model_get (model
, iter
, INFO_COLUMN
, &info
, -1);
365 normalized_string
= g_utf8_normalize (rb_plugins_engine_get_plugin_name (info
), -1, G_NORMALIZE_ALL
);
366 normalized_key
= g_utf8_normalize (key
, -1, G_NORMALIZE_ALL
);
367 case_normalized_string
= g_utf8_casefold (normalized_string
, -1);
368 case_normalized_key
= g_utf8_casefold (normalized_key
, -1);
370 key_len
= strlen (case_normalized_key
);
372 /* Oddly enough, this callback must return whether to stop the search
373 * because we found a match, not whether we actually matched.
375 retval
= (strncmp (case_normalized_key
, case_normalized_string
, key_len
) != 0);
377 g_free (normalized_key
);
378 g_free (normalized_string
);
379 g_free (case_normalized_key
);
380 g_free (case_normalized_string
);
386 plugin_manager_construct_tree (RBPluginManager
*pm
)
388 GtkTreeViewColumn
*column
;
389 GtkCellRenderer
*cell
;
390 GtkTreeModel
*filter
;
392 pm
->priv
->plugin_model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_POINTER
));
393 filter
= gtk_tree_model_filter_new (pm
->priv
->plugin_model
, NULL
);
394 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter
), VISIBLE_COLUMN
);
395 gtk_tree_view_set_model (GTK_TREE_VIEW (pm
->priv
->tree
), filter
);
396 g_object_unref (filter
);
398 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm
->priv
->tree
), TRUE
);
399 gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (pm
->priv
->tree
), TRUE
);
402 cell
= gtk_cell_renderer_toggle_new ();
403 g_signal_connect (cell
,
405 G_CALLBACK (active_toggled_cb
),
407 column
= gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE
,
412 gtk_tree_view_column_set_clickable (column
, TRUE
);
413 gtk_tree_view_column_set_resizable (column
, TRUE
);
414 g_signal_connect (column
, "clicked", G_CALLBACK (column_clicked_cb
), pm
);
415 gtk_tree_view_append_column (GTK_TREE_VIEW (pm
->priv
->tree
), column
);
418 cell
= gtk_cell_renderer_text_new ();
419 column
= gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_NAME_TITLE
, cell
, NULL
);
420 gtk_tree_view_column_set_resizable (column
, TRUE
);
421 gtk_tree_view_column_set_cell_data_func (column
, cell
, plugin_manager_view_cell_cb
,
423 gtk_tree_view_append_column (GTK_TREE_VIEW (pm
->priv
->tree
), column
);
425 /* Enable search for our non-string column */
426 gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm
->priv
->tree
), INFO_COLUMN
);
427 gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm
->priv
->tree
),
432 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
)),
434 G_CALLBACK (cursor_changed_cb
),
436 g_signal_connect (pm
->priv
->tree
,
438 G_CALLBACK (row_activated_cb
),
441 gtk_widget_show (pm
->priv
->tree
);
445 rb_plugin_manager_init (RBPluginManager
*pm
)
448 GtkWidget
*plugins_tree_vbox
;
450 pm
->priv
= RB_PLUGIN_MANAGER_GET_PRIVATE (pm
);
452 xml
= rb_glade_xml_new ("plugins.glade",
455 gtk_container_add (GTK_CONTAINER (pm
), glade_xml_get_widget (xml
, "plugins_vbox"));
457 gtk_box_set_spacing (GTK_BOX (pm
), 6);
459 pm
->priv
->tree
= gtk_tree_view_new ();
460 plugins_tree_vbox
= glade_xml_get_widget (xml
, "plugins_tree_vbox");
461 gtk_container_add (GTK_CONTAINER (plugins_tree_vbox
), pm
->priv
->tree
);
463 pm
->priv
->configure_button
= glade_xml_get_widget (xml
, "configure_button");
464 g_signal_connect (pm
->priv
->configure_button
,
466 G_CALLBACK (configure_button_cb
),
469 pm
->priv
->plugin_title
= glade_xml_get_widget (xml
, "plugin_title");
471 pm
->priv
->site_label
= glade_xml_get_widget (xml
, "site_label");
472 rb_glade_boldify_label (xml
, "site_label");
473 pm
->priv
->copyright_label
= glade_xml_get_widget (xml
, "copyright_label");
474 rb_glade_boldify_label (xml
, "copyright_label");
475 pm
->priv
->authors_label
= glade_xml_get_widget (xml
, "authors_label");
476 rb_glade_boldify_label (xml
, "authors_label");
477 pm
->priv
->description_label
= glade_xml_get_widget (xml
, "description_label");
478 rb_glade_boldify_label (xml
, "description_label");
480 pm
->priv
->plugin_icon
= glade_xml_get_widget (xml
, "plugin_icon");
481 pm
->priv
->site_text
= glade_xml_get_widget (xml
, "site_text");
482 pm
->priv
->copyright_text
= glade_xml_get_widget (xml
, "copyright_text");
483 pm
->priv
->authors_text
= glade_xml_get_widget (xml
, "authors_text");
484 pm
->priv
->description_text
= glade_xml_get_widget (xml
, "description_text");
486 plugin_manager_construct_tree (pm
);
488 /* get the list of available plugins (or installed) */
489 pm
->priv
->plugins
= rb_plugins_engine_get_plugins_list ();
491 plugin_manager_populate_lists (pm
);
495 rb_plugin_manager_new (void)
497 return g_object_new (RB_TYPE_PLUGIN_MANAGER
, 0);
501 rb_plugin_manager_finalize (GObject
*o
)
503 RBPluginManager
*pm
= RB_PLUGIN_MANAGER (o
);
505 g_list_free (pm
->priv
->plugins
);