/* * 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 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 #endif #include #include #include #include #include #include #include #include #include #include #include "ephy-node-view.h" #include "ephy-window.h" #include "ephy-history-window.h" #include "ephy-shell.h" #include "ephy-dnd.h" #include "egg-action-group.h" #include "egg-toggle-action.h" #include "egg-menu-merge.h" #include "ephy-state.h" #include "window-commands.h" #include "ephy-file-helpers.h" #include "ephy-debug.h" #include "ephy-new-bookmark.h" #include "ephy-stock-icons.h" #include "ephy-gui.h" #include "toolbar.h" #include "ephy-stock-icons.h" #include "ephy-search-entry.h" #include "session.h" #include "ephy-favicon-cache.h" static GtkTargetEntry page_drag_types [] = { { EPHY_DND_URI_LIST_TYPE, 0, 0 }, { EPHY_DND_TEXT_TYPE, 0, 1 }, { EPHY_DND_URL_TYPE, 0, 2 } }; static int n_page_drag_types = G_N_ELEMENTS (page_drag_types); static void ephy_history_window_class_init (EphyHistoryWindowClass *klass); static void ephy_history_window_init (EphyHistoryWindow *editor); static void ephy_history_window_finalize (GObject *object); static void ephy_history_window_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void ephy_history_window_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void ephy_history_window_dispose (GObject *object); static void cmd_open_bookmarks_in_tabs (EggAction *action, EphyHistoryWindow *editor); static void cmd_open_bookmarks_in_browser (EggAction *action, EphyHistoryWindow *editor); static void cmd_delete (EggAction *action, EphyHistoryWindow *editor); static void cmd_bookmark_link (EggAction *action, EphyHistoryWindow *editor); static void cmd_clear (EggAction *action, EphyHistoryWindow *editor); static void cmd_close (EggAction *action, EphyHistoryWindow *editor); static void cmd_cut (EggAction *action, EphyHistoryWindow *editor); static void cmd_copy (EggAction *action, EphyHistoryWindow *editor); static void cmd_paste (EggAction *action, EphyHistoryWindow *editor); static void cmd_select_all (EggAction *action, EphyHistoryWindow *editor); static void cmd_help_contents (EggAction *action, EphyHistoryWindow *editor); struct EphyHistoryWindowPrivate { EphyHistory *history; GtkWidget *sites_view; GtkWidget *pages_view; EphyNodeFilter *pages_filter; GtkWidget *search_entry; GtkWidget *menu_dock; GtkWidget *window; EggMenuMerge *ui_merge; EggActionGroup *action_group; GtkWidget *confirmation_dialog; }; enum { PROP_0, PROP_HISTORY }; static GObjectClass *parent_class = NULL; static EggActionGroupEntry ephy_history_ui_entries [] = { /* Toplevel */ { "File", N_("_File"), NULL, NULL, NULL, NULL, NULL }, { "Edit", N_("_Edit"), NULL, NULL, NULL, NULL, NULL }, { "View", N_("_View"), NULL, NULL, NULL, NULL, NULL }, { "Help", N_("_Help"), NULL, NULL, NULL, NULL, NULL }, { "FakeToplevel", (""), NULL, NULL, NULL, NULL, NULL }, /* File Menu */ { "OpenInWindow", N_("_Open in New Window"), GTK_STOCK_OPEN, "O", N_("Open the selected history link in a new window"), G_CALLBACK (cmd_open_bookmarks_in_browser), NULL }, { "OpenInTab", N_("Open in New _Tab"), NULL, "O", N_("Open the selected history link in a new tab"), G_CALLBACK (cmd_open_bookmarks_in_tabs), NULL }, { "Delete", N_("_Delete"), GTK_STOCK_DELETE, NULL, N_("Delete the selected history link"), G_CALLBACK (cmd_delete), NULL }, { "BookmarkLink", N_("Boo_kmark Link..."), EPHY_STOCK_BOOKMARK_PAGE, "D", N_("Bookmark the selected history link"), G_CALLBACK (cmd_bookmark_link), NULL }, { "Close", N_("_Close"), GTK_STOCK_CLOSE, "W", N_("Close the history window"), G_CALLBACK (cmd_close), NULL }, /* Edit Menu */ { "Cut", N_("Cu_t"), GTK_STOCK_CUT, "X", N_("Cut the selection"), G_CALLBACK (cmd_cut), NULL }, { "Copy", N_("_Copy"), GTK_STOCK_COPY, "C", N_("Copy the selection"), G_CALLBACK (cmd_copy), NULL }, { "Paste", N_("_Paste"), GTK_STOCK_PASTE, "V", N_("Paste the clipboard"), G_CALLBACK (cmd_paste), NULL }, { "SelectAll", N_("Select _All"), NULL, "A", N_("Select all history links or text"), G_CALLBACK (cmd_select_all), NULL }, { "Clear", N_("C_lear History"), GTK_STOCK_CLEAR, NULL, N_("Clear your browsing history"), G_CALLBACK (cmd_clear), NULL }, /* View Menu */ { "ViewTitle", N_("_Title"), NULL, NULL, N_("Show only the title column"), NULL, NULL, RADIO_ACTION, NULL }, { "ViewLocation", N_("_Address"), NULL, NULL, N_("Show only the address column"), NULL, NULL, RADIO_ACTION, "ViewTitle" }, { "ViewTitleLocation", N_("T_itle and Address"), NULL, NULL, N_("Show both the title and address columns"), NULL, NULL, RADIO_ACTION, "ViewTitle" }, /* Help Menu */ { "HelpContents", N_("_Contents"), GTK_STOCK_HELP, "F1", N_("Display history help"), G_CALLBACK (cmd_help_contents), NULL }, { "HelpAbout", N_("_About"), GNOME_STOCK_ABOUT, NULL, N_("Display credits for the web browser creators"), G_CALLBACK (window_cmd_help_about), NULL }, }; static guint ephy_history_ui_n_entries = G_N_ELEMENTS (ephy_history_ui_entries); static void confirmation_dialog_response_cb (GtkDialog *dialog, gint response, EphyHistoryWindow *editor) { const GList *windows; Session *session; gtk_widget_destroy (GTK_WIDGET (dialog)); if (response != GTK_RESPONSE_OK) return; session = SESSION (ephy_shell_get_session (ephy_shell)); windows = session_get_windows (session); for (; windows != NULL; windows = windows->next) { Toolbar *t; t = ephy_window_get_toolbar (EPHY_WINDOW (windows->data)); toolbar_clear_location_history (t); } ephy_history_clear (editor->priv->history); } static GtkWidget * confirmation_dialog_construct (EphyHistoryWindow *editor) { GtkWidget *dialog; GtkWidget *label; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *image; GtkWidget *button; GtkWidget *align; char *str; dialog = gtk_dialog_new_with_buttons (_("Clear history"), GTK_WINDOW (editor), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, NULL); gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); gtk_container_set_border_width (GTK_CONTAINER (dialog), 6); gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12); button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); gtk_widget_show (button); gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_CANCEL); button = gtk_button_new (); gtk_widget_show (button); gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); gtk_widget_show (align); gtk_container_add (GTK_CONTAINER (button), align); hbox = gtk_hbox_new (FALSE, 2); gtk_widget_show (hbox); gtk_container_add (GTK_CONTAINER (align), hbox); image = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON); gtk_widget_show (image); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic (_("C_lear")); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); hbox = gtk_hbox_new (FALSE, 6); gtk_widget_show (hbox); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, 0); image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); gtk_widget_show (image); gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0); vbox = gtk_vbox_new (FALSE, 6); gtk_widget_show (vbox); gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); str = g_strconcat ("", _("Clear browsing history?"), "", NULL); gtk_label_set_markup (GTK_LABEL (label), str); g_free (str); gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); gtk_widget_show (label); label = gtk_label_new (_("Clearing the browsing history will cause all" " history links to be permanently deleted.")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); gtk_widget_show (label); g_signal_connect (dialog, "response", G_CALLBACK (confirmation_dialog_response_cb), editor); return dialog; } static void cmd_clear (EggAction *action, EphyHistoryWindow *editor) { if (editor->priv->confirmation_dialog == NULL) { editor->priv->confirmation_dialog = confirmation_dialog_construct (editor); g_object_add_weak_pointer (G_OBJECT(editor->priv->confirmation_dialog), (gpointer *)&editor->priv->confirmation_dialog); } gtk_widget_show (editor->priv->confirmation_dialog); } static void cmd_close (EggAction *action, EphyHistoryWindow *editor) { if (editor->priv->confirmation_dialog != NULL) { gtk_widget_destroy (editor->priv->confirmation_dialog); } gtk_widget_hide (GTK_WIDGET (editor)); } static GtkWidget * get_target_window (EphyHistoryWindow *editor) { if (editor->priv->window) { return editor->priv->window; } else { return GTK_WIDGET (ephy_shell_get_active_window (ephy_shell)); } } static void cmd_open_bookmarks_in_tabs (EggAction *action, EphyHistoryWindow *editor) { EphyWindow *window; GList *selection; GList *l; window = EPHY_WINDOW (get_target_window (editor)); selection = ephy_node_view_get_selection (EPHY_NODE_VIEW (editor->priv->pages_view)); for (l = selection; l; l = l->next) { EphyNode *node = l->data; const char *location; location = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_LOCATION); ephy_shell_new_tab (ephy_shell, window, NULL, location, EPHY_NEW_TAB_OPEN_PAGE | EPHY_NEW_TAB_IN_EXISTING_WINDOW); } g_list_free (selection); } static void cmd_open_bookmarks_in_browser (EggAction *action, EphyHistoryWindow *editor) { EphyWindow *window; GList *selection; GList *l; window = EPHY_WINDOW (get_target_window (editor)); selection = ephy_node_view_get_selection (EPHY_NODE_VIEW (editor->priv->pages_view)); for (l = selection; l; l = l->next) { EphyNode *node = l->data; const char *location; location = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_LOCATION); ephy_shell_new_tab (ephy_shell, window, NULL, location, EPHY_NEW_TAB_OPEN_PAGE | EPHY_NEW_TAB_IN_NEW_WINDOW); } g_list_free (selection); } static void cmd_cut (EggAction *action, EphyHistoryWindow *editor) { GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (editor)); if (GTK_IS_EDITABLE (widget)) { gtk_editable_cut_clipboard (GTK_EDITABLE (widget)); } } static void cmd_copy (EggAction *action, EphyHistoryWindow *editor) { GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (editor)); if (GTK_IS_EDITABLE (widget)) { gtk_editable_copy_clipboard (GTK_EDITABLE (widget)); } else if (ephy_node_view_is_target (EPHY_NODE_VIEW (editor->priv->pages_view))) { GList *selection; selection = ephy_node_view_get_selection (EPHY_NODE_VIEW (editor->priv->pages_view)); if (g_list_length (selection) == 1) { const char *tmp; EphyNode *node = selection->data; tmp = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_LOCATION); gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), tmp, -1); } g_list_free (selection); } } static void cmd_paste (EggAction *action, EphyHistoryWindow *editor) { GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (editor)); if (GTK_IS_EDITABLE (widget)) { gtk_editable_paste_clipboard (GTK_EDITABLE (widget)); } } static void cmd_select_all (EggAction *action, EphyHistoryWindow *editor) { GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (editor)); GtkWidget *pages_view = editor->priv->pages_view; if (GTK_IS_EDITABLE (widget)) { gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1); } else if (ephy_node_view_is_target (EPHY_NODE_VIEW (pages_view))) { GtkTreeSelection *sel; sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (pages_view)); gtk_tree_selection_select_all (sel); } } static void cmd_delete (EggAction *action, EphyHistoryWindow *editor) { if (ephy_node_view_is_target (EPHY_NODE_VIEW (editor->priv->pages_view))) { ephy_node_view_remove (EPHY_NODE_VIEW (editor->priv->pages_view)); } } static void cmd_bookmark_link (EggAction *action, EphyHistoryWindow *editor) { GtkWindow *window; EphyBookmarks *bookmarks; GtkWidget *new_bookmark; GList *selection; window = GTK_WINDOW(get_target_window (editor)); bookmarks = ephy_shell_get_bookmarks (ephy_shell); selection = ephy_node_view_get_selection (EPHY_NODE_VIEW (editor->priv->pages_view)); if (g_list_length (selection) == 1) { const char *location; const char *title; EphyNode *node; node = selection->data; location = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_LOCATION); title = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_TITLE); if (ephy_new_bookmark_is_unique (bookmarks, GTK_WINDOW (window), location)) { new_bookmark = ephy_new_bookmark_new (bookmarks, window, location); ephy_new_bookmark_set_title (EPHY_NEW_BOOKMARK (new_bookmark), title); gtk_widget_show (new_bookmark); } } g_list_free (selection); } static void cmd_help_contents (EggAction *action, EphyHistoryWindow *editor) { ephy_gui_help (GTK_WINDOW (editor), "epiphany", "ephy-managing-history"); } GType ephy_history_window_get_type (void) { static GType ephy_history_window_type = 0; if (ephy_history_window_type == 0) { static const GTypeInfo our_info = { sizeof (EphyHistoryWindowClass), NULL, NULL, (GClassInitFunc) ephy_history_window_class_init, NULL, NULL, sizeof (EphyHistoryWindow), 0, (GInstanceInitFunc) ephy_history_window_init }; ephy_history_window_type = g_type_register_static (GTK_TYPE_WINDOW, "EphyHistoryWindow", &our_info, 0); } return ephy_history_window_type; } static void ephy_history_window_class_init (EphyHistoryWindowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = ephy_history_window_finalize; object_class->set_property = ephy_history_window_set_property; object_class->get_property = ephy_history_window_get_property; object_class->dispose = ephy_history_window_dispose; g_object_class_install_property (object_class, PROP_HISTORY, g_param_spec_object ("history", "Global history", "Global History", EPHY_HISTORY_TYPE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } static void ephy_history_window_finalize (GObject *object) { EphyHistoryWindow *editor; g_return_if_fail (object != NULL); g_return_if_fail (EPHY_IS_HISTORY_WINDOW (object)); editor = EPHY_HISTORY_WINDOW (object); g_return_if_fail (editor->priv != NULL); g_object_unref (G_OBJECT (editor->priv->pages_filter)); g_object_unref (editor->priv->action_group); egg_menu_merge_remove_action_group (editor->priv->ui_merge, editor->priv->action_group); g_object_unref (editor->priv->ui_merge); if (editor->priv->window) { g_object_remove_weak_pointer (G_OBJECT(editor->priv->window), (gpointer *)&editor->priv->window); } g_free (editor->priv); G_OBJECT_CLASS (parent_class)->finalize (object); } static void ephy_history_window_node_activated_cb (GtkWidget *view, EphyNode *node, EphyHistoryWindow *editor) { const char *location; EphyWindow *window; location = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_LOCATION); g_return_if_fail (location != NULL); window = EPHY_WINDOW (get_target_window (editor)); ephy_shell_new_tab (ephy_shell, NULL, NULL, location, EPHY_NEW_TAB_OPEN_PAGE); } static void ephy_history_window_update_menu (EphyHistoryWindow *editor) { gboolean open_in_window, open_in_tab; gboolean cut, copy, paste, select_all; gboolean pages_focus, pages_selection; gboolean pages_multiple_selection; gboolean delete, bookmark_page; EggActionGroup *action_group; EggAction *action; char *open_in_window_label, *open_in_tab_label, *copy_label; GtkWidget *focus_widget; pages_focus = ephy_node_view_is_target (EPHY_NODE_VIEW (editor->priv->pages_view)); pages_selection = ephy_node_view_has_selection (EPHY_NODE_VIEW (editor->priv->pages_view), &pages_multiple_selection); focus_widget = gtk_window_get_focus (GTK_WINDOW (editor)); if (GTK_IS_EDITABLE (focus_widget)) { gboolean has_selection; gboolean clipboard_contains_text; has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (focus_widget), NULL, NULL); clipboard_contains_text = gtk_clipboard_wait_is_text_available (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)); cut = has_selection; copy = has_selection; paste = clipboard_contains_text; select_all = TRUE; } else { cut = FALSE; copy = (pages_focus && !pages_multiple_selection && pages_selection); paste = FALSE; select_all = pages_focus; } if (pages_multiple_selection) { open_in_window_label = N_("_Open in New Windows"); open_in_tab_label = N_("Open in New _Tabs"); } else { open_in_window_label = _("_Open in New Window"); open_in_tab_label = _("Open in New _Tab"); } if (pages_focus) { copy_label = _("_Copy Address"); } else { copy_label = _("_Copy"); } open_in_window = (pages_focus && pages_selection); open_in_tab = (pages_focus && pages_selection); delete = (pages_focus && pages_selection); bookmark_page = (pages_focus && pages_selection && !pages_multiple_selection); action_group = editor->priv->action_group; action = egg_action_group_get_action (action_group, "OpenInWindow"); g_object_set (action, "sensitive", open_in_window, NULL); g_object_set (action, "label", open_in_window_label, NULL); action = egg_action_group_get_action (action_group, "OpenInTab"); g_object_set (action, "sensitive", open_in_tab, NULL); g_object_set (action, "label", open_in_tab_label, NULL); action = egg_action_group_get_action (action_group, "Cut"); g_object_set (action, "sensitive", cut, NULL); action = egg_action_group_get_action (action_group, "Copy"); g_object_set (action, "sensitive", copy, NULL); g_object_set (action, "label", copy_label, NULL); action = egg_action_group_get_action (action_group, "Paste"); g_object_set (action, "sensitive", paste, NULL); action = egg_action_group_get_action (action_group, "SelectAll"); g_object_set (action, "sensitive", select_all, NULL); action = egg_action_group_get_action (action_group, "Delete"); g_object_set (action, "sensitive", delete, NULL); action = egg_action_group_get_action (action_group, "BookmarkLink"); g_object_set (action, "sensitive", bookmark_page, NULL); } static void entry_selection_changed_cb (GtkWidget *widget, GParamSpec *pspec, EphyHistoryWindow *editor) { ephy_history_window_update_menu (editor); } static void add_entry_monitor (EphyHistoryWindow *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); } static gboolean view_focus_cb (EphyNodeView *view, GdkEventFocus *event, EphyHistoryWindow *editor) { ephy_history_window_update_menu (editor); return FALSE; } static void add_focus_monitor (EphyHistoryWindow *editor, GtkWidget *widget) { g_signal_connect (G_OBJECT (widget), "focus_in_event", G_CALLBACK (view_focus_cb), editor); g_signal_connect (G_OBJECT (widget), "focus_out_event", G_CALLBACK (view_focus_cb), editor); } static void remove_focus_monitor (EphyHistoryWindow *editor, GtkWidget *widget) { g_signal_handlers_disconnect_by_func (G_OBJECT (widget), G_CALLBACK (view_focus_cb), editor); } static void ephy_history_window_show_popup_cb (GtkWidget *view, EphyHistoryWindow *editor) { GtkWidget *widget; widget = egg_menu_merge_get_widget (editor->priv->ui_merge, "/popups/EphyHistoryWindowPopup"); gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL, 2, gtk_get_current_event_time ()); } static void pages_filter (EphyHistoryWindow *editor, EphyNode *site) { ephy_node_filter_empty (editor->priv->pages_filter); ephy_node_filter_add_expression (editor->priv->pages_filter, ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_HAS_PARENT, site), 0); ephy_node_filter_done_changing (editor->priv->pages_filter); } static gboolean key_pressed_cb (EphyNodeView *view, GdkEventKey *event, EphyHistoryWindow *editor) { switch (event->keyval) { case GDK_Delete: case GDK_KP_Delete: cmd_delete (NULL, editor); return TRUE; default: break; } return FALSE; } static void site_node_selected_cb (EphyNodeView *view, EphyNode *node, EphyHistoryWindow *editor) { EphyNode *pages; if (node == NULL) { pages = ephy_history_get_pages (editor->priv->history); ephy_node_view_select_node (EPHY_NODE_VIEW (editor->priv->sites_view), pages); } else { ephy_search_entry_clear (EPHY_SEARCH_ENTRY (editor->priv->search_entry)); pages_filter (editor, node); } } static void search_entry_search_cb (GtkWidget *entry, char *search_text, EphyHistoryWindow *editor) { EphyNode *all; g_signal_handlers_block_by_func (G_OBJECT (editor->priv->sites_view), G_CALLBACK (site_node_selected_cb), editor); all = ephy_history_get_pages (editor->priv->history); ephy_node_view_select_node (EPHY_NODE_VIEW (editor->priv->sites_view), all); g_signal_handlers_unblock_by_func (G_OBJECT (editor->priv->sites_view), G_CALLBACK (site_node_selected_cb), editor); GDK_THREADS_ENTER (); ephy_node_filter_empty (editor->priv->pages_filter); ephy_node_filter_add_expression (editor->priv->pages_filter, ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_STRING_PROP_CONTAINS, EPHY_NODE_PAGE_PROP_TITLE, search_text), 0); ephy_node_filter_add_expression (editor->priv->pages_filter, ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_STRING_PROP_CONTAINS, EPHY_NODE_PAGE_PROP_LOCATION, search_text), 0); ephy_node_filter_done_changing (editor->priv->pages_filter); GDK_THREADS_LEAVE (); } static GtkWidget * build_search_box (EphyHistoryWindow *editor) { GtkWidget *box; GtkWidget *label; GtkWidget *entry; char *str; box = gtk_hbox_new (FALSE, 6); gtk_container_set_border_width (GTK_CONTAINER (box), 6); gtk_widget_show (box); entry = ephy_search_entry_new (); add_focus_monitor (editor, entry); add_entry_monitor (editor, entry); editor->priv->search_entry = entry; gtk_widget_show (entry); g_signal_connect (G_OBJECT (entry), "search", G_CALLBACK (search_entry_search_cb), editor); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); str = g_strconcat ("", _("_Search:"), "", NULL); gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str); g_free (str); gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0); return box; } static void add_widget (EggMenuMerge *merge, GtkWidget *widget, EphyHistoryWindow *editor) { gtk_box_pack_start (GTK_BOX (editor->priv->menu_dock), widget, FALSE, FALSE, 0); gtk_widget_show (widget); } static gboolean delete_event_cb (EphyHistoryWindow *editor) { gtk_widget_hide (GTK_WIDGET (editor)); return TRUE; } static void provide_favicon (EphyNode *node, GValue *value, gpointer user_data) { EphyFaviconCache *cache; const char *icon_location; GdkPixbuf *pixbuf = NULL; cache = EPHY_FAVICON_CACHE (ephy_embed_shell_get_favicon_cache (EPHY_EMBED_SHELL (ephy_shell))); icon_location = ephy_node_get_property_string (node, EPHY_NODE_PAGE_PROP_ICON); LOG ("Get favicon for %s", icon_location ? icon_location : "None") if (icon_location) { pixbuf = ephy_favicon_cache_get (cache, icon_location); } g_value_init (value, GDK_TYPE_PIXBUF); g_value_set_object_take_ownership (value, pixbuf); } static void view_selection_changed_cb (GtkWidget *view, EphyHistoryWindow *editor) { ephy_history_window_update_menu (editor); } static void ephy_history_window_construct (EphyHistoryWindow *editor) { GtkTreeViewColumn *col; GtkTreeSelection *selection; GtkWidget *vbox, *hpaned; GtkWidget *pages_view, *sites_view; GtkWidget *scrolled_window; EphyNode *node; EggMenuMerge *ui_merge; EggActionGroup *action_group; EggAction *action; GdkPixbuf *icon; int i, col_id; gtk_window_set_title (GTK_WINDOW (editor), _("History")); icon = gtk_widget_render_icon (GTK_WIDGET (editor), EPHY_STOCK_HISTORY, GTK_ICON_SIZE_MENU, NULL); gtk_window_set_icon (GTK_WINDOW(editor), icon); g_signal_connect (editor, "delete_event", G_CALLBACK (delete_event_cb), NULL); for (i = 0; i < ephy_history_ui_n_entries; i++) { ephy_history_ui_entries[i].user_data = editor; } editor->priv->menu_dock = gtk_vbox_new (FALSE, 0); gtk_widget_show (editor->priv->menu_dock); gtk_container_add (GTK_CONTAINER (editor), editor->priv->menu_dock); ui_merge = egg_menu_merge_new (); g_signal_connect (ui_merge, "add_widget", G_CALLBACK (add_widget), editor); action_group = egg_action_group_new ("PopupActions"); egg_action_group_add_actions (action_group, ephy_history_ui_entries, ephy_history_ui_n_entries); egg_menu_merge_insert_action_group (ui_merge, action_group, 0); egg_menu_merge_add_ui_from_file (ui_merge, ephy_file ("epiphany-history-window-ui.xml"), NULL); gtk_window_add_accel_group (GTK_WINDOW (editor), ui_merge->accel_group); egg_menu_merge_ensure_update (ui_merge); editor->priv->ui_merge = ui_merge; editor->priv->action_group = action_group; /* Fixme: We should implement gconf prefs for monitoring this setting */ action = egg_action_group_get_action (action_group, "ViewTitle"); egg_toggle_action_set_active (EGG_TOGGLE_ACTION (action), TRUE); hpaned = gtk_hpaned_new (); gtk_container_set_border_width (GTK_CONTAINER (hpaned), 0); gtk_container_add (GTK_CONTAINER (editor->priv->menu_dock), hpaned); gtk_widget_show (hpaned); g_assert (editor->priv->history); /* Sites View */ node = ephy_history_get_hosts (editor->priv->history); scrolled_window = g_object_new (GTK_TYPE_SCROLLED_WINDOW, "hadjustment", NULL, "vadjustment", NULL, "hscrollbar_policy", GTK_POLICY_AUTOMATIC, "vscrollbar_policy", GTK_POLICY_AUTOMATIC, "shadow_type", GTK_SHADOW_IN, NULL); gtk_paned_add1 (GTK_PANED (hpaned), scrolled_window); gtk_widget_show (scrolled_window); sites_view = ephy_node_view_new (node, NULL); add_focus_monitor (editor, sites_view); col_id = ephy_node_view_add_data_column (EPHY_NODE_VIEW (sites_view), G_TYPE_STRING, EPHY_NODE_PAGE_PROP_LOCATION, NULL, NULL); ephy_node_view_select_node (EPHY_NODE_VIEW (sites_view), ephy_history_get_pages (editor->priv->history)); ephy_node_view_enable_drag_source (EPHY_NODE_VIEW (sites_view), page_drag_types, n_page_drag_types, col_id); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sites_view)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); ephy_node_view_add_column (EPHY_NODE_VIEW (sites_view), _("Sites"), G_TYPE_STRING, EPHY_NODE_PAGE_PROP_TITLE, EPHY_NODE_PAGE_PROP_PRIORITY, EPHY_NODE_VIEW_AUTO_SORT | EPHY_NODE_VIEW_SEARCHABLE, provide_favicon); gtk_container_add (GTK_CONTAINER (scrolled_window), sites_view); gtk_widget_show (sites_view); editor->priv->sites_view = sites_view; g_signal_connect (G_OBJECT (sites_view), "node_selected", G_CALLBACK (site_node_selected_cb), editor); g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (view_selection_changed_cb), editor); vbox = gtk_vbox_new (FALSE, 0); gtk_paned_add2 (GTK_PANED (hpaned), vbox); gtk_widget_show (vbox); gtk_box_pack_start (GTK_BOX (vbox), build_search_box (editor), FALSE, FALSE, 0); /* Pages View */ scrolled_window = g_object_new (GTK_TYPE_SCROLLED_WINDOW, "hadjustment", NULL, "vadjustment", NULL, "hscrollbar_policy", GTK_POLICY_AUTOMATIC, "vscrollbar_policy", GTK_POLICY_AUTOMATIC, "shadow_type", GTK_SHADOW_IN, NULL); gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0); gtk_widget_show (scrolled_window); node = ephy_history_get_pages (editor->priv->history); editor->priv->pages_filter = ephy_node_filter_new (); pages_view = ephy_node_view_new (node, editor->priv->pages_filter); add_focus_monitor (editor, pages_view); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pages_view)); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pages_view), TRUE); col_id = ephy_node_view_add_data_column (EPHY_NODE_VIEW (pages_view), G_TYPE_STRING, EPHY_NODE_PAGE_PROP_LOCATION, NULL, NULL); ephy_node_view_enable_drag_source (EPHY_NODE_VIEW (pages_view), page_drag_types, n_page_drag_types, col_id); col = ephy_node_view_add_column (EPHY_NODE_VIEW (pages_view), _("Title"), G_TYPE_STRING, EPHY_NODE_PAGE_PROP_TITLE, -1, EPHY_NODE_VIEW_USER_SORT | EPHY_NODE_VIEW_SEARCHABLE, NULL); gtk_tree_view_column_set_max_width (col, 250); col = ephy_node_view_add_column (EPHY_NODE_VIEW (pages_view), _("Address"), G_TYPE_STRING, EPHY_NODE_PAGE_PROP_LOCATION, -1, EPHY_NODE_VIEW_USER_SORT, NULL); gtk_tree_view_column_set_max_width (col, 200); gtk_container_add (GTK_CONTAINER (scrolled_window), pages_view); gtk_widget_show (pages_view); editor->priv->pages_view = pages_view; g_signal_connect (G_OBJECT (pages_view), "node_activated", G_CALLBACK (ephy_history_window_node_activated_cb), editor); g_signal_connect (G_OBJECT (pages_view), "show_popup", G_CALLBACK (ephy_history_window_show_popup_cb), editor); g_signal_connect (G_OBJECT (pages_view), "key_press_event", G_CALLBACK (key_pressed_cb), editor); g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (view_selection_changed_cb), editor); ephy_state_add_window (GTK_WIDGET (editor), "history_window", 450, 400, EPHY_STATE_WINDOW_SAVE_SIZE | EPHY_STATE_WINDOW_SAVE_POSITION); ephy_state_add_paned (GTK_WIDGET (hpaned), "history_paned", 130); } void ephy_history_window_set_parent (EphyHistoryWindow *ebe, GtkWidget *window) { if (ebe->priv->window) { g_object_remove_weak_pointer (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); } GtkWidget * ephy_history_window_new (EphyHistory *history) { EphyHistoryWindow *editor; g_assert (history != NULL); editor = EPHY_HISTORY_WINDOW (g_object_new (EPHY_TYPE_HISTORY_WINDOW, "history", history, NULL)); ephy_history_window_construct (editor); return GTK_WIDGET (editor); } static void ephy_history_window_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { EphyHistoryWindow *editor = EPHY_HISTORY_WINDOW (object); switch (prop_id) { case PROP_HISTORY: editor->priv->history = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ephy_history_window_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { EphyHistoryWindow *editor = EPHY_HISTORY_WINDOW (object); switch (prop_id) { case PROP_HISTORY: g_value_set_object (value, editor->priv->history); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ephy_history_window_init (EphyHistoryWindow *editor) { editor->priv = g_new0 (EphyHistoryWindowPrivate, 1); } static void ephy_history_window_dispose (GObject *object) { EphyHistoryWindow *editor; g_return_if_fail (object != NULL); g_return_if_fail (EPHY_IS_HISTORY_WINDOW (object)); editor = EPHY_HISTORY_WINDOW (object); if (editor->priv->sites_view != NULL) { remove_focus_monitor (editor, editor->priv->pages_view); remove_focus_monitor (editor, editor->priv->sites_view); remove_focus_monitor (editor, editor->priv->search_entry); editor->priv->sites_view = NULL; } G_OBJECT_CLASS (parent_class)->dispose (object); }