aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS8
-rw-r--r--CMakeLists.txt22
-rw-r--r--ChangeLog97
-rw-r--r--NEWS16
-rw-r--r--data/CMakeLists.txt35
-rw-r--r--data/ayatana-indicator-datetime.service.in4
-rw-r--r--data/lomiri-indicator-datetime.service.in11
-rw-r--r--debian/ayatana-indicator-datetime-common.install3
-rw-r--r--debian/ayatana-indicator-datetime.install3
-rw-r--r--debian/ayatana-indicator-datetime.links2
-rw-r--r--debian/changelog14
-rw-r--r--debian/compat1
-rw-r--r--debian/control65
-rw-r--r--debian/lomiri-indicator-datetime.install2
-rwxr-xr-xdebian/rules70
-rw-r--r--po/pt.po8
-rw-r--r--src/CMakeLists.txt25
-rw-r--r--src/engine-mkcal.cpp632
-rw-r--r--src/planner-snooze.cpp6
-rw-r--r--tests/CMakeLists.txt51
-rwxr-xr-xtests/run-eds-ics-test.sh10
-rwxr-xr-xtests/run-mkcal-db-test.sh68
-rwxr-xr-xtests/test-eds-ics-alarm-custom-sound.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-all-day-events.cpp8
-rw-r--r--tests/test-eds-ics-all-day-events.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-missing-trigger.cpp20
-rwxr-xr-xtests/test-eds-ics-missing-trigger.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-non-attending-alarms.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-nonrepeating-events.cpp10
-rw-r--r--tests/test-eds-ics-nonrepeating-events.dbbin0 -> 110592 bytes
-rwxr-xr-xtests/test-eds-ics-repeating-events-with-individual-change.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-repeating-events.cpp10
-rw-r--r--tests/test-eds-ics-repeating-events.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-repeating-valarms.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-tzids-2.cpp12
-rw-r--r--tests/test-eds-ics-tzids-2.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-tzids-utc.cpp12
-rw-r--r--tests/test-eds-ics-tzids-utc.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-eds-ics-tzids.cpp12
-rw-r--r--tests/test-eds-ics-tzids.dbbin0 -> 110592 bytes
-rw-r--r--tests/test-timezones.cpp12
41 files changed, 1167 insertions, 82 deletions
diff --git a/AUTHORS b/AUTHORS
index 9c0333b..d725ae4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,10 +17,12 @@ Baka Gaijin <lewdwarrior@waifu.club>
bittin1ddc447d824349b2 <bittin@reimu.nl>
Bob Owen <bobowen@spamcop.net>
Boyuan Yang <073plan@gmail.com>
+Bruno Fragoso <darth_signa@hotmail.com>
ButterflyOfFire <ButterflyOfFire@protonmail.com>
Charles Kerr <charles.kerr@canonical.com>
chrismeurer <christianmeurer@outlook.com>
CI Train Bot <ci-train-bot@canonical.com>
+Cleverson Cândido <optimuspraimu@gmail.com>
Colin Watson <cjwatson@canonical.com>
Cristian Gherman <c_gherman@yahoo.com>
Csaba <csab0825@gmail.com>
@@ -33,6 +35,7 @@ Davit Mayilyan <davit.mayilyan@protonmail.ch>
Didier Roche <didier.roche@canonical.com>
Didier Roche <didrocks@ubuntu.com>
Doma Gergő <domag02@gmail.com>
+Droit <3118138007@qq.com>
Dylan McCall <dylanmccall@ubuntu.com>
Eduardo Addad de Oliveira <duduaddad@gmail.com>
ElectrifiedSpeed <electrifiedsped@gmail.com>
@@ -55,6 +58,7 @@ Heimen Stoffels <vistausss@fastmail.com>
Heimen Stoffels <vistausss@outlook.com>
Henrik Dankvardt <dankvardt@gmail.com>
Hosted Weblate <hosted@weblate.org>
+hugoalh <hugoalh@users.noreply.hosted.weblate.org>
HuNteR GaMinG <rd7128089@gmail.com>
Iain Lane <iain.lane@canonical.com>
Iain Lane <iain@orangesquash.org.uk>
@@ -127,6 +131,7 @@ Phil Clifford <philip.clifford@gmail.com>
phlostically <phlostically@mailinator.com>
Quentin PAGÈS <quentinantonin@free.fr>
Ratchanan Srirattanamet <ratchanan@ubports.com>
+Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>
Renato Araujo Oliveira Filho <renato.filho@canonical.com>
Reza Almanda <rezaalmanda27@gmail.com>
Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>
@@ -154,6 +159,7 @@ Swann Martinet <swann.ranskassa@laposte.net>
Sylke Vicious <silkevicious@tuta.io>
taoky <taoky99@outlook.com>
Ted Gould <ted@gould.cx>
+Temuri Doghonadze <temuri.doghonadze@gmail.com>
THANOS SIOURDAKIS <siourdakisthanos@gmail.com>
thebylito <thebylito@gmail.com>
Tiago Silva Miguel <tiagos.miguel@outlook.com>
@@ -162,6 +168,7 @@ Tobias p <sorenautonom667@gmail.com>
Tomáš Marný <tomik.marny@gmail.com>
Tommy Cheng <csckcac@gmail.com>
Uddin Mtm <saifuddinmutammam@gmail.com>
+umesaburo sagawa <atowa-notonare-yamatonare427@pm.me>
Veselin Georgiev <vvgeorgievv@gmail.com>
Viktar Vauchkevich <victorenator@gmail.com>
WaldiS <admin@sto.ugu.pl>
@@ -176,4 +183,5 @@ Zhaoyu Gan <ganzhaoyu037@sina.com>
Володимир Бриняк <bardvv@gmail.com>
Марс Ямбар <mjambarmeta@gmail.com>
Мира Странная <miraityan2004@gmail.com>
+தமிழ்நேரம் <anishprabu.t@gmail.com>
复予 <clonewith@qq.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d6b893..e20f9fb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required (VERSION 3.13)
-project (ayatana-indicator-datetime VERSION 24.5.0 LANGUAGES C CXX)
+cmake_minimum_required (VERSION 3.16)
+project (ayatana-indicator-datetime VERSION 25.4.0 LANGUAGES C CXX)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
@@ -13,7 +13,7 @@ set (PACKAGE ${CMAKE_PROJECT_NAME})
option(ENABLE_TESTS "Enable all tests and checks" OFF)
option(ENABLE_COVERAGE "Enable coverage reports (includes enabling all tests and checks)" OFF)
option(ENABLE_WERROR "Treat all build warnings as errors" OFF)
-option(ENABLE_LOMIRI_FEATURES "Build with Lomiri-specific libraries, schemas and media" OFF)
+option(ENABLE_LOMIRI_FEATURES "Build with Lomiri-specific libraries, schemas, media and backend" OFF)
if(ENABLE_COVERAGE)
set(ENABLE_TESTS ON)
@@ -61,9 +61,6 @@ set (
libayatana-common>=0.9.3
glib-2.0>=2.36
gio-unix-2.0>=2.36
- libical>=0.48
- libecal-2.0>=3.16
- libedataserver-1.2>=3.5
gstreamer-1.0>=1.2
libnotify>=0.7.6
properties-cpp>=0.0.1
@@ -79,6 +76,7 @@ if (ENABLE_LOMIRI_FEATURES)
lomiri-url-dispatcher>=0
lomiri-sounds
lomiri-schemas
+ libmkcal-qt5
)
pkg_get_variable(ALARM_DEFAULT_SOUND lomiri-sounds alarm_default_sound)
@@ -91,7 +89,19 @@ if (ENABLE_LOMIRI_FEATURES)
-DALARM_DEFAULT_SOUND="${ALARM_DEFAULT_SOUND}"
-DCALENDAR_DEFAULT_SOUND="${CALENDAR_DEFAULT_SOUND}"
)
+
+ find_package (ECM REQUIRED NO_MODULE)
+ list (APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
+ find_package (KF5 COMPONENTS CalendarCore REQUIRED)
else ()
+ list (
+ APPEND
+ SERVICE_DEPS
+ libecal-2.0>=3.16
+ libedataserver-1.2>=3.5
+ libical>=0.48
+ )
+
add_definitions (
-DALARM_DEFAULT_SOUND="dummy"
-DCALENDAR_DEFAULT_SOUND="dummy"
diff --git a/ChangeLog b/ChangeLog
index de464c5..8fb8078 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,101 @@
+2025-04-02 Mike Gabriel
+
+ * release 25.4.0 (HEAD -> main, tag: 25.4.0)
+
+2025-04-01 Robert Tari
+
+ * Merge branch
+ 'sunweaver-pr/dually-build-datetime-indicator-variants'
+ (6214cc82)
+
+2025-03-20 Bruno Fragoso
+
+ * Translated using Weblate (Portuguese) (1e8bfab0)
+
+2025-04-01 Mike Gabriel
+
+ * Bump version to 25.4.0. (8ba92f6c)
+ * debian/: Dually build datetime indicator as
+ ayatana-indicator-datetime and lomiri-indicator-datetime.
+ (54838d78)
+ * d/{control,compat}: Bump to DH compat level version 12. (b21548ca)
+ * d/changelog: set to released (forgotten with 24.5.1 release)
+ (bf9bcc0b)
+ * debian/ayatana-indicator-datetime.links: Drop file. Long not needed
+ anymore. (99b1b574)
+ * CMake: Switch to building datetime indicator in two variants with
+ different service executable names and systemd service
+ files. (e46cd132)
+ * tests/run-mkcal-db-test.sh: Make test script executable. (7f59c03c)
+
+2025-03-20 Bruno Fragoso
+
+ * Translated using Weblate (Portuguese) (84723ee8)
+
+2025-04-01 Mike Gabriel
+
+ * Merge branch 'tari01-pr/mkcal-backend' (8493897d)
+
+2025-02-06 Robert Tari
+
+ * tests/run-eds-ics-test.sh: Quote file paths (be6251cb)
+ * tests/test-timezones.cpp: Avoid potential null pointer (227aa4bc)
+ * Add mkCal backend (e87e6651)
+
+2025-03-12 Mike Gabriel
+
+ * release 24.5.1 (f1f745da) (tag: 24.5.1)
+ * Merge branch 'tari01-pr/libnotify-0-8-4-icon-fix' (22b65e6b)
+
+2025-03-10 Robert Tari
+
+ * Fix missing notification icon with libnotify 0.8.4 (3bd6b2f4)
+
+2025-03-05 Droit
+
+ * Translated using Weblate (Chinese (Simplified) (zh_LATN@pinyin))
+ (d3dc11e4)
+
+2025-02-17 Temuri Doghonadze
+
+ * Translated using Weblate (Georgian) (831f5e82)
+
+2025-02-12 Mike Gabriel
+
+ * Merge branch 'tari01-pr/fix_calendar_not_updated' (439c0f7e)
+
+2024-12-13 Robert Tari
+
+ * fix calendar not refreshed on month range change (04038391)
+
+2025-02-01 Quentin PAGÈS
+
+ * Translated using Weblate (Occitan) (cabe8c5e)
+
+2024-11-13 Cleverson Cândido
+
+ * Translated using Weblate (Portuguese) (65427322)
+
+2024-11-08 தமிழ்நேரம்
+
+ * Translated using Weblate (Tamil) (e34dbedc)
+
+2024-10-30 hugoalh
+
+ * Translated using Weblate (Chinese (Traditional Han script))
+ (4afcdd50)
+
+2024-09-27 Remus-Gabriel Chelu
+
+ * Translated using Weblate (Romanian) (0f5ffc56)
+
+2024-08-13 umesaburo sagawa
+
+ * Translated using Weblate (Japanese) (2439918f)
+
2024-05-22 Mike Gabriel
- * release 24.5.0 (HEAD -> main, tag: 24.5.0)
+ * release 24.5.0 (b6d68d24) (tag: 24.5.0)
2024-05-22 Robert Tari
diff --git a/NEWS b/NEWS
index fbc0fe1..6b24932 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+Overview of changes in ayatana-indicator-datetime 25.4.0
+
+ - Add mkCal backend (to support Lomiri's calendar app backend).
+ - tests/test-timezones.cpp: Avoid potential null pointer.
+ - tests/run-eds-ics-test.sh: Quote file paths.
+ - tests/run-mkcal-db-test.sh: Make test script executable.
+ - CMake: Support building datetime indicator in two variants with
+ different service executable names and systemd service files.
+ - Translation updates.
+
+Overview of changes in ayatana-indicator-datetime 24.5.1
+
+ - Fix calendar not refreshed on month range change.
+ - Fix missing notification icon with libnotify 0.8.4.
+ - Translation updates.
+
Overview of changes in ayatana-indicator-datetime 24.5.0
- data/ayatana-indicator-datetime.service.in: Become part of
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 726bcec..80a5a93 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -1,4 +1,13 @@
##
+## indicator variant
+##
+if (ENABLE_LOMIRI_FEATURES)
+ set (INDICATOR_VARIANT_NAME "lomiri-indicator-datetime")
+else ()
+ set (INDICATOR_VARIANT_NAME "${CMAKE_PROJECT_NAME}")
+endif ()
+
+##
## GSettings schema
##
@@ -22,7 +31,7 @@ if (${SYSTEMD_FOUND})
pkg_get_variable(SYSTEMD_USER_DIR systemd systemduserunitdir)
message (STATUS "${SYSTEMD_USER_DIR} is the systemd user unit file install dir")
- set (SYSTEMD_USER_NAME "${CMAKE_PROJECT_NAME}.service")
+ set (SYSTEMD_USER_NAME "${INDICATOR_VARIANT_NAME}.service")
set (SYSTEMD_USER_FILE "${CMAKE_CURRENT_BINARY_DIR}/${SYSTEMD_USER_NAME}")
set (SYSTEMD_USER_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${SYSTEMD_USER_NAME}.in")
@@ -38,20 +47,22 @@ endif()
## XDG Autostart File
##
-# where to install
-set (XDG_AUTOSTART_DIR "/etc/xdg/autostart")
-message (STATUS "${XDG_AUTOSTART_DIR} is the DBus Service File install dir")
+if (NOT ENABLE_LOMIRI_FEATURES)
+ # where to install
+ set (XDG_AUTOSTART_DIR "/etc/xdg/autostart")
+ message (STATUS "${XDG_AUTOSTART_DIR} is the DBus Service File install dir")
-set (XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.desktop")
-set (XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${XDG_AUTOSTART_NAME}")
-set (XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${XDG_AUTOSTART_NAME}.in")
+ set (XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.desktop")
+ set (XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${XDG_AUTOSTART_NAME}")
+ set (XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${XDG_AUTOSTART_NAME}.in")
-# build it
-configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}")
+ # build it
+ configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}")
-# install XDG autostart
-install (FILES "${XDG_AUTOSTART_FILE}"
- DESTINATION "${XDG_AUTOSTART_DIR}")
+ # install XDG autostart
+ install (FILES "${XDG_AUTOSTART_FILE}"
+ DESTINATION "${XDG_AUTOSTART_DIR}")
+endif()
##
## Ayatana Indicator File
diff --git a/data/ayatana-indicator-datetime.service.in b/data/ayatana-indicator-datetime.service.in
index d0c1941..6b7803b 100644
--- a/data/ayatana-indicator-datetime.service.in
+++ b/data/ayatana-indicator-datetime.service.in
@@ -1,11 +1,11 @@
[Unit]
Description=Ayatana Indicator DateTime Service
PartOf=graphical-session.target
-PartOf=ayatana-indicators.target lomiri-indicators.target
+PartOf=ayatana-indicators.target
[Service]
ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/ayatana-indicator-datetime/ayatana-indicator-datetime-service
Restart=on-failure
[Install]
-WantedBy=ayatana-indicators.target lomiri-indicators.target
+WantedBy=ayatana-indicators.target
diff --git a/data/lomiri-indicator-datetime.service.in b/data/lomiri-indicator-datetime.service.in
new file mode 100644
index 0000000..517ca14
--- /dev/null
+++ b/data/lomiri-indicator-datetime.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=Lomiri Indicator DateTime Service
+PartOf=graphical-session.target
+PartOf=lomiri-indicators.target
+
+[Service]
+ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/lomiri-indicator-datetime/lomiri-indicator-datetime-service
+Restart=on-failure
+
+[Install]
+WantedBy=lomiri-indicators.target
diff --git a/debian/ayatana-indicator-datetime-common.install b/debian/ayatana-indicator-datetime-common.install
new file mode 100644
index 0000000..4c7a9da
--- /dev/null
+++ b/debian/ayatana-indicator-datetime-common.install
@@ -0,0 +1,3 @@
+usr/share/ayatana/indicators/
+usr/share/glib-2.0/schemas/
+usr/share/locale/
diff --git a/debian/ayatana-indicator-datetime.install b/debian/ayatana-indicator-datetime.install
new file mode 100644
index 0000000..b694faa
--- /dev/null
+++ b/debian/ayatana-indicator-datetime.install
@@ -0,0 +1,3 @@
+etc/xdg/autostart/ayatana-indicator-datetime.desktop
+usr/libexec/ayatana-indicator-datetime/ayatana-indicator-datetime-service
+usr/lib/systemd/user/ayatana-indicator-datetime.service
diff --git a/debian/ayatana-indicator-datetime.links b/debian/ayatana-indicator-datetime.links
deleted file mode 100644
index ba57b5b..0000000
--- a/debian/ayatana-indicator-datetime.links
+++ /dev/null
@@ -1,2 +0,0 @@
-# Because dh-systemd does not yet support user units, we manually make the WantedBy link
-/usr/lib/systemd/user/ayatana-indicator-datetime.service /usr/lib/systemd/user/ayatana-indicators.target.wants/ayatana-indicator-datetime.service
diff --git a/debian/changelog b/debian/changelog
index e524368..3d115ac 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+ayatana-indicator-datetime (25.4.0-0) unstable; urgency=medium
+
+ * Upstream-provided Debian package for ayatana-indicator-datetime.
+ See upstream ChangeLog for recent changes.
+
+ -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Wed, 02 Apr 2025 16:21:40 +0200
+
+ayatana-indicator-datetime (24.5.1-0) unstable; urgency=medium
+
+ * Upstream-provided Debian package for ayatana-indicator-datetime.
+ See upstream ChangeLog for recent changes.
+
+ -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Wed, 12 Mar 2025 08:52:32 +0100
+
ayatana-indicator-datetime (24.5.0-0) unstable; urgency=medium
* Upstream-provided Debian package for ayatana-indicator-datetime.
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
index f10f155..64d69f6 100644
--- a/debian/control
+++ b/debian/control
@@ -5,22 +5,28 @@ Maintainer: Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
Build-Depends: cmake,
cmake-extras (>= 0.10),
dbus,
- debhelper (>= 9),
- dh-systemd | hello,
+ debhelper-compat (= 12),
intltool,
libaccounts-glib-dev (>= 1.18),
libayatana-common-dev (>= 0.9.3),
libglib2.0-dev (>= 2.35.4),
libnotify-dev (>= 0.7.6),
libgstreamer1.0-dev,
+ libmessaging-menu-dev,
+ uuid-dev,
+# for non-Lomiri ICS data storage backend
libecal2.0-dev (>= 3.16),
libical-dev (>= 1.0),
libedataserver1.2-dev (>= 3.5),
- lomiri-schemas | hello,
+# for Lomiri ICS data storage backend
+ libkf5calendarcore-dev,
+ libmkcal-qt5-dev,
+# more Lomiri features
+ extra-cmake-modules,
+ lomiri-schemas,
+ lomiri-sounds,
libproperties-cpp-dev,
- liblomiri-url-dispatcher-dev | hello,
- libmessaging-menu-dev,
- uuid-dev,
+ liblomiri-url-dispatcher-dev,
# for the test harness:
libgtest-dev <!nocheck>,
libdbustest1-dev <!nocheck>,
@@ -31,7 +37,9 @@ Build-Depends: cmake,
# for running live EDS tests:
evolution-data-server <!nocheck>,
gvfs-daemons <!nocheck>,
- systemd [linux-any],
+ systemd-dev [linux-any],
+# for running live mkcal tests:
+ mkcal-bin <!nocheck>,
# for phone alarm/calendar notification sound tests:
lomiri-sounds | hello,
# tests that require the org.ayatana.common GSchema
@@ -46,6 +54,7 @@ Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
ayatana-indicator-common,
+ ayatana-indicator-datetime-common (>= ${source:Version}),
libglib2.0-bin,
Recommends: indicator-applet | mate-indicator-applet | xfce4-indicator-plugin | indicator-renderer,
evolution-data-server,
@@ -56,5 +65,43 @@ Description: Ayatana Indicator providing clock and calendar
This Ayatana Indicator provides a combined calendar, clock, alarm and
event management tool.
.
- On Lomiri, this Indicator supports phone devices. On other systems,
- the phone support has been disabled at build-time.
+ This variant of the datetime indicator is to be used for non-Lomiri
+ operating environments such as MATE, Xfce, etc.
+ .
+ This variant of the datetime indicator has been built for using
+ evolution-data-server as ICS data storage backend.
+
+Package: lomiri-indicator-datetime
+Architecture: any
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+ ayatana-indicator-common,
+ ayatana-indicator-datetime-common (>= ${source:Version}),
+ libglib2.0-bin,
+Recommends: geoclue-provider,
+ mkcal-bin,
+Suggests: lomiri,
+Breaks: indicator-datetime,
+Replaces: indicator-datetime,
+Description: Lomiri Indicator providing clock and calendar
+ This Lomiri Indicator provides a combined calendar, clock, alarm and
+ event management tool.
+ .
+ This variant of the datetime indicator is targetted for being used on
+ Lomiri, this indicator supports phone devices.
+ .
+ This variant of the datetime indicator has been built for using
+ msyncd (mkcal) as ICS data storage backend.
+
+Package: ayatana-indicator-datetime-common
+Architecture: any
+Depends: ${misc:Depends},
+Breaks: ayatana-indicator-datetime (<< 25.4.0),
+Replaces: ayatana-indicator-datetime (<< 25.4.0),
+Description: Common files used by both Ayatana/Lomiri Indicator Datetime variants
+ Ayatana / Lomiri Indicator Datetime are two variants of the Ayatana
+ Datetime Indicator built for different use cases. They provide a
+ combined calendar, clock, alarm and event management tool for common
+ desktop environments and for the Lomiri operating environment.
+ .
+ This package contains files used by both variants.
diff --git a/debian/lomiri-indicator-datetime.install b/debian/lomiri-indicator-datetime.install
new file mode 100644
index 0000000..cc3bd95
--- /dev/null
+++ b/debian/lomiri-indicator-datetime.install
@@ -0,0 +1,2 @@
+usr/libexec/lomiri-indicator-datetime/lomiri-indicator-datetime-service
+usr/lib/systemd/user/lomiri-indicator-datetime.service
diff --git a/debian/rules b/debian/rules
index 96adb33..932a8d8 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,14 +1,70 @@
#!/usr/bin/make -f
-LDFLAGS += -Wl,-z,defs -Wl,--as-needed
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/buildflags.mk
+
+DEB_CMAKE_EXTRA_FLAGS = \
+ -DENABLE_COVERAGE=OFF \
+ $(NULL)
+
+ifeq ($(filter nocheck,$(DEB_BUILD_PROFILES)),)
+ DEB_CMAKE_EXTRA_FLAGS += -DENABLE_TESTS=ON
+endif
%:
- dh $@ --with systemd
+ dh $@
-ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
override_dh_auto_configure:
- dh_auto_configure -- -DENABLE_TESTS=ON
-endif
+ dh_auto_configure --builddirectory=lomiri-variant \
+ --buildsystem=cmake \
+ -- \
+ $(DEB_CMAKE_EXTRA_FLAGS) \
+ -DENABLE_LOMIRI_FEATURES=ON \
+ ..
+ dh_auto_configure --builddirectory=ayatana-variant \
+ --buildsystem=cmake \
+ -- \
+ $(DEB_CMAKE_EXTRA_FLAGS) \
+ -DENABLE_LOMIRI_FEATURES=OFF \
+ ..
+
+override_dh_auto_build:
+ dh_auto_build --builddirectory=lomiri-variant \
+ --buildsystem=cmake \
+ ..
+ dh_auto_build --builddirectory=ayatana-variant \
+ --buildsystem=cmake \
+ ..
+
+override_dh_auto_test:
+ dh_auto_test --no-parallel \
+ --builddirectory=lomiri-variant \
+ --buildsystem=cmake \
+ ..
+ dh_auto_test --no-parallel \
+ --builddirectory=ayatana-variant \
+ --buildsystem=cmake \
+ ..
+
+override_dh_auto_install:
+ dh_auto_install --builddirectory=lomiri-variant \
+ --buildsystem=cmake \
+ ..
+ dh_auto_install --builddirectory=ayatana-variant \
+ --buildsystem=cmake \
+ ..
+
+override_dh_auto_clean:
+ dh_auto_clean --builddirectory=lomiri-variant \
+ --buildsystem=cmake \
+ ..
+ dh_auto_clean --builddirectory=ayatana-variant \
+ --buildsystem=cmake \
+ ..
-override_dh_install:
- dh_install --fail-missing
+override_dh_missing:
+ dh_missing --fail-missing
diff --git a/po/pt.po b/po/pt.po
index bd6358a..06d21c6 100644
--- a/po/pt.po
+++ b/po/pt.po
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: indicator-datetime\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-10-10 23:55+0200\n"
-"PO-Revision-Date: 2024-11-14 18:00+0000\n"
-"Last-Translator: Cleverson Cândido <optimuspraimu@gmail.com>\n"
+"PO-Revision-Date: 2025-03-20 10:13+0000\n"
+"Last-Translator: Bruno Fragoso <darth_signa@hotmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/"
"ayatana-indicators/datetime-applet/pt/>\n"
"Language: pt\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 5.9-dev\n"
+"X-Generator: Weblate 5.11-dev\n"
#. Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
#. Format string for the day on the first menuitem in the datetime indicator.
@@ -43,7 +43,7 @@ msgstr "Configurações de data e hora…"
#: src/menu.cpp:555
msgid "Date and Time"
-msgstr "Date and Time"
+msgstr "Data e Hora"
#: src/menu.cpp:564
msgid "Time & date settings, quick calendar access"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2305fdf..2bc4452 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,13 @@
set (SERVICE_LIB "indicatordatetimeservice")
-set (SERVICE_EXEC "ayatana-indicator-datetime-service")
-add_definitions (-DG_LOG_DOMAIN="ayatana-indicator-datetime")
+if (ENABLE_LOMIRI_FEATURES)
+ set (INDICATOR_VARIANT_NAME "lomiri-indicator-datetime")
+else ()
+ set (INDICATOR_VARIANT_NAME "${CMAKE_PROJECT_NAME}")
+endif ()
+
+add_definitions (-DG_LOG_DOMAIN="${INDICATOR_VARIANT_NAME}")
+set (SERVICE_EXEC "${INDICATOR_VARIANT_NAME}-service")
# handwritten sources
set (SERVICE_C_SOURCES
@@ -15,7 +21,6 @@ set (SERVICE_CXX_SOURCES
clock.cpp
clock-live.cpp
date-time.cpp
- engine-eds.cpp
exporter.cpp
formatter.cpp
formatter-desktop.cpp
@@ -41,6 +46,12 @@ set (SERVICE_CXX_SOURCES
wakeup-timer-mainloop.cpp
wakeup-timer-powerd.cpp)
+if (ENABLE_LOMIRI_FEATURES)
+ list (APPEND SERVICE_CXX_SOURCES engine-mkcal.cpp)
+else ()
+ list (APPEND SERVICE_CXX_SOURCES engine-eds.cpp)
+endif()
+
# generated sources
include (GdbusCodegen)
set(SERVICE_GENERATED_SOURCES)
@@ -69,6 +80,12 @@ endif()
include_directories (${CMAKE_SOURCE_DIR})
link_directories (${SERVICE_DEPS_LIBRARY_DIRS})
+if (ENABLE_LOMIRI_FEATURES)
+ set_source_files_properties (engine-mkcal.cpp PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
+ target_link_libraries (${SERVICE_LIB} KF5::CalendarCore)
+ target_compile_definitions (${SERVICE_LIB} PRIVATE -DQT_DEBUG -DQT_MESSAGELOGCONTEXT)
+endif ()
+
add_executable (${SERVICE_EXEC} main.cpp)
target_link_libraries (${SERVICE_EXEC} ${SERVICE_LIB} ${SERVICE_DEPS_LIBRARIES})
-install (TARGETS ${SERVICE_EXEC} RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}")
+install (TARGETS ${SERVICE_EXEC} RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${INDICATOR_VARIANT_NAME}")
diff --git a/src/engine-mkcal.cpp b/src/engine-mkcal.cpp
new file mode 100644
index 0000000..56e4821
--- /dev/null
+++ b/src/engine-mkcal.cpp
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2024-2025 Robert Tari
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Robert Tari <robert@tari.in>
+ */
+
+#include <gio/gio.h>
+#include <datetime/engine-eds.h>
+#include <datetime/myself.h>
+#include <extendedstorage.h>
+#include <QDebug>
+
+namespace ayatana
+{
+ namespace indicator
+ {
+ namespace datetime
+ {
+ class EdsEngine::Impl
+ {
+ public:
+
+ explicit Impl (const std::shared_ptr<Myself> &myself) : pMyself (myself)
+ {
+ this->pMyself->emails ().changed ().connect ([this] (const std::set<std::string> &)
+ {
+ setDirtySoon ();
+ });
+
+ // mKCal::ExtendedStorageObserver does not work
+ const gchar* sHome = g_get_home_dir ();
+ gchar *sDatabase = g_strdup_printf ("%s/.local/share/system/privileged/Calendar/mkcal/db.changed", sHome);
+ GFile *pFile = g_file_new_for_path (sDatabase);
+ g_free (sDatabase);
+ GError *pError = NULL;
+ this->pMonitor = g_file_monitor_file (pFile, G_FILE_MONITOR_NONE, NULL, &pError);
+ g_object_unref (pFile);
+
+ if (!this->pMonitor)
+ {
+ g_warning ("Panic: Error creating file monitor: %s", pError->message);
+ g_error_free (pError);
+ }
+ else
+ {
+ g_signal_connect (this->pMonitor, "changed", G_CALLBACK (onDatabaseChanged), this);
+ }
+ }
+
+ ~Impl ()
+ {
+ if (this->pMonitor)
+ {
+ g_object_unref (this->pMonitor);
+ }
+ }
+
+ core::Signal<>& changed ()
+ {
+ return this->pChanged;
+ }
+
+ void addAlarm (KCalendarCore::Alarm::Ptr pAlarm, std::map<std::pair<DateTime, DateTime>, std::map<DateTime, Alarm>> *pAlarms, QDateTime *pTriggerTime, QTimeZone *pTimeZone, KCalendarCore::Incidence::Ptr pIncidence, bool bAlarm)
+ {
+ /*
+ Loop through lAlarms to get information that we need to build the instance appointments and their alarms.
+
+ Outer map key is the instance component's start + end time. We build Appointment.begin and .end from that.
+
+ Inner map key is the alarm trigger, we build Alarm.time from that.
+
+ Inner map value is the Alarm.
+
+ We map the alarms based on their trigger time so that we can fold together multiple valarms that trigger for the same component at the same time. This is commonplace;
+ e.g. one valarm will have a display action and another will specify a sound to be played.
+ */
+ DateTime cBeginTime = datetimeFromQDateTime (pTriggerTime, pTimeZone);
+ QDateTime cQEndTime = {};
+ const bool bTime = pAlarm->hasTime ();
+
+ if (!bTime)
+ {
+ cQEndTime = *pTriggerTime;
+ }
+ else
+ {
+ cQEndTime = pAlarm->endTime ();
+ }
+
+ DateTime cEndTime = datetimeFromQDateTime (&cQEndTime, pTimeZone);
+ auto dInstanceTime = std::make_pair (cBeginTime, cEndTime);
+ DateTime cTriggerTime = datetimeFromQDateTime (pTriggerTime, pTimeZone);
+ auto &cAlarm = (*pAlarms)[dInstanceTime][cTriggerTime];
+ bool bTextEmpty = cAlarm.text.empty ();
+
+ if (bTextEmpty)
+ {
+ const KCalendarCore::Alarm::Type eType = pAlarm->type ();
+
+ if (eType == KCalendarCore::Alarm::Type::Display)
+ {
+ const QString sText = pAlarm->text ();
+ bool bEmpty = sText.isEmpty ();
+
+ if (!bEmpty)
+ {
+ cAlarm.text = sText.toStdString ();
+ }
+ }
+ }
+
+ bool bAudioEmpty = cAlarm.audio_url.empty ();
+
+ if (bAudioEmpty)
+ {
+ QString sUri = {};
+ const KCalendarCore::Alarm::Type eType = pAlarm->type ();
+
+ if (eType == KCalendarCore::Alarm::Type::Audio)
+ {
+ const QString sFile = pAlarm->audioFile ();
+ bool bEmpty = sFile.isEmpty ();
+
+ if (bEmpty)
+ {
+ cAlarm.audio_url = bAlarm ? "file://" ALARM_DEFAULT_SOUND : "file://" CALENDAR_DEFAULT_SOUND;
+ }
+ else
+ {
+ cAlarm.audio_url = sFile.toStdString ();
+ }
+ }
+ }
+
+ bool bTimeSet = cAlarm.time.is_set ();
+
+ if (!bTimeSet)
+ {
+ cAlarm.time = cTriggerTime;
+ }
+ }
+
+ void getAppointments (const QDateTime *pDateTimeBegin, const QDateTime *pDateTimeEnd, QTimeZone *pTimezone, std::function<void (const std::vector<Appointment>&)> pOnAppointments)
+ {
+ qDebug () << "Getting all appointments from " << *pDateTimeBegin << " to " << *pDateTimeEnd;
+
+ const QDate cDateBegin = pDateTimeBegin->date ();
+ const QDate cDateEnd = pDateTimeEnd->date ();
+
+ // Load the incidences
+ QTimeZone cSystemTimeZone = QTimeZone::systemTimeZone ();
+ mKCal::ExtendedCalendar *pCalendar = new mKCal::ExtendedCalendar (cSystemTimeZone);
+ mKCal::ExtendedCalendar::Ptr pCalendarPtr = mKCal::ExtendedCalendar::Ptr (pCalendar);
+ mKCal::ExtendedStorage::Ptr pStoragePtr = mKCal::ExtendedCalendar::defaultStorage (pCalendarPtr);
+ pStoragePtr->open ();
+ pStoragePtr->load (cDateBegin, cDateEnd);
+
+ // Get the notebooks
+ mKCal::Notebook::List lNotebooks = pStoragePtr->notebooks ();
+ std::map<QString, mKCal::Notebook::Ptr> dNotebooks;
+
+ for (mKCal::Notebook::Ptr pNotebook : lNotebooks)
+ {
+ QString sUid = pNotebook->uid ();
+ dNotebooks[sUid] = pNotebook;
+ }
+
+ std::vector<Appointment> lAppointments;
+ KCalendarCore::Incidence::List lIncidences = pCalendarPtr->incidences ();
+
+ std::sort (lIncidences.begin (), lIncidences.end (), [](const KCalendarCore::Incidence::Ptr &pIncidence1, const KCalendarCore::Incidence::Ptr &pIncidence2)
+ {
+ return (pIncidence1->dtStart () < pIncidence2->dtStart ());
+ });
+
+ // Walk through the incidences to build the appointment list
+ for (KCalendarCore::Incidence::Ptr pIncidence : lIncidences)
+ {
+ QString sCalendar = pCalendarPtr->notebook (pIncidence);
+ bool bAlarm = dNotebooks[sCalendar]->name () == "Alarms";
+ const QString sUid = pIncidence->uid ();
+ bool bEmpty = sUid.isEmpty ();
+
+ if (bEmpty == false)
+ {
+ bool bIncidenceInteresting = isIncidenceInteresting (pIncidence);
+
+ if (bIncidenceInteresting)
+ {
+ const QString sColor = dNotebooks[sCalendar]->color ();
+ std::string sColorStd = sColor.toStdString ();
+ Appointment cAppointment = getAppointment (pIncidence, pTimezone, bAlarm, sColorStd);
+ Appointment *pAppointment = nullptr;
+
+ if (!bAlarm)
+ {
+ // Walk the recurrences and add them
+ const KCalendarCore::Recurrence *pRecurrence = pIncidence->recurrence ();
+ const bool bRecurs = pRecurrence->recurs ();
+
+ if (bRecurs)
+ {
+ QDateTime cRecurrenceStart = pRecurrence->getNextDateTime (*pDateTimeBegin);
+ bool bRecurrenceValid = cRecurrenceStart.isValid ();
+
+ while (bRecurrenceValid && cRecurrenceStart <= *pDateTimeEnd)
+ {
+ Appointment cRecurringAppointment = cAppointment;
+ cRecurringAppointment.begin = datetimeFromQDateTime (&cRecurrenceStart, pTimezone);
+ /*const int64_t nAppointmentEnd = cRecurringAppointment.end.to_unix ();
+ QDateTime cRecurrenceEnd = QDateTime::fromSecsSinceEpoch (nAppointmentEnd);
+ const qint64 nRecurrenceStart = cRecurrenceStart.toSecsSinceEpoch ();
+ QDateTime cIncidenceStart = pIncidence->dtStart ();
+ const qint64 nIncidenceStart = cIncidenceStart.toSecsSinceEpoch ();
+ cRecurrenceEnd = cRecurrenceEnd.addSecs (nRecurrenceStart - nIncidenceStart);*/
+ const QDateTime cRecurrenceEnd = pIncidence->endDateForStart (cRecurrenceStart);
+ cRecurringAppointment.end = datetimeFromQDateTime (&cRecurrenceEnd, pTimezone);
+ lAppointments.push_back (cRecurringAppointment);
+ qDebug () << "Recurrence from " << cRecurringAppointment.begin.format ("%F %T %z").c_str () << " to " << cRecurringAppointment.end.format ("%F %T %z").c_str () << ":" << cRecurringAppointment.summary.c_str ();
+ cRecurrenceStart = pRecurrence->getNextDateTime (cRecurrenceStart);
+ bRecurrenceValid = cRecurrenceStart.isValid ();
+ }
+ }
+ else
+ {
+ lAppointments.push_back (cAppointment);
+ qDebug () << "Event from " << cAppointment.begin.format ("%F %T %z").c_str () << " to " << cAppointment.end.format ("%F %T %z").c_str () << ":" << cAppointment.summary.c_str ();
+
+ }
+
+ pAppointment = &lAppointments.back ();
+ }
+
+ // Generate alarms
+ KCalendarCore::Alarm::List lAlarms = pIncidence->alarms ();
+ std::map<std::pair<DateTime, DateTime>, std::map<DateTime, Alarm>> dAlarms;
+
+ // Walk the alarms and add them
+ for (KCalendarCore::Alarm::Ptr pAlarm : lAlarms)
+ {
+ // we only care about AUDIO or DISPLAY alarms, other kind of alarm will not generate a notification
+ bool bAlarmInteresting = isAlarmInteresting (pAlarm);
+
+ if (bAlarmInteresting)
+ {
+ const int nRepeat = pAlarm->repeatCount ();
+ const KCalendarCore::Duration cSnoozeTime = pAlarm->snoozeTime ();
+ const KCalendarCore::Duration cStartOffset = pAlarm->startOffset ();
+ const int nStartOffset = cStartOffset.asSeconds ();
+
+ if (nRepeat && cSnoozeTime)
+ {
+ const int nSnoozeTime = cSnoozeTime.asSeconds ();
+
+ for (int nIter = 0; nIter < nRepeat + 1; nIter++)
+ {
+ QDateTime cStartDateTime = pIncidence->dtStart ();
+ QDateTime cTriggerTime = cStartDateTime.addSecs (nStartOffset + (nIter * nSnoozeTime));
+ const Qt::TimeSpec cTimeSpec = cTriggerTime.timeSpec ();
+
+ if (cTimeSpec != Qt::LocalTime)
+ {
+ cTriggerTime = cTriggerTime.toTimeZone (*pTimezone);
+ }
+
+ this->addAlarm (pAlarm, &dAlarms, &cTriggerTime, pTimezone, pIncidence, bAlarm);
+ }
+ }
+ else
+ {
+ QDateTime cTriggerTime = (*pDateTimeBegin).addSecs (nStartOffset);
+ cTriggerTime = pAlarm->nextRepetition (cTriggerTime);
+ bool bValid = cTriggerTime.isValid ();
+
+ while (bValid && cTriggerTime <= *pDateTimeEnd)
+ {
+ const Qt::TimeSpec cTimeSpec = cTriggerTime.timeSpec ();
+
+ if (cTimeSpec != Qt::LocalTime)
+ {
+ cTriggerTime = cTriggerTime.toTimeZone (*pTimezone);
+ }
+
+ this->addAlarm (pAlarm, &dAlarms, &cTriggerTime, pTimezone, pIncidence, bAlarm);
+ cTriggerTime = pAlarm->nextRepetition (cTriggerTime);
+ bValid = cTriggerTime.isValid ();
+ }
+ }
+ }
+ }
+
+ for (auto &cAlarm : dAlarms)
+ {
+ if (bAlarm)
+ {
+ pAppointment = new Appointment (cAppointment);
+ pAppointment->begin = cAlarm.first.first;
+ pAppointment->end = cAlarm.first.second;
+ }
+
+ int nAlarms = cAlarm.second.size ();
+ pAppointment->alarms.reserve (nAlarms);
+
+ for (auto &cAlarmSecond : cAlarm.second)
+ {
+ bool bText = cAlarmSecond.second.has_text ();
+ bool bSound = cAlarmSecond.second.has_sound ();
+
+ if (bText || bSound)
+ {
+ pAppointment->alarms.push_back (cAlarmSecond.second);
+ qDebug () << "Alarm at " << cAlarmSecond.second.time.format ("%F %T %z").c_str ();
+ }
+ }
+
+ if (bAlarm)
+ {
+ lAppointments.push_back (*pAppointment);
+ qDebug () << "Alarm from " << (*pAppointment).begin.format ("%F %T %z").c_str () << " to " << (*pAppointment).end.format ("%F %T %z").c_str () << ":" << (*pAppointment).summary.c_str ();
+ delete pAppointment;
+ }
+ }
+ }
+ }
+ else
+ {
+ qWarning () << "Panic: incidence has no UID" << pIncidence;
+ }
+ }
+
+ // Give the caller the sorted finished product
+ auto &pAppointments = lAppointments;
+ std::sort (pAppointments.begin (), pAppointments.end (), [](const Appointment &pAppointment1, const Appointment &pAppointment2){return pAppointment1.begin < pAppointment2.begin;});
+ pOnAppointments (pAppointments);
+
+ qDebug () << "Returning appointments: " << lAppointments.size ();
+
+ pStoragePtr.clear ();
+ }
+
+ private:
+
+ static void onDatabaseChanged (GFileMonitor *pMonitor, GFile *pFile, GFile *OtherFile, GFileMonitorEvent eEvent, gpointer pData)
+ {
+ auto pSelf = static_cast<Impl*> (pData);
+
+ if (eEvent == G_FILE_MONITOR_EVENT_CHANGED)
+ {
+ pSelf->setDirtySoon ();
+ }
+ }
+
+ void setDirtyNow ()
+ {
+ this->pChanged ();
+ }
+
+ static gboolean setDirtyNowStatic (gpointer pSelfPtr)
+ {
+ auto pSelf = static_cast<Impl*> (pSelfPtr);
+ pSelf->nRebuildTag = 0;
+ pSelf->nRebuildDeadline = 0;
+ pSelf->setDirtyNow ();
+
+ return G_SOURCE_REMOVE;
+ }
+
+ void setDirtySoon ()
+ {
+ static constexpr int MIN_BATCH_SEC = 1;
+ static constexpr int MAX_BATCH_SEC = 60;
+ static_assert (MIN_BATCH_SEC <= MAX_BATCH_SEC, "bad boundaries");
+ const auto nNow = time (nullptr);
+
+ // First pass
+ if (this->nRebuildDeadline == 0)
+ {
+ this->nRebuildDeadline = nNow + MAX_BATCH_SEC;
+ this->nRebuildTag = g_timeout_add_seconds (MIN_BATCH_SEC, setDirtyNowStatic, this);
+ }
+ else if (nNow < this->nRebuildDeadline)
+ {
+ g_source_remove (this->nRebuildTag);
+ this->nRebuildTag = g_timeout_add_seconds (MIN_BATCH_SEC, setDirtyNowStatic, this);
+ }
+ }
+
+ static bool isAlarmInteresting (KCalendarCore::Alarm::Ptr pAlarm)
+ {
+ const KCalendarCore::Alarm::Type eType = pAlarm->type ();
+
+ if ((eType == KCalendarCore::Alarm::Type::Audio) || (eType == KCalendarCore::Alarm::Type::Display))
+ {
+ // We don't want disabled alarms
+ const bool bEnabled = pAlarm->enabled ();
+
+ return bEnabled;
+ }
+
+ return false;
+ }
+
+ static DateTime datetimeFromQDateTime (const QDateTime *pDateTime, QTimeZone *pTimeZone)
+ {
+ DateTime cDateTimeOut = {};
+ bool bValid = pDateTime->isValid ();
+
+ if (!bValid)
+ {
+ return cDateTimeOut;
+ }
+
+ const QByteArray sId = pTimeZone->id ();
+ const char *sIdData = sId.constData ();
+ GTimeZone *pGTimeZone = g_time_zone_new_identifier (sIdData);
+ const QDate cDate = pDateTime->date ();
+ const QTime cTime = pDateTime->time ();
+ const int nYear = cDate.year ();
+ const int nMonth = cDate.month ();
+ const int nDay = cDate.day ();
+ const int nHour = cTime.hour ();
+ const int nMinute = cTime.minute ();
+ const int nSecond = cTime.second ();
+ cDateTimeOut = DateTime (pGTimeZone, nYear, nMonth, nDay, nHour, nMinute, nSecond);
+ g_time_zone_unref (pGTimeZone);
+
+ return cDateTimeOut;
+ }
+
+ bool isIncidenceInteresting (KCalendarCore::Incidence::Ptr pIncidence)
+ {
+ // We only want calendar events and todos
+ const KCalendarCore::IncidenceBase::IncidenceType eType = pIncidence->type ();
+
+ if ((eType != KCalendarCore::IncidenceBase::IncidenceType::TypeEvent) && (eType != KCalendarCore::IncidenceBase::IncidenceType::TypeTodo))
+ {
+ return false;
+ }
+
+ // We're not interested in completed or cancelled incidences
+ const KCalendarCore::Incidence::Status eIncidenceStatus = pIncidence->status ();
+
+ if ((eIncidenceStatus == KCalendarCore::Incidence::Status::StatusCompleted) || (eIncidenceStatus == KCalendarCore::Incidence::Status::StatusCanceled))
+ {
+ return false;
+ }
+
+ // We don't want not attending alarms
+ const KCalendarCore::Attendee::List lAttendees = pIncidence->attendees ();
+
+ for (KCalendarCore::Attendee cAttendee : lAttendees)
+ {
+ const QString sEmail = cAttendee.email ();
+ const std::string sEmailStd = sEmail.toStdString ();
+ bool bMyEmail = this->pMyself->isMyEmail (sEmailStd);
+
+ // Check if the user is part of the attendee list
+ if (bMyEmail)
+ {
+ // Check the status
+ const KCalendarCore::Attendee::PartStat eAttendeeStatus = cAttendee.status ();
+ bool bDeclined = (eAttendeeStatus == KCalendarCore::Attendee::PartStat::Declined);
+
+ return !bDeclined;
+ }
+ }
+
+ return true;
+ }
+
+ static Appointment getAppointment (KCalendarCore::Incidence::Ptr pIncidence, QTimeZone *pTimeZone, bool bAlarm, std::string sColor)
+ {
+ Appointment cAppointment;
+
+ // Get Appointment.uid
+ const QString sUid = pIncidence->uid ();
+ cAppointment.uid = sUid.toStdString ();
+
+ // Get Appointment.summary
+ const QString sSummary = pIncidence->summary ();
+ cAppointment.summary = sSummary.toStdString ();
+
+ // Get Appointment.begin
+ QDateTime cBegin = pIncidence->dtStart ();
+ const Qt::TimeSpec cTimeSpecBegin = cBegin.timeSpec ();
+
+ if (cTimeSpecBegin != Qt::LocalTime)
+ {
+ cBegin = cBegin.toTimeZone (*pTimeZone);
+ }
+
+ cAppointment.begin = datetimeFromQDateTime (&cBegin, pTimeZone);
+
+ // Get Appointment.end
+ QDateTime cEnd = {};
+ const KCalendarCore::IncidenceBase::IncidenceType eType = pIncidence->type ();
+
+ if (eType == KCalendarCore::IncidenceBase::IncidenceType::TypeEvent)
+ {
+ KCalendarCore::Event::Ptr pEvent = qSharedPointerCast<KCalendarCore::Event> (pIncidence);
+ cEnd = pEvent->dtEnd ();
+ const Qt::TimeSpec cTimeSpecEnd = cEnd.timeSpec ();
+
+ if (cTimeSpecEnd != Qt::LocalTime)
+ {
+ cEnd = cEnd.toTimeZone (*pTimeZone);
+ }
+
+ // Check for all day event
+ bool bHasEndDate = pEvent->hasEndDate ();
+ bool bAllDay = pIncidence->allDay ();
+
+ if (!bHasEndDate && bAllDay)
+ {
+ cEnd = cBegin.addDays (1);
+ }
+ }
+
+ const bool bValid = cEnd.isValid ();
+
+ if (bValid)
+ {
+ cAppointment.end = datetimeFromQDateTime (&cEnd, pTimeZone);
+ }
+ else
+ {
+ cAppointment.end = cAppointment.begin;
+ }
+
+ // Get Appointment.type
+ if (bAlarm)
+ {
+ cAppointment.type = Appointment::ALARM;
+ }
+ else
+ {
+ cAppointment.type = Appointment::EVENT;
+ }
+
+ // Get Appointment.color
+ cAppointment.color = sColor;
+
+ return cAppointment;
+ }
+
+ core::Signal<> pChanged;
+ guint nRebuildTag {};
+ time_t nRebuildDeadline {};
+ std::shared_ptr<Myself> pMyself;
+ GFileMonitor *pMonitor;
+ };
+
+ EdsEngine::EdsEngine (const std::shared_ptr<Myself> &myself): p (new Impl (myself))
+ {
+ }
+
+ EdsEngine::~EdsEngine () = default;
+
+ core::Signal<>& EdsEngine::changed ()
+ {
+ return this->p->changed ();
+ }
+
+ void EdsEngine::get_appointments (const DateTime &pDateTimeBegin, const DateTime &pDateTimeEnd, const Timezone &pTimezone, std::function<void (const std::vector<Appointment>&)> pFunc)
+ {
+ qint64 nDateTimeBegin = pDateTimeBegin.to_unix ();
+ QDateTime cDateTimeBegin = QDateTime::fromSecsSinceEpoch (nDateTimeBegin, Qt::UTC);
+ qint64 nDateTimeEnd = pDateTimeEnd.to_unix ();
+ QDateTime cDateTimeEnd = QDateTime::fromSecsSinceEpoch (nDateTimeEnd, Qt::UTC);
+ QTimeZone cTimeZone = QTimeZone ();
+ std::string sTimeZone = pTimezone.timezone.get ();
+ const char *sTimeZoneData = sTimeZone.c_str ();
+ QTimeZone cTimezone = QTimeZone (sTimeZoneData);
+ this->p->getAppointments (&cDateTimeBegin, &cDateTimeEnd, &cTimezone, pFunc);
+ }
+
+ void EdsEngine::disable_alarm (const Appointment &pAppointment)
+ {
+ bool bAlarm = pAppointment.is_alarm ();
+
+ if (bAlarm)
+ {
+ QTimeZone cSystemTimeZone = QTimeZone::systemTimeZone ();
+ mKCal::ExtendedCalendar *pCalendar = new mKCal::ExtendedCalendar (cSystemTimeZone);
+ mKCal::ExtendedCalendar::Ptr pCalendarPtr = mKCal::ExtendedCalendar::Ptr (pCalendar);
+ mKCal::ExtendedStorage::Ptr pStoragePtr = mKCal::ExtendedCalendar::defaultStorage (pCalendarPtr);
+ pStoragePtr->open ();
+ const char *sUid = pAppointment.uid.c_str ();
+ pStoragePtr->load (sUid);
+ KCalendarCore::Incidence::List lIncidences = pCalendarPtr->incidences ();
+ bool bChanged = false;
+
+ for (KCalendarCore::Incidence::Ptr pIncidence : lIncidences)
+ {
+ KCalendarCore::Alarm::List lAlarms = pIncidence->alarms ();
+
+ for (KCalendarCore::Alarm::Ptr pAlarm : lAlarms)
+ {
+ const bool bEnabled = pAlarm->enabled ();
+
+ if (bEnabled)
+ {
+ pAlarm->setEnabled (false);
+ bChanged = true;
+ }
+ }
+ }
+
+ if (bChanged)
+ {
+ pStoragePtr->save ();
+ }
+
+ pStoragePtr.clear ();
+ }
+ }
+ }
+ }
+}
diff --git a/src/planner-snooze.cpp b/src/planner-snooze.cpp
index b81c912..3cbd740 100644
--- a/src/planner-snooze.cpp
+++ b/src/planner-snooze.cpp
@@ -1,5 +1,6 @@
/*
* Copyright 2014 Canonical Ltd.
+ * Copyright 2024 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -15,12 +16,11 @@
*
* Authors:
* Charles Kerr <charles.kerr@canonical.com>
+ * Robert Tari <robert@tari.in>
*/
#include <datetime/planner-snooze.h>
-#include <libedataserver/libedataserver.h> // e_uid_new()
-
namespace ayatana {
namespace indicator {
namespace datetime {
@@ -67,7 +67,7 @@ public:
appt.alarms[0].time += offset;
// give it a new ID
- gchar* uid = e_uid_new();
+ gchar* uid = g_uuid_string_random ();
appt.uid = uid;
g_free(uid);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 13dd0d8..4aaee45 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -77,23 +77,40 @@ target_link_libraries (${TEST_NAME} indicatordatetimeservice ${SERVICE_DEPS_LIBR
find_program(DBUS_RUNNER dbus-test-runner)
-function(add_eds_ics_test_by_name name)
- set (TEST_NAME ${name})
- set (COVERAGE_TEST_TARGETS ${COVERAGE_TEST_TARGETS} ${TEST_NAME} PARENT_SCOPE)
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.ics.in"
- "${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics")
- add_executable(${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled)
- target_link_options(${TEST_NAME} PRIVATE -no-pie)
- target_link_libraries (${TEST_NAME} indicatordatetimeservice ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
- add_test (${TEST_NAME}
- ${CMAKE_CURRENT_SOURCE_DIR}/run-eds-ics-test.sh
- ${DBUS_RUNNER} # arg1: dbus-test-runner exec
- ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
- ${TEST_NAME} # arg3: test name
- ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg4: base directory for config file template
- ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics # arg5: the ical file for this test
- ${CMAKE_CURRENT_SOURCE_DIR}/accounts.db) # arg6: online accounts database
-endfunction()
+if (ENABLE_LOMIRI_FEATURES)
+ function(add_eds_ics_test_by_name name)
+ set (TEST_NAME ${name})
+ set (COVERAGE_TEST_TARGETS ${COVERAGE_TEST_TARGETS} ${TEST_NAME} PARENT_SCOPE)
+ add_executable(${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled)
+ target_link_options(${TEST_NAME} PRIVATE -no-pie)
+ target_link_libraries (${TEST_NAME} indicatordatetimeservice ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
+ add_test (${TEST_NAME}
+ ${CMAKE_CURRENT_SOURCE_DIR}/run-mkcal-db-test.sh
+ ${DBUS_RUNNER} # arg1: dbus-test-runner exec
+ ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
+ ${TEST_NAME} # arg3: test name
+ ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.db # arg4: the database file for this test
+ ${CMAKE_CURRENT_SOURCE_DIR}/accounts.db) # arg5: online accounts database
+ endfunction()
+else ()
+ function(add_eds_ics_test_by_name name)
+ set (TEST_NAME ${name})
+ set (COVERAGE_TEST_TARGETS ${COVERAGE_TEST_TARGETS} ${TEST_NAME} PARENT_SCOPE)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.ics.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics")
+ add_executable(${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled)
+ target_link_options(${TEST_NAME} PRIVATE -no-pie)
+ target_link_libraries (${TEST_NAME} indicatordatetimeservice ${DBUSTEST_LIBRARIES} ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
+ add_test (${TEST_NAME}
+ ${CMAKE_CURRENT_SOURCE_DIR}/run-eds-ics-test.sh
+ ${DBUS_RUNNER} # arg1: dbus-test-runner exec
+ ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} # arg2: test executable path
+ ${TEST_NAME} # arg3: test name
+ ${CMAKE_CURRENT_SOURCE_DIR}/test-eds-ics-config-files # arg4: base directory for config file template
+ ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}.ics # arg5: the ical file for this test
+ ${CMAKE_CURRENT_SOURCE_DIR}/accounts.db) # arg6: online accounts database
+ endfunction()
+endif ()
add_eds_ics_test_by_name(test-eds-ics-all-day-events)
add_eds_ics_test_by_name(test-eds-ics-repeating-events)
add_eds_ics_test_by_name(test-eds-ics-nonrepeating-events)
diff --git a/tests/run-eds-ics-test.sh b/tests/run-eds-ics-test.sh
index 4cbc0d3..01ebc48 100755
--- a/tests/run-eds-ics-test.sh
+++ b/tests/run-eds-ics-test.sh
@@ -50,21 +50,21 @@ if [ -d ${CONFIG_DIR} ]; then
fi
# if there's a specific ics file to test, copy it on top of the canned config files
-if [ -e ${ICS_FILE} ]; then
+if [ -e "${ICS_FILE}" ]; then
echo "copying ${ICS_FILE} into $HOME"
mkdir -p ${XDG_DATA_HOME}/evolution/tasks/system/
- cp --verbose --archive ${ICS_FILE} ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics
+ cp --verbose --archive "${ICS_FILE}" ${XDG_DATA_HOME}/evolution/tasks/system/tasks.ics
fi
# prepare online accounts database
-if [ -e ${ACCOUNTS_DB} ]; then
+if [ -e "${ACCOUNTS_DB}" ]; then
echo "copying ${ACCOUNTS_DB} into $HOME"
mkdir -p ${XDG_CONFIG_HOME}/libaccounts-glib/
- cp --verbose --archive ${ACCOUNTS_DB} ${XDG_CONFIG_HOME}/libaccounts-glib/accounts.db
+ cp --verbose --archive "${ACCOUNTS_DB}" ${XDG_CONFIG_HOME}/libaccounts-glib/accounts.db
fi
# run the test
-${TEST_RUNNER} --keep-env --max-wait=90 --task ${TEST_EXEC} --task-name ${TEST_NAME} --wait-until-complete
+${TEST_RUNNER} --keep-env --max-wait=90 --task "${TEST_EXEC}" --task-name ${TEST_NAME} --wait-until-complete
rv=$?
# if the test passed, blow away the tmpdir
diff --git a/tests/run-mkcal-db-test.sh b/tests/run-mkcal-db-test.sh
new file mode 100755
index 0000000..114b9bd
--- /dev/null
+++ b/tests/run-mkcal-db-test.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+SELF=$0 # this script
+TEST_RUNNER=$1 # full executable path of dbus-test-runner
+TEST_EXEC=$2 # full executable path of test app
+TEST_NAME=$3 # test name
+DB_FILE=$4 # database file holding test data
+ACCOUNTS_DB=$5 # online account database
+
+echo "this script: ${SELF}"
+echo "test-runner: ${TEST_RUNNER}"
+echo "test-exec: ${TEST_EXEC}"
+echo "test-name: ${TEST_NAME}"
+echo "db-file: ${DB_FILE}"
+
+# set up the tmpdir
+export TEST_TMP_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d ${TEST_NAME}-XXXXXXXXXX) || exit 1
+echo "running test '${TEST_NAME}' in ${TEST_TMP_DIR}"
+
+# set up the environment variables
+export QT_QPA_PLATFORM=minimal
+export HOME=${TEST_TMP_DIR}
+export XDG_RUNTIME_DIR=${TEST_TMP_DIR}
+export XDG_CACHE_HOME=${TEST_TMP_DIR}/.cache
+export XDG_CONFIG_HOME=${TEST_TMP_DIR}/.config
+export XDG_DATA_HOME=${TEST_TMP_DIR}/.local/share
+export XDG_DESKTOP_DIR=${TEST_TMP_DIR}
+export XDG_DOCUMENTS_DIR=${TEST_TMP_DIR}
+export XDG_DOWNLOAD_DIR=${TEST_TMP_DIR}
+export XDG_MUSIC_DIR=${TEST_TMP_DIR}
+export XDG_PICTURES_DIR=${TEST_TMP_DIR}
+export XDG_PUBLICSHARE_DIR=${TEST_TMP_DIR}
+export XDG_TEMPLATES_DIR=${TEST_TMP_DIR}
+export XDG_VIDEOS_DIR=${TEST_TMP_DIR}
+export GIO_USE_VFS=local # needed to ensure GVFS shuts down cleanly after the test is over
+
+export G_MESSAGES_DEBUG=all
+export G_DBUS_DEBUG=messages
+
+echo HOMEDIR=${HOME}
+rm -rf ${XDG_DATA_HOME}
+
+# if there's a specific db file to test, copy it
+if [ -e "${DB_FILE}" ]; then
+ echo "copying ${DB_FILE} into $HOME"
+ mkdir -p ${XDG_DATA_HOME}/system/privileged/Calendar/mkcal/
+ cp --verbose --archive "${DB_FILE}" ${XDG_DATA_HOME}/system/privileged/Calendar/mkcal/db
+fi
+
+# prepare online accounts database
+if [ -e "${ACCOUNTS_DB}" ]; then
+ echo "copying ${ACCOUNTS_DB} into $HOME"
+ mkdir -p ${XDG_CONFIG_HOME}/libaccounts-glib/
+ cp --verbose --archive "${ACCOUNTS_DB}" ${XDG_CONFIG_HOME}/libaccounts-glib/accounts.db
+fi
+
+# run the test
+${TEST_RUNNER} --keep-env --max-wait=90 --task "${TEST_EXEC}" --task-name ${TEST_NAME} --wait-until-complete
+rv=$?
+
+# if the test passed, blow away the tmpdir
+if [ $rv -eq 0 ]; then
+ sleep 5
+ rm -rf $TEST_TMP_DIR
+fi
+
+# pass the test's return code to the caller.
+exit "$rv"
diff --git a/tests/test-eds-ics-alarm-custom-sound.db b/tests/test-eds-ics-alarm-custom-sound.db
new file mode 100755
index 0000000..f5ba86d
--- /dev/null
+++ b/tests/test-eds-ics-alarm-custom-sound.db
Binary files differ
diff --git a/tests/test-eds-ics-all-day-events.cpp b/tests/test-eds-ics-all-day-events.cpp
index 0fa40fd..e38c7c7 100644
--- a/tests/test-eds-ics-all-day-events.cpp
+++ b/tests/test-eds-ics-all-day-events.cpp
@@ -80,7 +80,11 @@ TEST_F(VAlarmFixture, MultipleAppointments)
// what we expect to get...
Appointment expected_appt;
+#ifndef LOMIRI_FEATURES_ENABLED
expected_appt.uid = "20150521T111538Z-7449-1000-3572-0@ghidorah";
+#else
+ expected_appt.uid = "51340540-a924-468e-b3ee-0c0f222cd0f8";
+#endif
expected_appt.summary = "Memorial Day";
expected_appt.begin = DateTime{gtz,2015,5,25,0,0,0};
expected_appt.end = DateTime{gtz,2015,5,26,0,0,0};
@@ -98,7 +102,11 @@ TEST_F(VAlarmFixture, MultipleAppointments)
EXPECT_PRED3([](auto sColourIn, auto sColourExpected1, auto sColourExpected2)
{
return sColourIn == sColourExpected1 || sColourIn == sColourExpected2;
+#ifndef LOMIRI_FEATURES_ENABLED
}, appt.color, "#becedd", "#62a0ea");
+#else
+ }, appt.color, "#0000FF", "");
+#endif
// cleanup
g_time_zone_unref(gtz);
diff --git a/tests/test-eds-ics-all-day-events.db b/tests/test-eds-ics-all-day-events.db
new file mode 100644
index 0000000..f297366
--- /dev/null
+++ b/tests/test-eds-ics-all-day-events.db
Binary files differ
diff --git a/tests/test-eds-ics-missing-trigger.cpp b/tests/test-eds-ics-missing-trigger.cpp
index 4030999..69ca109 100644
--- a/tests/test-eds-ics-missing-trigger.cpp
+++ b/tests/test-eds-ics-missing-trigger.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Canonical Ltd.
- * Copyright 2021-2024 Robert Tari
+ * Copyright 2021-2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -82,8 +82,13 @@ TEST_F(VAlarmFixture, MissingTriggers)
std::vector<Appointment> expected1;
Appointment a1;
a1.type = Appointment::ALARM;
+#ifndef LOMIRI_FEATURES_ENABLED
a1.uid = "20150617T211838Z-6217-32011-2036-1@lomiri-phablet";
a1.color = "#becedd";
+#else
+ a1.uid = "a0121159-8810-434f-9066-cc3b71e3793f";
+ a1.color = "#0000FF";
+#endif
a1.summary = "One Time Alarm";
a1.begin = DateTime { gtz, 2015, 6, 18, 10, 0, 0};
a1.end = a1.begin;
@@ -94,7 +99,11 @@ TEST_F(VAlarmFixture, MissingTriggers)
expected1.push_back(a1);
// build expected: recurring alarm 1
+#ifndef LOMIRI_FEATURES_ENABLED
a1.uid = "20150617T211913Z-6217-32011-2036-5@lomiri-phablet";
+#else
+ a1.uid = "3b45cbc9-d5c3-49a4-ad29-acc776818259";
+#endif
a1.summary = "Recurring Alarm";
a1.alarms[0].text = a1.summary;
std::array<DateTime,13> recurrences {
@@ -121,8 +130,13 @@ TEST_F(VAlarmFixture, MissingTriggers)
std::vector<Appointment> expected2;
Appointment a2;
a2.type = Appointment::ALARM;
+#ifndef LOMIRI_FEATURES_ENABLED
a2.uid = "20150617T211838Z-6217-32011-2036-1@lomiri-phablet";
a2.color = "#62a0ea";
+#else
+ a2.uid = "a0121159-8810-434f-9066-cc3b71e3793f";
+ a2.color = "";
+#endif
a2.summary = "One Time Alarm";
a2.begin = DateTime { gtz, 2015, 6, 18, 10, 0, 0};
a2.end = a2.begin;
@@ -133,7 +147,11 @@ TEST_F(VAlarmFixture, MissingTriggers)
expected2.push_back(a2);
// build expected: recurring alarm 2
+#ifndef LOMIRI_FEATURES_ENABLED
a2.uid = "20150617T211913Z-6217-32011-2036-5@lomiri-phablet";
+#else
+ a2.uid = "3b45cbc9-d5c3-49a4-ad29-acc776818259";
+#endif
a2.summary = "Recurring Alarm";
a2.alarms[0].text = a2.summary;
for (const auto& time : recurrences) {
diff --git a/tests/test-eds-ics-missing-trigger.db b/tests/test-eds-ics-missing-trigger.db
new file mode 100755
index 0000000..0be974d
--- /dev/null
+++ b/tests/test-eds-ics-missing-trigger.db
Binary files differ
diff --git a/tests/test-eds-ics-non-attending-alarms.db b/tests/test-eds-ics-non-attending-alarms.db
new file mode 100644
index 0000000..fae3aaf
--- /dev/null
+++ b/tests/test-eds-ics-non-attending-alarms.db
Binary files differ
diff --git a/tests/test-eds-ics-nonrepeating-events.cpp b/tests/test-eds-ics-nonrepeating-events.cpp
index 49fc9be..c126dba 100644
--- a/tests/test-eds-ics-nonrepeating-events.cpp
+++ b/tests/test-eds-ics-nonrepeating-events.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Canonical Ltd.
- * Copyright 2021-2024 Robert Tari
+ * Copyright 2021-2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -80,7 +80,11 @@ TEST_F(VAlarmFixture, MultipleAppointments)
// what we expect to get...
Appointment expected_appt;
+#ifndef LOMIRI_FEATURES_ENABLED
expected_appt.uid = "20150520T000726Z-3878-32011-1770-81@lomiri-phablet";
+#else
+ expected_appt.uid = "d7aeb192-8b2c-4427-834f-f30388e9e73c";
+#endif
expected_appt.summary = "Alarm";
std::array<Alarm,1> expected_alarms = {
Alarm({"Alarm", "file://" ALARM_DEFAULT_SOUND, DateTime(gtz,2015,5,20,20,00,0)})
@@ -99,7 +103,11 @@ TEST_F(VAlarmFixture, MultipleAppointments)
EXPECT_PRED3([](auto sColourIn, auto sColourExpected1, auto sColourExpected2)
{
return sColourIn == sColourExpected1 || sColourIn == sColourExpected2;
+ #ifndef LOMIRI_FEATURES_ENABLED
}, appt.color, "#becedd", "#62a0ea");
+ #else
+ }, appt.color, "#0000FF", "");
+ #endif
}
// cleanup
diff --git a/tests/test-eds-ics-nonrepeating-events.db b/tests/test-eds-ics-nonrepeating-events.db
new file mode 100644
index 0000000..4170aff
--- /dev/null
+++ b/tests/test-eds-ics-nonrepeating-events.db
Binary files differ
diff --git a/tests/test-eds-ics-repeating-events-with-individual-change.db b/tests/test-eds-ics-repeating-events-with-individual-change.db
new file mode 100755
index 0000000..6ca01a7
--- /dev/null
+++ b/tests/test-eds-ics-repeating-events-with-individual-change.db
Binary files differ
diff --git a/tests/test-eds-ics-repeating-events.cpp b/tests/test-eds-ics-repeating-events.cpp
index a570d0f..701f8da 100644
--- a/tests/test-eds-ics-repeating-events.cpp
+++ b/tests/test-eds-ics-repeating-events.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Canonical Ltd.
- * Copyright 2021-2024 Robert Tari
+ * Copyright 2021-2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -80,7 +80,11 @@ TEST_F(VAlarmFixture, MultipleAppointments)
// what we expect to get...
Appointment expected_appt;
+#ifndef LOMIRI_FEATURES_ENABLED
expected_appt.uid = "20150507T211449Z-4262-32011-1418-1@lomiri-phablet";
+#else
+ expected_appt.uid = "840ab899-1b0e-4697-9514-dcd336a5e125";
+#endif
expected_appt.summary = "Alarm";
std::array<Alarm,8> expected_alarms = {
Alarm({"Alarm", "file://" ALARM_DEFAULT_SOUND, DateTime(gtz,2015,5, 8,16,40,0)}),
@@ -106,7 +110,11 @@ TEST_F(VAlarmFixture, MultipleAppointments)
EXPECT_PRED3([](auto sColourIn, auto sColourExpected1, auto sColourExpected2)
{
return sColourIn == sColourExpected1 || sColourIn == sColourExpected2;
+ #ifndef LOMIRI_FEATURES_ENABLED
}, appt.color, "#becedd", "#62a0ea");
+ #else
+ }, appt.color, "#0000FF", "");
+ #endif
}
// cleanup
diff --git a/tests/test-eds-ics-repeating-events.db b/tests/test-eds-ics-repeating-events.db
new file mode 100644
index 0000000..ac9a0ea
--- /dev/null
+++ b/tests/test-eds-ics-repeating-events.db
Binary files differ
diff --git a/tests/test-eds-ics-repeating-valarms.db b/tests/test-eds-ics-repeating-valarms.db
new file mode 100644
index 0000000..361fffc
--- /dev/null
+++ b/tests/test-eds-ics-repeating-valarms.db
Binary files differ
diff --git a/tests/test-eds-ics-tzids-2.cpp b/tests/test-eds-ics-tzids-2.cpp
index 1bef68b..aff9de7 100644
--- a/tests/test-eds-ics-tzids-2.cpp
+++ b/tests/test-eds-ics-tzids-2.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Canonical Ltd.
- * Copyright 2021-2024 Robert Tari
+ * Copyright 2021-2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -81,8 +81,13 @@ TEST_F(VAlarmFixture, MultipleAppointments)
// what we expect to get...
std::array<Appointment,1> expected_appts1;
auto appt1 = &expected_appts1[0];
+#ifndef LOMIRI_FEATURES_ENABLED
appt1->uid = "109264742";
appt1->color = "#becedd";
+#else
+ appt1->uid = "4eade898-ffd4-49d6-a43a-c6ca9c20aace";
+ appt1->color = "#0000FF";
+#endif
appt1->summary = "National Incubator Initiative for Clean Energy (NIICE) FOA: Pre-Concept Paper Informational Webinar";
appt1->begin = DateTime{gtz,2014,1,21,11,0,0};
appt1->end = DateTime{gtz,2014,1,21,13,0,0};
@@ -90,8 +95,13 @@ TEST_F(VAlarmFixture, MultipleAppointments)
std::array<Appointment,1> expected_appts2;
auto appt2 = &expected_appts2[0];
+#ifndef LOMIRI_FEATURES_ENABLED
appt2->uid = "109264742";
appt2->color = "#62a0ea";
+#else
+ appt2->uid = "4eade898-ffd4-49d6-a43a-c6ca9c20aace";
+ appt2->color = "";
+#endif
appt2->summary = "National Incubator Initiative for Clean Energy (NIICE) FOA: Pre-Concept Paper Informational Webinar";
appt2->begin = DateTime{gtz,2014,1,21,11,0,0};
appt2->end = DateTime{gtz,2014,1,21,13,0,0};
diff --git a/tests/test-eds-ics-tzids-2.db b/tests/test-eds-ics-tzids-2.db
new file mode 100644
index 0000000..5e2b62d
--- /dev/null
+++ b/tests/test-eds-ics-tzids-2.db
Binary files differ
diff --git a/tests/test-eds-ics-tzids-utc.cpp b/tests/test-eds-ics-tzids-utc.cpp
index d88e95d..8226061 100644
--- a/tests/test-eds-ics-tzids-utc.cpp
+++ b/tests/test-eds-ics-tzids-utc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Canonical Ltd.
- * Copyright 2021-2024 Robert Tari
+ * Copyright 2021-2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -82,16 +82,26 @@ TEST_F(VAlarmFixture, UTCAppointments)
// what we expect to get...
std::array<Appointment,1> expected_appts1;
auto appt1 = &expected_appts1[0];
+#ifndef LOMIRI_FEATURES_ENABLED
appt1->uid = "20160322T132738Z";
appt1->color = "#becedd";
+#else
+ appt1->uid = "17ea8f73-4965-4a9c-9add-4a026a86ec60";
+ appt1->color = "#0000FF";
+#endif
appt1->summary = "UTC event";
appt1->begin = DateTime{gtz,2016,3,22,15,0,0};
appt1->end = DateTime{gtz,2016,3,22,16,0,0};
std::array<Appointment,1> expected_appts2;
auto appt2 = &expected_appts2[0];
+#ifndef LOMIRI_FEATURES_ENABLED
appt2->uid = "20160322T132738Z";
appt2->color = "#62a0ea";
+#else
+ appt2->uid = "17ea8f73-4965-4a9c-9add-4a026a86ec60";
+ appt2->color = "";
+#endif
appt2->summary = "UTC event";
appt2->begin = DateTime{gtz,2016,3,22,15,0,0};
appt2->end = DateTime{gtz,2016,3,22,16,0,0};
diff --git a/tests/test-eds-ics-tzids-utc.db b/tests/test-eds-ics-tzids-utc.db
new file mode 100644
index 0000000..5bc6bad
--- /dev/null
+++ b/tests/test-eds-ics-tzids-utc.db
Binary files differ
diff --git a/tests/test-eds-ics-tzids.cpp b/tests/test-eds-ics-tzids.cpp
index 4999e66..e676001 100644
--- a/tests/test-eds-ics-tzids.cpp
+++ b/tests/test-eds-ics-tzids.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2015 Canonical Ltd.
- * Copyright 2021-2024 Robert Tari
+ * Copyright 2021-2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -81,16 +81,26 @@ TEST_F(VAlarmFixture, MultipleAppointments)
// what we expect to get...
std::array<Appointment,1> expected_appts1;
auto appt1 = &expected_appts1[0];
+#ifndef LOMIRI_FEATURES_ENABLED
appt1->uid = "8ggc30kh89qql8vjumgtug7l14@google.com";
appt1->color = "#becedd";
+#else
+ appt1->uid = "01fd35a6-8fbb-4c31-97e1-71d920190f18";
+ appt1->color = "#0000FF";
+#endif
appt1->summary = "Hello";
appt1->begin = DateTime{gtz,2015,7,1,20,0,0};
appt1->end = DateTime{gtz,2015,7,1,22,0,0};
std::array<Appointment,1> expected_appts2;
auto appt2 = &expected_appts2[0];
+#ifndef LOMIRI_FEATURES_ENABLED
appt2->uid = "8ggc30kh89qql8vjumgtug7l14@google.com";
appt2->color = "#62a0ea";
+#else
+ appt2->uid = "01fd35a6-8fbb-4c31-97e1-71d920190f18";
+ appt2->color = "";
+#endif
appt2->summary = "Hello";
appt2->begin = DateTime{gtz,2015,7,1,20,0,0};
appt2->end = DateTime{gtz,2015,7,1,22,0,0};
diff --git a/tests/test-eds-ics-tzids.db b/tests/test-eds-ics-tzids.db
new file mode 100644
index 0000000..cf18ab3
--- /dev/null
+++ b/tests/test-eds-ics-tzids.db
Binary files differ
diff --git a/tests/test-timezones.cpp b/tests/test-timezones.cpp
index 7144aaf..1cbab16 100644
--- a/tests/test-timezones.cpp
+++ b/tests/test-timezones.cpp
@@ -1,5 +1,6 @@
/*
* Copyright 2013 Canonical Ltd.
+ * Copyright 2025 Robert Tari
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -15,6 +16,7 @@
*
* Authors:
* Charles Kerr <charles.kerr@canonical.com>
+ * Robert Tari <robert@tari.in>
*/
#include "geoclue-fixture.h"
@@ -39,9 +41,13 @@ namespace
void set_file(const std::string& text)
{
auto fp = fopen(TIMEZONE_FILE, "w+");
- fprintf(fp, "%s\n", text.c_str());
- fclose(fp);
- sync();
+
+ if (fp)
+ {
+ fprintf(fp, "%s\n", text.c_str());
+ fclose(fp);
+ sync();
+ }
}
}