Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kcalendarcore for openSUSE:Factory 
checked in at 2022-04-11 23:46:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kcalendarcore (Old)
 and      /work/SRC/openSUSE:Factory/.kcalendarcore.new.1900 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kcalendarcore"

Mon Apr 11 23:46:48 2022 rev:31 rq:968143 version:5.93.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kcalendarcore/kcalendarcore.changes      
2022-03-14 19:35:25.566008383 +0100
+++ /work/SRC/openSUSE:Factory/.kcalendarcore.new.1900/kcalendarcore.changes    
2022-04-11 23:48:00.775914340 +0200
@@ -1,0 +2,18 @@
+Sun Apr  3 10:47:01 UTC 2022 - Christophe Giboudeaux <[email protected]>
+
+- Update to 5.93.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/frameworks/5/5.93.0
+- Changes since 5.92.0:
+  * Notify on notebook change for exceptions.
+  * Note use of low-level libical function
+  * Print more information about errors when loading vCalendars
+  * Implement notebook association when parsing iCal data.
+  * Correct a comment
+  * Fix storing of times with UTC offsets
+  * Second attempt to make testTodoCompletedOnce work all year
+  * Revert "Don't use the current date for recurring todo completion test"
+  * Compare QDateTime times, timespecs, and timezones
+
+-------------------------------------------------------------------

Old:
----
  kcalendarcore-5.92.0.tar.xz
  kcalendarcore-5.92.0.tar.xz.sig

New:
----
  kcalendarcore-5.93.0.tar.xz
  kcalendarcore-5.93.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kcalendarcore.spec ++++++
--- /var/tmp/diff_new_pack.Qsw4Zv/_old  2022-04-11 23:48:03.083887958 +0200
+++ /var/tmp/diff_new_pack.Qsw4Zv/_new  2022-04-11 23:48:03.091887866 +0200
@@ -16,14 +16,14 @@
 #
 
 
-%define _tar_path 5.92
+%define _tar_path 5.93
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
 %{!?_kf5_bugfix_version: %define _kf5_bugfix_version %(echo %{_kf5_version} | 
awk -F. '{print $1"."$2}')}
 %bcond_without released
 Name:           kcalendarcore
-Version:        5.92.0
+Version:        5.93.0
 Release:        0
 Summary:        Library to access and handle calendar data
 License:        LGPL-2.0-or-later


++++++ kcalendarcore-5.92.0.tar.xz -> kcalendarcore-5.93.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/CMakeLists.txt 
new/kcalendarcore-5.93.0/CMakeLists.txt
--- old/kcalendarcore-5.92.0/CMakeLists.txt     2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/CMakeLists.txt     2022-04-02 11:55:43.000000000 
+0200
@@ -1,11 +1,11 @@
 cmake_minimum_required(VERSION 3.16)
-set(KF_VERSION "5.92.0") # handled by release scripts
+set(KF_VERSION "5.93.0") # handled by release scripts
 
 project(KCalendarCore VERSION ${KF_VERSION})
 
 # ECM setup
 include(FeatureSummary)
-find_package(ECM 5.92.0  NO_MODULE)
+find_package(ECM 5.93.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL "https://commits.kde.org/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/autotests/CMakeLists.txt 
new/kcalendarcore-5.93.0/autotests/CMakeLists.txt
--- old/kcalendarcore-5.92.0/autotests/CMakeLists.txt   2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/CMakeLists.txt   2022-04-02 
11:55:43.000000000 +0200
@@ -30,6 +30,7 @@
   testfreebusy
   testincidencerelation
   testicalformat
+  testidentical
   testjournal
   testmemorycalendar
   testperiod
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.92.0/autotests/testdateserialization.cpp 
new/kcalendarcore-5.93.0/autotests/testdateserialization.cpp
--- old/kcalendarcore-5.92.0/autotests/testdateserialization.cpp        
2022-03-05 12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testdateserialization.cpp        
2022-04-02 11:55:43.000000000 +0200
@@ -50,7 +50,7 @@
 // See bug 345565.
 void TestDateSerialization::testTodoCompletedOnce()
 {
-    QDateTime startDate = QDate(2022, 1, 27).startOfDay();
+    QDateTime startDate = QDate(QDate::currentDate().year(), 
QDate::currentDate().month(), 1).startOfDay();
     QDateTime dueDate{startDate.addDays(1)};
 
     Todo::Ptr todo(new Todo);
@@ -80,3 +80,26 @@
     QCOMPARE(todo->dtDue(true), dueDate);
     QCOMPARE(todo->dtDue(false), dueDate.addMonths(1));
 }
+
+// Check that QDateTime values with UTC offsets are handled correctly
+void TestDateSerialization::testUTCOffset()
+{
+    QDateTime startDate({2022, 3, 6}, {10, 25}, Qt::OffsetFromUTC, 3600);
+
+    Event::Ptr event(new Event);
+    event->setDtStart(startDate);
+
+    MemoryCalendar::Ptr cal{new MemoryCalendar(QTimeZone::utc())};
+    cal->addIncidence(event);
+
+    ICalFormat format;
+    QString result = format.toString(cal, QString());
+
+    Incidence::Ptr i = format.fromString(result);
+    QVERIFY(i);
+    QCOMPARE(i->dtStart(), startDate);
+    // Qt::OffsetFromUTC is turned into Qt::Timezone with a "UTC+/-X" timezone 
right now
+    // but Qt::OffsetFromUTC would be equally correct here should this ever 
change in the future
+    QCOMPARE(i->dtStart().timeSpec(), Qt::TimeZone);
+    QCOMPARE(i->dtStart().timeZone().offsetFromUtc(i->dtStart()), 3600);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.92.0/autotests/testdateserialization.h 
new/kcalendarcore-5.93.0/autotests/testdateserialization.h
--- old/kcalendarcore-5.92.0/autotests/testdateserialization.h  2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testdateserialization.h  2022-04-02 
11:55:43.000000000 +0200
@@ -14,6 +14,7 @@
 private Q_SLOTS:
     void testNewRecurringTodo();
     void testTodoCompletedOnce();
+    void testUTCOffset();
 };
 
 #endif // TESTDATESERIALIZATION_H
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/autotests/testicalformat.cpp 
new/kcalendarcore-5.93.0/autotests/testicalformat.cpp
--- old/kcalendarcore-5.92.0/autotests/testicalformat.cpp       2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testicalformat.cpp       2022-04-02 
11:55:43.000000000 +0200
@@ -350,3 +350,42 @@
     QVERIFY(event);
     QCOMPARE(dtStart, event->dtStart());
 }
+
+void ICalFormatTest::testNotebook()
+{
+    Event::Ptr event(new Event);
+    event->setDtStart(QDateTime(QDate(2022, 3, 21), QTime(8, 49), Qt::UTC));
+    Todo::Ptr todo(new Todo);
+    todo->setDtStart(QDateTime(QDate(2022, 3, 21), QTime(8, 49), Qt::UTC));
+    Journal::Ptr journal(new Journal);
+    journal->setDtStart(QDateTime(QDate(2022, 3, 21), QTime(8, 49), Qt::UTC));
+    MemoryCalendar::Ptr calendar(new MemoryCalendar(QTimeZone::utc()));
+    QVERIFY(calendar->addEvent(event));
+    QVERIFY(calendar->addTodo(todo));
+    QVERIFY(calendar->addJournal(journal));
+
+    ICalFormat format;
+    const QString data = format.toString(calendar, QString());
+    QVERIFY(!format.exception());
+
+    calendar->close();
+    QVERIFY(!calendar->event(event->uid(), event->recurrenceId()));
+    QVERIFY(!calendar->todo(todo->uid(), todo->recurrenceId()));
+    QVERIFY(!calendar->journal(journal->uid(), journal->recurrenceId()));
+
+    const QString notebook(QString::fromLatin1("my-imported-notebook"));
+    QVERIFY(calendar->addNotebook(notebook, true));
+    QVERIFY(format.fromString(calendar, data, false, notebook));
+
+    Event::Ptr reloadedEvent = calendar->event(event->uid(), 
event->recurrenceId());
+    QVERIFY(reloadedEvent);
+    Todo::Ptr reloadedTodo = calendar->todo(todo->uid(), todo->recurrenceId());
+    QVERIFY(reloadedTodo);
+    Journal::Ptr reloadedJournal = calendar->journal(journal->uid(), 
journal->recurrenceId());
+    QVERIFY(reloadedJournal);
+
+    QCOMPARE(calendar->incidences(notebook).length(), 3);
+    QCOMPARE(calendar->notebook(reloadedEvent), notebook);
+    QCOMPARE(calendar->notebook(reloadedTodo), notebook);
+    QCOMPARE(calendar->notebook(reloadedJournal), notebook);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/autotests/testicalformat.h 
new/kcalendarcore-5.93.0/autotests/testicalformat.h
--- old/kcalendarcore-5.92.0/autotests/testicalformat.h 2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testicalformat.h 2022-04-02 
11:55:43.000000000 +0200
@@ -26,6 +26,7 @@
     void testRDate();
     void testDateTime_data();
     void testDateTime();
+    void testNotebook();
 };
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/autotests/testidentical.cpp 
new/kcalendarcore-5.93.0/autotests/testidentical.cpp
--- old/kcalendarcore-5.92.0/autotests/testidentical.cpp        1970-01-01 
01:00:00.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testidentical.cpp        2022-04-02 
11:55:43.000000000 +0200
@@ -0,0 +1,71 @@
+/*
+ *  SPDX-FileCopyrightText: 2022 Glen Ditchfield <[email protected]>
+ *  SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include "incidencebase.h"
+
+#include <QTest>
+#include <QTimeZone>
+
+using namespace KCalendarCore;
+
+class TestIdentical: public QObject
+{
+    Q_OBJECT
+private Q_SLOTS:
+
+    void testTrue()
+    {
+        QVERIFY(
+            identical(QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
Qt::LocalTime),
+                      QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
Qt::LocalTime)));
+
+        QVERIFY(
+            identical(QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QTimeZone("Atlantic/Azores")),
+                      QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QTimeZone("Atlantic/Azores"))));
+
+        QVERIFY(identical(QDateTime(), QDateTime()));
+    }
+
+    void testFalse_data()
+    {
+        QTest::addColumn<QDateTime>("dt1");
+        QTest::addColumn<QDateTime>("dt2");
+
+        QTest::newRow("date")
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), Qt::LocalTime)
+            << QDateTime(QDate(2022, 02, 23), QTime(22, 22, 22), 
Qt::LocalTime);
+        QTest::newRow("time")
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), Qt::LocalTime)
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 23), 
Qt::LocalTime);
+
+        // Note:  Qt::LocalTime is used for "floating" date-times; "this time
+        // in the current system time zone".
+        QTest::newRow("timeSpec")
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), Qt::LocalTime)
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QTimeZone::systemTimeZone());
+
+        // Both zones are UTC+0.
+        QTest::newRow("timeZone")
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QTimeZone("Africa/Abidjan"))
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QTimeZone("Africa/Accra"));
+
+        QTest::newRow("invalid timeSpec")
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QDateTime().timeSpec())
+            << QDateTime();
+        QTest::newRow("invalid timeZone")
+            << QDateTime(QDate(2022, 02, 22), QTime(22, 22, 22), 
QDateTime().timeZone())
+            << QDateTime();
+    }
+
+    void testFalse()
+    {
+        QFETCH(QDateTime, dt1);
+        QFETCH(QDateTime, dt2);
+        QVERIFY(!identical(dt1, dt2));
+    }
+};
+
+QTEST_MAIN(TestIdentical)
+#include "testidentical.moc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcalendarcore-5.92.0/autotests/testmemorycalendar.cpp 
new/kcalendarcore-5.93.0/autotests/testmemorycalendar.cpp
--- old/kcalendarcore-5.92.0/autotests/testmemorycalendar.cpp   2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testmemorycalendar.cpp   2022-04-02 
11:55:43.000000000 +0200
@@ -350,6 +350,71 @@
     QVERIFY(!cal->isVisible(event));
 }
 
+class TestCalendarObserver: public Calendar::CalendarObserver
+{
+public:
+    TestCalendarObserver(const Calendar::Ptr &cal)
+        : mCalendar(cal)
+    {
+        cal->registerObserver(this);
+    }
+    ~TestCalendarObserver()
+    {
+        mCalendar->unregisterObserver(this);
+    }
+    void calendarIncidenceChanged(const Incidence::Ptr &incidence) override
+    {
+        mUpdated.append(incidence);
+    }
+    bool hasIncidenceChanged(const Incidence::Ptr &incidence) const
+    {
+        return std::find_if(mUpdated.constBegin(), mUpdated.constEnd(),
+                            [incidence] (const Incidence::Ptr &it) {
+                                return (it->uid() == incidence->uid()
+                                        && it->recurrenceId() == 
incidence->recurrenceId());
+                            }) != mUpdated.constEnd();
+    }
+    Incidence::List mUpdated;
+private:
+    Calendar::Ptr mCalendar;
+};
+
+void MemoryCalendarTest::testNotebookChange()
+{
+    MemoryCalendar::Ptr cal(new MemoryCalendar(QTimeZone::utc()));
+    TestCalendarObserver observer(cal);
+    const QString notebook1 = QLatin1String("Notebook1");
+    const QString notebook2 = QLatin1String("Notebook2");
+
+    QVERIFY(cal->addNotebook(notebook1, true));
+    QVERIFY(cal->addNotebook(notebook2, true));
+
+    Event::Ptr event = Event::Ptr(new Event());
+    event->setDtStart(QDateTime(QDate(2022, 3, 23), QTime(10, 12), Qt::UTC));
+    event->recurrence()->setDaily(1);
+    Incidence::Ptr exception = Calendar::createException(event, 
event->dtStart().addDays(3));
+    QVERIFY(exception);
+    exception->setDtStart(exception->recurrenceId().addSecs(1800));
+    QVERIFY(cal->addIncidence(event));
+    QVERIFY(cal->addIncidence(exception));
+    QVERIFY(cal->notebook(event).isEmpty());
+    QVERIFY(cal->notebook(exception).isEmpty());
+
+    QVERIFY(observer.mUpdated.isEmpty());
+    QVERIFY(cal->setNotebook(event, notebook1));
+    QCOMPARE(cal->notebook(event), notebook1);
+    QCOMPARE(cal->notebook(exception), notebook1);
+    QVERIFY(observer.hasIncidenceChanged(event));
+    QVERIFY(observer.hasIncidenceChanged(exception));
+
+    observer.mUpdated.clear();
+    QVERIFY(cal->setNotebook(event, notebook2));
+    QCOMPARE(cal->notebook(event), notebook2);
+    QCOMPARE(cal->notebook(exception), notebook2);
+    QVERIFY(observer.hasIncidenceChanged(event));
+    QVERIFY(observer.hasIncidenceChanged(exception));
+}
+
 void MemoryCalendarTest::testRawEvents()
 {
     MemoryCalendar::Ptr cal(new MemoryCalendar(QTimeZone::utc()));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/autotests/testmemorycalendar.h 
new/kcalendarcore-5.93.0/autotests/testmemorycalendar.h
--- old/kcalendarcore-5.92.0/autotests/testmemorycalendar.h     2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/autotests/testmemorycalendar.h     2022-04-02 
11:55:43.000000000 +0200
@@ -26,6 +26,7 @@
     void testRawEvents();
     void testRawEventsForDate();
     void testVisibility();
+    void testNotebookChange();
     void testDeleteIncidence();
     void testUpdateIncidence();
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/calendar.cpp 
new/kcalendarcore-5.93.0/src/calendar.cpp
--- old/kcalendarcore-5.92.0/src/calendar.cpp   2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/calendar.cpp   2022-04-02 11:55:43.000000000 
+0200
@@ -433,7 +433,7 @@
                 d->mNotebookIncidences.insert(notebook, incidence);
             }
             notifyIncidenceChanged(inc); // for removing from old notebook
-            // don not remove from mUidToNotebook to keep deleted incidences
+            // do not remove from mUidToNotebook to keep deleted incidences
             d->mNotebookIncidences.remove(old, inc);
         }
     }
@@ -442,6 +442,10 @@
         d->mNotebookIncidences.insert(notebook, inc);
         qCDebug(KCALCORE_LOG) << "setting notebook" << notebook << "for" << 
inc->uid();
         notifyIncidenceChanged(inc); // for inserting into new notebook
+        const Incidence::List list = instances(inc);
+        for (const auto &incidence : list) {
+            notifyIncidenceChanged(incidence);
+        }
     }
 
     return true;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/calformat.h 
new/kcalendarcore-5.93.0/src/calformat.h
--- old/kcalendarcore-5.92.0/src/calformat.h    2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/calformat.h    2022-04-02 11:55:43.000000000 
+0200
@@ -66,7 +66,9 @@
     virtual bool save(const Calendar::Ptr &calendar, const QString &fileName) 
= 0;
 
     /**
-      Loads a calendar from a string
+      Loads a calendar from a string. When a notebook is given, incidences are 
added to this
+      notebook, otherwise no notebook is associated to loaded incidences. The 
notebook
+      should already be added to the calendar, see Calendar::addNotebook().
 
       @param calendar is the Calendar to be loaded.
       @param string is the QString containing the Calendar data.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/event.cpp 
new/kcalendarcore-5.93.0/src/event.cpp
--- old/kcalendarcore-5.92.0/src/event.cpp      2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/event.cpp      2022-04-02 11:55:43.000000000 
+0200
@@ -94,8 +94,7 @@
     } else {
         // If they weren't the same type IncidenceBase::equals would had 
returned false already
         const Event *e = static_cast<const Event *>(&event);
-        return ((dtEnd() == e->dtEnd() && dtEnd().timeSpec() == 
e->dtEnd().timeSpec()) || (!dtEnd().isValid() && !e->dtEnd().isValid()))
-            && transparency() == e->transparency();
+        return identical(dtEnd(), e->dtEnd()) && transparency() == 
e->transparency();
     }
 }
 
@@ -123,7 +122,7 @@
     }
 
     Q_D(Event);
-    if (d->mDtEnd != dtEnd || d->mDtEnd.timeSpec() != dtEnd.timeSpec() || 
hasDuration() == dtEnd.isValid()) {
+    if (!identical(d->mDtEnd, dtEnd) || hasDuration() == dtEnd.isValid()) {
         update();
         d->mDtEnd = dtEnd;
         d->mMultiDayValid = false;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/freebusy.cpp 
new/kcalendarcore-5.93.0/src/freebusy.cpp
--- old/kcalendarcore-5.92.0/src/freebusy.cpp   2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/freebusy.cpp   2022-04-02 11:55:43.000000000 
+0200
@@ -325,7 +325,7 @@
         Q_D(const FreeBusy);
         // If they weren't the same type IncidenceBase::equals would had 
returned false already
         const FreeBusy *fb = static_cast<const FreeBusy *>(&freeBusy);
-        return dtEnd() == fb->dtEnd() && d->mBusyPeriods == 
fb->d_func()->mBusyPeriods;
+        return identical(dtEnd(), fb->dtEnd()) && d->mBusyPeriods == 
fb->d_func()->mBusyPeriods;
     }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/icalformat.cpp 
new/kcalendarcore-5.93.0/src/icalformat.cpp
--- old/kcalendarcore-5.92.0/src/icalformat.cpp 2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/icalformat.cpp 2022-04-02 11:55:43.000000000 
+0200
@@ -81,6 +81,9 @@
     file.close();
 
     if (!text.isEmpty()) {
+        if (!calendar->hasValidNotebook(fileName) && 
!calendar->addNotebook(fileName, true)) {
+            qCWarning(KCALCORE_LOG) << "Unable to add" << fileName << "as a 
notebook in calendar";
+        }
         if (!fromRawString(calendar, text, false, fileName)) {
             qCWarning(KCALCORE_LOG) << fileName << " is not a valid iCalendar 
file";
             setException(new Exception(Exception::ParseErrorIcal));
@@ -180,7 +183,6 @@
 
 bool ICalFormat::fromRawString(const Calendar::Ptr &cal, const QByteArray 
&string, bool deleted, const QString &notebook)
 {
-    Q_UNUSED(notebook);
     // Get first VCALENDAR component.
     // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components
     icalcomponent *calendar;
@@ -216,7 +218,7 @@
         success = false;
     } else {
         // put all objects into their proper places
-        if (!d->mImpl->populate(cal, calendar, deleted)) {
+        if (!d->mImpl->populate(cal, calendar, deleted, notebook)) {
             qCDebug(KCALCORE_LOG) << "Could not populate calendar";
             if (!exception()) {
                 setException(new Exception(Exception::ParseErrorKcal));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/icalformat.h 
new/kcalendarcore-5.93.0/src/icalformat.h
--- old/kcalendarcore-5.92.0/src/icalformat.h   2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/icalformat.h   2022-04-02 11:55:43.000000000 
+0200
@@ -68,8 +68,6 @@
     /**
       @copydoc
       CalFormat::fromString()
-
-      @note The notebook is ignored and the default one is used
     */
     bool fromString(const Calendar::Ptr &calendar, const QString &string, bool 
deleted = false, const QString &notebook = QString()) override;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/icalformat_p.cpp 
new/kcalendarcore-5.93.0/src/icalformat_p.cpp
--- old/kcalendarcore-5.92.0/src/icalformat_p.cpp       2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/src/icalformat_p.cpp       2022-04-02 
11:55:43.000000000 +0200
@@ -2298,6 +2298,12 @@
     return t;
 }
 
+static bool dateTimeIsInUTC(const QDateTime &datetime)
+{
+    return datetime.timeSpec() == Qt::UTC || (datetime.timeSpec() == 
Qt::TimeZone && datetime.timeZone() == QTimeZone::utc())
+        || (datetime.timeSpec() == Qt::OffsetFromUTC && 
datetime.offsetFromUtc() == 0);
+}
+
 icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &datetime, bool 
dateOnly)
 {
     icaltimetype t = icaltime_null_time();
@@ -2314,9 +2320,7 @@
         t.second = datetime.time().second();
     }
     t.zone = nullptr; // zone is NOT set
-    if (datetime.timeSpec() == Qt::UTC ||
-        (datetime.timeSpec() == Qt::TimeZone && datetime.timeZone() == 
QTimeZone::utc()) ||
-        (datetime.timeSpec() == Qt::OffsetFromUTC && datetime.offsetFromUtc() 
== 0)) {
+    if (dateTimeIsInUTC(datetime)) {
         t = icaltime_convert_to_zone(t, icaltimezone_get_utc_timezone());
     }
     return t;
@@ -2384,7 +2388,7 @@
     }
 
     QTimeZone qtz;
-    if (!icaltime_is_utc(t) && dt.timeSpec() == Qt::TimeZone) {
+    if (!icaltime_is_utc(t) && !dateTimeIsInUTC(dt) && dt.timeSpec() != 
Qt::LocalTime) {
         qtz = dt.timeZone();
     }
 
@@ -2659,8 +2663,6 @@
 // that is used internally in the ICalFormatImpl.
 bool ICalFormatImpl::populate(const Calendar::Ptr &cal, icalcomponent 
*calendar, bool deleted, const QString &notebook)
 {
-    Q_UNUSED(notebook);
-
     // qCDebug(KCALCORE_LOG)<<"Populate called";
 
     // this function will populate the caldict dictionary and other event
@@ -2776,6 +2778,9 @@
                 // qCDebug(KCALCORE_LOG) << "Adding todo " << todo.data() << 
todo->uid();
                 cal->addTodo(todo); // just add this one
             }
+            if (!notebook.isEmpty() && cal->todo(todo->uid(), 
todo->recurrenceId())) {
+                cal->setNotebook(todo, notebook);
+            }
         }
         c = icalcomponent_get_next_component(calendar, ICAL_VTODO_COMPONENT);
     }
@@ -2816,6 +2821,9 @@
                 // qCDebug(KCALCORE_LOG) << "Adding event " << event.data() << 
event->uid();
                 cal->addEvent(event); // just add this one
             }
+            if (!notebook.isEmpty() && cal->event(event->uid(), 
event->recurrenceId())) {
+                cal->setNotebook(event, notebook);
+            }
         }
         c = icalcomponent_get_next_component(calendar, ICAL_VEVENT_COMPONENT);
     }
@@ -2842,6 +2850,9 @@
             } else {
                 cal->addJournal(journal); // just add this one
             }
+            if (!notebook.isEmpty() && cal->journal(journal->uid(), 
journal->recurrenceId())) {
+                cal->setNotebook(journal, notebook);
+            }
         }
         c = icalcomponent_get_next_component(calendar, 
ICAL_VJOURNAL_COMPONENT);
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/incidencebase.cpp 
new/kcalendarcore-5.93.0/src/incidencebase.cpp
--- old/kcalendarcore-5.92.0/src/incidencebase.cpp      2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/src/incidencebase.cpp      2022-04-02 
11:55:43.000000000 +0200
@@ -164,7 +164,7 @@
     // of much use. We are not comparing for identity, after all.
     // no need to compare mObserver
 
-    bool a = ((dtStart() == other.dtStart() && dtStart().timeSpec() == 
other.dtStart().timeSpec()) || (!dtStart().isValid() && 
!other.dtStart().isValid()));
+    bool a = identical(dtStart(), other.dtStart());
     bool b = organizer() == other.organizer();
     bool c = uid() == other.uid();
     bool d = allDay() == other.allDay();
@@ -267,7 +267,7 @@
         qCWarning(KCALCORE_LOG) << "Invalid dtStart";
     }
 
-    if (d_ptr->mDtStart != dtStart || d_ptr->mDtStart.timeSpec() != 
dtStart.timeSpec()) {
+    if (!identical(d_ptr->mDtStart, dtStart)) {
         update();
         d_ptr->mDtStart = dtStart;
         d_ptr->mDirtyFields.insert(FieldDtStart);
@@ -614,6 +614,11 @@
     return KCALCORE_MAGIC_NUMBER;
 }
 
+bool KCalendarCore::identical(QDateTime dt1, QDateTime dt2)
+{
+    return dt1 == dt2 && dt1.timeSpec() == dt2.timeSpec() && dt1.timeZone() == 
dt2.timeZone();
+}
+
 QDataStream &KCalendarCore::operator<<(QDataStream &out, const 
KCalendarCore::IncidenceBase::Ptr &i)
 {
     if (!i) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/incidencebase.h 
new/kcalendarcore-5.93.0/src/incidencebase.h
--- old/kcalendarcore-5.92.0/src/incidencebase.h        2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/src/incidencebase.h        2022-04-02 
11:55:43.000000000 +0200
@@ -779,6 +779,18 @@
 };
 
 /**
+ * Compare two QDateTimes for extended equality.
+ *
+ * QDateTime::operator==() in Qt 5.12 returns true if its operands represent
+ * the same instant in time, regardless of their time zones or TimeSpecs (and
+ * contrary to the documentation).  This function returns true if and only if
+ * their times, time zones, and TimeSpecs are equal, or both are invalid().
+ *
+ * @since 5.93
+ */
+KCALENDARCORE_EXPORT bool identical(QDateTime, QDateTime);
+
+/**
  * Incidence serializer.
  *
  * @since 4.12
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/period.cpp 
new/kcalendarcore-5.93.0/src/period.cpp
--- old/kcalendarcore-5.92.0/src/period.cpp     2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/period.cpp     2022-04-02 11:55:43.000000000 
+0200
@@ -17,6 +17,7 @@
   @author Cornelius Schumacher \<[email protected]\>
 */
 
+#include "incidencebase.h"
 #include "period.h"
 #include "utils_p.h"
 
@@ -81,8 +82,8 @@
 
 bool Period::operator==(const Period &other) const
 {
-    return ((d->mStart == other.d->mStart) || (!d->mStart.isValid() && 
!other.d->mStart.isValid()))
-        && ((d->mEnd == other.d->mEnd) || (!d->mEnd.isValid() && 
!other.d->mEnd.isValid())) && d->mHasDuration == other.d->mHasDuration;
+    return identical(d->mStart, other.d->mStart) && identical(d->mEnd, 
other.d->mEnd)
+        && d->mHasDuration == other.d->mHasDuration;
 }
 
 Period &Period::operator=(const Period &other)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/recurrence.cpp 
new/kcalendarcore-5.93.0/src/recurrence.cpp
--- old/kcalendarcore-5.92.0/src/recurrence.cpp 2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/recurrence.cpp 2022-04-02 11:55:43.000000000 
+0200
@@ -8,6 +8,8 @@
 
   SPDX-License-Identifier: LGPL-2.0-or-later
 */
+
+#include "incidencebase.h"
 #include "recurrence.h"
 #include "recurrencehelper_p.h"
 #include "utils_p.h"
@@ -68,7 +70,7 @@
 bool Recurrence::Private::operator==(const Recurrence::Private &p) const
 {
     //   qCDebug(KCALCORE_LOG) << mStartDateTime << p.mStartDateTime;
-    if ((mStartDateTime != p.mStartDateTime && (mStartDateTime.isValid() || 
p.mStartDateTime.isValid())) || mAllDay != p.mAllDay
+    if (!identical(mStartDateTime, p.mStartDateTime) || mAllDay != p.mAllDay
         || mRecurReadOnly != p.mRecurReadOnly || mExDates != p.mExDates || 
mExDateTimes != p.mExDateTimes || mRDates != p.mRDates
         || mRDateTimes != p.mRDateTimes || mRDateTimePeriods != 
p.mRDateTimePeriods) {
         return false;
@@ -475,7 +477,7 @@
         return;
     }
 
-    if (dateTime != rrule->endDt()) {
+    if (!identical(dateTime, rrule->endDt())) {
         rrule->setEndDt(dateTime);
         updated();
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/recurrencerule.cpp 
new/kcalendarcore-5.93.0/src/recurrencerule.cpp
--- old/kcalendarcore-5.92.0/src/recurrencerule.cpp     2022-03-05 
12:10:30.000000000 +0100
+++ new/kcalendarcore-5.93.0/src/recurrencerule.cpp     2022-04-02 
11:55:43.000000000 +0200
@@ -6,6 +6,8 @@
 
   SPDX-License-Identifier: LGPL-2.0-or-later
 */
+
+#include "incidencebase.h"
 #include "recurrencerule.h"
 #include "kcalendarcore_debug.h"
 #include "recurrencehelper_p.h"
@@ -813,8 +815,8 @@
 
 bool RecurrenceRule::Private::operator==(const Private &r) const
 {
-    return mPeriod == r.mPeriod && ((mDateStart == r.mDateStart) || 
(!mDateStart.isValid() && !r.mDateStart.isValid())) && mDuration == r.mDuration
-        && ((mDateEnd == r.mDateEnd) || (!mDateEnd.isValid() && 
!r.mDateEnd.isValid())) && mFrequency == r.mFrequency && mIsReadOnly == 
r.mIsReadOnly
+    return mPeriod == r.mPeriod && identical(mDateStart, r.mDateStart) && 
mDuration == r.mDuration
+        && identical(mDateEnd, r.mDateEnd) && mFrequency == r.mFrequency && 
mIsReadOnly == r.mIsReadOnly
         && mAllDay == r.mAllDay && mBySeconds == r.mBySeconds && mByMinutes == 
r.mByMinutes && mByHours == r.mByHours && mByDays == r.mByDays
         && mByMonthDays == r.mByMonthDays && mByYearDays == r.mByYearDays && 
mByWeekNumbers == r.mByWeekNumbers && mByMonths == r.mByMonths
         && mBySetPos == r.mBySetPos && mWeekStart == r.mWeekStart && 
mNoByRules == r.mNoByRules;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/todo.cpp 
new/kcalendarcore-5.93.0/src/todo.cpp
--- old/kcalendarcore-5.92.0/src/todo.cpp       2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/todo.cpp       2022-04-02 11:55:43.000000000 
+0200
@@ -91,7 +91,7 @@
 
 void TodoPrivate::setDtDue(const QDateTime dd)
 {
-    if (dd != mDtDue || dd.timeSpec() != mDtDue.timeSpec()) {
+    if (!identical(dd, mDtDue)) {
         mDtDue = dd;
         mDirtyFields.insert(IncidenceBase::FieldDtDue);
     }
@@ -99,7 +99,7 @@
 
 void TodoPrivate::setDtRecurrence(const QDateTime dr)
 {
-    if (dr != mDtRecurrence) {
+    if (!identical(dr, mDtRecurrence)) {
         mDtRecurrence = dr;
         mDirtyFields.insert(IncidenceBase::FieldRecurrenceId);
     }
@@ -171,7 +171,7 @@
     } else {
         // If they weren't the same type IncidenceBase::equals would had 
returned false already
         const Todo *t = static_cast<const Todo *>(&todo);
-        return ((dtDue() == t->dtDue() && dtDue().timeSpec() == 
t->dtDue().timeSpec()) || (!dtDue().isValid() && !t->dtDue().isValid()))
+        return identical(dtDue(), t->dtDue())
             && hasDueDate() == t->hasDueDate()
             && hasStartDate() == t->hasStartDate() && ((completed() == 
t->completed()) || (!completed().isValid() && !t->completed().isValid()))
             && hasCompletedDate() == t->hasCompletedDate() && 
percentComplete() == t->percentComplete();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcalendarcore-5.92.0/src/vcalformat.cpp 
new/kcalendarcore-5.93.0/src/vcalformat.cpp
--- old/kcalendarcore-5.92.0/src/vcalformat.cpp 2022-03-05 12:10:30.000000000 
+0100
+++ new/kcalendarcore-5.93.0/src/vcalformat.cpp 2022-04-02 11:55:43.000000000 
+0200
@@ -81,6 +81,11 @@
     delete d;
 }
 
+static void mimeErrorHandler(char *e)
+{
+    qCWarning(KCALCORE_LOG) << "Error parsing vCalendar file:" << e;
+}
+
 bool VCalFormat::load(const Calendar::Ptr &calendar, const QString &fileName)
 {
     d->mCalendar = calendar;
@@ -89,7 +94,9 @@
 
     // this is not necessarily only 1 vcal.  Could be many vcals, or include
     // a vcard...
+    registerMimeErrorHandler(&mimeErrorHandler);    // Note: vCalendar error 
handler provided by libical.
     VObject *vcal = Parse_MIME_FromFileName(const_cast<char 
*>(QFile::encodeName(fileName).data()));
+    registerMimeErrorHandler(nullptr);
 
     if (!vcal) {
         setException(new Exception(Exception::CalVersionUnknown));

Reply via email to