1 /*
2  * e-attachment-icon-view.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-icon-view.h"
24 
25 #include <glib/gi18n.h>
26 #include <libebackend/libebackend.h>
27 
28 #include "e-attachment.h"
29 #include "e-attachment-store.h"
30 #include "e-attachment-view.h"
31 
32 #define E_ATTACHMENT_ICON_VIEW_GET_PRIVATE(obj) \
33 	(G_TYPE_INSTANCE_GET_PRIVATE \
34 	((obj), E_TYPE_ATTACHMENT_ICON_VIEW, EAttachmentIconViewPrivate))
35 
36 struct _EAttachmentIconViewPrivate {
37 	EAttachmentViewPrivate view_priv;
38 };
39 
40 enum {
41 	PROP_0,
42 	PROP_DRAGGING,
43 	PROP_EDITABLE
44 };
45 
46 /* Forward Declarations */
47 static void	e_attachment_icon_view_interface_init
48 					(EAttachmentViewInterface *iface);
49 
G_DEFINE_TYPE_WITH_CODE(EAttachmentIconView,e_attachment_icon_view,GTK_TYPE_ICON_VIEW,G_IMPLEMENT_INTERFACE (E_TYPE_ATTACHMENT_VIEW,e_attachment_icon_view_interface_init)G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE,NULL))50 G_DEFINE_TYPE_WITH_CODE (
51 	EAttachmentIconView,
52 	e_attachment_icon_view,
53 	GTK_TYPE_ICON_VIEW,
54 	G_IMPLEMENT_INTERFACE (
55 		E_TYPE_ATTACHMENT_VIEW,
56 		e_attachment_icon_view_interface_init)
57 	G_IMPLEMENT_INTERFACE (
58 		E_TYPE_EXTENSIBLE, NULL))
59 
60 static void
61 attachment_icon_view_set_property (GObject *object,
62                                    guint property_id,
63                                    const GValue *value,
64                                    GParamSpec *pspec)
65 {
66 	switch (property_id) {
67 		case PROP_DRAGGING:
68 			e_attachment_view_set_dragging (
69 				E_ATTACHMENT_VIEW (object),
70 				g_value_get_boolean (value));
71 			return;
72 
73 		case PROP_EDITABLE:
74 			e_attachment_view_set_editable (
75 				E_ATTACHMENT_VIEW (object),
76 				g_value_get_boolean (value));
77 			return;
78 	}
79 
80 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
81 }
82 
83 static void
attachment_icon_view_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)84 attachment_icon_view_get_property (GObject *object,
85                                    guint property_id,
86                                    GValue *value,
87                                    GParamSpec *pspec)
88 {
89 	switch (property_id) {
90 		case PROP_DRAGGING:
91 			g_value_set_boolean (
92 				value, e_attachment_view_get_dragging (
93 				E_ATTACHMENT_VIEW (object)));
94 			return;
95 
96 		case PROP_EDITABLE:
97 			g_value_set_boolean (
98 				value, e_attachment_view_get_editable (
99 				E_ATTACHMENT_VIEW (object)));
100 			return;
101 	}
102 
103 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
104 }
105 
106 static void
attachment_icon_view_dispose(GObject * object)107 attachment_icon_view_dispose (GObject *object)
108 {
109 	e_attachment_view_dispose (E_ATTACHMENT_VIEW (object));
110 
111 	/* Chain up to parent's dispose() method. */
112 	G_OBJECT_CLASS (e_attachment_icon_view_parent_class)->dispose (object);
113 }
114 
115 static void
attachment_icon_view_finalize(GObject * object)116 attachment_icon_view_finalize (GObject *object)
117 {
118 	e_attachment_view_finalize (E_ATTACHMENT_VIEW (object));
119 
120 	/* Chain up to parent's finalize() method. */
121 	G_OBJECT_CLASS (e_attachment_icon_view_parent_class)->finalize (object);
122 }
123 
124 static void
attachment_icon_view_constructed(GObject * object)125 attachment_icon_view_constructed (GObject *object)
126 {
127 	GtkCellLayout *cell_layout;
128 	GtkCellRenderer *renderer;
129 
130 	/* Chain up to parent's method. */
131 	G_OBJECT_CLASS (e_attachment_icon_view_parent_class)->constructed (object);
132 
133 	gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (object), GTK_SELECTION_MULTIPLE);
134 	gtk_icon_view_set_item_width (GTK_ICON_VIEW (object), 96);
135 
136 	cell_layout = GTK_CELL_LAYOUT (object);
137 
138 	/* This needs to happen after constructor properties are set
139 	 * so that GtkCellLayout.get_area() returns something valid. */
140 
141 	renderer = gtk_cell_renderer_pixbuf_new ();
142 	g_object_set (renderer,
143 		"stock-size", GTK_ICON_SIZE_DIALOG,
144 		"xalign", 0.5,
145 		"yalign", 0.5,
146 		NULL);
147 	gtk_cell_layout_pack_start (cell_layout, renderer, FALSE);
148 
149 	gtk_cell_layout_add_attribute (
150 		cell_layout, renderer, "gicon",
151 		E_ATTACHMENT_STORE_COLUMN_ICON);
152 
153 	renderer = gtk_cell_renderer_text_new ();
154 	g_object_set (renderer,
155 		"alignment", PANGO_ALIGN_LEFT,
156 		"ellipsize", PANGO_ELLIPSIZE_END,
157 		"wrap-mode", PANGO_WRAP_WORD,
158 		"wrap-width", 96,
159 		"scale", 0.8,
160 		"xpad", 0,
161 		"xalign", 0.5,
162 		"yalign", 0.0,
163 		NULL);
164 	gtk_cell_layout_pack_start (cell_layout, renderer, FALSE);
165 
166 	gtk_cell_layout_add_attribute (
167 		cell_layout, renderer, "text",
168 		E_ATTACHMENT_STORE_COLUMN_CAPTION);
169 
170 	renderer = gtk_cell_renderer_progress_new ();
171 	g_object_set (renderer, "text", _("Loading"), NULL);
172 	gtk_cell_layout_pack_start (cell_layout, renderer, TRUE);
173 
174 	gtk_cell_layout_add_attribute (
175 		cell_layout, renderer, "value",
176 		E_ATTACHMENT_STORE_COLUMN_PERCENT);
177 
178 	gtk_cell_layout_add_attribute (
179 		cell_layout, renderer, "visible",
180 		E_ATTACHMENT_STORE_COLUMN_LOADING);
181 
182 	renderer = gtk_cell_renderer_progress_new ();
183 	g_object_set (renderer, "text", _("Saving"), NULL);
184 	gtk_cell_layout_pack_start (cell_layout, renderer, TRUE);
185 
186 	gtk_cell_layout_add_attribute (
187 		cell_layout, renderer, "value",
188 		E_ATTACHMENT_STORE_COLUMN_PERCENT);
189 
190 	gtk_cell_layout_add_attribute (
191 		cell_layout, renderer, "visible",
192 		E_ATTACHMENT_STORE_COLUMN_SAVING);
193 
194 	e_extensible_load_extensions (E_EXTENSIBLE (object));
195 }
196 
197 static gboolean
attachment_icon_view_button_press_event(GtkWidget * widget,GdkEventButton * event)198 attachment_icon_view_button_press_event (GtkWidget *widget,
199                                          GdkEventButton *event)
200 {
201 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
202 
203 	if (!e_attachment_view_button_press_event (view, event)) {
204 		/* Chain up to parent's button_press_event() method. */
205 		GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
206 			button_press_event (widget, event);
207 	}
208 
209 	/* Never propagate the event to the parent */
210 	return TRUE;
211 }
212 
213 static gboolean
attachment_icon_view_button_release_event(GtkWidget * widget,GdkEventButton * event)214 attachment_icon_view_button_release_event (GtkWidget *widget,
215                                            GdkEventButton *event)
216 {
217 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
218 
219 	if (!e_attachment_view_button_release_event (view, event)) {
220 		/* Chain up to parent's button_release_event() method. */
221 		GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
222 			button_release_event (widget, event);
223 	}
224 
225 	/* Never propagate the event to the parent */
226 	return TRUE;
227 }
228 
229 static gboolean
attachment_icon_view_motion_notify_event(GtkWidget * widget,GdkEventMotion * event)230 attachment_icon_view_motion_notify_event (GtkWidget *widget,
231                                           GdkEventMotion *event)
232 {
233 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
234 
235 	if (!e_attachment_view_motion_notify_event (view, event)) {
236 		/* Chain up to parent's motion_notify_event() method. */
237 		GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
238 			motion_notify_event (widget, event);
239 	}
240 
241 	/* Never propagate the event to the parent */
242 	return TRUE;
243 }
244 
245 static gboolean
attachment_icon_view_key_press_event(GtkWidget * widget,GdkEventKey * event)246 attachment_icon_view_key_press_event (GtkWidget *widget,
247                                       GdkEventKey *event)
248 {
249 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
250 
251 	if (e_attachment_view_key_press_event (view, event))
252 		return TRUE;
253 
254 	/* Chain up to parent's key_press_event() method. */
255 	return GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
256 		key_press_event (widget, event);
257 }
258 
259 static void
attachment_icon_view_drag_begin(GtkWidget * widget,GdkDragContext * context)260 attachment_icon_view_drag_begin (GtkWidget *widget,
261                                  GdkDragContext *context)
262 {
263 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
264 
265 	/* Chain up to parent's drag_begin() method. */
266 	GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
267 		drag_begin (widget, context);
268 
269 	e_attachment_view_drag_begin (view, context);
270 }
271 
272 static void
attachment_icon_view_drag_end(GtkWidget * widget,GdkDragContext * context)273 attachment_icon_view_drag_end (GtkWidget *widget,
274                                GdkDragContext *context)
275 {
276 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
277 
278 	/* Chain up to parent's drag_end() method. */
279 	GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
280 		drag_end (widget, context);
281 
282 	e_attachment_view_drag_end (view, context);
283 }
284 
285 static void
attachment_icon_view_drag_data_get(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * selection,guint info,guint time)286 attachment_icon_view_drag_data_get (GtkWidget *widget,
287                                     GdkDragContext *context,
288                                     GtkSelectionData *selection,
289                                     guint info,
290                                     guint time)
291 {
292 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
293 
294 	e_attachment_view_drag_data_get (
295 		view, context, selection, info, time);
296 }
297 
298 static gboolean
attachment_icon_view_drag_motion(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time)299 attachment_icon_view_drag_motion (GtkWidget *widget,
300                                   GdkDragContext *context,
301                                   gint x,
302                                   gint y,
303                                   guint time)
304 {
305 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
306 
307 	return e_attachment_view_drag_motion (view, context, x, y, time);
308 }
309 
310 static gboolean
attachment_icon_view_drag_drop(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time)311 attachment_icon_view_drag_drop (GtkWidget *widget,
312                                 GdkDragContext *context,
313                                 gint x,
314                                 gint y,
315                                 guint time)
316 {
317 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
318 
319 	if (!e_attachment_view_drag_drop (view, context, x, y, time))
320 		return FALSE;
321 
322 	/* Chain up to parent's drag_drop() method. */
323 	return GTK_WIDGET_CLASS (e_attachment_icon_view_parent_class)->
324 		drag_drop (widget, context, x, y, time);
325 }
326 
327 static void
attachment_icon_view_drag_data_received(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection,guint info,guint time)328 attachment_icon_view_drag_data_received (GtkWidget *widget,
329                                          GdkDragContext *context,
330                                          gint x,
331                                          gint y,
332                                          GtkSelectionData *selection,
333                                          guint info,
334                                          guint time)
335 {
336 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
337 
338 	e_attachment_view_drag_data_received (
339 		view, context, x, y, selection, info, time);
340 }
341 
342 static gboolean
attachment_icon_view_popup_menu(GtkWidget * widget)343 attachment_icon_view_popup_menu (GtkWidget *widget)
344 {
345 	EAttachmentView *view = E_ATTACHMENT_VIEW (widget);
346 	GtkWidget *menu;
347 
348 	e_attachment_view_update_actions (view);
349 	menu = e_attachment_view_get_popup_menu (view);
350 	gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
351 
352 	return TRUE;
353 }
354 
355 static void
attachment_icon_view_item_activated(GtkIconView * icon_view,GtkTreePath * path)356 attachment_icon_view_item_activated (GtkIconView *icon_view,
357                                      GtkTreePath *path)
358 {
359 	EAttachmentView *view = E_ATTACHMENT_VIEW (icon_view);
360 
361 	e_attachment_view_open_path (view, path, NULL);
362 }
363 
364 static EAttachmentViewPrivate *
attachment_icon_view_get_private(EAttachmentView * view)365 attachment_icon_view_get_private (EAttachmentView *view)
366 {
367 	EAttachmentIconViewPrivate *priv;
368 
369 	priv = E_ATTACHMENT_ICON_VIEW_GET_PRIVATE (view);
370 
371 	return &priv->view_priv;
372 }
373 
374 static EAttachmentStore *
attachment_icon_view_get_store(EAttachmentView * view)375 attachment_icon_view_get_store (EAttachmentView *view)
376 {
377 	GtkIconView *icon_view;
378 	GtkTreeModel *model;
379 
380 	icon_view = GTK_ICON_VIEW (view);
381 	model = gtk_icon_view_get_model (icon_view);
382 
383 	return E_ATTACHMENT_STORE (model);
384 }
385 
386 static GtkTreePath *
attachment_icon_view_get_path_at_pos(EAttachmentView * view,gint x,gint y)387 attachment_icon_view_get_path_at_pos (EAttachmentView *view,
388                                       gint x,
389                                       gint y)
390 {
391 	GtkIconView *icon_view;
392 
393 	icon_view = GTK_ICON_VIEW (view);
394 
395 	return gtk_icon_view_get_path_at_pos (icon_view, x, y);
396 }
397 
398 static GList *
attachment_icon_view_get_selected_paths(EAttachmentView * view)399 attachment_icon_view_get_selected_paths (EAttachmentView *view)
400 {
401 	GtkIconView *icon_view;
402 
403 	icon_view = GTK_ICON_VIEW (view);
404 
405 	return gtk_icon_view_get_selected_items (icon_view);
406 }
407 
408 static gboolean
attachment_icon_view_path_is_selected(EAttachmentView * view,GtkTreePath * path)409 attachment_icon_view_path_is_selected (EAttachmentView *view,
410                                        GtkTreePath *path)
411 {
412 	GtkIconView *icon_view;
413 
414 	icon_view = GTK_ICON_VIEW (view);
415 
416 	return gtk_icon_view_path_is_selected (icon_view, path);
417 }
418 
419 static void
attachment_icon_view_select_path(EAttachmentView * view,GtkTreePath * path)420 attachment_icon_view_select_path (EAttachmentView *view,
421                                   GtkTreePath *path)
422 {
423 	GtkIconView *icon_view;
424 
425 	icon_view = GTK_ICON_VIEW (view);
426 
427 	gtk_icon_view_select_path (icon_view, path);
428 }
429 
430 static void
attachment_icon_view_unselect_path(EAttachmentView * view,GtkTreePath * path)431 attachment_icon_view_unselect_path (EAttachmentView *view,
432                                     GtkTreePath *path)
433 {
434 	GtkIconView *icon_view;
435 
436 	icon_view = GTK_ICON_VIEW (view);
437 
438 	gtk_icon_view_unselect_path (icon_view, path);
439 }
440 
441 static void
attachment_icon_view_select_all(EAttachmentView * view)442 attachment_icon_view_select_all (EAttachmentView *view)
443 {
444 	GtkIconView *icon_view;
445 
446 	icon_view = GTK_ICON_VIEW (view);
447 
448 	gtk_icon_view_select_all (icon_view);
449 }
450 
451 static void
attachment_icon_view_unselect_all(EAttachmentView * view)452 attachment_icon_view_unselect_all (EAttachmentView *view)
453 {
454 	GtkIconView *icon_view;
455 
456 	icon_view = GTK_ICON_VIEW (view);
457 
458 	gtk_icon_view_unselect_all (icon_view);
459 }
460 
461 static void
attachment_icon_view_drag_source_set(EAttachmentView * view,GdkModifierType start_button_mask,const GtkTargetEntry * targets,gint n_targets,GdkDragAction actions)462 attachment_icon_view_drag_source_set (EAttachmentView *view,
463                                       GdkModifierType start_button_mask,
464                                       const GtkTargetEntry *targets,
465                                       gint n_targets,
466                                       GdkDragAction actions)
467 {
468 	GtkIconView *icon_view;
469 
470 	icon_view = GTK_ICON_VIEW (view);
471 
472 	gtk_icon_view_enable_model_drag_source (
473 		icon_view, start_button_mask, targets, n_targets, actions);
474 }
475 
476 static void
attachment_icon_view_drag_dest_set(EAttachmentView * view,const GtkTargetEntry * targets,gint n_targets,GdkDragAction actions)477 attachment_icon_view_drag_dest_set (EAttachmentView *view,
478                                     const GtkTargetEntry *targets,
479                                     gint n_targets,
480                                     GdkDragAction actions)
481 {
482 	GtkIconView *icon_view;
483 
484 	icon_view = GTK_ICON_VIEW (view);
485 
486 	gtk_icon_view_enable_model_drag_dest (
487 		icon_view, targets, n_targets, actions);
488 }
489 
490 static void
attachment_icon_view_drag_source_unset(EAttachmentView * view)491 attachment_icon_view_drag_source_unset (EAttachmentView *view)
492 {
493 	GtkIconView *icon_view;
494 
495 	icon_view = GTK_ICON_VIEW (view);
496 
497 	gtk_icon_view_unset_model_drag_source (icon_view);
498 }
499 
500 static void
attachment_icon_view_drag_dest_unset(EAttachmentView * view)501 attachment_icon_view_drag_dest_unset (EAttachmentView *view)
502 {
503 	GtkIconView *icon_view;
504 
505 	icon_view = GTK_ICON_VIEW (view);
506 
507 	gtk_icon_view_unset_model_drag_dest (icon_view);
508 }
509 
510 static void
e_attachment_icon_view_class_init(EAttachmentIconViewClass * class)511 e_attachment_icon_view_class_init (EAttachmentIconViewClass *class)
512 {
513 	GObjectClass *object_class;
514 	GtkWidgetClass *widget_class;
515 	GtkIconViewClass *icon_view_class;
516 
517 	g_type_class_add_private (class, sizeof (EAttachmentViewPrivate));
518 
519 	object_class = G_OBJECT_CLASS (class);
520 	object_class->set_property = attachment_icon_view_set_property;
521 	object_class->get_property = attachment_icon_view_get_property;
522 	object_class->dispose = attachment_icon_view_dispose;
523 	object_class->finalize = attachment_icon_view_finalize;
524 	object_class->constructed = attachment_icon_view_constructed;
525 
526 	widget_class = GTK_WIDGET_CLASS (class);
527 	widget_class->button_press_event = attachment_icon_view_button_press_event;
528 	widget_class->button_release_event = attachment_icon_view_button_release_event;
529 	widget_class->motion_notify_event = attachment_icon_view_motion_notify_event;
530 	widget_class->key_press_event = attachment_icon_view_key_press_event;
531 	widget_class->drag_begin = attachment_icon_view_drag_begin;
532 	widget_class->drag_end = attachment_icon_view_drag_end;
533 	widget_class->drag_data_get = attachment_icon_view_drag_data_get;
534 	widget_class->drag_motion = attachment_icon_view_drag_motion;
535 	widget_class->drag_drop = attachment_icon_view_drag_drop;
536 	widget_class->drag_data_received = attachment_icon_view_drag_data_received;
537 	widget_class->popup_menu = attachment_icon_view_popup_menu;
538 
539 	icon_view_class = GTK_ICON_VIEW_CLASS (class);
540 	icon_view_class->item_activated = attachment_icon_view_item_activated;
541 
542 	g_object_class_override_property (
543 		object_class, PROP_DRAGGING, "dragging");
544 
545 	g_object_class_override_property (
546 		object_class, PROP_EDITABLE, "editable");
547 }
548 
549 static void
e_attachment_icon_view_init(EAttachmentIconView * icon_view)550 e_attachment_icon_view_init (EAttachmentIconView *icon_view)
551 {
552 	icon_view->priv = E_ATTACHMENT_ICON_VIEW_GET_PRIVATE (icon_view);
553 
554 	e_attachment_view_init (E_ATTACHMENT_VIEW (icon_view));
555 }
556 
557 static void
e_attachment_icon_view_interface_init(EAttachmentViewInterface * iface)558 e_attachment_icon_view_interface_init (EAttachmentViewInterface *iface)
559 {
560 	iface->get_private = attachment_icon_view_get_private;
561 	iface->get_store = attachment_icon_view_get_store;
562 
563 	iface->get_path_at_pos = attachment_icon_view_get_path_at_pos;
564 	iface->get_selected_paths = attachment_icon_view_get_selected_paths;
565 	iface->path_is_selected = attachment_icon_view_path_is_selected;
566 	iface->select_path = attachment_icon_view_select_path;
567 	iface->unselect_path = attachment_icon_view_unselect_path;
568 	iface->select_all = attachment_icon_view_select_all;
569 	iface->unselect_all = attachment_icon_view_unselect_all;
570 
571 	iface->drag_source_set = attachment_icon_view_drag_source_set;
572 	iface->drag_dest_set = attachment_icon_view_drag_dest_set;
573 	iface->drag_source_unset = attachment_icon_view_drag_source_unset;
574 	iface->drag_dest_unset = attachment_icon_view_drag_dest_unset;
575 }
576 
577 GtkWidget *
e_attachment_icon_view_new(void)578 e_attachment_icon_view_new (void)
579 {
580 	return g_object_new (E_TYPE_ATTACHMENT_ICON_VIEW, NULL);
581 }
582