Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
plugin-view.c
Go to the documentation of this file.
1 /*
2  * plugin-view.c
3  * Copyright 2010 John Lindgren
4  *
5  * This file is part of Audacious.
6  *
7  * Audacious is free software: you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation, version 2 or version 3 of the License.
10  *
11  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Audacious. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * The Audacious team does not consider modular code linking to Audacious or
19  * using our public API to be a derived work.
20  */
21 
22 #include <gtk/gtk.h>
23 
24 #include "plugin.h"
25 #include "plugins.h"
26 #include "ui_preferences.h"
27 
28 enum {
34 };
35 
36 typedef struct {
38  GtkTreeModel * model;
39  GtkTreePath * path;
40 } Node;
41 
42 static PluginHandle * get_selected_plugin (GtkTreeView * tree)
43 {
44  Node * n = NULL;
45 
46  GtkTreeSelection * sel = gtk_tree_view_get_selection (tree);
47 
48  /* the treeview may not have a model yet */
49  if (! sel)
50  return NULL;
51 
52  GtkTreeModel * model;
53  GtkTreeIter iter;
54  if (gtk_tree_selection_get_selected (sel, & model, & iter))
55  gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, -1);
56 
57  return n == NULL ? NULL : n->p;
58 }
59 
60 static Plugin * get_selected_header (GtkTreeView * tree)
61 {
62  PluginHandle * p = get_selected_plugin (tree);
63  g_return_val_if_fail (p != NULL, NULL);
64  g_return_val_if_fail (plugin_get_enabled (p), NULL);
65  return plugin_get_header (p);
66 }
67 
68 static void do_enable (GtkCellRendererToggle * cell, const char * path_str,
69  GtkTreeModel * model)
70 {
71  GtkTreePath * path = gtk_tree_path_new_from_string (path_str);
72  GtkTreeIter iter;
73  gtk_tree_model_get_iter (model, & iter, path);
74  gtk_tree_path_free (path);
75 
76  Node * n = NULL;
78  gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n,
79  PVIEW_COL_ENABLED, & enabled, -1);
80  g_return_if_fail (n != NULL);
81 
82  plugin_enable (n->p, ! enabled);
83 }
84 
86 {
87  GtkTreeIter iter;
88  gtk_tree_model_get_iter (n->model, & iter, n->path);
89  gtk_list_store_set ((GtkListStore *) n->model, & iter, PVIEW_COL_ENABLED,
90  plugin_get_enabled (n->p), -1);
91  return TRUE;
92 }
93 
94 static bool_t fill_cb (PluginHandle * p, GtkTreeModel * model)
95 {
96  Node * n = g_slice_new (Node);
97 
98  GtkTreeIter iter;
99  gtk_list_store_append ((GtkListStore *) model, & iter);
100  gtk_list_store_set ((GtkListStore *) model, & iter, PVIEW_COL_NODE, n,
102  (p), PVIEW_COL_PATH, plugin_get_filename (p), -1);
103 
104  n->p = p;
105  n->model = model;
106  n->path = gtk_tree_model_get_path (model, & iter);
107 
109 
110  return TRUE;
111 }
112 
113 static void list_fill (GtkTreeView * tree, void * type)
114 {
115  GtkTreeModel * model = (GtkTreeModel *) gtk_list_store_new (PVIEW_COLS,
116  G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING);
117  gtk_tree_view_set_model (tree, model);
118 
119  GtkTreeViewColumn * col = gtk_tree_view_column_new ();
120  gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
121  gtk_tree_view_column_set_resizable (col, FALSE);
122  gtk_tree_view_append_column (tree, col);
123 
124  GtkCellRenderer * rend = gtk_cell_renderer_toggle_new ();
125  g_signal_connect (rend, "toggled", (GCallback) do_enable, model);
126  gtk_tree_view_column_pack_start (col, rend, FALSE);
127  gtk_tree_view_column_set_attributes (col, rend, "active", PVIEW_COL_ENABLED,
128  NULL);
129 
130  for (int i = PVIEW_COL_NAME; i <= PVIEW_COL_PATH; i ++)
131  {
132  col = gtk_tree_view_column_new ();
133  gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
134  gtk_tree_view_column_set_resizable (col, FALSE);
135  gtk_tree_view_append_column (tree, col);
136 
137  rend = gtk_cell_renderer_text_new ();
138  gtk_tree_view_column_pack_start (col, rend, FALSE);
139  gtk_tree_view_column_set_attributes (col, rend, "text", i, NULL);
140  }
141 
142  plugin_for_each (GPOINTER_TO_INT (type), (PluginForEachFunc) fill_cb, model);
143 }
144 
145 static void list_destroy (GtkTreeView * tree)
146 {
147  GtkTreeModel * model = gtk_tree_view_get_model (tree);
148  if (model == NULL)
149  return;
150 
151  GtkTreeIter iter;
152  if (gtk_tree_model_get_iter_first (model, & iter))
153  {
154  do
155  {
156  Node * n = NULL;
157  gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, -1);
158  g_return_if_fail (n != NULL);
159 
161  gtk_tree_path_free (n->path);
162  g_slice_free (Node, n);
163  }
164  while (gtk_tree_model_iter_next (model, & iter));
165  }
166 
167  g_object_unref ((GObject *) model);
168 }
169 
170 static bool_t config_watcher (PluginHandle * p, GtkWidget * config)
171 {
172  gtk_widget_set_sensitive (config, plugin_has_configure (p) &&
173  plugin_get_enabled (p));
174  return TRUE;
175 }
176 
177 static bool_t about_watcher (PluginHandle * p, GtkWidget * about)
178 {
179  gtk_widget_set_sensitive (about, plugin_has_about (p) && plugin_get_enabled
180  (p));
181  return TRUE;
182 }
183 
184 static void button_update (GtkTreeView * tree, GtkWidget * b)
185 {
186  PluginForEachFunc watcher = (PluginForEachFunc) g_object_get_data
187  ((GObject *) b, "watcher");
188  g_return_if_fail (watcher != NULL);
189 
190  PluginHandle * p = g_object_steal_data ((GObject *) b, "plugin");
191  if (p != NULL)
192  plugin_remove_watch (p, watcher, b);
193 
194  p = get_selected_plugin (tree);
195  if (p != NULL)
196  {
197  g_object_set_data ((GObject *) b, "plugin", p);
198  watcher (p, b);
199  plugin_add_watch (p, watcher, b);
200  }
201  else
202  gtk_widget_set_sensitive (b, FALSE);
203 }
204 
205 static void do_config (GtkTreeView * tree)
206 {
207  Plugin * header = get_selected_header (tree);
208  g_return_if_fail (header != NULL);
209 
210  if (header->configure != NULL)
211  header->configure ();
212  else if (header->settings != NULL)
213  plugin_preferences_show (header->settings);
214 }
215 
216 static void do_about (GtkTreeView * tree)
217 {
218  Plugin * header = get_selected_header (tree);
219  g_return_if_fail (header != NULL);
220 
221  if (header->about != NULL)
222  header->about ();
223 }
224 
225 static void button_destroy (GtkWidget * b)
226 {
227  PluginForEachFunc watcher = (PluginForEachFunc) g_object_get_data
228  ((GObject *) b, "watcher");
229  g_return_if_fail (watcher != NULL);
230 
231  PluginHandle * p = g_object_steal_data ((GObject *) b, "plugin");
232  if (p != NULL)
233  plugin_remove_watch (p, watcher, b);
234 }
235 
236 GtkWidget * plugin_view_new (int type)
237 {
238  GtkWidget * vbox = gtk_vbox_new (FALSE, 6);
239  gtk_container_set_border_width ((GtkContainer *) vbox, 6);
240 
241  GtkWidget * scrolled = gtk_scrolled_window_new (NULL, NULL);
242  gtk_box_pack_start ((GtkBox *) vbox, scrolled, TRUE, TRUE, 0);
243  gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolled,
244  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
245  gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled,
246  GTK_SHADOW_IN);
247 
248  GtkWidget * tree = gtk_tree_view_new ();
249  gtk_container_add ((GtkContainer *) scrolled, tree);
250  gtk_tree_view_set_headers_visible ((GtkTreeView *) tree, FALSE);
251  g_signal_connect (tree, "realize", (GCallback) list_fill, GINT_TO_POINTER
252  (type));
253  g_signal_connect (tree, "destroy", (GCallback) list_destroy, NULL);
254 
255  GtkWidget * hbox = gtk_hbox_new (FALSE, 6);
256  gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
257 
258  GtkWidget * config = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES);
259  gtk_box_pack_start ((GtkBox *) hbox, config, FALSE, FALSE, 0);
260  gtk_widget_set_sensitive (config, FALSE);
261  g_object_set_data ((GObject *) config, "watcher", (void *) config_watcher);
262  g_signal_connect (tree, "cursor-changed", (GCallback) button_update, config);
263  g_signal_connect_swapped (config, "clicked", (GCallback)
264  do_config, tree);
265  g_signal_connect (config, "destroy", (GCallback) button_destroy, NULL);
266 
267  GtkWidget * about = gtk_button_new_from_stock (GTK_STOCK_ABOUT);
268  gtk_box_pack_start ((GtkBox *) hbox, about, FALSE, FALSE, 0);
269  gtk_widget_set_sensitive (about, FALSE);
270  g_object_set_data ((GObject *) about, "watcher", (void *) about_watcher);
271  g_signal_connect (tree, "cursor-changed", (GCallback) button_update, about);
272  g_signal_connect_swapped (about, "clicked", (GCallback) do_about, tree);
273  g_signal_connect (about, "destroy", (GCallback) button_destroy, NULL);
274 
275  return vbox;
276 }