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

Proposed by Renato Araujo Oliveira Filho on 2016-04-19
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 2016-04-19 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 on 2016-04-19

Fixed crash when clicking on messaging menu.

464. By Renato Araujo Oliveira Filho on 2016-04-20

Fix memory leak on messaging_menu.

465. By Renato Araujo Oliveira Filho on 2016-04-20

Vibrate only once when notification about calendar events.

466. By Renato Araujo Oliveira Filho on 2016-04-26

Fixed as reviewer requested.

467. By Renato Araujo Oliveira Filho on 2016-04-26

Make use of G_USEC_PER_SEC.

468. By Renato Araujo Oliveira Filho on 2016-04-27

Update notifications to use the new calendar icon.

469. By Renato Araujo Oliveira Filho on 2016-04-27

Use calendar app icon.

470. By Renato Araujo Oliveira Filho on 2016-04-27

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

471. By Renato Araujo Oliveira Filho on 2016-04-28

Small fixes requeted by charles during the review.

472. By Renato Araujo Oliveira Filho on 2016-04-28

Detect desktop to launch applications.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-02-03 16:33:39 +0000
3+++ CMakeLists.txt 2016-04-19 13:10:52 +0000
4@@ -20,7 +20,7 @@
5
6 ##
7 ## GNU standard installation directories
8-##
9+##
10
11 include (GNUInstallDirs)
12 if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian
13@@ -47,7 +47,10 @@
14 gstreamer-1.0>=1.2
15 libnotify>=0.7.6
16 url-dispatcher-1>=1
17- properties-cpp>=0.0.1)
18+ properties-cpp>=0.0.1
19+ libaccounts-glib>=1.18
20+ messaging-menu>=12.10
21+ uuid>=2.25)
22 include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
23
24 ##
25
26=== modified file 'data/CMakeLists.txt'
27--- data/CMakeLists.txt 2015-10-13 15:06:25 +0000
28+++ data/CMakeLists.txt 2016-04-19 13:10:52 +0000
29@@ -30,6 +30,7 @@
30
31 # build it
32 set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
33+set (messaging_menu_icon "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/suru/actions/scalable/appointment.svg")
34 configure_file ("${UPSTART_JOB_FILE_IN}" "${UPSTART_JOB_FILE}")
35
36 # install it
37@@ -52,7 +53,11 @@
38 set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
39 configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}")
40
41-# install it
42+# install desktop file used by messaging-menu
43+install (FILES "${XDG_AUTOSTART_FILE}"
44+ DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/")
45+
46+# install XDG autostart
47 install (FILES "${XDG_AUTOSTART_FILE}"
48 DESTINATION "${XDG_AUTOSTART_DIR}")
49
50
51=== modified file 'data/indicator-datetime.desktop.in'
52--- data/indicator-datetime.desktop.in 2014-04-04 13:05:59 +0000
53+++ data/indicator-datetime.desktop.in 2016-04-19 13:10:52 +0000
54@@ -7,3 +7,4 @@
55 StartupNotify=false
56 Terminal=false
57 AutostartCondition=GNOME3 unless-session gnome
58+Icon=@messaging_menu_icon@
59
60=== modified file 'debian/control'
61--- debian/control 2016-03-10 16:20:36 +0000
62+++ debian/control 2016-04-19 13:10:52 +0000
63@@ -29,6 +29,11 @@
64 gvfs-daemons,
65 # for phone alarm/calendar notification sound tests:
66 ubuntu-touch-sounds,
67+# for query user e-mails based on accounts
68+ libaccounts-glib-dev,
69+# messaging menu integration
70+ libmessaging-menu-dev,
71+ uuid-dev,
72 Standards-Version: 3.9.3
73 Homepage: https://launchpad.net/indicator-datetime
74 # If you aren't a member of ~indicator-applet-developers but need to upload
75
76=== modified file 'include/datetime/appointment.h'
77--- include/datetime/appointment.h 2016-03-16 14:42:06 +0000
78+++ include/datetime/appointment.h 2016-04-19 13:10:52 +0000
79@@ -39,6 +39,8 @@
80 DateTime time;
81
82 bool operator== (const Alarm& that) const;
83+ bool has_sound() const;
84+ bool has_text() const;
85 };
86
87 /**
88
89=== modified file 'include/datetime/engine-eds.h'
90--- include/datetime/engine-eds.h 2014-12-08 02:52:50 +0000
91+++ include/datetime/engine-eds.h 2016-04-19 13:10:52 +0000
92@@ -36,16 +36,17 @@
93 /****
94 *****
95 ****/
96+class Myself;
97
98 /**
99 * Class wrapper around EDS so multiple #EdsPlanners can share resources
100- *
101+ *
102 * @see EdsPlanner
103 */
104 class EdsEngine: public Engine
105 {
106 public:
107- EdsEngine();
108+ EdsEngine(const std::shared_ptr<Myself> &myself);
109 ~EdsEngine();
110
111 void get_appointments(const DateTime& begin,
112
113=== added file 'include/datetime/myself.h'
114--- include/datetime/myself.h 1970-01-01 00:00:00 +0000
115+++ include/datetime/myself.h 2016-04-19 13:10:52 +0000
116@@ -0,0 +1,62 @@
117+/*
118+ * Copyright 2016 Canonical Ltd.
119+ *
120+ * This program is free software: you can redistribute it and/or modify it
121+ * under the terms of the GNU General Public License version 3, as published
122+ * by the Free Software Foundation.
123+ *
124+ * This program is distributed in the hope that it will be useful, but
125+ * WITHOUT ANY WARRANTY; without even the implied warranties of
126+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
127+ * PURPOSE. See the GNU General Public License for more details.
128+ *
129+ * You should have received a copy of the GNU General Public License along
130+ * with this program. If not, see <http://www.gnu.org/licenses/>.
131+ *
132+ * Authors:
133+ * Renato Araujo Oliveira Filho <renato.filho@canonical.com>
134+ */
135+
136+#ifndef INDICATOR_DATETIME_MYSELF_H
137+#define INDICATOR_DATETIME_MYSELF_H
138+
139+#include <core/property.h>
140+
141+#include <string>
142+#include <set>
143+#include <memory.h>
144+#include <glib.h>
145+
146+typedef struct _AgManager AgManager;
147+
148+namespace unity {
149+namespace indicator {
150+namespace datetime {
151+
152+class Myself
153+{
154+public:
155+ Myself();
156+
157+ const core::Property<std::set<std::string>>& emails()
158+ {
159+ return m_emails;
160+ }
161+
162+ bool isMyEmail(const std::string &email);
163+
164+private:
165+ std::shared_ptr<AgManager> m_accounts_manager;
166+ core::Property<std::set<std::string> > m_emails;
167+
168+ static void on_accounts_changed(AgManager*, guint, Myself*);
169+ void reloadEmails();
170+
171+};
172+
173+
174+} // namespace datetime
175+} // namespace indicator
176+} // namespace unity
177+
178+#endif // INDICATOR_DATETIME_MYSELF_H
179
180=== modified file 'include/notifications/notifications.h'
181--- include/notifications/notifications.h 2014-09-19 14:35:07 +0000
182+++ include/notifications/notifications.h 2016-04-19 13:10:52 +0000
183@@ -50,6 +50,8 @@
184
185 void set_icon_name (const std::string& icon_name);
186
187+ void set_start_time(uint64_t time);
188+
189 /* Set an interval, after which the notification will automatically
190 be closed. If not set, the notification server's default timeout
191 is used. */
192@@ -62,19 +64,24 @@
193 static constexpr char const * HINT_NONSHAPED_ICON {"x-canonical-non-shaped-icon"};
194 static constexpr char const * HINT_AFFIRMATIVE_HINT {"x-canonical-private-affirmative-tint"};
195 static constexpr char const * HINT_REJECTION_TINT {"x-canonical-private-rejection-tint"};
196+ static constexpr char const * HINT_INTERACTIVE {"x-canonical-switch-to-application"};
197
198 /* Add an action button.
199 This may fail if the Engine doesn't support actions.
200 @see Engine::supports_actions() */
201 void add_action (const std::string& action, const std::string& label);
202
203- /** Sets the closed callback. This will be called exactly once. */
204+ /** Sets the closed callback. This will be called exactly once. After notification dissapear */
205 void set_closed_callback (std::function<void(const std::string& action)>);
206
207+ /** Sets the time-out callback. This will be called exactly once. */
208+ void set_missed_click_callback (std::function<void()>);
209+
210+
211 private:
212 friend class Engine;
213 class Impl;
214- std::unique_ptr<Impl> impl;
215+ std::shared_ptr<Impl> impl;
216 };
217
218 /**
219
220=== modified file 'src/CMakeLists.txt'
221--- src/CMakeLists.txt 2015-09-01 09:52:13 +0000
222+++ src/CMakeLists.txt 2016-04-19 13:10:52 +0000
223@@ -23,6 +23,7 @@
224 locations.cpp
225 locations-settings.cpp
226 menu.cpp
227+ myself.cpp
228 notifications.cpp
229 planner.cpp
230 planner-aggregate.cpp
231
232=== modified file 'src/appointment.cpp'
233--- src/appointment.cpp 2015-04-05 22:27:52 +0000
234+++ src/appointment.cpp 2016-04-19 13:10:52 +0000
235@@ -31,7 +31,17 @@
236 {
237 return (text==that.text)
238 && (audio_url==that.audio_url)
239- && (this->time==that.time);
240+ && (this->time==that.time);
241+}
242+
243+bool Alarm::has_sound() const
244+{
245+ return !audio_url.empty();
246+}
247+
248+bool Alarm::has_text() const
249+{
250+ return !text.empty();
251 }
252
253 bool Appointment::operator==(const Appointment& that) const
254
255=== modified file 'src/engine-eds.cpp'
256--- src/engine-eds.cpp 2016-03-22 19:32:25 +0000
257+++ src/engine-eds.cpp 2016-04-19 13:10:52 +0000
258@@ -18,6 +18,7 @@
259 */
260
261 #include <datetime/engine-eds.h>
262+#include <datetime/myself.h>
263
264 #include <libical/ical.h>
265 #include <libical/icaltime.h>
266@@ -48,7 +49,8 @@
267 {
268 public:
269
270- Impl()
271+ Impl(const std::shared_ptr<Myself> &myself)
272+ : m_myself(myself)
273 {
274 auto cancellable_deleter = [](GCancellable * c) {
275 g_cancellable_cancel(c);
276@@ -56,8 +58,10 @@
277 };
278
279 m_cancellable = std::shared_ptr<GCancellable>(g_cancellable_new(), cancellable_deleter);
280-
281 e_source_registry_new(m_cancellable.get(), on_source_registry_ready, this);
282+ m_myself->emails().changed().connect([this](const std::set<std::string> &) {
283+ set_dirty_soon();
284+ });
285 }
286
287 ~Impl()
288@@ -92,26 +96,19 @@
289 /**
290 *** init the default timezone
291 **/
292-
293 icaltimezone * default_timezone = nullptr;
294 const auto tz = timezone.timezone.get().c_str();
295- if (tz && *tz)
296- {
297- default_timezone = icaltimezone_get_builtin_timezone(tz);
298-
299- if (default_timezone == nullptr) // maybe str is a tzid?
300- default_timezone = icaltimezone_get_builtin_timezone_from_tzid(tz);
301-
302- g_debug("default_timezone is %p", (void*)default_timezone);
303+ auto gtz = timezone_from_name(tz, nullptr, nullptr, &default_timezone);
304+ if (gtz == nullptr) {
305+ gtz = g_time_zone_new_local();
306 }
307
308+ g_debug("default_timezone is %s", default_timezone ? icaltimezone_get_display_name(default_timezone) : "null");
309+
310 /**
311 *** walk through the sources to build the appointment list
312 **/
313
314- auto gtz = default_timezone != nullptr
315- ? g_time_zone_new(icaltimezone_get_location(default_timezone))
316- : g_time_zone_new_local();
317 auto main_task = std::make_shared<Task>(this, func, default_timezone, gtz, begin, end);
318
319 for (auto& kv : m_clients)
320@@ -125,35 +122,14 @@
321 auto extension = e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR);
322 const auto color = e_source_selectable_get_color(E_SOURCE_SELECTABLE(extension));
323
324- auto begin_str = isodate_from_time_t(begin.to_unix());
325- auto end_str = isodate_from_time_t(end.to_unix());
326- auto sexp_fmt = g_strdup_printf("(%%s? (make-time \"%s\") (make-time \"%s\"))", begin_str, end_str);
327- g_clear_pointer(&begin_str, g_free);
328- g_clear_pointer(&end_str, g_free);
329-
330- // ask EDS about alarms that occur in this window...
331- auto sexp = g_strdup_printf(sexp_fmt, "has-alarms-in-range");
332- g_debug("%s alarm sexp is %s", G_STRLOC, sexp);
333- e_cal_client_get_object_list_as_comps(
334- client,
335- sexp,
336- m_cancellable.get(),
337- on_alarm_component_list_ready,
338- new ClientSubtask(main_task, client, m_cancellable, color));
339- g_clear_pointer(&sexp, g_free);
340-
341- // ask EDS about events that occur in this window...
342- sexp = g_strdup_printf(sexp_fmt, "occur-in-time-range");
343- g_debug("%s event sexp is %s", G_STRLOC, sexp);
344- e_cal_client_get_object_list_as_comps(
345- client,
346- sexp,
347- m_cancellable.get(),
348- on_event_component_list_ready,
349- new ClientSubtask(main_task, client, m_cancellable, color));
350- g_clear_pointer(&sexp, g_free);
351-
352- g_clear_pointer(&sexp_fmt, g_free);
353+ e_cal_client_generate_instances(
354+ client,
355+ begin.to_unix(),
356+ end.to_unix(),
357+ m_cancellable.get(),
358+ on_event_generated,
359+ new ClientSubtask(main_task, client, m_cancellable, color),
360+ on_event_generated_list_ready);
361 }
362 }
363
364@@ -591,6 +567,8 @@
365 ECalClient* client;
366 std::shared_ptr<GCancellable> cancellable;
367 std::string color;
368+ GList *components;
369+ GList *instance_components;
370
371 ClientSubtask(const std::shared_ptr<Task>& task_in,
372 ECalClient* client_in,
373@@ -598,10 +576,13 @@
374 const char* color_in):
375 task(task_in),
376 client(client_in),
377- cancellable(cancellable_in)
378+ cancellable(cancellable_in),
379+ components(nullptr),
380+ instance_components(nullptr)
381 {
382 if (color_in)
383 color = color_in;
384+
385 }
386 };
387
388@@ -622,7 +603,7 @@
389 return ret;
390 }
391
392- static std::string get_alarm_sound_url(ECalComponentAlarm * alarm)
393+ static std::string get_alarm_sound_url(ECalComponentAlarm * alarm, const std::string & default_sound)
394 {
395 std::string ret;
396
397@@ -643,92 +624,129 @@
398
399 icalattach_unref(attach);
400 }
401+ if (ret.empty())
402+ ret = default_sound;
403 }
404
405 return ret;
406 }
407
408- static void
409- on_alarm_component_list_ready(GObject * oclient,
410- GAsyncResult * res,
411- gpointer gsubtask)
412- {
413- GError * error = NULL;
414- GSList * comps_slist = NULL;
415- auto subtask = static_cast<ClientSubtask*>(gsubtask);
416-
417- if (e_cal_client_get_object_list_as_comps_finish(E_CAL_CLIENT(oclient),
418- res,
419- &comps_slist,
420- &error))
421- {
422- // _generate_alarms takes a GList, so make a shallow one
423- GList * comps_list = nullptr;
424- for (auto l=comps_slist; l!=nullptr; l=l->next)
425- comps_list = g_list_prepend(comps_list, l->data);
426-
427- constexpr std::array<ECalComponentAlarmAction,1> omit = {
428- (ECalComponentAlarmAction)-1
429- }; // list of action types to omit, terminated with -1
430- GSList * comp_alarms = nullptr;
431- e_cal_util_generate_alarms_for_list(
432- comps_list,
433- subtask->task->begin.to_unix(),
434- subtask->task->end.to_unix(),
435- const_cast<ECalComponentAlarmAction*>(omit.data()),
436- &comp_alarms,
437- e_cal_client_resolve_tzid_cb,
438- oclient,
439- subtask->task->default_timezone);
440-
441- // walk the alarms & add them
442- for (auto l=comp_alarms; l!=nullptr; l=l->next)
443- add_alarms_to_subtask(static_cast<ECalComponentAlarms*>(l->data), subtask, subtask->task->gtz);
444-
445- // cleanup
446- e_cal_free_alarms(comp_alarms);
447- g_list_free(comps_list);
448- e_cal_client_free_ecalcomp_slist(comps_slist);
449- }
450- else if (error != nullptr)
451- {
452- if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
453- g_warning("can't get ecalcomponent list: %s", error->message);
454-
455- g_error_free(error);
456- }
457-
458- delete subtask;
459- }
460-
461- static void
462- on_event_component_list_ready(GObject * oclient,
463- GAsyncResult * res,
464- gpointer gsubtask)
465- {
466- GError * error = NULL;
467- GSList * comps_slist = NULL;
468- auto subtask = static_cast<ClientSubtask*>(gsubtask);
469-
470- if (e_cal_client_get_object_list_as_comps_finish(E_CAL_CLIENT(oclient),
471- res,
472- &comps_slist,
473- &error))
474- {
475- for (auto l=comps_slist; l!=nullptr; l=l->next)
476- add_event_to_subtask(static_cast<ECalComponent*>(l->data), subtask, subtask->task->gtz);
477-
478- e_cal_client_free_ecalcomp_slist(comps_slist);
479- }
480- else if (error != nullptr)
481- {
482- if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
483- g_warning("can't get ecalcomponent list: %s", error->message);
484-
485- g_error_free(error);
486- }
487-
488- delete subtask;
489+ static gboolean
490+ on_event_generated(ECalComponent *comp,
491+ time_t,
492+ time_t,
493+ gpointer gsubtask)
494+ {
495+ auto subtask = static_cast<ClientSubtask*>(gsubtask);
496+ const gchar *uid = nullptr;
497+ e_cal_component_get_uid (comp, &uid);
498+ g_object_ref(comp);
499+ if (e_cal_component_is_instance(comp))
500+ subtask->instance_components = g_list_append(subtask->instance_components, comp);
501+ else
502+ subtask->components = g_list_append(subtask->components, comp);
503+ return TRUE;
504+ }
505+
506+ static void
507+ on_event_generated_list_ready(gpointer gsubtask)
508+ {
509+ auto subtask = static_cast<ClientSubtask*>(gsubtask);
510+
511+ // generate alarms
512+ constexpr std::array<ECalComponentAlarmAction,1> omit = {
513+ (ECalComponentAlarmAction)-1
514+ }; // list of action types to omit, terminated with -1
515+ GSList * comp_alarms = nullptr;
516+
517+ // we do not need translate tz for instance events,
518+ // they are aredy in the correct time
519+ e_cal_util_generate_alarms_for_list(
520+ subtask->instance_components,
521+ subtask->task->begin.to_unix(),
522+ subtask->task->end.to_unix(),
523+ const_cast<ECalComponentAlarmAction*>(omit.data()),
524+ &comp_alarms,
525+ e_cal_client_resolve_tzid_cb,
526+ subtask->client,
527+ nullptr);
528+
529+ // convert timezone for non-instance events
530+ e_cal_util_generate_alarms_for_list(
531+ subtask->components,
532+ subtask->task->begin.to_unix(),
533+ subtask->task->end.to_unix(),
534+ const_cast<ECalComponentAlarmAction*>(omit.data()),
535+ &comp_alarms,
536+ e_cal_client_resolve_tzid_cb,
537+ subtask->client,
538+ subtask->task->default_timezone);
539+
540+ // walk the alarms & add them
541+ for (auto l=comp_alarms; l!=nullptr; l=l->next)
542+ add_alarms_to_subtask(static_cast<ECalComponentAlarms*>(l->data), subtask, subtask->task->gtz);
543+
544+ subtask->components = g_list_concat(subtask->components, subtask->instance_components);
545+ // add events without alarm
546+ for (auto l=subtask->components; l!=nullptr; l=l->next) {
547+ auto component = static_cast<ECalComponent*>(l->data);
548+ if (!e_cal_component_has_alarms(component))
549+ add_event_to_subtask(component, subtask, subtask->task->gtz);
550+ }
551+ g_list_free_full(subtask->components, g_object_unref);
552+ e_cal_free_alarms(comp_alarms);
553+ delete subtask;
554+ }
555+
556+ static GTimeZone *
557+ timezone_from_name (const char * tzid,
558+ ECalClient * client,
559+ GCancellable * cancellable,
560+ icaltimezone **itimezone)
561+ {
562+ if (tzid == nullptr)
563+ return nullptr;
564+
565+ auto itz = icaltimezone_get_builtin_timezone_from_tzid(tzid); // usually works
566+
567+ if (itz == nullptr) // fallback
568+ itz = icaltimezone_get_builtin_timezone(tzid);
569+
570+ if (client && (itz == nullptr)) // ok we have a strange tzid... ask EDS to look it up in VTIMEZONES
571+ e_cal_client_get_timezone_sync(client, tzid, &itz, cancellable, nullptr);
572+
573+ const char* identifier {};
574+ if (itimezone)
575+ *itimezone = itz;
576+
577+ if (itz != nullptr)
578+ {
579+ identifier = icaltimezone_get_display_name(itz);
580+
581+ if (identifier == nullptr)
582+ identifier = icaltimezone_get_location(itz);
583+ }
584+
585+ // handle the TZID /freeassociation.sourceforge.net/Tzfile/[Location] case
586+ if (identifier != nullptr)
587+ {
588+ const char* pch;
589+ const char* key = "/freeassociation.sourceforge.net/";
590+ if ((pch = strstr(identifier, key)))
591+ {
592+ identifier = pch + strlen(key);
593+ key = "Tzfile/"; // some don't have this, so check for it separately
594+ if ((pch = strstr(identifier, key)))
595+ identifier = pch + strlen(key);
596+ }
597+ }
598+
599+ if (identifier == nullptr)
600+ g_warning("Unrecognized TZID: '%s'", tzid);
601+ else
602+ return g_time_zone_new(identifier);
603+
604+ return nullptr;
605 }
606
607 static DateTime
608@@ -740,51 +758,9 @@
609 DateTime out;
610 g_return_val_if_fail(in.value != nullptr, out);
611
612- GTimeZone * gtz {};
613- if (in.tzid != nullptr)
614- {
615- auto itz = icaltimezone_get_builtin_timezone_from_tzid(in.tzid); // usually works
616-
617- if (itz == nullptr) // fallback
618- itz = icaltimezone_get_builtin_timezone(in.tzid);
619-
620- if (itz == nullptr) // ok we have a strange tzid... ask EDS to look it up in VTIMEZONES
621- e_cal_client_get_timezone_sync(client, in.tzid, &itz, cancellable.get(), nullptr);
622-
623- const char* identifier {};
624-
625- if (itz != nullptr)
626- {
627- identifier = icaltimezone_get_display_name(itz);
628-
629- if (identifier == nullptr)
630- identifier = icaltimezone_get_location(itz);
631- }
632-
633- // handle the TZID /freeassociation.sourceforge.net/Tzfile/[Location] case
634- if (identifier != nullptr)
635- {
636- const char* pch;
637- const char* key = "/freeassociation.sourceforge.net/";
638- if ((pch = strstr(identifier, key)))
639- {
640- identifier = pch + strlen(key);
641- key = "Tzfile/"; // some don't have this, so check for it separately
642- if ((pch = strstr(identifier, key)))
643- identifier = pch + strlen(key);
644- }
645- }
646-
647- if (identifier == nullptr)
648- g_warning("Unrecognized TZID: '%s'", in.tzid);
649-
650- gtz = g_time_zone_new(identifier);
651- g_debug("%s eccdt.tzid -> offset is %d", G_STRLOC, in.tzid, (int)g_time_zone_get_offset(gtz,0));
652- }
653- else
654- {
655+ GTimeZone * gtz = timezone_from_name(in.tzid, client, cancellable.get(), nullptr);
656+ if (gtz == nullptr)
657 gtz = g_time_zone_ref(default_timezone);
658- }
659
660 out = DateTime(gtz,
661 in.value->year,
662@@ -797,7 +773,7 @@
663 return out;
664 }
665
666- static bool
667+ bool
668 is_component_interesting(ECalComponent * component)
669 {
670 // we only want calendar events and vtodos
671@@ -823,6 +799,28 @@
672 disabled = true;
673 }
674 e_cal_component_free_categories_list(categ_list);
675+
676+ if (!disabled) {
677+ // we don't want not attending alarms
678+ // check if the user is part of attendee list if we found it check the status
679+ GSList *attendeeList = nullptr;
680+ e_cal_component_get_attendee_list(component, &attendeeList);
681+
682+ for (GSList *attendeeIter=attendeeList; attendeeIter != nullptr; attendeeIter = attendeeIter->next) {
683+ ECalComponentAttendee *attendee = static_cast<ECalComponentAttendee *>(attendeeIter->data);
684+ if (attendee->value) {
685+ if (strncmp(attendee->value, "mailto:", 7) == 0) {
686+ if (m_myself->isMyEmail(attendee->value+7)) {
687+ disabled = (attendee->status == ICAL_PARTSTAT_DECLINED);
688+ break;
689+ }
690+ }
691+ }
692+ }
693+ if (attendeeList)
694+ e_cal_component_free_attendee_list(attendeeList);
695+ }
696+
697 if (disabled)
698 return false;
699
700@@ -903,35 +901,13 @@
701 }
702
703 static void
704- add_event_to_subtask(ECalComponent * component,
705- ClientSubtask * subtask,
706- GTimeZone * gtz)
707- {
708- // events with alarms are covered by add_alarms_to_subtask(),
709- // so skip them here
710- auto auids = e_cal_component_get_alarm_uids(component);
711- const bool has_alarms = auids != nullptr;
712- cal_obj_uid_list_free(auids);
713- if (has_alarms)
714- return;
715-
716- // add it. simple, eh?
717- if (is_component_interesting(component))
718- {
719- Appointment appointment = get_appointment(subtask->client, subtask->cancellable, component, gtz);
720- appointment.color = subtask->color;
721- subtask->task->appointments.push_back(appointment);
722- }
723- }
724-
725- static void
726 add_alarms_to_subtask(ECalComponentAlarms * comp_alarms,
727 ClientSubtask * subtask,
728 GTimeZone * gtz)
729 {
730 auto& component = comp_alarms->comp;
731
732- if (!is_component_interesting(component))
733+ if (!subtask->task->p->is_component_interesting(component))
734 return;
735
736 Appointment baseline = get_appointment(subtask->client, subtask->cancellable, component, gtz);
737@@ -965,13 +941,15 @@
738 auto instance_time = std::make_pair(DateTime{gtz, ai->occur_start},
739 DateTime{gtz, ai->occur_end});
740 auto trigger_time = DateTime{gtz, ai->trigger};
741-
742 auto& alarm = alarms[instance_time][trigger_time];
743-
744 if (alarm.text.empty())
745 alarm.text = get_alarm_text(a);
746+
747 if (alarm.audio_url.empty())
748- alarm.audio_url = get_alarm_sound_url(a);
749+ alarm.audio_url = get_alarm_sound_url(a, (baseline.is_ubuntu_alarm() ?
750+ "file://" ALARM_DEFAULT_SOUND :
751+ "file://" CALENDAR_DEFAULT_SOUND));
752+
753 if (!alarm.time.is_set())
754 alarm.time = trigger_time;
755
756@@ -985,7 +963,25 @@
757 appointment.end = i.first.second;
758 appointment.alarms.reserve(i.second.size());
759 for (auto& j : i.second)
760- appointment.alarms.push_back(j.second);
761+ {
762+ if (j.second.has_text() || j.second.has_sound())
763+ appointment.alarms.push_back(j.second);
764+ }
765+ subtask->task->appointments.push_back(appointment);
766+ }
767+ }
768+
769+
770+ static void
771+ add_event_to_subtask(ECalComponent * component,
772+ ClientSubtask * subtask,
773+ GTimeZone * gtz)
774+ {
775+ // add it. simple, eh?
776+ if (subtask->task->p->is_component_interesting(component))
777+ {
778+ Appointment appointment = get_appointment(subtask->client, subtask->cancellable, component, gtz);
779+ appointment.color = subtask->color;
780 subtask->task->appointments.push_back(appointment);
781 }
782 }
783@@ -1062,14 +1058,15 @@
784 ESourceRegistry* m_source_registry {};
785 guint m_rebuild_tag {};
786 time_t m_rebuild_deadline {};
787+ std::shared_ptr<Myself> m_myself;
788 };
789
790 /***
791 ****
792 ***/
793
794-EdsEngine::EdsEngine():
795- p(new Impl())
796+EdsEngine::EdsEngine(const std::shared_ptr<Myself> &myself):
797+ p(new Impl(myself))
798 {
799 }
800
801
802=== modified file 'src/main.cpp'
803--- src/main.cpp 2016-04-12 17:03:36 +0000
804+++ src/main.cpp 2016-04-19 13:10:52 +0000
805@@ -25,6 +25,7 @@
806 #include <datetime/exporter.h>
807 #include <datetime/locations-settings.h>
808 #include <datetime/menu.h>
809+#include <datetime/myself.h>
810 #include <datetime/planner-aggregate.h>
811 #include <datetime/planner-snooze.h>
812 #include <datetime/planner-range.h>
813@@ -58,7 +59,7 @@
814 if (!g_strcmp0("lightdm", g_get_user_name()))
815 engine.reset(new MockEngine);
816 else
817- engine.reset(new EdsEngine);
818+ engine.reset(new EdsEngine(std::shared_ptr<Myself>(new Myself)));
819
820 return engine;
821 }
822@@ -151,7 +152,10 @@
823 auto on_snooze = [snooze_planner](const Appointment& appointment, const Alarm& alarm) {
824 snooze_planner->add(appointment, alarm);
825 };
826- auto on_ok = [](const Appointment&, const Alarm&){};
827+ auto on_ok = [actions](const Appointment& app, const Alarm&){
828+ //TODO: add support for desktop
829+ actions->phone_open_appointment(app, app.begin);
830+ };
831 auto on_alarm_reached = [&engine, &snap, &on_snooze, &on_ok](const Appointment& appointment, const Alarm& alarm) {
832 (*snap)(appointment, alarm, on_snooze, on_ok);
833 engine->disable_ubuntu_alarm(appointment);
834
835=== added file 'src/myself.cpp'
836--- src/myself.cpp 1970-01-01 00:00:00 +0000
837+++ src/myself.cpp 2016-04-19 13:10:52 +0000
838@@ -0,0 +1,76 @@
839+/*
840+ * Copyright 2016 Canonical Ltd.
841+ *
842+ * This program is free software: you can redistribute it and/or modify it
843+ * under the terms of the GNU General Public License version 3, as published
844+ * by the Free Software Foundation.
845+ *
846+ * This program is distributed in the hope that it will be useful, but
847+ * WITHOUT ANY WARRANTY; without even the implied warranties of
848+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
849+ * PURPOSE. See the GNU General Public License for more details.
850+ *
851+ * You should have received a copy of the GNU General Public License along
852+ * with this program. If not, see <http://www.gnu.org/licenses/>.
853+ *
854+ * Authors:
855+ * Renato Araujo Oliveira Filho <renato.filho@canonical.com>
856+ */
857+
858+#include "datetime/myself.h"
859+
860+#include <libaccounts-glib/ag-manager.h>
861+#include <libaccounts-glib/ag-account.h>
862+
863+#include <algorithm>
864+
865+namespace unity {
866+namespace indicator {
867+namespace datetime {
868+
869+Myself::Myself()
870+ : m_accounts_manager(ag_manager_new(), g_object_unref)
871+{
872+ reloadEmails();
873+ g_object_connect(m_accounts_manager.get(),
874+ "signal::account-created", on_accounts_changed, this,
875+ "signal::account-deleted", on_accounts_changed, this,
876+ "signal::account-updated", on_accounts_changed, this,
877+ nullptr);
878+}
879+
880+bool Myself::isMyEmail(const std::string &email)
881+{
882+ return m_emails.get().count(email) > 0;
883+}
884+
885+void Myself::on_accounts_changed(AgManager *, guint, Myself *self)
886+{
887+ self->reloadEmails();
888+}
889+
890+void Myself::reloadEmails()
891+{
892+ std::set<std::string> emails;
893+
894+ auto manager = m_accounts_manager.get();
895+ auto ids = ag_manager_list(manager);
896+ for (auto l=ids; l!=nullptr; l=l->next)
897+ {
898+ auto acc = ag_manager_get_account(manager, GPOINTER_TO_UINT(l->data));
899+ if (acc) {
900+ auto account_name = ag_account_get_display_name(acc);
901+ if (account_name != nullptr)
902+ emails.insert(account_name);
903+ g_object_unref(acc);
904+ }
905+ }
906+ ag_manager_list_free(ids);
907+
908+ m_emails.set(emails);
909+}
910+
911+} // namespace datetime
912+} // namespace indicator
913+} // namespace unity
914+
915
916=== modified file 'src/notifications.cpp'
917--- src/notifications.cpp 2014-09-17 17:08:01 +0000
918+++ src/notifications.cpp 2016-04-19 13:10:52 +0000
919@@ -21,10 +21,18 @@
920
921 #include <libnotify/notify.h>
922
923+#include <messaging-menu/messaging-menu-app.h>
924+#include <messaging-menu/messaging-menu-message.h>
925+
926+
927+#include <uuid/uuid.h>
928+
929 #include <map>
930 #include <set>
931 #include <string>
932 #include <vector>
933+#include <memory>
934+
935
936 namespace unity {
937 namespace indicator {
938@@ -45,9 +53,11 @@
939 std::string m_body;
940 std::string m_icon_name;
941 std::chrono::seconds m_duration;
942+ gint64 m_start_time;
943 std::set<std::string> m_string_hints;
944 std::vector<std::pair<std::string,std::string>> m_actions;
945 std::function<void(const std::string&)> m_closed_callback;
946+ std::function<void()> m_missed_click_callback;
947 };
948
949 Builder::Builder():
950@@ -101,6 +111,18 @@
951 impl->m_closed_callback.swap (cb);
952 }
953
954+void
955+Builder::set_missed_click_callback (std::function<void()> cb)
956+{
957+ impl->m_missed_click_callback.swap (cb);
958+}
959+
960+void
961+Builder::set_start_time (uint64_t time)
962+{
963+ impl->m_start_time = time;
964+}
965+
966 /***
967 ****
968 ***/
969@@ -110,23 +132,39 @@
970 struct notification_data
971 {
972 std::shared_ptr<NotifyNotification> nn;
973- std::function<void(const std::string&)> closed_callback;
974+ Builder::Impl data;
975+ };
976+
977+ struct messaging_menu_data
978+ {
979+ std::shared_ptr<MessagingMenuMessage> mm;
980+ std::function<void()> callback;
981 };
982
983 public:
984
985 Impl(const std::string& app_name):
986+ m_messaging_app(messaging_menu_app_new(DATETIME_INDICATOR_DESKTOP_FILE), g_object_unref),
987 m_app_name(app_name)
988 {
989 if (!notify_init(app_name.c_str()))
990 g_critical("Unable to initialize libnotify!");
991+
992+ // messaging menu
993+ GIcon *icon = g_themed_icon_new("calendar-app");
994+
995+ messaging_menu_app_register(m_messaging_app.get());
996+ messaging_menu_app_append_source(m_messaging_app.get(), m_app_name.c_str(), icon, "Calendar");
997+ g_object_unref(icon);
998 }
999
1000 ~Impl()
1001 {
1002 close_all ();
1003+ remove_all ();
1004
1005 notify_uninit ();
1006+ messaging_menu_app_unregister (m_messaging_app.get());
1007 }
1008
1009 const std::string& app_name() const
1010@@ -217,7 +255,7 @@
1011 notification_key_quark(),
1012 GINT_TO_POINTER(key));
1013
1014- m_notifications[key] = { nn, info.m_closed_callback };
1015+ m_notifications[key] = { nn, info };
1016 g_signal_connect (nn.get(), "closed",
1017 G_CALLBACK(on_notification_closed), this);
1018
1019@@ -238,6 +276,59 @@
1020 return ret;
1021 }
1022
1023+ std::string post(const Builder::Impl& data)
1024+ {
1025+ uuid_t message_uuid;
1026+ uuid_generate(message_uuid);
1027+
1028+ char message_id[37];
1029+ uuid_unparse(message_uuid, message_id);
1030+
1031+ GIcon *icon = g_themed_icon_new(data.m_icon_name.c_str());
1032+ std::shared_ptr<MessagingMenuMessage> msg (messaging_menu_message_new(message_id,
1033+ icon,
1034+ data.m_title.c_str(),
1035+ nullptr,
1036+ data.m_body.c_str(),
1037+ data.m_start_time * 1000000), // secs -> microsecs
1038+ g_object_ref);
1039+ g_object_unref(icon);
1040+ if (msg)
1041+ {
1042+ m_messaging_messages[std::string(message_id)] = { msg, data.m_missed_click_callback };
1043+ g_signal_connect(msg.get(), "activate",
1044+ G_CALLBACK(on_message_activated), this);
1045+ messaging_menu_app_append_message(m_messaging_app.get(), msg.get(), m_app_name.c_str(), false);
1046+ return message_id;
1047+ } else {
1048+ g_warning("Fail to create messaging menu message");
1049+ }
1050+ return "";
1051+ }
1052+
1053+ void remove (const std::string &key)
1054+ {
1055+ auto it = m_messaging_messages.find(key);
1056+ if (it != m_messaging_messages.end())
1057+ {
1058+ // tell the server to remove message
1059+ messaging_menu_app_remove_message(m_messaging_app.get(), it->second.mm.get());
1060+ m_messaging_messages.erase(it);
1061+ }
1062+ }
1063+
1064+ void remove_all ()
1065+ {
1066+ // call remove() on all our keys
1067+
1068+ std::set<std::string> keys;
1069+ for (const auto& it : m_messaging_messages)
1070+ keys.insert (it.first);
1071+
1072+ for (const std::string &key : keys)
1073+ remove (key);
1074+ }
1075+
1076 private:
1077
1078 const std::set<std::string>& server_caps() const
1079@@ -279,6 +370,22 @@
1080 static_cast<Impl*>(gself)->remove_closed_notification(GPOINTER_TO_INT(gkey));
1081 }
1082
1083+ static void on_message_activated (MessagingMenuMessage *,
1084+ const char *actionId,
1085+ GVariant *,
1086+ gpointer gself)
1087+ {
1088+ auto self = static_cast<Impl*>(gself);
1089+ auto it = self->m_messaging_messages.find(actionId);
1090+ g_return_if_fail (it != self->m_messaging_messages.end());
1091+ const auto& ndata = it->second;
1092+
1093+ if (ndata.callback)
1094+ ndata.callback();
1095+
1096+ self->m_messaging_messages.erase(it);
1097+ }
1098+
1099 void remove_closed_notification (int key)
1100 {
1101 auto it = m_notifications.find(key);
1102@@ -286,16 +393,20 @@
1103
1104 const auto& ndata = it->second;
1105 auto nn = ndata.nn.get();
1106- if (ndata.closed_callback)
1107+
1108+ if (ndata.data.m_closed_callback)
1109 {
1110 std::string action;
1111-
1112 const GQuark q = notification_action_quark();
1113 const gpointer p = g_object_get_qdata(G_OBJECT(nn), q);
1114 if (p != nullptr)
1115 action = static_cast<const char*>(p);
1116
1117- ndata.closed_callback (action);
1118+ ndata.data.m_closed_callback (action);
1119+ // empty action means that the notification got timeout
1120+ // post a message on messaging menu
1121+ if (action.empty())
1122+ post(ndata.data);
1123 }
1124
1125 m_notifications.erase(it);
1126@@ -305,6 +416,10 @@
1127 ****
1128 ***/
1129
1130+ // messaging menu
1131+ std::shared_ptr<MessagingMenuApp> m_messaging_app;
1132+ std::map<std::string, messaging_menu_data> m_messaging_messages;
1133+
1134 const std::string m_app_name;
1135
1136 // key-to-data
1137@@ -315,6 +430,8 @@
1138 mutable std::set<std::string> m_lazy_caps;
1139
1140 static constexpr char const * HINT_TIMEOUT {"x-canonical-snap-decisions-timeout"};
1141+ static constexpr char const * DATETIME_INDICATOR_DESKTOP_FILE {"indicator-datetime.desktop"};
1142+ static constexpr char const * DATETIME_INDICATOR_SOURCE_ID {"indicator-datetime"};
1143 };
1144
1145 /***
1146
1147=== modified file 'src/snap.cpp'
1148--- src/snap.cpp 2016-02-03 17:06:31 +0000
1149+++ src/snap.cpp 2016-04-19 13:10:52 +0000
1150@@ -102,7 +102,7 @@
1151
1152 // calendar events are muted in silent mode; alarm clocks never are
1153 std::shared_ptr<uin::Sound> sound;
1154- if (appointment.is_ubuntu_alarm() || !silent_mode()) {
1155+ if (appointment.is_ubuntu_alarm() || (alarm.has_sound() && !silent_mode())) {
1156 // create the sound.
1157 const auto role = appointment.is_ubuntu_alarm() ? "alarm" : "alert";
1158 const auto uri = get_alarm_uri(appointment, alarm, m_settings);
1159@@ -123,8 +123,9 @@
1160 const auto minutes = std::chrono::minutes(m_settings->alarm_duration.get());
1161 uin::Builder b;
1162 b.set_body (appointment.summary);
1163- b.set_icon_name (appointment.is_ubuntu_alarm() ? "alarm-clock" : "reminder");
1164+ b.set_icon_name (appointment.is_ubuntu_alarm() ? "alarm-clock" : "appointment");
1165 b.add_hint (uin::Builder::HINT_NONSHAPED_ICON);
1166+ b.set_start_time (appointment.begin.to_unix());
1167
1168 const char * timefmt;
1169 if (is_locale_12h()) {
1170@@ -150,6 +151,9 @@
1171 b.add_hint (uin::Builder::HINT_AFFIRMATIVE_HINT);
1172 b.add_action ("ok", _("OK"));
1173 b.add_action ("snooze", _("Snooze"));
1174+ } else {
1175+ b.add_hint (uin::Builder::HINT_INTERACTIVE);
1176+ b.add_action ("ok", _("OK"));
1177 }
1178
1179 // add 'sound', 'haptic', and 'awake' objects to the capture so
1180@@ -159,10 +163,14 @@
1181 (const std::string& action){
1182 if (action == "snooze")
1183 snooze(appointment, alarm);
1184- else
1185+ else if (action == "ok")
1186 ok(appointment, alarm);
1187 });
1188
1189+ b.set_missed_click_callback([appointment, alarm, ok](){
1190+ ok(appointment, alarm);
1191+ });
1192+
1193 const auto key = m_engine->show(b);
1194 if (key)
1195 m_notifications.insert (key);
1196
1197=== modified file 'tests/CMakeLists.txt'
1198--- tests/CMakeLists.txt 2016-03-22 18:51:50 +0000
1199+++ tests/CMakeLists.txt 2016-04-19 13:10:52 +0000
1200@@ -85,7 +85,8 @@
1201 ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
1202 ${TEST_NAME} # arg3: test name
1203 ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg4: base directory for config file template
1204- ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics) # arg5: the ical file for this test
1205+ ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics # arg5: the ical file for this test
1206+ ${CMAKE_CURRENT_SOURCE_DIR}/accounts.db) # arg6: online accounts database
1207 endfunction()
1208 add_eds_ics_test_by_name(test-eds-ics-all-day-events)
1209 add_eds_ics_test_by_name(test-eds-ics-repeating-events)
1210@@ -95,6 +96,7 @@
1211 add_eds_ics_test_by_name(test-eds-ics-tzids)
1212 add_eds_ics_test_by_name(test-eds-ics-tzids-2)
1213 add_eds_ics_test_by_name(test-eds-ics-tzids-utc)
1214+add_eds_ics_test_by_name(test-eds-ics-non-attending-alarms)
1215
1216
1217 # disabling the timezone unit tests because they require
1218
1219=== added file 'tests/accounts.db'
1220Binary files tests/accounts.db 1970-01-01 00:00:00 +0000 and tests/accounts.db 2016-04-19 13:10:52 +0000 differ
1221=== modified file 'tests/notification-fixture.h'
1222--- tests/notification-fixture.h 2016-02-10 20:48:24 +0000
1223+++ tests/notification-fixture.h 2016-04-19 13:10:52 +0000
1224@@ -53,7 +53,7 @@
1225 static constexpr char const * HAPTIC_METHOD_VIBRATE_PATTERN {"VibratePattern"};
1226
1227 static constexpr int SCREEN_COOKIE {8675309};
1228- static constexpr char const * SCREEN_METHOD_KEEP_DISPLAY_ON {"keepDisplayOn"};
1229+ static constexpr char const * SCREEN_METHOD_KEEP_DISPLAY_ON {"keepDisplayOn"};
1230 static constexpr char const * SCREEN_METHOD_REMOVE_DISPLAY_ON_REQUEST {"removeDisplayOnRequest"};
1231
1232 static constexpr int POWERD_SYS_STATE_ACTIVE = 1;
1233@@ -111,7 +111,7 @@
1234 const auto christmas = unity::indicator::datetime::DateTime::Local(2015,12,25,0,0,0);
1235 appt.begin = christmas.start_of_day();
1236 appt.end = christmas.end_of_day();
1237- appt.alarms.push_back(unity::indicator::datetime::Alarm{"Ho Ho Ho!", "", appt.begin});
1238+ appt.alarms.push_back(unity::indicator::datetime::Alarm{"Ho Ho Ho!", CALENDAR_DEFAULT_SOUND, appt.begin});
1239
1240 // init an Ubuntu Alarm
1241 ualarm.color = "red";
1242@@ -165,8 +165,8 @@
1243 NOTIFY_INTERFACE,
1244 &error);
1245 g_assert_no_error(error);
1246-
1247- // METHOD_GET_INFO
1248+
1249+ // METHOD_GET_INFO
1250 str = g_strdup("ret = ('mock-notify', 'test vendor', '1.0', '1.1')");
1251 dbus_test_dbus_mock_object_add_method(notify_mock,
1252 notify_obj,
1253@@ -196,7 +196,7 @@
1254 g_assert_no_error (error);
1255 g_free (str);
1256
1257- // METHOD_CLOSE
1258+ // METHOD_CLOSE
1259 str = g_strdup_printf("self.EmitSignal('%s', '%s', 'uu', [ args[0], %d ])",
1260 NOTIFY_INTERFACE,
1261 SIGNAL_CLOSED,
1262@@ -223,8 +223,8 @@
1263 BUS_POWERD_INTERFACE,
1264 &error);
1265 g_assert_no_error(error);
1266-
1267- str = g_strdup_printf ("ret = '%s'", POWERD_COOKIE);
1268+
1269+ str = g_strdup_printf ("ret = '%s'", POWERD_COOKIE);
1270 dbus_test_dbus_mock_object_add_method(powerd_mock,
1271 powerd_obj,
1272 POWERD_METHOD_REQUEST_SYS_STATE,
1273@@ -256,8 +256,8 @@
1274 BUS_SCREEN_INTERFACE,
1275 &error);
1276 g_assert_no_error(error);
1277-
1278- str = g_strdup_printf ("ret = %d", SCREEN_COOKIE);
1279+
1280+ str = g_strdup_printf ("ret = %d", SCREEN_COOKIE);
1281 dbus_test_dbus_mock_object_add_method(screen_mock,
1282 screen_obj,
1283 SCREEN_METHOD_KEEP_DISPLAY_ON,
1284@@ -287,7 +287,7 @@
1285 BUS_HAPTIC_PATH,
1286 BUS_HAPTIC_INTERFACE,
1287 &error);
1288-
1289+
1290 dbus_test_dbus_mock_object_add_method(haptic_mock,
1291 haptic_obj,
1292 HAPTIC_METHOD_VIBRATE_PATTERN,
1293
1294=== modified file 'tests/run-eds-ics-test.sh'
1295--- tests/run-eds-ics-test.sh 2015-07-20 16:31:28 +0000
1296+++ tests/run-eds-ics-test.sh 2016-04-19 13:10:52 +0000
1297@@ -6,6 +6,7 @@
1298 TEST_NAME=$3 # test name
1299 CONFIG_DIR=$4 # config files
1300 ICS_FILE=$5 # ical file holding test data
1301+ACCOUNTS_DB=$6 # online account database
1302
1303 echo "this script: ${SELF}"
1304 echo "test-runner: ${TEST_RUNNER}"
1305@@ -54,8 +55,15 @@
1306 cp --verbose --archive ${ICS_FILE} ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics
1307 fi
1308
1309+# prepare online accounts database
1310+if [ -e ${ACCOUNTS_DB} ]; then
1311+ echo "copying ${ACCOUNTS_DB} into $HOME"
1312+ mkdir -p ${XDG_CONFIG_HOME}/libaccounts-glib/
1313+ cp --verbose --archive ${ACCOUNTS_DB} ${XDG_CONFIG_HOME}/libaccounts-glib/accounts.db
1314+fi
1315+
1316 # run the test
1317-${TEST_RUNNER} --keep-env --max-wait=90 --task ${TEST_EXEC} --task-name ${TEST_NAME} --wait-until-complete
1318+${TEST_RUNNER} --keep-env --max-wait=90 --task ${TEST_EXEC} --task-name ${TEST_NAME} --wait-until-complete
1319 rv=$?
1320
1321 # if the test passed, blow away the tmpdir
1322
1323=== modified file 'tests/test-eds-ics-all-day-events.cpp'
1324--- tests/test-eds-ics-all-day-events.cpp 2015-05-21 12:47:24 +0000
1325+++ tests/test-eds-ics-all-day-events.cpp 2016-04-19 13:10:52 +0000
1326@@ -22,6 +22,7 @@
1327 #include <datetime/alarm-queue-simple.h>
1328 #include <datetime/clock-mock.h>
1329 #include <datetime/engine-eds.h>
1330+#include <datetime/myself.h>
1331 #include <datetime/planner-range.h>
1332
1333 #include <gtest/gtest.h>
1334@@ -41,7 +42,7 @@
1335 TEST_F(VAlarmFixture, MultipleAppointments)
1336 {
1337 // start the EDS engine
1338- auto engine = std::make_shared<EdsEngine>();
1339+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1340
1341 // we need a consistent timezone for the planner and our local DateTimes
1342 constexpr char const * zone_str {"America/Chicago"};
1343@@ -66,7 +67,7 @@
1344 constexpr int max_wait_sec = 10;
1345 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
1346 }
1347-
1348+
1349 // what we expect to get...
1350 Appointment expected_appt;
1351 expected_appt.uid = "20150521T111538Z-7449-1000-3572-0@ghidorah";
1352
1353=== modified file 'tests/test-eds-ics-missing-trigger.cpp'
1354--- tests/test-eds-ics-missing-trigger.cpp 2015-10-13 14:40:02 +0000
1355+++ tests/test-eds-ics-missing-trigger.cpp 2016-04-19 13:10:52 +0000
1356@@ -22,6 +22,7 @@
1357 #include <datetime/alarm-queue-simple.h>
1358 #include <datetime/clock-mock.h>
1359 #include <datetime/engine-eds.h>
1360+#include <datetime/myself.h>
1361 #include <datetime/planner-range.h>
1362
1363 #include <gtest/gtest.h>
1364@@ -41,7 +42,7 @@
1365 TEST_F(VAlarmFixture, MissingTriggers)
1366 {
1367 // start the EDS engine
1368- auto engine = std::make_shared<EdsEngine>();
1369+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1370
1371 // we need a consistent timezone for the planner and our local DateTimes
1372 constexpr char const * zone_str {"America/Chicago"};
1373
1374=== added file 'tests/test-eds-ics-non-attending-alarms.cpp'
1375--- tests/test-eds-ics-non-attending-alarms.cpp 1970-01-01 00:00:00 +0000
1376+++ tests/test-eds-ics-non-attending-alarms.cpp 2016-04-19 13:10:52 +0000
1377@@ -0,0 +1,79 @@
1378+/*
1379+ * Copyright 2015 Canonical Ltd.
1380+ *
1381+ * This program is free software: you can redistribute it and/or modify it
1382+ * under the terms of the GNU General Public License version 3, as published
1383+ * by the Free Software Foundation.
1384+ *
1385+ * This program is distributed in the hope that it will be useful, but
1386+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1387+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1388+ * PURPOSE. See the GNU General Public License for more details.
1389+ *
1390+ * You should have received a copy of the GNU General Public License along
1391+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1392+ *
1393+ * Authors:
1394+ * Charles Kerr <charles.kerr@canonical.com>
1395+ */
1396+
1397+#include <algorithm>
1398+
1399+#include <datetime/alarm-queue-simple.h>
1400+#include <datetime/clock-mock.h>
1401+#include <datetime/engine-eds.h>
1402+#include <datetime/myself.h>
1403+#include <datetime/planner-range.h>
1404+
1405+#include <gtest/gtest.h>
1406+
1407+#include "glib-fixture.h"
1408+#include "print-to.h"
1409+#include "timezone-mock.h"
1410+#include "wakeup-timer-mock.h"
1411+
1412+using namespace unity::indicator::datetime;
1413+using VAlarmFixture = GlibFixture;
1414+
1415+/***
1416+****
1417+***/
1418+
1419+TEST_F(VAlarmFixture, NonAttendingEvent)
1420+{
1421+ // start the EDS engine
1422+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1423+
1424+ // we need a consistent timezone for the planner and our local DateTimes
1425+ constexpr char const * zone_str {"America/Recife"};
1426+ auto tz = std::make_shared<MockTimezone>(zone_str);
1427+ auto gtz = g_time_zone_new(zone_str);
1428+
1429+ // make a planner that looks at the first half of 2016 in EDS
1430+ auto planner = std::make_shared<SimpleRangePlanner>(engine, tz);
1431+ const DateTime range_begin {gtz, 2016,1, 1, 0, 0, 0.0};
1432+ const DateTime range_end {gtz, 2016,6,31,23,59,59.5};
1433+ planner->range().set(std::make_pair(range_begin, range_end));
1434+
1435+ // give EDS a moment to load
1436+ if (planner->appointments().get().empty()) {
1437+ g_message("waiting a moment for EDS to load...");
1438+ auto on_appointments_changed = [this](const std::vector<Appointment>& appointments){
1439+ g_message("ah, they loaded");
1440+ if (!appointments.empty())
1441+ g_main_loop_quit(loop);
1442+ };
1443+ core::ScopedConnection conn(planner->appointments().changed().connect(on_appointments_changed));
1444+ constexpr int max_wait_sec = 10;
1445+ wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
1446+ }
1447+
1448+ // the planner should match what we've got in the calendar.ics file
1449+ const auto appts = planner->appointments().get();
1450+ EXPECT_EQ(2, appts.size());
1451+ EXPECT_EQ(appts[0].begin, DateTime(gtz, 2016, 4, 4, 16, 0, 0));
1452+ EXPECT_EQ(appts[1].begin, DateTime(gtz, 2016, 4, 6, 16, 0, 0));
1453+
1454+ // cleanup
1455+ g_time_zone_unref(gtz);
1456+}
1457
1458=== added file 'tests/test-eds-ics-non-attending-alarms.ics.in'
1459--- tests/test-eds-ics-non-attending-alarms.ics.in 1970-01-01 00:00:00 +0000
1460+++ tests/test-eds-ics-non-attending-alarms.ics.in 2016-04-19 13:10:52 +0000
1461@@ -0,0 +1,53 @@
1462+BEGIN:VCALENDAR
1463+CALSCALE:GREGORIAN
1464+PRODID:-//Ximian//NONSGML Evolution Calendar//EN
1465+VERSION:2.0
1466+X-EVOLUTION-DATA-REVISION:2015-04-05T21:32:47.354433Z(2)
1467+BEGIN:VEVENT
1468+STATUS:CONFIRMED
1469+DTSTAMP:20160405T152128Z
1470+CREATED:20160405T152128Z
1471+UID:ddtvl069dn2cquo8dhg3j9c360@google.com
1472+SEQUENCE:1
1473+TRANSP:OPAQUE
1474+SUMMARY:Every day at 4PM
1475+DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/America/Recife:
1476+ 20160404T160000
1477+RRULE:FREQ=DAILY;UNTIL=20160406T190000Z
1478+DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/America/Recife:
1479+ 20160404T170000
1480+ATTENDEE;CN=Uphablet;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;
1481+ CUTYPE=INDIVIDUAL:mailto:uphablet@ubuntu.com
1482+LAST-MODIFIED:20160405T152128Z
1483+BEGIN:VALARM
1484+TRIGGER;VALUE=DURATION:-PT30M
1485+ACTION:EMAIL
1486+DESCRIPTION:This is an event reminder
1487+X-EVOLUTION-ALARM-UID:20160405T152128Z-2848-32011-1844-65@ubuntu-phablet
1488+END:VALARM
1489+END:VEVENT
1490+BEGIN:VEVENT
1491+STATUS:CONFIRMED
1492+DTSTAMP:20160405T152128Z
1493+CREATED:20160405T151054Z
1494+UID:ddtvl069dn2cquo8dhg3j9c360@google.com
1495+SEQUENCE:1
1496+TRANSP:OPAQUE
1497+SUMMARY::Every day at 4PM
1498+DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/America/Fortaleza:
1499+ 20160405T160000
1500+RECURRENCE-ID;TZID=/freeassociation.sourceforge.net/Tzfile/America/Recife:
1501+ 20160405T160000
1502+DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/America/Fortaleza:
1503+ 20160405T170000
1504+ATTENDEE;CN=Uphablet;PARTSTAT=DECLINED;ROLE=REQ-PARTICIPANT;
1505+ CUTYPE=INDIVIDUAL:mailto:uphablet@ubuntu.com
1506+LAST-MODIFIED:20160405T152128Z
1507+BEGIN:VALARM
1508+TRIGGER;VALUE=DURATION:-PT30M
1509+ACTION:EMAIL
1510+DESCRIPTION:This is an event reminder
1511+X-EVOLUTION-ALARM-UID:20160405T152128Z-2848-32011-1844-66@ubuntu-phablet
1512+END:VALARM
1513+END:VEVENT
1514+END:VCALENDAR
1515
1516=== modified file 'tests/test-eds-ics-nonrepeating-events.cpp'
1517--- tests/test-eds-ics-nonrepeating-events.cpp 2015-10-13 14:40:02 +0000
1518+++ tests/test-eds-ics-nonrepeating-events.cpp 2016-04-19 13:10:52 +0000
1519@@ -22,6 +22,7 @@
1520 #include <datetime/alarm-queue-simple.h>
1521 #include <datetime/clock-mock.h>
1522 #include <datetime/engine-eds.h>
1523+#include <datetime/myself.h>
1524 #include <datetime/planner-range.h>
1525
1526 #include <gtest/gtest.h>
1527@@ -41,7 +42,7 @@
1528 TEST_F(VAlarmFixture, MultipleAppointments)
1529 {
1530 // start the EDS engine
1531- auto engine = std::make_shared<EdsEngine>();
1532+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1533
1534 // we need a consistent timezone for the planner and our local DateTimes
1535 constexpr char const * zone_str {"America/Chicago"};
1536@@ -66,7 +67,7 @@
1537 constexpr int max_wait_sec = 10;
1538 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
1539 }
1540-
1541+
1542 // what we expect to get...
1543 Appointment expected_appt;
1544 expected_appt.uid = "20150520T000726Z-3878-32011-1770-81@ubuntu-phablet";
1545
1546=== modified file 'tests/test-eds-ics-repeating-events.cpp'
1547--- tests/test-eds-ics-repeating-events.cpp 2015-10-13 14:40:02 +0000
1548+++ tests/test-eds-ics-repeating-events.cpp 2016-04-19 13:10:52 +0000
1549@@ -22,6 +22,7 @@
1550 #include <datetime/alarm-queue-simple.h>
1551 #include <datetime/clock-mock.h>
1552 #include <datetime/engine-eds.h>
1553+#include <datetime/myself.h>
1554 #include <datetime/planner-range.h>
1555
1556 #include <gtest/gtest.h>
1557@@ -41,7 +42,7 @@
1558 TEST_F(VAlarmFixture, MultipleAppointments)
1559 {
1560 // start the EDS engine
1561- auto engine = std::make_shared<EdsEngine>();
1562+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1563
1564 // we need a consistent timezone for the planner and our local DateTimes
1565 constexpr char const * zone_str {"America/Chicago"};
1566@@ -66,7 +67,7 @@
1567 constexpr int max_wait_sec = 10;
1568 wait_msec(max_wait_sec * G_TIME_SPAN_MILLISECOND);
1569 }
1570-
1571+
1572 // what we expect to get...
1573 Appointment expected_appt;
1574 expected_appt.uid = "20150507T211449Z-4262-32011-1418-1@ubuntu-phablet";
1575
1576=== modified file 'tests/test-eds-ics-repeating-valarms.cpp'
1577--- tests/test-eds-ics-repeating-valarms.cpp 2015-05-20 23:23:32 +0000
1578+++ tests/test-eds-ics-repeating-valarms.cpp 2016-04-19 13:10:52 +0000
1579@@ -22,6 +22,7 @@
1580 #include <datetime/alarm-queue-simple.h>
1581 #include <datetime/clock-mock.h>
1582 #include <datetime/engine-eds.h>
1583+#include <datetime/myself.h>
1584 #include <datetime/planner-range.h>
1585
1586 #include <gtest/gtest.h>
1587@@ -41,7 +42,7 @@
1588 TEST_F(VAlarmFixture, MultipleAppointments)
1589 {
1590 // start the EDS engine
1591- auto engine = std::make_shared<EdsEngine>();
1592+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1593
1594 // we need a consistent timezone for the planner and our local DateTimes
1595 constexpr char const * zone_str {"America/Chicago"};
1596@@ -72,14 +73,14 @@
1597 ASSERT_EQ(1, appts.size());
1598 const auto& appt = appts.front();
1599 ASSERT_EQ(8, appt.alarms.size());
1600- EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,35,0)}), appt.alarms[0]);
1601- EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,37,0)}), appt.alarms[1]);
1602- EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,39,0)}), appt.alarms[2]);
1603- EXPECT_EQ(Alarm({"Time to pack!", "", DateTime(gtz,2015,4,23,13,41,0)}), appt.alarms[3]);
1604- EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,35,0)}), appt.alarms[4]);
1605- EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,37,0)}), appt.alarms[5]);
1606- EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,39,0)}), appt.alarms[6]);
1607- EXPECT_EQ(Alarm({"Go to the airport!", "", DateTime(gtz,2015,4,24,10,41,0)}), appt.alarms[7]);
1608+ EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,35,0)}), appt.alarms[0]);
1609+ EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,37,0)}), appt.alarms[1]);
1610+ EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,39,0)}), appt.alarms[2]);
1611+ EXPECT_EQ(Alarm({"Time to pack!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,23,13,41,0)}), appt.alarms[3]);
1612+ EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,35,0)}), appt.alarms[4]);
1613+ EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,37,0)}), appt.alarms[5]);
1614+ EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,39,0)}), appt.alarms[6]);
1615+ EXPECT_EQ(Alarm({"Go to the airport!", "file://" CALENDAR_DEFAULT_SOUND, DateTime(gtz,2015,4,24,10,41,0)}), appt.alarms[7]);
1616
1617 // now let's try this out with AlarmQueue...
1618 // hook the planner up to a SimpleAlarmQueue and confirm that it triggers for each of the reminders
1619
1620=== modified file 'tests/test-eds-ics-tzids-2.cpp'
1621--- tests/test-eds-ics-tzids-2.cpp 2015-07-09 20:56:13 +0000
1622+++ tests/test-eds-ics-tzids-2.cpp 2016-04-19 13:10:52 +0000
1623@@ -22,6 +22,7 @@
1624 #include <datetime/alarm-queue-simple.h>
1625 #include <datetime/clock-mock.h>
1626 #include <datetime/engine-eds.h>
1627+#include <datetime/myself.h>
1628 #include <datetime/planner-range.h>
1629
1630 #include <gtest/gtest.h>
1631@@ -41,7 +42,7 @@
1632 TEST_F(VAlarmFixture, MultipleAppointments)
1633 {
1634 // start the EDS engine
1635- auto engine = std::make_shared<EdsEngine>();
1636+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1637
1638 // we need a consistent timezone for the planner and our local DateTimes
1639 constexpr char const * zone_str {"America/Los_Angeles"};
1640
1641=== modified file 'tests/test-eds-ics-tzids-utc.cpp'
1642--- tests/test-eds-ics-tzids-utc.cpp 2016-03-22 19:13:10 +0000
1643+++ tests/test-eds-ics-tzids-utc.cpp 2016-04-19 13:10:52 +0000
1644@@ -22,6 +22,7 @@
1645 #include <datetime/alarm-queue-simple.h>
1646 #include <datetime/clock-mock.h>
1647 #include <datetime/engine-eds.h>
1648+#include <datetime/myself.h>
1649 #include <datetime/planner-range.h>
1650
1651 #include <gtest/gtest.h>
1652@@ -41,7 +42,7 @@
1653 TEST_F(VAlarmFixture, UTCAppointments)
1654 {
1655 // start the EDS engine
1656- auto engine = std::make_shared<EdsEngine>();
1657+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1658
1659 // we need a consistent timezone for the planner and our local DateTimes
1660 constexpr char const * zone_str {"America/Recife"};
1661
1662=== modified file 'tests/test-eds-ics-tzids.cpp'
1663--- tests/test-eds-ics-tzids.cpp 2015-07-09 19:14:32 +0000
1664+++ tests/test-eds-ics-tzids.cpp 2016-04-19 13:10:52 +0000
1665@@ -22,6 +22,7 @@
1666 #include <datetime/alarm-queue-simple.h>
1667 #include <datetime/clock-mock.h>
1668 #include <datetime/engine-eds.h>
1669+#include <datetime/myself.h>
1670 #include <datetime/planner-range.h>
1671
1672 #include <gtest/gtest.h>
1673@@ -41,7 +42,7 @@
1674 TEST_F(VAlarmFixture, MultipleAppointments)
1675 {
1676 // start the EDS engine
1677- auto engine = std::make_shared<EdsEngine>();
1678+ auto engine = std::make_shared<EdsEngine>(std::make_shared<Myself>());
1679
1680 // we need a consistent timezone for the planner and our local DateTimes
1681 constexpr char const * zone_str {"Europe/Berlin"};
1682
1683=== modified file 'tests/test-notification.cpp'
1684--- tests/test-notification.cpp 2016-02-11 04:30:46 +0000
1685+++ tests/test-notification.cpp 2016-04-19 13:10:52 +0000
1686@@ -63,7 +63,7 @@
1687 bool expected_notify_called;
1688 bool expected_vibrate_called;
1689 } test_appts[] = {
1690- { appt, "reminder", "Event", true, true },
1691+ { appt, "appointment", "Event", true, true },
1692 { ualarm, "alarm-clock", "Alarm", true, true }
1693 };
1694
1695
1696=== modified file 'tests/test-sound.cpp'
1697--- tests/test-sound.cpp 2016-02-10 20:49:01 +0000
1698+++ tests/test-sound.cpp 2016-04-19 13:10:52 +0000
1699@@ -85,7 +85,7 @@
1700
1701 // confirm that the icon passed to Notify was "alarm-clock"
1702 g_variant_get_child (params, 2, "&s", &str);
1703- ASSERT_STREQ("reminder", str);
1704+ ASSERT_STREQ("appointment", str);
1705
1706 // confirm that the hints passed to Notify included a timeout matching duration_minutes
1707 int32_t i32;

Subscribers

People subscribed via source and target branches