e-shell-window-private.c 15.9 KB
Newer Older
1
/*
2 3 4
 * e-shell-window-private.c
 *
 * This program is free software; you can redistribute it and/or
5 6 7
 * 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.
8 9 10 11
 *
 * 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
12 13 14
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 17 18
 *
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 20 21 22 23
 *
 */

#include "e-shell-window-private.h"

Matthew Barnes's avatar
Matthew Barnes committed
24 25 26
static void
shell_window_save_switcher_style_cb (GtkRadioAction *action,
                                     GtkRadioAction *current,
Matthew Barnes's avatar
Matthew Barnes committed
27
                                     EShellWindow *shell_window)
Matthew Barnes's avatar
Matthew Barnes committed
28
{
29
	EShell *shell;
Matthew Barnes's avatar
Matthew Barnes committed
30 31 32 33 34 35
	GConfClient *client;
	GtkToolbarStyle style;
	const gchar *key;
	const gchar *string;
	GError *error = NULL;

36 37 38
	shell = e_shell_window_get_shell (shell_window);
	client = e_shell_get_gconf_client (shell);

Matthew Barnes's avatar
Matthew Barnes committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
	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
Matthew Barnes's avatar
Matthew Barnes committed
68
shell_window_init_switcher_style (EShellWindow *shell_window)
Matthew Barnes's avatar
Matthew Barnes committed
69
{
70
	EShell *shell;
Matthew Barnes's avatar
Matthew Barnes committed
71 72 73 74 75 76 77 78 79 80
	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. */

81 82 83
	shell = e_shell_window_get_shell (shell_window);
	client = e_shell_get_gconf_client (shell);

Matthew Barnes's avatar
Matthew Barnes committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
	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);
100 101

		g_free (string);
Matthew Barnes's avatar
Matthew Barnes committed
102 103 104 105
	}

	g_signal_connect (
		action, "changed",
Matthew Barnes's avatar
Matthew Barnes committed
106 107
		G_CALLBACK (shell_window_save_switcher_style_cb),
		shell_window);
Matthew Barnes's avatar
Matthew Barnes committed
108
}
109 110

static void
Matthew Barnes's avatar
Matthew Barnes committed
111
shell_window_menu_item_select_cb (EShellWindow *shell_window,
Matthew Barnes's avatar
Matthew Barnes committed
112
                                  GtkWidget *widget)
113 114
{
	GtkAction *action;
115
	GtkActivatable *activatable;
116
	GtkLabel *label;
Matthew Barnes's avatar
Matthew Barnes committed
117
	const gchar *tooltip;
118

119 120
	activatable = GTK_ACTIVATABLE (widget);
	action = gtk_activatable_get_related_action (activatable);
Matthew Barnes's avatar
Matthew Barnes committed
121
	tooltip = gtk_action_get_tooltip (action);
122 123 124 125

	if (tooltip == NULL)
		return;

Matthew Barnes's avatar
Matthew Barnes committed
126
	label = GTK_LABEL (shell_window->priv->tooltip_label);
127 128
	gtk_label_set_text (label, tooltip);

Matthew Barnes's avatar
Matthew Barnes committed
129 130
	gtk_widget_show (shell_window->priv->tooltip_label);
	gtk_widget_hide (shell_window->priv->status_notebook);
131 132 133
}

static void
Matthew Barnes's avatar
Matthew Barnes committed
134
shell_window_menu_item_deselect_cb (EShellWindow *shell_window)
135
{
Matthew Barnes's avatar
Matthew Barnes committed
136 137
	gtk_widget_hide (shell_window->priv->tooltip_label);
	gtk_widget_show (shell_window->priv->status_notebook);
138 139 140
}

static void
Matthew Barnes's avatar
Matthew Barnes committed
141
shell_window_connect_proxy_cb (EShellWindow *shell_window,
142 143 144 145 146 147 148 149
                               GtkAction *action,
                               GtkWidget *proxy)
{
	if (!GTK_IS_MENU_ITEM (proxy))
		return;

	g_signal_connect_swapped (
		proxy, "select",
Matthew Barnes's avatar
Matthew Barnes committed
150 151
		G_CALLBACK (shell_window_menu_item_select_cb),
		shell_window);
152 153 154

	g_signal_connect_swapped (
		proxy, "deselect",
Matthew Barnes's avatar
Matthew Barnes committed
155 156
		G_CALLBACK (shell_window_menu_item_deselect_cb),
		shell_window);
157 158
}

159 160 161 162 163
static GtkWidget *
shell_window_construct_menubar (EShellWindow *shell_window)
{
	EShellWindowClass *class;

164
	class = E_SHELL_WINDOW_GET_CLASS (shell_window);
165 166
	if (class->construct_menubar == NULL)
		return NULL;
167 168 169 170 171 172 173 174 175

	return class->construct_menubar (shell_window);
}

static GtkWidget *
shell_window_construct_toolbar (EShellWindow *shell_window)
{
	EShellWindowClass *class;

176
	class = E_SHELL_WINDOW_GET_CLASS (shell_window);
177 178
	if (class->construct_toolbar == NULL)
		return NULL;
179 180 181 182 183 184

	return class->construct_toolbar (shell_window);
}

static GtkWidget *
shell_window_construct_sidebar (EShellWindow *shell_window)
185
{
186 187 188
	EShellWindowClass *class;

	class = E_SHELL_WINDOW_GET_CLASS (shell_window);
189 190
	if (class->construct_sidebar == NULL)
		return NULL;
191 192 193 194 195 196 197 198 199 200

	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);
201 202
	if (class->construct_content == NULL)
		return NULL;
203 204 205 206 207 208 209 210 211 212

	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);
213 214
	if (class->construct_taskbar == NULL)
		return NULL;
215 216

	return class->construct_taskbar (shell_window);
217 218 219
}

void
Matthew Barnes's avatar
Matthew Barnes committed
220
e_shell_window_private_init (EShellWindow *shell_window)
221
{
Matthew Barnes's avatar
Matthew Barnes committed
222
	EShellWindowPrivate *priv = shell_window->priv;
223
	GHashTable *loaded_views;
Matthew Barnes's avatar
Matthew Barnes committed
224
	GArray *signal_handler_ids;
225

226
	loaded_views = g_hash_table_new_full (
Matthew Barnes's avatar
Matthew Barnes committed
227 228
		g_str_hash, g_str_equal,
		(GDestroyNotify) g_free,
229 230
		(GDestroyNotify) g_object_unref);

Matthew Barnes's avatar
Matthew Barnes committed
231 232
	signal_handler_ids = g_array_new (FALSE, FALSE, sizeof (gulong));

233
	priv->ui_manager = e_ui_manager_new ();
234
	priv->loaded_views = loaded_views;
Matthew Barnes's avatar
Matthew Barnes committed
235
	priv->signal_handler_ids = signal_handler_ids;
236

237 238 239 240
	/* XXX This kind of violates the shell window being unaware
	 *     of specific shell views, but we need a sane fallback. */
	priv->active_view = "mail";

241 242 243 244 245 246
	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");
247
	e_shell_window_add_action_group (shell_window, "new-window");
248 249 250 251 252
	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");

253 254
	gtk_window_set_title (GTK_WINDOW (shell_window), _("Evolution"));

255
	g_signal_connect_swapped (
256
		priv->ui_manager, "connect-proxy",
Matthew Barnes's avatar
Matthew Barnes committed
257
		G_CALLBACK (shell_window_connect_proxy_cb), shell_window);
258 259 260 261 262 263 264 265 266 267
}

void
e_shell_window_private_constructed (EShellWindow *shell_window)
{
	EShellWindowPrivate *priv = shell_window->priv;
	EShellSettings *shell_settings;
	EShell *shell;
	GConfBridge *bridge;
	GtkAction *action;
268
	GtkAccelGroup *accel_group;
269 270
	GtkActionGroup *action_group;
	GtkUIManager *ui_manager;
271 272
	GtkBox *box;
	GtkPaned *paned;
273 274 275
	GtkWidget *widget;
	GtkWindow *window;
	GObject *object;
276
	guint merge_id;
277 278 279 280 281 282 283 284
	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);

285 286
	ui_manager = e_shell_window_get_ui_manager (shell_window);
	e_shell_configure_ui_manager (shell, E_UI_MANAGER (ui_manager));
287 288 289 290 291

	/* Defer actions and menu merging until we have set express mode */

	e_shell_window_actions_init (shell_window);

292
	accel_group = gtk_ui_manager_get_accel_group (ui_manager);
293 294
	gtk_window_add_accel_group (GTK_WINDOW (shell_window), accel_group);

295
	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
296 297
	priv->custom_rule_merge_id = merge_id;

298
	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
299 300
	priv->gal_view_merge_id = merge_id;

301 302 303
	/* Construct window widgets. */

	widget = gtk_vbox_new (FALSE, 0);
Matthew Barnes's avatar
Matthew Barnes committed
304
	gtk_container_add (GTK_CONTAINER (shell_window), widget);
305
	gtk_widget_show (widget);
306

307
	box = GTK_BOX (widget);
308

309
	widget = shell_window_construct_menubar (shell_window);
310 311
	if (widget != NULL)
		gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
312

313
	widget = shell_window_construct_toolbar (shell_window);
314 315
	if (widget != NULL)
		gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
Matthew Barnes's avatar
Matthew Barnes committed
316

317
#if GTK_CHECK_VERSION(2,90,7)
318
	widget = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
319 320 321
#else
	widget = gtk_hpaned_new ();
#endif
322
	gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
323 324 325
	priv->content_pane = g_object_ref (widget);
	gtk_widget_show (widget);

326
	widget = shell_window_construct_taskbar (shell_window);
327 328
	if (widget != NULL)
		gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
329

330
	paned = GTK_PANED (priv->content_pane);
331

332
	widget = shell_window_construct_sidebar (shell_window);
333 334
	if (widget != NULL)
		gtk_paned_pack1 (paned, widget, FALSE, FALSE);
335

336
	widget = shell_window_construct_content (shell_window);
337 338
	if (widget != NULL)
		gtk_paned_pack2 (paned, widget, TRUE, FALSE);
339

340 341 342 343
	/* 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);
344

345
	/* Bunch of chores to do when the active view changes. */
346 347

	g_signal_connect (
348 349
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_icon), NULL);
Matthew Barnes's avatar
Matthew Barnes committed
350

351 352 353
	g_signal_connect (
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_title), NULL);
354

355 356 357
	g_signal_connect (
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_view_menu), NULL);
358

359 360 361
	g_signal_connect (
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_search_menu), NULL);
362

363
#ifndef G_OS_WIN32
364 365 366 367
	/* Support lockdown. */

	action_group = ACTION_GROUP (LOCKDOWN_PRINTING);

368
	g_object_bind_property (
369
		shell_settings, "disable-printing",
370 371 372
		action_group, "visible",
		G_BINDING_SYNC_CREATE |
		G_BINDING_INVERT_BOOLEAN);
373 374 375

	action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP);

376
	g_object_bind_property (
377
		shell_settings, "disable-print-setup",
378 379 380
		action_group, "visible",
		G_BINDING_SYNC_CREATE |
		G_BINDING_INVERT_BOOLEAN);
381 382 383

	action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK);

384
	g_object_bind_property (
385
		shell_settings, "disable-save-to-disk",
386 387 388
		action_group, "visible",
		G_BINDING_SYNC_CREATE |
		G_BINDING_INVERT_BOOLEAN);
389
#endif
390

391 392 393 394
	/* Bind GObject properties to GObject properties. */

	action = ACTION (WORK_OFFLINE);

395
	g_object_bind_property (
396
		shell, "online",
397 398
		action, "visible",
		G_BINDING_SYNC_CREATE);
399

400
	g_object_bind_property (
401
		shell, "network-available",
402 403
		action, "sensitive",
		G_BINDING_SYNC_CREATE);
404

405 406
	action = ACTION (WORK_ONLINE);

407
	g_object_bind_property (
408
		shell, "online",
409 410 411
		action, "visible",
		G_BINDING_SYNC_CREATE |
		G_BINDING_INVERT_BOOLEAN);
412

413
	g_object_bind_property (
414
		shell, "network-available",
415 416
		action, "sensitive",
		G_BINDING_SYNC_CREATE);
417

418 419 420 421
	/* Bind GObject properties to GConf keys. */

	bridge = gconf_bridge_get ();

Matthew Barnes's avatar
Matthew Barnes committed
422 423
	object = G_OBJECT (shell_window);
	key = "/apps/evolution/shell/view_defaults/component_id";
424
	gconf_bridge_bind_property (bridge, key, object, "active-view");
Matthew Barnes's avatar
Matthew Barnes committed
425

426 427 428 429
	object = G_OBJECT (priv->content_pane);
	key = "/apps/evolution/shell/view_defaults/folder_bar/width";
	gconf_bridge_bind_property_delayed (bridge, key, object, "position");

430
	object = G_OBJECT (shell_window);
431
	key = "/apps/evolution/shell/view_defaults/sidebar_visible";
432
	gconf_bridge_bind_property (bridge, key, object, "sidebar-visible");
433

434
	if (e_shell_get_express_mode (shell)) {
435 436 437 438 439
		const gchar *active_view;
		gboolean taskbar_visible;

		active_view = e_shell_window_get_active_view (shell_window);
		taskbar_visible = (g_strcmp0 (active_view, "mail") == 0);
440
		e_shell_window_set_switcher_visible (shell_window, FALSE);
441
		e_shell_window_set_taskbar_visible (shell_window, taskbar_visible);
442
	} else {
443 444 445 446
		object = G_OBJECT (shell_window);
		key = "/apps/evolution/shell/view_defaults/statusbar_visible";
		gconf_bridge_bind_property (bridge, key, object, "taskbar-visible");

447 448 449 450
		object = G_OBJECT (shell_window);
		key = "/apps/evolution/shell/view_defaults/buttons_visible";
		gconf_bridge_bind_property (bridge, key, object, "switcher-visible");
	}
451

452
	object = G_OBJECT (shell_window);
453
	key = "/apps/evolution/shell/view_defaults/toolbar_visible";
454
	gconf_bridge_bind_property (bridge, key, object, "toolbar-visible");
455

456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
	/* 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);
	}

Matthew Barnes's avatar
Matthew Barnes committed
472
	shell_window_init_switcher_style (shell_window);
473 474

	id = "org.gnome.evolution.shell";
475 476
	e_plugin_ui_register_manager (ui_manager, id, shell_window);
	e_plugin_ui_enable_manager (ui_manager, id);
477 478

	e_shell_watch_window (shell, window);
479 480 481
}

void
Matthew Barnes's avatar
Matthew Barnes committed
482
e_shell_window_private_dispose (EShellWindow *shell_window)
483
{
Matthew Barnes's avatar
Matthew Barnes committed
484
	EShellWindowPrivate *priv = shell_window->priv;
485

Matthew Barnes's avatar
Matthew Barnes committed
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
	/* 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;
	}

501 502 503 504 505 506
	if (priv->shell != NULL) {
		g_object_remove_weak_pointer (
			G_OBJECT (priv->shell), &priv->shell);
		priv->shell = NULL;
	}

507
	DISPOSE (priv->focus_tracker);
508
	DISPOSE (priv->ui_manager);
509

510 511
	g_hash_table_remove_all (priv->loaded_views);

512
	DISPOSE (priv->alert_bar);
513 514 515
	DISPOSE (priv->content_pane);
	DISPOSE (priv->content_notebook);
	DISPOSE (priv->sidebar_notebook);
516
	DISPOSE (priv->switcher);
517 518 519
	DISPOSE (priv->tooltip_label);
	DISPOSE (priv->status_notebook);

520
	priv->destroyed = TRUE;
521 522 523
}

void
Matthew Barnes's avatar
Matthew Barnes committed
524
e_shell_window_private_finalize (EShellWindow *shell_window)
525
{
Matthew Barnes's avatar
Matthew Barnes committed
526
	EShellWindowPrivate *priv = shell_window->priv;
527

528
	g_hash_table_destroy (priv->loaded_views);
529 530

	g_free (priv->geometry);
531
}
532 533 534 535 536 537 538

void
e_shell_window_switch_to_view (EShellWindow *shell_window,
                               const gchar *view_name)
{
	EShellView *shell_view;

539 540 541
	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
	g_return_if_fail (view_name != NULL);

542
	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
543

544 545
	shell_window->priv->active_view = view_name;
	g_object_notify (G_OBJECT (shell_window), "active-view");
546

Matthew Barnes's avatar
Matthew Barnes committed
547
	e_shell_view_update_actions (shell_view);
548 549 550 551 552 553 554 555
}

void
e_shell_window_update_icon (EShellWindow *shell_window)
{
	EShellView *shell_view;
	GtkAction *action;
	const gchar *view_name;
556 557 558
	gchar *icon_name = NULL;

	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
559

560
	view_name = e_shell_window_get_active_view (shell_window);
561
	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576

	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;

577 578
	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));

579
	view_name = e_shell_window_get_active_view (shell_window);
580
	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
581 582 583 584 585 586 587
	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);
}