aboutsummaryrefslogtreecommitdiffstats
path: root/src/bookmarks
diff options
context:
space:
mode:
authorPeter Harvey <pah06@uow.edu.au>2005-10-17 04:29:26 +0800
committerChristian Persch <chpe@src.gnome.org>2005-10-17 04:29:26 +0800
commitd21007362f8d0701d63e50fe6b219de067d95a87 (patch)
tree46326d5633d4f3c8504049476d0e72ae7ed0ca2c /src/bookmarks
parent35b9deda1f37ac0cc81d926b5295983de6b55dcf (diff)
downloadgsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.tar
gsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.tar.gz
gsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.tar.bz2
gsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.tar.lz
gsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.tar.xz
gsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.tar.zst
gsoc2013-epiphany-d21007362f8d0701d63e50fe6b219de067d95a87.zip
H18 patch, by Peter Harvey <pah06@uow.edu.au>.
2005-10-16 Peter Harvey <pah06@uow.edu.au> H18 patch, by Peter Harvey <pah06@uow.edu.au>. * data/ui/epiphany-bookmark-editor-ui.xml: * data/ui/epiphany-ui.xml: * lib/egg/egg-editable-toolbar.c: (get_dock_position), (get_toolbar_position), (get_toolbar_nth), (find_action), (drag_data_delete_cb), (drag_begin_cb), (drag_end_cb), (drag_data_get_cb), (move_item_cb), (set_dock_visible), (remove_item_cb), (remove_toolbar_cb), (toggle_visibility_cb), (egg_editable_toolbar_add_visibility_items), (egg_editable_toolbar_add_popup_items), (popup_context_menu_cb), (button_press_event_cb), (configure_item_sensitivity), (configure_item_cursor), (connect_widget_signals), (action_sensitive_cb), (create_item_from_action), (create_item_from_position), (toolbar_drag_data_received_cb), (toolbar_drag_drop_cb), (toolbar_drag_motion_cb), (toolbar_drag_leave_cb), (configure_drag_dest), (create_dock), (toolbar_changed_cb), (unparent_fixed), (update_fixed), (toolbar_added_cb), (toolbar_removed_cb), (item_added_cb), (item_removed_cb), (egg_editable_toolbar_construct), (egg_editable_toolbar_set_ui_manager), (egg_editable_toolbar_set_property), (egg_editable_toolbar_get_property), (egg_editable_toolbar_init), (egg_editable_toolbar_finalize), (egg_editable_toolbar_get_edit_mode), (egg_editable_toolbar_set_edit_mode), (egg_editable_toolbar_set_fixed): * lib/egg/egg-editable-toolbar.h: * lib/egg/egg-toolbar-editor.c: (compare_items), (item_added_or_removed_cb), (toolbar_removed_cb), (egg_toolbar_editor_set_model), (egg_toolbar_editor_finalize), (drag_begin_cb), (drag_end_cb), (drag_data_get_cb), (editor_create_item), (editor_create_item_from_name), (append_table), (update_editor_sheet), (egg_toolbar_editor_init): * lib/egg/egg-toolbar-editor.h: * lib/egg/egg-toolbars-model.c: (egg_toolbars_model_to_xml), (egg_toolbars_model_save), (toolbar_node_new), (item_node_new), (item_node_free), (toolbar_node_free), (egg_toolbars_model_get_flags), (egg_toolbars_model_set_flags), (egg_toolbars_model_get_data), (egg_toolbars_model_get_name), (impl_add_item), (egg_toolbars_model_add_item), (egg_toolbars_model_add_toolbar), (parse_data_list), (parse_item_list), (parse_toolbars), (egg_toolbars_model_load), (egg_toolbars_model_class_init), (egg_toolbars_model_init), (egg_toolbars_model_finalize), (egg_toolbars_model_remove_toolbar), (egg_toolbars_model_remove_item), (egg_toolbars_model_move_item), (egg_toolbars_model_n_items), (egg_toolbars_model_item_nth), (egg_toolbars_model_n_toolbars), (egg_toolbars_model_toolbar_nth), (egg_toolbars_model_get_types), (egg_toolbars_model_set_types), (fill_avail_array), (egg_toolbars_model_get_avail), (egg_toolbars_model_get_n_avail), (egg_toolbars_model_set_n_avail): * lib/egg/egg-toolbars-model.h: * src/bookmarks/Makefile.am: * src/bookmarks/ephy-bookmark-action-group.c: (smart_added_cb), (smart_removed_cb), (node_changed_cb), (node_added_cb), (node_removed_cb), (ephy_bookmark_group_new): * src/bookmarks/ephy-bookmark-action-group.h: * src/bookmarks/ephy-bookmark-action.c: (create_tool_item), (ephy_bookmark_action_sync_icon), (show_context_menu), (popup_menu_cb), (button_press_cb), (button_release_cb), (connect_proxy), (ephy_bookmark_action_updated), (ephy_bookmark_action_get_bookmark), (ephy_bookmark_action_set_bookmark), (ephy_bookmark_action_set_property), (ephy_bookmark_action_get_property), (ephy_bookmark_action_finalize), (ephy_bookmark_action_class_init), (ephy_bookmark_action_init), (ephy_bookmark_action_name), (ephy_bookmark_action_new): * src/bookmarks/ephy-bookmark-action.h: * src/bookmarks/ephy-bookmark-factory-action.c: (ephy_bookmark_factory_action_get_type), (activate_item_cb), (build_menu_for_topic), (build_menu), (remove_placeholder_cb), (activate_placeholder_cb), (clicked_placeholder_cb), (realize_placeholder_cb), (create_tool_item), (connect_proxy), (ephy_bookmark_factory_action_class_init), (ephy_bookmark_factory_action_new): * src/bookmarks/ephy-bookmark-factory-action.h: * src/bookmarks/ephy-bookmark-properties.c: (ephy_bookmark_properties_set_property), (ephy_bookmark_properties_get_property), (bookmark_properties_response_cb), (update_entry), (location_entry_changed_cb), (build_ui): * src/bookmarks/ephy-bookmarks-editor.c: (add_entry_monitor), (cmd_add_topic), (delete_topic_dialog_construct), (cmd_bookmarks_import), (ephy_bookmarks_editor_finalize), (ephy_bookmarks_editor_node_activated_cb), (ephy_bookmarks_editor_update_menu), (view_focus_cb), (add_focus_monitor), (remove_focus_monitor), (bookmarks_filter), (search_entry_search_cb), (ephy_bookmarks_editor_construct), (ephy_bookmarks_editor_set_parent), (ephy_bookmarks_editor_set_property), (ephy_bookmarks_editor_get_property), (ephy_bookmarks_editor_init): * src/bookmarks/ephy-bookmarks-menu.c: (append_bookmarks), (append_menu), (ephy_bookmarks_menu_build): * src/bookmarks/ephy-bookmarks-menu.h: * src/bookmarks/ephy-bookmarks-ui.c: (find_action), (activate_bookmarks_menu), (activate_favorites_menu), (erase_bookmarks_menu), (erase_favorites_menu), (tree_changed_cb), (node_added_cb), (node_changed_cb), (node_removed_cb), (ephy_bookmarks_ui_attach_window), (ephy_bookmarks_ui_detach_window), (toolbar_node_removed_cb), (topic_has_data), (topic_get_data), (topic_get_name), (bookmark_has_data), (bookmark_get_data), (bookmark_get_name), (bookmark_new_name), (ephy_bookmarks_ui_attach_toolbar_model), (ephy_bookmarks_ui_detach_toolbar_model): * src/bookmarks/ephy-bookmarks-ui.h: * src/bookmarks/ephy-bookmarks.c: (ephy_bookmarks_get_type), (ephy_bookmarks_init_defaults), (ephy_bookmarks_class_init), (ephy_bookmarks_save_delayed), (add_to_favorites), (update_bookmark_keywords), (ephy_bookmarks_init), (ephy_bookmarks_finalize), (ephy_bookmarks_add), (ephy_bookmarks_set_address), (ephy_bookmarks_set_icon), (ephy_bookmarks_add_keyword), (ephy_bookmarks_show_bookmark_properties), (ephy_bookmarks_get_from_id), (ephy_bookmarks_compare_topics), (ephy_bookmarks_compare_topic_pointers), (ephy_bookmarks_compare_bookmarks), (ephy_bookmarks_compare_bookmark_pointers): * src/bookmarks/ephy-bookmarks.h: * src/bookmarks/ephy-bookmarksbar-model.c: * src/bookmarks/ephy-bookmarksbar-model.h: * src/bookmarks/ephy-bookmarksbar.c: * src/bookmarks/ephy-bookmarksbar.h: * src/bookmarks/ephy-favorites-menu.c: * src/bookmarks/ephy-favorites-menu.h: * src/bookmarks/ephy-new-bookmark.c: (ephy_new_bookmark_add), (build_editing_table), (ephy_new_bookmark_construct), (ephy_new_bookmark_set_property), (ephy_new_bookmark_get_property): * src/bookmarks/ephy-nodes-cover.c: (ephy_nodes_count_covered), (ephy_nodes_remove_covered), (ephy_nodes_remove_not_covered), (ephy_nodes_get_covered), (ephy_nodes_covered), (ephy_nodes_get_covering): * src/bookmarks/ephy-nodes-cover.h: * src/bookmarks/ephy-open-tabs-action.c: (activate_cb), (node_added_cb), (node_removed_cb), (ephy_open_tabs_group_new), (ephy_open_tabs_action_name): * src/bookmarks/ephy-open-tabs-action.h: * src/bookmarks/ephy-related-action.c: (node_changed), (node_destroyed), (open_link), (iface_init), (ephy_related_action_get_type), (ephy_related_action_new): * src/bookmarks/ephy-related-action.h: * src/bookmarks/ephy-topic-action-group.c: (node_changed_cb), (node_added_cb), (node_removed_cb), (ephy_topic_group_new): * src/bookmarks/ephy-topic-action-group.h: * src/bookmarks/ephy-topic-action.c: (ephy_topic_action_get_type), (create_tool_item), (ephy_topic_action_sync_label), (get_popup), (erase_popup), (child_added_cb), (child_changed_cb), (child_removed_cb), (menu_destroy_cb), (menu_init_cb), (button_deactivate_cb), (button_toggled_cb), (button_release_cb), (button_press_cb), (connect_proxy), (ephy_topic_action_updated), (ephy_topic_action_get_topic), (ephy_topic_action_set_topic), (ephy_topic_action_set_property), (ephy_topic_action_get_property), (ephy_topic_action_class_init), (ephy_topic_action_init), (ephy_topic_action_name), (ephy_topic_action_new): * src/bookmarks/ephy-topic-action.h: * src/bookmarks/ephy-topic-factory-action.c: (ephy_topic_factory_action_get_type), (sort_topics), (activate_item_cb), (build_menu), (remove_placeholder_cb), (activate_placeholder_cb), (clicked_placeholder_cb), (realize_placeholder_cb), (create_tool_item), (connect_proxy), (ephy_topic_factory_action_class_init), (ephy_topic_factory_action_new): * src/bookmarks/ephy-topic-factory-action.h: * src/ephy-link-action.c: (ephy_link_action_group_get_type), (ephy_link_action_group_new): * src/ephy-link-action.h: * src/ephy-lockdown.c: (find_name), (find_action_group), (update_window): * src/ephy-notebook.c: (move_tab_to_another_notebook), (ephy_notebook_switch_page_cb), (ephy_notebook_init), (tab_label_style_set_cb), (build_tab_label), (ephy_notebook_add_tab): * src/ephy-shell.c: (ephy_shell_get_toolbars_model): * src/ephy-toolbar-editor.c: (ephy_toolbar_editor_constructor), (ephy_toolbar_editor_finalize), (ephy_toolbar_editor_set_property), (ephy_toolbar_editor_class_init): * src/ephy-toolbar.c: (ephy_toolbar_realize), (ephy_toolbar_unrealize), (ephy_toolbar_finalize): * src/ephy-toolbars-model.c: (update_flags), (ephy_toolbars_model_load): * src/ephy-window.c: (ephy_window_get_type), (get_chromes_visibility), (sync_chromes_visibility), (ephy_window_key_press_event), (tool_item_enter_cb), (tool_item_leave_cb), (tool_item_drag_begin_cb), (connect_tool_item), (disconnect_tool_item), (disconnect_proxy_cb), (connect_proxy_cb), (update_chromes_actions), (show_embed_popup), (tab_added_cb), (tab_removed_cb), (ephy_window_set_chrome), (ephy_window_dispose), (ephy_window_class_init), (ephy_window_init), (ephy_window_finalize), (ephy_window_remove_tab), (ephy_window_set_zoom), (sync_prefs_with_chrome), (ephy_window_view_toolbar_cb): * src/ephy-window.h: Revision history: h18, released 2005/09/23, for Epiphany 1.8.0 * Just an update for 1.8.0. h17, released 2005/08/30, for Epiphany 1.7.6 or CVS HEAD * Mostly just an update for 1.7.6. * Topic menus on the toolbar now open without releasing the mouse button. * Topic menus on the toolbar are now also hierarchical (see if you like it. h16, released 2005/08/25, for Epiphany 1.7.5 or CVS HEAD * Just an update for 1.7.5. Sorry, I've been busy. :) h15, released 2005/07/19, for Epiphany 1.7.2 or CVS HEAD * Code cleanup h14, released 2005/07/9, for Epiphany 1.7.1 or CVS HEAD * Improved helpful tip when adding a bookmark * Improved toolbar context menu * Toolbar visibility state is now saved * Separated bookmark/topic action groups into separate files * Topics in the overflow menu now behave as submenus * Now importing old bookmarksbar, and saving to new filename * Incremented toolbar file format version number to 1.1 * Fixed the 'sticky' statusbar help * Fixed a crashing bug (dnd then open a topic on the toolbar) h13, released 2005/05/12, for CVS HEAD * Added middle-mouse drag-drop for the editable toolbar. * Fixed some warnings at compile and run time. * Added brief help for the user when adding a new bookmark. * Cleaned up the editable toolbar code a little. h12, released 2005/05/10, for CVS HEAD * Added new editing facilities for the editable toolbar. h11, released 2005/04/29, for CVS HEAD * Fixed bug in statusbar information for toolbar items. * Added an all-new 'Related' toolbar widget which changes to show the most related topic whenever a bookmark is activated. h10, released 2005/04/15, for Epiphany 1.6.2 or CVS HEAD * Added statusbar information for all toolbar items. * Empty toolbars are now only deleted when exiting edit mode. * Fixed regression of middle-click for bookmarks on toolbar. * Fixed regression of ellipsized bookmark names in menus. h9, released 2005/04/12, for Epiphany 1.6.1 * Updated patch for 1.6.1. Long time no see. * Now using EphyLink objects everywhere. h7, released 2004/10/21, for Epiphany 1.4.4 * Updated patch for 1.4.4. * Fixed bugs causing crashes when bookmarks were added (thanks Reinout). * Added "Open in Tabs" back into bookmark menus where suitable. h6, released 2004/09/20, for Epiphany 1.4.0 * Updated patch for 1.4.0. * Removed the bookmarks bar. * Generate shared XML string for bookmarks menu. * Slightly improve performance of node-cover code. * Delay adding bookmarks menu until it is first used. * Fixed bug(?) in ephy-node. h4, released 2004/08/08, for Epiphany 1.3.4 * Updated patch due to changes to topics selector. * Removed 'Most Visited' from the min-cover calculations. * Fixed Epiphany 1.3.4 bug where topics in selector aren't sorted. * Updated patch due to other changes in Epiphany 1.3.4 source. h3, released 2004/07/12, for Epiphany 1.3.2 * Simple update for Epiphany 1.3.2 h3, released 2004/05/24, for Epiphany 1.2.5 * Moved duplicated functions into a seperate file. * Improved topic selector. * Bookmarks toolbar topic menus now have subdivisions. * Topic names in menu now change if modified in the bookmarks editor. h2, released 2004/05/23, for Epiphany 1.2.5 * Significantly cleaned up the code. * 'Most Visited' no longer appears as a submenu. * Subtopics are selected much more intelligently, giving a better approximation to a true minimum cover. * Topic selector now shows suggestions with arrows, not bold font. h1, released 2004/05/19, for Epiphany 1.2.5 * Initial release.
Diffstat (limited to 'src/bookmarks')
-rw-r--r--src/bookmarks/Makefile.am24
-rw-r--r--src/bookmarks/ephy-bookmark-action-group.c178
-rw-r--r--src/bookmarks/ephy-bookmark-action-group.h33
-rw-r--r--src/bookmarks/ephy-bookmark-action.c444
-rw-r--r--src/bookmarks/ephy-bookmark-action.h19
-rw-r--r--src/bookmarks/ephy-bookmark-factory-action.c319
-rw-r--r--src/bookmarks/ephy-bookmark-factory-action.h54
-rw-r--r--src/bookmarks/ephy-bookmark-properties.c77
-rw-r--r--src/bookmarks/ephy-bookmarks-editor.c239
-rw-r--r--src/bookmarks/ephy-bookmarks-menu.c902
-rw-r--r--src/bookmarks/ephy-bookmarks-menu.h37
-rw-r--r--src/bookmarks/ephy-bookmarks-ui.c552
-rw-r--r--src/bookmarks/ephy-bookmarks-ui.h33
-rw-r--r--src/bookmarks/ephy-bookmarks.c293
-rw-r--r--src/bookmarks/ephy-bookmarks.h8
-rwxr-xr-xsrc/bookmarks/ephy-bookmarksbar-model.c588
-rwxr-xr-xsrc/bookmarks/ephy-bookmarksbar-model.h76
-rw-r--r--src/bookmarks/ephy-bookmarksbar.c380
-rw-r--r--src/bookmarks/ephy-bookmarksbar.h64
-rw-r--r--src/bookmarks/ephy-favorites-menu.c319
-rw-r--r--src/bookmarks/ephy-favorites-menu.h59
-rw-r--r--src/bookmarks/ephy-new-bookmark.c33
-rw-r--r--src/bookmarks/ephy-nodes-cover.c196
-rw-r--r--src/bookmarks/ephy-nodes-cover.h41
-rw-r--r--src/bookmarks/ephy-open-tabs-action.c119
-rw-r--r--src/bookmarks/ephy-open-tabs-action.h30
-rw-r--r--src/bookmarks/ephy-related-action.c178
-rw-r--r--src/bookmarks/ephy-related-action.h59
-rw-r--r--src/bookmarks/ephy-topic-action-group.c123
-rw-r--r--src/bookmarks/ephy-topic-action-group.h34
-rw-r--r--src/bookmarks/ephy-topic-action.c996
-rw-r--r--src/bookmarks/ephy-topic-action.h38
-rw-r--r--src/bookmarks/ephy-topic-factory-action.c318
-rw-r--r--src/bookmarks/ephy-topic-factory-action.h55
34 files changed, 3099 insertions, 3819 deletions
diff --git a/src/bookmarks/Makefile.am b/src/bookmarks/Makefile.am
index 128ea9232..29c85d9c5 100644
--- a/src/bookmarks/Makefile.am
+++ b/src/bookmarks/Makefile.am
@@ -13,14 +13,19 @@ NOINST_H_FILES = \
ephy-bookmarks-editor.h \
ephy-bookmarks-export.h \
ephy-bookmarks-import.h \
+ ephy-bookmarks-ui.h \
ephy-bookmarks-menu.h \
- ephy-bookmarksbar-model.h \
- ephy-bookmarksbar.h \
ephy-bookmark-properties.h \
- ephy-favorites-menu.h \
ephy-new-bookmark.h \
ephy-topic-action.h \
- ephy-topics-selector.h
+ ephy-related-action.h \
+ ephy-open-tabs-action.h \
+ ephy-topic-factory-action.h \
+ ephy-bookmark-factory-action.h \
+ ephy-topic-action-group.h \
+ ephy-bookmark-action-group.h \
+ ephy-topics-selector.h \
+ ephy-nodes-cover.h
libephybookmarks_la_SOURCES = \
$(BUILT_SOURCES) \
@@ -29,14 +34,19 @@ libephybookmarks_la_SOURCES = \
ephy-bookmarks-editor.c \
ephy-bookmarks-export.c \
ephy-bookmarks-import.c \
+ ephy-bookmarks-ui.c \
ephy-bookmarks-menu.c \
- ephy-bookmarksbar-model.c \
- ephy-bookmarksbar.c \
ephy-bookmark-properties.c \
- ephy-favorites-menu.c \
ephy-new-bookmark.c \
ephy-topic-action.c \
+ ephy-related-action.c \
+ ephy-open-tabs-action.c \
+ ephy-topic-factory-action.c \
+ ephy-bookmark-factory-action.c \
+ ephy-topic-action-group.c \
+ ephy-bookmark-action-group.c \
ephy-topics-selector.c \
+ ephy-nodes-cover.c \
$(NOINST_H_FILES) \
$(INST_H_FILES)
diff --git a/src/bookmarks/ephy-bookmark-action-group.c b/src/bookmarks/ephy-bookmark-action-group.c
new file mode 100644
index 000000000..e9b2c970c
--- /dev/null
+++ b/src/bookmarks/ephy-bookmark-action-group.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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 "config.h"
+
+#include "ephy-shell.h"
+#include "ephy-bookmark-action-group.h"
+#include "ephy-bookmark-action.h"
+#include "ephy-bookmarks.h"
+#include "ephy-link.h"
+#include "ephy-node.h"
+#include "ephy-node-common.h"
+#include "ephy-debug.h"
+
+#include <gtk/gtkaction.h>
+#include <gtk/gtkactiongroup.h>
+#include <string.h>
+
+static void
+smart_added_cb (EphyNode *parent,
+ EphyNode *child,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name;
+
+ name = ephy_bookmark_action_name (child);
+ g_return_if_fail (name);
+ action = gtk_action_group_get_action (actions, name);
+
+ if (action)
+ {
+ ephy_bookmark_action_updated
+ (EPHY_BOOKMARK_ACTION (action));
+ }
+
+ g_free (name);
+}
+
+
+static void
+smart_removed_cb (EphyNode *parent,
+ EphyNode *child,
+ guint index,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name;
+
+ name = ephy_bookmark_action_name (child);
+ g_return_if_fail (name);
+ action = gtk_action_group_get_action (actions, name);
+
+ if (action)
+ {
+ ephy_bookmark_action_updated
+ (EPHY_BOOKMARK_ACTION (action));
+ }
+
+ g_free (name);
+}
+
+static void
+node_changed_cb (EphyNode *parent,
+ EphyNode *child,
+ guint property_id,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name;
+
+ name = ephy_bookmark_action_name (child);
+ g_return_if_fail (name);
+ action = gtk_action_group_get_action (actions, name);
+
+ if (action)
+ {
+ ephy_bookmark_action_updated
+ (EPHY_BOOKMARK_ACTION (action));
+ }
+
+ g_free (name);
+}
+
+static void
+node_added_cb (EphyNode *parent,
+ EphyNode *child,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name, *accel;
+
+ name = ephy_bookmark_action_name (child);
+ action = ephy_bookmark_action_new (child, name);
+ accel = g_strjoin ("/", "<Actions>",
+ gtk_action_group_get_name (actions),
+ name, NULL);
+ gtk_action_set_accel_path (action, accel);
+ gtk_action_group_add_action (actions, action);
+ g_object_unref (action);
+ g_free (accel);
+
+ ephy_bookmark_action_updated (EPHY_BOOKMARK_ACTION (action));
+
+ g_signal_connect_swapped (G_OBJECT(action), "open-link",
+ G_CALLBACK (ephy_link_open), actions);
+}
+
+static void
+node_removed_cb (EphyNode *parent,
+ EphyNode *child,
+ guint index,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name;
+
+ name = ephy_bookmark_action_name (child);
+ g_return_if_fail (name);
+ action = gtk_action_group_get_action (actions, name);
+
+ if (action)
+ {
+ gtk_action_group_remove_action (actions, action);
+ }
+
+ g_free (name);
+}
+
+GtkActionGroup *
+ephy_bookmark_group_new (EphyNode *node)
+{
+ EphyBookmarks *bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *smart = ephy_bookmarks_get_smart_bookmarks (bookmarks);
+
+ GPtrArray *children = ephy_node_get_children (node);
+ GObject *actions = (GObject *) ephy_link_action_group_new ("BA");
+ guint i;
+
+ for (i = 0; i < children->len; i++)
+ {
+ node_added_cb (node, g_ptr_array_index (children, i), (GtkActionGroup *) actions);
+ }
+
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ actions);
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ actions);
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)node_changed_cb,
+ actions);
+
+ ephy_node_signal_connect_object (smart, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)smart_added_cb,
+ actions);
+ ephy_node_signal_connect_object (smart, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)smart_removed_cb,
+ actions);
+
+ return GTK_ACTION_GROUP (actions);
+}
diff --git a/src/bookmarks/ephy-bookmark-action-group.h b/src/bookmarks/ephy-bookmark-action-group.h
new file mode 100644
index 000000000..fc401a4a4
--- /dev/null
+++ b/src/bookmarks/ephy-bookmark-action-group.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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.
+ */
+
+#ifndef EPHY_BOOKMARK_ACTION_GROUP_H
+#define EPHY_BOOKMARK_ACTION_GROUP_H
+
+#include "ephy-link-action.h"
+#include "ephy-node.h"
+
+#include <gtk/gtkactiongroup.h>
+
+G_BEGIN_DECLS
+
+GtkActionGroup * ephy_bookmark_group_new (EphyNode *node);
+
+G_END_DECLS
+
+#endif
diff --git a/src/bookmarks/ephy-bookmark-action.c b/src/bookmarks/ephy-bookmark-action.c
index a4154b298..db93b5824 100644
--- a/src/bookmarks/ephy-bookmark-action.c
+++ b/src/bookmarks/ephy-bookmark-action.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2003, 2004 Marco Pesenti Gritti
* Copyright (C) 2003, 2004 Christian Persch
+ * Copyright (C) 2005 Peter Harvey
*
* 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
@@ -21,12 +22,11 @@
#include "config.h"
+#include "egg-editable-toolbar.h"
#include "ephy-bookmark-action.h"
-#include "ephy-bookmarksbar-model.h"
-#include "ephy-bookmarksbar.h"
#include "ephy-bookmarks.h"
+#include "ephy-link-action.h"
#include "ephy-link.h"
-#include "ephy-dnd.h"
#include "ephy-favicon-cache.h"
#include "ephy-shell.h"
#include "ephy-gui.h"
@@ -37,16 +37,13 @@
#include <gtk/gtkhbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkbutton.h>
-#include <gtk/gtkentry.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkimagemenuitem.h>
#include <gtk/gtkseparatormenuitem.h>
-#include <gtk/gtkmenushell.h>
-#include <gtk/gtkmenu.h>
+#include <gtk/gtkentry.h>
#include <gtk/gtktoolitem.h>
-#include <gtk/gtktoolbar.h>
#include <gtk/gtkmain.h>
#include <libgnomevfs/gnome-vfs-uri.h>
@@ -62,20 +59,11 @@ static void ephy_bookmark_action_class_init (EphyBookmarkActionClass *class);
#define EPHY_BOOKMARK_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARK_ACTION, EphyBookmarkActionPrivate))
-static GtkTargetEntry drag_targets[] =
-{
- { EPHY_DND_URL_TYPE, 0, 0 }
-};
-static int n_drag_targets = G_N_ELEMENTS (drag_targets);
-
struct _EphyBookmarkActionPrivate
{
EphyNode *node;
gboolean smart_url;
guint cache_handler;
- guint motion_handler;
- gint drag_x;
- gint drag_y;
};
enum
@@ -138,6 +126,7 @@ create_tool_item (GtkAction *action)
gtk_widget_show (button);
gtk_container_add (GTK_CONTAINER (hbox), button);
g_object_set_data (G_OBJECT (item), "button", button);
+ g_object_set_data (G_OBJECT (item), "egg-drag-source", button);
entry = gtk_entry_new ();
gtk_entry_set_width_chars (GTK_ENTRY (entry), ENTRY_WIDTH_CHARS);
@@ -247,7 +236,7 @@ ephy_bookmark_action_sync_icon (GtkAction *action, GParamSpec *pspec, GtkWidget
if (pixbuf == NULL)
{
pixbuf = gtk_widget_render_icon (proxy, GTK_STOCK_NEW,
- GTK_ICON_SIZE_MENU, NULL);
+ GTK_ICON_SIZE_MENU, NULL);
}
gtk_image_set_from_pixbuf (icon, pixbuf);
@@ -379,142 +368,6 @@ activate_cb (GtkWidget *widget,
}
static void
-stop_drag_check (EphyBookmarkAction *action, GtkWidget *widget)
-{
- if (action->priv->motion_handler)
- {
- g_signal_handler_disconnect (widget, action->priv->motion_handler);
- action->priv->motion_handler = 0;
- }
-}
-
-static void
-drag_data_get_cb (GtkWidget *widget, GdkDragContext *context,
- GtkSelectionData *selection_data, guint info,
- guint32 time, EphyBookmarkAction *action)
-{
- const char *address, *title;
- char *data;
-
- g_return_if_fail (action->priv->node != NULL);
-
- address = ephy_node_get_property_string (action->priv->node,
- EPHY_NODE_BMK_PROP_LOCATION);
- g_return_if_fail (address != NULL);
-
- title = ephy_node_get_property_string (action->priv->node,
- EPHY_NODE_BMK_PROP_TITLE);
- g_return_if_fail (title != NULL);
-
- data = g_strdup_printf ("%s\n%s", address, title);
- gtk_selection_data_set (selection_data, selection_data->target, 8,
- (unsigned char *) data, strlen (data));
- g_free (data);
-}
-
-static int
-get_item_position (GtkWidget *widget, gboolean *last)
-{
- GtkWidget *item, *toolbar;
- int index;
-
- item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM);
- g_return_val_if_fail (item != NULL, -1);
-
- toolbar = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOLBAR);
- g_return_val_if_fail (toolbar != NULL, -1);
-
- index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar),
- GTK_TOOL_ITEM (item));
- if (last)
- {
- int n_items;
-
- n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar));
- *last = (index == n_items - 1);
- }
-
- return index;
-}
-
-static void
-remove_from_model (GtkWidget *widget)
-{
- EphyBookmarks *bookmarks;
- EggToolbarsModel *model;
- int pos;
-
- pos = get_item_position (widget, NULL);
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- model = EGG_TOOLBARS_MODEL (ephy_bookmarks_get_toolbars_model (bookmarks));
-
- egg_toolbars_model_remove_item (model, 0, pos);
-}
-
-static void
-move_in_model (GtkWidget *widget, int direction)
-{
- EphyBookmarks *bookmarks;
- EggToolbarsModel *model;
- int pos, new_pos;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- model = EGG_TOOLBARS_MODEL (ephy_bookmarks_get_toolbars_model (bookmarks));
-
- pos = get_item_position (widget, NULL);
- new_pos = MAX (0, pos + direction);
-
- egg_toolbars_model_move_item (model, 0, pos, 0, new_pos);
-}
-
-static void
-drag_data_delete_cb (GtkWidget *widget, GdkDragContext *context,
- EphyBookmarkAction *action)
-{
- remove_from_model (widget);
-}
-
-static gboolean
-drag_motion_cb (GtkWidget *widget, GdkEventMotion *event, EphyBookmarkAction *action)
-{
- if (gtk_drag_check_threshold (widget, action->priv->drag_x,
- action->priv->drag_y, event->x, event->y))
- {
- GtkTargetList *target_list;
-
- target_list = gtk_target_list_new (drag_targets, n_drag_targets);
-
- stop_drag_check (action, widget);
- gtk_drag_begin (widget, target_list, GDK_ACTION_ASK |
- GDK_ACTION_MOVE | GDK_ACTION_COPY, 1,
- (GdkEvent*)event);
-
- gtk_target_list_unref (target_list);
- }
-
- return TRUE;
-}
-
-static void
-remove_activate_cb (GtkWidget *menu, GtkWidget *proxy)
-{
- remove_from_model (proxy);
-}
-
-static void
-move_left_activate_cb (GtkWidget *menu, GtkWidget *proxy)
-{
- move_in_model (proxy, -1);
-}
-
-static void
-move_right_activate_cb (GtkWidget *menu, GtkWidget *proxy)
-{
- move_in_model (proxy, +1);
-}
-
-static void
properties_activate_cb (GtkWidget *menu,
EphyBookmarkAction *action)
{
@@ -535,8 +388,7 @@ show_context_menu (EphyBookmarkAction *action,
GdkEventButton *event,
GtkMenuPositionFunc func)
{
- GtkWidget *menu, *item, *image;
- gboolean last;
+ GtkWidget *menu, *item;
menu = gtk_menu_new ();
@@ -562,38 +414,8 @@ show_context_menu (EphyBookmarkAction *action,
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
g_signal_connect (item, "activate",
G_CALLBACK (properties_activate_cb), action);
-
- item = gtk_separator_menu_item_new ();
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- item = gtk_image_menu_item_new_with_mnemonic (_("_Remove from Toolbar"));
- gtk_widget_show (item);
- image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
- gtk_widget_show (image);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate",
- G_CALLBACK (remove_activate_cb), proxy);
-
- item = gtk_separator_menu_item_new ();
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- item = gtk_menu_item_new_with_mnemonic (_("Move _Left"));
- gtk_widget_set_sensitive (item, get_item_position (proxy, NULL) > 0);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate",
- G_CALLBACK (move_left_activate_cb), proxy);
-
- item = gtk_menu_item_new_with_mnemonic (_("Move Ri_ght"));
- get_item_position (proxy, &last);
- gtk_widget_set_sensitive (item, !last);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate",
- G_CALLBACK (move_right_activate_cb), proxy);
+
+ egg_editable_toolbar_add_popup_items (proxy, GTK_MENU (menu));
if (event != NULL)
{
@@ -611,14 +433,8 @@ show_context_menu (EphyBookmarkAction *action,
static gboolean
popup_menu_cb (GtkWidget *widget, EphyBookmarkAction *action)
{
- if (gtk_widget_get_ancestor (widget, EPHY_TYPE_BOOKMARKSBAR))
- {
- show_context_menu (action, widget, NULL,
- ephy_gui_menu_position_under_widget);
- return TRUE;
- }
-
- return FALSE;
+ show_context_menu (action, widget, NULL, ephy_gui_menu_position_under_widget);
+ return TRUE;
}
static gboolean
@@ -626,8 +442,7 @@ button_press_cb (GtkWidget *widget,
GdkEventButton *event,
EphyBookmarkAction *action)
{
- if (event->button == 3 &&
- gtk_widget_get_ancestor (widget, EPHY_TYPE_BOOKMARKSBAR))
+ if (event->button == 3)
{
show_context_menu (action, widget, event, NULL);
return TRUE;
@@ -636,35 +451,24 @@ button_press_cb (GtkWidget *widget,
{
gtk_button_pressed (GTK_BUTTON (widget));
}
- else if (event->button == 1 &&
- gtk_widget_get_ancestor (widget, EPHY_TYPE_BOOKMARKSBAR))
- {
- action->priv->drag_x = event->x;
- action->priv->drag_y = event->y;
- action->priv->motion_handler = g_signal_connect
- (widget, "motion_notify_event", G_CALLBACK (drag_motion_cb), action);
- }
return FALSE;
}
static gboolean
button_release_cb (GtkWidget *widget,
- GdkEventButton *event,
+ GdkEventButton *event,
EphyBookmarkAction *action)
{
if (event->button == 2)
{
gtk_button_released (GTK_BUTTON (widget));
}
- else if (event->button == 1)
- {
- stop_drag_check (action, widget);
- }
return FALSE;
}
+
static void
connect_proxy (GtkAction *action, GtkWidget *proxy)
{
@@ -676,11 +480,11 @@ connect_proxy (GtkAction *action, GtkWidget *proxy)
ephy_bookmark_action_sync_icon (action, NULL, proxy);
g_signal_connect_object (action, "notify::icon",
- G_CALLBACK (ephy_bookmark_action_sync_icon), proxy, 0);
+ G_CALLBACK (ephy_bookmark_action_sync_icon), proxy, 0);
ephy_bookmark_action_sync_smart_url (action, NULL, proxy);
g_signal_connect_object (action, "notify::smarturl",
- G_CALLBACK (ephy_bookmark_action_sync_smart_url), proxy, 0);
+ G_CALLBACK (ephy_bookmark_action_sync_smart_url), proxy, 0);
if (GTK_IS_TOOL_ITEM (proxy))
{
@@ -696,10 +500,6 @@ connect_proxy (GtkAction *action, GtkWidget *proxy)
G_CALLBACK (button_press_cb), action);
g_signal_connect (button, "button-release-event",
G_CALLBACK (button_release_cb), action);
- g_signal_connect (button, "drag_data_get",
- G_CALLBACK (drag_data_get_cb), action);
- g_signal_connect (button, "drag_data_delete",
- G_CALLBACK (drag_data_delete_cb), action);
entry = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "entry"));
g_signal_connect (entry, "activate", G_CALLBACK (activate_cb), action);
@@ -718,73 +518,73 @@ connect_proxy (GtkAction *action, GtkWidget *proxy)
}
}
-static void
-bookmark_changed_cb (EphyNode *node,
- guint property_id,
- EphyBookmarkAction *action)
+void
+ephy_bookmark_action_updated (EphyBookmarkAction *action)
{
- if (property_id == EPHY_NODE_BMK_PROP_TITLE)
- {
- GValue value = { 0, };
- const char *title;
+ GValue value = { 0, };
+ EphyBookmarks *bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *smart = ephy_bookmarks_get_smart_bookmarks (bookmarks);
+ EphyNode *node = action->priv->node;
+ const char *title;
+
+ g_return_if_fail (action != NULL);
+ g_return_if_fail (node != NULL);
+
+ g_object_freeze_notify (G_OBJECT (action));
- title = ephy_node_get_property_string
- (node, EPHY_NODE_BMK_PROP_TITLE);
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_static_string (&value, title);
- g_object_set_property (G_OBJECT (action), "label", &value);
- g_value_unset (&value);
- }
- else if (property_id == EPHY_NODE_BMK_PROP_ICON)
- {
- g_object_notify (G_OBJECT (action), "icon");
- }
+ // Set smart_url
+ action->priv->smart_url = ephy_node_has_child (smart, node);
+ g_object_notify (G_OBJECT (action), "smarturl");
+
+ // Set title
+ title = ephy_node_get_property_string (node, EPHY_NODE_BMK_PROP_TITLE);
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_static_string (&value, title);
+ g_object_set_property (G_OBJECT (action), "label", &value);
+ g_value_unset (&value);
+
+ // Notify all other properties
+ g_object_notify (G_OBJECT (action), "location");
+ g_object_notify (G_OBJECT (action), "tooltip");
+ g_object_notify (G_OBJECT (action), "icon");
+
+ g_object_thaw_notify (G_OBJECT (action));
}
-static void
-bookmark_destroy_cb (EphyNode *node, EphyBookmarkAction *action)
+EphyNode *
+ephy_bookmark_action_get_bookmark (EphyBookmarkAction *action)
{
- action->priv->node = NULL;
+ return action->priv->node;
}
-static void
+void
ephy_bookmark_action_set_bookmark (EphyBookmarkAction *action,
EphyNode *node)
-{
- EphyBookmarks *bookmarks;
- EphyNode *smart_bmks;
-
+{
g_return_if_fail (node != NULL);
-
+
action->priv->node = node;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- smart_bmks = ephy_bookmarks_get_smart_bookmarks (bookmarks);
- action->priv->smart_url = ephy_node_has_child (smart_bmks, node);
-
- bookmark_changed_cb (node, EPHY_NODE_BMK_PROP_TITLE, action);
-// bookmark_changed_cb (node, EPHY_NODE_BMK_PROP_ICON, action);
- ephy_node_signal_connect_object (node, EPHY_NODE_CHANGED,
- (EphyNodeCallback) bookmark_changed_cb,
- G_OBJECT (action));
- ephy_node_signal_connect_object (node, EPHY_NODE_DESTROY,
- (EphyNodeCallback) bookmark_destroy_cb,
- G_OBJECT (action));
+
+ g_object_freeze_notify (G_OBJECT (action));
+
+ g_object_notify (G_OBJECT (action), "bookmark");
+ ephy_bookmark_action_updated (action);
+
+ g_object_thaw_notify (G_OBJECT (action));
}
static void
ephy_bookmark_action_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
EphyBookmarkAction *action = EPHY_BOOKMARK_ACTION (object);
switch (prop_id)
{
case PROP_BOOKMARK:
- ephy_bookmark_action_set_bookmark
- (action, g_value_get_pointer (value));
+ ephy_bookmark_action_set_bookmark (action, g_value_get_pointer (value));
break;
case PROP_TOOLTIP:
case PROP_LOCATION:
@@ -797,9 +597,9 @@ ephy_bookmark_action_set_property (GObject *object,
static void
ephy_bookmark_action_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
EphyBookmarkAction *action = EPHY_BOOKMARK_ACTION (object);
@@ -830,8 +630,6 @@ ephy_bookmark_action_get_property (GObject *object,
static void
ephy_bookmark_action_finalize (GObject *object)
{
- /* EphyBookmarkAction *eba = EPHY_BOOKMARK_ACTION (object);*/
-
LOG ("Bookmark action %p finalized", object);
parent_class->finalize (object);
@@ -855,7 +653,7 @@ ephy_bookmark_action_class_init (EphyBookmarkActionClass *class)
object_class->get_property = ephy_bookmark_action_get_property;
g_object_class_install_property (object_class,
- PROP_BOOKMARK,
+ PROP_BOOKMARK,
g_param_spec_pointer ("bookmark",
"Bookmark",
"Bookmark",
@@ -864,89 +662,63 @@ ephy_bookmark_action_class_init (EphyBookmarkActionClass *class)
/* overwrite GtkActionClass::tooltip, so we can use the url as tooltip */
g_object_class_install_property (object_class,
- PROP_TOOLTIP,
- g_param_spec_string ("tooltip",
- "Tooltip",
- "Tooltip",
- NULL,
- G_PARAM_READABLE));
-
+ PROP_TOOLTIP,
+ g_param_spec_string ("tooltip",
+ "Tooltip",
+ "Tooltip",
+ NULL,
+ G_PARAM_READABLE));
+
g_object_class_install_property (object_class,
- PROP_LOCATION,
- g_param_spec_string ("location",
- "Location",
- "Location",
- NULL,
- G_PARAM_READABLE));
+ PROP_LOCATION,
+ g_param_spec_string ("location",
+ "Location",
+ "Location",
+ NULL,
+ G_PARAM_READABLE));
g_object_class_install_property (object_class,
- PROP_SMART_URL,
- g_param_spec_boolean ("smarturl",
- "Smart url",
- "Smart url",
- FALSE,
- G_PARAM_READABLE));
+ PROP_SMART_URL,
+ g_param_spec_boolean ("smarturl",
+ "Smart url",
+ "Smart url",
+ FALSE,
+ G_PARAM_READABLE));
g_object_class_install_property (object_class,
- PROP_ICON,
- g_param_spec_string ("icon",
- "Icon",
- "Icon",
- NULL,
- G_PARAM_READABLE));
+ PROP_ICON,
+ g_param_spec_string ("icon",
+ "Icon",
+ "Icon",
+ NULL,
+ G_PARAM_READABLE));
g_type_class_add_private (object_class, sizeof(EphyBookmarkActionPrivate));
}
static void
-smart_child_added_cb (EphyNode *smart_bmks,
- EphyNode *child,
- EphyBookmarkAction *action)
-{
- if (ephy_node_get_id (action->priv->node) == ephy_node_get_id (child))
- {
- action->priv->smart_url = TRUE;
- g_object_notify (G_OBJECT (action), "smarturl");
- }
-}
-
-static void
-smart_child_removed_cb (EphyNode *smart_bmks,
- EphyNode *child,
- guint old_index,
- EphyBookmarkAction *action)
-{
- if (ephy_node_get_id (action->priv->node) == ephy_node_get_id (child))
- {
- action->priv->smart_url = FALSE;
- g_object_notify (G_OBJECT (action), "smarturl");
- }
-}
-
-static void
ephy_bookmark_action_init (EphyBookmarkAction *action)
{
- EphyBookmarks *bookmarks;
- EphyNode *node;
-
action->priv = EPHY_BOOKMARK_ACTION_GET_PRIVATE (action);
+ action->priv->cache_handler = 0;
+}
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- node = ephy_bookmarks_get_smart_bookmarks (bookmarks);
- ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED,
- (EphyNodeCallback) smart_child_added_cb,
- G_OBJECT (action));
- ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED,
- (EphyNodeCallback) smart_child_removed_cb,
- G_OBJECT (action));
+char *
+ephy_bookmark_action_name (EphyNode *node)
+{
+ return g_strdup_printf("Bmk%u", ephy_node_get_id (node));
}
GtkAction *
-ephy_bookmark_action_new (const char *name,
- EphyNode *node)
+ephy_bookmark_action_new (EphyNode *node, char *name)
{
- g_return_val_if_fail (node != NULL, NULL);
+ GtkAction *action;
+
+ if(!name) name = ephy_bookmark_action_name (node);
+ g_return_val_if_fail (name, NULL);
+
+ action = GTK_ACTION (g_object_new (EPHY_TYPE_BOOKMARK_ACTION,
+ "name", name,
+ "bookmark", node,
+ NULL));
- return g_object_new (EPHY_TYPE_BOOKMARK_ACTION,
- "name", name,
- "bookmark", node,
- NULL);
+ return action;
}
diff --git a/src/bookmarks/ephy-bookmark-action.h b/src/bookmarks/ephy-bookmark-action.h
index 01d2c65d3..fbda7f371 100644
--- a/src/bookmarks/ephy-bookmark-action.h
+++ b/src/bookmarks/ephy-bookmark-action.h
@@ -25,6 +25,8 @@
#include "ephy-link-action.h"
#include "ephy-node.h"
+#include <gtk/gtkactiongroup.h>
+
G_BEGIN_DECLS
#define EPHY_TYPE_BOOKMARK_ACTION (ephy_bookmark_action_get_type ())
@@ -51,11 +53,20 @@ struct _EphyBookmarkActionClass
EphyLinkActionClass parent_class;
};
-GType ephy_bookmark_action_get_type (void);
-GtkAction *ephy_bookmark_action_new (const char *name,
- EphyNode *node);
+GType ephy_bookmark_action_get_type (void);
+
+char * ephy_bookmark_action_name (EphyNode *node);
+
+GtkAction * ephy_bookmark_action_new (EphyNode *node, char *name);
+
+
+void ephy_bookmark_action_set_bookmark (EphyBookmarkAction *action, EphyNode *node);
+
+EphyNode * ephy_bookmark_action_get_bookmark (EphyBookmarkAction *action);
+
+void ephy_bookmark_action_updated (EphyBookmarkAction *action);
G_END_DECLS
-#endif /* EPHY_BOOKMARK_ACTION_H */
+#endif
diff --git a/src/bookmarks/ephy-bookmark-factory-action.c b/src/bookmarks/ephy-bookmark-factory-action.c
new file mode 100644
index 000000000..89df8d05b
--- /dev/null
+++ b/src/bookmarks/ephy-bookmark-factory-action.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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 "config.h"
+
+#include <gtk/gtktoolitem.h>
+#include <glib/gi18n.h>
+
+#include "ephy-bookmark-factory-action.h"
+#include "ephy-bookmark-action.h"
+#include "ephy-node-common.h"
+#include "ephy-shell.h"
+#include "ephy-stock-icons.h"
+#include "egg-editable-toolbar.h"
+
+static void ephy_bookmark_factory_action_class_init (EphyBookmarkFactoryActionClass *class);
+
+#define EPHY_BOOKMARK_FACTORY_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARK_FACTORY_ACTION, EphyBookmarkActionPrivate))
+#define EGG_TOOLBARS_MODEL_DATA "ephy-bookmark-factory-menu"
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_bookmark_factory_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EphyBookmarkFactoryActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ephy_bookmark_factory_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EphyBookmarkFactoryAction),
+ 0, /* n_preallocs */
+ NULL
+ };
+
+ type = g_type_register_static (GTK_TYPE_ACTION,
+ "EphyBookmarkFactoryAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static void
+activate_item_cb (GtkWidget *menuitem, GtkWidget *placeholder)
+{
+ GtkWidget *toolbar, *etoolbar, *item;
+ EggToolbarsModel *model;
+ GList *children;
+ gint index, pos;
+ char *id;
+
+ item = gtk_widget_get_ancestor (placeholder, GTK_TYPE_TOOL_ITEM);
+ g_return_if_fail (item);
+ toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR);
+ g_return_if_fail (toolbar);
+ etoolbar = gtk_widget_get_ancestor (toolbar, EGG_TYPE_EDITABLE_TOOLBAR);
+ g_return_if_fail (etoolbar);
+ model = egg_editable_toolbar_get_model (EGG_EDITABLE_TOOLBAR (etoolbar));
+ g_return_if_fail (model);
+
+ children = gtk_container_get_children (GTK_CONTAINER (etoolbar));
+ pos = g_list_index (children, toolbar->parent);
+ index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item));
+ g_list_free (children);
+
+ id = g_object_get_data (G_OBJECT (menuitem), "ephy-action");
+ egg_toolbars_model_add_item (model, pos, index, id);
+}
+
+static GtkWidget *
+build_menu_for_topic (GtkWidget *placeholder, EggToolbarsModel *model, EphyNode *topic)
+{
+ GtkWidget *menu, *item;
+ EphyNode *node;
+ GPtrArray *children, *bookmarks;
+ const char *name, *action;
+ gint i;
+
+ children = ephy_node_get_children (topic);
+ bookmarks = g_ptr_array_sized_new (children->len);
+ for (i = 0; i < children->len; i++)
+ g_ptr_array_add (bookmarks, g_ptr_array_index (children, i));
+ g_ptr_array_sort (bookmarks, (GCompareFunc)ephy_bookmarks_compare_bookmark_pointers);
+
+ menu = NULL;
+
+ for (i = 0; i < bookmarks->len; i++)
+ {
+ node = g_ptr_array_index (bookmarks, i);
+
+ action = ephy_bookmark_action_name (node);
+ if (egg_toolbars_model_get_n_avail (model, action) < 0)
+ continue;
+
+ name = ephy_node_get_property_string (node, EPHY_NODE_BMK_PROP_TITLE);
+ item = gtk_menu_item_new_with_label (name);
+
+ g_object_set_data_full (G_OBJECT (item), "ephy-action", (gpointer) action, g_free);
+ g_signal_connect (item, "activate", G_CALLBACK (activate_item_cb), placeholder);
+ gtk_widget_show (item);
+
+ if (menu == NULL) menu = gtk_menu_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ g_ptr_array_free (bookmarks, TRUE);
+
+ return menu;
+}
+
+static GtkWidget *
+build_menu (GtkWidget *placeholder, EggToolbarsModel *model)
+{
+ GtkWidget *menu, *submenu, *item;
+
+ EphyBookmarks *eb;
+ EphyNode *node;
+ GPtrArray *children, *topics;
+
+ const char *name;
+ gint i, priority = -1, ptmp;
+
+ /* Get a sorted list of topics. */
+ eb = ephy_shell_get_bookmarks (ephy_shell);
+ node = ephy_bookmarks_get_keywords (eb);
+ children = ephy_node_get_children (node);
+ topics = g_ptr_array_sized_new (children->len);
+ for (i = 0; i < children->len; i++)
+ g_ptr_array_add (topics, g_ptr_array_index (children, i));
+ g_ptr_array_sort (topics, (GCompareFunc)ephy_bookmarks_compare_topic_pointers);
+
+ menu = gtk_menu_new ();
+ for (i = 0; i < topics->len; i++)
+ {
+ node = g_ptr_array_index (topics, i);
+
+ ptmp = ephy_node_get_property_int (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (ptmp == EPHY_NODE_ALL_PRIORITY)
+ continue;
+
+ submenu = build_menu_for_topic (placeholder, model, node);
+ if (submenu == NULL)
+ continue;
+
+ if (ptmp != priority && priority >= 0)
+ {
+ item = gtk_separator_menu_item_new ();
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ priority = ptmp;
+
+ name = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME);
+ item = gtk_menu_item_new_with_label (name);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+
+ gtk_widget_show (item);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ g_ptr_array_free (topics, TRUE);
+
+ return menu;
+}
+
+static void
+remove_placeholder_cb (GtkMenuShell *menushell,
+ GtkWidget *placeholder)
+{
+ GtkWidget *toolbar, *etoolbar, *item;
+ EggToolbarsModel *model;
+ GList *children;
+ gint index, pos;
+
+ item = gtk_widget_get_ancestor (placeholder, GTK_TYPE_TOOL_ITEM);
+ g_return_if_fail (item);
+ toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR);
+ g_return_if_fail (toolbar);
+ etoolbar = gtk_widget_get_ancestor (toolbar, EGG_TYPE_EDITABLE_TOOLBAR);
+ g_return_if_fail (etoolbar);
+ model = egg_editable_toolbar_get_model (EGG_EDITABLE_TOOLBAR (etoolbar));
+ g_return_if_fail (model);
+
+ g_object_set_data (G_OBJECT (model), EGG_TOOLBARS_MODEL_DATA, NULL);
+
+ children = gtk_container_get_children (GTK_CONTAINER (etoolbar));
+ pos = g_list_index (children, toolbar->parent);
+ index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item));
+ g_list_free (children);
+
+ egg_toolbars_model_remove_item (model, pos, index);
+}
+
+static gboolean
+activate_placeholder_cb (GtkWidget *placeholder)
+{
+ GtkWidget *toolbar, *etoolbar, *item, *menu;
+ EggToolbarsModel *model;
+ gint index;
+
+ /* Get our position on a toolbar. */
+ item = gtk_widget_get_ancestor (placeholder, GTK_TYPE_TOOL_ITEM);
+ g_return_val_if_fail (item, FALSE);
+ toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR);
+ g_return_val_if_fail (toolbar, FALSE);
+ etoolbar = gtk_widget_get_ancestor (toolbar, EGG_TYPE_EDITABLE_TOOLBAR);
+ g_return_val_if_fail (etoolbar, FALSE);
+ model = egg_editable_toolbar_get_model (EGG_EDITABLE_TOOLBAR (etoolbar));
+ g_return_val_if_fail (model, FALSE);
+
+ /* If we are not yet on the toolbar, abort. */
+ index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item));
+ if (index < 0 || index >= gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)))
+ return FALSE;
+
+ /* If there is already a popup menu, abort. */
+ menu = g_object_get_data (G_OBJECT (model), EGG_TOOLBARS_MODEL_DATA);
+ if (menu != NULL) return FALSE;
+
+ /* Create the menu and store it's pointer to ensure noone else creates a menu. */
+ menu = build_menu (placeholder, model);
+ g_object_set_data (G_OBJECT (model), EGG_TOOLBARS_MODEL_DATA, menu);
+
+ g_signal_connect (menu, "selection-done",
+ G_CALLBACK (remove_placeholder_cb), placeholder);
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0,
+ gtk_get_current_event_time ());
+
+ return FALSE;
+}
+
+static void
+clicked_placeholder_cb (GtkWidget *placeholder, GdkEventButton *event, gpointer user)
+{
+ activate_placeholder_cb (placeholder);
+}
+
+static void
+realize_placeholder_cb (GtkWidget *placeholder, gpointer user)
+{
+ g_idle_add ((GSourceFunc) activate_placeholder_cb, placeholder);
+}
+
+static GtkWidget *
+create_tool_item (GtkAction *action)
+{
+ GtkWidget *item = GTK_WIDGET (gtk_tool_item_new ());
+ GtkWidget *widget = gtk_button_new_with_label (" ? ");
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+
+ gtk_container_add (GTK_CONTAINER (item), widget);
+ gtk_widget_show (widget);
+
+ return item;
+}
+
+static void
+connect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+ GtkWidget *widget;
+
+ (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+
+ g_return_if_fail (GTK_IS_TOOL_ITEM (proxy));
+
+ widget = gtk_bin_get_child (GTK_BIN (proxy));
+
+ g_signal_connect (widget, "realize",
+ G_CALLBACK (realize_placeholder_cb),
+ action);
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (clicked_placeholder_cb),
+ action);
+}
+
+static void
+ephy_bookmark_factory_action_class_init (EphyBookmarkFactoryActionClass *class)
+{
+ GtkActionClass *action_class = GTK_ACTION_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;
+ action_class->connect_proxy = connect_proxy;
+ action_class->create_tool_item = create_tool_item;
+}
+
+GtkAction *
+ephy_bookmark_factory_action_new (const char *name)
+{
+ return GTK_ACTION (g_object_new (EPHY_TYPE_BOOKMARK_FACTORY_ACTION,
+ "name", name,
+ "label", _("Quick Bookmark"),
+ "stock-id", GTK_STOCK_ADD,
+ NULL));
+}
diff --git a/src/bookmarks/ephy-bookmark-factory-action.h b/src/bookmarks/ephy-bookmark-factory-action.h
new file mode 100644
index 000000000..472828726
--- /dev/null
+++ b/src/bookmarks/ephy-bookmark-factory-action.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004 Peter Harvey
+ *
+ * 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.
+ *
+ */
+
+#ifndef EPHY_BOOKMARK_FACTORY_ACTION_H
+#define EPHY_BOOKMARK_FACTORY_ACTION_H
+
+#include "ephy-node.h"
+#include "ephy-window.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkaction.h>
+#include <gtk/gtkactiongroup.h>
+
+#define EPHY_TYPE_BOOKMARK_FACTORY_ACTION (ephy_bookmark_factory_action_get_type ())
+#define EPHY_BOOKMARK_FACTORY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_BOOKMARK_FACTORY_ACTION, EphyBookmarkFactoryAction))
+#define EPHY_BOOKMARK_FACTORY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_BOOKMARK_FACTORY_ACTION, EphyBookmarkFactoryActionClass))
+#define EPHY_IS_BOOKMARK_FACTORY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_BOOKMARK_FACTORY_ACTION))
+#define EPHY_IS_BOOKMARK_FACTORY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_BOOKMARK_FACTORY_ACTION))
+#define EPHY_BOOKMARK_FACTORY_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_BOOKMARK_FACTORY_ACTION, EphyBookmarkFactoryActionClass))
+
+typedef struct _EphyBookmarkFactoryAction EphyBookmarkFactoryAction;
+typedef struct _EphyBookmarkFactoryActionClass EphyBookmarkFactoryActionClass;
+
+struct _EphyBookmarkFactoryAction
+{
+ GtkAction parent;
+};
+
+struct _EphyBookmarkFactoryActionClass
+{
+ GtkActionClass parent_class;
+};
+
+GType ephy_bookmark_factory_action_get_type (void);
+
+GtkAction * ephy_bookmark_factory_action_new (const char *name);
+
+#endif
diff --git a/src/bookmarks/ephy-bookmark-properties.c b/src/bookmarks/ephy-bookmark-properties.c
index 6749b58ec..07b83d319 100644
--- a/src/bookmarks/ephy-bookmark-properties.c
+++ b/src/bookmarks/ephy-bookmark-properties.c
@@ -20,7 +20,6 @@
#include "config.h"
-#include "ephy-bookmarksbar-model.h"
#include "ephy-bookmark-properties.h"
#include "ephy-topics-selector.h"
#include "ephy-debug.h"
@@ -43,13 +42,13 @@
static void ephy_bookmark_properties_class_init (EphyBookmarkPropertiesClass *klass);
static void ephy_bookmark_properties_init (EphyBookmarkProperties *editor);
static void ephy_bookmark_properties_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
static void ephy_bookmark_properties_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
#define EPHY_BOOKMARK_PROPERTIES_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARK_PROPERTIES, EphyBookmarkPropertiesPrivate))
@@ -61,8 +60,6 @@ struct _EphyBookmarkPropertiesPrivate
GtkWidget *title_entry;
GtkWidget *location_entry;
GtkWidget *topics_selector;
-
- EphyBookmarksBarModel *tb_model;
};
enum
@@ -143,9 +140,9 @@ ephy_bookmark_properties_set_bookmark (EphyBookmarkProperties *selector,
static void
ephy_bookmark_properties_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
EphyBookmarkProperties *selector = EPHY_BOOKMARK_PROPERTIES (object);
@@ -153,8 +150,6 @@ ephy_bookmark_properties_set_property (GObject *object,
{
case PROP_BOOKMARKS:
selector->priv->bookmarks = g_value_get_object (value);
- selector->priv->tb_model = EPHY_BOOKMARKSBAR_MODEL
- (ephy_bookmarks_get_toolbars_model (selector->priv->bookmarks));
break;
case PROP_BOOKMARK:
ephy_bookmark_properties_set_bookmark
@@ -168,9 +163,9 @@ ephy_bookmark_properties_set_property (GObject *object,
static void
ephy_bookmark_properties_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
EphyBookmarkProperties *selector = EPHY_BOOKMARK_PROPERTIES (object);
@@ -187,8 +182,8 @@ ephy_bookmark_properties_get_property (GObject *object,
static void
bookmark_properties_response_cb (GtkDialog *dialog,
- int response_id,
- gpointer data)
+ int response_id,
+ gpointer data)
{
switch (response_id)
{
@@ -213,8 +208,8 @@ update_entry (EphyBookmarkProperties *props, GtkWidget *entry, guint prop)
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, text);
ephy_node_set_property (props->priv->bookmark,
- prop,
- &value);
+ prop,
+ &value);
g_value_unset (&value);
g_free (text);
}
@@ -245,29 +240,7 @@ location_entry_changed_cb (GtkWidget *entry, EphyBookmarkProperties *props)
{
ephy_bookmarks_set_address (props->priv->bookmarks,
props->priv->bookmark,
- gtk_entry_get_text (GTK_ENTRY (entry)));
-}
-
-static void
-toolbar_checkbox_changed_cb (GtkWidget *checkbox, EphyBookmarkProperties *props)
-{
- gboolean state;
- guint id;
-
- state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
-
- id = ephy_node_get_id (props->priv->bookmark);
-
- if (state)
- {
- ephy_bookmarksbar_model_add_bookmark
- (props->priv->tb_model, FALSE, id);
- }
- else
- {
- ephy_bookmarksbar_model_remove_bookmark
- (props->priv->tb_model, id);
- }
+ gtk_entry_get_text (GTK_ENTRY (entry)));
}
static void
@@ -306,11 +279,9 @@ static void
build_ui (EphyBookmarkProperties *editor)
{
GtkWidget *table, *label, *entry, *topics_selector;
- GtkWidget *checkbox, *scrolled_window;
+ GtkWidget *scrolled_window;
char *str;
const char *tmp;
- gboolean state;
- guint id;
g_signal_connect (G_OBJECT (editor),
"response",
@@ -319,7 +290,7 @@ build_ui (EphyBookmarkProperties *editor)
ephy_state_add_window (GTK_WIDGET(editor),
"bookmark_properties",
- 290, 280, FALSE,
+ 290, 280, FALSE,
EPHY_STATE_WINDOW_SAVE_SIZE);
update_window_title (editor);
@@ -398,16 +369,6 @@ build_ui (EphyBookmarkProperties *editor)
gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 2, 2, 3,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
- checkbox = gtk_check_button_new_with_mnemonic (_("_Show in bookmarks bar"));
- id = ephy_node_get_id (editor->priv->bookmark);
- state = ephy_bookmarksbar_model_has_bookmark (editor->priv->tb_model, id);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), state);
- g_signal_connect (checkbox, "toggled",
- G_CALLBACK (toolbar_checkbox_changed_cb), editor);
- gtk_table_attach (GTK_TABLE (table), checkbox, 0, 2, 3, 4, GTK_FILL, 0, 0, 0);
- gtk_widget_show (checkbox);
-
-
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editor)->vbox),
table, TRUE, TRUE, 0);
gtk_dialog_add_button (GTK_DIALOG (editor),
diff --git a/src/bookmarks/ephy-bookmarks-editor.c b/src/bookmarks/ephy-bookmarks-editor.c
index 24dbeedac..7608823a6 100644
--- a/src/bookmarks/ephy-bookmarks-editor.c
+++ b/src/bookmarks/ephy-bookmarks-editor.c
@@ -62,10 +62,10 @@
#include "ephy-gui.h"
#include "ephy-stock-icons.h"
#include "ephy-search-entry.h"
-#include "ephy-bookmarksbar-model.h"
#include "ephy-favicon-cache.h"
#include "eel-gconf-extensions.h"
#include "ephy-debug.h"
+#include "egg-toolbars-model.h"
static GtkTargetEntry topic_drag_dest_types [] =
{
@@ -76,9 +76,9 @@ static int n_topic_drag_dest_types = G_N_ELEMENTS (topic_drag_dest_types);
static GtkTargetEntry bmk_drag_types [] =
{
- { EPHY_DND_URL_TYPE, 0, 0 },
- { EPHY_DND_URI_LIST_TYPE, 0, 1 },
- { EPHY_DND_TEXT_TYPE, 0, 2 }
+ { EPHY_DND_URL_TYPE, 0, 0 },
+ { EPHY_DND_URI_LIST_TYPE, 0, 1 },
+ { EPHY_DND_TEXT_TYPE, 0, 2 }
};
static int n_bmk_drag_types = G_N_ELEMENTS (bmk_drag_types);
@@ -93,9 +93,9 @@ static void ephy_bookmarks_editor_init (EphyBookmarksEditor *editor);
static void ephy_bookmarks_editor_finalize (GObject *object);
static void ephy_bookmarks_editor_dispose (GObject *object);
static void ephy_bookmarks_editor_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
static void ephy_bookmarks_editor_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -106,10 +106,8 @@ static void cmd_open_bookmarks_in_tabs (GtkAction *action,
EphyBookmarksEditor *editor);
static void cmd_open_bookmarks_in_browser (GtkAction *action,
EphyBookmarksEditor *editor);
-static void cmd_show_in_bookmarks_bar (GtkAction *action,
- EphyBookmarksEditor *editor);
static void cmd_delete (GtkAction *action,
- EphyBookmarksEditor *editor);
+ EphyBookmarksEditor *editor);
static void cmd_bookmark_properties (GtkAction *action,
EphyBookmarksEditor *editor);
static void cmd_bookmarks_import (GtkAction *action,
@@ -151,7 +149,6 @@ struct _EphyBookmarksEditorPrivate
GtkUIManager *ui_merge;
GtkActionGroup *action_group;
int priority_col;
- EphyBookmarksBarModel *tb_model;
GtkTreeViewColumn *title_col;
GtkTreeViewColumn *address_col;
@@ -225,15 +222,6 @@ static GtkActionEntry ephy_bookmark_popup_entries [] = {
};
static guint ephy_bookmark_popup_n_entries = G_N_ELEMENTS (ephy_bookmark_popup_entries);
-static GtkToggleActionEntry ephy_bookmark_popup_toggle_entries [] =
-{
- /* File Menu */
- { "ShowInBookmarksBar", NULL, N_("_Show in Bookmarks Bar"), NULL,
- N_("Show the selected bookmark or topic in the bookmarks bar"),
- G_CALLBACK (cmd_show_in_bookmarks_bar), FALSE }
-};
-static guint ephy_bookmark_popup_n_toggle_entries = G_N_ELEMENTS (ephy_bookmark_popup_toggle_entries);
-
enum
{
VIEW_TITLE,
@@ -260,14 +248,14 @@ entry_selection_changed_cb (GtkWidget *widget, GParamSpec *pspec, EphyBookmarksE
static void
add_entry_monitor (EphyBookmarksEditor *editor, GtkWidget *entry)
{
- g_signal_connect (G_OBJECT (entry),
- "notify::selection-bound",
- G_CALLBACK (entry_selection_changed_cb),
- editor);
- g_signal_connect (G_OBJECT (entry),
- "notify::cursor-position",
- G_CALLBACK (entry_selection_changed_cb),
- editor);
+ g_signal_connect (G_OBJECT (entry),
+ "notify::selection-bound",
+ G_CALLBACK (entry_selection_changed_cb),
+ editor);
+ g_signal_connect (G_OBJECT (entry),
+ "notify::cursor-position",
+ G_CALLBACK (entry_selection_changed_cb),
+ editor);
}
static void
@@ -288,7 +276,7 @@ cmd_add_topic (GtkAction *action,
EphyNode *node;
node = ephy_bookmarks_add_keyword (editor->priv->bookmarks,
- _("Type a topic"));
+ _("Type a topic"));
ephy_node_view_select_node (EPHY_NODE_VIEW (editor->priv->key_view), node);
ephy_node_view_edit (EPHY_NODE_VIEW (editor->priv->key_view), TRUE);
add_text_renderer_monitor (editor);
@@ -334,65 +322,6 @@ get_target_window (EphyBookmarksEditor *editor)
}
static void
-toolbar_items_changed_cb (EggToolbarsModel *model,
- int toolbar_position,
- int position,
- EphyBookmarksEditor *editor)
-{
- ephy_bookmarks_editor_update_menu (editor);
-}
-
-static void
-cmd_show_in_bookmarks_bar (GtkAction *action,
- EphyBookmarksEditor *editor)
-{
- EphyNode *node;
- GList *selection;
- gboolean state, topic;
- guint id;
-
- if (ephy_node_view_is_target (EPHY_NODE_VIEW (editor->priv->bm_view)))
- {
- selection = ephy_node_view_get_selection
- (EPHY_NODE_VIEW (editor->priv->bm_view));
- topic = FALSE;
- }
- else if (ephy_node_view_is_target (EPHY_NODE_VIEW (editor->priv->key_view)))
- {
- selection = ephy_node_view_get_selection
- (EPHY_NODE_VIEW (editor->priv->key_view));
- topic = TRUE;
- }
- else
- {
- return;
- }
-
- node = selection->data;
- id = ephy_node_get_id (node);
- state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
-
- if (state)
- {
- ephy_bookmarksbar_model_add_bookmark
- (editor->priv->tb_model, topic, id);
- }
- else
- {
- g_signal_handlers_block_by_func
- (editor->priv->tb_model,
- G_CALLBACK (toolbar_items_changed_cb), editor);
- ephy_bookmarksbar_model_remove_bookmark
- (editor->priv->tb_model, id);
- g_signal_handlers_unblock_by_func
- (editor->priv->tb_model,
- G_CALLBACK (toolbar_items_changed_cb), editor);
- }
-
- g_list_free (selection);
-}
-
-static void
cmd_open_bookmarks_in_tabs (GtkAction *action,
EphyBookmarksEditor *editor)
{
@@ -478,7 +407,7 @@ delete_topic_dialog_construct (GtkWindow *parent,
gtk_window_group_add_window (GTK_WINDOW (parent)->group, GTK_WINDOW (dialog));
- return dialog;
+ return dialog;
}
static void
@@ -863,7 +792,7 @@ cmd_bookmarks_import (GtkAction *action,
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
gtk_widget_show (label);
- store = GTK_LIST_STORE (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+ store = GTK_LIST_STORE (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
files = add_bookmarks_files (FIREFOX_BOOKMARKS_DIR_0, "bookmarks.html", 2);
files = g_slist_concat (add_bookmarks_files (FIREFOX_BOOKMARKS_DIR_1, "bookmarks.html", 2), files);
@@ -879,8 +808,8 @@ 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);
+ 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);
@@ -1129,8 +1058,8 @@ ephy_bookmarks_editor_finalize (GObject *object)
if (editor->priv->window)
{
g_object_remove_weak_pointer
- (G_OBJECT(editor->priv->window),
- (gpointer *)&editor->priv->window);
+ (G_OBJECT(editor->priv->window),
+ (gpointer *)&editor->priv->window);
}
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -1138,7 +1067,7 @@ ephy_bookmarks_editor_finalize (GObject *object)
static void
ephy_bookmarks_editor_node_activated_cb (GtkWidget *view,
- EphyNode *node,
+ EphyNode *node,
EphyBookmarksEditor *editor)
{
const char *location;
@@ -1161,8 +1090,8 @@ ephy_bookmarks_editor_update_menu (EphyBookmarksEditor *editor)
gboolean key_selection, bmk_selection, single_bmk_selected;
gboolean key_normal = FALSE;
gboolean cut, copy, paste, select_all;
- gboolean can_show_in_bookmarks_bar, show_in_bookmarks_bar = FALSE;
gboolean mutable = TRUE;
+
GtkActionGroup *action_group;
GtkAction *action;
GList *selected;
@@ -1210,11 +1139,6 @@ ephy_bookmarks_editor_update_menu (EphyBookmarksEditor *editor)
{
EphyNode *node = selected->data;
EphyNodePriority priority;
- guint id;
-
- id = ephy_node_get_id (node);
- show_in_bookmarks_bar = ephy_bookmarksbar_model_has_bookmark
- (editor->priv->tb_model, id);
priority = ephy_node_get_property_int
(node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
@@ -1233,8 +1157,6 @@ ephy_bookmarks_editor_update_menu (EphyBookmarksEditor *editor)
g_return_if_fail (node != NULL);
id = ephy_node_get_id (node);
- show_in_bookmarks_bar = ephy_bookmarksbar_model_has_bookmark
- (editor->priv->tb_model, id);
mutable = !ephy_node_get_property_boolean (node, EPHY_NODE_BMK_PROP_IMMUTABLE);
g_list_free (selected);
@@ -1263,8 +1185,6 @@ ephy_bookmarks_editor_update_menu (EphyBookmarksEditor *editor)
delete = (bmk_focus && bmk_selection && mutable) ||
(key_selection && key_focus && key_normal);
properties = bmk_focus && single_bmk_selected && mutable;
- can_show_in_bookmarks_bar = (bmk_focus && single_bmk_selected && mutable) ||
- (key_selection && key_focus);
action_group = editor->priv->action_group;
action = gtk_action_group_get_action (action_group, "OpenInWindow");
@@ -1287,25 +1207,13 @@ ephy_bookmarks_editor_update_menu (EphyBookmarksEditor *editor)
action = gtk_action_group_get_action (action_group, "Paste");
gtk_action_set_sensitive (action, paste);
action = gtk_action_group_get_action (action_group, "SelectAll");
- gtk_action_set_sensitive (action, select_all);
- action = gtk_action_group_get_action (action_group, "ShowInBookmarksBar");
- gtk_action_set_sensitive (action, can_show_in_bookmarks_bar);
-
- g_signal_handlers_block_by_func
- (G_OBJECT (GTK_TOGGLE_ACTION (action)),
- G_CALLBACK (cmd_show_in_bookmarks_bar),
- editor);
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_in_bookmarks_bar);
- g_signal_handlers_unblock_by_func
- (G_OBJECT (GTK_TOGGLE_ACTION (action)),
- G_CALLBACK (cmd_show_in_bookmarks_bar),
- editor);
+ g_object_set (action, "sensitive", select_all, NULL);
}
static gboolean
view_focus_cb (EphyNodeView *view,
- GdkEventFocus *event,
- EphyBookmarksEditor *editor)
+ GdkEventFocus *event,
+ EphyBookmarksEditor *editor)
{
ephy_bookmarks_editor_update_menu (editor);
@@ -1316,21 +1224,21 @@ static void
add_focus_monitor (EphyBookmarksEditor *editor, GtkWidget *widget)
{
g_signal_connect (G_OBJECT (widget),
- "focus_in_event",
- G_CALLBACK (view_focus_cb),
- editor);
+ "focus_in_event",
+ G_CALLBACK (view_focus_cb),
+ editor);
g_signal_connect (G_OBJECT (widget),
- "focus_out_event",
- G_CALLBACK (view_focus_cb),
- editor);
+ "focus_out_event",
+ G_CALLBACK (view_focus_cb),
+ editor);
}
static void
remove_focus_monitor (EphyBookmarksEditor *editor, GtkWidget *widget)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (widget),
- G_CALLBACK (view_focus_cb),
- editor);
+ G_CALLBACK (view_focus_cb),
+ editor);
}
static gboolean
@@ -1381,13 +1289,13 @@ ephy_bookmarks_editor_dispose (GObject *object)
static void
bookmarks_filter (EphyBookmarksEditor *editor,
- EphyNode *keyword)
+ EphyNode *keyword)
{
ephy_node_filter_empty (editor->priv->bookmarks_filter);
ephy_node_filter_add_expression (editor->priv->bookmarks_filter,
- ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_HAS_PARENT,
- keyword),
- 0);
+ ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_HAS_PARENT,
+ keyword),
+ 0);
ephy_node_filter_done_changing (editor->priv->bookmarks_filter);
}
@@ -1462,15 +1370,15 @@ search_entry_search_cb (GtkWidget *entry, const char *search_text, EphyBookmarks
ephy_node_filter_empty (editor->priv->bookmarks_filter);
ephy_node_filter_add_expression (editor->priv->bookmarks_filter,
- ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_STRING_PROP_CONTAINS,
- EPHY_NODE_BMK_PROP_TITLE,
- search_text),
- 0);
+ ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_STRING_PROP_CONTAINS,
+ EPHY_NODE_BMK_PROP_TITLE,
+ search_text),
+ 0);
ephy_node_filter_add_expression (editor->priv->bookmarks_filter,
- ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_STRING_PROP_CONTAINS,
- EPHY_NODE_BMK_PROP_KEYWORDS,
- search_text),
- 0);
+ ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_STRING_PROP_CONTAINS,
+ EPHY_NODE_BMK_PROP_KEYWORDS,
+ search_text),
+ 0);
ephy_node_filter_done_changing (editor->priv->bookmarks_filter);
}
@@ -1646,10 +1554,6 @@ ephy_bookmarks_editor_construct (EphyBookmarksEditor *editor)
gtk_action_group_set_translation_domain (action_group, NULL);
gtk_action_group_add_actions (action_group, ephy_bookmark_popup_entries,
ephy_bookmark_popup_n_entries, editor);
- gtk_action_group_add_toggle_actions (action_group,
- ephy_bookmark_popup_toggle_entries,
- ephy_bookmark_popup_n_toggle_entries,
- editor);
details_value = get_details_value (editor);
gtk_action_group_add_radio_actions (action_group,
@@ -1661,8 +1565,8 @@ ephy_bookmarks_editor_construct (EphyBookmarksEditor *editor)
gtk_ui_manager_insert_action_group (ui_merge,
action_group, 0);
gtk_ui_manager_add_ui_from_file (ui_merge,
- ephy_file ("epiphany-bookmark-editor-ui.xml"),
- NULL);
+ ephy_file ("epiphany-bookmark-editor-ui.xml"),
+ NULL);
gtk_window_add_accel_group (GTK_WINDOW (editor),
gtk_ui_manager_get_accel_group (ui_merge));
gtk_ui_manager_ensure_update (ui_merge);
@@ -1694,7 +1598,7 @@ ephy_bookmarks_editor_construct (EphyBookmarksEditor *editor)
key_view = ephy_node_view_new (node, NULL);
add_focus_monitor (editor, key_view);
col_id = ephy_node_view_add_data_column (EPHY_NODE_VIEW (key_view),
- G_TYPE_STRING, -1,
+ G_TYPE_STRING, -1,
provide_keyword_uri, editor);
ephy_node_view_add_column (EPHY_NODE_VIEW (key_view), _("Topics"),
G_TYPE_STRING,
@@ -1704,11 +1608,11 @@ ephy_bookmarks_editor_construct (EphyBookmarksEditor *editor)
EPHY_NODE_VIEW_SEARCHABLE, NULL, NULL);
ephy_node_view_enable_drag_source (EPHY_NODE_VIEW (key_view),
topic_drag_types,
- n_topic_drag_types,
+ n_topic_drag_types,
col_id, -1);
ephy_node_view_enable_drag_dest (EPHY_NODE_VIEW (key_view),
- topic_drag_dest_types,
- n_topic_drag_dest_types);
+ topic_drag_dest_types,
+ n_topic_drag_dest_types);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (key_view));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
g_signal_connect (G_OBJECT (selection),
@@ -1777,7 +1681,7 @@ ephy_bookmarks_editor_construct (EphyBookmarksEditor *editor)
0, NULL, &(editor->priv->address_col));
ephy_node_view_enable_drag_source (EPHY_NODE_VIEW (bm_view),
bmk_drag_types,
- n_bmk_drag_types,
+ n_bmk_drag_types,
url_col_id, title_col_id);
ephy_node_view_set_sort (EPHY_NODE_VIEW (bm_view), G_TYPE_STRING,
EPHY_NODE_BMK_PROP_TITLE, GTK_SORT_ASCENDING);
@@ -1804,11 +1708,11 @@ ephy_bookmarks_editor_construct (EphyBookmarksEditor *editor)
ephy_state_add_window (GTK_WIDGET(editor),
"bookmarks_editor",
- 450, 400, FALSE,
+ 450, 400, FALSE,
EPHY_STATE_WINDOW_SAVE_SIZE | EPHY_STATE_WINDOW_SAVE_POSITION);
ephy_state_add_paned (GTK_WIDGET (hpaned),
"bookmarks_paned",
- 130);
+ 130);
set_columns_visibility (editor, details_value);
}
@@ -1820,15 +1724,15 @@ ephy_bookmarks_editor_set_parent (EphyBookmarksEditor *ebe,
if (ebe->priv->window)
{
g_object_remove_weak_pointer
- (G_OBJECT(ebe->priv->window),
- (gpointer *)&ebe->priv->window);
+ (G_OBJECT(ebe->priv->window),
+ (gpointer *)&ebe->priv->window);
}
ebe->priv->window = window;
g_object_add_weak_pointer
- (G_OBJECT(ebe->priv->window),
- (gpointer *)&ebe->priv->window);
+ (G_OBJECT(ebe->priv->window),
+ (gpointer *)&ebe->priv->window);
}
@@ -1851,9 +1755,9 @@ ephy_bookmarks_editor_new (EphyBookmarks *bookmarks)
static void
ephy_bookmarks_editor_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
EphyBookmarksEditor *editor = EPHY_BOOKMARKS_EDITOR (object);
@@ -1870,9 +1774,9 @@ ephy_bookmarks_editor_set_property (GObject *object,
static void
ephy_bookmarks_editor_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
EphyBookmarksEditor *editor = EPHY_BOOKMARKS_EDITOR (object);
@@ -1891,13 +1795,4 @@ static void
ephy_bookmarks_editor_init (EphyBookmarksEditor *editor)
{
editor->priv = EPHY_BOOKMARKS_EDITOR_GET_PRIVATE (editor);
-
- editor->priv->tb_model = EPHY_BOOKMARKSBAR_MODEL
- (ephy_bookmarks_get_toolbars_model
- (ephy_shell_get_bookmarks (ephy_shell)));
-
- g_signal_connect (editor->priv->tb_model, "item_added",
- G_CALLBACK (toolbar_items_changed_cb), editor);
- g_signal_connect (editor->priv->tb_model, "item_removed",
- G_CALLBACK (toolbar_items_changed_cb), editor);
}
diff --git a/src/bookmarks/ephy-bookmarks-menu.c b/src/bookmarks/ephy-bookmarks-menu.c
index 8c54408bb..bbc223655 100644
--- a/src/bookmarks/ephy-bookmarks-menu.c
+++ b/src/bookmarks/ephy-bookmarks-menu.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2003, 2004 Marco Pesenti Gritti
* Copyright (C) 2003, 2004 Christian Persch
+ * Copyright (C) 2004 Peter Harvey
*
* 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
@@ -22,790 +23,213 @@
#include "config.h"
#include "ephy-bookmarks-menu.h"
+#include "ephy-bookmarks-ui.h"
#include "ephy-bookmark-action.h"
+#include "ephy-open-tabs-action.h"
+#include "ephy-topic-action.h"
+#include "ephy-nodes-cover.h"
+#include "ephy-node-common.h"
#include "ephy-link.h"
#include "ephy-shell.h"
-#include "ephy-node-common.h"
+#include "ephy-string.h"
#include "ephy-gui.h"
#include "ephy-debug.h"
-#include <glib/gprintf.h>
-#include <glib/gi18n.h>
-#include <gtk/gtkuimanager.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkmenuitem.h>
#include <string.h>
-#define EPHY_BOOKMARKS_MENU_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARKS_MENU, EphyBookmarksMenuPrivate))
-
-struct _EphyBookmarksMenuPrivate
-{
- GtkUIManager *manager;
- char *path;
- EphyBookmarks *bookmarks;
- GtkActionGroup *bmk_actions;
- GtkActionGroup *folder_actions;
- GSList *removed_bmks;
- guint ui_id;
- guint update_tag;
- gboolean needs_update;
-};
-
-/* 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 BMK_ACCEL_PATH_PREFIX "<Actions>/BmkActions/"
-
-#define GAZILLION 200
-#define UPDATE_DELAY 5000 /* ms */
-#define LABEL_WIDTH_CHARS 32
+#define MIN_MENU_SIZE 7
+#define MAX_MENU_SIZE 21
enum
{
- PROP_0,
- PROP_PATH,
- PROP_UI_MANAGER
+ BUILD_SUBDIVIS = 1 << 0,
+ BUILD_SUBMENUS = 1 << 1,
+ BUILD_CHILD_SUBDIVIS = 1 << 2,
+ BUILD_CHILD_SUBMENUS = 1 << 3
};
-static void ephy_bookmarks_menu_class_init (EphyBookmarksMenuClass *klass);
-static void ephy_bookmarks_menu_init (EphyBookmarksMenu *menu);
-
-static GObjectClass *parent_class = NULL;
-
-GType
-ephy_bookmarks_menu_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyBookmarksMenuClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) ephy_bookmarks_menu_class_init,
- NULL,
- NULL, /* class_data */
- sizeof (EphyBookmarksMenu),
- 0, /* n_preallocs */
- (GInstanceInitFunc) ephy_bookmarks_menu_init
- };
- static const GInterfaceInfo link_info =
- {
- NULL,
- NULL,
- NULL
- };
-
- type = g_type_register_static (G_TYPE_OBJECT,
- "EphyBookmarksMenu",
- &our_info, 0);
- g_type_add_interface_static (type,
- EPHY_TYPE_LINK,
- &link_info);
- }
-
- return type;
-}
-
-static void
-connect_proxy_cb (GtkActionGroup *action_group,
- GtkAction *action,
- GtkWidget *proxy)
-{
- if (GTK_IS_MENU_ITEM (proxy))
- {
- GtkLabel *label;
-
- label = (GtkLabel *) ((GtkBin *) proxy)->child;
-
- gtk_label_set_use_underline (label, FALSE);
- gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
- gtk_label_set_max_width_chars (label, LABEL_WIDTH_CHARS);
- }
-}
-
-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)
- {
- gtk_ui_manager_remove_ui (p->manager, p->ui_id);
- gtk_ui_manager_ensure_update (p->manager);
- p->ui_id = 0;
- }
-
- 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->manager, p->folder_actions);
- g_object_unref (p->folder_actions);
- }
-
- STOP_PROFILER ("Cleaning bookmarks menu")
-}
-
-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, bmk);
-
- gtk_action_set_accel_path (action, apath);
-
- g_signal_connect_swapped (action, "open-link",
- G_CALLBACK (ephy_link_open), 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);
-
- g_signal_connect (menu->priv->bmk_actions, "connect-proxy",
- G_CALLBACK (connect_proxy_cb), NULL);
-
- 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
-sort_topics (gconstpointer a, gconstpointer b)
-{
- EphyNode *node_a = (EphyNode *)a;
- EphyNode *node_b = (EphyNode *)b;
- const char *title1, *title2;
- int retval;
-
- title1 = ephy_node_get_property_string (node_a, EPHY_NODE_KEYWORD_PROP_NAME);
- title2 = ephy_node_get_property_string (node_b, EPHY_NODE_KEYWORD_PROP_NAME);
-
- if (title1 == NULL)
- {
- retval = -1;
- }
- else if (title2 == NULL)
- {
- retval = 1;
- }
- else
- {
- char *str_a, *str_b;
-
- str_a = g_utf8_casefold (title1, -1);
- str_b = g_utf8_casefold (title2, -1);
- retval = g_utf8_collate (str_a, str_b);
- g_free (str_a);
- g_free (str_b);
- }
-
- return retval;
-}
-
-static int
-sort_bookmarks (gconstpointer a, gconstpointer b)
-{
- EphyNode *node_a = (EphyNode *)a;
- EphyNode *node_b = (EphyNode *)b;
- const char *title1, *title2;
- int retval;
-
- title1 = ephy_node_get_property_string (node_a, EPHY_NODE_BMK_PROP_TITLE);
- title2 = ephy_node_get_property_string (node_b, EPHY_NODE_BMK_PROP_TITLE);
-
- if (title1 == NULL)
- {
- retval = -1;
- }
- else if (title2 == NULL)
- {
- retval = 1;
- }
- else
- {
- char *str_a, *str_b;
-
- str_a = g_utf8_casefold (title1, -1);
- str_b = g_utf8_casefold (title2, -1);
- retval = g_utf8_collate (str_a, str_b);
- g_free (str_a);
- g_free (str_b);
- }
-
- return retval;
-}
-
+/* Construct a block of bookmark actions, postfixing the names with a topic id
+ * to allow different. */
static void
-create_menu (EphyBookmarksMenu *menu,
- EphyNode *node,
- const char *path)
+append_bookmarks (GString *string, const GPtrArray *bookmarks, gint instance)
{
- 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)
- {
- node_list = g_list_prepend (node_list,
- g_ptr_array_index (children, i));
- }
-
- node_list = g_list_sort (node_list, (GCompareFunc)sort_bookmarks);
- for (l = node_list; l != NULL; l = l->next)
- {
- char verb[BMK_VERB_FORMAT_LENGTH];
- char name[BMK_NAME_FORMAT_LENGTH];
- guint id;
-
- id = ephy_node_get_id ((EphyNode *) l->data);
-
- g_snprintf (verb, sizeof (verb), BMK_VERB_FORMAT, id);
- g_snprintf (name, sizeof (name), BMK_NAME_FORMAT, id, phash);
-
- gtk_ui_manager_add_ui (p->manager, p->ui_id, path,
- name, verb,
- GTK_UI_MANAGER_MENUITEM, FALSE);
- }
- g_list_free (node_list);
-}
-
-#define FOLDER_ACCEL_PATH_PREFIX "<Actions>/FolderActions/"
-
-static char *
-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 *title;
- char *folder;
- char **folders;
- GString *path;
- guint phash, fhash;
- int i;
-
- title = ephy_node_get_property_string (topic, EPHY_NODE_KEYWORD_PROP_NAME);
- g_return_val_if_fail (title != NULL, NULL);
-
- folders = g_strsplit (title, BOOKMARKS_HIERARCHY_SEP, -1);
-
- /* occurs if topic name was "" or BOOKMARKS_HIERARCHY_SEP */
- if (folders == NULL || folders[0] == NULL)
- {
- g_strfreev (folders);
- return g_strdup (p->path);
- }
-
- path = g_string_new (p->path);
- for (i = 0; folders[i] != NULL; i++)
- {
- folder = folders[i];
-
- /* 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);
+ char *name;
+ long i;
- if (gtk_action_group_get_action (p->folder_actions, verb) == NULL)
+ for (i = 0; i < bookmarks->len; i++)
+ {
+ name = ephy_bookmark_action_name (g_ptr_array_index (bookmarks, i));
+ if (name)
{
- 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_printf (string, "<menuitem action=\"%s\" name=\"%s-%d\"/>",
+ name, name, instance);
+ g_free (name);
}
-
- g_string_append (path, "/");
- g_string_append (path, verb);
}
-
- g_strfreev (folders);
-
- return g_string_free (path, FALSE);
}
+/* Build a menu of the given bookmarks categorised by the given topics.
+ * Shows categorisation using subdivisions, submenus, or a mix of both. */
static void
-ephy_bookmarks_menu_rebuild (EphyBookmarksMenu *menu)
+append_menu (GString *string, const GPtrArray *topics, const GPtrArray *bookmarks, guint flags)
{
- EphyBookmarksMenuPrivate *p = menu->priv;
- 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");
+ GPtrArray *uncovered;
+ guint i;
- return;
- }
-
- LOG ("Rebuilding bookmarks menu");
-
- ephy_bookmarks_menu_clean (menu);
-
- START_PROFILER ("Rebuilding bookmarks menu")
-
- ensure_bookmark_actions (menu);
- p->folder_actions = gtk_action_group_new ("FolderActions");
- gtk_ui_manager_insert_action_group (p->manager, p->folder_actions, -1);
-
- g_signal_connect (p->folder_actions, "connect-proxy",
- G_CALLBACK (connect_proxy_cb), NULL);
-
- p->ui_id = gtk_ui_manager_new_merge_id (p->manager);
-
- topics = ephy_bookmarks_get_keywords (p->bookmarks);
- children = ephy_node_get_children (topics);
-
- for (i = 0; i < children->len; ++i)
- {
- EphyNode *kid;
- EphyNodePriority priority;
-
- kid = g_ptr_array_index (children, i);
-
- priority = ephy_node_get_property_int
- (kid, EPHY_NODE_KEYWORD_PROP_PRIORITY);
-
- if (priority == EPHY_NODE_NORMAL_PRIORITY)
+ gboolean use_subdivis = flags & BUILD_SUBDIVIS;
+ gboolean use_submenus = flags & BUILD_SUBMENUS;
+
+ if (use_subdivis || use_submenus)
+ {
+ GPtrArray *subset, *covering, *subdivisions, *submenus;
+ GArray *sizes = 0;
+ EphyNode *topic;
+ gint size, total;
+ gboolean separate = FALSE;
+ char *name;
+
+ /* Get the subtopics, uncovered bookmarks, and subtopic sizes. */
+ sizes = g_array_sized_new (FALSE, FALSE, sizeof(int), topics->len);
+ uncovered = g_ptr_array_sized_new (bookmarks->len);
+ covering = ephy_nodes_get_covering (topics, bookmarks, 0, uncovered, sizes);
+
+ /* Preallocate arrays for submenus, subdivisions, and bookmark subsets. */
+ subdivisions = g_ptr_array_sized_new (topics->len);
+ submenus = g_ptr_array_sized_new (topics->len);
+ subset = g_ptr_array_sized_new (bookmarks->len);
+
+ /* Get the total number of items in the menu. */
+ total = uncovered->len;
+ for (i = 0; i < covering->len; i++)
+ total += g_array_index (sizes, int, i);
+
+ /* Seperate covering into list of submenus and subdivisions */
+ for (i = 0; i < covering->len; i++)
{
- node_list = g_list_prepend (node_list, kid);
+ topic = g_ptr_array_index (covering, i);
+ size = g_array_index (sizes, int, i);
+
+ if (!use_submenus || (use_subdivis && (size < MIN_MENU_SIZE || total < MAX_MENU_SIZE)))
+ {
+ g_ptr_array_add (subdivisions, topic);
+ }
+ else
+ {
+ g_ptr_array_add (submenus, topic);
+ total = total - size + 1;
+ }
}
- }
-
- node_list = g_list_sort (node_list, (GCompareFunc) sort_topics);
-
- for (l = node_list; l != NULL; l = l->next)
- {
- node = (EphyNode *) l->data;
-
- 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, p->path);
- }
-
- 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_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)
+
+ /* Sort the list of submenus and subdivisions. */
+ g_ptr_array_sort (submenus, ephy_bookmarks_compare_topic_pointers);
+ g_ptr_array_sort (subdivisions, ephy_bookmarks_compare_topic_pointers);
+
+ if (flags & BUILD_CHILD_SUBDIVIS) flags |= BUILD_SUBDIVIS;
+ if (flags & BUILD_CHILD_SUBMENUS) flags |= BUILD_SUBMENUS;
+
+ /* Create each of the submenus. */
+ for (i = 0; i < submenus->len; i++)
{
- menu->priv->update_tag =
- g_timeout_add (UPDATE_DELAY,
- (GSourceFunc) do_update_cb, menu);
+ topic = g_ptr_array_index (submenus, i);
+ ephy_nodes_get_covered (topic, bookmarks, subset);
+
+ name = ephy_topic_action_name (topic);
+ if (name)
+ {
+ g_string_append_printf (string, "<menu name=\"%s\" action=\"%s\">",
+ name, name);
+ append_menu (string, topics, subset, flags);
+ g_string_append (string, "</menu>");
+ separate = TRUE;
+ g_free (name);
+ }
}
- }
- 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_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EphyBookmarksMenu *menu = EPHY_BOOKMARKS_MENU (object);
-
- switch (prop_id)
- {
- case PROP_PATH:
- menu->priv->path = g_value_dup_string (value);
- break;
- case PROP_UI_MANAGER:
- menu->priv->manager = g_value_get_object (value);
- break;
- }
-}
-
-static void
-ephy_bookmarks_menu_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- /* no readable properties */
- g_return_if_reached ();
-}
-
-static void
-bookmarks_tree_changed_cb (EphyBookmarks *bookmarks,
- EphyBookmarksMenu *menu)
-{
- LOG ("bookmarks_tree_changed_cb");
-
- ephy_bookmarks_menu_maybe_update (menu);
-}
-
-static void
-topics_added_cb (EphyNode *keywords,
- EphyNode *bmk,
- EphyBookmarksMenu *menu)
-{
- LOG ("topics_added_cb");
-
- ephy_bookmarks_menu_maybe_update (menu);
-}
-
-static void
-topics_removed_cb (EphyNode *keywords,
- EphyNode *child,
- guint old_index,
- EphyBookmarksMenu *menu)
-{
- LOG ("topics_removed_cb");
-
- ephy_bookmarks_menu_maybe_update (menu);
-}
-
-static void
-topic_child_changed_cb (EphyNode *node,
- EphyNode *child,
- guint property_id,
- EphyBookmarksMenu *menu)
-{
- LOG ("topic_child_changed_cb id=%d property=%d",
- ephy_node_get_id (child), property_id);
-
- if (property_id == EPHY_NODE_KEYWORD_PROP_NAME)
- {
- /* the title of the topic has changed, which may change the
- * hierarchy.
- */
- ephy_bookmarks_menu_maybe_update (menu);
- }
-}
-
-static void
-bookmark_added_cb (EphyNode *bookmarks,
- EphyNode *bmk,
- EphyBookmarksMenu *menu)
-{
- LOG ("bookmark_added_cb id=%d", ephy_node_get_id (bmk));
- if (menu->priv->bmk_actions != NULL)
- {
- /* If the new bookmark has the node ID of one scheduled to
- * be removed, remove the old one first then add new one.
- * This works since the action name depends only on the
- * node ID. See bug #154805.
- */
- GSList *l;
-
- l = g_slist_find (menu->priv->removed_bmks,
- GUINT_TO_POINTER (ephy_node_get_id (bmk)));
- if (l != NULL)
+ /* Create each of the subdivisions. */
+ for (i = 0; i < subdivisions->len; i++)
{
- remove_action (l->data, menu->priv->bmk_actions);
-
- menu->priv->removed_bmks = g_slist_delete_link
- (menu->priv->removed_bmks, l);
+ topic = g_ptr_array_index (subdivisions, i);
+ ephy_nodes_get_covered (topic, bookmarks, subset);
+ g_ptr_array_sort (subset, ephy_bookmarks_compare_bookmark_pointers);
+
+ if (separate) g_string_append (string, "<separator/>");
+ append_bookmarks (string, subset, i+1);
+ separate = TRUE;
}
- add_action_for_bookmark (menu, bmk);
-
- ephy_bookmarks_menu_maybe_update (menu);
+ g_array_free (sizes, TRUE);
+ g_ptr_array_free (covering, TRUE);
+ g_ptr_array_free (subdivisions, TRUE);
+ g_ptr_array_free (submenus, TRUE);
+ g_ptr_array_free (subset, TRUE);
+
+ if (separate && uncovered->len) g_string_append (string, "<separator/>");
}
-}
-
-static void
-bookmark_removed_cb (EphyNode *bookmarks,
- EphyNode *bmk,
- guint old_index,
- EphyBookmarksMenu *menu)
-{
- LOG ("bookmark_removed_cb id=%d", ephy_node_get_id (bmk));
-
- if (menu->priv->bmk_actions != NULL)
+ else
{
- /* 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);
+ uncovered = g_ptr_array_sized_new (bookmarks->len);
+ for (i = 0; i < bookmarks->len; i++)
+ g_ptr_array_add (uncovered, g_ptr_array_index (bookmarks, i));
+ g_ptr_array_sort (uncovered, ephy_bookmarks_compare_bookmark_pointers);
}
+
+ /* Create the final subdivision (uncovered bookmarks). */
+ g_ptr_array_sort (uncovered, ephy_bookmarks_compare_bookmark_pointers);
+ append_bookmarks (string, uncovered, 0);
+ g_ptr_array_free (uncovered, TRUE);
}
-static void
-activate_cb (GtkAction *action,
- EphyBookmarksMenu *menu)
-{
- LOG ("activate_cb");
-
- ephy_bookmarks_menu_rebuild (menu);
-}
-
-static void
-ephy_bookmarks_menu_init (EphyBookmarksMenu *menu)
-{
- menu->priv = EPHY_BOOKMARKS_MENU_GET_PRIVATE (menu);
-}
-
-static GObject *
-ephy_bookmarks_menu_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_params)
+void
+ephy_bookmarks_menu_build (GString *string, EphyNode *parent)
{
- EphyBookmarksMenu *menu;
- GObject *object;
- GtkAction *action;
+ GPtrArray *children, *topics;
+ EphyBookmarks *eb;
EphyNode *node;
+ gint priority;
+ guint flags, id, i;
+
+ eb = ephy_shell_get_bookmarks (ephy_shell);
- object = parent_class->constructor (type, n_construct_properties,
- construct_params);
-
- menu = EPHY_BOOKMARKS_MENU (object);
-
- g_assert (menu->priv->manager != NULL && menu->priv->path != NULL);
-
- menu->priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- g_signal_connect_object (menu->priv->bookmarks, "tree_changed",
- G_CALLBACK (bookmarks_tree_changed_cb),
- 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,
- menu->priv->path);
- g_signal_connect_object (action, "activate",
- G_CALLBACK (activate_cb), menu, 0);
-
- ephy_bookmarks_menu_maybe_update (menu);
-
- return object;
-}
-
-static void
-ephy_bookmarks_menu_finalize (GObject *o)
-{
- EphyBookmarksMenu *menu = EPHY_BOOKMARKS_MENU (o);
- EphyBookmarksMenuPrivate *p = menu->priv;
-
- if (menu->priv->update_tag != 0)
+ children = ephy_node_get_children (ephy_bookmarks_get_keywords (eb));
+ topics = g_ptr_array_sized_new (children->len);
+ for (i = 0; i < children->len; i++)
{
- g_source_remove (menu->priv->update_tag);
+ node = g_ptr_array_index (children, i);
+ priority = ephy_node_get_property_int (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (priority == EPHY_NODE_NORMAL_PRIORITY)
+ g_ptr_array_add (topics, node);
}
- g_slist_free (menu->priv->removed_bmks);
+ /* If no parent was supplied, use the default 'All' */
+ node = parent ? parent : ephy_bookmarks_get_bookmarks(eb);
+ children = ephy_node_get_children (node);
- if (p->bmk_actions != NULL)
- {
- g_object_unref (p->bmk_actions);
- }
+ /* Determine what kind of menu we want. */
+ id = ephy_node_get_id (node);
+ switch(id)
+ {
+ case FAVORITES_NODE_ID:
+ flags = 0;
+ break;
+ case BOOKMARKS_NODE_ID:
+ flags = BUILD_SUBMENUS | BUILD_CHILD_SUBDIVIS;
+ break;
+ default:
+ flags = BUILD_SUBMENUS | BUILD_SUBDIVIS | BUILD_CHILD_SUBDIVIS;
+ /* flags = BUILD_SUBDIVIS; */
+ break;
+ }
- if (p->folder_actions != NULL)
+ /* Build the menu, and return the merge_id */
+ append_menu (string, topics, children, flags);
+ g_ptr_array_free (topics, TRUE);
+
+ /* Add a "Open in tabs" menu item if this menu isn't the 'All' menu. */
+ if (id != BOOKMARKS_NODE_ID)
{
- g_object_unref (p->folder_actions);
+ char *name = ephy_open_tabs_action_name (node);
+ g_string_append_printf
+ (string, "<separator/><menuitem action=\"%s\" name=\"OpenTabs\"/>", name);
+ g_free (name);
}
-
- g_free (p->path);
-
- 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_PATH,
- g_param_spec_string ("path",
- "Path",
- "Merge path",
- NULL,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_UI_MANAGER,
- g_param_spec_object ("ui-manager",
- "UI Manager",
- "UI Manager",
- GTK_TYPE_UI_MANAGER,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_type_class_add_private (object_class, sizeof (EphyBookmarksMenuPrivate));
-}
-
-EphyBookmarksMenu *
-ephy_bookmarks_menu_new (GtkUIManager *manager,
- const char *path)
-{
- return EPHY_BOOKMARKS_MENU (g_object_new (EPHY_TYPE_BOOKMARKS_MENU,
- "ui-manager", manager,
- "path", path,
- NULL));
}
diff --git a/src/bookmarks/ephy-bookmarks-menu.h b/src/bookmarks/ephy-bookmarks-menu.h
index 82a828b50..813d90805 100644
--- a/src/bookmarks/ephy-bookmarks-menu.h
+++ b/src/bookmarks/ephy-bookmarks-menu.h
@@ -23,40 +23,11 @@
#ifndef EPHY_BOOKMARKS_MENU_H
#define EPHY_BOOKMARKS_MENU_H
-#include <glib-object.h>
-#include <gtk/gtkuimanager.h>
+#include "ephy-window.h"
+#include "ephy-node.h"
-G_BEGIN_DECLS
+#include <gtk/gtk.h>
-#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))
-#define EPHY_BOOKMARKS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_BOOKMARKS_MENU, EphyBookmarksMenuClass))
-#define EPHY_IS_BOOKMARKS_MENU(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_BOOKMARKS_MENU))
-#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 _EphyBookmarksMenuPrivate EphyBookmarksMenuPrivate;
-typedef struct _EphyBookmarksMenuClass EphyBookmarksMenuClass;
-
-struct _EphyBookmarksMenuClass
-{
- GObjectClass parent_class;
-};
-
-struct _EphyBookmarksMenu
-{
- GObject parent_object;
-
- /*< private >*/
- EphyBookmarksMenuPrivate *priv;
-};
-
-GType ephy_bookmarks_menu_get_type (void);
-
-EphyBookmarksMenu *ephy_bookmarks_menu_new (GtkUIManager *manager,
- const char *path);
-
-G_END_DECLS
+void ephy_bookmarks_menu_build (GString *string, EphyNode *parent);
#endif
diff --git a/src/bookmarks/ephy-bookmarks-ui.c b/src/bookmarks/ephy-bookmarks-ui.c
new file mode 100644
index 000000000..0b97a8fa8
--- /dev/null
+++ b/src/bookmarks/ephy-bookmarks-ui.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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 "config.h"
+
+#include "ephy-bookmarks.h"
+#include "ephy-bookmarks-ui.h"
+#include "ephy-bookmarks-menu.h"
+#include "ephy-bookmark-action.h"
+#include "ephy-topic-action.h"
+#include "ephy-bookmark-action-group.h"
+#include "ephy-topic-action-group.h"
+#include "ephy-related-action.h"
+#include "ephy-open-tabs-action.h"
+#include "ephy-topic-factory-action.h"
+#include "ephy-bookmark-factory-action.h"
+#include "ephy-node-common.h"
+#include "ephy-link.h"
+#include "ephy-dnd.h"
+#include "ephy-history.h"
+#include "ephy-shell.h"
+#include "ephy-string.h"
+#include "ephy-debug.h"
+#include "ephy-file-helpers.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#define BM_WINDOW_DATA_KEY "bookmarks-window-data"
+
+typedef struct
+{
+ guint bookmarks_menu;
+ guint favorites_menu;
+} BookmarksWindowData;
+
+
+
+static GString * bookmarks_menu_string = 0;
+static GString * favorites_menu_string = 0;
+
+static GtkAction *
+find_action (GtkUIManager *manager, const char *name)
+{
+ GList *l = gtk_ui_manager_get_action_groups (manager);
+ GtkAction *action;
+
+ while (l != NULL)
+ {
+ action = gtk_action_group_get_action (GTK_ACTION_GROUP (l->data), name);
+ if (action) return action;
+ l = l->next;
+ }
+
+ return NULL;
+}
+
+static void
+activate_bookmarks_menu (GtkAction *action, EphyWindow *window)
+{
+ BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY);
+ if (data && !data->bookmarks_menu)
+ {
+ GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+ gtk_ui_manager_ensure_update (manager);
+
+ if (!bookmarks_menu_string->len)
+ {
+ g_string_append (bookmarks_menu_string,
+ "<ui><menubar><menu name=\"BookmarksMenu\" action=\"Bookmarks\">");
+ ephy_bookmarks_menu_build (bookmarks_menu_string, 0);
+ g_string_append (bookmarks_menu_string, "</menu></menubar></ui>");
+ }
+
+ data->bookmarks_menu = gtk_ui_manager_add_ui_from_string
+ (manager, bookmarks_menu_string->str, bookmarks_menu_string->len, 0);
+
+ gtk_ui_manager_ensure_update (manager);
+ }
+}
+
+static void
+activate_favorites_menu (GtkAction *action, EphyWindow *window)
+{
+ BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY);
+ if (data && !data->favorites_menu)
+ {
+ GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+ gtk_ui_manager_ensure_update (manager);
+
+ if (!favorites_menu_string->len)
+ {
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *favorites = ephy_bookmarks_get_favorites (eb);
+
+ g_string_append (favorites_menu_string,
+ "<ui><menubar><menu name=\"GoMenu\" action=\"Go\">");
+ ephy_bookmarks_menu_build (favorites_menu_string, favorites);
+ g_string_append (favorites_menu_string, "</menu></menubar></ui>");
+ }
+
+ data->favorites_menu = gtk_ui_manager_add_ui_from_string
+ (manager, favorites_menu_string->str, favorites_menu_string->len, 0);
+
+ gtk_ui_manager_ensure_update (manager);
+ }
+}
+
+static void
+erase_bookmarks_menu (EphyWindow *window)
+{
+ BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY);
+ GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+
+ if (data != NULL && data->bookmarks_menu != 0)
+ {
+ gtk_ui_manager_remove_ui (manager, data->bookmarks_menu);
+ data->bookmarks_menu = 0;
+ }
+ g_string_truncate (bookmarks_menu_string, 0);
+}
+
+static void
+erase_favorites_menu (EphyWindow *window)
+{
+ BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY);
+ GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+
+ if (data != NULL && data->favorites_menu != 0)
+ {
+ gtk_ui_manager_remove_ui (manager, data->favorites_menu);
+ data->favorites_menu = 0;
+ }
+ g_string_truncate (favorites_menu_string, 0);
+}
+
+static void
+tree_changed_cb (EphyBookmarks *bookmarks, EphyWindow *window)
+{
+ erase_bookmarks_menu (window);
+}
+
+static void
+node_added_cb (EphyNode *parent, EphyNode *child, EphyWindow *window)
+{
+ erase_bookmarks_menu (window);
+ erase_favorites_menu (window);
+}
+
+static void
+node_changed_cb (EphyNode *parent, EphyNode *child, guint property_id, EphyWindow *window)
+{
+ if (property_id == EPHY_NODE_KEYWORD_PROP_NAME || property_id == EPHY_NODE_BMK_PROP_TITLE)
+ {
+ erase_bookmarks_menu (window);
+ erase_favorites_menu (window);
+ }
+}
+
+static void
+node_removed_cb (EphyNode *parent, EphyNode *child, guint index, EphyWindow *window)
+{
+ erase_bookmarks_menu (window);
+ erase_favorites_menu (window);
+}
+
+void
+ephy_bookmarks_ui_attach_window (EphyWindow *window)
+{
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *bookmarks = ephy_bookmarks_get_bookmarks (eb);
+ EphyNode *topics = ephy_bookmarks_get_keywords (eb);
+ EphyNode *favorites = ephy_bookmarks_get_favorites (eb);
+
+ BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY);
+ GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+ GtkActionGroup *actions;
+ GtkAction *action;
+
+ g_return_if_fail (data == 0);
+ data = g_new0 (BookmarksWindowData, 1);
+ g_object_set_data_full (G_OBJECT (window), BM_WINDOW_DATA_KEY, data, g_free);
+
+ actions = ephy_bookmark_group_new (bookmarks);
+ gtk_ui_manager_insert_action_group (manager, actions, 0);
+ g_signal_connect_swapped (G_OBJECT (actions), "open-link",
+ G_CALLBACK (ephy_link_open), G_OBJECT (window));
+ g_object_unref (G_OBJECT (actions));
+
+ actions = ephy_topic_group_new (topics, manager);
+ gtk_ui_manager_insert_action_group (manager, actions, 0);
+ g_object_unref (G_OBJECT (actions));
+
+ actions = ephy_open_tabs_group_new (topics);
+ gtk_ui_manager_insert_action_group (manager, actions, 0);
+ g_signal_connect_swapped (G_OBJECT (actions), "open-link",
+ G_CALLBACK (ephy_link_open), G_OBJECT (window));
+ g_object_unref (G_OBJECT (actions));
+
+ actions = gtk_action_group_new ("BookmarkToolbarActions");
+
+ action = ephy_topic_factory_action_new ("AddTopicToToolbar");
+ gtk_action_group_add_action (actions, action);
+ g_object_unref (action);
+
+ action = ephy_bookmark_factory_action_new ("AddBookmarkToToolbar");
+ gtk_action_group_add_action (actions, action);
+ g_object_unref (action);
+
+ action = ephy_related_action_new (EPHY_LINK (window), manager, "RelatedTopic");
+ gtk_action_group_add_action (actions, action);
+ g_object_unref (action);
+
+ gtk_ui_manager_insert_action_group (manager, actions, 0);
+ g_object_unref (G_OBJECT (actions));
+
+
+ ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ G_OBJECT (window));
+ ephy_node_signal_connect_object (topics, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ G_OBJECT (window));
+ ephy_node_signal_connect_object (favorites, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ G_OBJECT (window));
+
+ ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ G_OBJECT (window));
+ ephy_node_signal_connect_object (topics, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ G_OBJECT (window));
+ ephy_node_signal_connect_object (favorites, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ G_OBJECT (window));
+
+ ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)node_changed_cb,
+ G_OBJECT (window));
+ ephy_node_signal_connect_object (topics, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)node_changed_cb,
+ G_OBJECT (window));
+
+ g_signal_connect_object (G_OBJECT (eb), "tree_changed",
+ G_CALLBACK (tree_changed_cb),
+ G_OBJECT (window), 0);
+
+ /* Build menus on demand. */
+ if (!favorites_menu_string) favorites_menu_string = g_string_new ("");
+ if (!bookmarks_menu_string) bookmarks_menu_string = g_string_new ("");
+ action = find_action (manager, "Bookmarks");
+ g_signal_connect_object (G_OBJECT (action), "activate",
+ G_CALLBACK (activate_bookmarks_menu),
+ G_OBJECT (window), 0);
+ action = find_action (manager, "Go");
+ g_signal_connect_object (G_OBJECT (action), "activate",
+ G_CALLBACK (activate_favorites_menu),
+ G_OBJECT (window), 0);
+}
+
+void
+ephy_bookmarks_ui_detach_window (EphyWindow *window)
+{
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *bookmarks = ephy_bookmarks_get_bookmarks (eb);
+ EphyNode *topics = ephy_bookmarks_get_keywords (eb);
+ EphyNode *favorites = ephy_bookmarks_get_favorites (eb);
+
+ BookmarksWindowData *data = g_object_get_data (G_OBJECT (window), BM_WINDOW_DATA_KEY);
+ GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+ GtkAction *action;
+
+ g_return_if_fail (data != 0);
+ if (data->bookmarks_menu) gtk_ui_manager_remove_ui (manager, data->bookmarks_menu);
+ if (data->favorites_menu) gtk_ui_manager_remove_ui (manager, data->favorites_menu);
+ g_object_set_data (G_OBJECT (window), BM_WINDOW_DATA_KEY, 0);
+
+ ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ G_OBJECT (window));
+ ephy_node_signal_disconnect_object (topics, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ G_OBJECT (window));
+ ephy_node_signal_disconnect_object (favorites, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ G_OBJECT (window));
+
+ ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ G_OBJECT (window));
+ ephy_node_signal_disconnect_object (topics, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ G_OBJECT (window));
+ ephy_node_signal_disconnect_object (favorites, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ G_OBJECT (window));
+
+ ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)node_changed_cb,
+ G_OBJECT (window));
+ ephy_node_signal_disconnect_object (topics, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)node_changed_cb,
+ G_OBJECT (window));
+
+ g_signal_handlers_disconnect_by_func
+ (G_OBJECT (eb), G_CALLBACK (tree_changed_cb), G_OBJECT (window));
+
+ action = find_action (manager, "Bookmarks");
+ g_signal_handlers_disconnect_by_func
+ (G_OBJECT (action), G_CALLBACK (activate_bookmarks_menu), G_OBJECT (window));
+
+ action = find_action (manager, "Go");
+ g_signal_handlers_disconnect_by_func
+ (G_OBJECT (action), G_CALLBACK (activate_favorites_menu), G_OBJECT (window));
+}
+
+static void
+toolbar_node_removed_cb (EphyNode *parent, EphyNode *child, guint index, EggToolbarsModel *model)
+{
+ gint i, j;
+ char *nid = NULL;
+ const char *id;
+
+ switch (ephy_node_get_id (parent))
+ {
+ case BOOKMARKS_NODE_ID:
+ nid = ephy_bookmark_action_name (child);
+ break;
+ case KEYWORDS_NODE_ID:
+ nid = ephy_topic_action_name (child);
+ break;
+ default:
+ return;
+ }
+
+ for (i=egg_toolbars_model_n_toolbars(model)-1; i>=0; i--)
+ for (j=egg_toolbars_model_n_items(model, i)-1; j>=0; j--)
+ {
+ id = egg_toolbars_model_item_nth (model, i, j);
+ if (!strcmp (id, nid))
+ {
+ egg_toolbars_model_remove_item (model, i, j);
+ }
+ }
+
+ free (nid);
+}
+
+/* Below this line we have functions relating to toolbar code */
+
+static EggToolbarsItemType bookmark_type;
+static EggToolbarsItemType topic_type;
+static EphyBookmarks *eb;
+
+static gboolean
+topic_has_data (EggToolbarsItemType *type,
+ const char *name)
+{
+ EphyNode *node, *topics;
+ guint node_id;
+
+ if (sscanf (name, "OpenTopic%u", &node_id) != 1 ||
+ sscanf (name, "Tpc%u", &node_id) != 1) return FALSE;
+ node = ephy_bookmarks_get_from_id (eb, node_id);
+ if (!node) return FALSE;
+ topics = ephy_bookmarks_get_keywords (eb);
+ return ephy_node_has_child (topics, node);
+}
+
+static char *
+topic_get_data (EggToolbarsItemType *type,
+ const char *name)
+{
+ EphyNode *node;
+ guint node_id;
+
+ if (sscanf (name, "OpenTopic%u", &node_id) != 1 ||
+ sscanf (name, "Tpc%u", &node_id) != 1) return NULL;
+ node = ephy_bookmarks_get_from_id (eb, node_id);
+ if (!node) return NULL;
+ return ephy_bookmarks_get_topic_uri (eb, node);
+}
+
+static char *
+topic_get_name (EggToolbarsItemType *type,
+ const char *name)
+{
+ EphyNode *topic = ephy_bookmarks_find_keyword (eb, name, FALSE);
+ if (topic == NULL) return NULL;
+ return ephy_topic_action_name (topic);
+}
+
+
+static gboolean
+bookmark_has_data (EggToolbarsItemType *type,
+ const char *name)
+{
+ EphyNode *node;
+ guint node_id;
+
+ if (sscanf (name, "OpenBmk%u", &node_id) != 1 ||
+ sscanf (name, "Bmk%u", &node_id) != 1) return FALSE;
+ node = ephy_bookmarks_get_from_id (eb, node_id);
+ if (!node) return FALSE;
+
+ return (ephy_node_get_property_string (node, EPHY_NODE_BMK_PROP_LOCATION) != NULL);
+}
+
+static char *
+bookmark_get_data (EggToolbarsItemType *type,
+ const char *name)
+{
+ EphyNode *node;
+ guint node_id;
+
+ if (sscanf (name, "OpenBmk%u", &node_id) != 1 ||
+ sscanf (name, "Bmk%u", &node_id) != 1) return NULL;
+ node = ephy_bookmarks_get_from_id (eb, node_id);
+ if (!node) return NULL;
+
+ return g_strdup (ephy_node_get_property_string (node, EPHY_NODE_BMK_PROP_LOCATION));
+}
+
+static char *
+bookmark_get_name (EggToolbarsItemType *type,
+ const char *data)
+{
+ EphyNode *node;
+ gchar **netscape_url;
+
+ netscape_url = g_strsplit (data, "\n", 2);
+ if (!netscape_url || !netscape_url[0])
+ {
+ g_strfreev (netscape_url);
+ return NULL;
+ }
+
+ node = ephy_bookmarks_find_bookmark (eb, netscape_url[0]);
+ g_strfreev (netscape_url);
+
+ if (!node) return NULL;
+ return ephy_bookmark_action_name (node);
+}
+
+static char *
+bookmark_new_name (EggToolbarsItemType *type,
+ const char *data)
+{
+ EphyHistory *gh;
+ EphyNode *node;
+ gchar **netscape_url;
+ const char *icon;
+ const char *title;
+
+ netscape_url = g_strsplit (data, "\n", 2);
+ if (!netscape_url || !netscape_url[0])
+ {
+ g_strfreev (netscape_url);
+ return NULL;
+ }
+
+ title = netscape_url[1];
+ if (title == NULL || title[0] == '\0')
+ {
+ title = _("Untitled");
+ }
+
+ node = ephy_bookmarks_add (eb, title, netscape_url[0]);
+
+ if (node != NULL)
+ {
+ gh = EPHY_HISTORY (ephy_embed_shell_get_global_history (embed_shell));
+ icon = ephy_history_get_icon (gh, netscape_url[0]);
+
+ if (icon)
+ {
+ ephy_bookmarks_set_icon (eb, netscape_url[0], icon);
+ }
+ }
+
+ g_strfreev (netscape_url);
+
+ return ephy_bookmark_action_name (node);
+}
+
+void
+ephy_bookmarks_ui_attach_toolbar_model (EggToolbarsModel *model)
+{
+ eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *bookmarks = ephy_bookmarks_get_bookmarks (eb);
+ EphyNode *topics = ephy_bookmarks_get_keywords (eb);
+ GList *types = egg_toolbars_model_get_types (model);
+
+ topic_type.type = gdk_atom_intern (EPHY_DND_TOPIC_TYPE, TRUE);
+ topic_type.has_data = topic_has_data;
+ topic_type.get_data = topic_get_data;
+ topic_type.new_name = NULL;
+ topic_type.get_name = topic_get_name;
+
+ bookmark_type.type = gdk_atom_intern (EPHY_DND_URL_TYPE, TRUE);
+ bookmark_type.has_data = bookmark_has_data;
+ bookmark_type.get_data = bookmark_get_data;
+ bookmark_type.new_name = bookmark_new_name;
+ bookmark_type.get_name = bookmark_get_name;
+
+ types = g_list_prepend (types, &bookmark_type);
+ types = g_list_prepend (types, &topic_type);
+ egg_toolbars_model_set_types (model, types);
+
+ ephy_node_signal_connect_object (bookmarks, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)toolbar_node_removed_cb,
+ G_OBJECT (model));
+ ephy_node_signal_connect_object (topics, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)toolbar_node_removed_cb,
+ G_OBJECT (model));
+
+ egg_toolbars_model_set_n_avail (model, "AddTopicToToolbar", G_MAXINT);
+ egg_toolbars_model_set_n_avail (model, "AddBookmarkToToolbar", G_MAXINT);
+ egg_toolbars_model_set_n_avail (model, "RelatedTopic", 1);
+}
+
+
+void
+ephy_bookmarks_ui_detach_toolbar_model (EggToolbarsModel *model)
+{
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *bookmarks = ephy_bookmarks_get_bookmarks (eb);
+ EphyNode *topics = ephy_bookmarks_get_keywords (eb);
+
+ ephy_node_signal_disconnect_object (bookmarks, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)toolbar_node_removed_cb,
+ G_OBJECT (model));
+ ephy_node_signal_disconnect_object (topics, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)toolbar_node_removed_cb,
+ G_OBJECT (model));
+}
diff --git a/src/bookmarks/ephy-bookmarks-ui.h b/src/bookmarks/ephy-bookmarks-ui.h
new file mode 100644
index 000000000..084b37eea
--- /dev/null
+++ b/src/bookmarks/ephy-bookmarks-ui.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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.
+ */
+
+#ifndef EPHY_BOOKMARKS_UI_H
+#define EPHY_BOOKMARKS_UI_H
+
+#include "ephy-window.h"
+#include "egg-toolbars-model.h"
+
+#include <gtk/gtk.h>
+
+void ephy_bookmarks_ui_attach_window (EphyWindow *window);
+void ephy_bookmarks_ui_detach_window (EphyWindow *window);
+
+void ephy_bookmarks_ui_attach_toolbar_model (EggToolbarsModel *model);
+void ephy_bookmarks_ui_detach_toolbar_model (EggToolbarsModel *model);
+
+#endif
diff --git a/src/bookmarks/ephy-bookmarks.c b/src/bookmarks/ephy-bookmarks.c
index c6435e40d..4e661a497 100644
--- a/src/bookmarks/ephy-bookmarks.c
+++ b/src/bookmarks/ephy-bookmarks.c
@@ -30,7 +30,6 @@
#include "ephy-debug.h"
#include "ephy-tree-model-node.h"
#include "ephy-node-common.h"
-#include "ephy-bookmarksbar-model.h"
#include "ephy-bookmarks-export.h"
#include "ephy-bookmarks-import.h"
#include "ephy-bookmark-properties.h"
@@ -58,7 +57,6 @@
struct _EphyBookmarksPrivate
{
- EphyBookmarksBarModel *toolbars_model;
gboolean init_defaults;
gboolean dirty;
guint save_timeout_id;
@@ -110,12 +108,6 @@ static const char *default_topics [] =
};
static int n_default_topics = G_N_ELEMENTS (default_topics);
-enum
-{
- PROP_0,
- PROP_TOOLBARS_MODEL
-};
-
/* Signals */
enum
{
@@ -136,33 +128,33 @@ static GObjectClass *parent_class = NULL;
GType
ephy_bookmarks_get_type (void)
{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyBookmarksClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) ephy_bookmarks_class_init,
- NULL,
- NULL, /* class_data */
- sizeof (EphyBookmarks),
- 0, /* n_preallocs */
- (GInstanceInitFunc) ephy_bookmarks_init
- };
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EphyBookmarksClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ephy_bookmarks_class_init,
+ NULL,
+ NULL, /* class_data */
+ sizeof (EphyBookmarks),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) ephy_bookmarks_init
+ };
volatile GType flags_type; /* work around gcc's optimiser */
/* make sure the flags type is known */
flags_type = EPHY_TYPE_BOOKMARK_PROPERTY;
- type = g_type_register_static (G_TYPE_OBJECT,
+ type = g_type_register_static (G_TYPE_OBJECT,
"EphyBookmarks",
&our_info, 0);
- }
+ }
- return type;
+ return type;
}
static void
@@ -180,126 +172,18 @@ ephy_bookmarks_init_defaults (EphyBookmarks *eb)
EphyNode *bmk;
bmk = ephy_bookmarks_add (eb, _(default_bookmarks[i].title),
- _(default_bookmarks[i].location));
- ephy_bookmarksbar_model_add_bookmark (eb->priv->toolbars_model, FALSE,
- ephy_node_get_id (bmk));
- }
-}
-
-static char *
-get_item_type_forward_cb (EggToolbarsModel *model,
- GdkAtom type,
- EggToolbarsModel *bookmarksbar_model)
-{
- char *retval;
-
- g_signal_emit_by_name (bookmarksbar_model, "get_item_type",
- type, &retval);
-
- return retval;
-}
-
-static char *
-get_item_id_forward_cb (EggToolbarsModel *model,
- const char *type,
- const char *name,
- EggToolbarsModel *bookmarksbar_model)
-{
- char *retval;
-
- g_signal_emit_by_name (bookmarksbar_model, "get_item_id",
- type, name, &retval);
-
- return retval;
-}
-
-static char *
-get_item_data_forward_cb (EggToolbarsModel *model,
- const char *type,
- const char *id,
- EggToolbarsModel *bookmarksbar_model)
-{
- char *retval;
-
- g_signal_emit_by_name (bookmarksbar_model, "get_item_data",
- type, id, &retval);
-
- return retval;
-}
-
-GObject *
-ephy_bookmarks_get_toolbars_model (EphyBookmarks *eb)
-{
- g_return_val_if_fail (EPHY_IS_BOOKMARKS (eb), NULL);
-
- LOG ("ephy_bookmarks_get_toolbars_model");
-
- if (eb->priv->toolbars_model == NULL)
- {
- GObject *toolbars_model;
-
- eb->priv->toolbars_model = EPHY_BOOKMARKSBAR_MODEL
- (ephy_bookmarksbar_model_new (eb));
-
- /* forward those signals, so that bookmarks can also be on the main model */
- toolbars_model = ephy_shell_get_toolbars_model (ephy_shell, FALSE);
-
- g_signal_connect_after (toolbars_model, "get_item_type",
- G_CALLBACK (get_item_type_forward_cb),
- eb->priv->toolbars_model);
- g_signal_connect_after (toolbars_model, "get_item_id",
- G_CALLBACK (get_item_id_forward_cb),
- eb->priv->toolbars_model);
- g_signal_connect_after (toolbars_model, "get_item_data",
- G_CALLBACK (get_item_data_forward_cb),
- eb->priv->toolbars_model);
-
- if (eb->priv->init_defaults)
- {
- ephy_bookmarks_init_defaults (eb);
- }
+ _(default_bookmarks[i].location));
}
-
- return G_OBJECT (eb->priv->toolbars_model);
}
static void
-ephy_bookmarks_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- /* no writable properties */
- g_assert_not_reached ();
-}
-
-static void
-ephy_bookmarks_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EphyBookmarks *eb = EPHY_BOOKMARKS (object);
-
- switch (prop_id)
- {
- case PROP_TOOLBARS_MODEL:
- g_value_set_object (value, ephy_bookmarks_get_toolbars_model (eb));
- break;
- }
-}
-
-
-static void
ephy_bookmarks_class_init (EphyBookmarksClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- parent_class = g_type_class_peek_parent (klass);
+ parent_class = g_type_class_peek_parent (klass);
- object_class->finalize = ephy_bookmarks_finalize;
- object_class->set_property = ephy_bookmarks_set_property;
- object_class->get_property = ephy_bookmarks_get_property;
+ object_class->finalize = ephy_bookmarks_finalize;
klass->resolve_address = impl_resolve_address;
@@ -325,14 +209,6 @@ ephy_bookmarks_class_init (EphyBookmarksClass *klass)
G_TYPE_STRING,
G_TYPE_STRING);
- g_object_class_install_property (object_class,
- PROP_TOOLBARS_MODEL,
- g_param_spec_object ("toolbars-model",
- "Toolbars model",
- "Toolbars model",
- EPHY_TYPE_BOOKMARKSBAR_MODEL,
- G_PARAM_READABLE));
-
g_type_class_add_private (object_class, sizeof(EphyBookmarksPrivate));
}
@@ -408,7 +284,7 @@ ephy_bookmarks_save_delayed (EphyBookmarks *bookmarks, int delay)
{
bookmarks->priv->save_timeout_id =
g_timeout_add (BOOKMARKS_SAVE_DELAY,
- (GSourceFunc) save_bookmarks_delayed,
+ (GSourceFunc) save_bookmarks_delayed,
bookmarks);
}
else
@@ -485,7 +361,7 @@ add_to_favorites (EphyBookmarks *eb, EphyNode *node, EphyHistory *eh)
if (eb->priv->lower_fav && full_menu)
{
ephy_node_remove_child (eb->priv->favorites,
- eb->priv->lower_fav);
+ eb->priv->lower_fav);
}
ephy_node_add_child (eb->priv->favorites, node);
@@ -692,7 +568,7 @@ update_bookmark_keywords (EphyBookmarks *eb, EphyNode *bookmark)
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, case_normalized_keywords);
ephy_node_set_property (bookmark, EPHY_NODE_BMK_PROP_KEYWORDS,
- &value);
+ &value);
g_value_unset (&value);
g_string_free (list, TRUE);
@@ -998,30 +874,30 @@ ephy_bookmarks_init (EphyBookmarks *eb)
/* Translators: this topic contains all bookmarks */
g_value_set_string (&value, Q_("bookmarks|All"));
ephy_node_set_property (eb->priv->bookmarks,
- EPHY_NODE_KEYWORD_PROP_NAME,
- &value);
+ EPHY_NODE_KEYWORD_PROP_NAME,
+ &value);
g_value_unset (&value);
ephy_node_signal_connect_object (eb->priv->bookmarks,
- EPHY_NODE_CHILD_REMOVED,
- (EphyNodeCallback) bookmarks_removed_cb,
- G_OBJECT (eb));
+ EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback) bookmarks_removed_cb,
+ G_OBJECT (eb));
ephy_node_signal_connect_object (eb->priv->bookmarks,
- EPHY_NODE_CHILD_CHANGED,
- (EphyNodeCallback) bookmarks_changed_cb,
- G_OBJECT (eb));
+ EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback) bookmarks_changed_cb,
+ G_OBJECT (eb));
/* Keywords */
eb->priv->keywords = ephy_node_new_with_id (db, KEYWORDS_NODE_ID);
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, EPHY_NODE_ALL_PRIORITY);
ephy_node_set_property (eb->priv->bookmarks,
- EPHY_NODE_KEYWORD_PROP_PRIORITY,
- &value);
+ EPHY_NODE_KEYWORD_PROP_PRIORITY,
+ &value);
g_value_unset (&value);
ephy_node_signal_connect_object (eb->priv->keywords,
- EPHY_NODE_CHILD_REMOVED,
- (EphyNodeCallback) topics_removed_cb,
- G_OBJECT (eb));
+ EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback) topics_removed_cb,
+ G_OBJECT (eb));
ephy_node_add_child (eb->priv->keywords,
eb->priv->bookmarks);
@@ -1034,8 +910,8 @@ ephy_bookmarks_init (EphyBookmarks *eb)
/* Translators: this topic contains the most used bookmarks */
g_value_set_string (&value, Q_("bookmarks|Most Visited"));
ephy_node_set_property (eb->priv->favorites,
- EPHY_NODE_KEYWORD_PROP_NAME,
- &value);
+ EPHY_NODE_KEYWORD_PROP_NAME,
+ &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, EPHY_NODE_SPECIAL_PRIORITY);
@@ -1053,8 +929,8 @@ ephy_bookmarks_init (EphyBookmarks *eb)
/* Translators: this topic contains the not categorized bookmarks */
g_value_set_string (&value, Q_("bookmarks|Not Categorized"));
ephy_node_set_property (eb->priv->notcategorized,
- EPHY_NODE_KEYWORD_PROP_NAME,
- &value);
+ EPHY_NODE_KEYWORD_PROP_NAME,
+ &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, EPHY_NODE_SPECIAL_PRIORITY);
@@ -1120,6 +996,11 @@ ephy_bookmarks_init (EphyBookmarks *eb)
eb->priv->init_defaults = TRUE;
}
}
+
+ if (eb->priv->init_defaults)
+ {
+ ephy_bookmarks_init_defaults (eb);
+ }
eb->priv->disable_bookmark_editing_notifier_id = eel_gconf_notification_add
(CONF_LOCKDOWN_DISABLE_BOOKMARK_EDITING,
@@ -1150,13 +1031,6 @@ ephy_bookmarks_finalize (GObject *object)
ephy_bookmarks_save (eb);
- /* have to do this before unreffing the nodes */
- LOG ("Unref bookmarks toolbars model");
- if (eb->priv->toolbars_model != NULL)
- {
- g_object_unref (eb->priv->toolbars_model);
- }
-
ephy_node_unref (eb->priv->bookmarks);
ephy_node_unref (eb->priv->keywords);
ephy_node_unref (eb->priv->favorites);
@@ -1236,13 +1110,13 @@ ephy_bookmarks_add (EphyBookmarks *eb,
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, title);
ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_TITLE,
- &value);
+ &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, url);
ephy_node_set_property (bm, EPHY_NODE_BMK_PROP_LOCATION,
- &value);
+ &value);
g_value_unset (&value);
update_has_smart_address (eb, bm, url);
@@ -1266,7 +1140,7 @@ ephy_bookmarks_set_address (EphyBookmarks *eb,
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, address);
ephy_node_set_property (bookmark, EPHY_NODE_BMK_PROP_LOCATION,
- &value);
+ &value);
g_value_unset (&value);
update_has_smart_address (eb, bookmark, address);
@@ -1318,7 +1192,7 @@ ephy_bookmarks_set_icon (EphyBookmarks *eb,
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, icon);
ephy_node_set_property (node, EPHY_NODE_BMK_PROP_ICON,
- &value);
+ &value);
g_value_unset (&value);
}
@@ -1468,13 +1342,13 @@ ephy_bookmarks_add_keyword (EphyBookmarks *eb,
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, name);
ephy_node_set_property (key, EPHY_NODE_KEYWORD_PROP_NAME,
- &value);
+ &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, EPHY_NODE_NORMAL_PRIORITY);
ephy_node_set_property (key, EPHY_NODE_KEYWORD_PROP_PRIORITY,
- &value);
+ &value);
g_value_unset (&value);
ephy_node_add_child (eb->priv->keywords, key);
@@ -1504,7 +1378,7 @@ bookmark_destroyed_cb (EphyNode *bookmark,
GtkWidget *
ephy_bookmarks_show_bookmark_properties (EphyBookmarks *bookmarks,
EphyNode *bookmark,
- GtkWidget *parent)
+ GtkWidget *parent)
{
GtkWidget *dialog = NULL;
@@ -1734,3 +1608,60 @@ ephy_bookmarks_get_from_id (EphyBookmarks *eb, long id)
{
return ephy_node_db_get_node_from_id (eb->priv->db, id);
}
+
+int
+ephy_bookmarks_compare_topics (gconstpointer a, gconstpointer b)
+{
+ EphyNode *node_a = (EphyNode *)a;
+ EphyNode *node_b = (EphyNode *)b;
+ const char *title1, *title2;
+ int priority1, priority2;
+
+ priority1 = ephy_node_get_property_int (node_a, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ priority2 = ephy_node_get_property_int (node_b, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+
+ if (priority1 > priority2) return 1;
+ if (priority1 < priority2) return -1;
+
+ title1 = ephy_node_get_property_string (node_a, EPHY_NODE_KEYWORD_PROP_NAME);
+ title2 = ephy_node_get_property_string (node_b, EPHY_NODE_KEYWORD_PROP_NAME);
+
+ if (title1 == title2) return 0;
+ if (title1 == NULL) return -1;
+ if (title2 == NULL) return 1;
+ return g_utf8_collate (title1, title2);
+}
+
+int
+ephy_bookmarks_compare_topic_pointers (gconstpointer a, gconstpointer b)
+{
+ EphyNode *node_a = *(EphyNode **)a;
+ EphyNode *node_b = *(EphyNode **)b;
+
+ return ephy_bookmarks_compare_topics (node_a, node_b);
+}
+
+int
+ephy_bookmarks_compare_bookmarks (gconstpointer a, gconstpointer b)
+{
+ EphyNode *node_a = (EphyNode *)a;
+ EphyNode *node_b = (EphyNode *)b;
+ const char *title1, *title2;
+
+ title1 = ephy_node_get_property_string (node_a, EPHY_NODE_BMK_PROP_TITLE);
+ title2 = ephy_node_get_property_string (node_b, EPHY_NODE_BMK_PROP_TITLE);
+
+ if (title1 == title2) return 0;
+ if (title1 == NULL) return -1;
+ if (title2 == NULL) return 1;
+ return g_utf8_collate (title1, title2);
+}
+
+int
+ephy_bookmarks_compare_bookmark_pointers (gconstpointer a, gconstpointer b)
+{
+ EphyNode *node_a = *(EphyNode **)a;
+ EphyNode *node_b = *(EphyNode **)b;
+
+ return ephy_bookmarks_compare_bookmarks (node_a, node_b);
+}
diff --git a/src/bookmarks/ephy-bookmarks.h b/src/bookmarks/ephy-bookmarks.h
index cae6b82ba..3322cd3b7 100644
--- a/src/bookmarks/ephy-bookmarks.h
+++ b/src/bookmarks/ephy-bookmarks.h
@@ -78,8 +78,6 @@ EphyBookmarks *ephy_bookmarks_new (void);
EphyNode *ephy_bookmarks_get_from_id (EphyBookmarks *eb,
long id);
-GObject *ephy_bookmarks_get_toolbars_model (EphyBookmarks *eb);
-
/* Bookmarks */
EphyNode *ephy_bookmarks_add (EphyBookmarks *eb,
@@ -151,6 +149,12 @@ EphyNode *ephy_bookmarks_get_smart_bookmarks (EphyBookmarks *eb);
EphyNode *ephy_bookmarks_get_local (EphyBookmarks *eb);
+/* Comparison functions, useful for sorting lists and arrays. */
+int ephy_bookmarks_compare_topics (gconstpointer a, gconstpointer b);
+int ephy_bookmarks_compare_topic_pointers (gconstpointer a, gconstpointer b);
+int ephy_bookmarks_compare_bookmarks (gconstpointer a, gconstpointer b);
+int ephy_bookmarks_compare_bookmark_pointers (gconstpointer a, gconstpointer b);
+
G_END_DECLS
#endif
diff --git a/src/bookmarks/ephy-bookmarksbar-model.c b/src/bookmarks/ephy-bookmarksbar-model.c
deleted file mode 100755
index 13928950e..000000000
--- a/src/bookmarks/ephy-bookmarksbar-model.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * 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
- * 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.
- *
- * $Id$
- */
-
-#include "config.h"
-
-#include "ephy-bookmarksbar-model.h"
-#include "ephy-bookmarks.h"
-#include "ephy-dnd.h"
-#include "ephy-node-common.h"
-#include "ephy-file-helpers.h"
-#include "ephy-history.h"
-#include "ephy-shell.h"
-#include "ephy-string.h"
-#include "ephy-debug.h"
-
-#include <string.h>
-#include <glib/gi18n.h>
-
-#define EPHY_BOOKMARKSBARS_XML_FILE "epiphany-bookmarksbar.xml"
-#define EPHY_BOOKMARKSBARS_XML_VERSION "1.0"
-
-enum
-{
- PROP_0,
- PROP_BOOKMARKS
-};
-
-enum
-{
- URL,
- NAME
-};
-
-#define EPHY_BOOKMARKSBAR_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARKSBAR_MODEL, EphyBookmarksBarModelPrivate))
-
-struct _EphyBookmarksBarModelPrivate
-{
- EphyBookmarks *bookmarks;
- char *xml_file;
- guint timeout;
-};
-
-static void ephy_bookmarksbar_model_class_init (EphyBookmarksBarModelClass *klass);
-static void ephy_bookmarksbar_model_init (EphyBookmarksBarModel *t);
-
-static GObjectClass *parent_class = NULL;
-
-GType
-ephy_bookmarksbar_model_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- {
- static const GTypeInfo our_info = {
- sizeof (EphyBookmarksBarModelClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) ephy_bookmarksbar_model_class_init,
- NULL,
- NULL, /* class_data */
- sizeof (EphyBookmarksBarModel),
- 0, /* n_preallocs */
- (GInstanceInitFunc) ephy_bookmarksbar_model_init
- };
-
- type = g_type_register_static (EGG_TYPE_TOOLBARS_MODEL,
- "EphyBookmarksBarModel",
- &our_info, 0);
- }
-
- return type;
-}
-
-static gboolean
-get_toolbar_and_item_pos (EphyBookmarksBarModel *model,
- const char *name,
- int *toolbar,
- int *position)
-{
- EggToolbarsModel *eggmodel = EGG_TOOLBARS_MODEL (model);
- int n_toolbars, n_items;
- int t,i;
-
- n_toolbars = egg_toolbars_model_n_toolbars (eggmodel);
-
- for (t = 0; t < n_toolbars; t++)
- {
- n_items = egg_toolbars_model_n_items (eggmodel, t);
-
- for (i = 0; i < n_items; i++)
- {
- const char *i_name;
- gboolean is_separator;
-
- egg_toolbars_model_item_nth (EGG_TOOLBARS_MODEL (model),
- t , i, &is_separator, &i_name, NULL);
- g_return_val_if_fail (i_name != NULL, FALSE);
-
- if (strcmp (i_name, name) == 0)
- {
- if (toolbar) *toolbar = t;
- if (position) *position = i;
-
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-static int
-get_toolbar_pos (EphyBookmarksBarModel *model,
- const char *name)
-{
- EggToolbarsModel *eggmodel = EGG_TOOLBARS_MODEL (model);
- int i, n_toolbars;
-
- n_toolbars = egg_toolbars_model_n_toolbars (eggmodel);
-
- for (i = 0; i < n_toolbars; i++)
- {
- const char *t_name;
-
- t_name = egg_toolbars_model_toolbar_nth (eggmodel, i);
- if (strcmp (name, t_name) == 0)
- {
- return i;
- }
- }
-
- return -1;
-}
-
-char *
-ephy_bookmarksbar_model_get_action_name (EphyBookmarksBarModel *model,
- long id)
-{
- return g_strdup_printf ("GoBookmark-%ld", id);
-}
-
-EphyNode *
-ephy_bookmarksbar_model_get_node (EphyBookmarksBarModel *model,
- const char *action_name)
-{
- EphyBookmarks *bookmarks = EPHY_BOOKMARKSBAR_MODEL (model)->priv->bookmarks;
- unsigned long node_id;
-
- if (!ephy_string_to_int (action_name + strlen ("GoBookmark-"), &node_id))
- {
- return NULL;
- }
-
- return ephy_bookmarks_get_from_id (bookmarks, node_id);
-}
-
-void
-ephy_bookmarksbar_model_add_bookmark (EphyBookmarksBarModel *model,
- gboolean topic,
- long id)
-{
- char *name;
- int toolbar_position;
-
- toolbar_position = get_toolbar_pos (model, "BookmarksBar");
- g_return_if_fail (toolbar_position != -1);
-
- name = ephy_bookmarksbar_model_get_action_name (model, id);
- egg_toolbars_model_add_item (EGG_TOOLBARS_MODEL (model),
- toolbar_position, -1, name,
- topic ? EPHY_DND_TOPIC_TYPE :
- EPHY_DND_URL_TYPE);
- g_free (name);
-}
-
-void
-ephy_bookmarksbar_model_remove_bookmark (EphyBookmarksBarModel *model,
- long id)
-{
- char *action_name;
- int toolbar, position;
-
- action_name = ephy_bookmarksbar_model_get_action_name (model, id);
- g_return_if_fail (action_name != NULL);
-
- while (get_toolbar_and_item_pos (model, action_name, &toolbar, &position))
- {
- egg_toolbars_model_remove_item (EGG_TOOLBARS_MODEL (model),
- toolbar, position);
- }
-
- g_free (action_name);
-}
-
-gboolean
-ephy_bookmarksbar_model_has_bookmark (EphyBookmarksBarModel *model,
- long id)
-{
- char *action_name;
- gboolean found;
- int toolbar, pos;
-
- action_name = ephy_bookmarksbar_model_get_action_name (model, id);
- g_return_val_if_fail (action_name != NULL, FALSE);
-
- found = get_toolbar_and_item_pos (model, action_name, &toolbar, &pos);
-
- g_free (action_name);
-
- return found;
-}
-
-static gboolean
-save_changes_idle (EphyBookmarksBarModel *model)
-{
- LOG ("Saving bookmarks toolbars model");
-
- egg_toolbars_model_save
- (EGG_TOOLBARS_MODEL (model),
- model->priv->xml_file,
- EPHY_BOOKMARKSBARS_XML_VERSION);
-
- model->priv->timeout = 0;
-
- /* don't run again */
- return FALSE;
-}
-
-static void
-save_changes (EphyBookmarksBarModel *model)
-{
- if (model->priv->timeout == 0)
- {
- model->priv->timeout =
- g_idle_add ((GSourceFunc) save_changes_idle, model);
- }
-}
-
-static void
-update_flags_and_save_changes (EphyBookmarksBarModel *model)
-{
- EggToolbarsModel *eggmodel = EGG_TOOLBARS_MODEL (model);
- int i, n_toolbars;
- int flag = 0;
-
- n_toolbars = egg_toolbars_model_n_toolbars (eggmodel);
-
- if (n_toolbars <= 1)
- {
- flag = EGG_TB_MODEL_NOT_REMOVABLE;
- }
-
- for (i = 0; i < n_toolbars; i++)
- {
- const char *t_name;
-
- t_name = egg_toolbars_model_toolbar_nth (eggmodel, i);
- g_return_if_fail (t_name != NULL);
-
- egg_toolbars_model_set_flags (eggmodel, i, flag);
- }
-
- save_changes (model);
-}
-
-static void
-item_added_cb (EphyBookmarksBarModel *model,
- int toolbar_position,
- int position)
-{
- save_changes (model);
-}
-
-static char *
-impl_get_item_type (EggToolbarsModel *model,
- GdkAtom type)
-{
- if (gdk_atom_intern (EPHY_DND_TOPIC_TYPE, FALSE) == type)
- {
- return g_strdup (EPHY_DND_TOPIC_TYPE);
- }
- else if (gdk_atom_intern (EPHY_DND_URL_TYPE, FALSE) == type)
- {
- return g_strdup (EPHY_DND_URL_TYPE);
- }
-
- return EGG_TOOLBARS_MODEL_CLASS (parent_class)->get_item_type (model, type);
-}
-
-static char *
-impl_get_item_id (EggToolbarsModel *eggmodel,
- const char *type,
- const char *name)
-{
- EphyBookmarksBarModel *model = EPHY_BOOKMARKSBAR_MODEL (eggmodel);
- EphyBookmarks *bookmarks = model->priv->bookmarks;
-
- if (strcmp (type, EPHY_DND_TOPIC_TYPE) == 0)
- {
- EphyNode *topic;
-
- topic = ephy_bookmarks_find_keyword (bookmarks, name, FALSE);
- if (topic == NULL) return NULL;
-
- return ephy_bookmarksbar_model_get_action_name
- (model, ephy_node_get_id (topic));
- }
- else if (strcmp (type, EPHY_DND_URL_TYPE) == 0)
- {
- EphyNode *node = NULL;
- gchar **netscape_url;
-
- netscape_url = g_strsplit (name, "\n", 2);
- if (!netscape_url || !netscape_url[URL]) {
- g_strfreev (netscape_url);
- return NULL;
- }
-
- node = ephy_bookmarks_find_bookmark (bookmarks, netscape_url[URL]);
-
- if (!node)
- {
- /* Create the bookmark, it does not exist */
- EphyHistory *gh;
- const char *icon;
- const char *title;
-
- title = netscape_url[NAME];
- if (title == NULL || *title == '\0')
- {
- title = _("Untitled");
- }
-
- node = ephy_bookmarks_add (bookmarks, title, netscape_url[URL]);
-
- if (node != NULL)
- {
- gh = EPHY_HISTORY (ephy_embed_shell_get_global_history (embed_shell));
- icon = ephy_history_get_icon (gh, netscape_url[URL]);
-
- if (icon)
- {
- ephy_bookmarks_set_icon (bookmarks, netscape_url[URL], icon);
- }
- }
- }
-
- g_strfreev (netscape_url);
-
- if (node == NULL) return NULL;
-
- return ephy_bookmarksbar_model_get_action_name
- (model, ephy_node_get_id (node));
- }
-
- return EGG_TOOLBARS_MODEL_CLASS (parent_class)->get_item_id (eggmodel, type, name);
-}
-
-static char *
-impl_get_item_data (EggToolbarsModel *eggmodel,
- const char *type,
- const char *id)
-{
- EphyBookmarksBarModel *model = EPHY_BOOKMARKSBAR_MODEL (eggmodel);
- EphyNode *node;
-
- if (strcmp (type, EPHY_DND_TOPIC_TYPE) == 0)
- {
- char *uri;
-
- node = ephy_bookmarksbar_model_get_node (model, id);
- g_return_val_if_fail (node != NULL, NULL);
-
- uri = ephy_bookmarks_get_topic_uri
- (model->priv->bookmarks, node);
-
- return uri;
- }
- else if (strcmp (type, EPHY_DND_URL_TYPE) == 0)
- {
- const char *name;
-
- node = ephy_bookmarksbar_model_get_node (model, id);
- g_return_val_if_fail (node != NULL, NULL);
-
- name = ephy_node_get_property_string
- (node, EPHY_NODE_BMK_PROP_LOCATION);
-
- return g_strdup (name);
- }
-
- return EGG_TOOLBARS_MODEL_CLASS (parent_class)->get_item_data (eggmodel, type, id);
-}
-
-static void
-load_toolbars (EphyBookmarksBarModel *model)
-{
- EggToolbarsModel *eggmodel = EGG_TOOLBARS_MODEL (model);
- gboolean success = FALSE;
-
- success = egg_toolbars_model_load (eggmodel, model->priv->xml_file);
- LOG ("Loading the toolbars was %ssuccessful", success ? "" : "un");
-
- /* Try migration first: load the old layout, and remove every toolbar
- * except the BookmarksBar toolbar
- */
- if (success == FALSE)
- {
- char *old_xml;
- int i, n_toolbars;
-
- old_xml = g_build_filename (ephy_dot_dir (),
- "epiphany-toolbars.xml",
- NULL);
- success = egg_toolbars_model_load (eggmodel, old_xml);
- g_free (old_xml);
-
- if (success)
- {
- n_toolbars = egg_toolbars_model_n_toolbars (eggmodel);
-
- for (i = n_toolbars - 1; i >= 0; i--)
- {
- const char *t_name;
-
- t_name = egg_toolbars_model_toolbar_nth (eggmodel, i);
- g_return_if_fail (t_name != NULL);
-
- if (strcmp (t_name, "BookmarksBar") != 0)
- {
- egg_toolbars_model_remove_toolbar (eggmodel, i);
- }
- }
- }
-
- LOG ("Migration was %ssuccessful", success ? "" : "un");
- }
-
- /* Load default set */
- if (success == FALSE)
- {
- egg_toolbars_model_load
- (eggmodel, ephy_file ("epiphany-bookmarksbar.xml"));
- LOG ("Loading the default toolbars was %ssuccessful", success ? "" : "un");
- }
-
- /* Ensure that we have a BookmarksBar */
- if (get_toolbar_pos (model, "BookmarksBar") == -1)
- {
- egg_toolbars_model_add_toolbar
- (eggmodel, -1, "BookmarksBar");
- }
-}
-
-static void
-ephy_bookmarksbar_model_init (EphyBookmarksBarModel *model)
-{
- model->priv = EPHY_BOOKMARKSBAR_MODEL_GET_PRIVATE (model);
-
- LOG ("EphyBookmarksBarModel initialising");
-
- model->priv->xml_file = g_build_filename (ephy_dot_dir (),
- EPHY_BOOKMARKSBARS_XML_FILE,
- NULL);
-
- g_signal_connect_after (model, "item_added",
- G_CALLBACK (item_added_cb), NULL);
- g_signal_connect_after (model, "item_removed",
- G_CALLBACK (save_changes), NULL);
- g_signal_connect_after (model, "toolbar_added",
- G_CALLBACK (update_flags_and_save_changes), NULL);
- g_signal_connect_after (model, "toolbar_removed",
- G_CALLBACK (update_flags_and_save_changes), NULL);
-}
-
-static void
-ephy_bookmarksbar_model_dispose (GObject *object)
-{
- EphyBookmarksBarModel *model = EPHY_BOOKMARKSBAR_MODEL (object);
-
- LOG ("EphyBookmarksBarModel disposing");
-
- if (model->priv->timeout != 0)
- {
- g_source_remove (model->priv->timeout);
- model->priv->timeout = 0;
- }
-
- save_changes_idle (model);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-ephy_bookmarksbar_model_finalize (GObject *object)
-{
- EphyBookmarksBarModel *model = EPHY_BOOKMARKSBAR_MODEL (object);
-
- g_free (model->priv->xml_file);
-
- LOG ("EphyBookmarksBarModel finalised");
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-ephy_bookmarksbar_model_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EphyBookmarksBarModel *model = EPHY_BOOKMARKSBAR_MODEL (object);
-
- switch (prop_id)
- {
- case PROP_BOOKMARKS:
- /* we're owned by bookmarks, so don't g_object_ref() here */
- model->priv->bookmarks = g_value_get_object (value);
- load_toolbars (model);
- break;
- }
-}
-
-static void
-ephy_bookmarksbar_model_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- /* no readable properties */
- g_assert_not_reached ();
-}
-
-static void
-ephy_bookmarksbar_model_class_init (EphyBookmarksBarModelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- EggToolbarsModelClass *eggclass = EGG_TOOLBARS_MODEL_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- object_class->dispose = ephy_bookmarksbar_model_dispose;
- object_class->finalize = ephy_bookmarksbar_model_finalize;
- object_class->set_property = ephy_bookmarksbar_model_set_property;
- object_class->get_property = ephy_bookmarksbar_model_get_property;
-
- eggclass->get_item_type = impl_get_item_type;
- eggclass->get_item_id = impl_get_item_id;
- eggclass->get_item_data = impl_get_item_data;
-
- g_object_class_install_property (object_class,
- PROP_BOOKMARKS,
- g_param_spec_object ("bookmarks",
- "Bookmarks",
- "Bookmarks",
- EPHY_TYPE_BOOKMARKS,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_type_class_add_private (object_class, sizeof (EphyBookmarksBarModelPrivate));
-}
-
-EggToolbarsModel *
-ephy_bookmarksbar_model_new (EphyBookmarks *bookmarks)
-{
- return EGG_TOOLBARS_MODEL (g_object_new (EPHY_TYPE_BOOKMARKSBAR_MODEL,
- "bookmarks", bookmarks,
- NULL));
-}
diff --git a/src/bookmarks/ephy-bookmarksbar-model.h b/src/bookmarks/ephy-bookmarksbar-model.h
deleted file mode 100755
index 1849e20c9..000000000
--- a/src/bookmarks/ephy-bookmarksbar-model.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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
- * 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.
- *
- * $Id$
- */
-
-#ifndef EPHY_BOOKMARKSBAR_MODEL_H
-#define EPHY_BOOKMARKSBAR_MODEL_H
-
-#include "egg-toolbars-model.h"
-#include "ephy-bookmarks.h"
-
-G_BEGIN_DECLS
-
-#define EPHY_TYPE_BOOKMARKSBAR_MODEL (ephy_bookmarksbar_model_get_type ())
-#define EPHY_BOOKMARKSBAR_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_BOOKMARKSBAR_MODEL, EphyBookmarksBarModel))
-#define EPHY_BOOKMARKSBAR_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_BOOKMARKSBAR_MODEL, EphyBookmarksBarModelClass))
-#define EPHY_IS_BOOKMARKSBAR_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_BOOKMARKSBAR_MODEL))
-#define EPHY_IS_BOOKMARKSBAR_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_BOOKMARKSBAR_MODEL))
-#define EPHY_BOOKMARKSBAR_MODEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_BOOKMARKSBAR_MODEL, EphyBookmarksBarModelClass))
-
-typedef struct _EphyBookmarksBarModelClass EphyBookmarksBarModelClass;
-typedef struct _EphyBookmarksBarModel EphyBookmarksBarModel;
-typedef struct _EphyBookmarksBarModelPrivate EphyBookmarksBarModelPrivate;
-
-struct _EphyBookmarksBarModel
-{
- EggToolbarsModel parent_object;
-
- /*< private >*/
- EphyBookmarksBarModelPrivate *priv;
-};
-
-struct _EphyBookmarksBarModelClass
-{
- EggToolbarsModelClass parent_class;
-};
-
-GType ephy_bookmarksbar_model_get_type (void);
-
-EggToolbarsModel *ephy_bookmarksbar_model_new (EphyBookmarks *bookmarks);
-
-char *ephy_bookmarksbar_model_get_action_name (EphyBookmarksBarModel *model,
- long id);
-
-EphyNode *ephy_bookmarksbar_model_get_node (EphyBookmarksBarModel *model,
- const char *action_name);
-
-void ephy_bookmarksbar_model_add_bookmark (EphyBookmarksBarModel *model,
- gboolean topic,
- long id);
-
-void ephy_bookmarksbar_model_remove_bookmark (EphyBookmarksBarModel *model,
- long id);
-
-gboolean ephy_bookmarksbar_model_has_bookmark (EphyBookmarksBarModel *model,
- long id);
-
-G_END_DECLS
-
-#endif
diff --git a/src/bookmarks/ephy-bookmarksbar.c b/src/bookmarks/ephy-bookmarksbar.c
deleted file mode 100644
index d34dcf86c..000000000
--- a/src/bookmarks/ephy-bookmarksbar.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jorn Baayen
- * 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
- * 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.
- *
- * $Id$
- */
-
-#include "config.h"
-
-#include "ephy-bookmarksbar.h"
-#include "ephy-bookmarksbar-model.h"
-#include "ephy-bookmarks.h"
-#include "ephy-shell.h"
-#include "ephy-topic-action.h"
-#include "ephy-link.h"
-#include "ephy-bookmark-action.h"
-#include "ephy-new-bookmark.h"
-#include "ephy-stock-icons.h"
-#include "ephy-dnd.h"
-#include "ephy-debug.h"
-
-#include <gtk/gtkuimanager.h>
-#include <gtk/gtktoolbar.h>
-#include <glib/gi18n.h>
-#include <string.h>
-
-static GtkTargetEntry drag_targets[] =
-{
- { EPHY_DND_TOPIC_TYPE, 0, 0 },
- { EPHY_DND_URL_TYPE, 0, 1 }
-};
-static int n_drag_targets = G_N_ELEMENTS (drag_targets);
-
-enum
-{
- PROP_0,
- PROP_BOOKMARKS,
- PROP_WINDOW
-};
-
-static GObjectClass *parent_class = NULL;
-
-#define EPHY_BOOKMARKSBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_BOOKMARKSBAR, EphyBookmarksBarPrivate))
-
-struct _EphyBookmarksBarPrivate
-{
- EphyWindow *window;
- GtkActionGroup *action_group;
- EphyBookmarks *bookmarks;
- EggToolbarsModel *toolbars_model;
-};
-
-static void ephy_bookmarksbar_class_init (EphyBookmarksBarClass *klass);
-static void ephy_bookmarksbar_init (EphyBookmarksBar *toolbar);
-
-GType
-ephy_bookmarksbar_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyBookmarksBarClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) ephy_bookmarksbar_class_init,
- NULL,
- NULL, /* class_data */
- sizeof (EphyBookmarksBar),
- 0, /* n_preallocs */
- (GInstanceInitFunc) ephy_bookmarksbar_init
- };
-
- static const GInterfaceInfo link_info =
- {
- NULL,
- NULL,
- NULL
- };
-
- type = g_type_register_static (EGG_TYPE_EDITABLE_TOOLBAR,
- "EphyBookmarksBar",
- &our_info, 0);
- g_type_add_interface_static (type,
- EPHY_TYPE_LINK,
- &link_info);
- }
-
- return type;
-}
-
-static gboolean
-remove_action_from_model (EggToolbarsModel *model, const char *name)
-{
- int n_toolbars, n_items, t, i;
-
- n_toolbars = egg_toolbars_model_n_toolbars (model);
-
- for (t = 0; t < n_toolbars; t++)
- {
- n_items = egg_toolbars_model_n_items (model, t);
-
- for (i = 0; i < n_items; i++)
- {
- const char *i_name;
- gboolean is_separator;
-
- egg_toolbars_model_item_nth (model, t , i, &is_separator,
- &i_name, NULL);
- g_return_val_if_fail (i_name != NULL, FALSE);
-
- if (strcmp (i_name, name) == 0)
- {
- egg_toolbars_model_remove_item (model, t, i);
-
- if (!remove_action_from_model (model, name))
- {
- return FALSE;
- }
- }
- }
- }
-
- return FALSE;
-}
-
-static void
-bookmark_destroy_cb (EphyNode *node,
- EphyBookmarksBar *toolbar)
-{
- EggToolbarsModel *model;
- GtkAction *action;
- char *name;
- long id;
-
-
- model = toolbar->priv->toolbars_model;
- id = ephy_node_get_id (node);
- name = ephy_bookmarksbar_model_get_action_name
- (EPHY_BOOKMARKSBAR_MODEL (model), id);
- remove_action_from_model (model, name);
-
- model = EGG_TOOLBARS_MODEL (ephy_shell_get_toolbars_model
- (ephy_shell, FALSE));
- remove_action_from_model (model, name);
-
- action = gtk_action_group_get_action (toolbar->priv->action_group, name);
- if (action)
- {
- gtk_action_group_remove_action (toolbar->priv->action_group, action);
- }
-
- g_free (name);
-}
-
-static void
-ephy_bookmarksbar_action_request (EggEditableToolbar *eggtoolbar,
- const char *name)
-{
- EphyBookmarksBar *toolbar = EPHY_BOOKMARKSBAR (eggtoolbar);
- GtkAction *action = NULL;
- EphyNode *bmks, *topics;
-
- bmks = ephy_bookmarks_get_bookmarks (toolbar->priv->bookmarks);
- topics = ephy_bookmarks_get_keywords (toolbar->priv->bookmarks);
-
- LOG ("Action request for action '%s'", name);
-
- if (g_str_has_prefix (name, "GoBookmark-"))
- {
- EphyNode *node;
-
- node = ephy_bookmarksbar_model_get_node
- (EPHY_BOOKMARKSBAR_MODEL (toolbar->priv->toolbars_model),
- name);
- g_return_if_fail (node != NULL);
-
- if (ephy_node_has_child (topics, node))
- {
- action = ephy_topic_action_new (name, node);
- }
- else if (ephy_node_has_child (bmks, node))
- {
- action = ephy_bookmark_action_new (name, node);
- }
-
- g_return_if_fail (action != NULL);
-
- g_signal_connect_swapped (action, "open-link",
- G_CALLBACK (ephy_link_open), toolbar);
-
- gtk_action_group_add_action (toolbar->priv->action_group, action);
- g_object_unref (action);
-
- ephy_node_signal_connect_object (node,
- EPHY_NODE_DESTROY,
- (EphyNodeCallback) bookmark_destroy_cb,
- G_OBJECT (toolbar));
- }
-
- if (EGG_EDITABLE_TOOLBAR_CLASS (parent_class)->action_request)
- {
- EGG_EDITABLE_TOOLBAR_CLASS (parent_class)->action_request (eggtoolbar, name);
- }
-}
-
-static void
-toolbar_added_cb (EggToolbarsModel *model,
- int position,
- EggEditableToolbar *toolbar)
-{
- const char *t_name;
-
- t_name = egg_toolbars_model_toolbar_nth (model, position);
- g_return_if_fail (t_name != NULL);
-
- egg_editable_toolbar_set_drag_dest
- (toolbar, drag_targets, n_drag_targets, t_name);
-}
-
-static void
-ephy_bookmarksbar_set_window (EphyBookmarksBar *toolbar,
- EphyWindow *window)
-{
- EggEditableToolbar *eggtoolbar = EGG_EDITABLE_TOOLBAR (toolbar);
- EggToolbarsModel *model = toolbar->priv->toolbars_model;
- GtkUIManager *manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
- int i, n_toolbars;
-
- g_return_if_fail (toolbar->priv->window == NULL);
- g_return_if_fail (model != NULL);
-
- toolbar->priv->window = window;
-
- toolbar->priv->action_group =
- gtk_action_group_new ("BookmarksToolbarActions");
-
- gtk_ui_manager_insert_action_group (manager,
- toolbar->priv->action_group, -1);
-
- g_object_set (G_OBJECT (toolbar),
- "ui-manager", manager,
- "model", model,
- NULL);
-
- g_signal_connect_after (model, "toolbar_added",
- G_CALLBACK (toolbar_added_cb), toolbar);
-
- /* now that the toolbar has been constructed, set drag dests */
- n_toolbars = egg_toolbars_model_n_toolbars (model);
- for (i = 0; i < n_toolbars; i++)
- {
- const char *t_name;
-
- t_name = egg_toolbars_model_toolbar_nth (model, i);
- g_return_if_fail (t_name != NULL);
-
- egg_editable_toolbar_set_drag_dest
- (eggtoolbar, drag_targets, n_drag_targets, t_name);
- }
-}
-
-static void
-ephy_bookmarksbar_init (EphyBookmarksBar *toolbar)
-{
- toolbar->priv = EPHY_BOOKMARKSBAR_GET_PRIVATE (toolbar);
-}
-
-static void
-ephy_bookmarksbar_finalize (GObject *object)
-{
- EphyBookmarksBar *toolbar = EPHY_BOOKMARKSBAR (object);
-
- g_object_unref (toolbar->priv->action_group);
-
- g_signal_handlers_disconnect_by_func
- (toolbar->priv->toolbars_model,
- G_CALLBACK (toolbar_added_cb),
- toolbar);
-
- LOG ("EphyBookmarksBar %p finalised", object);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-ephy_bookmarksbar_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EphyBookmarksBar *toolbar = EPHY_BOOKMARKSBAR (object);
-
- switch (prop_id)
- {
- case PROP_BOOKMARKS:
- toolbar->priv->bookmarks = g_value_get_object (value);
- toolbar->priv->toolbars_model =
- EGG_TOOLBARS_MODEL (ephy_bookmarks_get_toolbars_model (toolbar->priv->bookmarks));
- break;
- case PROP_WINDOW:
- ephy_bookmarksbar_set_window (toolbar, g_value_get_object (value));
- break;
- }
-}
-
-static void
-ephy_bookmarksbar_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- /* no readable properties */
- g_assert_not_reached ();
-}
-
-static void
-ephy_bookmarksbar_class_init (EphyBookmarksBarClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- EggEditableToolbarClass *eet_class = EGG_EDITABLE_TOOLBAR_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- object_class->finalize = ephy_bookmarksbar_finalize;
- object_class->set_property = ephy_bookmarksbar_set_property;
- object_class->get_property = ephy_bookmarksbar_get_property;
-
- eet_class->action_request = ephy_bookmarksbar_action_request;
-
- g_object_class_install_property (object_class,
- PROP_WINDOW,
- g_param_spec_object ("window",
- "Window",
- "Parent window",
- EPHY_TYPE_WINDOW,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_BOOKMARKS,
- g_param_spec_object ("bookmarks",
- "Bookmarks",
- "Bookmarks Model",
- EPHY_TYPE_BOOKMARKS,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_type_class_add_private (object_class, sizeof(EphyBookmarksBarPrivate));
-}
-
-GtkWidget *
-ephy_bookmarksbar_new (EphyWindow *window)
-{
- EphyBookmarks *bookmarks;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
-
- return GTK_WIDGET (g_object_new (EPHY_TYPE_BOOKMARKSBAR,
- "bookmarks", bookmarks,
- "window", window,
- NULL));
-}
diff --git a/src/bookmarks/ephy-bookmarksbar.h b/src/bookmarks/ephy-bookmarksbar.h
deleted file mode 100644
index b715f8ecb..000000000
--- a/src/bookmarks/ephy-bookmarksbar.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2002 Jorn Baayen
- * 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
- * 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.
- *
- * $Id$
- */
-
-#ifndef EPHY_BOOKMARKSBAR_H
-#define EPHY_BOOKMARKSBAR_H
-
-#include "egg-editable-toolbar.h"
-#include "ephy-window.h"
-
-#include <glib-object.h>
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-#define EPHY_TYPE_BOOKMARKSBAR (ephy_bookmarksbar_get_type ())
-#define EPHY_BOOKMARKSBAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_BOOKMARKSBAR, EphyBookmarksBar))
-#define EPHY_BOOKMARKSBAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_BOOKMARKSBAR, EphyBookmarksBarClass))
-#define EPHY_IS_BOOKMARKSBAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_BOOKMARKSBAR))
-#define EPHY_IS_BOOKMARKSBAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_BOOKMARKSBAR))
-#define EPHY_BOOKMARKSBAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_BOOKMARKSBAR, EphyBookmarksBarClass))
-
-typedef struct _EphyBookmarksBar EphyBookmarksBar;
-typedef struct _EphyBookmarksBarClass EphyBookmarksBarClass;
-typedef struct _EphyBookmarksBarPrivate EphyBookmarksBarPrivate;
-
-struct _EphyBookmarksBar
-{
- EggEditableToolbar parent_object;
-
- /*< private >*/
- EphyBookmarksBarPrivate *priv;
-};
-
-struct _EphyBookmarksBarClass
-{
- EggEditableToolbarClass parent_class;
-};
-
-GType ephy_bookmarksbar_get_type (void);
-
-GtkWidget *ephy_bookmarksbar_new (EphyWindow *window);
-
-G_END_DECLS
-
-#endif
diff --git a/src/bookmarks/ephy-favorites-menu.c b/src/bookmarks/ephy-favorites-menu.c
deleted file mode 100644
index d6f93d6c8..000000000
--- a/src/bookmarks/ephy-favorites-menu.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- * 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
- * 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.
- *
- * $Id$
- */
-
-#include "config.h"
-
-#include "ephy-favorites-menu.h"
-#include "ephy-bookmark-action.h"
-#include "ephy-link.h"
-#include "ephy-shell.h"
-#include "ephy-debug.h"
-
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkuimanager.h>
-#include <glib/gprintf.h>
-
-#define LABEL_WIDTH_CHARS 32
-
-#define EPHY_FAVORITES_MENU_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_FAVORITES_MENU, EphyFavoritesMenuPrivate))
-
-struct _EphyFavoritesMenuPrivate
-{
- EphyWindow *window;
- EphyBookmarks *bookmarks;
- GtkActionGroup *action_group;
- guint ui_id;
- guint update_tag;
-};
-
-static void ephy_favorites_menu_class_init (EphyFavoritesMenuClass *klass);
-static void ephy_favorites_menu_init (EphyFavoritesMenu *menu);
-static void ephy_favorites_menu_finalize (GObject *o);
-
-enum
-{
- PROP_0,
- PROP_WINDOW
-};
-
-static gpointer parent_class;
-
-GType
-ephy_favorites_menu_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyFavoritesMenuClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) ephy_favorites_menu_class_init,
- NULL,
- NULL, /* class_data */
- sizeof (EphyFavoritesMenu),
- 0, /* n_preallocs */
- (GInstanceInitFunc) ephy_favorites_menu_init
- };
- static const GInterfaceInfo link_info =
- {
- NULL,
- NULL,
- NULL
- };
-
- type = g_type_register_static (G_TYPE_OBJECT,
- "EphyFavoritesMenu",
- &our_info, 0);
- g_type_add_interface_static (type,
- EPHY_TYPE_LINK,
- &link_info);
- }
-
- return type;
-}
-
-static void
-ephy_favorites_menu_clean (EphyFavoritesMenu *menu)
-{
- EphyFavoritesMenuPrivate *p = menu->priv;
- GtkUIManager *merge = GTK_UI_MANAGER (ephy_window_get_ui_manager (p->window));
-
- if (p->ui_id > 0)
- {
- gtk_ui_manager_remove_ui (merge, p->ui_id);
- gtk_ui_manager_ensure_update (merge);
- p->ui_id = 0;
- }
-
- if (p->action_group != NULL)
- {
- gtk_ui_manager_remove_action_group (merge, p->action_group);
- g_object_unref (p->action_group);
- }
-}
-
-static void
-connect_proxy_cb (GtkActionGroup *action_group,
- GtkAction *action,
- GtkWidget *proxy)
-{
- if (GTK_IS_MENU_ITEM (proxy))
- {
- GtkLabel *label;
-
- label = (GtkLabel *) ((GtkBin *) proxy)->child;
- gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
- gtk_label_set_max_width_chars (label, LABEL_WIDTH_CHARS);
- }
-}
-
-static void
-ephy_favorites_menu_rebuild (EphyFavoritesMenu *menu)
-{
- EphyFavoritesMenuPrivate *p = menu->priv;
- gint i;
- EphyNode *fav;
- GPtrArray *children;
- GtkUIManager *merge = GTK_UI_MANAGER (ephy_window_get_ui_manager (p->window));
-
- LOG ("Rebuilding favorites menu");
-
- START_PROFILER ("Rebuild favorites menu")
-
- ephy_favorites_menu_clean (menu);
-
- fav = ephy_bookmarks_get_favorites (p->bookmarks);
- children = ephy_node_get_children (fav);
-
- p->action_group = gtk_action_group_new ("FavoritesActions");
- gtk_ui_manager_insert_action_group (merge, p->action_group, -1);
- g_signal_connect (p->action_group, "connect-proxy",
- G_CALLBACK (connect_proxy_cb), NULL);
-
- p->ui_id = gtk_ui_manager_new_merge_id (merge);
-
- for (i = 0; i < children->len; i++)
- {
- char verb[20];
- char name[20];
- char accel_path[48];
- EphyNode *node;
- GtkAction *action;
-
- g_snprintf (verb, sizeof (verb),"GoFav%d", i);
- g_snprintf (name, sizeof (name), "GoFav%dMenu", i);
- g_snprintf (accel_path, sizeof (accel_path),
- "<Actions>/FavoritesActions/%s", verb);
-
- node = g_ptr_array_index (children, i);
-
- action = ephy_bookmark_action_new (verb, node);
- gtk_action_set_accel_path (action, accel_path);
- gtk_action_group_add_action (p->action_group, action);
- g_object_unref (action);
- g_signal_connect_swapped (action, "open-link",
- G_CALLBACK (ephy_link_open), menu);
-
- gtk_ui_manager_add_ui (merge, p->ui_id,
- "/menubar/GoMenu",
- name, verb,
- GTK_UI_MANAGER_MENUITEM, FALSE);
- }
-
- STOP_PROFILER ("Rebuild favorites menu")
-}
-
-static void
-ephy_favorites_menu_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EphyFavoritesMenu *menu = EPHY_FAVORITES_MENU (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- menu->priv->window = g_value_get_object (value);
- ephy_favorites_menu_rebuild (menu);
- break;
- }
-}
-
-static void
-ephy_favorites_menu_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EphyFavoritesMenu *menu = EPHY_FAVORITES_MENU (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- g_value_set_object (value, menu->priv->window);
- break;
- }
-}
-
-
-static void
-ephy_favorites_menu_class_init (EphyFavoritesMenuClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- object_class->finalize = ephy_favorites_menu_finalize;
- object_class->set_property = ephy_favorites_menu_set_property;
- object_class->get_property = ephy_favorites_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(EphyFavoritesMenuPrivate));
-}
-
-static gboolean
-do_updates (EphyFavoritesMenu *menu)
-{
- ephy_favorites_menu_rebuild (menu);
-
- menu->priv->update_tag = 0;
-
- /* don't run again */
- return FALSE;
-}
-
-static void
-fav_removed_cb (EphyNode *node,
- EphyNode *child,
- guint old_index,
- EphyFavoritesMenu *menu)
-{
- if (menu->priv->update_tag == 0)
- {
- menu->priv->update_tag = g_idle_add((GSourceFunc)do_updates, menu);
- }
-}
-
-static void
-fav_added_cb (EphyNode *node,
- EphyNode *child,
- EphyFavoritesMenu *menu)
-{
- if (menu->priv->update_tag == 0)
- {
- menu->priv->update_tag = g_idle_add((GSourceFunc)do_updates, menu);
- }
-}
-
-static void
-ephy_favorites_menu_init (EphyFavoritesMenu *menu)
-{
- EphyFavoritesMenuPrivate *p = EPHY_FAVORITES_MENU_GET_PRIVATE (menu);
- EphyNode *fav;
- menu->priv = p;
-
- menu->priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell);
-
- fav = ephy_bookmarks_get_favorites (menu->priv->bookmarks);
- ephy_node_signal_connect_object (fav,
- EPHY_NODE_CHILD_REMOVED,
- (EphyNodeCallback) fav_removed_cb,
- G_OBJECT (menu));
- ephy_node_signal_connect_object (fav,
- EPHY_NODE_CHILD_ADDED,
- (EphyNodeCallback) fav_added_cb,
- G_OBJECT (menu));
-}
-
-static void
-ephy_favorites_menu_finalize (GObject *o)
-{
- EphyFavoritesMenu *menu = EPHY_FAVORITES_MENU (o);
-
- if (menu->priv->action_group != NULL)
- {
- g_object_unref (menu->priv->action_group);
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (o);
-}
-
-EphyFavoritesMenu *
-ephy_favorites_menu_new (EphyWindow *window)
-{
- return g_object_new (EPHY_TYPE_FAVORITES_MENU,
- "window", window,
- NULL);
-}
diff --git a/src/bookmarks/ephy-favorites-menu.h b/src/bookmarks/ephy-favorites-menu.h
deleted file mode 100644
index c399218b9..000000000
--- a/src/bookmarks/ephy-favorites-menu.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- * Copyright (C) 2003 Marco Pesenti Gritti
- *
- * 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.
- *
- * $Id$
- */
-
-#ifndef EPHY_FAVORITES_MENU_H
-#define EPHY_FAVORITES_MENU_H
-
-#include "ephy-window.h"
-
-G_BEGIN_DECLS
-
-#define EPHY_TYPE_FAVORITES_MENU (ephy_favorites_menu_get_type())
-#define EPHY_FAVORITES_MENU(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_FAVORITES_MENU, EphyFavoritesMenu))
-#define EPHY_FAVORITES_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_FAVORITES_MENU, EphyFavoritesMenuClass))
-#define EPHY_IS_FAVORITES_MENU(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_FAVORITES_MENU))
-#define EPHY_IS_FAVORITES_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_FAVORITES_MENU))
-#define EPHY_FAVORITES_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_FAVORITES_MENU, EphyFavoritesMenuClass))
-
-typedef struct _EphyFavoritesMenu EphyFavoritesMenu;
-typedef struct _EphyFavoritesMenuClass EphyFavoritesMenuClass;
-typedef struct _EphyFavoritesMenuPrivate EphyFavoritesMenuPrivate;
-
-struct _EphyFavoritesMenuClass
-{
- GObjectClass parent_class;
-};
-
-struct _EphyFavoritesMenu
-{
- GObject parent_object;
-
- /*< private >*/
- EphyFavoritesMenuPrivate *priv;
-};
-
-GType ephy_favorites_menu_get_type (void);
-
-EphyFavoritesMenu *ephy_favorites_menu_new (EphyWindow *window);
-
-G_END_DECLS
-
-#endif
diff --git a/src/bookmarks/ephy-new-bookmark.c b/src/bookmarks/ephy-new-bookmark.c
index 46c05b216..c1e2f2a83 100644
--- a/src/bookmarks/ephy-new-bookmark.c
+++ b/src/bookmarks/ephy-new-bookmark.c
@@ -46,9 +46,9 @@ static void ephy_new_bookmark_class_init (EphyNewBookmarkClass *klass);
static void ephy_new_bookmark_init (EphyNewBookmark *editor);
static void ephy_new_bookmark_finalize (GObject *object);
static void ephy_new_bookmark_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
static void ephy_new_bookmark_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -164,7 +164,7 @@ ephy_new_bookmark_add (EphyNewBookmark *new_bookmark)
title = gtk_editable_get_chars
(GTK_EDITABLE (new_bookmark->priv->title_entry), 0, -1);
node = ephy_bookmarks_add (new_bookmark->priv->bookmarks, title,
- new_bookmark->priv->location);
+ new_bookmark->priv->location);
new_bookmark->priv->id = ephy_node_get_id (node);
ephy_topics_selector_apply (selector, node);
@@ -260,6 +260,17 @@ build_editing_table (EphyNewBookmark *editor)
gtk_table_attach (GTK_TABLE (table), scrolled_window, 1, 2, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+
+ label = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
+
+ label = gtk_label_new (_("Each \xE2\x80\xA2 highlights a topic to consider, derived from your current selections and existing bookmarks."));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 1, 2, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
+
return table;
}
@@ -268,7 +279,7 @@ ephy_new_bookmark_construct (EphyNewBookmark *editor)
{
ephy_state_add_window (GTK_WIDGET(editor),
"new_bookmark",
- 280, 240, FALSE,
+ 280, 240, FALSE,
EPHY_STATE_WINDOW_SAVE_SIZE);
gtk_window_set_title (GTK_WINDOW (editor),
@@ -414,9 +425,9 @@ ephy_new_bookmark_new (EphyBookmarks *bookmarks,
static void
ephy_new_bookmark_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
EphyNewBookmark *editor = EPHY_NEW_BOOKMARK (object);
@@ -437,9 +448,9 @@ ephy_new_bookmark_set_property (GObject *object,
static void
ephy_new_bookmark_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
EphyNewBookmark *editor = EPHY_NEW_BOOKMARK (object);
diff --git a/src/bookmarks/ephy-nodes-cover.c b/src/bookmarks/ephy-nodes-cover.c
new file mode 100644
index 000000000..dfe461ee3
--- /dev/null
+++ b/src/bookmarks/ephy-nodes-cover.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2004 Peter Harvey <pah06@uow.edu.au>
+ *
+ * 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 of the License, 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 "config.h"
+
+#include "ephy-nodes-cover.h"
+
+/* Count the number of node entries which are children of parent. */
+gint
+ephy_nodes_count_covered (EphyNode *parent, const GPtrArray *children)
+{
+ guint i, len = 0;
+ EphyNode *child;
+
+ for(i = 0; i < children->len; i++)
+ {
+ child = g_ptr_array_index (children, i);
+ if (ephy_node_has_child (parent, child))
+ {
+ len++;
+ }
+ }
+ return len;
+}
+
+/* Removes from the array of children those which are children of the given parent. */
+gint
+ephy_nodes_remove_covered (EphyNode *parent, GPtrArray *children)
+{
+ guint i, len = children->len;
+ EphyNode *child;
+
+ for(i = 0; i < children->len; i++)
+ {
+ child = g_ptr_array_index (children, i);
+ if (ephy_node_has_child (parent, child))
+ {
+ g_ptr_array_remove_index_fast (children, i);
+ i--;
+ }
+ }
+ return len - children->len;
+}
+
+/* Removes from the array of children those which are children of the given parent. */
+gint
+ephy_nodes_remove_not_covered (EphyNode *parent, GPtrArray *children)
+{
+ guint i, len = children->len;
+ EphyNode *child;
+
+ for(i = 0; i < children->len; i++)
+ {
+ child = g_ptr_array_index (children, i);
+ if (!ephy_node_has_child (parent, child))
+ {
+ g_ptr_array_remove_index_fast (children, i);
+ i--;
+ }
+ }
+ return len - children->len;
+}
+
+/* Returns the subset of children which are childs of the given parent.
+ * Stores the result in the given _covered array if non-null. */
+GPtrArray *
+ephy_nodes_get_covered (EphyNode *parent, const GPtrArray *children, GPtrArray *_covered)
+{
+ GPtrArray *covered = _covered?_covered:g_ptr_array_sized_new (children->len);
+ EphyNode *child;
+ guint i;
+
+ covered->len = 0;
+ for (i = 0; i < children->len; i++)
+ {
+ child = g_ptr_array_index (children, i);
+ if (ephy_node_has_child (parent, child))
+ {
+ g_ptr_array_add (covered, child);
+ }
+ }
+
+ return covered;
+}
+
+/* Returns true if the parent covers all the children. */
+gboolean
+ephy_nodes_covered (EphyNode *parent, const GPtrArray *children)
+{
+ EphyNode *child;
+ guint i;
+
+ for (i = 0; i < children->len; i++)
+ {
+ child = g_ptr_array_index (children, i);
+ if (!ephy_node_has_child (parent, child))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Returns the subset of parents which provide a covering of children.
+ * Arguments other than parents and children arguments are only used if non-null.
+ * Uses the _covering array to store the subset of parents.
+ * Uses the _uncovered array to store those children which couldn't be covered.
+ * Uses the _sizes array to store the number of children covered by each parent. */
+GPtrArray *
+ephy_nodes_get_covering (const GPtrArray *parents, const GPtrArray *children,
+ GPtrArray *_covering, GPtrArray *_uncovered, GArray *_sizes)
+{
+ GPtrArray *uncovered = _uncovered?_uncovered:g_ptr_array_sized_new (children->len);
+ GPtrArray *covering = _covering?_covering:g_ptr_array_sized_new (parents->len);
+ GArray *sizes = _sizes;
+
+ /* Create arrays to store the number of children each parent has which
+ * are currently not covered, and the number of children it has total. */
+ int *count_u = g_malloc (sizeof(int) * parents->len);
+ int *count_c = g_malloc (sizeof(int) * parents->len);
+
+ EphyNode *parent;
+ guint i, p;
+
+ /* Empty all the returning arrays. */
+ uncovered->len = 0;
+ covering->len = 0;
+ if (sizes) sizes->len = 0;
+
+ /* Initialise the array of uncovered bookmarks. */
+ for (i = 0; i < children->len; i++)
+ {
+ g_ptr_array_add (uncovered, g_ptr_array_index (children, i));
+ }
+
+ /* Initialise the count_u and count_c arrays.
+ * NB: count_u[0] is set to 0 if the parent node
+ covers the entire set of children. */
+ for (i = 0, p = 0; i < parents->len; i++)
+ {
+ parent = g_ptr_array_index (parents, i);
+ count_c[i] = ephy_nodes_count_covered (parent, children);
+ count_u[i] = (count_c[i]<children->len) ? count_c[i] : 0;
+ if (count_u[i] > count_u[p]) p = i;
+ }
+
+ /* While there are more suitable topics... */
+ while (count_u[p])
+ {
+ /* Update the arrays of uncovered bookmarks and covering topics. */
+ parent = g_ptr_array_index (parents, p);
+ ephy_nodes_remove_covered (parent, uncovered);
+ g_ptr_array_add (covering, parent);
+ if (sizes) g_array_append_val (sizes, count_c[p]);
+
+ /* Find the next most suitable topic. */
+ count_u[p] = 0;
+ for (i = 0; i < parents->len; i++)
+ {
+ /* Lazy update the count_u[i] array. */
+ if (count_u[i] > count_u[p] || (count_u[i] == count_u[p] && count_c[i] < count_c[p]))
+ {
+ parent = g_ptr_array_index (parents, i);
+ count_u[i] = ephy_nodes_count_covered (parent, uncovered);
+ }
+
+ if (count_u[i] > count_u[p] || (count_u[i] == count_u[p] && count_c[i] < count_c[p]))
+ {
+ p = i;
+ }
+ }
+ }
+
+ if (_uncovered != uncovered) g_ptr_array_free (uncovered, TRUE);
+ g_free (count_u);
+ g_free (count_c);
+
+ return covering;
+}
diff --git a/src/bookmarks/ephy-nodes-cover.h b/src/bookmarks/ephy-nodes-cover.h
new file mode 100644
index 000000000..10d9a4edd
--- /dev/null
+++ b/src/bookmarks/ephy-nodes-cover.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004 Peter Harvey <pah06@uow.edu.au>
+ *
+ * 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.
+ */
+
+#ifndef EPHY_NODES_COVER_H
+#define EPHY_NODES_COVER_H
+
+#include "ephy-bookmarks.h"
+
+G_BEGIN_DECLS
+
+gint ephy_nodes_remove_covered (EphyNode *parent, GPtrArray *children);
+
+gint ephy_nodes_remove_not_covered (EphyNode *parent, GPtrArray *children);
+
+gint ephy_nodes_count_covered (EphyNode *parent, const GPtrArray *children);
+
+gboolean ephy_nodes_covered (EphyNode *parent, const GPtrArray *children);
+
+GPtrArray * ephy_nodes_get_covered (EphyNode *parent, const GPtrArray *children, GPtrArray *_covered);
+
+GPtrArray * ephy_nodes_get_covering (const GPtrArray *parents, const GPtrArray *children,
+ GPtrArray *_covering, GPtrArray *_uncovered, GArray *_sizes);
+
+G_END_DECLS
+
+#endif /* EPHY_NODES_COVER_H */
diff --git a/src/bookmarks/ephy-open-tabs-action.c b/src/bookmarks/ephy-open-tabs-action.c
new file mode 100644
index 000000000..482ec84d1
--- /dev/null
+++ b/src/bookmarks/ephy-open-tabs-action.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2004 Peter Harvey <pah06@uow.edu.au>
+ *
+ * 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 of the License, 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtktoolitem.h>
+#include <glib/gi18n.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <string.h>
+
+#include "ephy-open-tabs-action.h"
+#include "ephy-bookmarks.h"
+#include "ephy-node-common.h"
+#include "ephy-link-action.h"
+#include "ephy-link.h"
+
+static void
+activate_cb (GtkAction *action, gpointer dummy)
+{
+ EphyLink *link = g_object_get_data (G_OBJECT (action), "ephy-link");
+ EphyNode *node = g_object_get_data (G_OBJECT (action), "ephy-node");
+ GPtrArray *children = ephy_node_get_children (node);
+ EphyTab *tab = 0;
+
+ gint i;
+ const char *url;
+
+ for (i = 0; i < children->len; i++)
+ {
+ node = g_ptr_array_index (children, i);
+ url = ephy_node_get_property_string (node, EPHY_NODE_BMK_PROP_LOCATION);
+ tab = ephy_link_open (link, url, tab, EPHY_LINK_NEW_TAB);
+ }
+}
+
+static void
+node_added_cb (EphyNode *parent, EphyNode *child, GObject *object)
+{
+ GtkActionGroup *actions = GTK_ACTION_GROUP (object);
+ GtkAction *action;
+ char *name, *accel;
+
+ name = ephy_open_tabs_action_name (child);
+ g_return_if_fail (name);
+
+ action = gtk_action_new (name, _("Open in New _Tabs"), "Open this topic in tabs", NULL);
+
+ g_object_set_data (G_OBJECT (action), "ephy-node", child);
+ g_object_set_data (G_OBJECT (action), "ephy-link", EPHY_LINK (object));
+
+ g_signal_connect (G_OBJECT (action), "activate",
+ G_CALLBACK (activate_cb), NULL);
+
+ accel = g_strjoin ("/", "<Actions>",
+ gtk_action_group_get_name (actions),
+ name,
+ NULL);
+ gtk_action_set_accel_path (action, accel);
+ gtk_action_group_add_action (actions, action);
+ g_object_unref (action);
+ g_free (accel);
+}
+
+static void
+node_removed_cb (EphyNode *parent, EphyNode *child, guint index, GObject *object)
+{
+ char *name = ephy_open_tabs_action_name (child);
+ if (name)
+ {
+ GtkActionGroup *actions = GTK_ACTION_GROUP (object);
+ GtkAction *action = gtk_action_group_get_action (actions, name);
+ if (action) gtk_action_group_remove_action (actions, action);
+ g_free (name);
+ }
+}
+
+GtkActionGroup *
+ephy_open_tabs_group_new (EphyNode *node)
+{
+ GPtrArray *children = ephy_node_get_children (node);
+ GObject *actions = G_OBJECT (ephy_link_action_group_new ("OpenTabsActions"));
+ gint i;
+
+ for (i = 0; i < children->len; i++)
+ node_added_cb (node, g_ptr_array_index (children, i), actions);
+
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ actions);
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ actions);
+
+ return GTK_ACTION_GROUP (actions);
+}
+
+char *
+ephy_open_tabs_action_name (EphyNode *node)
+{
+ return g_strdup_printf("OpenTabs%u", ephy_node_get_id (node));
+}
diff --git a/src/bookmarks/ephy-open-tabs-action.h b/src/bookmarks/ephy-open-tabs-action.h
new file mode 100644
index 000000000..8ab83c070
--- /dev/null
+++ b/src/bookmarks/ephy-open-tabs-action.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2003 Peter Harvey
+ *
+ * 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.
+ */
+
+#ifndef EPHY_OPEN_TABS_ACTION_H
+#define EPHY_OPEN_TABS_ACTION_H
+
+#include <gtk/gtkactiongroup.h>
+
+#include "ephy-node.h"
+
+char * ephy_open_tabs_action_name (EphyNode *node);
+
+GtkActionGroup * ephy_open_tabs_group_new (EphyNode *node);
+
+#endif
diff --git a/src/bookmarks/ephy-related-action.c b/src/bookmarks/ephy-related-action.c
new file mode 100644
index 000000000..00c3327b5
--- /dev/null
+++ b/src/bookmarks/ephy-related-action.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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 "config.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkaction.h>
+#include <gtk/gtkactiongroup.h>
+#include <glib/gi18n.h>
+
+#include "ephy-window.h"
+#include "ephy-bookmarks.h"
+#include "ephy-shell.h"
+#include "ephy-node-common.h"
+#include "ephy-stock-icons.h"
+#include "ephy-related-action.h"
+
+static void
+node_changed (EphyNode *node, guint propertyid, GObject *object)
+{
+ ephy_topic_action_updated (EPHY_TOPIC_ACTION (object));
+}
+
+static void
+node_destroyed (EphyNode *node, GObject *object)
+{
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+
+ ephy_topic_action_set_topic (EPHY_TOPIC_ACTION (object),
+ ephy_bookmarks_get_favorites (eb));
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHANGED,
+ (EphyNodeCallback) node_changed,
+ object);
+ ephy_node_signal_connect_object (node, EPHY_NODE_DESTROY,
+ (EphyNodeCallback) node_destroyed,
+ object);
+}
+
+static EphyTab *
+open_link (EphyLink *link,
+ const char *address,
+ EphyTab *tab,
+ EphyLinkFlags flags)
+{
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *bookmark = ephy_bookmarks_find_bookmark (eb, address);
+ EphyNode *topic, *chosen = NULL;
+
+ if (bookmark != NULL)
+ {
+ GPtrArray *topics;
+ gint i, tmp, best = 0;
+
+ topic = ephy_topic_action_get_topic (EPHY_TOPIC_ACTION (link));
+ tmp = ephy_node_get_property_int (topic, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (tmp == EPHY_NODE_NORMAL_PRIORITY &&
+ ephy_node_has_child (topic, bookmark))
+ {
+ return NULL;
+ }
+ ephy_node_signal_disconnect_object (topic, EPHY_NODE_CHANGED,
+ (EphyNodeCallback) node_changed,
+ G_OBJECT (link));
+ ephy_node_signal_disconnect_object (topic, EPHY_NODE_DESTROY,
+ (EphyNodeCallback) node_destroyed,
+ G_OBJECT (link));
+
+ topics = ephy_node_get_children (ephy_bookmarks_get_keywords (eb));
+ for (i = 0; i < topics->len; i++)
+ {
+ topic = g_ptr_array_index (topics, i);
+ tmp = ephy_node_get_property_int (topic, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (tmp == EPHY_NODE_NORMAL_PRIORITY &&
+ ephy_node_has_child (topic, bookmark))
+ {
+ tmp = ephy_node_get_n_children (topic);
+ if (chosen == NULL || (tmp >= 10 && tmp <= best))
+ {
+ chosen = topic;
+ best = tmp;
+ }
+ }
+ }
+
+ if (chosen == NULL) chosen = ephy_bookmarks_get_favorites (eb);
+
+ ephy_topic_action_set_topic (EPHY_TOPIC_ACTION (link), chosen);
+ ephy_node_signal_connect_object (chosen, EPHY_NODE_CHANGED,
+ (EphyNodeCallback) node_changed,
+ G_OBJECT (link));
+ ephy_node_signal_connect_object (chosen, EPHY_NODE_DESTROY,
+ (EphyNodeCallback) node_destroyed,
+ G_OBJECT (link));
+ }
+
+ return NULL;
+}
+
+static void
+iface_init (EphyLinkIface *iface)
+{
+ iface->open_link = open_link;
+}
+
+GType
+ephy_related_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EphyRelatedActionClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL,
+ NULL, /* class_data */
+ sizeof (EphyRelatedAction),
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ static const GInterfaceInfo link_info =
+ {
+ (GInterfaceInitFunc) iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (EPHY_TYPE_TOPIC_ACTION,
+ "EphyRelatedAction",
+ &our_info, 0);
+ g_type_add_interface_static (type,
+ EPHY_TYPE_LINK,
+ &link_info);
+ }
+
+ return type;
+}
+
+GtkAction *
+ephy_related_action_new (EphyLink *link, GtkUIManager *manager, char * name)
+{
+ EphyBookmarks *eb = ephy_shell_get_bookmarks (ephy_shell);
+ EphyNode *favorites = ephy_bookmarks_get_favorites (eb);
+
+ EphyRelatedAction *action =
+ EPHY_RELATED_ACTION (g_object_new (EPHY_TYPE_RELATED_ACTION,
+ "name", name,
+ "topic", favorites,
+ "short_label", _("Related"),
+ "stock-id", GTK_STOCK_INDEX,
+ "manager", manager,
+ NULL));
+
+ g_signal_connect_object (G_OBJECT (link), "open-link",
+ G_CALLBACK (ephy_link_open), action,
+ G_CONNECT_SWAPPED);
+
+ return GTK_ACTION (action);
+}
+
diff --git a/src/bookmarks/ephy-related-action.h b/src/bookmarks/ephy-related-action.h
new file mode 100644
index 000000000..adf9139e0
--- /dev/null
+++ b/src/bookmarks/ephy-related-action.h
@@ -0,0 +1,59 @@
+/*
+ * 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
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_RELATED_ACTION_H
+#define EPHY_RELATED_ACTION_H
+
+#include "ephy-link.h"
+#include "ephy-topic-action.h"
+
+#include <gtk/gtkactiongroup.h>
+#include <gtk/gtkuimanager.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_RELATED_ACTION (ephy_related_action_get_type ())
+#define EPHY_RELATED_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_RELATED_ACTION, EphyRelatedAction))
+#define EPHY_RELATED_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_RELATED_ACTION, EphyRelatedActionClass))
+#define EPHY_IS_RELATED_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_RELATED_ACTION))
+#define EPHY_IS_RELATED_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_RELATED_ACTION))
+#define EPHY_RELATED_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_RELATED_ACTION, EphyRelatedActionClass))
+
+typedef struct _EphyRelatedAction EphyRelatedAction;
+typedef struct _EphyRelatedActionClass EphyRelatedActionClass;
+
+struct _EphyRelatedAction
+{
+ EphyTopicAction parent_instance;
+};
+
+struct _EphyRelatedActionClass
+{
+ EphyTopicActionClass parent_class;
+};
+
+GType ephy_related_action_get_type (void);
+
+GtkAction * ephy_related_action_new (EphyLink *link, GtkUIManager *manager, char *name);
+
+G_END_DECLS
+
+#endif
diff --git a/src/bookmarks/ephy-topic-action-group.c b/src/bookmarks/ephy-topic-action-group.c
new file mode 100644
index 000000000..c7ecd7105
--- /dev/null
+++ b/src/bookmarks/ephy-topic-action-group.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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 "config.h"
+
+#include "ephy-topic-action-group.h"
+#include "ephy-topic-action.h"
+#include "ephy-node.h"
+#include "ephy-node-common.h"
+#include "ephy-bookmarks.h"
+#include "ephy-debug.h"
+
+#include <gtk/gtkaction.h>
+#include <gtk/gtkactiongroup.h>
+#include <string.h>
+
+
+static void
+node_changed_cb (EphyNode *parent,
+ EphyNode *child,
+ guint property_id,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name;
+
+ name = ephy_topic_action_name (child);
+ g_return_if_fail (name != NULL);
+ action = gtk_action_group_get_action (actions, name);
+
+ if (property_id == EPHY_NODE_KEYWORD_PROP_NAME)
+ {
+ ephy_topic_action_updated (EPHY_TOPIC_ACTION (action));
+ }
+
+ g_free (name);
+}
+
+static void
+node_added_cb (EphyNode *parent,
+ EphyNode *child,
+ GtkActionGroup *actions)
+{
+ GtkUIManager *manager;
+ GtkAction *action;
+ char *name, *accel;
+
+ manager = g_object_get_data ((GObject *)actions, "ui-manager");
+ name = ephy_topic_action_name (child);
+ action = ephy_topic_action_new (child, manager, name);
+ accel = g_strjoin ("/", "<Actions>",
+ gtk_action_group_get_name (actions),
+ name, NULL);
+ gtk_action_set_accel_path (action, accel);
+ gtk_action_group_add_action (actions, action);
+ g_object_unref (action);
+ g_free (accel);
+
+ ephy_topic_action_updated (EPHY_TOPIC_ACTION (action));
+}
+
+static void
+node_removed_cb (EphyNode *parent,
+ EphyNode *child, guint index,
+ GtkActionGroup *actions)
+{
+ GtkAction *action;
+ char *name;
+
+ name = ephy_topic_action_name (child);
+ g_return_if_fail (name != NULL);
+ action = gtk_action_group_get_action (actions, name);
+
+ if (action)
+ {
+ gtk_action_group_remove_action (actions, action);
+ }
+
+ g_free (name);
+}
+
+GtkActionGroup *
+ephy_topic_group_new (EphyNode *node,
+ GtkUIManager *manager)
+{
+ GPtrArray *children = ephy_node_get_children (node);
+ GObject *actions = (GObject *) gtk_action_group_new ("TopicActions");
+ gint i;
+
+ g_object_set_data (G_OBJECT (actions), "ui-manager", manager);
+
+ for (i = 0; i < children->len; i++)
+ {
+ node_added_cb (node, g_ptr_array_index (children, i), (GtkActionGroup *)actions);
+ }
+
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)node_added_cb,
+ actions);
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)node_removed_cb,
+ actions);
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)node_changed_cb,
+ actions);
+
+ return GTK_ACTION_GROUP (actions);
+}
diff --git a/src/bookmarks/ephy-topic-action-group.h b/src/bookmarks/ephy-topic-action-group.h
new file mode 100644
index 000000000..d1640b1c8
--- /dev/null
+++ b/src/bookmarks/ephy-topic-action-group.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005 Peter Harvey
+ *
+ * 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.
+ */
+
+#ifndef EPHY_TOPIC_ACTION_GROUP_H
+#define EPHY_TOPIC_ACTION_GROUP_H
+
+#include "ephy-link-action.h"
+#include "ephy-node.h"
+
+#include <gtk/gtkactiongroup.h>
+#include <gtk/gtkuimanager.h>
+
+G_BEGIN_DECLS
+
+GtkActionGroup * ephy_topic_group_new (EphyNode *node, GtkUIManager *manager);
+
+G_END_DECLS
+
+#endif
diff --git a/src/bookmarks/ephy-topic-action.c b/src/bookmarks/ephy-topic-action.c
index 4885d2af6..3e0607509 100644
--- a/src/bookmarks/ephy-topic-action.c
+++ b/src/bookmarks/ephy-topic-action.c
@@ -22,28 +22,27 @@
#include "config.h"
#include "ephy-topic-action.h"
+#include "ephy-node.h"
#include "ephy-node-common.h"
+#include "ephy-nodes-cover.h"
#include "ephy-bookmarks.h"
-#include "ephy-bookmarksbar.h"
-#include "ephy-link.h"
-#include "ephy-favicon-cache.h"
-#include "ephy-shell.h"
-#include "ephy-dnd.h"
+#include "ephy-bookmarks-ui.h"
+#include "ephy-bookmarks-menu.h"
#include "ephy-gui.h"
#include "ephy-debug.h"
#include <glib/gi18n.h>
#include <gtk/gtkwidget.h>
-#include <gtk/gtkarrow.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkbutton.h>
-#include <gtk/gtktogglebutton.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkimagemenuitem.h>
#include <gtk/gtkseparatormenuitem.h>
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtkarrow.h>
#include <gtk/gtkmain.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <string.h>
@@ -54,26 +53,18 @@
#define EPHY_TOPIC_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_TOPIC_ACTION, EphyTopicActionPrivate))
-static GtkTargetEntry drag_targets[] =
-{
- { EPHY_DND_TOPIC_TYPE, 0, 0 }
-};
-static int n_drag_targets = G_N_ELEMENTS (drag_targets);
-
struct _EphyTopicActionPrivate
{
- EphyNode *topic_node;
-
- guint motion_handler;
- guint release_handler;
- gint drag_x;
- gint drag_y;
+ EphyNode *node;
+ GtkUIManager *manager;
+ guint merge_id;
};
enum
{
PROP_0,
- PROP_TOPIC
+ PROP_TOPIC,
+ PROP_MANAGER
};
static void ephy_topic_action_class_init (EphyTopicActionClass *class);
@@ -101,7 +92,7 @@ ephy_topic_action_get_type (void)
(GInstanceInitFunc) ephy_topic_action_init,
};
- type = g_type_register_static (EPHY_TYPE_LINK_ACTION,
+ type = g_type_register_static (GTK_TYPE_ACTION,
"EphyTopicAction",
&type_info, 0);
}
@@ -120,16 +111,11 @@ create_tool_item (GtkAction *action)
item = (* GTK_ACTION_CLASS (parent_class)->create_tool_item) (action);
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox);
- gtk_container_add (GTK_CONTAINER (item), hbox);
-
button = gtk_toggle_button_new ();
- gtk_widget_add_events (GTK_WIDGET (button), GDK_BUTTON1_MOTION_MASK);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
gtk_widget_show (button);
- gtk_container_add (GTK_CONTAINER (hbox), button);
+ gtk_container_add (GTK_CONTAINER (item), button);
g_object_set_data (G_OBJECT (item), "button", button);
arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
@@ -151,560 +137,122 @@ create_tool_item (GtkAction *action)
}
static void
-menu_deactivate_cb (GtkMenuShell *ms, GtkWidget *button)
-{
- g_object_set_data (G_OBJECT (button), "popup", NULL);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
- gtk_button_released (GTK_BUTTON (button));
-}
-
-static void
-menu_activate_cb (GtkWidget *item, GtkAction *action)
+ephy_topic_action_sync_label (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
{
- EphyBookmarks *bookmarks;
- EphyNode *node;
- const char *location;
- char *address;
-
- node = g_object_get_data (G_OBJECT (item), "node");
- location = ephy_node_get_property_string
- (node, EPHY_NODE_BMK_PROP_LOCATION);
- g_return_if_fail (location != NULL);
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell_get_default ());
- address = ephy_bookmarks_resolve_address (bookmarks, location, NULL);
- g_return_if_fail (address != NULL);
-
- ephy_link_open (EPHY_LINK (action), address, NULL,
- ephy_gui_is_middle_click () ? EPHY_LINK_NEW_TAB : 0);
-
- g_free (address);
-}
+ GtkWidget *label = NULL;
+ GValue value = { 0, };
+ const char *label_text;
-static void
-ephy_topic_action_sync_label (GtkAction *gaction,
- GParamSpec *pspec,
- GtkWidget *proxy)
-{
- EphyTopicAction *action = EPHY_TOPIC_ACTION (gaction);
+ g_value_init (&value, G_TYPE_STRING);
+ g_object_get_property (G_OBJECT (action), "label", &value);
- g_return_if_fail (EPHY_IS_NODE (action->priv->topic_node));
+ label_text = g_value_get_string (&value);
- /* note that we cannot use ellipsizing label with defined width,
- * since that makes the label exactly that wide, even if the
- * text takes less space. So we have to shorten the string.
- */
if (GTK_IS_TOOL_ITEM (proxy))
{
- GtkWidget *label = NULL;
- char *title, *separator;
-
- label = g_object_get_data (G_OBJECT (proxy), "label");
- g_return_if_fail (label != NULL);
-
- g_object_get (G_OBJECT (action), "label", &title, NULL);
- g_return_if_fail (label != NULL);
-
- /* In case this is a multi-hierarchy topic, we only want to
- * display the leaf name. See bug #310963.
- */
- separator = g_strrstr (title, BOOKMARKS_HIERARCHY_SEP);
-
- gtk_label_set_label (GTK_LABEL (label),
- separator != NULL ? separator + strlen(BOOKMARKS_HIERARCHY_SEP) : title);
-
- g_free (title);
- }
-}
-
-static int
-sort_bookmarks (gconstpointer a, gconstpointer b)
-{
- EphyNode *node_a = (EphyNode *)a;
- EphyNode *node_b = (EphyNode *)b;
- const char *title1, *title2;
- int retval;
-
- title1 = ephy_node_get_property_string (node_a, EPHY_NODE_BMK_PROP_TITLE);
- title2 = ephy_node_get_property_string (node_b, EPHY_NODE_BMK_PROP_TITLE);
-
- if (title1 == NULL)
- {
- retval = -1;
+ label = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "label"));
}
- else if (title2 == NULL)
+ else if (GTK_IS_MENU_ITEM (proxy))
{
- retval = 1;
+ label = GTK_BIN (proxy)->child;
}
else
{
- char *str_a, *str_b;
-
- str_a = g_utf8_casefold (title1, -1);
- str_b = g_utf8_casefold (title2, -1);
- retval = g_utf8_collate (str_a, str_b);
- g_free (str_a);
- g_free (str_b);
- }
-
- return retval;
-}
-
-static gboolean
-can_open_in_tabs (EphyNode *node)
-{
- GPtrArray *children;
- int priority;
-
- priority = ephy_node_get_property_int (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
- children = ephy_node_get_children (node);
-
- return (priority != EPHY_NODE_ALL_PRIORITY) && (children->len > 1);
-}
-
-static void
-append_bookmarks_menu (EphyTopicAction *action, GtkWidget *menu, EphyNode *node, gboolean show_empty)
-{
- EphyFaviconCache *cache;
- GtkWidget *item;
- GtkLabel *label;
- GPtrArray *children;
-
- cache = EPHY_FAVICON_CACHE
- (ephy_embed_shell_get_favicon_cache (EPHY_EMBED_SHELL (ephy_shell)));
-
- children = ephy_node_get_children (node);
-
- if (children->len < 1 && show_empty)
- {
- /* This is the adjective, not the verb */
- item = gtk_menu_item_new_with_label (_("Empty"));
- gtk_widget_set_sensitive (item, FALSE);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
+ g_warning ("Unknown widget");
return;
}
- else
- {
- GList *node_list = NULL, *l;
- int i;
-
- for (i = 0; i < children->len; ++i)
- {
- node_list = g_list_prepend (node_list,
- g_ptr_array_index (children, i));
- }
-
- node_list = g_list_sort (node_list, (GCompareFunc)sort_bookmarks);
-
- for (l = node_list; l != NULL; l = l->next)
- {
- EphyNode *kid = (EphyNode*) l->data;
- const char *icon_location;
- const char *title;
-
- icon_location = ephy_node_get_property_string
- (kid, EPHY_NODE_BMK_PROP_ICON);
- title = ephy_node_get_property_string
- (kid, EPHY_NODE_BMK_PROP_TITLE);
- if (title == NULL) continue;
- item = gtk_image_menu_item_new_with_label (title);
- label = (GtkLabel *) ((GtkBin *) item)->child;
- gtk_label_set_max_width_chars (label, LABEL_WIDTH_CHARS);
- gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
- gtk_label_set_use_underline (label, FALSE);
+ g_return_if_fail (label != NULL);
- if (icon_location)
- {
- GdkPixbuf *icon;
- GtkWidget *image;
-
- icon = ephy_favicon_cache_get (cache, icon_location);
- if (icon != NULL)
- {
- image = gtk_image_new_from_pixbuf (icon);
- gtk_widget_show (image);
- gtk_image_menu_item_set_image
- (GTK_IMAGE_MENU_ITEM (item), image);
- g_object_unref (icon);
- }
- }
-
- g_object_set_data (G_OBJECT (item), "node", kid);
- g_signal_connect (item, "activate",
- G_CALLBACK (menu_activate_cb), action);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- }
-
- g_list_free (node_list);
+ if (label_text)
+ {
+ gtk_label_set_label (GTK_LABEL (label), label_text);
}
+
+ g_value_unset (&value);
}
-#define TOPIC_NODE_DATA_KEY "TopicNode"
-
-static void
-open_in_tabs_activate_cb (GtkWidget *item, EphyTopicAction *action)
+static GtkWidget *
+get_popup (EphyTopicAction *action)
{
- EphyBookmarks *bookmarks;
- EphyNode *node;
- GPtrArray *children;
- EphyTab *tab = NULL;
- GList *node_list = NULL, *l;
- int i;
-
- node = g_object_get_data (G_OBJECT (item), TOPIC_NODE_DATA_KEY);
- g_return_if_fail (node != NULL);
-
- children = ephy_node_get_children (node);
- for (i = 0; i < children->len; ++i)
- {
- node_list = g_list_prepend (node_list,
- g_ptr_array_index (children, i));
- }
-
- node_list = g_list_sort (node_list, (GCompareFunc) sort_bookmarks);
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell_get_default ());
+ char path[40];
- for (l = node_list; l != NULL; l = l->next)
+ g_snprintf (path, sizeof (path), "/PopupTopic%ld",
+ (long int) ephy_node_get_id (action->priv->node));
+
+ if (action->priv->merge_id == 0)
{
- EphyNode *child = (EphyNode *) l->data;
- const char *location;
- char *address;
-
- location = ephy_node_get_property_string
- (child, EPHY_NODE_BMK_PROP_LOCATION);
- g_return_if_fail (location != NULL);
-
- address = ephy_bookmarks_resolve_address (bookmarks, location, NULL);
- g_return_if_fail (address != NULL);
-
- tab = ephy_link_open (EPHY_LINK (action), address, tab,
- tab ? EPHY_LINK_NEW_TAB : EPHY_LINK_NEW_WINDOW);
- g_free (address);
+ GString *popup_menu_string = g_string_new ("");
+ g_string_append_printf (popup_menu_string, "<ui><popup name=\"%s\">", path+1);
+ ephy_bookmarks_menu_build (popup_menu_string, action->priv->node);
+ g_string_append (popup_menu_string, "</popup></ui>");
+
+ action->priv->merge_id = gtk_ui_manager_add_ui_from_string
+ (action->priv->manager, popup_menu_string->str, popup_menu_string->len, 0);
+
+ g_string_free (popup_menu_string, TRUE);
}
-
- g_list_free (node_list);
+
+ return gtk_ui_manager_get_widget (action->priv->manager, path);
}
-static int
-get_item_position (GtkWidget *widget, gboolean *last)
+static void
+erase_popup (EphyTopicAction *action)
{
- GtkWidget *item, *toolbar;
- int index;
-
- item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM);
- g_return_val_if_fail (item != NULL, -1);
-
- toolbar = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOLBAR);
- g_return_val_if_fail (toolbar != NULL, -1);
-
- index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar),
- GTK_TOOL_ITEM (item));
- if (last)
+ if (action->priv->merge_id != 0)
{
- int n_items;
-
- n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar));
- *last = (index == n_items - 1);
+ gtk_ui_manager_remove_ui (action->priv->manager, action->priv->merge_id);
+ action->priv->merge_id = 0;
}
-
- return index;
}
static void
-remove_from_model (GtkWidget *widget)
+child_added_cb (EphyNode *node, EphyNode *child, GObject *object)
{
- EphyBookmarks *bookmarks;
- EggToolbarsModel *model;
- int pos;
-
- pos = get_item_position (widget, NULL);
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- model = EGG_TOOLBARS_MODEL (ephy_bookmarks_get_toolbars_model (bookmarks));
-
- egg_toolbars_model_remove_item (model, 0, pos);
+ EphyTopicAction *action = EPHY_TOPIC_ACTION (object);
+ erase_popup (action);
}
static void
-move_in_model (GtkWidget *widget, int direction)
+child_changed_cb (EphyNode *node, EphyNode *child, guint property, GObject *object)
{
- EphyBookmarks *bookmarks;
- EggToolbarsModel *model;
- int pos, new_pos;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- model = EGG_TOOLBARS_MODEL (ephy_bookmarks_get_toolbars_model (bookmarks));
-
- pos = get_item_position (widget, NULL);
- new_pos = MAX (0, pos + direction);
-
- egg_toolbars_model_move_item (model, 0, pos, 0, new_pos);
+ EphyTopicAction *action = EPHY_TOPIC_ACTION (object);
+ erase_popup (action);
}
static void
-remove_activate_cb (GtkWidget *menu, GtkWidget *proxy)
+child_removed_cb (EphyNode *node, EphyNode *child, guint index, GObject *object)
{
- remove_from_model (proxy);
+ EphyTopicAction *action = EPHY_TOPIC_ACTION (object);
+ erase_popup (action);
}
static void
-move_left_activate_cb (GtkWidget *menu, GtkWidget *proxy)
+menu_destroy_cb (GtkWidget *menuitem,
+ gpointer user_data)
{
- move_in_model (proxy, -1);
+ /* Save the submenu from similar destruction,
+ * because it doesn't rightly belong to this menuitem. */
+ gtk_menu_item_remove_submenu (GTK_MENU_ITEM (menuitem));
}
static void
-move_right_activate_cb (GtkWidget *menu, GtkWidget *proxy)
-{
- move_in_model (proxy, +1);
-}
-
-static GtkWidget *
-add_open_in_tabs_menu (EphyTopicAction *action,
- GtkWidget *menu,
- EphyNode *node)
-{
- GtkWidget *item;
- const char *label;
-
- label = ngettext ("Open in New _Tab",
- "Open in New _Tabs",
- ephy_node_get_n_children (node));
-
- item = gtk_menu_item_new_with_mnemonic (label);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- g_object_set_data (G_OBJECT (item), TOPIC_NODE_DATA_KEY, node);
-
- g_signal_connect (item, "activate",
- G_CALLBACK (open_in_tabs_activate_cb), action);
-
- return item;
-}
-
-static GtkWidget *
-build_bookmarks_menu (EphyTopicAction *action, EphyNode *node)
-{
- GtkWidget *menu;
-
- menu = gtk_menu_new ();
-
- append_bookmarks_menu (action, menu, node, TRUE);
-
- if (can_open_in_tabs (node))
- {
- GtkWidget *item;
-
- item = gtk_separator_menu_item_new ();
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- add_open_in_tabs_menu (action, menu, node);
- }
-
- return menu;
-}
-
-static int
-sort_topics (gconstpointer a, gconstpointer b)
-{
- EphyNode *node_a = (EphyNode *)a;
- EphyNode *node_b = (EphyNode *)b;
- const char *title1, *title2;
- int retval;
-
- title1 = ephy_node_get_property_string (node_a, EPHY_NODE_KEYWORD_PROP_NAME);
- title2 = ephy_node_get_property_string (node_b, EPHY_NODE_KEYWORD_PROP_NAME);
-
- if (title1 == NULL)
- {
- retval = -1;
- }
- else if (title2 == NULL)
- {
- retval = 1;
- }
- else
- {
- char *str_a, *str_b;
-
- str_a = g_utf8_casefold (title1, -1);
- str_b = g_utf8_casefold (title2, -1);
- retval = g_utf8_collate (str_a, str_b);
- g_free (str_a);
- g_free (str_b);
- }
-
- return retval;
-}
-
-static GtkWidget *
-build_topics_menu (EphyTopicAction *action)
-{
- GtkWidget *menu, *item;
- GPtrArray *children;
- int i;
- EphyBookmarks *bookmarks;
- EphyNode *all, *uncategorized, *node;
- EphyNodePriority priority;
- GList *node_list = NULL, *l = NULL;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- all = ephy_bookmarks_get_bookmarks (bookmarks);
- node = ephy_bookmarks_get_keywords (bookmarks);
-
- menu = gtk_menu_new ();
-
- children = ephy_node_get_children (node);
-
- for (i = 0; i < children->len; ++i)
- {
- EphyNode *kid;
-
- kid = g_ptr_array_index (children, i);
- priority = ephy_node_get_property_int
- (kid, EPHY_NODE_KEYWORD_PROP_PRIORITY);
- if (priority == EPHY_NODE_NORMAL_PRIORITY)
- {
- node_list = g_list_prepend (node_list, kid);
- }
- }
-
- node_list = g_list_sort (node_list, (GCompareFunc)sort_topics);
-
- for (l = g_list_first (node_list); l != NULL; l = g_list_next (l))
- {
- EphyNode *kid;
- const char *title;
- GtkWidget *bmk_menu;
- GtkLabel *label;
-
- kid = (EphyNode*)l->data;
- if (kid == all) continue;
-
- title = ephy_node_get_property_string
- (kid, EPHY_NODE_KEYWORD_PROP_NAME);
-
- item = gtk_image_menu_item_new_with_label (title);
- label = (GtkLabel *) ((GtkBin *) item)->child;
- gtk_label_set_max_width_chars (label, MENUITEM_WIDTH_CHARS);
- gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
-
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- bmk_menu = build_bookmarks_menu (action, kid);
- gtk_widget_show (bmk_menu);
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), bmk_menu);
- }
- g_list_free (node_list);
-
- uncategorized = ephy_bookmarks_get_not_categorized (bookmarks);
- append_bookmarks_menu (action, menu, uncategorized, FALSE);
-
- return menu;
-}
-
-static GtkWidget *
-build_menu (EphyTopicAction *action)
+menu_init_cb (GtkWidget *menuitem,
+ EphyTopicAction *action)
{
- if (ephy_node_get_id (action->priv->topic_node) == BOOKMARKS_NODE_ID)
- {
- return build_topics_menu (action);
- }
- else
+ if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem)) == NULL)
{
- return build_bookmarks_menu (action, action->priv->topic_node);
+ GtkWidget *popup = get_popup (action);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), popup);
+ g_signal_connect (menuitem, "destroy", G_CALLBACK (menu_destroy_cb), NULL);
}
}
static void
-drag_data_get_cb (GtkWidget *widget, GdkDragContext *context,
- GtkSelectionData *selection_data, guint info,
- guint32 time, EphyTopicAction *action)
-{
- EphyBookmarks *bookmarks;
- char *uri;
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
- g_return_if_fail (bookmarks != NULL);
-
- uri = ephy_bookmarks_get_topic_uri (bookmarks, action->priv->topic_node);
- g_return_if_fail (uri != NULL);
-
- gtk_selection_data_set (selection_data, selection_data->target, 8,
- (unsigned char *) uri, strlen (uri));
-
- g_free (uri);
-}
-
-static void
-drag_data_delete_cb (GtkWidget *widget, GdkDragContext *context,
- EphyTopicAction *action)
-{
- remove_from_model (widget);
-}
-
-static void
-stop_drag_check (EphyTopicAction *action, GtkWidget *widget)
-{
- if (action->priv->motion_handler)
- {
- g_signal_handler_disconnect (widget, action->priv->motion_handler);
- action->priv->motion_handler = 0;
-
- g_signal_handler_disconnect (widget, action->priv->release_handler);
- action->priv->release_handler = 0;
- }
-}
-
-static gboolean
-check_horizontal_threshold (GtkWidget *widget, gint start_x, gint start_y,
- gint current_x, gint current_y)
-{
- gint drag_threshold;
-
- g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-dnd-drag-threshold", &drag_threshold,
- NULL);
-
- return (ABS (current_x - start_x) > drag_threshold &&
- ABS (current_y - start_y) < drag_threshold);
-}
-
-static gboolean
-drag_motion_cb (GtkWidget *widget, GdkEventMotion *event, EphyTopicAction *action)
+button_deactivate_cb (GtkMenuShell *ms, GtkWidget *button)
{
- GtkWidget *button, *event_widget;
-
- event_widget = gtk_get_event_widget ((GdkEvent*) event);
- button = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "button"));
-
- if (!gtk_widget_is_ancestor (event_widget, widget) &&
- check_horizontal_threshold (widget, action->priv->drag_x,
- action->priv->drag_y, event->x, event->y))
- {
- GtkTargetList *target_list;
-
- target_list = gtk_target_list_new (drag_targets, n_drag_targets);
-
- stop_drag_check (action, widget);
- gtk_menu_popdown (GTK_MENU (widget));
- gtk_drag_begin (button, target_list, GDK_ACTION_MOVE |
- GDK_ACTION_COPY, 1, (GdkEvent*)event);
-
- gtk_target_list_unref (target_list);
- }
-
- return TRUE;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+ gtk_button_released (GTK_BUTTON (button));
}
static void
@@ -713,196 +261,43 @@ button_toggled_cb (GtkWidget *button,
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
{
- GtkWidget *menu;
- GdkEvent *event;
- guint32 event_time = 0;
- guint event_button = 0;
-
- menu = build_menu (action);
- g_signal_connect_object (menu, "deactivate",
- G_CALLBACK (menu_deactivate_cb), button, 0);
-
- event = gtk_get_current_event ();
- if (event != NULL)
- {
- if (event->type == GDK_BUTTON_PRESS)
- {
- event_button = ((GdkEventButton *) event)->button;
- event_time = ((GdkEventButton *) event)->time;
- }
-
- gdk_event_free (event);
- }
-
- if (event_button == 0)
- {
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
- ephy_gui_menu_position_under_widget,
- button, 0 , gtk_get_current_event_time ());
- gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
- }
- else
- {
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
- ephy_gui_menu_position_under_widget,
- button, event_button, event_time);
- }
-
- g_object_set_data (G_OBJECT (button), "popup", menu);
- }
-}
-
-static GtkWidget *
-create_menu_item (GtkAction *action)
-{
- GtkWidget *menu, *menu_item;
- GValue value = { 0, };
- const char *title;
-
- g_value_init (&value, G_TYPE_STRING);
- g_object_get_property (G_OBJECT (action), "label", &value);
-
- title = g_value_get_string (&value);
-
- menu_item = gtk_menu_item_new_with_label (title);
-
- g_value_unset (&value);
-
- menu = build_menu (EPHY_TOPIC_ACTION (action));
- gtk_widget_show (menu);
-
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
-
- return menu_item;
-}
-
-static void
-show_context_menu (EphyTopicAction *action,
- GtkWidget *proxy,
- GdkEventButton *event,
- GtkMenuPositionFunc func)
-{
- GtkWidget *menu, *item, *image;
- gboolean last;
-
- menu = gtk_menu_new ();
-
- item = add_open_in_tabs_menu (action, menu, action->priv->topic_node);
- gtk_widget_set_sensitive (item, can_open_in_tabs (action->priv->topic_node));
-
- item = gtk_separator_menu_item_new ();
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- item = gtk_image_menu_item_new_with_mnemonic (_("_Remove from Toolbar"));
- gtk_widget_show (item);
- image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
- gtk_widget_show (image);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate",
- G_CALLBACK (remove_activate_cb), proxy);
-
- item = gtk_separator_menu_item_new ();
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
- item = gtk_menu_item_new_with_mnemonic (_("Move _Left"));
- gtk_widget_set_sensitive (item, get_item_position (proxy, NULL) > 0);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate",
- G_CALLBACK (move_left_activate_cb), proxy);
-
- item = gtk_menu_item_new_with_mnemonic (_("Move Ri_ght"));
- get_item_position (proxy, &last);
- gtk_widget_set_sensitive (item, !last);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- g_signal_connect (item, "activate",
- G_CALLBACK (move_right_activate_cb), proxy);
-
- if (event != NULL)
- {
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL, func, proxy,
- event->button, event->time);
- }
- else
- {
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL, func, proxy, 0,
- gtk_get_current_event_time ());
- gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
+ GtkWidget *popup = get_popup (action);
+ g_signal_connect_object (popup, "deactivate",
+ G_CALLBACK (button_deactivate_cb), button, 0);
+ gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
+ ephy_gui_menu_position_under_widget,
+ button, 1, gtk_get_current_event_time ());
}
}
static gboolean
-popup_menu_cb (GtkWidget *widget, EphyTopicAction *action)
-{
- if (gtk_widget_get_ancestor (widget, EPHY_TYPE_BOOKMARKSBAR))
- {
- show_context_menu (action, widget, NULL,
- ephy_gui_menu_position_under_widget);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-button_release_cb (GtkWidget *widget,
+button_release_cb (GtkWidget *button,
GdkEventButton *event,
EphyTopicAction *action)
{
if (event->button == 1)
{
- stop_drag_check (action, widget);
-
- if (GTK_IS_TOGGLE_BUTTON (widget))
- {
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON (widget), FALSE);
- }
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON (button), FALSE);
}
return FALSE;
}
static gboolean
-button_press_cb (GtkWidget *widget,
+button_press_cb (GtkWidget *button,
GdkEventButton *event,
EphyTopicAction *action)
{
- if (event->button == 1 &&
- gtk_widget_get_ancestor (widget, EPHY_TYPE_BOOKMARKSBAR))
+ if (event->button == 1)
{
- if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
{
- GtkWidget *menu;
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
- menu = g_object_get_data (G_OBJECT (widget), "popup");
- g_return_val_if_fail (menu != NULL, FALSE);
-
- g_object_set_data (G_OBJECT (menu), "button", widget);
-
- action->priv->drag_x = event->x;
- action->priv->drag_y = event->y;
- action->priv->motion_handler = g_signal_connect
- (menu, "motion_notify_event",
- G_CALLBACK (drag_motion_cb), action);
- action->priv->release_handler = g_signal_connect
- (menu, "button_release_event",
- G_CALLBACK (button_release_cb), action);
-
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+ button_toggled_cb (button, action);
return TRUE;
}
}
- else if (event->button == 3 &&
- gtk_widget_get_ancestor (widget, EPHY_TYPE_BOOKMARKSBAR))
- {
- show_context_menu (action, widget, event, NULL);
- return TRUE;
- }
return FALSE;
}
@@ -910,113 +305,140 @@ button_press_cb (GtkWidget *widget,
static void
connect_proxy (GtkAction *action, GtkWidget *proxy)
{
- GtkWidget *button;
-
- LOG ("connect_proxy action %p, proxy %p", action, proxy);
-
(* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+
+ ephy_topic_action_sync_label (action, NULL, proxy);
+ g_signal_connect_object (action, "notify::label",
+ G_CALLBACK (ephy_topic_action_sync_label), proxy, 0);
if (GTK_IS_TOOL_ITEM (proxy))
{
- ephy_topic_action_sync_label (action, NULL, proxy);
- g_signal_connect_object (action, "notify::label",
- G_CALLBACK (ephy_topic_action_sync_label), proxy, 0);
-
- button = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "button"));
+ GtkWidget *button = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "button"));
g_signal_connect (button, "toggled",
G_CALLBACK (button_toggled_cb), action);
- g_signal_connect (button, "popup_menu",
- G_CALLBACK (popup_menu_cb), action);
g_signal_connect (button, "button-press-event",
G_CALLBACK (button_press_cb), action);
g_signal_connect (button, "button-release-event",
G_CALLBACK (button_release_cb), action);
- g_signal_connect (button, "drag_data_get",
- G_CALLBACK (drag_data_get_cb), action);
- g_signal_connect (button, "drag_data_delete",
- G_CALLBACK (drag_data_delete_cb), action);
}
else if (GTK_IS_MENU_ITEM (proxy))
{
- GtkLabel *label;
-
- label = (GtkLabel *) ((GtkBin *) proxy)->child;
-
- gtk_label_set_use_underline (label, FALSE);
- gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
- gtk_label_set_max_width_chars (label, LABEL_WIDTH_CHARS);
+ g_signal_connect (proxy, "map", G_CALLBACK (menu_init_cb), action);
}
}
-static void
-topic_changed_cb (EphyNode *node,
- guint property_id,
- EphyTopicAction *action)
+void
+ephy_topic_action_updated (EphyTopicAction *action)
{
- if (property_id == EPHY_NODE_KEYWORD_PROP_NAME)
+ GValue value = { 0, };
+ const char *title;
+ int priority;
+
+ g_return_if_fail (action->priv->node != NULL);
+
+ priority = ephy_node_get_property_int
+ (action->priv->node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+
+ if (priority == EPHY_NODE_ALL_PRIORITY)
{
- GValue value = { 0, };
- const char *title;
- int priority;
-
- priority = ephy_node_get_property_int
- (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
-
- if (priority == EPHY_NODE_ALL_PRIORITY)
- {
- title = _("Bookmarks");
- }
- else
- {
- title = ephy_node_get_property_string
- (node, EPHY_NODE_KEYWORD_PROP_NAME);
- }
-
- g_value_init(&value, G_TYPE_STRING);
- g_value_set_static_string (&value, title);
- g_object_set_property (G_OBJECT (action), "label", &value);
- g_value_unset (&value);
+ title = _("Bookmarks");
+ }
+ else
+ {
+ title = ephy_node_get_property_string
+ (action->priv->node, EPHY_NODE_KEYWORD_PROP_NAME);
}
+
+ g_value_init(&value, G_TYPE_STRING);
+ g_value_set_static_string (&value, title);
+ g_object_set_property (G_OBJECT (action), "label", &value);
+ g_object_set_property (G_OBJECT (action), "tooltip", &value);
+ g_value_unset (&value);
}
-static void
+EphyNode *
+ephy_topic_action_get_topic (EphyTopicAction *action)
+{
+ return action->priv->node;
+}
+
+void
ephy_topic_action_set_topic (EphyTopicAction *action,
EphyNode *node)
{
- action->priv->topic_node = node;
+ g_return_if_fail (node != NULL);
+
+ if (action->priv->node == node) return;
+
+ if (action->priv->node != NULL)
+ {
+ ephy_node_signal_disconnect_object
+ (action->priv->node, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)child_added_cb, G_OBJECT (action));
+ ephy_node_signal_disconnect_object
+ (action->priv->node, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)child_changed_cb, G_OBJECT (action));
+ ephy_node_signal_disconnect_object
+ (action->priv->node, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)child_removed_cb, G_OBJECT (action));
+ }
- topic_changed_cb (node, EPHY_NODE_KEYWORD_PROP_NAME, action);
- ephy_node_signal_connect_object (node, EPHY_NODE_CHANGED,
- (EphyNodeCallback) topic_changed_cb,
- G_OBJECT (action));
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)child_added_cb,
+ G_OBJECT (action));
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)child_changed_cb,
+ G_OBJECT (action));
+ ephy_node_signal_connect_object (node, EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)child_removed_cb,
+ G_OBJECT (action));
+
+ action->priv->node = node;
+
+ erase_popup (action);
+
+ g_object_freeze_notify (G_OBJECT (action));
+ g_object_notify (G_OBJECT (action), "topic");
+ ephy_topic_action_updated (action);
+ g_object_thaw_notify (G_OBJECT (action));
}
static void
ephy_topic_action_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- EphyTopicAction *topic;
-
- topic = EPHY_TOPIC_ACTION (object);
+ EphyTopicAction *action = EPHY_TOPIC_ACTION (object);
switch (prop_id)
{
case PROP_TOPIC:
- ephy_topic_action_set_topic (topic, g_value_get_pointer (value));
+ ephy_topic_action_set_topic (action, g_value_get_pointer (value));
+ break;
+ case PROP_MANAGER:
+ action->priv->manager = g_value_get_object (value);
break;
}
}
static void
ephy_topic_action_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- /* no readable properties */
- g_return_if_reached ();
+ EphyTopicAction *action = EPHY_TOPIC_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_TOPIC:
+ g_value_set_pointer (value, action->priv->node);
+ break;
+ case PROP_MANAGER:
+ g_value_set_object (value, action->priv->manager);
+ break;
+ }
}
static void
@@ -1029,21 +451,28 @@ ephy_topic_action_class_init (EphyTopicActionClass *class)
action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;
action_class->create_tool_item = create_tool_item;
- action_class->create_menu_item = create_menu_item;
action_class->connect_proxy = connect_proxy;
object_class->set_property = ephy_topic_action_set_property;
object_class->get_property = ephy_topic_action_get_property;
- g_object_class_install_property
- (object_class,
- PROP_TOPIC,
- g_param_spec_pointer ("topic",
- "Topic",
- "Topic",
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
+ g_object_class_install_property (object_class,
+ PROP_TOPIC,
+ g_param_spec_pointer ("topic",
+ "Topic",
+ "Topic",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_MANAGER,
+ g_param_spec_object ("manager",
+ "Manager",
+ "UI Manager",
+ GTK_TYPE_UI_MANAGER,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY));
+
g_type_class_add_private (object_class, sizeof(EphyTopicActionPrivate));
}
@@ -1051,14 +480,27 @@ static void
ephy_topic_action_init (EphyTopicAction *action)
{
action->priv = EPHY_TOPIC_ACTION_GET_PRIVATE (action);
+
+ action->priv->merge_id = 0;
+ action->priv->node = NULL;
+ action->priv->manager = NULL;
+}
+
+char *
+ephy_topic_action_name (EphyNode *node)
+{
+ return g_strdup_printf("Tpc%u", ephy_node_get_id (node));
}
GtkAction *
-ephy_topic_action_new (const char *name,
- EphyNode *node)
+ephy_topic_action_new (EphyNode *node, GtkUIManager *manager, char *name)
{
- return g_object_new (EPHY_TYPE_TOPIC_ACTION,
- "name", name,
- "topic", node,
- NULL);
+ if(!name) name = ephy_topic_action_name (node);
+ g_return_val_if_fail (name, NULL);
+
+ return GTK_ACTION (g_object_new (EPHY_TYPE_TOPIC_ACTION,
+ "name", name,
+ "topic", node,
+ "manager", manager,
+ NULL));
}
diff --git a/src/bookmarks/ephy-topic-action.h b/src/bookmarks/ephy-topic-action.h
index 7c39e2e19..f6be79b4c 100644
--- a/src/bookmarks/ephy-topic-action.h
+++ b/src/bookmarks/ephy-topic-action.h
@@ -25,22 +25,25 @@
#include "ephy-link-action.h"
#include "ephy-node.h"
+#include <gtk/gtkactiongroup.h>
+#include <gtk/gtkuimanager.h>
+
G_BEGIN_DECLS
-#define EPHY_TYPE_TOPIC_ACTION (ephy_topic_action_get_type ())
-#define EPHY_TOPIC_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_TOPIC_ACTION, EphyTopicAction))
-#define EPHY_TOPIC_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_TOPIC_ACTION, EphyTopicActionClass))
-#define EPHY_IS_TOPIC_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_TOPIC_ACTION))
-#define EPHY_IS_TOPIC_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_TOPIC_ACTION))
-#define EPHY_TOPIC_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_TOPIC_ACTION, EphyTopicActionClass))
+#define EPHY_TYPE_TOPIC_ACTION (ephy_topic_action_get_type ())
+#define EPHY_TOPIC_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_TOPIC_ACTION, EphyTopicAction))
+#define EPHY_TOPIC_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_TOPIC_ACTION, EphyTopicActionClass))
+#define EPHY_IS_TOPIC_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_TOPIC_ACTION))
+#define EPHY_IS_TOPIC_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_TOPIC_ACTION))
+#define EPHY_TOPIC_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_TOPIC_ACTION, EphyTopicActionClass))
-typedef struct _EphyTopicAction EphyTopicAction;
-typedef struct _EphyTopicActionPrivate EphyTopicActionPrivate;
-typedef struct _EphyTopicActionClass EphyTopicActionClass;
+typedef struct _EphyTopicAction EphyTopicAction;
+typedef struct _EphyTopicActionPrivate EphyTopicActionPrivate;
+typedef struct _EphyTopicActionClass EphyTopicActionClass;
struct _EphyTopicAction
{
- EphyLinkAction parent_instance;
+ GtkAction parent_instance;
/*< private >*/
EphyTopicActionPrivate *priv;
@@ -51,10 +54,19 @@ struct _EphyTopicActionClass
EphyLinkActionClass parent_class;
};
-GType ephy_topic_action_get_type (void);
-GtkAction *ephy_topic_action_new (const char *name,
- EphyNode *node);
+GType ephy_topic_action_get_type (void);
+
+char * ephy_topic_action_name (EphyNode *node);
+
+GtkAction * ephy_topic_action_new (EphyNode *node, GtkUIManager *manager, char *name);
+
+
+void ephy_topic_action_set_topic (EphyTopicAction *action, EphyNode *node);
+
+EphyNode * ephy_topic_action_get_topic (EphyTopicAction *action);
+
+void ephy_topic_action_updated (EphyTopicAction *action);
G_END_DECLS
diff --git a/src/bookmarks/ephy-topic-factory-action.c b/src/bookmarks/ephy-topic-factory-action.c
new file mode 100644
index 000000000..909d02abb
--- /dev/null
+++ b/src/bookmarks/ephy-topic-factory-action.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2004 Peter Harvey
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtktoolitem.h>
+#include <glib/gi18n.h>
+
+#include "ephy-topic-factory-action.h"
+#include "ephy-topic-action.h"
+#include "ephy-shell.h"
+#include "ephy-stock-icons.h"
+#include "egg-editable-toolbar.h"
+
+static void ephy_topic_factory_action_class_init (EphyTopicFactoryActionClass *class);
+
+#define EPHY_TOPIC_FACTORY_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_TOPIC_FACTORY_ACTION, EphyTopicActionPrivate))
+#define EGG_TOOLBARS_MODEL_DATA "ephy-topic-factory-menu"
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_topic_factory_action_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (EphyTopicFactoryActionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) ephy_topic_factory_action_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (EphyTopicFactoryAction),
+ 0, /* n_preallocs */
+ NULL
+ };
+
+ type = g_type_register_static (GTK_TYPE_ACTION,
+ "EphyTopicFactoryAction",
+ &type_info, 0);
+ }
+ return type;
+}
+
+static int
+sort_topics (gconstpointer a, gconstpointer b)
+{
+ EphyNode *node_a = *(EphyNode **)a;
+ EphyNode *node_b = *(EphyNode **)b;
+ const char *title1, *title2;
+ int priority1, priority2;
+
+ priority1 = ephy_node_get_property_int (node_a, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ priority2 = ephy_node_get_property_int (node_b, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+
+ if (priority1 > priority2)
+ {
+ return 1;
+ }
+ else if (priority1 < priority2)
+ {
+ return -1;
+ }
+ else
+ {
+ title1 = ephy_node_get_property_string (node_a, EPHY_NODE_KEYWORD_PROP_NAME);
+ title2 = ephy_node_get_property_string (node_b, EPHY_NODE_KEYWORD_PROP_NAME);
+
+ if (title1 == NULL)
+ {
+ return -1;
+ }
+ else if (title2 == NULL)
+ {
+ return 1;
+ }
+ else
+ {
+ return g_utf8_collate (title1, title2);
+ }
+ }
+
+ return 0;
+}
+
+static void
+activate_item_cb (GtkWidget *menuitem, GtkWidget *placeholder)
+{
+ GtkWidget *toolbar, *etoolbar, *item;
+ EggToolbarsModel *model;
+ GList *children;
+ gint index, pos;
+ char *id;
+
+ item = gtk_widget_get_ancestor (placeholder, GTK_TYPE_TOOL_ITEM);
+ g_return_if_fail (item);
+ toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR);
+ g_return_if_fail (toolbar);
+ etoolbar = gtk_widget_get_ancestor (toolbar, EGG_TYPE_EDITABLE_TOOLBAR);
+ g_return_if_fail (etoolbar);
+ model = egg_editable_toolbar_get_model (EGG_EDITABLE_TOOLBAR (etoolbar));
+ g_return_if_fail (model);
+
+ children = gtk_container_get_children (GTK_CONTAINER (etoolbar));
+ pos = g_list_index (children, toolbar->parent);
+ index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item));
+ g_list_free (children);
+
+ id = g_object_get_data (G_OBJECT (menuitem), "ephy-action");
+ egg_toolbars_model_add_item (model, pos, index, id);
+}
+
+static GtkWidget *
+build_menu (GtkWidget *placeholder, EggToolbarsModel *model)
+{
+ GtkWidget *menu, *item;
+
+ EphyBookmarks *eb;
+ EphyNode *node;
+ GPtrArray *children, *topics;
+
+ const char *name, *action;
+ gint i, priority = -1, ptmp;
+
+ /* Get a sorted list of topics. */
+ eb = ephy_shell_get_bookmarks (ephy_shell);
+ node = ephy_bookmarks_get_keywords (eb);
+ children = ephy_node_get_children (node);
+ topics = g_ptr_array_sized_new (children->len);
+ for (i = 0; i < children->len; i++)
+ g_ptr_array_add (topics, g_ptr_array_index (children, i));
+ g_ptr_array_sort (topics, (GCompareFunc)sort_topics);
+
+ menu = gtk_menu_new ();
+ for (i = 0; i < topics->len; i++)
+ {
+ node = g_ptr_array_index (topics, i);
+
+ action = ephy_topic_action_name (node);
+ if (egg_toolbars_model_get_n_avail (model, action) < 0)
+ continue;
+
+ ptmp = ephy_node_get_property_int (node, EPHY_NODE_KEYWORD_PROP_PRIORITY);
+ if (ptmp != priority && priority >= 0)
+ {
+ item = gtk_separator_menu_item_new ();
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ priority = ptmp;
+
+ name = ephy_node_get_property_string (node, EPHY_NODE_KEYWORD_PROP_NAME);
+ item = gtk_menu_item_new_with_label (name);
+
+ g_object_set_data_full (G_OBJECT (item), "ephy-action", (gpointer) action, g_free);
+ g_signal_connect (item, "activate", G_CALLBACK (activate_item_cb), placeholder);
+ gtk_widget_show (item);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ g_ptr_array_free (topics, TRUE);
+
+ return menu;
+}
+
+static void
+remove_placeholder_cb (GtkMenuShell *menushell, GtkWidget *placeholder)
+{
+ GtkWidget *toolbar, *etoolbar, *item;
+ EggToolbarsModel *model;
+ GList *children;
+ gint index, pos;
+
+ item = gtk_widget_get_ancestor (placeholder, GTK_TYPE_TOOL_ITEM);
+ g_return_if_fail (item);
+ toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR);
+ g_return_if_fail (toolbar);
+ etoolbar = gtk_widget_get_ancestor (toolbar, EGG_TYPE_EDITABLE_TOOLBAR);
+ g_return_if_fail (etoolbar);
+ model = egg_editable_toolbar_get_model (EGG_EDITABLE_TOOLBAR (etoolbar));
+ g_return_if_fail (model);
+
+ g_object_set_data (G_OBJECT (model), EGG_TOOLBARS_MODEL_DATA, NULL);
+
+ children = gtk_container_get_children (GTK_CONTAINER (etoolbar));
+ pos = g_list_index (children, toolbar->parent);
+ index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item));
+ g_list_free (children);
+
+ egg_toolbars_model_remove_item (model, pos, index);
+}
+
+static gboolean
+activate_placeholder_cb (GtkWidget *placeholder)
+{
+ GtkWidget *toolbar, *etoolbar, *item, *menu;
+ EggToolbarsModel *model;
+ gint index;
+
+ /* Get our position on a toolbar. */
+ item = gtk_widget_get_ancestor (placeholder, GTK_TYPE_TOOL_ITEM);
+ g_return_val_if_fail (item, FALSE);
+ toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR);
+ g_return_val_if_fail (toolbar, FALSE);
+ etoolbar = gtk_widget_get_ancestor (toolbar, EGG_TYPE_EDITABLE_TOOLBAR);
+ g_return_val_if_fail (etoolbar, FALSE);
+ model = egg_editable_toolbar_get_model (EGG_EDITABLE_TOOLBAR (etoolbar));
+ g_return_val_if_fail (model, FALSE);
+
+ /* If we are not yet on the toolbar, abort. */
+ index = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (item));
+ if (index < 0 || index >= gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)))
+ return FALSE;
+
+ /* If there is already a popup menu, abort. */
+ menu = g_object_get_data (G_OBJECT (model), EGG_TOOLBARS_MODEL_DATA);
+ if (menu != NULL) return FALSE;
+
+ /* Create the menu and store it's pointer to ensure noone else creates a menu. */
+ menu = build_menu (placeholder, model);
+ g_object_set_data (G_OBJECT (model), EGG_TOOLBARS_MODEL_DATA, menu);
+
+ g_signal_connect (menu, "selection-done",
+ G_CALLBACK (remove_placeholder_cb), placeholder);
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0,
+ gtk_get_current_event_time ());
+
+ return FALSE;
+}
+
+static void
+clicked_placeholder_cb (GtkWidget *placeholder, GdkEventButton *event, gpointer user)
+{
+ activate_placeholder_cb (placeholder);
+}
+
+static void
+realize_placeholder_cb (GtkWidget *placeholder, gpointer user)
+{
+ g_idle_add ((GSourceFunc) activate_placeholder_cb, placeholder);
+}
+
+static GtkWidget *
+create_tool_item (GtkAction *action)
+{
+ GtkWidget *item = GTK_WIDGET (gtk_tool_item_new ());
+ GtkWidget *widget = gtk_button_new_with_label (" ? ");
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+
+ gtk_container_add (GTK_CONTAINER (item), widget);
+ gtk_widget_show (widget);
+
+ return item;
+}
+
+static void
+connect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+ GtkWidget *widget;
+
+ (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
+
+ g_return_if_fail (GTK_IS_TOOL_ITEM (proxy));
+
+ widget = gtk_bin_get_child (GTK_BIN (proxy));
+
+ g_signal_connect (G_OBJECT (widget), "realize",
+ G_CALLBACK (realize_placeholder_cb),
+ G_OBJECT (action));
+ g_signal_connect (G_OBJECT (widget), "clicked",
+ G_CALLBACK (clicked_placeholder_cb),
+ G_OBJECT (action));
+}
+
+static void
+ephy_topic_factory_action_class_init (EphyTopicFactoryActionClass *class)
+{
+ GtkActionClass *action_class = GTK_ACTION_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;
+ action_class->connect_proxy = connect_proxy;
+ action_class->create_tool_item = create_tool_item;
+}
+
+GtkAction *
+ephy_topic_factory_action_new (const char *name)
+{
+ return GTK_ACTION (g_object_new (EPHY_TYPE_TOPIC_FACTORY_ACTION,
+ "name", name,
+ "label", _("Quick Topic"),
+ "stock-id", GTK_STOCK_ADD,
+ NULL));
+}
diff --git a/src/bookmarks/ephy-topic-factory-action.h b/src/bookmarks/ephy-topic-factory-action.h
new file mode 100644
index 000000000..70b40e676
--- /dev/null
+++ b/src/bookmarks/ephy-topic-factory-action.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004 Peter Harvey
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef EPHY_TOPIC_FACTORY_ACTION_H
+#define EPHY_TOPIC_FACTORY_ACTION_H
+
+#include "ephy-node.h"
+#include "ephy-window.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkaction.h>
+#include <gtk/gtkactiongroup.h>
+
+#define EPHY_TYPE_TOPIC_FACTORY_ACTION (ephy_topic_factory_action_get_type ())
+#define EPHY_TOPIC_FACTORY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_TOPIC_FACTORY_ACTION, EphyTopicFactoryAction))
+#define EPHY_TOPIC_FACTORY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_TOPIC_FACTORY_ACTION, EphyTopicFactoryActionClass))
+#define EPHY_IS_TOPIC_FACTORY_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_TOPIC_FACTORY_ACTION))
+#define EPHY_IS_TOPIC_FACTORY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_TOPIC_FACTORY_ACTION))
+#define EPHY_TOPIC_FACTORY_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_TOPIC_FACTORY_ACTION, EphyTopicFactoryActionClass))
+
+typedef struct _EphyTopicFactoryAction EphyTopicFactoryAction;
+typedef struct _EphyTopicFactoryActionClass EphyTopicFactoryActionClass;
+
+struct _EphyTopicFactoryAction
+{
+ GtkAction parent;
+};
+
+struct _EphyTopicFactoryActionClass
+{
+ GtkActionClass parent_class;
+};
+
+GType ephy_topic_factory_action_get_type (void);
+
+GtkAction * ephy_topic_factory_action_new (const char *name);
+
+#endif