1 /*
2  * SPDX-FileCopyrightText: 2020 Dimitris Kardarakos <dimkard@posteo.net>
3  *
4  * SPDX-License-Identifier: GPL-3.0-or-later
5  */
6 
7 #include "calindoriconfig.h"
8 #include <KLocalizedString>
9 #include <KConfig>
10 #include <KConfigGroup>
11 #include <QDebug>
12 #include <QRegExp>
13 #include <QDir>
14 #include <QUrl>
15 
16 class CalindoriConfig::Private
17 {
18 public:
Private()19     Private()
20         : config("calindorirc")
21     {};
22     KConfig config;
23 };
24 
CalindoriConfig(QObject * parent)25 CalindoriConfig::CalindoriConfig(QObject *parent)
26     : QObject(parent)
27     , d(new Private)
28 {
29     if (internalCalendars().isEmpty() && (d->config.group("general").readEntry("externalCalendars", QString())).isEmpty()) {
30         qDebug() << "No calendar found, creating a default one";
31         addInternalCalendar("personal");
32         setActiveCalendar("personal");
33         d->config.sync();
34     }
35 }
36 
~CalindoriConfig()37 CalindoriConfig::~CalindoriConfig()
38 {
39     delete d;
40 }
41 
internalCalendars() const42 QStringList CalindoriConfig::internalCalendars() const
43 {
44     auto cals = d->config.group("general").readEntry("calendars", QString());
45 
46     return cals.isEmpty() ? QStringList() : cals.split(";");
47 }
48 
externalCalendars() const49 QStringList CalindoriConfig::externalCalendars() const
50 {
51     auto cals = d->config.group("general").readEntry("externalCalendars", QString());
52 
53     return cals.isEmpty() ? QStringList() : cals.split(";");
54 }
55 
activeCalendar() const56 QString CalindoriConfig::activeCalendar() const
57 {
58     return d->config.group("general").readEntry("activeCalendar", QString());
59 }
60 
setActiveCalendar(const QString & calendar)61 void CalindoriConfig::setActiveCalendar(const QString &calendar)
62 {
63     d->config.group("general").writeEntry("activeCalendar", calendar);
64     d->config.sync();
65     Q_EMIT activeCalendarChanged();
66 }
67 
canAddCalendar(const QString & calendar)68 QVariantMap CalindoriConfig::canAddCalendar(const QString &calendar)
69 {
70     QRegExp invalidChars("[\\;\\\\/<>:\\?\\*|\"\']");
71     if (calendar.contains(invalidChars)) {
72         return QVariantMap({
73             {"success", false},
74             {"reason", i18n("Calendar name contains invalid characters")}
75         });
76     }
77 
78     auto externalCalendars = d->config.group("general").readEntry("externalCalendars", QString());
79 
80     if (internalCalendars().isEmpty() && externalCalendars.isEmpty()) {
81         return QVariantMap({
82             {"success", true},
83             {"reason", QString()}
84         });
85     }
86 
87     auto calendarsList = internalCalendars();
88     if (!(externalCalendars.isEmpty())) {
89         calendarsList.append(externalCalendars.split(";"));
90     }
91 
92     if (calendarsList.contains(calendar)) {
93         return QVariantMap({
94             {"success", false},
95             {"reason", i18n("Calendar already exists")}
96         });
97     }
98 
99     return QVariantMap({
100         {"success", true},
101         {"reason", QString()}
102     });
103 }
104 
addInternalCalendar(const QString & calendar,const QString & ownerName,const QString & ownerEmail)105 QVariantMap CalindoriConfig::addInternalCalendar(const QString &calendar, const QString &ownerName, const QString &ownerEmail)
106 {
107     QVariantMap canAddResult = canAddCalendar(calendar);
108 
109     if (!(canAddResult["success"].toBool())) {
110         return QVariantMap({
111             {"success", false}, {"reason ", canAddResult["reason"].toString()}
112         });
113     }
114 
115     QStringList calendars = internalCalendars();
116     calendars.append(calendar);
117     d->config.group("general").writeEntry("calendars", calendars.join(";"));
118 
119     d->config.sync();
120     setOwnerInfo(calendar, ownerName, ownerEmail);
121 
122     Q_EMIT internalCalendarsChanged();
123 
124     return QVariantMap({
125         {"success", true}, {"reason ", QString()}
126     });
127 }
128 
addExternalCalendar(const QString & calendar,const QString & ownerName,const QString & ownerEmail,const QUrl & calendarPathUrl)129 QVariantMap CalindoriConfig::addExternalCalendar(const QString &calendar, const QString &ownerName, const QString &ownerEmail, const QUrl &calendarPathUrl)
130 {
131     QVariantMap canAddResult = canAddCalendar(calendar);
132 
133     if (!(canAddResult["success"].toBool())) {
134         return QVariantMap({
135             {"success", false}, {"reason ", canAddResult["reason"].toString()}
136         });
137     }
138 
139     auto eCals = d->config.group("general").readEntry("externalCalendars", QString());
140     if (eCals.isEmpty()) {
141         d->config.group("general").writeEntry("externalCalendars", calendar);
142     } else {
143         QStringList calendarsList = eCals.split(";");
144         calendarsList.append(calendar);
145         d->config.group("general").writeEntry("externalCalendars", calendarsList.join(";"));
146     }
147     d->config.group(calendar).writeEntry("file", calendarPathUrl.toString(QUrl::RemoveScheme));
148     d->config.group(calendar).writeEntry("external", true);
149     d->config.sync();
150 
151     setOwnerInfo(calendar, ownerName, ownerEmail);
152     Q_EMIT externalCalendarsChanged();
153 
154     return QVariantMap({
155         {"success", true}, {"reason ", QString()}
156     });
157 }
158 
removeCalendar(const QString & calendar)159 void CalindoriConfig::removeCalendar(const QString &calendar)
160 {
161     d->config.reparseConfiguration();
162 
163     QStringList iCalendarsList = internalCalendars();
164     auto eCalendarsStr = d->config.group("general").readEntry("externalCalendars", QString());
165     auto eCalendarsList = eCalendarsStr.isEmpty() ? QStringList() : eCalendarsStr.split(";");
166 
167     if (iCalendarsList.contains(calendar)) {
168         iCalendarsList.removeAll(calendar);
169         d->config.group("general").writeEntry("calendars", iCalendarsList.join(";"));
170 
171         Q_EMIT internalCalendarsChanged();
172     }
173 
174     if (eCalendarsList.contains(calendar)) {
175         eCalendarsList.removeAll(calendar);
176         d->config.group("general").writeEntry("externalCalendars", eCalendarsList.join(";"));
177 
178         Q_EMIT externalCalendarsChanged();
179     }
180 
181     d->config.deleteGroup(calendar);
182     d->config.sync();
183 }
184 
calendarFile(const QString & calendarName)185 QString CalindoriConfig::calendarFile(const QString &calendarName)
186 {
187     d->config.reparseConfiguration();
188 
189     qDebug() << "calendar: " << calendarName;
190 
191     if (d->config.hasGroup(calendarName) && d->config.group(calendarName).hasKey("file")) {
192         return d->config.group(calendarName).readEntry("file");
193     }
194     d->config.group(calendarName).writeEntry("file", filenameToPath(calendarName));
195     d->config.sync();
196 
197     return filenameToPath(calendarName);
198 }
199 
filenameToPath(const QString & calendarName)200 QString CalindoriConfig::filenameToPath(const QString &calendarName)
201 {
202     QString basePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
203     QDir baseFolder(basePath);
204     baseFolder.mkpath(QStringLiteral("."));
205 
206     return basePath + "/calindori_" + calendarName + ".ics";
207 }
208 
eventsDuration() const209 int CalindoriConfig::eventsDuration() const
210 {
211     return d->config.group("events").readEntry("duration", 60);
212 }
213 
setEventsDuration(int duration)214 void CalindoriConfig::setEventsDuration(int duration)
215 {
216     d->config.group("events").writeEntry("duration", duration);
217     d->config.sync();
218 
219     Q_EMIT eventsDurationChanged();
220 }
221 
preEventRemindTime() const222 int CalindoriConfig::preEventRemindTime() const
223 {
224     return d->config.group("events").readEntry("preEventRemindTime", 15);
225 }
226 
setPreEventRemindTime(int remindBefore)227 void CalindoriConfig::setPreEventRemindTime(int remindBefore)
228 {
229     d->config.group("events").writeEntry("preEventRemindTime", remindBefore);
230     d->config.sync();
231 
232     Q_EMIT preEventRemindTimeChanged();
233 }
234 
alwaysRemind() const235 bool CalindoriConfig::alwaysRemind() const
236 {
237     return d->config.group("events").readEntry("alwaysRemind", true);
238 }
239 
setAlwaysRemind(bool remind)240 void CalindoriConfig::setAlwaysRemind(bool remind)
241 {
242     d->config.group("events").writeEntry("alwaysRemind", remind);
243     d->config.sync();
244 
245     Q_EMIT alwaysRemindChanged();
246 }
247 
isExternal(const QString & calendarName)248 bool CalindoriConfig::isExternal(const QString &calendarName)
249 {
250     if (d->config.hasGroup(calendarName) && d->config.group(calendarName).hasKey("external")) {
251         return d->config.group(calendarName).readEntry("external", false);
252     }
253 
254     return false;
255 }
256 
setOwnerInfo(const QString & calendar,const QString & ownerName,const QString & ownerEmail)257 void CalindoriConfig::setOwnerInfo(const QString &calendar, const QString &ownerName, const QString &ownerEmail)
258 {
259     setOwnerName(calendar, ownerName);
260     setOwnerEmail(calendar, ownerEmail);
261 }
262 
ownerName(const QString & calendarName)263 QString CalindoriConfig::ownerName(const QString &calendarName)
264 {
265     if (d->config.hasGroup(calendarName) && d->config.group(calendarName).hasKey("ownerName")) {
266         return d->config.group(calendarName).readEntry("ownerName", QString());
267     }
268 
269     return QString();
270 }
271 
ownerEmail(const QString & calendarName)272 QString CalindoriConfig::ownerEmail(const QString &calendarName)
273 {
274     if (d->config.hasGroup(calendarName) && d->config.group(calendarName).hasKey("ownerEmail")) {
275         return d->config.group(calendarName).readEntry("ownerEmail", QString());
276     }
277 
278     return QString();
279 }
280 
setOwnerName(const QString & calendar,const QString & ownerName)281 void CalindoriConfig::setOwnerName(const QString &calendar, const QString &ownerName)
282 {
283     d->config.group(calendar).writeEntry("ownerName", ownerName);
284     d->config.sync();
285 
286     if (isExternal(calendar)) {
287         Q_EMIT externalCalendarsChanged();
288 
289         return;
290     }
291 
292     Q_EMIT internalCalendarsChanged();
293 }
294 
setOwnerEmail(const QString & calendar,const QString & ownerEmail)295 void CalindoriConfig::setOwnerEmail(const QString &calendar, const QString &ownerEmail)
296 {
297     d->config.group(calendar).writeEntry("ownerEmail", ownerEmail);
298     d->config.sync();
299 
300     if (isExternal(calendar)) {
301         Q_EMIT externalCalendarsChanged();
302 
303         return;
304     }
305 
306     Q_EMIT internalCalendarsChanged();
307 }
308