• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • sources
  • kde-4.12
  • kdepimlibs
  • akonadi
  • calendar
incidencechanger_p.h
1 /*
2  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
3 
4  Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
5  Author: Sergio Martins, <sergio.martins@kdab.com>
6 
7  Copyright (C) 2010-2012 SĂ©rgio Martins <iamsergio@gmail.com>
8 
9  This library is free software; you can redistribute it and/or modify it
10  under the terms of the GNU Library General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or (at your
12  option) any later version.
13 
14  This library is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
17  License for more details.
18 
19  You should have received a copy of the GNU Library General Public License
20  along with this library; see the file COPYING.LIB. If not, write to the
21  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  02110-1301, USA.
23 */
24 #ifndef AKONADI_INCIDENCECHANGER_P_H
25 #define AKONADI_INCIDENCECHANGER_P_H
26 
27 #include "incidencechanger.h"
28 #include "itiphandlerhelper_p.h"
29 #include "history.h"
30 
31 #include <akonadi/item.h>
32 #include <akonadi/collection.h>
33 #include <akonadi/transactionsequence.h>
34 
35 #include <QSet>
36 #include <QObject>
37 #include <QPointer>
38 #include <QVector>
39 
40 class KJob;
41 class QWidget;
42 
43 namespace Akonadi {
44 
45 class TransactionSequence;
46 class CollectionFetchJob;
47 
48 class Change {
49 
50 public:
51  typedef QSharedPointer<Change> Ptr;
52  typedef QList<Ptr> List;
53  Change(IncidenceChanger *incidenceChanger, int changeId,
54  IncidenceChanger::ChangeType changeType, uint operationId,
55  QWidget *parent) : id(changeId)
56  , type(changeType)
57  , recordToHistory(incidenceChanger->historyEnabled())
58  , parentWidget(parent)
59  , atomicOperationId(operationId)
60  , resultCode(Akonadi::IncidenceChanger::ResultCodeSuccess)
61  , completed(false)
62  , queuedModification(false)
63  , useGroupwareCommunication(incidenceChanger->groupwareCommunication())
64  , changer(incidenceChanger)
65  {
66  }
67 
68  virtual ~Change()
69  {
70  if (parentChange) {
71  parentChange->childAboutToDie(this);
72  }
73  }
74 
75  virtual void childAboutToDie(Change *child)
76  {
77  Q_UNUSED(child);
78  }
79 
80  virtual void emitCompletionSignal() = 0;
81 
82  const int id;
83  const IncidenceChanger::ChangeType type;
84  const bool recordToHistory;
85  const QPointer<QWidget> parentWidget;
86  uint atomicOperationId;
87 
88  // If this change is internal, i.e. not initiated by the user, mParentChange will
89  // contain the non-internal change.
90  QSharedPointer<Change> parentChange;
91 
92  Akonadi::Item::List originalItems;
93  Akonadi::Item newItem;
94 
95  QString errorString;
96  IncidenceChanger::ResultCode resultCode;
97  bool completed;
98  bool queuedModification;
99  bool useGroupwareCommunication;
100 protected:
101  IncidenceChanger *const changer;
102 };
103 
104 class ModificationChange : public Change
105 {
106 public:
107  typedef QSharedPointer<ModificationChange> Ptr;
108  ModificationChange(IncidenceChanger *changer, int id, uint atomicOperationId,
109  QWidget *parent) : Change(changer, id,
110  IncidenceChanger::ChangeTypeModify,
111  atomicOperationId, parent)
112  {
113  }
114 
115  ~ModificationChange()
116  {
117  if (!parentChange)
118  emitCompletionSignal();
119  }
120 
122  void emitCompletionSignal();
123 };
124 
125 class CreationChange : public Change
126 {
127 public:
128  typedef QSharedPointer<CreationChange> Ptr;
129  CreationChange(IncidenceChanger *changer, int id, uint atomicOperationId,
130  QWidget *parent) : Change(changer, id, IncidenceChanger::ChangeTypeCreate,
131  atomicOperationId, parent)
132  {
133  }
134 
135  ~CreationChange()
136  {
137  //kDebug() << "CreationChange::~ will emit signal with " << resultCode;
138  if (!parentChange)
139  emitCompletionSignal();
140  }
141 
143  void emitCompletionSignal();
144 
145  Akonadi::Collection mUsedCol1lection;
146 };
147 
148 class DeletionChange : public Change
149 {
150 public:
151  typedef QSharedPointer<DeletionChange> Ptr;
152  DeletionChange(IncidenceChanger *changer, int id, uint atomicOperationId,
153  QWidget *parent) : Change(changer, id, IncidenceChanger::ChangeTypeDelete,
154  atomicOperationId, parent)
155  {
156  }
157 
158  ~DeletionChange()
159  {
160  //kDebug() << "DeletionChange::~ will emit signal with " << resultCode;
161  if (!parentChange)
162  emitCompletionSignal();
163  }
164 
166  void emitCompletionSignal();
167 
168  QVector<Akonadi::Item::Id> mItemIds;
169 };
170 
171 class AtomicOperation {
172 public:
173  uint m_id;
174 
175  // To make sure they are not repeated
176  QSet<Akonadi::Item::Id> m_itemIdsInOperation;
177 
178  // After endAtomicOperation() is called we don't accept more changes
179  bool m_endCalled;
180 
181  // Number of completed changes(jobs)
182  int m_numCompletedChanges;
183  QString m_description;
184  bool m_transactionCompleted;
185 
186  AtomicOperation(IncidenceChanger::Private *icp, uint ident);
187 
188  ~AtomicOperation()
189  {
190  //kDebug() << "AtomicOperation::~ " << wasRolledback << changes.count();
191  if (m_wasRolledback) {
192  for (int i=0; i<m_changes.count(); ++i) {
193  // When a job that can finish successfully is aborted because the transaction failed
194  // because of some other job, akonadi is returning an Unknown error
195  // which isnt very specific
196  if (m_changes[i]->completed &&
197  (m_changes[i]->resultCode == IncidenceChanger::ResultCodeSuccess ||
198  (m_changes[i]->resultCode == IncidenceChanger::ResultCodeJobError &&
199  m_changes[i]->errorString == QLatin1String("Unknown error.")))) {
200  m_changes[i]->resultCode = IncidenceChanger::ResultCodeRolledback;
201  }
202  }
203  }
204  }
205 
206  // Did all jobs return ?
207  bool pendingJobs() const
208  {
209  return m_changes.count() > m_numCompletedChanges;
210  }
211 
212  void setRolledback()
213  {
214  //kDebug() << "AtomicOperation::setRolledBack()";
215  m_wasRolledback = true;
216  transaction()->rollback();
217  }
218 
219  bool rolledback() const
220  {
221  return m_wasRolledback;
222  }
223 
224  void addChange(const Change::Ptr &change)
225  {
226  if (change->type == IncidenceChanger::ChangeTypeDelete) {
227  DeletionChange::Ptr deletion = change.staticCast<DeletionChange>();
228  foreach(Akonadi::Item::Id id, deletion->mItemIds) {
229  Q_ASSERT(!m_itemIdsInOperation.contains(id));
230  m_itemIdsInOperation.insert(id);
231  }
232  } else if (change->type == IncidenceChanger::ChangeTypeModify) {
233  Q_ASSERT(!m_itemIdsInOperation.contains(change->newItem.id()));
234  m_itemIdsInOperation.insert(change->newItem.id());
235  }
236 
237  m_changes << change;
238  }
239 
240  Akonadi::TransactionSequence *transaction();
241 
242 private:
243  QVector<Change::Ptr> m_changes;
244  bool m_wasRolledback;
245  Akonadi::TransactionSequence *m_transaction; // constructed in first use
246  IncidenceChanger::Private *m_incidenceChangerPrivate;
247 };
248 
249 class IncidenceChanger::Private : public QObject
250 {
251  Q_OBJECT
252 public:
253  explicit Private(bool enableHistory, IncidenceChanger *mIncidenceChanger);
254  ~Private();
255 
256  void loadCollections(); // async-loading of list of writable collections
257  bool isLoadingCollections() const;
258  Collection::List collectionsForMimeType(const QString &mimeType, const Collection::List &collections);
259 
260  // steps for the async operation:
261  void step1DetermineDestinationCollection(const Change::Ptr &change, const Collection &collection);
262  void step2CreateIncidence(const Change::Ptr &change, const Collection &collection);
263 
264 
265 
270  bool deleteAlreadyCalled(Akonadi::Item::Id id) const;
271 
272  QString showErrorDialog(Akonadi::IncidenceChanger::ResultCode, QWidget *parent);
273 
274  void setChangeInternal(int changeId);
275 
276  void adjustRecurrence(const KCalCore::Incidence::Ptr &originalIncidence,
277  const KCalCore::Incidence::Ptr &incidence);
278 
279  bool hasRights(const Akonadi::Collection &collection, IncidenceChanger::ChangeType) const;
280  void queueModification(Change::Ptr);
281  void performModification(Change::Ptr);
282  bool atomicOperationIsValid(uint atomicOperationId) const;
283  Akonadi::Job* parentJob(const Change::Ptr &) const;
284  void cancelTransaction();
285  void cleanupTransaction();
286  bool allowAtomicOperation(int atomicOperationId, const Change::Ptr &change) const;
287 
288  bool handleInvitationsBeforeChange(const Change::Ptr &change);
289  bool handleInvitationsAfterChange(const Change::Ptr &change);
290  static bool myAttendeeStatusChanged(const KCalCore::Incidence::Ptr &newIncidence,
291  const KCalCore::Incidence::Ptr &oldIncidence,
292  const QStringList &myEmails);
293 
294 public Q_SLOTS:
295  void handleCreateJobResult(KJob*);
296  void handleModifyJobResult(KJob*);
297  void handleDeleteJobResult(KJob*);
298  void handleTransactionJobResult(KJob*);
299  void performNextModification(Akonadi::Item::Id id);
300  void onCollectionsLoaded(KJob*);
301 
302 public:
303  int mLatestChangeId;
304  QHash<const KJob*,Change::Ptr> mChangeForJob;
305  bool mShowDialogsOnError;
306  Akonadi::Collection mDefaultCollection;
307  DestinationPolicy mDestinationPolicy;
308  QVector<Akonadi::Item::Id> mDeletedItemIds;
309  Change::List mPendingCreations; // Creations waiting for collections to be loaded
310 
311  History *mHistory;
312  bool mUseHistory;
313 
322  QHash<Akonadi::Item::Id,Change::Ptr> mQueuedModifications;
323 
327  QHash<Akonadi::Item::Id,Change::Ptr> mModificationsInProgress;
328 
329  QHash<int,Change::Ptr> mChangeById;
330 
334  QHash<uint,AtomicOperation*> mAtomicOperations;
335 
336  bool mRespectsCollectionRights;
337  bool mGroupwareCommunication;
338 
339  QHash<Akonadi::TransactionSequence*, uint> mAtomicOperationByTransaction;
340  QHash<uint,ITIPHandlerHelper::SendResult> mInvitationStatusByAtomicOperation;
341 
342  uint mLatestAtomicOperationId;
343  bool mBatchOperationInProgress;
344  Akonadi::Collection mLastCollectionUsed;
345  bool mAutoAdjustRecurrence;
346 
347  Akonadi::CollectionFetchJob *m_collectionFetchJob;
348 
349  QMap<KJob *, QSet<KCalCore::IncidenceBase::Field> > mDirtyFieldsByJob;
350 
351  IncidenceChanger::InvitationPolicy m_invitationPolicy;
352 
353 private:
354  IncidenceChanger *q;
355 };
356 
357 }
358 
359 #endif
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::CollectionFetchJob
Job that fetches collections from the Akonadi storage.
Definition: collectionfetchjob.h:53
Akonadi::Job
Base class for all actions in the Akonadi storage.
Definition: job.h:86
Akonadi::TransactionSequence
Base class for jobs that need to run a sequence of sub-jobs in a transaction.
Definition: transactionsequence.h:69
Akonadi::Collection::List
QList< Collection > List
Describes a list of collections.
Definition: collection.h:81
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:27 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal