Branch 'kolab/integration/4.13.0' - 2 commits - akonadi/calendar
Sandro Knauß
knauss at kolabsys.com
Thu Mar 5 15:15:47 CET 2015
akonadi/calendar/incidencechanger.cpp | 59 +++++-
akonadi/calendar/tests/incidencechangertest.cpp | 219 ++++++++++++++++++++++++
2 files changed, 273 insertions(+), 5 deletions(-)
New commits:
commit d204ffcb187c762a089091b40adadca9b6353b11
Author: Sandro Knauà <knauss at kolabsys.com>
Date: Thu Mar 5 15:12:20 2015 +0100
Only alarm modifications should not trigger a out-of-sync event
Users should be able to set their own alarm settings for events without
triggering a out-of-sync dialog.
KOLAB #1386
diff --git a/akonadi/calendar/incidencechanger.cpp b/akonadi/calendar/incidencechanger.cpp
index a038ced..8f51cef 100644
--- a/akonadi/calendar/incidencechanger.cpp
+++ b/akonadi/calendar/incidencechanger.cpp
@@ -69,6 +69,20 @@ bool weAreOrganizer(Incidence::Ptr incidence)
return Akonadi::CalendarUtils::thatIsMe(email);
}
+bool allowedModificationsWithoutRevisionUpdate(Incidence::Ptr incidence)
+{
+ // Modifications that are per user allowd without getting outofsync with organisator
+ // * if only alarm settings are modified.
+ const QSet<KCalCore::IncidenceBase::Field> dirtyFields = incidence->dirtyFields();
+ QSet<KCalCore::IncidenceBase::Field> alarmOnlyModify;
+ alarmOnlyModify << IncidenceBase::FieldAlarms << IncidenceBase::FieldLastModified;
+ if (dirtyFields == alarmOnlyModify) {
+ return true;
+ }
+
+ return false;
+}
+
namespace Akonadi {
// Does a queued emit, with QMetaObject::invokeMethod
static void emitCreateFinished(IncidenceChanger *changer,
@@ -558,6 +572,11 @@ void IncidenceChanger::Private::handleInvitationsBeforeChange(const Change::Ptr
break;
}
+ if (allowedModificationsWithoutRevisionUpdate(newIncidence)) {
+ change->emitUserDialogClosedBeforeChange(ITIPHandlerHelper::ResultSuccess);
+ return;
+ }
+
if (RUNNING_UNIT_TESTS && !weAreOrganizer(newIncidence)) {
// This is a bit of a workaround when running tests. I don't want to show the
// "You're not organizer, do you want to modify event?" dialog in unit-tests, but want
@@ -679,6 +698,10 @@ void IncidenceChanger::Private::handleInvitationsAfterChange(const Change::Ptr &
break;
}
+ if (allowedModificationsWithoutRevisionUpdate(newIncidence)) {
+ break;
+ }
+
if (!neverSend && !alwaysSend && mInvitationStatusByAtomicOperation.contains(change->atomicOperationId)) {
handler->setDefaultAction(actionFromStatus(mInvitationStatusByAtomicOperation.value(change->atomicOperationId)));
}
@@ -1028,9 +1051,11 @@ void IncidenceChanger::Private::performModification2(int changeId, ITIPHandlerHe
}
Incidence::Ptr incidence = CalendarUtils::incidence(newItem);
- { // increment revision ( KCalCore revision, not akonadi )
- const int revision = incidence->revision();
- incidence->setRevision(revision + 1);
+ {
+ if (!allowedModificationsWithoutRevisionUpdate(incidence)) { // increment revision ( KCalCore revision, not akonadi )
+ const int revision = incidence->revision();
+ incidence->setRevision(revision + 1);
+ }
//Reset attendee status, when resceduling
QSet<IncidenceBase::Field> resetPartStatus;
diff --git a/akonadi/calendar/tests/incidencechangertest.cpp b/akonadi/calendar/tests/incidencechangertest.cpp
index 1766d9d..2cce1ed 100644
--- a/akonadi/calendar/tests/incidencechangertest.cpp
+++ b/akonadi/calendar/tests/incidencechangertest.cpp
@@ -377,6 +377,48 @@ private Q_SLOTS:
}
}
+ void testModifyingAlarmSettings()
+ {
+ // A user should be able to change alarm settings independently
+ // do not trigger a revision increment
+ // kolab #1386
+ Item item;
+ item.setMimeType(Event::eventMimeType());
+ Incidence::Ptr incidence = Incidence::Ptr(new Event());
+ incidence->setUid(QLatin1String("test123uid"));
+ incidence->setSummary(QLatin1String("summary"));
+ incidence->setOrganizer(Person::Ptr(new Person(QLatin1String("orga"), QLatin1String("orga at dev.nul"))));
+ incidence->setDirtyFields(QSet<IncidenceBase::Field>());
+ item.setPayload<KCalCore::Incidence::Ptr>(incidence);
+ ItemCreateJob *job = new ItemCreateJob(item, mCollection, this);
+ AKVERIFYEXEC(job);
+ item = job->item();
+ Alarm::Ptr alarm = Alarm::Ptr(new Alarm(incidence.data()));
+ alarm->setStartOffset(Duration(-15));
+ alarm->setType(Alarm::Display);
+ incidence->addAlarm(alarm);
+ item.setPayload<KCalCore::Incidence::Ptr>(incidence);
+
+ mChanger->setRespectsCollectionRights(true);
+ const int changeId = mChanger->modifyIncidence(item);
+ QVERIFY(changeId != -1);
+
+ mIncidencesToModify = 1;
+ mExpectedResultByChangeId.insert(changeId, IncidenceChanger::ResultCodeSuccess);
+ waitForSignals();
+ ItemFetchJob *fetchJob = new ItemFetchJob(item, this);
+ fetchJob->fetchScope().fetchFullPayload();
+ AKVERIFYEXEC(fetchJob);
+ QVERIFY(fetchJob->items().count() == 1);
+ Item fetchedItem = fetchJob->items().first();
+ QVERIFY(fetchedItem.isValid());
+ QVERIFY(fetchedItem.hasPayload<KCalCore::Incidence::Ptr>());
+ Incidence::Ptr incidence2 = fetchedItem.payload<KCalCore::Incidence::Ptr>();
+ QCOMPARE(incidence2->alarms().count(), 1);
+ QCOMPARE(incidence2->revision(), 0);
+ delete fetchJob;
+ }
+
void testModifyRescedule_data()
{
// When a event is resceduled than all attendees part status should set to NEEDS-ACTION
commit caa4b133ac0dbb9c796108f1a3869f0f443e2940
Author: Sandro Knauà <knauss at kolabsys.com>
Date: Thu Mar 5 15:05:25 2015 +0100
rescedule event triggers attendee status to NEEDS-ACTION
If an event is resceduled ( date or location) all attendees should be
ask again, for there status. Therefore the partStatus should be set back
to NEEDS-ACTION
KOLAB: #4533
diff --git a/akonadi/calendar/incidencechanger.cpp b/akonadi/calendar/incidencechanger.cpp
index 0d0bddd..a038ced 100644
--- a/akonadi/calendar/incidencechanger.cpp
+++ b/akonadi/calendar/incidencechanger.cpp
@@ -63,6 +63,12 @@ ITIPHandlerDialogDelegate::Action actionFromStatus(ITIPHandlerHelper::SendResult
}
}
+bool weAreOrganizer(Incidence::Ptr incidence)
+{
+ const QString email = incidence->organizer()->email();
+ return Akonadi::CalendarUtils::thatIsMe(email);
+}
+
namespace Akonadi {
// Does a queued emit, with QMetaObject::invokeMethod
static void emitCreateFinished(IncidenceChanger *changer,
@@ -552,8 +558,7 @@ void IncidenceChanger::Private::handleInvitationsBeforeChange(const Change::Ptr
break;
}
- const bool weAreOrganizer = Akonadi::CalendarUtils::thatIsMe(newIncidence->organizer()->email());
- if (RUNNING_UNIT_TESTS && !weAreOrganizer) {
+ if (RUNNING_UNIT_TESTS && !weAreOrganizer(newIncidence)) {
// This is a bit of a workaround when running tests. I don't want to show the
// "You're not organizer, do you want to modify event?" dialog in unit-tests, but want
// to emulate a "yes" and a "no" press.
@@ -1026,6 +1031,25 @@ void IncidenceChanger::Private::performModification2(int changeId, ITIPHandlerHe
{ // increment revision ( KCalCore revision, not akonadi )
const int revision = incidence->revision();
incidence->setRevision(revision + 1);
+
+ //Reset attendee status, when resceduling
+ QSet<IncidenceBase::Field> resetPartStatus;
+ resetPartStatus << IncidenceBase::FieldDtStart
+ << IncidenceBase::FieldDtEnd
+ << IncidenceBase::FieldDtStart
+ << IncidenceBase::FieldLocation
+ << IncidenceBase::FieldDtDue
+ << IncidenceBase::FieldDuration
+ << IncidenceBase::FieldRecurrence;
+ if (!(incidence->dirtyFields() & resetPartStatus).isEmpty() && weAreOrganizer(incidence)) {
+ foreach (const Attendee::Ptr &attendee, incidence->attendees()) {
+ if ( attendee->role() != Attendee::NonParticipant &&
+ attendee->status() != Attendee::Delegated && !Akonadi::CalendarUtils::thatIsMe(attendee)) {
+ attendee->setStatus(Attendee::NeedsAction);
+ attendee->setRSVP(true);
+ }
+ }
+ }
}
// Dav Fix
diff --git a/akonadi/calendar/tests/incidencechangertest.cpp b/akonadi/calendar/tests/incidencechangertest.cpp
index 2d8d388..1766d9d 100644
--- a/akonadi/calendar/tests/incidencechangertest.cpp
+++ b/akonadi/calendar/tests/incidencechangertest.cpp
@@ -29,6 +29,7 @@
#include <akonadi/itemfetchjob.h>
#include <akonadi/itemcreatejob.h>
#include <akonadi/itemfetchscope.h>
+#include <akonadi/itemdeletejob.h>
#include <kcalcore/event.h>
#include <kcalcore/journal.h>
@@ -46,6 +47,9 @@ Q_DECLARE_METATYPE(QList<Akonadi::Collection::Rights>)
Q_DECLARE_METATYPE(QList<Akonadi::IncidenceChanger::ResultCode>)
Q_DECLARE_METATYPE(KCalCore::RecurrenceRule::PeriodType)
+QString s_ourEmail = QLatin1String("unittests at dev.nul"); // change also in kdepimlibs/akonadi/calendar/tests/unittestenv/kdehome/share/config
+QString s_outEmail2 = QLatin1String("identity2 at kde.org");
+
static Akonadi::Item item()
{
Item item;
@@ -373,6 +377,179 @@ private Q_SLOTS:
}
}
+ void testModifyRescedule_data()
+ {
+ // When a event is resceduled than all attendees part status should set to NEEDS-ACTION
+ // kolab #4533
+ QTest::addColumn<Akonadi::Item>("item");
+ QTest::addColumn<Event::Ptr>("event");
+ QTest::addColumn<bool>("expectReset");
+
+ const Attendee::Ptr us = Attendee::Ptr(new Attendee(QString(), s_ourEmail));
+ us->setStatus(Attendee::Accepted);
+ const Attendee::Ptr mia = Attendee::Ptr(new Attendee(QLatin1String("Mia Wallace"), QLatin1String("mia at dev.nul")));
+ mia->setStatus(Attendee::Declined);
+ mia->setRSVP(false);
+ const Attendee::Ptr vincent = Attendee::Ptr(new Attendee(QLatin1String("Vincent"), QLatin1String("vincent at dev.nul")));
+ vincent->setStatus(Attendee::Delegated);
+ const Attendee::Ptr jules = Attendee::Ptr(new Attendee(QLatin1String("Jules"), QLatin1String("jules at dev.nul")));
+ jules->setStatus(Attendee::Accepted);
+ jules->setRole(Attendee::NonParticipant);
+
+ // we as organizator
+ Item item;
+ item.setMimeType(Event::eventMimeType());
+ Event::Ptr incidence = Event::Ptr(new Event());
+ incidence->setUid(QLatin1String("test123uid"));
+ incidence->setDtStart(KDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), KDateTime::UTC));
+ incidence->setDtEnd(KDateTime(QDate(2006, 1, 8), QTime(14, 0, 0), KDateTime::UTC));
+ incidence->setAllDay(false);
+ incidence->setLocation(QLatin1String("location"));
+ incidence->setOrganizer(Person::Ptr(new Person(QString(), s_ourEmail)));
+ incidence->addAttendee(us);
+ incidence->addAttendee(mia);
+ incidence->addAttendee(vincent);
+ incidence->addAttendee(jules);
+ incidence->setDirtyFields(QSet<IncidenceBase::Field>());
+ item.setPayload<KCalCore::Incidence::Ptr>(incidence);
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence));
+ event->setDtStart(KDateTime(QDate(2006, 1, 8), QTime(13, 0, 0), KDateTime::UTC));
+ QCOMPARE(event->dirtyFields().count(), 1);
+ QTest::newRow("organizator:start Date") << item << event << true;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence));
+ event->setDtEnd(KDateTime(QDate(2006, 1, 8), QTime(13, 0, 0), KDateTime::UTC));
+ QCOMPARE(event->dirtyFields().count(), 1);
+ QTest::newRow("organizator:end Date") << item << event << true;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence));
+ event->setAllDay(true);
+ QCOMPARE(event->dirtyFields().count(), 2);
+ QTest::newRow("organizator:allDay") << item << event << true;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence));
+ event->setLocation(QLatin1String("location2"));
+ QCOMPARE(event->dirtyFields().count(), 1);
+ QTest::newRow("organizator:location") << item << event << true;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence));
+ event->setSummary(QLatin1String("summary"));
+ QCOMPARE(event->dirtyFields().count(), 1);
+ QTest::newRow("organizator:summary") << item << event << false;
+ }
+
+ //we are normal attendee
+ Item item2;
+ item2.setMimeType(Event::eventMimeType());
+ Event::Ptr incidence2 = Event::Ptr(new Event());
+ incidence2->setUid(QLatin1String("test123uid"));
+ incidence2->setDtStart(KDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), KDateTime::UTC));
+ incidence2->setDtEnd(KDateTime(QDate(2006, 1, 8), QTime(14, 0, 0), KDateTime::UTC));
+ incidence2->setAllDay(false);
+ incidence2->setLocation(QLatin1String("location"));
+ incidence2->setOrganizer(Person::Ptr(new Person(QLatin1String("External organizator"), QLatin1String("exorga at dev.nul"))));
+ incidence2->addAttendee(us);
+ incidence2->addAttendee(mia);
+ incidence2->addAttendee(vincent);
+ incidence2->addAttendee(jules);
+ incidence2->setDirtyFields(QSet<IncidenceBase::Field>());
+ item2.setPayload<KCalCore::Incidence::Ptr>(incidence2);
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence2));
+ event->setDtStart(KDateTime(QDate(2006, 1, 8), QTime(13, 0, 0), KDateTime::UTC));
+ QTest::newRow("attendee:start Date") << item2 << event << false;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence2));
+ event->setDtEnd(KDateTime(QDate(2006, 1, 8), QTime(13, 0, 0), KDateTime::UTC));
+ QTest::newRow("attendee:end Date") << item2 << event << false;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence2));
+ event->setAllDay(false);
+ QTest::newRow("attendee:allDay") << item2 << event << false;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence2));
+ event->setLocation(QLatin1String("location2"));
+ QTest::newRow("attendee:location") << item2 << event << false;
+ }
+
+ {
+ Event::Ptr event = Event::Ptr(new Event(*incidence2));
+ event->setSummary(QLatin1String("summary"));
+ QTest::newRow("attendee:summary") << item2 << event << false;
+ }
+
+ }
+
+ void testModifyRescedule()
+ {
+ QFETCH(Akonadi::Item, item);
+ QFETCH(Event::Ptr, event);
+ QFETCH(bool, expectReset);
+
+ item.setId(-1);
+ ItemCreateJob *job = new ItemCreateJob(item, mCollection, this);
+ AKVERIFYEXEC(job);
+ item = job->item();
+ item.setPayload<KCalCore::Incidence::Ptr>(event);
+
+ int revision = event->revision();
+
+ mChanger->setRespectsCollectionRights(true);
+ const int changeId = mChanger->modifyIncidence(item);
+ QVERIFY(changeId != -1);
+
+ mIncidencesToModify = 1;
+ mExpectedResultByChangeId.insert(changeId, IncidenceChanger::ResultCodeSuccess);
+ waitForSignals();
+ ItemFetchJob *fetchJob = new ItemFetchJob(item, this);
+ fetchJob->fetchScope().fetchFullPayload();
+ AKVERIFYEXEC(fetchJob);
+ QVERIFY(fetchJob->items().count() == 1);
+ Item fetchedItem = fetchJob->items().first();
+
+ QVERIFY(fetchedItem.isValid());
+ QVERIFY(fetchedItem.hasPayload<KCalCore::Event::Ptr>());
+ Event::Ptr incidence = fetchedItem.payload<KCalCore::Event::Ptr>();
+
+ QCOMPARE(incidence->revision(), revision + 1);
+
+ if (expectReset) {
+ if (incidence->organizer()->email() == s_ourEmail) {
+ QCOMPARE(incidence->attendeeByMail(s_ourEmail)->status(), Attendee::Accepted);
+ } else {
+ QCOMPARE(incidence->attendeeByMail(s_ourEmail)->status(), Attendee::NeedsAction);
+ }
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("mia at dev.nul"))->status(), Attendee::NeedsAction);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("mia at dev.nul"))->RSVP(), true);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("vincent at dev.nul"))->status(), Attendee::Delegated);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("vincent at dev.nul"))->RSVP(), false);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("jules at dev.nul"))->status(), Attendee::Accepted);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("jules at dev.nul"))->RSVP(), false);
+ } else {
+ QCOMPARE(incidence->attendeeByMail(s_ourEmail)->status(), Attendee::Accepted);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("mia at dev.nul"))->status(), Attendee::Declined);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("vincent at dev.nul"))->status(), Attendee::Delegated);
+ QCOMPARE(incidence->attendeeByMail(QLatin1String("jules at dev.nul"))->status(), Attendee::Accepted);
+ }
+ delete fetchJob;
+ }
void testMassModifyForConflicts_data()
{
QTest::addColumn<Akonadi::Item>("item");
More information about the commits
mailing list