Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
plugin-view.c
Go to the documentation of this file.
00001 /*
00002  * plugin-view.c
00003  * Copyright 2010 John Lindgren
00004  *
00005  * This file is part of Audacious.
00006  *
00007  * Audacious is free software: you can redistribute it and/or modify it under
00008  * the terms of the GNU General Public License as published by the Free Software
00009  * Foundation, version 2 or version 3 of the License.
00010  *
00011  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00013  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * Audacious. If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The Audacious team does not consider modular code linking to Audacious or
00019  * using our public API to be a derived work.
00020  */
00021 
00022 #include <gtk/gtk.h>
00023 
00024 #include "plugin.h"
00025 #include "plugins.h"
00026 #include "ui_preferences.h"
00027 
00028 enum {
00029  PVIEW_COL_NODE,
00030  PVIEW_COL_ENABLED,
00031  PVIEW_COL_NAME,
00032  PVIEW_COL_PATH,
00033  PVIEW_COLS
00034 };
00035 
00036 typedef struct {
00037     PluginHandle * p;
00038     GtkTreeModel * model;
00039     GtkTreePath * path;
00040 } Node;
00041 
00042 static PluginHandle * get_selected_plugin (GtkTreeView * tree)
00043 {
00044     Node * n = NULL;
00045 
00046     GtkTreeSelection * sel = gtk_tree_view_get_selection (tree);
00047     GtkTreeModel * model;
00048     GtkTreeIter iter;
00049     if (gtk_tree_selection_get_selected (sel, & model, & iter))
00050         gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, -1);
00051 
00052     return n == NULL ? NULL : n->p;
00053 }
00054 
00055 static Plugin * get_selected_header (GtkTreeView * tree)
00056 {
00057     PluginHandle * p = get_selected_plugin (tree);
00058     g_return_val_if_fail (p != NULL, NULL);
00059     g_return_val_if_fail (plugin_get_enabled (p), NULL);
00060     return plugin_get_header (p);
00061 }
00062 
00063 static void do_enable (GtkCellRendererToggle * cell, const gchar * path_str,
00064  GtkTreeModel * model)
00065 {
00066     GtkTreePath * path = gtk_tree_path_new_from_string (path_str);
00067     GtkTreeIter iter;
00068     gtk_tree_model_get_iter (model, & iter, path);
00069     gtk_tree_path_free (path);
00070 
00071     Node * n = NULL;
00072     gboolean enabled;
00073     gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n,
00074      PVIEW_COL_ENABLED, & enabled, -1);
00075     g_return_if_fail (n != NULL);
00076 
00077     plugin_enable (n->p, ! enabled);
00078 }
00079 
00080 static gboolean list_watcher (PluginHandle * p, Node * n)
00081 {
00082     GtkTreeIter iter;
00083     gtk_tree_model_get_iter (n->model, & iter, n->path);
00084     gtk_list_store_set ((GtkListStore *) n->model, & iter, PVIEW_COL_ENABLED,
00085      plugin_get_enabled (n->p), -1);
00086     return TRUE;
00087 }
00088 
00089 static gboolean fill_cb (PluginHandle * p, GtkTreeModel * model)
00090 {
00091     Node * n = g_slice_new (Node);
00092 
00093     GtkTreeIter iter;
00094     gtk_list_store_append ((GtkListStore *) model, & iter);
00095     gtk_list_store_set ((GtkListStore *) model, & iter, PVIEW_COL_NODE, n,
00096      PVIEW_COL_ENABLED, plugin_get_enabled (p), PVIEW_COL_NAME, plugin_get_name
00097      (p), PVIEW_COL_PATH, plugin_get_filename (p), -1);
00098 
00099     n->p = p;
00100     n->model = model;
00101     n->path = gtk_tree_model_get_path (model, & iter);
00102 
00103     plugin_add_watch (p, (PluginForEachFunc) list_watcher, n);
00104 
00105     return TRUE;
00106 }
00107 
00108 static void list_fill (GtkTreeView * tree, void * type)
00109 {
00110     GtkTreeModel * model = (GtkTreeModel *) gtk_list_store_new (PVIEW_COLS,
00111      G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING);
00112     gtk_tree_view_set_model (tree, model);
00113 
00114     GtkTreeViewColumn * col = gtk_tree_view_column_new ();
00115     gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
00116     gtk_tree_view_column_set_resizable (col, FALSE);
00117     gtk_tree_view_append_column (tree, col);
00118 
00119     GtkCellRenderer * rend = gtk_cell_renderer_toggle_new ();
00120     g_signal_connect (rend, "toggled", (GCallback) do_enable, model);
00121     gtk_tree_view_column_pack_start (col, rend, FALSE);
00122     gtk_tree_view_column_set_attributes (col, rend, "active", PVIEW_COL_ENABLED,
00123      NULL);
00124 
00125     for (gint i = PVIEW_COL_NAME; i <= PVIEW_COL_PATH; i ++)
00126     {
00127         col = gtk_tree_view_column_new ();
00128         gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
00129         gtk_tree_view_column_set_resizable (col, FALSE);
00130         gtk_tree_view_append_column (tree, col);
00131 
00132         rend = gtk_cell_renderer_text_new ();
00133         gtk_tree_view_column_pack_start (col, rend, FALSE);
00134         gtk_tree_view_column_set_attributes (col, rend, "text", i, NULL);
00135     }
00136 
00137     plugin_for_each (GPOINTER_TO_INT (type), (PluginForEachFunc) fill_cb, model);
00138 }
00139 
00140 static void list_destroy (GtkTreeView * tree)
00141 {
00142     GtkTreeModel * model = gtk_tree_view_get_model (tree);
00143     if (model == NULL)
00144         return;
00145 
00146     GtkTreeIter iter;
00147     if (gtk_tree_model_get_iter_first (model, & iter))
00148     {
00149         do
00150         {
00151             Node * n = NULL;
00152             gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, -1);
00153             g_return_if_fail (n != NULL);
00154 
00155             plugin_remove_watch (n->p, (PluginForEachFunc) list_watcher, n);
00156             gtk_tree_path_free (n->path);
00157             g_slice_free (Node, n);
00158         }
00159         while (gtk_tree_model_iter_next (model, & iter));
00160     }
00161 
00162     g_object_unref ((GObject *) model);
00163 }
00164 
00165 static gboolean config_watcher (PluginHandle * p, GtkWidget * config)
00166 {
00167     gtk_widget_set_sensitive (config, plugin_has_configure (p) &&
00168      plugin_get_enabled (p));
00169     return TRUE;
00170 }
00171 
00172 static gboolean about_watcher (PluginHandle * p, GtkWidget * about)
00173 {
00174     gtk_widget_set_sensitive (about, plugin_has_about (p) && plugin_get_enabled
00175      (p));
00176     return TRUE;
00177 }
00178 
00179 static void button_update (GtkTreeView * tree, GtkWidget * b)
00180 {
00181     PluginForEachFunc watcher = g_object_get_data ((GObject *) b, "watcher");
00182     g_return_if_fail (watcher != NULL);
00183 
00184     PluginHandle * p = g_object_steal_data ((GObject *) b, "plugin");
00185     if (p != NULL)
00186         plugin_remove_watch (p, watcher, b);
00187 
00188     p = get_selected_plugin (tree);
00189     if (p != NULL)
00190     {
00191         g_object_set_data ((GObject *) b, "plugin", p);
00192         watcher (p, b);
00193         plugin_add_watch (p, watcher, b);
00194     }
00195     else
00196         gtk_widget_set_sensitive (b, FALSE);
00197 }
00198 
00199 static void do_config (GtkTreeView * tree)
00200 {
00201     Plugin * header = get_selected_header (tree);
00202     g_return_if_fail (header != NULL);
00203 
00204     if (header->configure != NULL)
00205         header->configure ();
00206     else if (header->settings != NULL)
00207         plugin_preferences_show (header->settings);
00208 }
00209 
00210 static void do_about (GtkTreeView * tree)
00211 {
00212     Plugin * header = get_selected_header (tree);
00213     g_return_if_fail (header != NULL);
00214 
00215     if (header->about != NULL)
00216         header->about ();
00217 }
00218 
00219 static void button_destroy (GtkWidget * b)
00220 {
00221     PluginForEachFunc watcher = g_object_get_data ((GObject *) b, "watcher");
00222     g_return_if_fail (watcher != NULL);
00223 
00224     PluginHandle * p = g_object_steal_data ((GObject *) b, "plugin");
00225     if (p != NULL)
00226         plugin_remove_watch (p, watcher, b);
00227 }
00228 
00229 GtkWidget * plugin_view_new (gint type)
00230 {
00231     GtkWidget * vbox = gtk_vbox_new (FALSE, 6);
00232     gtk_container_set_border_width ((GtkContainer *) vbox, 6);
00233 
00234     GtkWidget * scrolled = gtk_scrolled_window_new (NULL, NULL);
00235     gtk_box_pack_start ((GtkBox *) vbox, scrolled, TRUE, TRUE, 0);
00236     gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolled,
00237      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00238     gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled,
00239      GTK_SHADOW_IN);
00240 
00241     GtkWidget * tree = gtk_tree_view_new ();
00242     gtk_container_add ((GtkContainer *) scrolled, tree);
00243     gtk_tree_view_set_headers_visible ((GtkTreeView *) tree, FALSE);
00244     g_signal_connect (tree, "realize", (GCallback) list_fill, GINT_TO_POINTER
00245      (type));
00246     g_signal_connect (tree, "destroy", (GCallback) list_destroy, NULL);
00247 
00248     GtkWidget * hbox = gtk_hbox_new (FALSE, 6);
00249     gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
00250 
00251     GtkWidget * config = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES);
00252     gtk_box_pack_start ((GtkBox *) hbox, config, FALSE, FALSE, 0);
00253     gtk_widget_set_sensitive (config, FALSE);
00254     g_object_set_data ((GObject *) config, "watcher", config_watcher);
00255     g_signal_connect (tree, "cursor-changed", (GCallback) button_update, config);
00256     g_signal_connect_swapped (config, "clicked", (GCallback)
00257      do_config, tree);
00258     g_signal_connect (config, "destroy", (GCallback) button_destroy, NULL);
00259 
00260     GtkWidget * about = gtk_button_new_from_stock (GTK_STOCK_ABOUT);
00261     gtk_box_pack_start ((GtkBox *) hbox, about, FALSE, FALSE, 0);
00262     gtk_widget_set_sensitive (about, FALSE);
00263     g_object_set_data ((GObject *) about, "watcher", about_watcher);
00264     g_signal_connect (tree, "cursor-changed", (GCallback) button_update, about);
00265     g_signal_connect_swapped (about, "clicked", (GCallback) do_about, tree);
00266     g_signal_connect (about, "destroy", (GCallback) button_destroy, NULL);
00267 
00268     return vbox;
00269 }