1/*
2 * akonadi_serializer_kalarm.cpp - Akonadi resource serializer for KAlarm
3 * Copyright © 2009-2012 by David Jarvie <djarvie@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Library General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 * License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
19 */
20
21#include "akonadi_serializer_kalarm.h"
22#include "kaeventformatter.h"
23
24#include <kalarmcal/eventattribute.h>
25#include <kalarmcal/kacalendar.h>
26#include <kalarmcal/kaevent.h>
27
28#include <akonadi/item.h>
29#include <akonadi/abstractdifferencesreporter.h>
30#include <akonadi/attributefactory.h>
31
32#include <klocale.h>
33#include <kdebug.h>
34
35#include <QtCore/qplugin.h>
36
37using namespace Akonadi;
38using namespace KAlarmCal;
39
40
41// Convert from backend data stream to a KAEvent, and set it into the item's payload.
42bool SerializerPluginKAlarm::deserialize(Item& item, const QByteArray& label, QIODevice& data, int version)
43{
44 Q_UNUSED(version);
45
46 if (label != Item::FullPayload)
47 return false;
48
49 KCalCore::Incidence::Ptr i = mFormat.fromString(QString::fromUtf8(data.readAll()));
50 if (!i)
51 {
52 kWarning(5954) << "Failed to parse incidence!";
53 data.seek(0);
54 kWarning(5954) << QString::fromUtf8(data.readAll());
55 return false;
56 }
57 if (i->type() != KCalCore::Incidence::TypeEvent)
58 {
59 kWarning(5954) << "Incidence with uid" << i->uid() << "is not an Event!";
60 data.seek(0);
61 return false;
62 }
63 KAEvent event(i.staticCast<KCalCore::Event>());
64 const QString mime = CalEvent::mimeType(event.category());
65 if (mime.isEmpty() || !event.isValid())
66 {
67 kWarning(5954) << "Event with uid" << event.id() << "contains no usable alarms!";
68 data.seek(0);
69 return false;
70 }
71 event.setItemId(item.id());
72
73 // Set additional event data contained in attributes
74 if (mRegistered.isEmpty())
75 {
76 AttributeFactory::registerAttribute<KAlarmCal::EventAttribute>();
77 mRegistered = QLatin1String("x"); // set to any non-null string
78 }
79 const EventAttribute dummy;
80 if (item.hasAttribute(dummy.type()))
81 {
82 Attribute* a = item.attribute(dummy.type());
83 if (!a)
84 kError(5954) << "deserialize(): Event with uid" << event.id() << "contains null attribute";
85 else
86 {
87 EventAttribute* evAttr = dynamic_cast<EventAttribute*>(a);
88 if (!evAttr)
89 {
90 // Registering EventAttribute doesn't work in the serializer
91 // unless the application also registers it. This doesn't
92 // matter unless the application uses KAEvent class.
93 kError(5954) << "deserialize(): Event with uid" << event.id() << "contains unknown type EventAttribute (application must call AttributeFactory::registerAttribute())";
94 }
95 else
96 {
97 KAEvent::CmdErrType err = evAttr->commandError();
98 event.setCommandError(err);
99 }
100 }
101 }
102
103 item.setMimeType(mime);
104 item.setPayload<KAEvent>(event);
105 return true;
106}
107
108// Convert an item's KAEvent payload to backend data stream.
109void SerializerPluginKAlarm::serialize(const Item& item, const QByteArray& label, QIODevice& data, int& version)
110{
111 Q_UNUSED(version);
112
113 if (label != Item::FullPayload || !item.hasPayload<KAEvent>())
114 return;
115 const KAEvent e = item.payload<KAEvent>();
116 KCalCore::Event::Ptr kcalEvent(new KCalCore::Event);
117 e.updateKCalEvent(kcalEvent, KAEvent::UID_SET);
118 QByteArray head = "BEGIN:VCALENDAR\nPRODID:";
119 head += KACalendar::icalProductId();
120 head += "\nVERSION:2.0\nX-KDE-KALARM-VERSION:";
121 head += KAEvent::currentCalendarVersionString();
122 head += '\n';
123 data.write(head);
124 data.write(mFormat.toString(kcalEvent.staticCast<KCalCore::Incidence>()).toUtf8());
125 data.write("\nEND:VCALENDAR");
126}
127
128#include <kglobal.h>
129
130void SerializerPluginKAlarm::compare(AbstractDifferencesReporter* reporter, const Item& left, const Item& right)
131{
132 Q_ASSERT(reporter);
133 Q_ASSERT(left.hasPayload<KAEvent>());
134 Q_ASSERT(right.hasPayload<KAEvent>());
135
136 KAEvent eventL = left.payload<KAEvent>();
137 KAEvent eventR = right.payload<KAEvent>();
138 // Note that event attributes are not included, since they are not part of the payload
139 mValueL = KAEventFormatter(eventL, false);
140 mValueR = KAEventFormatter(eventR, false);
141
142 reporter->setLeftPropertyValueTitle(i18nc("@title:column", "Changed Alarm"));
143 reporter->setRightPropertyValueTitle(i18nc("@title:column", "Conflicting Alarm"));
144
145 reportDifference(reporter, KAEventFormatter::Id);
146 if (eventL.revision() != eventR.revision())
147 reportDifference(reporter, KAEventFormatter::Revision);
148 if (eventL.actionSubType() != eventR.actionSubType())
149 reportDifference(reporter, KAEventFormatter::AlarmType);
150 if (eventL.category() != eventR.category())
151 reportDifference(reporter, KAEventFormatter::AlarmCategory);
152 if (eventL.templateName() != eventR.templateName())
153 reportDifference(reporter, KAEventFormatter::TemplateName);
154 if (eventL.createdDateTime() != eventR.createdDateTime())
155 reportDifference(reporter, KAEventFormatter::CreatedTime);
156 if (eventL.startDateTime() != eventR.startDateTime())
157 reportDifference(reporter, KAEventFormatter::StartTime);
158 if (eventL.templateAfterTime() != eventR.templateAfterTime())
159 reportDifference(reporter, KAEventFormatter::TemplateAfterTime);
160 if (*eventL.recurrence() != *eventR.recurrence())
161 reportDifference(reporter, KAEventFormatter::Recurrence);
162 if (eventL.mainDateTime(true) != eventR.mainDateTime(true))
163 reportDifference(reporter, KAEventFormatter::NextRecurrence);
164 if (eventL.repetition() != eventR.repetition())
165 reportDifference(reporter, KAEventFormatter::SubRepetition);
166 if (eventL.repetition().interval() != eventR.repetition().interval())
167 reportDifference(reporter, KAEventFormatter::RepeatInterval);
168 if (eventL.repetition().count() != eventR.repetition().count())
169 reportDifference(reporter, KAEventFormatter::RepeatCount);
170 if (eventL.nextRepetition() != eventR.nextRepetition())
171 reportDifference(reporter, KAEventFormatter::NextRepetition);
172 if (eventL.holidaysExcluded() != eventR.holidaysExcluded())
173 reportDifference(reporter, KAEventFormatter::HolidaysExcluded);
174 if (eventL.workTimeOnly() != eventR.workTimeOnly())
175 reportDifference(reporter, KAEventFormatter::WorkTimeOnly);
176 if (eventL.lateCancel() != eventR.lateCancel())
177 reportDifference(reporter, KAEventFormatter::LateCancel);
178 if (eventL.autoClose() != eventR.autoClose())
179 reportDifference(reporter, KAEventFormatter::AutoClose);
180 if (eventL.copyToKOrganizer() != eventR.copyToKOrganizer())
181 reportDifference(reporter, KAEventFormatter::CopyKOrganizer);
182 if (eventL.enabled() != eventR.enabled())
183 reportDifference(reporter, KAEventFormatter::Enabled);
184 if (eventL.isReadOnly() != eventR.isReadOnly())
185 reportDifference(reporter, KAEventFormatter::ReadOnly);
186 if (eventL.toBeArchived() != eventR.toBeArchived())
187 reportDifference(reporter, KAEventFormatter::Archive);
188 if (eventL.customProperties() != eventR.customProperties())
189 reportDifference(reporter, KAEventFormatter::CustomProperties);
190 if (eventL.message() != eventR.message())
191 reportDifference(reporter, KAEventFormatter::MessageText);
192 if (eventL.fileName() != eventR.fileName())
193 reportDifference(reporter, KAEventFormatter::MessageFile);
194 if (eventL.fgColour() != eventR.fgColour())
195 reportDifference(reporter, KAEventFormatter::FgColour);
196 if (eventL.bgColour() != eventR.bgColour())
197 reportDifference(reporter, KAEventFormatter::BgColour);
198 if (eventL.font() != eventR.font())
199 reportDifference(reporter, KAEventFormatter::Font);
200 if (eventL.preAction() != eventR.preAction())
201 reportDifference(reporter, KAEventFormatter::PreAction);
202 if (eventL.cancelOnPreActionError() != eventR.cancelOnPreActionError())
203 reportDifference(reporter, KAEventFormatter::PreActionCancel);
204 if (eventL.dontShowPreActionError() != eventR.dontShowPreActionError())
205 reportDifference(reporter, KAEventFormatter::PreActionNoError);
206 if (eventL.postAction() != eventR.postAction())
207 reportDifference(reporter, KAEventFormatter::PostAction);
208 if (eventL.confirmAck() != eventR.confirmAck())
209 reportDifference(reporter, KAEventFormatter::ConfirmAck);
210 if (eventL.kmailSerialNumber() != eventR.kmailSerialNumber())
211 reportDifference(reporter, KAEventFormatter::KMailSerial);
212 if (eventL.beep() != eventR.beep()
213 || eventL.speak() != eventR.speak()
214 || eventL.audioFile() != eventR.audioFile())
215 reportDifference(reporter, KAEventFormatter::Sound);
216 if (eventL.repeatSound() != eventR.repeatSound())
217 reportDifference(reporter, KAEventFormatter::SoundRepeat);
218 if (eventL.soundVolume() != eventR.soundVolume())
219 reportDifference(reporter, KAEventFormatter::SoundVolume);
220 if (eventL.fadeVolume() != eventR.fadeVolume())
221 reportDifference(reporter, KAEventFormatter::SoundFadeVolume);
222 if (eventL.fadeSeconds() != eventR.fadeSeconds())
223 reportDifference(reporter, KAEventFormatter::SoundFadeTime);
224 if (eventL.reminderMinutes() != eventR.reminderMinutes())
225 reportDifference(reporter, KAEventFormatter::Reminder);
226 if (eventL.reminderOnceOnly() != eventR.reminderOnceOnly())
227 reportDifference(reporter, KAEventFormatter::ReminderOnce);
228 if (eventL.deferred() != eventR.deferred())
229 reportDifference(reporter, KAEventFormatter::DeferralType);
230 if (eventL.deferDateTime() != eventR.deferDateTime())
231 reportDifference(reporter, KAEventFormatter::DeferralTime);
232 if (eventL.deferDefaultMinutes() != eventR.deferDefaultMinutes())
233 reportDifference(reporter, KAEventFormatter::DeferDefault);
234 if (eventL.deferDefaultDateOnly() != eventR.deferDefaultDateOnly())
235 reportDifference(reporter, KAEventFormatter::DeferDefaultDate);
236 if (eventL.command() != eventR.command())
237 reportDifference(reporter, KAEventFormatter::Command);
238 if (eventL.logFile() != eventR.logFile())
239 reportDifference(reporter, KAEventFormatter::LogFile);
240 if (eventL.commandXterm() != eventR.commandXterm())
241 reportDifference(reporter, KAEventFormatter::CommandXTerm);
242 if (eventL.emailSubject() != eventR.emailSubject())
243 reportDifference(reporter, KAEventFormatter::EmailSubject);
244 if (eventL.emailFromId() != eventR.emailFromId())
245 reportDifference(reporter, KAEventFormatter::EmailFromId);
246 if (eventL.emailAddresses() != eventR.emailAddresses())
247 reportDifference(reporter, KAEventFormatter::EmailTo);
248 if (eventL.emailBcc() != eventR.emailBcc())
249 reportDifference(reporter, KAEventFormatter::EmailBcc);
250 if (eventL.emailMessage() != eventR.emailMessage())
251 reportDifference(reporter, KAEventFormatter::EmailBody);
252 if (eventL.emailAttachments() != eventR.emailAttachments())
253 reportDifference(reporter, KAEventFormatter::EmailAttachments);
254
255 KLocale* locale = KGlobal::locale();
256 reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18nc("@label", "Item revision"),
257 locale->convertDigits(QString::number(left.revision()), locale->digitSet()),
258 locale->convertDigits(QString::number(right.revision()), locale->digitSet()));
259}
260
261void SerializerPluginKAlarm::reportDifference(AbstractDifferencesReporter* reporter, KAEventFormatter::Parameter id)
262{
263 if (mValueL.isApplicable(id) || mValueR.isApplicable(id))
264 reporter->addProperty(AbstractDifferencesReporter::ConflictMode, KAEventFormatter::label(id), mValueL.value(id), mValueR.value(id));
265}
266
267QString SerializerPluginKAlarm::extractGid(const Item& item) const
268{
269 return item.hasPayload<KAEvent>() ? item.payload<KAEvent>().id() : QString();
270}
271
272Q_EXPORT_PLUGIN2(akonadi_serializer_kalarm, SerializerPluginKAlarm)
273
274
275// vim: et sw=4:
276