Akonadi Calendar

incidencechanger.h
1/*
2 SPDX-FileCopyrightText: 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
3 SPDX-FileCopyrightText: 2010-2012 Sérgio Martins <iamsergio@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7#pragma once
8
9#include "akonadi-calendar_export.h"
10
11#include "itiphandler.h"
12#include <Akonadi/Collection>
13#include <Akonadi/Item>
14
15#include <KCalendarCore/Incidence>
16
17#include <QFlags>
18#include <QWidget>
19
20#include <memory>
21
22namespace Akonadi
23{
24class EntityTreeModel;
25class IncidenceChangerPrivate;
26
27/**
28 * @short IncidenceChanger is the preferred way to easily create, modify and delete incidences.
29 *
30 * It hides the communication with akonadi from the library user.
31 *
32 * It provides the following features that ItemCreateJob, ItemModifyJob and
33 * ItemDeleteJob do not:
34 * - Sending groupware ( iTip ) messages to attendees and organizers.
35 * - Aware of recurrences, allowing to only change one occurrence.
36 * - Undo/Redo
37 * - Group operations which are executed in an atomic manner.
38 * - Collection ACLs
39 * - Error dialogs with calendaring lingo
40 *
41 * In the context of this API, "change", means "creation", "deletion" or incidence "modification".
42 *
43 * @code
44 * IncidenceChanger *changer = new IncidenceChanger( parent );
45 * connect( changer,
46 * SIGNAL(createFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
47 * SLOT(slotCreateFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)) );
48 *
49 * connect( changer,
50 * SIGNAL(deleteFinished(int,QList<Akonadi::Item::Id>,Akonadi::IncidenceChanger::ResultCode,QString)),
51 * SLOT(slotDeleteFinished(int,QList<Akonadi::Item::Id>,Akonadi::IncidenceChanger::ResultCode,QString)) );
52 *
53 * connect( changer,SIGNAL(modifyFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
54 * SLOT(slotModifyFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)) );
55 *
56 * changer->setDestinationPolicy( IncidenceChanger::DestinationPolicyAsk );
57 *
58 * KCalendarCore::Incidence::Ptr incidence = (...);
59 * int changeId = changer->createIncidence( incidence, Akonadi::Collection() );
60 *
61 *
62 * if ( changeId == -1 )
63 * {
64 * // Invalid parameters, incidence is null.
65 * }
66 *
67 * @endcode
68 *
69 * @author Sérgio Martins <iamsergio@gmail.com>
70 * @since 4.11
71 */
72
73class History;
74
75class AKONADI_CALENDAR_EXPORT IncidenceChanger : public QObject
76{
77 Q_OBJECT
78public:
79 /**
80 * This enum describes result codes which are returned by createFinished(),
81 * modifyfinished() and deleteFinished() signals.
82 */
83 enum ResultCode {
84 ResultCodeSuccess = 0,
85 ResultCodeJobError, ///< ItemCreateJob, ItemModifyJob or ItemDeleteJob weren't successful
86 ResultCodeAlreadyDeleted, ///< That incidence was already deleted, or currently being deleted.
87 ResultCodeInvalidDefaultCollection, ///< Default collection is invalid and DestinationPolicyNeverAsk was used
88 ResultCodeRolledback, ///< One change belonging to an atomic operation failed. All other changes were rolled back.
89 ResultCodePermissions, ///< The parent collection doesn't have ACLs for this operation
90 ResultCodeUserCanceled, ///< User canceled the operation
91 ResultCodeInvalidUserCollection, ///< User somehow chose an invalid collection in the collection dialog ( should not happen )
92 ResultCodeModificationDiscarded, ///< A new modification came in, the old one is discarded
93 ResultCodeDuplicateId ///< Duplicate Akonadi::Item::Ids must be unique in group operations
94 };
95
96 /**
97 * This enum describes destination policies.
98 * Destination policies control how the createIncidence() method chooses the
99 * collection where the item will be created.
100 */
101 enum DestinationPolicy {
102 DestinationPolicyDefault, ///< The default collection is used, if it's invalid, the user is prompted. @see setDefaultCollection().
103 DestinationPolicyAsk, ///< User is always asked which collection to use.
104 DestinationPolicyNeverAsk ///< The default collection is used, if it's invalid, an error is returned, and the incidence isn't added.
105 };
106
107 /**
108 * Enum for controlling "Do you want to e-mail attendees" type of dialogs.
109 * This is only honoured if groupware communication is active.
110 *
111 * @see groupwareCommunication()
112 * @since 4.12
113 */
114 enum InvitationPolicy {
115 InvitationPolicySend = 0, ///< Invitation e-mails are sent without asking the user if he wants to.
116 InvitationPolicyAsk, ///< The user is asked if an e-mail should be sent. This is the default.
117 InvitationPolicyDontSend ///< E-mails aren't sent
118 };
119
120 /**
121 * Flags describing whether invitation emails should signed and/or encrypted.
122 */
123 enum InvitationPrivacy {
124 InvitationPrivacyPlain = 0, ///< Invitation emails are not signed or encrpyted
125 InvitationPrivacySign = 1, ///< Invitation emails are signed
126 InvitationPrivacyEncrypt = 2 //< Invitation emails are encrypted
127 };
128 Q_DECLARE_FLAGS(InvitationPrivacyFlags, InvitationPrivacy)
129
130 /**
131 * This enum describes change types.
132 */
133 enum ChangeType {
134 ChangeTypeCreate, ///> Represents an incidence creation.
135 ChangeTypeModify, ///> Represents an incidence modification.
136 ChangeTypeDelete ///> Represents an incidence deletion.
137 };
138
139 /**
140 * Creates a new IncidenceChanger instance.
141 * creates a default ITIPHandlerComponentFactory object.
142 * @param parent parent QObject
143 */
144 explicit IncidenceChanger(QObject *parent = nullptr);
145
146 /**
147 * Creates a new IncidenceChanger instance.
148 * @param factory factory for creating dialogs and the mail transport job. To create a default
149 * factory set factory == 0
150 * @param parent parent QObject
151 * @since 4.15
152 */
153 explicit IncidenceChanger(ITIPHandlerComponentFactory *factory, QObject *parent);
154
155 /**
156 * Destroys this IncidenceChanger instance.
157 */
158 ~IncidenceChanger() override;
159
160 /**
161 * Creates a new incidence.
162 *
163 * @param incidence Incidence to create, must be valid.
164 * @param collection Collection where the incidence will be created. If invalid, one according
165 * to the DestinationPolicy will be used. You can know which collection was
166 * used by calling lastCollectionUsed();
167 * @param parent widget parent to be used in dialogs.
168 *
169 * @return Returns an integer which identifies this change. This identifier is useful
170 * to correlate this operation with the IncidenceChanger::createFinished() signal.
171 *
172 * Returns -1 if @p incidence is invalid. The createFinished() signal
173 * won't be emitted in this case.
174 */
175 int
176 createIncidence(const KCalendarCore::Incidence::Ptr &incidence, const Akonadi::Collection &collection = Akonadi::Collection(), QWidget *parent = nullptr);
177
178 /**
179 * Creates a new incidence.
180 *
181 * @param item Item containing the incidence to create and metadata, such as tags.
182 * @param collection Collection where the incidence will be created. If invalid, one according
183 * to the DestinationPolicy will be used. You can know which collection was
184 * used by calling lastCollectionUsed();
185 * @param parent widget parent to be used in dialogs.
186 *
187 * @return Returns an integer which identifies this change. This identifier is useful
188 * to correlate this operation with the IncidenceChanger::createFinished() signal.
189 *
190 * Returns -1 if @p item is invalid. The createFinished() signal
191 * won't be emitted in this case.
192 */
193 int createFromItem(const Akonadi::Item &item, const Akonadi::Collection &collection = Akonadi::Collection(), QWidget *parent = nullptr);
194
195 /**
196 * Deletes an incidence. If it's recurring, all occurrences are deleted.
197 *
198 * @param item Item to delete. Item must be valid.
199 * @param parent Parent to be used in dialogs.
200 *
201 * @return Returns an integer which identifies this deletion. This identifier is useful
202 * to correlate this deletion with the IncidenceChanger::deleteFinished() signal.
203 *
204 * Returns -1 if item is invalid. The deleteFinished() signal won't be emitted in this
205 * case.
206 */
207 int deleteIncidence(const Akonadi::Item &item, QWidget *parent = nullptr);
208
209 /**
210 * Deletes a list of Items.
211 *
212 * @param items List of items do delete. They must be valid.
213 * @param parent Parent to be used in dialogs.
214 * @return Returns an integer which identifies this deletion. This identifier is useful
215 * to correlate this operation with the IncidenceChanger::deleteFinished() signal.
216 *
217 * Returns -1 if any item is invalid or if @p items is empty. The deleteFinished() signal
218 * won't be emitted in this case.
219 */
220 int deleteIncidences(const Akonadi::Item::List &items, QWidget *parent = nullptr);
221
222 /**
223 * Modifies an incidence.
224 *
225 * @param item A valid item, with the new payload.
226 * @param originalPayload The payload before the modification. If invalid it won't be recorded
227 * to the undo stack and groupware functionality won't be used for this
228 * deletion.
229 * @param parent Parent to be used in dialogs.
230 *
231 * @return Returns an integer which identifies this modification. This identifier is useful
232 * to correlate this operation with the IncidenceChanger::modifyFinished() signal.
233 *
234 * Returns -1 if the item doesn't have a valid payload. The modifyFinished() signal
235 * won't be emitted in this case.
236 */
237 int modifyIncidence(const Akonadi::Item &item,
239 QWidget *parent = nullptr);
240
241 /**
242 * Some incidence operations require more than one change. Like dissociating
243 * occurrences, which needs an incidence add and an incidence change.
244 *
245 * If you want to prevent that the same dialogs are presented multiple times
246 * use this function to start a batch operation.
247 *
248 * If one change belonging to a batch operation fails, all other changes
249 * are rolled back.
250 *
251 * @param operationDescription Describes what the atomic operation does.
252 * This will be what incidenceChanger->history()->descriptionForNextUndo()
253 * if you have history enabled.
254 *
255 * @see endAtomicOperation()
256 */
257 void startAtomicOperation(const QString &operationDescription = QString());
258
259 /**
260 * Tells IncidenceChanger you finished doing changes that belong to a
261 * batch operation.
262 *
263 * @see startAtomicOperation()
264 */
265 void endAtomicOperation();
266
267 /**
268 * Sets the base ETM tree model
269 * Used by the editor dialog's collection combobox, for instance.
270 */
271 void setEntityTreeModel(Akonadi::EntityTreeModel *model);
272
273 /**
274 * Returns the base ETM tree model
275 */
276 [[nodiscard]] Akonadi::EntityTreeModel *entityTreeModel() const;
277
278 /**
279 * Sets the default collection.
280 * @param collection The collection to be used in createIncidence() if the
281 * proper destination policy is set.
282 * @see createIncidence()
283 * @see destinationPolicy()
284 * @see defaultCollection()
285 */
286 void setDefaultCollection(const Akonadi::Collection &collection);
287
288 /**
289 * Returns the defaultCollection.
290 * If none is set, an invalid Collection is returned.
291 * @see setDefaultCollection()
292 * @see DestinationPolicy
293 */
294 [[nodiscard]] Akonadi::Collection defaultCollection() const;
295
296 /**
297 * Sets the destination policy to use. The destination policy determines the
298 * collection to use in createIncidence()
299 *
300 * @see createIncidence()
301 * @see destinationPolicy()
302 */
303 void setDestinationPolicy(DestinationPolicy destinationPolicy);
304
305 /**
306 * Returns the current destination policy.
307 * If none is set, DestinationPolicyDefault is returned.
308 * @see setDestinationPolicy()
309 * @see DestinationPolicy
310 */
311 [[nodiscard]] DestinationPolicy destinationPolicy() const;
312
313 /**
314 * Sets if IncidenceChanger should show error dialogs.
315 */
316 void setShowDialogsOnError(bool enable);
317
318 /**
319 * Returns true if error dialogs are shown by IncidenceChanger.
320 * The default is true.
321 *
322 * @see setShowDialogsOnError()
323 */
324 [[nodiscard]] bool showDialogsOnError() const;
325
326 /**
327 * Sets if IncidenceChanger should honour collection's ACLs by disallowing changes if
328 * necessary.
329 */
330 void setRespectsCollectionRights(bool respect);
331
332 /**
333 * Returns true if IncidenceChanger honors collection's ACLs by disallowing
334 * changes if necessary.
335 *
336 * The default is true.
337 * @see setRespectsCollectionRights()
338 * @see ResultCode::ResultCodePermissions
339 */
340 [[nodiscard]] bool respectsCollectionRights() const;
341
342 /**
343 * Enable or disable history.
344 * With history enabled all changes are recorded into the undo/redo stack.
345 *
346 * @see history()
347 * @see historyEnabled()
348 */
349 void setHistoryEnabled(bool enable);
350
351 /**
352 * Returns true if changes are added into the undo stack.
353 * Default is true.
354 *
355 * @see history()
356 * @see historyEnabled()
357 */
358 [[nodiscard]] bool historyEnabled() const;
359
360 /**
361 * Returns a pointer to the history object.
362 * It's always valid.
363 * Ownership remains with IncidenceChanger.
364 */
365 [[nodiscard]] History *history() const;
366
367 /**
368 * For performance reasons, IncidenceChanger internally caches the ids of the last deleted items,
369 * to avoid creating useless delete jobs.
370 *
371 * This function exposes that functionality so it can be used in other scenarios.
372 * One popular scenario is when you're using an ETM and the user is deleting items very fast,
373 * ETM doesn't know about the deletions immediately, so it can happen that some items are
374 * deleted more than once, resulting in an error.
375 *
376 * @return true if the item was deleted recently, false otherwise.
377 */
378 [[nodiscard]] bool deletedRecently(Akonadi::Item::Id) const;
379
380 /**
381 * Enables or disabled groupware communication.
382 * With groupware communication enabled, invitations and update e-mails will be sent to each
383 * attendee.
384 */
385 void setGroupwareCommunication(bool enabled);
386
387 /**
388 * Returns if we're using groupware communication.
389 * Default is false.
390 * @see setGroupwareCommuniation()
391 */
392 [[nodiscard]] bool groupwareCommunication() const;
393
394 /**
395 * Makes modifyIncidence() adjust recurrence parameters when modifying DTSTART.
396 */
397 void setAutoAdjustRecurrence(bool enable);
398
399 /**
400 * True if recurrence parameters are adjusted when modifying DTSTART.
401 * Default is true.
402 */
403 [[nodiscard]] bool autoAdjustRecurrence() const;
404
405 /**
406 * Sets the invitation policy.
407 *
408 * @since 4.12
409 */
410 void setInvitationPolicy(InvitationPolicy policy);
411
412 /**
413 * Returns the invitation policy.
414 * The default is InvitationPolicyAsk.
415 *
416 * @since 4.12
417 */
418 [[nodiscard]] InvitationPolicy invitationPolicy() const;
419
420 /**
421 * Returns the collection that the last createIncidence() used.
422 * Will be invalid if no incidences were created yet.
423 *
424 * @see createIncidence().
425 */
426 [[nodiscard]] Akonadi::Collection lastCollectionUsed() const;
427
428 /**
429 * Sets the invitation privacy flags.
430 */
431 void setInvitationPrivacy(InvitationPrivacyFlags invitationPrivacy);
432
433 /**
434 * Returns the invitation privacy policy.
435 * Default value is InvitationPrivacyPlain.
436 */
437 [[nodiscard]] InvitationPrivacyFlags invitationPrivacy() const;
438
439Q_SIGNALS:
440 /**
441 * Emitted when IncidenceChanger creates an Incidence in akonadi.
442 *
443 * @param changeId the unique identifier of this change, returned by createIncidence().
444 * @param item the created item, might be invalid if the @p resultCode is not ResultCodeSuccess
445 * @param resultCode success/error code
446 * @param errorString if @p resultCode is not ResultCodeSuccess, contains an i18n'ed error
447 * message. If you enabled error dialogs, this string was already presented to the user.
448 */
449 void createFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString);
450 /**
451 * Emitted when IncidenceChanger modifies an Incidence in akonadi.
452 *
453 * @param changeId the unique identifier of this change, returned by modifyIncidence().
454 * @param item the modified item, might be invalid if the @p resultCode is not ResultCodeSuccess
455 * @param resultCode success/error code
456 * @param errorString if @p resultCode is not ResultCodeSuccess, contains an i18n'ed error
457 * message. If you enabled error dialogs, this string was already presented to the user.
458 */
459 void modifyFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString);
460 /**
461 * Emitted when IncidenceChanger deletes an Incidence in akonadi.
462 *
463 * @param changeId the unique identifier of this change, returned by deletedIncidence().
464 * @param itemIdList list of deleted item ids, might be emptu if the @p resultCode is not
465 * ResultCodeSuccess
466 * @param resultCode success/error code
467 * @param errorString if @p resultCode is not ResultCodeSuccess, contains an i18n'ed error
468 * message. If you enabled error dialogs, this string was already presented to the user.
469 */
470 void deleteFinished(int changeId, const QList<Akonadi::Item::Id> &itemIdList, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString);
471
472private:
473 //@cond PRIVATE
474 friend class HistoryPrivate;
475 friend class AtomicOperation;
476 // used internally by the History class
477 explicit IncidenceChanger(bool enableHistory, QObject *parent = nullptr);
478
479 std::unique_ptr<IncidenceChangerPrivate> const d;
480 //@endcond
481};
482}
483
484Q_DECLARE_OPERATORS_FOR_FLAGS(Akonadi::IncidenceChanger::InvitationPrivacyFlags)
485
486Q_DECLARE_METATYPE(Akonadi::IncidenceChanger::DestinationPolicy)
487Q_DECLARE_METATYPE(Akonadi::IncidenceChanger::ResultCode)
488Q_DECLARE_METATYPE(Akonadi::IncidenceChanger::ChangeType)
FreeBusyManager::Singleton.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:37:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.