1 /*
2 * e-attachment-bar.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-bar.h"
24
25 #include <glib/gi18n.h>
26
27 #include "e-attachment-store.h"
28 #include "e-attachment-icon-view.h"
29 #include "e-attachment-tree-view.h"
30 #include "e-misc-utils.h"
31
32 #define E_ATTACHMENT_BAR_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE \
34 ((obj), E_TYPE_ATTACHMENT_BAR, EAttachmentBarPrivate))
35
36 #define NUM_VIEWS 2
37
38 struct _EAttachmentBarPrivate {
39 GtkTreeModel *model;
40 GtkWidget *vbox;
41 GtkWidget *expander;
42 GtkWidget *combo_box;
43 GtkWidget *icon_view;
44 GtkWidget *tree_view;
45 GtkWidget *icon_frame;
46 GtkWidget *tree_frame;
47 GtkWidget *status_icon;
48 GtkWidget *status_label;
49 GtkWidget *save_all_button;
50 GtkWidget *save_one_button;
51 GtkWidget *icon_scrolled_window; /* not referenced */
52 GtkWidget *tree_scrolled_window; /* not referenced */
53
54 gint active_view;
55 guint expanded : 1;
56 };
57
58 enum {
59 PROP_0,
60 PROP_ACTIVE_VIEW,
61 PROP_DRAGGING,
62 PROP_EDITABLE,
63 PROP_EXPANDED,
64 PROP_STORE
65 };
66
67 /* Forward Declarations */
68 static void e_attachment_bar_interface_init
69 (EAttachmentViewInterface *iface);
70
G_DEFINE_TYPE_WITH_CODE(EAttachmentBar,e_attachment_bar,GTK_TYPE_BOX,G_IMPLEMENT_INTERFACE (E_TYPE_ATTACHMENT_VIEW,e_attachment_bar_interface_init))71 G_DEFINE_TYPE_WITH_CODE (
72 EAttachmentBar,
73 e_attachment_bar,
74 GTK_TYPE_BOX,
75 G_IMPLEMENT_INTERFACE (
76 E_TYPE_ATTACHMENT_VIEW,
77 e_attachment_bar_interface_init))
78
79 static void
80 attachment_bar_update_status (EAttachmentBar *bar)
81 {
82 EAttachmentStore *store;
83 GtkActivatable *activatable;
84 GtkAction *action;
85 GtkLabel *label;
86 gint num_attachments;
87 guint64 total_size;
88 gchar *display_size;
89 gchar *markup;
90
91 store = E_ATTACHMENT_STORE (bar->priv->model);
92 label = GTK_LABEL (bar->priv->status_label);
93
94 num_attachments = e_attachment_store_get_num_attachments (store);
95 total_size = e_attachment_store_get_total_size (store);
96 display_size = g_format_size (total_size);
97
98 if (total_size > 0)
99 markup = g_strdup_printf (
100 "<b>%d</b> %s (%s)", num_attachments, ngettext (
101 "Attachment", "Attachments", num_attachments),
102 display_size);
103 else
104 markup = g_strdup_printf (
105 "<b>%d</b> %s", num_attachments, ngettext (
106 "Attachment", "Attachments", num_attachments));
107 gtk_label_set_markup (label, markup);
108 g_free (markup);
109
110 activatable = GTK_ACTIVATABLE (bar->priv->save_all_button);
111 action = gtk_activatable_get_related_action (activatable);
112 gtk_action_set_visible (action, num_attachments > 1);
113
114 activatable = GTK_ACTIVATABLE (bar->priv->save_one_button);
115 action = gtk_activatable_get_related_action (activatable);
116 gtk_action_set_visible (action, (num_attachments == 1));
117
118 g_free (display_size);
119 }
120
121 static void
attachment_bar_notify_vadjustment_upper_cb(GObject * object,GParamSpec * param,gpointer user_data)122 attachment_bar_notify_vadjustment_upper_cb (GObject *object,
123 GParamSpec *param,
124 gpointer user_data)
125 {
126 EAttachmentBar *bar = user_data;
127 GtkAdjustment *adjustment;
128 gint max_upper, max_content_height = -2;
129 gint request_height = -1;
130
131 g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
132
133 adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (bar->priv->icon_scrolled_window));
134 max_upper = gtk_adjustment_get_upper (adjustment);
135
136 adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (bar->priv->tree_scrolled_window));
137 max_upper = MAX (max_upper, gtk_adjustment_get_upper (adjustment));
138
139 gtk_widget_style_get (GTK_WIDGET (bar), "max-content-height", &max_content_height, NULL);
140
141 if ((max_content_height >= 0 && max_content_height < 50) || max_content_height <= -2)
142 max_content_height = 50;
143
144 if (max_content_height == -1) {
145 request_height = max_upper;
146 } else if (max_content_height < max_upper) {
147 request_height = max_content_height;
148 } else {
149 request_height = max_upper;
150 }
151
152 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (bar->priv->icon_scrolled_window),
153 request_height);
154 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (bar->priv->tree_scrolled_window),
155 request_height);
156 }
157
158 static void
attachment_bar_set_store(EAttachmentBar * bar,EAttachmentStore * store)159 attachment_bar_set_store (EAttachmentBar *bar,
160 EAttachmentStore *store)
161 {
162 g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
163
164 bar->priv->model = GTK_TREE_MODEL (g_object_ref (store));
165
166 gtk_icon_view_set_model (
167 GTK_ICON_VIEW (bar->priv->icon_view),
168 bar->priv->model);
169 gtk_tree_view_set_model (
170 GTK_TREE_VIEW (bar->priv->tree_view),
171 bar->priv->model);
172
173 e_signal_connect_notify_object (
174 bar->priv->model, "notify::num-attachments",
175 G_CALLBACK (attachment_bar_update_status), bar,
176 G_CONNECT_SWAPPED);
177
178 e_signal_connect_notify_object (
179 bar->priv->model, "notify::total-size",
180 G_CALLBACK (attachment_bar_update_status), bar,
181 G_CONNECT_SWAPPED);
182
183 /* Initialize */
184 attachment_bar_update_status (bar);
185 }
186
187 static void
attachment_bar_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)188 attachment_bar_set_property (GObject *object,
189 guint property_id,
190 const GValue *value,
191 GParamSpec *pspec)
192 {
193 switch (property_id) {
194 case PROP_ACTIVE_VIEW:
195 e_attachment_bar_set_active_view (
196 E_ATTACHMENT_BAR (object),
197 g_value_get_int (value));
198 return;
199
200 case PROP_DRAGGING:
201 e_attachment_view_set_dragging (
202 E_ATTACHMENT_VIEW (object),
203 g_value_get_boolean (value));
204 return;
205
206 case PROP_EDITABLE:
207 e_attachment_view_set_editable (
208 E_ATTACHMENT_VIEW (object),
209 g_value_get_boolean (value));
210 return;
211
212 case PROP_EXPANDED:
213 e_attachment_bar_set_expanded (
214 E_ATTACHMENT_BAR (object),
215 g_value_get_boolean (value));
216 return;
217 case PROP_STORE:
218 attachment_bar_set_store (
219 E_ATTACHMENT_BAR (object),
220 g_value_get_object (value));
221 return;
222 }
223
224 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
225 }
226
227 static void
attachment_bar_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)228 attachment_bar_get_property (GObject *object,
229 guint property_id,
230 GValue *value,
231 GParamSpec *pspec)
232 {
233 switch (property_id) {
234 case PROP_ACTIVE_VIEW:
235 g_value_set_int (
236 value,
237 e_attachment_bar_get_active_view (
238 E_ATTACHMENT_BAR (object)));
239 return;
240
241 case PROP_DRAGGING:
242 g_value_set_boolean (
243 value,
244 e_attachment_view_get_dragging (
245 E_ATTACHMENT_VIEW (object)));
246 return;
247
248 case PROP_EDITABLE:
249 g_value_set_boolean (
250 value,
251 e_attachment_view_get_editable (
252 E_ATTACHMENT_VIEW (object)));
253 return;
254
255 case PROP_EXPANDED:
256 g_value_set_boolean (
257 value,
258 e_attachment_bar_get_expanded (
259 E_ATTACHMENT_BAR (object)));
260 return;
261 case PROP_STORE:
262 g_value_set_object (
263 value,
264 e_attachment_bar_get_store (
265 E_ATTACHMENT_BAR (object)));
266 }
267
268 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
269 }
270
271 static void
attachment_bar_dispose(GObject * object)272 attachment_bar_dispose (GObject *object)
273 {
274 EAttachmentBarPrivate *priv;
275
276 priv = E_ATTACHMENT_BAR_GET_PRIVATE (object);
277 g_clear_object (&priv->model);
278 g_clear_object (&priv->vbox);
279 g_clear_object (&priv->expander);
280 g_clear_object (&priv->combo_box);
281 g_clear_object (&priv->icon_view);
282 g_clear_object (&priv->tree_view);
283 g_clear_object (&priv->icon_frame);
284 g_clear_object (&priv->tree_frame);
285 g_clear_object (&priv->status_icon);
286 g_clear_object (&priv->status_label);
287 g_clear_object (&priv->save_all_button);
288 g_clear_object (&priv->save_one_button);
289
290 /* Chain up to parent's dispose() method. */
291 G_OBJECT_CLASS (e_attachment_bar_parent_class)->dispose (object);
292 }
293
294 static void
attachment_bar_constructed(GObject * object)295 attachment_bar_constructed (GObject *object)
296 {
297 EAttachmentBarPrivate *priv;
298 GSettings *settings;
299
300 priv = E_ATTACHMENT_BAR_GET_PRIVATE (object);
301
302 /* Set up property-to-property bindings. */
303
304 e_binding_bind_property (
305 object, "active-view",
306 priv->combo_box, "active",
307 G_BINDING_BIDIRECTIONAL |
308 G_BINDING_SYNC_CREATE);
309
310 e_binding_bind_property (
311 object, "dragging",
312 priv->icon_view, "dragging",
313 G_BINDING_BIDIRECTIONAL |
314 G_BINDING_SYNC_CREATE);
315
316 e_binding_bind_property (
317 object, "dragging",
318 priv->tree_view, "dragging",
319 G_BINDING_BIDIRECTIONAL |
320 G_BINDING_SYNC_CREATE);
321
322 e_binding_bind_property (
323 object, "editable",
324 priv->icon_view, "editable",
325 G_BINDING_BIDIRECTIONAL |
326 G_BINDING_SYNC_CREATE);
327
328 e_binding_bind_property (
329 object, "editable",
330 priv->tree_view, "editable",
331 G_BINDING_BIDIRECTIONAL |
332 G_BINDING_SYNC_CREATE);
333
334 e_binding_bind_property (
335 object, "expanded",
336 priv->expander, "expanded",
337 G_BINDING_BIDIRECTIONAL |
338 G_BINDING_SYNC_CREATE);
339
340 e_binding_bind_property (
341 object, "expanded",
342 priv->combo_box, "visible",
343 G_BINDING_BIDIRECTIONAL |
344 G_BINDING_SYNC_CREATE);
345
346 e_binding_bind_property (
347 object, "expanded",
348 priv->vbox, "visible",
349 G_BINDING_BIDIRECTIONAL |
350 G_BINDING_SYNC_CREATE);
351
352 /* Set up property-to-GSettings bindings. */
353 settings = e_util_ref_settings ("org.gnome.evolution.shell");
354 g_settings_bind (
355 settings, "attachment-view",
356 object, "active-view",
357 G_SETTINGS_BIND_DEFAULT);
358 g_object_unref (settings);
359
360 /* Chain up to parent's constructed() method. */
361 G_OBJECT_CLASS (e_attachment_bar_parent_class)->constructed (object);
362 }
363
364 static EAttachmentViewPrivate *
attachment_bar_get_private(EAttachmentView * view)365 attachment_bar_get_private (EAttachmentView *view)
366 {
367 EAttachmentBar *bar;
368
369 bar = E_ATTACHMENT_BAR (view);
370 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
371
372 return e_attachment_view_get_private (view);
373 }
374
375 static GtkTreePath *
attachment_bar_get_path_at_pos(EAttachmentView * view,gint x,gint y)376 attachment_bar_get_path_at_pos (EAttachmentView *view,
377 gint x,
378 gint y)
379 {
380 EAttachmentBar *bar;
381
382 bar = E_ATTACHMENT_BAR (view);
383 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
384
385 return e_attachment_view_get_path_at_pos (view, x, y);
386 }
387
388 static EAttachmentStore *
attachment_bar_get_store(EAttachmentView * view)389 attachment_bar_get_store (EAttachmentView *view)
390 {
391 return e_attachment_bar_get_store (E_ATTACHMENT_BAR (view));
392 }
393
394 static GList *
attachment_bar_get_selected_paths(EAttachmentView * view)395 attachment_bar_get_selected_paths (EAttachmentView *view)
396 {
397 EAttachmentBar *bar;
398
399 bar = E_ATTACHMENT_BAR (view);
400 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
401
402 return e_attachment_view_get_selected_paths (view);
403 }
404
405 static gboolean
attachment_bar_path_is_selected(EAttachmentView * view,GtkTreePath * path)406 attachment_bar_path_is_selected (EAttachmentView *view,
407 GtkTreePath *path)
408 {
409 EAttachmentBar *bar;
410
411 bar = E_ATTACHMENT_BAR (view);
412 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
413
414 return e_attachment_view_path_is_selected (view, path);
415 }
416
417 static void
attachment_bar_select_path(EAttachmentView * view,GtkTreePath * path)418 attachment_bar_select_path (EAttachmentView *view,
419 GtkTreePath *path)
420 {
421 EAttachmentBar *bar;
422
423 bar = E_ATTACHMENT_BAR (view);
424 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
425
426 e_attachment_view_select_path (view, path);
427 }
428
429 static void
attachment_bar_unselect_path(EAttachmentView * view,GtkTreePath * path)430 attachment_bar_unselect_path (EAttachmentView *view,
431 GtkTreePath *path)
432 {
433 EAttachmentBar *bar;
434
435 bar = E_ATTACHMENT_BAR (view);
436 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
437
438 e_attachment_view_unselect_path (view, path);
439 }
440
441 static void
attachment_bar_select_all(EAttachmentView * view)442 attachment_bar_select_all (EAttachmentView *view)
443 {
444 EAttachmentBar *bar;
445
446 bar = E_ATTACHMENT_BAR (view);
447 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
448
449 e_attachment_view_select_all (view);
450 }
451
452 static void
attachment_bar_unselect_all(EAttachmentView * view)453 attachment_bar_unselect_all (EAttachmentView *view)
454 {
455 EAttachmentBar *bar;
456
457 bar = E_ATTACHMENT_BAR (view);
458 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
459
460 e_attachment_view_unselect_all (view);
461 }
462
463 static void
attachment_bar_update_actions(EAttachmentView * view)464 attachment_bar_update_actions (EAttachmentView *view)
465 {
466 EAttachmentBar *bar;
467
468 bar = E_ATTACHMENT_BAR (view);
469 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
470
471 e_attachment_view_update_actions (view);
472 }
473
474 static gboolean
attachment_bar_button_press_event(GtkWidget * widget,GdkEventButton * event)475 attachment_bar_button_press_event (GtkWidget *widget,
476 GdkEventButton *event)
477 {
478 /* Chain up to parent's button_press_event() method. */
479 GTK_WIDGET_CLASS (e_attachment_bar_parent_class)->button_press_event (widget, event);
480
481 /* Never propagate the event to the parent */
482 return TRUE;
483 }
484
485 static gboolean
attachment_bar_button_release_event(GtkWidget * widget,GdkEventButton * event)486 attachment_bar_button_release_event (GtkWidget *widget,
487 GdkEventButton *event)
488 {
489 /* Chain up to parent's button_release_event() method. */
490 GTK_WIDGET_CLASS (e_attachment_bar_parent_class)->button_release_event (widget, event);
491
492 /* Never propagate the event to the parent */
493 return TRUE;
494 }
495
496 static gboolean
attachment_bar_motion_notify_event(GtkWidget * widget,GdkEventMotion * event)497 attachment_bar_motion_notify_event (GtkWidget *widget,
498 GdkEventMotion *event)
499 {
500 /* Chain up to parent's motion_notify_event() method. */
501 GTK_WIDGET_CLASS (e_attachment_bar_parent_class)->motion_notify_event (widget, event);
502
503 /* Never propagate the event to the parent */
504 return TRUE;
505 }
506
507 static void
e_attachment_bar_class_init(EAttachmentBarClass * class)508 e_attachment_bar_class_init (EAttachmentBarClass *class)
509 {
510 GObjectClass *object_class;
511 GtkWidgetClass *widget_class;
512
513 g_type_class_add_private (class, sizeof (EAttachmentBarPrivate));
514
515 object_class = G_OBJECT_CLASS (class);
516 object_class->set_property = attachment_bar_set_property;
517 object_class->get_property = attachment_bar_get_property;
518 object_class->dispose = attachment_bar_dispose;
519 object_class->constructed = attachment_bar_constructed;
520
521 widget_class = GTK_WIDGET_CLASS (class);
522 widget_class->button_press_event = attachment_bar_button_press_event;
523 widget_class->button_release_event = attachment_bar_button_release_event;
524 widget_class->motion_notify_event = attachment_bar_motion_notify_event;
525
526 gtk_widget_class_set_css_name (widget_class, G_OBJECT_CLASS_NAME (class));
527
528 g_object_class_install_property (
529 object_class,
530 PROP_ACTIVE_VIEW,
531 g_param_spec_int (
532 "active-view",
533 "Active View",
534 NULL,
535 0,
536 NUM_VIEWS,
537 0,
538 G_PARAM_READWRITE |
539 G_PARAM_CONSTRUCT));
540
541 g_object_class_install_property (
542 object_class,
543 PROP_EXPANDED,
544 g_param_spec_boolean (
545 "expanded",
546 "Expanded",
547 NULL,
548 FALSE,
549 G_PARAM_READWRITE |
550 G_PARAM_CONSTRUCT));
551
552 g_object_class_install_property (
553 object_class,
554 PROP_STORE,
555 g_param_spec_object (
556 "store",
557 "Attachment Store",
558 NULL,
559 E_TYPE_ATTACHMENT_STORE,
560 G_PARAM_READWRITE |
561 G_PARAM_CONSTRUCT_ONLY));
562
563 g_object_class_override_property (
564 object_class, PROP_DRAGGING, "dragging");
565
566 g_object_class_override_property (
567 object_class, PROP_EDITABLE, "editable");
568
569 gtk_widget_class_install_style_property (
570 widget_class,
571 g_param_spec_int (
572 "max-content-height",
573 "Max Content Height",
574 NULL,
575 -1, G_MAXINT, 150,
576 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
577 }
578
579 static void
e_attachment_bar_interface_init(EAttachmentViewInterface * iface)580 e_attachment_bar_interface_init (EAttachmentViewInterface *iface)
581 {
582 iface->get_private = attachment_bar_get_private;
583 iface->get_store = attachment_bar_get_store;
584 iface->get_path_at_pos = attachment_bar_get_path_at_pos;
585 iface->get_selected_paths = attachment_bar_get_selected_paths;
586 iface->path_is_selected = attachment_bar_path_is_selected;
587 iface->select_path = attachment_bar_select_path;
588 iface->unselect_path = attachment_bar_unselect_path;
589 iface->select_all = attachment_bar_select_all;
590 iface->unselect_all = attachment_bar_unselect_all;
591 iface->update_actions = attachment_bar_update_actions;
592 }
593
594 static void
e_attachment_bar_init(EAttachmentBar * bar)595 e_attachment_bar_init (EAttachmentBar *bar)
596 {
597 EAttachmentView *view;
598 GtkSizeGroup *size_group;
599 GtkWidget *container;
600 GtkWidget *widget;
601 GtkAction *action;
602 GtkAdjustment *adjustment;
603
604 gtk_widget_set_name (GTK_WIDGET (bar), "e-attachment-bar");
605
606 bar->priv = E_ATTACHMENT_BAR_GET_PRIVATE (bar);
607
608 gtk_orientable_set_orientation (GTK_ORIENTABLE (bar), GTK_ORIENTATION_VERTICAL);
609
610 /* Keep the expander label and save button 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 (bar);
616
617 widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
618 gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
619 bar->priv->vbox = g_object_ref (widget);
620 gtk_widget_show (widget);
621
622 container = bar->priv->vbox;
623
624 widget = gtk_frame_new (NULL);
625 gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_NONE);
626 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
627 bar->priv->icon_frame = g_object_ref (widget);
628 gtk_widget_show (widget);
629
630 container = widget;
631
632 widget = gtk_scrolled_window_new (NULL, NULL);
633 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
634 gtk_container_add (GTK_CONTAINER (container), widget);
635 bar->priv->icon_scrolled_window = widget;
636 gtk_widget_show (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), bar->priv->model);
641 gtk_container_add (GTK_CONTAINER (bar->priv->icon_scrolled_window), widget);
642 bar->priv->icon_view = g_object_ref (widget);
643 gtk_widget_show (widget);
644
645 container = bar->priv->vbox;
646
647 widget = gtk_frame_new (NULL);
648 gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_NONE);
649 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
650 bar->priv->tree_frame = g_object_ref (widget);
651 gtk_widget_hide (widget);
652
653 container = widget;
654
655 widget = gtk_scrolled_window_new (NULL, NULL);
656 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
657 gtk_container_add (GTK_CONTAINER (container), widget);
658 bar->priv->tree_scrolled_window = widget;
659 gtk_widget_show (widget);
660
661 widget = e_attachment_tree_view_new ();
662 gtk_widget_set_can_focus (widget, TRUE);
663 gtk_tree_view_set_model (GTK_TREE_VIEW (widget), bar->priv->model);
664 gtk_container_add (GTK_CONTAINER (bar->priv->tree_scrolled_window), widget);
665 bar->priv->tree_view = g_object_ref (widget);
666 gtk_widget_show (widget);
667
668 /* Construct the Controls */
669
670 container = GTK_WIDGET (bar);
671
672 widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
673 gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
674 gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
675 gtk_widget_show (widget);
676
677 container = widget;
678
679 widget = gtk_expander_new (NULL);
680 gtk_expander_set_spacing (GTK_EXPANDER (widget), 0);
681 gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
682 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
683 bar->priv->expander = g_object_ref (widget);
684 gtk_widget_show (widget);
685
686 /* The "Save All" button proxies the "save-all" action from
687 * one of the two attachment views. Doesn't matter which. */
688 widget = gtk_button_new ();
689 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
690 action = e_attachment_view_get_action (view, "save-all");
691 gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ());
692 gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action);
693 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
694 bar->priv->save_all_button = g_object_ref (widget);
695 gtk_widget_show (widget);
696
697 /* Same deal with the "Save" button. */
698 widget = gtk_button_new ();
699 view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
700 action = e_attachment_view_get_action (view, "save-one");
701 gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ());
702 gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action);
703 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
704 bar->priv->save_one_button = g_object_ref (widget);
705 gtk_widget_show (widget);
706
707 widget = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
708 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
709 gtk_widget_show (widget);
710
711 container = widget;
712
713 widget = gtk_combo_box_text_new ();
714 gtk_size_group_add_widget (size_group, widget);
715 gtk_combo_box_text_append_text (
716 GTK_COMBO_BOX_TEXT (widget), _("Icon View"));
717 gtk_combo_box_text_append_text (
718 GTK_COMBO_BOX_TEXT (widget), _("List View"));
719 gtk_container_add (GTK_CONTAINER (container), widget);
720 bar->priv->combo_box = g_object_ref (widget);
721 gtk_widget_show (widget);
722
723 container = bar->priv->expander;
724
725 widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
726 gtk_size_group_add_widget (size_group, widget);
727 gtk_expander_set_label_widget (GTK_EXPANDER (container), widget);
728 gtk_widget_show (widget);
729
730 container = widget;
731
732 widget = gtk_image_new_from_icon_name (
733 "mail-attachment", GTK_ICON_SIZE_MENU);
734 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
735 bar->priv->status_icon = g_object_ref (widget);
736 gtk_widget_show (widget);
737
738 widget = gtk_label_new (NULL);
739 gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
740 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
741 bar->priv->status_label = g_object_ref (widget);
742 gtk_widget_show (widget);
743
744 g_object_unref (size_group);
745
746 adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (bar->priv->icon_scrolled_window));
747 e_signal_connect_notify (adjustment, "notify::upper",
748 G_CALLBACK (attachment_bar_notify_vadjustment_upper_cb), bar);
749
750 adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (bar->priv->tree_scrolled_window));
751 e_signal_connect_notify (adjustment, "notify::upper",
752 G_CALLBACK (attachment_bar_notify_vadjustment_upper_cb), bar);
753 }
754
755 GtkWidget *
e_attachment_bar_new(EAttachmentStore * store)756 e_attachment_bar_new (EAttachmentStore *store)
757 {
758 g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), NULL);
759
760 return g_object_new (
761 E_TYPE_ATTACHMENT_BAR,
762 "editable", FALSE,
763 "store", store, NULL);
764 }
765
766 gint
e_attachment_bar_get_active_view(EAttachmentBar * bar)767 e_attachment_bar_get_active_view (EAttachmentBar *bar)
768 {
769 g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
770
771 return bar->priv->active_view;
772 }
773
774 void
e_attachment_bar_set_active_view(EAttachmentBar * bar,gint active_view)775 e_attachment_bar_set_active_view (EAttachmentBar *bar,
776 gint active_view)
777 {
778 EAttachmentView *source;
779 EAttachmentView *target;
780
781 g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
782 g_return_if_fail (active_view >= 0 && active_view < NUM_VIEWS);
783
784 if (active_view == bar->priv->active_view)
785 return;
786
787 bar->priv->active_view = active_view;
788
789 if (active_view == 0) {
790 gtk_widget_show (bar->priv->icon_frame);
791 gtk_widget_hide (bar->priv->tree_frame);
792 } else {
793 gtk_widget_hide (bar->priv->icon_frame);
794 gtk_widget_show (bar->priv->tree_frame);
795 }
796
797 /* Synchronize the item selection of the view we're
798 * switching TO with the view we're switching FROM. */
799 if (active_view == 0) {
800 /* from tree view to icon view */
801 source = E_ATTACHMENT_VIEW (bar->priv->tree_view);
802 target = E_ATTACHMENT_VIEW (bar->priv->icon_view);
803 } else {
804 /* from icon view to tree view */
805 source = E_ATTACHMENT_VIEW (bar->priv->icon_view);
806 target = E_ATTACHMENT_VIEW (bar->priv->tree_view);
807 }
808
809 e_attachment_view_sync_selection (source, target);
810
811 g_object_notify (G_OBJECT (bar), "active-view");
812 }
813
814 gboolean
e_attachment_bar_get_expanded(EAttachmentBar * bar)815 e_attachment_bar_get_expanded (EAttachmentBar *bar)
816 {
817 g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), FALSE);
818
819 return bar->priv->expanded;
820 }
821
822 void
e_attachment_bar_set_expanded(EAttachmentBar * bar,gboolean expanded)823 e_attachment_bar_set_expanded (EAttachmentBar *bar,
824 gboolean expanded)
825 {
826 g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
827
828 if (bar->priv->expanded == expanded)
829 return;
830
831 bar->priv->expanded = expanded;
832
833 g_object_notify (G_OBJECT (bar), "expanded");
834 }
835
836 EAttachmentStore *
e_attachment_bar_get_store(EAttachmentBar * bar)837 e_attachment_bar_get_store (EAttachmentBar *bar)
838 {
839 g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
840
841 return E_ATTACHMENT_STORE (bar->priv->model);
842 }
843