d9e778f501
See https://bugzilla.gnome.org/show_bug.cgi?id=632109#c56 Signed-off-by: David Zeuthen <davidz@redhat.com>
266 lines
8.0 KiB
C
266 lines
8.0 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
#include "config.h"
|
|
|
|
#include "calendar-client/calendar-client.h"
|
|
#include "shell-evolution-event-source.h"
|
|
|
|
|
|
struct _ShellEvolutionEventSourceClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
struct _ShellEvolutionEventSource {
|
|
GObject parent;
|
|
CalendarClient *client;
|
|
/* The month that we are currently requesting events from */
|
|
gint req_year;
|
|
gint req_mon; /* starts at 1, not zero */
|
|
};
|
|
|
|
/* Signals */
|
|
enum
|
|
{
|
|
CHANGED_SIGNAL,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
G_DEFINE_TYPE (ShellEvolutionEventSource, shell_evolution_event_source, G_TYPE_OBJECT);
|
|
|
|
static void
|
|
on_tasks_changed (CalendarClient *client,
|
|
gpointer user_data)
|
|
{
|
|
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (user_data);
|
|
/* g_print ("on tasks changed\n"); */
|
|
g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
|
|
}
|
|
|
|
static void
|
|
on_appointments_changed (CalendarClient *client,
|
|
gpointer user_data)
|
|
{
|
|
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (user_data);
|
|
/* g_print ("on appointments changed\n"); */
|
|
g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
|
|
}
|
|
|
|
static void
|
|
shell_evolution_event_source_init (ShellEvolutionEventSource *source)
|
|
{
|
|
source->client = calendar_client_new ();
|
|
g_signal_connect (source->client,
|
|
"tasks-changed",
|
|
G_CALLBACK (on_tasks_changed),
|
|
source);
|
|
g_signal_connect (source->client,
|
|
"appointments-changed",
|
|
G_CALLBACK (on_appointments_changed),
|
|
source);
|
|
}
|
|
|
|
static void
|
|
shell_evolution_event_source_finalize (GObject *object)
|
|
{
|
|
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (object);
|
|
g_object_unref (source->client);
|
|
G_OBJECT_CLASS (shell_evolution_event_source_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
shell_evolution_event_source_class_init (ShellEvolutionEventSourceClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
gobject_class->finalize = shell_evolution_event_source_finalize;
|
|
|
|
signals[CHANGED_SIGNAL] =
|
|
g_signal_new ("changed",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
}
|
|
|
|
ShellEvolutionEventSource *
|
|
shell_evolution_event_source_new (void)
|
|
{
|
|
return SHELL_EVOLUTION_EVENT_SOURCE (g_object_new (SHELL_TYPE_EVOLUTION_EVENT_SOURCE, NULL));
|
|
}
|
|
|
|
void
|
|
shell_evolution_event_source_request_range (ShellEvolutionEventSource *source,
|
|
gint64 msec_begin,
|
|
gint64 msec_end)
|
|
{
|
|
GDateTime *middle_utc, *middle;
|
|
|
|
/* The CalendarClient type is a convenience wrapper on top of
|
|
* Evolution Data Server. It is based on the assumption that only
|
|
* a single month is shown at a time.
|
|
*
|
|
* To avoid reimplemting all the work already done in CalendarClient
|
|
* we make the same assumption. This means that we only show events
|
|
* in the month that is in the middle of @msec_begin and
|
|
* @msec_end. Since the Shell displays a month at a time (plus the
|
|
* days before and after) it works out just fine.
|
|
*/
|
|
|
|
middle_utc = g_date_time_new_from_unix_utc ((msec_begin + msec_end) / 2 / 1000);
|
|
/* CalendarClient uses localtime rather than UTC */
|
|
middle = g_date_time_to_local (middle_utc);
|
|
g_date_time_unref (middle_utc);
|
|
g_date_time_get_ymd (middle, &source->req_year, &source->req_mon, NULL);
|
|
g_date_time_unref (middle);
|
|
calendar_client_select_month (source->client, source->req_mon - 1, source->req_year);
|
|
}
|
|
|
|
static gint
|
|
event_cmp (gconstpointer a,
|
|
gconstpointer b)
|
|
{
|
|
const ShellEvolutionEvent *ea;
|
|
const ShellEvolutionEvent *eb;
|
|
|
|
ea = a;
|
|
eb = b;
|
|
if (ea->msec_begin < eb->msec_begin)
|
|
return -1;
|
|
else if (ea->msec_begin > eb->msec_begin)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* shell_evolution_event_source_get_events:
|
|
* @source: A #ShellEvolutionEventSource.
|
|
* @msec_begin: Start date (milli-seconds since Epoch).
|
|
* @msec_end: End date (milli-seconds since Epoch).
|
|
*
|
|
* Gets all events that occur between @msec_begin and @msec_end.
|
|
*
|
|
* Returns: (element-type ShellEvolutionEvent) (transfer full): List of events.
|
|
*/
|
|
GList *
|
|
shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
|
gint64 msec_begin,
|
|
gint64 msec_end)
|
|
{
|
|
GList *result;
|
|
GDateTime *cur_date;
|
|
GDateTime *begin_date_utc, *begin_date;
|
|
GDateTime *end_date_utc, *end_date;
|
|
|
|
g_return_val_if_fail (msec_begin <= msec_end, NULL);
|
|
|
|
result = NULL;
|
|
|
|
begin_date_utc = g_date_time_new_from_unix_utc (msec_begin / 1000);
|
|
end_date_utc = g_date_time_new_from_unix_utc (msec_end / 1000);
|
|
|
|
/* CalendarClient uses localtime rather than UTC */
|
|
begin_date = g_date_time_to_local (begin_date_utc);
|
|
end_date = g_date_time_to_local (end_date_utc);
|
|
g_date_time_unref (begin_date_utc);
|
|
g_date_time_unref (end_date_utc);
|
|
|
|
cur_date = g_date_time_ref (begin_date);
|
|
do
|
|
{
|
|
gint year, mon, day;
|
|
GDateTime *next_date;
|
|
|
|
g_date_time_get_ymd (cur_date, &year, &mon, &day);
|
|
/* g_print ("y=%04d m=%02d d=%02d\n", year, mon, day); */
|
|
|
|
/* Silently drop events not in range (see comment in
|
|
* shell_evolution_event_source_request_range() above)
|
|
*/
|
|
if (!(year == source->req_year && mon == source->req_mon))
|
|
{
|
|
/* g_print ("skipping day\n"); */
|
|
}
|
|
else
|
|
{
|
|
GSList *events;
|
|
GSList *l;
|
|
calendar_client_select_day (source->client, day);
|
|
events = calendar_client_get_events (source->client, CALENDAR_EVENT_APPOINTMENT);
|
|
/* g_print ("num_events: %d\n", g_slist_length (events)); */
|
|
for (l = events; l; l = l->next)
|
|
{
|
|
CalendarAppointment *appointment = l->data;
|
|
ShellEvolutionEvent *event;
|
|
gint64 start_time;
|
|
|
|
if (appointment->is_all_day)
|
|
{
|
|
start_time = g_date_time_to_unix (cur_date) * G_GINT64_CONSTANT (1000);
|
|
}
|
|
else
|
|
{
|
|
start_time = appointment->start_time * G_GINT64_CONSTANT (1000);
|
|
}
|
|
event = shell_evolution_event_new (appointment->summary,
|
|
appointment->is_all_day,
|
|
start_time);
|
|
result = g_list_prepend (result, event);
|
|
}
|
|
g_slist_foreach (events, (GFunc) calendar_event_free, NULL);
|
|
g_slist_free (events);
|
|
}
|
|
|
|
next_date = g_date_time_add_days (cur_date, 1);
|
|
g_date_time_unref (cur_date);
|
|
cur_date = next_date;
|
|
}
|
|
while (g_date_time_difference (end_date, cur_date) > 0);
|
|
g_date_time_unref (begin_date);
|
|
g_date_time_unref (end_date);
|
|
|
|
result = g_list_sort (result, event_cmp);
|
|
|
|
return result;
|
|
}
|
|
|
|
G_DEFINE_BOXED_TYPE (ShellEvolutionEvent,
|
|
shell_evolution_event,
|
|
shell_evolution_event_copy,
|
|
shell_evolution_event_free);
|
|
|
|
void
|
|
shell_evolution_event_free (ShellEvolutionEvent *event)
|
|
{
|
|
g_free (event->summary);
|
|
g_free (event);
|
|
}
|
|
|
|
ShellEvolutionEvent *
|
|
shell_evolution_event_copy (ShellEvolutionEvent *event)
|
|
{
|
|
ShellEvolutionEvent *copy;
|
|
copy = g_memdup (event, sizeof (ShellEvolutionEvent));
|
|
copy->summary = g_strdup (event->summary);
|
|
return copy;
|
|
}
|
|
|
|
ShellEvolutionEvent *
|
|
shell_evolution_event_new (const gchar *summary,
|
|
gboolean all_day,
|
|
gint64 msec_begin)
|
|
{
|
|
ShellEvolutionEvent *event;
|
|
event = g_new0 (ShellEvolutionEvent, 1);
|
|
event->summary = g_strdup (summary);
|
|
event->all_day = all_day;
|
|
event->msec_begin = msec_begin;
|
|
return event;
|
|
}
|