evolution-3.6.4/calendar/gui/e-memo-table.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-memo-table.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-memo-table.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU Lesser General Public
   4  * License as published by the Free Software Foundation; either
   5  * version 2 of the License, or (at your option) version 3.
   6  *
   7  * This program is distributed in the hope that it will be useful,
   8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10  * Lesser General Public License for more details.
  11  *
  12  * You should have received a copy of the GNU Lesser General Public
  13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  14  *
  15  *
  16  * Authors:
  17  *		Damon Chaplin <damon@ximian.com>
  18  *		Rodrigo Moya <rodrigo@ximian.com>
  19  *		Nathan Owens <pianocomp81@yahoo.com>
  20  *
  21  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  22  *
  23  */
  24 
  25 /*
  26  * EMemoTable - displays the ECalComponent objects in a table (an ETable).
  27  */
  28 
  29 #ifdef HAVE_CONFIG_H
  30 #include <config.h>
  31 #endif
  32 
  33 #include <sys/stat.h>
  34 #include <unistd.h>
  35 #include <glib/gi18n.h>
  36 #include <glib/gstdio.h>
  37 #include <misc/e-selectable.h>
  38 #include <table/e-cell-checkbox.h>
  39 #include <table/e-cell-toggle.h>
  40 #include <table/e-cell-text.h>
  41 #include <table/e-cell-combo.h>
  42 #include <table/e-cell-date.h>
  43 #include <e-util/e-selection.h>
  44 #include <e-util/e-dialog-utils.h>
  45 #include <e-util/e-util-private.h>
  46 #include <table/e-cell-date-edit.h>
  47 #include <table/e-cell-percent.h>
  48 
  49 #include "dialogs/delete-comp.h"
  50 #include "dialogs/delete-error.h"
  51 #include "dialogs/memo-editor.h"
  52 #include "e-cal-model-memos.h"
  53 #include "e-memo-table.h"
  54 #include "e-calendar-view.h"
  55 #include "e-cell-date-edit-text.h"
  56 #include "print.h"
  57 #include <e-util/e-util-private.h>
  58 #include <e-util/e-icon-factory.h>
  59 #include "misc.h"
  60 
  61 #define E_MEMO_TABLE_GET_PRIVATE(obj) \
  62 	(G_TYPE_INSTANCE_GET_PRIVATE \
  63 	((obj), E_TYPE_MEMO_TABLE, EMemoTablePrivate))
  64 
  65 struct _EMemoTablePrivate {
  66 	gpointer shell_view;  /* weak pointer */
  67 	ECalModel *model;
  68 
  69 	GtkTargetList *copy_target_list;
  70 	GtkTargetList *paste_target_list;
  71 };
  72 
  73 enum {
  74 	PROP_0,
  75 	PROP_COPY_TARGET_LIST,
  76 	PROP_MODEL,
  77 	PROP_PASTE_TARGET_LIST,
  78 	PROP_SHELL_VIEW
  79 };
  80 
  81 enum {
  82 	OPEN_COMPONENT,
  83 	POPUP_EVENT,
  84 	STATUS_MESSAGE,
  85 	LAST_SIGNAL
  86 };
  87 
  88 static guint signals[LAST_SIGNAL];
  89 
  90 /* The icons to represent the task. */
  91 static const gchar *icon_names[] = {
  92 	"stock_notes",
  93 	"stock_insert-note"
  94 };
  95 
  96 /* Forward Declarations */
  97 static void	e_memo_table_selectable_init
  98 					(ESelectableInterface *interface);
  99 
 100 G_DEFINE_TYPE_WITH_CODE (
 101 	EMemoTable,
 102 	e_memo_table,
 103 	E_TYPE_TABLE,
 104 	G_IMPLEMENT_INTERFACE (
 105 		E_TYPE_SELECTABLE,
 106 		e_memo_table_selectable_init))
 107 
 108 static void
 109 memo_table_emit_open_component (EMemoTable *memo_table,
 110                                 ECalModelComponent *comp_data)
 111 {
 112 	guint signal_id = signals[OPEN_COMPONENT];
 113 
 114 	g_signal_emit (memo_table, signal_id, 0, comp_data);
 115 }
 116 
 117 static void
 118 memo_table_emit_popup_event (EMemoTable *memo_table,
 119                              GdkEvent *event)
 120 {
 121 	guint signal_id = signals[POPUP_EVENT];
 122 
 123 	g_signal_emit (memo_table, signal_id, 0, event);
 124 }
 125 
 126 static void
 127 memo_table_emit_status_message (EMemoTable *memo_table,
 128                                 const gchar *message,
 129                                 gdouble percent)
 130 {
 131 	guint signal_id = signals[STATUS_MESSAGE];
 132 
 133 	g_signal_emit (memo_table, signal_id, 0, message, percent);
 134 }
 135 
 136 /* Returns the current time, for the ECellDateEdit items.
 137  * FIXME: Should probably use the timezone of the item rather than the
 138  * current timezone, though that may be difficult to get from here. */
 139 static struct tm
 140 memo_table_get_current_time (ECellDateEdit *ecde,
 141                              gpointer user_data)
 142 {
 143 	EMemoTable *memo_table = user_data;
 144 	ECalModel *model;
 145 	icaltimezone *zone;
 146 	struct tm tmp_tm = { 0 };
 147 	struct icaltimetype tt;
 148 
 149 	/* Get the current timezone. */
 150 	model = e_memo_table_get_model (memo_table);
 151 	zone = e_cal_model_get_timezone (model);
 152 
 153 	tt = icaltime_from_timet_with_zone (time (NULL), FALSE, zone);
 154 
 155 	/* Now copy it to the struct tm and return it. */
 156 	tmp_tm.tm_year  = tt.year - 1900;
 157 	tmp_tm.tm_mon   = tt.month - 1;
 158 	tmp_tm.tm_mday  = tt.day;
 159 	tmp_tm.tm_hour  = tt.hour;
 160 	tmp_tm.tm_min   = tt.minute;
 161 	tmp_tm.tm_sec   = tt.second;
 162 	tmp_tm.tm_isdst = -1;
 163 
 164 	return tmp_tm;
 165 }
 166 
 167 static void
 168 memo_table_model_cal_view_progress_cb (EMemoTable *memo_table,
 169                                        const gchar *message,
 170                                        gint progress,
 171                                        ECalClientSourceType type)
 172 {
 173 	gdouble percent = (gdouble) progress;
 174 
 175 	memo_table_emit_status_message (memo_table, message, percent);
 176 }
 177 
 178 static void
 179 memo_table_model_cal_view_complete_cb (EMemoTable *memo_table,
 180                                        const GError *error,
 181                                        ECalClientSourceType type)
 182 {
 183 	memo_table_emit_status_message (memo_table, NULL, -1.0);
 184 }
 185 
 186 /* Deletes all of the selected components in the table */
 187 static void
 188 delete_selected_components (EMemoTable *memo_table)
 189 {
 190 	GSList *objs, *l;
 191 	const gchar *status_message;
 192 
 193 	objs = e_memo_table_get_selected (memo_table);
 194 
 195 	status_message = _("Deleting selected objects");
 196 	memo_table_emit_status_message (memo_table, status_message, -1.0);
 197 
 198 	for (l = objs; l; l = l->next) {
 199 		ECalModelComponent *comp_data = (ECalModelComponent *) l->data;
 200 		GError *error = NULL;
 201 
 202 		e_cal_client_remove_object_sync (
 203 			comp_data->client,
 204 			icalcomponent_get_uid (comp_data->icalcomp),
 205 			NULL, CALOBJ_MOD_THIS, NULL, &error);
 206 		delete_error_dialog (error, E_CAL_COMPONENT_JOURNAL);
 207 		g_clear_error (&error);
 208 	}
 209 
 210 	memo_table_emit_status_message (memo_table, NULL, -1.0);
 211 
 212 	g_slist_free (objs);
 213 }
 214 
 215 static void
 216 memo_table_set_model (EMemoTable *memo_table,
 217                       ECalModel *model)
 218 {
 219 	g_return_if_fail (memo_table->priv->model == NULL);
 220 
 221 	memo_table->priv->model = g_object_ref (model);
 222 
 223 	g_signal_connect_swapped (
 224 		model, "cal-view-progress",
 225 		G_CALLBACK (memo_table_model_cal_view_progress_cb),
 226 		memo_table);
 227 
 228 	g_signal_connect_swapped (
 229 		model, "cal-view-complete",
 230 		G_CALLBACK (memo_table_model_cal_view_complete_cb),
 231 		memo_table);
 232 }
 233 
 234 static void
 235 memo_table_set_shell_view (EMemoTable *memo_table,
 236                            EShellView *shell_view)
 237 {
 238 	g_return_if_fail (memo_table->priv->shell_view == NULL);
 239 
 240 	memo_table->priv->shell_view = shell_view;
 241 
 242 	g_object_add_weak_pointer (
 243 		G_OBJECT (shell_view),
 244 		&memo_table->priv->shell_view);
 245 }
 246 
 247 static void
 248 memo_table_set_property (GObject *object,
 249                          guint property_id,
 250                          const GValue *value,
 251                          GParamSpec *pspec)
 252 {
 253 	switch (property_id) {
 254 		case PROP_MODEL:
 255 			memo_table_set_model (
 256 				E_MEMO_TABLE (object),
 257 				g_value_get_object (value));
 258 			return;
 259 
 260 		case PROP_SHELL_VIEW:
 261 			memo_table_set_shell_view (
 262 				E_MEMO_TABLE (object),
 263 				g_value_get_object (value));
 264 			return;
 265 	}
 266 
 267 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 268 }
 269 
 270 static void
 271 memo_table_get_property (GObject *object,
 272                          guint property_id,
 273                          GValue *value,
 274                          GParamSpec *pspec)
 275 {
 276 	switch (property_id) {
 277 		case PROP_COPY_TARGET_LIST:
 278 			g_value_set_boxed (
 279 				value, e_memo_table_get_copy_target_list (
 280 				E_MEMO_TABLE (object)));
 281 			return;
 282 
 283 		case PROP_MODEL:
 284 			g_value_set_object (
 285 				value, e_memo_table_get_model (
 286 				E_MEMO_TABLE (object)));
 287 			return;
 288 
 289 		case PROP_PASTE_TARGET_LIST:
 290 			g_value_set_boxed (
 291 				value, e_memo_table_get_paste_target_list (
 292 				E_MEMO_TABLE (object)));
 293 			return;
 294 
 295 		case PROP_SHELL_VIEW:
 296 			g_value_set_object (
 297 				value, e_memo_table_get_shell_view (
 298 				E_MEMO_TABLE (object)));
 299 			return;
 300 	}
 301 
 302 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 303 }
 304 
 305 static void
 306 memo_table_dispose (GObject *object)
 307 {
 308 	EMemoTablePrivate *priv;
 309 
 310 	priv = E_MEMO_TABLE_GET_PRIVATE (object);
 311 
 312 	if (priv->shell_view != NULL) {
 313 		g_object_remove_weak_pointer (
 314 			G_OBJECT (priv->shell_view), &priv->shell_view);
 315 		priv->shell_view = NULL;
 316 	}
 317 
 318 	if (priv->model != NULL) {
 319 		g_object_unref (priv->model);
 320 		priv->model = NULL;
 321 	}
 322 
 323 	if (priv->copy_target_list != NULL) {
 324 		gtk_target_list_unref (priv->copy_target_list);
 325 		priv->copy_target_list = NULL;
 326 	}
 327 
 328 	if (priv->paste_target_list != NULL) {
 329 		gtk_target_list_unref (priv->paste_target_list);
 330 		priv->paste_target_list = NULL;
 331 	}
 332 
 333 	/* Chain up to parent's dispose() method. */
 334 	G_OBJECT_CLASS (e_memo_table_parent_class)->dispose (object);
 335 }
 336 
 337 static void
 338 memo_table_constructed (GObject *object)
 339 {
 340 	EMemoTable *memo_table;
 341 	ECalModel *model;
 342 	ECell *cell, *popup_cell;
 343 	ETableExtras *extras;
 344 	AtkObject *a11y;
 345 	gchar *etspecfile;
 346 
 347 	memo_table = E_MEMO_TABLE (object);
 348 	model = e_memo_table_get_model (memo_table);
 349 
 350 	/* Create the header columns */
 351 
 352 	extras = e_table_extras_new ();
 353 
 354 	/*
 355 	 * Normal string fields.
 356 	 */
 357 	cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
 358 	g_object_set (cell, "bg_color_column", E_CAL_MODEL_FIELD_COLOR, NULL);
 359 	e_table_extras_add_cell (extras, "calstring", cell);
 360 	g_object_unref (cell);
 361 
 362 	/*
 363 	 * Date fields.
 364 	 */
 365 	cell = e_cell_date_edit_text_new (NULL, GTK_JUSTIFY_LEFT);
 366 	g_object_set (cell, "bg_color_column", E_CAL_MODEL_FIELD_COLOR, NULL);
 367 
 368 	g_object_bind_property (
 369 		model, "timezone",
 370 		cell, "timezone",
 371 		G_BINDING_BIDIRECTIONAL |
 372 		G_BINDING_SYNC_CREATE);
 373 
 374 	g_object_bind_property (
 375 		model, "use-24-hour-format",
 376 		cell, "use-24-hour-format",
 377 		G_BINDING_BIDIRECTIONAL |
 378 		G_BINDING_SYNC_CREATE);
 379 
 380 	popup_cell = e_cell_date_edit_new ();
 381 	e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
 382 	g_object_unref (cell);
 383 
 384 	g_object_bind_property (
 385 		model, "use-24-hour-format",
 386 		popup_cell, "use-24-hour-format",
 387 		G_BINDING_BIDIRECTIONAL |
 388 		G_BINDING_SYNC_CREATE);
 389 
 390 	e_table_extras_add_cell (extras, "dateedit", popup_cell);
 391 	g_object_unref (popup_cell);
 392 	memo_table->dates_cell = E_CELL_DATE_EDIT (popup_cell);
 393 
 394 	e_cell_date_edit_set_get_time_callback (
 395 		E_CELL_DATE_EDIT (popup_cell),
 396 		memo_table_get_current_time, memo_table, NULL);
 397 
 398 	/* Sorting */
 399 	e_table_extras_add_compare (
 400 		extras, "date-compare", e_cell_date_edit_compare_cb);
 401 
 402 	/* Create pixmaps */
 403 
 404 	cell = e_cell_toggle_new (icon_names, G_N_ELEMENTS (icon_names));
 405 	e_table_extras_add_cell (extras, "icon", cell);
 406 	g_object_unref (cell);
 407 
 408 	e_table_extras_add_icon_name (extras, "icon", "stock_notes");
 409 
 410 	/* set proper format component for a default 'date' cell renderer */
 411 	cell = e_table_extras_get_cell (extras, "date");
 412 	e_cell_date_set_format_component (E_CELL_DATE (cell), "calendar");
 413 
 414 	/* set proper format component for a default 'date' cell renderer */
 415 	cell = e_table_extras_get_cell (extras, "date");
 416 	e_cell_date_set_format_component (E_CELL_DATE (cell), "calendar");
 417 
 418 	/* Construct the table */
 419 
 420 	etspecfile = g_build_filename (
 421 		EVOLUTION_ETSPECDIR, "e-memo-table.etspec", NULL);
 422 	e_table_construct_from_spec_file (
 423 		E_TABLE (memo_table), E_TABLE_MODEL (model),
 424 		extras, etspecfile, NULL);
 425 	g_free (etspecfile);
 426 
 427 	gtk_widget_set_has_tooltip (GTK_WIDGET (memo_table), TRUE);
 428 
 429 	g_object_unref (extras);
 430 
 431 	a11y = gtk_widget_get_accessible (GTK_WIDGET (memo_table));
 432 	if (a11y)
 433 		atk_object_set_name (a11y, _("Memos"));
 434 
 435 	/* Chain up to parent's constructed() method. */
 436 	G_OBJECT_CLASS (e_memo_table_parent_class)->constructed (object);
 437 }
 438 
 439 static gboolean
 440 memo_table_popup_menu (GtkWidget *widget)
 441 {
 442 	EMemoTable *memo_table;
 443 
 444 	memo_table = E_MEMO_TABLE (widget);
 445 	memo_table_emit_popup_event (memo_table, NULL);
 446 
 447 	return TRUE;
 448 }
 449 
 450 static gboolean
 451 memo_table_query_tooltip (GtkWidget *widget,
 452                           gint x,
 453                           gint y,
 454                           gboolean keyboard_mode,
 455                           GtkTooltip *tooltip)
 456 {
 457 	EMemoTable *memo_table;
 458 	ECalModel *model;
 459 	ECalModelComponent *comp_data;
 460 	gint row = -1, col = -1;
 461 	GtkWidget *box, *l, *w;
 462 	GtkStyle *style = gtk_widget_get_default_style ();
 463 	gchar *tmp;
 464 	const gchar *str;
 465 	GString *tmp2;
 466 	gchar buff[1001];
 467 	gboolean free_text = FALSE;
 468 	gboolean use_24_hour_format;
 469 	ECalComponent *new_comp;
 470 	ECalComponentOrganizer organizer;
 471 	ECalComponentDateTime dtstart, dtdue;
 472 	icalcomponent *clone;
 473 	icaltimezone *zone, *default_zone;
 474 	GSList *desc, *p;
 475 	gint len;
 476 	ESelectionModel *esm;
 477 	struct tm tmp_tm;
 478 
 479 	if (keyboard_mode)
 480 		return FALSE;
 481 
 482 	memo_table = E_MEMO_TABLE (widget);
 483 
 484 	e_table_get_mouse_over_cell (E_TABLE (memo_table), &row, &col);
 485 	if (row == -1)
 486 		return FALSE;
 487 
 488 	/* Respect sorting option; the 'e_table_get_mouse_over_cell'
 489 	 * returns sorted row, not the model one. */
 490 	esm = e_table_get_selection_model (E_TABLE (memo_table));
 491 	if (esm && esm->sorter && e_sorter_needs_sorting (esm->sorter))
 492 		row = e_sorter_sorted_to_model (esm->sorter, row);
 493 
 494 	model = e_memo_table_get_model (memo_table);
 495 	comp_data = e_cal_model_get_component_at (model, row);
 496 	if (!comp_data || !comp_data->icalcomp)
 497 		return FALSE;
 498 
 499 	new_comp = e_cal_component_new ();
 500 	clone = icalcomponent_new_clone (comp_data->icalcomp);
 501 	if (!e_cal_component_set_icalcomponent (new_comp, clone)) {
 502 		g_object_unref (new_comp);
 503 		return FALSE;
 504 	}
 505 
 506 	box = gtk_vbox_new (FALSE, 0);
 507 
 508 	str = e_calendar_view_get_icalcomponent_summary (
 509 		comp_data->client, comp_data->icalcomp, &free_text);
 510 	if (!(str && *str)) {
 511 		if (free_text)
 512 			g_free ((gchar *) str);
 513 		free_text = FALSE;
 514 		str = _("* No Summary *");
 515 	}
 516 
 517 	l = gtk_label_new (NULL);
 518 	tmp = g_markup_printf_escaped ("<b>%s</b>", str);
 519 	gtk_label_set_line_wrap (GTK_LABEL (l), TRUE);
 520 	gtk_label_set_markup (GTK_LABEL (l), tmp);
 521 	gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
 522 	w = gtk_event_box_new ();
 523 
 524 	gtk_widget_modify_bg (w, GTK_STATE_NORMAL, &(style->bg[GTK_STATE_SELECTED]));
 525 	gtk_widget_modify_fg (l, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED]));
 526 	gtk_container_add (GTK_CONTAINER (w), l);
 527 	gtk_box_pack_start (GTK_BOX (box), w, TRUE, TRUE, 0);
 528 	g_free (tmp);
 529 
 530 	if (free_text)
 531 		g_free ((gchar *) str);
 532 	free_text = FALSE;
 533 
 534 	w = gtk_event_box_new ();
 535 	gtk_widget_modify_bg (w, GTK_STATE_NORMAL, &(style->bg[GTK_STATE_NORMAL]));
 536 
 537 	l = gtk_vbox_new (FALSE, 0);
 538 	gtk_container_add (GTK_CONTAINER (w), l);
 539 	gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
 540 	w = l;
 541 
 542 	e_cal_component_get_organizer (new_comp, &organizer);
 543 	if (organizer.cn) {
 544 		gchar *ptr;
 545 		ptr = strchr (organizer.value, ':');
 546 
 547 		if (ptr) {
 548 			ptr++;
 549 			/* Translators: It will display
 550 			 * "Organizer: NameOfTheUser <email@ofuser.com>" */
 551 			tmp = g_strdup_printf (
 552 				_("Organizer: %s <%s>"), organizer.cn, ptr);
 553 		} else {
 554 			/* With SunOne accounts, there may be no ':' in
 555 			 * organizer.value */
 556 			tmp = g_strdup_printf (
 557 				_("Organizer: %s"), organizer.cn);
 558 		}
 559 
 560 		l = gtk_label_new (tmp);
 561 		gtk_label_set_line_wrap (GTK_LABEL (l), FALSE);
 562 		gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
 563 		gtk_box_pack_start (GTK_BOX (w), l, FALSE, FALSE, 0);
 564 		g_free (tmp);
 565 
 566 		gtk_widget_modify_fg (l, GTK_STATE_NORMAL, &(style->text[GTK_STATE_NORMAL]));
 567 	}
 568 
 569 	e_cal_component_get_dtstart (new_comp, &dtstart);
 570 	e_cal_component_get_due (new_comp, &dtdue);
 571 
 572 	default_zone = e_cal_model_get_timezone (model);
 573 
 574 	if (dtstart.tzid) {
 575 		zone = icalcomponent_get_timezone (
 576 			e_cal_component_get_icalcomponent (new_comp),
 577 			dtstart.tzid);
 578 		if (!zone)
 579 			e_cal_client_get_timezone_sync (
 580 				comp_data->client, dtstart.tzid, &zone, NULL, NULL);
 581 		if (!zone)
 582 			zone = default_zone;
 583 	} else {
 584 		zone = NULL;
 585 	}
 586 
 587 	tmp2 = g_string_new ("");
 588 	use_24_hour_format = e_cal_model_get_use_24_hour_format (model);
 589 
 590 	if (dtstart.value) {
 591 		buff[0] = 0;
 592 
 593 		tmp_tm = icaltimetype_to_tm_with_zone (
 594 			dtstart.value, zone, default_zone);
 595 		e_time_format_date_and_time (
 596 			&tmp_tm, use_24_hour_format,
 597 			FALSE, FALSE, buff, 1000);
 598 
 599 		if (buff[0]) {
 600 			/* Translators: This is followed by an event's start date/time */
 601 			g_string_append (tmp2, _("Start: "));
 602 			g_string_append (tmp2, buff);
 603 		}
 604 	}
 605 
 606 	if (dtdue.value) {
 607 		buff[0] = 0;
 608 
 609 		tmp_tm = icaltimetype_to_tm_with_zone (
 610 			dtdue.value, zone, default_zone);
 611 		e_time_format_date_and_time (
 612 			&tmp_tm, use_24_hour_format,
 613 			FALSE, FALSE, buff, 1000);
 614 
 615 		if (buff[0]) {
 616 			if (tmp2->len)
 617 				g_string_append (tmp2, "; ");
 618 
 619 			/* Translators: This is followed by an event's due date/time */
 620 			g_string_append (tmp2, _("Due: "));
 621 			g_string_append (tmp2, buff);
 622 		}
 623 	}
 624 
 625 	if (tmp2->len) {
 626 		l = gtk_label_new (tmp2->str);
 627 		gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
 628 		gtk_box_pack_start (GTK_BOX (w), l, FALSE, FALSE, 0);
 629 
 630 		gtk_widget_modify_fg (l, GTK_STATE_NORMAL, &(style->text[GTK_STATE_NORMAL]));
 631 	}
 632 
 633 	g_string_free (tmp2, TRUE);
 634 
 635 	e_cal_component_free_datetime (&dtstart);
 636 	e_cal_component_free_datetime (&dtdue);
 637 
 638 	tmp2 = g_string_new ("");
 639 	e_cal_component_get_description_list (new_comp, &desc);
 640 	for (len = 0, p = desc; p != NULL; p = p->next) {
 641 		ECalComponentText *text = p->data;
 642 
 643 		if (text->value != NULL) {
 644 			len += strlen (text->value);
 645 			g_string_append (tmp2, text->value);
 646 			if (len > 1024) {
 647 				g_string_set_size (tmp2, 1020);
 648 				g_string_append (tmp2, "...");
 649 				break;
 650 			}
 651 		}
 652 	}
 653 	e_cal_component_free_text_list (desc);
 654 
 655 	if (tmp2->len) {
 656 		l = gtk_label_new (tmp2->str);
 657 		gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
 658 		gtk_box_pack_start (GTK_BOX (w), l, FALSE, FALSE, 0);
 659 
 660 		gtk_widget_modify_fg (l, GTK_STATE_NORMAL, &(style->text[GTK_STATE_NORMAL]));
 661 	}
 662 
 663 	g_string_free (tmp2, TRUE);
 664 
 665 	gtk_widget_show_all (box);
 666 	gtk_tooltip_set_custom (tooltip, box);
 667 
 668 	g_object_unref (new_comp);
 669 
 670 	return TRUE;
 671 }
 672 
 673 static void
 674 memo_table_double_click (ETable *table,
 675                          gint row,
 676                          gint col,
 677                          GdkEvent *event)
 678 {
 679 	EMemoTable *memo_table;
 680 	ECalModel *model;
 681 	ECalModelComponent *comp_data;
 682 
 683 	memo_table = E_MEMO_TABLE (table);
 684 	model = e_memo_table_get_model (memo_table);
 685 	comp_data = e_cal_model_get_component_at (model, row);
 686 	memo_table_emit_open_component (memo_table, comp_data);
 687 }
 688 
 689 static gint
 690 memo_table_right_click (ETable *table,
 691                         gint row,
 692                         gint col,
 693                         GdkEvent *event)
 694 {
 695 	EMemoTable *memo_table;
 696 
 697 	memo_table = E_MEMO_TABLE (table);
 698 	memo_table_emit_popup_event (memo_table, event);
 699 
 700 	return TRUE;
 701 }
 702 
 703 static void
 704 memo_table_update_actions (ESelectable *selectable,
 705                            EFocusTracker *focus_tracker,
 706                            GdkAtom *clipboard_targets,
 707                            gint n_clipboard_targets)
 708 {
 709 	EMemoTable *memo_table;
 710 	GtkAction *action;
 711 	GtkTargetList *target_list;
 712 	GSList *list, *iter;
 713 	gboolean can_paste = FALSE;
 714 	gboolean sources_are_editable = TRUE;
 715 	gboolean sensitive;
 716 	const gchar *tooltip;
 717 	gint n_selected;
 718 	gint ii;
 719 
 720 	memo_table = E_MEMO_TABLE (selectable);
 721 	n_selected = e_table_selected_count (E_TABLE (memo_table));
 722 
 723 	list = e_memo_table_get_selected (memo_table);
 724 	for (iter = list; iter != NULL && sources_are_editable; iter = iter->next) {
 725 		ECalModelComponent *comp_data = iter->data;
 726 
 727 		sources_are_editable = sources_are_editable &&
 728 			!e_client_is_readonly (E_CLIENT (comp_data->client));
 729 	}
 730 	g_slist_free (list);
 731 
 732 	target_list = e_selectable_get_paste_target_list (selectable);
 733 	for (ii = 0; ii < n_clipboard_targets && !can_paste; ii++)
 734 		can_paste = gtk_target_list_find (
 735 			target_list, clipboard_targets[ii], NULL);
 736 
 737 	action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
 738 	sensitive = (n_selected > 0) && sources_are_editable;
 739 	tooltip = _("Cut selected memos to the clipboard");
 740 	gtk_action_set_sensitive (action, sensitive);
 741 	gtk_action_set_tooltip (action, tooltip);
 742 
 743 	action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
 744 	sensitive = (n_selected > 0);
 745 	tooltip = _("Copy selected memos to the clipboard");
 746 	gtk_action_set_sensitive (action, sensitive);
 747 	gtk_action_set_tooltip (action, tooltip);
 748 
 749 	action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
 750 	sensitive = sources_are_editable && can_paste;
 751 	tooltip = _("Paste memos from the clipboard");
 752 	gtk_action_set_sensitive (action, sensitive);
 753 	gtk_action_set_tooltip (action, tooltip);
 754 
 755 	action = e_focus_tracker_get_delete_selection_action (focus_tracker);
 756 	sensitive = (n_selected > 0) && sources_are_editable;
 757 	tooltip = _("Delete selected memos");
 758 	gtk_action_set_sensitive (action, sensitive);
 759 	gtk_action_set_tooltip (action, tooltip);
 760 
 761 	action = e_focus_tracker_get_select_all_action (focus_tracker);
 762 	sensitive = TRUE;
 763 	tooltip = _("Select all visible memos");
 764 	gtk_action_set_sensitive (action, sensitive);
 765 	gtk_action_set_tooltip (action, tooltip);
 766 }
 767 
 768 static void
 769 memo_table_cut_clipboard (ESelectable *selectable)
 770 {
 771 	EMemoTable *memo_table;
 772 
 773 	memo_table = E_MEMO_TABLE (selectable);
 774 
 775 	e_selectable_copy_clipboard (selectable);
 776 	delete_selected_components (memo_table);
 777 }
 778 
 779 /* Helper for memo_table_copy_clipboard() */
 780 static void
 781 copy_row_cb (gint model_row,
 782              gpointer data)
 783 {
 784 	EMemoTable *memo_table;
 785 	ECalModelComponent *comp_data;
 786 	ECalModel *model;
 787 	gchar *comp_str;
 788 	icalcomponent *child;
 789 
 790 	memo_table = E_MEMO_TABLE (data);
 791 
 792 	g_return_if_fail (memo_table->tmp_vcal != NULL);
 793 
 794 	model = e_memo_table_get_model (memo_table);
 795 	comp_data = e_cal_model_get_component_at (model, model_row);
 796 	if (comp_data == NULL)
 797 		return;
 798 
 799 	/* Add timezones to the VCALENDAR component. */
 800 	e_cal_util_add_timezones_from_component (
 801 		memo_table->tmp_vcal, comp_data->icalcomp);
 802 
 803 	/* Add the new component to the VCALENDAR component. */
 804 	comp_str = icalcomponent_as_ical_string_r (comp_data->icalcomp);
 805 	child = icalparser_parse_string (comp_str);
 806 	if (child) {
 807 		icalcomponent_add_component (
 808 			memo_table->tmp_vcal,
 809 			icalcomponent_new_clone (child));
 810 		icalcomponent_free (child);
 811 	}
 812 	g_free (comp_str);
 813 }
 814 
 815 static void
 816 memo_table_copy_clipboard (ESelectable *selectable)
 817 {
 818 	EMemoTable *memo_table;
 819 	GtkClipboard *clipboard;
 820 	gchar *comp_str;
 821 
 822 	memo_table = E_MEMO_TABLE (selectable);
 823 
 824 	/* Create a temporary VCALENDAR object. */
 825 	memo_table->tmp_vcal = e_cal_util_new_top_level ();
 826 
 827 	e_table_selected_row_foreach (
 828 		E_TABLE (memo_table), copy_row_cb, memo_table);
 829 	comp_str = icalcomponent_as_ical_string_r (memo_table->tmp_vcal);
 830 
 831 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
 832 	e_clipboard_set_calendar (clipboard, comp_str, -1);
 833 	gtk_clipboard_store (clipboard);
 834 
 835 	g_free (comp_str);
 836 
 837 	icalcomponent_free (memo_table->tmp_vcal);
 838 	memo_table->tmp_vcal = NULL;
 839 }
 840 
 841 /* Helper for memo_table_paste_clipboard() */
 842 static void
 843 clipboard_get_calendar_data (EMemoTable *memo_table,
 844                              const gchar *text)
 845 {
 846 	icalcomponent *icalcomp;
 847 	gchar *uid;
 848 	ECalComponent *comp;
 849 	ECalClient *client;
 850 	ECalModel *model;
 851 	icalcomponent_kind kind;
 852 	const gchar *status_message;
 853 
 854 	g_return_if_fail (E_IS_MEMO_TABLE (memo_table));
 855 
 856 	if (!text || !*text)
 857 		return;
 858 
 859 	icalcomp = icalparser_parse_string (text);
 860 	if (!icalcomp)
 861 		return;
 862 
 863 	/* check the type of the component */
 864 	kind = icalcomponent_isa (icalcomp);
 865 	if (kind != ICAL_VCALENDAR_COMPONENT &&
 866 	    kind != ICAL_VEVENT_COMPONENT &&
 867 	    kind != ICAL_VTODO_COMPONENT &&
 868 	    kind != ICAL_VJOURNAL_COMPONENT) {
 869 		return;
 870 	}
 871 
 872 	model = e_memo_table_get_model (memo_table);
 873 	client = e_cal_model_get_default_client (model);
 874 
 875 	status_message = _("Updating objects");
 876 	memo_table_emit_status_message (memo_table, status_message, -1.0);
 877 
 878 	if (kind == ICAL_VCALENDAR_COMPONENT) {
 879 		icalcomponent_kind child_kind;
 880 		icalcomponent *subcomp;
 881 		icalcomponent *vcal_comp;
 882 
 883 		vcal_comp = icalcomp;
 884 		subcomp = icalcomponent_get_first_component (
 885 			vcal_comp, ICAL_ANY_COMPONENT);
 886 		while (subcomp) {
 887 			child_kind = icalcomponent_isa (subcomp);
 888 			if (child_kind == ICAL_VEVENT_COMPONENT ||
 889 			    child_kind == ICAL_VTODO_COMPONENT ||
 890 			    child_kind == ICAL_VJOURNAL_COMPONENT) {
 891 				ECalComponent *tmp_comp;
 892 				GError *error = NULL;
 893 
 894 				uid = e_cal_component_gen_uid ();
 895 				tmp_comp = e_cal_component_new ();
 896 				e_cal_component_set_icalcomponent (
 897 					tmp_comp,
 898 					icalcomponent_new_clone (subcomp));
 899 				e_cal_component_set_uid (tmp_comp, uid);
 900 				g_free (uid);
 901 				uid = NULL;
 902 
 903 				/* FIXME Should we convert start/due/complete
 904 				 *       times?  Also, need error handling.*/
 905 				if (!e_cal_client_create_object_sync (client, e_cal_component_get_icalcomponent (tmp_comp), &uid, NULL, &error))
 906 					uid = NULL;
 907 
 908 				g_free (uid);
 909 				g_object_unref (tmp_comp);
 910 
 911 				if (error != NULL) {
 912 					g_warning (
 913 						"%s: Failed to create object: %s",
 914 						G_STRFUNC, error->message);
 915 					g_error_free (error);
 916 				}
 917 			}
 918 			subcomp = icalcomponent_get_next_component (
 919 				vcal_comp, ICAL_ANY_COMPONENT);
 920 		}
 921 	} else {
 922 		GError *error = NULL;
 923 
 924 		comp = e_cal_component_new ();
 925 		e_cal_component_set_icalcomponent (comp, icalcomp);
 926 		uid = e_cal_component_gen_uid ();
 927 		e_cal_component_set_uid (comp, (const gchar *) uid);
 928 		g_free (uid);
 929 
 930 		uid = NULL;
 931 		if (!e_cal_client_create_object_sync (client, e_cal_component_get_icalcomponent (comp), &uid, NULL, &error))
 932 			uid = NULL;
 933 
 934 		g_free (uid);
 935 		g_object_unref (comp);
 936 
 937 		if (error != NULL) {
 938 			g_warning (
 939 				"%s: Failed to create object: %s",
 940 				G_STRFUNC, error->message);
 941 			g_error_free (error);
 942 		}
 943 	}
 944 
 945 	memo_table_emit_status_message (memo_table, NULL, -1.0);
 946 }
 947 
 948 static void
 949 memo_table_paste_clipboard (ESelectable *selectable)
 950 {
 951 	EMemoTable *memo_table;
 952 	GtkClipboard *clipboard;
 953 	GnomeCanvasItem *item;
 954 	GnomeCanvas *table_canvas;
 955 
 956 	memo_table = E_MEMO_TABLE (selectable);
 957 
 958 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
 959 
 960 	table_canvas = E_TABLE (memo_table)->table_canvas;
 961 	item = table_canvas->focused_item;
 962 
 963 	/* XXX Should ECellText implement GtkEditable? */
 964 
 965 	/* Paste text into a cell being edited. */
 966 	if (gtk_clipboard_wait_is_text_available (clipboard) &&
 967 		gtk_widget_has_focus (GTK_WIDGET (table_canvas)) &&
 968 		E_IS_TABLE_ITEM (item) &&
 969 		E_TABLE_ITEM (item)->editing_col >= 0 &&
 970 		E_TABLE_ITEM (item)->editing_row >= 0) {
 971 
 972 		ETableItem *etable_item = E_TABLE_ITEM (item);
 973 
 974 		e_cell_text_paste_clipboard (
 975 			etable_item->cell_views[etable_item->editing_col],
 976 			etable_item->editing_col,
 977 			etable_item->editing_row);
 978 
 979 	/* Paste iCalendar data into the table. */
 980 	} else if (e_clipboard_wait_is_calendar_available (clipboard)) {
 981 		gchar *calendar_source;
 982 
 983 		calendar_source = e_clipboard_wait_for_calendar (clipboard);
 984 		clipboard_get_calendar_data (memo_table, calendar_source);
 985 		g_free (calendar_source);
 986 	}
 987 }
 988 
 989 /* Used from e_table_selected_row_foreach(); puts the selected row number in an
 990  * gint pointed to by the closure data.
 991  */
 992 static void
 993 get_selected_row_cb (gint model_row,
 994                      gpointer data)
 995 {
 996 	gint *row;
 997 
 998 	row = data;
 999 	*row = model_row;
1000 }
1001 
1002 /*
1003  * Returns the component that is selected in the table; only works if there is
1004  * one and only one selected row.
1005  */
1006 static ECalModelComponent *
1007 get_selected_comp (EMemoTable *memo_table)
1008 {
1009 	ECalModel *model;
1010 	gint row;
1011 
1012 	model = e_memo_table_get_model (memo_table);
1013 	if (e_table_selected_count (E_TABLE (memo_table)) != 1)
1014 		return NULL;
1015 
1016 	row = -1;
1017 	e_table_selected_row_foreach (
1018 		E_TABLE (memo_table), get_selected_row_cb, &row);
1019 	g_return_val_if_fail (row != -1, NULL);
1020 
1021 	return e_cal_model_get_component_at (model, row);
1022 }
1023 
1024 static void
1025 memo_table_delete_selection (ESelectable *selectable)
1026 {
1027 	ECalModel *model;
1028 	EMemoTable *memo_table;
1029 	ECalComponent *comp = NULL;
1030 	ECalModelComponent *comp_data;
1031 	gboolean delete = TRUE;
1032 	gint n_selected;
1033 
1034 	memo_table = E_MEMO_TABLE (selectable);
1035 	model = e_memo_table_get_model (memo_table);
1036 
1037 	n_selected = e_table_selected_count (E_TABLE (memo_table));
1038 	if (n_selected <= 0)
1039 		return;
1040 
1041 	if (n_selected == 1)
1042 		comp_data = get_selected_comp (memo_table);
1043 	else
1044 		comp_data = NULL;
1045 
1046 	/* FIXME: this may be something other than a TODO component */
1047 
1048 	if (comp_data) {
1049 		comp = e_cal_component_new ();
1050 		e_cal_component_set_icalcomponent (
1051 			comp, icalcomponent_new_clone (comp_data->icalcomp));
1052 	}
1053 
1054 	if (e_cal_model_get_confirm_delete (model))
1055 		delete = delete_component_dialog (
1056 			comp, FALSE, n_selected,
1057 			E_CAL_COMPONENT_JOURNAL,
1058 			GTK_WIDGET (memo_table));
1059 
1060 	if (delete)
1061 		delete_selected_components (memo_table);
1062 
1063 	/* free memory */
1064 	if (comp)
1065 		g_object_unref (comp);
1066 }
1067 
1068 static void
1069 memo_table_select_all (ESelectable *selectable)
1070 {
1071 	e_table_select_all (E_TABLE (selectable));
1072 }
1073 
1074 static void
1075 e_memo_table_class_init (EMemoTableClass *class)
1076 {
1077 	GObjectClass *object_class;
1078 	GtkWidgetClass *widget_class;
1079 	ETableClass *table_class;
1080 
1081 	g_type_class_add_private (class, sizeof (EMemoTablePrivate));
1082 
1083 	object_class = G_OBJECT_CLASS (class);
1084 	object_class->set_property = memo_table_set_property;
1085 	object_class->get_property = memo_table_get_property;
1086 	object_class->dispose = memo_table_dispose;
1087 	object_class->constructed = memo_table_constructed;
1088 
1089 	widget_class = GTK_WIDGET_CLASS (class);
1090 	widget_class->popup_menu = memo_table_popup_menu;
1091 	widget_class->query_tooltip = memo_table_query_tooltip;
1092 
1093 	table_class = E_TABLE_CLASS (class);
1094 	table_class->double_click = memo_table_double_click;
1095 	table_class->right_click = memo_table_right_click;
1096 
1097 	/* Inherited from ESelectableInterface */
1098 	g_object_class_override_property (
1099 		object_class,
1100 		PROP_COPY_TARGET_LIST,
1101 		"copy-target-list");
1102 
1103 	g_object_class_install_property (
1104 		object_class,
1105 		PROP_MODEL,
1106 		g_param_spec_object (
1107 			"model",
1108 			"Model",
1109 			NULL,
1110 			E_TYPE_CAL_MODEL,
1111 			G_PARAM_READWRITE |
1112 			G_PARAM_CONSTRUCT_ONLY));
1113 
1114 	/* Inherited from ESelectableInterface */
1115 	g_object_class_override_property (
1116 		object_class,
1117 		PROP_PASTE_TARGET_LIST,
1118 		"paste-target-list");
1119 
1120 	g_object_class_install_property (
1121 		object_class,
1122 		PROP_SHELL_VIEW,
1123 		g_param_spec_object (
1124 			"shell-view",
1125 			"Shell View",
1126 			NULL,
1127 			E_TYPE_SHELL_VIEW,
1128 			G_PARAM_READWRITE |
1129 			G_PARAM_CONSTRUCT_ONLY));
1130 
1131 	signals[OPEN_COMPONENT] = g_signal_new (
1132 		"open-component",
1133 		G_TYPE_FROM_CLASS (class),
1134 		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1135 		G_STRUCT_OFFSET (EMemoTableClass, open_component),
1136 		NULL, NULL,
1137 		g_cclosure_marshal_VOID__OBJECT,
1138 		G_TYPE_NONE, 1,
1139 		E_TYPE_CAL_MODEL_COMPONENT);
1140 
1141 	signals[POPUP_EVENT] = g_signal_new (
1142 		"popup-event",
1143 		G_TYPE_FROM_CLASS (class),
1144 		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1145 		G_STRUCT_OFFSET (EMemoTableClass, popup_event),
1146 		NULL, NULL,
1147 		g_cclosure_marshal_VOID__BOXED,
1148 		G_TYPE_NONE, 1,
1149 		GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
1150 
1151 	signals[STATUS_MESSAGE] = g_signal_new (
1152 		"status-message",
1153 		G_TYPE_FROM_CLASS (class),
1154 		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1155 		G_STRUCT_OFFSET (EMemoTableClass, status_message),
1156 		NULL, NULL,
1157 		e_marshal_VOID__STRING_DOUBLE,
1158 		G_TYPE_NONE, 2,
1159 		G_TYPE_STRING, G_TYPE_DOUBLE);
1160 }
1161 
1162 static void
1163 e_memo_table_init (EMemoTable *memo_table)
1164 {
1165 	GtkTargetList *target_list;
1166 
1167 	memo_table->priv = E_MEMO_TABLE_GET_PRIVATE (memo_table);
1168 
1169 	target_list = gtk_target_list_new (NULL, 0);
1170 	e_target_list_add_calendar_targets (target_list, 0);
1171 	memo_table->priv->copy_target_list = target_list;
1172 
1173 	target_list = gtk_target_list_new (NULL, 0);
1174 	e_target_list_add_calendar_targets (target_list, 0);
1175 	memo_table->priv->paste_target_list = target_list;
1176 }
1177 
1178 static void
1179 e_memo_table_selectable_init (ESelectableInterface *interface)
1180 {
1181 	interface->update_actions = memo_table_update_actions;
1182 	interface->cut_clipboard = memo_table_cut_clipboard;
1183 	interface->copy_clipboard = memo_table_copy_clipboard;
1184 	interface->paste_clipboard = memo_table_paste_clipboard;
1185 	interface->delete_selection = memo_table_delete_selection;
1186 	interface->select_all = memo_table_select_all;
1187 }
1188 
1189 /**
1190  * e_memo_table_new:
1191  * @shell_view: an #EShellView
1192  * @model: an #ECalModel for the table
1193  *
1194  * Returns a new #EMemoTable.
1195  *
1196  * Returns: a new #EMemoTable
1197  **/
1198 GtkWidget *
1199 e_memo_table_new (EShellView *shell_view,
1200                   ECalModel *model)
1201 {
1202 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1203 	g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1204 
1205 	return g_object_new (
1206 		E_TYPE_MEMO_TABLE,
1207 		"model", model, "shell-view", shell_view, NULL);
1208 }
1209 
1210 /**
1211  * e_memo_table_get_model:
1212  * @memo_table: A calendar table.
1213  *
1214  * Queries the calendar data model that a calendar table is using.
1215  *
1216  * Return value: A memo model.
1217  **/
1218 ECalModel *
1219 e_memo_table_get_model (EMemoTable *memo_table)
1220 {
1221 	g_return_val_if_fail (memo_table != NULL, NULL);
1222 	g_return_val_if_fail (E_IS_MEMO_TABLE (memo_table), NULL);
1223 
1224 	return memo_table->priv->model;
1225 }
1226 
1227 EShellView *
1228 e_memo_table_get_shell_view (EMemoTable *memo_table)
1229 {
1230 	g_return_val_if_fail (E_IS_MEMO_TABLE (memo_table), NULL);
1231 
1232 	return memo_table->priv->shell_view;
1233 }
1234 
1235 struct get_selected_uids_closure {
1236 	EMemoTable *memo_table;
1237 	GSList *objects;
1238 };
1239 
1240 /* Used from e_table_selected_row_foreach(), builds a list of the selected UIDs */
1241 static void
1242 add_uid_cb (gint model_row,
1243             gpointer data)
1244 {
1245 	struct get_selected_uids_closure *closure;
1246 	ECalModelComponent *comp_data;
1247 	ECalModel *model;
1248 
1249 	closure = data;
1250 
1251 	model = e_memo_table_get_model (closure->memo_table);
1252 	comp_data = e_cal_model_get_component_at (model, model_row);
1253 
1254 	closure->objects = g_slist_prepend (closure->objects, comp_data);
1255 }
1256 
1257 /**
1258  * e_memo_table_get_selected:
1259  * @memo_table:
1260  *
1261  * Get the currently selected ECalModelComponent's on the table.
1262  *
1263  * Return value: A GSList of the components, which should be
1264  * g_slist_free'd when finished with.
1265  **/
1266 GSList *
1267 e_memo_table_get_selected (EMemoTable *memo_table)
1268 {
1269 	struct get_selected_uids_closure closure;
1270 
1271 	closure.memo_table = memo_table;
1272 	closure.objects = NULL;
1273 
1274 	e_table_selected_row_foreach (
1275 		E_TABLE (memo_table), add_uid_cb, &closure);
1276 
1277 	return closure.objects;
1278 }
1279 
1280 GtkTargetList *
1281 e_memo_table_get_copy_target_list (EMemoTable *memo_table)
1282 {
1283 	g_return_val_if_fail (E_IS_MEMO_TABLE (memo_table), NULL);
1284 
1285 	return memo_table->priv->copy_target_list;
1286 }
1287 
1288 GtkTargetList *
1289 e_memo_table_get_paste_target_list (EMemoTable *memo_table)
1290 {
1291 	g_return_val_if_fail (E_IS_MEMO_TABLE (memo_table), NULL);
1292 
1293 	return memo_table->priv->paste_target_list;
1294 }