2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 * Damon Chaplin <damon@ximian.com>
17 * Rodrigo Moya <rodrigo@ximian.com>
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
24 * ETaskTable - displays the ECalComponent objects in a table (an ETable).
27 #include "evolution-config.h"
29 #include "e-task-table.h"
33 #include <glib/gi18n.h>
34 #include <glib/gstdio.h>
36 #include <gdk/gdkkeysyms.h>
38 #include "calendar-config.h"
39 #include "comp-util.h"
40 #include "e-cal-dialogs.h"
41 #include "e-cal-model-tasks.h"
42 #include "e-cal-ops.h"
43 #include "e-calendar-view.h"
44 #include "e-cell-date-edit-text.h"
45 #include "itip-utils.h"
49 #define E_TASK_TABLE_GET_PRIVATE(obj) \
50 (G_TYPE_INSTANCE_GET_PRIVATE \
51 ((obj), E_TYPE_TASK_TABLE, ETaskTablePrivate))
53 struct _ETaskTablePrivate
{
54 gpointer shell_view
; /* weak pointer */
56 GCancellable
*completed_cancellable
; /* when processing completed tasks */
58 GtkTargetList
*copy_target_list
;
59 GtkTargetList
*paste_target_list
;
61 gulong notify_highlight_due_today_id
;
62 gulong notify_color_due_today_id
;
63 gulong notify_highlight_overdue_id
;
64 gulong notify_color_overdue_id
;
69 PROP_COPY_TARGET_LIST
,
71 PROP_PASTE_TARGET_LIST
,
81 static struct tm
e_task_table_get_current_time (ECellDateEdit
*ecde
, gpointer data
);
83 static guint signals
[LAST_SIGNAL
];
85 /* The icons to represent the task. */
86 static const gchar
*icon_names
[] = {
88 "stock_task-recurring",
89 "stock_task-assigned",
90 "stock_task-assigned-to"
93 /* Forward Declarations */
94 static void e_task_table_selectable_init
95 (ESelectableInterface
*iface
);
97 G_DEFINE_TYPE_WITH_CODE (
101 G_IMPLEMENT_INTERFACE (
103 e_task_table_selectable_init
))
106 task_table_emit_open_component (ETaskTable
*task_table
,
107 ECalModelComponent
*comp_data
)
109 guint signal_id
= signals
[OPEN_COMPONENT
];
111 g_signal_emit (task_table
, signal_id
, 0, comp_data
);
115 task_table_emit_popup_event (ETaskTable
*task_table
,
118 g_signal_emit (task_table
, signals
[POPUP_EVENT
], 0, event
);
122 task_table_percent_compare_cb (gconstpointer a
,
126 gint percent1
= GPOINTER_TO_INT (a
);
127 gint percent2
= GPOINTER_TO_INT (b
);
129 return (percent1
< percent2
) ? -1 : (percent1
> percent2
);
133 task_table_priority_compare_cb (gconstpointer a
,
137 gint priority1
, priority2
;
139 priority1
= e_cal_util_priority_from_string ((const gchar
*) a
);
140 priority2
= e_cal_util_priority_from_string ((const gchar
*) b
);
142 /* We change undefined priorities so they appear after 'Low'. */
148 /* We'll just use the ordering of the priority values. */
149 return (priority1
< priority2
) ? -1 : (priority1
> priority2
);
153 get_cache_str (gpointer cmp_cache
,
158 if (!cmp_cache
|| !str
)
161 value
= e_table_sorting_utils_lookup_cmp_cache (cmp_cache
, str
);
165 ckey
= g_utf8_collate_key (str
, -1);
166 e_table_sorting_utils_add_to_cmp_cache (cmp_cache
, (gchar
*) str
, ckey
);
174 same_cache_string (gpointer cmp_cache
,
179 return g_utf8_collate (str_a
, str_b
) == 0;
181 str_b
= get_cache_str (cmp_cache
, str_b
);
183 g_return_val_if_fail (str_a
!= NULL
, FALSE
);
184 g_return_val_if_fail (str_b
!= NULL
, FALSE
);
186 return strcmp (str_a
, str_b
) == 0;
190 task_table_status_compare_cb (gconstpointer a
,
194 const gchar
*string_a
= a
;
195 const gchar
*string_b
= b
;
199 if (string_a
== NULL
|| *string_a
== '\0')
202 const gchar
*cache_str
= get_cache_str (cmp_cache
, string_a
);
204 if (same_cache_string (cmp_cache
, cache_str
, _("Not Started")))
206 else if (same_cache_string (cmp_cache
, cache_str
, _("In Progress")))
208 else if (same_cache_string (cmp_cache
, cache_str
, _("Completed")))
210 else if (same_cache_string (cmp_cache
, cache_str
, _("Cancelled")))
214 if (string_b
== NULL
|| *string_b
== '\0')
217 const gchar
*cache_str
= get_cache_str (cmp_cache
, string_b
);
219 if (same_cache_string (cmp_cache
, cache_str
, _("Not Started")))
221 else if (same_cache_string (cmp_cache
, cache_str
, _("In Progress")))
223 else if (same_cache_string (cmp_cache
, cache_str
, _("Completed")))
225 else if (same_cache_string (cmp_cache
, cache_str
, _("Cancelled")))
229 return (status_a
< status_b
) ? -1 : (status_a
> status_b
);
232 /* Deletes all of the selected components in the table */
234 delete_selected_components (ETaskTable
*task_table
)
238 objs
= e_task_table_get_selected (task_table
);
239 e_cal_ops_delete_ecalmodel_components (task_table
->priv
->model
, objs
);
244 task_table_queue_draw_cb (ECalModelTasks
*tasks_model
,
246 GtkWidget
*task_table
)
248 g_return_if_fail (task_table
!= NULL
);
250 gtk_widget_queue_draw (task_table
);
254 task_table_dates_cell_before_popup_cb (ECellDateEdit
*dates_cell
,
260 ECalModelComponent
*comp_data
;
261 ETaskTable
*task_table
= user_data
;
262 ESelectionModel
*esm
;
265 g_return_if_fail (E_IS_TASK_TABLE (task_table
));
267 esm
= e_table_get_selection_model (E_TABLE (task_table
));
268 if (esm
&& esm
->sorter
&& e_sorter_needs_sorting (esm
->sorter
))
269 row
= e_sorter_sorted_to_model (esm
->sorter
, row
);
271 model
= e_task_table_get_model (task_table
);
272 comp_data
= e_cal_model_get_component_at (model
, row
);
273 date_only
= comp_data
&& comp_data
->client
&& e_client_check_capability (E_CLIENT (comp_data
->client
), CAL_STATIC_CAPABILITY_TASK_DATE_ONLY
);
275 g_object_set (G_OBJECT (dates_cell
), "show-time", !date_only
, NULL
);
279 task_table_set_model (ETaskTable
*task_table
,
282 g_return_if_fail (task_table
->priv
->model
== NULL
);
284 task_table
->priv
->model
= g_object_ref (model
);
286 /* redraw on drawing options change */
287 task_table
->priv
->notify_highlight_due_today_id
= e_signal_connect_notify (
288 model
, "notify::highlight-due-today",
289 G_CALLBACK (task_table_queue_draw_cb
),
292 task_table
->priv
->notify_color_due_today_id
= e_signal_connect_notify (
293 model
, "notify::color-due-today",
294 G_CALLBACK (task_table_queue_draw_cb
),
297 task_table
->priv
->notify_highlight_overdue_id
= e_signal_connect_notify (
298 model
, "notify::highlight-overdue",
299 G_CALLBACK (task_table_queue_draw_cb
),
302 task_table
->priv
->notify_color_overdue_id
= e_signal_connect_notify (
303 model
, "notify::color-overdue",
304 G_CALLBACK (task_table_queue_draw_cb
),
309 task_table_set_shell_view (ETaskTable
*task_table
,
310 EShellView
*shell_view
)
312 g_return_if_fail (task_table
->priv
->shell_view
== NULL
);
314 task_table
->priv
->shell_view
= shell_view
;
316 g_object_add_weak_pointer (
317 G_OBJECT (shell_view
),
318 &task_table
->priv
->shell_view
);
322 task_table_set_property (GObject
*object
,
327 switch (property_id
) {
329 task_table_set_model (
330 E_TASK_TABLE (object
),
331 g_value_get_object (value
));
334 case PROP_SHELL_VIEW
:
335 task_table_set_shell_view (
336 E_TASK_TABLE (object
),
337 g_value_get_object (value
));
341 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
345 task_table_get_property (GObject
*object
,
350 switch (property_id
) {
351 case PROP_COPY_TARGET_LIST
:
353 value
, e_task_table_get_copy_target_list (
354 E_TASK_TABLE (object
)));
359 value
, e_task_table_get_model (
360 E_TASK_TABLE (object
)));
363 case PROP_PASTE_TARGET_LIST
:
365 value
, e_task_table_get_paste_target_list (
366 E_TASK_TABLE (object
)));
369 case PROP_SHELL_VIEW
:
371 value
, e_task_table_get_shell_view (
372 E_TASK_TABLE (object
)));
376 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
380 task_table_dispose (GObject
*object
)
382 ETaskTablePrivate
*priv
;
384 priv
= E_TASK_TABLE_GET_PRIVATE (object
);
386 if (priv
->completed_cancellable
) {
387 g_cancellable_cancel (priv
->completed_cancellable
);
388 g_object_unref (priv
->completed_cancellable
);
389 priv
->completed_cancellable
= NULL
;
392 if (priv
->shell_view
!= NULL
) {
393 g_object_remove_weak_pointer (
394 G_OBJECT (priv
->shell_view
), &priv
->shell_view
);
395 priv
->shell_view
= NULL
;
398 if (priv
->model
!= NULL
) {
399 g_signal_handlers_disconnect_by_data (priv
->model
, object
);
401 e_signal_disconnect_notify_handler (priv
->model
, &priv
->notify_highlight_due_today_id
);
402 e_signal_disconnect_notify_handler (priv
->model
, &priv
->notify_color_due_today_id
);
403 e_signal_disconnect_notify_handler (priv
->model
, &priv
->notify_highlight_overdue_id
);
404 e_signal_disconnect_notify_handler (priv
->model
, &priv
->notify_color_overdue_id
);
406 g_object_unref (priv
->model
);
410 if (priv
->copy_target_list
!= NULL
) {
411 gtk_target_list_unref (priv
->copy_target_list
);
412 priv
->copy_target_list
= NULL
;
415 if (priv
->paste_target_list
!= NULL
) {
416 gtk_target_list_unref (priv
->paste_target_list
);
417 priv
->paste_target_list
= NULL
;
420 /* Chain up to parent's dispose() method. */
421 G_OBJECT_CLASS (e_task_table_parent_class
)->dispose (object
);
425 task_table_constructed (GObject
*object
)
427 ETaskTable
*task_table
;
429 ECell
*cell
, *popup_cell
;
430 ETableExtras
*extras
;
431 ETableSpecification
*specification
;
436 GError
*local_error
= NULL
;
438 task_table
= E_TASK_TABLE (object
);
439 model
= e_task_table_get_model (task_table
);
441 /* Create the header columns */
443 extras
= e_table_extras_new ();
446 * Normal string fields.
448 cell
= e_cell_text_new (NULL
, GTK_JUSTIFY_LEFT
);
451 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
452 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
453 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
456 e_table_extras_add_cell (extras
, "calstring", cell
);
457 g_object_unref (cell
);
462 cell
= e_cell_date_edit_text_new (NULL
, GTK_JUSTIFY_LEFT
);
465 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
466 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
467 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
470 e_binding_bind_property (
473 G_BINDING_BIDIRECTIONAL
|
474 G_BINDING_SYNC_CREATE
);
476 e_binding_bind_property (
477 model
, "use-24-hour-format",
478 cell
, "use-24-hour-format",
479 G_BINDING_BIDIRECTIONAL
|
480 G_BINDING_SYNC_CREATE
);
482 popup_cell
= e_cell_date_edit_new ();
483 e_cell_popup_set_child (E_CELL_POPUP (popup_cell
), cell
);
484 g_object_unref (cell
);
486 e_binding_bind_property (
487 model
, "use-24-hour-format",
488 popup_cell
, "use-24-hour-format",
489 G_BINDING_BIDIRECTIONAL
|
490 G_BINDING_SYNC_CREATE
);
492 e_table_extras_add_cell (extras
, "dateedit", popup_cell
);
493 g_object_unref (popup_cell
);
495 task_table
->dates_cell
= E_CELL_DATE_EDIT (popup_cell
);
497 g_signal_connect (task_table
->dates_cell
, "before-popup",
498 G_CALLBACK (task_table_dates_cell_before_popup_cb
), task_table
);
500 e_cell_date_edit_set_get_time_callback (
501 E_CELL_DATE_EDIT (popup_cell
),
502 e_task_table_get_current_time
, task_table
, NULL
);
508 /* Classification field. */
509 cell
= e_cell_text_new (NULL
, GTK_JUSTIFY_LEFT
);
512 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
513 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
514 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
518 popup_cell
= e_cell_combo_new ();
519 e_cell_popup_set_child (E_CELL_POPUP (popup_cell
), cell
);
520 g_object_unref (cell
);
523 strings
= g_list_append (strings
, (gchar
*) _("Public"));
524 strings
= g_list_append (strings
, (gchar
*) _("Private"));
525 strings
= g_list_append (strings
, (gchar
*) _("Confidential"));
526 e_cell_combo_set_popdown_strings (
527 E_CELL_COMBO (popup_cell
),
529 g_list_free (strings
);
531 e_table_extras_add_cell (extras
, "classification", popup_cell
);
532 g_object_unref (popup_cell
);
534 /* Priority field. */
535 cell
= e_cell_text_new (NULL
, GTK_JUSTIFY_LEFT
);
538 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
539 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
540 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
544 popup_cell
= e_cell_combo_new ();
545 e_cell_popup_set_child (E_CELL_POPUP (popup_cell
), cell
);
546 g_object_unref (cell
);
549 strings
= g_list_append (strings
, (gchar
*) _("High"));
550 strings
= g_list_append (strings
, (gchar
*) _("Normal"));
551 strings
= g_list_append (strings
, (gchar
*) _("Low"));
552 strings
= g_list_append (strings
, (gchar
*) _("Undefined"));
553 e_cell_combo_set_popdown_strings (
554 E_CELL_COMBO (popup_cell
),
556 g_list_free (strings
);
558 e_table_extras_add_cell (extras
, "priority", popup_cell
);
559 g_object_unref (popup_cell
);
562 cell
= e_cell_percent_new (NULL
, GTK_JUSTIFY_LEFT
);
565 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
566 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
567 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
570 popup_cell
= e_cell_combo_new ();
571 e_cell_popup_set_child (E_CELL_POPUP (popup_cell
), cell
);
572 g_object_unref (cell
);
575 for (percent
= 0; percent
<= 100; percent
+= 10) {
576 /* Translators: "%d%%" is the percentage of a task done.
577 * %d is the actual value, %% is replaced with a percent sign.
578 * Result values will be 0%, 10%, 20%, ... 100%
580 strings
= g_list_append (strings
, g_strdup_printf (_("%d%%"), percent
));
582 e_cell_combo_set_popdown_strings (
583 E_CELL_COMBO (popup_cell
),
586 g_list_foreach (strings
, (GFunc
) g_free
, NULL
);
587 g_list_free (strings
);
589 e_table_extras_add_cell (extras
, "percent", popup_cell
);
590 g_object_unref (popup_cell
);
592 /* Transparency field. */
593 cell
= e_cell_text_new (NULL
, GTK_JUSTIFY_LEFT
);
596 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
597 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
598 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
602 popup_cell
= e_cell_combo_new ();
603 e_cell_popup_set_child (E_CELL_POPUP (popup_cell
), cell
);
604 g_object_unref (cell
);
607 strings
= g_list_append (strings
, (gchar
*) _("Free"));
608 strings
= g_list_append (strings
, (gchar
*) _("Busy"));
609 e_cell_combo_set_popdown_strings (
610 E_CELL_COMBO (popup_cell
),
612 g_list_free (strings
);
614 e_table_extras_add_cell (extras
, "transparency", popup_cell
);
615 g_object_unref (popup_cell
);
618 cell
= e_cell_text_new (NULL
, GTK_JUSTIFY_LEFT
);
621 "strikeout_column", E_CAL_MODEL_TASKS_FIELD_STRIKEOUT
,
622 "bold_column", E_CAL_MODEL_TASKS_FIELD_OVERDUE
,
623 "bg_color_column", E_CAL_MODEL_FIELD_COLOR
,
627 popup_cell
= e_cell_combo_new ();
628 e_cell_popup_set_child (E_CELL_POPUP (popup_cell
), cell
);
629 g_object_unref (cell
);
632 strings
= g_list_append (strings
, (gchar
*) _("Not Started"));
633 strings
= g_list_append (strings
, (gchar
*) _("In Progress"));
634 strings
= g_list_append (strings
, (gchar
*) _("Completed"));
635 strings
= g_list_append (strings
, (gchar
*) _("Cancelled"));
636 e_cell_combo_set_popdown_strings (
637 E_CELL_COMBO (popup_cell
),
639 g_list_free (strings
);
641 e_table_extras_add_cell (extras
, "calstatus", popup_cell
);
642 g_object_unref (popup_cell
);
644 e_table_extras_add_compare (
645 extras
, "date-compare",
646 e_cell_date_edit_compare_cb
);
647 e_table_extras_add_compare (
648 extras
, "percent-compare",
649 task_table_percent_compare_cb
);
650 e_table_extras_add_compare (
651 extras
, "priority-compare",
652 task_table_priority_compare_cb
);
653 e_table_extras_add_compare (
654 extras
, "status-compare",
655 task_table_status_compare_cb
);
659 cell
= e_cell_toggle_new (icon_names
, G_N_ELEMENTS (icon_names
));
660 e_table_extras_add_cell (extras
, "icon", cell
);
661 g_object_unref (cell
);
663 e_table_extras_add_icon_name (extras
, "icon", "stock_task");
665 e_table_extras_add_icon_name (extras
, "complete", "stock_check-filled");
667 /* set proper format component for a default 'date' cell renderer */
668 cell
= e_table_extras_get_cell (extras
, "date");
669 e_cell_date_set_format_component (E_CELL_DATE (cell
), "calendar");
671 /* Create the table */
673 etspecfile
= g_build_filename (
674 EVOLUTION_ETSPECDIR
, "e-task-table.etspec", NULL
);
675 specification
= e_table_specification_new (etspecfile
, &local_error
);
677 /* Failure here is fatal. */
678 if (local_error
!= NULL
) {
679 g_error ("%s: %s", etspecfile
, local_error
->message
);
680 g_return_if_reached ();
684 E_TABLE (task_table
),
685 E_TABLE_MODEL (model
),
686 extras
, specification
);
688 g_object_unref (specification
);
691 gtk_widget_set_has_tooltip (GTK_WIDGET (task_table
), TRUE
);
693 g_object_unref (extras
);
695 a11y
= gtk_widget_get_accessible (GTK_WIDGET (task_table
));
697 atk_object_set_name (a11y
, _("Tasks"));
699 /* Chain up to parent's constructed() method. */
700 G_OBJECT_CLASS (e_task_table_parent_class
)->constructed (object
);
704 task_table_popup_menu (GtkWidget
*widget
)
706 ETaskTable
*task_table
;
708 task_table
= E_TASK_TABLE (widget
);
709 task_table_emit_popup_event (task_table
, NULL
);
715 task_table_query_tooltip (GtkWidget
*widget
,
718 gboolean keyboard_mode
,
721 ETaskTable
*task_table
;
723 ECalModelComponent
*comp_data
;
724 gint row
= -1, col
= -1, row_y
= -1, row_height
= -1;
725 GtkWidget
*box
, *l
, *w
;
726 GdkRGBA sel_bg
, sel_fg
, norm_bg
, norm_text
;
730 gboolean free_text
= FALSE
;
731 ECalComponent
*new_comp
;
732 ECalComponentOrganizer organizer
;
733 ECalComponentDateTime dtstart
, dtdue
;
734 icalcomponent
*clone
;
735 icaltimezone
*zone
, *default_zone
;
738 ESelectionModel
*esm
;
744 task_table
= E_TASK_TABLE (widget
);
746 e_table_get_mouse_over_cell (E_TABLE (task_table
), &row
, &col
);
750 /* Respect sorting option; the 'e_table_get_mouse_over_cell'
751 * returns sorted row, not the model one. */
752 esm
= e_table_get_selection_model (E_TABLE (task_table
));
753 if (esm
&& esm
->sorter
&& e_sorter_needs_sorting (esm
->sorter
))
754 row
= e_sorter_sorted_to_model (esm
->sorter
, row
);
756 model
= e_task_table_get_model (task_table
);
757 comp_data
= e_cal_model_get_component_at (model
, row
);
759 if (!comp_data
|| !comp_data
->icalcomp
)
762 new_comp
= e_cal_component_new ();
763 clone
= icalcomponent_new_clone (comp_data
->icalcomp
);
764 if (!e_cal_component_set_icalcomponent (new_comp
, clone
)) {
765 g_object_unref (new_comp
);
769 e_utils_get_theme_color (widget
, "theme_selected_bg_color", E_UTILS_DEFAULT_THEME_SELECTED_BG_COLOR
, &sel_bg
);
770 e_utils_get_theme_color (widget
, "theme_selected_fg_color", E_UTILS_DEFAULT_THEME_SELECTED_FG_COLOR
, &sel_fg
);
771 e_utils_get_theme_color (widget
, "theme_bg_color", E_UTILS_DEFAULT_THEME_BG_COLOR
, &norm_bg
);
772 e_utils_get_theme_color (widget
, "theme_text_color,theme_fg_color", E_UTILS_DEFAULT_THEME_TEXT_COLOR
, &norm_text
);
774 box
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
776 str
= e_calendar_view_get_icalcomponent_summary (
777 comp_data
->client
, comp_data
->icalcomp
, &free_text
);
778 if (!(str
&& *str
)) {
780 g_free ((gchar
*) str
);
782 str
= _("* No Summary *");
785 l
= gtk_label_new (NULL
);
786 tmp
= g_markup_printf_escaped ("<b>%s</b>", str
);
787 gtk_label_set_line_wrap (GTK_LABEL (l
), TRUE
);
788 gtk_label_set_markup (GTK_LABEL (l
), tmp
);
789 gtk_misc_set_alignment (GTK_MISC (l
), 0.0, 0.5);
790 w
= gtk_event_box_new ();
792 gtk_widget_override_background_color (w
, GTK_STATE_FLAG_NORMAL
, &sel_bg
);
793 gtk_widget_override_color (l
, GTK_STATE_FLAG_NORMAL
, &sel_fg
);
794 gtk_container_add (GTK_CONTAINER (w
), l
);
795 gtk_box_pack_start (GTK_BOX (box
), w
, TRUE
, TRUE
, 0);
799 g_free ((gchar
*) str
);
802 w
= gtk_event_box_new ();
803 gtk_widget_override_background_color (w
, GTK_STATE_FLAG_NORMAL
, &norm_bg
);
805 l
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
806 gtk_container_add (GTK_CONTAINER (w
), l
);
807 gtk_box_pack_start (GTK_BOX (box
), w
, FALSE
, FALSE
, 0);
810 e_cal_component_get_organizer (new_comp
, &organizer
);
813 ptr
= strchr (organizer
.value
, ':');
817 /* To Translators: It will display
818 * "Organizer: NameOfTheUser <email@ofuser.com>" */
819 tmp
= g_strdup_printf (_("Organizer: %s <%s>"), organizer
.cn
, ptr
);
821 /* With SunOne accounts, there may be no ':' in
822 * organizer.value. */
823 tmp
= g_strdup_printf (_("Organizer: %s"), organizer
.cn
);
826 l
= gtk_label_new (tmp
);
827 gtk_label_set_line_wrap (GTK_LABEL (l
), FALSE
);
828 gtk_misc_set_alignment (GTK_MISC (l
), 0.0, 0.5);
829 gtk_box_pack_start (GTK_BOX (w
), l
, FALSE
, FALSE
, 0);
832 gtk_widget_override_color (l
, GTK_STATE_FLAG_NORMAL
, &norm_text
);
835 e_cal_component_get_dtstart (new_comp
, &dtstart
);
836 e_cal_component_get_due (new_comp
, &dtdue
);
838 default_zone
= e_cal_model_get_timezone (model
);
841 zone
= icalcomponent_get_timezone (
842 e_cal_component_get_icalcomponent (new_comp
),
845 e_cal_client_get_timezone_sync (
846 comp_data
->client
, dtstart
.tzid
, &zone
, NULL
, NULL
);
853 tmp2
= g_string_new ("");
858 tmp_tm
= icaltimetype_to_tm_with_zone (dtstart
.value
, zone
, default_zone
);
859 str
= e_datetime_format_format_tm ("calendar", "table",
860 dtstart
.value
->is_date
? DTFormatKindDate
: DTFormatKindDateTime
,
864 g_string_append (tmp2
, _("Start: "));
865 g_string_append (tmp2
, str
);
874 tmp_tm
= icaltimetype_to_tm_with_zone (dtdue
.value
, zone
, default_zone
);
875 str
= e_datetime_format_format_tm ("calendar", "table",
876 dtdue
.value
->is_date
? DTFormatKindDate
: DTFormatKindDateTime
,
881 g_string_append (tmp2
, "; ");
883 g_string_append (tmp2
, _("Due: "));
884 g_string_append (tmp2
, str
);
891 l
= gtk_label_new (tmp2
->str
);
892 gtk_misc_set_alignment (GTK_MISC (l
), 0.0, 0.5);
893 gtk_box_pack_start (GTK_BOX (w
), l
, FALSE
, FALSE
, 0);
895 gtk_widget_override_color (l
, GTK_STATE_FLAG_NORMAL
, &norm_text
);
898 g_string_free (tmp2
, TRUE
);
900 e_cal_component_free_datetime (&dtstart
);
901 e_cal_component_free_datetime (&dtdue
);
903 tmp
= e_cal_model_get_attendees_status_info (
904 model
, new_comp
, comp_data
->client
);
906 l
= gtk_label_new (tmp
);
907 gtk_misc_set_alignment (GTK_MISC (l
), 0.0, 0.5);
908 gtk_box_pack_start (GTK_BOX (w
), l
, FALSE
, FALSE
, 0);
913 gtk_widget_override_color (l
, GTK_STATE_FLAG_NORMAL
, &norm_text
);
916 tmp
= cal_comp_util_get_attendee_comments (e_cal_component_get_icalcomponent (new_comp
));
918 l
= gtk_label_new (tmp
);
919 gtk_misc_set_alignment (GTK_MISC (l
), 0.0, 0.5);
920 gtk_box_pack_start (GTK_BOX (w
), l
, FALSE
, FALSE
, 0);
921 gtk_widget_override_color (l
, GTK_STATE_FLAG_NORMAL
, &norm_text
);
927 tmp2
= g_string_new ("");
928 e_cal_component_get_description_list (new_comp
, &desc
);
929 for (len
= 0, p
= desc
; p
!= NULL
; p
= p
->next
) {
930 ECalComponentText
*text
= p
->data
;
932 if (text
->value
!= NULL
) {
933 len
+= strlen (text
->value
);
934 g_string_append (tmp2
, text
->value
);
936 g_string_set_size (tmp2
, 1020);
937 g_string_append (tmp2
, "...");
942 e_cal_component_free_text_list (desc
);
945 l
= gtk_label_new (tmp2
->str
);
946 gtk_label_set_line_wrap (GTK_LABEL (l
), TRUE
);
947 gtk_misc_set_alignment (GTK_MISC (l
), 0.0, 0.5);
948 gtk_box_pack_start (GTK_BOX (w
), l
, FALSE
, FALSE
, 0);
950 gtk_widget_override_color (l
, GTK_STATE_FLAG_NORMAL
, &norm_text
);
953 g_string_free (tmp2
, TRUE
);
955 gtk_widget_show_all (box
);
956 gtk_tooltip_set_custom (tooltip
, box
);
958 g_object_unref (new_comp
);
960 if (esm
&& esm
->sorter
&& e_sorter_needs_sorting (esm
->sorter
))
961 row
= e_sorter_model_to_sorted (esm
->sorter
, row
);
963 e_table_get_cell_geometry (E_TABLE (task_table
), row
, 0, NULL
, &row_y
, NULL
, &row_height
);
965 if (row_y
!= -1 && row_height
!= -1) {
968 GtkAllocation allocation
;
970 etable
= E_TABLE (task_table
);
972 if (etable
&& etable
->table_canvas
) {
973 gtk_widget_get_allocation (GTK_WIDGET (etable
->table_canvas
), &allocation
);
977 allocation
.width
= 0;
978 allocation
.height
= 0;
981 rect
.x
= allocation
.x
;
982 rect
.y
= allocation
.y
+ row_y
- BUTTON_PADDING
;
983 rect
.width
= allocation
.width
;
984 rect
.height
= row_height
+ 2 * BUTTON_PADDING
;
986 if (etable
&& etable
->header_canvas
) {
987 gtk_widget_get_allocation (GTK_WIDGET (etable
->header_canvas
), &allocation
);
989 rect
.y
+= allocation
.height
;
992 gtk_tooltip_set_tip_area (tooltip
, &rect
);
999 task_table_double_click (ETable
*table
,
1004 ETaskTable
*task_table
;
1006 ECalModelComponent
*comp_data
;
1008 task_table
= E_TASK_TABLE (table
);
1009 model
= e_task_table_get_model (task_table
);
1010 comp_data
= e_cal_model_get_component_at (model
, row
);
1011 task_table_emit_open_component (task_table
, comp_data
);
1015 task_table_right_click (ETable
*table
,
1020 ETaskTable
*task_table
;
1022 task_table
= E_TASK_TABLE (table
);
1023 task_table_emit_popup_event (task_table
, event
);
1029 task_table_white_space_event (ETable
*table
,
1032 guint event_button
= 0;
1034 g_return_val_if_fail (E_IS_TASK_TABLE (table
), FALSE
);
1035 g_return_val_if_fail (event
!= NULL
, FALSE
);
1037 if (event
->type
== GDK_BUTTON_PRESS
&&
1038 gdk_event_get_button (event
, &event_button
) &&
1039 event_button
== 3) {
1040 GtkWidget
*table_canvas
;
1042 table_canvas
= GTK_WIDGET (table
->table_canvas
);
1044 if (!gtk_widget_has_focus (table_canvas
))
1045 gtk_widget_grab_focus (table_canvas
);
1047 task_table_emit_popup_event (E_TASK_TABLE (table
), event
);
1056 task_table_update_actions (ESelectable
*selectable
,
1057 EFocusTracker
*focus_tracker
,
1058 GdkAtom
*clipboard_targets
,
1059 gint n_clipboard_targets
)
1061 ETaskTable
*task_table
;
1063 GtkTargetList
*target_list
;
1064 GSList
*list
, *iter
;
1065 gboolean can_paste
= FALSE
;
1066 gboolean sources_are_editable
= TRUE
;
1067 gboolean is_editing
;
1069 const gchar
*tooltip
;
1073 task_table
= E_TASK_TABLE (selectable
);
1074 n_selected
= e_table_selected_count (E_TABLE (task_table
));
1075 is_editing
= e_table_is_editing (E_TABLE (task_table
));
1077 list
= e_task_table_get_selected (task_table
);
1078 for (iter
= list
; iter
!= NULL
&& sources_are_editable
; iter
= iter
->next
) {
1079 ECalModelComponent
*comp_data
= iter
->data
;
1084 sources_are_editable
= sources_are_editable
&&
1085 !e_client_is_readonly (E_CLIENT (comp_data
->client
));
1087 g_slist_free (list
);
1089 target_list
= e_selectable_get_paste_target_list (selectable
);
1090 for (ii
= 0; ii
< n_clipboard_targets
&& !can_paste
; ii
++)
1091 can_paste
= gtk_target_list_find (
1092 target_list
, clipboard_targets
[ii
], NULL
);
1094 action
= e_focus_tracker_get_cut_clipboard_action (focus_tracker
);
1095 sensitive
= (n_selected
> 0) && sources_are_editable
&& !is_editing
;
1096 tooltip
= _("Cut selected tasks to the clipboard");
1097 gtk_action_set_sensitive (action
, sensitive
);
1098 gtk_action_set_tooltip (action
, tooltip
);
1100 action
= e_focus_tracker_get_copy_clipboard_action (focus_tracker
);
1101 sensitive
= (n_selected
> 0) && !is_editing
;
1102 tooltip
= _("Copy selected tasks to the clipboard");
1103 gtk_action_set_sensitive (action
, sensitive
);
1104 gtk_action_set_tooltip (action
, tooltip
);
1106 action
= e_focus_tracker_get_paste_clipboard_action (focus_tracker
);
1107 sensitive
= sources_are_editable
&& can_paste
&& !is_editing
;
1108 tooltip
= _("Paste tasks from the clipboard");
1109 gtk_action_set_sensitive (action
, sensitive
);
1110 gtk_action_set_tooltip (action
, tooltip
);
1112 action
= e_focus_tracker_get_delete_selection_action (focus_tracker
);
1113 sensitive
= (n_selected
> 0) && sources_are_editable
&& !is_editing
;
1114 tooltip
= _("Delete selected tasks");
1115 gtk_action_set_sensitive (action
, sensitive
);
1116 gtk_action_set_tooltip (action
, tooltip
);
1118 action
= e_focus_tracker_get_select_all_action (focus_tracker
);
1120 tooltip
= _("Select all visible tasks");
1121 gtk_action_set_sensitive (action
, sensitive
);
1122 gtk_action_set_tooltip (action
, tooltip
);
1126 task_table_cut_clipboard (ESelectable
*selectable
)
1128 ETaskTable
*task_table
;
1130 task_table
= E_TASK_TABLE (selectable
);
1132 e_selectable_copy_clipboard (selectable
);
1133 delete_selected_components (task_table
);
1136 /* Helper for task_table_copy_clipboard() */
1138 copy_row_cb (gint model_row
,
1141 ETaskTable
*task_table
;
1142 ECalModelComponent
*comp_data
;
1145 icalcomponent
*child
;
1147 task_table
= E_TASK_TABLE (data
);
1149 g_return_if_fail (task_table
->tmp_vcal
!= NULL
);
1151 model
= e_task_table_get_model (task_table
);
1152 comp_data
= e_cal_model_get_component_at (model
, model_row
);
1156 /* Add timezones to the VCALENDAR component. */
1157 e_cal_util_add_timezones_from_component (
1158 task_table
->tmp_vcal
, comp_data
->icalcomp
);
1160 /* Add the new component to the VCALENDAR component. */
1161 comp_str
= icalcomponent_as_ical_string_r (comp_data
->icalcomp
);
1162 child
= icalparser_parse_string (comp_str
);
1164 icalcomponent_add_component (
1165 task_table
->tmp_vcal
,
1166 icalcomponent_new_clone (child
));
1167 icalcomponent_free (child
);
1173 task_table_copy_clipboard (ESelectable
*selectable
)
1175 ETaskTable
*task_table
;
1176 GtkClipboard
*clipboard
;
1179 task_table
= E_TASK_TABLE (selectable
);
1181 /* Create a temporary VCALENDAR object. */
1182 task_table
->tmp_vcal
= e_cal_util_new_top_level ();
1184 e_table_selected_row_foreach (
1185 E_TABLE (task_table
), copy_row_cb
, task_table
);
1186 comp_str
= icalcomponent_as_ical_string_r (task_table
->tmp_vcal
);
1188 clipboard
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
1189 e_clipboard_set_calendar (clipboard
, comp_str
, -1);
1190 gtk_clipboard_store (clipboard
);
1194 icalcomponent_free (task_table
->tmp_vcal
);
1195 task_table
->tmp_vcal
= NULL
;
1198 /* Helper for calenable_table_paste_clipboard() */
1200 clipboard_get_calendar_data (ETaskTable
*task_table
,
1203 g_return_if_fail (E_IS_TASK_TABLE (task_table
));
1205 if (!text
|| !*text
)
1208 e_cal_ops_paste_components (e_task_table_get_model (task_table
), text
);
1212 task_table_paste_clipboard (ESelectable
*selectable
)
1214 ETaskTable
*task_table
;
1215 GtkClipboard
*clipboard
;
1216 GnomeCanvasItem
*item
;
1217 GnomeCanvas
*table_canvas
;
1219 task_table
= E_TASK_TABLE (selectable
);
1221 clipboard
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
1223 table_canvas
= E_TABLE (task_table
)->table_canvas
;
1224 item
= table_canvas
->focused_item
;
1226 /* XXX Should ECellText implement GtkEditable? */
1228 /* Paste text into a cell being edited. */
1229 if (gtk_clipboard_wait_is_text_available (clipboard
) &&
1230 gtk_widget_has_focus (GTK_WIDGET (table_canvas
)) &&
1231 E_IS_TABLE_ITEM (item
) &&
1232 E_TABLE_ITEM (item
)->editing_col
>= 0 &&
1233 E_TABLE_ITEM (item
)->editing_row
>= 0) {
1235 ETableItem
*etable_item
= E_TABLE_ITEM (item
);
1237 e_cell_text_paste_clipboard (
1238 etable_item
->cell_views
[etable_item
->editing_col
],
1239 etable_item
->editing_col
,
1240 etable_item
->editing_row
);
1242 /* Paste iCalendar data into the table. */
1243 } else if (e_clipboard_wait_is_calendar_available (clipboard
)) {
1244 gchar
*calendar_source
;
1246 calendar_source
= e_clipboard_wait_for_calendar (clipboard
);
1247 clipboard_get_calendar_data (task_table
, calendar_source
);
1248 g_free (calendar_source
);
1252 /* Used from e_table_selected_row_foreach(); puts the selected row number in an
1253 * gint pointed to by the closure data.
1256 get_selected_row_cb (gint model_row
,
1266 * Returns the component that is selected in the table; only works if there is
1267 * one and only one selected row.
1269 static ECalModelComponent
*
1270 get_selected_comp (ETaskTable
*task_table
)
1275 model
= e_task_table_get_model (task_table
);
1276 if (e_table_selected_count (E_TABLE (task_table
)) != 1)
1280 e_table_selected_row_foreach (
1281 E_TABLE (task_table
), get_selected_row_cb
, &row
);
1282 g_return_val_if_fail (row
!= -1, NULL
);
1284 return e_cal_model_get_component_at (model
, row
);
1288 add_retract_data (ECalComponent
*comp
,
1289 const gchar
*retract_comment
)
1291 icalcomponent
*icalcomp
= NULL
;
1292 icalproperty
*icalprop
= NULL
;
1294 icalcomp
= e_cal_component_get_icalcomponent (comp
);
1295 if (retract_comment
&& *retract_comment
)
1296 icalprop
= icalproperty_new_x (retract_comment
);
1298 icalprop
= icalproperty_new_x ("0");
1299 icalproperty_set_x_name (icalprop
, "X-EVOLUTION-RETRACT-COMMENT");
1300 icalcomponent_add_property (icalcomp
, icalprop
);
1304 check_for_retract (ECalComponent
*comp
,
1307 ECalComponentOrganizer org
;
1308 gchar
*email
= NULL
;
1309 const gchar
*strip
= NULL
;
1312 if (!e_cal_component_has_attendees (comp
))
1315 if (!e_cal_client_check_save_schedules (client
))
1318 e_cal_component_get_organizer (comp
, &org
);
1319 strip
= itip_strip_mailto (org
.value
);
1321 ret_val
= e_client_get_backend_property_sync (
1323 CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS
,
1324 &email
, NULL
, NULL
) && email
!= NULL
&&
1325 g_ascii_strcasecmp (email
, strip
) == 0;
1333 task_table_delete_selection (ESelectable
*selectable
)
1336 ETaskTable
*task_table
;
1337 ECalModelComponent
*comp_data
;
1338 ECalComponent
*comp
= NULL
;
1339 gboolean
delete = TRUE
;
1342 task_table
= E_TASK_TABLE (selectable
);
1343 model
= e_task_table_get_model (task_table
);
1345 n_selected
= e_table_selected_count (E_TABLE (task_table
));
1346 if (n_selected
<= 0)
1349 if (n_selected
== 1)
1350 comp_data
= get_selected_comp (task_table
);
1354 /* FIXME: this may be something other than a TODO component */
1357 comp
= e_cal_component_new ();
1358 e_cal_component_set_icalcomponent (
1359 comp
, icalcomponent_new_clone (comp_data
->icalcomp
));
1362 if ((n_selected
== 1) && comp
&& check_for_retract (comp
, comp_data
->client
)) {
1363 gchar
*retract_comment
= NULL
;
1364 gboolean retract
= FALSE
;
1366 delete = e_cal_dialogs_prompt_retract (GTK_WIDGET (task_table
), comp
, &retract_comment
, &retract
);
1368 icalcomponent
*icalcomp
= NULL
;
1370 add_retract_data (comp
, retract_comment
);
1371 icalcomp
= e_cal_component_get_icalcomponent (comp
);
1372 icalcomponent_set_method (icalcomp
, ICAL_METHOD_CANCEL
);
1374 e_cal_ops_send_component (model
, comp_data
->client
, icalcomp
);
1377 g_free (retract_comment
);
1378 } else if (e_cal_model_get_confirm_delete (model
))
1379 delete = e_cal_dialogs_delete_component (
1380 comp
, FALSE
, n_selected
,
1381 E_CAL_COMPONENT_TODO
,
1382 GTK_WIDGET (task_table
));
1385 delete_selected_components (task_table
);
1389 g_object_unref (comp
);
1393 task_table_select_all (ESelectable
*selectable
)
1395 e_table_select_all (E_TABLE (selectable
));
1399 e_task_table_class_init (ETaskTableClass
*class)
1401 GObjectClass
*object_class
;
1402 GtkWidgetClass
*widget_class
;
1403 ETableClass
*table_class
;
1405 g_type_class_add_private (class, sizeof (ETaskTablePrivate
));
1407 object_class
= G_OBJECT_CLASS (class);
1408 object_class
->set_property
= task_table_set_property
;
1409 object_class
->get_property
= task_table_get_property
;
1410 object_class
->dispose
= task_table_dispose
;
1411 object_class
->constructed
= task_table_constructed
;
1413 widget_class
= GTK_WIDGET_CLASS (class);
1414 widget_class
->popup_menu
= task_table_popup_menu
;
1415 widget_class
->query_tooltip
= task_table_query_tooltip
;
1417 table_class
= E_TABLE_CLASS (class);
1418 table_class
->double_click
= task_table_double_click
;
1419 table_class
->right_click
= task_table_right_click
;
1420 table_class
->white_space_event
= task_table_white_space_event
;
1422 /* Inherited from ESelectableInterface */
1423 g_object_class_override_property (
1425 PROP_COPY_TARGET_LIST
,
1426 "copy-target-list");
1428 g_object_class_install_property (
1431 g_param_spec_object (
1437 G_PARAM_CONSTRUCT_ONLY
));
1439 /* Inherited from ESelectableInterface */
1440 g_object_class_override_property (
1442 PROP_PASTE_TARGET_LIST
,
1443 "paste-target-list");
1445 g_object_class_install_property (
1448 g_param_spec_object (
1454 G_PARAM_CONSTRUCT_ONLY
));
1456 signals
[OPEN_COMPONENT
] = g_signal_new (
1458 G_TYPE_FROM_CLASS (class),
1459 G_SIGNAL_RUN_LAST
| G_SIGNAL_ACTION
,
1460 G_STRUCT_OFFSET (ETaskTableClass
, open_component
),
1462 g_cclosure_marshal_VOID__OBJECT
,
1464 E_TYPE_CAL_MODEL_COMPONENT
);
1466 signals
[POPUP_EVENT
] = g_signal_new (
1468 G_TYPE_FROM_CLASS (class),
1469 G_SIGNAL_RUN_LAST
| G_SIGNAL_ACTION
,
1470 G_STRUCT_OFFSET (ETaskTableClass
, popup_event
),
1472 g_cclosure_marshal_VOID__BOXED
,
1474 GDK_TYPE_EVENT
| G_SIGNAL_TYPE_STATIC_SCOPE
);
1478 e_task_table_init (ETaskTable
*task_table
)
1480 GtkTargetList
*target_list
;
1482 task_table
->priv
= E_TASK_TABLE_GET_PRIVATE (task_table
);
1484 task_table
->priv
->completed_cancellable
= NULL
;
1486 target_list
= gtk_target_list_new (NULL
, 0);
1487 e_target_list_add_calendar_targets (target_list
, 0);
1488 task_table
->priv
->copy_target_list
= target_list
;
1490 target_list
= gtk_target_list_new (NULL
, 0);
1491 e_target_list_add_calendar_targets (target_list
, 0);
1492 task_table
->priv
->paste_target_list
= target_list
;
1496 e_task_table_selectable_init (ESelectableInterface
*iface
)
1498 iface
->update_actions
= task_table_update_actions
;
1499 iface
->cut_clipboard
= task_table_cut_clipboard
;
1500 iface
->copy_clipboard
= task_table_copy_clipboard
;
1501 iface
->paste_clipboard
= task_table_paste_clipboard
;
1502 iface
->delete_selection
= task_table_delete_selection
;
1503 iface
->select_all
= task_table_select_all
;
1508 * @shell_view: an #EShellView
1509 * @model: an #ECalModel for the table
1511 * Returns a new #ETaskTable.
1513 * Returns: a new #ETaskTable
1516 e_task_table_new (EShellView
*shell_view
,
1519 g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view
), NULL
);
1520 g_return_val_if_fail (E_IS_CAL_MODEL (model
), NULL
);
1522 return g_object_new (
1524 "model", model
, "shell-view", shell_view
, NULL
);
1528 * e_task_table_get_model:
1529 * @task_table: A calendar table.
1531 * Queries the calendar data model that a calendar table is using.
1533 * Return value: A calendar model.
1536 e_task_table_get_model (ETaskTable
*task_table
)
1538 g_return_val_if_fail (E_IS_TASK_TABLE (task_table
), NULL
);
1540 return task_table
->priv
->model
;
1544 e_task_table_get_shell_view (ETaskTable
*task_table
)
1546 g_return_val_if_fail (E_IS_TASK_TABLE (task_table
), NULL
);
1548 return task_table
->priv
->shell_view
;
1551 struct get_selected_uids_closure
{
1552 ETaskTable
*task_table
;
1556 /* Used from e_table_selected_row_foreach(), builds a list of the selected UIDs */
1558 add_uid_cb (gint model_row
,
1561 struct get_selected_uids_closure
*closure
= data
;
1562 ECalModelComponent
*comp_data
;
1565 model
= e_task_table_get_model (closure
->task_table
);
1566 comp_data
= e_cal_model_get_component_at (model
, model_row
);
1568 closure
->objects
= g_slist_prepend (closure
->objects
, comp_data
);
1572 * e_task_table_get_selected:
1575 * Get the currently selected ECalModelComponent's on the table.
1577 * Return value: A GSList of the components, which should be
1578 * g_slist_free'd when finished with.
1581 e_task_table_get_selected (ETaskTable
*task_table
)
1583 struct get_selected_uids_closure closure
;
1585 closure
.task_table
= task_table
;
1586 closure
.objects
= NULL
;
1588 e_table_selected_row_foreach (
1589 E_TABLE (task_table
), add_uid_cb
, &closure
);
1591 return closure
.objects
;
1595 e_task_table_get_copy_target_list (ETaskTable
*task_table
)
1597 g_return_val_if_fail (E_IS_TASK_TABLE (task_table
), NULL
);
1599 return task_table
->priv
->copy_target_list
;
1603 e_task_table_get_paste_target_list (ETaskTable
*task_table
)
1605 g_return_val_if_fail (E_IS_TASK_TABLE (task_table
), NULL
);
1607 return task_table
->priv
->paste_target_list
;
1611 task_table_get_object_list_async (GList
*clients_list
,
1613 GCancellable
*cancellable
,
1614 GAsyncReadyCallback callback
,
1615 gpointer callback_data
)
1619 for (l
= clients_list
; l
!= NULL
; l
= l
->next
) {
1620 ECalClient
*client
= l
->data
;
1622 e_cal_client_get_object_list (
1623 client
, sexp
, cancellable
,
1624 callback
, callback_data
);
1629 hide_completed_rows_ready (GObject
*source_object
,
1630 GAsyncResult
*result
,
1633 ECalModel
*model
= user_data
;
1634 ECalClient
*cal_client
;
1635 GSList
*m
, *objects
;
1636 gboolean changed
= FALSE
;
1638 GPtrArray
*comp_objects
;
1639 GError
*error
= NULL
;
1641 cal_client
= E_CAL_CLIENT (source_object
);
1643 e_cal_client_get_object_list_finish (cal_client
, result
, &objects
, &error
);
1645 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
)) {
1646 g_error_free (error
);
1649 } else if (error
!= NULL
) {
1652 source
= e_client_get_source (E_CLIENT (source_object
));
1655 "%s: Could not get the objects from '%s': %s",
1657 e_source_get_display_name (source
),
1660 g_error_free (error
);
1664 comp_objects
= e_cal_model_get_object_array (model
);
1665 g_return_if_fail (comp_objects
!= NULL
);
1667 for (m
= objects
; m
; m
= m
->next
) {
1668 ECalModelComponent
*comp_data
;
1669 ECalComponentId
*id
;
1670 ECalComponent
*comp
= e_cal_component_new ();
1672 e_cal_component_set_icalcomponent (
1673 comp
, icalcomponent_new_clone (m
->data
));
1674 id
= e_cal_component_get_id (comp
);
1676 comp_data
= e_cal_model_get_component_for_client_and_uid (model
, cal_client
, id
);
1677 if (comp_data
!= NULL
) {
1678 e_table_model_pre_change (E_TABLE_MODEL (model
));
1679 pos
= get_position_in_array (
1680 comp_objects
, comp_data
);
1681 if (g_ptr_array_remove (comp_objects
, comp_data
))
1682 g_object_unref (comp_data
);
1683 e_table_model_row_deleted (
1684 E_TABLE_MODEL (model
), pos
);
1687 e_cal_component_free_id (id
);
1688 g_object_unref (comp
);
1691 e_cal_client_free_icalcomp_slist (objects
);
1694 /* To notify about changes, because in call of
1695 * row_deleted there are still all events. */
1696 e_table_model_changed (E_TABLE_MODEL (model
));
1701 show_completed_rows_ready (GObject
*source_object
,
1702 GAsyncResult
*result
,
1705 ECalClient
*cal_client
;
1706 ECalModel
*model
= user_data
;
1707 GSList
*m
, *objects
;
1708 GPtrArray
*comp_objects
;
1709 GError
*error
= NULL
;
1711 cal_client
= E_CAL_CLIENT (source_object
);
1712 g_return_if_fail (cal_client
!= NULL
);
1714 e_cal_client_get_object_list_finish (cal_client
, result
, &objects
, &error
);
1716 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
)) {
1717 g_error_free (error
);
1720 } else if (error
!= NULL
) {
1723 source
= e_client_get_source (E_CLIENT (source_object
));
1726 "%s: Could not get the objects from '%s': %s",
1728 e_source_get_display_name (source
),
1731 g_error_free (error
);
1735 comp_objects
= e_cal_model_get_object_array (model
);
1736 g_return_if_fail (comp_objects
!= NULL
);
1738 for (m
= objects
; m
; m
= m
->next
) {
1739 ECalModelComponent
*comp_data
;
1740 ECalComponentId
*id
;
1741 ECalComponent
*comp
= e_cal_component_new ();
1743 e_cal_component_set_icalcomponent (
1744 comp
, icalcomponent_new_clone (m
->data
));
1745 id
= e_cal_component_get_id (comp
);
1747 if (!(e_cal_model_get_component_for_client_and_uid (model
, cal_client
, id
))) {
1748 e_table_model_pre_change (E_TABLE_MODEL (model
));
1749 comp_data
= g_object_new (
1750 E_TYPE_CAL_MODEL_COMPONENT
, NULL
);
1751 comp_data
->client
= g_object_ref (cal_client
);
1752 comp_data
->icalcomp
=
1753 icalcomponent_new_clone (m
->data
);
1754 e_cal_model_set_instance_times (
1756 e_cal_model_get_timezone (model
));
1757 comp_data
->dtstart
= NULL
;
1758 comp_data
->dtend
= NULL
;
1759 comp_data
->due
= NULL
;
1760 comp_data
->completed
= NULL
;
1761 comp_data
->color
= NULL
;
1763 g_ptr_array_add (comp_objects
, comp_data
);
1764 e_table_model_row_inserted (
1765 E_TABLE_MODEL (model
),
1766 comp_objects
->len
- 1);
1768 e_cal_component_free_id (id
);
1769 g_object_unref (comp
);
1772 e_cal_client_free_icalcomp_slist (objects
);
1775 /* Returns the current time, for the ECellDateEdit items.
1776 * FIXME: Should probably use the timezone of the item rather than the
1777 * current timezone, though that may be difficult to get from here. */
1779 e_task_table_get_current_time (ECellDateEdit
*ecde
,
1782 ETaskTable
*task_table
= data
;
1785 struct tm tmp_tm
= { 0 };
1786 struct icaltimetype tt
;
1788 /* Get the current timezone. */
1789 model
= e_task_table_get_model (task_table
);
1790 zone
= e_cal_model_get_timezone (model
);
1792 tt
= icaltime_from_timet_with_zone (time (NULL
), FALSE
, zone
);
1794 /* Now copy it to the struct tm and return it. */
1795 tmp_tm
.tm_year
= tt
.year
- 1900;
1796 tmp_tm
.tm_mon
= tt
.month
- 1;
1797 tmp_tm
.tm_mday
= tt
.day
;
1798 tmp_tm
.tm_hour
= tt
.hour
;
1799 tmp_tm
.tm_min
= tt
.minute
;
1800 tmp_tm
.tm_sec
= tt
.second
;
1801 tmp_tm
.tm_isdst
= -1;
1807 * e_task_table_process_completed_tasks:
1808 * @table: A calendar table model.
1810 * Process completed tasks.
1813 e_task_table_process_completed_tasks (ETaskTable
*task_table
,
1814 gboolean config_changed
)
1817 ECalDataModel
*data_model
;
1819 GCancellable
*cancellable
;
1820 gchar
*hide_sexp
, *show_sexp
;
1822 if (task_table
->priv
->completed_cancellable
) {
1823 g_cancellable_cancel (task_table
->priv
->completed_cancellable
);
1824 g_object_unref (task_table
->priv
->completed_cancellable
);
1827 task_table
->priv
->completed_cancellable
= g_cancellable_new ();
1828 cancellable
= task_table
->priv
->completed_cancellable
;
1830 model
= e_task_table_get_model (task_table
);
1831 data_model
= e_cal_model_get_data_model (model
);
1832 hide_sexp
= calendar_config_get_hide_completed_tasks_sexp (TRUE
);
1833 show_sexp
= calendar_config_get_hide_completed_tasks_sexp (FALSE
);
1835 /* If hide option is unchecked */
1836 if (!(hide_sexp
&& show_sexp
))
1837 show_sexp
= g_strdup ("(is-completed?)");
1839 client_list
= e_cal_data_model_get_clients (data_model
);
1841 /* Delete rows from model */
1843 task_table_get_object_list_async (
1844 client_list
, hide_sexp
, cancellable
,
1845 hide_completed_rows_ready
, model
);
1848 /* Insert rows into model */
1849 if (config_changed
) {
1850 task_table_get_object_list_async (
1851 client_list
, show_sexp
, cancellable
,
1852 show_completed_rows_ready
, model
);
1855 g_list_free_full (client_list
, (GDestroyNotify
) g_object_unref
);