File indexing completed on 2024-05-12 05:10:45
0001 /* 0002 SPDX-FileCopyrightText: 2010-2012 Sérgio Martins <iamsergio@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "history.h" 0010 #include "incidencechanger.h" 0011 #include <Akonadi/Collection> 0012 #include <KCalendarCore/Incidence> 0013 0014 #include <QList> 0015 #include <QPointer> 0016 #include <QStack> 0017 0018 using namespace Akonadi; 0019 using namespace KCalendarCore; 0020 0021 namespace Akonadi 0022 { 0023 class History; 0024 0025 enum OperationType { TypeNone, TypeUndo, TypeRedo }; 0026 0027 class Entry : public QObject 0028 { 0029 Q_OBJECT 0030 public: 0031 using Ptr = QSharedPointer<Entry>; 0032 using List = QList<Entry::Ptr>; 0033 Entry(const Akonadi::Item &item, const QString &description, History *qq); 0034 Entry(const Akonadi::Item::List &items, const QString &description, History *qq); 0035 virtual void updateIds(Item::Id oldId, Item::Id newId); 0036 void doIt(OperationType); 0037 0038 Akonadi::Item::List mItems; 0039 QString mDescription; 0040 Q_SIGNALS: 0041 void finished(Akonadi::IncidenceChanger::ResultCode, const QString &errorString); 0042 0043 protected: 0044 virtual bool undo() = 0; 0045 virtual bool redo() = 0; 0046 void updateIdsGlobaly(Item::Id oldId, Item::Id newId); 0047 QWidget *currentParent() const; 0048 IncidenceChanger *mChanger = nullptr; 0049 QHash<Akonadi::Item::Id, int> mLatestRevisionByItemId; 0050 History *q = nullptr; 0051 QList<int> mChangeIds; 0052 0053 private: 0054 void init(const QString &description, History *qq); 0055 Q_DISABLE_COPY(Entry) 0056 }; 0057 0058 class AKONADI_CALENDAR_EXPORT HistoryPrivate : public QObject 0059 { 0060 Q_OBJECT 0061 public: 0062 explicit HistoryPrivate(History *qq); 0063 ~HistoryPrivate() override = default; 0064 0065 void doIt(OperationType); 0066 void stackEntry(const Entry::Ptr &entry, uint atomicOperationId); 0067 void updateIds(Item::Id oldId, Item::Id newId); 0068 QStack<Entry::Ptr> &destinationStack(); 0069 QStack<Entry::Ptr> &stack(OperationType); 0070 QStack<Entry::Ptr> &stack(); 0071 void undoOrRedo(OperationType, QWidget *parent); 0072 0073 void emitDone(OperationType, History::ResultCode); 0074 void setEnabled(bool enabled); 0075 0076 int redoCount() const; 0077 int undoCount() const; 0078 0079 IncidenceChanger *const mChanger; 0080 0081 QStack<Entry::Ptr> mUndoStack; 0082 QStack<Entry::Ptr> mRedoStack; 0083 0084 OperationType mOperationTypeInProgress; 0085 0086 Entry::Ptr mEntryInProgress; 0087 0088 QString mLastErrorString; 0089 bool mUndoAllInProgress = false; 0090 0091 /** 0092 * When recordCreation/Deletion/Modification is called and an undo operation is already in progress 0093 * the entry is added here. 0094 */ 0095 QList<Entry::Ptr> mQueuedEntries; 0096 bool mEnabled = true; 0097 QPointer<QWidget> mCurrentParent; 0098 0099 public Q_SLOTS: 0100 void handleFinished(Akonadi::IncidenceChanger::ResultCode, const QString &errorString); 0101 0102 private: 0103 History *const q; 0104 }; 0105 0106 class CreationEntry : public Entry 0107 { 0108 Q_OBJECT 0109 public: 0110 using Ptr = QSharedPointer<CreationEntry>; 0111 CreationEntry(const Akonadi::Item &item, const QString &description, History *q); 0112 0113 bool undo() override; 0114 bool redo() override; 0115 0116 private Q_SLOTS: 0117 void 0118 onDeleteFinished(int changeId, const QList<Akonadi::Item::Id> &deletedIds, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 0119 0120 void onCreateFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 0121 0122 private: 0123 Q_DISABLE_COPY(CreationEntry) 0124 }; 0125 0126 class DeletionEntry : public Entry 0127 { 0128 Q_OBJECT 0129 public: 0130 DeletionEntry(const Akonadi::Item::List &items, const QString &description, History *q); 0131 bool undo() override; 0132 bool redo() override; 0133 0134 private Q_SLOTS: 0135 void 0136 onDeleteFinished(int changeId, const QList<Akonadi::Item::Id> &deletedIds, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 0137 0138 void onCreateFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 0139 0140 private: 0141 IncidenceChanger::ResultCode mResultCode; 0142 QString mErrorString; 0143 QHash<int, Akonadi::Item::Id> mOldIdByChangeId; 0144 int mNumPendingCreations; 0145 Q_DISABLE_COPY(DeletionEntry) 0146 }; 0147 0148 class ModificationEntry : public Entry 0149 { 0150 Q_OBJECT 0151 public: 0152 ModificationEntry(const Akonadi::Item &item, const Incidence::Ptr &originalPayload, const QString &description, History *q); 0153 0154 bool undo() override; 0155 bool redo() override; 0156 0157 private Q_SLOTS: 0158 void onModifyFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 0159 0160 private: 0161 Q_DISABLE_COPY(ModificationEntry) 0162 Incidence::Ptr mOriginalPayload; 0163 }; 0164 0165 class MultiEntry : public Entry 0166 { 0167 Q_OBJECT 0168 public: 0169 using Ptr = QSharedPointer<MultiEntry>; 0170 MultiEntry(int id, const QString &description, History *q); 0171 0172 void addEntry(const Entry::Ptr &entry); 0173 void updateIds(Item::Id oldId, Item::Id newId) override; 0174 0175 protected: 0176 bool undo() override; 0177 bool redo() override; 0178 0179 private Q_SLOTS: 0180 void onEntryFinished(Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); 0181 0182 public: 0183 const uint mAtomicOperationId; 0184 0185 private: 0186 Entry::List mEntries; 0187 int mFinishedEntries; 0188 OperationType mOperationInProgress; 0189 Q_DISABLE_COPY(MultiEntry) 0190 }; 0191 }