[nautilus] view: handle view menu



commit 764b98f6f47395559fde40d47f09ce0cafc4719c
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.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=753673

 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      |  243 ++++++++++++++-----------------------------
 src/nautilus-toolbar.h      |    5 +-
 src/nautilus-view.c         |  218 +++++++++++++++++++++++++++++++++++++-
 src/nautilus-view.h         |    6 +
 src/nautilus-window-slot.c  |   49 +++++++++
 src/nautilus-window-slot.h  |    4 +
 src/nautilus-window.c       |    2 +
 11 files changed, 398 insertions(+), 171 deletions(-)
---
diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c
index 8d42d6f..d77ca2a 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,
@@ -1851,6 +1853,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,
@@ -1870,6 +1874,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)
 {
@@ -1914,6 +1926,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",
@@ -1955,6 +1968,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 35a7472..3beff66 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -103,6 +103,8 @@ struct NautilusListViewDetails {
        gulong clipboard_handler_id;
 
        GQuark last_sort_attr;
+
+        GIcon *icon;
 };
 
 struct SelectionForeachData {
@@ -3120,6 +3122,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,
@@ -3281,6 +3285,14 @@ nautilus_list_view_compute_rename_popover_relative_to (NautilusView *view)
         return rect;
 }
 
+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)
 {
@@ -3319,6 +3331,7 @@ nautilus_list_view_class_init (NautilusListViewClass *class)
        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->compute_rename_popover_relative_to = 
nautilus_list_view_compute_rename_popover_relative_to;
+        nautilus_view_class->get_icon = nautilus_list_view_get_icon;
 }
 
 static void
@@ -3327,6 +3340,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..d7899f6 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,74 @@ 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_icon_transform_to (GBinding     *binding,
+                                         const GValue *from_value,
+                                         GValue       *to_value,
+                                         gpointer      user_data)
+{
+        GIcon *icon;
+
+        icon = g_value_get_object (from_value);
+
+        if (icon) {
+                g_value_set_object (to_value, icon);
+        }
+
+        return TRUE;
+}
+
+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);
+
+        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) {
+                        toolbar->priv->icon_binding =
+                                        g_object_bind_property_full (slot, "icon",
+                                                                     toolbar->priv->view_icon, "gicon",
+                                                                     G_BINDING_DEFAULT | 
G_BINDING_SYNC_CREATE,
+                                                                     (GBindingTransformFunc) 
nautilus_toolbar_view_icon_transform_to,
+                                                                     NULL,
+                                                                     toolbar,
+                                                                     NULL);
+                        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 d5ec6a1..56638c4 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
 };
 
@@ -239,6 +241,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 {
@@ -594,6 +611,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.
@@ -1515,6 +1565,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)
 {
@@ -2643,6 +2702,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
@@ -2656,6 +2719,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
@@ -6760,6 +6826,47 @@ 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;
+
+       view_action_group = nautilus_view_get_action_group (view);
+
+       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
@@ -6768,7 +6875,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));
@@ -6781,10 +6887,9 @@ nautilus_view_update_toolbar_menus (NautilusView *view)
                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);
 }
 
@@ -7450,6 +7555,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,
@@ -7552,31 +7680,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);
        }
 }
 
@@ -7590,6 +7765,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;
@@ -7697,6 +7873,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);
 }
@@ -7728,6 +7917,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),
@@ -7838,7 +8045,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 3cc87da..263eec9 100644
--- a/src/nautilus-view.h
+++ b/src/nautilus-view.h
@@ -278,6 +278,8 @@ struct NautilusViewClass {
        NautilusWindow * (*get_window)            (NautilusView *view);
 
         GdkRectangle * (*compute_rename_popover_relative_to) (NautilusView *view);
+
+        GIcon *        (* get_icon)               (NautilusView *view);
 };
 
 /* GObject support */
@@ -392,4 +394,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..36d27bc 100644
--- a/src/nautilus-window-slot.h
+++ b/src/nautilus-window-slot.h
@@ -127,4 +127,8 @@ 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);
+
 #endif /* NAUTILUS_WINDOW_SLOT_H */
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 6daebbf..99667d1 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -2278,6 +2278,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");
        }


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