diff options
Diffstat (limited to 'lib/widgets/ephy-editable-toolbar.c')
-rwxr-xr-x | lib/widgets/ephy-editable-toolbar.c | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/lib/widgets/ephy-editable-toolbar.c b/lib/widgets/ephy-editable-toolbar.c new file mode 100755 index 000000000..8ba8e50d7 --- /dev/null +++ b/lib/widgets/ephy-editable-toolbar.c @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2000 Marco Pesenti Gritti + * (C) 2001, 2002 Jorn Baayen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "ephy-editable-toolbar.h" +#include "ephy-file-helpers.h" +#include "ephy-debug.h" + +#include <libxml/parser.h> + +static void ephy_editable_toolbar_class_init (EphyEditableToolbarClass *klass); +static void ephy_editable_toolbar_init (EphyEditableToolbar *t); +static void ephy_editable_toolbar_finalize (GObject *object); + +enum +{ + PROP_0, + PROP_MENU_MERGE +}; + +enum +{ + REQUEST_ACTION, + LAST_SIGNAL +}; + +static GObjectClass *parent_class = NULL; + +static gint EphyEditableToolbarSignals[LAST_SIGNAL]; + +struct EphyEditableToolbarPrivate +{ + EggMenuMerge *merge; + EggAction *separator; + GList *available_actions; + GList *toolbars; + char *filename; +}; + +GType +ephy_editable_toolbar_get_type (void) +{ + static GType ephy_editable_toolbar_type = 0; + + if (ephy_editable_toolbar_type == 0) + { + static const GTypeInfo our_info = + { + sizeof (EphyEditableToolbarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) ephy_editable_toolbar_class_init, + NULL, + NULL, /* class_data */ + sizeof (EphyEditableToolbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) ephy_editable_toolbar_init + }; + + ephy_editable_toolbar_type = g_type_register_static (G_TYPE_OBJECT, + "EphyEditableToolbar", + &our_info, 0); + } + + return ephy_editable_toolbar_type; + +} + +static EggAction * +find_action (EphyEditableToolbar *t, const char *name) +{ + GList *l = t->priv->merge->action_groups; + EggAction *action = NULL; + + for (; l != NULL; l = l->next) + { + EggAction *tmp; + + tmp = egg_action_group_get_action + (EGG_ACTION_GROUP (l->data), name); + if (tmp) action = tmp; + } + + return action; +} + +static void +add_action_to_list (EphyEditableToolbar *t, GList **list, const char *name) +{ + EggAction *action = NULL; + + action = find_action (t, name); + + if (!action) + { + g_signal_emit (t, EphyEditableToolbarSignals[REQUEST_ACTION], 0, name); + } + + action = find_action (t, name); + + if (action) + { + *list = g_list_append (*list, action); + } +} + +static void +parse_item_list (EphyEditableToolbar *t, + xmlNodePtr child, + GList **actions) +{ + while (child) + { + if (xmlStrEqual (child->name, "toolitem")) + { + xmlChar *verb; + + verb = xmlGetProp (child, "verb"); + add_action_to_list (t, actions, verb); + + xmlFree (verb); + } + else if (xmlStrEqual (child->name, "separator")) + { + *actions = g_list_append + (*actions, t->priv->separator); + } + + child = child->next; + } +} + +static void +parse_toolbars (EphyEditableToolbar *t, + xmlNodePtr child, + GList **toolbars) +{ + while (child) + { + if (xmlStrEqual (child->name, "toolbar")) + { + GList *list = NULL; + + parse_item_list (t, child->children, &list); + *toolbars = g_list_append (*toolbars, list); + } + + child = child->next; + } +} + +static void +load_defaults (EphyEditableToolbar *t) +{ + xmlDocPtr doc; + xmlNodePtr child; + xmlNodePtr root; + const char *xml_filepath; + + LOG ("Load default toolbar info") + + xml_filepath = ephy_file ("epiphany-toolbar.xml"); + + doc = xmlParseFile (xml_filepath); + root = xmlDocGetRootElement (doc); + + child = root->children; + while (child) + { + if (xmlStrEqual (child->name, "available")) + { + parse_item_list (t, child->children, + &t->priv->available_actions); + } + else if (xmlStrEqual (child->name, "default") && + t->priv->toolbars == NULL) + { + parse_toolbars (t, child->children, + &t->priv->toolbars); + } + + child = child->next; + } +} + +static void +load_toolbar (EphyEditableToolbar *t) +{ + xmlDocPtr doc; + xmlNodePtr root; + const char *xml_filepath = t->priv->filename; + + LOG ("Load custom toolbar") + + if (!g_file_test (xml_filepath, G_FILE_TEST_EXISTS)) return; + + doc = xmlParseFile (xml_filepath); + root = xmlDocGetRootElement (doc); + + parse_toolbars (t, root->children, + &t->priv->toolbars); +} + +static xmlDocPtr +toolbar_list_to_xml (EphyEditableToolbar *t, GList *tl) +{ + GList *l1, *l2; + xmlDocPtr doc; + + xmlIndentTreeOutput = TRUE; + doc = xmlNewDoc ("1.0"); + doc->children = xmlNewDocNode (doc, NULL, "toolbars", NULL); + + for (l1 = tl; l1 != NULL; l1 = l1->next) + { + xmlNodePtr tnode; + + tnode = xmlNewChild (doc->children, NULL, "toolbar", NULL); + + for (l2 = l1->data; l2 != NULL; l2 = l2->next) + { + xmlNodePtr node; + EggAction *action = EGG_ACTION (l2->data); + + if (action == t->priv->separator) + { + node = xmlNewChild (tnode, NULL, "separator", NULL); + } + else + { + node = xmlNewChild (tnode, NULL, "toolitem", NULL); + xmlSetProp (node, "verb", action->name); + } + } + } + + return doc; +} + +static char * +toolbar_list_to_string (EphyEditableToolbar *t, GList *tl) +{ + GString *s; + GList *l1, *l2; + char *result; + + s = g_string_new (NULL); + g_string_append (s, "<Root>"); + for (l1 = tl; l1 != NULL; l1 = l1->next) + { + int i = 0; + + g_string_append_printf + (s, "<dockitem name=\"Toolbar%d\">", + g_list_index (tl, l1->data)); + + for (l2 = l1->data; l2 != NULL; l2 = l2->next) + { + EggAction *action = EGG_ACTION (l2->data); + + if (action == t->priv->separator) + { + g_string_append_printf + (s, "<separator name=\"ToolItem%d\"/>", i); + } + else + { + g_string_append_printf + (s, "<toolitem name=\"ToolItem%d\" verb=\"%s\"/>", + i, action->name); + } + + i++; + } + + g_string_append (s, "</dockitem>"); + } + g_string_append (s, "</Root>"); + + result = s->str; + + g_string_free (s, FALSE); + + return result; +} + +static void +do_merge (EphyEditableToolbar *t) +{ + GList *tl; + char *str; + + tl = t->priv->toolbars; + + str = toolbar_list_to_string (t, tl); + + LOG ("Merge UI\n%s", str) + + egg_menu_merge_add_ui_from_string + (t->priv->merge, str, -1, NULL); + egg_menu_merge_ensure_update (t->priv->merge); + + g_free (str); +} + +static void +ephy_editable_toolbar_set_merge (EphyEditableToolbar *t, EggMenuMerge *merge) +{ + t->priv->merge = merge; + + LOG ("Got MenuMerge") + + load_toolbar (t); + load_defaults (t); + do_merge (t); +} + +static void +ephy_editable_toolbar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyEditableToolbar *t = EPHY_EDITABLE_TOOLBAR (object); + + switch (prop_id) + { + case PROP_MENU_MERGE: + ephy_editable_toolbar_set_merge (t, g_value_get_object (value)); + break; + } +} + +static void +ephy_editable_toolbar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyEditableToolbar *t = EPHY_EDITABLE_TOOLBAR (object); + + switch (prop_id) + { + case PROP_MENU_MERGE: + g_value_set_object (value, t->priv->merge); + break; + } +} + +static void +ephy_editable_toolbar_class_init (EphyEditableToolbarClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = ephy_editable_toolbar_finalize; + + object_class->set_property = ephy_editable_toolbar_set_property; + object_class->get_property = ephy_editable_toolbar_get_property; + + EphyEditableToolbarSignals[REQUEST_ACTION] = + g_signal_new + ("request_action", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, + G_STRUCT_OFFSET (EphyEditableToolbarClass, request_action), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + g_object_class_install_property (object_class, + PROP_MENU_MERGE, + g_param_spec_object ("MenuMerge", + "MenuMerge", + "Menu merge", + EGG_TYPE_MENU_MERGE, + G_PARAM_READWRITE)); +} + +static void +ephy_editable_toolbar_init (EphyEditableToolbar *t) +{ + t->priv = g_new0 (EphyEditableToolbarPrivate, 1); + + t->priv->merge = NULL; + t->priv->available_actions = NULL; + t->priv->toolbars = NULL; + t->priv->filename = g_build_filename (ephy_dot_dir (), "toolbar.xml", NULL); + t->priv->separator = g_object_new (EGG_TYPE_ACTION, NULL); +} + +static void +ephy_editable_toolbar_save (EphyEditableToolbar *t) +{ + xmlDocPtr doc; + + doc = toolbar_list_to_xml (t, t->priv->toolbars); + xmlSaveFormatFile (t->priv->filename, doc, 1); + xmlFreeDoc (doc); +} + +static void +ephy_editable_toolbar_finalize (GObject *object) +{ + EphyEditableToolbar *t = EPHY_EDITABLE_TOOLBAR (object); + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_EPHY_EDITABLE_TOOLBAR (object)); + + ephy_editable_toolbar_save (t); + + g_object_unref (t->priv->separator); + g_free (t->priv->filename); + + g_free (t->priv); + + LOG ("EphyEditableToolbar finalized") + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +EphyEditableToolbar * +ephy_editable_toolbar_new (EggMenuMerge *merge) +{ + EphyEditableToolbar *t; + + t = EPHY_EDITABLE_TOOLBAR (g_object_new (EPHY_EDITABLE_TOOLBAR_TYPE, + "MenuMerge", merge, + NULL)); + + g_return_val_if_fail (t->priv != NULL, NULL); + + return t; +} |