1 /*
2  *  fileresourcesettings.h  -  settings for calendar resource accessed via file system
3  *  Program:  kalarm
4  *  SPDX-FileCopyrightText: 2020,2021 David Jarvie <djarvie@kde.org>
5  *
6  *  SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #pragma once
10 
11 #include "fileresource.h"
12 
13 #include <KAlarmCal/KACalendar>
14 #include <KAlarmCal/KAEvent>
15 
16 #include <QUrl>
17 #include <QColor>
18 #include <QByteArray>
19 #include <QSharedPointer>
20 #include <QHash>
21 
22 class KConfig;
23 class KConfigGroup;
24 
25 using namespace KAlarmCal;
26 
27 class FileResourceSettings
28 {
29 public:
30     /** A shared pointer to a FileResourceSettings object. */
31     using Ptr = QSharedPointer<FileResourceSettings>;
32 
33     enum StorageType { NoStorage, File, Directory };
34 
35     struct CommandError
36     {
37         QString             id;
38         KAEvent::CmdErrType error;
39     };
40 
FileResourceSettings()41     FileResourceSettings()  {}
42 
43     /** Initialises the settings from a config file section. */
44     FileResourceSettings(KConfig* config, const QString& resourceGroup);
45 
46     /** Initialises the settings. This should only be used by the
47      *  ResourceMigrator.
48      */
49     FileResourceSettings(StorageType, const QUrl& location, CalEvent::Types alarmTypes,
50                          const QString& displayName, const QColor& backgroundColour,
51                          CalEvent::Types enabledTypes, CalEvent::Types standardTypes,
52                          bool readOnly);
53 
54     ~FileResourceSettings();
55 
56     /** Reads the settings from the resource's config file section.
57      *  The settings are validated and amended to be consistent.
58      *  @return true if the settings are valid, false if not.
59      */
60     bool readConfig();
61 
62     /** Sets the settings into a new config file section for the resource, and
63      *  write the config to disc.
64      *  The settings will not be set if they are invalid.
65      *  The settings are validated and amended to be consistent.
66      *  @return true if the settings were written, false if invalid.
67      */
68     bool createConfig(KConfig* config, const QString& resourceGroup);
69 
70     /** Writes the settings to the config file. */
71     void save() const;
72 
73     /** Return whether the settings contain valid data. */
74     bool isValid() const;
75 
76     /** Return the resource's unique ID. */
77     ResourceId id() const;
78 
79     /** Return the resource's storage location, as a URL. */
80     QUrl url() const;
81 
82     /** Return the resource's storage location, as a displayable string. */
83     QString displayLocation() const;
84 
85     /** Return the resource's storage type. */
86     StorageType storageType() const;
87 
88     /** Return the resource's display name. */
89     QString displayName() const;
90 
91     /** Set the resource's display name.
92      *  @param name  display name to set
93      *  @param save  whether to save the config
94      *  @return  The status changes which have actually occurred, ie. the
95      *           status types (Name) for which the new status differs from the
96      *           old status.
97      */
98     ResourceType::Changes setDisplayName(const QString& name, bool save = true);
99 
100     /** Return the resource's configuration identifier. This is not the
101      *  name normally displayed to the user.
102      */
103     QString configName() const;
104 
105     /** Return which alarm types (active, archived or template) the resource
106      *  can contain. */
107     CalEvent::Types alarmTypes() const;
108 
109     /** Set which alarm types (active, archived or template) the resource can
110      *  contain.
111      *  @param types  alarm types
112      *  @param save   whether to save the config
113      *  @return  The status changes which have actually occurred, ie. the
114      *           status types (AlarmTypes/Enabled/Standard) for which the new
115      *           status differs from the old status.
116      */
117     ResourceType::Changes setAlarmTypes(CalEvent::Types types, bool save = true);
118 
119     /** Return whether the resource is enabled for a specified alarm type
120      *  (active, archived, template or displaying).
121      *  @param type  alarm type to check for.
122      */
123     bool isEnabled(CalEvent::Type type) const;
124 
125     /** Return which alarm types (active, archived or template) the resource
126      *  is enabled for. This is restricted to the alarm types which the
127      *  resource can contain (@see alarmTypes()).
128      *  @return alarm types.
129      */
130     CalEvent::Types enabledTypes() const;
131 
132     /** Set the enabled/disabled state of the resource and its alarms,
133      *  for a specified alarm type (active, archived or template). The
134      *  enabled/disabled state for other alarm types is not affected.
135      *  The alarms of that type in a disabled resource are ignored, and
136      *  not displayed in the alarm list. The standard status for that type
137      *  for a disabled resource is automatically cleared.
138      *  @param type     alarm type
139      *  @param enabled  true to set enabled, false to set disabled.
140      *  @param save     whether to save the config
141      *  @return  The status changes which have actually occurred, ie. the
142      *           status types (Enabled/Standard) for which the new status
143      *           differs from the old status.
144      */
145     ResourceType::Changes setEnabled(CalEvent::Type type, bool enabled, bool save = true);
146 
147     /** Set which alarm types (active, archived or template) the resource
148      *  is enabled for.
149      *  @param types  alarm types to enable
150      *  @param save   whether to save the config
151      *  @return  The status changes which have actually occurred, ie. the
152      *           status types (Enabled/Standard) for which the new status
153      *           differs from the old status.
154      */
155     ResourceType::Changes setEnabled(CalEvent::Types types, bool save = true);
156 
157     /** Return whether the resource is the standard resource for a specified
158      *  alarm type (active, archived or template). There is no check for
159      *  whether the resource is enabled or whether it is writable.
160      *  @param type  alarm type
161      */
162     bool isStandard(CalEvent::Type type) const;
163 
164     /** Return which alarm types (active, archived or template) the resource
165      *  is standard for. This is restricted to the alarm types which the
166      *  resource can contain (@see alarmTypes()). There is no check for
167      *  whether the resource is enabled or whether it is writable.
168      *  @return alarm types.
169      */
170     CalEvent::Types standardTypes() const;
171 
172     /** Set or clear the resource as the standard resource for a specified
173      *  alarm type (active, archived or template).
174      *  If an alarm type is newly set as standard, that alarm type will be
175      *  cleared as standard in all other settings instances.
176      *  @param type      alarm type
177      *  @param standard  true to set as standard, false to clear standard status.
178      *  @param save      whether to save the config
179      *  @return  The status changes which have actually occurred, ie. the
180      *           status types (Standard) for which the new status differs from
181      *           the old status.
182      */
183     ResourceType::Changes setStandard(CalEvent::Type, bool standard, bool save = true);
184 
185     /** Set which alarm types (active, archived or template) the
186      *  resource is the standard resource for.
187      *  If an alarm type is newly set as standard, that alarm type will be
188      *  cleared as standard in all other settings instances.
189      *  @param types  alarm types.to set as standard
190      *  @param save   whether to save the config
191      *  @return  The status changes which have actually occurred, ie. the
192      *           status types (Standard) for which the new status differs from
193      *           the old status.
194      */
195     ResourceType::Changes setStandard(CalEvent::Types types, bool save = true);
196 
197     /** Return the background colour to display this resource and its alarms,
198      *  or invalid colour if none is set.
199      */
200     QColor backgroundColour() const;
201 
202     /** Set the background colour for this resource and its alarms.
203      *  @param c     background colour
204      *  @param save  whether to save the config
205      *  @return  The status changes which have actually occurred, ie. the
206      *           status types (BackgroundColour) for which the new status
207      *           differs from the old status.
208      */
209     ResourceType::Changes setBackgroundColour(const QColor& c, bool save = true);
210 
211     /** Return whether the resource is specified as read-only. */
212     bool readOnly() const;
213 
214     /** Specify the read-only status of the resource.
215      *  Note that even if set NOT read-only, it will not be writable if it
216      *  is not in the current KAlarm calendar format.
217      *  @param ronly  true to set read-only, false to allow writes.
218      *  @param save   whether to save the config
219      *  @return  The status changes which have actually occurred, ie. the
220      *           status types (ReadOnly) for which the new status
221      *           differs from the old status.
222      */
223     ResourceType::Changes setReadOnly(bool ronly, bool save = true);
224 
225     /** Return whether the user has chosen to keep the old calendar storage
226      *  format, i.e. not update to current KAlarm format.
227      */
228     bool keepFormat() const;
229 
230     /** Set whether to keep the old calendar storage format unchanged.
231      *  @param keep  true to keep format unchanged, false to allow changes.
232      *  @param save  whether to save the config
233      *  @return  The status changes which have actually occurred, ie. the
234      *           status types (KeepFormat) for which the new status
235      *           differs from the old status.
236      */
237     ResourceType::Changes setKeepFormat(bool keep, bool save = true);
238 
239     /** Return whether the user has chosen to update the calendar storage
240      *  format to the current KAlarm format.
241      */
242     bool updateFormat() const;
243 
244     /** Set whether to update the calendar storage format to the current
245      *  KAlarm format.
246      *  @param update  true to update format, false to leave unchanged
247      *  @param save    whether to save the config
248      *  @return  The status changes which have actually occurred, ie. the
249      *           status types (UpdateFormat) for which the new status
250      *           differs from the old status.
251      */
252     ResourceType::Changes setUpdateFormat(bool update, bool save = true);
253 
254     /** Return the saved hash of the calendar file contents. */
255     QByteArray hash() const;
256 
257     /** Set the saved hash of the calendar file contents.
258      *  @param hash  hash value
259      *  @param save  whether to save the config
260      */
261     void setHash(const QByteArray& hash, bool save = true);
262 
263     /** Return the command error data for all events in the resource which have
264      *  command errors.
265      *  @return command error types, indexed by event ID.
266      */
267     QHash<QString, KAEvent::CmdErrType> commandErrors() const;
268 
269     /** Set the command error data for all events in the resource which have
270      *  command errors.
271      *  @param cmdErrors  command error types, indexed by event ID.
272      *  @param save       whether to save the config
273      */
274     void setCommandErrors(const QHash<QString, KAEvent::CmdErrType>& cmdErrors, bool save = true);
275 
276 protected:
277     /** Set the resource's unique ID.
278      *  This method can only be called when initialising the instance.
279      */
280     void setId(ResourceId id);
281 
282     friend class FileResourceConfigManager;
283 
284 private:
285     bool                  validate();
286     CalEvent::Types       readAlarmTypes(const char* key) const;
287     static QString        alarmTypesString(CalEvent::Types alarmTypes);
288     static StorageType    storageType(const QUrl& url);
289     ResourceType::Changes handleEnabledChange(CalEvent::Types oldEnabled, CalEvent::Types oldStandard, bool typesChanged, bool save);
290     ResourceType::Changes handleStandardChange(CalEvent::Types oldStandard, bool sync);
291     void writeConfigDisplayName(bool save);
292     void writeConfigAlarmTypes(bool save);
293     void writeConfigEnabled(bool save);
294     void writeConfigStandard(bool save);
295     void writeConfigBackgroundColour(bool save);
296     void writeConfigReadOnly(bool save);
297     void writeConfigKeepFormat(bool save);
298     void writeConfigUpdateFormat(bool save);
299     void writeConfigHash(bool save);
300     void writeConfigCommandErrors(bool save);
301 
302     KConfigGroup*     mConfigGroup {nullptr}; // the config group holding all this resource's config
303                                               // Until this is set, no notifications will be made
304     ResourceId        mId {-1};          // resource's unique ID
305     QUrl              mUrl;              // location of file or directory
306     QString           mDisplayLocation;  // displayable location of file or directory
307     QString           mDisplayName;      // name for user display
308     QByteArray        mHash;             // hash of the calendar file contents
309     QHash<QString, KAEvent::CmdErrType> mCommandErrors;  // event IDs and their command error types
310     QColor            mBackgroundColour; // background colour to display the resource and its alarms
311     StorageType       mStorageType {NoStorage};      // how the calendar is stored
312     CalEvent::Types   mAlarmTypes {CalEvent::EMPTY}; // alarm types which the resource contains
313     CalEvent::Types   mEnabled {CalEvent::EMPTY};    // alarm types for which the resource is enabled
314     CalEvent::Types   mStandard {CalEvent::EMPTY};   // alarm types for which the resource is the standard resource
315     bool              mReadOnly {false};  // the resource is read-only
316     bool              mKeepFormat {true}; // do not update the calendar file to the current KAlarm format
317     bool              mUpdateFormat {false}; // request to update the calendar file to the current KAlarm format
318 };
319 
320 
321 // vim: et sw=4:
322