diff options
53 files changed, 4973 insertions, 5225 deletions
@@ -1,3 +1,304 @@ +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. + 2005-10-16 Philip Langdale <philipl@mail.utexas.edu> * configure.ac: Add another necessary mozilla include subdir to diff --git a/data/ui/epiphany-bookmark-editor-ui.xml b/data/ui/epiphany-bookmark-editor-ui.xml index 9002767bf..79bb82e49 100644 --- a/data/ui/epiphany-bookmark-editor-ui.xml +++ b/data/ui/epiphany-bookmark-editor-ui.xml @@ -10,7 +10,6 @@ <menuitem name="FileRename" action="Rename"/> <menuitem name="FileDelete" action="Delete"/> <separator name="FileSep3"/> - <menuitem name="FileShowInBookmarksBar" action="ShowInBookmarksBar"/> <menuitem name="FileProperties" action="Properties"/> <separator name="FileSep4"/> <menuitem name="FileImport" action="Import"/> @@ -47,16 +46,12 @@ <menuitem name="RenameBMK" action="Rename"/> <menuitem name="DeleteBMK" action="Delete"/> <separator name="BookmarksPopupSep3"/> - <menuitem name="ShowInBookmarksBarBMK" action="ShowInBookmarksBar"/> - <separator name="BookmarksPopupSep4"/> <menuitem name="BMKProperties" action="Properties"/> </popup> <popup name="EphyBookmarkKeywordPopup" action="PopupAction"> <menuitem name="RenameTPC" action="Rename"/> <menuitem name="DeleteTPC" action="Delete"/> - <separator name="TopicPopupSep3"/> - <menuitem name="ShowInBookmarksBarTPC" action="ShowInBookmarksBar"/> </popup> </ui> diff --git a/data/ui/epiphany-ui.xml b/data/ui/epiphany-ui.xml index b7c3b4a1a..1e30279c5 100644 --- a/data/ui/epiphany-ui.xml +++ b/data/ui/epiphany-ui.xml @@ -38,7 +38,6 @@ <menu name="ViewMenu" action="View"> <placeholder name="ViewTogglesGroup" position="top"> <menuitem name="ViewToolbarMenu" action="ViewToolbar"/> - <menuitem name="ViewBookmarksBarMenu" action="ViewBookmarksBar"/> <menuitem name="ViewStatusbarMenu" action="ViewStatusbar"/> </placeholder> <separator name="ViewSep1"/> diff --git a/lib/egg/egg-editable-toolbar.c b/lib/egg/egg-editable-toolbar.c index 006df26a7..87b26b3bd 100755 --- a/lib/egg/egg-editable-toolbar.c +++ b/lib/egg/egg-editable-toolbar.c @@ -32,20 +32,27 @@ #include <gtk/gtkdnd.h> #include <gtk/gtkhbox.h> #include <gtk/gtkimage.h> +#include <gtk/gtkcheckmenuitem.h> #include <gtk/gtkimagemenuitem.h> +#include <gtk/gtkseparatormenuitem.h> #include <gtk/gtkmenu.h> #include <gtk/gtkstock.h> +#include <gtk/gtklabel.h> +#include <gtk/gtkbutton.h> #include <gtk/gtktoolbar.h> #include <gtk/gtktoolitem.h> +#include <gtk/gtktoolbutton.h> #include <gtk/gtkseparatortoolitem.h> #include <glib/gi18n.h> #include <string.h> static void egg_editable_toolbar_class_init (EggEditableToolbarClass *klass); -static void egg_editable_toolbar_init (EggEditableToolbar *t); +static void egg_editable_toolbar_init (EggEditableToolbar *etoolbar); static void egg_editable_toolbar_finalize (GObject *object); #define MIN_TOOLBAR_HEIGHT 20 +#define EGG_ITEM_NAME "egg-item-name" +#define EGG_TOOLITEM "egg-toolitem" static const GtkTargetEntry dest_drag_types[] = { {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0}, @@ -74,13 +81,13 @@ struct _EggEditableToolbarPrivate { GtkUIManager *manager; EggToolbarsModel *model; - gboolean edit_mode; - GtkWidget *selected_toolbar; + guint edit_mode; + gboolean save_hidden; GtkWidget *fixed_toolbar; - gboolean pending; - GtkToolbar *target_toolbar; - GtkWidget *dragged_item; + guint dnd_pending; + GtkToolbar *dnd_toolbar; + GtkToolItem *dnd_toolitem; }; GType @@ -111,19 +118,25 @@ egg_editable_toolbar_get_type (void) } static int -get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar) +get_dock_position (EggEditableToolbar *etoolbar, GtkWidget *dock) { GList *l; int result; l = gtk_container_get_children (GTK_CONTAINER (etoolbar)); - result = g_list_index (l, toolbar->parent); + result = g_list_index (l, dock); g_list_free (l); return result; } static int +get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar) +{ + return get_dock_position (etoolbar, toolbar->parent); +} + +static int get_n_toolbars (EggEditableToolbar *etoolbar) { GList *l; @@ -159,6 +172,7 @@ get_toolbar_nth (EggEditableToolbar *etoolbar, GtkWidget *result; dock = get_dock_nth (etoolbar, position); + g_return_val_if_fail (dock != NULL, NULL); l = gtk_container_get_children (GTK_CONTAINER (dock)); result = GTK_WIDGET (l->data); @@ -168,13 +182,13 @@ get_toolbar_nth (EggEditableToolbar *etoolbar, } static GtkAction * -find_action (EggEditableToolbar *t, +find_action (EggEditableToolbar *etoolbar, const char *name) { GList *l; GtkAction *action = NULL; - l = gtk_ui_manager_get_action_groups (t->priv->manager); + l = gtk_ui_manager_get_action_groups (etoolbar->priv->manager); g_return_val_if_fail (name != NULL, NULL); @@ -197,6 +211,8 @@ drag_data_delete_cb (GtkWidget *widget, { int pos, toolbar_pos; + widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); + g_return_if_fail (widget != NULL); g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar)); pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (widget->parent), @@ -212,7 +228,9 @@ drag_begin_cb (GtkWidget *widget, GdkDragContext *context, EggEditableToolbar *etoolbar) { - gtk_widget_hide (widget); + widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); + g_return_if_fail (widget != NULL); + gtk_widget_hide (widget); } static void @@ -220,7 +238,9 @@ drag_end_cb (GtkWidget *widget, GdkDragContext *context, EggEditableToolbar *etoolbar) { - gtk_widget_show (widget); + widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); + g_return_if_fail (widget != NULL); + gtk_widget_show (widget); } static void @@ -231,223 +251,481 @@ drag_data_get_cb (GtkWidget *widget, guint32 time, EggEditableToolbar *etoolbar) { - const char *id, *type; - char *target; + EggToolbarsModel *model; + const char *name; + char *data; + widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); + g_return_if_fail (widget != NULL); + g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar)); - - type = g_object_get_data (G_OBJECT (widget), "type"); - id = g_object_get_data (G_OBJECT (widget), "id"); - if (strcmp (id, "separator") == 0) + model = egg_editable_toolbar_get_model (etoolbar); + + name = g_object_get_data (G_OBJECT (widget), EGG_ITEM_NAME); + if (name == NULL) { - target = g_strdup (id); + name = g_object_get_data (G_OBJECT (gtk_widget_get_parent (widget)), EGG_ITEM_NAME); + g_return_if_fail (name != NULL); } - else + + data = egg_toolbars_model_get_data (model, selection_data->target, name); + if (data != NULL) { - target = egg_toolbars_model_get_item_data (etoolbar->priv->model, - type, id); + gtk_selection_data_set (selection_data, selection_data->target, 8, (unsigned char *)data, strlen (data)); + g_free (data); } +} - gtk_selection_data_set (selection_data, - selection_data->target, 8, - (const guchar *)target, strlen (target)); - - g_free (target); +static void +move_item_cb (GtkWidget *menuitem, + EggEditableToolbar *etoolbar) +{ + GtkWidget *toolitem = g_object_get_data (G_OBJECT (menuitem), EGG_TOOLITEM); + GtkTargetList *list = gtk_target_list_new (dest_drag_types, G_N_ELEMENTS (dest_drag_types)); + gtk_drag_begin (toolitem, list, GDK_ACTION_MOVE, 1, NULL); + gtk_target_list_unref (list); } static void -set_drag_cursor (GtkWidget *widget) +set_dock_visible (EggEditableToolbar *etoolbar, + GtkWidget *dock, + gboolean visible) { - if (widget->window) + if (visible) { - GdkCursor *cursor; - GdkPixbuf *pixbuf; - - pixbuf = gdk_pixbuf_new_from_file (CURSOR_DIR "/hand-open.png", NULL); - cursor = gdk_cursor_new_from_pixbuf (gdk_display_get_default (), - pixbuf, 12, 12); - gdk_window_set_cursor (widget->window, cursor); - gdk_cursor_unref (cursor); - g_object_unref (pixbuf); + gtk_widget_show (dock); + } + else + { + gtk_widget_hide (dock); + } + + if (etoolbar->priv->save_hidden) + { + int position = get_dock_position (etoolbar, dock); + EggTbModelFlags flags = egg_toolbars_model_get_flags + (etoolbar->priv->model, position); + + if (visible) + { + flags &= ~(EGG_TB_MODEL_HIDDEN); + } + else + { + flags |= (EGG_TB_MODEL_HIDDEN); + } + + egg_toolbars_model_set_flags (etoolbar->priv->model, position, flags); } } static void -unset_drag_cursor (GtkWidget *widget) +remove_item_cb (GtkWidget *menuitem, + EggEditableToolbar *etoolbar) { - if (widget->window) + GtkWidget *toolitem = g_object_get_data (G_OBJECT (menuitem), EGG_TOOLITEM); + int pos, toolbar_pos; + + toolbar_pos = get_toolbar_position (etoolbar, toolitem->parent); + pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolitem->parent), + GTK_TOOL_ITEM (toolitem)); + + egg_toolbars_model_remove_item (etoolbar->priv->model, + toolbar_pos, pos); + + if (egg_toolbars_model_n_items (etoolbar->priv->model, toolbar_pos) == 0) { - gdk_window_set_cursor (widget->window, NULL); + egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); } } static void -set_item_drag_source (EggToolbarsModel *model, - GtkWidget *item, - GtkAction *action, - gboolean is_separator, - const char *type) +remove_toolbar_cb (GtkWidget *menuitem, + EggEditableToolbar *etoolbar) { - GtkTargetEntry target_entry; - const char *id; + GtkWidget *toolbar = g_object_get_data (G_OBJECT (menuitem), "egg-toolbar"); + int toolbar_pos; - target_entry.target = (char *)type; - target_entry.flags = GTK_TARGET_SAME_APP; - target_entry.info = 0; + toolbar_pos = get_toolbar_position (etoolbar, toolbar); + egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); +} - gtk_drag_source_set (item, GDK_BUTTON1_MASK, - &target_entry, 1, - GDK_ACTION_MOVE); +static void +toggle_visibility_cb (GtkWidget *menuitem, + EggEditableToolbar *etoolbar) +{ + GtkWidget *dock = g_object_get_data (G_OBJECT (menuitem), "egg-dock"); + set_dock_visible (etoolbar, dock, !GTK_WIDGET_VISIBLE (dock)); +} - if (is_separator) - { - GtkWidget *icon; - GdkPixbuf *pixbuf; +static void +egg_editable_toolbar_add_visibility_items (EggEditableToolbar *etoolbar, + GtkMenu *popup) +{ + EggToolbarsModel *model = etoolbar->priv->model; + GtkCheckMenuItem *item; + GtkWidget *dock; + int n_toolbars, n_items, n_visible = 0; + int i, j, k, l; - id = "separator"; + g_return_if_fail (model != NULL); + g_return_if_fail (etoolbar->priv->manager != NULL); - icon = _egg_editable_toolbar_new_separator_image (); - pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (icon)); - gtk_drag_source_set_icon_pixbuf (item, pixbuf); + n_toolbars = egg_toolbars_model_n_toolbars (model); + + for (i = 0; i < n_toolbars; i++) + { + dock = get_dock_nth (etoolbar, i); + if (GTK_WIDGET_VISIBLE (dock)) + n_visible++; } - else + + if (GTK_MENU_SHELL(popup)->children != NULL) { - const char *stock_id; - GValue value = { 0, }; - GdkPixbuf *pixbuf; + GtkWidget *separator = gtk_separator_menu_item_new (); + gtk_widget_show (separator); + gtk_menu_shell_append (GTK_MENU_SHELL (popup), separator); + } + + for (i = 0; i < n_toolbars; i++) + { + char buffer[40] = "Empty"; - id = gtk_action_get_name (action); + n_items = egg_toolbars_model_n_items (model, i); + for (k = 0, j = 0; j < n_items && k < sizeof(buffer)-1; j++) + { + GValue value = { 0, }; + GtkAction *action; + const char *name; + + name = egg_toolbars_model_item_nth (model, i, j); + if (name == NULL) continue; + action = find_action (etoolbar, name); + if (action == NULL) continue; + + g_value_init (&value, G_TYPE_STRING); + g_object_get_property (G_OBJECT (action), "label", &value); + name = g_value_get_string (&value); + if (name == NULL) continue; + + if (j > 0) + { + if(k<sizeof(buffer)-1) buffer[k++] = ','; + if(k<sizeof(buffer)-1) buffer[k++] = ' '; + } + + for (l = 0; name[l] && k<sizeof(buffer)-1; l++) + { + switch(name[l]) + { + case '_': + case '.': + case ',': + break; + default: + buffer[k++] = name[l]; + } + } + + if (name[l]) + { + l = k-5; + while(l>0 && buffer[l] != ',') l--; + if(buffer[l] == ',') k = l + 2; + else k = k-3; + + buffer[k++] = '.'; + buffer[k++] = '.'; + buffer[k++] = '.'; + buffer[k] = 0; + break; + } + + buffer[k] = 0; - g_value_init (&value, G_TYPE_STRING); - g_object_get_property (G_OBJECT (action), "stock_id", &value); - stock_id = g_value_get_string (&value); + g_value_unset (&value); + } + + + dock = get_dock_nth (etoolbar, i); + item = GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (buffer)); + gtk_check_menu_item_set_active (item, GTK_WIDGET_VISIBLE (dock)); + gtk_widget_set_sensitive (GTK_WIDGET (item), (n_visible > 1 || !GTK_WIDGET_VISIBLE (dock))); + gtk_widget_show (GTK_WIDGET (item)); + gtk_menu_shell_append (GTK_MENU_SHELL (popup), GTK_WIDGET (item)); + + g_object_set_data (G_OBJECT (item), "egg-dock", dock); + g_signal_connect (item, "toggled", + G_CALLBACK (toggle_visibility_cb), + etoolbar); + } +} - if (stock_id != NULL) +void +egg_editable_toolbar_add_popup_items (GtkWidget *widget, + GtkMenu *popup) +{ + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR + (gtk_widget_get_ancestor (widget, EGG_TYPE_EDITABLE_TOOLBAR)); + GtkWidget *toolbar = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOLBAR); + GtkWidget *toolitem = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); + GtkWidget *item, *image; + int separated; + + separated = (GTK_MENU_SHELL(popup)->children == NULL); + + if (etoolbar != NULL && toolitem != NULL) + { + if (!separated) { - pixbuf = gtk_widget_render_icon (item, stock_id, - GTK_ICON_SIZE_LARGE_TOOLBAR, NULL); + item = gtk_separator_menu_item_new (); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); + separated = 1; } - else + + item = gtk_menu_item_new_with_mnemonic (_("_Move on Toolbar")); + g_object_set_data (G_OBJECT (item), EGG_TOOLITEM, toolitem); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); + g_signal_connect (item, "activate", + G_CALLBACK (move_item_cb), + etoolbar); + + item = gtk_image_menu_item_new_with_mnemonic (_("_Remove from Toolbar")); + g_object_set_data (G_OBJECT (item), EGG_TOOLITEM, toolitem); + 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_menu_shell_append (GTK_MENU_SHELL (popup), item); + g_signal_connect (item, "activate", + G_CALLBACK (remove_item_cb), + etoolbar); + } + + if (etoolbar != NULL && toolbar != NULL) + { + int position; + EggTbModelFlags flags; + + position = get_toolbar_position (etoolbar, toolbar); + flags = egg_toolbars_model_get_flags (etoolbar->priv->model, position); + + if (etoolbar->priv->edit_mode > 0 && (flags & EGG_TB_MODEL_NOT_REMOVABLE)==0) { - pixbuf = gtk_widget_render_icon (item, GTK_STOCK_DND, - GTK_ICON_SIZE_LARGE_TOOLBAR, NULL); + if (!separated) + { + item = gtk_separator_menu_item_new (); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); + separated = 1; + } + + item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Toolbar")); + g_object_set_data (G_OBJECT (item), "egg-toolbar", 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_menu_shell_append (GTK_MENU_SHELL (popup), item); + g_signal_connect (item, "activate", + G_CALLBACK (remove_toolbar_cb), + etoolbar); } - gtk_drag_source_set_icon_pixbuf (item, pixbuf); - g_object_unref (pixbuf); - - g_value_unset (&value); + if (egg_toolbars_model_n_toolbars (etoolbar->priv->model) > 1) + { + egg_editable_toolbar_add_visibility_items (etoolbar, popup); + } } +} - g_object_set_data_full (G_OBJECT (item), "id", - g_strdup (id), g_free); - g_object_set_data_full (G_OBJECT (item), "type", - g_strdup (type), g_free); +static void +popup_context_menu_cb (GtkWidget *toolbar, + gint x, + gint y, + gint button_number, + EggEditableToolbar *etoolbar) +{ + GtkMenu *menu = GTK_MENU (gtk_menu_new ()); + egg_editable_toolbar_add_popup_items (toolbar, menu); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button_number, + gtk_get_current_event_time ()); } -static GtkWidget * -create_item_from_action (EggEditableToolbar *t, - const char *action_name, - const char *type, - gboolean is_separator, - GtkAction **ret_action) +static gboolean +button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + EggEditableToolbar *etoolbar) +{ + if (event->button == 3) + { + GtkMenu *menu = GTK_MENU (gtk_menu_new ()); + egg_editable_toolbar_add_popup_items (widget, menu); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, + event->time); + return TRUE; + } + + return FALSE; +} + +static void +configure_item_sensitivity (GtkToolItem *item, EggEditableToolbar *etoolbar) { - GtkWidget *item; GtkAction *action; + char *name; + + g_return_if_fail (etoolbar != NULL); + + if (etoolbar->priv->edit_mode > 0) + { + GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (item), GTK_SENSITIVE); + gtk_tool_item_set_use_drag_window (item, TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); + return; + } + + name = g_object_get_data (G_OBJECT (item), EGG_ITEM_NAME); + action = name ? find_action (etoolbar, name) : NULL; - if (is_separator) + if (action != NULL && gtk_action_is_sensitive (action)) { - item = GTK_WIDGET (gtk_separator_tool_item_new ()); - action = NULL; + GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (item), GTK_SENSITIVE); + gtk_tool_item_set_use_drag_window (item, FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); } else { - g_return_val_if_fail (action_name != NULL, NULL); - - g_signal_emit (G_OBJECT (t), egg_editable_toolbar_signals[ACTION_REQUEST], - 0, action_name); - - action = find_action (t, action_name); - if (action) - { - item = gtk_action_create_tool_item (action); - } - else - { - return NULL; - } + gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE); + gtk_tool_item_set_use_drag_window (item, TRUE); + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (item), GTK_SENSITIVE); } +} - gtk_widget_show (item); +static void +configure_item_cursor (GtkToolItem *item, EggEditableToolbar *etoolbar) +{ + g_return_if_fail (etoolbar != NULL); + g_return_if_fail (GTK_WIDGET(item)->window != NULL); + + if (etoolbar->priv->edit_mode > 0) + { + GdkCursor *cursor; + GdkPixbuf *pixbuf; + + pixbuf = gdk_pixbuf_new_from_file (CURSOR_DIR "/hand-open.png", NULL); + cursor = gdk_cursor_new_from_pixbuf (gdk_display_get_default (), + pixbuf, 12, 12); + gdk_window_set_cursor (GTK_WIDGET(item)->window, cursor); + gdk_cursor_unref (cursor); + g_object_unref (pixbuf); - g_signal_connect (item, "drag_begin", - G_CALLBACK (drag_begin_cb), t); - g_signal_connect (item, "drag_end", - G_CALLBACK (drag_end_cb), t); - g_signal_connect (item, "drag_data_get", - G_CALLBACK (drag_data_get_cb), t); - g_signal_connect (item, "drag_data_delete", - G_CALLBACK (drag_data_delete_cb), t); + gtk_drag_source_set (GTK_WIDGET (item), GDK_BUTTON1_MASK, dest_drag_types, + G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); + } + else + { + gdk_window_set_cursor (GTK_WIDGET(item)->window, NULL); + + gtk_drag_source_set (GTK_WIDGET (item), GDK_BUTTON2_MASK, dest_drag_types, + G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); + } +} - if (t->priv->edit_mode) +static void +connect_widget_signals (GtkWidget *proxy, EggEditableToolbar *etoolbar) +{ + if (GTK_IS_CONTAINER (proxy)) { - set_drag_cursor (item); - gtk_widget_set_sensitive (item, TRUE); - set_item_drag_source (t->priv->model, item, action, - is_separator, type); - gtk_tool_item_set_use_drag_window (GTK_TOOL_ITEM (item), TRUE); + gtk_container_foreach (GTK_CONTAINER (proxy), + (GtkCallback) connect_widget_signals, + (gpointer) etoolbar); } - if (ret_action) + if (GTK_IS_BUTTON (proxy) || GTK_IS_TOOL_ITEM (proxy)) { - *ret_action = action; + g_signal_connect (proxy, "drag_begin", + G_CALLBACK (drag_begin_cb), etoolbar); + g_signal_connect (proxy, "drag_end", + G_CALLBACK (drag_end_cb), etoolbar); + g_signal_connect (proxy, "drag_data_get", + G_CALLBACK (drag_data_get_cb), etoolbar); + g_signal_connect (proxy, "drag_data_delete", + G_CALLBACK (drag_data_delete_cb), etoolbar); + g_signal_connect (proxy, "drag_data_get", + G_CALLBACK (drag_data_get_cb), etoolbar); + g_signal_connect (proxy, "button-press-event", + G_CALLBACK (button_press_event_cb), etoolbar); + gtk_drag_source_set (proxy, GDK_BUTTON2_MASK, dest_drag_types, + G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); } +} - return item; +static void +action_sensitive_cb (GtkAction *action, + GParamSpec *pspec, + GtkToolItem *item) +{ + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR + (gtk_widget_get_ancestor (GTK_WIDGET (item), EGG_TYPE_EDITABLE_TOOLBAR)); + configure_item_sensitivity (item, etoolbar); } -static GtkWidget * -create_item (EggEditableToolbar *t, - EggToolbarsModel *model, - int toolbar_position, - int position, - GtkAction **ret_action) +static GtkToolItem * +create_item_from_action (EggEditableToolbar *etoolbar, + const char *name) { - const char *action_name, *type; - gboolean is_separator; + GtkToolItem *item; + + g_return_val_if_fail (name != NULL, NULL); + + if (strcmp (name, "_separator") == 0) + { + item = gtk_separator_tool_item_new (); + gtk_tool_item_set_use_drag_window (item, TRUE); + } + else + { + GtkAction *action = find_action (etoolbar, name); + g_return_val_if_fail (action != NULL, NULL); + item = GTK_TOOL_ITEM (gtk_action_create_tool_item (action)); + + g_signal_connect_object (action, "notify::sensitive", + G_CALLBACK (action_sensitive_cb), item, 0); + } - egg_toolbars_model_item_nth (model, toolbar_position, position, - &is_separator, &action_name, &type); - return create_item_from_action (t, action_name, type, - is_separator, ret_action); + gtk_widget_show (GTK_WIDGET (item)); + + g_object_set_data_full (G_OBJECT (item), EGG_ITEM_NAME, + g_strdup (name), g_free); + + return item; } -static gboolean -data_is_separator (const char *data) +static GtkToolItem * +create_item_from_position (EggEditableToolbar *etoolbar, + int toolbar_position, + int position) { - return strcmp (data, "separator") == 0; + GtkToolItem *item; + const char *name; + + name = egg_toolbars_model_item_nth (etoolbar->priv->model, toolbar_position, position); + item = create_item_from_action (etoolbar, name); + + return item; } static void -drag_data_received_cb (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time, - EggEditableToolbar *etoolbar) +toolbar_drag_data_received_cb (GtkToolbar *toolbar, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + EggEditableToolbar *etoolbar) { - char *type; - char *id; - - GdkAtom target; - - target = gtk_drag_dest_find_target (widget, context, NULL); - type = egg_toolbars_model_get_item_type (etoolbar->priv->model, target); - id = egg_toolbars_model_get_item_id (etoolbar->priv->model, type, - (const char*)selection_data->data); - /* This function can be called for two reasons * * (1) drag_motion() needs an item to pass to @@ -459,113 +737,60 @@ drag_data_received_cb (GtkWidget *widget, * actually add a new item to the toolbar. */ - if (id == NULL) + GdkAtom type = selection_data->type; + const char *data = (char *)selection_data->data; + + int ipos = -1; + char *name = NULL; + + /* Find out where the drop is occuring, and the name of what is being dropped. */ + if (selection_data->length >= 0) { - etoolbar->priv->pending = FALSE; - g_free (type); - return; + ipos = gtk_toolbar_get_drop_index (toolbar, x, y); + name = egg_toolbars_model_get_name (etoolbar->priv->model, type, data, FALSE); } - if (etoolbar->priv->pending) + /* If we just want a highlight item, then . */ + if (etoolbar->priv->dnd_pending > 0) { - etoolbar->priv->pending = FALSE; - etoolbar->priv->dragged_item = - create_item_from_action (etoolbar, id, type, - data_is_separator (id), NULL); - g_object_ref (etoolbar->priv->dragged_item); - gtk_object_sink (GTK_OBJECT (etoolbar->priv->dragged_item)); - } - else - { - int pos, toolbar_pos; - - pos = gtk_toolbar_get_drop_index (GTK_TOOLBAR (widget), x, y); - toolbar_pos = get_toolbar_position (etoolbar, widget); - - if (data_is_separator ((const char*)selection_data->data)) - { - egg_toolbars_model_add_separator (etoolbar->priv->model, - toolbar_pos, pos); - } - else - { - egg_toolbars_model_add_item (etoolbar->priv->model, - toolbar_pos, pos, id, type); - } + etoolbar->priv->dnd_pending--; - gtk_drag_finish (context, TRUE, context->action == GDK_ACTION_MOVE, - time); - } - - g_free (type); - g_free (id); -} - -static void -remove_toolbar_cb (GtkWidget *menuitem, - EggEditableToolbar *etoolbar) -{ - int pos; - - pos = get_toolbar_position (etoolbar, etoolbar->priv->selected_toolbar); - egg_toolbars_model_remove_toolbar (etoolbar->priv->model, pos); -} - -static void -popup_toolbar_context_menu_cb (GtkWidget *toolbar, - gint x, - gint y, - gint button_number, - EggEditableToolbar *t) -{ - GtkWidget *menu; - GtkWidget *item; - GtkWidget *image; - - if (t->priv->edit_mode) - { - EggTbModelFlags flags; - int position; - - t->priv->selected_toolbar = toolbar; - - menu = gtk_menu_new (); - - item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Toolbar")); - gtk_widget_show (item); - image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); - gtk_widget_show (image); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - g_signal_connect (item, "activate", - G_CALLBACK (remove_toolbar_cb), - t); - - position = get_toolbar_position (t, toolbar); - flags = egg_toolbars_model_get_flags (t->priv->model, position); - if (flags & EGG_TB_MODEL_NOT_REMOVABLE) + if (name != NULL && etoolbar->priv->dnd_toolbar == toolbar) { - gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE); + etoolbar->priv->dnd_toolitem = create_item_from_action (etoolbar, name); + gtk_toolbar_set_drop_highlight_item (etoolbar->priv->dnd_toolbar, + etoolbar->priv->dnd_toolitem, ipos); } - - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 2, - gtk_get_current_event_time ()); } -} - -static void -free_dragged_item (EggEditableToolbar *etoolbar) -{ - if (etoolbar->priv->dragged_item) + else { - gtk_widget_destroy (etoolbar->priv->dragged_item); - g_object_unref (etoolbar->priv->dragged_item); - etoolbar->priv->dragged_item = NULL; + gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0); + etoolbar->priv->dnd_toolbar = NULL; + etoolbar->priv->dnd_toolitem = NULL; + + /* If we don't have a name to use yet, try to create one. */ + if (name == NULL && selection_data->length >= 0) + { + name = egg_toolbars_model_get_name (etoolbar->priv->model, type, data, TRUE); + } + + if (name != NULL) + { + gint tpos = get_toolbar_position (etoolbar, GTK_WIDGET (toolbar)); + egg_toolbars_model_add_item (etoolbar->priv->model, tpos, ipos, name); + gtk_drag_finish (context, TRUE, context->action == GDK_ACTION_MOVE, time); + } + else + { + gtk_drag_finish (context, FALSE, context->action == GDK_ACTION_MOVE, time); + } } + + g_free (name); } static gboolean -toolbar_drag_drop_cb (GtkWidget *widget, +toolbar_drag_drop_cb (GtkToolbar *toolbar, GdkDragContext *context, gint x, gint y, @@ -574,88 +799,46 @@ toolbar_drag_drop_cb (GtkWidget *widget, { GdkAtom target; - target = gtk_drag_dest_find_target (widget, context, NULL); + target = gtk_drag_dest_find_target (GTK_WIDGET (toolbar), context, NULL); if (target != GDK_NONE) { - gtk_drag_get_data (widget, context, - target, - time); + gtk_drag_get_data (GTK_WIDGET (toolbar), context, target, time); return TRUE; } - free_dragged_item (etoolbar); - return FALSE; } static gboolean -toolbar_drag_motion_cb (GtkWidget *widget, +toolbar_drag_motion_cb (GtkToolbar *toolbar, GdkDragContext *context, gint x, gint y, guint time, EggEditableToolbar *etoolbar) { - GdkAtom target; - int index; - GtkToolbar *toolbar = GTK_TOOLBAR (widget); - GtkToolItem *item; - GtkWidget *source; - - source = gtk_drag_get_source_widget (context); - if (source) - { - EggTbModelFlags flags; - int pos; - gboolean is_item; - - pos = get_toolbar_position (etoolbar, widget); - flags = egg_toolbars_model_get_flags (etoolbar->priv->model, pos); - - is_item = etoolbar->priv->edit_mode && - (gtk_widget_get_ancestor (source, EGG_TYPE_EDITABLE_TOOLBAR) || - gtk_widget_get_ancestor (source, EGG_TYPE_TOOLBAR_EDITOR)); - - if ((flags & EGG_TB_MODEL_ACCEPT_ITEMS_ONLY) && !is_item) - { - gdk_drag_status (context, 0, time); - return FALSE; - } - - if (gtk_widget_is_ancestor (source, widget)) - { - context->suggested_action = GDK_ACTION_MOVE; - } - } - - target = gtk_drag_dest_find_target (widget, context, NULL); + GdkAtom target = gtk_drag_dest_find_target (GTK_WIDGET (toolbar), context, NULL); if (target == GDK_NONE) { gdk_drag_status (context, 0, time); return FALSE; } - if (etoolbar->priv->target_toolbar != toolbar) + /* Make ourselves the current dnd toolbar, and request a highlight item. */ + if (etoolbar->priv->dnd_toolbar != toolbar) { - if (etoolbar->priv->target_toolbar) - gtk_toolbar_set_drop_highlight_item - (etoolbar->priv->target_toolbar, NULL, 0); - - free_dragged_item (etoolbar); - etoolbar->priv->pending = TRUE; - - etoolbar->priv->target_toolbar = toolbar; - - gtk_drag_get_data (widget, context, target, time); + etoolbar->priv->dnd_toolbar = toolbar; + etoolbar->priv->dnd_toolitem = NULL; + etoolbar->priv->dnd_pending++; + gtk_drag_get_data (GTK_WIDGET (toolbar), context, target, time); } - - if (etoolbar->priv->dragged_item != NULL && - etoolbar->priv->edit_mode) + + /* If a highlight item is available, use it. */ + else if (etoolbar->priv->dnd_toolitem) { - item = GTK_TOOL_ITEM (etoolbar->priv->dragged_item); - - index = gtk_toolbar_get_drop_index (toolbar, x, y); - gtk_toolbar_set_drop_highlight_item (toolbar, item, index); + gint ipos = gtk_toolbar_get_drop_index (etoolbar->priv->dnd_toolbar, x, y); + gtk_toolbar_set_drop_highlight_item (etoolbar->priv->dnd_toolbar, + etoolbar->priv->dnd_toolitem, ipos); } gdk_drag_status (context, context->suggested_action, time); @@ -669,53 +852,68 @@ toolbar_drag_leave_cb (GtkToolbar *toolbar, guint time, EggEditableToolbar *etoolbar) { - /* This is a workaround for bug 125557. Sometimes - * we seemingly enter another toolbar *before* leaving - * the current one. - * - * In that case etoolbar->priv->target_toolbar will - * have been set to something else and the highlighting - * will already have been turned off - */ - - if (etoolbar->priv->target_toolbar == toolbar) - { - gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0); + gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0); - etoolbar->priv->target_toolbar = NULL; - free_dragged_item (etoolbar); + /* If we were the current dnd toolbar target, remove the item. */ + if (etoolbar->priv->dnd_toolbar == toolbar) + { + etoolbar->priv->dnd_toolbar = NULL; + etoolbar->priv->dnd_toolitem = NULL; } } +static void +configure_drag_dest (EggEditableToolbar *etoolbar, + GtkToolbar *toolbar) +{ + EggToolbarsItemType *type; + GtkTargetList *targets; + GList *list; + + /* Make every toolbar able to receive drag-drops. */ + gtk_drag_dest_set (GTK_WIDGET (toolbar), 0, + dest_drag_types, G_N_ELEMENTS (dest_drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); + + /* Add any specialist drag-drop abilities. */ + targets = gtk_drag_dest_get_target_list (GTK_WIDGET (toolbar)); + list = egg_toolbars_model_get_types (etoolbar->priv->model); + while (list) + { + type = list->data; + if (type->new_name != NULL || type->get_name != NULL) + gtk_target_list_add (targets, type->type, 0, 0); + list = list->next; + } +} + + static GtkWidget * -create_dock (EggEditableToolbar *t) +create_dock (EggEditableToolbar *etoolbar) { GtkWidget *toolbar, *hbox; hbox = gtk_hbox_new (0, FALSE); - gtk_widget_show (hbox); toolbar = gtk_toolbar_new (); gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), TRUE); gtk_widget_show (toolbar); gtk_box_pack_start (GTK_BOX (hbox), toolbar, TRUE, TRUE, 0); - gtk_drag_dest_set (toolbar, 0, - dest_drag_types, G_N_ELEMENTS (dest_drag_types), - GDK_ACTION_MOVE | GDK_ACTION_COPY); - g_signal_connect (toolbar, "drag_drop", - G_CALLBACK (toolbar_drag_drop_cb), t); + G_CALLBACK (toolbar_drag_drop_cb), etoolbar); g_signal_connect (toolbar, "drag_motion", - G_CALLBACK (toolbar_drag_motion_cb), t); + G_CALLBACK (toolbar_drag_motion_cb), etoolbar); g_signal_connect (toolbar, "drag_leave", - G_CALLBACK (toolbar_drag_leave_cb), t); + G_CALLBACK (toolbar_drag_leave_cb), etoolbar); g_signal_connect (toolbar, "drag_data_received", - G_CALLBACK (drag_data_received_cb), t); + G_CALLBACK (toolbar_drag_data_received_cb), etoolbar); g_signal_connect (toolbar, "popup_context_menu", - G_CALLBACK (popup_toolbar_context_menu_cb), t); + G_CALLBACK (popup_context_menu_cb), etoolbar); + configure_drag_dest (etoolbar, GTK_TOOLBAR (toolbar)); + return hbox; } @@ -737,14 +935,14 @@ unset_fixed_style (EggEditableToolbar *t) static void toolbar_changed_cb (EggToolbarsModel *model, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { GtkWidget *toolbar; EggTbModelFlags flags; GtkToolbarStyle style; flags = egg_toolbars_model_get_flags (model, position); - toolbar = get_toolbar_nth (t, position); + toolbar = get_toolbar_nth (etoolbar, position); if (flags & EGG_TB_MODEL_ICONS) { @@ -765,28 +963,28 @@ toolbar_changed_cb (EggToolbarsModel *model, else { gtk_toolbar_unset_style (GTK_TOOLBAR (toolbar)); - if (position == 0 && t->priv->fixed_toolbar) + if (position == 0 && etoolbar->priv->fixed_toolbar) { - unset_fixed_style (t); + unset_fixed_style (etoolbar); } return; } gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), style); - if (position == 0 && t->priv->fixed_toolbar) + if (position == 0 && etoolbar->priv->fixed_toolbar) { - set_fixed_style (t, style); + set_fixed_style (etoolbar, style); } } static void -unparent_fixed (EggEditableToolbar *t) +unparent_fixed (EggEditableToolbar *etoolbar) { GtkWidget *toolbar, *dock; - g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar)); + g_return_if_fail (GTK_IS_TOOLBAR (etoolbar->priv->fixed_toolbar)); - toolbar = t->priv->fixed_toolbar; - dock = get_dock_nth (t, 0); + toolbar = etoolbar->priv->fixed_toolbar; + dock = get_dock_nth (etoolbar, 0); if (dock && toolbar->parent != NULL) { @@ -795,13 +993,13 @@ unparent_fixed (EggEditableToolbar *t) } static void -update_fixed (EggEditableToolbar *t) +update_fixed (EggEditableToolbar *etoolbar) { GtkWidget *toolbar, *dock; - if (!t->priv->fixed_toolbar) return; + if (!etoolbar->priv->fixed_toolbar) return; - toolbar = t->priv->fixed_toolbar; - dock = get_dock_nth (t, 0); + toolbar = etoolbar->priv->fixed_toolbar; + dock = get_dock_nth (etoolbar, 0); if (dock && toolbar && toolbar->parent == NULL) { @@ -817,97 +1015,103 @@ update_fixed (EggEditableToolbar *t) static void toolbar_added_cb (EggToolbarsModel *model, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { GtkWidget *dock; - dock = create_dock (t); + dock = create_dock (etoolbar); + if ((egg_toolbars_model_get_flags (model, position) & EGG_TB_MODEL_HIDDEN) == 0) + gtk_widget_show (dock); gtk_widget_set_size_request (dock, -1, MIN_TOOLBAR_HEIGHT); - gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (etoolbar), dock, TRUE, TRUE, 0); - gtk_box_reorder_child (GTK_BOX (t), dock, position); + gtk_box_reorder_child (GTK_BOX (etoolbar), dock, position); gtk_widget_show_all (dock); - update_fixed (t); + update_fixed (etoolbar); } static void toolbar_removed_cb (EggToolbarsModel *model, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { - GtkWidget *toolbar; + GtkWidget *dock; + int i; - if (position == 0 && t->priv->fixed_toolbar != NULL) + if (position == 0 && etoolbar->priv->fixed_toolbar != NULL) { - unparent_fixed (t); + unparent_fixed (etoolbar); } - toolbar = get_dock_nth (t, position); - gtk_widget_destroy (toolbar); + dock = get_dock_nth (etoolbar, position); + gtk_widget_destroy (dock); - update_fixed (t); + dock = NULL; + for (i = egg_toolbars_model_n_toolbars (model)-1; i >= 0; i--) + { + dock = get_dock_nth (etoolbar, i); + if (GTK_WIDGET_VISIBLE (dock)) break; + } + + if (i < 0 && dock != NULL) + { + set_dock_visible (etoolbar, dock, TRUE); + } + + update_fixed (etoolbar); } static void item_added_cb (EggToolbarsModel *model, - int toolbar_position, - int position, - EggEditableToolbar *t) + int tpos, + int ipos, + EggEditableToolbar *etoolbar) { GtkWidget *dock; GtkWidget *toolbar; - GtkWidget *item; - GtkAction *action; - - toolbar = get_toolbar_nth (t, toolbar_position); - item = create_item (t, model, toolbar_position, position, &action); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), - GTK_TOOL_ITEM (item), position); + GtkToolItem *item; - dock = get_dock_nth (t, toolbar_position); + toolbar = get_toolbar_nth (etoolbar, tpos); + item = create_item_from_position (etoolbar, tpos, ipos); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, ipos); + + connect_widget_signals (GTK_WIDGET (item), etoolbar); + configure_item_cursor (item, etoolbar); + configure_item_sensitivity (item, etoolbar); + + dock = get_dock_nth (etoolbar, tpos); gtk_widget_set_size_request (dock, -1, -1); gtk_widget_queue_resize_no_redraw (dock); - - /* FIXME Hack to make tooltip work from gtk */ - if (action) - { - g_object_notify (G_OBJECT (action), "tooltip"); - } } static void item_removed_cb (EggToolbarsModel *model, int toolbar_position, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { GtkWidget *toolbar; GtkWidget *item; - toolbar = get_toolbar_nth (t, toolbar_position); + toolbar = get_toolbar_nth (etoolbar, toolbar_position); item = GTK_WIDGET (gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), position)); g_return_if_fail (item != NULL); gtk_container_remove (GTK_CONTAINER (toolbar), item); - - if (egg_toolbars_model_n_items (model, toolbar_position) == 0) - { - egg_toolbars_model_remove_toolbar (model, toolbar_position); - } } static void -egg_editable_toolbar_construct (EggEditableToolbar *t) +egg_editable_toolbar_construct (EggEditableToolbar *etoolbar) { int i, l, n_items, n_toolbars; - EggToolbarsModel *model = t->priv->model; + EggToolbarsModel *model = etoolbar->priv->model; g_return_if_fail (model != NULL); - g_return_if_fail (t->priv->manager != NULL); + g_return_if_fail (etoolbar->priv->manager != NULL); n_toolbars = egg_toolbars_model_n_toolbars (model); @@ -915,26 +1119,24 @@ egg_editable_toolbar_construct (EggEditableToolbar *t) { GtkWidget *toolbar, *dock; - dock = create_dock (t); - gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0); - toolbar = get_toolbar_nth (t, i); + dock = create_dock (etoolbar); + if ((egg_toolbars_model_get_flags (model, i) & EGG_TB_MODEL_HIDDEN) == 0) + gtk_widget_show (dock); + gtk_box_pack_start (GTK_BOX (etoolbar), dock, TRUE, TRUE, 0); + toolbar = get_toolbar_nth (etoolbar, i); n_items = egg_toolbars_model_n_items (model, i); for (l = 0; l < n_items; l++) { - GtkWidget *item; - GtkAction *action; + GtkToolItem *item; - item = create_item (t, model, i, l, &action); + item = create_item_from_position (etoolbar, i, l); if (item) { - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), - GTK_TOOL_ITEM (item), l); - /* FIXME Hack to make tooltip work from gtk */ - if (action) - { - g_object_notify (G_OBJECT (action), "tooltip"); - } + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, l); + + connect_widget_signals (GTK_WIDGET (item), etoolbar); + configure_item_sensitivity (item, etoolbar); } else { @@ -950,12 +1152,12 @@ egg_editable_toolbar_construct (EggEditableToolbar *t) } } - update_fixed (t); + update_fixed (etoolbar); /* apply styles */ for (i = 0; i < n_toolbars; i ++) { - toolbar_changed_cb (model, i, t); + toolbar_changed_cb (model, i, etoolbar); } } @@ -1030,12 +1232,12 @@ egg_editable_toolbar_set_model (EggEditableToolbar *toolbar, } static void -egg_editable_toolbar_set_ui_manager (EggEditableToolbar *t, +egg_editable_toolbar_set_ui_manager (EggEditableToolbar *etoolbar, GtkUIManager *manager) { g_return_if_fail (GTK_IS_UI_MANAGER (manager)); - t->priv->manager = g_object_ref (manager); + etoolbar->priv->manager = g_object_ref (manager); } static void @@ -1044,15 +1246,15 @@ egg_editable_toolbar_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); switch (prop_id) { case PROP_UI_MANAGER: - egg_editable_toolbar_set_ui_manager (t, g_value_get_object (value)); + egg_editable_toolbar_set_ui_manager (etoolbar, g_value_get_object (value)); break; case PROP_TOOLBARS_MODEL: - egg_editable_toolbar_set_model (t, g_value_get_object (value)); + egg_editable_toolbar_set_model (etoolbar, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1066,15 +1268,15 @@ egg_editable_toolbar_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); switch (prop_id) { case PROP_UI_MANAGER: - g_value_set_object (value, t->priv->manager); + g_value_set_object (value, etoolbar->priv->manager); break; case PROP_TOOLBARS_MODEL: - g_value_set_object (value, t->priv->model); + g_value_set_object (value, etoolbar->priv->model); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1120,30 +1322,31 @@ egg_editable_toolbar_class_init (EggEditableToolbarClass *klass) } static void -egg_editable_toolbar_init (EggEditableToolbar *t) +egg_editable_toolbar_init (EggEditableToolbar *etoolbar) { - t->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (t); + etoolbar->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (etoolbar); + etoolbar->priv->save_hidden = TRUE; } static void egg_editable_toolbar_finalize (GObject *object) { - EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); - if (t->priv->fixed_toolbar) + if (etoolbar->priv->fixed_toolbar) { - g_object_unref (t->priv->fixed_toolbar); + g_object_unref (etoolbar->priv->fixed_toolbar); } - if (t->priv->manager) + if (etoolbar->priv->manager) { - g_object_unref (t->priv->manager); + g_object_unref (etoolbar->priv->manager); } - if (t->priv->model) + if (etoolbar->priv->model) { - egg_editable_toolbar_disconnect_model (t); - g_object_unref (t->priv->model); + egg_editable_toolbar_disconnect_model (etoolbar); + g_object_unref (etoolbar->priv->model); } G_OBJECT_CLASS (parent_class)->finalize (object); @@ -1170,55 +1373,52 @@ egg_editable_toolbar_new_with_model (GtkUIManager *manager, gboolean egg_editable_toolbar_get_edit_mode (EggEditableToolbar *etoolbar) { - return etoolbar->priv->edit_mode; + return (etoolbar->priv->edit_mode > 0); } void egg_editable_toolbar_set_edit_mode (EggEditableToolbar *etoolbar, gboolean mode) { - int i, l, n_toolbars, n_items; + int i, l, n_items; - etoolbar->priv->edit_mode = mode; - - n_toolbars = get_n_toolbars (etoolbar); - for (i = 0; i < n_toolbars; i++) + i = etoolbar->priv->edit_mode; + if (mode) { - GtkWidget *toolbar; - - toolbar = get_toolbar_nth (etoolbar, i); - n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)); - for (l = 0; l < n_items; l++) + etoolbar->priv->edit_mode++; + } + else + { + g_return_if_fail (etoolbar->priv->edit_mode > 0); + etoolbar->priv->edit_mode--; + } + i *= etoolbar->priv->edit_mode; + + if (i == 0) + { + for (i = get_n_toolbars (etoolbar)-1; i >= 0; i--) { - GtkToolItem *item; - const char *action_name, *type; - gboolean is_separator; - GtkAction *action = NULL; - - egg_toolbars_model_item_nth (etoolbar->priv->model, i, l, - &is_separator, &action_name, &type); - action = find_action (etoolbar, action_name); - - item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), l); - gtk_tool_item_set_use_drag_window (item, mode); - - if (mode) - { - set_drag_cursor (GTK_WIDGET (item)); - gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); - set_item_drag_source (etoolbar->priv->model, GTK_WIDGET (item), - action, is_separator, type); - } - else - { - unset_drag_cursor (GTK_WIDGET (item)); - gtk_drag_source_unset (GTK_WIDGET (item)); + GtkWidget *toolbar; + + toolbar = get_toolbar_nth (etoolbar, i); + n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)); - if (!is_separator) + if (n_items == 0 && etoolbar->priv->edit_mode == 0) + { + egg_toolbars_model_remove_toolbar (etoolbar->priv->model, i); + } + else + { + for (l = 0; l < n_items; l++) { - g_object_notify (G_OBJECT (action), "sensitive"); + GtkToolItem *item; + + item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), l); + + configure_item_cursor (item, etoolbar); + configure_item_sensitivity (item, etoolbar); } - } + } } } } @@ -1292,35 +1492,6 @@ egg_editable_toolbar_set_fixed (EggEditableToolbar *toolbar, update_fixed (toolbar); } -void -egg_editable_toolbar_set_drag_dest (EggEditableToolbar *etoolbar, - const GtkTargetEntry *targets, - gint n_targets, - const char *toolbar_name) -{ - int i, n_toolbars; - EggToolbarsModel *model = etoolbar->priv->model; - - g_return_if_fail (model != NULL); - - n_toolbars = egg_toolbars_model_n_toolbars (model); - for (i = 0; i < n_toolbars; i++) - { - const char *name; - - name = egg_toolbars_model_toolbar_nth (model, i); - if (strcmp (toolbar_name, name) == 0) - { - GtkWidget *widget = get_toolbar_nth (etoolbar, i); - - gtk_drag_dest_unset (widget); - gtk_drag_dest_set (widget, 0, - targets, n_targets, - GDK_ACTION_MOVE | GDK_ACTION_COPY); - } - } -} - #define DEFAULT_ICON_HEIGHT 20 #define DEFAULT_ICON_WIDTH 0 diff --git a/lib/egg/egg-editable-toolbar.h b/lib/egg/egg-editable-toolbar.h index 9f143da70..d91e916dd 100755 --- a/lib/egg/egg-editable-toolbar.h +++ b/lib/egg/egg-editable-toolbar.h @@ -29,6 +29,7 @@ #include <gtk/gtkvbox.h> #include <gtk/gtktoolitem.h> #include <gtk/gtktoolbar.h> +#include <gtk/gtkmenu.h> G_BEGIN_DECLS @@ -80,6 +81,8 @@ void egg_editable_toolbar_set_drag_dest (EggEditableToolbar *etoolbar, void egg_editable_toolbar_set_fixed (EggEditableToolbar *etoolbar, GtkToolbar *fixed_toolbar); +void egg_editable_toolbar_add_popup_items (GtkWidget *widget, + GtkMenu *popup); /* Private Functions */ diff --git a/lib/egg/egg-toolbar-editor.c b/lib/egg/egg-toolbar-editor.c index bd79724a8..4cb7d0ccc 100755 --- a/lib/egg/egg-toolbar-editor.c +++ b/lib/egg/egg-toolbar-editor.c @@ -34,6 +34,7 @@ #include <gtk/gtktable.h> #include <gtk/gtkstock.h> #include <gtk/gtkhbox.h> +#include <gtk/gtk.h> static const GtkTargetEntry dest_drag_types[] = { {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0}, @@ -46,7 +47,6 @@ static const GtkTargetEntry source_drag_types[] = { static void egg_toolbar_editor_class_init (EggToolbarEditorClass *klass); static void egg_toolbar_editor_init (EggToolbarEditor *t); static void egg_toolbar_editor_finalize (GObject *object); -static void update_actions_list (EggToolbarEditor *editor); static void update_editor_sheet (EggToolbarEditor *editor); enum @@ -67,9 +67,8 @@ struct EggToolbarEditorPrivate GtkWidget *table; GtkWidget *scrolled_window; - - GList *default_actions_list; - GList *actions_list; + GList *actions_list; + GList *factory_list; }; GType @@ -100,27 +99,18 @@ egg_toolbar_editor_get_type (void) } static gint -compare_actions (gconstpointer a, - gconstpointer b) +compare_items (gconstpointer a, + gconstpointer b) { - GValue value_a = { 0, }, value_b = { 0, }; - const char *short_label_a, *short_label_b; - int ret; - - g_value_init (&value_a, G_TYPE_STRING); - g_object_get_property (G_OBJECT (a), "short_label", &value_a); - short_label_a = g_value_get_string (&value_a); - - g_value_init (&value_b, G_TYPE_STRING); - g_object_get_property (G_OBJECT (b), "short_label", &value_b); - short_label_b = g_value_get_string (&value_b); - - ret = g_utf8_collate (short_label_a, short_label_b); - - g_value_unset (&value_a); - g_value_unset (&value_b); - - return ret; + const GtkWidget *item1 = a; + const GtkWidget *item2 = b; + + char *key1 = g_object_get_data (G_OBJECT (item1), + "egg-collate-key"); + char *key2 = g_object_get_data (G_OBJECT (item2), + "egg-collate-key"); + + return strcmp (key1, key2); } static GtkAction * @@ -157,11 +147,19 @@ egg_toolbar_editor_set_ui_manager (EggToolbarEditor *t, } static void +item_added_or_removed_cb (EggToolbarsModel *model, + int tpos, + int ipos, + EggToolbarEditor *editor) +{ + update_editor_sheet (editor); +} + +static void toolbar_removed_cb (EggToolbarsModel *model, int position, EggToolbarEditor *editor) { - update_actions_list (editor); update_editor_sheet (editor); } @@ -172,7 +170,13 @@ egg_toolbar_editor_set_model (EggToolbarEditor *t, g_return_if_fail (EGG_IS_TOOLBAR_EDITOR (t)); t->priv->model = g_object_ref (model); + + update_editor_sheet (t); + g_signal_connect_object (model, "item_added", + G_CALLBACK (item_added_or_removed_cb), t, 0); + g_signal_connect_object (model, "item_removed", + G_CALLBACK (item_added_or_removed_cb), t, 0); g_signal_connect_object (model, "toolbar_removed", G_CALLBACK (toolbar_removed_cb), t, 0); } @@ -261,8 +265,8 @@ egg_toolbar_editor_finalize (GObject *object) g_object_unref (editor->priv->model); } - g_list_free (editor->priv->default_actions_list); g_list_free (editor->priv->actions_list); + g_list_free (editor->priv->factory_list); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -281,66 +285,14 @@ static void drag_begin_cb (GtkWidget *widget, GdkDragContext *context) { - gtk_widget_hide (widget); + gtk_widget_hide (widget); } static void drag_end_cb (GtkWidget *widget, GdkDragContext *context) { - gtk_widget_show (widget); -} - -static void -editor_drag_data_received_cb (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time_, - EggToolbarEditor *editor) -{ - GtkAction *action; - const char *data; - - g_return_if_fail (EGG_IS_TOOLBAR_EDITOR (editor)); - g_return_if_fail (selection_data != NULL); - - if (selection_data->length <= 0 || selection_data->data == NULL) return; - - data = (const char *) selection_data->data; - - if (strcmp (data, "separator") == 0) return; - - action = find_action (editor, data); - g_return_if_fail (action != NULL); - - if (g_list_find (editor->priv->default_actions_list, action)) - { - editor->priv->actions_list = g_list_insert_sorted - (editor->priv->actions_list, action, compare_actions); - } - - update_editor_sheet (editor); -} - -static void -editor_drag_data_delete_cb (GtkWidget *widget, - GdkDragContext *context, - EggToolbarEditor *editor) -{ - GtkAction *action; - g_return_if_fail (EGG_IS_TOOLBAR_EDITOR (editor)); - - action = GTK_ACTION (g_object_get_data (G_OBJECT (widget), "egg-action")); - if (action) - { - editor->priv->actions_list = g_list_remove - (editor->priv->actions_list, action); - } - - update_editor_sheet (editor); + gtk_widget_show (widget); } static void @@ -351,23 +303,12 @@ drag_data_get_cb (GtkWidget *widget, guint32 time, EggToolbarEditor *editor) { - GtkAction *action; const char *target; - action = GTK_ACTION (g_object_get_data (G_OBJECT (widget), "egg-action")); - - if (action) - { - target = gtk_action_get_name (action); - } - else - { - target = "separator"; - } - - gtk_selection_data_set (selection_data, - selection_data->target, 8, - (const guchar *)target, strlen (target)); + target = g_object_get_data (G_OBJECT (widget), "egg-item-name"); + g_return_if_fail (target != NULL); + + gtk_selection_data_set (selection_data, selection_data->target, 8, target, strlen (target)); } static gchar * @@ -454,8 +395,6 @@ editor_create_item (EggToolbarEditor *editor, source_drag_types, G_N_ELEMENTS (source_drag_types), action); g_signal_connect (event_box, "drag_data_get", G_CALLBACK (drag_data_get_cb), editor); - g_signal_connect (event_box, "drag_data_delete", - G_CALLBACK (editor_drag_data_delete_cb), editor); g_signal_connect_after (event_box, "realize", G_CALLBACK (event_box_realize_cb), icon); @@ -482,80 +421,174 @@ editor_create_item (EggToolbarEditor *editor, return event_box; } -static void -update_editor_sheet (EggToolbarEditor *editor) +static GtkWidget * +editor_create_item_from_name (EggToolbarEditor *editor, + const char * name, + GdkDragAction drag_action) { - GList *l; - GList *to_drag; - int x, y, height, width; - GtkWidget *table; - GtkWidget *viewport; GtkWidget *item; - GtkWidget *icon; - - g_return_if_fail (EGG_IS_TOOLBAR_EDITOR (editor)); - - viewport = GTK_BIN (editor->priv->scrolled_window)->child; - if (viewport) + const char *item_name; + const char *stock_id; + const char *short_label; + const char *collate_key; + + if (strcmp (name, "_separator") == 0) { - table = GTK_BIN (viewport)->child; - gtk_container_remove (GTK_CONTAINER (viewport), table); + GtkWidget *icon; + + icon = _egg_editable_toolbar_new_separator_image (); + short_label = _("Separator"); + item_name = strdup (name); + collate_key = g_utf8_collate_key (short_label, -1); + item = editor_create_item (editor, GTK_IMAGE (icon), + short_label, drag_action); } - table = gtk_table_new (0, 0, TRUE); - editor->priv->table = table; - gtk_container_set_border_width (GTK_CONTAINER (table), 12); - gtk_widget_show (table); - gtk_scrolled_window_add_with_viewport - (GTK_SCROLLED_WINDOW (editor->priv->scrolled_window), table); - gtk_drag_dest_set (table, GTK_DEST_DEFAULT_ALL, - dest_drag_types, G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); - g_signal_connect (table, "drag_data_received", - G_CALLBACK (editor_drag_data_received_cb), editor); - - to_drag = editor->priv->actions_list; - - x = y = 0; - width = 4; - height = (g_list_length (to_drag)) / width + 1; - gtk_table_resize (GTK_TABLE (editor->priv->table), height, width); - - for (l = to_drag; l != NULL; l = l->next) + else { - GtkAction *action = (l->data); - const char *stock_id, *short_label; GValue value = { 0, }; + GtkAction *action; + GtkWidget *icon; + + action = find_action (editor, name); + g_return_val_if_fail (action != NULL, NULL); g_value_init (&value, G_TYPE_STRING); g_object_get_property (G_OBJECT (action), "stock_id", &value); stock_id = g_value_get_string (&value); - icon = gtk_image_new_from_stock - (stock_id ? stock_id : GTK_STOCK_DND, - GTK_ICON_SIZE_LARGE_TOOLBAR); + icon = gtk_image_new_from_stock (stock_id ? stock_id : GTK_STOCK_DND, + GTK_ICON_SIZE_LARGE_TOOLBAR); g_value_unset (&value); - + g_value_init (&value, G_TYPE_STRING); g_object_get_property (G_OBJECT (action), "short_label", &value); short_label = g_value_get_string (&value); + + item_name = strdup (name); + collate_key = g_utf8_collate_key (short_label, -1); item = editor_create_item (editor, GTK_IMAGE (icon), - short_label, GDK_ACTION_MOVE); + short_label, drag_action); g_value_unset (&value); - g_object_set_data (G_OBJECT (item), "egg-action", action); - gtk_table_attach_defaults (GTK_TABLE (editor->priv->table), - item, x, x + 1, y, y + 1); + } + + g_object_set_data_full (G_OBJECT (item), "egg-collate-key", + (gpointer) collate_key, g_free); + g_object_set_data_full (G_OBJECT (item), "egg-item-name", + (gpointer) item_name, g_free); + + return item; +} - x++; - if (x >= width) - { - x = 0; - y++; - } +static gint +append_table (GtkTable *table, GList *items, gint y, gint width) +{ + if (items != NULL) + { + gint x = 0, height; + GtkWidget *alignment; + GtkWidget *item; + + height = g_list_length (items) / width + 1; + gtk_table_resize (table, height, width); + + if (y > 0) + { + item = gtk_hseparator_new (); + alignment = gtk_alignment_new (0.5, 0.5, 1.0, 0.0); + gtk_container_add (GTK_CONTAINER (alignment), item); + gtk_widget_show (alignment); + gtk_widget_show (item); + + gtk_table_attach_defaults (table, alignment, 0, width, y-1, y+1); + } + + for (; items != NULL; items = items->next) + { + item = items->data; + alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); + gtk_container_add (GTK_CONTAINER (alignment), item); + gtk_widget_show (alignment); + gtk_widget_show (item); + + if (x >= width) + { + x = 0; + y++; + } + gtk_table_attach_defaults (table, alignment, x, x+1, y, y+1); + x++; + } + + y++; } + return y; +} + +static void +update_editor_sheet (EggToolbarEditor *editor) +{ + gint y; + GPtrArray *items; + GList *to_move = NULL, *to_copy = NULL; + GtkWidget *table; + GtkWidget *viewport; + + g_return_if_fail (EGG_IS_TOOLBAR_EDITOR (editor)); + + /* Create new table. */ + table = gtk_table_new (0, 0, TRUE); + editor->priv->table = table; + gtk_container_set_border_width (GTK_CONTAINER (table), 12); + gtk_table_set_row_spacings (GTK_TABLE (table), 24); + gtk_widget_show (table); + gtk_drag_dest_set (table, GTK_DEST_DEFAULT_ALL, + dest_drag_types, G_N_ELEMENTS (dest_drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); + + /* Build two lists of items (one for copying, one for moving). */ + items = egg_toolbars_model_get_avail (editor->priv->model); + while (items->len > 0) + { + GtkWidget *item; + const char *name; + + name = g_ptr_array_index (items, 0); + g_ptr_array_remove_index_fast (items, 0); + + if (egg_toolbars_model_get_n_avail (editor->priv->model, name) == 1) + { + item = editor_create_item_from_name (editor, name, GDK_ACTION_MOVE); + if (item != NULL) + to_move = g_list_insert_sorted (to_move, item, compare_items); + } + else + { + item = editor_create_item_from_name (editor, name, GDK_ACTION_COPY); + if (item != NULL) + to_copy = g_list_insert_sorted (to_copy, item, compare_items); + } + } + + /* Add them to the sheet. */ + y = 0; + y = append_table (GTK_TABLE (table), to_move, y, 4); + y = append_table (GTK_TABLE (table), to_copy, y, 4); + + g_list_free (to_move); + g_list_free (to_copy); + g_ptr_array_free (items, TRUE); + + /* Delete old table. */ + viewport = GTK_BIN (editor->priv->scrolled_window)->child; + if (viewport) + { + gtk_container_remove (GTK_CONTAINER (viewport), + GTK_BIN (viewport)->child); + } + + /* Add table to window. */ + gtk_scrolled_window_add_with_viewport + (GTK_SCROLLED_WINDOW (editor->priv->scrolled_window), table); - icon = _egg_editable_toolbar_new_separator_image (); - item = editor_create_item (editor, GTK_IMAGE (icon), _("Separator"), - GDK_ACTION_COPY); - gtk_table_attach_defaults (GTK_TABLE (editor->priv->table), - item, x, x + 1, y, y + 1); } static void @@ -578,113 +611,8 @@ egg_toolbar_editor_init (EggToolbarEditor *t) t->priv = EGG_TOOLBAR_EDITOR_GET_PRIVATE (t); t->priv->manager = NULL; - t->priv->default_actions_list = NULL; t->priv->actions_list = NULL; setup_editor (t); } -void -egg_toolbar_editor_add_action (EggToolbarEditor *editor, - const char *action_name) -{ - GtkAction *action; - - action = find_action (editor, action_name); - g_return_if_fail (action != NULL); - - editor->priv->default_actions_list = g_list_insert_sorted - (editor->priv->default_actions_list, action, compare_actions); -} - -static void -parse_item_list (EggToolbarEditor *t, - xmlNodePtr child) -{ - while (child) - { - if (xmlStrEqual (child->name, (const xmlChar*) "toolitem")) - { - xmlChar *name; - - name = xmlGetProp (child, (const xmlChar*) "name"); - egg_toolbar_editor_add_action (t, (const char*)name); - xmlFree (name); - } - child = child->next; - } -} - -static gboolean -model_has_action (EggToolbarsModel *model, GtkAction *action) -{ - int i, l, n_items, n_toolbars; - - n_toolbars = egg_toolbars_model_n_toolbars (model); - for (i = 0; i < n_toolbars; i++) - { - n_items = egg_toolbars_model_n_items (model, i); - for (l = 0; l < n_items; l++) - { - const char *name; - const char *action_name; - gboolean sep; - - egg_toolbars_model_item_nth (model, i, l, &sep, &name, NULL); - action_name = gtk_action_get_name (action); - if (!sep && strcmp (name, action_name) == 0) return TRUE; - } - } - - return FALSE; -} - -static void -update_actions_list (EggToolbarEditor *editor) -{ - GList *l; - - if (editor->priv->actions_list) - g_list_free (editor->priv->actions_list); - - /* Remove the already used items */ - editor->priv->actions_list = NULL; - - for (l = editor->priv->default_actions_list; l != NULL; l = l->next) - { - GtkAction *action = GTK_ACTION (l->data); - - if (!model_has_action (editor->priv->model, action)) - { - editor->priv->actions_list = g_list_insert_sorted - (editor->priv->actions_list, action, compare_actions); - } - } -} - -void -egg_toolbar_editor_load_actions (EggToolbarEditor *editor, - const char *xml_file) -{ - xmlDocPtr doc; - xmlNodePtr root; - xmlNodePtr child; - - doc = xmlParseFile (xml_file); - root = xmlDocGetRootElement (doc); - child = root->children; - - while (child) - { - if (xmlStrEqual (child->name, (const xmlChar*) "available")) - { - parse_item_list (editor, child->children); - } - child = child->next; - } - - xmlFreeDoc (doc); - - update_actions_list (editor); - update_editor_sheet (editor); -} diff --git a/lib/egg/egg-toolbar-editor.h b/lib/egg/egg-toolbar-editor.h index e1e1f35ab..e29e5482b 100755 --- a/lib/egg/egg-toolbar-editor.h +++ b/lib/egg/egg-toolbar-editor.h @@ -56,11 +56,6 @@ struct EggToolbarEditorClass GType egg_toolbar_editor_get_type (void); GtkWidget *egg_toolbar_editor_new (GtkUIManager *manager, EggToolbarsModel *model); -void egg_toolbar_editor_load_actions (EggToolbarEditor *editor, - const char *xml_file); - -void egg_toolbar_editor_add_action (EggToolbarEditor *editor, - const char *action_name); G_END_DECLS diff --git a/lib/egg/egg-toolbars-model.c b/lib/egg/egg-toolbars-model.c index 56f4c8fbf..1d8c59476 100755 --- a/lib/egg/egg-toolbars-model.c +++ b/lib/egg/egg-toolbars-model.c @@ -31,7 +31,7 @@ #include <gdk/gdkproperty.h> static void egg_toolbars_model_class_init (EggToolbarsModelClass *klass); -static void egg_toolbars_model_init (EggToolbarsModel *t); +static void egg_toolbars_model_init (EggToolbarsModel *model); static void egg_toolbars_model_finalize (GObject *object); enum @@ -41,9 +41,6 @@ enum TOOLBAR_ADDED, TOOLBAR_CHANGED, TOOLBAR_REMOVED, - GET_ITEM_TYPE, - GET_ITEM_ID, - GET_ITEM_DATA, LAST_SIGNAL }; @@ -55,9 +52,7 @@ typedef struct typedef struct { - char *id; - char *type; - gboolean separator; + char *name; } EggToolbarsItem; static guint signals[LAST_SIGNAL] = { 0 }; @@ -69,6 +64,8 @@ static GObjectClass *parent_class = NULL; struct EggToolbarsModelPrivate { GNode *toolbars; + GList *types; + GHashTable *avail; }; GType @@ -103,45 +100,64 @@ egg_toolbars_model_get_type (void) } static xmlDocPtr -egg_toolbars_model_to_xml (EggToolbarsModel *t) +egg_toolbars_model_to_xml (EggToolbarsModel *model) { GNode *l1, *l2, *tl; + GList *l3; xmlDocPtr doc; - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), NULL); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), NULL); - tl = t->priv->toolbars; + tl = model->priv->toolbars; xmlIndentTreeOutput = TRUE; - doc = xmlNewDoc ((const xmlChar*) "1.0"); - doc->children = xmlNewDocNode (doc, NULL, (const xmlChar*) "toolbars", NULL); + doc = xmlNewDoc ("1.0"); + doc->children = xmlNewDocNode (doc, NULL, "toolbars", NULL); for (l1 = tl->children; l1 != NULL; l1 = l1->next) { xmlNodePtr tnode; EggToolbarsToolbar *toolbar = l1->data; - tnode = xmlNewChild (doc->children, NULL, (const xmlChar*) "toolbar", NULL); - xmlSetProp (tnode, (const xmlChar*) "name", (const xmlChar*) toolbar->name); + tnode = xmlNewChild (doc->children, NULL, "toolbar", NULL); + xmlSetProp (tnode, "name", toolbar->name); + xmlSetProp (tnode, "hidden", (toolbar->flags&EGG_TB_MODEL_HIDDEN)?"true":"false"); for (l2 = l1->children; l2 != NULL; l2 = l2->next) { xmlNodePtr node; EggToolbarsItem *item = l2->data; - if (item->separator) - { - node = xmlNewChild (tnode, NULL, (const xmlChar*) "separator", NULL); - } - else - { - char *data; - - node = xmlNewChild (tnode, NULL, (const xmlChar*) "toolitem", NULL); - data = egg_toolbars_model_get_item_data (t, item->type, item->id); - xmlSetProp (node, (const xmlChar*) "type", (const xmlChar*) item->type); - xmlSetProp (node, (const xmlChar*) "name", (const xmlChar*) data); - g_free (data); + if (strcmp (item->name, "_separator") == 0) + { + node = xmlNewChild (tnode, NULL, "separator", NULL); + continue; + } + + node = xmlNewChild (tnode, NULL, "toolitem", NULL); + xmlSetProp (node, "name", item->name); + + /* Add 'data' nodes for each data type which can be written out for this + * item. Only write types which can be used to restore the data. */ + for (l3 = model->priv->types; l3 != NULL; l3 = l3->next) + { + EggToolbarsItemType *type = l3->data; + if (type->get_name != NULL && type->get_data != NULL) + { + xmlNodePtr dnode; + char *tmp; + + tmp = type->get_data (type, item->name); + if (tmp != NULL) + { + dnode = xmlNewTextChild (node, NULL, "data", tmp); + g_free (tmp); + + tmp = gdk_atom_name (type->type); + xmlSetProp (dnode, "type", tmp); + g_free (tmp); + } + } } } } @@ -206,24 +222,24 @@ safe_save_xml (const char *xml_file, xmlDocPtr doc) } void -egg_toolbars_model_save (EggToolbarsModel *t, +egg_toolbars_model_save (EggToolbarsModel *model, const char *xml_file, const char *version) { xmlDocPtr doc; xmlNodePtr root; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - doc = egg_toolbars_model_to_xml (t); + doc = egg_toolbars_model_to_xml (model); root = xmlDocGetRootElement (doc); - xmlSetProp (root, (const xmlChar*) "version", (const xmlChar*) version); + xmlSetProp (root, "version", version); safe_save_xml (xml_file, doc); xmlFreeDoc (doc); } -static EggToolbarsToolbar * -toolbars_toolbar_new (const char *name) +static GNode * +toolbar_node_new (const char *name) { EggToolbarsToolbar *toolbar; @@ -231,58 +247,67 @@ toolbars_toolbar_new (const char *name) toolbar->name = g_strdup (name); toolbar->flags = 0; - return toolbar; + return g_node_new (toolbar); } -static EggToolbarsItem * -toolbars_item_new (const char *id, - const char *type, - gboolean separator) +static GNode * +item_node_new (const char *name, EggToolbarsModel *model) { EggToolbarsItem *item; - g_return_val_if_fail (id != NULL, NULL); - g_return_val_if_fail (type != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); item = g_new (EggToolbarsItem, 1); - item->id = g_strdup (id); - item->type = g_strdup (type); - item->separator = separator; + item->name = g_strdup (name); + + gint count = (gint) g_hash_table_lookup (model->priv->avail, item->name); + if (count > G_MININT && count < G_MAXINT) + g_hash_table_insert (model->priv->avail, + g_strdup (item->name), + (gpointer) (count-1)); - return item; + return g_node_new (item); } static void -free_toolbar_node (GNode *toolbar_node) +item_node_free (GNode *item_node, EggToolbarsModel *model) { - EggToolbarsToolbar *toolbar = toolbar_node->data; + EggToolbarsItem *item = item_node->data; - g_free (toolbar->name); - g_free (toolbar); + gint count = (gint) g_hash_table_lookup (model->priv->avail, item->name); + if (count < G_MAXINT-1) + g_hash_table_insert (model->priv->avail, + g_strdup (item->name), + (gpointer) (count+1)); - g_node_destroy (toolbar_node); + g_free (item->name); + g_free (item); + + g_node_destroy (item_node); } static void -free_item_node (GNode *item_node) +toolbar_node_free (GNode *toolbar_node, EggToolbarsModel *model) { - EggToolbarsItem *item = item_node->data; + EggToolbarsToolbar *toolbar = toolbar_node->data; - g_free (item->id); - g_free (item->type); - g_free (item); + g_node_children_foreach (toolbar_node, G_TRAVERSE_ALL, + (GNodeForeachFunc) item_node_free, model); + + g_free (toolbar->name); + g_free (toolbar); - g_node_destroy (item_node); + g_node_destroy (toolbar_node); } EggTbModelFlags -egg_toolbars_model_get_flags (EggToolbarsModel *t, +egg_toolbars_model_get_flags (EggToolbarsModel *model, int toolbar_position) { GNode *toolbar_node; EggToolbarsToolbar *toolbar; - toolbar_node = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar_node = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_val_if_fail (toolbar_node != NULL, 0); toolbar = toolbar_node->data; @@ -291,162 +316,262 @@ egg_toolbars_model_get_flags (EggToolbarsModel *t, } void -egg_toolbars_model_set_flags (EggToolbarsModel *t, +egg_toolbars_model_set_flags (EggToolbarsModel *model, int toolbar_position, EggTbModelFlags flags) { GNode *toolbar_node; EggToolbarsToolbar *toolbar; - toolbar_node = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar_node = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_if_fail (toolbar_node != NULL); toolbar = toolbar_node->data; toolbar->flags = flags; - g_signal_emit (G_OBJECT (t), signals[TOOLBAR_CHANGED], + g_signal_emit (G_OBJECT (model), signals[TOOLBAR_CHANGED], 0, toolbar_position); } -void -egg_toolbars_model_add_separator (EggToolbarsModel *t, - int toolbar_position, - int position) + +char * +egg_toolbars_model_get_data (EggToolbarsModel *model, + GdkAtom type, + const char *name) +{ + EggToolbarsItemType *t; + char *data = NULL; + GList *l; + + if (type == GDK_NONE || type == gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE)) + { + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (*name != 0, NULL); + return strdup (name); + } + + for (l = model->priv->types; l != NULL; l = l->next) + { + t = l->data; + if (t->type == type && t->get_data != NULL) + { + data = t->get_data (t, name); + if (data != NULL) break; + } + } + + return data; +} + +char * +egg_toolbars_model_get_name (EggToolbarsModel *model, + GdkAtom type, + const char *data, + gboolean create) +{ + EggToolbarsItemType *t; + char *name = NULL; + GList *l; + + if (type == GDK_NONE || type == gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE)) + { + g_return_val_if_fail (data, NULL); + g_return_val_if_fail (*data, NULL); + return strdup (data); + } + + if (create) + { + for (l = model->priv->types; name == NULL && l != NULL; l = l->next) + { + t = l->data; + if (t->type == type && t->new_name != NULL) + name = t->new_name (t, data); + } + + return name; + } + else + { + for (l = model->priv->types; name == NULL && l != NULL; l = l->next) + { + t = l->data; + if (t->type == type && t->get_name != NULL) + name = t->get_name (t, data); + } + + return name; + } +} + +static gboolean +impl_add_item (EggToolbarsModel *model, + int toolbar_position, + int position, + const char *name) { GNode *parent_node; - GNode *node; - EggToolbarsItem *item; + GNode *child_node; int real_position; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE); + g_return_val_if_fail (name != NULL, FALSE); - parent_node = g_node_nth_child (t->priv->toolbars, toolbar_position); - item = toolbars_item_new ("separator", EGG_TOOLBAR_ITEM_TYPE, TRUE); - node = g_node_new (item); - g_node_insert (parent_node, position, node); + parent_node = g_node_nth_child (model->priv->toolbars, toolbar_position); + child_node = item_node_new (name, model); + g_node_insert (parent_node, position, child_node); - real_position = g_node_child_position (parent_node, node); + real_position = g_node_child_position (parent_node, child_node); - g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_ADDED], 0, toolbar_position, real_position); + + return TRUE; } -static gboolean -impl_add_item (EggToolbarsModel *t, - int toolbar_position, - int position, - const char *id, - const char *type) +gboolean +egg_toolbars_model_add_item (EggToolbarsModel *model, + int toolbar_position, + int position, + const char *name) +{ + EggToolbarsModelClass *klass = EGG_TOOLBARS_MODEL_GET_CLASS (model); + return klass->add_item (model, toolbar_position, position, name); +} + +int +egg_toolbars_model_add_toolbar (EggToolbarsModel *model, + int position, + const char *name) { - GNode *parent_node; GNode *node; - EggToolbarsItem *item; int real_position; - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), FALSE); - g_return_val_if_fail (id != NULL, FALSE); - g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), -1); - parent_node = g_node_nth_child (t->priv->toolbars, toolbar_position); - item = toolbars_item_new (id, type, FALSE); - node = g_node_new (item); - g_node_insert (parent_node, position, node); + node = toolbar_node_new (name); + g_node_insert (model->priv->toolbars, position, node); - real_position = g_node_child_position (parent_node, node); + real_position = g_node_child_position (model->priv->toolbars, node); - g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0, - toolbar_position, real_position); + g_signal_emit (G_OBJECT (model), signals[TOOLBAR_ADDED], + 0, real_position); - return TRUE; + return g_node_child_position (model->priv->toolbars, node); +} + +static char * +parse_data_list (EggToolbarsModel *model, + xmlNodePtr child, + gboolean create) +{ + char *name = NULL; + while (child && name == NULL) + { + if (xmlStrEqual (child->name, "data")) + { + xmlChar *type = xmlGetProp (child, "type"); + xmlChar *data = xmlNodeGetContent (child); + + if (type != NULL) + { + GdkAtom atom = gdk_atom_intern (type, TRUE); + name = egg_toolbars_model_get_name (model, atom, data, create); + } + + xmlFree (type); + xmlFree (data); + } + + child = child->next; + } + + return name; } static void -parse_item_list (EggToolbarsModel *t, +parse_item_list (EggToolbarsModel *model, xmlNodePtr child, int position) { while (child) { - if (xmlStrEqual (child->name, (const xmlChar*) "toolitem")) + if (xmlStrEqual (child->name, "toolitem")) { - xmlChar *name, *type; - char *id; + char *name; - name = xmlGetProp (child, (const xmlChar*) "name"); - type = xmlGetProp (child, (const xmlChar*) "type"); - if (type == NULL) + /* Try to get the name using the data elements first, + as they are more 'portable' or 'persistent'. */ + name = parse_data_list (model, child->children, FALSE); + if (name == NULL) { - type = xmlCharStrdup (EGG_TOOLBAR_ITEM_TYPE); + name = parse_data_list (model, child->children, TRUE); } - - if (name != NULL && name[0] != '\0' && type != NULL) - { - id = egg_toolbars_model_get_item_id (t, (const char*)type, (const char*)name); - if (id != NULL) - { - egg_toolbars_model_add_item (t, position, -1, id, (const char*)type); + + /* If that fails, try to use the name. */ + if (name == NULL) + { + xmlChar *type = xmlGetProp (child, "type"); + xmlChar *data = xmlGetProp (child, "name"); + GdkAtom atom = type ? gdk_atom_intern (type, TRUE) : GDK_NONE; + + /* If an old format, try to use it. */ + name = egg_toolbars_model_get_name (model, atom, data, FALSE); + if (name == NULL) + { + name = egg_toolbars_model_get_name (model, atom, data, TRUE); } - g_free (id); + + xmlFree (type); + xmlFree (data); + } + + if (name != NULL) + { + egg_toolbars_model_add_item (model, position, -1, name); + g_free (name); } - xmlFree (name); - xmlFree (type); } - else if (xmlStrEqual (child->name, (const xmlChar*) "separator")) + else if (xmlStrEqual (child->name, "separator")) { - egg_toolbars_model_add_separator (t, position, -1); + egg_toolbars_model_add_item (model, position, -1, "_separator"); } child = child->next; } } -int -egg_toolbars_model_add_toolbar (EggToolbarsModel *t, - int position, - const char *name) -{ - GNode *node; - int real_position; - - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), -1); - - node = g_node_new (toolbars_toolbar_new (name)); - g_node_insert (t->priv->toolbars, position, node); - - real_position = g_node_child_position (t->priv->toolbars, node); - - g_signal_emit (G_OBJECT (t), signals[TOOLBAR_ADDED], - 0, real_position); - - return g_node_child_position (t->priv->toolbars, node); -} - static void -parse_toolbars (EggToolbarsModel *t, +parse_toolbars (EggToolbarsModel *model, xmlNodePtr child) { while (child) { - if (xmlStrEqual (child->name, (const xmlChar*) "toolbar")) + if (xmlStrEqual (child->name, "toolbar")) { - xmlChar *name; - xmlChar *style; + xmlChar *string; int position; - - name = xmlGetProp (child, (const xmlChar*) "name"); - position = egg_toolbars_model_add_toolbar (t, -1, (const char*) name); - xmlFree (name); - - style = xmlGetProp (child, (const xmlChar*) "style"); - if (style && xmlStrEqual (style, (const xmlChar*) "icons-only")) - { - /* FIXME: use toolbar position instead of 0 */ - egg_toolbars_model_set_flags (t, 0, EGG_TB_MODEL_ICONS); - } - xmlFree (style); - - parse_item_list (t, child->children, position); + EggTbModelFlags flags; + + string = xmlGetProp (child, "name"); + position = egg_toolbars_model_add_toolbar (model, -1, string); + flags = egg_toolbars_model_get_flags (model, position); + xmlFree (string); + + string = xmlGetProp (child, "hidden"); + if (string && xmlStrEqual (string, "true")) + flags |= EGG_TB_MODEL_HIDDEN; + xmlFree (string); + + string = xmlGetProp (child, "style"); + if (string && xmlStrEqual (string, "icons-only")) + flags |= EGG_TB_MODEL_ICONS; + xmlFree (string); + + egg_toolbars_model_set_flags (model, position, flags); + + parse_item_list (model, child->children, position); } child = child->next; @@ -454,13 +579,13 @@ parse_toolbars (EggToolbarsModel *t, } gboolean -egg_toolbars_model_load (EggToolbarsModel *t, +egg_toolbars_model_load (EggToolbarsModel *model, const char *xml_file) { xmlDocPtr doc; xmlNodePtr root; - g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (t), FALSE); + g_return_val_if_fail (EGG_IS_TOOLBARS_MODEL (model), FALSE); if (!xml_file || !g_file_test (xml_file, G_FILE_TEST_EXISTS)) return FALSE; @@ -472,68 +597,13 @@ egg_toolbars_model_load (EggToolbarsModel *t, } root = xmlDocGetRootElement (doc); - parse_toolbars (t, root->children); + parse_toolbars (model, root->children); xmlFreeDoc (doc); return TRUE; } -static char * -impl_get_item_id (EggToolbarsModel *t, - const char *type, - const char *data) -{ - if (strcmp (type, EGG_TOOLBAR_ITEM_TYPE) == 0) - { - return g_strdup (data); - } - - return NULL; -} - -static char * -impl_get_item_data (EggToolbarsModel *t, - const char *type, - const char *id) -{ - if (strcmp (type, EGG_TOOLBAR_ITEM_TYPE) == 0) - { - return g_strdup (id); - } - - return NULL; -} - -static char * -impl_get_item_type (EggToolbarsModel *t, - GdkAtom type) -{ - if (gdk_atom_intern (EGG_TOOLBAR_ITEM_TYPE, FALSE) == type) - { - return g_strdup (EGG_TOOLBAR_ITEM_TYPE); - } - - return NULL; -} - -static gboolean -_egg_accumulator_STRING (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy) -{ - gboolean continue_emission; - const char *retval; - - retval = g_value_get_string (handler_return); - g_value_set_string (return_accu, retval); - continue_emission = !retval || !retval[0]; - - return continue_emission; -} - - static void egg_toolbars_model_class_init (EggToolbarsModelClass *klass) { @@ -544,9 +614,6 @@ egg_toolbars_model_class_init (EggToolbarsModelClass *klass) object_class->finalize = egg_toolbars_model_finalize; klass->add_item = impl_add_item; - klass->get_item_id = impl_get_item_id; - klass->get_item_data = impl_get_item_data; - klass->get_item_type = impl_get_item_type; signals[ITEM_ADDED] = g_signal_new ("item_added", @@ -583,58 +650,29 @@ egg_toolbars_model_class_init (EggToolbarsModelClass *klass) G_STRUCT_OFFSET (EggToolbarsModelClass, toolbar_changed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - signals[GET_ITEM_TYPE] = - g_signal_new ("get_item_type", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_type), - _egg_accumulator_STRING, NULL, - _egg_marshal_STRING__POINTER, - G_TYPE_STRING, 1, G_TYPE_POINTER); - signals[GET_ITEM_ID] = - g_signal_new ("get_item_id", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_id), - _egg_accumulator_STRING, NULL, - _egg_marshal_STRING__STRING_STRING, - G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING); - signals[GET_ITEM_DATA] = - g_signal_new ("get_item_data", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EggToolbarsModelClass, get_item_data), - _egg_accumulator_STRING, NULL, - _egg_marshal_STRING__STRING_STRING, - G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING); g_type_class_add_private (object_class, sizeof (EggToolbarsModelPrivate)); } static void -egg_toolbars_model_init (EggToolbarsModel *t) +egg_toolbars_model_init (EggToolbarsModel *model) { - t->priv =EGG_TOOLBARS_MODEL_GET_PRIVATE (t); - - t->priv->toolbars = g_node_new (NULL); -} + model->priv =EGG_TOOLBARS_MODEL_GET_PRIVATE (model); -static void -free_toolbar (GNode *toolbar_node) -{ - g_node_children_foreach (toolbar_node, G_TRAVERSE_ALL, - (GNodeForeachFunc) free_item_node, NULL); - free_toolbar_node (toolbar_node); + model->priv->toolbars = g_node_new (NULL); + model->priv->avail = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + egg_toolbars_model_set_n_avail (model, "_separator", G_MAXINT); } static void egg_toolbars_model_finalize (GObject *object) { - EggToolbarsModel *t = EGG_TOOLBARS_MODEL (object); + EggToolbarsModel *model = EGG_TOOLBARS_MODEL (object); - g_node_children_foreach (t->priv->toolbars, G_TRAVERSE_ALL, - (GNodeForeachFunc) free_toolbar, NULL); - g_node_destroy (t->priv->toolbars); + g_node_children_foreach (model->priv->toolbars, G_TRAVERSE_ALL, + (GNodeForeachFunc) toolbar_node_free, model); + g_node_destroy (model->priv->toolbars); + g_hash_table_destroy (model->priv->avail); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -646,51 +684,51 @@ egg_toolbars_model_new (void) } void -egg_toolbars_model_remove_toolbar (EggToolbarsModel *t, +egg_toolbars_model_remove_toolbar (EggToolbarsModel *model, int position) { GNode *node; EggTbModelFlags flags; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - flags = egg_toolbars_model_get_flags (t, position); + flags = egg_toolbars_model_get_flags (model, position); if (!(flags & EGG_TB_MODEL_NOT_REMOVABLE)) { - node = g_node_nth_child (t->priv->toolbars, position); + node = g_node_nth_child (model->priv->toolbars, position); g_return_if_fail (node != NULL); - free_toolbar_node (node); + toolbar_node_free (node, model); - g_signal_emit (G_OBJECT (t), signals[TOOLBAR_REMOVED], + g_signal_emit (G_OBJECT (model), signals[TOOLBAR_REMOVED], 0, position); } } void -egg_toolbars_model_remove_item (EggToolbarsModel *t, +egg_toolbars_model_remove_item (EggToolbarsModel *model, int toolbar_position, int position) { GNode *node, *toolbar; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_if_fail (toolbar != NULL); node = g_node_nth_child (toolbar, position); g_return_if_fail (node != NULL); - free_item_node (node); + item_node_free (node, model); - g_signal_emit (G_OBJECT (t), signals[ITEM_REMOVED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_REMOVED], 0, toolbar_position, position); } void -egg_toolbars_model_move_item (EggToolbarsModel *t, +egg_toolbars_model_move_item (EggToolbarsModel *model, int toolbar_position, int position, int new_toolbar_position, @@ -698,12 +736,12 @@ egg_toolbars_model_move_item (EggToolbarsModel *t, { GNode *node, *toolbar, *new_toolbar; - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (t)); + g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_if_fail (toolbar != NULL); - new_toolbar = g_node_nth_child (t->priv->toolbars, new_toolbar_position); + new_toolbar = g_node_nth_child (model->priv->toolbars, new_toolbar_position); g_return_if_fail (new_toolbar != NULL); node = g_node_nth_child (toolbar, position); @@ -711,74 +749,60 @@ egg_toolbars_model_move_item (EggToolbarsModel *t, g_node_unlink (node); - g_signal_emit (G_OBJECT (t), signals[ITEM_REMOVED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_REMOVED], 0, toolbar_position, position); g_node_insert (new_toolbar, new_position, node); - g_signal_emit (G_OBJECT (t), signals[ITEM_ADDED], 0, + g_signal_emit (G_OBJECT (model), signals[ITEM_ADDED], 0, new_toolbar_position, new_position); } int -egg_toolbars_model_n_items (EggToolbarsModel *t, +egg_toolbars_model_n_items (EggToolbarsModel *model, int toolbar_position) { GNode *toolbar; - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); g_return_val_if_fail (toolbar != NULL, -1); return g_node_n_children (toolbar); } -void -egg_toolbars_model_item_nth (EggToolbarsModel *t, +const char * +egg_toolbars_model_item_nth (EggToolbarsModel *model, int toolbar_position, - int position, - gboolean *is_separator, - const char **id, - const char **type) + int position) { GNode *toolbar; GNode *item; EggToolbarsItem *idata; - toolbar = g_node_nth_child (t->priv->toolbars, toolbar_position); - g_return_if_fail (toolbar != NULL); + toolbar = g_node_nth_child (model->priv->toolbars, toolbar_position); + g_return_val_if_fail (toolbar != NULL, NULL); item = g_node_nth_child (toolbar, position); - g_return_if_fail (item != NULL); + g_return_val_if_fail (item != NULL, NULL); idata = item->data; - - *is_separator = idata->separator; - - if (id) - { - *id = idata->id; - } - - if (type) - { - *type = idata->type; - } + return idata->name; } int -egg_toolbars_model_n_toolbars (EggToolbarsModel *t) +egg_toolbars_model_n_toolbars (EggToolbarsModel *model) { - return g_node_n_children (t->priv->toolbars); + return g_node_n_children (model->priv->toolbars); } const char * -egg_toolbars_model_toolbar_nth (EggToolbarsModel *t, +egg_toolbars_model_toolbar_nth (EggToolbarsModel *model, int position) { GNode *toolbar; EggToolbarsToolbar *tdata; - toolbar = g_node_nth_child (t->priv->toolbars, position); + toolbar = g_node_nth_child (model->priv->toolbars, position); g_return_val_if_fail (toolbar != NULL, NULL); tdata = toolbar->data; @@ -786,48 +810,40 @@ egg_toolbars_model_toolbar_nth (EggToolbarsModel *t, return tdata->name; } -gboolean -egg_toolbars_model_add_item (EggToolbarsModel *t, - int toolbar_position, - int position, - const char *id, - const char *type) +GList * +egg_toolbars_model_get_types (EggToolbarsModel *model) { - EggToolbarsModelClass *klass = EGG_TOOLBARS_MODEL_GET_CLASS (t); - return klass->add_item (t, toolbar_position, position, id, type); + return model->priv->types; } -char * -egg_toolbars_model_get_item_id (EggToolbarsModel *t, - const char *type, - const char *name) +void +egg_toolbars_model_set_types (EggToolbarsModel *model, GList *types) { - char *retval; - - g_signal_emit (t, signals[GET_ITEM_ID], 0, type, name, &retval); - - return retval; + model->priv->types = types; } -char * -egg_toolbars_model_get_item_data (EggToolbarsModel *t, - const char *type, - const char *id) +static void +fill_avail_array (gpointer key, gpointer value, GPtrArray *array) { - char *retval; - - g_signal_emit (t, signals[GET_ITEM_DATA], 0, type, id, &retval); - - return retval; + if (GPOINTER_TO_INT (value) > 0) g_ptr_array_add (array, key); } -char * -egg_toolbars_model_get_item_type (EggToolbarsModel *t, - GdkAtom type) +GPtrArray * +egg_toolbars_model_get_avail (EggToolbarsModel *model) { - char *retval; + GPtrArray *array = g_ptr_array_new (); + g_hash_table_foreach (model->priv->avail, (GHFunc) fill_avail_array, array); + return array; +} - g_signal_emit (t, signals[GET_ITEM_TYPE], 0, type, &retval); +gint +egg_toolbars_model_get_n_avail (EggToolbarsModel *model, const char *name) +{ + return (gint) g_hash_table_lookup (model->priv->avail, name); +} - return retval; +void +egg_toolbars_model_set_n_avail (EggToolbarsModel *model, const char *name, gint count) +{ + g_hash_table_insert (model->priv->avail, g_strdup (name), (gpointer) count); } diff --git a/lib/egg/egg-toolbars-model.h b/lib/egg/egg-toolbars-model.h index aaaa2140a..fe5467aa8 100755 --- a/lib/egg/egg-toolbars-model.h +++ b/lib/egg/egg-toolbars-model.h @@ -48,7 +48,8 @@ typedef enum EGG_TB_MODEL_ICONS = 1 << 3, EGG_TB_MODEL_TEXT = 1 << 4, EGG_TB_MODEL_STYLES_MASK = 0x1F, - EGG_TB_MODEL_ACCEPT_ITEMS_ONLY = 1 << 5 + EGG_TB_MODEL_ACCEPT_ITEMS_ONLY = 1 << 5, + EGG_TB_MODEL_HIDDEN = 1 << 6 } EggTbModelFlags; struct EggToolbarsModel @@ -76,21 +77,35 @@ struct EggToolbarsModelClass int position); void (* toolbar_removed) (EggToolbarsModel *model, int position); - char * (* get_item_type) (EggToolbarsModel *model, - GdkAtom dnd_type); - char * (* get_item_id) (EggToolbarsModel *model, - const char *type, - const char *data); - char * (* get_item_data) (EggToolbarsModel *model, - const char *type, - const char *id); /* Virtual Table */ gboolean (* add_item) (EggToolbarsModel *t, int toolbar_position, int position, - const char *id, - const char *type); + const char *name); +}; + +typedef struct EggToolbarsItemType EggToolbarsItemType; + +struct EggToolbarsItemType +{ + GdkAtom type; + + gboolean (* has_data) (EggToolbarsItemType *type, + const char *name); + char * (* get_data) (EggToolbarsItemType *type, + const char *name); + + char * (* new_name) (EggToolbarsItemType *type, + const char *data); + char * (* get_name) (EggToolbarsItemType *type, + const char *data); +}; + +struct EggToolbarsItemAvailable +{ + const char * name; + guint available; }; GType egg_toolbars_model_flags_get_type (void); @@ -101,32 +116,48 @@ gboolean egg_toolbars_model_load (EggToolbarsModel *model, void egg_toolbars_model_save (EggToolbarsModel *model, const char *xml_file, const char *version); -int egg_toolbars_model_add_toolbar (EggToolbarsModel *model, - int position, - const char *name); + +/* Functions for manipulating the types of portable data this toolbar understands. */ +GList * egg_toolbars_model_get_types (EggToolbarsModel *model); +void egg_toolbars_model_set_types (EggToolbarsModel *model, + GList *types); + +/* Functions for converting between name and portable data. */ +char * egg_toolbars_model_get_name (EggToolbarsModel *model, + GdkAtom type, + const char *data, + gboolean create); +char * egg_toolbars_model_get_data (EggToolbarsModel *model, + GdkAtom type, + const char *name); + +/* Functions for retrieving what items are available for adding to the toolbars. */ +GPtrArray * egg_toolbars_model_get_avail (EggToolbarsModel *model); +gint egg_toolbars_model_get_n_avail (EggToolbarsModel *model, + const char *name); +void egg_toolbars_model_set_n_avail (EggToolbarsModel *model, + const char *name, + gint count); + +/* Functions for manipulating flags on individual toolbars. */ EggTbModelFlags egg_toolbars_model_get_flags (EggToolbarsModel *model, int toolbar_position); void egg_toolbars_model_set_flags (EggToolbarsModel *model, int toolbar_position, EggTbModelFlags flags); -void egg_toolbars_model_add_separator (EggToolbarsModel *model, - int toolbar_position, + +/* Functions for adding and removing toolbars. */ +int egg_toolbars_model_add_toolbar (EggToolbarsModel *model, + int position, + const char *name); +void egg_toolbars_model_remove_toolbar (EggToolbarsModel *model, int position); -char *egg_toolbars_model_get_item_type (EggToolbarsModel *model, - GdkAtom dnd_type); -char *egg_toolbars_model_get_item_id (EggToolbarsModel *model, - const char *type, - const char *name); -char *egg_toolbars_model_get_item_data (EggToolbarsModel *model, - const char *type, - const char *id); + +/* Functions for adding, removing and moving items. */ gboolean egg_toolbars_model_add_item (EggToolbarsModel *model, int toolbar_position, int position, - const char *id, - const char *type); -void egg_toolbars_model_remove_toolbar (EggToolbarsModel *model, - int position); + const char *name); void egg_toolbars_model_remove_item (EggToolbarsModel *model, int toolbar_position, int position); @@ -135,14 +166,15 @@ void egg_toolbars_model_move_item (EggToolbarsModel *model, int position, int new_toolbar_position, int new_position); + +/* Functions for accessing the names of items. */ int egg_toolbars_model_n_items (EggToolbarsModel *model, int toolbar_position); -void egg_toolbars_model_item_nth (EggToolbarsModel *model, +const char * egg_toolbars_model_item_nth (EggToolbarsModel *model, int toolbar_position, - int position, - gboolean *is_separator, - const char **id, - const char **type); + int position); + +/* Functions for accessing the names of toolbars. */ int egg_toolbars_model_n_toolbars (EggToolbarsModel *model); const char *egg_toolbars_model_toolbar_nth (EggToolbarsModel *model, int position); 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 diff --git a/src/ephy-link-action.c b/src/ephy-link-action.c index 5eca8a65b..d4667090f 100644 --- a/src/ephy-link-action.c +++ b/src/ephy-link-action.c @@ -178,3 +178,47 @@ ephy_link_action_get_type (void) return type; } + +GType +ephy_link_action_group_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo our_info = + { + sizeof (EphyLinkActionGroupClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, + NULL, /* class_data */ + sizeof (EphyLinkActionGroup), + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + static const GInterfaceInfo link_info = + { + NULL, + NULL, + NULL + }; + + type = g_type_register_static (GTK_TYPE_ACTION_GROUP, + "EphyLinkActionGroup", + &our_info, 0); + g_type_add_interface_static (type, + EPHY_TYPE_LINK, + &link_info); + } + + return type; +} + +EphyLinkActionGroup * +ephy_link_action_group_new (char * name) +{ + return EPHY_LINK_ACTION_GROUP (g_object_new (EPHY_TYPE_LINK_ACTION_GROUP, + "name", "BookmarkActions", NULL)); +} diff --git a/src/ephy-link-action.h b/src/ephy-link-action.h index 046fed715..7dbc5794c 100644 --- a/src/ephy-link-action.h +++ b/src/ephy-link-action.h @@ -22,18 +22,29 @@ #define EPHY_LINK_ACTION_H #include <gtk/gtkaction.h> +#include <gtk/gtkactiongroup.h> G_BEGIN_DECLS -#define EPHY_TYPE_LINK_ACTION (ephy_link_action_get_type ()) -#define EPHY_LINK_ACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_LINK_ACTION, EphyLinkAction)) -#define EPHY_LINK_ACTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_LINK_ACTION, EphyLinkActionClass)) -#define EPHY_IS_LINK_ACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_LINK_ACTION)) -#define EPHY_IS_LINK_ACTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_LINK_ACTION)) -#define EPHY_LINK_ACTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_LINK_ACTION, EphyLinkActionClass)) +#define EPHY_TYPE_LINK_ACTION (ephy_link_action_get_type ()) +#define EPHY_LINK_ACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_LINK_ACTION, EphyLinkAction)) +#define EPHY_LINK_ACTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_LINK_ACTION, EphyLinkActionClass)) +#define EPHY_IS_LINK_ACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_LINK_ACTION)) +#define EPHY_IS_LINK_ACTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_LINK_ACTION)) +#define EPHY_LINK_ACTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_LINK_ACTION, EphyLinkActionClass)) -typedef struct _EphyLinkAction EphyLinkAction; -typedef struct _EphyLinkActionClass EphyLinkActionClass; +#define EPHY_TYPE_LINK_ACTION_GROUP (ephy_link_action_group_get_type ()) +#define EPHY_LINK_ACTION_GROUP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_LINK_ACTION_GROUP, EphyLinkActionGroup)) +#define EPHY_LINK_ACTION_GROUP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_LINK_ACTION_GROUP, EphyLinkActionGroupClass)) +#define EPHY_IS_LINK_ACTION_GROUP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_LINK_ACTION_GROUP)) +#define EPHY_IS_LINK_ACTION_GROUP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_LINK_ACTION_GROUP)) +#define EPHY_LINK_ACTION_GROUP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_LINK_ACTION_GROUP, EphyLinkActionGroupClass)) + +typedef struct _EphyLinkAction EphyLinkAction; +typedef struct _EphyLinkActionClass EphyLinkActionClass; + +typedef struct _EphyLinkActionGroup EphyLinkActionGroup; +typedef struct _EphyLinkActionGroupClass EphyLinkActionGroupClass; struct _EphyLinkAction { @@ -45,8 +56,22 @@ struct _EphyLinkActionClass GtkActionClass parent_class; }; +struct _EphyLinkActionGroup +{ + GtkActionGroup parent_instance; +}; + +struct _EphyLinkActionGroupClass +{ + GtkActionGroupClass parent_class; +}; + GType ephy_link_action_get_type (void); +GType ephy_link_action_group_get_type (void); + +EphyLinkActionGroup * ephy_link_action_group_new (char *name); + G_END_DECLS #endif diff --git a/src/ephy-lockdown.c b/src/ephy-lockdown.c index 1d2a9def7..2495a7b46 100644 --- a/src/ephy-lockdown.c +++ b/src/ephy-lockdown.c @@ -65,22 +65,22 @@ static GObjectClass *parent_class = NULL; static int find_name (GtkActionGroup *action_group, - const char *name) + const char *name) { - return strcmp (gtk_action_group_get_name (action_group), name); + return strcmp (gtk_action_group_get_name (action_group), name); } static GtkActionGroup * find_action_group (GtkUIManager *manager, const char *name) { - GList *list, *element; + GList *list, *element; - list = gtk_ui_manager_get_action_groups (manager); - element = g_list_find_custom (list, name, (GCompareFunc) find_name); - g_return_val_if_fail (element != NULL, NULL); + list = gtk_ui_manager_get_action_groups (manager); + element = g_list_find_custom (list, name, (GCompareFunc) find_name); + g_return_val_if_fail (element != NULL, NULL); - return GTK_ACTION_GROUP (element->data); + return GTK_ACTION_GROUP (element->data); } static void @@ -149,10 +149,6 @@ update_window (EphyWindow *window, action = gtk_action_group_get_action (action_group, "ViewToolbar"); ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, !writable); - writable = eel_gconf_key_is_writable (CONF_WINDOWS_SHOW_BOOKMARKS_BAR); - action = gtk_action_group_get_action (action_group, "ViewBookmarksBar"); - ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, !writable); - writable = eel_gconf_key_is_writable (CONF_WINDOWS_SHOW_STATUSBAR); action = gtk_action_group_get_action (action_group, "ViewStatusbar"); ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, !writable); diff --git a/src/ephy-notebook.c b/src/ephy-notebook.c index 63e4a92c1..ae572da81 100644 --- a/src/ephy-notebook.c +++ b/src/ephy-notebook.c @@ -59,7 +59,7 @@ #define INSANE_NUMBER_OF_URLS 20 /* Until https://bugzilla.mozilla.org/show_bug.cgi?id=296002 is fixed */ -#define KEEP_TAB_IN_SAME_TOPLEVEL +//#define KEEP_TAB_IN_SAME_TOPLEVEL #define EPHY_NOTEBOOK_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_NOTEBOOK, EphyNotebookPrivate)) @@ -85,7 +85,7 @@ static void ephy_notebook_init (EphyNotebook *notebook); static void ephy_notebook_class_init (EphyNotebookClass *klass); static void ephy_notebook_finalize (GObject *object); static void move_tab_to_another_notebook (EphyNotebook *src, - EphyNotebook *dest, + EphyNotebook *dest, GdkEventMotion *event, int dest_position); static void move_tab (EphyNotebook *notebook, @@ -96,8 +96,8 @@ static GdkCursor *cursor = NULL; static const GtkTargetEntry url_drag_types [] = { - { EPHY_DND_URI_LIST_TYPE, 0, 0 }, - { EPHY_DND_URL_TYPE, 0, 1 } + { EPHY_DND_URI_LIST_TYPE, 0, 0 }, + { EPHY_DND_URL_TYPE, 0, 1 } }; enum @@ -722,7 +722,6 @@ move_tab_to_another_notebook (EphyNotebook *src, tab = EPHY_TAB (gtk_notebook_get_nth_page (GTK_NOTEBOOK (src), cur_page)); /* stop drag in origin window */ - */ drag_stop (src, event->time); ephy_notebook_move_tab (src, dest, tab, dest_position); @@ -804,9 +803,9 @@ ephy_notebook_new (void) static void ephy_notebook_switch_page_cb (GtkNotebook *notebook, - GtkNotebookPage *page, - guint page_num, - gpointer data) + GtkNotebookPage *page, + guint page_num, + gpointer data) { EphyNotebook *nb = EPHY_NOTEBOOK (notebook); GtkWidget *child; @@ -929,17 +928,17 @@ ephy_notebook_init (EphyNotebook *notebook) gtk_widget_add_events (GTK_WIDGET (notebook), GDK_BUTTON1_MOTION_MASK); g_signal_connect_after (G_OBJECT (notebook), "switch_page", - G_CALLBACK (ephy_notebook_switch_page_cb), - NULL); + G_CALLBACK (ephy_notebook_switch_page_cb), + NULL); /* Set up drag-and-drop target */ g_signal_connect (G_OBJECT(notebook), "drag_data_received", G_CALLBACK(notebook_drag_data_received_cb), NULL); - gtk_drag_dest_set (GTK_WIDGET(notebook), GTK_DEST_DEFAULT_MOTION | + gtk_drag_dest_set (GTK_WIDGET(notebook), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, - url_drag_types, G_N_ELEMENTS (url_drag_types), - GDK_ACTION_MOVE | GDK_ACTION_COPY); + url_drag_types, G_N_ELEMENTS (url_drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); notebook->priv->tabs_vis_notifier_id = eel_gconf_notification_add (CONF_ALWAYS_SHOW_TABS_BAR, @@ -1040,7 +1039,7 @@ tab_label_style_set_cb (GtkWidget *hbox, context = gtk_widget_get_pango_context (hbox); metrics = pango_context_get_metrics (context, - hbox->style->font_desc, + hbox->style->font_desc, pango_context_get_language (context)); char_width = pango_font_metrics_get_approximate_digit_width (metrics); @@ -1087,8 +1086,8 @@ build_tab_label (EphyNotebook *nb, EphyTab *tab) _("Close tab"), NULL); g_signal_connect (G_OBJECT (close_button), "clicked", - G_CALLBACK (close_button_clicked_cb), - tab); + G_CALLBACK (close_button_clicked_cb), + tab); /* setup load feedback */ spinner = ephy_spinner_new (); @@ -1100,11 +1099,11 @@ build_tab_label (EphyNotebook *nb, EphyTab *tab) gtk_box_pack_start (GTK_BOX (label_hbox), icon, FALSE, FALSE, 0); /* setup label */ - label = gtk_label_new (""); + label = gtk_label_new (""); gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); gtk_label_set_single_line_mode (GTK_LABEL (label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_misc_set_padding (GTK_MISC (label), 0, 0); + gtk_misc_set_padding (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (label_hbox), label, TRUE, TRUE, 0); /* Set minimal size */ @@ -1165,9 +1164,9 @@ ephy_notebook_add_tab (EphyNotebook *nb, sync_load_status (tab, NULL, label); g_signal_connect_object (tab, "notify::icon", - G_CALLBACK (sync_icon), label, 0); + G_CALLBACK (sync_icon), label, 0); g_signal_connect_object (tab, "notify::title", - G_CALLBACK (sync_label), label, 0); + G_CALLBACK (sync_label), label, 0); g_signal_connect_object (tab, "notify::load-status", G_CALLBACK (sync_load_status), label, 0); diff --git a/src/ephy-shell.c b/src/ephy-shell.c index d1144f816..c7dc315c5 100644 --- a/src/ephy-shell.c +++ b/src/ephy-shell.c @@ -30,6 +30,7 @@ #include "ephy-file-helpers.h" #include "ephy-favicon-cache.h" #include "ephy-window.h" +#include "ephy-bookmarks-ui.h" #include "ephy-bookmarks-import.h" #include "ephy-bookmarks-editor.h" #include "ephy-history-window.h" @@ -938,19 +939,10 @@ ephy_shell_get_toolbars_model (EphyShell *shell, gboolean fullscreen) { if (shell->priv->toolbars_model == NULL) { - EphyBookmarks *bookmarks; - GObject *bookmarksbar_model; - shell->priv->toolbars_model = ephy_toolbars_model_new (); - - /* get the bookmarks toolbars model. we have to do this - * before loading the toolbars model from disk, since - * this will connect the get_item_* signals - */ - bookmarks = ephy_shell_get_bookmarks (shell); - bookmarksbar_model = ephy_bookmarks_get_toolbars_model (bookmarks); - - /* ok, now we can load the model */ + + ephy_bookmarks_ui_attach_toolbar_model (shell->priv->toolbars_model); + ephy_toolbars_model_load (EPHY_TOOLBARS_MODEL (shell->priv->toolbars_model)); } diff --git a/src/ephy-toolbar-editor.c b/src/ephy-toolbar-editor.c index a8179dd42..7726e4b62 100644 --- a/src/ephy-toolbar-editor.c +++ b/src/ephy-toolbar-editor.c @@ -167,7 +167,7 @@ ephy_toolbar_editor_constructor (GType type, GObjectConstructParam *construct_params) { - GObject *object; + GObject *object; EphyToolbarEditorPrivate *priv; GtkWidget *dialog, *editor, *toolbar, *vbox, *hbox, *label, *combo; GtkUIManager *manager; @@ -180,13 +180,13 @@ ephy_toolbar_editor_constructor (GType type, char *pref; int i; - object = parent_class->constructor (type, n_construct_properties, + object = parent_class->constructor (type, n_construct_properties, construct_params); #ifdef ENABLE_NLS - /* Initialize the control centre domain */ - bindtextdomain (CONTROL_CENTRE_DOMAIN, GNOMELOCALEDIR); - bind_textdomain_codeset(CONTROL_CENTRE_DOMAIN, "UTF-8"); + /* Initialize the control centre domain */ + bindtextdomain (CONTROL_CENTRE_DOMAIN, GNOMELOCALEDIR); + bind_textdomain_codeset(CONTROL_CENTRE_DOMAIN, "UTF-8"); #endif dialog = GTK_WIDGET (object); @@ -199,14 +199,12 @@ ephy_toolbar_editor_constructor (GType type, gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2); gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); gtk_window_set_title (GTK_WINDOW (dialog), _("Toolbar Editor")); - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (priv->window)); + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (priv->window)); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (priv->window)); editor = egg_toolbar_editor_new (manager, priv->model); - egg_toolbar_editor_load_actions (EGG_TOOLBAR_EDITOR (editor), - ephy_file ("epiphany-toolbar.xml")); gtk_container_set_border_width (GTK_CONTAINER (EGG_TOOLBAR_EDITOR (editor)), 5); gtk_box_set_spacing (GTK_BOX (EGG_TOOLBAR_EDITOR (editor)), 5); gtk_box_pack_start (GTK_BOX (vbox), editor, TRUE, TRUE, 0); @@ -294,13 +292,11 @@ ephy_toolbar_editor_constructor (GType type, gtk_widget_show (editor); ephy_state_add_window (dialog, "toolbar_editor", - 500, 330, FALSE, + 500, 330, FALSE, EPHY_STATE_WINDOW_SAVE_SIZE); gtk_widget_show (dialog); egg_editable_toolbar_set_edit_mode (EGG_EDITABLE_TOOLBAR (toolbar), TRUE); - egg_editable_toolbar_set_edit_mode - (EGG_EDITABLE_TOOLBAR (ephy_window_get_bookmarksbar (priv->window)), TRUE); return object; } @@ -313,8 +309,6 @@ ephy_toolbar_editor_finalize (GObject *object) egg_editable_toolbar_set_edit_mode (EGG_EDITABLE_TOOLBAR (ephy_window_get_toolbar (priv->window)), FALSE); - egg_editable_toolbar_set_edit_mode (EGG_EDITABLE_TOOLBAR - (ephy_window_get_bookmarksbar (priv->window)), FALSE); g_object_set_data (G_OBJECT (priv->window), DATA_KEY, NULL); @@ -337,14 +331,14 @@ ephy_toolbar_editor_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - EphyToolbarEditorPrivate *priv = EPHY_TOOLBAR_EDITOR (object)->priv; + EphyToolbarEditorPrivate *priv = EPHY_TOOLBAR_EDITOR (object)->priv; - switch (prop_id) - { + switch (prop_id) + { case PROP_WINDOW: priv->window = g_value_get_object (value); break; - } + } } static void @@ -363,10 +357,10 @@ ephy_toolbar_editor_class_init (EphyToolbarEditorClass *klass) dialog_class->response = ephy_toolbar_editor_response; g_object_class_install_property (object_class, - PROP_WINDOW, - g_param_spec_object ("window", - "Window", - "Parent window", + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "Parent window", EPHY_TYPE_WINDOW, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); diff --git a/src/ephy-toolbar.c b/src/ephy-toolbar.c index eb31c1ed3..26af93311 100755 --- a/src/ephy-toolbar.c +++ b/src/ephy-toolbar.c @@ -167,20 +167,6 @@ fixed_toolbar_reconfigured_cb (GtkToolItem *item, ephy_spinner_set_size (spinner, size); } -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, G_N_ELEMENTS (drag_targets), t_name); -} - static void maybe_finish_activation_cb (EphyWindow *window, GtkWidget *widget, @@ -528,42 +514,12 @@ ephy_toolbar_set_zoom (EphyToolbar *toolbar, static void ephy_toolbar_realize (GtkWidget *widget) { - EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (widget); - EphyToolbar *toolbar = EPHY_TOOLBAR (widget); - EggToolbarsModel *model = egg_editable_toolbar_get_model (etoolbar); - int i, n_toolbars; - GTK_WIDGET_CLASS (parent_class)->realize (widget); - - 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 - (etoolbar, drag_targets, G_N_ELEMENTS (drag_targets), t_name); - } } static void ephy_toolbar_unrealize (GtkWidget *widget) { - EggEditableToolbar *eggtoolbar = EGG_EDITABLE_TOOLBAR (widget); - EphyToolbar *toolbar = EPHY_TOOLBAR (widget); - EggToolbarsModel *model; - - model = egg_editable_toolbar_get_model (eggtoolbar); - - g_signal_handlers_disconnect_by_func - (model, G_CALLBACK (toolbar_added_cb), toolbar); - GTK_WIDGET_CLASS (parent_class)->unrealize (widget); } @@ -649,7 +605,6 @@ ephy_toolbar_finalize (GObject *object) { EphyToolbar *toolbar = EPHY_TOOLBAR (object); EphyToolbarPrivate *priv = toolbar->priv; - EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); if (priv->set_focus_handler != 0) { @@ -657,10 +612,6 @@ ephy_toolbar_finalize (GObject *object) priv->set_focus_handler); } - g_signal_handlers_disconnect_by_func - (egg_editable_toolbar_get_model (etoolbar), - G_CALLBACK (toolbar_added_cb), toolbar); - G_OBJECT_CLASS (parent_class)->finalize (object); } diff --git a/src/ephy-toolbars-model.c b/src/ephy-toolbars-model.c index b36c0cc1b..a575b53f4 100755 --- a/src/ephy-toolbars-model.c +++ b/src/ephy-toolbars-model.c @@ -30,8 +30,8 @@ #include <string.h> -#define EPHY_TOOLBARS_XML_FILE "epiphany-toolbars-2.xml" -#define EPHY_TOOLBARS_XML_VERSION "1.0" +#define EPHY_TOOLBARS_XML_FILE "epiphany-toolbars-3.xml" +#define EPHY_TOOLBARS_XML_VERSION "1.1" #define EPHY_TOOLBARS_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_TOOLBARS_MODEL, EphyToolbarsModelPrivate)) @@ -106,7 +106,7 @@ update_flags (EphyToolbarsModel *model) { EggToolbarsModel *eggmodel = EGG_TOOLBARS_MODEL (model); int i, n_toolbars; - int flag = EGG_TB_MODEL_ACCEPT_ITEMS_ONLY; + int flag = 0; n_toolbars = egg_toolbars_model_n_toolbars (eggmodel); @@ -138,29 +138,6 @@ update_flags_and_save_changes (EphyToolbarsModel *model) save_changes (model); } -static int -get_toolbar_pos (EggToolbarsModel *model, - const char *name) -{ - int i, n_toolbars; - - 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_val_if_fail (t_name != NULL, -1); - if (strcmp (name, t_name) == 0) - { - return i; - } - } - - return -1; -} - static EggTbModelFlags get_toolbar_style (void) { @@ -203,7 +180,28 @@ ephy_toolbars_model_load (EphyToolbarsModel *model) { EggToolbarsModel *eggmodel = EGG_TOOLBARS_MODEL (model); gboolean success; - + int i; + + egg_toolbars_model_set_n_avail (eggmodel, "NavigationBack", 1); + egg_toolbars_model_set_n_avail (eggmodel, "NavigationForward", 1); + egg_toolbars_model_set_n_avail (eggmodel, "NavigationUp", 1); + egg_toolbars_model_set_n_avail (eggmodel, "ViewStop", 1); + egg_toolbars_model_set_n_avail (eggmodel, "ViewReload", 1); + egg_toolbars_model_set_n_avail (eggmodel, "GoHome", 1); + egg_toolbars_model_set_n_avail (eggmodel, "GoHistory", 1); + egg_toolbars_model_set_n_avail (eggmodel, "GoBookmarks", 1); + egg_toolbars_model_set_n_avail (eggmodel, "FileNewTab", 1); + egg_toolbars_model_set_n_avail (eggmodel, "FileNewWindow", 1); + egg_toolbars_model_set_n_avail (eggmodel, "FileOpen", 1); + egg_toolbars_model_set_n_avail (eggmodel, "FileSaveAs", 1); + egg_toolbars_model_set_n_avail (eggmodel, "FilePrint", 1); + egg_toolbars_model_set_n_avail (eggmodel, "FileBookmarkPage", 1); + egg_toolbars_model_set_n_avail (eggmodel, "ViewFullscreen", 1); + egg_toolbars_model_set_n_avail (eggmodel, "EditFind", 1); + egg_toolbars_model_set_n_avail (eggmodel, "Location", 1); + egg_toolbars_model_set_n_avail (eggmodel, "ToolbarGo", 1); + egg_toolbars_model_set_n_avail (eggmodel, "Zoom", 1); + success = egg_toolbars_model_load (eggmodel, model->priv->xml_file); LOG ("Loading the toolbars was %ssuccessful", success ? "" : "un"); @@ -213,25 +211,37 @@ ephy_toolbars_model_load (EphyToolbarsModel *model) if (success == FALSE) { char *old_xml; - int toolbar; old_xml = g_build_filename (ephy_dot_dir (), - "epiphany-toolbars.xml", + "epiphany-toolbars-2.xml", NULL); success = egg_toolbars_model_load (eggmodel, old_xml); g_free (old_xml); - if (success) + if (success == TRUE) { - toolbar = get_toolbar_pos (eggmodel, "BookmarksBar"); - if (toolbar != -1) - { - egg_toolbars_model_remove_toolbar (eggmodel, toolbar); - } + old_xml = g_build_filename (ephy_dot_dir (), + "epiphany-bookmarksbar.xml", + NULL); + egg_toolbars_model_load (eggmodel, old_xml); + g_free (old_xml); } LOG ("Migration was %ssuccessful", success ? "" : "un"); } + + if (success == FALSE) + { + char *old_xml; + + old_xml = g_build_filename (ephy_dot_dir (), + "epiphany-toolbars.xml", + NULL); + success = egg_toolbars_model_load (eggmodel, old_xml); + g_free (old_xml); + + LOG ("Migration was %ssuccessful", success ? "" : "un"); + } /* Still no success, load the default toolbars */ if (success == FALSE) @@ -241,6 +251,15 @@ ephy_toolbars_model_load (EphyToolbarsModel *model) LOG ("Loading the default toolbars was %ssuccessful", success ? "" : "un"); } + /* Cleanup any empty toolbars */ + for (i = egg_toolbars_model_n_toolbars (eggmodel)-1; i >= 0; i--) + { + if (egg_toolbars_model_n_items (eggmodel, i) == 0) + { + egg_toolbars_model_remove_toolbar (eggmodel, i); + } + } + /* Ensure we have at least 1 toolbar */ if (egg_toolbars_model_n_toolbars (eggmodel) < 1) { diff --git a/src/ephy-window.c b/src/ephy-window.c index 5493b4585..ceaaa8719 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -26,8 +26,6 @@ #include "ephy-type-builtins.h" #include "ephy-embed-type-builtins.h" #include "ephy-command-manager.h" -#include "ephy-bookmarks-menu.h" -#include "ephy-favorites-menu.h" #include "ephy-state.h" #include "ppview-toolbar.h" #include "window-commands.h" @@ -43,12 +41,12 @@ #include "ephy-statusbar.h" #include "egg-editable-toolbar.h" #include "ephy-toolbar.h" -#include "ephy-bookmarksbar.h" #include "popup-commands.h" #include "ephy-encoding-menu.h" #include "ephy-tabs-menu.h" #include "ephy-stock-icons.h" #include "ephy-extension.h" +#include "ephy-bookmarks-ui.h" #include "ephy-link.h" #include "ephy-gui.h" #include "ephy-notebook.h" @@ -94,11 +92,9 @@ static void ephy_window_notebook_switch_page_cb (GtkNotebook *notebook, guint page_num, EphyWindow *window); static void ephy_window_view_statusbar_cb (GtkAction *action, - EphyWindow *window); + EphyWindow *window); static void ephy_window_view_toolbar_cb (GtkAction *action, - EphyWindow *window); -static void ephy_window_view_bookmarksbar_cb (GtkAction *action, - EphyWindow *window); + EphyWindow *window); static void ephy_window_view_popup_windows_cb (GtkAction *action, EphyWindow *window); static void sync_tab_load_status (EphyTab *tab, @@ -295,9 +291,6 @@ static const GtkToggleActionEntry ephy_menu_toggle_entries [] = { "ViewToolbar", NULL, N_("_Toolbar"), "<shift><control>T", N_("Show or hide toolbar"), G_CALLBACK (ephy_window_view_toolbar_cb), TRUE }, - { "ViewBookmarksBar", NULL, N_("_Bookmarks Bar"), NULL, - N_("Show or hide bookmarks bar"), - G_CALLBACK (ephy_window_view_bookmarksbar_cb), TRUE }, { "ViewStatusbar", NULL, N_("St_atusbar"), NULL, N_("Show or hide statusbar"), G_CALLBACK (ephy_window_view_statusbar_cb), TRUE }, @@ -397,7 +390,7 @@ static const struct #define BOOKMARKS_MENU_PATH "/menubar/BookmarksMenu" /* Until https://bugzilla.mozilla.org/show_bug.cgi?id=296002 is fixed */ -#define KEEP_TAB_IN_SAME_TOPLEVEL +//#define KEEP_TAB_IN_SAME_TOPLEVEL #define EPHY_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_WINDOW, EphyWindowPrivate)) @@ -407,15 +400,12 @@ struct _EphyWindowPrivate GtkWidget *menu_dock; GtkWidget *fullscreen_popup; EphyToolbar *toolbar; - GtkWidget *bookmarksbar; GtkWidget *statusbar; GtkUIManager *manager; GtkActionGroup *action_group; GtkActionGroup *popups_action_group; - EphyFavoritesMenu *fav_menu; EphyEncodingMenu *enc_menu; EphyTabsMenu *tabs_menu; - EphyBookmarksMenu *bmk_menu; PPViewToolbar *ppview_toolbar; GtkNotebook *notebook; EphyTab *active_tab; @@ -464,22 +454,22 @@ static GObjectClass *parent_class = NULL; GType ephy_window_get_type (void) { - static GType type = 0; - - if (G_UNLIKELY (type == 0)) - { - static const GTypeInfo our_info = - { - sizeof (EphyWindowClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) ephy_window_class_init, - NULL, - NULL, /* class_data */ - sizeof (EphyWindow), - 0, /* n_preallocs */ - (GInstanceInitFunc) ephy_window_init - }; + static GType type = 0; + + if (G_UNLIKELY (type == 0)) + { + static const GTypeInfo our_info = + { + sizeof (EphyWindowClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) ephy_window_class_init, + NULL, + NULL, /* class_data */ + sizeof (EphyWindow), + 0, /* n_preallocs */ + (GInstanceInitFunc) ephy_window_init + }; static const GInterfaceInfo link_info = { (GInterfaceInitFunc) ephy_window_link_iface_init, @@ -487,16 +477,16 @@ ephy_window_get_type (void) NULL }; - type = g_type_register_static (GTK_TYPE_WINDOW, + type = g_type_register_static (GTK_TYPE_WINDOW, "EphyWindow", &our_info, 0); g_type_add_interface_static (type, EPHY_TYPE_LINK, &link_info); - } + } - return type; + return type; } static void @@ -541,7 +531,6 @@ get_chromes_visibility (EphyWindow *window, gboolean *show_menubar, gboolean *show_statusbar, gboolean *show_toolbar, - gboolean *show_bookmarksbar, gboolean *show_tabsbar) { EphyWindowPrivate *priv = window->priv; @@ -551,14 +540,13 @@ get_chromes_visibility (EphyWindow *window, { *show_menubar = *show_statusbar = *show_toolbar - = *show_bookmarksbar = *show_tabsbar = FALSE; } else if (window->priv->fullscreen_mode) { *show_toolbar = (flags & EPHY_EMBED_CHROME_TOOLBAR) != 0; - *show_menubar = *show_statusbar = *show_bookmarksbar = FALSE; + *show_menubar = *show_statusbar = FALSE; *show_tabsbar = !priv->is_popup; } else @@ -566,7 +554,6 @@ get_chromes_visibility (EphyWindow *window, *show_menubar = (flags & EPHY_EMBED_CHROME_MENUBAR) != 0; *show_statusbar = (flags & EPHY_EMBED_CHROME_STATUSBAR) != 0; *show_toolbar = (flags & EPHY_EMBED_CHROME_TOOLBAR) != 0; - *show_bookmarksbar = (flags & EPHY_EMBED_CHROME_BOOKMARKSBAR) != 0; *show_tabsbar = !priv->is_popup; } } @@ -576,20 +563,19 @@ sync_chromes_visibility (EphyWindow *window) { EphyWindowPrivate *priv = window->priv; GtkWidget *menubar; - gboolean show_statusbar, show_menubar, show_toolbar, show_bookmarksbar, show_tabsbar; + gboolean show_statusbar, show_menubar, show_toolbar, show_tabsbar; if (priv->closing) return; get_chromes_visibility (window, &show_menubar, &show_statusbar, &show_toolbar, - &show_bookmarksbar, &show_tabsbar); + &show_tabsbar); menubar = gtk_ui_manager_get_widget (window->priv->manager, "/menubar"); g_assert (menubar != NULL); g_object_set (menubar, "visible", show_menubar, NULL); g_object_set (priv->toolbar, "visible", show_toolbar, NULL); - g_object_set (priv->bookmarksbar, "visible", show_bookmarksbar, NULL); g_object_set (priv->statusbar, "visible", show_statusbar, NULL); ephy_notebook_set_show_tabs (EPHY_NOTEBOOK (priv->notebook), show_tabsbar); @@ -765,7 +751,7 @@ ephy_window_key_press_event (GtkWidget *widget, } /* Show and activate the menubar, if it isn't visible */ - if (event->keyval == keyval && (event->state & mask) == (modifier & mask)) + if (event->keyval == keyval && (event->state & mask) == (modifier & mask)) { menubar = gtk_ui_manager_get_widget (window->priv->manager, "/menubar"); g_return_val_if_fail (menubar != NULL , FALSE); @@ -780,7 +766,7 @@ ephy_window_key_press_event (GtkWidget *widget, return TRUE; } - } + } return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); } @@ -1010,6 +996,94 @@ menu_item_deselect_cb (GtkMenuItem *proxy, window->priv->help_message_cid); } +static gboolean +tool_item_enter_cb (GtkWidget *proxy, + GdkEventCrossing *event, + EphyWindow *window) +{ + if (event->mode == GDK_CROSSING_NORMAL && + event->detail == GDK_NOTIFY_NONLINEAR) + { + GtkToolItem *item; + GtkAction *action; + char *message; + + item = GTK_TOOL_ITEM (gtk_widget_get_ancestor (proxy, GTK_TYPE_TOOL_ITEM)); + + action = g_object_get_data (G_OBJECT (item), "gtk-action"); + g_return_val_if_fail (action != NULL, FALSE); + + g_object_get (G_OBJECT (action), "tooltip", &message, NULL); + if (message) + { + gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar), + window->priv->help_message_cid, message); + g_free (message); + } + } + + return FALSE; +} + +static gboolean +tool_item_leave_cb (GtkWidget *proxy, + GdkEventCrossing *event, + EphyWindow *window) +{ + if (event->mode == GDK_CROSSING_NORMAL && + event->detail == GDK_NOTIFY_NONLINEAR) + { + gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar), + window->priv->help_message_cid); + } + + return FALSE; +} + +static void +tool_item_drag_begin_cb (GtkWidget *widget, + GdkDragContext *context, + EphyWindow *window) +{ + gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar), + window->priv->help_message_cid); +} + + +static void +connect_tool_item (GtkWidget *proxy, EphyWindow *window) +{ + if (GTK_IS_CONTAINER (proxy)) + { + gtk_container_foreach (GTK_CONTAINER (proxy), + (GtkCallback) connect_tool_item, + (gpointer) window); + } + + g_signal_connect (proxy, "drag_begin", + G_CALLBACK (tool_item_drag_begin_cb), window); + g_signal_connect (proxy, "enter-notify-event", + G_CALLBACK (tool_item_enter_cb), window); + g_signal_connect (proxy, "leave-notify-event", + G_CALLBACK (tool_item_leave_cb), window); +} + +static void +disconnect_tool_item (GtkWidget *proxy, EphyWindow *window) +{ + if (GTK_IS_CONTAINER (proxy)) + { + gtk_container_foreach (GTK_CONTAINER (proxy), + (GtkCallback) disconnect_tool_item, + (gpointer) window); + } + + g_signal_handlers_disconnect_by_func + (proxy, G_CALLBACK (tool_item_enter_cb), window); + g_signal_handlers_disconnect_by_func + (proxy, G_CALLBACK (tool_item_leave_cb), window); +} + static void disconnect_proxy_cb (GtkUIManager *manager, GtkAction *action, @@ -1023,6 +1097,10 @@ disconnect_proxy_cb (GtkUIManager *manager, g_signal_handlers_disconnect_by_func (proxy, G_CALLBACK (menu_item_deselect_cb), window); } + else if (GTK_IS_TOOL_ITEM (proxy)) + { + disconnect_tool_item (proxy, window); + } } static void @@ -1038,6 +1116,10 @@ connect_proxy_cb (GtkUIManager *manager, g_signal_connect (proxy, "deselect", G_CALLBACK (menu_item_deselect_cb), window); } + else if (GTK_IS_TOOL_ITEM (proxy)) + { + connect_tool_item (proxy, window); + } } static void @@ -1045,11 +1127,11 @@ update_chromes_actions (EphyWindow *window) { GtkActionGroup *action_group = window->priv->action_group; GtkAction *action; - gboolean show_statusbar, show_menubar, show_toolbar, show_bookmarksbar, show_tabsbar; + gboolean show_statusbar, show_menubar, show_toolbar, show_tabsbar; get_chromes_visibility (window, &show_menubar, &show_statusbar, &show_toolbar, - &show_bookmarksbar, &show_tabsbar); + &show_tabsbar); action = gtk_action_group_get_action (action_group, "ViewToolbar"); g_signal_handlers_block_by_func (G_OBJECT (action), @@ -1060,15 +1142,6 @@ update_chromes_actions (EphyWindow *window) G_CALLBACK (ephy_window_view_toolbar_cb), window); - action = gtk_action_group_get_action (action_group, "ViewBookmarksBar"); - g_signal_handlers_block_by_func (G_OBJECT (action), - G_CALLBACK (ephy_window_view_bookmarksbar_cb), - window); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_bookmarksbar); - g_signal_handlers_unblock_by_func (G_OBJECT (action), - G_CALLBACK (ephy_window_view_bookmarksbar_cb), - window); - action = gtk_action_group_get_action (action_group, "ViewStatusbar"); g_signal_handlers_block_by_func (G_OBJECT (action), G_CALLBACK (ephy_window_view_statusbar_cb), @@ -1845,6 +1918,7 @@ show_embed_popup (EphyWindow *window, G_CALLBACK (embed_popup_deactivate_cb), window); button = ephy_embed_event_get_button (event); + if (button == 0) { gtk_menu_popup (GTK_MENU (widget), NULL, NULL, @@ -2277,7 +2351,7 @@ tab_added_cb (EphyNotebook *notebook, EphyExtension *manager; EphyEmbed *embed; - g_return_if_fail (EPHY_IS_TAB (tab)); + g_return_if_fail (EPHY_IS_TAB (tab)); window->priv->num_tabs++; @@ -2314,7 +2388,7 @@ tab_removed_cb (EphyNotebook *notebook, EphyExtension *manager; EphyEmbed *embed; - g_return_if_fail (EPHY_IS_TAB (tab)); + g_return_if_fail (EPHY_IS_TAB (tab)); /* Let the extensions remove themselves from the tab */ manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell)); @@ -2447,11 +2521,6 @@ ephy_window_set_chrome (EphyWindow *window, EphyEmbedChrome mask) chrome_mask &= ~EPHY_EMBED_CHROME_STATUSBAR; } - if (!eel_gconf_get_boolean (CONF_WINDOWS_SHOW_BOOKMARKS_BAR)) - { - chrome_mask &= ~EPHY_EMBED_CHROME_BOOKMARKSBAR; - } - if (eel_gconf_get_boolean (CONF_LOCKDOWN_HIDE_MENUBAR)) { chrome_mask &= ~EPHY_EMBED_CHROME_MENUBAR; @@ -2507,6 +2576,7 @@ ephy_window_dispose (GObject *object) /* Let the extensions detach themselves from the window */ manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell)); ephy_extension_detach_window (manager, window); + ephy_bookmarks_ui_detach_window (window); /* Deactivate menus */ popups = gtk_ui_manager_get_toplevels (window->priv->manager, GTK_UI_MANAGER_POPUP); @@ -2530,18 +2600,12 @@ ephy_window_dispose (GObject *object) g_hash_table_foreach_remove (priv->tabs_to_remove, (GHRFunc) remove_true, NULL); - g_object_unref (priv->fav_menu); - priv->fav_menu = NULL; - g_object_unref (priv->enc_menu); priv->enc_menu = NULL; g_object_unref (priv->tabs_menu); priv->tabs_menu = NULL; - g_object_unref (priv->bmk_menu); - priv->bmk_menu = NULL; - if (priv->ppview_toolbar) { g_object_unref (priv->ppview_toolbar); @@ -2559,7 +2623,7 @@ ephy_window_dispose (GObject *object) destroy_fullscreen_popup (window); - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (parent_class)->dispose (object); } static void @@ -2710,11 +2774,11 @@ ephy_window_class_init (EphyWindowClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - parent_class = g_type_class_peek_parent (klass); + parent_class = g_type_class_peek_parent (klass); object_class->constructor = ephy_window_constructor; object_class->dispose = ephy_window_dispose; - object_class->finalize = ephy_window_finalize; + object_class->finalize = ephy_window_finalize; object_class->get_property = ephy_window_get_property; object_class->set_property = ephy_window_set_property; @@ -2799,14 +2863,6 @@ allow_popups_notifier (GConfClient *client, } } -static void -action_request_forward_cb (GObject *toolbar, - const char *name, - GObject *bookmarksbar) -{ - g_signal_emit_by_name (bookmarksbar, "action_request", name); -} - static EphyTab * ephy_window_open_link (EphyLink *link, const char *address, @@ -2950,10 +3006,6 @@ ephy_window_init (EphyWindow *window) G_CALLBACK (ephy_link_open), window); g_signal_connect_swapped (window->priv->toolbar, "exit-clicked", G_CALLBACK (exit_fullscreen_clicked_cb), window); - window->priv->bookmarksbar = ephy_bookmarksbar_new (window); - g_signal_connect_swapped (window->priv->bookmarksbar, "open-link", - G_CALLBACK (ephy_link_open), window); - g_signal_connect_swapped (window->priv->toolbar, "activation-finished", G_CALLBACK (sync_chromes_visibility), window); @@ -2964,37 +3016,21 @@ ephy_window_init (EphyWindow *window) { g_warning ("Could not merge epiphany-ui.xml: %s", error->message); g_error_free (error); - } + } /* Initialize the menus */ window->priv->tabs_menu = ephy_tabs_menu_new (window); window->priv->enc_menu = ephy_encoding_menu_new (window); - window->priv->fav_menu = ephy_favorites_menu_new (window); - g_signal_connect_swapped (window->priv->fav_menu, "open-link", - G_CALLBACK (ephy_link_open), window); - window->priv->bmk_menu = ephy_bookmarks_menu_new (window->priv->manager, - BOOKMARKS_MENU_PATH); - g_signal_connect_swapped (window->priv->bmk_menu, "open-link", - G_CALLBACK (ephy_link_open), window); - - /* forward the toolbar's action_request signal to the bookmarks toolbar, - * so the user can also have bookmarks on the normal toolbar - */ - g_signal_connect (window->priv->toolbar, "action_request", - G_CALLBACK (action_request_forward_cb), - window->priv->bookmarksbar); /* Add the toolbars to the window */ gtk_box_pack_end (GTK_BOX (window->priv->menu_dock), - window->priv->bookmarksbar, - FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (window->priv->menu_dock), GTK_WIDGET (window->priv->toolbar), FALSE, FALSE, 0); /* Once the window is sufficiently created let the extensions attach to it */ manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell)); ephy_extension_attach_window (manager, window); + ephy_bookmarks_ui_attach_window (window); /* We only set the model now after attaching the extensions, so that * extensions already have created their actions which may be on @@ -3051,7 +3087,7 @@ ephy_window_finalize (GObject *object) g_hash_table_destroy (priv->tabs_to_remove); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (parent_class)->finalize (object); LOG ("EphyWindow finalised %p", object); @@ -3169,22 +3205,6 @@ ephy_window_get_toolbar (EphyWindow *window) } /** - * ephy_window_get_bookmarksbar: - * @window: an #EphyWindow - * - * Returns this window's bookmarks toolbar, which is an #EggEditableToolbar. - * - * Return value: an #EggEditableToolbar - **/ -GtkWidget * -ephy_window_get_bookmarksbar (EphyWindow *window) -{ - g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL); - - return GTK_WIDGET (window->priv->bookmarksbar); -} - -/** * ephy_window_get_notebook: * @window: an #EphyWindow * @@ -3304,7 +3324,7 @@ real_get_active_tab (EphyWindow *window, int page_num) **/ void ephy_window_remove_tab (EphyWindow *window, - EphyTab *tab) + EphyTab *tab) { EphyEmbed *embed; gboolean modified; @@ -3483,10 +3503,10 @@ ephy_window_set_zoom (EphyWindow *window, EphyEmbed *embed; float current_zoom = 1.0; - g_return_if_fail (EPHY_IS_WINDOW (window)); + g_return_if_fail (EPHY_IS_WINDOW (window)); embed = ephy_window_get_active_embed (window); - g_return_if_fail (embed != NULL); + g_return_if_fail (embed != NULL); current_zoom = ephy_embed_get_zoom (embed); @@ -3512,8 +3532,6 @@ sync_prefs_with_chrome (EphyWindow *window) if (window->priv->should_save_chrome) { - eel_gconf_set_boolean (CONF_WINDOWS_SHOW_BOOKMARKS_BAR, - flags & EPHY_EMBED_CHROME_BOOKMARKSBAR); eel_gconf_set_boolean (CONF_WINDOWS_SHOW_TOOLBARS, flags & EPHY_EMBED_CHROME_TOOLBAR); eel_gconf_set_boolean (CONF_WINDOWS_SHOW_STATUSBAR, @@ -3552,14 +3570,6 @@ ephy_window_view_toolbar_cb (GtkAction *action, } static void -ephy_window_view_bookmarksbar_cb (GtkAction *action, - EphyWindow *window) -{ - sync_chrome_with_view_toggle (action, window, - EPHY_EMBED_CHROME_BOOKMARKSBAR); -} - -static void ephy_window_view_popup_windows_cb (GtkAction *action, EphyWindow *window) { diff --git a/src/ephy-window.h b/src/ephy-window.h index a3c31f994..9722488c4 100644 --- a/src/ephy-window.h +++ b/src/ephy-window.h @@ -43,15 +43,15 @@ typedef struct _EphyWindowPrivate EphyWindowPrivate; struct _EphyWindow { - GtkWindow parent; + GtkWindow parent; /*< private >*/ - EphyWindowPrivate *priv; + EphyWindowPrivate *priv; }; struct _EphyWindowClass { - GtkWindowClass parent_class; + GtkWindowClass parent_class; }; GType ephy_window_get_type (void); @@ -68,8 +68,6 @@ GObject *ephy_window_get_ui_manager (EphyWindow *window); GtkWidget *ephy_window_get_toolbar (EphyWindow *window); -GtkWidget *ephy_window_get_bookmarksbar (EphyWindow *window); - GtkWidget *ephy_window_get_notebook (EphyWindow *window); GtkWidget *ephy_window_get_find_toolbar (EphyWindow *window); |