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 00048 /* the treeview may not have a model yet */ 00049 if (! sel) 00050 return NULL; 00051 00052 GtkTreeModel * model; 00053 GtkTreeIter iter; 00054 if (gtk_tree_selection_get_selected (sel, & model, & iter)) 00055 gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, -1); 00056 00057 return n == NULL ? NULL : n->p; 00058 } 00059 00060 static Plugin * get_selected_header (GtkTreeView * tree) 00061 { 00062 PluginHandle * p = get_selected_plugin (tree); 00063 g_return_val_if_fail (p != NULL, NULL); 00064 g_return_val_if_fail (plugin_get_enabled (p), NULL); 00065 return plugin_get_header (p); 00066 } 00067 00068 static void do_enable (GtkCellRendererToggle * cell, const char * path_str, 00069 GtkTreeModel * model) 00070 { 00071 GtkTreePath * path = gtk_tree_path_new_from_string (path_str); 00072 GtkTreeIter iter; 00073 gtk_tree_model_get_iter (model, & iter, path); 00074 gtk_tree_path_free (path); 00075 00076 Node * n = NULL; 00077 bool_t enabled; 00078 gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, 00079 PVIEW_COL_ENABLED, & enabled, -1); 00080 g_return_if_fail (n != NULL); 00081 00082 plugin_enable (n->p, ! enabled); 00083 } 00084 00085 static bool_t list_watcher (PluginHandle * p, Node * n) 00086 { 00087 GtkTreeIter iter; 00088 gtk_tree_model_get_iter (n->model, & iter, n->path); 00089 gtk_list_store_set ((GtkListStore *) n->model, & iter, PVIEW_COL_ENABLED, 00090 plugin_get_enabled (n->p), -1); 00091 return TRUE; 00092 } 00093 00094 static bool_t fill_cb (PluginHandle * p, GtkTreeModel * model) 00095 { 00096 Node * n = g_slice_new (Node); 00097 00098 GtkTreeIter iter; 00099 gtk_list_store_append ((GtkListStore *) model, & iter); 00100 gtk_list_store_set ((GtkListStore *) model, & iter, PVIEW_COL_NODE, n, 00101 PVIEW_COL_ENABLED, plugin_get_enabled (p), PVIEW_COL_NAME, plugin_get_name 00102 (p), PVIEW_COL_PATH, plugin_get_filename (p), -1); 00103 00104 n->p = p; 00105 n->model = model; 00106 n->path = gtk_tree_model_get_path (model, & iter); 00107 00108 plugin_add_watch (p, (PluginForEachFunc) list_watcher, n); 00109 00110 return TRUE; 00111 } 00112 00113 static void list_fill (GtkTreeView * tree, void * type) 00114 { 00115 GtkTreeModel * model = (GtkTreeModel *) gtk_list_store_new (PVIEW_COLS, 00116 G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); 00117 gtk_tree_view_set_model (tree, model); 00118 00119 GtkTreeViewColumn * col = gtk_tree_view_column_new (); 00120 gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); 00121 gtk_tree_view_column_set_resizable (col, FALSE); 00122 gtk_tree_view_append_column (tree, col); 00123 00124 GtkCellRenderer * rend = gtk_cell_renderer_toggle_new (); 00125 g_signal_connect (rend, "toggled", (GCallback) do_enable, model); 00126 gtk_tree_view_column_pack_start (col, rend, FALSE); 00127 gtk_tree_view_column_set_attributes (col, rend, "active", PVIEW_COL_ENABLED, 00128 NULL); 00129 00130 for (int i = PVIEW_COL_NAME; i <= PVIEW_COL_PATH; i ++) 00131 { 00132 col = gtk_tree_view_column_new (); 00133 gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); 00134 gtk_tree_view_column_set_resizable (col, FALSE); 00135 gtk_tree_view_append_column (tree, col); 00136 00137 rend = gtk_cell_renderer_text_new (); 00138 gtk_tree_view_column_pack_start (col, rend, FALSE); 00139 gtk_tree_view_column_set_attributes (col, rend, "text", i, NULL); 00140 } 00141 00142 plugin_for_each (GPOINTER_TO_INT (type), (PluginForEachFunc) fill_cb, model); 00143 } 00144 00145 static void list_destroy (GtkTreeView * tree) 00146 { 00147 GtkTreeModel * model = gtk_tree_view_get_model (tree); 00148 if (model == NULL) 00149 return; 00150 00151 GtkTreeIter iter; 00152 if (gtk_tree_model_get_iter_first (model, & iter)) 00153 { 00154 do 00155 { 00156 Node * n = NULL; 00157 gtk_tree_model_get (model, & iter, PVIEW_COL_NODE, & n, -1); 00158 g_return_if_fail (n != NULL); 00159 00160 plugin_remove_watch (n->p, (PluginForEachFunc) list_watcher, n); 00161 gtk_tree_path_free (n->path); 00162 g_slice_free (Node, n); 00163 } 00164 while (gtk_tree_model_iter_next (model, & iter)); 00165 } 00166 00167 g_object_unref ((GObject *) model); 00168 } 00169 00170 static bool_t config_watcher (PluginHandle * p, GtkWidget * config) 00171 { 00172 gtk_widget_set_sensitive (config, plugin_has_configure (p) && 00173 plugin_get_enabled (p)); 00174 return TRUE; 00175 } 00176 00177 static bool_t about_watcher (PluginHandle * p, GtkWidget * about) 00178 { 00179 gtk_widget_set_sensitive (about, plugin_has_about (p) && plugin_get_enabled 00180 (p)); 00181 return TRUE; 00182 } 00183 00184 static void button_update (GtkTreeView * tree, GtkWidget * b) 00185 { 00186 PluginForEachFunc watcher = (PluginForEachFunc) g_object_get_data 00187 ((GObject *) b, "watcher"); 00188 g_return_if_fail (watcher != NULL); 00189 00190 PluginHandle * p = g_object_steal_data ((GObject *) b, "plugin"); 00191 if (p != NULL) 00192 plugin_remove_watch (p, watcher, b); 00193 00194 p = get_selected_plugin (tree); 00195 if (p != NULL) 00196 { 00197 g_object_set_data ((GObject *) b, "plugin", p); 00198 watcher (p, b); 00199 plugin_add_watch (p, watcher, b); 00200 } 00201 else 00202 gtk_widget_set_sensitive (b, FALSE); 00203 } 00204 00205 static void do_config (GtkTreeView * tree) 00206 { 00207 Plugin * header = get_selected_header (tree); 00208 g_return_if_fail (header != NULL); 00209 00210 if (header->configure != NULL) 00211 header->configure (); 00212 else if (header->settings != NULL) 00213 plugin_preferences_show (header->settings); 00214 } 00215 00216 static void do_about (GtkTreeView * tree) 00217 { 00218 Plugin * header = get_selected_header (tree); 00219 g_return_if_fail (header != NULL); 00220 00221 if (header->about != NULL) 00222 header->about (); 00223 } 00224 00225 static void button_destroy (GtkWidget * b) 00226 { 00227 PluginForEachFunc watcher = (PluginForEachFunc) g_object_get_data 00228 ((GObject *) b, "watcher"); 00229 g_return_if_fail (watcher != NULL); 00230 00231 PluginHandle * p = g_object_steal_data ((GObject *) b, "plugin"); 00232 if (p != NULL) 00233 plugin_remove_watch (p, watcher, b); 00234 } 00235 00236 GtkWidget * plugin_view_new (int type) 00237 { 00238 GtkWidget * vbox = gtk_vbox_new (FALSE, 6); 00239 gtk_container_set_border_width ((GtkContainer *) vbox, 6); 00240 00241 GtkWidget * scrolled = gtk_scrolled_window_new (NULL, NULL); 00242 gtk_box_pack_start ((GtkBox *) vbox, scrolled, TRUE, TRUE, 0); 00243 gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolled, 00244 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 00245 gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, 00246 GTK_SHADOW_IN); 00247 00248 GtkWidget * tree = gtk_tree_view_new (); 00249 gtk_container_add ((GtkContainer *) scrolled, tree); 00250 gtk_tree_view_set_headers_visible ((GtkTreeView *) tree, FALSE); 00251 g_signal_connect (tree, "realize", (GCallback) list_fill, GINT_TO_POINTER 00252 (type)); 00253 g_signal_connect (tree, "destroy", (GCallback) list_destroy, NULL); 00254 00255 GtkWidget * hbox = gtk_hbox_new (FALSE, 6); 00256 gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0); 00257 00258 GtkWidget * config = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES); 00259 gtk_box_pack_start ((GtkBox *) hbox, config, FALSE, FALSE, 0); 00260 gtk_widget_set_sensitive (config, FALSE); 00261 g_object_set_data ((GObject *) config, "watcher", (void *) config_watcher); 00262 g_signal_connect (tree, "cursor-changed", (GCallback) button_update, config); 00263 g_signal_connect_swapped (config, "clicked", (GCallback) 00264 do_config, tree); 00265 g_signal_connect (config, "destroy", (GCallback) button_destroy, NULL); 00266 00267 GtkWidget * about = gtk_button_new_from_stock (GTK_STOCK_ABOUT); 00268 gtk_box_pack_start ((GtkBox *) hbox, about, FALSE, FALSE, 0); 00269 gtk_widget_set_sensitive (about, FALSE); 00270 g_object_set_data ((GObject *) about, "watcher", (void *) about_watcher); 00271 g_signal_connect (tree, "cursor-changed", (GCallback) button_update, about); 00272 g_signal_connect_swapped (about, "clicked", (GCallback) do_about, tree); 00273 g_signal_connect (about, "destroy", (GCallback) button_destroy, NULL); 00274 00275 return vbox; 00276 }