diff options
41 files changed, 1167 insertions, 82 deletions
@@ -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" @@ -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 @@ -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 @@ -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 Binary files differnew file mode 100755 index 0000000..f5ba86d --- /dev/null +++ b/tests/test-eds-ics-alarm-custom-sound.db 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 Binary files differnew file mode 100644 index 0000000..f297366 --- /dev/null +++ b/tests/test-eds-ics-all-day-events.db 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 Binary files differnew file mode 100755 index 0000000..0be974d --- /dev/null +++ b/tests/test-eds-ics-missing-trigger.db diff --git a/tests/test-eds-ics-non-attending-alarms.db b/tests/test-eds-ics-non-attending-alarms.db Binary files differnew file mode 100644 index 0000000..fae3aaf --- /dev/null +++ b/tests/test-eds-ics-non-attending-alarms.db 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 Binary files differnew file mode 100644 index 0000000..4170aff --- /dev/null +++ b/tests/test-eds-ics-nonrepeating-events.db diff --git a/tests/test-eds-ics-repeating-events-with-individual-change.db b/tests/test-eds-ics-repeating-events-with-individual-change.db Binary files differnew file mode 100755 index 0000000..6ca01a7 --- /dev/null +++ b/tests/test-eds-ics-repeating-events-with-individual-change.db 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 Binary files differnew file mode 100644 index 0000000..ac9a0ea --- /dev/null +++ b/tests/test-eds-ics-repeating-events.db diff --git a/tests/test-eds-ics-repeating-valarms.db b/tests/test-eds-ics-repeating-valarms.db Binary files differnew file mode 100644 index 0000000..361fffc --- /dev/null +++ b/tests/test-eds-ics-repeating-valarms.db 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 Binary files differnew file mode 100644 index 0000000..5e2b62d --- /dev/null +++ b/tests/test-eds-ics-tzids-2.db 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 Binary files differnew file mode 100644 index 0000000..5bc6bad --- /dev/null +++ b/tests/test-eds-ics-tzids-utc.db 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 Binary files differnew file mode 100644 index 0000000..cf18ab3 --- /dev/null +++ b/tests/test-eds-ics-tzids.db 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(); + } } } |