diff options
Diffstat (limited to 'src/ephy-notebook.c')
-rw-r--r-- | src/ephy-notebook.c | 314 |
1 files changed, 167 insertions, 147 deletions
diff --git a/src/ephy-notebook.c b/src/ephy-notebook.c index 1671126dd..878807e14 100644 --- a/src/ephy-notebook.c +++ b/src/ephy-notebook.c @@ -29,6 +29,7 @@ #include "ephy-embed.h" #include "ephy-window.h" #include "ephy-shell.h" +#include "ephy-debug.h" #include <gtk/gtk.h> #include <glib-object.h> @@ -45,8 +46,6 @@ struct EphyNotebookPrivate GList *focused_pages; GList *opened_tabs; - EphyNotebookPageLoadStatus current_status; - GtkTooltips *title_tips; /* Used during tab drag'n'drop */ @@ -86,13 +85,16 @@ static gboolean motion_notify_cb (EphyNotebook *notebook, /* Signals */ enum { - TAB_DROPPED, + TAB_ADDED, + TAB_REMOVED, + TABS_REORDERED, TAB_DETACHED, - TABS_CHANGED, LAST_SIGNAL }; -static guint ephy_notebook_signals[LAST_SIGNAL] = { 0 }; +static GObjectClass *parent_class = NULL; + +static guint signals[LAST_SIGNAL] = { 0 }; GType ephy_notebook_get_type (void) @@ -126,41 +128,50 @@ static void ephy_notebook_class_init (EphyNotebookClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + object_class->finalize = ephy_notebook_finalize; - /* init signals */ - ephy_notebook_signals[TAB_DROPPED] = - g_signal_new ("tab_dropped", + signals[TAB_ADDED] = + g_signal_new ("tab_added", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EphyNotebookClass, tab_dropped), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EphyNotebookClass, tab_added), NULL, NULL, - ephy_marshal_VOID__OBJECT_OBJECT_INT, + ephy_marshal_VOID__OBJECT, G_TYPE_NONE, - 3, - GTK_TYPE_WIDGET, - EPHY_NOTEBOOK_TYPE, - G_TYPE_INT); - ephy_notebook_signals[TAB_DETACHED] = + 1, + GTK_TYPE_WIDGET); + signals[TAB_REMOVED] = + g_signal_new ("tab_removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EphyNotebookClass, tab_removed), + NULL, NULL, + ephy_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + GTK_TYPE_WIDGET); + signals[TAB_DETACHED] = g_signal_new ("tab_detached", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (EphyNotebookClass, tab_detached), NULL, NULL, - ephy_marshal_VOID__INT_INT_INT, + ephy_marshal_VOID__OBJECT, G_TYPE_NONE, - 3, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INT); - ephy_notebook_signals[TABS_CHANGED] = - g_signal_new ("tabs_changed", + 1, + GTK_TYPE_WIDGET); + signals[TABS_REORDERED] = + g_signal_new ("tabs_reordered", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EphyNotebookClass, tabs_changed), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EphyNotebookClass, tabs_reordered), NULL, NULL, ephy_marshal_VOID__VOID, - G_TYPE_NONE, 0); + G_TYPE_NONE, + 0); } static gboolean @@ -220,7 +231,6 @@ find_notebook_at_pointer (gint abs_x, gint abs_y) return NULL; } - static gint find_tab_num_at_pos (EphyNotebook *notebook, gint abs_x, gint abs_y) { @@ -277,7 +287,6 @@ find_tab_num_at_pos (EphyNotebook *notebook, gint abs_x, gint abs_y) return AFTER_ALL_TABS; } - static gint find_notebook_and_tab_at_pos (gint abs_x, gint abs_y, EphyNotebook **notebook, gint *page_num) @@ -331,31 +340,26 @@ void ephy_notebook_move_page (EphyNotebook *src, EphyNotebook *dest, GtkWidget *src_page, gint dest_page) { - GtkWidget *tab_label; - if (dest == NULL || src == dest) { gtk_notebook_reorder_child (GTK_NOTEBOOK (src), src_page, dest_page); - g_signal_emit (G_OBJECT (src), ephy_notebook_signals[TABS_CHANGED], 0); + + if (src->priv->drag_in_progress == FALSE) + { + g_signal_emit (G_OBJECT (src), signals[TABS_REORDERED], 0); + } } else { - tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (src), src_page); - - /* We don't want gtk to destroy tab and src_page behind our back */ + /* make sure the tab isn't destroyed while we move its embed */ g_object_ref (G_OBJECT (src_page)); - g_object_ref (G_OBJECT (tab_label)); ephy_notebook_remove_page (EPHY_NOTEBOOK (src), src_page); ephy_notebook_insert_page (EPHY_NOTEBOOK (dest), src_page, dest_page, TRUE); - gtk_notebook_set_tab_label (GTK_NOTEBOOK (dest), src_page, tab_label); g_object_unref (G_OBJECT (src_page)); - g_object_unref (G_OBJECT (tab_label)); } } - - static void move_tab_to_another_notebook(EphyNotebook *src, EphyNotebook *dest, gint dest_page) @@ -390,7 +394,9 @@ move_tab_to_another_notebook(EphyNotebook *src, NULL); } - +/* this function is only called during dnd, we don't need to emit TABS_REORDERED + * here, instead we do it on drag_stop + */ static void move_tab (EphyNotebook *notebook, gint dest_page_num) { @@ -437,6 +443,11 @@ drag_start (EphyNotebook *notebook, static void drag_stop (EphyNotebook *notebook) { + if (notebook->priv->drag_in_progress) + { + g_signal_emit (G_OBJECT (notebook), signals[TABS_REORDERED], 0); + } + notebook->priv->drag_in_progress = FALSE; notebook->priv->src_notebook = NULL; notebook->priv->src_page = -1; @@ -466,20 +477,8 @@ button_release_cb (EphyNotebook *notebook, GdkEventButton *event, if (!is_in_notebook_window (notebook, event->x_root, event->y_root)) { /* Tab was detached */ - g_signal_emit (G_OBJECT(notebook), - ephy_notebook_signals[TAB_DETACHED], 0, - cur_page_num, (gint)event->x_root, - (gint)event->y_root); - } - else - { - /* Tab was dragged and dropped (but it may have stayed - in the same place) */ - g_signal_emit (G_OBJECT(notebook), - ephy_notebook_signals[TAB_DROPPED], 0, - cur_page, - notebook->priv->src_notebook, - notebook->priv->src_page); + g_signal_emit (G_OBJECT (notebook), + signals[TAB_DETACHED], 0, cur_page); } /* ungrab the pointer if it's grabbed */ @@ -694,8 +693,6 @@ ephy_notebook_init (EphyNotebook *notebook) { notebook->priv = g_new (EphyNotebookPrivate, 1); - notebook->priv->current_status = EPHY_NOTEBOOK_TAB_LOAD_NORMAL; - notebook->priv->title_tips = gtk_tooltips_new (); g_object_ref (G_OBJECT (notebook->priv->title_tips)); gtk_object_sink (GTK_OBJECT (notebook->priv->title_tips)); @@ -744,75 +741,84 @@ ephy_notebook_finalize (GObject *object) g_object_unref (notebook->priv->title_tips); g_free (notebook->priv); -} + LOG ("EphyNotebook finalised %p", object) +} -void -ephy_notebook_set_page_status (EphyNotebook *nb, - GtkWidget *child, - EphyNotebookPageLoadStatus status) +static void +sync_load_status (EphyTab *tab, GParamSpec *pspec, GtkWidget *proxy) { - GtkWidget *tab, *image, *icon; + GtkWidget *animation = NULL, *icon = NULL; - g_return_if_fail (nb != NULL); + animation = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "loading-image")); + icon = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "icon")); + g_return_if_fail (animation != NULL && icon != NULL); - if (status == nb->priv->current_status) + switch (ephy_tab_get_load_status (tab)) { - return; + case TRUE: + gtk_widget_hide (icon); + gtk_widget_show (animation); + break; + case FALSE: + gtk_widget_hide (animation); + gtk_widget_show (icon); + break; } +} - tab = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), child); - - g_return_if_fail (tab != NULL); - - image = g_object_get_data (G_OBJECT (tab), "loading-image"); - - g_return_if_fail (image != NULL); - - icon = g_object_get_data (G_OBJECT (tab), "icon"); +static void +sync_icon (EphyTab *tab, GParamSpec *pspec, GtkWidget *proxy) +{ + EphyFaviconCache *cache; + GdkPixbuf *pixbuf = NULL; + GtkImage *icon = NULL; + const char *address; - g_return_if_fail (icon != NULL); + cache = ephy_embed_shell_get_favicon_cache (EPHY_EMBED_SHELL (ephy_shell)); + address = ephy_tab_get_icon_address (tab); - switch (status) + if (address) { - case EPHY_NOTEBOOK_TAB_LOAD_LOADING: - gtk_widget_hide (icon); - gtk_widget_show (image); - break; + pixbuf = ephy_favicon_cache_get (cache, address); + } - case EPHY_NOTEBOOK_TAB_LOAD_COMPLETED: - case EPHY_NOTEBOOK_TAB_LOAD_NORMAL: - gtk_widget_hide (image); - gtk_widget_show (icon); - break; + icon = GTK_IMAGE (g_object_get_data (G_OBJECT (proxy), "icon")); + if (icon) + { + gtk_image_set_from_pixbuf (icon, pixbuf); } - nb->priv->current_status = status; + if (pixbuf) + { + g_object_unref (pixbuf); + } } -void -ephy_notebook_set_page_icon (EphyNotebook *nb, - GtkWidget *child, - GdkPixbuf *icon) +static void +sync_label (EphyTab *tab, GParamSpec *pspec, GtkWidget *proxy) { - GtkWidget *tab, *image; - - g_return_if_fail (nb != NULL); - - tab = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), child); + GtkWidget *label, *ebox; + GtkTooltips *tips; + const char *title; - g_return_if_fail (tab != NULL); + ebox = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "label-ebox")); + tips = GTK_TOOLTIPS (g_object_get_data (G_OBJECT (proxy), "tooltips")); + label = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "label")); - image = g_object_get_data (G_OBJECT (tab), "icon"); + g_return_if_fail (ebox != NULL && tips != NULL && label != NULL); - g_return_if_fail (image != NULL); + title = ephy_tab_get_title (tab); - gtk_image_set_from_pixbuf (GTK_IMAGE (image), icon); + if (title) + { + gtk_label_set_label (GTK_LABEL (label), title); + gtk_tooltips_set_tip (tips, ebox, title, NULL); + } } static void -ephy_tab_close_button_clicked_cb (GtkWidget *widget, - GtkWidget *child) +close_button_clicked_cb (GtkWidget *widget, GtkWidget *child) { EphyNotebook *notebook; @@ -821,7 +827,7 @@ ephy_tab_close_button_clicked_cb (GtkWidget *widget, } static GtkWidget * -tab_build_label (EphyNotebook *nb, GtkWidget *child) +build_tab_label (EphyNotebook *nb, GtkWidget *child) { GtkWidget *label, *hbox, *close_button, *image; int h, w; @@ -850,6 +856,7 @@ tab_build_label (EphyNotebook *nb, GtkWidget *child) image); /* setup load feedback image */ + /* FIXME: make the animation themeable */ loading_pixbuf = gdk_pixbuf_animation_new_from_file (ephy_file ("epiphany-tab-loading.gif"), NULL); loading_image = gtk_image_new_from_animation (loading_pixbuf); g_object_unref (loading_pixbuf); @@ -861,7 +868,7 @@ tab_build_label (EphyNotebook *nb, GtkWidget *child) /* setup label */ label_ebox = gtk_event_box_new (); - label = gtk_label_new (_("Untitled")); + label = gtk_label_new (""); gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.5); gtk_misc_set_padding (GTK_MISC (label), 4, 0); gtk_box_pack_start (GTK_BOX (hbox), label_ebox, TRUE, TRUE, 0); @@ -883,7 +890,7 @@ tab_build_label (EphyNotebook *nb, GtkWidget *child) FALSE, FALSE, 0); g_signal_connect (G_OBJECT (close_button), "clicked", - G_CALLBACK (ephy_tab_close_button_clicked_cb), + G_CALLBACK (close_button_clicked_cb), child); gtk_widget_show (hbox); @@ -896,6 +903,7 @@ tab_build_label (EphyNotebook *nb, GtkWidget *child) g_object_set_data (G_OBJECT (hbox), "label-ebox", label_ebox); g_object_set_data (G_OBJECT (hbox), "loading-image", loading_image); g_object_set_data (G_OBJECT (hbox), "icon", icon); + g_object_set_data (G_OBJECT (hbox), "tooltips", nb->priv->title_tips); return hbox; } @@ -903,19 +911,18 @@ tab_build_label (EphyNotebook *nb, GtkWidget *child) /* * update_tabs_visibility: Hide tabs if there is only one tab * and the pref is not set. - * HACK We need to show tabs before inserting the second. Otherwise - * gtknotebook go crazy. */ static void update_tabs_visibility (EphyNotebook *nb, gboolean before_inserting) { gboolean show_tabs; - guint tabs_num = 1; + guint num; + + num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)); - if (before_inserting) tabs_num--; + if (before_inserting) num++; - show_tabs = eel_gconf_get_boolean (CONF_TABS_TABBED) || - gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), tabs_num) > 0; + show_tabs = eel_gconf_get_boolean (CONF_TABS_TABBED) || num > 1; gtk_notebook_set_show_tabs (GTK_NOTEBOOK (nb), show_tabs); } @@ -926,9 +933,14 @@ ephy_notebook_insert_page (EphyNotebook *nb, int position, gboolean jump_to) { - GtkWidget *tab_hbox; + EphyTab *tab; + GtkWidget *label; - tab_hbox = tab_build_label (nb, child); + g_return_if_fail (IS_EPHY_EMBED (child)); + tab = EPHY_TAB (g_object_get_data (G_OBJECT (child), "EphyTab")); + g_return_if_fail (IS_EPHY_TAB (tab)); + + label = build_tab_label (nb, child); update_tabs_visibility (nb, TRUE); @@ -954,17 +966,28 @@ ephy_notebook_insert_page (EphyNotebook *nb, g_list_append (nb->priv->opened_tabs, child); } - gtk_notebook_insert_page (GTK_NOTEBOOK (nb), - child, - tab_hbox, position); + + gtk_notebook_insert_page (GTK_NOTEBOOK (nb), child, + label, position); /* Set up drag-and-drop target */ - g_signal_connect (G_OBJECT(tab_hbox), "drag_data_received", + g_signal_connect (G_OBJECT(label), "drag_data_received", G_CALLBACK(notebook_drag_data_received_cb), child); - gtk_drag_dest_set (tab_hbox, GTK_DEST_DEFAULT_ALL, + gtk_drag_dest_set (label, GTK_DEST_DEFAULT_ALL, url_drag_types,n_url_drag_types, GDK_ACTION_MOVE | GDK_ACTION_COPY); + sync_icon (tab, NULL, label); + sync_label (tab, NULL, label); + sync_load_status (tab, NULL, label); + + g_signal_connect_object (tab, "notify::icon", + G_CALLBACK (sync_icon), label, 0); + g_signal_connect_object (tab, "notify::title", + G_CALLBACK (sync_label), label, 0); + g_signal_connect_object (tab, "notify::load-status", + G_CALLBACK (sync_load_status), label, 0); + if (jump_to) { gtk_notebook_set_current_page (GTK_NOTEBOOK (nb), @@ -973,7 +996,7 @@ ephy_notebook_insert_page (EphyNotebook *nb, GINT_TO_POINTER (jump_to)); } - g_signal_emit (G_OBJECT (nb), ephy_notebook_signals[TABS_CHANGED], 0); + g_signal_emit (G_OBJECT (nb), signals[TAB_ADDED], 0, child); } static void @@ -1009,16 +1032,18 @@ void ephy_notebook_remove_page (EphyNotebook *nb, GtkWidget *child) { - int position, cur; - gboolean last_tab; - GtkWidget *hbox, *ebox; + int num, position, curr; + EphyTab *tab; + GtkWidget *label, *ebox; - hbox = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), child); - ebox = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label-ebox")); - gtk_tooltips_set_tip (GTK_TOOLTIPS (nb->priv->title_tips), ebox, NULL, NULL); + g_return_if_fail (IS_EPHY_NOTEBOOK (nb)); + g_return_if_fail (IS_EPHY_EMBED (child)); + + tab = EPHY_TAB (g_object_get_data (G_OBJECT (child), "EphyTab")); + g_return_if_fail (IS_EPHY_TAB (tab)); - last_tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), 1) == NULL; - if (last_tab) + num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)); + if (num <= 1) { GtkWidget *window; window = gtk_widget_get_toplevel (GTK_WIDGET (nb)); @@ -1031,34 +1056,29 @@ ephy_notebook_remove_page (EphyNotebook *nb, child); nb->priv->opened_tabs = g_list_remove (nb->priv->opened_tabs, child); + position = gtk_notebook_page_num (GTK_NOTEBOOK (nb), child); + curr = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb)); - position = gtk_notebook_page_num (GTK_NOTEBOOK (nb), - child); - - cur = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb)); - if (position == cur) + if (position == curr) { smart_tab_switching_on_closure (nb, child); } - gtk_notebook_remove_page (GTK_NOTEBOOK (nb), position); - g_signal_emit (G_OBJECT (nb), ephy_notebook_signals[TABS_CHANGED], 0); + label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), child); + ebox = GTK_WIDGET (g_object_get_data (G_OBJECT (label), "label-ebox")); + gtk_tooltips_set_tip (GTK_TOOLTIPS (nb->priv->title_tips), ebox, NULL, NULL); - update_tabs_visibility (nb, FALSE); -} + g_signal_handlers_disconnect_by_func (label, + G_CALLBACK (sync_icon), tab); + g_signal_handlers_disconnect_by_func (label, + G_CALLBACK (sync_label), tab); + g_signal_handlers_disconnect_by_func (label, + G_CALLBACK (sync_load_status), tab); -void -ephy_notebook_set_page_title (EphyNotebook *nb, - GtkWidget *child, - const char *title) -{ - GtkWidget *hbox, *ebox, *label; - hbox = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb), child); + g_signal_emit (G_OBJECT (nb), signals[TAB_REMOVED], 0, child); - label = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label")); - gtk_label_set_label (GTK_LABEL (label), title); + gtk_notebook_remove_page (GTK_NOTEBOOK (nb), position); - ebox = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label-ebox")); - gtk_tooltips_set_tip (GTK_TOOLTIPS (nb->priv->title_tips), ebox, title, NULL); + update_tabs_visibility (nb, FALSE); } |