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 }