[nautilus/wip/gbsneto/view-menu] view: handle view menu



commit 0458e11fc8d8ff86b35dcd2501ceac947d3c3d4f
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Aug 11 12:33:39 2015 -0300

    view: handle view menu
    
    NautilusToolbar handles the view menu, requiring
    direct access to the underlying view inside the
    window slot.
    
    Since we're wiping out every access to the underlying
    view, we shouldn't access it from NautilusToolbar.
    
    To fix that, makes the view handle the view widget.
    Since we're making NautilusWindowSlot a wrapper, add
    the necessary properties for it to expose view data
    without exposing the view itself.

 src/nautilus-canvas-view.c  |   14 +++
 src/nautilus-empty-view.c   |    7 ++
 src/nautilus-list-view.c    |   15 +++
 src/nautilus-toolbar-ui.xml |    6 +
 src/nautilus-toolbar.c      |  238 +++++++++++++-----------------------------
 src/nautilus-toolbar.h      |    5 +-
 src/nautilus-view.c         |  228 +++++++++++++++++++++++++++++++++++++++--
 src/nautilus-view.h         |    6 +
 src/nautilus-window-slot.c  |   49 +++++++++
 src/nautilus-window-slot.h  |    6 +
 src/nautilus-window.c       |    8 +-
 src/nautilus-window.h       |    2 -
 12 files changed, 400 insertions(+), 184 deletions(-)
---
diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c
index 53e37d9..879d1a6 100644
--- a/src/nautilus-canvas-view.c
+++ b/src/nautilus-canvas-view.c
@@ -105,6 +105,8 @@ struct NautilusCanvasViewDetails
        gboolean supports_manual_layout;
        gboolean supports_scaling;
        gboolean supports_keep_aligned;
+
+        GIcon *icon;
 };
 
 /* Note that the first item in this list is the default sort,
@@ -1834,6 +1836,8 @@ nautilus_canvas_view_finalize (GObject *object)
 
        canvas_view = NAUTILUS_CANVAS_VIEW (object);
 
+        g_clear_object (&canvas_view->details->icon);
+
        g_free (canvas_view->details);
 
        g_signal_handlers_disconnect_by_func (nautilus_preferences,
@@ -1853,6 +1857,14 @@ nautilus_canvas_view_finalize (GObject *object)
        G_OBJECT_CLASS (nautilus_canvas_view_parent_class)->finalize (object);
 }
 
+static GIcon*
+nautilus_canvas_view_get_icon (NautilusView *view)
+{
+        g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NULL);
+
+        return NAUTILUS_CANVAS_VIEW (view)->details->icon;
+}
+
 static void
 nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass)
 {
@@ -1896,6 +1908,7 @@ nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass)
        nautilus_view_class->get_view_id = nautilus_canvas_view_get_id;
        nautilus_view_class->get_first_visible_file = canvas_view_get_first_visible_file;
        nautilus_view_class->scroll_to_file = canvas_view_scroll_to_file;
+        nautilus_view_class->get_icon = nautilus_canvas_view_get_icon;
 
        properties[PROP_SUPPORTS_AUTO_LAYOUT] =
                g_param_spec_boolean ("supports-auto-layout",
@@ -1937,6 +1950,7 @@ nautilus_canvas_view_init (NautilusCanvasView *canvas_view)
 
        canvas_view->details = g_new0 (NautilusCanvasViewDetails, 1);
        canvas_view->details->sort = &sort_criteria[0];
+        canvas_view->details->icon = g_themed_icon_new ("view-grid-symbolic");
 
        canvas_container = create_canvas_container (canvas_view);
 
diff --git a/src/nautilus-empty-view.c b/src/nautilus-empty-view.c
index 9881b84..5ece1c4 100644
--- a/src/nautilus-empty-view.c
+++ b/src/nautilus-empty-view.c
@@ -229,6 +229,12 @@ nautilus_empty_view_get_id (NautilusView *view)
        return NAUTILUS_EMPTY_VIEW_ID;
 }
 
+static GIcon*
+nautilus_empty_view_get_icon (NautilusView *view)
+{
+        return NULL;
+}
+
 static void
 nautilus_empty_view_class_init (NautilusEmptyViewClass *class)
 {
@@ -266,6 +272,7 @@ nautilus_empty_view_class_init (NautilusEmptyViewClass *class)
        nautilus_view_class->get_view_id = nautilus_empty_view_get_id;
        nautilus_view_class->get_first_visible_file = nautilus_empty_view_get_first_visible_file;
        nautilus_view_class->scroll_to_file = nautilus_empty_view_scroll_to_file;
+        nautilus_view_class->get_icon = nautilus_empty_view_get_icon;
 }
 
 static void
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index 20a4882..d39b681 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -97,6 +97,8 @@ struct NautilusListViewDetails {
        gulong clipboard_handler_id;
 
        GQuark last_sort_attr;
+
+        GIcon *icon;
 };
 
 struct SelectionForeachData {
@@ -3114,6 +3116,8 @@ nautilus_list_view_finalize (GObject *object)
                gtk_widget_destroy (list_view->details->column_editor);
        }
 
+        g_clear_object (&list_view->details->icon);
+
        g_free (list_view->details);
 
        g_signal_handlers_disconnect_by_func (nautilus_preferences,
@@ -3240,6 +3244,14 @@ nautilus_list_view_get_id (NautilusView *view)
        return NAUTILUS_LIST_VIEW_ID;
 }
 
+static GIcon*
+nautilus_list_view_get_icon (NautilusView *view)
+{
+        g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), NULL);
+
+        return NAUTILUS_LIST_VIEW (view)->details->icon;
+}
+
 static void
 nautilus_list_view_class_init (NautilusListViewClass *class)
 {
@@ -3277,6 +3289,7 @@ nautilus_list_view_class_init (NautilusListViewClass *class)
        nautilus_view_class->get_view_id = nautilus_list_view_get_id;
        nautilus_view_class->get_first_visible_file = nautilus_list_view_get_first_visible_file;
        nautilus_view_class->scroll_to_file = list_view_scroll_to_file;
+        nautilus_view_class->get_icon = nautilus_list_view_get_icon;
 }
 
 static void
@@ -3285,6 +3298,8 @@ nautilus_list_view_init (NautilusListView *list_view)
        GActionGroup *view_action_group;
        list_view->details = g_new0 (NautilusListViewDetails, 1);
 
+        list_view->details->icon = g_themed_icon_new ("view-list-symbolic");
+
        /* ensure that the zoom level is always set before settings up the tree view columns */
        list_view->details->zoom_level = get_default_zoom_level ();
 
diff --git a/src/nautilus-toolbar-ui.xml b/src/nautilus-toolbar-ui.xml
index a417667..52d5d63 100644
--- a/src/nautilus-toolbar-ui.xml
+++ b/src/nautilus-toolbar-ui.xml
@@ -104,6 +104,12 @@
         <style>
           <class name="image-button"/>
         </style>
+        <child>
+          <object class="GtkImage" id="view_icon">
+            <property name="visible">True</property>
+            <property name="icon-size">1</property>
+          </object>
+        </child>
         <child internal-child="accessible">
           <object class="AtkObject">
             <property name="accessible-name" translatable="yes">View menu</property>
diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c
index 3e33d28..6b40696 100644
--- a/src/nautilus-toolbar.c
+++ b/src/nautilus-toolbar.c
@@ -71,21 +71,18 @@ struct _NautilusToolbarPrivate {
         GtkWidget *operations_container;
         GtkWidget *operations_revealer;
         GtkWidget *operations_icon;
-       GtkWidget *view_menu_widget;
-       GtkWidget *sort_menu;
-       GtkWidget *sort_trash_time;
-       GtkWidget *sort_search_relevance;
-       GtkWidget *visible_columns;
-       GtkWidget *stop;
-       GtkWidget *reload;
-       GtkAdjustment *zoom_adjustment;
-       GtkWidget *zoom_level_scale;
+       GtkWidget *view_icon;
        GMenu *action_menu;
 
        GtkWidget *forward_button;
        GtkWidget *back_button;
 
         NautilusProgressInfoManager *progress_manager;
+
+        /* active slot & bindings */
+        NautilusWindowSlot *active_slot;
+        GBinding *icon_binding;
+        GBinding *view_widget_binding;
 };
 
 enum {
@@ -262,66 +259,6 @@ show_menu (NautilusToolbar *self,
                         button, event_time);
 }
 
-static void
-action_view_mode_state_changed (GActionGroup *action_group,
-                               gchar *action_name,
-                               GVariant *value,
-                               gpointer user_data)
-{
-       NautilusToolbar *self = user_data;
-       const gchar *view_mode = g_variant_get_string (value, NULL);
-       const gchar *name;
-       GtkWidget *image;
-
-       if (g_strcmp0 (view_mode, "list") == 0) {
-               name = "view-list-symbolic";
-       } else if (g_strcmp0 (view_mode, "grid") == 0) {
-               name = "view-grid-symbolic";
-       } else {
-               g_assert_not_reached ();
-       }
-
-       image = gtk_image_new ();
-       gtk_button_set_image (GTK_BUTTON (self->priv->view_button), image);
-       gtk_image_set_from_icon_name (GTK_IMAGE (image), name,
-                                     GTK_ICON_SIZE_MENU);
-}
-
-static void
-action_reload_enabled_changed (GActionGroup *action_group,
-                              gchar *action_name,
-                              gboolean enabled,
-                              gpointer user_data)
-{
-       NautilusToolbar *self = user_data;
-       gtk_widget_set_visible (self->priv->reload, enabled);
-}
-
-static void
-action_stop_enabled_changed (GActionGroup *action_group,
-                            gchar *action_name,
-                            gboolean enabled,
-                            gpointer user_data)
-{
-       NautilusToolbar *self = user_data;
-       gtk_widget_set_visible (self->priv->stop, enabled);
-}
-
-static void
-nautilus_toolbar_set_window (NautilusToolbar *self,
-                            NautilusWindow *window)
-
-{
-       self->priv->window = window;
-
-       g_signal_connect (self->priv->window, "action-enabled-changed::stop",
-                         G_CALLBACK (action_stop_enabled_changed), self);
-       g_signal_connect (self->priv->window, "action-enabled-changed::reload",
-                         G_CALLBACK (action_reload_enabled_changed), self);
-       g_signal_connect (self->priv->window, "action-state-changed::view-mode",
-                         G_CALLBACK (action_view_mode_state_changed), self);
-}
-
 #define MENU_POPUP_TIMEOUT 1200
 
 typedef struct {
@@ -405,30 +342,6 @@ navigation_button_release_cb (GtkButton *button,
         return FALSE;
 }
 
-static void
-zoom_level_changed (GtkRange *range,
-                   NautilusToolbar *self)
-{
-       NautilusWindowSlot *slot;
-       NautilusView *view;
-       gdouble zoom_level;
-
-       zoom_level = gtk_range_get_value (range);
-       slot = nautilus_window_get_active_slot (self->priv->window);
-       view = nautilus_window_slot_get_current_view (slot);
-
-       g_action_group_change_action_state (nautilus_view_get_action_group (view),
-                                           "zoom-to-level",
-                                           g_variant_new_int32 ((gint) zoom_level));
-}
-
-static void
-view_menu_popover_closed (GtkPopover *popover,
-                         NautilusToolbar *self)
-{
-        gtk_widget_grab_focus (GTK_WIDGET (self->priv->window));
-}
-
 static gboolean
 should_hide_operations_button (NautilusToolbar *self)
 {
@@ -755,24 +668,6 @@ nautilus_toolbar_init (NautilusToolbar *self)
        gtk_container_add (GTK_CONTAINER (self->priv->location_entry_container),
                                          self->priv->location_entry);
 
-       builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-view-menu.xml");
-       self->priv->view_menu_widget =  GTK_WIDGET (gtk_builder_get_object (builder, "view_menu_widget"));
-       self->priv->zoom_level_scale = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_level_scale"));
-       self->priv->zoom_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment"));
-
-       self->priv->sort_menu =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_menu"));
-       self->priv->sort_trash_time =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_trash_time"));
-       self->priv->sort_search_relevance =  GTK_WIDGET (gtk_builder_get_object (builder, 
"sort_search_relevance"));
-       self->priv->visible_columns =  GTK_WIDGET (gtk_builder_get_object (builder, "visible_columns"));
-       self->priv->reload =  GTK_WIDGET (gtk_builder_get_object (builder, "reload"));
-       self->priv->stop =  GTK_WIDGET (gtk_builder_get_object (builder, "stop"));
-
-       g_signal_connect (self->priv->view_menu_widget, "closed",
-                         G_CALLBACK (view_menu_popover_closed), self);
-       gtk_menu_button_set_popover (GTK_MENU_BUTTON (self->priv->view_button),
-                                    self->priv->view_menu_widget);
-       g_object_unref (builder);
-
        builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-action-menu.xml");
        self->priv->action_menu = G_MENU (gtk_builder_get_object (builder, "action-menu"));
        gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (self->priv->action_button),
@@ -796,8 +691,6 @@ nautilus_toolbar_init (NautilusToolbar *self)
                          G_CALLBACK (navigation_button_press_cb), self);
        g_signal_connect (self->priv->forward_button, "button-release-event",
                          G_CALLBACK (navigation_button_release_cb), self);
-       g_signal_connect (self->priv->zoom_level_scale, "value-changed",
-                         G_CALLBACK (zoom_level_changed), self);
 
        gtk_widget_show_all (GTK_WIDGET (self));
        toolbar_update_appearance (self);
@@ -831,7 +724,7 @@ nautilus_toolbar_set_property (GObject *object,
 
        switch (property_id) {
        case PROP_WINDOW:
-               nautilus_toolbar_set_window (self, g_value_get_object (value));
+               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));
@@ -901,6 +794,7 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, operations_container);
        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, operations_revealer);
        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, view_button);
+        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, view_icon);
        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, action_button);
        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, path_bar_container);
        gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, 
location_entry_container);
@@ -911,56 +805,6 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
         gtk_widget_class_bind_template_callback (widget_class, on_operations_button_toggled);
 }
 
-void
-nautilus_toolbar_reset_menus (NautilusToolbar *self)
-{
-       NautilusWindowSlot *slot;
-       NautilusView *view;
-       GActionGroup *view_action_group;
-       GVariant *variant;
-       GVariantIter iter;
-       gboolean show_sort_trash, show_sort_search, show_sort_access, show_sort_modification, enable_sort;
-       const gchar *hint;
-
-       /* Allow actions from the current view to be activated through
-        * the view menu and action menu of the toolbar */
-       slot = nautilus_window_get_active_slot (self->priv->window);
-       view = nautilus_window_slot_get_current_view (slot);
-       view_action_group = nautilus_view_get_action_group (view);
-       gtk_widget_insert_action_group (GTK_WIDGET (self),
-                                       "view",
-                                       G_ACTION_GROUP (view_action_group));
-
-       gtk_widget_set_visible (self->priv->visible_columns,
-                               g_action_group_has_action (view_action_group, "visible-columns"));
-
-       enable_sort = g_action_group_get_action_enabled (view_action_group, "sort");
-       show_sort_trash = show_sort_search = show_sort_modification = show_sort_access = FALSE;
-       gtk_widget_set_visible (self->priv->sort_menu, enable_sort);
-
-       if (enable_sort) {
-               variant = g_action_group_get_action_state_hint (view_action_group, "sort");
-               g_variant_iter_init (&iter, variant);
-
-               while (g_variant_iter_next (&iter, "&s", &hint)) {
-                       if (g_strcmp0 (hint, "trash-time") == 0)
-                               show_sort_trash = TRUE;
-                       if (g_strcmp0 (hint, "search-relevance") == 0)
-                               show_sort_search = TRUE;
-               }
-
-               g_variant_unref (variant);
-       }
-
-       gtk_widget_set_visible (self->priv->sort_trash_time, show_sort_trash);
-       gtk_widget_set_visible (self->priv->sort_search_relevance, show_sort_search);
-
-       variant = g_action_group_get_action_state (view_action_group, "zoom-to-level");
-       gtk_adjustment_set_value (self->priv->zoom_adjustment,
-                                 g_variant_get_int32 (variant));
-       g_variant_unref (variant);
-}
-
 GtkWidget *
 nautilus_toolbar_new ()
 {
@@ -1000,3 +844,69 @@ nautilus_toolbar_set_show_location_entry (NautilusToolbar *self,
                g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_LOCATION_ENTRY]);
        }
 }
+
+static gboolean
+nautilus_toolbar_view_widget_transform_to (GBinding     *binding,
+                                           const GValue *from_value,
+                                           GValue       *to_value,
+                                           gpointer      user_data)
+{
+        NautilusToolbar *toolbar;
+        GtkWidget *view_widget;
+
+        toolbar = NAUTILUS_TOOLBAR (user_data);
+        view_widget = g_value_get_object (from_value);
+
+        gtk_widget_set_sensitive (toolbar->priv->view_button, view_widget != NULL);
+        gtk_menu_button_set_popover (GTK_MENU_BUTTON (toolbar->priv->view_button), NULL);
+
+        if (view_widget) {
+                if (!GTK_IS_POPOVER (view_widget)) {
+                        GtkWidget *popover;
+
+                        popover = gtk_popover_new (toolbar->priv->view_button);
+                        gtk_container_add (GTK_CONTAINER (popover), view_widget);
+
+                        view_widget = popover;
+                }
+        }
+
+        g_value_set_object (to_value, view_widget);
+
+        return TRUE;
+}
+
+void
+nautilus_toolbar_set_active_slot (NautilusToolbar    *toolbar,
+                                  NautilusWindowSlot *slot)
+{
+        g_return_if_fail (NAUTILUS_IS_TOOLBAR (toolbar));
+
+        g_clear_pointer (&toolbar->priv->icon_binding, g_binding_unbind);
+        g_clear_pointer (&toolbar->priv->view_widget_binding, g_binding_unbind);
+
+        if (toolbar->priv->active_slot != slot) {
+                toolbar->priv->active_slot = slot;
+
+                if (slot) {
+                        GIcon *icon;
+
+                        icon = nautilus_window_slot_get_icon (slot);
+
+                        gtk_image_set_from_gicon (GTK_IMAGE (toolbar->priv->view_icon), icon, 
GTK_ICON_SIZE_BUTTON);
+
+                        toolbar->priv->icon_binding = g_object_bind_property (slot, "icon",
+                                                                              toolbar->priv->view_icon, 
"gicon",
+                                                                              G_BINDING_DEFAULT);
+                        toolbar->priv->view_widget_binding =
+                                        g_object_bind_property_full (slot, "view-widget",
+                                                                     toolbar->priv->view_button, "popover",
+                                                                     G_BINDING_DEFAULT | 
G_BINDING_SYNC_CREATE,
+                                                                     (GBindingTransformFunc) 
nautilus_toolbar_view_widget_transform_to,
+                                                                     NULL,
+                                                                     toolbar,
+                                                                     NULL);
+                }
+
+        }
+}
diff --git a/src/nautilus-toolbar.h b/src/nautilus-toolbar.h
index f281b95..c66ef91 100644
--- a/src/nautilus-toolbar.h
+++ b/src/nautilus-toolbar.h
@@ -27,6 +27,7 @@
 
 #include <gtk/gtk.h>
 
+#include "nautilus-window-slot.h"
 
 #define NAUTILUS_TYPE_TOOLBAR nautilus_toolbar_get_type()
 #define NAUTILUS_TOOLBAR(obj) \
@@ -70,6 +71,8 @@ GMenu     *nautilus_toolbar_get_action_menu (NautilusToolbar *self);
 
 void nautilus_toolbar_set_show_location_entry (NautilusToolbar *self,
                                               gboolean show_location_entry);
-void nautilus_toolbar_reset_menus (NautilusToolbar *self);
+
+void       nautilus_toolbar_set_active_slot    (NautilusToolbar    *toolbar,
+                                                NautilusWindowSlot *slot);
 
 #endif /* __NAUTILUS_TOOLBAR_H__ */
diff --git a/src/nautilus-view.c b/src/nautilus-view.c
index 073bacc..120b13e 100644
--- a/src/nautilus-view.c
+++ b/src/nautilus-view.c
@@ -141,6 +141,8 @@ enum {
 enum {
        PROP_WINDOW_SLOT = 1,
        PROP_SUPPORTS_ZOOMING,
+        PROP_ICON,
+        PROP_VIEW_WIDGET,
        NUM_PROPERTIES
 };
 
@@ -238,6 +240,21 @@ struct NautilusViewDetails
         guint floating_bar_set_status_timeout_id;
         guint floating_bar_loading_timeout_id;
         GtkWidget *floating_bar;
+
+        /* View menu */
+        GtkWidget *view_menu_widget;
+        GtkWidget *view_icon;
+        GtkWidget *sort_menu;
+        GtkWidget *sort_trash_time;
+        GtkWidget *sort_search_relevance;
+        GtkWidget *visible_columns;
+        GtkWidget *stop;
+        GtkWidget *reload;
+        GtkAdjustment *zoom_adjustment;
+        GtkWidget *zoom_level_scale;
+
+        gulong stop_signal_handler;
+        gulong reload_signal_handler;
 };
 
 typedef struct {
@@ -593,6 +610,39 @@ nautilus_view_using_manual_layout (NautilusView  *view)
 }
 
 /**
+ * nautilus_view_get_icon:
+ * @view: a #NautilusView
+ *
+ * Retrieves the #GIcon that represents @view.
+ *
+ * Returns: (transfer none): the #Gicon that represents @view
+ */
+GIcon*
+nautilus_view_get_icon (NautilusView *view)
+{
+        g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
+
+        return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_icon (view);
+}
+
+/**
+ * nautilus_view_get_view_widget:
+ * @view: a #NautilusView
+ *
+ * Retrieves the view menu, as a #GtkWidget. If it's %NULL,
+ * the button renders insensitive.
+ *
+ * Returns: (transfer none): a #GtkWidget for the view menu
+ */
+GtkWidget*
+nautilus_view_get_view_widget (NautilusView *view)
+{
+        g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL);
+
+        return view->details->view_menu_widget;
+}
+
+/**
  * nautilus_view_can_rename_file
  *
  * Determine whether a file can be renamed.
@@ -1514,6 +1564,15 @@ action_select_pattern (GSimpleAction *action,
 }
 
 static void
+zoom_level_changed (GtkRange     *range,
+                    NautilusView *view)
+{
+        g_action_group_change_action_state (view->details->view_action_group,
+                                            "zoom-to-level",
+                                            g_variant_new_int32 (gtk_range_get_value (range)));
+}
+
+static void
 reveal_newly_added_folder (NautilusView *view, NautilusFile *new_file,
                           NautilusDirectory *directory, GFile *target_location)
 {
@@ -2617,6 +2676,10 @@ slot_active (NautilusWindowSlot *slot,
        nautilus_view_update_toolbar_menus (view);
 
        schedule_update_context_menus (view);
+
+        gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)),
+                                        "view",
+                                        G_ACTION_GROUP (view->details->view_action_group));
 }
 
 static void
@@ -2630,6 +2693,9 @@ slot_inactive (NautilusWindowSlot *slot,
        view->details->active = FALSE;
 
        remove_update_context_menus_timeout_callback (view);
+        gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)),
+                                        "view",
+                                        NULL);
 }
 
 static void
@@ -6734,6 +6800,52 @@ nautilus_view_update_context_menus (NautilusView *view)
        NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_context_menus (view);
 }
 
+static void
+nautilus_view_reset_view_menu (NautilusView *view)
+{
+       GActionGroup *view_action_group;
+       GVariant *variant;
+       GVariantIter iter;
+       gboolean show_sort_trash, show_sort_search, show_sort_access, show_sort_modification, enable_sort;
+       const gchar *hint;
+
+       /* Allow actions from the current view to be activated through
+        * the view menu and action menu of the toolbar */
+       view_action_group = nautilus_view_get_action_group (view);
+        gtk_widget_insert_action_group (GTK_WIDGET (view),
+                                       "view",
+                                       G_ACTION_GROUP (view_action_group));
+
+       gtk_widget_set_visible (view->details->visible_columns,
+                               g_action_group_has_action (view_action_group, "visible-columns"));
+
+       enable_sort = g_action_group_get_action_enabled (view_action_group, "sort");
+       show_sort_trash = show_sort_search = show_sort_modification = show_sort_access = FALSE;
+       gtk_widget_set_visible (view->details->sort_menu, enable_sort);
+
+       if (enable_sort) {
+               variant = g_action_group_get_action_state_hint (view_action_group, "sort");
+               g_variant_iter_init (&iter, variant);
+
+               while (g_variant_iter_next (&iter, "&s", &hint)) {
+                       if (g_strcmp0 (hint, "trash-time") == 0)
+                               show_sort_trash = TRUE;
+                       if (g_strcmp0 (hint, "search-relevance") == 0)
+                               show_sort_search = TRUE;
+               }
+
+               g_variant_unref (variant);
+       }
+
+       gtk_widget_set_visible (view->details->sort_trash_time, show_sort_trash);
+       gtk_widget_set_visible (view->details->sort_search_relevance, show_sort_search);
+
+       variant = g_action_group_get_action_state (view_action_group, "zoom-to-level");
+       gtk_adjustment_set_value (view->details->zoom_adjustment,
+                                 g_variant_get_int32 (variant));
+       g_variant_unref (variant);
+}
+
 /* Convenience function to reset the menus owned by the view but managed on
  * the toolbar, and update them with the current state.
  * It will also update the actions state, which will also update children
@@ -6742,9 +6854,6 @@ nautilus_view_update_context_menus (NautilusView *view)
 void
 nautilus_view_update_toolbar_menus (NautilusView *view)
 {
-       NautilusToolbar *toolbar;
-       NautilusWindow *window;
-
        g_assert (NAUTILUS_IS_VIEW (view));
 
        /* Don't update after destroy (#349551),
@@ -6754,11 +6863,7 @@ nautilus_view_update_toolbar_menus (NautilusView *view)
            !view->details->active) {
                return;
        }
-       window = nautilus_view_get_window (view);
-       toolbar = NAUTILUS_TOOLBAR (nautilus_window_get_toolbar (window));
-       nautilus_toolbar_reset_menus (toolbar);
-       nautilus_window_reset_menus (window);
-
+       nautilus_view_reset_view_menu (view);
        nautilus_view_update_actions_state (view);
 }
 
@@ -7424,6 +7529,29 @@ real_get_selected_icon_locations (NautilusView *view)
 }
 
 static void
+nautilus_view_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+        NautilusView *view = NAUTILUS_VIEW (object);
+
+        switch (prop_id) {
+        case PROP_ICON:
+                g_value_set_object (value, nautilus_view_get_icon (view));
+                break;
+
+        case PROP_VIEW_WIDGET:
+                g_value_set_object (value, nautilus_view_get_view_widget (view));
+                break;
+
+        default:
+                g_assert_not_reached ();
+
+        }
+}
+
+static void
 nautilus_view_set_property (GObject         *object,
                            guint            prop_id,
                            const GValue    *value,
@@ -7526,31 +7654,78 @@ nautilus_view_scroll_event (GtkWidget *widget,
        return FALSE;
 }
 
+
+static void
+action_reload_enabled_changed (GActionGroup *action_group,
+                               gchar        *action_name,
+                               gboolean      enabled,
+                               NautilusView *view)
+{
+       gtk_widget_set_visible (view->details->reload, enabled);
+}
+
+static void
+action_stop_enabled_changed (GActionGroup *action_group,
+                             gchar        *action_name,
+                             gboolean      enabled,
+                             NautilusView *view)
+{
+       gtk_widget_set_visible (view->details->stop, enabled);
+}
+
 static void
 nautilus_view_parent_set (GtkWidget *widget,
                          GtkWidget *old_parent)
 {
+        NautilusWindow *window;
        NautilusView *view;
        GtkWidget *parent;
 
        view = NAUTILUS_VIEW (widget);
 
        parent = gtk_widget_get_parent (widget);
+        window = nautilus_view_get_window (view);
        g_assert (parent == NULL || old_parent == NULL);
 
        if (GTK_WIDGET_CLASS (nautilus_view_parent_class)->parent_set != NULL) {
                GTK_WIDGET_CLASS (nautilus_view_parent_class)->parent_set (widget, old_parent);
        }
 
+        if (view->details->stop_signal_handler > 0) {
+                g_signal_handler_disconnect (window, view->details->stop_signal_handler);
+                view->details->stop_signal_handler = 0;
+        }
+
+        if (view->details->reload_signal_handler > 0) {
+                g_signal_handler_disconnect (window, view->details->reload_signal_handler);
+                view->details->reload_signal_handler = 0;
+        }
+
        if (parent != NULL) {
                g_assert (old_parent == NULL);
 
-               if (view->details->slot == 
-                   nautilus_window_get_active_slot (nautilus_view_get_window (view))) {
+               if (view->details->slot == nautilus_window_get_active_slot (window)) {
                        view->details->active = TRUE;
+                        gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)),
+                                                        "view",
+                                                        G_ACTION_GROUP (view->details->view_action_group));
                }
+
+                view->details->stop_signal_handler =
+                                g_signal_connect (window,
+                                                  "action-enabled-changed::stop",
+                                                  G_CALLBACK (action_stop_enabled_changed),
+                                                  view);
+                view->details->reload_signal_handler =
+                                g_signal_connect (window,
+                                                  "action-enabled-changed::reload",
+                                                  G_CALLBACK (action_reload_enabled_changed),
+                                                  view);
        } else {
                remove_update_context_menus_timeout_callback (view);
+                gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)),
+                                                "view",
+                                                NULL);
        }
 }
 
@@ -7564,6 +7739,7 @@ nautilus_view_class_init (NautilusViewClass *klass)
        oclass = G_OBJECT_CLASS (klass);
 
        oclass->finalize = nautilus_view_finalize;
+        oclass->get_property = nautilus_view_get_property;
        oclass->set_property = nautilus_view_set_property;
 
        widget_class->destroy = nautilus_view_destroy;
@@ -7671,6 +7847,19 @@ nautilus_view_class_init (NautilusViewClass *klass)
                                      TRUE,
                                      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
                                      G_PARAM_STATIC_STRINGS);
+        properties[PROP_ICON] =
+                g_param_spec_object ("icon",
+                                     "Icon",
+                                     "The icon that represents the view",
+                                     G_TYPE_ICON,
+                                     G_PARAM_READABLE);
+
+        properties[PROP_VIEW_WIDGET] =
+                g_param_spec_object ("view-widget",
+                                     "View widget",
+                                     "The view's widget that will appear under the view menu button",
+                                     GTK_TYPE_WIDGET,
+                                     G_PARAM_READABLE);
 
        g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
 }
@@ -7702,6 +7891,24 @@ nautilus_view_init (NautilusView *view)
         gtk_widget_add_events (GTK_WIDGET (view),
                                GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
 
+        /* View menu */
+        builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-view-menu.xml");
+       view->details->view_menu_widget =  g_object_ref (gtk_builder_get_object (builder, 
"view_menu_widget"));
+       view->details->zoom_level_scale = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_level_scale"));
+       view->details->zoom_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment"));
+
+       view->details->sort_menu =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_menu"));
+       view->details->sort_trash_time =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_trash_time"));
+       view->details->sort_search_relevance =  GTK_WIDGET (gtk_builder_get_object (builder, 
"sort_search_relevance"));
+       view->details->visible_columns =  GTK_WIDGET (gtk_builder_get_object (builder, "visible_columns"));
+       view->details->reload =  GTK_WIDGET (gtk_builder_get_object (builder, "reload"));
+       view->details->stop =  GTK_WIDGET (gtk_builder_get_object (builder, "stop"));
+
+        g_signal_connect (view->details->zoom_level_scale, "value-changed",
+                          G_CALLBACK (zoom_level_changed), view);
+
+        g_object_unref (builder);
+
         /* Scrolled Window */
         view->details->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view->details->scrolled_window),
@@ -7812,7 +8019,6 @@ nautilus_view_init (NautilusView *view)
        gtk_widget_insert_action_group (GTK_WIDGET (view),
                                        "view",
                                        G_ACTION_GROUP (view->details->view_action_group));
-
        app = g_application_get_default ();
 
        /* Toolbar menu */
diff --git a/src/nautilus-view.h b/src/nautilus-view.h
index 93fbc89..b6e73ce 100644
--- a/src/nautilus-view.h
+++ b/src/nautilus-view.h
@@ -276,6 +276,8 @@ struct NautilusViewClass {
                                                   const char            *uri);
 
        NautilusWindow * (*get_window)            (NautilusView *view);
+
+        GIcon *        (* get_icon)               (NautilusView *view);
 };
 
 /* GObject support */
@@ -390,4 +392,8 @@ GActionGroup *    nautilus_view_get_action_group           (NautilusView      *v
 GtkWidget*        nautilus_view_get_content_widget         (NautilusView      *view);
 gboolean          nautilus_view_is_search                  (NautilusView      *view);
 
+GIcon*            nautilus_view_get_icon                   (NautilusView      *view);
+
+GtkWidget*        nautilus_view_get_view_widget            (NautilusView      *view);
+
 #endif /* NAUTILUS_VIEW_H */
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c
index 766c6a5..0c5e393 100644
--- a/src/nautilus-window-slot.c
+++ b/src/nautilus-window-slot.c
@@ -55,6 +55,8 @@ enum {
 
 enum {
        PROP_WINDOW = 1,
+        PROP_ICON,
+        PROP_VIEW_WIDGET,
        NUM_PROPERTIES
 };
 
@@ -527,6 +529,12 @@ nautilus_window_slot_get_property (GObject *object,
        case PROP_WINDOW:
                g_value_set_object (value, slot->details->window);
                break;
+        case PROP_ICON:
+                g_value_set_object (value, nautilus_window_slot_get_icon (slot));
+                break;
+        case PROP_VIEW_WIDGET:
+                g_value_set_object (value, nautilus_window_slot_get_view_widget (slot));
+                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
@@ -2267,6 +2275,9 @@ nautilus_window_slot_switch_new_content_view (NautilusWindowSlot *slot)
                 gtk_container_add (GTK_CONTAINER (slot), widget);
                 gtk_widget_set_vexpand (widget, TRUE);
                gtk_widget_show (widget);
+
+                g_object_notify_by_pspec (G_OBJECT (slot), properties[PROP_ICON]);
+                g_object_notify_by_pspec (G_OBJECT (slot), properties[PROP_VIEW_WIDGET]);
        }
 }
 
@@ -2448,6 +2459,20 @@ nautilus_window_slot_class_init (NautilusWindowSlotClass *klass)
                                     NAUTILUS_TYPE_WINDOW,
                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
 
+        properties[PROP_ICON] =
+               g_param_spec_object ("icon",
+                                    "Icon that represents the slot",
+                                    "The icon that represents the slot",
+                                    G_TYPE_ICON,
+                                    G_PARAM_READABLE);
+
+        properties[PROP_VIEW_WIDGET] =
+               g_param_spec_object ("view-widget",
+                                    "Widget for the view menu",
+                                    "The widget for the view's menu",
+                                    GTK_TYPE_WIDGET,
+                                    G_PARAM_READABLE);
+
        g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
        g_type_class_add_private (klass, sizeof (NautilusWindowSlotDetails));
 }
@@ -2656,3 +2681,27 @@ nautilus_window_slot_new (NautilusWindow *window)
                             "window", window,
                             NULL);
 }
+
+GIcon*
+nautilus_window_slot_get_icon (NautilusWindowSlot *slot)
+{
+        NautilusView *view;
+
+        g_return_val_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot), NULL);
+
+        view = nautilus_window_slot_get_current_view (slot);
+
+        return view ? nautilus_view_get_icon (view) : NULL;
+}
+
+GtkWidget*
+nautilus_window_slot_get_view_widget (NautilusWindowSlot *slot)
+{
+        NautilusView *view;
+
+        g_return_val_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot), NULL);
+
+        view = nautilus_window_slot_get_current_view (slot);
+
+        return view ? nautilus_view_get_view_widget (view) : NULL;
+}
diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h
index 97ff788..c7c3e8a 100644
--- a/src/nautilus-window-slot.h
+++ b/src/nautilus-window-slot.h
@@ -127,4 +127,10 @@ void nautilus_window_slot_display_view_selection_failure   (NautilusWindow *wind
                                                             GFile          *location,
                                                             GError         *error);
 
+GIcon*   nautilus_window_slot_get_icon                     (NautilusWindowSlot *slot);
+
+GtkWidget* nautilus_window_slot_get_view_widget            (NautilusWindowSlot *slot);
+
+gboolean   nautilus_window_slot_get_active                 (NautilusWindowSlot *slot);
+
 #endif /* NAUTILUS_WINDOW_SLOT_H */
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 6daebbf..eb0df24 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -768,12 +768,6 @@ update_cursor (NautilusWindow *window)
 }
 
 void
-nautilus_window_reset_menus (NautilusWindow *window)
-{
-       nautilus_window_sync_allow_stop (window, nautilus_window_get_active_slot (window));
-}
-
-void
 nautilus_window_sync_allow_stop (NautilusWindow *window,
                                 NautilusWindowSlot *slot)
 {
@@ -2278,6 +2272,8 @@ nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new
                /* inform sidebar panels */
                 nautilus_window_report_location_change (window);
 
+                nautilus_toolbar_set_active_slot (NAUTILUS_TOOLBAR (window->priv->toolbar), new_slot);
+
                /* inform slot & view */
                 g_signal_emit_by_name (new_slot, "active");
        }
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index 7bb3e2d..f018340 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -126,8 +126,6 @@ void     nautilus_window_back_or_forward      (NautilusWindow *window,
                                                gboolean        back,
                                                guint           distance,
                                                NautilusWindowOpenFlags flags);
-void nautilus_window_reset_menus (NautilusWindow *window);
-
 GtkWidget *         nautilus_window_get_notebook (NautilusWindow *window);
 
 NautilusWindowOpenFlags nautilus_event_get_window_open_flags   (void);



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