Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
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 }