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
);
244 g_object_unref (model
);
248 plugin_manager_set_active (GtkTreeIter
*iter
,
254 GtkTreeIter child_iter
;
256 gtk_tree_model_get (model
, iter
, INFO_COLUMN
, &info
, -1);
258 g_return_if_fail (info
!= NULL
);
261 /* activate the plugin */
262 if (!rb_plugins_engine_activate_plugin (info
)) {
263 rb_debug ("Could not activate %s.", rb_plugins_engine_get_plugin_name (info
));
267 /* deactivate the plugin */
268 if (!rb_plugins_engine_deactivate_plugin (info
)) {
269 rb_debug ("Could not deactivate %s.", rb_plugins_engine_get_plugin_name (info
));
275 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model
),
277 gtk_list_store_set (GTK_LIST_STORE (pm
->priv
->plugin_model
),
280 rb_plugins_engine_plugin_is_active (info
),
283 /* cause the configure button sensitivity to be updated */
284 cursor_changed_cb (gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
)), pm
);
288 plugin_manager_toggle_active (GtkTreeIter
*iter
,
292 gboolean active
, visible
;
294 gtk_tree_model_get (model
, iter
,
295 ACTIVE_COLUMN
, &active
,
296 VISIBLE_COLUMN
, &visible
,
301 plugin_manager_set_active (iter
, model
, active
, pm
);
305 static RBPluginInfo
*
306 plugin_manager_get_selected_plugin (RBPluginManager
*pm
)
308 RBPluginInfo
*info
= NULL
;
311 GtkTreeSelection
*selection
;
313 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
314 g_return_val_if_fail (model
!= NULL
, NULL
);
316 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
));
317 g_return_val_if_fail (selection
!= NULL
, NULL
);
319 if (gtk_tree_selection_get_selected (selection
, NULL
, &iter
)) {
320 gtk_tree_model_get (model
, &iter
, INFO_COLUMN
, &info
, -1);
327 plugin_manager_toggle_all (RBPluginManager
*pm
)
331 static gboolean active
;
335 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (pm
->priv
->tree
));
337 g_return_if_fail (model
!= NULL
);
339 if (gtk_tree_model_get_iter_first (model
, &iter
)) {
341 plugin_manager_set_active (&iter
, model
, active
, pm
);
342 } while (gtk_tree_model_iter_next (model
, &iter
));
346 /* Callback used as the interactive search comparison function */
348 name_search_cb (GtkTreeModel
*model
,
355 gchar
*normalized_string
;
356 gchar
*normalized_key
;
357 gchar
*case_normalized_string
;
358 gchar
*case_normalized_key
;
362 gtk_tree_model_get (model
, iter
, INFO_COLUMN
, &info
, -1);
366 normalized_string
= g_utf8_normalize (rb_plugins_engine_get_plugin_name (info
), -1, G_NORMALIZE_ALL
);
367 normalized_key
= g_utf8_normalize (key
, -1, G_NORMALIZE_ALL
);
368 case_normalized_string
= g_utf8_casefold (normalized_string
, -1);
369 case_normalized_key
= g_utf8_casefold (normalized_key
, -1);
371 key_len
= strlen (case_normalized_key
);
373 /* Oddly enough, this callback must return whether to stop the search
374 * because we found a match, not whether we actually matched.
376 retval
= (strncmp (case_normalized_key
, case_normalized_string
, key_len
) != 0);
378 g_free (normalized_key
);
379 g_free (normalized_string
);
380 g_free (case_normalized_key
);
381 g_free (case_normalized_string
);
387 plugin_manager_construct_tree (RBPluginManager
*pm
)
389 GtkTreeViewColumn
*column
;
390 GtkCellRenderer
*cell
;
391 GtkTreeModel
*filter
;
393 pm
->priv
->plugin_model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_POINTER
));
394 filter
= gtk_tree_model_filter_new (pm
->priv
->plugin_model
, NULL
);
395 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter
), VISIBLE_COLUMN
);
396 gtk_tree_view_set_model (GTK_TREE_VIEW (pm
->priv
->tree
), filter
);
397 g_object_unref (filter
);
399 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm
->priv
->tree
), TRUE
);
400 gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (pm
->priv
->tree
), TRUE
);
403 cell
= gtk_cell_renderer_toggle_new ();
404 g_signal_connect (cell
,
406 G_CALLBACK (active_toggled_cb
),
408 column
= gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE
,
413 gtk_tree_view_column_set_clickable (column
, TRUE
);
414 gtk_tree_view_column_set_resizable (column
, TRUE
);
415 g_signal_connect (column
, "clicked", G_CALLBACK (column_clicked_cb
), pm
);
416 gtk_tree_view_append_column (GTK_TREE_VIEW (pm
->priv
->tree
), column
);
419 cell
= gtk_cell_renderer_text_new ();
420 column
= gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_NAME_TITLE
, cell
, NULL
);
421 gtk_tree_view_column_set_resizable (column
, TRUE
);
422 gtk_tree_view_column_set_cell_data_func (column
, cell
, plugin_manager_view_cell_cb
,
424 gtk_tree_view_append_column (GTK_TREE_VIEW (pm
->priv
->tree
), column
);
426 /* Enable search for our non-string column */
427 gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm
->priv
->tree
), INFO_COLUMN
);
428 gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm
->priv
->tree
),
433 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (pm
->priv
->tree
)),
435 G_CALLBACK (cursor_changed_cb
),
437 g_signal_connect (pm
->priv
->tree
,
439 G_CALLBACK (row_activated_cb
),
442 gtk_widget_show (pm
->priv
->tree
);
446 rb_plugin_manager_init (RBPluginManager
*pm
)
449 GtkWidget
*plugins_tree_vbox
;
451 pm
->priv
= RB_PLUGIN_MANAGER_GET_PRIVATE (pm
);
453 xml
= rb_glade_xml_new ("plugins.glade",
456 gtk_container_add (GTK_CONTAINER (pm
), glade_xml_get_widget (xml
, "plugins_vbox"));
458 gtk_box_set_spacing (GTK_BOX (pm
), 6);
460 pm
->priv
->tree
= gtk_tree_view_new ();
461 plugins_tree_vbox
= glade_xml_get_widget (xml
, "plugins_tree_vbox");
462 gtk_container_add (GTK_CONTAINER (plugins_tree_vbox
), pm
->priv
->tree
);
464 pm
->priv
->configure_button
= glade_xml_get_widget (xml
, "configure_button");
465 g_signal_connect (pm
->priv
->configure_button
,
467 G_CALLBACK (configure_button_cb
),
470 pm
->priv
->plugin_title
= glade_xml_get_widget (xml
, "plugin_title");
472 pm
->priv
->site_label
= glade_xml_get_widget (xml
, "site_label");
473 rb_glade_boldify_label (xml
, "site_label");
474 pm
->priv
->copyright_label
= glade_xml_get_widget (xml
, "copyright_label");
475 rb_glade_boldify_label (xml
, "copyright_label");
476 pm
->priv
->authors_label
= glade_xml_get_widget (xml
, "authors_label");
477 rb_glade_boldify_label (xml
, "authors_label");
478 pm
->priv
->description_label
= glade_xml_get_widget (xml
, "description_label");
479 rb_glade_boldify_label (xml
, "description_label");
481 pm
->priv
->plugin_icon
= glade_xml_get_widget (xml
, "plugin_icon");
482 pm
->priv
->site_text
= glade_xml_get_widget (xml
, "site_text");
483 pm
->priv
->copyright_text
= glade_xml_get_widget (xml
, "copyright_text");
484 pm
->priv
->authors_text
= glade_xml_get_widget (xml
, "authors_text");
485 pm
->priv
->description_text
= glade_xml_get_widget (xml
, "description_text");
487 plugin_manager_construct_tree (pm
);
489 /* get the list of available plugins (or installed) */
490 pm
->priv
->plugins
= rb_plugins_engine_get_plugins_list ();
492 plugin_manager_populate_lists (pm
);
496 rb_plugin_manager_new (void)
498 return g_object_new (RB_TYPE_PLUGIN_MANAGER
, 0);
502 rb_plugin_manager_finalize (GObject
*o
)
504 RBPluginManager
*pm
= RB_PLUGIN_MANAGER (o
);
506 g_list_free (pm
->priv
->plugins
);