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 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 }