evolution-3.6.4/widgets/misc/e-attachment-paned.c

No issues found

  1 /*
  2  * e-attachment-paned.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * 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 #ifdef HAVE_CONFIG_H
 23 #include <config.h>
 24 #endif
 25 
 26 #include "e-attachment-paned.h"
 27 
 28 #include <glib/gi18n.h>
 29 
 30 #include "e-attachment-view.h"
 31 #include "e-attachment-store.h"
 32 #include "e-attachment-icon-view.h"
 33 #include "e-attachment-tree-view.h"
 34 
 35 #define E_ATTACHMENT_PANED_GET_PRIVATE(obj) \
 36 	(G_TYPE_INSTANCE_GET_PRIVATE \
 37 	((obj), E_TYPE_ATTACHMENT_PANED, EAttachmentPanedPrivate))
 38 
 39 #define NUM_VIEWS 2
 40 
 41 /* Initial height of the lower pane. */
 42 static gint initial_height = 150;
 43 
 44 struct _EAttachmentPanedPrivate {
 45 	GtkTreeModel *model;
 46 	GtkWidget *expander;
 47 	GtkWidget *notebook;
 48 	GtkWidget *combo_box;
 49 	GtkWidget *controls_container;
 50 	GtkWidget *icon_view;
 51 	GtkWidget *tree_view;
 52 	GtkWidget *show_hide_label;
 53 	GtkWidget *status_icon;
 54 	GtkWidget *status_label;
 55 	GtkWidget *content_area;
 56 
 57 	gint active_view;
 58 	gboolean expanded;
 59 	gboolean resize_toplevel;
 60 };
 61 
 62 enum {
 63 	PROP_0,
 64 	PROP_ACTIVE_VIEW,
 65 	PROP_DRAGGING,
 66 	PROP_EDITABLE,
 67 	PROP_EXPANDED,
 68 	PROP_RESIZE_TOPLEVEL
 69 };
 70 
 71 /* Forward Declarations */
 72 static void	e_attachment_paned_interface_init
 73 					(EAttachmentViewInterface *interface);
 74 
 75 G_DEFINE_TYPE_WITH_CODE (
 76 	EAttachmentPaned,
 77 	e_attachment_paned,
 78 	GTK_TYPE_VPANED,
 79 	G_IMPLEMENT_INTERFACE (
 80 		E_TYPE_ATTACHMENT_VIEW,
 81 		e_attachment_paned_interface_init))
 82 
 83 void
 84 e_attachment_paned_set_default_height (gint height)
 85 {
 86 	initial_height = height;
 87 }
 88 
 89 static void
 90 attachment_paned_notify_cb (EAttachmentPaned *paned,
 91                             GParamSpec *pspec,
 92                             GtkExpander *expander)
 93 {
 94 	GtkAllocation toplevel_allocation;
 95 	GtkWidget *toplevel;
 96 	GtkWidget *child;
 97 	GtkLabel *label;
 98 	const gchar *text;
 99 
100 	label = GTK_LABEL (paned->priv->show_hide_label);
101 
102 	/* Update the expander label. */
103 	if (gtk_expander_get_expanded (expander))
104 		text = _("Hide Attachment _Bar");
105 	else
106 		text = _("Show Attachment _Bar");
107 
108 	gtk_label_set_text_with_mnemonic (label, text);
109 
110 	/* Resize the top-level window if required conditions are met.
111 	 * This is based on gtk_expander_resize_toplevel(), but adapted
112 	 * to the fact our GtkExpander has no direct child widget. */
113 
114 	if (!e_attachment_paned_get_resize_toplevel (paned))
115 		return;
116 
117 	if (!gtk_widget_get_realized (GTK_WIDGET (paned)))
118 		return;
119 
120 	child = gtk_paned_get_child2 (GTK_PANED (paned));
121 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (paned));
122 
123 	if (toplevel == NULL)
124 		return;
125 
126 	if (!gtk_widget_get_realized (GTK_WIDGET (toplevel)))
127 		return;
128 
129 	gtk_widget_get_allocation (toplevel, &toplevel_allocation);
130 
131 	if (gtk_expander_get_expanded (expander)) {
132 		GtkRequisition child_requisition;
133 
134 		gtk_widget_get_preferred_size (
135 			child, &child_requisition, NULL);
136 
137 		toplevel_allocation.height += child_requisition.height;
138 	} else {
139 		GtkAllocation child_allocation;
140 
141 		gtk_widget_get_allocation (child, &child_allocation);
142 
143 		toplevel_allocation.height -= child_allocation.height;
144 	}
145 
146 	gtk_window_resize (
147 		GTK_WINDOW (toplevel),
148 		toplevel_allocation.width,
149 		toplevel_allocation.height);
150 }
151 
152 static void
153 attachment_paned_update_status (EAttachmentPaned *paned)
154 {
155 	EAttachmentView *view;
156 	EAttachmentStore *store;
157 	GtkExpander *expander;
158 	GtkLabel *label;
159 	guint num_attachments;
160 	guint64 total_size;
161 	gchar *display_size;
162 	gchar *markup;
163 
164 	view = E_ATTACHMENT_VIEW (paned);
165 	store = e_attachment_view_get_store (view);
166 	expander = GTK_EXPANDER (paned->priv->expander);
167 	label = GTK_LABEL (paned->priv->status_label);
168 
169 	num_attachments = e_attachment_store_get_num_attachments (store);
170 	total_size = e_attachment_store_get_total_size (store);
171 	display_size = g_format_size_for_display (total_size);
172 
173 	if (total_size > 0)
174 		markup = g_strdup_printf (
175 			"<b>%d</b> %s (%s)", num_attachments, ngettext (
176 			"Attachment", "Attachments", num_attachments),
177 			display_size);
178 	else
179 		markup = g_strdup_printf (
180 			"<b>%d</b> %s", num_attachments, ngettext (
181 			"Attachment", "Attachments", num_attachments));
182 	gtk_label_set_markup (label, markup);
183 	g_free (markup);
184 
185 	g_free (display_size);
186 
187 	if (num_attachments > 0) {
188 		gtk_widget_show (paned->priv->status_icon);
189 		gtk_widget_show (paned->priv->status_label);
190 		gtk_expander_set_expanded (expander, TRUE);
191 	} else {
192 		gtk_widget_hide (paned->priv->status_icon);
193 		gtk_widget_hide (paned->priv->status_label);
194 		gtk_expander_set_expanded (expander, FALSE);
195 	}
196 }
197 
198 static void
199 attachment_paned_set_property (GObject *object,
200                                guint property_id,
201                                const GValue *value,
202                                GParamSpec *pspec)
203 {
204 	switch (property_id) {
205 		case PROP_ACTIVE_VIEW:
206 			e_attachment_paned_set_active_view (
207 				E_ATTACHMENT_PANED (object),
208 				g_value_get_int (value));
209 			return;
210 
211 		case PROP_DRAGGING:
212 			e_attachment_view_set_dragging (
213 				E_ATTACHMENT_VIEW (object),
214 				g_value_get_boolean (value));
215 			return;
216 
217 		case PROP_EDITABLE:
218 			e_attachment_view_set_editable (
219 				E_ATTACHMENT_VIEW (object),
220 				g_value_get_boolean (value));
221 			return;
222 
223 		case PROP_EXPANDED:
224 			e_attachment_paned_set_expanded (
225 				E_ATTACHMENT_PANED (object),
226 				g_value_get_boolean (value));
227 			return;
228 
229 		case PROP_RESIZE_TOPLEVEL:
230 			e_attachment_paned_set_resize_toplevel (
231 				E_ATTACHMENT_PANED (object),
232 				g_value_get_boolean (value));
233 			return;
234 	}
235 
236 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
237 }
238 
239 static void
240 attachment_paned_get_property (GObject *object,
241                                guint property_id,
242                                GValue *value,
243                                GParamSpec *pspec)
244 {
245 	switch (property_id) {
246 		case PROP_ACTIVE_VIEW:
247 			g_value_set_int (
248 				value,
249 				e_attachment_paned_get_active_view (
250 				E_ATTACHMENT_PANED (object)));
251 			return;
252 
253 		case PROP_DRAGGING:
254 			g_value_set_boolean (
255 				value,
256 				e_attachment_view_get_dragging (
257 				E_ATTACHMENT_VIEW (object)));
258 			return;
259 
260 		case PROP_EDITABLE:
261 			g_value_set_boolean (
262 				value,
263 				e_attachment_view_get_editable (
264 				E_ATTACHMENT_VIEW (object)));
265 			return;
266 
267 		case PROP_EXPANDED:
268 			g_value_set_boolean (
269 				value,
270 				e_attachment_paned_get_expanded (
271 				E_ATTACHMENT_PANED (object)));
272 			return;
273 
274 		case PROP_RESIZE_TOPLEVEL:
275 			g_value_set_boolean (
276 				value,
277 				e_attachment_paned_get_resize_toplevel (
278 				E_ATTACHMENT_PANED (object)));
279 			return;
280 	}
281 
282 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
283 }
284 
285 static void
286 attachment_paned_dispose (GObject *object)
287 {
288 	EAttachmentPanedPrivate *priv;
289 
290 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (object);
291 
292 	if (priv->model != NULL) {
293 		e_attachment_store_remove_all (E_ATTACHMENT_STORE (priv->model));
294 		g_object_unref (priv->model);
295 		priv->model = NULL;
296 	}
297 
298 	if (priv->expander != NULL) {
299 		g_object_unref (priv->expander);
300 		priv->expander = NULL;
301 	}
302 
303 	if (priv->notebook != NULL) {
304 		g_object_unref (priv->notebook);
305 		priv->notebook = NULL;
306 	}
307 
308 	if (priv->combo_box != NULL) {
309 		g_object_unref (priv->combo_box);
310 		priv->combo_box = NULL;
311 	}
312 
313 	if (priv->icon_view != NULL) {
314 		g_object_unref (priv->icon_view);
315 		priv->icon_view = NULL;
316 	}
317 
318 	if (priv->tree_view != NULL) {
319 		g_object_unref (priv->tree_view);
320 		priv->tree_view = NULL;
321 	}
322 
323 	if (priv->show_hide_label != NULL) {
324 		g_object_unref (priv->show_hide_label);
325 		priv->show_hide_label = NULL;
326 	}
327 
328 	if (priv->status_icon != NULL) {
329 		g_object_unref (priv->status_icon);
330 		priv->status_icon = NULL;
331 	}
332 
333 	if (priv->status_label != NULL) {
334 		g_object_unref (priv->status_label);
335 		priv->status_label = NULL;
336 	}
337 
338 	if (priv->content_area != NULL) {
339 		g_object_unref (priv->content_area);
340 		priv->content_area = NULL;
341 	}
342 
343 	/* Chain up to parent's dispose() method. */
344 	G_OBJECT_CLASS (e_attachment_paned_parent_class)->dispose (object);
345 }
346 
347 static void
348 attachment_paned_constructed (GObject *object)
349 {
350 	EAttachmentPanedPrivate *priv;
351 	GSettings *settings;
352 
353 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (object);
354 
355 	settings = g_settings_new ("org.gnome.evolution.shell");
356 
357 	/* Set up property-to-property bindings. */
358 
359 	g_object_bind_property (
360 		object, "active-view",
361 		priv->combo_box, "active",
362 		G_BINDING_BIDIRECTIONAL |
363 		G_BINDING_SYNC_CREATE);
364 
365 	g_object_bind_property (
366 		object, "active-view",
367 		priv->notebook, "page",
368 		G_BINDING_BIDIRECTIONAL |
369 		G_BINDING_SYNC_CREATE);
370 
371 	g_object_bind_property (
372 		object, "dragging",
373 		priv->icon_view, "dragging",
374 		G_BINDING_BIDIRECTIONAL |
375 		G_BINDING_SYNC_CREATE);
376 
377 	g_object_bind_property (
378 		object, "dragging",
379 		priv->tree_view, "dragging",
380 		G_BINDING_BIDIRECTIONAL |
381 		G_BINDING_SYNC_CREATE);
382 
383 	g_object_bind_property (
384 		object, "editable",
385 		priv->icon_view, "editable",
386 		G_BINDING_BIDIRECTIONAL |
387 		G_BINDING_SYNC_CREATE);
388 
389 	g_object_bind_property (
390 		object, "editable",
391 		priv->tree_view, "editable",
392 		G_BINDING_BIDIRECTIONAL |
393 		G_BINDING_SYNC_CREATE);
394 
395 	g_object_bind_property (
396 		object, "expanded",
397 		priv->expander, "expanded",
398 		G_BINDING_BIDIRECTIONAL |
399 		G_BINDING_SYNC_CREATE);
400 
401 	g_object_bind_property (
402 		object, "expanded",
403 		priv->combo_box, "sensitive",
404 		G_BINDING_BIDIRECTIONAL |
405 		G_BINDING_SYNC_CREATE);
406 
407 	g_object_bind_property (
408 		object, "expanded",
409 		priv->notebook, "visible",
410 		G_BINDING_BIDIRECTIONAL |
411 		G_BINDING_SYNC_CREATE);
412 
413 	/* Set up property-to-GSettings bindings. */
414 	g_settings_bind (
415 		settings, "attachment-view",
416 		object, "active-view",
417 		G_SETTINGS_BIND_DEFAULT);
418 
419 	g_object_unref (settings);
420 
421 	/* Chain up to parent's constructed() method. */
422 	G_OBJECT_CLASS (e_attachment_paned_parent_class)->constructed (object);
423 }
424 
425 static EAttachmentViewPrivate *
426 attachment_paned_get_private (EAttachmentView *view)
427 {
428 	EAttachmentPanedPrivate *priv;
429 
430 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
431 	view = E_ATTACHMENT_VIEW (priv->icon_view);
432 
433 	return e_attachment_view_get_private (view);
434 }
435 
436 static EAttachmentStore *
437 attachment_paned_get_store (EAttachmentView *view)
438 {
439 	EAttachmentPanedPrivate *priv;
440 
441 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
442 	view = E_ATTACHMENT_VIEW (priv->icon_view);
443 
444 	return e_attachment_view_get_store (view);
445 }
446 
447 static GtkTreePath *
448 attachment_paned_get_path_at_pos (EAttachmentView *view,
449                                   gint x,
450                                   gint y)
451 {
452 	EAttachmentPanedPrivate *priv;
453 
454 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
455 	view = E_ATTACHMENT_VIEW (priv->icon_view);
456 
457 	return e_attachment_view_get_path_at_pos (view, x, y);
458 }
459 
460 static GList *
461 attachment_paned_get_selected_paths (EAttachmentView *view)
462 {
463 	EAttachmentPanedPrivate *priv;
464 
465 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
466 	view = E_ATTACHMENT_VIEW (priv->icon_view);
467 
468 	return e_attachment_view_get_selected_paths (view);
469 }
470 
471 static gboolean
472 attachment_paned_path_is_selected (EAttachmentView *view,
473                                    GtkTreePath *path)
474 {
475 	EAttachmentPanedPrivate *priv;
476 
477 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
478 	view = E_ATTACHMENT_VIEW (priv->icon_view);
479 
480 	return e_attachment_view_path_is_selected (view, path);
481 }
482 
483 static void
484 attachment_paned_select_path (EAttachmentView *view,
485                               GtkTreePath *path)
486 {
487 	EAttachmentPanedPrivate *priv;
488 
489 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
490 	view = E_ATTACHMENT_VIEW (priv->icon_view);
491 
492 	e_attachment_view_select_path (view, path);
493 }
494 
495 static void
496 attachment_paned_unselect_path (EAttachmentView *view,
497                                 GtkTreePath *path)
498 {
499 	EAttachmentPanedPrivate *priv;
500 
501 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
502 	view = E_ATTACHMENT_VIEW (priv->icon_view);
503 
504 	e_attachment_view_unselect_path (view, path);
505 }
506 
507 static void
508 attachment_paned_select_all (EAttachmentView *view)
509 {
510 	EAttachmentPanedPrivate *priv;
511 
512 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
513 	view = E_ATTACHMENT_VIEW (priv->icon_view);
514 
515 	e_attachment_view_select_all (view);
516 }
517 
518 static void
519 attachment_paned_unselect_all (EAttachmentView *view)
520 {
521 	EAttachmentPanedPrivate *priv;
522 
523 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
524 	view = E_ATTACHMENT_VIEW (priv->icon_view);
525 
526 	e_attachment_view_unselect_all (view);
527 }
528 
529 static void
530 attachment_paned_update_actions (EAttachmentView *view)
531 {
532 	EAttachmentPanedPrivate *priv;
533 
534 	priv = E_ATTACHMENT_PANED_GET_PRIVATE (view);
535 	view = E_ATTACHMENT_VIEW (priv->icon_view);
536 
537 	e_attachment_view_update_actions (view);
538 }
539 
540 static void
541 e_attachment_paned_class_init (EAttachmentPanedClass *class)
542 {
543 	GObjectClass *object_class;
544 
545 	g_type_class_add_private (class, sizeof (EAttachmentPanedPrivate));
546 
547 	object_class = G_OBJECT_CLASS (class);
548 	object_class->set_property = attachment_paned_set_property;
549 	object_class->get_property = attachment_paned_get_property;
550 	object_class->dispose = attachment_paned_dispose;
551 	object_class->constructed = attachment_paned_constructed;
552 
553 	g_object_class_install_property (
554 		object_class,
555 		PROP_ACTIVE_VIEW,
556 		g_param_spec_int (
557 			"active-view",
558 			"Active View",
559 			NULL,
560 			0,
561 			NUM_VIEWS,
562 			0,
563 			G_PARAM_READWRITE |
564 			G_PARAM_CONSTRUCT |
565 			G_PARAM_STATIC_STRINGS));
566 
567 	g_object_class_override_property (
568 		object_class, PROP_DRAGGING, "dragging");
569 
570 	g_object_class_override_property (
571 		object_class, PROP_EDITABLE, "editable");
572 
573 	g_object_class_install_property (
574 		object_class,
575 		PROP_EXPANDED,
576 		g_param_spec_boolean (
577 			"expanded",
578 			"Expanded",
579 			NULL,
580 			FALSE,
581 			G_PARAM_READWRITE |
582 			G_PARAM_CONSTRUCT |
583 			G_PARAM_STATIC_STRINGS));
584 
585 	g_object_class_install_property (
586 		object_class,
587 		PROP_RESIZE_TOPLEVEL,
588 		g_param_spec_boolean (
589 			"resize-toplevel",
590 			"Resize-Toplevel",
591 			NULL,
592 			FALSE,
593 			G_PARAM_READWRITE |
594 			G_PARAM_CONSTRUCT |
595 			G_PARAM_STATIC_STRINGS));
596 }
597 
598 static void
599 e_attachment_paned_init (EAttachmentPaned *paned)
600 {
601 	EAttachmentView *view;
602 	GtkSizeGroup *size_group;
603 	GtkWidget *container;
604 	GtkWidget *widget;
605 	GtkAction *action;
606 
607 	paned->priv = E_ATTACHMENT_PANED_GET_PRIVATE (paned);
608 	paned->priv->model = e_attachment_store_new ();
609 
610 	/* Keep the expander label and combo box the same height. */
611 	size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
612 
613 	/* Construct the Attachment Views */
614 
615 	container = GTK_WIDGET (paned);
616 
617 	widget = gtk_notebook_new ();
618 	gtk_widget_set_size_request (widget, -1, initial_height);
619 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
620 	gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE);
621 	gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE);
622 	paned->priv->notebook = g_object_ref (widget);
623 	gtk_widget_hide (widget);
624 
625 	container = paned->priv->notebook;
626 
627 	widget = gtk_scrolled_window_new (NULL, NULL);
628 	gtk_scrolled_window_set_policy (
629 		GTK_SCROLLED_WINDOW (widget),
630 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
631 	gtk_scrolled_window_set_shadow_type (
632 		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
633 	gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL);
634 	gtk_widget_show (widget);
635 
636 	container = widget;
637 
638 	widget = e_attachment_icon_view_new ();
639 	gtk_widget_set_can_focus (widget, TRUE);
640 	gtk_icon_view_set_model (GTK_ICON_VIEW (widget), paned->priv->model);
641 	gtk_container_add (GTK_CONTAINER (container), widget);
642 	paned->priv->icon_view = g_object_ref (widget);
643 	gtk_widget_show (widget);
644 
645 	container = paned->priv->notebook;
646 
647 	widget = gtk_scrolled_window_new (NULL, NULL);
648 	gtk_scrolled_window_set_policy (
649 		GTK_SCROLLED_WINDOW (widget),
650 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
651 	gtk_scrolled_window_set_shadow_type (
652 		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
653 	gtk_notebook_append_page (GTK_NOTEBOOK (container), widget, NULL);
654 	gtk_widget_show (widget);
655 
656 	container = widget;
657 
658 	widget = e_attachment_tree_view_new ();
659 	gtk_widget_set_can_focus (widget, TRUE);
660 	gtk_tree_view_set_model (GTK_TREE_VIEW (widget), paned->priv->model);
661 	gtk_container_add (GTK_CONTAINER (container), widget);
662 	paned->priv->tree_view = g_object_ref (widget);
663 	gtk_widget_show (widget);
664 
665 	/* Construct the Controls */
666 
667 	container = GTK_WIDGET (paned);
668 
669 	widget = gtk_vbox_new (FALSE, 6);
670 	gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE);
671 	paned->priv->content_area = g_object_ref (widget);
672 	gtk_widget_show (widget);
673 
674 	container = widget;
675 
676 	widget = gtk_hbox_new (FALSE, 6);
677 	gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
678 	paned->priv->controls_container = widget;
679 	gtk_widget_show (widget);
680 
681 	container = widget;
682 
683 	widget = gtk_expander_new (NULL);
684 	gtk_expander_set_spacing (GTK_EXPANDER (widget), 0);
685 	gtk_expander_set_label_fill (GTK_EXPANDER (widget), TRUE);
686 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
687 	paned->priv->expander = g_object_ref (widget);
688 	gtk_widget_show (widget);
689 
690 	/* The "Add Attachment" button proxies the "add" action from
691 	 * one of the two attachment views.  Doesn't matter which. */
692 	widget = gtk_button_new ();
693 	view = E_ATTACHMENT_VIEW (paned->priv->icon_view);
694 	action = e_attachment_view_get_action (view, "add");
695 	gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ());
696 	gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action);
697 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
698 	gtk_widget_show (widget);
699 
700 	widget = gtk_combo_box_text_new ();
701 	gtk_size_group_add_widget (size_group, widget);
702 	gtk_combo_box_text_append_text (
703 		GTK_COMBO_BOX_TEXT (widget), _("Icon View"));
704 	gtk_combo_box_text_append_text (
705 		GTK_COMBO_BOX_TEXT (widget), _("List View"));
706 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
707 	paned->priv->combo_box = g_object_ref (widget);
708 	gtk_widget_show (widget);
709 
710 	container = paned->priv->expander;
711 
712 	widget = gtk_hbox_new (FALSE, 6);
713 	gtk_size_group_add_widget (size_group, widget);
714 	gtk_expander_set_label_widget (GTK_EXPANDER (container), widget);
715 	gtk_widget_show (widget);
716 
717 	container = widget;
718 
719 	widget = gtk_label_new_with_mnemonic (_("Show Attachment _Bar"));
720 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
721 	paned->priv->show_hide_label = g_object_ref (widget);
722 	gtk_widget_show (widget);
723 
724 	widget = gtk_alignment_new (0.5, 0.5, 0.0, 1.0);
725 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
726 	gtk_widget_show (widget);
727 
728 	container = widget;
729 
730 	widget = gtk_hbox_new (FALSE, 6);
731 	gtk_container_add (GTK_CONTAINER (container), widget);
732 	gtk_widget_show (widget);
733 
734 	container = widget;
735 
736 	widget = gtk_image_new_from_icon_name (
737 		"mail-attachment", GTK_ICON_SIZE_MENU);
738 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
739 	paned->priv->status_icon = g_object_ref (widget);
740 	gtk_widget_hide (widget);
741 
742 	widget = gtk_label_new (NULL);
743 	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
744 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
745 	paned->priv->status_label = g_object_ref (widget);
746 	gtk_widget_hide (widget);
747 
748 	g_signal_connect_swapped (
749 		paned->priv->expander, "notify::expanded",
750 		G_CALLBACK (attachment_paned_notify_cb), paned);
751 
752 	g_signal_connect_swapped (
753 		paned->priv->model, "notify::num-attachments",
754 		G_CALLBACK (attachment_paned_update_status), paned);
755 
756 	g_signal_connect_swapped (
757 		paned->priv->model, "notify::total-size",
758 		G_CALLBACK (attachment_paned_update_status), paned);
759 
760 	g_object_unref (size_group);
761 }
762 
763 static void
764 e_attachment_paned_interface_init (EAttachmentViewInterface *interface)
765 {
766 	interface->get_private = attachment_paned_get_private;
767 	interface->get_store = attachment_paned_get_store;
768 	interface->get_path_at_pos = attachment_paned_get_path_at_pos;
769 	interface->get_selected_paths = attachment_paned_get_selected_paths;
770 	interface->path_is_selected = attachment_paned_path_is_selected;
771 	interface->select_path = attachment_paned_select_path;
772 	interface->unselect_path = attachment_paned_unselect_path;
773 	interface->select_all = attachment_paned_select_all;
774 	interface->unselect_all = attachment_paned_unselect_all;
775 	interface->update_actions = attachment_paned_update_actions;
776 }
777 
778 GtkWidget *
779 e_attachment_paned_new (void)
780 {
781 	return g_object_new (E_TYPE_ATTACHMENT_PANED, NULL);
782 }
783 
784 GtkWidget *
785 e_attachment_paned_get_content_area (EAttachmentPaned *paned)
786 {
787 	g_return_val_if_fail (E_IS_ATTACHMENT_PANED (paned), NULL);
788 
789 	return paned->priv->content_area;
790 }
791 
792 gint
793 e_attachment_paned_get_active_view (EAttachmentPaned *paned)
794 {
795 	g_return_val_if_fail (E_IS_ATTACHMENT_PANED (paned), 0);
796 
797 	return paned->priv->active_view;
798 }
799 
800 void
801 e_attachment_paned_set_active_view (EAttachmentPaned *paned,
802                                     gint active_view)
803 {
804 	EAttachmentView *source;
805 	EAttachmentView *target;
806 
807 	g_return_if_fail (E_IS_ATTACHMENT_PANED (paned));
808 	g_return_if_fail (active_view >= 0 && active_view < NUM_VIEWS);
809 
810 	if (active_view == paned->priv->active_view)
811 		return;
812 
813 	paned->priv->active_view = active_view;
814 
815 	/* Synchronize the item selection of the view we're
816 	 * switching TO with the view we're switching FROM. */
817 	if (active_view == 0) {
818 		/* from tree view to icon view */
819 		source = E_ATTACHMENT_VIEW (paned->priv->tree_view);
820 		target = E_ATTACHMENT_VIEW (paned->priv->icon_view);
821 	} else {
822 		/* from icon view to tree view */
823 		source = E_ATTACHMENT_VIEW (paned->priv->icon_view);
824 		target = E_ATTACHMENT_VIEW (paned->priv->tree_view);
825 	}
826 
827 	e_attachment_view_sync_selection (source, target);
828 
829 	g_object_notify (G_OBJECT (paned), "active-view");
830 }
831 
832 gboolean
833 e_attachment_paned_get_expanded (EAttachmentPaned *paned)
834 {
835 	g_return_val_if_fail (E_IS_ATTACHMENT_PANED (paned), FALSE);
836 
837 	return paned->priv->expanded;
838 }
839 
840 void
841 e_attachment_paned_set_expanded (EAttachmentPaned *paned,
842                                  gboolean expanded)
843 {
844 	g_return_if_fail (E_IS_ATTACHMENT_PANED (paned));
845 
846 	if (paned->priv->expanded == expanded)
847 		return;
848 
849 	paned->priv->expanded = expanded;
850 
851 	g_object_notify (G_OBJECT (paned), "expanded");
852 }
853 
854 gboolean
855 e_attachment_paned_get_resize_toplevel (EAttachmentPaned *paned)
856 {
857 	g_return_val_if_fail (E_IS_ATTACHMENT_PANED (paned), FALSE);
858 
859 	return paned->priv->resize_toplevel;
860 }
861 
862 void
863 e_attachment_paned_set_resize_toplevel (EAttachmentPaned *paned,
864                                         gboolean resize_toplevel)
865 {
866 	g_return_if_fail (E_IS_ATTACHMENT_PANED (paned));
867 
868 	if (paned->priv->resize_toplevel == resize_toplevel)
869 		return;
870 
871 	paned->priv->resize_toplevel = resize_toplevel;
872 
873 	g_object_notify (G_OBJECT (paned), "resize-toplevel");
874 }
875 
876 void
877 e_attachment_paned_drag_data_received (EAttachmentPaned *paned,
878                                        GdkDragContext *context,
879                                        gint x,
880                                        gint y,
881                                        GtkSelectionData *selection,
882                                        guint info,
883                                        guint time)
884 {
885 	g_return_if_fail (E_IS_ATTACHMENT_PANED (paned));
886 
887 	/* XXX Dirty hack for forwarding drop events. */
888 	g_signal_emit_by_name (
889 		paned->priv->icon_view, "drag-data-received",
890 		context, x, y, selection, info, time);
891 }
892 
893 GtkWidget *
894 e_attachment_paned_get_controls_container (EAttachmentPaned *paned)
895 {
896 	return paned->priv->controls_container;
897 }
898 
899 GtkWidget *
900 e_attachment_paned_get_view_combo (EAttachmentPaned *paned)
901 {
902 	return paned->priv->combo_box;
903 }