00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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 }