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