1/*
2 * kaeventformatter.cpp - converts KAlarmCal::KAEvent properties to text
3 * Copyright © 2010,2011 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 "kaeventformatter.h"
22
23#include <kalarmcal/kacalendar.h>
24#include <kalarmcal/kaevent.h>
25#include <kalarmcal/datetime.h>
26
27#include <kcalutils/incidenceformatter.h>
28
29#include <kglobal.h>
30#include <klocale.h>
31#include <kdatetime.h>
32#include <kdebug.h>
33
34static QString trueFalse(bool value);
35static QString number(unsigned long n);
36static QString minutes(int n);
37static QString minutesHoursDays(int minutes);
38static QString dateTime(const KDateTime&);
39
40KAEventFormatter::KAEventFormatter(const KAEvent& e, bool falseForUnspecified)
41 : mEvent(e)
42{
43 if (falseForUnspecified)
44 mUnspecifiedValue = trueFalse(false);
45}
46
47QString KAEventFormatter::label(Parameter param)
48{
49 switch (param)
50 {
51 case Id: return i18nc("@label Unique identifier", "UID");
52 case AlarmType: return i18nc("@label", "Alarm type");
53 case AlarmCategory: return i18nc("@label", "Alarm status");
54 case TemplateName: return i18nc("@label", "Template name");
55 case CreatedTime: return i18nc("@label", "Creation time");
56 case StartTime: return i18nc("@label", "Start time");
57 case TemplateAfterTime: return i18nc("@label Start delay configured in an alarm template", "Template after time");
58 case Recurs: return i18nc("@label", "Recurs");
59 case Recurrence: return i18nc("@label", "Recurrence");
60 case SubRepetition: return i18nc("@label", "Sub-repetition");
61 case RepeatInterval: return i18nc("@label", "Sub-repetition interval");
62 case RepeatCount: return i18nc("@label", "Sub-repetition count");
63 case NextRepetition: return i18nc("@label", "Next sub-repetition");
64 case WorkTimeOnly: return i18nc("@label", "Work time only");
65 case HolidaysExcluded: return i18nc("@label", "Holidays excluded");
66 case NextRecurrence: return i18nc("@label", "Next recurrence");
67 case LateCancel: return i18nc("@label", "Late cancel");
68 case AutoClose: return i18nc("@label Automatically close window", "Auto close");
69 case CopyKOrganizer: return i18nc("@label", "Copy to KOrganizer");
70 case Enabled: return i18nc("@label", "Enabled");
71 case ReadOnly: return i18nc("@label", "Read-only");
72 case Archive: return i18nc("@label Whether alarm should be archived", "Archive");
73 case Revision: return i18nc("@label", "Revision");
74 case CustomProperties: return i18nc("@label", "Custom properties");
75
76 case MessageText: return i18nc("@label", "Message text");
77 case MessageFile: return i18nc("@label File to provide text for message", "Message file");
78 case FgColour: return i18nc("@label", "Foreground color");
79 case BgColour: return i18nc("@label", "Background color");
80 case Font: return i18nc("@label", "Font");
81 case PreAction: return i18nc("@label Shell command to execute before alarm", "Pre-alarm action");
82 case PreActionCancel: return i18nc("@label", "Pre-alarm action cancel");
83 case PreActionNoError: return i18nc("@label", "Pre-alarm action no error");
84 case PostAction: return i18nc("@label Shell command to execute after alarm", "Post-alarm action");
85 case ConfirmAck: return i18nc("@label", "Confirm acknowledgement");
86 case KMailSerial: return i18nc("@label", "KMail serial number");
87 case Sound: return i18nc("@label Audio method", "Sound");
88 case SoundRepeat: return i18nc("@label Whether audio should repeat", "Sound repeat");
89 case SoundVolume: return i18nc("@label", "Sound volume");
90 case SoundFadeVolume: return i18nc("@label", "Sound fade volume");
91 case SoundFadeTime: return i18nc("@label", "Sound fade time");
92 case Reminder: return i18nc("@label Whether the alarm has a reminder", "Reminder");
93 case ReminderOnce: return i18nc("@label Whether reminder is on first recurrence only", "Reminder once only");
94 case DeferralType: return i18nc("@label Deferral type", "Deferral");
95 case DeferralTime: return i18nc("@label", "Deferral time");
96 case DeferDefault: return i18nc("@label Default deferral delay", "Deferral default");
97 case DeferDefaultDate: return i18nc("@label Whether deferral time is date-only by default", "Deferral default date only");
98
99 case Command: return i18nc("@label A shell command", "Command");
100 case LogFile: return i18nc("@label", "Log file");
101 case CommandXTerm: return i18nc("@label Execute in terminal window", "Execute in terminal");
102
103 case EmailSubject: return i18nc("@label", "Email subject");
104 case EmailFromId: return i18nc("@label Email address", "Email sender ID");
105 case EmailTo: return i18nc("@label Email address", "Email to");
106 case EmailBcc: return i18nc("@label true/false", "Email bcc");
107 case EmailBody: return i18nc("@label", "Email body");
108 case EmailAttachments: return i18nc("@label", "Email attachments");
109 }
110 return QString();
111}
112
113bool KAEventFormatter::isApplicable(Parameter param) const
114{
115 switch (param)
116 {
117 case Id:
118 case AlarmType:
119 case AlarmCategory:
120 case CreatedTime:
121 case StartTime:
122 case Recurs:
123 case LateCancel:
124 case Enabled:
125 case ReadOnly:
126 case Archive:
127 case Revision:
128 case CustomProperties:
129 case CopyKOrganizer:
130 return true;
131 case TemplateName:
132 case TemplateAfterTime:
133 return mEvent.isTemplate();
134 case Recurrence:
135 case RepeatCount:
136 case SubRepetition:
137 case WorkTimeOnly:
138 case HolidaysExcluded:
139 case NextRecurrence:
140 return mEvent.recurs();
141 case RepeatInterval:
142 case NextRepetition:
143 return mEvent.repetition();
144 case AutoClose:
145 return mEvent.lateCancel();
146
147
148 case MessageText:
149 return mEvent.actionSubType() == KAEvent::MESSAGE;
150 case MessageFile:
151 return mEvent.actionSubType() == KAEvent::FILE;
152 case FgColour:
153 case BgColour:
154 case Font:
155 case PreAction:
156 case PostAction:
157 case ConfirmAck:
158 case KMailSerial:
159 case Reminder:
160 case DeferralType:
161 case DeferDefault:
162 return mEvent.actionTypes() & KAEvent::ACT_DISPLAY;
163 case ReminderOnce:
164 return mEvent.reminderMinutes() && mEvent.recurs();
165 case DeferralTime:
166 return mEvent.deferred();
167 case DeferDefaultDate:
168 return mEvent.deferDefaultMinutes() > 0;
169 case PreActionCancel:
170 case PreActionNoError:
171 return !mEvent.preAction().isEmpty();
172 case Sound:
173 return mEvent.actionSubType() == KAEvent::MESSAGE || mEvent.actionSubType() == KAEvent::AUDIO;
174 case SoundRepeat:
175 return !mEvent.audioFile().isEmpty();
176 case SoundVolume:
177 return mEvent.soundVolume() >= 0;
178 case SoundFadeVolume:
179 case SoundFadeTime:
180 return mEvent.fadeVolume() >= 0;
181
182 case Command:
183 case LogFile:
184 case CommandXTerm:
185 return mEvent.actionSubType() == KAEvent::COMMAND;
186
187 case EmailSubject:
188 case EmailFromId:
189 case EmailTo:
190 case EmailBcc:
191 case EmailBody:
192 case EmailAttachments:
193 return mEvent.actionSubType() == KAEvent::EMAIL;
194 }
195 return false;
196}
197
198QString KAEventFormatter::value(Parameter param) const
199{
200 switch (param)
201 {
202 case Id: return mEvent.id();
203 case AlarmType:
204 switch (mEvent.actionSubType())
205 {
206 case KAEvent::MESSAGE: return i18nc("@info/plain Alarm type", "Display (text)");
207 case KAEvent::FILE: return i18nc("@info/plain Alarm type", "Display (file)");
208 case KAEvent::COMMAND: return mEvent.commandDisplay()
209 ? i18nc("@info/plain Alarm type", "Display (command)")
210 : i18nc("@info/plain Alarm type", "Command");
211 case KAEvent::EMAIL: return i18nc("@info/plain Alarm type", "Email");
212 case KAEvent::AUDIO: return i18nc("@info/plain Alarm type", "Audio");
213 }
214 break;
215 case AlarmCategory:
216 switch (mEvent.category())
217 {
218 case CalEvent::ACTIVE: return i18nc("@info/plain Alarm type", "Active");
219 case CalEvent::ARCHIVED: return i18nc("@info/plain Alarm type", "Archived");
220 case CalEvent::TEMPLATE: return i18nc("@info/plain Alarm type", "Template");
221 default:
222 break;
223 }
224 break;
225 case TemplateName: return mEvent.templateName();
226 case CreatedTime: return mEvent.createdDateTime().toUtc().toString(QLatin1String("%Y-%m-%d %H:%M:%SZ"));
227 case StartTime: return dateTime(mEvent.startDateTime().kDateTime());
228 case TemplateAfterTime: return (mEvent.templateAfterTime() >= 0) ? number(mEvent.templateAfterTime()) : trueFalse(false);
229 case Recurs: return trueFalse(mEvent.recurs());
230 case Recurrence:
231 {
232 if (mEvent.repeatAtLogin(true))
233 return i18nc("@info/plain Repeat at login", "At login until %1", dateTime(mEvent.mainDateTime().kDateTime()));
234 KCalCore::Event::Ptr eptr(new KCalCore::Event);
235 mEvent.updateKCalEvent(eptr, KAEvent::UID_SET);
236 return KCalUtils::IncidenceFormatter::recurrenceString(eptr);
237 }
238 case NextRecurrence: return dateTime(mEvent.mainDateTime().kDateTime());
239 case SubRepetition: return trueFalse(mEvent.repetition());
240 case RepeatInterval: return mEvent.repetitionText(true);
241 case RepeatCount: return mEvent.repetition() ? number(mEvent.repetition().count()) : QString();
242 case NextRepetition: return mEvent.repetition() ? number(mEvent.nextRepetition()) : QString();
243 case WorkTimeOnly: return trueFalse(mEvent.workTimeOnly());
244 case HolidaysExcluded: return trueFalse(mEvent.holidaysExcluded());
245 case LateCancel: return mEvent.lateCancel() ? minutesHoursDays(mEvent.lateCancel()) : trueFalse(false);
246 case AutoClose: return trueFalse(mEvent.lateCancel() ? mEvent.autoClose() : false);
247 case CopyKOrganizer: return trueFalse(mEvent.copyToKOrganizer());
248 case Enabled: return trueFalse(mEvent.enabled());
249 case ReadOnly: return trueFalse(mEvent.isReadOnly());
250 case Archive: return trueFalse(mEvent.toBeArchived());
251 case Revision: return number(mEvent.revision());
252 case CustomProperties:
253 {
254 if (mEvent.customProperties().isEmpty())
255 return QString();
256 QString value;
257 for (QMap<QByteArray, QString>::ConstIterator it = mEvent.customProperties().constBegin(); it != mEvent.customProperties().constEnd(); ++it)
258 value += QString::fromLatin1(it.key()) + QLatin1String(":") + it.value() + QLatin1String("<nl/>");
259 return i18nc("@info/plain", "%1", value);
260 }
261
262 case MessageText: return (mEvent.actionSubType() == KAEvent::MESSAGE) ? mEvent.cleanText() : QString();
263 case MessageFile: return (mEvent.actionSubType() == KAEvent::FILE) ? mEvent.cleanText() : QString();
264 case FgColour: return mEvent.fgColour().name();
265 case BgColour: return mEvent.bgColour().name();
266 case Font: return mEvent.useDefaultFont() ? i18nc("@info/plain Using default font", "Default") : mEvent.font().toString();
267 case PreActionCancel: return trueFalse(mEvent.cancelOnPreActionError());
268 case PreActionNoError: return trueFalse(mEvent.dontShowPreActionError());
269 case PreAction: return mEvent.preAction();
270 case PostAction: return mEvent.postAction();
271 case Reminder: return mEvent.reminderMinutes() ? minutesHoursDays(mEvent.reminderMinutes()) : trueFalse(false);
272 case ReminderOnce: return trueFalse(mEvent.reminderOnceOnly());
273 case DeferralType: return mEvent.reminderDeferral() ? i18nc("@info/plain", "Reminder") : trueFalse(mEvent.deferred());
274 case DeferralTime: return mEvent.deferred() ? dateTime(mEvent.deferDateTime().kDateTime()) : trueFalse(false);
275 case DeferDefault: return (mEvent.deferDefaultMinutes() > 0) ? minutes(mEvent.deferDefaultMinutes()) : trueFalse(false);
276 case DeferDefaultDate: return trueFalse(mEvent.deferDefaultDateOnly());
277 case ConfirmAck: return trueFalse(mEvent.confirmAck());
278 case KMailSerial: return mEvent.kmailSerialNumber() ? number(mEvent.kmailSerialNumber()) : trueFalse(false);
279 case Sound: return !mEvent.audioFile().isEmpty() ? mEvent.audioFile()
280 : mEvent.speak() ? i18nc("@info/plain", "Speak")
281 : mEvent.beep() ? i18nc("@info/plain", "Beep") : trueFalse(false);
282 case SoundRepeat: return trueFalse(mEvent.repeatSound());
283 case SoundVolume: return mEvent.soundVolume() >= 0
284 ? i18nc("@info/plain Percentage", "%1%%", static_cast<int>(mEvent.soundVolume() * 100))
285 : mUnspecifiedValue;
286 case SoundFadeVolume: return mEvent.fadeVolume() >= 0
287 ? i18nc("@info/plain Percentage", "%1%%", static_cast<int>(mEvent.fadeVolume() * 100))
288 : mUnspecifiedValue;
289 case SoundFadeTime: return mEvent.fadeSeconds()
290 ? i18ncp("@info/plain", "1 Second", "%1 Seconds", mEvent.fadeSeconds())
291 : mUnspecifiedValue;
292
293 case Command: return (mEvent.actionSubType() == KAEvent::COMMAND) ? mEvent.cleanText() : QString();
294 case LogFile: return mEvent.logFile();
295 case CommandXTerm: return trueFalse(mEvent.commandXterm());
296
297 case EmailSubject: return mEvent.emailSubject();
298 case EmailFromId: return (mEvent.actionSubType() == KAEvent::EMAIL) ? number(mEvent.emailFromId()) : QString();
299 case EmailTo: return mEvent.emailAddresses(QLatin1String(", "));
300 case EmailBcc: return trueFalse(mEvent.emailBcc());
301 case EmailBody: return mEvent.emailMessage();
302 case EmailAttachments: return mEvent.emailAttachments(QLatin1String(", "));
303 }
304 return i18nc("@info/plain Error indication", "error!");
305}
306
307QString trueFalse(bool value)
308{
309 return value ? i18nc("@info/plain General purpose status indication: yes or no", "Yes")
310 : i18nc("@info/plain General purpose status indication: yes or no", "No");
311}
312
313// Convert an integer to digits for the locale.
314// Do not use for date/time or monetary numbers (which have their own digit sets).
315QString number(unsigned long n)
316{
317 KLocale* locale = KGlobal::locale();
318 return locale->convertDigits(QString::number(n), locale->digitSet());
319}
320
321QString minutes(int n)
322{
323 return i18ncp("@info/plain", "1 Minute", "%1 Minutes", n);
324}
325
326QString dateTime(const KDateTime& dt)
327{
328 if (dt.isDateOnly())
329 return dt.toString(QLatin1String("%Y-%m-%d %:Z"));
330 else
331 return dt.toString(QLatin1String("%Y-%m-%d %H:%M %:Z"));
332}
333
334QString minutesHoursDays(int minutes)
335{
336 if (minutes % 60)
337 return i18ncp("@info/plain", "1 Minute", "%1 Minutes", minutes);
338 else if (minutes % 1440)
339 return i18ncp("@info/plain", "1 Hour", "%1 Hours", minutes/60);
340 else
341 return i18ncp("@info/plain", "1 Day", "%1 Days", minutes/1440);
342}
343
344// vim: et sw=4:
345