1 /* 2 SPDX-FileCopyrightText: 2010-2012 Sérgio Martins <iamsergio@gmail.com> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5 */ 6 7 #pragma once 8 9 #include "history.h" 10 #include "incidencechanger.h" 11 #include <Akonadi/Collection> 12 #include <KCalendarCore/Incidence> 13 14 #include <QPointer> 15 #include <QStack> 16 #include <QVector> 17 18 using namespace Akonadi; 19 using namespace KCalendarCore; 20 21 namespace Akonadi 22 { 23 class History; 24 25 enum OperationType { TypeNone, TypeUndo, TypeRedo }; 26 27 class Entry : public QObject 28 { 29 Q_OBJECT 30 public: 31 using Ptr = QSharedPointer<Entry>; 32 using List = QVector<Entry::Ptr>; 33 Entry(const Akonadi::Item &item, const QString &description, History *qq); 34 Entry(const Akonadi::Item::List &items, const QString &description, History *qq); 35 virtual void updateIds(Item::Id oldId, Item::Id newId); 36 void doIt(OperationType); 37 38 Akonadi::Item::List mItems; 39 QString mDescription; 40 Q_SIGNALS: 41 void finished(Akonadi::IncidenceChanger::ResultCode, const QString &errorString); 42 43 protected: 44 virtual bool undo() = 0; 45 virtual bool redo() = 0; 46 void updateIdsGlobaly(Item::Id oldId, Item::Id newId); 47 QWidget *currentParent() const; 48 IncidenceChanger *mChanger = nullptr; 49 QHash<Akonadi::Item::Id, int> mLatestRevisionByItemId; 50 History *q = nullptr; 51 QVector<int> mChangeIds; 52 53 private: 54 void init(const QString &description, History *qq); 55 Q_DISABLE_COPY(Entry) 56 }; 57 58 class AKONADI_CALENDAR_EXPORT HistoryPrivate : public QObject 59 { 60 Q_OBJECT 61 public: 62 explicit HistoryPrivate(History *qq); ~HistoryPrivate()63 ~HistoryPrivate() override 64 { 65 } 66 67 void doIt(OperationType); 68 void stackEntry(const Entry::Ptr &entry, uint atomicOperationId); 69 void updateIds(Item::Id oldId, Item::Id newId); 70 QStack<Entry::Ptr> &destinationStack(); 71 QStack<Entry::Ptr> &stack(OperationType); 72 QStack<Entry::Ptr> &stack(); 73 void undoOrRedo(OperationType, QWidget *parent); 74 75 void emitDone(OperationType, History::ResultCode); 76 void setEnabled(bool enabled); 77 78 79 int redoCount() const; 80 int undoCount() const; 81 82 IncidenceChanger *const mChanger; 83 84 QStack<Entry::Ptr> mUndoStack; 85 QStack<Entry::Ptr> mRedoStack; 86 87 OperationType mOperationTypeInProgress; 88 89 Entry::Ptr mEntryInProgress; 90 91 QString mLastErrorString; 92 bool mUndoAllInProgress = false; 93 94 /** 95 * When recordCreation/Deletion/Modification is called and an undo operation is already in progress 96 * the entry is added here. 97 */ 98 QVector<Entry::Ptr> mQueuedEntries; 99 bool mEnabled = true; 100 QPointer<QWidget> mCurrentParent; 101 102 public Q_SLOTS: 103 void handleFinished(Akonadi::IncidenceChanger::ResultCode, const QString &errorString); 104 105 private: 106 History *const q; 107 }; 108 109 class CreationEntry : public Entry 110 { 111 Q_OBJECT 112 public: 113 using Ptr = QSharedPointer<CreationEntry>; 114 CreationEntry(const Akonadi::Item &item, const QString &description, History *q); 115 116 bool undo() override; 117 bool redo() override; 118 119 private Q_SLOTS: 120 void 121 onDeleteFinished(int changeId, const QVector<Akonadi::Item::Id> &deletedIds, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 122 123 void onCreateFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 124 125 private: 126 Q_DISABLE_COPY(CreationEntry) 127 }; 128 129 class DeletionEntry : public Entry 130 { 131 Q_OBJECT 132 public: 133 DeletionEntry(const Akonadi::Item::List &items, const QString &description, History *q); 134 bool undo() override; 135 bool redo() override; 136 137 private Q_SLOTS: 138 void 139 onDeleteFinished(int changeId, const QVector<Akonadi::Item::Id> &deletedIds, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 140 141 void onCreateFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 142 143 private: 144 IncidenceChanger::ResultCode mResultCode; 145 QString mErrorString; 146 QHash<int, Akonadi::Item::Id> mOldIdByChangeId; 147 int mNumPendingCreations; 148 Q_DISABLE_COPY(DeletionEntry) 149 }; 150 151 class ModificationEntry : public Entry 152 { 153 Q_OBJECT 154 public: 155 ModificationEntry(const Akonadi::Item &item, const Incidence::Ptr &originalPayload, const QString &description, History *q); 156 157 bool undo() override; 158 bool redo() override; 159 160 private Q_SLOTS: 161 void onModifyFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 162 163 private: 164 Q_DISABLE_COPY(ModificationEntry) 165 Incidence::Ptr mOriginalPayload; 166 }; 167 168 class MultiEntry : public Entry 169 { 170 Q_OBJECT 171 public: 172 using Ptr = QSharedPointer<MultiEntry>; 173 MultiEntry(int id, const QString &description, History *q); 174 175 void addEntry(const Entry::Ptr &entry); 176 void updateIds(Item::Id oldId, Item::Id newId) override; 177 178 protected: 179 bool undo() override; 180 bool redo() override; 181 182 private Q_SLOTS: 183 void onEntryFinished(Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 184 185 public: 186 const uint mAtomicOperationId; 187 188 private: 189 Entry::List mEntries; 190 int mFinishedEntries; 191 OperationType mOperationInProgress; 192 Q_DISABLE_COPY(MultiEntry) 193 }; 194 } 195 196