Commit 52679f97 authored by Cosimo Cecchi's avatar Cosimo Cecchi

window: simplify toolbar actions creation

Instead of having the toolbar create a different action group, with
different actions, and having to keep those in sync with the window's
main action group manually, just pass the main action group to the
toolbar.
This also makes NautilusNavigationState useless (and removes a lot of
boilerplate code), and fixes Ctrl+1/Ctrl+2 not working correctly as
shorcuts to switch view type.
parent 6f6171a1
......@@ -168,8 +168,6 @@ nautilus_SOURCES = \
nautilus-mime-actions.h \
nautilus-navigation-action.c \
nautilus-navigation-action.h \
nautilus-navigation-state.c \
nautilus-navigation-state.h \
nautilus-notebook.c \
nautilus-notebook.h \
nautilus-pathbar.c \
......
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* Nautilus - Nautilus navigation state
*
* Copyright (C) 2011 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Cosimo Cecchi <cosimoc@redhat.com>
*
*/
#include <config.h>
#include "nautilus-navigation-state.h"
struct _NautilusNavigationStateDetails {
GtkActionGroup *slave;
GtkActionGroup *master;
GList *groups;
gchar **action_names;
GList *active_bindings;
};
enum {
PROP_SLAVE = 1,
PROP_MASTER,
PROP_ACTION_NAMES,
NUM_PROPERTIES,
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
G_DEFINE_TYPE (NautilusNavigationState, nautilus_navigation_state, G_TYPE_OBJECT);
static void
clear_bindings (NautilusNavigationState *self)
{
g_list_free_full (self->priv->active_bindings, g_object_unref);
self->priv->active_bindings = NULL;
}
static void
update_bindings (NautilusNavigationState *self)
{
gint length, idx;
GBinding *binding;
GtkAction *master_action, *slave_action;
length = g_strv_length (self->priv->action_names);
for (idx = 0; idx < length; idx++) {
master_action = gtk_action_group_get_action (self->priv->master,
self->priv->action_names[idx]);
slave_action = gtk_action_group_get_action (self->priv->slave,
self->priv->action_names[idx]);
binding = g_object_bind_property (master_action, "sensitive",
slave_action, "sensitive",
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
/* bind "active" too for toggle actions */
if (GTK_IS_TOGGLE_ACTION (master_action)) {
binding = g_object_bind_property (master_action, "active",
slave_action, "active",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
}
self->priv->active_bindings = g_list_prepend (self->priv->active_bindings, binding);
}
}
static void
nautilus_navigation_state_init (NautilusNavigationState *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_NAVIGATION_STATE,
NautilusNavigationStateDetails);
}
static void
nautilus_navigation_state_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
NautilusNavigationState *self = NAUTILUS_NAVIGATION_STATE (object);
switch (property_id) {
case PROP_SLAVE:
self->priv->slave = g_value_dup_object (value);
nautilus_navigation_state_add_group (self, g_value_get_object (value));
break;
case PROP_MASTER:
self->priv->master = g_value_dup_object (value);
break;
case PROP_ACTION_NAMES:
self->priv->action_names = g_value_dup_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
nautilus_navigation_state_finalize (GObject *obj)
{
NautilusNavigationState *self = NAUTILUS_NAVIGATION_STATE (obj);
g_strfreev (self->priv->action_names);
G_OBJECT_CLASS (nautilus_navigation_state_parent_class)->finalize (obj);
}
static void
nautilus_navigation_state_dispose (GObject *obj)
{
NautilusNavigationState *self = NAUTILUS_NAVIGATION_STATE (obj);
clear_bindings (self);
g_clear_object (&self->priv->slave);
g_clear_object (&self->priv->master);
if (self->priv->groups != NULL) {
g_list_free_full (self->priv->groups, g_object_unref);
self->priv->groups = NULL;
}
G_OBJECT_CLASS (nautilus_navigation_state_parent_class)->dispose (obj);
}
static void
nautilus_navigation_state_class_init (NautilusNavigationStateClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS (klass);
oclass->dispose = nautilus_navigation_state_dispose;
oclass->finalize = nautilus_navigation_state_finalize;
oclass->set_property = nautilus_navigation_state_set_property;
properties[PROP_SLAVE] =
g_param_spec_object ("slave",
"The slave GtkActionGroup",
"The GtkActionGroup that will sync with the current master",
GTK_TYPE_ACTION_GROUP,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
G_PARAM_STATIC_STRINGS);
properties[PROP_MASTER] =
g_param_spec_object ("master",
"The master GtkActionGroup",
"The GtkActionGroup that will be used to sync the slave",
GTK_TYPE_ACTION_GROUP,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
properties[PROP_ACTION_NAMES] =
g_param_spec_boxed ("action-names",
"The action names to sync",
"The action names to sync",
G_TYPE_STRV,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
g_type_class_add_private (klass, sizeof (NautilusNavigationStateDetails));
}
NautilusNavigationState *
nautilus_navigation_state_new (GtkActionGroup *slave,
const gchar **action_names)
{
return g_object_new (NAUTILUS_TYPE_NAVIGATION_STATE,
"slave", slave,
"action-names", action_names,
NULL);
}
void
nautilus_navigation_state_set_master (NautilusNavigationState *self,
GtkActionGroup *master)
{
if (self->priv->master != master) {
clear_bindings (self);
g_clear_object (&self->priv->master);
self->priv->master = g_object_ref (master);
update_bindings (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MASTER]);
}
}
void
nautilus_navigation_state_add_group (NautilusNavigationState *self,
GtkActionGroup *group)
{
self->priv->groups = g_list_prepend (self->priv->groups, g_object_ref (group));
}
void
nautilus_navigation_state_sync_all (NautilusNavigationState *self)
{
GList *l;
gint length, idx;
const gchar *action_name;
GtkAction *action;
gboolean master_value;
GtkActionGroup *group;
length = g_strv_length (self->priv->action_names);
for (idx = 0; idx < length; idx++) {
action_name = self->priv->action_names[idx];
action = gtk_action_group_get_action (self->priv->master,
action_name);
master_value = gtk_action_get_sensitive (action);
for (l = self->priv->groups; l != NULL; l = l->next) {
group = l->data;
action = gtk_action_group_get_action (group, action_name);
gtk_action_set_sensitive (action, master_value);
}
}
}
GtkActionGroup *
nautilus_navigation_state_get_master (NautilusNavigationState *self)
{
return self->priv->master;
}
void
nautilus_navigation_state_set_boolean (NautilusNavigationState *self,
const gchar *action_name,
gboolean value)
{
GtkAction *action;
action = gtk_action_group_get_action (self->priv->master,
action_name);
if (action == NULL) {
return;
}
gtk_action_set_sensitive (action, value);
}
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* Nautilus - Nautilus navigation state
*
* Copyright (C) 2011 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Cosimo Cecchi <cosimoc@redhat.com>
*
*/
#ifndef __NAUTILUS_NAVIGATION_STATE_H__
#define __NAUTILUS_NAVIGATION_STATE_H__
#include <glib-object.h>
#include <gtk/gtk.h>
#define NAUTILUS_TYPE_NAVIGATION_STATE nautilus_navigation_state_get_type()
#define NAUTILUS_NAVIGATION_STATE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_NAVIGATION_STATE, NautilusNavigationState))
#define NAUTILUS_NAVIGATION_STATE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_NAVIGATION_STATE, NautilusNavigationStateClass))
#define NAUTILUS_IS_NAVIGATION_STATE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_NAVIGATION_STATE))
#define NAUTILUS_IS_NAVIGATION_STATE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_NAVIGATION_STATE))
#define NAUTILUS_NAVIGATION_STATE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_NAVIGATION_STATE, NautilusNavigationStateClass))
typedef struct _NautilusNavigationState NautilusNavigationState;
typedef struct _NautilusNavigationStateClass NautilusNavigationStateClass;
typedef struct _NautilusNavigationStateDetails NautilusNavigationStateDetails;
struct _NautilusNavigationState {
GObject parent;
NautilusNavigationStateDetails *priv;
};
struct _NautilusNavigationStateClass {
GObjectClass parent_class;
};
/* GObject */
GType nautilus_navigation_state_get_type (void);
NautilusNavigationState * nautilus_navigation_state_new (GtkActionGroup *slave,
const gchar **action_names);
void nautilus_navigation_state_add_group (NautilusNavigationState *state,
GtkActionGroup *group);
void nautilus_navigation_state_set_master (NautilusNavigationState *state,
GtkActionGroup *master);
GtkActionGroup * nautilus_navigation_state_get_master (NautilusNavigationState *self);
void nautilus_navigation_state_sync_all (NautilusNavigationState *state);
void nautilus_navigation_state_set_boolean (NautilusNavigationState *self,
const gchar *action_name,
gboolean value);
#endif /* __NAUTILUS_NAVIGATION_STATE_H__ */
......@@ -8,6 +8,8 @@
<accelerator action="TabsMoveLeft"/>
<accelerator action="TabsMoveRight"/>
<accelerator action="Up"/>
<accelerator action="View Grid"/>
<accelerator action="View List"/>
<accelerator action="ZoomInAccel"/>
<accelerator action="ZoomInAccel2"/>
<accelerator action="ZoomOutAccel"/>
......
......@@ -31,8 +31,10 @@
#include "nautilus-actions.h"
#include "nautilus-application.h"
#include "nautilus-canvas-view.h"
#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"
......@@ -437,6 +439,34 @@ action_tab_change_action_activate_callback (GtkAction *action,
}
}
static void
action_show_hide_search_callback (GtkAction *action,
NautilusWindow *window)
{
gboolean active;
active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
nautilus_window_set_search_visible (window, active);
}
static void
action_view_radio_changed (GtkRadioAction *action,
GtkRadioAction *current,
NautilusWindow *window)
{
const gchar *name;
NautilusWindowSlot *slot;
name = gtk_action_get_name (GTK_ACTION (current));
slot = nautilus_window_get_active_slot (window);
if (g_strcmp0 (name, NAUTILUS_ACTION_VIEW_LIST) == 0) {
nautilus_window_slot_set_content_view (slot, NAUTILUS_LIST_VIEW_ID);
} else if (g_strcmp0 (name, NAUTILUS_ACTION_VIEW_GRID) == 0) {
nautilus_window_slot_set_content_view (slot, NAUTILUS_CANVAS_VIEW_ID);
}
}
static const GtkActionEntry main_entries[] = {
/* name, stock id, label */ { "Help", NULL, N_("_Help") },
/* name, stock id */ { NAUTILUS_ACTION_CLOSE, GTK_STOCK_CLOSE,
......@@ -566,10 +596,17 @@ static const GtkToggleActionEntry main_toggle_entries[] = {
/* name, stock id */ { NAUTILUS_ACTION_SEARCH, "edit-find-symbolic",
/* label, accelerator */ N_("_Search for Files..."), "<control>f",
/* tooltip */ N_("Search documents and folders by name"),
NULL,
G_CALLBACK (action_show_hide_search_callback),
/* is_active */ FALSE },
};
static const GtkRadioActionEntry view_radio_entries[] = {
{ NAUTILUS_ACTION_VIEW_LIST, "view-list-symbolic", N_("List"),
"<control>1", N_("View items as a list"), 0 },
{ NAUTILUS_ACTION_VIEW_GRID, "view-grid-symbolic", N_("List"),
"<control>2", N_("View items as a grid of icons"), 1 }
};
static const gchar* app_actions[] = {
NAUTILUS_ACTION_NEW_WINDOW,
NAUTILUS_ACTION_CONNECT_TO_SERVER,
......@@ -584,88 +621,6 @@ static const gchar* app_actions[] = {
"Help"
};
GtkActionGroup *
nautilus_window_create_toolbar_action_group (NautilusWindow *window)
{
NautilusNavigationState *navigation_state;
GtkActionGroup *action_group;
GtkAction *action;
GSList *radio_group = NULL;
action_group = gtk_action_group_new ("ToolbarActions");
gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
action = g_object_new (NAUTILUS_TYPE_NAVIGATION_ACTION,
"name", NAUTILUS_ACTION_BACK,
"label", _("_Back"),
"icon-name", "go-previous-symbolic",
"tooltip", _("Go to the previous visited location"),
"arrow-tooltip", _("Back history"),
"window", window,
"direction", NAUTILUS_NAVIGATION_DIRECTION_BACK,
"sensitive", FALSE,
NULL);
g_signal_connect (action, "activate",
G_CALLBACK (action_back_callback), window);
gtk_action_group_add_action (action_group, action);
g_object_unref (action);
action = g_object_new (NAUTILUS_TYPE_NAVIGATION_ACTION,
"name", NAUTILUS_ACTION_FORWARD,
"label", _("_Forward"),
"icon-name", "go-next-symbolic",
"tooltip", _("Go to the next visited location"),
"arrow-tooltip", _("Forward history"),
"window", window,
"direction", NAUTILUS_NAVIGATION_DIRECTION_FORWARD,
"sensitive", FALSE,
NULL);
g_signal_connect (action, "activate",
G_CALLBACK (action_forward_callback), window);
gtk_action_group_add_action (action_group, action);
g_object_unref (action);
action = GTK_ACTION
(gtk_toggle_action_new (NAUTILUS_ACTION_SEARCH,
_("Search"),
_("Search documents and folders by name"),
NULL));
gtk_action_group_add_action (action_group, action);
gtk_action_set_icon_name (GTK_ACTION (action), "edit-find-symbolic");
g_object_unref (action);
action = GTK_ACTION
(gtk_radio_action_new (NAUTILUS_ACTION_VIEW_LIST,
_("List"),
_("View items as a list"),
NULL, 0));
gtk_action_group_add_action (action_group, action);
gtk_accel_map_add_entry ("<Nautilus-Window>/View List", GDK_KEY_1, GDK_CONTROL_MASK);
gtk_action_set_accel_path (GTK_ACTION (action), "<Nautilus-Window>/View List");
gtk_action_set_icon_name (GTK_ACTION (action), "view-list-symbolic");
radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
g_object_unref (action);
action = GTK_ACTION
(gtk_radio_action_new (NAUTILUS_ACTION_VIEW_GRID,
_("Icons"),
_("View items as a grid of icons"),
NULL, 0));
gtk_action_group_add_action (action_group, action);
gtk_action_set_icon_name (GTK_ACTION (action), "view-grid-symbolic");
gtk_accel_map_add_entry ("<Nautilus-Window>/View Grid", GDK_KEY_2, GDK_CONTROL_MASK);
gtk_action_set_accel_path (GTK_ACTION (action), "<Nautilus-Window>/View Grid");
gtk_radio_action_set_group (GTK_RADIO_ACTION (action), radio_group);
g_object_unref (action);
navigation_state = nautilus_window_get_navigation_state (window);
nautilus_navigation_state_add_group (navigation_state, action_group);
return action_group;
}
static void
window_menus_set_bindings (NautilusWindow *window)
{
......@@ -704,20 +659,9 @@ const GActionEntry win_entries[] = {
void
nautilus_window_initialize_actions (NautilusWindow *window)
{
GtkActionGroup *action_group;
const gchar *nav_state_actions[] = {
NAUTILUS_ACTION_BACK, NAUTILUS_ACTION_FORWARD,
NAUTILUS_ACTION_SEARCH, NULL
};
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
window);
action_group = nautilus_window_get_main_action_group (window);
window->details->nav_state = nautilus_navigation_state_new (action_group,
nav_state_actions);
window_menus_set_bindings (window);
}
......@@ -770,6 +714,10 @@ nautilus_window_initialize_menus (NautilusWindow *window)
gtk_action_group_add_toggle_actions (action_group,
main_toggle_entries, G_N_ELEMENTS (main_toggle_entries),
window);
gtk_action_group_add_radio_actions (action_group,
view_radio_entries, G_N_ELEMENTS (view_radio_entries),
-1, G_CALLBACK (action_view_radio_changed),
window);
nautilus_window_menus_set_visibility_for_app_menu (window);
window->details->app_menu_visibility_id =
......
......@@ -30,7 +30,6 @@
#include "nautilus-window.h"
#include "nautilus-window-slot.h"
#include "nautilus-navigation-state.h"
#include "nautilus-bookmark-list.h"
#include <libnautilus-private/nautilus-directory.h>
......@@ -62,7 +61,6 @@ struct NautilusWindowDetails
NautilusWindowSlot *active_slot;
GtkWidget *content_paned;
NautilusNavigationState *nav_state;
/* Side Pane */
int side_pane_width;
......@@ -73,7 +71,6 @@ struct NautilusWindowDetails
/* Toolbar */
GtkWidget *toolbar;
GtkActionGroup *toolbar_action_group;
gboolean temporary_navigation_bar;
/* focus widget before the location bar has been shown temporarily */
......@@ -119,8 +116,10 @@ void nautilus_window_sync_title (NautilusWindow *window,
void nautilus_window_sync_zoom_widgets (NautilusWindow *window);
void nautilus_window_sync_up_button (NautilusWindow *window);
void nautilus_window_set_search_visible (NautilusWindow *window,
gboolean visible);
/* window menus */
GtkActionGroup *nautilus_window_create_toolbar_action_group (NautilusWindow *window);
void nautilus_window_initialize_actions (NautilusWindow *window);
void nautilus_window_initialize_menus (NautilusWindow *window);
void nautilus_window_finalize_menus (NautilusWindow *window);
......
......@@ -133,9 +133,12 @@ query_editor_cancel_callback (NautilusQueryEditor *editor,
NautilusWindowSlot *slot)
{
GtkAction *search;
NautilusWindow *window;
GtkActionGroup *action_group;
search = gtk_action_group_get_action (slot->window->details->toolbar_action_group,
NAUTILUS_ACTION_SEARCH);
window = slot->window;
action_group = nautilus_window_get_main_action_group (window);
search = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_SEARCH);
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (search), FALSE);
}
......
......@@ -276,16 +276,15 @@ notebook_switch_page_cb (GtkNotebook *notebook,
return FALSE;
}
static void
action_show_hide_search_callback (GtkAction *action,
gpointer user_data)
void
nautilus_window_set_search_visible (NautilusWindow *window,
gboolean visible)
{
NautilusWindow *window = user_data;
NautilusWindowSlot *slot;
slot = window->details->active_slot;
if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
if (visible) {
remember_focus_widget (window);
nautilus_window_slot_set_query_editor_visible (slot, TRUE);
} else {
......@@ -693,7 +692,8 @@ toggle_toolbar_search_button (NautilusWindow *window,
{
GtkAction *action;
action = gtk_action_group_get_action (window->details->toolbar_action_group, NAUTILUS_ACTION_SEARCH);
action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window),
NAUTILUS_ACTION_SEARCH);
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
}
......@@ -727,7 +727,8 @@ void
nautilus_window_sync_location_widgets (NautilusWindow *window)
{
NautilusWindowSlot *slot, *active_slot;
NautilusNavigationState *nav_state;
GtkActionGroup *action_group;
GtkAction *action;
slot = window->details->active_slot;
......@@ -751,14 +752,13 @@ nautilus_window_sync_location_widgets (NautilusWindow *window)
/* Check if the back and forward buttons need enabling or disabling. */
active_slot = nautilus_window_get_active_slot (window);
nav_state = nautilus_window_get_navigation_state (window);
action_group = nautilus_window_get_main_action_group (window);
action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_BACK);
gtk_action_set_sensitive (action, active_slot->back_list != NULL);
nautilus_navigation_state_set_boolean (nav_state,
NAUTILUS_ACTION_BACK,
active_slot->back_list != NULL);
nautilus_navigation_state_set_boolean (nav_state,
NAUTILUS_ACTION_FORWARD,
active_slot->forward_list != NULL);
action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_FORWARD);
gtk_action_set_sensitive (action, active_slot->forward_list != NULL);