Files
evolution/shell/e-shell-window-private.c
Matthew Barnes abc0e4c694 Introduce ESelectable and EFocusTracker.
EFocusTracker tracks the input focus within a window and helps keep
the sensitivity of "selectable" actions in the main menu up-to-date.
Selectable actions include Cut, Copy, Paste, Select All and Delete.

EFocusTracker has built-in support for widgets that implement the
GtkEditable interface such as GtkEntry and GtkTextView.  It also
supports custom widgets that implement the ESelectable interface,
which is a subset of GtkEditable and can apply to anything that
displays selectable content (esp. tree views and ETables).

This commit integrates EFocusTracker with EShellWindow, CompEditor,
EMsgComposer, and ESignatureManager.

It also bumps the GtkHTML requirement to 2.29.5 to utilize the new
GtkhtmlEditor:html constructor property.
2009-12-25 15:42:17 -05:00

556 lines
15 KiB
C

/*
* e-shell-window-private.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) version 3.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
#include "e-shell-window-private.h"
static void
shell_window_save_switcher_style_cb (GtkRadioAction *action,
GtkRadioAction *current,
EShellWindow *shell_window)
{
EShell *shell;
GConfClient *client;
GtkToolbarStyle style;
const gchar *key;
const gchar *string;
GError *error = NULL;
shell = e_shell_window_get_shell (shell_window);
client = e_shell_get_gconf_client (shell);
style = gtk_radio_action_get_current_value (action);
key = "/apps/evolution/shell/view_defaults/buttons_style";
switch (style) {
case GTK_TOOLBAR_ICONS:
string = "icons";
break;
case GTK_TOOLBAR_TEXT:
string = "text";
break;
case GTK_TOOLBAR_BOTH:
case GTK_TOOLBAR_BOTH_HORIZ:
string = "both";
break;
default:
string = "toolbar";
break;
}
if (!gconf_client_set_string (client, key, string, &error)) {
g_warning ("%s", error->message);
g_error_free (error);
}
}
static void
shell_window_init_switcher_style (EShellWindow *shell_window)
{
EShell *shell;
GtkAction *action;
GConfClient *client;
GtkToolbarStyle style;
const gchar *key;
gchar *string;
GError *error = NULL;
/* XXX GConfBridge doesn't let you convert between numeric properties
* and string keys, so we have to create the binding manually. */
shell = e_shell_window_get_shell (shell_window);
client = e_shell_get_gconf_client (shell);
action = ACTION (SWITCHER_STYLE_ICONS);
key = "/apps/evolution/shell/view_defaults/buttons_style";
string = gconf_client_get_string (client, key, &error);
if (string != NULL) {
if (strcmp (string, "icons") == 0)
style = GTK_TOOLBAR_ICONS;
else if (strcmp (string, "text") == 0)
style = GTK_TOOLBAR_TEXT;
else if (strcmp (string, "both") == 0)
style = GTK_TOOLBAR_BOTH_HORIZ;
else
style = -1;
gtk_radio_action_set_current_value (
GTK_RADIO_ACTION (action), style);
}
g_signal_connect (
action, "changed",
G_CALLBACK (shell_window_save_switcher_style_cb),
shell_window);
}
static void
shell_window_menu_item_select_cb (EShellWindow *shell_window,
GtkWidget *widget)
{
GtkAction *action;
GtkActivatable *activatable;
GtkLabel *label;
const gchar *tooltip;
activatable = GTK_ACTIVATABLE (widget);
action = gtk_activatable_get_related_action (activatable);
tooltip = gtk_action_get_tooltip (action);
if (tooltip == NULL)
return;
label = GTK_LABEL (shell_window->priv->tooltip_label);
gtk_label_set_text (label, tooltip);
gtk_widget_show (shell_window->priv->tooltip_label);
gtk_widget_hide (shell_window->priv->status_notebook);
}
static void
shell_window_menu_item_deselect_cb (EShellWindow *shell_window)
{
gtk_widget_hide (shell_window->priv->tooltip_label);
gtk_widget_show (shell_window->priv->status_notebook);
}
static void
shell_window_connect_proxy_cb (EShellWindow *shell_window,
GtkAction *action,
GtkWidget *proxy)
{
if (!GTK_IS_MENU_ITEM (proxy))
return;
g_signal_connect_swapped (
proxy, "select",
G_CALLBACK (shell_window_menu_item_select_cb),
shell_window);
g_signal_connect_swapped (
proxy, "deselect",
G_CALLBACK (shell_window_menu_item_deselect_cb),
shell_window);
}
static GtkWidget *
shell_window_construct_menubar (EShellWindow *shell_window)
{
EShellWindowClass *class;
class = E_SHELL_WINDOW_GET_CLASS (shell_window);
if (class->construct_menubar == NULL)
return NULL;
return class->construct_menubar (shell_window);
}
static GtkWidget *
shell_window_construct_toolbar (EShellWindow *shell_window)
{
EShellWindowClass *class;
class = E_SHELL_WINDOW_GET_CLASS (shell_window);
if (class->construct_toolbar == NULL)
return NULL;
return class->construct_toolbar (shell_window);
}
static GtkWidget *
shell_window_construct_sidebar (EShellWindow *shell_window)
{
EShellWindowClass *class;
class = E_SHELL_WINDOW_GET_CLASS (shell_window);
if (class->construct_sidebar == NULL)
return NULL;
return class->construct_sidebar (shell_window);
}
static GtkWidget *
shell_window_construct_content (EShellWindow *shell_window)
{
EShellWindowClass *class;
class = E_SHELL_WINDOW_GET_CLASS (shell_window);
if (class->construct_content == NULL)
return NULL;
return class->construct_content (shell_window);
}
static GtkWidget *
shell_window_construct_taskbar (EShellWindow *shell_window)
{
EShellWindowClass *class;
class = E_SHELL_WINDOW_GET_CLASS (shell_window);
if (class->construct_taskbar == NULL)
return NULL;
return class->construct_taskbar (shell_window);
}
void
e_shell_window_private_init (EShellWindow *shell_window)
{
EShellWindowPrivate *priv = shell_window->priv;
GHashTable *loaded_views;
GArray *signal_handler_ids;
GtkAccelGroup *accel_group;
guint merge_id;
loaded_views = g_hash_table_new_full (
g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
signal_handler_ids = g_array_new (FALSE, FALSE, sizeof (gulong));
priv->ui_manager = gtk_ui_manager_new ();
priv->loaded_views = loaded_views;
priv->active_view = "unknown";
priv->signal_handler_ids = signal_handler_ids;
e_shell_window_add_action_group (shell_window, "shell");
e_shell_window_add_action_group (shell_window, "gal-view");
e_shell_window_add_action_group (shell_window, "new-item");
e_shell_window_add_action_group (shell_window, "new-source");
e_shell_window_add_action_group (shell_window, "custom-rules");
e_shell_window_add_action_group (shell_window, "switcher");
e_shell_window_add_action_group (shell_window, "lockdown-application-handlers");
e_shell_window_add_action_group (shell_window, "lockdown-printing");
e_shell_window_add_action_group (shell_window, "lockdown-print-setup");
e_shell_window_add_action_group (shell_window, "lockdown-save-to-disk");
merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
priv->custom_rule_merge_id = merge_id;
merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
priv->gal_view_merge_id = merge_id;
gtk_window_set_title (GTK_WINDOW (shell_window), _("Evolution"));
e_shell_window_actions_init (shell_window);
accel_group = gtk_ui_manager_get_accel_group (priv->ui_manager);
gtk_window_add_accel_group (GTK_WINDOW (shell_window), accel_group);
g_signal_connect_swapped (
priv->ui_manager, "connect-proxy",
G_CALLBACK (shell_window_connect_proxy_cb), shell_window);
}
void
e_shell_window_private_constructed (EShellWindow *shell_window)
{
EShellWindowPrivate *priv = shell_window->priv;
EShellSettings *shell_settings;
EShell *shell;
GConfBridge *bridge;
GtkAction *action;
GtkActionGroup *action_group;
GtkUIManager *ui_manager;
GtkBox *box;
GtkPaned *paned;
GtkWidget *widget;
GtkWindow *window;
GObject *object;
const gchar *key;
const gchar *id;
window = GTK_WINDOW (shell_window);
shell = e_shell_window_get_shell (shell_window);
shell_settings = e_shell_get_shell_settings (shell);
e_shell_watch_window (shell, window);
/* Construct window widgets. */
widget = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (shell_window), widget);
gtk_widget_show (widget);
box = GTK_BOX (widget);
widget = shell_window_construct_menubar (shell_window);
if (widget != NULL)
gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
widget = shell_window_construct_toolbar (shell_window);
if (widget != NULL)
gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
widget = gtk_hpaned_new ();
gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
priv->content_pane = g_object_ref (widget);
gtk_widget_show (widget);
widget = shell_window_construct_taskbar (shell_window);
if (widget != NULL)
gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
paned = GTK_PANED (priv->content_pane);
widget = shell_window_construct_sidebar (shell_window);
if (widget != NULL)
gtk_paned_pack1 (paned, widget, FALSE, FALSE);
widget = shell_window_construct_content (shell_window);
if (widget != NULL)
gtk_paned_pack2 (paned, widget, TRUE, FALSE);
/* Create the switcher actions before we set the initial
* shell view, because the shell view relies on them for
* default settings during construction. */
e_shell_window_create_switcher_actions (shell_window);
/* Bunch of chores to do when the active view changes. */
g_signal_connect (
shell_window, "notify::active-view",
G_CALLBACK (e_shell_window_update_icon), NULL);
g_signal_connect (
shell_window, "notify::active-view",
G_CALLBACK (e_shell_window_update_title), NULL);
g_signal_connect (
shell_window, "notify::active-view",
G_CALLBACK (e_shell_window_update_view_menu), NULL);
g_signal_connect (
shell_window, "notify::active-view",
G_CALLBACK (e_shell_window_update_search_menu), NULL);
/* Support lockdown. */
action_group = ACTION_GROUP (LOCKDOWN_PRINTING);
e_binding_new_with_negation (
shell_settings, "disable-printing",
action_group, "visible");
action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP);
e_binding_new_with_negation (
shell_settings, "disable-print-setup",
action_group, "visible");
action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK);
e_binding_new_with_negation (
shell_settings, "disable-save-to-disk",
action_group, "visible");
/* Bind GObject properties to GObject properties. */
action = ACTION (SEND_RECEIVE);
e_binding_new (
shell, "online",
action, "sensitive");
action = ACTION (WORK_OFFLINE);
e_binding_new (
shell, "online",
action, "visible");
e_binding_new (
shell, "network-available",
action, "sensitive");
action = ACTION (WORK_ONLINE);
e_binding_new_with_negation (
shell, "online",
action, "visible");
e_binding_new (
shell, "network-available",
action, "sensitive");
/* Bind GObject properties to GConf keys. */
bridge = gconf_bridge_get ();
object = G_OBJECT (shell_window);
key = "/apps/evolution/shell/view_defaults/component_id";
gconf_bridge_bind_property (bridge, key, object, "active-view");
object = G_OBJECT (priv->content_pane);
key = "/apps/evolution/shell/view_defaults/folder_bar/width";
gconf_bridge_bind_property_delayed (bridge, key, object, "position");
object = G_OBJECT (shell_window);
key = "/apps/evolution/shell/view_defaults/sidebar_visible";
gconf_bridge_bind_property (bridge, key, object, "sidebar-visible");
object = G_OBJECT (shell_window);
key = "/apps/evolution/shell/view_defaults/statusbar_visible";
gconf_bridge_bind_property (bridge, key, object, "taskbar-visible");
object = G_OBJECT (shell_window);
key = "/apps/evolution/shell/view_defaults/buttons_visible";
gconf_bridge_bind_property (bridge, key, object, "switcher-visible");
object = G_OBJECT (shell_window);
key = "/apps/evolution/shell/view_defaults/toolbar_visible";
gconf_bridge_bind_property (bridge, key, object, "toolbar-visible");
/* Configure the initial size and position of the window by way
* of either a user-supplied geometry string or the last recorded
* values. Note that if a geometry string is applied, the window
* size and position are -not- recorded. */
if (priv->geometry != NULL) {
if (!gtk_window_parse_geometry (window, priv->geometry))
g_printerr (
"Failed to parse geometry '%s'\n",
priv->geometry);
g_free (priv->geometry);
priv->geometry = NULL;
} else {
key = "/apps/evolution/shell/view_defaults/window";
gconf_bridge_bind_window (bridge, key, window, TRUE, TRUE);
}
shell_window_init_switcher_style (shell_window);
id = "org.gnome.evolution.shell";
ui_manager = e_shell_window_get_ui_manager (shell_window);
e_plugin_ui_register_manager (ui_manager, id, shell_window);
e_plugin_ui_enable_manager (ui_manager, id);
}
void
e_shell_window_private_dispose (EShellWindow *shell_window)
{
EShellWindowPrivate *priv = shell_window->priv;
/* Need to disconnect handlers before we unref the shell. */
if (priv->signal_handler_ids != NULL) {
GArray *array = priv->signal_handler_ids;
gulong handler_id;
guint ii;
for (ii = 0; ii < array->len; ii++) {
handler_id = g_array_index (array, gulong, ii);
g_signal_handler_disconnect (priv->shell, handler_id);
}
g_array_free (array, TRUE);
priv->signal_handler_ids = NULL;
}
if (priv->shell != NULL) {
g_object_remove_weak_pointer (
G_OBJECT (priv->shell), &priv->shell);
priv->shell = NULL;
}
DISPOSE (priv->focus_tracker);
DISPOSE (priv->ui_manager);
g_hash_table_remove_all (priv->loaded_views);
DISPOSE (priv->content_pane);
DISPOSE (priv->content_notebook);
DISPOSE (priv->sidebar_notebook);
DISPOSE (priv->switcher);
DISPOSE (priv->tooltip_label);
DISPOSE (priv->status_notebook);
priv->destroyed = TRUE;
}
void
e_shell_window_private_finalize (EShellWindow *shell_window)
{
EShellWindowPrivate *priv = shell_window->priv;
g_hash_table_destroy (priv->loaded_views);
g_free (priv->geometry);
}
void
e_shell_window_switch_to_view (EShellWindow *shell_window,
const gchar *view_name)
{
EShellView *shell_view;
g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
g_return_if_fail (view_name != NULL);
shell_view = e_shell_window_get_shell_view (shell_window, view_name);
shell_window->priv->active_view = view_name;
g_object_notify (G_OBJECT (shell_window), "active-view");
e_shell_view_update_actions (shell_view);
}
void
e_shell_window_update_icon (EShellWindow *shell_window)
{
EShellView *shell_view;
GtkAction *action;
const gchar *view_name;
gchar *icon_name = NULL;
g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
view_name = e_shell_window_get_active_view (shell_window);
shell_view = e_shell_window_get_shell_view (shell_window, view_name);
action = e_shell_view_get_action (shell_view);
g_object_get (action, "icon-name", &icon_name, NULL);
gtk_window_set_icon_name (GTK_WINDOW (shell_window), icon_name);
g_free (icon_name);
}
void
e_shell_window_update_title (EShellWindow *shell_window)
{
EShellView *shell_view;
const gchar *view_title;
const gchar *view_name;
gchar *window_title;
g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
view_name = e_shell_window_get_active_view (shell_window);
shell_view = e_shell_window_get_shell_view (shell_window, view_name);
view_title = e_shell_view_get_title (shell_view);
/* Translators: This is used for the main window title. */
window_title = g_strdup_printf (_("%s - Evolution"), view_title);
gtk_window_set_title (GTK_WINDOW (shell_window), window_title);
g_free (window_title);
}