Merge lp:~renatofilho/indicator-datetime/notify-missing-alarm into lp:indicator-datetime/15.10

Proposed by Renato Araujo Oliveira Filho
Status: Superseded
Proposed branch: lp:~renatofilho/indicator-datetime/notify-missing-alarm
Merge into: lp:indicator-datetime/15.10
Diff against target: 1707 lines (+700/-251)
30 files modified
CMakeLists.txt (+5/-2)
data/CMakeLists.txt (+6/-1)
data/indicator-datetime.desktop.in (+1/-0)
debian/control (+5/-0)
include/datetime/appointment.h (+2/-0)
include/datetime/engine-eds.h (+3/-2)
include/datetime/myself.h (+62/-0)
include/notifications/notifications.h (+9/-2)
src/CMakeLists.txt (+1/-0)
src/appointment.cpp (+11/-1)
src/engine-eds.cpp (+197/-200)
src/main.cpp (+6/-2)
src/myself.cpp (+76/-0)
src/notifications.cpp (+122/-5)
src/snap.cpp (+11/-3)
tests/CMakeLists.txt (+3/-1)
tests/notification-fixture.h (+10/-10)
tests/run-eds-ics-test.sh (+9/-1)
tests/test-eds-ics-all-day-events.cpp (+3/-2)
tests/test-eds-ics-missing-trigger.cpp (+2/-1)
tests/test-eds-ics-non-attending-alarms.cpp (+79/-0)
tests/test-eds-ics-non-attending-alarms.ics.in (+53/-0)
tests/test-eds-ics-nonrepeating-events.cpp (+3/-2)
tests/test-eds-ics-repeating-events.cpp (+3/-2)
tests/test-eds-ics-repeating-valarms.cpp (+10/-9)
tests/test-eds-ics-tzids-2.cpp (+2/-1)
tests/test-eds-ics-tzids-utc.cpp (+2/-1)
tests/test-eds-ics-tzids.cpp (+2/-1)
tests/test-notification.cpp (+1/-1)
tests/test-sound.cpp (+1/-1)
To merge this branch: bzr merge lp:~renatofilho/indicator-datetime/notify-missing-alarm
Reviewer Review Type Date Requested Status
Indicator Applet Developers Pending
Review via email: mp+292269@code.launchpad.net

This proposal has been superseded by a proposal from 2016-04-19.

Description of the change

Post message on messaging menu if the notification get timeout.

To post a comment you must log in.
463. By Renato Araujo Oliveira Filho

Fixed crash when clicking on messaging menu.

464. By Renato Araujo Oliveira Filho

Fix memory leak on messaging_menu.

465. By Renato Araujo Oliveira Filho

Vibrate only once when notification about calendar events.

466. By Renato Araujo Oliveira Filho

Fixed as reviewer requested.

467. By Renato Araujo Oliveira Filho

Make use of G_USEC_PER_SEC.

468. By Renato Araujo Oliveira Filho

Update notifications to use the new calendar icon.

469. By Renato Araujo Oliveira Filho

Use calendar app icon.

470. By Renato Araujo Oliveira Filho

Only creates messaging menu if calendar app is instaled.
Update tests.

471. By Renato Araujo Oliveira Filho

Small fixes requeted by charles during the review.

472. By Renato Araujo Oliveira Filho

Detect desktop to launch applications.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2016-02-03 16:33:39 +0000
+++ CMakeLists.txt 2016-04-19 13:10:52 +0000
@@ -20,7 +20,7 @@
2020
21##21##
22## GNU standard installation directories22## GNU standard installation directories
23## 23##
2424
25include (GNUInstallDirs)25include (GNUInstallDirs)
26if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian26if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian
@@ -47,7 +47,10 @@
47 gstreamer-1.0>=1.247 gstreamer-1.0>=1.2
48 libnotify>=0.7.648 libnotify>=0.7.6
49 url-dispatcher-1>=149 url-dispatcher-1>=1
50 properties-cpp>=0.0.1)50 properties-cpp>=0.0.1
51 libaccounts-glib>=1.18
52 messaging-menu>=12.10
53 uuid>=2.25)
51include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})54include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
5255
53##56##
5457
=== modified file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 2015-10-13 15:06:25 +0000
+++ data/CMakeLists.txt 2016-04-19 13:10:52 +0000
@@ -30,6 +30,7 @@
3030
31# build it31# build it
32set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")32set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
33set (messaging_menu_icon "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/suru/actions/scalable/appointment.svg")
33configure_file ("${UPSTART_JOB_FILE_IN}" "${UPSTART_JOB_FILE}")34configure_file ("${UPSTART_JOB_FILE_IN}" "${UPSTART_JOB_FILE}")
3435
35# install it36# install it
@@ -52,7 +53,11 @@
52set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")53set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
53configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}")54configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}")
5455
55# install it56# install desktop file used by messaging-menu
57install (FILES "${XDG_AUTOSTART_FILE}"
58 DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/")
59
60# install XDG autostart
56install (FILES "${XDG_AUTOSTART_FILE}"61install (FILES "${XDG_AUTOSTART_FILE}"
57 DESTINATION "${XDG_AUTOSTART_DIR}")62 DESTINATION "${XDG_AUTOSTART_DIR}")
5863
5964
=== modified file 'data/indicator-datetime.desktop.in'
--- data/indicator-datetime.desktop.in 2014-04-04 13:05:59 +0000
+++ data/indicator-datetime.desktop.in 2016-04-19 13:10:52 +0000
@@ -7,3 +7,4 @@
7StartupNotify=false7StartupNotify=false
8Terminal=false8Terminal=false
9AutostartCondition=GNOME3 unless-session gnome9AutostartCondition=GNOME3 unless-session gnome
10Icon=@messaging_menu_icon@
1011
=== modified file 'debian/control'
--- debian/control 2016-03-10 16:20:36 +0000
+++ debian/control 2016-04-19 13:10:52 +0000
@@ -29,6 +29,11 @@
29 gvfs-daemons,29 gvfs-daemons,
30# for phone alarm/calendar notification sound tests:30# for phone alarm/calendar notification sound tests:
31 ubuntu-touch-sounds,31 ubuntu-touch-sounds,
32# for query user e-mails based on accounts
33 libaccounts-glib-dev,
34# messaging menu integration
35 libmessaging-menu-dev,
36 uuid-dev,
32Standards-Version: 3.9.337Standards-Version: 3.9.3
33Homepage: https://launchpad.net/indicator-datetime38Homepage: https://launchpad.net/indicator-datetime
34# If you aren't a member of ~indicator-applet-developers but need to upload39# If you aren't a member of ~indicator-applet-developers but need to upload
3540
=== modified file 'include/datetime/appointment.h'
--- include/datetime/appointment.h 2016-03-16 14:42:06 +0000
+++ include/datetime/appointment.h 2016-04-19 13:10:52 +0000
@@ -39,6 +39,8 @@
39 DateTime time;39 DateTime time;
4040
41 bool operator== (const Alarm& that) const;41 bool operator== (const Alarm& that) const;
42 bool has_sound() const;
43 bool has_text() const;
42};44};
4345
44/**46/**
4547
=== modified file 'include/datetime/engine-eds.h'
--- include/datetime/engine-eds.h 2014-12-08 02:52:50 +0000
+++ include/datetime/engine-eds.h 2016-04-19 13:10:52 +0000
@@ -36,16 +36,17 @@
36/****36/****
37*****37*****
38****/38****/
39class Myself;
3940
40/**41/**
41 * Class wrapper around EDS so multiple #EdsPlanners can share resources42 * Class wrapper around EDS so multiple #EdsPlanners can share resources
42 * 43 *
43 * @see EdsPlanner44 * @see EdsPlanner
44 */45 */
45class EdsEngine: public Engine46class EdsEngine: public Engine
46{47{
47public:48public:
48 EdsEngine();49 EdsEngine(const std::shared_ptr<Myself> &myself);
49 ~EdsEngine();50 ~EdsEngine();
5051
51 void get_appointments(const DateTime& begin,52 void get_appointments(const DateTime& begin,
5253
=== added file 'include/datetime/myself.h'
--- include/datetime/myself.h 1970-01-01 00:00:00 +0000
+++ include/datetime/myself.h 2016-04-19 13:10:52 +0000
@@ -0,0 +1,62 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Renato Araujo Oliveira Filho <renato.filho@canonical.com>
18 */
19
20#ifndef INDICATOR_DATETIME_MYSELF_H
21#define INDICATOR_DATETIME_MYSELF_H
22
23#include <core/property.h>
24
25#include <string>
26#include <set>
27#include <memory.h>
28#include <glib.h>
29
30typedef struct _AgManager AgManager;
31
32namespace unity {
33namespace indicator {
34namespace datetime {
35
36class Myself
37{
38public:
39 Myself();
40
41 const core::Property<std::set<std::string>>& emails()
42 {
43 return m_emails;
44 }
45
46 bool isMyEmail(const std::string &email);
47
48private:
49 std::shared_ptr<AgManager> m_accounts_manager;
50 core::Property<std::set<std::string> > m_emails;
51
52 static void on_accounts_changed(AgManager*, guint, Myself*);
53 void reloadEmails();
54
55};
56
57
58} // namespace datetime
59} // namespace indicator
60} // namespace unity
61
62#endif // INDICATOR_DATETIME_MYSELF_H
063
=== modified file 'include/notifications/notifications.h'
--- include/notifications/notifications.h 2014-09-19 14:35:07 +0000
+++ include/notifications/notifications.h 2016-04-19 13:10:52 +0000
@@ -50,6 +50,8 @@
5050
51 void set_icon_name (const std::string& icon_name);51 void set_icon_name (const std::string& icon_name);
5252
53 void set_start_time(uint64_t time);
54
53 /* Set an interval, after which the notification will automatically55 /* Set an interval, after which the notification will automatically
54 be closed. If not set, the notification server's default timeout56 be closed. If not set, the notification server's default timeout
55 is used. */57 is used. */
@@ -62,19 +64,24 @@
62 static constexpr char const * HINT_NONSHAPED_ICON {"x-canonical-non-shaped-icon"};64 static constexpr char const * HINT_NONSHAPED_ICON {"x-canonical-non-shaped-icon"};
63 static constexpr char const * HINT_AFFIRMATIVE_HINT {"x-canonical-private-affirmative-tint"};65 static constexpr char const * HINT_AFFIRMATIVE_HINT {"x-canonical-private-affirmative-tint"};
64 static constexpr char const * HINT_REJECTION_TINT {"x-canonical-private-rejection-tint"};66 static constexpr char const * HINT_REJECTION_TINT {"x-canonical-private-rejection-tint"};
67 static constexpr char const * HINT_INTERACTIVE {"x-canonical-switch-to-application"};
6568
66 /* Add an action button.69 /* Add an action button.
67 This may fail if the Engine doesn't support actions.70 This may fail if the Engine doesn't support actions.
68 @see Engine::supports_actions() */71 @see Engine::supports_actions() */
69 void add_action (const std::string& action, const std::string& label);72 void add_action (const std::string& action, const std::string& label);
7073
71 /** Sets the closed callback. This will be called exactly once. */74 /** Sets the closed callback. This will be called exactly once. After notification dissapear */
72 void set_closed_callback (std::function<void(const std::string& action)>);75 void set_closed_callback (std::function<void(const std::string& action)>);
7376
77 /** Sets the time-out callback. This will be called exactly once. */
78 void set_missed_click_callback (std::function<void()>);
79
80
74private:81private:
75 friend class Engine;82 friend class Engine;
76 class Impl;83 class Impl;
77 std::unique_ptr<Impl> impl;84 std::shared_ptr<Impl> impl;
78};85};
7986
80/**87/**
8188
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2015-09-01 09:52:13 +0000
+++ src/CMakeLists.txt 2016-04-19 13:10:52 +0000
@@ -23,6 +23,7 @@
23 locations.cpp23 locations.cpp
24 locations-settings.cpp24 locations-settings.cpp
25 menu.cpp25 menu.cpp
26 myself.cpp
26 notifications.cpp27 notifications.cpp
27 planner.cpp28 planner.cpp
28 planner-aggregate.cpp29 planner-aggregate.cpp
2930
=== modified file 'src/appointment.cpp'
--- src/appointment.cpp 2015-04-05 22:27:52 +0000
+++ src/appointment.cpp 2016-04-19 13:10:52 +0000
@@ -31,7 +31,17 @@
31{31{
32 return (text==that.text)32 return (text==that.text)
33 && (audio_url==that.audio_url)33 && (audio_url==that.audio_url)
34 && (this->time==that.time);34 && (this->time==that.time);
35}
36
37bool Alarm::has_sound() const
38{
39 return !audio_url.empty();
40}
41
42bool Alarm::has_text() const
43{
44 return !text.empty();
35}45}
3646
37bool Appointment::operator==(const Appointment& that) const47bool Appointment::operator==(const Appointment& that) const
3848
=== modified file 'src/engine-eds.cpp'
--- src/engine-eds.cpp 2016-03-22 19:32:25 +0000
+++ src/engine-eds.cpp 2016-04-19 13:10:52 +0000
@@ -18,6 +18,7 @@
18 */18 */
1919
20#include <datetime/engine-eds.h>20#include <datetime/engine-eds.h>
21#include <datetime/myself.h>
2122
22#include <libical/ical.h>23#include <libical/ical.h>
23#include <libical/icaltime.h>24#include <libical/icaltime.h>
@@ -48,7 +49,8 @@
48{49{
49public:50public:
5051
51 Impl()52 Impl(const std::shared_ptr<Myself> &myself)
53 : m_myself(myself)
52 {54 {
53 auto cancellable_deleter = [](GCancellable * c) {55 auto cancellable_deleter = [](GCancellable * c) {
54 g_cancellable_cancel(c);56 g_cancellable_cancel(c);
@@ -56,8 +58,10 @@
56 };58 };
5759
58 m_cancellable = std::shared_ptr<GCancellable>(g_cancellable_new(), cancellable_deleter);60 m_cancellable = std::shared_ptr<GCancellable>(g_cancellable_new(), cancellable_deleter);
59
60 e_source_registry_new(m_cancellable.get(), on_source_registry_ready, this);61 e_source_registry_new(m_cancellable.get(), on_source_registry_ready, this);
62 m_myself->emails().changed().connect([this](const std::set<std::string> &) {
63 set_dirty_soon();
64 });
61 }65 }
6266
63 ~Impl()67 ~Impl()
@@ -92,26 +96,19 @@
92 /**96 /**
93 *** init the default timezone97 *** init the default timezone
94 **/98 **/
95
96 icaltimezone * default_timezone = nullptr;99 icaltimezone * default_timezone = nullptr;
97 const auto tz = timezone.timezone.get().c_str();100 const auto tz = timezone.timezone.get().c_str();
98 if (tz && *tz)101 auto gtz = timezone_from_name(tz, nullptr, nullptr, &default_timezone);
99 {102 if (gtz == nullptr) {
100 default_timezone = icaltimezone_get_builtin_timezone(tz);103 gtz = g_time_zone_new_local();
101
102 if (default_timezone == nullptr) // maybe str is a tzid?
103 default_timezone = icaltimezone_get_builtin_timezone_from_tzid(tz);
104
105 g_debug("default_timezone is %p", (void*)default_timezone);
106 }104 }
107105
106 g_debug("default_timezone is %s", default_timezone ? icaltimezone_get_display_name(default_timezone) : "null");
107
108 /**108 /**
109 *** walk through the sources to build the appointment list109 *** walk through the sources to build the appointment list
110 **/110 **/
111111
112 auto gtz = default_timezone != nullptr
113 ? g_time_zone_new(icaltimezone_get_location(default_timezone))
114 : g_time_zone_new_local();
115 auto main_task = std::make_shared<Task>(this, func, default_timezone, gtz, begin, end);112 auto main_task = std::make_shared<Task>(this, func, default_timezone, gtz, begin, end);
116113
117 for (auto& kv : m_clients)114 for (auto& kv : m_clients)
@@ -125,35 +122,14 @@
125 auto extension = e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR);122 auto extension = e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR);
126 const auto color = e_source_selectable_get_color(E_SOURCE_SELECTABLE(extension));123 const auto color = e_source_selectable_get_color(E_SOURCE_SELECTABLE(extension));
127124
128 auto begin_str = isodate_from_time_t(begin.to_unix());125 e_cal_client_generate_instances(
129 auto end_str = isodate_from_time_t(end.to_unix());126 client,
130 auto sexp_fmt = g_strdup_printf("(%%s? (make-time \"%s\") (make-time \"%s\"))", begin_str, end_str);127 begin.to_unix(),
131 g_clear_pointer(&begin_str, g_free);128 end.to_unix(),
132 g_clear_pointer(&end_str, g_free);129 m_cancellable.get(),
133130 on_event_generated,
134 // ask EDS about alarms that occur in this window...131 new ClientSubtask(main_task, client, m_cancellable, color),
135 auto sexp = g_strdup_printf(sexp_fmt, "has-alarms-in-range");132 on_event_generated_list_ready);
136 g_debug("%s alarm sexp is %s", G_STRLOC, sexp);
137 e_cal_client_get_object_list_as_comps(
138 client,
139 sexp,
140 m_cancellable.get(),
141 on_alarm_component_list_ready,
142 new ClientSubtask(main_task, client, m_cancellable, color));
143 g_clear_pointer(&sexp, g_free);
144
145 // ask EDS about events that occur in this window...
146 sexp = g_strdup_printf(sexp_fmt, "occur-in-time-range");
147 g_debug("%s event sexp is %s", G_STRLOC, sexp);
148 e_cal_client_get_object_list_as_comps(
149 client,
150 sexp,
151 m_cancellable.get(),
152 on_event_component_list_ready,
153 new ClientSubtask(main_task, client, m_cancellable, color));
154 g_clear_pointer(&sexp, g_free);
155
156 g_clear_pointer(&sexp_fmt, g_free);
157 }133 }
158 }134 }
159135
@@ -591,6 +567,8 @@
591 ECalClient* client;567 ECalClient* client;
592 std::shared_ptr<GCancellable> cancellable;568 std::shared_ptr<GCancellable> cancellable;
593 std::string color;569 std::string color;
570 GList *components;
571 GList *instance_components;
594572
595 ClientSubtask(const std::shared_ptr<Task>& task_in,573 ClientSubtask(const std::shared_ptr<Task>& task_in,
596 ECalClient* client_in,574 ECalClient* client_in,
@@ -598,10 +576,13 @@
598 const char* color_in):576 const char* color_in):
599 task(task_in),577 task(task_in),
600 client(client_in),578 client(client_in),
601 cancellable(cancellable_in)579 cancellable(cancellable_in),
580 components(nullptr),
581 instance_components(nullptr)
602 {582 {
603 if (color_in)583 if (color_in)
604 color = color_in;584 color = color_in;
585
605 }586 }
606 };587 };
607588
@@ -622,7 +603,7 @@
622 return ret;603 return ret;
623 }604 }
624605
625 static std::string get_alarm_sound_url(ECalComponentAlarm * alarm)606 static std::string get_alarm_sound_url(ECalComponentAlarm * alarm, const std::string & default_sound)
626 {607 {
627 std::string ret;608 std::string ret;
628609
@@ -643,92 +624,129 @@
643624
644 icalattach_unref(attach);625 icalattach_unref(attach);
645 }626 }
627 if (ret.empty())
628 ret = default_sound;
646 }629 }
647630
648 return ret;631 return ret;
649 }632 }
650633
651 static void634 static gboolean
652 on_alarm_component_list_ready(GObject * oclient,635 on_event_generated(ECalComponent *comp,
653 GAsyncResult * res,636 time_t,
654 gpointer gsubtask)637 time_t,
655 {638 gpointer gsubtask)
656 GError * error = NULL;639 {
657 GSList * comps_slist = NULL;640 auto subtask = static_cast<ClientSubtask*>(gsubtask);
658 auto subtask = static_cast<ClientSubtask*>(gsubtask);641 const gchar *uid = nullptr;
659642 e_cal_component_get_uid (comp, &uid);
660 if (e_cal_client_get_object_list_as_comps_finish(E_CAL_CLIENT(oclient),643 g_object_ref(comp);
661 res,644 if (e_cal_component_is_instance(comp))
662 &comps_slist,645 subtask->instance_components = g_list_append(subtask->instance_components, comp);
663 &error))646 else
664 {647 subtask->components = g_list_append(subtask->components, comp);
665 // _generate_alarms takes a GList, so make a shallow one648 return TRUE;
666 GList * comps_list = nullptr;649 }
667 for (auto l=comps_slist; l!=nullptr; l=l->next)650
668 comps_list = g_list_prepend(comps_list, l->data);651 static void
669652 on_event_generated_list_ready(gpointer gsubtask)
670 constexpr std::array<ECalComponentAlarmAction,1> omit = {653 {
671 (ECalComponentAlarmAction)-1654 auto subtask = static_cast<ClientSubtask*>(gsubtask);
672 }; // list of action types to omit, terminated with -1655
673 GSList * comp_alarms = nullptr;656 // generate alarms
674 e_cal_util_generate_alarms_for_list(657 constexpr std::array<ECalComponentAlarmAction,1> omit = {
675 comps_list,658 (ECalComponentAlarmAction)-1
676 subtask->task->begin.to_unix(),659 }; // list of action types to omit, terminated with -1
677 subtask->task->end.to_unix(),660 GSList * comp_alarms = nullptr;
678 const_cast<ECalComponentAlarmAction*>(omit.data()),661
679 &comp_alarms,662 // we do not need translate tz for instance events,
680 e_cal_client_resolve_tzid_cb,663 // they are aredy in the correct time
681 oclient,664 e_cal_util_generate_alarms_for_list(
682 subtask->task->default_timezone);665 subtask->instance_components,
683666 subtask->task->begin.to_unix(),
684 // walk the alarms & add them667 subtask->task->end.to_unix(),
685 for (auto l=comp_alarms; l!=nullptr; l=l->next)668 const_cast<ECalComponentAlarmAction*>(omit.data()),
686 add_alarms_to_subtask(static_cast<ECalComponentAlarms*>(l->data), subtask, subtask->task->gtz);669 &comp_alarms,
687670 e_cal_client_resolve_tzid_cb,
688 // cleanup671 subtask->client,
689 e_cal_free_alarms(comp_alarms);672 nullptr);
690 g_list_free(comps_list);673
691 e_cal_client_free_ecalcomp_slist(comps_slist);674 // convert timezone for non-instance events
692 }675 e_cal_util_generate_alarms_for_list(
693 else if (error != nullptr)676 subtask->components,
694 {677 subtask->task->begin.to_unix(),
695 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))678 subtask->task->end.to_unix(),
696 g_warning("can't get ecalcomponent list: %s", error->message);679 const_cast<ECalComponentAlarmAction*>(omit.data()),
697680 &comp_alarms,
698 g_error_free(error);681 e_cal_client_resolve_tzid_cb,
699 }682 subtask->client,
700683 subtask->task->default_timezone);
701 delete subtask;684
702 }685 // walk the alarms & add them
703686 for (auto l=comp_alarms; l!=nullptr; l=l->next)
704 static void687 add_alarms_to_subtask(static_cast<ECalComponentAlarms*>(l->data), subtask, subtask->task->gtz);
705 on_event_component_list_ready(GObject * oclient,688
706 GAsyncResult * res,689 subtask->components = g_list_concat(subtask->components, subtask->instance_components);
707 gpointer gsubtask)690 // add events without alarm
708 {691 for (auto l=subtask->components; l!=nullptr; l=l->next) {
709 GError * error = NULL;692 auto component = static_cast<ECalComponent*>(l->data);
710 GSList * comps_slist = NULL;693 if (!e_cal_component_has_alarms(component))
711 auto subtask = static_cast<ClientSubtask*>(gsubtask);694 add_event_to_subtask(component, subtask, subtask->task->gtz);
712695 }
713 if (e_cal_client_get_object_list_as_comps_finish(E_CAL_CLIENT(oclient),696 g_list_free_full(subtask->components, g_object_unref);
714 res,697 e_cal_free_alarms(comp_alarms);
715 &comps_slist,698 delete subtask;
716 &error))699 }
717 {700
718 for (auto l=comps_slist; l!=nullptr; l=l->next)701 static GTimeZone *
719 add_event_to_subtask(static_cast<ECalComponent*>(l->data), subtask, subtask->task->gtz);702 timezone_from_name (const char * tzid,
720703 ECalClient * client,
721 e_cal_client_free_ecalcomp_slist(comps_slist);704 GCancellable * cancellable,
722 }705 icaltimezone **itimezone)
723 else if (error != nullptr)706 {
724 {707 if (tzid == nullptr)
725 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))708 return nullptr;
726 g_warning("can't get ecalcomponent list: %s", error->message);709
727710 auto itz = icaltimezone_get_builtin_timezone_from_tzid(tzid); // usually works
728 g_error_free(error);711
729 }712 if (itz == nullptr) // fallback
730713 itz = icaltimezone_get_builtin_timezone(tzid);
731 delete subtask;714
715 if (client && (itz == nullptr)) // ok we have a strange tzid... ask EDS to look it up in VTIMEZONES
716 e_cal_client_get_timezone_sync(client, tzid, &itz, cancellable, nullptr);
717
718 const char* identifier {};
719 if (itimezone)
720 *itimezone = itz;
721
722 if (itz != nullptr)
723 {
724 identifier = icaltimezone_get_display_name(itz);
725
726 if (identifier == nullptr)
727 identifier = icaltimezone_get_location(itz);
728 }
729
730 // handle the TZID /freeassociation.sourceforge.net/Tzfile/[Location] case
731 if (identifier != nullptr)
732 {
733 const char* pch;
734 const char* key = "/freeassociation.sourceforge.net/";
735 if ((pch = strstr(identifier, key)))
736 {
737 identifier = pch + strlen(key);
738 key = "Tzfile/"; // some don't have this, so check for it separately
739 if ((pch = strstr(identifier, key)))
740 identifier = pch + strlen(key);
741 }
742 }
743
744 if (identifier == nullptr)
745 g_warning("Unrecognized TZID: '%s'", tzid);
746 else
747 return g_time_zone_new(identifier);
748
749 return nullptr;
732 }750 }
733751
734 static DateTime752 static DateTime
@@ -740,51 +758,9 @@
740 DateTime out;758 DateTime out;
741 g_return_val_if_fail(in.value != nullptr, out);759 g_return_val_if_fail(in.value != nullptr, out);
742760
743 GTimeZone * gtz {};761 GTimeZone * gtz = timezone_from_name(in.tzid, client, cancellable.get(), nullptr);
744 if (in.tzid != nullptr)762 if (gtz == nullptr)
745 {
746 auto itz = icaltimezone_get_builtin_timezone_from_tzid(in.tzid); // usually works
747
748 if (itz == nullptr) // fallback
749 itz = icaltimezone_get_builtin_timezone(in.tzid);
750
751 if (itz == nullptr) // ok we have a strange tzid... ask EDS to look it up in VTIMEZONES
752 e_cal_client_get_timezone_sync(client, in.tzid, &itz, cancellable.get(), nullptr);
753
754 const char* identifier {};
755
756 if (itz != nullptr)
757 {
758 identifier = icaltimezone_get_display_name(itz);
759
760 if (identifier == nullptr)
761 identifier = icaltimezone_get_location(itz);
762 }
763
764 // handle the TZID /freeassociation.sourceforge.net/Tzfile/[Location] case
765 if (identifier != nullptr)
766 {
767 const char* pch;
768 const char* key = "/freeassociation.sourceforge.net/";
769 if ((pch = strstr(identifier, key)))
770 {
771 identifier = pch + strlen(key);
772 key = "Tzfile/"; // some don't have this, so check for it separately
773 if ((pch = strstr(identifier, key)))
774 identifier = pch + strlen(key);
775 }
776 }
777
778 if (identifier == nullptr)
779 g_warning("Unrecognized TZID: '%s'", in.tzid);
780
781 gtz = g_time_zone_new(identifier);
782 g_debug("%s eccdt.tzid -> offset is %d", G_STRLOC, in.tzid, (int)g_time_zone_get_offset(gtz,0));
783 }
784 else
785 {
786 gtz = g_time_zone_ref(default_timezone);763 gtz = g_time_zone_ref(default_timezone);
787 }
788764
789 out = DateTime(gtz,765 out = DateTime(gtz,
790 in.value->year,766 in.value->year,
@@ -797,7 +773,7 @@
797 return out;773 return out;
798 }774 }
799775
800 static bool776 bool
801 is_component_interesting(ECalComponent * component)777 is_component_interesting(ECalComponent * component)
802 {778 {
803 // we only want calendar events and vtodos779 // we only want calendar events and vtodos
@@ -823,6 +799,28 @@
823 disabled = true;799 disabled = true;
824 }800 }
825 e_cal_component_free_categories_list(categ_list);801 e_cal_component_free_categories_list(categ_list);
802
803 if (!disabled) {
804 // we don't want not attending alarms
805 // check if the user is part of attendee list if we found it check the status
806 GSList *attendeeList = nullptr;
807 e_cal_component_get_attendee_list(component, &attendeeList);
808
809 for (GSList *attendeeIter=attendeeList; attendeeIter != nullptr; attendeeIter = attendeeIter->next) {
810 ECalComponentAttendee *attendee = static_cast<ECalComponentAttendee *>(attendeeIter->data);
811 if (attendee->value) {
812 if (strncmp(attendee->value, "mailto:", 7) == 0) {
813 if (m_myself->isMyEmail(attendee->value+7)) {
814 disabled = (attendee->status == ICAL_PARTSTAT_DECLINED);
815 break;
816 }
817 }
818 }
819 }
820 if (attendeeList)
821 e_cal_component_free_attendee_list(attendeeList);
822 }
823
826 if (disabled)824 if (disabled)
827 return false;825 return false;
828826
@@ -903,35 +901,13 @@
903 }901 }
904902
905 static void903 static void
906 add_event_to_subtask(ECalComponent * component,
907 ClientSubtask * subtask,
908 GTimeZone * gtz)
909 {
910 // events with alarms are covered by add_alarms_to_subtask(),
911 // so skip them here
912 auto auids = e_cal_component_get_alarm_uids(component);
913 const bool has_alarms = auids != nullptr;
914 cal_obj_uid_list_free(auids);
915 if (has_alarms)
916 return;
917
918 // add it. simple, eh?
919 if (is_component_interesting(component))
920 {
921 Appointment appointment = get_appointment(subtask->client, subtask->cancellable, component, gtz);
922 appointment.color = subtask->color;
923 subtask->task->appointments.push_back(appointment);
924 }
925 }
926
927 static void
928 add_alarms_to_subtask(ECalComponentAlarms * comp_alarms,904 add_alarms_to_subtask(ECalComponentAlarms * comp_alarms,
929 ClientSubtask * subtask,905 ClientSubtask * subtask,
930 GTimeZone * gtz)906 GTimeZone * gtz)
931 {907 {
932 auto& component = comp_alarms->comp;908 auto& component = comp_alarms->comp;
933909
934 if (!is_component_interesting(component))910 if (!subtask->task->p->is_component_interesting(component))
935 return;911 return;
936912
937 Appointment baseline = get_appointment(subtask->client, subtask->cancellable, component, gtz);913 Appointment baseline = get_appointment(subtask->client, subtask->cancellable, component, gtz);
@@ -965,13 +941,15 @@
965 auto instance_time = std::make_pair(DateTime{gtz, ai->occur_start},941 auto instance_time = std::make_pair(DateTime{gtz, ai->occur_start},
966 DateTime{gtz, ai->occur_end});942 DateTime{gtz, ai->occur_end});
967 auto trigger_time = DateTime{gtz, ai->trigger};943 auto trigger_time = DateTime{gtz, ai->trigger};
968
969 auto& alarm = alarms[instance_time][trigger_time];944 auto& alarm = alarms[instance_time][trigger_time];
970
971 if (alarm.text.empty())945 if (alarm.text.empty())
972 alarm.text = get_alarm_text(a);946 alarm.text = get_alarm_text(a);
947
973 if (alarm.audio_url.empty())948 if (alarm.audio_url.empty())
974 alarm.audio_url = get_alarm_sound_url(a);949 alarm.audio_url = get_alarm_sound_url(a, (baseline.is_ubuntu_alarm() ?
950 "file://" ALARM_DEFAULT_SOUND :
951 "file://" CALENDAR_DEFAULT_SOUND));
952
975 if (!alarm.time.is_set())953 if (!alarm.time.is_set())
976 alarm.time = trigger_time;954 alarm.time = trigger_time;
977955
@@ -985,7 +963,25 @@
985 appointment.end = i.first.second;963 appointment.end = i.first.second;
986 appointment.alarms.reserve(i.second.size());964 appointment.alarms.reserve(i.second.size());
987 for (auto& j : i.second)965 for (auto& j : i.second)
988 appointment.alarms.push_back(j.second);966 {
967 if (j.second.has_text() || j.second.has_sound())
968 appointment.alarms.push_back(j.second);
969 }
970 subtask->task->appointments.push_back(appointment);
971 }
972 }
973
974
975 static void
976 add_event_to_subtask(ECalComponent * component,
977 ClientSubtask * subtask,
978 GTimeZone * gtz)
979 {
980 // add it. simple, eh?
981 if (subtask->task->p->is_component_interesting(component))
982 {
983 Appointment appointment = get_appointment(subtask->client, subtask->cancellable, component, gtz);
984 appointment.color = subtask->color;
989 subtask->task->appointments.push_back(appointment);985 subtask->task->appointments.push_back(appointment);
990 }986 }
991 }987 }
@@ -1062,14 +1058,15 @@
1062 ESourceRegistry* m_source_registry {};1058 ESourceRegistry* m_source_registry {};
1063 guint m_rebuild_tag {};1059 guint m_rebuild_tag {};
1064 time_t m_rebuild_deadline {};1060 time_t m_rebuild_deadline {};
1061 std::shared_ptr<Myself> m_myself;
1065};1062};
10661063
1067/***1064/***
1068****1065****
1069***/1066***/
10701067
1071EdsEngine::EdsEngine():1068EdsEngine::EdsEngine(const std::shared_ptr<Myself> &myself):
1072 p(new Impl())1069 p(new Impl(myself))
1073{1070{
1074}1071}
10751072
10761073
=== modified file 'src/main.cpp'
--- src/main.cpp 2016-04-12 17:03:36 +0000
+++ src/main.cpp 2016-04-19 13:10:52 +0000
@@ -25,6 +25,7 @@
25#include <datetime/exporter.h>25#include <datetime/exporter.h>
26#include <datetime/locations-settings.h>26#include <datetime/locations-settings.h>
27#include <datetime/menu.h>27#include <datetime/menu.h>
28#include <datetime/myself.h>
28#include <datetime/planner-aggregate.h>29#include <datetime/planner-aggregate.h>
29#include <datetime/planner-snooze.h>30#include <datetime/planner-snooze.h>
30#include <datetime/planner-range.h>31#include <datetime/planner-range.h>
@@ -58,7 +59,7 @@
58 if (!g_strcmp0("lightdm", g_get_user_name()))59 if (!g_strcmp0("lightdm", g_get_user_name()))
59 engine.reset(new MockEngine);60 engine.reset(new MockEngine);
60 else61 else
61 engine.reset(new EdsEngine);62 engine.reset(new EdsEngine(std::shared_ptr<Myself>(new Myself)));
6263
63 return engine;64 return engine;
64 }65 }
@@ -151,7 +152,10 @@
151 auto on_snooze = [snooze_planner](const Appointment& appointment, const Alarm& alarm) {152 auto on_snooze = [snooze_planner](const Appointment& appointment, const Alarm& alarm) {
152 snooze_planner->add(appointment, alarm);153 snooze_planner->add(appointment, alarm);
153 };154 };
154 auto on_ok = [](const Appointment&, const Alarm&){};155 auto on_ok = [actions](const Appointment& app, const Alarm&){
156 //TODO: add support for desktop
157 actions->phone_open_appointment(app, app.begin);
158 };
155 auto on_alarm_reached = [&engine, &snap, &on_snooze, &on_ok](const Appointment& appointment, const Alarm& alarm) {159 auto on_alarm_reached = [&engine, &snap, &on_snooze, &on_ok](const Appointment& appointment, const Alarm& alarm) {
156 (*snap)(appointment, alarm, on_snooze, on_ok);160 (*snap)(appointment, alarm, on_snooze, on_ok);
157 engine->disable_ubuntu_alarm(appointment);161 engine->disable_ubuntu_alarm(appointment);
158162
=== added file 'src/myself.cpp'
--- src/myself.cpp 1970-01-01 00:00:00 +0000
+++ src/myself.cpp 2016-04-19 13:10:52 +0000
@@ -0,0 +1,76 @@
1/*
2 * Copyright 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Renato Araujo Oliveira Filho <renato.filho@canonical.com>
18 */
19
20#include "datetime/myself.h"
21
22#include <libaccounts-glib/ag-manager.h>
23#include <libaccounts-glib/ag-account.h>
24
25#include <algorithm>
26
27namespace unity {
28namespace indicator {
29namespace datetime {
30
31Myself::Myself()
32 : m_accounts_manager(ag_manager_new(), g_object_unref)
33{
34 reloadEmails();
35 g_object_connect(m_accounts_manager.get(),
36 "signal::account-created", on_accounts_changed, this,
37 "signal::account-deleted", on_accounts_changed, this,
38 "signal::account-updated", on_accounts_changed, this,
39 nullptr);
40}
41
42bool Myself::isMyEmail(const std::string &email)
43{
44 return m_emails.get().count(email) > 0;
45}
46
47void Myself::on_accounts_changed(AgManager *, guint, Myself *self)
48{
49 self->reloadEmails();
50}
51
52void Myself::reloadEmails()
53{
54 std::set<std::string> emails;
55
56 auto manager = m_accounts_manager.get();
57 auto ids = ag_manager_list(manager);
58 for (auto l=ids; l!=nullptr; l=l->next)
59 {
60 auto acc = ag_manager_get_account(manager, GPOINTER_TO_UINT(l->data));
61 if (acc) {
62 auto account_name = ag_account_get_display_name(acc);
63 if (account_name != nullptr)
64 emails.insert(account_name);
65 g_object_unref(acc);
66 }
67 }
68 ag_manager_list_free(ids);
69
70 m_emails.set(emails);
71}
72
73} // namespace datetime
74} // namespace indicator
75} // namespace unity
76
077
=== modified file 'src/notifications.cpp'
--- src/notifications.cpp 2014-09-17 17:08:01 +0000
+++ src/notifications.cpp 2016-04-19 13:10:52 +0000
@@ -21,10 +21,18 @@
2121
22#include <libnotify/notify.h>22#include <libnotify/notify.h>
2323
24#include <messaging-menu/messaging-menu-app.h>
25#include <messaging-menu/messaging-menu-message.h>
26
27
28#include <uuid/uuid.h>
29
24#include <map>30#include <map>
25#include <set>31#include <set>
26#include <string>32#include <string>
27#include <vector>33#include <vector>
34#include <memory>
35
2836
29namespace unity {37namespace unity {
30namespace indicator {38namespace indicator {
@@ -45,9 +53,11 @@
45 std::string m_body;53 std::string m_body;
46 std::string m_icon_name;54 std::string m_icon_name;
47 std::chrono::seconds m_duration;55 std::chrono::seconds m_duration;
56 gint64 m_start_time;
48 std::set<std::string> m_string_hints;57 std::set<std::string> m_string_hints;
49 std::vector<std::pair<std::string,std::string>> m_actions;58 std::vector<std::pair<std::string,std::string>> m_actions;
50 std::function<void(const std::string&)> m_closed_callback;59 std::function<void(const std::string&)> m_closed_callback;
60 std::function<void()> m_missed_click_callback;
51};61};
5262
53Builder::Builder():63Builder::Builder():
@@ -101,6 +111,18 @@
101 impl->m_closed_callback.swap (cb);111 impl->m_closed_callback.swap (cb);
102}112}
103113
114void
115Builder::set_missed_click_callback (std::function<void()> cb)
116{
117 impl->m_missed_click_callback.swap (cb);
118}
119
120void
121Builder::set_start_time (uint64_t time)
122{
123 impl->m_start_time = time;
124}
125
104/***126/***
105****127****
106***/128***/
@@ -110,23 +132,39 @@
110 struct notification_data132 struct notification_data
111 {133 {
112 std::shared_ptr<NotifyNotification> nn;134 std::shared_ptr<NotifyNotification> nn;
113 std::function<void(const std::string&)> closed_callback;135 Builder::Impl data;
136 };
137
138 struct messaging_menu_data
139 {
140 std::shared_ptr<MessagingMenuMessage> mm;
141 std::function<void()> callback;
114 };142 };
115143
116public:144public:
117145
118 Impl(const std::string& app_name):146 Impl(const std::string& app_name):
147 m_messaging_app(messaging_menu_app_new(DATETIME_INDICATOR_DESKTOP_FILE), g_object_unref),
119 m_app_name(app_name)148 m_app_name(app_name)
120 {149 {
121 if (!notify_init(app_name.c_str()))150 if (!notify_init(app_name.c_str()))
122 g_critical("Unable to initialize libnotify!");151 g_critical("Unable to initialize libnotify!");
152
153 // messaging menu
154 GIcon *icon = g_themed_icon_new("calendar-app");
155
156 messaging_menu_app_register(m_messaging_app.get());
157 messaging_menu_app_append_source(m_messaging_app.get(), m_app_name.c_str(), icon, "Calendar");
158 g_object_unref(icon);
123 }159 }
124160
125 ~Impl()161 ~Impl()
126 {162 {
127 close_all ();163 close_all ();
164 remove_all ();
128165
129 notify_uninit ();166 notify_uninit ();
167 messaging_menu_app_unregister (m_messaging_app.get());
130 }168 }
131169
132 const std::string& app_name() const170 const std::string& app_name() const
@@ -217,7 +255,7 @@
217 notification_key_quark(),255 notification_key_quark(),
218 GINT_TO_POINTER(key));256 GINT_TO_POINTER(key));
219257
220 m_notifications[key] = { nn, info.m_closed_callback };258 m_notifications[key] = { nn, info };
221 g_signal_connect (nn.get(), "closed",259 g_signal_connect (nn.get(), "closed",
222 G_CALLBACK(on_notification_closed), this);260 G_CALLBACK(on_notification_closed), this);
223 261
@@ -238,6 +276,59 @@
238 return ret;276 return ret;
239 }277 }
240278
279 std::string post(const Builder::Impl& data)
280 {
281 uuid_t message_uuid;
282 uuid_generate(message_uuid);
283
284 char message_id[37];
285 uuid_unparse(message_uuid, message_id);
286
287 GIcon *icon = g_themed_icon_new(data.m_icon_name.c_str());
288 std::shared_ptr<MessagingMenuMessage> msg (messaging_menu_message_new(message_id,
289 icon,
290 data.m_title.c_str(),
291 nullptr,
292 data.m_body.c_str(),
293 data.m_start_time * 1000000), // secs -> microsecs
294 g_object_ref);
295 g_object_unref(icon);
296 if (msg)
297 {
298 m_messaging_messages[std::string(message_id)] = { msg, data.m_missed_click_callback };
299 g_signal_connect(msg.get(), "activate",
300 G_CALLBACK(on_message_activated), this);
301 messaging_menu_app_append_message(m_messaging_app.get(), msg.get(), m_app_name.c_str(), false);
302 return message_id;
303 } else {
304 g_warning("Fail to create messaging menu message");
305 }
306 return "";
307 }
308
309 void remove (const std::string &key)
310 {
311 auto it = m_messaging_messages.find(key);
312 if (it != m_messaging_messages.end())
313 {
314 // tell the server to remove message
315 messaging_menu_app_remove_message(m_messaging_app.get(), it->second.mm.get());
316 m_messaging_messages.erase(it);
317 }
318 }
319
320 void remove_all ()
321 {
322 // call remove() on all our keys
323
324 std::set<std::string> keys;
325 for (const auto& it : m_messaging_messages)
326 keys.insert (it.first);
327
328 for (const std::string &key : keys)
329 remove (key);
330 }
331
241private:332private:
242333
243 const std::set<std::string>& server_caps() const334 const std::set<std::string>& server_caps() const
@@ -279,6 +370,22 @@
279 static_cast<Impl*>(gself)->remove_closed_notification(GPOINTER_TO_INT(gkey));370 static_cast<Impl*>(gself)->remove_closed_notification(GPOINTER_TO_INT(gkey));
280 }371 }
281372
373 static void on_message_activated (MessagingMenuMessage *,
374 const char *actionId,
375 GVariant *,
376 gpointer gself)
377 {
378 auto self = static_cast<Impl*>(gself);
379 auto it = self->m_messaging_messages.find(actionId);
380 g_return_if_fail (it != self->m_messaging_messages.end());
381 const auto& ndata = it->second;
382
383 if (ndata.callback)
384 ndata.callback();
385
386 self->m_messaging_messages.erase(it);
387 }
388
282 void remove_closed_notification (int key)389 void remove_closed_notification (int key)
283 {390 {
284 auto it = m_notifications.find(key);391 auto it = m_notifications.find(key);
@@ -286,16 +393,20 @@
286393
287 const auto& ndata = it->second;394 const auto& ndata = it->second;
288 auto nn = ndata.nn.get();395 auto nn = ndata.nn.get();
289 if (ndata.closed_callback)396
397 if (ndata.data.m_closed_callback)
290 {398 {
291 std::string action;399 std::string action;
292
293 const GQuark q = notification_action_quark();400 const GQuark q = notification_action_quark();
294 const gpointer p = g_object_get_qdata(G_OBJECT(nn), q);401 const gpointer p = g_object_get_qdata(G_OBJECT(nn), q);
295 if (p != nullptr)402 if (p != nullptr)
296 action = static_cast<const char*>(p);403 action = static_cast<const char*>(p);
297404
298 ndata.closed_callback (action);405 ndata.data.m_closed_callback (action);
406 // empty action means that the notification got timeout
407 // post a message on messaging menu
408 if (action.empty())
409 post(ndata.data);
299 }410 }
300411
301 m_notifications.erase(it);412 m_notifications.erase(it);
@@ -305,6 +416,10 @@
305 ****416 ****
306 ***/417 ***/
307418
419 // messaging menu
420 std::shared_ptr<MessagingMenuApp> m_messaging_app;
421 std::map<std::string, messaging_menu_data> m_messaging_messages;
422
308 const std::string m_app_name;423 const std::string m_app_name;
309424
310 // key-to-data425 // key-to-data
@@ -315,6 +430,8 @@
315 mutable std::set<std::string> m_lazy_caps;430 mutable std::set<std::string> m_lazy_caps;
316431
317 static constexpr char const * HINT_TIMEOUT {"x-canonical-snap-decisions-timeout"};432 static constexpr char const * HINT_TIMEOUT {"x-canonical-snap-decisions-timeout"};
433 static constexpr char const * DATETIME_INDICATOR_DESKTOP_FILE {"indicator-datetime.desktop"};
434 static constexpr char const * DATETIME_INDICATOR_SOURCE_ID {"indicator-datetime"};
318};435};
319436
320/***437/***
321438
=== modified file 'src/snap.cpp'
--- src/snap.cpp 2016-02-03 17:06:31 +0000
+++ src/snap.cpp 2016-04-19 13:10:52 +0000
@@ -102,7 +102,7 @@
102102
103 // calendar events are muted in silent mode; alarm clocks never are103 // calendar events are muted in silent mode; alarm clocks never are
104 std::shared_ptr<uin::Sound> sound;104 std::shared_ptr<uin::Sound> sound;
105 if (appointment.is_ubuntu_alarm() || !silent_mode()) {105 if (appointment.is_ubuntu_alarm() || (alarm.has_sound() && !silent_mode())) {
106 // create the sound.106 // create the sound.
107 const auto role = appointment.is_ubuntu_alarm() ? "alarm" : "alert";107 const auto role = appointment.is_ubuntu_alarm() ? "alarm" : "alert";
108 const auto uri = get_alarm_uri(appointment, alarm, m_settings);108 const auto uri = get_alarm_uri(appointment, alarm, m_settings);
@@ -123,8 +123,9 @@
123 const auto minutes = std::chrono::minutes(m_settings->alarm_duration.get());123 const auto minutes = std::chrono::minutes(m_settings->alarm_duration.get());
124 uin::Builder b;124 uin::Builder b;
125 b.set_body (appointment.summary);125 b.set_body (appointment.summary);
126 b.set_icon_name (appointment.is_ubuntu_alarm() ? "alarm-clock" : "reminder");126 b.set_icon_name (appointment.is_ubuntu_alarm() ? "alarm-clock" : "appointment");
127 b.add_hint (uin::Builder::HINT_NONSHAPED_ICON);127 b.add_hint (uin::Builder::HINT_NONSHAPED_ICON);
128 b.set_start_time (appointment.begin.to_unix());
128129
129 const char * timefmt;130 const char * timefmt;
130 if (is_locale_12h()) {131 if (is_locale_12h()) {
@@ -150,6 +151,9 @@
150 b.add_hint (uin::Builder::HINT_AFFIRMATIVE_HINT);151 b.add_hint (uin::Builder::HINT_AFFIRMATIVE_HINT);
151 b.add_action ("ok", _("OK"));152 b.add_action ("ok", _("OK"));
152 b.add_action ("snooze", _("Snooze"));153 b.add_action ("snooze", _("Snooze"));
154 } else {
155 b.add_hint (uin::Builder::HINT_INTERACTIVE);
156 b.add_action ("ok", _("OK"));
153 }157 }
154158
155 // add 'sound', 'haptic', and 'awake' objects to the capture so159 // add 'sound', 'haptic', and 'awake' objects to the capture so
@@ -159,10 +163,14 @@
159 (const std::string& action){163 (const std::string& action){
160 if (action == "snooze")164 if (action == "snooze")
161 snooze(appointment, alarm);165 snooze(appointment, alarm);
162 else166 else if (action == "ok")
163 ok(appointment, alarm);167 ok(appointment, alarm);
164 });168 });
165169
170 b.set_missed_click_callback([appointment, alarm, ok](){
171 ok(appointment, alarm);
172 });
173
166 const auto key = m_engine->show(b);174 const auto key = m_engine->show(b);
167 if (key)175 if (key)
168 m_notifications.insert (key);176 m_notifications.insert (key);
169177
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2016-03-22 18:51:50 +0000
+++ tests/CMakeLists.txt 2016-04-19 13:10:52 +0000
@@ -85,7 +85,8 @@
85 ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path85 ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
86 ${TEST_NAME} # arg3: test name86 ${TEST_NAME} # arg3: test name
87 ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg4: base directory for config file template87 ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg4: base directory for config file template
88 ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics) # arg5: the ical file for this test88 ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics # arg5: the ical file for this test
89 ${CMAKE_CURRENT_SOURCE_DIR}/accounts.db) # arg6: online accounts database
89endfunction()90endfunction()
90add_eds_ics_test_by_name(test-eds-ics-all-day-events)91add_eds_ics_test_by_name(test-eds-ics-all-day-events)
91add_eds_ics_test_by_name(test-eds-ics-repeating-events)92add_eds_ics_test_by_name(test-eds-ics-repeating-events)
@@ -95,6 +96,7 @@
95add_eds_ics_test_by_name(test-eds-ics-tzids)96add_eds_ics_test_by_name(test-eds-ics-tzids)
96add_eds_ics_test_by_name(test-eds-ics-tzids-2)97add_eds_ics_test_by_name(test-eds-ics-tzids-2)
97add_eds_ics_test_by_name(test-eds-ics-tzids-utc)98add_eds_ics_test_by_name(test-eds-ics-tzids-utc)
99add_eds_ics_test_by_name(test-eds-ics-non-attending-alarms)
98100
99101
100# disabling the timezone unit tests because they require102# disabling the timezone unit tests because they require
101103
=== added file 'tests/accounts.db'
102Binary files tests/accounts.db 1970-01-01 00:00:00 +0000 and tests/accounts.db 2016-04-19 13:10:52 +0000 differ104Binary files tests/accounts.db 1970-01-01 00:00:00 +0000 and tests/accounts.db 2016-04-19 13:10:52 +0000 differ
=== modified file 'tests/notification-fixture.h'
--- tests/notification-fixture.h 2016-02-10 20:48:24 +0000
+++ tests/notification-fixture.h 2016-04-19 13:10:52 +0000
@@ -53,7 +53,7 @@
53 static constexpr char const * HAPTIC_METHOD_VIBRATE_PATTERN {"VibratePattern"};53 static constexpr char const * HAPTIC_METHOD_VIBRATE_PATTERN {"VibratePattern"};
5454
55 static constexpr int SCREEN_COOKIE {8675309};55 static constexpr int SCREEN_COOKIE {8675309};
56 static constexpr char const * SCREEN_METHOD_KEEP_DISPLAY_ON {"keepDisplayOn"}; 56 static constexpr char const * SCREEN_METHOD_KEEP_DISPLAY_ON {"keepDisplayOn"};
57 static constexpr char const * SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST {"removeDisplayOnRequest"};57 static constexpr char const * SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST {"removeDisplayOnRequest"};
5858
59 static constexpr int POWERD_SYS_STATE_ACTIVE = 1;59 static constexpr int POWERD_SYS_STATE_ACTIVE = 1;
@@ -111,7 +111,7 @@
111 const auto christmas = unity::indicator::datetime::DateTime::Local(2015,12,25,0,0,0);111 const auto christmas = unity::indicator::datetime::DateTime::Local(2015,12,25,0,0,0);
112 appt.begin = christmas.start_of_day();112 appt.begin = christmas.start_of_day();
113 appt.end = christmas.end_of_day();113 appt.end = christmas.end_of_day();
114 appt.alarms.push_back(unity::indicator::datetime::Alarm{"Ho Ho Ho!", "", appt.begin});114 appt.alarms.push_back(unity::indicator::datetime::Alarm{"Ho Ho Ho!", CALENDAR_DEFAULT_SOUND, appt.begin});
115115
116 // init an Ubuntu Alarm116 // init an Ubuntu Alarm
117 ualarm.color = "red";117 ualarm.color = "red";
@@ -165,8 +165,8 @@
165 NOTIFY_INTERFACE,165 NOTIFY_INTERFACE,
166 &error);166 &error);
167 g_assert_no_error(error);167 g_assert_no_error(error);
168 168
169 // METHOD_GET_INFO 169 // METHOD_GET_INFO
170 str = g_strdup("ret = ('mock-notify', 'test vendor', '1.0', '1.1')");170 str = g_strdup("ret = ('mock-notify', 'test vendor', '1.0', '1.1')");
171 dbus_test_dbus_mock_object_add_method(notify_mock,171 dbus_test_dbus_mock_object_add_method(notify_mock,
172 notify_obj,172 notify_obj,
@@ -196,7 +196,7 @@
196 g_assert_no_error (error);196 g_assert_no_error (error);
197 g_free (str);197 g_free (str);
198198
199 // METHOD_CLOSE 199 // METHOD_CLOSE
200 str = g_strdup_printf("self.EmitSignal('%s', '%s', 'uu', [ args[0], %d ])",200 str = g_strdup_printf("self.EmitSignal('%s', '%s', 'uu', [ args[0], %d ])",
201 NOTIFY_INTERFACE,201 NOTIFY_INTERFACE,
202 SIGNAL_CLOSED,202 SIGNAL_CLOSED,
@@ -223,8 +223,8 @@
223 BUS_POWERD_INTERFACE,223 BUS_POWERD_INTERFACE,
224 &error);224 &error);
225 g_assert_no_error(error);225 g_assert_no_error(error);
226 226
227 str = g_strdup_printf ("ret = '%s'", POWERD_COOKIE); 227 str = g_strdup_printf ("ret = '%s'", POWERD_COOKIE);
228 dbus_test_dbus_mock_object_add_method(powerd_mock,228 dbus_test_dbus_mock_object_add_method(powerd_mock,
229 powerd_obj,229 powerd_obj,
230 POWERD_METHOD_REQUEST_SYS_STATE,230 POWERD_METHOD_REQUEST_SYS_STATE,
@@ -256,8 +256,8 @@
256 BUS_SCREEN_INTERFACE,256 BUS_SCREEN_INTERFACE,
257 &error);257 &error);
258 g_assert_no_error(error);258 g_assert_no_error(error);
259 259
260 str = g_strdup_printf ("ret = %d", SCREEN_COOKIE); 260 str = g_strdup_printf ("ret = %d", SCREEN_COOKIE);
261 dbus_test_dbus_mock_object_add_method(screen_mock,261 dbus_test_dbus_mock_object_add_method(screen_mock,
262 screen_obj,262 screen_obj,
263 SCREEN_METHOD_KEEP_DISPLAY_ON,263 SCREEN_METHOD_KEEP_DISPLAY_ON,
@@ -287,7 +287,7 @@
287 BUS_HAPTIC_PATH,287 BUS_HAPTIC_PATH,
288 BUS_HAPTIC_INTERFACE,288 BUS_HAPTIC_INTERFACE,
289 &error);289 &error);
290 290
291 dbus_test_dbus_mock_object_add_method(haptic_mock,291 dbus_test_dbus_mock_object_add_method(haptic_mock,
292 haptic_obj,292 haptic_obj,
293 HAPTIC_METHOD_VIBRATE_PATTERN,293 HAPTIC_METHOD_VIBRATE_PATTERN,
294294
=== modified file 'tests/run-eds-ics-test.sh'
--- tests/run-eds-ics-test.sh 2015-07-20 16:31:28 +0000
+++ tests/run-eds-ics-test.sh 2016-04-19 13:10:52 +0000
@@ -6,6 +6,7 @@
6TEST_NAME=$3 # test name6TEST_NAME=$3 # test name
7CONFIG_DIR=$4 # config files7CONFIG_DIR=$4 # config files
8ICS_FILE=$5 # ical file holding test data8ICS_FILE=$5 # ical file holding test data
9ACCOUNTS_DB=$6 # online account database
910
10echo "this script: ${SELF}"11echo "this script: ${SELF}"
11echo "test-runner: ${TEST_RUNNER}"12echo "test-runner: ${TEST_RUNNER}"
@@ -54,8 +55,15 @@
54 cp --verbose --archive ${ICS_FILE} ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics55 cp --verbose --archive ${ICS_FILE} ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics
55fi56fi
5657
58# prepare online accounts database
59if [ -e ${ACCOUNTS_DB} ]; then
60 echo "copying ${ACCOUNTS_DB} into $HOME"
61 mkdir -p ${XDG_CONFIG_HOME}/libaccounts-glib/
62 cp --verbose --archive ${ACCOUNTS_DB} ${XDG_CONFIG_HOME}/libaccounts-glib/accounts.db
63fi
64
57# run the test65# run the test
58${TEST_RUNNER} --keep-env --max-wait=90 --task ${TEST_EXEC} --task-name ${TEST_NAME} --wait-until-complete 66${TEST_RUNNER} --keep-env --max-wait=90 --task ${TEST_EXEC} --task-name ${TEST_NAME} --wait-until-complete
59rv=$?67rv=$?
6068
61# if the test passed, blow away the tmpdir69# if the test passed, blow away the tmpdir
6270
=== modified file 'tests/test-eds-ics-all-day-events.cpp'
--- tests/test-eds-ics-all-day-events.cpp 2015-05-21 12:47:24 +0000
+++ tests/test-eds-ics-all-day-events.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MultipleAppointments)42TEST_F(VAlarmFixture, MultipleAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Chicago"};48 constexpr char const * zone_str {"America/Chicago"};
@@ -66,7 +67,7 @@
66 constexpr int max_wait_sec = 10;67 constexpr int max_wait_sec = 10;
67 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);68 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
68 }69 }
69 70
70 // what we expect to get...71 // what we expect to get...
71 Appointment expected_appt;72 Appointment expected_appt;
72 expected_appt.uid = "20150521T111538Z-7449-1000-3572-0@ghidorah";73 expected_appt.uid = "20150521T111538Z-7449-1000-3572-0@ghidorah";
7374
=== modified file 'tests/test-eds-ics-missing-trigger.cpp'
--- tests/test-eds-ics-missing-trigger.cpp 2015-10-13 14:40:02 +0000
+++ tests/test-eds-ics-missing-trigger.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MissingTriggers)42TEST_F(VAlarmFixture, MissingTriggers)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Chicago"};48 constexpr char const * zone_str {"America/Chicago"};
4849
=== added file 'tests/test-eds-ics-non-attending-alarms.cpp'
--- tests/test-eds-ics-non-attending-alarms.cpp 1970-01-01 00:00:00 +0000
+++ tests/test-eds-ics-non-attending-alarms.cpp 2016-04-19 13:10:52 +0000
@@ -0,0 +1,79 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <algorithm>
21
22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
26#include <datetime/planner-range.h>
27
28#include <gtest/gtest.h>
29
30#include "glib-fixture.h"
31#include "print-to.h"
32#include "timezone-mock.h"
33#include "wakeup-timer-mock.h"
34
35using namespace unity::indicator::datetime;
36using VAlarmFixture = GlibFixture;
37
38/***
39****
40***/
41
42TEST_F(VAlarmFixture, NonAttendingEvent)
43{
44 // start the EDS engine
45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
46
47 // we need a consistent timezone for the planner and our local DateTimes
48 constexpr char const * zone_str {"America/Recife"};
49 auto tz = std::make_shared<MockTimezone>(zone_str);
50 auto gtz = g_time_zone_new(zone_str);
51
52 // make a planner that looks at the first half of 2016 in EDS
53 auto planner = std::make_shared<SimpleRangePlanner>(engine, tz);
54 const DateTime range_begin {gtz, 2016,1, 1, 0, 0, 0.0};
55 const DateTime range_end {gtz, 2016,6,31,23,59,59.5};
56 planner->range().set(std::make_pair(range_begin, range_end));
57
58 // give EDS a moment to load
59 if (planner->appointments().get().empty()) {
60 g_message("waiting a moment for EDS to load...");
61 auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){
62 g_message("ah, they loaded");
63 if (!appointments.empty())
64 g_main_loop_quit(loop);
65 };
66 core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed));
67 constexpr int max_wait_sec = 10;
68 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
69 }
70
71 // the planner should match what we've got in the calendar.ics file
72 const auto appts = planner->appointments().get();
73 EXPECT_EQ(2, appts.size());
74 EXPECT_EQ(appts[0].begin, DateTime(gtz, 2016, 4, 4, 16, 0, 0));
75 EXPECT_EQ(appts[1].begin, DateTime(gtz, 2016, 4, 6, 16, 0, 0));
76
77 // cleanup
78 g_time_zone_unref(gtz);
79}
080
=== added file 'tests/test-eds-ics-non-attending-alarms.ics.in'
--- tests/test-eds-ics-non-attending-alarms.ics.in 1970-01-01 00:00:00 +0000
+++ tests/test-eds-ics-non-attending-alarms.ics.in 2016-04-19 13:10:52 +0000
@@ -0,0 +1,53 @@
1BEGIN:VCALENDAR
2CALSCALE:GREGORIAN
3PRODID:-//Ximian//NONSGML Evolution Calendar//EN
4VERSION:2.0
5X-EVOLUTION-DATA-REVISION:2015-04-05T21:32:47.354433Z(2)
6BEGIN:VEVENT
7STATUS:CONFIRMED
8DTSTAMP:20160405T152128Z
9CREATED:20160405T152128Z
10UID:ddtvl069dn2cquo8dhg3j9c360@google.com
11SEQUENCE:1
12TRANSP:OPAQUE
13SUMMARY:Every day at 4PM
14DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/America/Recife:
15 20160404T160000
16RRULE:FREQ=DAILY;UNTIL=20160406T190000Z
17DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/America/Recife:
18 20160404T170000
19ATTENDEE;CN=Uphablet;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;
20 CUTYPE=INDIVIDUAL:mailto:uphablet@ubuntu.com
21LAST-MODIFIED:20160405T152128Z
22BEGIN:VALARM
23TRIGGER;VALUE=DURATION:-PT30M
24ACTION:EMAIL
25DESCRIPTION:This is an event reminder
26X-EVOLUTION-ALARM-UID:20160405T152128Z-2848-32011-1844-65@ubuntu-phablet
27END:VALARM
28END:VEVENT
29BEGIN:VEVENT
30STATUS:CONFIRMED
31DTSTAMP:20160405T152128Z
32CREATED:20160405T151054Z
33UID:ddtvl069dn2cquo8dhg3j9c360@google.com
34SEQUENCE:1
35TRANSP:OPAQUE
36SUMMARY::Every day at 4PM
37DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/America/Fortaleza:
38 20160405T160000
39RECURRENCE-ID;TZID=/freeassociation.sourceforge.net/Tzfile/America/Recife:
40 20160405T160000
41DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/America/Fortaleza:
42 20160405T170000
43ATTENDEE;CN=Uphablet;PARTSTAT=DECLINED;ROLE=REQ-PARTICIPANT;
44 CUTYPE=INDIVIDUAL:mailto:uphablet@ubuntu.com
45LAST-MODIFIED:20160405T152128Z
46BEGIN:VALARM
47TRIGGER;VALUE=DURATION:-PT30M
48ACTION:EMAIL
49DESCRIPTION:This is an event reminder
50X-EVOLUTION-ALARM-UID:20160405T152128Z-2848-32011-1844-66@ubuntu-phablet
51END:VALARM
52END:VEVENT
53END:VCALENDAR
054
=== modified file 'tests/test-eds-ics-nonrepeating-events.cpp'
--- tests/test-eds-ics-nonrepeating-events.cpp 2015-10-13 14:40:02 +0000
+++ tests/test-eds-ics-nonrepeating-events.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MultipleAppointments)42TEST_F(VAlarmFixture, MultipleAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Chicago"};48 constexpr char const * zone_str {"America/Chicago"};
@@ -66,7 +67,7 @@
66 constexpr int max_wait_sec = 10;67 constexpr int max_wait_sec = 10;
67 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);68 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
68 }69 }
69 70
70 // what we expect to get...71 // what we expect to get...
71 Appointment expected_appt;72 Appointment expected_appt;
72 expected_appt.uid = "20150520T000726Z-3878-32011-1770-81@ubuntu-phablet";73 expected_appt.uid = "20150520T000726Z-3878-32011-1770-81@ubuntu-phablet";
7374
=== modified file 'tests/test-eds-ics-repeating-events.cpp'
--- tests/test-eds-ics-repeating-events.cpp 2015-10-13 14:40:02 +0000
+++ tests/test-eds-ics-repeating-events.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MultipleAppointments)42TEST_F(VAlarmFixture, MultipleAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Chicago"};48 constexpr char const * zone_str {"America/Chicago"};
@@ -66,7 +67,7 @@
66 constexpr int max_wait_sec = 10;67 constexpr int max_wait_sec = 10;
67 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);68 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
68 }69 }
69 70
70 // what we expect to get...71 // what we expect to get...
71 Appointment expected_appt;72 Appointment expected_appt;
72 expected_appt.uid = "20150507T211449Z-4262-32011-1418-1@ubuntu-phablet";73 expected_appt.uid = "20150507T211449Z-4262-32011-1418-1@ubuntu-phablet";
7374
=== modified file 'tests/test-eds-ics-repeating-valarms.cpp'
--- tests/test-eds-ics-repeating-valarms.cpp 2015-05-20 23:23:32 +0000
+++ tests/test-eds-ics-repeating-valarms.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MultipleAppointments)42TEST_F(VAlarmFixture, MultipleAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Chicago"};48 constexpr char const * zone_str {"America/Chicago"};
@@ -72,14 +73,14 @@
72 ASSERT_EQ(1, appts.size());73 ASSERT_EQ(1, appts.size());
73 const auto& appt = appts.front();74 const auto& appt = appts.front();
74 ASSERT_EQ(8, appt.alarms.size());75 ASSERT_EQ(8, appt.alarms.size());
75 EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,35,0)}), appt.alarms[0]);76 EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,35,0)}), appt.alarms[0]);
76 EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,37,0)}), appt.alarms[1]);77 EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,37,0)}), appt.alarms[1]);
77 EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,39,0)}), appt.alarms[2]);78 EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,39,0)}), appt.alarms[2]);
78 EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,41,0)}), appt.alarms[3]);79 EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,41,0)}), appt.alarms[3]);
79 EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,35,0)}), appt.alarms[4]);80 EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,35,0)}), appt.alarms[4]);
80 EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,37,0)}), appt.alarms[5]);81 EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,37,0)}), appt.alarms[5]);
81 EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,39,0)}), appt.alarms[6]);82 EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,39,0)}), appt.alarms[6]);
82 EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,41,0)}), appt.alarms[7]);83 EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,41,0)}), appt.alarms[7]);
8384
84 // now let's try this out with AlarmQueue...85 // now let's try this out with AlarmQueue...
85 // hook the planner up to a SimpleAlarmQueue and confirm that it triggers for each of the reminders86 // hook the planner up to a SimpleAlarmQueue and confirm that it triggers for each of the reminders
8687
=== modified file 'tests/test-eds-ics-tzids-2.cpp'
--- tests/test-eds-ics-tzids-2.cpp 2015-07-09 20:56:13 +0000
+++ tests/test-eds-ics-tzids-2.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MultipleAppointments)42TEST_F(VAlarmFixture, MultipleAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Los_Angeles"};48 constexpr char const * zone_str {"America/Los_Angeles"};
4849
=== modified file 'tests/test-eds-ics-tzids-utc.cpp'
--- tests/test-eds-ics-tzids-utc.cpp 2016-03-22 19:13:10 +0000
+++ tests/test-eds-ics-tzids-utc.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, UTCAppointments)42TEST_F(VAlarmFixture, UTCAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"America/Recife"};48 constexpr char const * zone_str {"America/Recife"};
4849
=== modified file 'tests/test-eds-ics-tzids.cpp'
--- tests/test-eds-ics-tzids.cpp 2015-07-09 19:14:32 +0000
+++ tests/test-eds-ics-tzids.cpp 2016-04-19 13:10:52 +0000
@@ -22,6 +22,7 @@
22#include <datetime/alarm-queue-simple.h>22#include <datetime/alarm-queue-simple.h>
23#include <datetime/clock-mock.h>23#include <datetime/clock-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/myself.h>
25#include <datetime/planner-range.h>26#include <datetime/planner-range.h>
2627
27#include <gtest/gtest.h>28#include <gtest/gtest.h>
@@ -41,7 +42,7 @@
41TEST_F(VAlarmFixture, MultipleAppointments)42TEST_F(VAlarmFixture, MultipleAppointments)
42{43{
43 // start the EDS engine44 // start the EDS engine
44 auto engine = std::make_shared<EdsEngine>();45 auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
4546
46 // we need a consistent timezone for the planner and our local DateTimes47 // we need a consistent timezone for the planner and our local DateTimes
47 constexpr char const * zone_str {"Europe/Berlin"};48 constexpr char const * zone_str {"Europe/Berlin"};
4849
=== modified file 'tests/test-notification.cpp'
--- tests/test-notification.cpp 2016-02-11 04:30:46 +0000
+++ tests/test-notification.cpp 2016-04-19 13:10:52 +0000
@@ -63,7 +63,7 @@
63 bool expected_notify_called;63 bool expected_notify_called;
64 bool expected_vibrate_called;64 bool expected_vibrate_called;
65 } test_appts[] = {65 } test_appts[] = {
66 { appt, "reminder", "Event", true, true },66 { appt, "appointment", "Event", true, true },
67 { ualarm, "alarm-clock", "Alarm", true, true }67 { ualarm, "alarm-clock", "Alarm", true, true }
68 };68 };
6969
7070
=== modified file 'tests/test-sound.cpp'
--- tests/test-sound.cpp 2016-02-10 20:49:01 +0000
+++ tests/test-sound.cpp 2016-04-19 13:10:52 +0000
@@ -85,7 +85,7 @@
8585
86 // confirm that the icon passed to Notify was "alarm-clock"86 // confirm that the icon passed to Notify was "alarm-clock"
87 g_variant_get_child (params, 2, "&s", &str);87 g_variant_get_child (params, 2, "&s", &str);
88 ASSERT_STREQ("reminder", str);88 ASSERT_STREQ("appointment", str);
8989
90 // confirm that the hints passed to Notify included a timeout matching duration_minutes90 // confirm that the hints passed to Notify included a timeout matching duration_minutes
91 int32_t i32;91 int32_t i32;

Subscribers

People subscribed via source and target branches