Commit c5d7bc89 authored by Damien Caliste's avatar Damien Caliste

Add COLOR property serialization from RFC7986.

parent b0d38456
......@@ -20,6 +20,76 @@ QTEST_MAIN(ICalFormatTest)
using namespace KCalendarCore;
void ICalFormatTest::testDeserializeSerialize()
{
ICalFormat format;
const QString serializedCalendar
= QLatin1String("BEGIN:VCALENDAR\n"
"PRODID:-//IDN nextcloud.com//Calendar app 2.0.4//EN\n"
"VERSION:2.0\n"
"BEGIN:VEVENT\n"
"CREATED:20201103T161248Z\n"
"DTSTAMP:20201103T161340Z\n"
"LAST-MODIFIED:20201103T161340Z\n"
"SEQUENCE:2\n"
"UID:bd1d299d-3b03-4514-be69-e680ad2ff884\n"
"DTSTART;TZID=Europe/Paris:20201103T100000\n"
"DTEND;TZID=Europe/Paris:20201103T110000\n"
"SUMMARY:test recur\n"
"RRULE:FREQ=DAILY;COUNT=4\n"
"END:VEVENT\n"
"BEGIN:VEVENT\n"
"CREATED:20201103T161823Z\n"
"DTSTAMP:20201103T161823Z\n"
"LAST-MODIFIED:20201103T161823Z\n"
"SEQUENCE:1\n"
"UID:bd1d299d-3b03-4514-be69-e680ad2ff884\n"
"DTSTART;TZID=Europe/Paris:20201104T111500\n"
"DTEND;TZID=Europe/Paris:20201104T121500\n"
"SUMMARY:test recur\n"
"COLOR:khaki\n"
"RECURRENCE-ID;TZID=Europe/Paris:20201104T100000\n"
"END:VEVENT\n"
"END:VCALENDAR");
MemoryCalendar::Ptr calendar = MemoryCalendar::Ptr(new MemoryCalendar(QTimeZone::utc()));
QVERIFY(format.fromString(calendar, serializedCalendar));
const QString uid = QString::fromLatin1("bd1d299d-3b03-4514-be69-e680ad2ff884");
Incidence::Ptr parent = calendar->incidence(uid);
QVERIFY(parent);
const QDateTime start(QDate(2020, 11, 3), QTime(9,0), QTimeZone::utc());
QCOMPARE(parent->dtStart(), start);
QCOMPARE(parent.staticCast<Event>()->dtEnd(), start.addSecs(3600));
QCOMPARE(parent->summary(), QString::fromLatin1("test recur"));
QCOMPARE(parent->revision(), 2);
Recurrence *recur = parent->recurrence();
QVERIFY(recur->recurs());
QCOMPARE(recur->duration(), 4);
QCOMPARE(recur->recurrenceType(), Recurrence::rDaily);
Incidence::Ptr occurrence = calendar->incidence(uid, start.addDays(1));
QVERIFY(occurrence);
const QDateTime startOcc(QDate(2020, 11, 4), QTime(10,15), QTimeZone::utc());
QCOMPARE(occurrence->dtStart(), startOcc);
QCOMPARE(occurrence.staticCast<Event>()->dtEnd(), startOcc.addSecs(3600));
QCOMPARE(occurrence->color(), QString::fromLatin1("khaki"));
QCOMPARE(occurrence->summary(), QString::fromLatin1("test recur"));
QCOMPARE(occurrence->revision(), 1);
QVERIFY(occurrence->hasRecurrenceId());
QCOMPARE(occurrence->recurrenceId(), start.addDays(1));
const QString serialization = format.toString(calendar);
QVERIFY(!serialization.isEmpty());
MemoryCalendar::Ptr check = MemoryCalendar::Ptr(new MemoryCalendar(QTimeZone::utc()));
QVERIFY(format.fromString(check, serialization));
Incidence::Ptr reparent = check->incidence(uid);
QVERIFY(reparent);
QCOMPARE(*parent, *reparent);
Incidence::Ptr reoccurence = check->incidence(uid, start.addDays(1));
QVERIFY(reoccurence);
QCOMPARE(*occurrence, *reoccurence);
}
void ICalFormatTest::testCharsets()
{
ICalFormat format;
......
......@@ -16,6 +16,7 @@ class ICalFormatTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testDeserializeSerialize();
void testCharsets();
void testVolatileProperties();
void testCuType();
......
......@@ -530,6 +530,12 @@ void ICalFormatImpl::writeIncidence(icalcomponent *parent,
icalcomponent_add_property(parent, icalproperty_new_class(secClass));
}
// color
if (!incidence->color().isEmpty()) {
icalcomponent_add_property(
parent, icalproperty_new_color(incidence->color().toUtf8().constData()));
}
// geo
if (incidence->hasGeo()) {
icalgeotype geo;
......@@ -1881,6 +1887,10 @@ void ICalFormatImpl::readIncidence(icalcomponent *parent, const Incidence::Ptr &
incidence->addAttachment(readAttachment(p));
break;
case ICAL_COLOR_PROPERTY:
incidence->setColor(QString::fromUtf8(icalproperty_get_color(p)));
break;
default:
// TODO: do something about unknown properties?
break;
......
......@@ -73,6 +73,7 @@ public:
, mPriority(p.mPriority)
, mStatus(p.mStatus)
, mSecrecy(p.mSecrecy)
, mColor(p.mColor)
, mDescriptionIsRich(p.mDescriptionIsRich)
, mSummaryIsRich(p.mSummaryIsRich)
, mLocationIsRich(p.mLocationIsRich)
......@@ -150,6 +151,7 @@ public:
int mPriority; // priority: 1 = highest, 2 = less, etc.
Status mStatus; // status
Secrecy mSecrecy; // secrecy
QString mColor; // background color
bool mDescriptionIsRich = false; // description string is richtext.
bool mSummaryIsRich = false; // summary string is richtext.
bool mLocationIsRich = false; // location string is richtext.
......@@ -284,6 +286,7 @@ bool Incidence::equals(const IncidenceBase &incidence) const
&& secrecy() == i2->secrecy()
&& priority() == i2->priority()
&& stringCompare(location(), i2->location())
&& stringCompare(color(), i2->color())
&& stringCompare(schedulingID(), i2->schedulingID())
&& recurrenceId() == i2->recurrenceId()
&& thisAndFuture() == i2->thisAndFuture();
......@@ -542,6 +545,24 @@ QString Incidence::relatedTo(RelType relType) const
return d->mRelatedToUid.value(relType);
}
void Incidence::setColor(const QString &colorName)
{
if (mReadOnly) {
return;
}
if (!stringCompare(d->mColor, colorName)) {
update();
d->mColor = colorName;
setFieldDirty(FieldColor);
updated();
}
}
QString Incidence::color() const
{
return d->mColor;
}
// %%%%%%%%%%%% Recurrence-related methods %%%%%%%%%%%%%%%%%%%%
Recurrence *Incidence::recurrence() const
......
......@@ -397,6 +397,22 @@ public:
*/
Q_REQUIRED_RESULT QString relatedTo(RelType relType = RelTypeParent) const;
/**
Set the incidence color, as added in RFC7986.
@param colorName a named color as defined in CSS3 color name, see
https://www.w3.org/TR/css-color-3/#svg-color.
@since: 5.76
*/
void setColor(const QString &colorName);
/**
Returns the color, if any is defined, for this incidence.
@since: 5.76
*/
Q_REQUIRED_RESULT QString color() const;
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %%%%% Convenience wrappers for property handling
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
......
......@@ -185,7 +185,8 @@ public:
FieldComment, ///> Field representing the COMMENT component.
FieldUid, ///> Field representing the UID component.
FieldUnknown, ///> Something changed. Always set when you use the assignment operator.
FieldUrl ///> Field representing the URL component.
FieldUrl, ///> Field representing the URL component.
FieldColor ///> Field representing the COLOR component.
};
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment