From f84d3bdb7006eee351942a31d033ca0d62f3292a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 7 Dec 2014 20:52:50 -0600 Subject: disable one-time alarms after their notifications are shown. --- include/datetime/engine-eds.h | 5 +-- include/datetime/engine-mock.h | 7 ++-- include/datetime/engine.h | 1 + src/engine-eds.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 5 ++- tests/manual | 10 ++++++ 6 files changed, 105 insertions(+), 5 deletions(-) diff --git a/include/datetime/engine-eds.h b/include/datetime/engine-eds.h index ebee838..7372f71 100644 --- a/include/datetime/engine-eds.h +++ b/include/datetime/engine-eds.h @@ -51,9 +51,10 @@ public: void get_appointments(const DateTime& begin, const DateTime& end, const Timezone& default_timezone, - std::function&)> appointment_func); + std::function&)> appointment_func) override; + void disable_ubuntu_alarm(const Appointment&) override; - core::Signal<>& changed(); + core::Signal<>& changed() override; private: class Impl; diff --git a/include/datetime/engine-mock.h b/include/datetime/engine-mock.h index 4b25120..9fb0442 100644 --- a/include/datetime/engine-mock.h +++ b/include/datetime/engine-mock.h @@ -44,14 +44,17 @@ public: void get_appointments(const DateTime& /*begin*/, const DateTime& /*end*/, const Timezone& /*default_timezone*/, - std::function&)> appointment_func) { + std::function&)> appointment_func) override { appointment_func(m_appointments); } - core::Signal<>& changed() { + core::Signal<>& changed() override { return m_changed; } + void disable_ubuntu_alarm(const Appointment&) override { + } + private: core::Signal<> m_changed; std::vector m_appointments; diff --git a/include/datetime/engine.h b/include/datetime/engine.h index 56e9343..59468d1 100644 --- a/include/datetime/engine.h +++ b/include/datetime/engine.h @@ -50,6 +50,7 @@ public: const DateTime& end, const Timezone& default_timezone, std::function&)> appointment_func) =0; + virtual void disable_ubuntu_alarm(const Appointment&) =0; virtual core::Signal<>& changed() =0; diff --git a/src/engine-eds.cpp b/src/engine-eds.cpp index 23e2883..210ef42 100644 --- a/src/engine-eds.cpp +++ b/src/engine-eds.cpp @@ -136,6 +136,22 @@ public: } } + void disable_ubuntu_alarm(const Appointment& appointment) + { + if (appointment.is_ubuntu_alarm()) + { + for (auto& kv : m_clients) // find the matching icalcomponent + { + e_cal_client_get_object(kv.second, + appointment.uid.c_str(), + nullptr, + m_cancellable, + on_object_ready_for_disable, + this); + } + } + } + private: void set_dirty_now() @@ -506,6 +522,67 @@ private: return G_SOURCE_CONTINUE; } + + /*** + **** + ***/ + + static void on_object_ready_for_disable(GObject * client, + GAsyncResult * result, + gpointer gself) + { + icalcomponent * icc = nullptr; + if (e_cal_client_get_object_finish (E_CAL_CLIENT(client), result, &icc, nullptr)) + { + struct icaltimetype itt = icalcomponent_get_recurrenceid(icc); + if (icaltime_is_null_time(itt)) + { + g_debug("'%s' appears to be a one-time alarm... adding 'disabled' tag.", + icalcomponent_as_ical_string(icc)); + + auto ecc = e_cal_component_new_from_icalcomponent (icc); // takes ownership of icc + icc = nullptr; + + if (ecc != nullptr) + { + // add TAG_DISABLED to the list of categories + GSList * old_categories = nullptr; + e_cal_component_get_categories_list(ecc, &old_categories); + auto new_categories = g_slist_copy(old_categories); + new_categories = g_slist_append(new_categories, const_cast(TAG_DISABLED)); + e_cal_component_set_categories_list(ecc, new_categories); + g_slist_free(new_categories); + e_cal_component_free_categories_list(old_categories); + e_cal_client_modify_object(E_CAL_CLIENT(client), + e_cal_component_get_icalcomponent(ecc), + E_CAL_OBJ_MOD_THIS, + static_cast(gself)->m_cancellable, + on_disable_done, + nullptr); + + g_clear_object(&ecc); + } + } + + g_clear_pointer(&icc, icalcomponent_free); + } + } + + static void on_disable_done (GObject* gclient, GAsyncResult *res, gpointer) + { + GError * error = nullptr; + if (!e_cal_client_modify_object_finish (E_CAL_CLIENT(gclient), res, &error)) + { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("indicator-datetime cannot mark one-time alarm as disabled: %s", error->message); + + g_error_free(error); + } + } + + /*** + **** + ***/ core::Signal<> m_changed; std::set m_sources; @@ -541,6 +618,11 @@ void EdsEngine::get_appointments(const DateTime& begin, p->get_appointments(begin, end, tz, func); } +void EdsEngine::disable_ubuntu_alarm(const Appointment& appointment) +{ + p->disable_ubuntu_alarm(appointment); +} + /*** **** ***/ diff --git a/src/main.cpp b/src/main.cpp index aa8f829..1761f84 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -139,7 +139,10 @@ main(int /*argc*/, char** /*argv*/) auto alarm_queue = create_simple_alarm_queue(state->clock, snooze_planner, engine, timezone_); auto on_snooze = [snooze_planner](const Appointment& a) {snooze_planner->add(a);}; auto on_ok = [](const Appointment&){}; - auto on_alarm_reached = [&snap, &on_snooze, &on_ok](const Appointment& a) {(*snap)(a, on_snooze, on_ok);}; + auto on_alarm_reached = [&engine, &snap, &on_snooze, &on_ok](const Appointment& a) { + (*snap)(a, on_snooze, on_ok); + engine->disable_ubuntu_alarm(a); + }; alarm_queue->alarm_reached().connect(on_alarm_reached); // create the menus diff --git a/tests/manual b/tests/manual index c2522aa..71d1e06 100644 --- a/tests/manual +++ b/tests/manual @@ -48,6 +48,16 @@ Test-case indicator-datetime/disabled-alarms
When the alarm is enabled, the alarm icon should reappear.
+Test-case indicator-datetime/disable-one-time-alarms-after-notification +
+
Create and save an upcoming nonrepeating alarm in ubuntu-clock-app
+
Confirm that the alarm icon appears next to the current time in unity's indicator display
+
Wait until the alarm time is reached
+
Confirm that the alarm notification is shown
+
Confirm that the alarm's sound is played while the alarm notification is present
+
Confirm that the one-time alarm is disabled after the notification is shown. NOTE: due to a refresh bug in clock-app you may need to refresh its alarms page (by swapping back to the main page, then the alarm page again, this is tracked in #1362341) in order to see the alarm change from enabled to disabled.
+
+ Test-case indicator-datetime/calendar-event-notification
In the calendar app, create and save a new upcoming calendar event that will occur in the next few minutes.
-- cgit v1.2.3