From 35850dcd7c95e08b86052d5ac72ca23d00b5180f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 3 Feb 2014 00:32:03 -0600 Subject: from alarm dev branch: snap decision handler --- src/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 1534777..3c17923 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,11 +21,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -67,6 +69,13 @@ main(int /*argc*/, char** /*argv*/) std::shared_ptr actions(new LiveActions(state)); MenuFactory factory(actions, state); + // snap decisions + ClockWatcherImpl clock_watcher(state); + Snap snap(state->clock); + clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ + snap(appt); + }); + // create the menus std::vector> menus; for(int i=0, n=Menu::NUM_PROFILES; i Date: Tue, 4 Feb 2014 00:10:17 -0600 Subject: pin the planner's upcoming appointments to the live clock time, rather than the calendar's time, so that they always update correctly in real-time --- include/datetime/planner-eds.h | 5 +- src/main.cpp | 2 +- src/planner-eds.cpp | 117 ++++++++++++++++++++++++----------------- tests/test-planner.cpp | 14 ++--- 4 files changed, 82 insertions(+), 56 deletions(-) (limited to 'src/main.cpp') diff --git a/include/datetime/planner-eds.h b/include/datetime/planner-eds.h index f3abce0..a99f611 100644 --- a/include/datetime/planner-eds.h +++ b/include/datetime/planner-eds.h @@ -20,9 +20,10 @@ #ifndef INDICATOR_DATETIME_PLANNER_EDS_H #define INDICATOR_DATETIME_PLANNER_EDS_H +#include #include -#include // unique_ptr +#include // shared_ptr, unique_ptr namespace unity { namespace indicator { @@ -34,7 +35,7 @@ namespace datetime { class PlannerEds: public Planner { public: - PlannerEds(); + PlannerEds(const std::shared_ptr& clock); virtual ~PlannerEds(); private: diff --git a/src/main.cpp b/src/main.cpp index 3c17923..87bfed1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,7 @@ main(int /*argc*/, char** /*argv*/) state->settings = live_settings; state->clock = live_clock; state->locations.reset(new SettingsLocations(live_settings, live_timezones)); - state->planner.reset(new PlannerEds); + state->planner.reset(new PlannerEds(live_clock)); state->planner->time = live_clock->localtime(); std::shared_ptr actions(new LiveActions(state)); MenuFactory factory(actions, state); diff --git a/src/planner-eds.cpp b/src/planner-eds.cpp index 9048f52..7d9416c 100644 --- a/src/planner-eds.cpp +++ b/src/planner-eds.cpp @@ -41,18 +41,24 @@ class PlannerEds::Impl { public: - Impl(PlannerEds& owner): + Impl(PlannerEds& owner, const std::shared_ptr& clock): m_owner(owner), + m_clock(clock), m_cancellable(g_cancellable_new()) { e_source_registry_new(m_cancellable, on_source_registry_ready, this); + m_clock->minute_changed.connect([this](){ + g_debug("rebuilding upcoming because the clock's minute_changed"); + rebuild_soon(UPCOMING); + }); + m_owner.time.changed().connect([this](const DateTime& dt) { g_debug("planner's datetime property changed to %s; calling rebuild_soon()", dt.format("%F %T").c_str()); - rebuild_soon(); + rebuild_soon(MONTH); }); - rebuild_soon(); + rebuild_soon(ALL); } ~Impl() @@ -164,7 +170,7 @@ private: self); g_debug("client connected; calling rebuild_soon()"); - self->rebuild_soon(); + self->rebuild_soon(ALL); } } @@ -185,7 +191,7 @@ private: g_signal_connect(view, "objects-modified", G_CALLBACK(on_view_objects_modified), self); g_signal_connect(view, "objects-removed", G_CALLBACK(on_view_objects_removed), self); g_debug("view connected; calling rebuild_soon()"); - self->rebuild_soon(); + self->rebuild_soon(ALL); } else if(error != nullptr) { @@ -199,17 +205,17 @@ private: static void on_view_objects_added(ECalClientView* /*view*/, gpointer /*objects*/, gpointer gself) { g_debug("%s", G_STRFUNC); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } static void on_view_objects_modified(ECalClientView* /*view*/, gpointer /*objects*/, gpointer gself) { g_debug("%s", G_STRFUNC); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } static void on_view_objects_removed(ECalClientView* /*view*/, gpointer /*objects*/, gpointer gself) { g_debug("%s", G_STRFUNC); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } static void on_source_disabled(ESourceRegistry* /*registry*/, ESource* source, gpointer gself) @@ -228,7 +234,7 @@ private: g_warn_if_fail(n_disconnected == 3); g_object_unref(view); m_views.erase(vit); - rebuild_soon(); + rebuild_soon(ALL); } // if an ECalClient is associated with this source, remove it @@ -238,7 +244,7 @@ private: auto& client = cit->second; g_object_unref(client); m_clients.erase(cit); - rebuild_soon(); + rebuild_soon(ALL); } } @@ -255,14 +261,14 @@ private: { g_object_unref(*sit); m_sources.erase(sit); - rebuild_soon(); + rebuild_soon(ALL); } } static void on_source_changed(ESourceRegistry* /*registry*/, ESource* /*source*/, gpointer gself) { g_debug("source changed; calling rebuild_soon()"); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } private: @@ -286,9 +292,11 @@ private: task(task_in), client(client_in), color(color_in) {} }; - void rebuild_soon() + void rebuild_soon(int rebuild_flags) { - const static guint ARBITRARY_INTERVAL_SECS = 2; + static const guint ARBITRARY_INTERVAL_SECS = 2; + + m_rebuild_flags |= rebuild_flags; if (m_rebuild_tag == 0) m_rebuild_tag = g_timeout_add_seconds(ARBITRARY_INTERVAL_SECS, rebuild_now_static, this); @@ -297,44 +305,56 @@ private: static gboolean rebuild_now_static(gpointer gself) { auto self = static_cast(gself); + const auto flags = self->m_rebuild_flags; self->m_rebuild_tag = 0; - self->rebuild_now(); + self->m_rebuild_flags = 0; + self->rebuild_now(flags); return G_SOURCE_REMOVE; } - void rebuild_now() + void rebuild_now(int rebuild_flags) { - const auto calendar_date = m_owner.time.get().get(); - GDateTime* begin; - GDateTime* end; - int y, m, d; - - // get all the appointments in the calendar month - g_date_time_get_ymd(calendar_date, &y, &m, &d); - begin = g_date_time_new_local(y, m, 1, 0, 0, 0.1); - end = g_date_time_new_local(y, m, g_date_get_days_in_month(GDateMonth(m),GDateYear(y)), 23, 59, 59.9); - if (begin && end) - { - get_appointments(begin, end, [this](const std::vector& appointments) { - g_debug("got %d appointments in this calendar month", (int)appointments.size()); - m_owner.this_month.set(appointments); - }); - } - g_clear_pointer(&begin, g_date_time_unref); - g_clear_pointer(&end, g_date_time_unref); + if (rebuild_flags & UPCOMING) + rebuild_upcoming(); - // get the upcoming appointments - begin = g_date_time_ref(calendar_date); - end = g_date_time_add_months(begin, 1); - if (begin && end) - { - get_appointments(begin, end, [this](const std::vector& appointments) { - g_debug("got %d upcoming appointments", (int)appointments.size()); - m_owner.upcoming.set(appointments); - }); - } - g_clear_pointer(&begin, g_date_time_unref); - g_clear_pointer(&end, g_date_time_unref); + if (rebuild_flags & MONTH) + rebuild_month(); + } + + void rebuild_month() + { + const auto ref = m_owner.time.get().get(); + auto month_begin = g_date_time_add_full(ref, + 0, // subtract no years + 0, // subtract no months + -(g_date_time_get_day_of_month(ref)-1), + -g_date_time_get_hour(ref), + -g_date_time_get_minute(ref), + -g_date_time_get_seconds(ref)); + auto month_end = g_date_time_add_full(month_begin, 0, 1, 0, 0, 0, -0.1); + + get_appointments(month_begin, month_end, [this](const std::vector& appointments) { + g_debug("got %d appointments in this calendar month", (int)appointments.size()); + m_owner.this_month.set(appointments); + }); + + g_date_time_unref(month_end); + g_date_time_unref(month_begin); + } + + void rebuild_upcoming() + { + const auto ref = m_clock->localtime(); + const auto begin = g_date_time_add_minutes(ref.get(),-10); + const auto end = g_date_time_add_months(begin,1); + + get_appointments(begin, end, [this](const std::vector& appointments) { + g_debug("got %d upcoming appointments", (int)appointments.size()); + m_owner.upcoming.set(appointments); + }); + + g_date_time_unref(end); + g_date_time_unref(begin); } void get_appointments(GDateTime* begin_dt, GDateTime* end_dt, appointment_func func) @@ -496,15 +516,18 @@ private: } PlannerEds& m_owner; + std::shared_ptr m_clock; std::set m_sources; std::map m_clients; std::map m_views; GCancellable* m_cancellable = nullptr; ESourceRegistry* m_source_registry = nullptr; guint m_rebuild_tag = 0; + guint m_rebuild_flags = 0; + enum { UPCOMING=(1<<0), MONTH=(1<<1), ALL=UPCOMING|MONTH }; }; -PlannerEds::PlannerEds(): p(new Impl(*this)) {} +PlannerEds::PlannerEds(const std::shared_ptr& clock): p(new Impl(*this, clock)) {} PlannerEds::~PlannerEds() =default; diff --git a/tests/test-planner.cpp b/tests/test-planner.cpp index b476ee8..1923ba1 100644 --- a/tests/test-planner.cpp +++ b/tests/test-planner.cpp @@ -28,9 +28,7 @@ #include #include -using unity::indicator::datetime::Appointment; -using unity::indicator::datetime::DateTime; -using unity::indicator::datetime::PlannerEds; +using namespace unity::indicator::datetime; /*** **** @@ -40,11 +38,15 @@ typedef GlibFixture PlannerFixture; TEST_F(PlannerFixture, EDS) { - PlannerEds planner; + auto tmp = g_date_time_new_now_local(); + const auto now = DateTime(tmp); + g_date_time_unref(tmp); + + std::shared_ptr clock(new MockClock(now)); + PlannerEds planner(clock); wait_msec(100); - auto now = g_date_time_new_now_local(); - planner.time.set(DateTime(now)); + planner.time.set(now); wait_msec(2500); std::vector this_month = planner.this_month.get(); -- cgit v1.2.3 From 61accb9ce497e1f1cbe8038ac495d66d6a4505ff Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 4 Feb 2014 09:57:51 -0600 Subject: use the appointment's beginning time in the title of the alarm Snap Decision --- include/datetime/snap.h | 9 ++------- src/main.cpp | 2 +- src/snap.cpp | 15 ++++++++++----- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/main.cpp') diff --git a/include/datetime/snap.h b/include/datetime/snap.h index d6f5aad..584d895 100644 --- a/include/datetime/snap.h +++ b/include/datetime/snap.h @@ -21,8 +21,6 @@ #define INDICATOR_DATETIME_SNAP_H #include -#include -#include #include @@ -36,12 +34,9 @@ namespace datetime { class Snap { public: - Snap(const std::shared_ptr&); - virtual ~Snap() =default; + Snap(); + virtual ~Snap(); void operator()(const Appointment&); - -private: - PhoneFormatter m_formatter; }; } // namespace datetime diff --git a/src/main.cpp b/src/main.cpp index 87bfed1..71a1ce5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -71,7 +71,7 @@ main(int /*argc*/, char** /*argv*/) // snap decisions ClockWatcherImpl clock_watcher(state); - Snap snap(state->clock); + Snap snap; clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ snap(appt); }); diff --git a/src/snap.cpp b/src/snap.cpp index 7acac9c..a290f99 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -20,6 +20,7 @@ #include #include #include +#include // generate_full_format_string_at_time() #include @@ -72,8 +73,11 @@ void on_snap_decided(NotifyNotification * /*notification*/, **** ***/ -Snap::Snap(const std::shared_ptr& clock): - m_formatter(clock) +Snap::Snap() +{ +} + +Snap::~Snap() { } @@ -82,10 +86,10 @@ void Snap::operator()(const Appointment& appointment) if (!appointment.has_alarms) return; - const auto timestr = m_formatter.header.get(); + auto timestr = generate_full_format_string_at_time (appointment.begin.get(), nullptr, nullptr); + auto title = g_strdup_printf(_("Alarm %s"), timestr); const auto body = appointment.summary; - gchar* title = g_strdup_printf(_("Alarm %s"), timestr.c_str()); - const gchar* icon_name = "clock"; + const gchar* icon_name = "alarm-clock"; g_debug("creating a snap decision with title '%s', body '%s', icon '%s'", title, body.c_str(), icon_name); auto nn = notify_notification_new(title, body.c_str(), icon_name); @@ -104,6 +108,7 @@ void Snap::operator()(const Appointment& appointment) } g_free(title); + g_free(timestr); } /*** -- cgit v1.2.3 From 61581201f13509fbce9eb05fc90a5da17307c6a3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 4 Feb 2014 13:00:22 -0600 Subject: Add audio notitication when the alarm is triggered. Add a manual test to tests/ to trigger a snap decision. --- CMakeLists.txt | 1 + debian/control | 1 + include/datetime/snap.h | 7 ++- src/main.cpp | 15 ++--- src/snap.cpp | 146 +++++++++++++++++++++++++++++++++++---------- tests/CMakeLists.txt | 4 ++ tests/manual-test-snap.cpp | 63 +++++++++++++++++++ 7 files changed, 194 insertions(+), 43 deletions(-) create mode 100644 tests/manual-test-snap.cpp (limited to 'src/main.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index ab8cca4..3e6a810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ pkg_check_modules (SERVICE_DEPS REQUIRED libical>=0.48 libecal-1.2>=3.5 libedataserver-1.2>=3.5 + libcanberra>=0.12 libnotify>=0.7.6 url-dispatcher-1>=1 properties-cpp>=0.0.1) diff --git a/debian/control b/debian/control index 54d265d..76fc5a1 100644 --- a/debian/control +++ b/debian/control @@ -16,6 +16,7 @@ Build-Depends: cmake, libgtest-dev, libglib2.0-dev (>= 2.35.4), libnotify-dev (>= 0.7.6), + libcanberra-dev, libido3-0.1-dev (>= 0.2.90), libgeoclue-dev (>= 0.12.0), libecal1.2-dev (>= 3.5), diff --git a/include/datetime/snap.h b/include/datetime/snap.h index 584d895..a493772 100644 --- a/include/datetime/snap.h +++ b/include/datetime/snap.h @@ -23,6 +23,7 @@ #include #include +#include namespace unity { namespace indicator { @@ -36,7 +37,11 @@ class Snap public: Snap(); virtual ~Snap(); - void operator()(const Appointment&); + + typedef std::function appointment_func; + void operator()(const Appointment& appointment, + appointment_func show, + appointment_func dismiss); }; } // namespace datetime diff --git a/src/main.cpp b/src/main.cpp index 71a1ce5..7e09fda 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,8 +17,6 @@ * with this program. If not, see . */ - - #include #include #include @@ -33,10 +31,11 @@ #include // bindtextdomain() #include -#include + +#include #include -#include // exit() +#include // exit() using namespace unity::indicator::datetime; @@ -52,10 +51,6 @@ main(int /*argc*/, char** /*argv*/) bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain(GETTEXT_PACKAGE); - // init libnotify - if(!notify_init("indicator-datetime-service")) - g_critical("libnotify initialization failed"); - // build the state, actions, and menufactory std::shared_ptr state(new State); std::shared_ptr live_settings(new LiveSettings); @@ -73,7 +68,9 @@ main(int /*argc*/, char** /*argv*/) ClockWatcherImpl clock_watcher(state); Snap snap; clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ - snap(appt); + snap(appt, + [](const Appointment& a){url_dispatch_send(a.url.c_str(), nullptr, nullptr);}, + [](const Appointment&){}); }); // create the menus diff --git a/src/snap.cpp b/src/snap.cpp index a290f99..5f46dc7 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -22,13 +22,14 @@ #include #include // generate_full_format_string_at_time() -#include - +#include #include #include #include +#define ALARM_SOUND_FILENAME "/usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg" + namespace unity { namespace indicator { namespace datetime { @@ -40,77 +41,156 @@ namespace datetime { namespace { -void dispatch_alarm_url(const Appointment& appointment) +/** +*** libcanberra -- play sounds +**/ + +ca_context *c_context = nullptr; + +ca_context* get_ca_context() { - g_return_if_fail(!appointment.has_alarms); + if (G_UNLIKELY(c_context == nullptr)) + { + int rv; + if ((rv = ca_context_create(&c_context)) != CA_SUCCESS) + { + g_warning("Failed to create canberra context: %s\n", ca_strerror(rv)); + c_context = nullptr; + } + } - const auto fmt = appointment.begin.format("%F %T"); - g_debug("dispatching url \"%s\" for appointment \"%s\", which begins at %s", - appointment.url.c_str(), - appointment.summary.c_str(), - fmt.c_str()); + return c_context; +} + +void play_soundfile(const char* filename) +{ + auto context = get_ca_context(); + g_return_if_fail(context != nullptr); - url_dispatch_send(appointment.url.c_str(), nullptr, nullptr); + const auto rv = ca_context_play(context, 0, CA_PROP_MEDIA_FILENAME, filename, NULL); + if (rv != CA_SUCCESS) + g_warning("Failed to play file '%s': %s\n", filename, ca_strerror(rv)); } -void on_snap_decided(NotifyNotification * /*notification*/, - char * action, - gpointer gurl) +void play_alarm_sound() { - g_debug("%s: %s", G_STRFUNC, action); + play_soundfile(ALARM_SOUND_FILENAME); +} + +/** +*** libnotify -- snap decisions +**/ - if (!g_strcmp0(action, "show")) +void first_time_init() +{ + static bool inited = false; + + if (G_UNLIKELY(!inited)) { - const auto url = static_cast(gurl); - g_debug("dispatching url '%s'", url); - url_dispatch_send(url, nullptr, nullptr); + inited = true; + + if(!notify_init("indicator-datetime-service")) + g_critical("libnotify initialization failed"); } } -} // unnamed namespace +struct SnapData +{ + Snap::appointment_func show; + Snap::appointment_func dismiss; + Appointment appointment; +}; -/*** -**** -***/ +void on_snap_show(NotifyNotification*, gchar* /*action*/, gpointer gdata) +{ + auto data = static_cast(gdata); + data->show(data->appointment); +} -Snap::Snap() +void on_snap_dismiss(NotifyNotification*, gchar* /*action*/, gpointer gdata) { + auto data = static_cast(gdata); + data->dismiss(data->appointment); } -Snap::~Snap() +void snap_data_destroy_notify(gpointer gdata) { + delete static_cast(gdata); } -void Snap::operator()(const Appointment& appointment) +void show_snap_decision(SnapData* data) { - if (!appointment.has_alarms) - return; + const Appointment& appointment = data->appointment; - auto timestr = generate_full_format_string_at_time (appointment.begin.get(), nullptr, nullptr); + auto timestr = generate_full_format_string_at_time(appointment.begin.get(), nullptr, nullptr); auto title = g_strdup_printf(_("Alarm %s"), timestr); const auto body = appointment.summary; const gchar* icon_name = "alarm-clock"; - g_debug("creating a snap decision with title '%s', body '%s', icon '%s'", title, body.c_str(), icon_name); auto nn = notify_notification_new(title, body.c_str(), icon_name); notify_notification_set_hint_string(nn, "x-canonical-snap-decisions", "true"); notify_notification_set_hint_string(nn, "x-canonical-private-button-tint", "true"); - notify_notification_add_action(nn, "show", _("Show"), on_snap_decided, g_strdup(appointment.url.c_str()), g_free); - notify_notification_add_action(nn, "dismiss", _("Dismiss"), on_snap_decided, nullptr, nullptr); + notify_notification_add_action(nn, "show", _("Show"), on_snap_show, data, nullptr); + notify_notification_add_action(nn, "dismiss", _("Dismiss"), on_snap_dismiss, data, nullptr); + g_object_set_data_full(G_OBJECT(nn), "snap-data", data, snap_data_destroy_notify); GError * error = nullptr; notify_notification_show(nn, &error); if (error != NULL) { - g_warning("Unable to show alarm '%s' popup: %s", body.c_str(), error->message); + g_warning("Unable to show snap decision for '%s': %s", body.c_str(), error->message); g_error_free(error); - dispatch_alarm_url(appointment); + data->show(data->appointment); } g_free(title); g_free(timestr); } +/** +*** +**/ + +void notify(const Appointment& appointment, + Snap::appointment_func show, + Snap::appointment_func dismiss) +{ + auto data = new SnapData; + data->appointment = appointment; + data->show = show; + data->dismiss = dismiss; + + play_alarm_sound(); + show_snap_decision(data); +} + +} // unnamed namespace + + +/*** +**** +***/ + +Snap::Snap() +{ + first_time_init(); +} + +Snap::~Snap() +{ + g_clear_pointer(&c_context, ca_context_destroy); +} + +void Snap::operator()(const Appointment& appointment, + appointment_func show, + appointment_func dismiss) +{ + if (appointment.has_alarms) + notify(appointment, show, dismiss); + else + dismiss(appointment); +} + /*** **** ***/ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 06e40a7..7d590c9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,6 +53,10 @@ add_test_by_name(test-settings) add_test_by_name(test-timezone-file) add_test_by_name(test-utils) +set (TEST_NAME manual-test-snap) +add_executable (${TEST_NAME} ${TEST_NAME}.cpp) +add_dependencies (${TEST_NAME} libindicatordatetimeservice) +target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) # disabling the timezone unit tests because they require # https://code.launchpad.net/~ted/dbus-test-runner/multi-interface-test/+merge/199724 diff --git a/tests/manual-test-snap.cpp b/tests/manual-test-snap.cpp new file mode 100644 index 0000000..51556cd --- /dev/null +++ b/tests/manual-test-snap.cpp @@ -0,0 +1,63 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include + +#include + +using namespace unity::indicator::datetime; + +/*** +**** +***/ + +int main() +{ + Appointment a; + a.color = "green"; + a.summary = "Alarm"; + a.url = "alarm:///hello-world"; + a.uid = "D4B57D50247291478ED31DED17FF0A9838DED402"; + a.is_event = false; + a.is_daily = false; + a.has_alarms = true; + auto begin = g_date_time_new_local(2014,12,25,0,0,0); + auto end = g_date_time_add_full(begin,0,0,1,0,0,-1); + a.begin = begin; + a.end = end; + g_date_time_unref(end); + g_date_time_unref(begin); + + auto loop = g_main_loop_new(nullptr, false); + auto show = [loop](const Appointment& appt){ + g_message("You clicked 'show' for appt url '%s'", appt.url.c_str()); + g_main_loop_quit(loop); + }; + auto dismiss = [loop](const Appointment&){ + g_message("You clicked 'dismiss'"); + g_main_loop_quit(loop); + }; + + Snap snap; + snap(a, show, dismiss); + g_main_loop_run(loop); + return 0; +} -- cgit v1.2.3 From 7137a652b136d375637390b1659007104e96b61f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 5 Feb 2014 15:31:03 -0600 Subject: copyediting: make the Snap lambdas a little easier to read. --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 7e09fda..daf2a22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,9 +68,9 @@ main(int /*argc*/, char** /*argv*/) ClockWatcherImpl clock_watcher(state); Snap snap; clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ - snap(appt, - [](const Appointment& a){url_dispatch_send(a.url.c_str(), nullptr, nullptr);}, - [](const Appointment&){}); + auto snap_show = [](const Appointment& a){url_dispatch_send(a.url.c_str(), nullptr, nullptr);}; + auto snap_dismiss = [](const Appointment&){}; + snap(appt, snap_show, snap_dismiss); }); // create the menus -- cgit v1.2.3 From 613cbb1d468fe99767a5541956266191511ec9ef Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 5 Feb 2014 16:26:34 -0600 Subject: remove alarms from the menu once they've been shown in a snap decision. --- include/datetime/planner-eds.h | 2 ++ src/main.cpp | 8 +++++--- src/planner-eds.cpp | 22 +++++++++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/include/datetime/planner-eds.h b/include/datetime/planner-eds.h index a99f611..4110ba5 100644 --- a/include/datetime/planner-eds.h +++ b/include/datetime/planner-eds.h @@ -20,6 +20,7 @@ #ifndef INDICATOR_DATETIME_PLANNER_EDS_H #define INDICATOR_DATETIME_PLANNER_EDS_H +#include #include #include @@ -37,6 +38,7 @@ class PlannerEds: public Planner public: PlannerEds(const std::shared_ptr& clock); virtual ~PlannerEds(); + void block_appointment(const Appointment& appointment); private: class Impl; diff --git a/src/main.cpp b/src/main.cpp index daf2a22..5f5ee3c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,15 +59,17 @@ main(int /*argc*/, char** /*argv*/) state->settings = live_settings; state->clock = live_clock; state->locations.reset(new SettingsLocations(live_settings, live_timezones)); - state->planner.reset(new PlannerEds(live_clock)); - state->planner->time = live_clock->localtime(); + std::shared_ptr eds_planner(new PlannerEds(live_clock)); + eds_planner->time = live_clock->localtime(); + state->planner = eds_planner; std::shared_ptr actions(new LiveActions(state)); MenuFactory factory(actions, state); // snap decisions ClockWatcherImpl clock_watcher(state); Snap snap; - clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ + clock_watcher.alarm_reached().connect([&snap,&eds_planner](const Appointment& appt){ + eds_planner->block_appointment(appt); // when we show a snap decision, take it out of the menu auto snap_show = [](const Appointment& a){url_dispatch_send(a.url.c_str(), nullptr, nullptr);}; auto snap_dismiss = [](const Appointment&){}; snap(appt, snap_show, snap_dismiss); diff --git a/src/planner-eds.cpp b/src/planner-eds.cpp index 7d9416c..e9452f0 100644 --- a/src/planner-eds.cpp +++ b/src/planner-eds.cpp @@ -77,6 +77,12 @@ public: g_clear_object(&m_source_registry); } + void block_appointment(const Appointment& appointment) + { + m_blocked.insert(appointment.uid); + rebuild_soon(UPCOMING); + } + private: static void on_source_registry_ready(GObject* /*source*/, GAsyncResult* res, gpointer gself) @@ -348,9 +354,13 @@ private: const auto begin = g_date_time_add_minutes(ref.get(),-10); const auto end = g_date_time_add_months(begin,1); - get_appointments(begin, end, [this](const std::vector& appointments) { - g_debug("got %d upcoming appointments", (int)appointments.size()); - m_owner.upcoming.set(appointments); + get_appointments(begin, end, [this](const std::vector& all) { + std::vector unblocked; + for(const auto& a : all) + if (m_blocked.count(a.uid) == 0) + unblocked.push_back(a); + g_debug("got %d upcoming appointments, %d of which are unblocked", (int)all.size(), (int)unblocked.size()); + m_owner.upcoming.set(unblocked); }); g_date_time_unref(end); @@ -520,6 +530,7 @@ private: std::set m_sources; std::map m_clients; std::map m_views; + std::set m_blocked; GCancellable* m_cancellable = nullptr; ESourceRegistry* m_source_registry = nullptr; guint m_rebuild_tag = 0; @@ -531,6 +542,11 @@ PlannerEds::PlannerEds(const std::shared_ptr& clock): p(new Impl(*this, c PlannerEds::~PlannerEds() =default; +void PlannerEds::block_appointment(const Appointment& appointment) +{ + p->block_appointment(appointment); +} + } // namespace datetime } // namespace indicator } // namespace unity -- cgit v1.2.3 From 5c91c53c1d56a356e091d6910b8c71e7c139f46a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 5 Feb 2014 16:30:11 -0600 Subject: if an alarm doesn't have a URL associated with it, use 'appid://com.ubuntu.clock/clock/current-user-version' as a fallback url. --- src/main.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 5f5ee3c..2be727f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,7 +70,14 @@ main(int /*argc*/, char** /*argv*/) Snap snap; clock_watcher.alarm_reached().connect([&snap,&eds_planner](const Appointment& appt){ eds_planner->block_appointment(appt); // when we show a snap decision, take it out of the menu - auto snap_show = [](const Appointment& a){url_dispatch_send(a.url.c_str(), nullptr, nullptr);}; + auto snap_show = [](const Appointment& a){ + const char* url; + if(!a.url.empty()) + url = a.url.c_str(); + else // alarm doesn't have a URl associated with it; use a fallback + url = "appid://com.ubuntu.clock/clock/current-user-version"; + url_dispatch_send(url, nullptr, nullptr); + }; auto snap_dismiss = [](const Appointment&){}; snap(appt, snap_show, snap_dismiss); }); -- cgit v1.2.3 From 4f27e42b0a517fac386042c67efc721463115bb9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 5 Feb 2014 16:52:57 -0600 Subject: revert r400; we can't block alarms by UID because that would hide recurring alarms --- include/datetime/planner-eds.h | 2 -- src/main.cpp | 8 +++----- src/planner-eds.cpp | 22 +++------------------- 3 files changed, 6 insertions(+), 26 deletions(-) (limited to 'src/main.cpp') diff --git a/include/datetime/planner-eds.h b/include/datetime/planner-eds.h index 4110ba5..a99f611 100644 --- a/include/datetime/planner-eds.h +++ b/include/datetime/planner-eds.h @@ -20,7 +20,6 @@ #ifndef INDICATOR_DATETIME_PLANNER_EDS_H #define INDICATOR_DATETIME_PLANNER_EDS_H -#include #include #include @@ -38,7 +37,6 @@ class PlannerEds: public Planner public: PlannerEds(const std::shared_ptr& clock); virtual ~PlannerEds(); - void block_appointment(const Appointment& appointment); private: class Impl; diff --git a/src/main.cpp b/src/main.cpp index 2be727f..31d9db6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,17 +59,15 @@ main(int /*argc*/, char** /*argv*/) state->settings = live_settings; state->clock = live_clock; state->locations.reset(new SettingsLocations(live_settings, live_timezones)); - std::shared_ptr eds_planner(new PlannerEds(live_clock)); - eds_planner->time = live_clock->localtime(); - state->planner = eds_planner; + state->planner.reset(new PlannerEds(live_clock)); + state->planner->time = live_clock->localtime(); std::shared_ptr actions(new LiveActions(state)); MenuFactory factory(actions, state); // snap decisions ClockWatcherImpl clock_watcher(state); Snap snap; - clock_watcher.alarm_reached().connect([&snap,&eds_planner](const Appointment& appt){ - eds_planner->block_appointment(appt); // when we show a snap decision, take it out of the menu + clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ auto snap_show = [](const Appointment& a){ const char* url; if(!a.url.empty()) diff --git a/src/planner-eds.cpp b/src/planner-eds.cpp index e9452f0..7d9416c 100644 --- a/src/planner-eds.cpp +++ b/src/planner-eds.cpp @@ -77,12 +77,6 @@ public: g_clear_object(&m_source_registry); } - void block_appointment(const Appointment& appointment) - { - m_blocked.insert(appointment.uid); - rebuild_soon(UPCOMING); - } - private: static void on_source_registry_ready(GObject* /*source*/, GAsyncResult* res, gpointer gself) @@ -354,13 +348,9 @@ private: const auto begin = g_date_time_add_minutes(ref.get(),-10); const auto end = g_date_time_add_months(begin,1); - get_appointments(begin, end, [this](const std::vector& all) { - std::vector unblocked; - for(const auto& a : all) - if (m_blocked.count(a.uid) == 0) - unblocked.push_back(a); - g_debug("got %d upcoming appointments, %d of which are unblocked", (int)all.size(), (int)unblocked.size()); - m_owner.upcoming.set(unblocked); + get_appointments(begin, end, [this](const std::vector& appointments) { + g_debug("got %d upcoming appointments", (int)appointments.size()); + m_owner.upcoming.set(appointments); }); g_date_time_unref(end); @@ -530,7 +520,6 @@ private: std::set m_sources; std::map m_clients; std::map m_views; - std::set m_blocked; GCancellable* m_cancellable = nullptr; ESourceRegistry* m_source_registry = nullptr; guint m_rebuild_tag = 0; @@ -542,11 +531,6 @@ PlannerEds::PlannerEds(const std::shared_ptr& clock): p(new Impl(*this, c PlannerEds::~PlannerEds() =default; -void PlannerEds::block_appointment(const Appointment& appointment) -{ - p->block_appointment(appointment); -} - } // namespace datetime } // namespace indicator } // namespace unity -- cgit v1.2.3