126
127
auto extension = e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR);
127
128
const auto color = e_source_selectable_get_color(E_SOURCE_SELECTABLE(extension));
128
129
g_debug("calling e_cal_client_generate_instances for %p", (void*)client);
130
auto subtask = new AppointmentSubtask(main_task,
129
136
e_cal_client_generate_instances(client,
133
140
my_get_appointments_foreach,
134
new AppointmentSubtask (main_task, client, color),
135
142
[](gpointer g){delete static_cast<AppointmentSubtask*>(g);});
409
416
std::shared_ptr<Task> task;
410
417
ECalClient* client;
411
418
std::string color;
412
AppointmentSubtask(const std::shared_ptr<Task>& task_in, ECalClient* client_in, const char* color_in):
413
task(task_in), client(client_in)
419
icaltimezone* default_timezone;
423
AppointmentSubtask(const std::shared_ptr<Task>& task_in,
424
ECalClient* client_in,
425
const char* color_in,
426
icaltimezone* default_tz,
431
default_timezone(default_tz),
416
436
color = color_in;
440
static std::string get_alarm_text(ECalComponentAlarm * alarm)
444
ECalComponentAlarmAction action;
445
e_cal_component_alarm_get_action(alarm, &action);
446
if (action == E_CAL_COMPONENT_ALARM_DISPLAY)
448
ECalComponentText text {};
449
e_cal_component_alarm_get_description(alarm, &text);
457
static std::string get_alarm_sound_url(ECalComponentAlarm * alarm)
461
ECalComponentAlarmAction action;
462
e_cal_component_alarm_get_action(alarm, &action);
463
if (action == E_CAL_COMPONENT_ALARM_AUDIO)
465
icalattach* attach = nullptr;
466
e_cal_component_alarm_get_attach(alarm, &attach);
467
if (attach != nullptr)
469
if (icalattach_get_is_url (attach))
471
const char* url = icalattach_get_url(attach);
476
icalattach_unref(attach);
421
484
my_get_appointments_foreach(ECalComponent* component,
434
497
auto status = ICAL_STATUS_NONE;
435
498
e_cal_component_get_status(component, &status);
437
const auto begin_dt = DateTime(begin);
438
const auto end_dt = DateTime(end);
500
// get the timezone we want to use for generated Appointments/Alarms
501
const char * location = icaltimezone_get_location(subtask->default_timezone);
502
auto gtz = g_time_zone_new(location);
503
g_debug("timezone abbreviation is %s", g_time_zone_get_abbreviation (gtz, 0));
505
const DateTime begin_dt { gtz, begin };
506
const DateTime end_dt { gtz, end };
439
507
g_debug ("got appointment from %s to %s, uid %s status %d",
440
begin_dt.format("%F %T").c_str(),
441
end_dt.format("%F %T").c_str(),
508
begin_dt.format("%F %T %z").c_str(),
509
end_dt.format("%F %T %z").c_str(),
475
543
appointment.uid = uid;
476
544
appointment.type = type;
478
// Look through all of this component's alarms
479
// for DISPLAY or AUDIO url attachments.
480
// If we find any, use them for appointment.url and audio_sound
481
auto alarm_uids = e_cal_component_get_alarm_uids(component);
482
for(auto walk=alarm_uids; appointment.url.empty() && walk!=nullptr; walk=walk->next)
484
auto alarm = e_cal_component_get_alarm(component, static_cast<const char*>(walk->data));
486
ECalComponentAlarmAction action;
487
e_cal_component_alarm_get_action(alarm, &action);
488
if ((action == E_CAL_COMPONENT_ALARM_DISPLAY) || (action == E_CAL_COMPONENT_ALARM_AUDIO))
490
icalattach* attach = nullptr;
491
e_cal_component_alarm_get_attach(alarm, &attach);
492
if (attach != nullptr)
494
if (icalattach_get_is_url (attach))
496
const char* url = icalattach_get_url(attach);
499
if ((action == E_CAL_COMPONENT_ALARM_DISPLAY) && appointment.url.empty())
501
appointment.url = url;
503
else if ((action == E_CAL_COMPONENT_ALARM_AUDIO) && appointment.audio_url.empty())
505
appointment.audio_url = url;
510
icalattach_unref(attach);
514
e_cal_component_alarm_free(alarm);
516
cal_obj_uid_list_free(alarm_uids);
518
g_debug("adding appointment '%s' '%s'", appointment.summary.c_str(), appointment.url.c_str());
546
icalcomponent * icc = e_cal_component_get_icalcomponent(component);
547
g_debug("%s", icalcomponent_as_ical_string(icc)); // libical owns this string; no leak
549
auto e_alarms = e_cal_util_generate_alarms_for_comp(component,
552
const_cast<ECalComponentAlarmAction*>(omit.data()),
553
e_cal_client_resolve_tzid_cb,
555
subtask->default_timezone);
557
std::map<DateTime,Alarm> alarms;
559
if (e_alarms != nullptr)
561
for (auto l=e_alarms->alarms; l!=nullptr; l=l->next)
563
auto ai = static_cast<ECalComponentAlarmInstance*>(l->data);
564
auto a = e_cal_component_get_alarm(component, ai->auid);
568
const DateTime alarm_begin{gtz, ai->trigger};
569
auto& alarm = alarms[alarm_begin];
571
if (alarm.text.empty())
572
alarm.text = get_alarm_text(a);
573
if (alarm.audio_url.empty())
574
alarm.audio_url = get_alarm_sound_url(a);
575
if (!alarm.time.is_set())
576
alarm.time = alarm_begin;
578
e_cal_component_alarm_free(a);
582
e_cal_component_alarms_free(e_alarms);
584
// Hm, no alarm triggers?
585
// That's a bug in alarms created by some versions of ubuntu-ui-toolkit.
586
// If that's what's happening here, let's handle those alarms anyway
587
// by effectively injecting a TRIGGER;VALUE=DURATION;RELATED=START:PT0S
588
else if (appointment.is_ubuntu_alarm())
591
tmp.time = appointment.begin;
593
auto auids = e_cal_component_get_alarm_uids(component);
594
for(auto l=auids; l!=nullptr; l=l->next)
596
const auto auid = static_cast<const char*>(l->data);
597
auto a = e_cal_component_get_alarm(component, auid);
600
if (tmp.text.empty())
601
tmp.text = get_alarm_text(a);
602
if (tmp.audio_url.empty())
603
tmp.audio_url = get_alarm_sound_url(a);
604
e_cal_component_alarm_free(a);
607
cal_obj_uid_list_free(auids);
609
alarms[tmp.time] = tmp;
612
appointment.alarms.reserve(alarms.size());
613
for (const auto& it : alarms)
614
appointment.alarms.push_back(it.second);
519
616
subtask->task->appointments.push_back(appointment);
619
g_time_zone_unref(gtz);
523
622
return G_SOURCE_CONTINUE;