~charlesk/indicator-datetime/lp-1001595

« back to all changes in this revision

Viewing changes to src/planner-eds.c

  • Committer: CI bot
  • Author(s): Charles Kerr
  • Date: 2014-01-31 11:46:08 UTC
  • mfrom: (290.2.86 cpp)
  • Revision ID: ps-jenkins@lists.canonical.com-20140131114608-8sfzhimcfdywmk46
Finally land this. Other, still open bugs will be fixed in subsequent commits. Fixes: 793450, 1271484, 1274046

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2013 Canonical Ltd.
3
 
 *
4
 
 * Authors:
5
 
 *   Charles Kerr <charles.kerr@canonical.com>
6
 
 *
7
 
 * This program is free software: you can redistribute it and/or modify it
8
 
 * under the terms of the GNU General Public License version 3, as published
9
 
 * by the Free Software Foundation.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful, but
12
 
 * WITHOUT ANY WARRANTY; without even the implied warranties of
13
 
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
 
 * PURPOSE.  See the GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License along
17
 
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <libical/ical.h>
21
 
#include <libical/icaltime.h>
22
 
#include <libecal/libecal.h>
23
 
#include <libedataserver/libedataserver.h>
24
 
 
25
 
#include "planner-eds.h"
26
 
 
27
 
struct _IndicatorDatetimePlannerEdsPriv
28
 
{
29
 
  GSList * sources;
30
 
  GCancellable * cancellable;
31
 
  ESourceRegistry * source_registry;
32
 
};
33
 
 
34
 
typedef IndicatorDatetimePlannerEdsPriv priv_t;
35
 
 
36
 
G_DEFINE_TYPE (IndicatorDatetimePlannerEds,
37
 
               indicator_datetime_planner_eds,
38
 
               INDICATOR_TYPE_DATETIME_PLANNER)
39
 
 
40
 
G_DEFINE_QUARK ("source-client", source_client)
41
 
 
42
 
/***
43
 
****
44
 
****  my_get_appointments() helpers
45
 
****
46
 
***/
47
 
 
48
 
/* whole-task data that all the subtasks can see */
49
 
struct appointment_task_data
50
 
{
51
 
  /* a ref to the planner's cancellable */
52
 
  GCancellable * cancellable;
53
 
 
54
 
  /* how many subtasks are still running on */
55
 
  int subtask_count;
56
 
 
57
 
  /* the list of appointments to be returned */
58
 
  GSList * appointments;
59
 
};
60
 
 
61
 
static struct appointment_task_data *
62
 
appointment_task_data_new (GCancellable * cancellable)
63
 
{
64
 
  struct appointment_task_data * data;
65
 
 
66
 
  data = g_slice_new0 (struct appointment_task_data);
67
 
  data->cancellable = g_object_ref (cancellable);
68
 
  return data;
69
 
}
70
 
 
71
 
static void
72
 
appointment_task_data_free (gpointer gdata)
73
 
{
74
 
  struct appointment_task_data * data = gdata;
75
 
 
76
 
  g_object_unref (data->cancellable);
77
 
 
78
 
  g_slice_free (struct appointment_task_data, data);
79
 
}
80
 
 
81
 
static void
82
 
appointment_task_done (GTask * task)
83
 
{
84
 
  struct appointment_task_data * data = g_task_get_task_data (task);
85
 
 
86
 
  g_task_return_pointer (task, data->appointments, NULL);
87
 
  g_object_unref (task);
88
 
}
89
 
 
90
 
static void
91
 
appointment_task_decrement_subtasks (GTask * task)
92
 
{
93
 
  struct appointment_task_data * data = g_task_get_task_data (task);
94
 
 
95
 
  if (g_atomic_int_dec_and_test (&data->subtask_count))
96
 
    appointment_task_done (task);
97
 
}
98
 
 
99
 
static void
100
 
appointment_task_increment_subtasks (GTask * task)
101
 
{
102
 
  struct appointment_task_data * data = g_task_get_task_data (task);
103
 
 
104
 
  g_atomic_int_inc (&data->subtask_count);
105
 
}
106
 
 
107
 
/**
108
 
***  get-the-appointment's-uri subtasks
109
 
**/
110
 
 
111
 
struct appointment_uri_subtask_data
112
 
{
113
 
  /* The parent task */
114
 
  GTask * task;
115
 
 
116
 
  /* The appointment whose uri we're looking for.
117
 
     This pointer is owned by the Task and isn't reffed/unreffed by the subtask */
118
 
  struct IndicatorDatetimeAppt * appt;
119
 
};
120
 
 
121
 
static void
122
 
appointment_uri_subtask_done (struct appointment_uri_subtask_data * subdata)
123
 
{
124
 
  GTask * task = subdata->task;
125
 
 
126
 
  /* free the subtask data */
127
 
  g_slice_free (struct appointment_uri_subtask_data, subdata);
128
 
 
129
 
  appointment_task_decrement_subtasks (task);
130
 
}
131
 
 
132
 
static struct appointment_uri_subtask_data *
133
 
appointment_uri_subtask_data_new (GTask * task, struct IndicatorDatetimeAppt * appt)
134
 
{
135
 
  struct appointment_uri_subtask_data * subdata;
136
 
 
137
 
  appointment_task_increment_subtasks (task);
138
 
 
139
 
  subdata = g_slice_new0 (struct appointment_uri_subtask_data);
140
 
  subdata->task = task;
141
 
  subdata->appt = appt;
142
 
  return subdata;
143
 
}
144
 
 
145
 
static void
146
 
on_appointment_uris_ready (GObject      * client,
147
 
                           GAsyncResult * res,
148
 
                           gpointer       gsubdata)
149
 
{
150
 
  GSList * uris;
151
 
  GError * error;
152
 
  struct appointment_uri_subtask_data * subdata = gsubdata;
153
 
 
154
 
  uris = NULL;
155
 
  error = NULL;
156
 
  e_cal_client_get_attachment_uris_finish (E_CAL_CLIENT(client), res, &uris, &error);
157
 
  if (error != NULL)
158
 
    {
159
 
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
160
 
        g_warning ("Error getting appointment uris: %s", error->message);
161
 
 
162
 
      g_error_free (error);
163
 
    }
164
 
  else if (uris != NULL)
165
 
    {
166
 
      struct IndicatorDatetimeAppt * appt = subdata->appt;
167
 
      appt->url = g_strdup (uris->data); /* copy the first URL */
168
 
      g_debug ("found url '%s' for appointment '%s'", appt->url, appt->summary);
169
 
      e_client_util_free_string_slist (uris);
170
 
    }
171
 
 
172
 
  appointment_uri_subtask_done (subdata);
173
 
}
174
 
 
175
 
/**
176
 
***  enumerate-the-components subtasks
177
 
**/
178
 
 
179
 
/* data struct for the enumerate-components subtask */
180
 
struct appointment_component_subtask_data
181
 
{
182
 
  /* The parent task */
183
 
  GTask * task;
184
 
 
185
 
  /* The client we're walking through. The subtask owns a ref to this */
186
 
  ECalClient * client;
187
 
 
188
 
  /* The appointment's color coding. The subtask owns this string */
189
 
  gchar * color;
190
 
};
191
 
 
192
 
static void
193
 
on_appointment_component_subtask_done (gpointer gsubdata)
194
 
{
195
 
  struct appointment_component_subtask_data * subdata = gsubdata;
196
 
  GTask * task = subdata->task;
197
 
 
198
 
  /* free the subtask data */
199
 
  g_free (subdata->color);
200
 
  g_object_unref (subdata->client);
201
 
  g_slice_free (struct appointment_component_subtask_data, subdata);
202
 
 
203
 
  appointment_task_decrement_subtasks (task);
204
 
}
205
 
 
206
 
static struct appointment_component_subtask_data *
207
 
appointment_component_subtask_data_new (GTask * task, ECalClient * client, const gchar * color)
208
 
{
209
 
  struct appointment_component_subtask_data * subdata;
210
 
 
211
 
  appointment_task_increment_subtasks (task);
212
 
 
213
 
  subdata = g_slice_new0 (struct appointment_component_subtask_data);
214
 
  subdata->task = task;
215
 
  subdata->client = g_object_ref (client);
216
 
  subdata->color = g_strdup (color);
217
 
  return subdata;
218
 
}
219
 
 
220
 
static gboolean
221
 
my_get_appointments_foreach (ECalComponent * component,
222
 
                             time_t          begin,
223
 
                             time_t          end,
224
 
                             gpointer        gsubdata)
225
 
{
226
 
  const ECalComponentVType vtype = e_cal_component_get_vtype (component);
227
 
  struct appointment_component_subtask_data * subdata = gsubdata;
228
 
  struct appointment_task_data * data = g_task_get_task_data (subdata->task);
229
 
 
230
 
  if ((vtype == E_CAL_COMPONENT_EVENT) || (vtype == E_CAL_COMPONENT_TODO))
231
 
    {
232
 
      const gchar * uid = NULL;
233
 
      icalproperty_status status = 0;
234
 
 
235
 
      e_cal_component_get_uid (component, &uid);
236
 
      e_cal_component_get_status (component, &status);
237
 
 
238
 
      if ((uid != NULL) &&
239
 
          (status != ICAL_STATUS_COMPLETED) &&
240
 
          (status != ICAL_STATUS_CANCELLED))
241
 
        {
242
 
          GList * alarm_uids;
243
 
          GSList * l;
244
 
          GSList * recur_list;
245
 
          ECalComponentText text;
246
 
          struct IndicatorDatetimeAppt * appt;
247
 
          struct appointment_uri_subtask_data * uri_subdata;
248
 
 
249
 
          appt = g_slice_new0 (struct IndicatorDatetimeAppt);
250
 
 
251
 
          /* Determine whether this is a recurring event.
252
 
             NB: icalrecurrencetype supports complex recurrence patterns;
253
 
             however, since design only allows daily recurrence,
254
 
             that's all we support here. */
255
 
          e_cal_component_get_rrule_list (component, &recur_list);
256
 
          for (l=recur_list; l!=NULL; l=l->next)
257
 
            {
258
 
              const struct icalrecurrencetype * recur = l->data;
259
 
              appt->is_daily |= ((recur->freq == ICAL_DAILY_RECURRENCE)
260
 
                                  && (recur->interval == 1));
261
 
            }
262
 
          e_cal_component_free_recur_list (recur_list);
263
 
 
264
 
          text.value = "";
265
 
          e_cal_component_get_summary (component, &text);
266
 
 
267
 
          appt->begin = g_date_time_new_from_unix_local (begin);
268
 
          appt->end = g_date_time_new_from_unix_local (end);
269
 
          appt->color = g_strdup (subdata->color);
270
 
          appt->is_event = vtype == E_CAL_COMPONENT_EVENT;
271
 
          appt->summary = g_strdup (text.value);
272
 
          appt->uid = g_strdup (uid);
273
 
 
274
 
          alarm_uids = e_cal_component_get_alarm_uids (component);
275
 
          appt->has_alarms = alarm_uids != NULL;
276
 
          cal_obj_uid_list_free (alarm_uids);
277
 
 
278
 
          data->appointments = g_slist_prepend (data->appointments, appt);
279
 
 
280
 
          /* start a new subtask to get the associated URIs */
281
 
          uri_subdata = appointment_uri_subtask_data_new (subdata->task, appt);
282
 
          e_cal_client_get_attachment_uris (subdata->client,
283
 
                                            uid,
284
 
                                            NULL,
285
 
                                            data->cancellable,
286
 
                                            on_appointment_uris_ready,
287
 
                                            uri_subdata);
288
 
        }
289
 
    }
290
 
 
291
 
  return G_SOURCE_CONTINUE;
292
 
}
293
 
 
294
 
/***
295
 
****  IndicatorDatetimePlanner virtual funcs
296
 
***/
297
 
 
298
 
static void
299
 
my_get_appointments (IndicatorDatetimePlanner  * planner,
300
 
                     GDateTime                 * begin_datetime,
301
 
                     GDateTime                 * end_datetime,
302
 
                     GAsyncReadyCallback         callback,
303
 
                     gpointer                    user_data)
304
 
{
305
 
  GSList * l;
306
 
  priv_t * p;
307
 
  const char * str;
308
 
  icaltimezone * default_timezone;
309
 
  const int64_t begin = g_date_time_to_unix (begin_datetime);
310
 
  const int64_t end = g_date_time_to_unix (end_datetime);
311
 
  GTask * task;
312
 
  gboolean subtasks_added;
313
 
 
314
 
  p = INDICATOR_DATETIME_PLANNER_EDS (planner)->priv;
315
 
 
316
 
  /**
317
 
  ***  init the default timezone
318
 
  **/
319
 
 
320
 
  default_timezone = NULL;
321
 
 
322
 
  if ((str = indicator_datetime_planner_get_timezone (planner)))
323
 
    {
324
 
      default_timezone = icaltimezone_get_builtin_timezone (str);
325
 
 
326
 
      if (default_timezone == NULL) /* maybe str is a tzid? */
327
 
        default_timezone = icaltimezone_get_builtin_timezone_from_tzid (str);
328
 
    }
329
 
 
330
 
  /**
331
 
  ***  walk through the sources to build the appointment list
332
 
  **/
333
 
 
334
 
  task = g_task_new (planner, p->cancellable, callback, user_data);
335
 
  g_task_set_task_data (task,
336
 
                        appointment_task_data_new (p->cancellable),
337
 
                        appointment_task_data_free);
338
 
 
339
 
  subtasks_added = FALSE;
340
 
  for (l=p->sources; l!=NULL; l=l->next)
341
 
    {
342
 
      ESource * source;
343
 
      ECalClient * client;
344
 
      const char * color;
345
 
      struct appointment_component_subtask_data * subdata;
346
 
 
347
 
      source = l->data;
348
 
      client = g_object_get_qdata (l->data, source_client_quark());
349
 
      if (client == NULL)
350
 
        continue;
351
 
 
352
 
      if (default_timezone != NULL)
353
 
        e_cal_client_set_default_timezone (client, default_timezone);
354
 
 
355
 
      /* start a new subtask to enumerate all the components in this client. */
356
 
      color = e_source_selectable_get_color (e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR));
357
 
      subdata = appointment_component_subtask_data_new (task, client, color);
358
 
      subtasks_added = TRUE;
359
 
      e_cal_client_generate_instances (client,
360
 
                                       begin,
361
 
                                       end,
362
 
                                       p->cancellable,
363
 
                                       my_get_appointments_foreach,
364
 
                                       subdata,
365
 
                                       on_appointment_component_subtask_done);
366
 
    }
367
 
 
368
 
  if (!subtasks_added)
369
 
    appointment_task_done (task);
370
 
}
371
 
 
372
 
static GSList *
373
 
my_get_appointments_finish (IndicatorDatetimePlanner  * self  G_GNUC_UNUSED,
374
 
                            GAsyncResult              * res,
375
 
                            GError                   ** error)
376
 
{
377
 
  return g_task_propagate_pointer (G_TASK(res), error);
378
 
}
379
 
 
380
 
static gboolean
381
 
my_is_configured (IndicatorDatetimePlanner * planner)
382
 
{
383
 
  IndicatorDatetimePlannerEds * self;
384
 
 
385
 
  /* confirm that it's installed... */
386
 
  gchar *evo = g_find_program_in_path ("evolution");
387
 
  if (evo == NULL)
388
 
    return FALSE;
389
 
 
390
 
  g_debug ("found calendar app: '%s'", evo);
391
 
  g_free (evo);
392
 
 
393
 
  /* see if there are any calendar sources */
394
 
  self = INDICATOR_DATETIME_PLANNER_EDS (planner);
395
 
  return self->priv->sources != NULL;
396
 
}
397
 
 
398
 
static void
399
 
my_activate (IndicatorDatetimePlanner * self G_GNUC_UNUSED)
400
 
{
401
 
  GError * error = NULL;
402
 
  const char * const command = "evolution -c calendar";
403
 
 
404
 
  if (!g_spawn_command_line_async (command, &error))
405
 
    {
406
 
      g_warning ("Unable to start %s: %s", command, error->message);
407
 
      g_error_free (error);
408
 
    }
409
 
}
410
 
 
411
 
static void
412
 
my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED,
413
 
                  GDateTime * activate_time)
414
 
{
415
 
  gchar * isodate;
416
 
  gchar * command;
417
 
  GError * err;
418
 
 
419
 
  isodate = g_date_time_format (activate_time, "%Y%m%d");
420
 
  command = g_strdup_printf ("evolution \"calendar:///?startdate=%s\"", isodate);
421
 
  err = 0;
422
 
  if (!g_spawn_command_line_async (command, &err))
423
 
    {
424
 
      g_warning ("Unable to start %s: %s", command, err->message);
425
 
      g_error_free (err);
426
 
    }
427
 
 
428
 
  g_free (command);
429
 
  g_free (isodate);
430
 
}
431
 
 
432
 
/***
433
 
****  Source / Client Wrangling
434
 
***/
435
 
 
436
 
static void
437
 
on_client_connected (GObject      * unused G_GNUC_UNUSED,
438
 
                     GAsyncResult * res,
439
 
                     gpointer       gself)
440
 
{
441
 
  GError * error;
442
 
  EClient * client;
443
 
 
444
 
  error = NULL;
445
 
  client = e_cal_client_connect_finish (res, &error);
446
 
  if (error != NULL)
447
 
    {
448
 
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
449
 
        g_warning ("indicator-datetime cannot connect to EDS source: %s", error->message);
450
 
 
451
 
      g_error_free (error);
452
 
    }
453
 
  else
454
 
    {
455
 
      /* we've got a new connected ECalClient, so store it & notify clients */
456
 
 
457
 
      g_object_set_qdata_full (G_OBJECT(e_client_get_source(client)),
458
 
                               source_client_quark(),
459
 
                               client,
460
 
                               g_object_unref);
461
 
 
462
 
      indicator_datetime_planner_emit_appointments_changed (gself);
463
 
    }
464
 
}
465
 
 
466
 
static void
467
 
on_source_enabled (ESourceRegistry * registry  G_GNUC_UNUSED,
468
 
                   ESource         * source,
469
 
                   gpointer          gself)
470
 
{
471
 
  IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (gself);
472
 
  priv_t * p = self->priv;
473
 
 
474
 
  e_cal_client_connect (source,
475
 
                        E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
476
 
                        p->cancellable,
477
 
                        on_client_connected,
478
 
                        self);
479
 
}
480
 
 
481
 
static void
482
 
on_source_added (ESourceRegistry * registry,
483
 
                 ESource         * source,
484
 
                 gpointer          gself)
485
 
{
486
 
  IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (gself);
487
 
  priv_t * p = self->priv;
488
 
 
489
 
  p->sources = g_slist_prepend (p->sources, g_object_ref(source));
490
 
 
491
 
  if (e_source_get_enabled (source))
492
 
    on_source_enabled (registry, source, gself);
493
 
}
494
 
 
495
 
static void
496
 
on_source_disabled (ESourceRegistry * registry  G_GNUC_UNUSED,
497
 
                    ESource         * source,
498
 
                    gpointer          gself)
499
 
{
500
 
  ECalClient * client;
501
 
 
502
 
  /* If this source has a connected ECalClient, remove it & notify clients */
503
 
  if ((client = g_object_steal_qdata (G_OBJECT(source), source_client_quark())))
504
 
    {
505
 
      g_object_unref (client);
506
 
      indicator_datetime_planner_emit_appointments_changed (gself);
507
 
    }
508
 
}
509
 
 
510
 
static void
511
 
on_source_removed (ESourceRegistry * registry,
512
 
                   ESource         * source,
513
 
                   gpointer          gself)
514
 
{
515
 
  IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (gself);
516
 
  priv_t * p = self->priv;
517
 
 
518
 
  on_source_disabled (registry, source, gself);
519
 
 
520
 
  p->sources = g_slist_remove (p->sources, source);
521
 
  g_object_unref (source);
522
 
}
523
 
 
524
 
static void
525
 
on_source_changed (ESourceRegistry * registry  G_GNUC_UNUSED,
526
 
                   ESource         * source    G_GNUC_UNUSED,
527
 
                   gpointer          gself)
528
 
{
529
 
  indicator_datetime_planner_emit_appointments_changed (gself);
530
 
}
531
 
 
532
 
static void
533
 
on_source_registry_ready (GObject      * source_object  G_GNUC_UNUSED,
534
 
                          GAsyncResult * res,
535
 
                          gpointer       gself)
536
 
{
537
 
  GError * error;
538
 
  ESourceRegistry * r;
539
 
 
540
 
  error = NULL;
541
 
  r = e_source_registry_new_finish (res, &error);
542
 
  if (error != NULL)
543
 
    {
544
 
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
545
 
        g_warning ("indicator-datetime cannot show EDS appointments: %s", error->message);
546
 
 
547
 
      g_error_free (error);
548
 
    }
549
 
  else
550
 
    {
551
 
      IndicatorDatetimePlannerEds * self;
552
 
      priv_t * p;
553
 
      GList * l;
554
 
      GList * sources;
555
 
 
556
 
      self = INDICATOR_DATETIME_PLANNER_EDS (gself);
557
 
      p = self->priv;
558
 
 
559
 
      g_signal_connect (r, "source-added",    G_CALLBACK(on_source_added), self);
560
 
      g_signal_connect (r, "source-removed",  G_CALLBACK(on_source_removed), self);
561
 
      g_signal_connect (r, "source-changed",  G_CALLBACK(on_source_changed), self);
562
 
      g_signal_connect (r, "source-disabled", G_CALLBACK(on_source_disabled), self);
563
 
      g_signal_connect (r, "source-enabled",  G_CALLBACK(on_source_enabled), self);
564
 
 
565
 
      p->source_registry = r;
566
 
 
567
 
      sources = e_source_registry_list_sources (r, E_SOURCE_EXTENSION_CALENDAR);
568
 
      for (l=sources; l!=NULL; l=l->next)
569
 
        on_source_added (r, l->data, self);
570
 
      g_list_free_full (sources, g_object_unref);
571
 
    }
572
 
}
573
 
 
574
 
/***
575
 
****  GObject virtual funcs
576
 
***/
577
 
 
578
 
static void
579
 
my_dispose (GObject * o)
580
 
{
581
 
  IndicatorDatetimePlannerEds * self = INDICATOR_DATETIME_PLANNER_EDS (o);
582
 
  priv_t * p = self->priv;
583
 
 
584
 
  if (p->cancellable != NULL)
585
 
    {
586
 
      g_cancellable_cancel (p->cancellable);
587
 
      g_clear_object (&p->cancellable);
588
 
    }
589
 
 
590
 
  if (p->source_registry != NULL)
591
 
    {
592
 
      g_signal_handlers_disconnect_by_func (p->source_registry,
593
 
                                            indicator_datetime_planner_emit_appointments_changed,
594
 
                                            self);
595
 
 
596
 
      g_clear_object (&self->priv->source_registry);
597
 
    }
598
 
 
599
 
  G_OBJECT_CLASS (indicator_datetime_planner_eds_parent_class)->dispose (o);
600
 
}
601
 
 
602
 
/***
603
 
****  Instantiation
604
 
***/
605
 
 
606
 
static void
607
 
indicator_datetime_planner_eds_class_init (IndicatorDatetimePlannerEdsClass * klass)
608
 
{
609
 
  GObjectClass * object_class;
610
 
  IndicatorDatetimePlannerClass * planner_class;
611
 
 
612
 
  object_class = G_OBJECT_CLASS (klass);
613
 
  object_class->dispose = my_dispose;
614
 
 
615
 
  planner_class = INDICATOR_DATETIME_PLANNER_CLASS (klass);
616
 
  planner_class->is_configured = my_is_configured;
617
 
  planner_class->activate = my_activate;
618
 
  planner_class->activate_time = my_activate_time;
619
 
  planner_class->get_appointments = my_get_appointments;
620
 
  planner_class->get_appointments_finish = my_get_appointments_finish;
621
 
 
622
 
  g_type_class_add_private (klass, sizeof (IndicatorDatetimePlannerEdsPriv));
623
 
}
624
 
 
625
 
static void
626
 
indicator_datetime_planner_eds_init (IndicatorDatetimePlannerEds * self)
627
 
{
628
 
  priv_t * p;
629
 
 
630
 
  p = G_TYPE_INSTANCE_GET_PRIVATE (self,
631
 
                                   INDICATOR_TYPE_DATETIME_PLANNER_EDS,
632
 
                                   IndicatorDatetimePlannerEdsPriv);
633
 
 
634
 
  self->priv = p;
635
 
 
636
 
  p->cancellable = g_cancellable_new ();
637
 
 
638
 
  e_source_registry_new (p->cancellable,
639
 
                         on_source_registry_ready,
640
 
                         self);
641
 
}
642
 
 
643
 
/***
644
 
****  Public
645
 
***/
646
 
 
647
 
IndicatorDatetimePlanner *
648
 
indicator_datetime_planner_eds_new (void)
649
 
{
650
 
  gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_PLANNER_EDS, NULL);
651
 
 
652
 
  return INDICATOR_DATETIME_PLANNER (o);
653
 
}