e-shell-window-private.c 15.2 KB
Newer Older
1
/*
2 3
 * e-shell-window-private.c
 *
4 5 6
 * 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.
7
 *
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 General Public License
 * for more details.
12
 *
13 14
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 16 17
 *
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
18 19 20
 *
 */

21 22 23 24
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

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

Matthew Barnes's avatar
Matthew Barnes committed
27 28 29
static void
shell_window_save_switcher_style_cb (GtkRadioAction *action,
                                     GtkRadioAction *current,
Matthew Barnes's avatar
Matthew Barnes committed
30
                                     EShellWindow *shell_window)
Matthew Barnes's avatar
Matthew Barnes committed
31
{
32
	GSettings *settings;
Matthew Barnes's avatar
Matthew Barnes committed
33 34 35
	GtkToolbarStyle style;
	const gchar *string;

36
	settings = g_settings_new ("org.gnome.evolution.shell");
37

Matthew Barnes's avatar
Matthew Barnes committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
	style = gtk_radio_action_get_current_value (action);

	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;
	}

59 60
	g_settings_set_string (settings, "buttons-style", string);
	g_object_unref (settings);
Matthew Barnes's avatar
Matthew Barnes committed
61 62 63
}

static void
Matthew Barnes's avatar
Matthew Barnes committed
64
shell_window_init_switcher_style (EShellWindow *shell_window)
Matthew Barnes's avatar
Matthew Barnes committed
65 66
{
	GtkAction *action;
67
	GSettings *settings;
Matthew Barnes's avatar
Matthew Barnes committed
68 69 70
	GtkToolbarStyle style;
	gchar *string;

71
	settings = g_settings_new ("org.gnome.evolution.shell");
72

Matthew Barnes's avatar
Matthew Barnes committed
73
	action = ACTION (SWITCHER_STYLE_ICONS);
74 75
	string = g_settings_get_string (settings, "buttons-style");
	g_object_unref (settings);
Matthew Barnes's avatar
Matthew Barnes committed
76 77 78 79 80 81 82 83 84 85 86 87 88

	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);
89 90

		g_free (string);
Matthew Barnes's avatar
Matthew Barnes committed
91 92 93 94
	}

	g_signal_connect (
		action, "changed",
Matthew Barnes's avatar
Matthew Barnes committed
95 96
		G_CALLBACK (shell_window_save_switcher_style_cb),
		shell_window);
Matthew Barnes's avatar
Matthew Barnes committed
97
}
98 99

static void
Matthew Barnes's avatar
Matthew Barnes committed
100
shell_window_menu_item_select_cb (EShellWindow *shell_window,
Matthew Barnes's avatar
Matthew Barnes committed
101
                                  GtkWidget *widget)
102 103
{
	GtkAction *action;
104
	GtkActivatable *activatable;
105
	GtkLabel *label;
Matthew Barnes's avatar
Matthew Barnes committed
106
	const gchar *tooltip;
107

108 109
	activatable = GTK_ACTIVATABLE (widget);
	action = gtk_activatable_get_related_action (activatable);
Matthew Barnes's avatar
Matthew Barnes committed
110
	tooltip = gtk_action_get_tooltip (action);
111 112 113 114

	if (tooltip == NULL)
		return;

Matthew Barnes's avatar
Matthew Barnes committed
115
	label = GTK_LABEL (shell_window->priv->tooltip_label);
116 117
	gtk_label_set_text (label, tooltip);

Matthew Barnes's avatar
Matthew Barnes committed
118 119
	gtk_widget_show (shell_window->priv->tooltip_label);
	gtk_widget_hide (shell_window->priv->status_notebook);
120 121 122
}

static void
Matthew Barnes's avatar
Matthew Barnes committed
123
shell_window_menu_item_deselect_cb (EShellWindow *shell_window)
124
{
Matthew Barnes's avatar
Matthew Barnes committed
125 126
	gtk_widget_hide (shell_window->priv->tooltip_label);
	gtk_widget_show (shell_window->priv->status_notebook);
127 128 129
}

static void
Matthew Barnes's avatar
Matthew Barnes committed
130
shell_window_connect_proxy_cb (EShellWindow *shell_window,
131 132 133 134 135 136 137 138
                               GtkAction *action,
                               GtkWidget *proxy)
{
	if (!GTK_IS_MENU_ITEM (proxy))
		return;

	g_signal_connect_swapped (
		proxy, "select",
Matthew Barnes's avatar
Matthew Barnes committed
139 140
		G_CALLBACK (shell_window_menu_item_select_cb),
		shell_window);
141 142 143

	g_signal_connect_swapped (
		proxy, "deselect",
Matthew Barnes's avatar
Matthew Barnes committed
144 145
		G_CALLBACK (shell_window_menu_item_deselect_cb),
		shell_window);
146 147
}

148 149 150 151 152
static GtkWidget *
shell_window_construct_menubar (EShellWindow *shell_window)
{
	EShellWindowClass *class;

153
	class = E_SHELL_WINDOW_GET_CLASS (shell_window);
154 155
	if (class->construct_menubar == NULL)
		return NULL;
156 157 158 159 160 161 162 163 164

	return class->construct_menubar (shell_window);
}

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

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

	return class->construct_toolbar (shell_window);
}

static GtkWidget *
shell_window_construct_sidebar (EShellWindow *shell_window)
174
{
175 176 177
	EShellWindowClass *class;

	class = E_SHELL_WINDOW_GET_CLASS (shell_window);
178 179
	if (class->construct_sidebar == NULL)
		return NULL;
180 181 182 183 184 185 186 187 188 189

	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);
190 191
	if (class->construct_content == NULL)
		return NULL;
192 193 194 195 196 197 198 199 200 201

	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);
202 203
	if (class->construct_taskbar == NULL)
		return NULL;
204 205

	return class->construct_taskbar (shell_window);
206 207 208
}

void
Matthew Barnes's avatar
Matthew Barnes committed
209
e_shell_window_private_init (EShellWindow *shell_window)
210
{
Matthew Barnes's avatar
Matthew Barnes committed
211
	EShellWindowPrivate *priv = shell_window->priv;
212
	GHashTable *loaded_views;
Matthew Barnes's avatar
Matthew Barnes committed
213
	GArray *signal_handler_ids;
214

215
	loaded_views = g_hash_table_new_full (
Matthew Barnes's avatar
Matthew Barnes committed
216 217
		g_str_hash, g_str_equal,
		(GDestroyNotify) g_free,
218 219
		(GDestroyNotify) g_object_unref);

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

Matthew Barnes's avatar
Matthew Barnes committed
222
	priv->ui_manager = gtk_ui_manager_new ();
223
	priv->loaded_views = loaded_views;
Matthew Barnes's avatar
Matthew Barnes committed
224
	priv->signal_handler_ids = signal_handler_ids;
225

226 227 228 229
	/* XXX This kind of violates the shell window being unaware
	 *     of specific shell views, but we need a sane fallback. */
	priv->active_view = "mail";

230 231 232 233 234 235
	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");
236
	e_shell_window_add_action_group (shell_window, "new-window");
237 238 239 240 241
	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");

Matthew Barnes's avatar
Matthew Barnes committed
242 243
	gtk_window_set_title (GTK_WINDOW (shell_window), _("Evolution"));

244
	g_signal_connect_swapped (
245
		priv->ui_manager, "connect-proxy",
Matthew Barnes's avatar
Matthew Barnes committed
246
		G_CALLBACK (shell_window_connect_proxy_cb), shell_window);
247 248 249 250 251 252 253 254
}

void
e_shell_window_private_constructed (EShellWindow *shell_window)
{
	EShellWindowPrivate *priv = shell_window->priv;
	EShell *shell;
	GtkAction *action;
255
	GtkAccelGroup *accel_group;
256
	GtkUIManager *ui_manager;
257 258
	GtkBox *box;
	GtkPaned *paned;
259 260
	GtkWidget *widget;
	GtkWindow *window;
261
	guint merge_id;
262
	const gchar *id;
263
	GSettings *settings;
264

265 266 267 268
#ifndef G_OS_WIN32
	GtkActionGroup *action_group;
#endif

269 270 271 272
	window = GTK_WINDOW (shell_window);

	shell = e_shell_window_get_shell (shell_window);

273
	ui_manager = e_shell_window_get_ui_manager (shell_window);
274 275 276 277 278

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

	e_shell_window_actions_init (shell_window);

279
	accel_group = gtk_ui_manager_get_accel_group (ui_manager);
280 281
	gtk_window_add_accel_group (GTK_WINDOW (shell_window), accel_group);

282
	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
283 284
	priv->custom_rule_merge_id = merge_id;

285
	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
286 287
	priv->gal_view_merge_id = merge_id;

288 289
	/* Construct window widgets. */

290
	widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
Matthew Barnes's avatar
Matthew Barnes committed
291
	gtk_container_add (GTK_CONTAINER (shell_window), widget);
292
	gtk_widget_show (widget);
293

294
	box = GTK_BOX (widget);
295

296
	widget = shell_window_construct_menubar (shell_window);
297 298
	if (widget != NULL)
		gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
299

300
	widget = shell_window_construct_toolbar (shell_window);
301 302
	if (widget != NULL)
		gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
Matthew Barnes's avatar
Matthew Barnes committed
303

304
	widget = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
305
	gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
306 307 308
	priv->content_pane = g_object_ref (widget);
	gtk_widget_show (widget);

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

313
	paned = GTK_PANED (priv->content_pane);
314

315
	widget = shell_window_construct_sidebar (shell_window);
316 317
	if (widget != NULL)
		gtk_paned_pack1 (paned, widget, FALSE, FALSE);
318

319
	widget = shell_window_construct_content (shell_window);
320 321
	if (widget != NULL)
		gtk_paned_pack2 (paned, widget, TRUE, FALSE);
322

323 324 325 326
	/* 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);
327

328
	/* Bunch of chores to do when the active view changes. */
329

330
	e_signal_connect_notify (
331 332
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_icon), NULL);
Matthew Barnes's avatar
Matthew Barnes committed
333

334
	e_signal_connect_notify (
335 336
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_title), NULL);
337

338
	e_signal_connect_notify (
339 340
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_view_menu), NULL);
341

342
	e_signal_connect_notify (
343 344
		shell_window, "notify::active-view",
		G_CALLBACK (e_shell_window_update_search_menu), NULL);
345

346
#ifndef G_OS_WIN32
347 348
	/* Support lockdown. */

349 350
	settings = g_settings_new ("org.gnome.desktop.lockdown");

351 352
	action_group = ACTION_GROUP (LOCKDOWN_PRINTING);

353 354
	g_settings_bind (
		settings, "disable-printing",
355
		action_group, "visible",
356 357
		G_SETTINGS_BIND_GET |
		G_SETTINGS_BIND_INVERT_BOOLEAN);
358 359 360

	action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP);

361 362
	g_settings_bind (
		settings, "disable-print-setup",
363
		action_group, "visible",
364 365
		G_SETTINGS_BIND_GET |
		G_SETTINGS_BIND_INVERT_BOOLEAN);
366 367 368

	action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK);

369 370
	g_settings_bind (
		settings, "disable-save-to-disk",
371
		action_group, "visible",
372 373 374 375
		G_SETTINGS_BIND_GET |
		G_SETTINGS_BIND_INVERT_BOOLEAN);

	g_object_unref (settings);
376
#endif /* G_OS_WIN32 */
377

378 379 380 381
	/* Bind GObject properties to GObject properties. */

	action = ACTION (WORK_OFFLINE);

382
	g_object_bind_property (
383
		shell, "online",
384 385
		action, "visible",
		G_BINDING_SYNC_CREATE);
386

387
	g_object_bind_property (
388
		shell, "network-available",
389 390
		action, "sensitive",
		G_BINDING_SYNC_CREATE);
391

392 393
	action = ACTION (WORK_ONLINE);

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

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

405
	/* Bind GObject properties to GSettings keys. */
406

407
	settings = g_settings_new ("org.gnome.evolution.shell");
408

409 410 411 412
	/* Use G_SETTINGS_BIND_GET_NO_CHANGES so shell windows
	 * are initialized to the most recently used shell view,
	 * but still allows different windows to show different
	 * views at once. */
413 414 415
	g_settings_bind (
		settings, "default-component-id",
		shell_window, "active-view",
416 417
		G_SETTINGS_BIND_DEFAULT |
		G_SETTINGS_BIND_GET_NO_CHANGES);
Matthew Barnes's avatar
Matthew Barnes committed
418

419 420 421 422
	g_settings_bind (
		settings, "folder-bar-width",
		priv->content_pane, "position",
		G_SETTINGS_BIND_DEFAULT);
423

424 425 426 427
	g_settings_bind (
		settings, "sidebar-visible",
		shell_window, "sidebar-visible",
		G_SETTINGS_BIND_DEFAULT);
428

429 430 431 432
	g_settings_bind (
		settings, "statusbar-visible",
		shell_window, "taskbar-visible",
		G_SETTINGS_BIND_DEFAULT);
Matthew Barnes's avatar
Matthew Barnes committed
433

434 435 436 437
	g_settings_bind (
		settings, "buttons-visible",
		shell_window, "switcher-visible",
		G_SETTINGS_BIND_DEFAULT);
438

439 440 441 442
	g_settings_bind (
		settings, "toolbar-visible",
		shell_window, "toolbar-visible",
		G_SETTINGS_BIND_DEFAULT);
443

444 445 446 447 448 449 450 451 452 453 454 455
	/* 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 {
456 457 458 459
		gtk_window_set_default_size (window, 640, 480);
		e_restore_window (
			window, "/org/gnome/evolution/shell/window/",
			E_RESTORE_WINDOW_SIZE | E_RESTORE_WINDOW_POSITION);
460 461
	}

Matthew Barnes's avatar
Matthew Barnes committed
462
	shell_window_init_switcher_style (shell_window);
Matthew Barnes's avatar
Matthew Barnes committed
463 464

	id = "org.gnome.evolution.shell";
465 466
	e_plugin_ui_register_manager (ui_manager, id, shell_window);
	e_plugin_ui_enable_manager (ui_manager, id);
467

468
	gtk_application_add_window (GTK_APPLICATION (shell), window);
469 470

	g_object_unref (settings);
471 472 473
}

void
Matthew Barnes's avatar
Matthew Barnes committed
474
e_shell_window_private_dispose (EShellWindow *shell_window)
475
{
Matthew Barnes's avatar
Matthew Barnes committed
476
	EShellWindowPrivate *priv = shell_window->priv;
477

Matthew Barnes's avatar
Matthew Barnes committed
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
	/* 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;
	}

493 494 495 496 497 498
	if (priv->shell != NULL) {
		g_object_remove_weak_pointer (
			G_OBJECT (priv->shell), &priv->shell);
		priv->shell = NULL;
	}

Matthew Barnes's avatar
Matthew Barnes committed
499 500
	g_clear_object (&priv->focus_tracker);
	g_clear_object (&priv->ui_manager);
501

502 503
	g_hash_table_remove_all (priv->loaded_views);

Matthew Barnes's avatar
Matthew Barnes committed
504 505 506 507 508 509 510
	g_clear_object (&priv->alert_bar);
	g_clear_object (&priv->content_pane);
	g_clear_object (&priv->content_notebook);
	g_clear_object (&priv->sidebar_notebook);
	g_clear_object (&priv->switcher);
	g_clear_object (&priv->tooltip_label);
	g_clear_object (&priv->status_notebook);
511

512
	priv->destroyed = TRUE;
513 514 515
}

void
Matthew Barnes's avatar
Matthew Barnes committed
516
e_shell_window_private_finalize (EShellWindow *shell_window)
517
{
Matthew Barnes's avatar
Matthew Barnes committed
518
	EShellWindowPrivate *priv = shell_window->priv;
519

520
	g_hash_table_destroy (priv->loaded_views);
521 522

	g_free (priv->geometry);
523
}
524 525 526 527 528 529 530

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

531 532 533
	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
	g_return_if_fail (view_name != NULL);

534 535 536
	if (shell_window->priv->active_view == view_name)
		return;

537
	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
538

539 540
	shell_window->priv->active_view = view_name;
	g_object_notify (G_OBJECT (shell_window), "active-view");
541

Matthew Barnes's avatar
Matthew Barnes committed
542
	e_shell_view_update_actions (shell_view);
543 544 545 546 547 548 549 550
}

void
e_shell_window_update_icon (EShellWindow *shell_window)
{
	EShellView *shell_view;
	GtkAction *action;
	const gchar *view_name;
551 552 553
	gchar *icon_name = NULL;

	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
554

555
	view_name = e_shell_window_get_active_view (shell_window);
556
	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571

	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;

572 573
	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));

574
	view_name = e_shell_window_get_active_view (shell_window);
575
	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
576 577 578 579 580 581 582
	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);
}