2 * Copyright (C) 2017 Red Hat, Inc. (www.redhat.com)
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "evolution-config.h"
21 #include <glib/gi18n-lib.h>
24 #include <libedataserverui/libedataserverui.h>
25 #include <libecal/libecal.h>
27 #include "e-cal-data-model.h"
28 #include "e-cal-data-model-subscriber.h"
29 #include "e-cal-dialogs.h"
30 #include "e-cal-ops.h"
33 #include "e-to-do-pane.h"
36 #define MAX_TOOLTIP_DESCRIPTION_LEN 128
38 struct _EToDoPanePrivate
{
39 GWeakRef shell_view_weakref
; /* EShellView * */
40 gboolean highlight_overdue
;
41 GdkRGBA
*overdue_color
;
42 gboolean show_completed_tasks
;
43 gboolean show_no_duedate_tasks
;
44 gboolean use_24hour_format
;
46 EClientCache
*client_cache
;
47 ESourceRegistryWatcher
*watcher
;
48 GtkTreeStore
*tree_store
;
49 GtkTreeView
*tree_view
;
50 ECalDataModel
*events_data_model
;
51 ECalDataModel
*tasks_data_model
;
52 GHashTable
*component_refs
; /* ComponentIdent * ~> GSList * { GtkTreeRowRefenrece * } */
53 GHashTable
*client_colors
; /* ESource * ~> GdkRGBA * */
55 GCancellable
*cancellable
;
57 guint time_checker_id
;
61 gulong source_changed_id
;
63 GtkTreeRowReference
*roots
[N_ROOTS
];
68 PROP_HIGHLIGHT_OVERDUE
,
71 PROP_SHOW_COMPLETED_TASKS
,
72 PROP_SHOW_NO_DUEDATE_TASKS
,
73 PROP_USE_24HOUR_FORMAT
76 static void e_to_do_pane_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface
*iface
);
78 G_DEFINE_TYPE_WITH_CODE (EToDoPane
, e_to_do_pane
, GTK_TYPE_GRID
,
79 G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER
, e_to_do_pane_cal_data_model_subscriber_init
))
95 typedef struct _ComponentIdent
{
101 static ComponentIdent
*
102 component_ident_new (gconstpointer client
,
108 ci
= g_new0 (ComponentIdent
, 1);
110 ci
->uid
= g_strdup (uid
);
111 ci
->rid
= (rid
&& *rid
) ? g_strdup (rid
) : NULL
;
116 static ComponentIdent
*
117 component_ident_copy (const ComponentIdent
*src
)
122 return component_ident_new (src
->client
, src
->uid
, src
->rid
);
126 component_ident_free (gpointer ptr
)
128 ComponentIdent
*ci
= ptr
;
138 component_ident_hash (gconstpointer ptr
)
140 const ComponentIdent
*ci
= ptr
;
145 return g_direct_hash (ci
->client
) ^
146 (ci
->uid
? g_str_hash (ci
->uid
) : 0) ^
147 (ci
->rid
? g_str_hash (ci
->rid
) : 0);
151 component_ident_equal (gconstpointer ptr1
,
154 const ComponentIdent
*ci1
= ptr1
, *ci2
= ptr2
;
159 return ci1
->client
== ci2
->client
&&
160 g_strcmp0 (ci1
->uid
, ci2
->uid
) == 0 &&
161 g_strcmp0 (ci1
->rid
, ci2
->rid
) == 0;
165 etdp_free_component_refs (gpointer ptr
)
169 g_slist_free_full (roots
, (GDestroyNotify
) gtk_tree_row_reference_free
);
173 etdp_create_date_mark (const struct icaltimetype
*itt
)
178 return itt
->year
* 10000 + itt
->month
* 100 + itt
->day
;
182 etdp_itt_to_zone (struct icaltimetype
*itt
,
183 const gchar
*itt_tzid
,
185 icaltimezone
*default_zone
)
187 icaltimezone
*zone
= NULL
;
189 g_return_if_fail (itt
!= NULL
);
192 e_cal_client_get_timezone_sync (client
, itt_tzid
, &zone
, NULL
, NULL
);
193 } else if (icaltime_is_utc (*itt
)) {
194 zone
= icaltimezone_get_utc_timezone ();
198 icaltimezone_convert_time (itt
, zone
, default_zone
);
202 etdp_date_time_to_string (const ECalComponentDateTime
*dt
,
204 icaltimezone
*default_zone
,
205 guint today_date_mark
,
207 gboolean use_24hour_format
,
208 struct icaltimetype
*out_itt
)
213 g_return_val_if_fail (dt
!= NULL
, NULL
);
214 g_return_val_if_fail (dt
->value
!= NULL
, NULL
);
215 g_return_val_if_fail (out_itt
!= NULL
, NULL
);
217 *out_itt
= *dt
->value
;
219 etdp_itt_to_zone (out_itt
, dt
->tzid
, client
, default_zone
);
221 is_overdue
= is_task
&& etdp_create_date_mark (out_itt
) < today_date_mark
;
223 if (out_itt
->is_date
&& !is_overdue
)
229 tm
= icaltimetype_to_tm (out_itt
);
231 res
= e_datetime_format_format_tm ("calendar", "table", out_itt
->is_date
? DTFormatKindDate
: DTFormatKindDateTime
, &tm
);
233 if (use_24hour_format
) {
234 res
= g_strdup_printf ("%d:%02d", out_itt
->hour
, out_itt
->minute
);
236 gint hour
= out_itt
->hour
;
240 /* String to use in 12-hour time format for times in the morning. */
244 /* String to use in 12-hour time format for times in the afternoon. */
251 if (!out_itt
->minute
)
252 res
= g_strdup_printf ("%d %s", hour
, suffix
);
254 res
= g_strdup_printf ("%d:%02d %s", hour
, out_itt
->minute
, suffix
);
262 etdp_append_to_string_escaped (GString
*str
,
269 g_return_if_fail (str
!= NULL
);
270 g_return_if_fail (format
!= NULL
);
272 if (!value1
|| !*value1
)
275 escaped
= g_markup_printf_escaped (format
, value1
, value2
);
276 g_string_append (str
, escaped
);
281 etdp_format_date_time (ECalClient
*client
,
282 icaltimezone
*default_zone
,
283 const struct icaltimetype
*in_itt
,
286 struct icaltimetype itt
;
294 etdp_itt_to_zone (&itt
, tzid
, client
, default_zone
);
296 tm
= icaltimetype_to_tm (&itt
);
298 return e_datetime_format_format_tm ("calendar", "table", itt
.is_date
? DTFormatKindDate
: DTFormatKindDateTime
, &tm
);
302 etdp_get_component_data (EToDoPane
*to_do_pane
,
305 icaltimezone
*default_zone
,
306 guint today_date_mark
,
309 gboolean
*out_is_task
,
310 gboolean
*out_is_completed
,
311 gchar
**out_sort_key
,
312 guint
*out_date_mark
)
314 icalcomponent
*icalcomp
;
315 ECalComponentDateTime dt
= { 0 };
317 struct icaltimetype itt
= icaltime_null_time ();
318 const gchar
*prefix
, *location
, *description
;
319 gboolean task_has_due_date
= TRUE
; /* ignored for events, thus like being set */
322 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
323 g_return_val_if_fail (E_IS_CAL_CLIENT (client
), FALSE
);
324 g_return_val_if_fail (E_IS_CAL_COMPONENT (comp
), FALSE
);
325 g_return_val_if_fail (out_summary
, FALSE
);
326 g_return_val_if_fail (out_tooltip
, FALSE
);
327 g_return_val_if_fail (out_is_task
, FALSE
);
328 g_return_val_if_fail (out_is_completed
, FALSE
);
329 g_return_val_if_fail (out_sort_key
, FALSE
);
330 g_return_val_if_fail (out_date_mark
, FALSE
);
332 icalcomp
= e_cal_component_get_icalcomponent (comp
);
333 g_return_val_if_fail (icalcomp
!= NULL
, FALSE
);
335 location
= icalcomponent_get_location (icalcomp
);
336 if (location
&& !*location
)
339 tooltip
= g_string_sized_new (512);
341 etdp_append_to_string_escaped (tooltip
, "<b>%s</b>", icalcomponent_get_summary (icalcomp
), NULL
);
344 g_string_append (tooltip
, "\n");
345 /* Translators: It will display "Location: LocationOfTheAppointment" */
346 etdp_append_to_string_escaped (tooltip
, _("Location: %s"), location
, NULL
);
349 *out_is_task
= e_cal_component_get_vtype (comp
) == E_CAL_COMPONENT_TODO
;
350 *out_is_completed
= FALSE
;
353 ECalComponentDateTime dtstart
= { 0 };
354 struct icaltimetype
*completed
= NULL
;
356 /* Tasks after events */
359 e_cal_component_get_dtstart (comp
, &dtstart
);
360 e_cal_component_get_due (comp
, &dt
);
361 e_cal_component_get_completed (comp
, &completed
);
366 tmp
= etdp_format_date_time (client
, default_zone
, dtstart
.value
, dtstart
.tzid
);
368 g_string_append (tooltip
, "\n");
369 /* Translators: It will display "Start: StartDateAndTime" */
370 etdp_append_to_string_escaped (tooltip
, _("Start: %s"), tmp
, NULL
);
375 /* Fill the itt structure in case the task has no Due date */
376 itt
= *dtstart
.value
;
377 etdp_itt_to_zone (&itt
, dtstart
.tzid
, client
, default_zone
);
380 e_cal_component_free_datetime (&dtstart
);
386 tmp
= etdp_format_date_time (client
, default_zone
, dt
.value
, dt
.tzid
);
388 g_string_append (tooltip
, "\n");
389 /* Translators: It will display "Due: DueDateAndTime" */
390 etdp_append_to_string_escaped (tooltip
, _("Due: %s"), tmp
, NULL
);
394 task_has_due_date
= FALSE
;
400 tmp
= etdp_format_date_time (client
, default_zone
, completed
, NULL
);
402 g_string_append (tooltip
, "\n");
403 /* Translators: It will display "Completed: DateAndTimeWhenCompleted" */
404 etdp_append_to_string_escaped (tooltip
, _("Completed: %s"), tmp
, NULL
);
408 *out_is_completed
= TRUE
;
409 e_cal_component_free_icaltimetype (completed
);
411 icalproperty_status status
= ICAL_STATUS_NONE
;
413 e_cal_component_get_status (comp
, &status
);
414 *out_is_completed
= *out_is_completed
|| status
== ICAL_STATUS_COMPLETED
;
420 e_cal_component_get_dtstart (comp
, &dt
);
423 ECalComponentDateTime dtend
= { 0 };
424 struct icaltimetype ittstart
, ittend
;
425 gchar
*strstart
, *strduration
;
427 e_cal_component_get_dtend (comp
, &dtend
);
429 ittstart
= *dt
.value
;
431 ittend
= *dtend
.value
;
435 etdp_itt_to_zone (&ittstart
, dt
.tzid
, client
, default_zone
);
436 etdp_itt_to_zone (&ittend
, dtend
.value
? dtend
.tzid
: dt
.tzid
, client
, default_zone
);
438 strstart
= etdp_format_date_time (client
, default_zone
, &ittstart
, NULL
);
439 strduration
= calculate_time (icaltime_as_timet (ittstart
), icaltime_as_timet (ittend
));
441 g_string_append (tooltip
, "\n");
442 /* Translators: It will display "Time: StartDateAndTime (Duration)" */
443 etdp_append_to_string_escaped (tooltip
, _("Time: %s %s"), strstart
, strduration
);
445 g_free (strduration
);
448 e_cal_component_free_datetime (&dtend
);
457 time_str
= etdp_date_time_to_string (&dt
, client
, default_zone
, today_date_mark
, *out_is_task
,
458 to_do_pane
->priv
->use_24hour_format
, &itt
);
461 *out_summary
= g_markup_printf_escaped ("<span size=\"xx-small\">%s</span> %s%s%s%s",
462 time_str
, icalcomponent_get_summary (icalcomp
), location
? " (" : "",
463 location
? location
: "", location
? ")" : "");
470 *out_summary
= g_markup_printf_escaped ("%s%s%s%s", icalcomponent_get_summary (icalcomp
),
471 location
? " (" : "", location
? location
: "", location
? ")" : "");
474 if (*out_is_completed
) {
475 gchar
*tmp
= *out_summary
;
477 /* With leading space, to have proper row height in GtkTreeView */
478 *out_summary
= g_strdup_printf (" <s>%s</s>", *out_summary
);
482 gchar
*tmp
= *out_summary
;
484 /* With leading space, to have proper row height in GtkTreeView */
485 *out_summary
= g_strconcat (" ", *out_summary
, NULL
);
490 e_cal_component_free_datetime (&dt
);
492 id
= e_cal_component_get_id (comp
);
494 if (!task_has_due_date
) {
495 if (icaltime_is_null_time (itt
)) {
496 /* Sort those without Start date after those with it */
497 *out_sort_key
= g_strdup_printf ("%s-Z-%s-%s-%s",
498 prefix
, icalcomponent_get_summary (icalcomp
),
499 (id
&& id
->uid
) ? id
->uid
: "", (id
&& id
->rid
) ? id
->rid
: "");
501 *out_sort_key
= g_strdup_printf ("%s-%04d%02d%02d%02d%02d%02d-%s-%s-%s",
502 prefix
, itt
.year
, itt
.month
, itt
.day
, itt
.hour
, itt
.minute
, itt
.second
,
503 icalcomponent_get_summary (icalcomp
),
504 (id
&& id
->uid
) ? id
->uid
: "", (id
&& id
->rid
) ? id
->rid
: "");
507 *out_sort_key
= g_strdup_printf ("%s-%04d%02d%02d%02d%02d%02d-%s-%s",
508 prefix
, itt
.year
, itt
.month
, itt
.day
, itt
.hour
, itt
.minute
, itt
.second
,
509 (id
&& id
->uid
) ? id
->uid
: "", (id
&& id
->rid
) ? id
->rid
: "");
513 e_cal_component_free_id (id
);
515 description
= icalcomponent_get_description (icalcomp
);
516 if (description
&& *description
&& g_utf8_validate (description
, -1, NULL
)) {
520 len
= g_utf8_strlen (description
, -1);
521 if (len
> MAX_TOOLTIP_DESCRIPTION_LEN
) {
525 end
= g_utf8_offset_to_pointer (description
, MAX_TOOLTIP_DESCRIPTION_LEN
);
526 str
= g_string_new_len (description
, end
- description
);
527 g_string_append (str
, "…");
529 tmp
= g_string_free (str
, FALSE
);
532 g_string_append (tooltip
, "\n\n");
533 etdp_append_to_string_escaped (tooltip
, "%s", tmp
? tmp
: description
, NULL
);
538 *out_date_mark
= etdp_create_date_mark (&itt
);
539 *out_tooltip
= g_string_free (tooltip
, FALSE
);
545 etdp_get_fgcolor_for_bgcolor (const GdkRGBA
*bgcolor
)
547 GdkRGBA fgcolor
= { 1.0, 1.0, 1.0, 1.0 };
550 if ((bgcolor
->red
> 0.7) || (bgcolor
->green
> 0.7) || (bgcolor
->blue
> 0.7)) {
564 static GSList
* /* GtkTreePath * */
565 etdp_get_component_root_paths (EToDoPane
*to_do_pane
,
568 icaltimezone
*default_zone
)
570 ECalComponentDateTime dt
;
571 struct icaltimetype itt
;
572 GtkTreePath
*first_root_path
= NULL
;
574 GSList
*roots
= NULL
;
575 guint start_date_mark
, end_date_mark
, prev_date_mark
= 0;
578 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), NULL
);
579 g_return_val_if_fail (E_IS_CAL_CLIENT (client
), NULL
);
580 g_return_val_if_fail (E_IS_CAL_COMPONENT (comp
), NULL
);
582 if (e_cal_component_get_vtype (comp
) == E_CAL_COMPONENT_TODO
) {
583 e_cal_component_get_due (comp
, &dt
);
588 etdp_itt_to_zone (&itt
, dt
.tzid
, client
, default_zone
);
589 start_date_mark
= etdp_create_date_mark (&itt
);
594 end_date_mark
= start_date_mark
;
596 e_cal_component_free_datetime (&dt
);
598 e_cal_component_get_dtstart (comp
, &dt
);
603 etdp_itt_to_zone (&itt
, dt
.tzid
, client
, default_zone
);
604 start_date_mark
= etdp_create_date_mark (&itt
);
609 e_cal_component_free_datetime (&dt
);
611 e_cal_component_get_dtend (comp
, &dt
);
616 etdp_itt_to_zone (&itt
, dt
.tzid
, client
, default_zone
);
617 end_date_mark
= etdp_create_date_mark (&itt
);
619 end_date_mark
= start_date_mark
;
622 e_cal_component_free_datetime (&dt
);
625 model
= GTK_TREE_MODEL (to_do_pane
->priv
->tree_store
);
627 if (start_date_mark
== 0 && e_cal_component_get_vtype (comp
) == E_CAL_COMPONENT_TODO
) {
628 if (!to_do_pane
->priv
->show_no_duedate_tasks
)
631 if (gtk_tree_row_reference_valid (to_do_pane
->priv
->roots
[N_ROOTS
- 1])) {
632 GtkTreePath
*root_path
;
633 GtkTreeIter root_iter
;
635 root_path
= gtk_tree_row_reference_get_path (to_do_pane
->priv
->roots
[N_ROOTS
- 1]);
636 if (root_path
&& gtk_tree_model_get_iter (model
, &root_iter
, root_path
)) {
637 roots
= g_slist_prepend (roots
, root_path
);
641 gtk_tree_path_free (root_path
);
647 for (ii
= 0; ii
< N_ROOTS
- 1; ii
++) {
648 if (gtk_tree_row_reference_valid (to_do_pane
->priv
->roots
[ii
])) {
649 GtkTreePath
*root_path
;
650 GtkTreeIter root_iter
;
651 guint root_date_mark
= 0;
653 root_path
= gtk_tree_row_reference_get_path (to_do_pane
->priv
->roots
[ii
]);
654 if (root_path
&& gtk_tree_model_get_iter (model
, &root_iter
, root_path
)) {
655 gtk_tree_model_get (model
, &root_iter
, COLUMN_DATE_MARK
, &root_date_mark
, -1);
657 if (start_date_mark
< root_date_mark
&& (end_date_mark
> prev_date_mark
||
658 (start_date_mark
== end_date_mark
&& end_date_mark
>= prev_date_mark
))) {
659 roots
= g_slist_prepend (roots
, gtk_tree_path_copy (root_path
));
660 } else if (!first_root_path
) {
661 first_root_path
= gtk_tree_path_copy (root_path
);
664 prev_date_mark
= root_date_mark
;
667 gtk_tree_path_free (root_path
);
671 if (!roots
&& first_root_path
&& start_date_mark
< prev_date_mark
)
672 roots
= g_slist_prepend (roots
, first_root_path
);
674 gtk_tree_path_free (first_root_path
);
676 return g_slist_reverse (roots
);
679 static GSList
* /* GtkTreeRowReference * */
680 etdp_merge_with_root_paths (EToDoPane
*to_do_pane
,
682 const GSList
*new_root_paths
, /* GtkTreePath * */
683 const GSList
*current_refs
) /* GtkTreeRowReference * */
685 GSList
*new_references
= NULL
;
686 const GSList
*paths_link
, *refs_link
;
687 GtkTreeIter iter
, parent
;
689 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), NULL
);
690 g_return_val_if_fail (GTK_IS_TREE_MODEL (model
), NULL
);
691 g_return_val_if_fail (new_root_paths
!= NULL
, NULL
);
693 refs_link
= current_refs
;
694 for (paths_link
= new_root_paths
; paths_link
; paths_link
= g_slist_next (paths_link
)) {
695 GtkTreePath
*root_path
= paths_link
->data
;
696 gboolean found
= FALSE
;
698 while (refs_link
&& !found
) {
699 GtkTreeRowReference
*reference
= refs_link
->data
;
700 GtkTreePath
*ref_path
;
702 ref_path
= gtk_tree_row_reference_get_path (reference
);
704 gtk_tree_model_get_iter (model
, &iter
, ref_path
) &&
705 gtk_tree_model_iter_parent (model
, &parent
, &iter
)) {
706 GtkTreePath
*parent_path
;
709 parent_path
= gtk_tree_model_get_path (model
, &parent
);
710 cmp
= gtk_tree_path_compare (parent_path
, root_path
);
711 gtk_tree_path_free (parent_path
);
715 new_references
= g_slist_prepend (new_references
, gtk_tree_row_reference_copy (reference
));
716 } else if (cmp
> 0) {
717 gtk_tree_path_free (ref_path
);
720 gtk_tree_store_remove (to_do_pane
->priv
->tree_store
, &iter
);
723 gtk_tree_path_free (ref_path
);
725 refs_link
= g_slist_next (refs_link
);
732 g_warn_if_fail (gtk_tree_model_get_iter (model
, &parent
, root_path
));
734 gtk_tree_store_append (to_do_pane
->priv
->tree_store
, &iter
, &parent
);
735 path
= gtk_tree_model_get_path (model
, &iter
);
737 if (gtk_tree_model_iter_n_children (model
, &parent
) == 1) {
738 gtk_tree_view_expand_row (to_do_pane
->priv
->tree_view
, root_path
, TRUE
);
741 new_references
= g_slist_prepend (new_references
, gtk_tree_row_reference_new (model
, path
));
743 gtk_tree_path_free (path
);
748 GtkTreeRowReference
*reference
= refs_link
->data
;
749 GtkTreePath
*ref_path
;
751 ref_path
= gtk_tree_row_reference_get_path (reference
);
753 gtk_tree_model_get_iter (model
, &iter
, ref_path
)) {
754 gtk_tree_store_remove (to_do_pane
->priv
->tree_store
, &iter
);
757 gtk_tree_path_free (ref_path
);
759 refs_link
= g_slist_next (refs_link
);
762 g_warn_if_fail (g_slist_length (new_references
) == g_slist_length ((GSList
*) new_root_paths
));
764 return g_slist_reverse (new_references
);
768 etdp_get_comp_colors (EToDoPane
*to_do_pane
,
771 GdkRGBA
*out_bgcolor
,
772 gboolean
*out_bgcolor_set
,
773 GdkRGBA
*out_fgcolor
,
774 gboolean
*out_fgcolor_set
,
775 time_t *out_nearest_due
)
777 GdkRGBA
*bgcolor
, fgcolor
;
779 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
780 g_return_if_fail (out_bgcolor
);
781 g_return_if_fail (out_bgcolor_set
);
782 g_return_if_fail (out_fgcolor
);
783 g_return_if_fail (out_fgcolor_set
);
785 *out_bgcolor_set
= FALSE
;
786 *out_fgcolor_set
= FALSE
;
788 g_return_if_fail (E_IS_CAL_CLIENT (client
));
789 g_return_if_fail (E_IS_CAL_COMPONENT (comp
));
791 bgcolor
= g_hash_table_lookup (to_do_pane
->priv
->client_colors
, e_client_get_source (E_CLIENT (client
)));
793 if (e_cal_component_get_vtype (comp
) == E_CAL_COMPONENT_TODO
&&
794 to_do_pane
->priv
->highlight_overdue
&&
795 to_do_pane
->priv
->overdue_color
) {
796 ECalComponentDateTime dt
= { 0 };
798 e_cal_component_get_due (comp
, &dt
);
801 icaltimezone
*default_zone
;
802 struct icaltimetype itt
, now
;
804 default_zone
= e_cal_data_model_get_timezone (to_do_pane
->priv
->events_data_model
);
807 etdp_itt_to_zone (&itt
, dt
.tzid
, client
, default_zone
);
809 now
= icaltime_current_time_with_zone (default_zone
);
811 if ((dt
.value
->is_date
&& icaltime_compare_date_only (itt
, now
) < 0) ||
812 (!dt
.value
->is_date
&& icaltime_compare (itt
, now
) <= 0)) {
813 bgcolor
= to_do_pane
->priv
->overdue_color
;
814 } else if (out_nearest_due
) {
817 due_tt
= icaltime_as_timet_with_zone (itt
, default_zone
);
818 if (*out_nearest_due
== (time_t) -1 ||
819 *out_nearest_due
> due_tt
)
820 *out_nearest_due
= due_tt
;
824 e_cal_component_free_datetime (&dt
);
827 fgcolor
= etdp_get_fgcolor_for_bgcolor (bgcolor
);
829 *out_bgcolor_set
= bgcolor
!= NULL
;
831 *out_bgcolor
= *bgcolor
;
833 *out_fgcolor_set
= *out_bgcolor_set
;
834 *out_fgcolor
= fgcolor
;
838 etdp_add_component (EToDoPane
*to_do_pane
,
843 ComponentIdent
*ident
;
844 icaltimezone
*default_zone
;
845 GSList
*new_root_paths
, *new_references
, *link
;
847 GtkTreeIter iter
= { 0 };
848 GdkRGBA bgcolor
, fgcolor
;
849 gboolean bgcolor_set
= FALSE
, fgcolor_set
= FALSE
;
850 gchar
*summary
= NULL
, *tooltip
= NULL
, *sort_key
= NULL
;
851 gboolean is_task
= FALSE
, is_completed
= FALSE
;
852 const gchar
*icon_name
;
855 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
856 g_return_if_fail (E_IS_CAL_CLIENT (client
));
857 g_return_if_fail (E_IS_CAL_COMPONENT (comp
));
859 id
= e_cal_component_get_id (comp
);
860 g_return_if_fail (id
!= NULL
);
862 default_zone
= e_cal_data_model_get_timezone (to_do_pane
->priv
->events_data_model
);
864 if (!etdp_get_component_data (to_do_pane
, client
, comp
, default_zone
, to_do_pane
->priv
->last_today
,
865 &summary
, &tooltip
, &is_task
, &is_completed
, &sort_key
, &date_mark
)) {
866 e_cal_component_free_id (id
);
870 model
= GTK_TREE_MODEL (to_do_pane
->priv
->tree_store
);
871 ident
= component_ident_new (client
, id
->uid
, id
->rid
);
873 new_root_paths
= etdp_get_component_root_paths (to_do_pane
, client
, comp
, default_zone
);
875 new_references
= etdp_merge_with_root_paths (to_do_pane
, model
, new_root_paths
,
876 g_hash_table_lookup (to_do_pane
->priv
->component_refs
, ident
));
878 g_slist_free_full (new_root_paths
, (GDestroyNotify
) gtk_tree_path_free
);
880 if (e_cal_component_has_attendees (comp
)) {
882 icon_name
= "stock_task-assigned";
884 icon_name
= "stock_people";
887 icon_name
= "stock_task";
889 icon_name
= "appointment-new";
892 etdp_get_comp_colors (to_do_pane
, client
, comp
, &bgcolor
, &bgcolor_set
, &fgcolor
, &fgcolor_set
,
893 &to_do_pane
->priv
->nearest_due
);
895 for (link
= new_references
; link
; link
= g_slist_next (link
)) {
896 GtkTreeRowReference
*reference
= link
->data
;
898 if (gtk_tree_row_reference_valid (reference
)) {
901 path
= gtk_tree_row_reference_get_path (reference
);
902 if (path
&& gtk_tree_model_get_iter (model
, &iter
, path
)) {
903 gtk_tree_store_set (to_do_pane
->priv
->tree_store
, &iter
,
904 COLUMN_BGCOLOR
, bgcolor_set
? &bgcolor
: NULL
,
905 COLUMN_FGCOLOR
, fgcolor_set
? &fgcolor
: NULL
,
906 COLUMN_HAS_ICON_NAME
, TRUE
,
907 COLUMN_ICON_NAME
, icon_name
,
908 COLUMN_SUMMARY
, summary
,
909 COLUMN_TOOLTIP
, tooltip
,
910 COLUMN_SORTKEY
, sort_key
,
911 COLUMN_DATE_MARK
, date_mark
,
912 COLUMN_CAL_CLIENT
, client
,
913 COLUMN_CAL_COMPONENT
, comp
,
917 gtk_tree_path_free (path
);
921 g_hash_table_insert (to_do_pane
->priv
->component_refs
, component_ident_copy (ident
), new_references
);
923 component_ident_free (ident
);
924 e_cal_component_free_id (id
);
931 etdp_got_client_cb (GObject
*source_object
,
932 GAsyncResult
*result
,
935 EToDoPane
*to_do_pane
= user_data
;
937 GError
*error
= NULL
;
939 client
= e_client_cache_get_client_finish (E_CLIENT_CACHE (source_object
), result
, &error
);
941 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
)) {
942 g_clear_error (&error
);
946 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
948 if (client
&& gtk_widget_get_visible (GTK_WIDGET (to_do_pane
))) {
949 ECalClient
*cal_client
= E_CAL_CLIENT (client
);
951 ESourceSelectable
*selectable
= NULL
;
952 ECalDataModel
*data_model
= NULL
;
954 g_warn_if_fail (cal_client
!= NULL
);
956 source
= e_client_get_source (client
);
958 if (e_cal_client_get_source_type (cal_client
) == E_CAL_CLIENT_SOURCE_TYPE_EVENTS
) {
959 selectable
= e_source_get_extension (source
, E_SOURCE_EXTENSION_CALENDAR
);
960 data_model
= to_do_pane
->priv
->events_data_model
;
961 } else if (e_cal_client_get_source_type (cal_client
) == E_CAL_CLIENT_SOURCE_TYPE_TASKS
) {
962 selectable
= e_source_get_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
);
963 data_model
= to_do_pane
->priv
->tasks_data_model
;
967 g_hash_table_remove (to_do_pane
->priv
->client_colors
, source
);
972 color_spec
= e_source_selectable_dup_color (selectable
);
973 if (color_spec
&& gdk_rgba_parse (&rgba
, color_spec
)) {
974 g_hash_table_insert (to_do_pane
->priv
->client_colors
, source
, gdk_rgba_copy (&rgba
));
980 e_cal_data_model_add_client (data_model
, cal_client
);
982 } else if (!client
) {
986 g_clear_object (&client
);
987 g_clear_error (&error
);
991 e_to_do_pane_watcher_filter_cb (ESourceRegistryWatcher
*watcher
,
995 ESourceSelectable
*selectable
= NULL
;
997 g_return_val_if_fail (E_IS_SOURCE (source
), FALSE
);
999 if (e_source_has_extension (source
, E_SOURCE_EXTENSION_CALENDAR
))
1000 selectable
= e_source_get_extension (source
, E_SOURCE_EXTENSION_CALENDAR
);
1001 else if (e_source_has_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
))
1002 selectable
= e_source_get_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
);
1004 return selectable
&& e_source_selectable_get_selected (selectable
);
1008 e_to_do_pane_watcher_appeared_cb (ESourceRegistryWatcher
*watcher
,
1012 EToDoPane
*to_do_pane
= user_data
;
1013 const gchar
*extension_name
= NULL
;
1015 g_return_if_fail (E_IS_SOURCE (source
));
1016 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1018 if (!gtk_widget_get_visible (GTK_WIDGET (to_do_pane
)))
1021 if (e_source_has_extension (source
, E_SOURCE_EXTENSION_CALENDAR
))
1022 extension_name
= E_SOURCE_EXTENSION_CALENDAR
;
1023 else if (e_source_has_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
))
1024 extension_name
= E_SOURCE_EXTENSION_TASK_LIST
;
1026 g_return_if_fail (extension_name
!= NULL
);
1028 e_client_cache_get_client (to_do_pane
->priv
->client_cache
, source
, extension_name
,
1029 (guint32
) -1, to_do_pane
->priv
->cancellable
, etdp_got_client_cb
, to_do_pane
);
1033 e_to_do_pane_watcher_disappeared_cb (ESourceRegistryWatcher
*watcher
,
1037 EToDoPane
*to_do_pane
= user_data
;
1039 g_return_if_fail (E_IS_SOURCE (source
));
1040 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1042 g_hash_table_remove (to_do_pane
->priv
->client_colors
, source
);
1044 if (e_source_has_extension (source
, E_SOURCE_EXTENSION_CALENDAR
))
1045 e_cal_data_model_remove_client (to_do_pane
->priv
->events_data_model
, e_source_get_uid (source
));
1046 else if (e_source_has_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
))
1047 e_cal_data_model_remove_client (to_do_pane
->priv
->tasks_data_model
, e_source_get_uid (source
));
1051 etdp_data_subscriber_component_added (ECalDataModelSubscriber
*subscriber
,
1053 ECalComponent
*comp
)
1055 g_return_if_fail (E_IS_TO_DO_PANE (subscriber
));
1057 etdp_add_component (E_TO_DO_PANE (subscriber
), client
, comp
);
1061 etdp_data_subscriber_component_modified (ECalDataModelSubscriber
*subscriber
,
1063 ECalComponent
*comp
)
1065 g_return_if_fail (E_IS_TO_DO_PANE (subscriber
));
1067 etdp_add_component (E_TO_DO_PANE (subscriber
), client
, comp
);
1071 etdp_data_subscriber_component_removed (ECalDataModelSubscriber
*subscriber
,
1076 EToDoPane
*to_do_pane
;
1077 ComponentIdent ident
;
1080 g_return_if_fail (E_IS_TO_DO_PANE (subscriber
));
1082 to_do_pane
= E_TO_DO_PANE (subscriber
);
1084 ident
.client
= client
;
1085 ident
.uid
= (gchar
*) uid
;
1086 ident
.rid
= (gchar
*) (rid
&& *rid
? rid
: NULL
);
1088 for (link
= g_hash_table_lookup (to_do_pane
->priv
->component_refs
, &ident
); link
; link
= g_slist_next (link
)) {
1089 GtkTreeRowReference
*reference
= link
->data
;
1091 if (reference
&& gtk_tree_row_reference_valid (reference
)) {
1095 path
= gtk_tree_row_reference_get_path (reference
);
1097 if (path
&& gtk_tree_model_get_iter (gtk_tree_row_reference_get_model (reference
), &iter
, path
)) {
1098 gtk_tree_store_remove (to_do_pane
->priv
->tree_store
, &iter
);
1101 gtk_tree_path_free (path
);
1105 g_hash_table_remove (to_do_pane
->priv
->component_refs
, &ident
);
1109 etdp_data_subscriber_freeze (ECalDataModelSubscriber
*subscriber
)
1111 g_return_if_fail (E_IS_TO_DO_PANE (subscriber
));
1115 etdp_data_subscriber_thaw (ECalDataModelSubscriber
*subscriber
)
1117 g_return_if_fail (E_IS_TO_DO_PANE (subscriber
));
1120 static GCancellable
*
1121 e_to_do_pane_submit_thread_job (GObject
*responder
,
1122 const gchar
*description
,
1123 const gchar
*alert_ident
,
1124 const gchar
*alert_arg_0
,
1125 EAlertSinkThreadJobFunc func
,
1127 GDestroyNotify free_user_data
)
1129 EShellView
*shell_view
;
1130 EActivity
*activity
;
1131 GCancellable
*cancellable
= NULL
;
1133 g_return_val_if_fail (E_IS_TO_DO_PANE (responder
), NULL
);
1135 shell_view
= e_to_do_pane_ref_shell_view (E_TO_DO_PANE (responder
));
1139 activity
= e_shell_view_submit_thread_job (shell_view
, description
,
1140 alert_ident
, alert_arg_0
, func
, user_data
, free_user_data
);
1143 cancellable
= e_activity_get_cancellable (activity
);
1145 g_object_ref (cancellable
);
1146 g_object_unref (activity
);
1149 g_clear_object (&shell_view
);
1155 etdp_update_all (EToDoPane
*to_do_pane
)
1157 GtkTreeModel
*model
;
1158 GtkTreeIter iter
, next
;
1160 gboolean done
= FALSE
;
1161 GHashTable
*comps_by_client
; /* ECalClient ~> GHashTable { ECalComponent *, NULL } */
1162 GHashTableIter htiter
;
1163 gpointer key
, value
;
1165 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1167 to_do_pane
->priv
->nearest_due
= (time_t) -1;
1169 model
= GTK_TREE_MODEL (to_do_pane
->priv
->tree_store
);
1171 if (!gtk_tree_model_get_iter_first (model
, &iter
))
1174 comps_by_client
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
, g_object_unref
, (GDestroyNotify
) g_hash_table_unref
);
1178 ECalClient
*client
= NULL
;
1179 ECalComponent
*comp
= NULL
;
1181 gtk_tree_model_get (model
, &iter
,
1182 COLUMN_CAL_CLIENT
, &client
,
1183 COLUMN_CAL_COMPONENT
, &comp
,
1186 if (client
&& comp
) {
1189 comps
= g_hash_table_lookup (comps_by_client
, client
);
1191 g_hash_table_ref (comps
);
1193 comps
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
, g_object_unref
, NULL
);
1196 g_hash_table_insert (comps
, g_object_ref (comp
), NULL
);
1197 g_hash_table_insert (comps_by_client
, g_object_ref (client
), comps
);
1200 g_clear_object (&client
);
1201 g_clear_object (&comp
);
1204 done
= !gtk_tree_model_iter_children (model
, &next
, &iter
);
1208 done
= !gtk_tree_model_iter_next (model
, &next
);
1214 while (done
= !gtk_tree_model_iter_parent (model
, &next
, &iter
), !done
) {
1218 done
= !gtk_tree_model_iter_next (model
, &next
);
1228 g_hash_table_iter_init (&htiter
, comps_by_client
);
1229 while (g_hash_table_iter_next (&htiter
, &key
, &value
)) {
1230 ECalClient
*client
= key
;
1231 GHashTable
*comps
= value
;
1232 GHashTableIter citer
;
1234 g_hash_table_iter_init (&citer
, comps
);
1235 while (g_hash_table_iter_next (&citer
, &key
, NULL
)) {
1236 ECalComponent
*comp
= key
;
1238 etdp_add_component (to_do_pane
, client
, comp
);
1242 g_hash_table_destroy (comps_by_client
);
1246 etdp_update_colors (EToDoPane
*to_do_pane
,
1247 gboolean only_overdue
)
1249 GtkTreeModel
*model
;
1250 GtkTreeIter iter
, next
;
1252 time_t nearest_due
= (time_t) -1;
1253 gboolean done
= FALSE
;
1255 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1257 model
= GTK_TREE_MODEL (to_do_pane
->priv
->tree_store
);
1259 if (!gtk_tree_model_get_iter_first (model
, &iter
))
1264 ECalClient
*client
= NULL
;
1265 ECalComponent
*comp
= NULL
;
1267 gtk_tree_model_get (model
, &iter
,
1268 COLUMN_CAL_CLIENT
, &client
,
1269 COLUMN_CAL_COMPONENT
, &comp
,
1272 if (client
&& comp
) {
1273 GdkRGBA bgcolor
, fgcolor
;
1274 gboolean bgcolor_set
= FALSE
, fgcolor_set
= FALSE
;
1276 etdp_get_comp_colors (to_do_pane
, client
, comp
, &bgcolor
, &bgcolor_set
, &fgcolor
, &fgcolor_set
, &nearest_due
);
1278 gtk_tree_store_set (to_do_pane
->priv
->tree_store
, &iter
,
1279 COLUMN_BGCOLOR
, bgcolor_set
? &bgcolor
: NULL
,
1280 COLUMN_FGCOLOR
, fgcolor_set
? &fgcolor
: NULL
,
1284 g_clear_object (&client
);
1285 g_clear_object (&comp
);
1288 done
= !gtk_tree_model_iter_children (model
, &next
, &iter
);
1292 done
= !gtk_tree_model_iter_next (model
, &next
);
1294 /* Overdue can be only those 'Today', thus under the first child. */
1295 if (only_overdue
&& !level
)
1302 while (done
= !gtk_tree_model_iter_parent (model
, &next
, &iter
), !done
) {
1306 done
= !gtk_tree_model_iter_next (model
, &next
);
1308 /* Overdue can be only those 'Today', thus under the first child. */
1309 if (only_overdue
&& !level
)
1320 to_do_pane
->priv
->nearest_due
= nearest_due
;
1324 etdp_check_time_changed (EToDoPane
*to_do_pane
,
1325 gboolean force_update
)
1331 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1333 zone
= e_cal_data_model_get_timezone (to_do_pane
->priv
->events_data_model
);
1334 itt
= icaltime_current_time_with_zone (zone
);
1335 new_today
= etdp_create_date_mark (&itt
);
1337 if (force_update
|| new_today
!= to_do_pane
->priv
->last_today
) {
1338 gchar
*tasks_filter
;
1339 time_t tt_begin
, tt_end
;
1340 gchar
*iso_begin_all
, *iso_begin
, *iso_end
;
1343 to_do_pane
->priv
->last_today
= new_today
;
1345 tt_begin
= icaltime_as_timet_with_zone (itt
, zone
);
1346 tt_begin
= time_day_begin_with_zone (tt_begin
, zone
);
1347 tt_end
= time_add_week_with_zone (tt_begin
, 1, zone
) - 1;
1349 iso_begin_all
= isodate_from_time_t (0);
1350 iso_begin
= isodate_from_time_t (tt_begin
);
1351 iso_end
= isodate_from_time_t (tt_end
);
1352 if (to_do_pane
->priv
->show_no_duedate_tasks
) {
1353 if (to_do_pane
->priv
->show_completed_tasks
) {
1354 tasks_filter
= g_strdup ("#t");
1356 tasks_filter
= g_strdup ("(not (is-completed?))");
1358 } else if (to_do_pane
->priv
->show_completed_tasks
) {
1359 tasks_filter
= g_strdup_printf (
1362 " (not (is-completed?))"
1363 " (due-in-time-range? (make-time \"%s\") (make-time \"%s\"))"
1366 " (due-in-time-range? (make-time \"%s\") (make-time \"%s\"))"
1369 iso_begin_all
, iso_begin
, iso_begin
, iso_end
);
1371 tasks_filter
= g_strdup_printf (
1373 " (not (is-completed?))"
1374 " (due-in-time-range? (make-time \"%s\") (make-time \"%s\"))"
1376 iso_begin_all
, iso_end
);
1379 /* Re-label the roots */
1380 for (ii
= 0; ii
< N_ROOTS
; ii
++) {
1384 if (!gtk_tree_row_reference_valid (to_do_pane
->priv
->roots
[ii
])) {
1385 if (ii
== N_ROOTS
- 1) {
1386 GtkTreeModel
*model
;
1389 if (!to_do_pane
->priv
->show_no_duedate_tasks
)
1392 sort_key
= g_strdup_printf ("%c", 'A' + ii
);
1394 gtk_tree_store_append (to_do_pane
->priv
->tree_store
, &iter
, NULL
);
1395 gtk_tree_store_set (to_do_pane
->priv
->tree_store
, &iter
,
1396 COLUMN_SORTKEY
, sort_key
,
1397 COLUMN_HAS_ICON_NAME
, FALSE
,
1402 model
= GTK_TREE_MODEL (to_do_pane
->priv
->tree_store
);
1403 path
= gtk_tree_model_get_path (model
, &iter
);
1405 gtk_tree_row_reference_free (to_do_pane
->priv
->roots
[ii
]);
1406 to_do_pane
->priv
->roots
[ii
] = gtk_tree_row_reference_new (model
, path
);
1407 g_warn_if_fail (to_do_pane
->priv
->roots
[ii
] != NULL
);
1409 gtk_tree_path_free (path
);
1415 path
= gtk_tree_row_reference_get_path (to_do_pane
->priv
->roots
[ii
]);
1417 if (gtk_tree_model_get_iter (gtk_tree_row_reference_get_model (to_do_pane
->priv
->roots
[ii
]), &iter
, path
)) {
1422 tm
= icaltimetype_to_tm (&itt
);
1424 icaltime_adjust (&itt
, 1, 0, 0, 0);
1426 date_mark
= etdp_create_date_mark (&itt
);
1429 markup
= g_markup_printf_escaped ("<b>%s</b>", _("Today"));
1430 } else if (ii
== 1) {
1431 markup
= g_markup_printf_escaped ("<b>%s</b>", _("Tomorrow"));
1432 } else if (ii
== N_ROOTS
- 1) {
1433 if (!to_do_pane
->priv
->show_no_duedate_tasks
) {
1434 gtk_tree_store_remove (to_do_pane
->priv
->tree_store
, &iter
);
1435 gtk_tree_row_reference_free (to_do_pane
->priv
->roots
[ii
]);
1436 to_do_pane
->priv
->roots
[ii
] = NULL
;
1437 gtk_tree_path_free (path
);
1441 markup
= g_markup_printf_escaped ("<b>%s</b>", _("Tasks without Due date"));
1445 date
= e_datetime_format_format_tm ("calendar", "table", DTFormatKindDate
, &tm
);
1446 markup
= g_markup_printf_escaped ("<b>%s</b>", date
);
1450 gtk_tree_store_set (to_do_pane
->priv
->tree_store
, &iter
,
1451 COLUMN_SUMMARY
, markup
,
1452 COLUMN_DATE_MARK
, date_mark
,
1457 icaltime_adjust (&itt
, 1, 0, 0, 0);
1460 gtk_tree_path_free (path
);
1463 /* Update data-model-s */
1464 e_cal_data_model_subscribe (to_do_pane
->priv
->events_data_model
,
1465 E_CAL_DATA_MODEL_SUBSCRIBER (to_do_pane
), tt_begin
, tt_end
);
1467 e_cal_data_model_set_filter (to_do_pane
->priv
->tasks_data_model
, tasks_filter
);
1469 e_cal_data_model_subscribe (to_do_pane
->priv
->tasks_data_model
,
1470 E_CAL_DATA_MODEL_SUBSCRIBER (to_do_pane
), 0, 0);
1472 g_free (tasks_filter
);
1473 g_free (iso_begin_all
);
1477 etdp_update_all (to_do_pane
);
1479 time_t now_tt
= icaltime_as_timet_with_zone (itt
, zone
);
1481 if (to_do_pane
->priv
->nearest_due
!= (time_t) -1 &&
1482 to_do_pane
->priv
->nearest_due
<= now_tt
)
1483 etdp_update_colors (to_do_pane
, TRUE
);
1488 etdp_check_time_cb (gpointer user_data
)
1490 EToDoPane
*to_do_pane
= user_data
;
1492 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
1494 etdp_check_time_changed (to_do_pane
, FALSE
);
1500 etdp_update_queries (EToDoPane
*to_do_pane
)
1502 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1504 etdp_check_time_changed (to_do_pane
, TRUE
);
1508 etdp_timezone_changed_cb (ECalDataModel
*data_model
,
1512 EToDoPane
*to_do_pane
= user_data
;
1514 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1516 etdp_check_time_changed (to_do_pane
, TRUE
);
1520 etdp_settings_map_string_to_icaltimezone (GValue
*value
,
1524 GSettings
*settings
;
1525 const gchar
*location
= NULL
;
1526 icaltimezone
*timezone
= NULL
;
1528 settings
= e_util_ref_settings ("org.gnome.evolution.calendar");
1530 if (g_settings_get_boolean (settings
, "use-system-timezone"))
1531 timezone
= e_cal_util_get_system_timezone ();
1533 location
= g_variant_get_string (variant
, NULL
);
1535 if (location
!= NULL
&& *location
!= '\0')
1536 timezone
= icaltimezone_get_builtin_timezone (location
);
1538 if (timezone
== NULL
)
1539 timezone
= icaltimezone_get_utc_timezone ();
1541 g_value_set_pointer (value
, timezone
);
1543 g_object_unref (settings
);
1549 etdp_settings_map_string_to_rgba (GValue
*value
,
1554 const gchar
*color_str
;
1556 color_str
= g_variant_get_string (variant
, NULL
);
1558 if (color_str
&& gdk_rgba_parse (&rgba
, color_str
))
1559 g_value_set_boxed (value
, &rgba
);
1561 g_value_set_boxed (value
, NULL
);
1567 etdp_row_activated_cb (GtkTreeView
*tree_view
,
1569 GtkTreeViewColumn
*column
,
1572 EToDoPane
*to_do_pane
= user_data
;
1573 GtkTreeModel
*model
;
1576 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1578 model
= gtk_tree_view_get_model (tree_view
);
1580 if (gtk_tree_model_get_iter (model
, &iter
, path
)) {
1581 ECalClient
*client
= NULL
;
1582 ECalComponent
*comp
= NULL
;
1584 gtk_tree_model_get (model
, &iter
,
1585 COLUMN_CAL_CLIENT
, &client
,
1586 COLUMN_CAL_COMPONENT
, &comp
,
1589 if (client
&& comp
) {
1590 e_cal_ops_open_component_in_editor_sync (NULL
, client
,
1591 e_cal_component_get_icalcomponent (comp
), FALSE
);
1594 g_clear_object (&client
);
1595 g_clear_object (&comp
);
1600 etdp_source_changed_cb (ESourceRegistry
*registry
,
1604 EToDoPane
*to_do_pane
= user_data
;
1606 g_return_if_fail (E_IS_SOURCE (source
));
1607 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1609 if (g_hash_table_contains (to_do_pane
->priv
->client_colors
, source
)) {
1610 ESourceSelectable
*selectable
= NULL
;
1612 if (e_source_has_extension (source
, E_SOURCE_EXTENSION_CALENDAR
))
1613 selectable
= e_source_get_extension (source
, E_SOURCE_EXTENSION_CALENDAR
);
1614 else if (e_source_has_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
))
1615 selectable
= e_source_get_extension (source
, E_SOURCE_EXTENSION_TASK_LIST
);
1621 color_spec
= e_source_selectable_dup_color (selectable
);
1622 if (color_spec
&& gdk_rgba_parse (&rgba
, color_spec
)) {
1623 GdkRGBA
*current_rgba
;
1625 current_rgba
= g_hash_table_lookup (to_do_pane
->priv
->client_colors
, source
);
1626 if (!gdk_rgba_equal (current_rgba
, &rgba
)) {
1627 g_hash_table_insert (to_do_pane
->priv
->client_colors
, source
, gdk_rgba_copy (&rgba
));
1628 etdp_update_colors (to_do_pane
, FALSE
);
1632 g_free (color_spec
);
1638 etdp_get_tree_view_selected_one (EToDoPane
*to_do_pane
,
1639 ECalClient
**out_client
,
1640 ECalComponent
**out_comp
)
1642 GtkTreeSelection
*selection
;
1645 GtkTreeModel
*model
= NULL
;
1646 gboolean had_any
= FALSE
;
1648 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
1656 selection
= gtk_tree_view_get_selection (to_do_pane
->priv
->tree_view
);
1657 rows
= gtk_tree_selection_get_selected_rows (selection
, &model
);
1659 if (rows
&& gtk_tree_model_get_iter (model
, &iter
, rows
->data
)) {
1660 ECalClient
*client
= NULL
;
1661 ECalComponent
*comp
= NULL
;
1663 gtk_tree_model_get (model
, &iter
,
1664 COLUMN_CAL_CLIENT
, &client
,
1665 COLUMN_CAL_COMPONENT
, &comp
,
1668 if (out_client
&& client
)
1669 *out_client
= g_object_ref (client
);
1671 if (out_comp
&& comp
)
1672 *out_comp
= g_object_ref (comp
);
1674 had_any
= client
|| comp
;
1676 g_clear_object (&client
);
1677 g_clear_object (&comp
);
1680 g_list_free_full (rows
, (GDestroyNotify
) gtk_tree_path_free
);
1686 etdp_new_common (EToDoPane
*to_do_pane
,
1687 ECalClientSourceType source_type
,
1688 gboolean is_assigned
)
1690 ECalClient
*client
= NULL
;
1691 EShellView
*shell_view
;
1692 EShellWindow
*shell_window
;
1693 gchar
*client_source_uid
= NULL
;
1695 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1697 if (etdp_get_tree_view_selected_one (to_do_pane
, &client
, NULL
) && client
) {
1700 source
= e_client_get_source (E_CLIENT (client
));
1702 const gchar
*extension_name
= NULL
;
1704 switch (source_type
) {
1705 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS
:
1706 extension_name
= E_SOURCE_EXTENSION_CALENDAR
;
1708 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS
:
1709 extension_name
= E_SOURCE_EXTENSION_MEMO_LIST
;
1711 case E_CAL_CLIENT_SOURCE_TYPE_TASKS
:
1712 extension_name
= E_SOURCE_EXTENSION_TASK_LIST
;
1718 /* Cannot ask to create an event in a task list or vice versa. */
1719 if (!extension_name
|| !e_source_has_extension (source
, extension_name
))
1724 client_source_uid
= e_source_dup_uid (source
);
1727 g_clear_object (&client
);
1729 shell_view
= e_to_do_pane_ref_shell_view (to_do_pane
);
1730 shell_window
= shell_view
? e_shell_view_get_shell_window (shell_view
) : NULL
;
1732 if (source_type
== E_CAL_CLIENT_SOURCE_TYPE_EVENTS
) {
1733 GSettings
*settings
;
1734 time_t dtstart
= 0, dtend
= 0;
1735 GtkTreeSelection
*selection
;
1738 GtkTreeModel
*model
= NULL
;
1740 settings
= e_util_ref_settings ("org.gnome.evolution.calendar");
1742 selection
= gtk_tree_view_get_selection (to_do_pane
->priv
->tree_view
);
1743 rows
= gtk_tree_selection_get_selected_rows (selection
, &model
);
1745 if (rows
&& gtk_tree_model_get_iter (model
, &iter
, rows
->data
)) {
1747 guint date_mark
= 0;
1749 while (gtk_tree_model_iter_parent (model
, &parent
, &iter
))
1752 gtk_tree_model_get (model
, &iter
, COLUMN_DATE_MARK
, &date_mark
, -1);
1754 if (date_mark
> 0) {
1755 struct icaltimetype now
;
1756 gint time_divisions_secs
;
1759 time_divisions_secs
= g_settings_get_int (settings
, "time-divisions") * 60;
1760 zone
= e_cal_data_model_get_timezone (to_do_pane
->priv
->events_data_model
);
1761 now
= icaltime_current_time_with_zone (zone
);
1763 now
.year
= date_mark
/ 10000;
1764 now
.month
= (date_mark
/ 100) % 100;
1765 now
.day
= date_mark
% 100;
1767 /* The date_mark is the next day, not the day it belongs to */
1768 icaltime_adjust (&now
, -1, 0, 0, 0);
1770 dtstart
= icaltime_as_timet_with_zone (now
, zone
);
1771 if (dtstart
> 0 && time_divisions_secs
> 0) {
1772 dtstart
= dtstart
+ time_divisions_secs
- (dtstart
% time_divisions_secs
);
1773 dtend
= dtstart
+ time_divisions_secs
;
1780 g_list_free_full (rows
, (GDestroyNotify
) gtk_tree_path_free
);
1782 e_cal_ops_new_event_editor (shell_window
, client_source_uid
, is_assigned
, FALSE
,
1783 g_settings_get_boolean (settings
, "use-default-reminder"),
1784 g_settings_get_int (settings
, "default-reminder-interval"),
1785 g_settings_get_enum (settings
, "default-reminder-units"),
1788 g_clear_object (&settings
);
1790 e_cal_ops_new_component_editor (shell_window
, source_type
, client_source_uid
, is_assigned
);
1793 g_clear_object (&shell_view
);
1794 g_free (client_source_uid
);
1798 etdp_new_appointment_cb (GtkMenuItem
*item
,
1801 EToDoPane
*to_do_pane
= user_data
;
1803 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1805 etdp_new_common (to_do_pane
, E_CAL_CLIENT_SOURCE_TYPE_EVENTS
, FALSE
);
1809 etdp_new_meeting_cb (GtkMenuItem
*item
,
1812 EToDoPane
*to_do_pane
= user_data
;
1814 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1816 etdp_new_common (to_do_pane
, E_CAL_CLIENT_SOURCE_TYPE_EVENTS
, TRUE
);
1820 etdp_new_task_cb (GtkMenuItem
*item
,
1823 EToDoPane
*to_do_pane
= user_data
;
1825 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1827 etdp_new_common (to_do_pane
, E_CAL_CLIENT_SOURCE_TYPE_TASKS
, FALSE
);
1831 etdp_new_assigned_task_cb (GtkMenuItem
*item
,
1834 EToDoPane
*to_do_pane
= user_data
;
1836 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1838 etdp_new_common (to_do_pane
, E_CAL_CLIENT_SOURCE_TYPE_TASKS
, TRUE
);
1842 etdp_open_selected_cb (GtkMenuItem
*item
,
1845 EToDoPane
*to_do_pane
= user_data
;
1846 ECalClient
*client
= NULL
;
1847 ECalComponent
*comp
= NULL
;
1849 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1851 if (etdp_get_tree_view_selected_one (to_do_pane
, &client
, &comp
) && client
&& comp
) {
1852 e_cal_ops_open_component_in_editor_sync (NULL
, client
,
1853 e_cal_component_get_icalcomponent (comp
), FALSE
);
1856 g_clear_object (&client
);
1857 g_clear_object (&comp
);
1860 typedef struct _RemoveOperationData
{
1865 } RemoveOperationData
;
1868 remove_operation_data_free (gpointer ptr
)
1870 RemoveOperationData
*rod
= ptr
;
1873 g_clear_object (&rod
->client
);
1881 etdp_remove_component_thread (EAlertSinkThreadJobData
*job_data
,
1883 GCancellable
*cancellable
,
1886 RemoveOperationData
*rod
= user_data
;
1888 g_return_if_fail (rod
!= NULL
);
1890 e_cal_client_remove_object_sync (rod
->client
, rod
->uid
, rod
->rid
, rod
->mod
, cancellable
, error
);
1894 etdp_delete_common (EToDoPane
*to_do_pane
,
1897 ECalClient
*client
= NULL
;
1898 ECalComponent
*comp
= NULL
;
1900 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1902 if (etdp_get_tree_view_selected_one (to_do_pane
, &client
, &comp
) && client
&& comp
) {
1903 const gchar
*description
;
1904 const gchar
*alert_ident
;
1905 gchar
*display_name
;
1906 GCancellable
*cancellable
;
1908 RemoveOperationData
*rod
;
1909 ECalComponentId
*id
;
1911 id
= e_cal_component_get_id (comp
);
1912 g_return_if_fail (id
!= NULL
);
1914 if (!e_cal_dialogs_delete_component (comp
, FALSE
, 1, e_cal_component_get_vtype (comp
), GTK_WIDGET (to_do_pane
))) {
1915 e_cal_component_free_id (id
);
1916 g_clear_object (&client
);
1917 g_clear_object (&comp
);
1921 switch (e_cal_client_get_source_type (client
)) {
1922 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS
:
1923 description
= _("Removing an event");
1924 alert_ident
= "calendar:failed-remove-event";
1926 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS
:
1927 description
= _("Removing a memo");
1928 alert_ident
= "calendar:failed-remove-memo";
1930 case E_CAL_CLIENT_SOURCE_TYPE_TASKS
:
1931 description
= _("Removing a task");
1932 alert_ident
= "calendar:failed-remove-task";
1935 g_warn_if_reached ();
1939 if (!e_cal_component_is_instance (comp
))
1940 mod
= E_CAL_OBJ_MOD_ALL
;
1942 rod
= g_new0 (RemoveOperationData
,1);
1943 rod
->client
= g_object_ref (client
);
1944 rod
->uid
= g_strdup (id
->uid
);
1945 rod
->rid
= g_strdup (id
->rid
);
1948 source
= e_client_get_source (E_CLIENT (client
));
1949 display_name
= e_util_get_source_full_name (e_source_registry_watcher_get_registry (to_do_pane
->priv
->watcher
), source
);
1951 /* It doesn't matter which data-model is picked, because it's used
1952 only for thread creation and manipulation, not for its content. */
1953 cancellable
= e_cal_data_model_submit_thread_job (to_do_pane
->priv
->events_data_model
, description
, alert_ident
,
1954 display_name
, etdp_remove_component_thread
, rod
, remove_operation_data_free
);
1956 e_cal_component_free_id (id
);
1957 g_clear_object (&cancellable
);
1958 g_free (display_name
);
1961 g_clear_object (&client
);
1962 g_clear_object (&comp
);
1966 etdp_delete_selected_cb (GtkMenuItem
*item
,
1969 EToDoPane
*to_do_pane
= user_data
;
1971 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1973 etdp_delete_common (to_do_pane
, E_CAL_OBJ_MOD_THIS
);
1977 etdp_delete_series_cb (GtkMenuItem
*item
,
1980 EToDoPane
*to_do_pane
= user_data
;
1982 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1984 etdp_delete_common (to_do_pane
, E_CAL_OBJ_MOD_ALL
);
1988 etdp_show_tasks_without_due_date_cb (GtkCheckMenuItem
*check_menu_item
,
1991 EToDoPane
*to_do_pane
= user_data
;
1993 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
1995 e_to_do_pane_set_show_no_duedate_tasks (to_do_pane
, !e_to_do_pane_get_show_no_duedate_tasks (to_do_pane
));
1999 etdp_fill_popup_menu (EToDoPane
*to_do_pane
,
2003 GtkMenuShell
*menu_shell
;
2004 ECalClient
*client
= NULL
;
2005 ECalComponent
*comp
= NULL
;
2007 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2008 g_return_if_fail (GTK_IS_MENU (menu
));
2010 etdp_get_tree_view_selected_one (to_do_pane
, &client
, &comp
);
2012 menu_shell
= GTK_MENU_SHELL (menu
);
2014 item
= gtk_image_menu_item_new_with_mnemonic (_("New _Appointment..."));
2015 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2016 gtk_image_new_from_icon_name ("appointment-new", GTK_ICON_SIZE_MENU
));
2017 g_signal_connect (item
, "activate",
2018 G_CALLBACK (etdp_new_appointment_cb
), to_do_pane
);
2019 gtk_widget_show (item
);
2020 gtk_menu_shell_append (menu_shell
, item
);
2022 item
= gtk_image_menu_item_new_with_mnemonic (_("New _Meeting..."));
2023 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2024 gtk_image_new_from_icon_name ("stock_people", GTK_ICON_SIZE_MENU
));
2025 g_signal_connect (item
, "activate",
2026 G_CALLBACK (etdp_new_meeting_cb
), to_do_pane
);
2027 gtk_widget_show (item
);
2028 gtk_menu_shell_append (menu_shell
, item
);
2030 item
= gtk_image_menu_item_new_with_mnemonic (_("New _Task..."));
2031 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2032 gtk_image_new_from_icon_name ("stock_task", GTK_ICON_SIZE_MENU
));
2033 g_signal_connect (item
, "activate",
2034 G_CALLBACK (etdp_new_task_cb
), to_do_pane
);
2035 gtk_widget_show (item
);
2036 gtk_menu_shell_append (menu_shell
, item
);
2038 item
= gtk_image_menu_item_new_with_mnemonic (_("_New Assigned Task..."));
2039 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2040 gtk_image_new_from_icon_name ("stock_task-assigned", GTK_ICON_SIZE_MENU
));
2041 g_signal_connect (item
, "activate",
2042 G_CALLBACK (etdp_new_assigned_task_cb
), to_do_pane
);
2043 gtk_widget_show (item
);
2044 gtk_menu_shell_append (menu_shell
, item
);
2046 if (client
&& comp
) {
2047 item
= gtk_separator_menu_item_new ();
2048 gtk_widget_show (item
);
2049 gtk_menu_shell_append (menu_shell
, item
);
2051 item
= gtk_image_menu_item_new_with_mnemonic (_("_Open..."));
2052 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2053 gtk_image_new_from_icon_name ("document-open", GTK_ICON_SIZE_MENU
));
2054 g_signal_connect (item
, "activate",
2055 G_CALLBACK (etdp_open_selected_cb
), to_do_pane
);
2056 gtk_widget_show (item
);
2057 gtk_menu_shell_append (menu_shell
, item
);
2059 item
= gtk_separator_menu_item_new ();
2060 gtk_widget_show (item
);
2061 gtk_menu_shell_append (menu_shell
, item
);
2063 if (e_cal_component_get_vtype (comp
) == E_CAL_COMPONENT_EVENT
&&
2064 e_cal_component_is_instance (comp
)) {
2065 item
= gtk_image_menu_item_new_with_mnemonic (_("_Delete This Instance..."));
2066 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2067 gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_MENU
));
2068 g_signal_connect (item
, "activate",
2069 G_CALLBACK (etdp_delete_selected_cb
), to_do_pane
);
2070 gtk_widget_show (item
);
2071 gtk_menu_shell_append (menu_shell
, item
);
2073 item
= gtk_image_menu_item_new_with_mnemonic (_("D_elete All Instances..."));
2074 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2075 gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_MENU
));
2076 g_signal_connect (item
, "activate",
2077 G_CALLBACK (etdp_delete_series_cb
), to_do_pane
);
2078 gtk_widget_show (item
);
2079 gtk_menu_shell_append (menu_shell
, item
);
2081 item
= gtk_image_menu_item_new_with_mnemonic (_("_Delete..."));
2082 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
),
2083 gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_MENU
));
2084 g_signal_connect (item
, "activate",
2085 G_CALLBACK (etdp_delete_series_cb
), to_do_pane
);
2086 gtk_widget_show (item
);
2087 gtk_menu_shell_append (menu_shell
, item
);
2091 g_clear_object (&client
);
2092 g_clear_object (&comp
);
2094 item
= gtk_separator_menu_item_new ();
2095 gtk_widget_show (item
);
2096 gtk_menu_shell_append (menu_shell
, item
);
2098 item
= gtk_check_menu_item_new_with_mnemonic (_("_Show Tasks without Due date"));
2099 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item
), to_do_pane
->priv
->show_no_duedate_tasks
);
2100 g_signal_connect (item
, "toggled",
2101 G_CALLBACK (etdp_show_tasks_without_due_date_cb
), to_do_pane
);
2102 gtk_widget_show (item
);
2103 gtk_menu_shell_append (menu_shell
, item
);
2107 etdp_popup_menu (EToDoPane
*to_do_pane
,
2112 menu
= GTK_MENU (gtk_menu_new ());
2114 etdp_fill_popup_menu (to_do_pane
, menu
);
2116 gtk_menu_attach_to_widget (menu
, GTK_WIDGET (to_do_pane
->priv
->tree_view
), NULL
);
2117 g_signal_connect (menu
, "deactivate", G_CALLBACK (gtk_menu_detach
), NULL
);
2118 gtk_menu_popup_at_pointer (menu
, event
);
2122 etdp_button_press_event_cb (GtkWidget
*widget
,
2126 EToDoPane
*to_do_pane
= user_data
;
2128 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
2130 if (event
->type
== GDK_BUTTON_PRESS
&&
2131 gdk_event_triggers_context_menu (event
)) {
2132 GtkTreeSelection
*selection
;
2135 selection
= gtk_tree_view_get_selection (to_do_pane
->priv
->tree_view
);
2136 if (gtk_tree_selection_get_mode (selection
) == GTK_SELECTION_SINGLE
)
2137 gtk_tree_selection_unselect_all (selection
);
2139 if (gtk_tree_view_get_path_at_pos (to_do_pane
->priv
->tree_view
, event
->button
.x
, event
->button
.y
, &path
, NULL
, NULL
, NULL
)) {
2140 gtk_tree_selection_select_path (selection
, path
);
2141 gtk_tree_view_set_cursor (to_do_pane
->priv
->tree_view
, path
, NULL
, FALSE
);
2143 gtk_tree_path_free (path
);
2146 etdp_popup_menu (to_do_pane
, event
);
2155 etdp_popup_menu_cb (GtkWidget
*widget
,
2158 EToDoPane
*to_do_pane
= user_data
;
2160 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
2162 etdp_popup_menu (to_do_pane
, NULL
);
2168 etcp_notify_visible_cb (EToDoPane
*to_do_pane
,
2172 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2174 if (gtk_widget_get_visible (GTK_WIDGET (to_do_pane
))) {
2175 e_source_registry_watcher_reclaim (to_do_pane
->priv
->watcher
);
2177 GList
*clients
, *link
;
2179 clients
= e_cal_data_model_get_clients (to_do_pane
->priv
->events_data_model
);
2180 for (link
= clients
; link
; link
= g_list_next (link
)) {
2181 ECalClient
*client
= link
->data
;
2182 ESource
*source
= e_client_get_source (E_CLIENT (client
));
2184 e_cal_data_model_remove_client (to_do_pane
->priv
->events_data_model
, e_source_get_uid (source
));
2186 g_list_free_full (clients
, g_object_unref
);
2188 clients
= e_cal_data_model_get_clients (to_do_pane
->priv
->tasks_data_model
);
2189 for (link
= clients
; link
; link
= g_list_next (link
)) {
2190 ECalClient
*client
= link
->data
;
2191 ESource
*source
= e_client_get_source (E_CLIENT (client
));
2193 e_cal_data_model_remove_client (to_do_pane
->priv
->tasks_data_model
, e_source_get_uid (source
));
2195 g_list_free_full (clients
, g_object_unref
);
2200 e_to_do_pane_set_shell_view (EToDoPane
*to_do_pane
,
2201 EShellView
*shell_view
)
2203 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2204 g_return_if_fail (E_IS_SHELL_VIEW (shell_view
));
2206 g_weak_ref_set (&to_do_pane
->priv
->shell_view_weakref
, shell_view
);
2210 e_to_do_pane_set_property (GObject
*object
,
2212 const GValue
*value
,
2215 switch (property_id
) {
2216 case PROP_HIGHLIGHT_OVERDUE
:
2217 e_to_do_pane_set_highlight_overdue (
2218 E_TO_DO_PANE (object
),
2219 g_value_get_boolean (value
));
2222 case PROP_OVERDUE_COLOR
:
2223 e_to_do_pane_set_overdue_color (
2224 E_TO_DO_PANE (object
),
2225 g_value_get_boxed (value
));
2228 case PROP_SHELL_VIEW
:
2229 e_to_do_pane_set_shell_view (
2230 E_TO_DO_PANE (object
),
2231 g_value_get_object (value
));
2234 case PROP_SHOW_COMPLETED_TASKS
:
2235 e_to_do_pane_set_show_completed_tasks (
2236 E_TO_DO_PANE (object
),
2237 g_value_get_boolean (value
));
2240 case PROP_SHOW_NO_DUEDATE_TASKS
:
2241 e_to_do_pane_set_show_no_duedate_tasks (
2242 E_TO_DO_PANE (object
),
2243 g_value_get_boolean (value
));
2246 case PROP_USE_24HOUR_FORMAT
:
2247 e_to_do_pane_set_use_24hour_format (
2248 E_TO_DO_PANE (object
),
2249 g_value_get_boolean (value
));
2253 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
2257 e_to_do_pane_get_property (GObject
*object
,
2262 switch (property_id
) {
2263 case PROP_HIGHLIGHT_OVERDUE
:
2264 g_value_set_boolean (
2266 e_to_do_pane_get_highlight_overdue (
2267 E_TO_DO_PANE (object
)));
2270 case PROP_OVERDUE_COLOR
:
2273 e_to_do_pane_get_overdue_color (
2274 E_TO_DO_PANE (object
)));
2277 case PROP_SHELL_VIEW
:
2278 g_value_set_object (
2280 e_to_do_pane_ref_shell_view (
2281 E_TO_DO_PANE (object
)));
2284 case PROP_SHOW_COMPLETED_TASKS
:
2285 g_value_set_boolean (
2287 e_to_do_pane_get_show_completed_tasks (
2288 E_TO_DO_PANE (object
)));
2291 case PROP_SHOW_NO_DUEDATE_TASKS
:
2292 g_value_set_boolean (
2294 e_to_do_pane_get_show_no_duedate_tasks (
2295 E_TO_DO_PANE (object
)));
2298 case PROP_USE_24HOUR_FORMAT
:
2299 g_value_set_boolean (
2301 e_to_do_pane_get_use_24hour_format (
2302 E_TO_DO_PANE (object
)));
2306 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
2310 e_to_do_pane_constructed (GObject
*object
)
2312 EToDoPane
*to_do_pane
= E_TO_DO_PANE (object
);
2313 EShellView
*shell_view
;
2317 GtkCellRenderer
*renderer
;
2318 GtkTreeView
*tree_view
;
2319 GtkTreeViewColumn
*column
;
2320 GtkTreeModel
*model
, *sort_model
;
2322 GSettings
*settings
;
2323 PangoAttrList
*bold
;
2326 /* Chain up to parent's method. */
2327 G_OBJECT_CLASS (e_to_do_pane_parent_class
)->constructed (object
);
2329 shell_view
= e_to_do_pane_ref_shell_view (to_do_pane
);
2330 shell
= e_shell_backend_get_shell (e_shell_view_get_shell_backend (shell_view
));
2332 to_do_pane
->priv
->client_cache
= g_object_ref (e_shell_get_client_cache (shell
));
2333 to_do_pane
->priv
->watcher
= e_source_registry_watcher_new (e_shell_get_registry (shell
), NULL
);
2334 to_do_pane
->priv
->source_changed_id
=
2335 g_signal_connect (e_source_registry_watcher_get_registry (to_do_pane
->priv
->watcher
), "source-changed",
2336 G_CALLBACK (etdp_source_changed_cb
), to_do_pane
);
2338 g_signal_connect (to_do_pane
->priv
->watcher
, "filter",
2339 G_CALLBACK (e_to_do_pane_watcher_filter_cb
), NULL
);
2341 g_signal_connect (to_do_pane
->priv
->watcher
, "appeared",
2342 G_CALLBACK (e_to_do_pane_watcher_appeared_cb
), to_do_pane
);
2344 g_signal_connect (to_do_pane
->priv
->watcher
, "disappeared",
2345 G_CALLBACK (e_to_do_pane_watcher_disappeared_cb
), to_do_pane
);
2347 to_do_pane
->priv
->tree_store
= GTK_TREE_STORE (gtk_tree_store_new (N_COLUMNS
,
2348 GDK_TYPE_RGBA
, /* COLUMN_BGCOLOR */
2349 GDK_TYPE_RGBA
, /* COLUMN_FGCOLOR */
2350 G_TYPE_BOOLEAN
, /* COLUMN_HAS_ICON_NAME */
2351 G_TYPE_STRING
, /* COLUMN_ICON_NAME */
2352 G_TYPE_STRING
, /* COLUMN_SUMMARY */
2353 G_TYPE_STRING
, /* COLUMN_TOOLTIP */
2354 G_TYPE_STRING
, /* COLUMN_SORTKEY */
2355 G_TYPE_UINT
, /* COLUMN_DATE_MARK */
2356 E_TYPE_CAL_CLIENT
, /* COLUMN_CAL_CLIENT */
2357 E_TYPE_CAL_COMPONENT
)); /* COLUMN_CAL_COMPONENT */
2359 grid
= GTK_GRID (to_do_pane
);
2361 bold
= pango_attr_list_new ();
2362 pango_attr_list_insert (bold
, pango_attr_weight_new (PANGO_WEIGHT_BOLD
));
2364 widget
= gtk_label_new (_("To Do"));
2365 g_object_set (G_OBJECT (widget
),
2366 "halign", GTK_ALIGN_CENTER
,
2368 "valign", GTK_ALIGN_START
,
2372 gtk_grid_attach (grid
, widget
, 0, 0, 1, 1);
2374 pango_attr_list_unref (bold
);
2376 model
= GTK_TREE_MODEL (to_do_pane
->priv
->tree_store
);
2378 sort_model
= gtk_tree_model_sort_new_with_model (model
);
2379 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model
), COLUMN_SORTKEY
, GTK_SORT_ASCENDING
);
2381 widget
= gtk_tree_view_new_with_model (sort_model
);
2383 g_object_set (G_OBJECT (widget
),
2384 "halign", GTK_ALIGN_FILL
,
2386 "valign", GTK_ALIGN_FILL
,
2390 tree_view
= GTK_TREE_VIEW (widget
);
2392 widget
= gtk_scrolled_window_new (NULL
, NULL
);
2393 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget
), GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
2394 gtk_container_add (GTK_CONTAINER (widget
), GTK_WIDGET (tree_view
));
2396 g_object_set (G_OBJECT (widget
),
2397 "halign", GTK_ALIGN_FILL
,
2399 "valign", GTK_ALIGN_FILL
,
2403 gtk_grid_attach (grid
, widget
, 0, 1, 1, 1);
2405 column
= gtk_tree_view_column_new ();
2407 renderer
= gtk_cell_renderer_pixbuf_new ();
2409 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
2411 gtk_tree_view_column_set_attributes (column
, renderer
,
2412 "icon-name", COLUMN_ICON_NAME
,
2413 "visible", COLUMN_HAS_ICON_NAME
,
2416 renderer
= gtk_cell_renderer_text_new ();
2418 g_object_set (G_OBJECT (renderer
),
2419 "ellipsize", PANGO_ELLIPSIZE_END
,
2422 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
2424 gtk_tree_view_column_set_attributes (column
, renderer
,
2425 "markup", COLUMN_SUMMARY
,
2426 "background-rgba", COLUMN_BGCOLOR
,
2427 "foreground-rgba", COLUMN_FGCOLOR
,
2430 gtk_tree_view_append_column (tree_view
, column
);
2431 gtk_tree_view_set_expander_column (tree_view
, column
);
2433 for (ii
= 0; ii
< N_ROOTS
- 1; ii
++) {
2437 sort_key
= g_strdup_printf ("%c", 'A' + ii
);
2439 gtk_tree_store_append (to_do_pane
->priv
->tree_store
, &iter
, NULL
);
2440 gtk_tree_store_set (to_do_pane
->priv
->tree_store
, &iter
,
2441 COLUMN_SORTKEY
, sort_key
,
2442 COLUMN_HAS_ICON_NAME
, FALSE
,
2447 path
= gtk_tree_model_get_path (model
, &iter
);
2449 to_do_pane
->priv
->roots
[ii
] = gtk_tree_row_reference_new (model
, path
);
2450 g_warn_if_fail (to_do_pane
->priv
->roots
[ii
] != NULL
);
2452 gtk_tree_path_free (path
);
2455 gtk_tree_view_set_headers_visible (tree_view
, FALSE
);
2456 gtk_tree_view_set_tooltip_column (tree_view
, COLUMN_TOOLTIP
);
2458 gtk_widget_show_all (GTK_WIDGET (grid
));
2460 to_do_pane
->priv
->events_data_model
= e_cal_data_model_new (e_to_do_pane_submit_thread_job
, G_OBJECT (to_do_pane
));
2461 to_do_pane
->priv
->tasks_data_model
= e_cal_data_model_new (e_to_do_pane_submit_thread_job
, G_OBJECT (to_do_pane
));
2462 to_do_pane
->priv
->time_checker_id
= g_timeout_add_seconds (60, etdp_check_time_cb
, to_do_pane
);
2464 e_cal_data_model_set_expand_recurrences (to_do_pane
->priv
->events_data_model
, TRUE
);
2465 e_cal_data_model_set_expand_recurrences (to_do_pane
->priv
->tasks_data_model
, FALSE
);
2467 settings
= e_util_ref_settings ("org.gnome.evolution.calendar");
2469 g_settings_bind_with_mapping (
2470 settings
, "timezone",
2471 to_do_pane
->priv
->events_data_model
, "timezone",
2472 G_SETTINGS_BIND_GET
,
2473 etdp_settings_map_string_to_icaltimezone
,
2474 NULL
, /* one-way binding */
2477 g_settings_bind_with_mapping (
2478 settings
, "timezone",
2479 to_do_pane
->priv
->tasks_data_model
, "timezone",
2480 G_SETTINGS_BIND_GET
,
2481 etdp_settings_map_string_to_icaltimezone
,
2482 NULL
, /* one-way binding */
2486 settings
, "task-overdue-highlight",
2487 to_do_pane
, "highlight-overdue",
2488 G_SETTINGS_BIND_GET
);
2490 g_settings_bind_with_mapping (
2491 settings
, "task-overdue-color",
2492 to_do_pane
, "overdue-color",
2493 G_SETTINGS_BIND_GET
,
2494 etdp_settings_map_string_to_rgba
,
2495 NULL
, /* one-way binding */
2499 settings
, "use-24hour-format",
2500 to_do_pane
, "use-24hour-format",
2501 G_SETTINGS_BIND_GET
);
2503 g_object_unref (settings
);
2505 g_signal_connect (to_do_pane
->priv
->events_data_model
, "notify::timezone",
2506 G_CALLBACK (etdp_timezone_changed_cb
), to_do_pane
);
2508 g_signal_connect (tree_view
, "row-activated",
2509 G_CALLBACK (etdp_row_activated_cb
), to_do_pane
);
2511 g_signal_connect (tree_view
, "button-press-event",
2512 G_CALLBACK (etdp_button_press_event_cb
), to_do_pane
);
2514 g_signal_connect (tree_view
, "popup-menu",
2515 G_CALLBACK (etdp_popup_menu_cb
), to_do_pane
);
2517 to_do_pane
->priv
->tree_view
= tree_view
;
2519 etdp_check_time_changed (to_do_pane
, TRUE
);
2521 g_clear_object (&shell_view
);
2522 g_clear_object (&sort_model
);
2524 g_signal_connect (to_do_pane
, "notify::visible",
2525 G_CALLBACK (etcp_notify_visible_cb
), NULL
);
2527 if (gtk_widget_get_visible (GTK_WIDGET (to_do_pane
)))
2528 e_source_registry_watcher_reclaim (to_do_pane
->priv
->watcher
);
2532 e_to_do_pane_dispose (GObject
*object
)
2534 EToDoPane
*to_do_pane
= E_TO_DO_PANE (object
);
2537 if (to_do_pane
->priv
->cancellable
) {
2538 g_cancellable_cancel (to_do_pane
->priv
->cancellable
);
2539 g_clear_object (&to_do_pane
->priv
->cancellable
);
2542 if (to_do_pane
->priv
->time_checker_id
) {
2543 g_source_remove (to_do_pane
->priv
->time_checker_id
);
2544 to_do_pane
->priv
->time_checker_id
= 0;
2547 if (to_do_pane
->priv
->source_changed_id
) {
2548 g_signal_handler_disconnect (e_source_registry_watcher_get_registry (to_do_pane
->priv
->watcher
),
2549 to_do_pane
->priv
->source_changed_id
);
2550 to_do_pane
->priv
->source_changed_id
= 0;
2553 for (ii
= 0; ii
< N_ROOTS
; ii
++) {
2554 gtk_tree_row_reference_free (to_do_pane
->priv
->roots
[ii
]);
2555 to_do_pane
->priv
->roots
[ii
] = NULL
;
2558 g_hash_table_remove_all (to_do_pane
->priv
->component_refs
);
2559 g_hash_table_remove_all (to_do_pane
->priv
->client_colors
);
2561 g_clear_object (&to_do_pane
->priv
->client_cache
);
2562 g_clear_object (&to_do_pane
->priv
->watcher
);
2563 g_clear_object (&to_do_pane
->priv
->tree_store
);
2564 g_clear_object (&to_do_pane
->priv
->events_data_model
);
2565 g_clear_object (&to_do_pane
->priv
->tasks_data_model
);
2567 g_weak_ref_set (&to_do_pane
->priv
->shell_view_weakref
, NULL
);
2569 /* Chain up to parent's method. */
2570 G_OBJECT_CLASS (e_to_do_pane_parent_class
)->dispose (object
);
2574 e_to_do_pane_finalize (GObject
*object
)
2576 EToDoPane
*to_do_pane
= E_TO_DO_PANE (object
);
2578 g_weak_ref_clear (&to_do_pane
->priv
->shell_view_weakref
);
2580 g_hash_table_destroy (to_do_pane
->priv
->component_refs
);
2581 g_hash_table_destroy (to_do_pane
->priv
->client_colors
);
2583 if (to_do_pane
->priv
->overdue_color
)
2584 gdk_rgba_free (to_do_pane
->priv
->overdue_color
);
2586 /* Chain up to parent's method. */
2587 G_OBJECT_CLASS (e_to_do_pane_parent_class
)->finalize (object
);
2591 e_to_do_pane_init (EToDoPane
*to_do_pane
)
2593 to_do_pane
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (to_do_pane
, E_TYPE_TO_DO_PANE
, EToDoPanePrivate
);
2594 to_do_pane
->priv
->cancellable
= g_cancellable_new ();
2596 to_do_pane
->priv
->component_refs
= g_hash_table_new_full (component_ident_hash
, component_ident_equal
,
2597 component_ident_free
, etdp_free_component_refs
);
2599 to_do_pane
->priv
->client_colors
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
2600 NULL
, (GDestroyNotify
) gdk_rgba_free
);
2602 to_do_pane
->priv
->nearest_due
= (time_t) -1;
2604 g_weak_ref_init (&to_do_pane
->priv
->shell_view_weakref
, NULL
);
2608 e_to_do_pane_class_init (EToDoPaneClass
*klass
)
2610 GObjectClass
*object_class
;
2612 g_type_class_add_private (klass
, sizeof (EToDoPanePrivate
));
2614 object_class
= G_OBJECT_CLASS (klass
);
2615 object_class
->set_property
= e_to_do_pane_set_property
;
2616 object_class
->get_property
= e_to_do_pane_get_property
;
2617 object_class
->constructed
= e_to_do_pane_constructed
;
2618 object_class
->dispose
= e_to_do_pane_dispose
;
2619 object_class
->finalize
= e_to_do_pane_finalize
;
2621 g_object_class_install_property (
2623 PROP_HIGHLIGHT_OVERDUE
,
2624 g_param_spec_boolean (
2625 "highlight-overdue",
2626 "Highlight Overdue Tasks",
2631 G_PARAM_STATIC_STRINGS
));
2633 g_object_class_install_property (
2636 g_param_spec_boxed (
2642 G_PARAM_STATIC_STRINGS
));
2644 g_object_class_install_property (
2647 g_param_spec_object (
2653 G_PARAM_CONSTRUCT_ONLY
|
2654 G_PARAM_STATIC_STRINGS
));
2656 g_object_class_install_property (
2658 PROP_SHOW_COMPLETED_TASKS
,
2659 g_param_spec_boolean (
2660 "show-completed-tasks",
2661 "Show Completed Tasks",
2666 G_PARAM_STATIC_STRINGS
));
2668 g_object_class_install_property (
2670 PROP_SHOW_NO_DUEDATE_TASKS
,
2671 g_param_spec_boolean (
2672 "show-no-duedate-tasks",
2673 "Show tasks without Due date",
2678 G_PARAM_STATIC_STRINGS
));
2680 g_object_class_install_property (
2682 PROP_USE_24HOUR_FORMAT
,
2683 g_param_spec_boolean (
2684 "use-24hour-format",
2685 "Use 24hour Format",
2690 G_PARAM_STATIC_STRINGS
));
2694 e_to_do_pane_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface
*iface
)
2696 iface
->component_added
= etdp_data_subscriber_component_added
;
2697 iface
->component_modified
= etdp_data_subscriber_component_modified
;
2698 iface
->component_removed
= etdp_data_subscriber_component_removed
;
2699 iface
->freeze
= etdp_data_subscriber_freeze
;
2700 iface
->thaw
= etdp_data_subscriber_thaw
;
2705 * @shell_view: an #EShellView
2707 * Creates a new #EToDoPane.
2709 * Returns: (transfer full): A new #EToDoPane.
2714 e_to_do_pane_new (EShellView
*shell_view
)
2716 g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view
), NULL
);
2718 return g_object_new (E_TYPE_TO_DO_PANE
,
2719 "shell-view", shell_view
,
2724 * e_to_do_pane_ref_shell_view:
2725 * @to_do_pane: an #EToDoPane
2727 * Returns: (transfer full): an #EShellView used to create the @to_do_pane with added reference.
2728 * Free it with g_object_unref() when no longer needed.
2733 e_to_do_pane_ref_shell_view (EToDoPane
*to_do_pane
)
2735 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), NULL
);
2737 return g_weak_ref_get (&to_do_pane
->priv
->shell_view_weakref
);
2741 * e_to_do_pane_get_highlight_overdue:
2742 * @to_do_pane: an #EToDoPane
2744 * Returns: Whether highlights overdue tasks with overdue-color.
2749 e_to_do_pane_get_highlight_overdue (EToDoPane
*to_do_pane
)
2751 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
2753 return to_do_pane
->priv
->highlight_overdue
;
2757 * e_to_do_pane_set_highlight_overdue:
2758 * @to_do_pane: an #EToDoPane
2759 * @highlight_overdue: a value to set
2761 * Sets whether should highlight overdue tasks with overdue-color.
2766 e_to_do_pane_set_highlight_overdue (EToDoPane
*to_do_pane
,
2767 gboolean highlight_overdue
)
2769 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2771 if ((to_do_pane
->priv
->highlight_overdue
? 1 : 0) == (highlight_overdue
? 1 : 0))
2774 to_do_pane
->priv
->highlight_overdue
= highlight_overdue
;
2776 if (to_do_pane
->priv
->overdue_color
)
2777 etdp_update_colors (to_do_pane
, TRUE
);
2779 g_object_notify (G_OBJECT (to_do_pane
), "highlight-overdue");
2783 * e_to_do_pane_get_overdue_color:
2784 * @to_do_pane: an #EToDoPane
2786 * Returns: (transfer none) (nullable): Currently set color to use for overdue tasks.
2791 e_to_do_pane_get_overdue_color (EToDoPane
*to_do_pane
)
2793 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), NULL
);
2795 return to_do_pane
->priv
->overdue_color
;
2799 * e_to_do_pane_set_overdue_color:
2800 * @to_do_pane: an #EToDoPane
2801 * @overdue_color: (nullable): a color to set, or %NULL
2803 * Sets a color to use for overdue tasks, or unsets the previous,
2809 e_to_do_pane_set_overdue_color (EToDoPane
*to_do_pane
,
2810 const GdkRGBA
*overdue_color
)
2812 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2814 if (to_do_pane
->priv
->overdue_color
== overdue_color
||
2815 (to_do_pane
->priv
->overdue_color
&& overdue_color
&&
2816 gdk_rgba_equal (to_do_pane
->priv
->overdue_color
, overdue_color
)))
2819 if (to_do_pane
->priv
->overdue_color
) {
2820 gdk_rgba_free (to_do_pane
->priv
->overdue_color
);
2821 to_do_pane
->priv
->overdue_color
= NULL
;
2825 to_do_pane
->priv
->overdue_color
= gdk_rgba_copy (overdue_color
);
2827 if (to_do_pane
->priv
->highlight_overdue
)
2828 etdp_update_colors (to_do_pane
, TRUE
);
2830 g_object_notify (G_OBJECT (to_do_pane
), "overdue-color");
2834 * e_to_do_pane_get_show_completed_tasks:
2835 * @to_do_pane: an #EToDoPane
2837 * Returns: Whether completed tasks should be shown in the view.
2842 e_to_do_pane_get_show_completed_tasks (EToDoPane
*to_do_pane
)
2844 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
2846 return to_do_pane
->priv
->show_completed_tasks
;
2850 * e_to_do_pane_set_show_completed_tasks:
2851 * @to_do_pane: an #EToDoPane
2852 * @show_completed_tasks: a value to set
2854 * Sets whether completed tasks should be shown in the view.
2859 e_to_do_pane_set_show_completed_tasks (EToDoPane
*to_do_pane
,
2860 gboolean show_completed_tasks
)
2862 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2864 if ((to_do_pane
->priv
->show_completed_tasks
? 1 : 0) == (show_completed_tasks
? 1 : 0))
2867 to_do_pane
->priv
->show_completed_tasks
= show_completed_tasks
;
2869 etdp_update_queries (to_do_pane
);
2871 g_object_notify (G_OBJECT (to_do_pane
), "show-completed-tasks");
2875 * e_to_do_pane_get_show_no_duedate_tasks:
2876 * @to_do_pane: an #EToDoPane
2878 * Returns: Whether tasks without Due date should be shown in the view.
2883 e_to_do_pane_get_show_no_duedate_tasks (EToDoPane
*to_do_pane
)
2885 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
2887 return to_do_pane
->priv
->show_no_duedate_tasks
;
2891 * e_to_do_pane_set_show_no_duedate_tasks:
2892 * @to_do_pane: an #EToDoPane
2893 * @show_no_duedate_tasks: a value to set
2895 * Sets whether tasks without Due date should be shown in the view.
2900 e_to_do_pane_set_show_no_duedate_tasks (EToDoPane
*to_do_pane
,
2901 gboolean show_no_duedate_tasks
)
2903 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2905 if ((to_do_pane
->priv
->show_no_duedate_tasks
? 1 : 0) == (show_no_duedate_tasks
? 1 : 0))
2908 to_do_pane
->priv
->show_no_duedate_tasks
= show_no_duedate_tasks
;
2910 etdp_update_queries (to_do_pane
);
2912 g_object_notify (G_OBJECT (to_do_pane
), "show-no-duedate-tasks");
2916 * e_to_do_pane_get_use_24hour_format:
2917 * @to_do_pane: an #EToDoPane
2919 * Returns: Whether uses 24-hour format for time display.
2924 e_to_do_pane_get_use_24hour_format (EToDoPane
*to_do_pane
)
2926 g_return_val_if_fail (E_IS_TO_DO_PANE (to_do_pane
), FALSE
);
2928 return to_do_pane
->priv
->use_24hour_format
;
2932 * e_to_do_pane_set_use_24hour_format:
2933 * @to_do_pane: an #EToDoPane
2934 * @use_24hour_format: a value to set
2936 * Sets whether to use 24-hour format for time display.
2941 e_to_do_pane_set_use_24hour_format (EToDoPane
*to_do_pane
,
2942 gboolean use_24hour_format
)
2944 g_return_if_fail (E_IS_TO_DO_PANE (to_do_pane
));
2946 if ((to_do_pane
->priv
->use_24hour_format
? 1 : 0) == (use_24hour_format
? 1 : 0))
2949 to_do_pane
->priv
->use_24hour_format
= use_24hour_format
;
2951 etdp_update_all (to_do_pane
);
2953 g_object_notify (G_OBJECT (to_do_pane
), "use-24hour-format");