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