diff options
author | Christian Persch <chpe@cvs.gnome.org> | 2004-08-23 20:08:01 +0800 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2004-08-23 20:08:01 +0800 |
commit | b5a198b5d45ae6460919c4001a27574ff640ba27 (patch) | |
tree | 45a45e66ef0451e8b60186f75ec89a333d1ba69f | |
parent | d07a7cfd1903d727b888eeafd1858850ed467540 (diff) | |
download | gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.tar gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.tar.gz gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.tar.bz2 gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.tar.lz gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.tar.xz gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.tar.zst gsoc2013-epiphany-b5a198b5d45ae6460919c4001a27574ff640ba27.zip |
Make the hierarchy separator a #define.
2004-08-23 Christian Persch <chpe@cvs.gnome.org>
* src/bookmarks/ephy-bookmarks-editor.c: (cmd_bookmarks_import):
* src/bookmarks/ephy-bookmarks-import.c: (xbel_parse_folder),
(folders_list_to_topic_name):
* src/bookmarks/ephy-bookmarks.h:
Make the hierarchy separator a #define.
* src/bookmarks/ephy-bookmarks-menu.c: (remove_action),
(ephy_bookmarks_menu_clean), (open_bookmark_cb),
(add_action_for_bookmark), (ensure_bookmark_actions),
(create_menu), (create_submenu), (ephy_bookmarks_menu_rebuild),
(do_update_cb), (ephy_bookmarks_menu_maybe_update),
(ephy_bookmarks_menu_set_window),
(ephy_bookmarks_menu_set_property),
(ephy_bookmarks_menu_get_property), (bookmarks_tree_changed_cb),
(topics_added_cb), (topics_removed_cb), (topic_child_changed_cb),
(bookmark_added_cb), (bookmark_removed_cb), (activate_cb),
(ephy_bookmarks_menu_init), (ephy_bookmarks_menu_constructor),
(ephy_bookmarks_menu_finalize), (ephy_bookmarks_menu_class_init),
(ephy_bookmarks_menu_new):
* src/bookmarks/ephy-bookmarks-menu.h:
* src/bookmarks/ephy-bookmarks.c: (bookmarks_removed_cb),
(topics_removed_cb), (ephy_bookmarks_add):
Speed up bookmarks menu with large bookmarks collections, partially
fixes bug #141269.
Fix topic hierarchy and updating on changes, fixes bug #147470,
bug 147786, and bug #150246.
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-editor.c | 33 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-import.c | 8 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-menu.c | 565 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-menu.h | 17 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks.c | 4 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks.h | 2 |
7 files changed, 463 insertions, 197 deletions
@@ -1,5 +1,36 @@ 2004-08-23 Christian Persch <chpe@cvs.gnome.org> + * src/bookmarks/ephy-bookmarks-editor.c: (cmd_bookmarks_import): + * src/bookmarks/ephy-bookmarks-import.c: (xbel_parse_folder), + (folders_list_to_topic_name): + * src/bookmarks/ephy-bookmarks.h: + + Make the hierarchy separator a #define. + + * src/bookmarks/ephy-bookmarks-menu.c: (remove_action), + (ephy_bookmarks_menu_clean), (open_bookmark_cb), + (add_action_for_bookmark), (ensure_bookmark_actions), + (create_menu), (create_submenu), (ephy_bookmarks_menu_rebuild), + (do_update_cb), (ephy_bookmarks_menu_maybe_update), + (ephy_bookmarks_menu_set_window), + (ephy_bookmarks_menu_set_property), + (ephy_bookmarks_menu_get_property), (bookmarks_tree_changed_cb), + (topics_added_cb), (topics_removed_cb), (topic_child_changed_cb), + (bookmark_added_cb), (bookmark_removed_cb), (activate_cb), + (ephy_bookmarks_menu_init), (ephy_bookmarks_menu_constructor), + (ephy_bookmarks_menu_finalize), (ephy_bookmarks_menu_class_init), + (ephy_bookmarks_menu_new): + * src/bookmarks/ephy-bookmarks-menu.h: + * src/bookmarks/ephy-bookmarks.c: (bookmarks_removed_cb), + (topics_removed_cb), (ephy_bookmarks_add): + + Speed up bookmarks menu with large bookmarks collections, partially + fixes bug #141269. + Fix topic hierarchy and updating on changes, fixes bug #147470, + bug 147786, and bug #150246. + +2004-08-23 Christian Persch <chpe@cvs.gnome.org> + * NEWS: Merge from gnome-2-6 branch. diff --git a/src/bookmarks/ephy-bookmarks-editor.c b/src/bookmarks/ephy-bookmarks-editor.c index 74de22a34..5d80ec2aa 100644 --- a/src/bookmarks/ephy-bookmarks-editor.c +++ b/src/bookmarks/ephy-bookmarks-editor.c @@ -660,21 +660,6 @@ cmd_bookmarks_import (GtkAction *action, store = GTK_LIST_STORE (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING)); - sortmodel = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store)); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sortmodel), 0, GTK_SORT_ASCENDING); - - combo = gtk_combo_box_new (); - gtk_combo_box_set_model(GTK_COMBO_BOX (combo), sortmodel); - gtk_widget_show (combo); - g_object_set_data (G_OBJECT (dialog), "combo_box", combo); - g_object_unref (store); - - cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, - "text", 0, - NULL); - add_bookmarks_source (store, _("Firebird"), FIREBIRD_BOOKMARKS_DIR, "bookmarks.html", 4); add_bookmarks_source (store, _("Firefox"), @@ -689,9 +674,27 @@ cmd_bookmarks_import (GtkAction *action, gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, _("File"), 1, NULL, -1); + sortmodel = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store)); + g_object_unref (store); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sortmodel), 0, GTK_SORT_ASCENDING); + + combo = gtk_combo_box_new (); + gtk_combo_box_set_model(GTK_COMBO_BOX (combo), sortmodel); + g_object_set_data (G_OBJECT (dialog), "combo_box", combo); + g_object_unref (sortmodel); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell, + "text", 0, + NULL); + gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0); gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); + gtk_widget_show (combo); + g_signal_connect (dialog, "response", G_CALLBACK (import_dialog_response_cb), editor); diff --git a/src/bookmarks/ephy-bookmarks-import.c b/src/bookmarks/ephy-bookmarks-import.c index 9d5b0b19a..f41c882d5 100644 --- a/src/bookmarks/ephy-bookmarks-import.c +++ b/src/bookmarks/ephy-bookmarks-import.c @@ -1,6 +1,7 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Copyright (C) 2003 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Christian Persch * * 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 @@ -301,7 +302,8 @@ xbel_parse_folder (EphyBookmarks *eb, xmlTextReaderPtr reader, char *parent_fold } else { - folder = g_strconcat (parent_folder, "/", + folder = g_strconcat (parent_folder, + BOOKMARKS_HIERARCHY_SEP, title, NULL); } @@ -675,7 +677,7 @@ folders_list_to_topic_name (GList *folders) for (l = folders->next; l != NULL; l = l->next) { - g_string_append (topic, "/"); + g_string_append (topic, BOOKMARKS_HIERARCHY_SEP); g_string_append (topic, l->data); } diff --git a/src/bookmarks/ephy-bookmarks-menu.c b/src/bookmarks/ephy-bookmarks-menu.c index 2d383c850..4134e2c8e 100644 --- a/src/bookmarks/ephy-bookmarks-menu.c +++ b/src/bookmarks/ephy-bookmarks-menu.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003, 2004 Marco Pesenti Gritti + * Copyright (C) 2003, 2004 Christian Persch * * 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 @@ -32,31 +33,54 @@ #include <glib/gprintf.h> #include <glib/gi18n.h> #include <gtk/gtkuimanager.h> - -#define BOOKMARKS_MENU_PATH "/menubar/BookmarksMenu" +#include <string.h> #define EPHY_BOOKMARKS_MENU_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARKS_MENU, EphyBookmarksMenuPrivate)) struct _EphyBookmarksMenuPrivate { - GtkUIManager *merge; + GtkUIManager *manager; EphyWindow *window; EphyBookmarks *bookmarks; - GtkActionGroup *action_group; + GtkActionGroup *bmk_actions; + GtkActionGroup *folder_actions; + GSList *removed_bmks; guint ui_id; guint update_tag; + gboolean needs_update; }; -static void ephy_bookmarks_menu_class_init (EphyBookmarksMenuClass *klass); -static void ephy_bookmarks_menu_init (EphyBookmarksMenu *menu); -static void ephy_bookmarks_menu_finalize (GObject *o); +#define BOOKMARKS_MENU_PATH "/menubar/BookmarksMenu" + +/* 14 = strlen ("0000000000000000") - strlen ("%x") + * FIXME: for 32bit, 6 is sufficient -> use some #if magic? + */ +#define MAXLEN 14 + +/* this %x is bookmark node id */ +#define BMK_VERB_FORMAT "Bmk%x" +#define BMK_VERB_FORMAT_LENGTH strlen (BMK_VERB_FORMAT) + MAXLEN + 1 + +/* first %x is bookmark node id, second %x is g_str_hash of path */ +#define BMK_NAME_FORMAT "Bmk%x%x" +#define BMK_NAME_FORMAT_LENGTH strlen (BMK_NAME_FORMAT) + 2 * MAXLEN + 1 + +/* first %x is g_str_hash of folder name, 2nd %x is g_str_hash of path */ +#define FOLDER_VERB_FORMAT "Fld%x%x" +#define FOLDER_VERB_FORMAT_LENGTH strlen (FOLDER_VERB_FORMAT) + 2 * MAXLEN + 1 + +#define GAZILLION 200 +#define UPDATE_DELAY 5000 /* ms */ enum { PROP_0, - PROP_EPHY_WINDOW + PROP_WINDOW }; +static void ephy_bookmarks_menu_class_init (EphyBookmarksMenuClass *klass); +static void ephy_bookmarks_menu_init (EphyBookmarksMenu *menu); + static GObjectClass *parent_class = NULL; GType @@ -88,32 +112,113 @@ ephy_bookmarks_menu_get_type (void) } static void +remove_action (gpointer idptr, + GtkActionGroup *action_group) +{ + GtkAction *action; + char verb[BMK_VERB_FORMAT_LENGTH]; + + g_snprintf (verb, sizeof (verb), BMK_VERB_FORMAT, GPOINTER_TO_UINT (idptr)); + action = gtk_action_group_get_action (action_group, verb); + g_return_if_fail (action != NULL); + + gtk_action_group_remove_action (action_group, action); +} + +static void ephy_bookmarks_menu_clean (EphyBookmarksMenu *menu) { EphyBookmarksMenuPrivate *p = menu->priv; START_PROFILER ("Cleaning bookmarks menu") - if (p->ui_id > 0) + if (p->ui_id != 0) { - gtk_ui_manager_remove_ui (p->merge, p->ui_id); - gtk_ui_manager_ensure_update (p->merge); + gtk_ui_manager_remove_ui (p->manager, p->ui_id); + gtk_ui_manager_ensure_update (p->manager); p->ui_id = 0; } - if (p->action_group != NULL) + if (p->bmk_actions != NULL && menu->priv->removed_bmks != NULL) + { + /* now we can remove the actions for removed bookmarks */ + g_slist_foreach (menu->priv->removed_bmks, (GFunc) remove_action, + menu->priv->bmk_actions); + g_slist_free (menu->priv->removed_bmks); + menu->priv->removed_bmks = NULL; + } + + if (p->folder_actions != NULL) { - gtk_ui_manager_remove_action_group (p->merge, p->action_group); - g_object_unref (p->action_group); + gtk_ui_manager_remove_action_group (p->manager, p->folder_actions); + g_object_unref (p->folder_actions); } STOP_PROFILER ("Cleaning bookmarks menu") } static void -open_bookmark_cb (GtkAction *action, char *location, EphyWindow *window) +open_bookmark_cb (GtkAction *action, + char *location, + EphyBookmarksMenu *menu) { - ephy_window_load_url (window, location); + ephy_window_load_url (menu->priv->window, location); +} + +#define BMK_ACCEL_PATH_PREFIX "<Actions>/BmkActions/" + +static void +add_action_for_bookmark (EphyBookmarksMenu *menu, + EphyNode *bmk) +{ + GtkAction *action; + char verb[BMK_VERB_FORMAT_LENGTH]; + char apath[strlen (BMK_ACCEL_PATH_PREFIX) + BMK_VERB_FORMAT_LENGTH]; + guint id; + + g_return_if_fail (bmk != NULL); + + id = ephy_node_get_id (bmk); + + g_snprintf (verb, sizeof (verb), BMK_VERB_FORMAT, id); + g_snprintf (apath, sizeof (apath), BMK_ACCEL_PATH_PREFIX "%s", verb); + + action = ephy_bookmark_action_new (verb, id); + + gtk_action_set_accel_path (action, apath); + + g_signal_connect (action, "activate", + G_CALLBACK (open_bookmark_cb), menu); + + gtk_action_group_add_action (menu->priv->bmk_actions, action); + g_object_unref (action); +} + +static void +ensure_bookmark_actions (EphyBookmarksMenu *menu) +{ + EphyNode *bookmarks, *bmk; + GPtrArray *children; + int i; + + if (menu->priv->bmk_actions != NULL) return; + + START_PROFILER ("Adding bookmarks actions") + + menu->priv->bmk_actions = gtk_action_group_new ("BmkActions"); + gtk_ui_manager_insert_action_group (menu->priv->manager, + menu->priv->bmk_actions, -1); + + bookmarks = ephy_bookmarks_get_bookmarks (menu->priv->bookmarks); + children = ephy_node_get_children (bookmarks); + for (i = 0; i < children->len; i++) + { + bmk = g_ptr_array_index (children, i); + + add_action_for_bookmark (menu, bmk); + } + + STOP_PROFILER ("Adding bookmarks actions") } static int @@ -183,13 +288,18 @@ sort_bookmarks (gconstpointer a, gconstpointer b) } static void -create_menu (EphyBookmarksMenu *menu, EphyNode *node, const char *path) +create_menu (EphyBookmarksMenu *menu, + EphyNode *node, + const char *path) { GPtrArray *children; EphyBookmarksMenuPrivate *p = menu->priv; GList *node_list = NULL, *l; + guint phash; int i; + phash = g_str_hash (path); + children = ephy_node_get_children (node); for (i = 0; i < children->len; ++i) { @@ -197,96 +307,93 @@ create_menu (EphyBookmarksMenu *menu, EphyNode *node, const char *path) g_ptr_array_index (children, i)); } - if (node_list != NULL) + node_list = g_list_sort (node_list, (GCompareFunc)sort_bookmarks); + for (l = node_list; l != NULL; l = l->next) { - node_list = g_list_sort (node_list, (GCompareFunc)sort_bookmarks); - for (l = node_list; l != NULL; l = l->next) - { - GtkAction *action; - EphyNode *child; - long id; - char verb[30], name[30], accel_path[60]; - - child = l->data; - id = ephy_node_get_id (child); - g_snprintf (verb, sizeof (verb), - "OpenBmk%d", ephy_node_get_id (child)); - g_snprintf (name, sizeof (name), "%sName", verb); - g_snprintf (accel_path, sizeof (accel_path), - "<Actions>/BookmarksActions/%s", verb); - - action = ephy_bookmark_action_new (verb, id); - gtk_action_set_accel_path (action, accel_path); - gtk_action_group_add_action (p->action_group, action); - g_object_unref (action); - g_signal_connect (action, "open", - G_CALLBACK (open_bookmark_cb), p->window); + char verb[BMK_VERB_FORMAT_LENGTH]; + char name[BMK_NAME_FORMAT_LENGTH]; + guint id; - gtk_ui_manager_add_ui (p->merge, p->ui_id, path, - name, verb, - GTK_UI_MANAGER_MENUITEM, FALSE); - } - g_list_free (node_list); - } -} + id = ephy_node_get_id ((EphyNode *) l->data); -static void -ensure_folder (EphyBookmarksMenu *menu, const char *path, const char *folder) -{ - EphyBookmarksMenuPrivate *p = menu->priv; - char *action_name; - GtkAction *action; + g_snprintf (verb, sizeof (verb), BMK_VERB_FORMAT, id); + g_snprintf (name, sizeof (name), BMK_NAME_FORMAT, id, phash); - g_return_if_fail (folder != NULL); - - action_name = g_strdup_printf ("TopicAction-%s\n", folder); - action = gtk_action_group_get_action (p->action_group, action_name); - - if (action == NULL) - { - action = g_object_new (GTK_TYPE_ACTION, - "name", action_name, - "label", folder, - "hide_if_empty", FALSE, - NULL); - gtk_action_group_add_action (p->action_group, action); - g_object_unref (action); - - gtk_ui_manager_add_ui (p->merge, p->ui_id, path, - folder, action_name, - GTK_UI_MANAGER_MENU, FALSE); + gtk_ui_manager_add_ui (p->manager, p->ui_id, path, + name, verb, + GTK_UI_MANAGER_MENUITEM, FALSE); } - - g_free (action_name); + g_list_free (node_list); } +#define FOLDER_ACCEL_PATH_PREFIX "<Actions>/FolderActions/" + static char * -create_submenu (EphyBookmarksMenu *menu, EphyNode *topic) +create_submenu (EphyBookmarksMenu *menu, + EphyNode *topic) { + EphyBookmarksMenuPrivate *p = menu->priv; + GtkAction *action; + char verb[FOLDER_VERB_FORMAT_LENGTH]; + char apath[strlen (FOLDER_ACCEL_PATH_PREFIX) + FOLDER_VERB_FORMAT_LENGTH]; const char *tmp; char *title, *folder; char **folders; GString *path; + guint phash, fhash; int i; tmp = ephy_node_get_property_string (topic, EPHY_NODE_KEYWORD_PROP_NAME); - title = ephy_string_double_underscores (tmp); - - g_return_val_if_fail (title != NULL, NULL); + g_return_val_if_fail (tmp != NULL, NULL); - folders = g_strsplit (title, "/", -1); + title = ephy_string_double_underscores (tmp); + folders = g_strsplit (title, BOOKMARKS_HIERARCHY_SEP, -1); g_free (title); - g_return_val_if_fail (folders != NULL, NULL); /* FIXME */ + + /* occurs if topic name was "" or BOOKMARKS_HIERARCHY_SEP */ + if (folders == NULL || folders[0] == NULL) + { + g_strfreev (folders); + return g_strdup (BOOKMARKS_MENU_PATH); + } path = g_string_new (BOOKMARKS_MENU_PATH); for (i = 0; folders[i] != NULL; i++) { folder = folders[i]; - ensure_folder (menu, path->str, folder); + /* happens for BOOKMARKS_HIERARCHY_SEP at start/end of title, + * or when occurring twice in succession. + * Treat as if it didn't occur/only occurred once. + */ + if (folders[i][0] == '\0') continue; + + phash = g_str_hash (path->str); + fhash = g_str_hash (folder); + g_snprintf (verb, sizeof (verb), FOLDER_VERB_FORMAT, fhash, phash); + + if (gtk_action_group_get_action (p->folder_actions, verb) == NULL) + { + g_snprintf (apath, sizeof (apath), + FOLDER_ACCEL_PATH_PREFIX "%s", verb); + + action = g_object_new (GTK_TYPE_ACTION, + "name", verb, + "label", folder, + "hide_if_empty", FALSE, + NULL); + gtk_action_set_accel_path (action, apath); + + gtk_action_group_add_action (p->folder_actions, action); + g_object_unref (action); + + gtk_ui_manager_add_ui (p->manager, p->ui_id, path->str, + verb, verb, + GTK_UI_MANAGER_MENU, FALSE); + } g_string_append (path, "/"); - g_string_append (path, folder); + g_string_append (path, verb); } g_strfreev (folders); @@ -298,11 +405,18 @@ static void ephy_bookmarks_menu_rebuild (EphyBookmarksMenu *menu) { EphyBookmarksMenuPrivate *p = menu->priv; - gint i; - EphyNode *topics; - EphyNode *not_categorized; + EphyNode *topics, *not_categorized, *node; GPtrArray *children; GList *node_list = NULL, *l; + char *path; + int i; + + if (menu->priv->needs_update == FALSE) + { + LOG ("No update required") + + return; + } LOG ("Rebuilding bookmarks menu") @@ -310,14 +424,14 @@ ephy_bookmarks_menu_rebuild (EphyBookmarksMenu *menu) START_PROFILER ("Rebuilding bookmarks menu") - topics = ephy_bookmarks_get_keywords (p->bookmarks); - not_categorized = ephy_bookmarks_get_not_categorized (p->bookmarks); - children = ephy_node_get_children (topics); + ensure_bookmark_actions (menu); + p->folder_actions = gtk_action_group_new ("FolderActions"); + gtk_ui_manager_insert_action_group (p->manager, p->folder_actions, -1); - p->ui_id = gtk_ui_manager_new_merge_id (p->merge); + p->ui_id = gtk_ui_manager_new_merge_id (p->manager); - p->action_group = gtk_action_group_new ("BookmarksActions"); - gtk_ui_manager_insert_action_group (p->merge, p->action_group, 0); + topics = ephy_bookmarks_get_keywords (p->bookmarks); + children = ephy_node_get_children (topics); for (i = 0; i < children->len; ++i) { @@ -335,17 +449,19 @@ ephy_bookmarks_menu_rebuild (EphyBookmarksMenu *menu) } } - node_list = g_list_sort (node_list, (GCompareFunc)sort_topics); + node_list = g_list_sort (node_list, (GCompareFunc) sort_topics); for (l = node_list; l != NULL; l = l->next) { - char *path; + node = (EphyNode *) l->data; - path = create_submenu (menu, l->data); - create_menu (menu, l->data, path); + path = create_submenu (menu, node); + create_menu (menu, node, path); g_free (path); } + not_categorized = ephy_bookmarks_get_not_categorized (p->bookmarks); + if (ephy_node_get_n_children (not_categorized) > 0) { create_menu (menu, not_categorized, BOOKMARKS_MENU_PATH); @@ -354,14 +470,60 @@ ephy_bookmarks_menu_rebuild (EphyBookmarksMenu *menu) g_list_free (node_list); STOP_PROFILER ("Rebuilding bookmarks menu") + + menu->priv->needs_update = FALSE; +} + +static gboolean +do_update_cb (EphyBookmarksMenu *menu) +{ + LOG ("do_update_cb") + + ephy_bookmarks_menu_rebuild (menu); + menu->priv->update_tag = 0; + + /* don't run again */ + return FALSE; } static void -ephy_bookmarks_menu_set_window (EphyBookmarksMenu *menu, EphyWindow *window) +ephy_bookmarks_menu_maybe_update (EphyBookmarksMenu *menu) +{ + EphyNode *bookmarks; + GPtrArray *children; + + menu->priv->needs_update = TRUE; + + /* FIXME: is there any way that we get here while the menu is popped up? + * if so, needs to do_update NOW + */ + + /* if there are only a few bookmarks, update soon */ + bookmarks = ephy_bookmarks_get_bookmarks (menu->priv->bookmarks); + children = ephy_node_get_children (bookmarks); + if (children->len < GAZILLION) + { + if (menu->priv->update_tag == 0) + { + menu->priv->update_tag = + g_timeout_add (UPDATE_DELAY, + (GSourceFunc) do_update_cb, menu); + } + } + else if (menu->priv->update_tag != 0) + { + /* remove scheduled update, update on demand */ + g_source_remove (menu->priv->update_tag); + menu->priv->update_tag = 0; + } +} + +static void +ephy_bookmarks_menu_set_window (EphyBookmarksMenu *menu, + EphyWindow *window) { menu->priv->window = window; - menu->priv->merge = GTK_UI_MANAGER (window->ui_merge); - ephy_bookmarks_menu_rebuild (menu); + menu->priv->manager = GTK_UI_MANAGER (window->ui_merge); } static void @@ -374,7 +536,7 @@ ephy_bookmarks_menu_set_property (GObject *object, switch (prop_id) { - case PROP_EPHY_WINDOW: + case PROP_WINDOW: ephy_bookmarks_menu_set_window (m, g_value_get_object (value)); break; @@ -391,109 +553,127 @@ ephy_bookmarks_menu_get_property (GObject *object, switch (prop_id) { - case PROP_EPHY_WINDOW: + case PROP_WINDOW: g_value_set_object (value, m->priv->window); break; } } - static void -ephy_bookmarks_menu_class_init (EphyBookmarksMenuClass *klass) +bookmarks_tree_changed_cb (EphyBookmarks *bookmarks, + EphyBookmarksMenu *menu) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); + LOG ("bookmarks_tree_changed_cb") - object_class->finalize = ephy_bookmarks_menu_finalize; - object_class->set_property = ephy_bookmarks_menu_set_property; - object_class->get_property = ephy_bookmarks_menu_get_property; + ephy_bookmarks_menu_maybe_update (menu); +} - g_object_class_install_property (object_class, - PROP_EPHY_WINDOW, - g_param_spec_object ("EphyWindow", - "EphyWindow", - "Parent window", - EPHY_TYPE_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); +static void +topics_added_cb (EphyNode *keywords, + EphyNode *bmk, + EphyBookmarksMenu *menu) +{ + LOG ("topics_added_cb") - g_type_class_add_private (object_class, sizeof(EphyBookmarksMenuPrivate)); + ephy_bookmarks_menu_maybe_update (menu); } -static gboolean -do_updates (EphyBookmarksMenu *menu) +static void +topics_removed_cb (EphyNode *keywords, + EphyNode *child, + guint old_index, + EphyBookmarksMenu *menu) { - ephy_bookmarks_menu_rebuild (menu); - - menu->priv->update_tag = 0; + LOG ("topics_removed_cb") - return FALSE; + ephy_bookmarks_menu_maybe_update (menu); } static void -bookmarks_tree_changed_cb (EphyBookmarks *bookmarks, EphyBookmarksMenu *menu) +topic_child_changed_cb (EphyNode *node, + EphyNode *child, + guint property_id, + EphyBookmarksMenu *menu) { - if (menu->priv->update_tag == 0) + LOG ("topic_child_changed_cb id=%d property=%d", + ephy_node_get_id (child), property_id) + + if (property_id == EPHY_NODE_KEYWORD_PROP_NAME) { - menu->priv->update_tag = g_idle_add((GSourceFunc)do_updates, menu); + /* the title of the topic has changed, which may change the + * hierarchy. + */ + ephy_bookmarks_menu_maybe_update (menu); } } static void -sync_topic_properties (GtkAction *action, EphyNode *bmk) +bookmark_added_cb (EphyNode *bookmarks, + EphyNode *bmk, + EphyBookmarksMenu *menu) { - const char *tmp; - char *title; - int priority; - - priority = ephy_node_get_property_int - (bmk, EPHY_NODE_KEYWORD_PROP_PRIORITY); - - tmp = ephy_node_get_property_string - (bmk, EPHY_NODE_KEYWORD_PROP_NAME); + LOG ("bookmark_added_cb id=%d", ephy_node_get_id (bmk)) - title = ephy_string_double_underscores (tmp); - - g_object_set (action, "label", title, NULL); + if (menu->priv->bmk_actions != NULL) + { + add_action_for_bookmark (menu, bmk); - g_free (title); + ephy_bookmarks_menu_maybe_update (menu); + } } static void -topic_child_changed_cb (EphyNode *node, - EphyNode *child, - guint property_id, - EphyBookmarksMenu *menu) +bookmark_removed_cb (EphyNode *bookmarks, + EphyNode *bmk, + guint old_index, + EphyBookmarksMenu *menu) { - GtkAction *action; - char name[64]; + LOG ("bookmark_removed_cb id=%d", ephy_node_get_id (bmk)) - if (menu->priv->update_tag != 0 || menu->priv->action_group == NULL) + if (menu->priv->bmk_actions != NULL) { - return; + /* we cannot remove the action here since the menu might still + * reference it. + */ + menu->priv->removed_bmks = + g_slist_prepend (menu->priv->removed_bmks, + GUINT_TO_POINTER (ephy_node_get_id (bmk))); + + ephy_bookmarks_menu_maybe_update (menu); } +} - g_snprintf (name, sizeof (name), "OpenTopic%d", ephy_node_get_id (child)); - - action = gtk_action_group_get_action (menu->priv->action_group, name); +static void +activate_cb (GtkAction *action, + EphyBookmarksMenu *menu) +{ + LOG ("activate_cb") - if (action != NULL) - { - sync_topic_properties (action, child); - } + ephy_bookmarks_menu_rebuild (menu); } static void ephy_bookmarks_menu_init (EphyBookmarksMenu *menu) { - EphyBookmarksMenuPrivate *p = EPHY_BOOKMARKS_MENU_GET_PRIVATE (menu); + menu->priv = EPHY_BOOKMARKS_MENU_GET_PRIVATE (menu); +} + +static GObject * +ephy_bookmarks_menu_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + EphyBookmarksMenu *menu; + GObject *object; + GtkAction *action; EphyNode *node; - menu->priv = p; - menu->priv->ui_id = 0; - menu->priv->action_group = NULL; - menu->priv->update_tag = 0; + object = parent_class->constructor (type, n_construct_properties, + construct_params); + + menu = EPHY_BOOKMARKS_MENU (object); + + g_assert (menu->priv->window != NULL); menu->priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell); g_signal_connect_object (menu->priv->bookmarks, "tree_changed", @@ -501,9 +681,32 @@ ephy_bookmarks_menu_init (EphyBookmarksMenu *menu) menu, 0); node = ephy_bookmarks_get_keywords (menu->priv->bookmarks); + ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED, + (EphyNodeCallback) topics_added_cb, + G_OBJECT (menu)); + ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED, + (EphyNodeCallback) topics_removed_cb, + G_OBJECT (menu)); ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_CHANGED, (EphyNodeCallback) topic_child_changed_cb, G_OBJECT (menu)); + + node = ephy_bookmarks_get_bookmarks (menu->priv->bookmarks); + ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED, + (EphyNodeCallback) bookmark_added_cb, + G_OBJECT (menu)); + ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED, + (EphyNodeCallback) bookmark_removed_cb, + G_OBJECT (menu)); + + action = gtk_ui_manager_get_action (menu->priv->manager, + BOOKMARKS_MENU_PATH); + g_signal_connect_object (action, "activate", + G_CALLBACK (activate_cb), menu, 0); + + ephy_bookmarks_menu_maybe_update (menu); + + return object; } static void @@ -517,19 +720,51 @@ ephy_bookmarks_menu_finalize (GObject *o) g_source_remove (menu->priv->update_tag); } - if (p->action_group != NULL) + g_slist_free (menu->priv->removed_bmks); + + if (p->bmk_actions != NULL) + { + g_object_unref (p->bmk_actions); + } + + if (p->folder_actions != NULL) { - g_object_unref (p->action_group); + g_object_unref (p->folder_actions); } + LOG ("EphyBookmarksMenu finalised %p", o); + G_OBJECT_CLASS (parent_class)->finalize (o); } +static void +ephy_bookmarks_menu_class_init (EphyBookmarksMenuClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->constructor = ephy_bookmarks_menu_constructor; + object_class->finalize = ephy_bookmarks_menu_finalize; + object_class->set_property = ephy_bookmarks_menu_set_property; + object_class->get_property = ephy_bookmarks_menu_get_property; + + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "Parent window", + EPHY_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof (EphyBookmarksMenuPrivate)); +} + EphyBookmarksMenu * ephy_bookmarks_menu_new (EphyWindow *window) { - EphyBookmarksMenu *ret = g_object_new (EPHY_TYPE_BOOKMARKS_MENU, - "EphyWindow", window, - NULL); - return ret; + return EPHY_BOOKMARKS_MENU (g_object_new (EPHY_TYPE_BOOKMARKS_MENU, + "window", window, + NULL)); } diff --git a/src/bookmarks/ephy-bookmarks-menu.h b/src/bookmarks/ephy-bookmarks-menu.h index a17797923..890b388fe 100644 --- a/src/bookmarks/ephy-bookmarks-menu.h +++ b/src/bookmarks/ephy-bookmarks-menu.h @@ -23,15 +23,7 @@ #include "ephy-window.h" -/* object forward declarations */ - -typedef struct _EphyBookmarksMenu EphyBookmarksMenu; -typedef struct _EphyBookmarksMenuClass EphyBookmarksMenuClass; -typedef struct _EphyBookmarksMenuPrivate EphyBookmarksMenuPrivate; - -/** - * Editor object - */ +G_BEGIN_DECLS #define EPHY_TYPE_BOOKMARKS_MENU (ephy_bookmarks_menu_get_type()) #define EPHY_BOOKMARKS_MENU(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_BOOKMARKS_MENU, EphyBookmarksMenu)) @@ -40,6 +32,10 @@ typedef struct _EphyBookmarksMenuPrivate EphyBookmarksMenuPrivate; #define EPHY_IS_BOOKMARKS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_BOOKMARKS_MENU)) #define EPHY_BOOKMARKS_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_BOOKMARKS_MENU, EphyBookmarksMenuClass)) +typedef struct _EphyBookmarksMenu EphyBookmarksMenu; +typedef struct _EphyBookmarksMenuClass EphyBookmarksMenuClass; +typedef struct _EphyBookmarksMenuPrivate EphyBookmarksMenuPrivate; + struct _EphyBookmarksMenuClass { GObjectClass parent_class; @@ -57,5 +53,6 @@ GType ephy_bookmarks_menu_get_type (void); EphyBookmarksMenu *ephy_bookmarks_menu_new (EphyWindow *window); -#endif +G_END_DECLS +#endif diff --git a/src/bookmarks/ephy-bookmarks.c b/src/bookmarks/ephy-bookmarks.c index 99681204a..0ce26d9f4 100644 --- a/src/bookmarks/ephy-bookmarks.c +++ b/src/bookmarks/ephy-bookmarks.c @@ -564,7 +564,6 @@ bookmarks_removed_cb (EphyNode *node, guint old_index, EphyBookmarks *eb) { - g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0); ephy_bookmarks_save_delayed (eb, BOOKMARKS_SAVE_DELAY); } @@ -618,8 +617,6 @@ topics_removed_cb (EphyNode *node, update_bookmark_keywords (eb, kid); } - - g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0); } static void @@ -901,7 +898,6 @@ ephy_bookmarks_add (EphyBookmarks *eb, ephy_node_add_child (eb->priv->bookmarks, bm); ephy_node_add_child (eb->priv->notcategorized, bm); - g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0); ephy_bookmarks_save_delayed (eb, 0); return bm; diff --git a/src/bookmarks/ephy-bookmarks.h b/src/bookmarks/ephy-bookmarks.h index 26c83832e..2cd6862a2 100644 --- a/src/bookmarks/ephy-bookmarks.h +++ b/src/bookmarks/ephy-bookmarks.h @@ -40,6 +40,8 @@ typedef struct EphyBookmarksClass EphyBookmarksClass; typedef struct EphyBookmarks EphyBookmarks; typedef struct EphyBookmarksPrivate EphyBookmarksPrivate; +#define BOOKMARKS_HIERARCHY_SEP "/" + enum { EPHY_NODE_BMK_PROP_TITLE = 2, |