[epiphany] Add tab switcher menu to notebook
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Add tab switcher menu to notebook
- Date: Mon, 16 Jan 2017 03:26:42 +0000 (UTC)
commit a5643ef6273f49d8ea453684e7c3ae2fa4378e85
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Sun Jan 15 21:24:42 2017 -0600
Add tab switcher menu to notebook
This makes it easy to switch to a particular tab when you have lots of
tabs open.
src/ephy-notebook.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++--
src/ephy-window.c | 2 +
src/window-commands.c | 16 ++++++
src/window-commands.h | 3 +
4 files changed, 159 insertions(+), 6 deletions(-)
---
diff --git a/src/ephy-notebook.c b/src/ephy-notebook.c
index 7fda28a..1a0d664 100644
--- a/src/ephy-notebook.c
+++ b/src/ephy-notebook.c
@@ -51,6 +51,8 @@ struct _EphyNotebook {
GList *focused_pages;
guint tabs_vis_notifier_id;
+ GMenu *tab_menu;
+
guint tabs_allowed : 1;
};
@@ -63,6 +65,15 @@ static int ephy_notebook_insert_page (GtkNotebook *notebook,
int position);
static void ephy_notebook_remove (GtkContainer *container,
GtkWidget *tab_widget);
+static void ephy_notebook_page_added (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num);
+static void ephy_notebook_page_removed (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num);
+static void ephy_notebook_page_reordered (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num);
static const GtkTargetEntry url_drag_types [] =
{
@@ -139,6 +150,9 @@ ephy_notebook_class_init (EphyNotebookClass *klass)
container_class->remove = ephy_notebook_remove;
notebook_class->insert_page = ephy_notebook_insert_page;
+ notebook_class->page_added = ephy_notebook_page_added;
+ notebook_class->page_removed = ephy_notebook_page_removed;
+ notebook_class->page_reordered = ephy_notebook_page_reordered;
signals[TAB_CLOSE_REQUEST] =
g_signal_new ("tab-close-request",
@@ -450,7 +464,8 @@ ephy_notebook_constructed (GObject *object)
{
EphyNotebook *notebook = EPHY_NOTEBOOK (object);
GtkWidget *hbox;
- GtkWidget *widget;
+ GtkWidget *button;
+ GtkWidget *popover;
G_OBJECT_CLASS (ephy_notebook_parent_class)->constructed (object);
@@ -458,11 +473,21 @@ ephy_notebook_constructed (GObject *object)
gtk_notebook_set_action_widget (GTK_NOTEBOOK (notebook), hbox, GTK_PACK_END);
gtk_widget_show (hbox);
- widget = gtk_button_new_from_icon_name ("tab-new-symbolic", GTK_ICON_SIZE_BUTTON);
- gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
- gtk_actionable_set_action_name (GTK_ACTIONABLE (widget), "win.new-tab");
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6);
- gtk_widget_show (widget);
+ button = gtk_button_new_from_icon_name ("tab-new-symbolic", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "win.new-tab");
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 6);
+ gtk_widget_show (button);
+
+ button = gtk_menu_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 6);
+ gtk_widget_show (button);
+
+ notebook->tab_menu = g_menu_new ();
+ popover = gtk_popover_new (button);
+ gtk_popover_bind_model (GTK_POPOVER (popover), G_MENU_MODEL (notebook->tab_menu), "win");
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), popover);
}
static void
@@ -485,6 +510,69 @@ ephy_notebook_finalize (GObject *object)
G_OBJECT_CLASS (ephy_notebook_parent_class)->finalize (object);
}
+static const char *
+get_nth_tab_label_text (GtkNotebook *notebook,
+ int n)
+{
+ GtkWidget *page;
+ GtkWidget *tab_label;
+ GtkWidget *label;
+
+ g_assert (n >= 0);
+
+ page = gtk_notebook_get_nth_page (notebook, n);
+ g_assert (page != NULL);
+
+ tab_label = gtk_notebook_get_tab_label (notebook, page);
+ g_assert (GTK_IS_BOX (tab_label));
+
+ label = g_object_get_data (G_OBJECT (tab_label), "label");
+ g_assert (GTK_IS_LABEL (label));
+
+ return gtk_label_get_text (GTK_LABEL (label));
+}
+
+static char *
+ellipsize_tab_label (const char *label)
+{
+ static const int MAX_LENGTH = 50;
+ char *substring;
+ char *result;
+
+ if (g_utf8_strlen (label, -1) < MAX_LENGTH)
+ return g_strdup (label);
+
+ substring = g_utf8_substring (label, 0, MAX_LENGTH);
+ result = g_strconcat (substring, "…", NULL);
+ g_free (substring);
+
+ return result;
+}
+
+static void
+ephy_notebook_rebuild_tab_menu (EphyNotebook *notebook)
+{
+ GMenuItem *item;
+ const char *text;
+ char *ellipsized_text;
+ int num_pages;
+
+ g_menu_remove_all (notebook->tab_menu);
+
+ num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
+
+ /* TODO: Add favicon as well. Will have to ditch GMenu. :( */
+ for (int i = 0; i < num_pages; i++) {
+ text = get_nth_tab_label_text (GTK_NOTEBOOK (notebook), i);
+ ellipsized_text = ellipsize_tab_label (text);
+ item = g_menu_item_new (ellipsized_text, NULL);
+ g_menu_item_set_action_and_target (item, "show-tab", "u", (guint)i, NULL);
+ g_menu_append_item (notebook->tab_menu, item);
+ g_free (ellipsized_text);
+ g_object_unref (item);
+ }
+}
+
static void
sync_load_status (EphyWebView *view, GParamSpec *pspec, GtkWidget *proxy)
{
@@ -532,6 +620,14 @@ sync_label (EphyEmbed *embed, GParamSpec *pspec, GtkWidget *label)
}
static void
+rebuild_tab_menu_cb (EphyEmbed *embed,
+ GParamSpec *pspec,
+ EphyNotebook *notebook)
+{
+ ephy_notebook_rebuild_tab_menu (notebook);
+}
+
+static void
sync_is_playing_audio (WebKitWebView *view,
GParamSpec *pspec,
GtkWidget *speaker_icon)
@@ -667,6 +763,8 @@ build_tab_label (EphyNotebook *nb, EphyEmbed *embed)
G_CALLBACK (sync_icon), icon, 0);
g_signal_connect_object (embed, "notify::title",
G_CALLBACK (sync_label), label, 0);
+ g_signal_connect_object (embed, "notify::title",
+ G_CALLBACK (rebuild_tab_menu_cb), nb, 0);
g_signal_connect_object (view, "load-changed",
G_CALLBACK (load_changed_cb), box, 0);
g_signal_connect_object (view, "notify::is-playing-audio",
@@ -815,6 +913,8 @@ ephy_notebook_remove (GtkContainer *container,
g_signal_handlers_disconnect_by_func
(tab_widget, G_CALLBACK (sync_label), tab_label_label);
g_signal_handlers_disconnect_by_func
+ (tab_widget, G_CALLBACK (sync_label), notebook);
+ g_signal_handlers_disconnect_by_func
(view, G_CALLBACK (sync_load_status), tab_label);
g_signal_handlers_disconnect_by_func
(view, G_CALLBACK (sync_is_playing_audio), tab_label_speaker_icon);
@@ -824,6 +924,38 @@ ephy_notebook_remove (GtkContainer *container,
update_tabs_visibility (notebook, FALSE);
}
+static void
+ephy_notebook_page_added (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ if (GTK_NOTEBOOK_CLASS (ephy_notebook_parent_class)->page_added != NULL)
+ GTK_NOTEBOOK_CLASS (ephy_notebook_parent_class)->page_added (notebook, child, page_num);
+
+ ephy_notebook_rebuild_tab_menu (EPHY_NOTEBOOK (notebook));
+}
+
+static void
+ephy_notebook_page_removed (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ if (GTK_NOTEBOOK_CLASS (ephy_notebook_parent_class)->page_removed != NULL)
+ GTK_NOTEBOOK_CLASS (ephy_notebook_parent_class)->page_removed (notebook, child, page_num);
+
+ ephy_notebook_rebuild_tab_menu (EPHY_NOTEBOOK (notebook));
+}
+
+static void ephy_notebook_page_reordered (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num)
+{
+ if (GTK_NOTEBOOK_CLASS (ephy_notebook_parent_class)->page_reordered != NULL)
+ GTK_NOTEBOOK_CLASS (ephy_notebook_parent_class)->page_reordered (notebook, child, page_num);
+
+ ephy_notebook_rebuild_tab_menu (EPHY_NOTEBOOK (notebook));
+}
+
/**
* ephy_notebook_next_page:
* @notebook: an #EphyNotebook
diff --git a/src/ephy-window.c b/src/ephy-window.c
index f58497f..69c29a2 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -782,6 +782,8 @@ static const GActionEntry window_entries [] =
{ "location", window_cmd_go_location },
{ "home", window_cmd_go_home },
+ { "show-tab", window_cmd_show_tab, "u" },
+
/* Toggle actions */
{ "browse-with-caret", NULL, NULL, "false", window_cmd_change_browse_with_caret_state },
{ "fullscreen", NULL, NULL, "false", window_cmd_change_fullscreen_state },
diff --git a/src/window-commands.c b/src/window-commands.c
index 96424a2..3c3c6bd 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -2312,3 +2312,19 @@ window_cmd_tabs_close (GSimpleAction *action,
g_signal_emit_by_name (notebook, "tab-close-request", embed);
}
+
+void
+window_cmd_show_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ EphyWindow *window = EPHY_WINDOW (user_data);
+ GtkWidget *notebook;
+ guint32 tab_num;
+
+ g_assert (g_variant_is_of_type (parameter, G_VARIANT_TYPE_UINT32));
+ tab_num = g_variant_get_uint32 (parameter);
+
+ notebook = ephy_window_get_notebook (window);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), tab_num);
+}
diff --git a/src/window-commands.h b/src/window-commands.h
index e8b0831..5db5771 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -179,5 +179,8 @@ void window_cmd_tabs_detach (GSimpleAction *action,
void window_cmd_tabs_close (GSimpleAction *action,
GVariant *parameter,
gpointer user_data);
+void window_cmd_show_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]