[nautilus] toolbar: restore history context menu on navigation action buttons



commit de36d7e7dfd77904c568fb126f45ae3a49c67b46
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Thu Aug 23 16:42:31 2012 +0200

    toolbar: restore history context menu on navigation action buttons
    
    This code stopped working when we changed the way we build the toolbar
    layout; take this as an occasion to remove NautilusNavigationAction and
    folding the menu code into NautilusToolbar (where the buttons live).

 src/Makefile.am                  |    2 -
 src/nautilus-navigation-action.c |  376 --------------------------------------
 src/nautilus-navigation-action.h |   68 -------
 src/nautilus-toolbar.c           |  250 ++++++++++++++++++++++---
 src/nautilus-toolbar.h           |    5 +-
 src/nautilus-window-menus.c      |    1 -
 src/nautilus-window.c            |    3 +-
 7 files changed, 223 insertions(+), 482 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b60814..336c06f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -166,8 +166,6 @@ nautilus_SOURCES = \
 	nautilus-main.c 			\
 	nautilus-mime-actions.c 		\
 	nautilus-mime-actions.h 		\
-	nautilus-navigation-action.c		\
-	nautilus-navigation-action.h		\
 	nautilus-notebook.c			\
 	nautilus-notebook.h			\
 	nautilus-pathbar.c			\
diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c
index 7481548..56ce4cc 100644
--- a/src/nautilus-toolbar.c
+++ b/src/nautilus-toolbar.c
@@ -30,18 +30,21 @@
 #include "nautilus-location-bar.h"
 #include "nautilus-pathbar.h"
 #include "nautilus-actions.h"
-#include "nautilus-window-private.h"
 
 #include <libnautilus-private/nautilus-global-preferences.h>
 #include <libnautilus-private/nautilus-ui-utilities.h>
 
 #include <math.h>
 
+typedef enum {
+	NAUTILUS_NAVIGATION_DIRECTION_NONE,
+	NAUTILUS_NAVIGATION_DIRECTION_BACK,
+	NAUTILUS_NAVIGATION_DIRECTION_FORWARD
+} NautilusNavigationDirection;
+
 struct _NautilusToolbarPriv {
 	GtkWidget *toolbar;
-
-	GtkActionGroup *action_group;
-	GtkUIManager *ui_manager;
+	NautilusWindow *window;
 
 	GtkWidget *path_bar;
 	GtkWidget *location_bar;
@@ -49,11 +52,12 @@ struct _NautilusToolbarPriv {
 	GtkToolItem *back_forward;
 
 	gboolean show_location_entry;
+
+	guint popup_timeout_id;
 };
 
 enum {
-	PROP_ACTION_GROUP = 1,
-	PROP_UI_MANAGER,
+	PROP_WINDOW = 1,
 	PROP_SHOW_LOCATION_ENTRY,
 	NUM_PROPERTIES
 };
@@ -62,6 +66,8 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 
 G_DEFINE_TYPE (NautilusToolbar, nautilus_toolbar, GTK_TYPE_BOX);
 
+static void unschedule_menu_popup_timeout (NautilusToolbar *self);
+
 static void
 toolbar_update_appearance (NautilusToolbar *self)
 {
@@ -97,8 +103,11 @@ toolbar_create_toolbutton (NautilusToolbar *self,
 			   const gchar *name)
 {
 	GtkWidget *button, *image;
+	GtkActionGroup *action_group;
 	GtkAction *action;
 
+	action_group = nautilus_window_get_main_action_group (self->priv->window);
+
 	if (create_menu) {
 		button = gtk_menu_button_new ();
 	} else if (create_toggle) {
@@ -116,7 +125,7 @@ toolbar_create_toolbutton (NautilusToolbar *self,
 		gtk_image_set_from_icon_name (GTK_IMAGE (image), name,
 					      GTK_ICON_SIZE_MENU);
 	} else {
-		action = gtk_action_group_get_action (self->priv->action_group, name);
+		action = gtk_action_group_get_action (action_group, name);
 		gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
 		gtk_button_set_label (GTK_BUTTON (button), NULL);
 	}
@@ -125,6 +134,192 @@ toolbar_create_toolbutton (NautilusToolbar *self,
 }
 
 static void
+activate_back_or_forward_menu_item (GtkMenuItem *menu_item, 
+				    NautilusWindow *window,
+				    gboolean back)
+{
+	int index;
+	
+	g_assert (GTK_IS_MENU_ITEM (menu_item));
+
+	index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "user_data"));
+
+	nautilus_window_back_or_forward (window, back, index, nautilus_event_get_window_open_flags ());
+}
+
+static void
+activate_back_menu_item_callback (GtkMenuItem *menu_item,
+                                  NautilusWindow *window)
+{
+	activate_back_or_forward_menu_item (menu_item, window, TRUE);
+}
+
+static void
+activate_forward_menu_item_callback (GtkMenuItem *menu_item, NautilusWindow *window)
+{
+	activate_back_or_forward_menu_item (menu_item, window, FALSE);
+}
+
+static void
+fill_menu (NautilusWindow *window,
+	   GtkWidget *menu,
+	   gboolean back)
+{
+	NautilusWindowSlot *slot;
+	GtkWidget *menu_item;
+	int index;
+	GList *list;
+
+	slot = nautilus_window_get_active_slot (window);
+
+	list = back ? slot->back_list : slot->forward_list;
+	index = 0;
+	while (list != NULL) {
+		menu_item = nautilus_bookmark_menu_item_new (NAUTILUS_BOOKMARK (list->data));
+		g_object_set_data (G_OBJECT (menu_item), "user_data", GINT_TO_POINTER (index));
+		gtk_widget_show (GTK_WIDGET (menu_item));
+  		g_signal_connect_object (menu_item, "activate",
+					 back
+					 ? G_CALLBACK (activate_back_menu_item_callback)
+					 : G_CALLBACK (activate_forward_menu_item_callback),
+					 window, 0);
+
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+		list = g_list_next (list);
+		++index;
+	}
+}
+
+static void
+show_menu (NautilusToolbar *self,
+	   NautilusNavigationDirection direction,
+           guint button,
+           guint32 event_time)
+{
+	NautilusWindow *window;
+	GtkWidget *menu;
+
+	window = self->priv->window;
+	menu = gtk_menu_new ();
+
+	switch (direction) {
+	case NAUTILUS_NAVIGATION_DIRECTION_FORWARD:
+		fill_menu (window, menu, FALSE);
+		break;
+	case NAUTILUS_NAVIGATION_DIRECTION_BACK:
+		fill_menu (window, menu, TRUE);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+
+        gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+                        button, event_time);
+}
+
+#define MENU_POPUP_TIMEOUT 1200
+
+typedef struct {
+	NautilusToolbar *self;
+	NautilusNavigationDirection direction;
+} ScheduleMenuData;
+
+static void
+schedule_menu_data_free (ScheduleMenuData *data)
+{
+	g_slice_free (ScheduleMenuData, data);
+}
+
+static gboolean
+popup_menu_timeout_cb (gpointer user_data)
+{
+	ScheduleMenuData *data = user_data;
+
+        show_menu (data->self, data->direction,
+		   1, gtk_get_current_event_time ());
+
+        return FALSE;
+}
+
+static void
+unschedule_menu_popup_timeout (NautilusToolbar *self)
+{
+        if (self->priv->popup_timeout_id != 0) {
+                g_source_remove (self->priv->popup_timeout_id);
+                self->priv->popup_timeout_id = 0;
+        }
+}
+
+static void
+schedule_menu_popup_timeout (NautilusToolbar *self,
+			     NautilusNavigationDirection direction)
+{
+	ScheduleMenuData *data;
+
+        /* unschedule any previous timeouts */
+        unschedule_menu_popup_timeout (self);
+
+	data = g_slice_new0 (ScheduleMenuData);
+	data->self = self;
+	data->direction = direction;
+
+        self->priv->popup_timeout_id =
+                g_timeout_add_full (G_PRIORITY_DEFAULT, MENU_POPUP_TIMEOUT,
+				    popup_menu_timeout_cb, data,
+				    (GDestroyNotify) schedule_menu_data_free);
+}
+
+static gboolean
+tool_button_press_cb (GtkButton *button,
+                      GdkEventButton *event,
+                      gpointer user_data)
+{
+        NautilusToolbar *self = user_data;
+	NautilusNavigationDirection direction;
+
+	direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button),
+							 "nav-direction"));
+
+        if (event->button == 3) {
+                /* right click */
+                show_menu (self, direction, event->button, event->time);
+                return TRUE;
+        }
+
+        if (event->button == 1) {
+                schedule_menu_popup_timeout (self, direction);
+        }
+
+	return FALSE;
+}
+
+static gboolean
+tool_button_release_cb (GtkButton *button,
+                        GdkEventButton *event,
+                        gpointer user_data)
+{
+        NautilusToolbar *self = user_data;
+
+        unschedule_menu_popup_timeout (self);
+
+        return FALSE;
+}
+
+static void
+navigation_button_setup_menu (NautilusToolbar *self,
+			      GtkWidget *button,
+			      NautilusNavigationDirection direction)
+{
+	g_object_set_data (G_OBJECT (button), "nav-direction", GUINT_TO_POINTER (direction));
+
+	g_signal_connect (button, "button-press-event",
+			  G_CALLBACK (tool_button_press_cb), self);
+	g_signal_connect (button, "button-release-event",
+			  G_CALLBACK (tool_button_release_cb), self);
+}
+
+static void
 nautilus_toolbar_constructed (GObject *obj)
 {
 	NautilusToolbar *self = NAUTILUS_TOOLBAR (obj);
@@ -135,9 +330,12 @@ nautilus_toolbar_constructed (GObject *obj)
 	GtkWidget *box;
 	GtkToolItem *back_forward;
 	GtkToolItem *tool_item;
+	GtkUIManager *ui_manager;
 
 	G_OBJECT_CLASS (nautilus_toolbar_parent_class)->constructed (obj);
 
+	ui_manager = nautilus_window_get_ui_manager (self->priv->window);
+
 	gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (self)),
 					      GTK_JUNCTION_BOTTOM);
 
@@ -158,10 +356,12 @@ nautilus_toolbar_constructed (GObject *obj)
 
 	/* Back */
 	tool_button = toolbar_create_toolbutton (self, FALSE, FALSE, NAUTILUS_ACTION_BACK);
+	navigation_button_setup_menu (self, tool_button, NAUTILUS_NAVIGATION_DIRECTION_BACK);
 	gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (tool_button));
 
 	/* Forward */
 	tool_button = toolbar_create_toolbutton (self, FALSE, FALSE, NAUTILUS_ACTION_FORWARD);
+	navigation_button_setup_menu (self, tool_button, NAUTILUS_NAVIGATION_DIRECTION_FORWARD);
 	gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (tool_button));
 
 	gtk_style_context_add_class (gtk_widget_get_style_context (box),
@@ -210,7 +410,7 @@ nautilus_toolbar_constructed (GObject *obj)
 	gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (tool_button));
 	tool_button = toolbar_create_toolbutton (self, TRUE, FALSE, "go-down-symbolic");
 	gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (tool_button));
-	menu = gtk_ui_manager_get_widget (self->priv->ui_manager, "/ViewMenu");
+	menu = gtk_ui_manager_get_widget (ui_manager, "/ViewMenu");
 	gtk_menu_button_set_popup (GTK_MENU_BUTTON (tool_button), menu);
 
 	gtk_style_context_add_class (gtk_widget_get_style_context (box),
@@ -226,7 +426,7 @@ nautilus_toolbar_constructed (GObject *obj)
 	/* Action Menu */
 	tool_item = gtk_tool_item_new ();
 	tool_button = toolbar_create_toolbutton (self, TRUE, FALSE, "emblem-system-symbolic");
-	menu = gtk_ui_manager_get_widget (self->priv->ui_manager, "/ActionMenu");
+	menu = gtk_ui_manager_get_widget (ui_manager, "/ActionMenu");
 	gtk_widget_set_halign (menu, GTK_ALIGN_END);
 	gtk_menu_button_set_popup (GTK_MENU_BUTTON (tool_button), menu);
 	gtk_actionable_set_action_name (GTK_ACTIONABLE (tool_button), "win.gear-menu");
@@ -277,11 +477,8 @@ nautilus_toolbar_set_property (GObject *object,
 	NautilusToolbar *self = NAUTILUS_TOOLBAR (object);
 
 	switch (property_id) {
-	case PROP_UI_MANAGER:
-		self->priv->ui_manager = g_value_get_object (value);
-		break;
-	case PROP_ACTION_GROUP:
-		self->priv->action_group = g_value_dup_object (value);
+	case PROP_WINDOW:
+		self->priv->window = g_value_get_object (value);
 		break;
 	case PROP_SHOW_LOCATION_ENTRY:
 		nautilus_toolbar_set_show_location_entry (self, g_value_get_boolean (value));
@@ -297,9 +494,9 @@ nautilus_toolbar_dispose (GObject *obj)
 {
 	NautilusToolbar *self = NAUTILUS_TOOLBAR (obj);
 
-	g_clear_object (&self->priv->action_group);
 	g_signal_handlers_disconnect_by_func (nautilus_preferences,
 					      toolbar_update_appearance, self);
+	unschedule_menu_popup_timeout (self);
 
 	G_OBJECT_CLASS (nautilus_toolbar_parent_class)->dispose (obj);
 }
@@ -315,18 +512,11 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
 	oclass->constructed = nautilus_toolbar_constructed;
 	oclass->dispose = nautilus_toolbar_dispose;
 
-	properties[PROP_ACTION_GROUP] =
-		g_param_spec_object ("action-group",
-				     "The action group",
-				     "The action group to get actions from",
-				     GTK_TYPE_ACTION_GROUP,
-				     G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
-				     G_PARAM_STATIC_STRINGS);
-	properties[PROP_UI_MANAGER] =
-		g_param_spec_object ("ui-manager",
-				     "The UI manager",
-				     "The UI manager",
-				     GTK_TYPE_UI_MANAGER,
+	properties[PROP_WINDOW] =
+		g_param_spec_object ("window",
+				     "The NautilusWindow",
+				     "The NautilusWindow this toolbar is part of",
+				     NAUTILUS_TYPE_WINDOW,
 				     G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
 				     G_PARAM_STATIC_STRINGS);
 	properties[PROP_SHOW_LOCATION_ENTRY] =
@@ -341,12 +531,10 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
 }
 
 GtkWidget *
-nautilus_toolbar_new (GtkUIManager *ui_manager,
-		      GtkActionGroup *action_group)
+nautilus_toolbar_new (NautilusWindow *window)
 {
 	return g_object_new (NAUTILUS_TYPE_TOOLBAR,
-			     "action-group", action_group,
-			     "ui-manager", ui_manager,
+			     "window", window,
 			     "orientation", GTK_ORIENTATION_VERTICAL,
 			     NULL);
 }
diff --git a/src/nautilus-toolbar.h b/src/nautilus-toolbar.h
index 344760a..79ec18b 100644
--- a/src/nautilus-toolbar.h
+++ b/src/nautilus-toolbar.h
@@ -28,6 +28,8 @@
 
 #include <gtk/gtk.h>
 
+#include "nautilus-window.h"
+
 #define NAUTILUS_TYPE_TOOLBAR nautilus_toolbar_get_type()
 #define NAUTILUS_TOOLBAR(obj) \
 	(G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_TOOLBAR, NautilusToolbar))
@@ -62,8 +64,7 @@ struct _NautilusToolbarClass {
 
 GType nautilus_toolbar_get_type (void);
 
-GtkWidget *nautilus_toolbar_new (GtkUIManager *ui_manager,
-				 GtkActionGroup *action_group);
+GtkWidget *nautilus_toolbar_new (NautilusWindow *window);
 
 GtkWidget *nautilus_toolbar_get_path_bar (NautilusToolbar *self);
 GtkWidget *nautilus_toolbar_get_location_bar (NautilusToolbar *self);
diff --git a/src/nautilus-window-menus.c b/src/nautilus-window-menus.c
index 093f3ad..28a50f7 100644
--- a/src/nautilus-window-menus.c
+++ b/src/nautilus-window-menus.c
@@ -35,7 +35,6 @@
 #include "nautilus-connect-server-dialog.h"
 #include "nautilus-file-management-properties.h"
 #include "nautilus-list-view.h"
-#include "nautilus-navigation-action.h"
 #include "nautilus-notebook.h"
 #include "nautilus-window-manage-views.h"
 #include "nautilus-window-private.h"
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 1602d24..89b1738 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -988,8 +988,7 @@ create_toolbar (NautilusWindow *window)
 	gtk_size_group_set_ignore_hidden (header_size_group, FALSE);
 
 	/* build the toolbar */
-	toolbar = nautilus_toolbar_new (nautilus_window_get_ui_manager (NAUTILUS_WINDOW (window)),
-					nautilus_window_get_main_action_group (NAUTILUS_WINDOW (window)));
+	toolbar = nautilus_toolbar_new (NAUTILUS_WINDOW (window));
 
 	g_object_bind_property (window, "disable-chrome",
 				toolbar, "visible",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]