1 /*
2  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
3  * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "evolution-config.h"
19 
20 #include <string.h>
21 #include <glib/gi18n-lib.h>
22 
23 #include <calendar/gui/comp-util.h>
24 #include <calendar/gui/e-cal-component-preview.h>
25 #include <calendar/gui/e-cal-model-memos.h>
26 #include <calendar/gui/e-memo-table.h>
27 
28 #include "e-cal-base-shell-sidebar.h"
29 #include "e-memo-shell-content.h"
30 
31 #define E_MEMO_SHELL_CONTENT_GET_PRIVATE(obj) \
32 	(G_TYPE_INSTANCE_GET_PRIVATE \
33 	((obj), E_TYPE_MEMO_SHELL_CONTENT, EMemoShellContentPrivate))
34 
35 struct _EMemoShellContentPrivate {
36 	GtkWidget *paned;
37 	GtkWidget *memo_table;
38 	GtkWidget *preview_pane;
39 
40 	GtkOrientation orientation;
41 
42 	gchar *current_uid;
43 
44 	guint preview_visible : 1;
45 };
46 
47 enum {
48 	PROP_0,
49 	PROP_ORIENTATION,
50 	PROP_PREVIEW_VISIBLE
51 };
52 
53 G_DEFINE_DYNAMIC_TYPE_EXTENDED (EMemoShellContent, e_memo_shell_content, E_TYPE_CAL_BASE_SHELL_CONTENT, 0,
54 	G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_ORIENTABLE, NULL))
55 
56 static void
memo_shell_content_display_view_cb(EMemoShellContent * memo_shell_content,GalView * gal_view)57 memo_shell_content_display_view_cb (EMemoShellContent *memo_shell_content,
58                                     GalView *gal_view)
59 {
60 	EMemoTable *memo_table;
61 
62 	if (!GAL_IS_VIEW_ETABLE (gal_view))
63 		return;
64 
65 	memo_table = e_memo_shell_content_get_memo_table (memo_shell_content);
66 
67 	gal_view_etable_attach_table (
68 		GAL_VIEW_ETABLE (gal_view), E_TABLE (memo_table));
69 }
70 
71 static void
memo_shell_content_table_foreach_cb(gint model_row,gpointer user_data)72 memo_shell_content_table_foreach_cb (gint model_row,
73                                      gpointer user_data)
74 {
75 	ECalModelComponent *comp_data;
76 	ICalComponent *clone;
77 	ICalComponent *vcal;
78 	gchar *string;
79 
80 	struct {
81 		ECalModel *model;
82 		GSList *list;
83 	} *foreach_data = user_data;
84 
85 	comp_data = e_cal_model_get_component_at (
86 		foreach_data->model, model_row);
87 
88 	vcal = e_cal_util_new_top_level ();
89 	clone = i_cal_component_clone (comp_data->icalcomp);
90 	e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
91 	i_cal_component_take_component (vcal, clone);
92 
93 	string = i_cal_component_as_ical_string (vcal);
94 	if (string != NULL) {
95 		ESource *source;
96 		const gchar *source_uid;
97 
98 		source = e_client_get_source (E_CLIENT (comp_data->client));
99 		source_uid = e_source_get_uid (source);
100 
101 		foreach_data->list = g_slist_prepend (
102 			foreach_data->list,
103 			g_strdup_printf ("%s\n%s", source_uid, string));
104 
105 		g_free (string);
106 	}
107 
108 	g_object_unref (vcal);
109 }
110 
111 static void
memo_shell_content_table_drag_data_get_cb(EMemoShellContent * memo_shell_content,gint row,gint col,GdkDragContext * context,GtkSelectionData * selection_data,guint info,guint time)112 memo_shell_content_table_drag_data_get_cb (EMemoShellContent *memo_shell_content,
113                                            gint row,
114                                            gint col,
115                                            GdkDragContext *context,
116                                            GtkSelectionData *selection_data,
117                                            guint info,
118                                            guint time)
119 {
120 	EMemoTable *memo_table;
121 	GdkAtom target;
122 
123 	struct {
124 		ECalModel *model;
125 		GSList *list;
126 	} foreach_data;
127 
128 	/* Sanity check the selection target. */
129 	target = gtk_selection_data_get_target (selection_data);
130 	if (!e_targets_include_calendar (&target, 1))
131 		return;
132 
133 	memo_table = e_memo_shell_content_get_memo_table (memo_shell_content);
134 
135 	foreach_data.model = e_memo_table_get_model (memo_table);
136 	foreach_data.list = NULL;
137 
138 	e_table_selected_row_foreach (
139 		E_TABLE (memo_table),
140 		memo_shell_content_table_foreach_cb,
141 		&foreach_data);
142 
143 	if (foreach_data.list != NULL) {
144 		cal_comp_selection_set_string_list (
145 			selection_data, foreach_data.list);
146 		g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL);
147 		g_slist_free (foreach_data.list);
148 	}
149 }
150 
151 static void
memo_shell_content_table_drag_data_delete_cb(EMemoShellContent * memo_shell_content,gint row,gint col,GdkDragContext * context)152 memo_shell_content_table_drag_data_delete_cb (EMemoShellContent *memo_shell_content,
153                                               gint row,
154                                               gint col,
155                                               GdkDragContext *context)
156 {
157 	/* Moved components are deleted from source immediately when moved,
158 	 * because some of them can be part of destination source, and we
159 	 * don't want to delete not-moved memos.  There is no such information
160 	 * which event has been moved and which not, so skip this method. */
161 }
162 
163 static void
memo_shell_content_cursor_change_cb(EMemoShellContent * memo_shell_content,gint row,ETable * table)164 memo_shell_content_cursor_change_cb (EMemoShellContent *memo_shell_content,
165                                      gint row,
166                                      ETable *table)
167 {
168 	ECalComponentPreview *memo_preview;
169 	ECalModel *memo_model;
170 	ECalModelComponent *comp_data;
171 	EPreviewPane *preview_pane;
172 	EWebView *web_view;
173 	const gchar *uid;
174 
175 	memo_model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (memo_shell_content));
176 	preview_pane = e_memo_shell_content_get_preview_pane (memo_shell_content);
177 
178 	web_view = e_preview_pane_get_web_view (preview_pane);
179 	memo_preview = E_CAL_COMPONENT_PREVIEW (web_view);
180 
181 	if (e_table_selected_count (table) != 1) {
182 		if (memo_shell_content->priv->preview_visible)
183 			e_cal_component_preview_clear (memo_preview);
184 		return;
185 	}
186 
187 	row = e_table_get_cursor_row (table);
188 	comp_data = e_cal_model_get_component_at (memo_model, row);
189 
190 	if (memo_shell_content->priv->preview_visible) {
191 		ECalComponent *comp;
192 
193 		comp = e_cal_component_new_from_icalcomponent (
194 			i_cal_component_clone (comp_data->icalcomp));
195 
196 		e_cal_component_preview_display (
197 			memo_preview, comp_data->client, comp,
198 			e_cal_model_get_timezone (memo_model),
199 			e_cal_model_get_use_24_hour_format (memo_model));
200 
201 		g_object_unref (comp);
202 	}
203 
204 	uid = i_cal_component_get_uid (comp_data->icalcomp);
205 	g_free (memo_shell_content->priv->current_uid);
206 	memo_shell_content->priv->current_uid = g_strdup (uid);
207 }
208 
209 static void
memo_shell_content_selection_change_cb(EMemoShellContent * memo_shell_content,ETable * table)210 memo_shell_content_selection_change_cb (EMemoShellContent *memo_shell_content,
211                                         ETable *table)
212 {
213 	ECalComponentPreview *memo_preview;
214 	EPreviewPane *preview_pane;
215 	EWebView *web_view;
216 
217 	preview_pane = e_memo_shell_content_get_preview_pane (memo_shell_content);
218 
219 	web_view = e_preview_pane_get_web_view (preview_pane);
220 	memo_preview = E_CAL_COMPONENT_PREVIEW (web_view);
221 
222 	/* XXX Old code emits a "selection-changed" signal here. */
223 
224 	if (e_table_selected_count (table) != 1)
225 		e_cal_component_preview_clear (memo_preview);
226 }
227 
228 static void
memo_shell_content_model_row_changed_cb(EMemoShellContent * memo_shell_content,gint row,ETableModel * model)229 memo_shell_content_model_row_changed_cb (EMemoShellContent *memo_shell_content,
230                                          gint row,
231                                          ETableModel *model)
232 {
233 	ECalModelComponent *comp_data;
234 	EMemoTable *memo_table;
235 	const gchar *current_uid;
236 	const gchar *uid;
237 
238 	current_uid = memo_shell_content->priv->current_uid;
239 	if (current_uid == NULL)
240 		return;
241 
242 	comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
243 	if (comp_data == NULL)
244 		return;
245 
246 	uid = i_cal_component_get_uid (comp_data->icalcomp);
247 	if (g_strcmp0 (uid, current_uid) != 0)
248 		return;
249 
250 	memo_table = e_memo_shell_content_get_memo_table (memo_shell_content);
251 
252 	memo_shell_content_cursor_change_cb (
253 		memo_shell_content, 0, E_TABLE (memo_table));
254 }
255 
256 static void
memo_shell_content_is_editing_changed_cb(EMemoTable * memo_table,GParamSpec * param,EShellView * shell_view)257 memo_shell_content_is_editing_changed_cb (EMemoTable *memo_table,
258                                           GParamSpec *param,
259                                           EShellView *shell_view)
260 {
261 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
262 
263 	e_shell_view_update_actions (shell_view);
264 }
265 
266 static guint32
memo_shell_content_check_state(EShellContent * shell_content)267 memo_shell_content_check_state (EShellContent *shell_content)
268 {
269 	EMemoShellContent *memo_shell_content;
270 	EMemoTable *memo_table;
271 	GSList *list, *iter;
272 	gboolean editable = TRUE;
273 	gboolean has_url = FALSE;
274 	gint n_selected;
275 	guint32 state = 0;
276 
277 	memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content);
278 	memo_table = e_memo_shell_content_get_memo_table (memo_shell_content);
279 
280 	n_selected = e_table_selected_count (E_TABLE (memo_table));
281 
282 	list = e_memo_table_get_selected (memo_table);
283 	for (iter = list; iter != NULL; iter = iter->next) {
284 		ECalModelComponent *comp_data = iter->data;
285 		gboolean read_only;
286 
287 		if (!comp_data)
288 			continue;
289 
290 		read_only = e_client_is_readonly (E_CLIENT (comp_data->client));
291 		editable &= !read_only;
292 
293 		has_url |= e_cal_util_component_has_property (comp_data->icalcomp, I_CAL_URL_PROPERTY);
294 	}
295 	g_slist_free (list);
296 
297 	if (n_selected == 1)
298 		state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_SINGLE;
299 	if (n_selected > 1)
300 		state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_MULTIPLE;
301 	if (editable)
302 		state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_EDITABLE;
303 	if (has_url)
304 		state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_HAS_URL;
305 
306 	return state;
307 }
308 
309 static void
memo_shell_content_focus_search_results(EShellContent * shell_content)310 memo_shell_content_focus_search_results (EShellContent *shell_content)
311 {
312 	EMemoShellContent *memo_shell_content;
313 
314 	memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content);
315 
316 	gtk_widget_grab_focus (memo_shell_content->priv->memo_table);
317 }
318 
319 static GtkOrientation
memo_shell_content_get_orientation(EMemoShellContent * memo_shell_content)320 memo_shell_content_get_orientation (EMemoShellContent *memo_shell_content)
321 {
322 	return memo_shell_content->priv->orientation;
323 }
324 
325 static void
memo_shell_content_set_orientation(EMemoShellContent * memo_shell_content,GtkOrientation orientation)326 memo_shell_content_set_orientation (EMemoShellContent *memo_shell_content,
327                                     GtkOrientation orientation)
328 {
329 	if (memo_shell_content->priv->orientation == orientation)
330 		return;
331 
332 	memo_shell_content->priv->orientation = orientation;
333 
334 	g_object_notify (G_OBJECT (memo_shell_content), "orientation");
335 }
336 
337 static void
memo_shell_content_view_created(ECalBaseShellContent * cal_base_shell_content)338 memo_shell_content_view_created (ECalBaseShellContent *cal_base_shell_content)
339 {
340 	EMemoShellContent *memo_shell_content;
341 	EShellView *shell_view;
342 	GalViewInstance *view_instance;
343 	GSettings *settings;
344 
345 	memo_shell_content = E_MEMO_SHELL_CONTENT (cal_base_shell_content);
346 	shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (memo_shell_content));
347 
348 	/* Bind GObject properties to settings keys. */
349 
350 	settings = e_util_ref_settings ("org.gnome.evolution.calendar");
351 
352 	g_settings_bind (
353 		settings, "memo-hpane-position",
354 		memo_shell_content->priv->paned, "hposition",
355 		G_SETTINGS_BIND_DEFAULT);
356 
357 	g_settings_bind (
358 		settings, "memo-vpane-position",
359 		memo_shell_content->priv->paned, "vposition",
360 		G_SETTINGS_BIND_DEFAULT);
361 
362 	g_object_unref (settings);
363 
364 	/* Finally load the view instance */
365 	view_instance = e_shell_view_get_view_instance (shell_view);
366 	gal_view_instance_load (view_instance);
367 
368 	/* Show everything known by default */
369 	e_cal_model_set_time_range (e_cal_base_shell_content_get_model (cal_base_shell_content), 0, 0);
370 }
371 
372 static void
memo_shell_content_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)373 memo_shell_content_set_property (GObject *object,
374                                  guint property_id,
375                                  const GValue *value,
376                                  GParamSpec *pspec)
377 {
378 	switch (property_id) {
379 		case PROP_ORIENTATION:
380 			memo_shell_content_set_orientation (
381 				E_MEMO_SHELL_CONTENT (object),
382 				g_value_get_enum (value));
383 			return;
384 
385 		case PROP_PREVIEW_VISIBLE:
386 			e_memo_shell_content_set_preview_visible (
387 				E_MEMO_SHELL_CONTENT (object),
388 				g_value_get_boolean (value));
389 			return;
390 	}
391 
392 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
393 }
394 
395 static void
memo_shell_content_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)396 memo_shell_content_get_property (GObject *object,
397 				 guint property_id,
398 				 GValue *value,
399 				 GParamSpec *pspec)
400 {
401 	switch (property_id) {
402 		case PROP_ORIENTATION:
403 			g_value_set_enum (
404 				value,
405 				memo_shell_content_get_orientation (
406 				E_MEMO_SHELL_CONTENT (object)));
407 			return;
408 
409 		case PROP_PREVIEW_VISIBLE:
410 			g_value_set_boolean (
411 				value,
412 				e_memo_shell_content_get_preview_visible (
413 				E_MEMO_SHELL_CONTENT (object)));
414 			return;
415 	}
416 
417 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
418 }
419 
420 static void
memo_shell_content_dispose(GObject * object)421 memo_shell_content_dispose (GObject *object)
422 {
423 	EMemoShellContent *memo_shell_content = E_MEMO_SHELL_CONTENT (object);
424 
425 	g_clear_object (&memo_shell_content->priv->paned);
426 	g_clear_object (&memo_shell_content->priv->memo_table);
427 	g_clear_object (&memo_shell_content->priv->preview_pane);
428 
429 	g_free (memo_shell_content->priv->current_uid);
430 	memo_shell_content->priv->current_uid = NULL;
431 
432 	/* Chain up to parent's dispose() method. */
433 	G_OBJECT_CLASS (e_memo_shell_content_parent_class)->dispose (object);
434 }
435 
436 static void
memo_shell_content_constructed(GObject * object)437 memo_shell_content_constructed (GObject *object)
438 {
439 	EMemoShellContent *memo_shell_content;
440 	EShellView *shell_view;
441 	EShellContent *shell_content;
442 	EShellTaskbar *shell_taskbar;
443 	ECalModel *model;
444 	GalViewInstance *view_instance;
445 	GtkTargetList *target_list;
446 	GtkTargetEntry *targets;
447 	GtkWidget *container;
448 	GtkWidget *widget;
449 	gint n_targets;
450 
451 	memo_shell_content = E_MEMO_SHELL_CONTENT (object);
452 
453 	/* Chain up to parent's constructed() method. */
454 	G_OBJECT_CLASS (e_memo_shell_content_parent_class)->constructed (object);
455 
456 	model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (memo_shell_content));
457 
458 	shell_content = E_SHELL_CONTENT (object);
459 	shell_view = e_shell_content_get_shell_view (shell_content);
460 	shell_taskbar = e_shell_view_get_shell_taskbar (shell_view);
461 
462 	/* Build content widgets. */
463 
464 	container = GTK_WIDGET (object);
465 
466 	widget = e_paned_new (GTK_ORIENTATION_VERTICAL);
467 	gtk_container_add (GTK_CONTAINER (container), widget);
468 	memo_shell_content->priv->paned = g_object_ref (widget);
469 	gtk_widget_show (widget);
470 
471 	e_binding_bind_property (
472 		object, "orientation",
473 		widget, "orientation",
474 		G_BINDING_SYNC_CREATE);
475 
476 	container = memo_shell_content->priv->paned;
477 
478 	widget = gtk_scrolled_window_new (NULL, NULL);
479 	gtk_scrolled_window_set_policy (
480 		GTK_SCROLLED_WINDOW (widget),
481 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
482 	gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE);
483 	gtk_widget_show (widget);
484 
485 	container = widget;
486 
487 	widget = e_memo_table_new (shell_view, model);
488 	gtk_container_add (GTK_CONTAINER (container), widget);
489 	memo_shell_content->priv->memo_table = g_object_ref (widget);
490 	gtk_widget_show (widget);
491 
492 	container = memo_shell_content->priv->paned;
493 
494 	widget = e_cal_component_preview_new ();
495 	gtk_widget_show (widget);
496 
497 	g_signal_connect_swapped (
498 		widget, "status-message",
499 		G_CALLBACK (e_shell_taskbar_set_message),
500 		shell_taskbar);
501 
502 	widget = e_preview_pane_new (E_WEB_VIEW (widget));
503 	gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE);
504 	memo_shell_content->priv->preview_pane = g_object_ref (widget);
505 	gtk_widget_show (widget);
506 
507 	e_binding_bind_property (
508 		object, "preview-visible",
509 		widget, "visible",
510 		G_BINDING_SYNC_CREATE);
511 
512 	target_list = gtk_target_list_new (NULL, 0);
513 	e_target_list_add_calendar_targets (target_list, 0);
514 	targets = gtk_target_table_new_from_list (target_list, &n_targets);
515 
516 	e_table_drag_source_set (
517 		E_TABLE (memo_shell_content->priv->memo_table),
518 		GDK_BUTTON1_MASK, targets, n_targets,
519 		GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK);
520 
521 	gtk_target_table_free (targets, n_targets);
522 	gtk_target_list_unref (target_list);
523 
524 	g_signal_connect_swapped (
525 		memo_shell_content->priv->memo_table, "table-drag-data-get",
526 		G_CALLBACK (memo_shell_content_table_drag_data_get_cb),
527 		object);
528 
529 	g_signal_connect_swapped (
530 		memo_shell_content->priv->memo_table, "table-drag-data-delete",
531 		G_CALLBACK (memo_shell_content_table_drag_data_delete_cb),
532 		object);
533 
534 	g_signal_connect_swapped (
535 		memo_shell_content->priv->memo_table, "cursor-change",
536 		G_CALLBACK (memo_shell_content_cursor_change_cb),
537 		object);
538 
539 	g_signal_connect_swapped (
540 		memo_shell_content->priv->memo_table, "selection-change",
541 		G_CALLBACK (memo_shell_content_selection_change_cb),
542 		object);
543 
544 	e_signal_connect_notify (
545 		memo_shell_content->priv->memo_table, "notify::is-editing",
546 		G_CALLBACK (memo_shell_content_is_editing_changed_cb), shell_view);
547 
548 	g_signal_connect_swapped (
549 		model, "model-row-changed",
550 		G_CALLBACK (memo_shell_content_model_row_changed_cb),
551 		object);
552 
553 	/* Prepare the view instance. */
554 
555 	view_instance = e_shell_view_new_view_instance (shell_view, NULL);
556 	g_signal_connect_swapped (
557 		view_instance, "display-view",
558 		G_CALLBACK (memo_shell_content_display_view_cb),
559 		object);
560 	e_shell_view_set_view_instance (shell_view, view_instance);
561 	g_object_unref (view_instance);
562 }
563 
564 static void
e_memo_shell_content_class_init(EMemoShellContentClass * class)565 e_memo_shell_content_class_init (EMemoShellContentClass *class)
566 {
567 	GObjectClass *object_class;
568 	EShellContentClass *shell_content_class;
569 	ECalBaseShellContentClass *cal_base_shell_content_class;
570 
571 	g_type_class_add_private (class, sizeof (EMemoShellContentPrivate));
572 
573 	object_class = G_OBJECT_CLASS (class);
574 	object_class->set_property = memo_shell_content_set_property;
575 	object_class->get_property = memo_shell_content_get_property;
576 	object_class->dispose = memo_shell_content_dispose;
577 	object_class->constructed = memo_shell_content_constructed;
578 
579 	shell_content_class = E_SHELL_CONTENT_CLASS (class);
580 	shell_content_class->check_state = memo_shell_content_check_state;
581 	shell_content_class->focus_search_results = memo_shell_content_focus_search_results;
582 
583 	cal_base_shell_content_class = E_CAL_BASE_SHELL_CONTENT_CLASS (class);
584 	cal_base_shell_content_class->new_cal_model = e_cal_model_memos_new;
585 	cal_base_shell_content_class->view_created = memo_shell_content_view_created;
586 
587 	g_object_class_install_property (
588 		object_class,
589 		PROP_PREVIEW_VISIBLE,
590 		g_param_spec_boolean (
591 			"preview-visible",
592 			"Preview is Visible",
593 			"Whether the preview pane is visible",
594 			TRUE,
595 			G_PARAM_READWRITE |
596 			G_PARAM_CONSTRUCT));
597 
598 	g_object_class_override_property (
599 		object_class, PROP_ORIENTATION, "orientation");
600 }
601 
602 static void
e_memo_shell_content_class_finalize(EMemoShellContentClass * class)603 e_memo_shell_content_class_finalize (EMemoShellContentClass *class)
604 {
605 }
606 
607 static void
e_memo_shell_content_init(EMemoShellContent * memo_shell_content)608 e_memo_shell_content_init (EMemoShellContent *memo_shell_content)
609 {
610 	memo_shell_content->priv = E_MEMO_SHELL_CONTENT_GET_PRIVATE (memo_shell_content);
611 
612 	/* Postpone widget construction until we have a shell view. */
613 }
614 
615 void
e_memo_shell_content_type_register(GTypeModule * type_module)616 e_memo_shell_content_type_register (GTypeModule *type_module)
617 {
618 	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
619 	 *     function, so we have to wrap it with a public function in
620 	 *     order to register types from a separate compilation unit. */
621 	e_memo_shell_content_register_type (type_module);
622 }
623 
624 GtkWidget *
e_memo_shell_content_new(EShellView * shell_view)625 e_memo_shell_content_new (EShellView *shell_view)
626 {
627 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
628 
629 	return g_object_new (
630 		E_TYPE_MEMO_SHELL_CONTENT,
631 		"shell-view", shell_view, NULL);
632 }
633 
634 EMemoTable *
e_memo_shell_content_get_memo_table(EMemoShellContent * memo_shell_content)635 e_memo_shell_content_get_memo_table (EMemoShellContent *memo_shell_content)
636 {
637 	g_return_val_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL);
638 
639 	return E_MEMO_TABLE (memo_shell_content->priv->memo_table);
640 }
641 
642 EPreviewPane *
e_memo_shell_content_get_preview_pane(EMemoShellContent * memo_shell_content)643 e_memo_shell_content_get_preview_pane (EMemoShellContent *memo_shell_content)
644 {
645 	g_return_val_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL);
646 
647 	return E_PREVIEW_PANE (memo_shell_content->priv->preview_pane);
648 }
649 
650 gboolean
e_memo_shell_content_get_preview_visible(EMemoShellContent * memo_shell_content)651 e_memo_shell_content_get_preview_visible (EMemoShellContent *memo_shell_content)
652 {
653 	g_return_val_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content), FALSE);
654 
655 	return memo_shell_content->priv->preview_visible;
656 }
657 
658 void
e_memo_shell_content_set_preview_visible(EMemoShellContent * memo_shell_content,gboolean preview_visible)659 e_memo_shell_content_set_preview_visible (EMemoShellContent *memo_shell_content,
660                                           gboolean preview_visible)
661 {
662 	g_return_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content));
663 
664 	if (memo_shell_content->priv->preview_visible == preview_visible)
665 		return;
666 
667 	memo_shell_content->priv->preview_visible = preview_visible;
668 
669 	if (preview_visible && memo_shell_content->priv->preview_pane) {
670 		memo_shell_content_cursor_change_cb (
671 			memo_shell_content, 0,
672 			E_TABLE (memo_shell_content->priv->memo_table));
673 	}
674 
675 	g_object_notify (G_OBJECT (memo_shell_content), "preview-visible");
676 }
677 
678 EShellSearchbar *
e_memo_shell_content_get_searchbar(EMemoShellContent * memo_shell_content)679 e_memo_shell_content_get_searchbar (EMemoShellContent *memo_shell_content)
680 {
681 	EShellView *shell_view;
682 	EShellContent *shell_content;
683 	GtkWidget *widget;
684 
685 	g_return_val_if_fail (E_IS_MEMO_SHELL_CONTENT (memo_shell_content), NULL);
686 
687 	shell_content = E_SHELL_CONTENT (memo_shell_content);
688 	shell_view = e_shell_content_get_shell_view (shell_content);
689 	widget = e_shell_view_get_searchbar (shell_view);
690 
691 	return E_SHELL_SEARCHBAR (widget);
692 }
693