1 /*
2   This file is part of the kcalutils library.
3 
4   SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
5   SPDX-FileCopyrightText: 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6   SPDX-FileCopyrightText: 2005 Rafal Rzepecki <divide@users.sourceforge.net>
7   SPDX-FileCopyrightText: 2009-2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
8   SPDX-FileCopyrightText: 2017 Allen Winter <winter@kde.org>
9 
10   SPDX-License-Identifier: LGPL-2.0-or-later
11 */
12 /**
13   @file
14   This file is part of the API for handling calendar data and provides
15   static functions for formatting Incidence properties for various purposes.
16 
17   @brief
18   Provides methods to format Incidence properties in various ways for display purposes.
19 
20   @author Cornelius Schumacher \<schumacher@kde.org\>
21   @author Reinhold Kainhofer \<reinhold@kainhofer.com\>
22   @author Allen Winter \<allen@kdab.com\>
23 */
24 #include "stringify.h"
25 
26 #include <KCalendarCore/Exceptions>
27 using namespace KCalendarCore;
28 
29 #include <KLocalizedString>
30 
31 #include <QLocale>
32 
33 using namespace KCalUtils;
34 using namespace Stringify;
35 
incidenceType(Incidence::IncidenceType type)36 QString Stringify::incidenceType(Incidence::IncidenceType type)
37 {
38     switch (type) {
39     case Incidence::TypeEvent:
40         return i18nc("@item incidence type is event", "event");
41     case Incidence::TypeTodo:
42         return i18nc("@item incidence type is to-do/task", "to-do");
43     case Incidence::TypeJournal:
44         return i18nc("@item incidence type is journal", "journal");
45     case Incidence::TypeFreeBusy:
46         return i18nc("@item incidence type is freebusy", "free/busy");
47     default:
48         return QString();
49     }
50 }
51 
todoCompletedDateTime(const Todo::Ptr & todo,bool shortfmt)52 QString Stringify::todoCompletedDateTime(const Todo::Ptr &todo, bool shortfmt)
53 {
54     return QLocale().toString(todo->completed(), (shortfmt ? QLocale::ShortFormat : QLocale::LongFormat));
55 }
56 
incidenceSecrecy(Incidence::Secrecy secrecy)57 QString Stringify::incidenceSecrecy(Incidence::Secrecy secrecy)
58 {
59     switch (secrecy) {
60     case Incidence::SecrecyPublic:
61         return i18nc("@item incidence access if for everyone", "Public");
62     case Incidence::SecrecyPrivate:
63         return i18nc("@item incidence access is by owner only", "Private");
64     case Incidence::SecrecyConfidential:
65         return i18nc("@item incidence access is by owner and a controlled group", "Confidential");
66     }
67     return QString();
68 }
69 
incidenceSecrecyList()70 QStringList Stringify::incidenceSecrecyList()
71 {
72     const QStringList list{incidenceSecrecy(Incidence::SecrecyPublic),
73                            incidenceSecrecy(Incidence::SecrecyPrivate),
74                            incidenceSecrecy(Incidence::SecrecyConfidential)};
75 
76     return list;
77 }
78 
incidenceStatus(Incidence::Status status)79 QString Stringify::incidenceStatus(Incidence::Status status)
80 {
81     switch (status) {
82     case Incidence::StatusTentative:
83         return i18nc("@item event is tentative", "Tentative");
84     case Incidence::StatusConfirmed:
85         return i18nc("@item event is definite", "Confirmed");
86     case Incidence::StatusCompleted:
87         return i18nc("@item to-do is complete", "Completed");
88     case Incidence::StatusNeedsAction:
89         return i18nc("@item to-do needs action", "Needs-Action");
90     case Incidence::StatusCanceled:
91         return i18nc("@item event orto-do is canceled; journal is removed", "Canceled");
92     case Incidence::StatusInProcess:
93         return i18nc("@item to-do is in process", "In-Process");
94     case Incidence::StatusDraft:
95         return i18nc("@item journal is in draft form", "Draft");
96     case Incidence::StatusFinal:
97         return i18nc("@item journal is in final form", "Final");
98     case Incidence::StatusX:
99     case Incidence::StatusNone:
100         return QString();
101     }
102     return QString();
103 }
104 
incidenceStatus(const Incidence::Ptr & incidence)105 QString Stringify::incidenceStatus(const Incidence::Ptr &incidence)
106 {
107     if (incidence->status() == Incidence::StatusX) {
108         return incidence->customStatus();
109     } else {
110         return incidenceStatus(incidence->status());
111     }
112 }
113 
attendeeRole(Attendee::Role role)114 QString Stringify::attendeeRole(Attendee::Role role)
115 {
116     switch (role) {
117     case Attendee::Chair:
118         return i18nc("@item chairperson", "Chair");
119     case Attendee::ReqParticipant:
120         return i18nc("@item participation is required", "Participant");
121     case Attendee::OptParticipant:
122         return i18nc("@item participation is optional", "Optional Participant");
123     case Attendee::NonParticipant:
124         return i18nc("@item non-participant copied for information", "Observer");
125     }
126     return {};
127 }
128 
attendeeStatus(Attendee::PartStat status)129 QString Stringify::attendeeStatus(Attendee::PartStat status)
130 {
131     switch (status) {
132     case Attendee::NeedsAction:
133         return i18nc("@item event, to-do or journal needs action", "Needs Action");
134     case Attendee::Accepted:
135         return i18nc("@item event, to-do or journal accepted", "Accepted");
136     case Attendee::Declined:
137         return i18nc("@item event, to-do or journal declined", "Declined");
138     case Attendee::Tentative:
139         return i18nc("@item event or to-do tentatively accepted", "Tentative");
140     case Attendee::Delegated:
141         return i18nc("@item event or to-do delegated", "Delegated");
142     case Attendee::Completed:
143         return i18nc("@item to-do completed", "Completed");
144     case Attendee::InProcess:
145         return i18nc("@item to-do in process of being completed", "In Process");
146     case Attendee::None:
147         return i18nc("@item event or to-do status unknown", "Unknown");
148     }
149     return {};
150 }
151 
errorMessage(const Exception & exception)152 QString Stringify::errorMessage(const Exception &exception)
153 {
154     QString message;
155 
156     switch (exception.code()) {
157     case Exception::LoadError:
158         message = i18nc("@item", "Load Error");
159         break;
160     case Exception::SaveError:
161         message = i18nc("@item", "Save Error");
162         break;
163     case Exception::ParseErrorIcal:
164         message = i18nc("@item", "Parse Error in libical");
165         break;
166     case Exception::ParseErrorKcal:
167         message = i18nc("@item", "Parse Error in the kcalcore library");
168         break;
169     case Exception::NoCalendar:
170         message = i18nc("@item", "No calendar component found.");
171         break;
172     case Exception::CalVersion1:
173         message = i18nc("@item", "Expected iCalendar, got vCalendar format");
174         break;
175     case Exception::CalVersion2:
176         message = i18nc("@item", "iCalendar Version 2.0 detected.");
177         break;
178     case Exception::CalVersionUnknown:
179         message = i18nc("@item", "Expected iCalendar, got unknown format");
180         break;
181     case Exception::Restriction:
182         message = i18nc("@item", "Restriction violation");
183         break;
184     case Exception::NoWritableFound:
185         message = i18nc("@item", "No writable resource found");
186         break;
187     case Exception::SaveErrorOpenFile:
188         Q_ASSERT(exception.arguments().count() == 1);
189         message = i18nc("@item", "Error saving to '%1'.", exception.arguments().at(0));
190         break;
191     case Exception::SaveErrorSaveFile:
192         Q_ASSERT(exception.arguments().count() == 1);
193         message = i18nc("@item", "Could not save '%1'", exception.arguments().at(0));
194         break;
195     case Exception::LibICalError:
196         message = i18nc("@item", "libical error");
197         break;
198     case Exception::VersionPropertyMissing:
199         message = i18nc("@item", "No VERSION property found");
200         break;
201     case Exception::ExpectedCalVersion2:
202         message = i18nc("@item", "Expected iCalendar, got vCalendar format");
203         break;
204     case Exception::ExpectedCalVersion2Unknown:
205         message = i18nc("@item", "Expected iCalendar, got unknown format");
206         break;
207     case Exception::ParseErrorNotIncidence:
208         message = i18nc("@item", "object is not a freebusy, event, todo or journal");
209         break;
210     case Exception::ParseErrorEmptyMessage:
211         message = i18nc("@item", "messageText is empty, unable to parse into a ScheduleMessage");
212         break;
213     case Exception::ParseErrorUnableToParse:
214         message = i18nc("@item", "icalparser is unable to parse messageText into a ScheduleMessage");
215         break;
216     case Exception::ParseErrorMethodProperty:
217         message = i18nc("@item", "message does not contain ICAL_METHOD_PROPERTY");
218         break;
219     case Exception::UserCancel:
220         // no real error; the user canceled the operation
221         break;
222     }
223 
224     return message;
225 }
226 
scheduleMessageStatus(ScheduleMessage::Status status)227 QString Stringify::scheduleMessageStatus(ScheduleMessage::Status status)
228 {
229     switch (status) {
230     case ScheduleMessage::PublishNew:
231         return i18nc("@item this is a new scheduling message", "New Scheduling Message");
232     case ScheduleMessage::PublishUpdate:
233         return i18nc("@item this is an update to an existing scheduling message", "Updated Scheduling Message");
234     case ScheduleMessage::Obsolete:
235         return i18nc("@item obsolete status", "Obsolete");
236     case ScheduleMessage::RequestNew:
237         return i18nc("@item this is a request for a new scheduling message", "New Scheduling Message Request");
238     case ScheduleMessage::RequestUpdate:
239         return i18nc("@item this is a request for an update to an existing scheduling message", "Updated Scheduling Message Request");
240     default:
241         return i18nc("@item unknown status", "Unknown Status: %1", int(status));
242     }
243 }
244 
tzUTCOffsetStr(const QTimeZone & tz)245 QString Stringify::tzUTCOffsetStr(const QTimeZone &tz)
246 {
247     int currentOffset = tz.offsetFromUtc(QDateTime::currentDateTimeUtc());
248     int absOffset = qAbs(currentOffset);
249     int utcOffsetHrs = absOffset / 3600; // in hours
250     int utcOffsetMins = (absOffset % 3600) / 60; // in minutes
251 
252     const QString hrStr = QStringLiteral("%1").arg(utcOffsetHrs, 2, 10, QLatin1Char('0'));
253     const QString mnStr = QStringLiteral("%1").arg(utcOffsetMins, 2, 10, QLatin1Char('0'));
254 
255     if (currentOffset < 0) {
256         return QStringLiteral("-%1:%2").arg(hrStr, mnStr);
257     } else {
258         return QStringLiteral("+%1:%2").arg(hrStr, mnStr);
259     }
260 }
261