File indexing completed on 2024-05-12 05:14:59

0001 /*
0002  *  undo.cpp  -  undo/redo facility
0003  *  Program:  kalarm
0004  *  SPDX-FileCopyrightText: 2005-2022 David Jarvie <djarvie@kde.org>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "undo.h"
0010 
0011 #include "functions.h"
0012 #include "resources/resources.h"
0013 #include "lib/messagebox.h"
0014 #include "kalarmcalendar/alarmtext.h"
0015 #include "kalarm_debug.h"
0016 
0017 #include <KLocalizedString>
0018 
0019 #include <QApplication>
0020 
0021 static int maxCount = 12;
0022 
0023 #ifdef DELETE
0024 #undef DELETE // conflicting Windows macro
0025 #endif
0026 
0027 class UndoItem
0028 {
0029     public:
0030         enum Operation { ADD, EDIT, DELETE, REACTIVATE, DEACTIVATE, MULTI };
0031         UndoItem();           // needed by QList
0032         virtual ~UndoItem();
0033         virtual Operation  operation() const = 0;
0034         virtual QString    actionText() const    { return !mName.isEmpty() ? mName : defaultActionText(); }
0035         virtual QString    defaultActionText() const = 0;
0036         virtual QString    description() const   { return {}; }
0037         virtual QString    eventID() const       { return {}; }
0038         virtual QString    oldEventID() const    { return {}; }
0039         virtual QString    newEventID() const    { return {}; }
0040         virtual Resource   resource() const      { return {}; }
0041         int                id() const            { return mId; }
0042         Undo::Type         type() const          { return mType; }
0043         void               setType(Undo::Type t) { mType = t; }
0044         CalEvent::Type     calendar() const      { return mCalendar; }
0045         virtual void       setCalendar(CalEvent::Type s) { mCalendar = s; }
0046         virtual UndoItem*  restore() = 0;
0047         virtual bool       deleteID(const QString& /*id*/)  { return false; }
0048         virtual void       dumpDebug() const;
0049 
0050         enum Error   { ERR_NONE, ERR_PROG, ERR_NOT_FOUND, ERR_CREATE, ERR_TEMPLATE, ERR_ARCHIVED };
0051         enum Warning { WARN_NONE, WARN_KORG_ADD, WARN_KORG_MODIFY, WARN_KORG_DELETE };
0052         static int         mLastId;
0053         static Error       mRestoreError;         // error code valid only if restore() returns 0
0054         static Warning     mRestoreWarning;       // warning code set by restore()
0055         static KAlarm::UpdateResult mRestoreWarningKorg; // KOrganizer error status set by restore()
0056         static int         mRestoreWarningCount;  // item count for mRestoreWarning (to allow i18n messages to work correctly)
0057 
0058     protected:
0059         UndoItem(Undo::Type, const QString& name = QString());
0060         static QString     addDeleteActionText(CalEvent::Type, bool add);
0061         QString            description(const KAEvent&) const;
0062         void               replaceWith(UndoItem* item)   { Undo::replace(this, item); }
0063         virtual void       dumpDebugTitle(const char* typeName) const;
0064 
0065         QString            mName;      // specified action name (overrides default)
0066         int                mId {0};    // unique identifier (only for mType = UNDO, REDO)
0067         Undo::Type         mType;      // which list (if any) the object is in
0068         CalEvent::Type     mCalendar;
0069 };
0070 
0071 class UndoMultiBase : public UndoItem
0072 {
0073     public:
0074         UndoMultiBase(Undo::Type t, const QString& name)
0075                 : UndoItem(t, name), mUndos(new Undo::List) {}
0076         UndoMultiBase(Undo::Type t, Undo::List* undos, const QString& name)
0077                 : UndoItem(t, name), mUndos(undos) {}
0078         UndoMultiBase(const UndoMultiBase&) = delete;
0079         UndoMultiBase& operator=(const UndoMultiBase&) = delete;
0080         ~UndoMultiBase() override { delete mUndos; }
0081         const Undo::List* undos() const         { return mUndos; }
0082     protected:
0083         void               dumpDebugTitle(const char* typeName) const override;
0084 
0085         Undo::List* mUndos;    // this list must always have >= 2 entries
0086 };
0087 
0088 template <class T> class UndoMulti : public UndoMultiBase
0089 {
0090     public:
0091         UndoMulti(Undo::Type, const Undo::EventList&, const QString& name);
0092         UndoMulti(Undo::Type t, Undo::List* undos, const QString& name)  : UndoMultiBase(t, undos, name) {}
0093         Operation         operation() const override     { return MULTI; }
0094         UndoItem*         restore() override;
0095         bool              deleteID(const QString& id) override;
0096         virtual UndoItem* createRedo(Undo::List*) = 0;
0097 };
0098 
0099 class UndoAdd : public UndoItem
0100 {
0101     public:
0102         UndoAdd(Undo::Type, const Undo::Event&, const QString& name = QString());
0103         UndoAdd(Undo::Type, const KAEvent&, const Resource&, const QString& name = QString());
0104         UndoAdd(Undo::Type, const KAEvent&, const Resource&, const QString& name, CalEvent::Type);
0105         Operation          operation() const override     { return ADD; }
0106         QString            defaultActionText() const override;
0107         QString            description() const override   { return mDescription; }
0108         Resource           resource() const override      { return mResource; }
0109         QString            eventID() const override       { return mEventId; }
0110         QString            newEventID() const override    { return mEventId; }
0111         UndoItem*          restore() override             { return doRestore(); }
0112         void               dumpDebug() const override;
0113     protected:
0114         UndoItem*          doRestore(bool setArchive = false);
0115         virtual UndoItem*  createRedo(const KAEvent&, const Resource&);
0116         void               dumpDebugTitle(const char* typeName) const override;
0117     private:
0118         Resource       mResource;  // resource containing the event
0119         QString        mEventId;
0120         QString        mDescription;
0121 };
0122 
0123 class UndoEdit : public UndoItem
0124 {
0125     public:
0126         UndoEdit(Undo::Type, const KAEvent& oldEvent, const QString& newEventID,
0127                  const Resource&, const QStringList& dontShowErrors, const QString& description);
0128         UndoEdit(const UndoEdit&) = delete;
0129         UndoEdit& operator=(const UndoEdit&) = delete;
0130         ~UndoEdit() override;
0131         Operation          operation() const override     { return EDIT; }
0132         QString            defaultActionText() const override;
0133         QString            description() const override   { return mDescription; }
0134         Resource           resource() const override      { return mResource; }
0135         QString            eventID() const override       { return mNewEventId; }
0136         QString            oldEventID() const override    { return mOldEvent->id(); }
0137         QString            newEventID() const override    { return mNewEventId; }
0138         UndoItem*          restore() override;
0139         void               dumpDebug() const override;
0140     protected:
0141         void               dumpDebugTitle(const char* typeName) const override;
0142     private:
0143         Resource       mResource;  // resource containing the event
0144         KAEvent*       mOldEvent;
0145         QString        mNewEventId;
0146         QString        mDescription;
0147         QStringList    mDontShowErrors;
0148 };
0149 
0150 class UndoDelete : public UndoItem
0151 {
0152     public:
0153         UndoDelete(Undo::Type, const Undo::Event&, const QString& name = QString());
0154         UndoDelete(Undo::Type, const KAEvent&, const Resource&, const QStringList& dontShowErrors, const QString& name = QString());
0155         UndoDelete(const UndoDelete&) = delete;
0156         UndoDelete& operator=(const UndoDelete&) = delete;
0157         ~UndoDelete() override;
0158         Operation          operation() const override     { return DELETE; }
0159         QString            defaultActionText() const override;
0160         QString            description() const override   { return UndoItem::description(*mEvent); }
0161         Resource           resource() const override      { return mResource; }
0162         QString            eventID() const override       { return mEvent->id(); }
0163         QString            oldEventID() const override    { return mEvent->id(); }
0164         UndoItem*          restore() override;
0165         KAEvent*           event() const                  { return mEvent; }
0166         void               dumpDebug() const override;
0167     protected:
0168         virtual UndoItem*  createRedo(const KAEvent&, const Resource&);
0169         void               dumpDebugTitle(const char* typeName) const override;
0170     private:
0171         Resource       mResource;  // resource containing the event
0172         KAEvent*       mEvent;
0173         QStringList    mDontShowErrors;
0174 };
0175 
0176 class UndoReactivate : public UndoAdd
0177 {
0178     public:
0179         UndoReactivate(Undo::Type t, const Undo::Event& e, const QString& name = QString())
0180                  : UndoAdd(t, e.event, e.resource, name, CalEvent::ACTIVE) {}
0181         UndoReactivate(Undo::Type t, const KAEvent& e, const Resource& r, const QString& name = QString())
0182                  : UndoAdd(t, e, r, name, CalEvent::ACTIVE) {}
0183         Operation          operation() const override     { return REACTIVATE; }
0184         QString            defaultActionText() const override;
0185         UndoItem*          restore() override;
0186         void               dumpDebug() const override;
0187     protected:
0188         UndoItem*          createRedo(const KAEvent&, const Resource&) override;
0189 };
0190 
0191 class UndoDeactivate : public UndoDelete
0192 {
0193     public:
0194         UndoDeactivate(Undo::Type t, const KAEvent& e, const Resource& r, const QString& name = QString())
0195                  : UndoDelete(t, e, r, QStringList(), name) {}
0196         Operation          operation() const override     { return DEACTIVATE; }
0197         QString            defaultActionText() const override;
0198         UndoItem*          restore() override;
0199         void               dumpDebug() const override;
0200     protected:
0201         UndoItem*          createRedo(const KAEvent&, const Resource&) override;
0202 };
0203 
0204 class UndoAdds : public UndoMulti<UndoAdd>
0205 {
0206     public:
0207         UndoAdds(Undo::Type t, const Undo::EventList& events, const QString& name = QString())
0208                  : UndoMulti<UndoAdd>(t, events, name) {}   // UNDO only
0209         UndoAdds(Undo::Type t, Undo::List* undos, const QString& name)
0210                  : UndoMulti<UndoAdd>(t, undos, name) {}
0211         QString            defaultActionText() const override;
0212         UndoItem*          createRedo(Undo::List*) override;
0213         void               dumpDebug() const override;
0214 };
0215 
0216 class UndoDeletes : public UndoMulti<UndoDelete>
0217 {
0218     public:
0219         UndoDeletes(Undo::Type t, const Undo::EventList& events, const QString& name = QString())
0220                  : UndoMulti<UndoDelete>(t, events, name) {}   // UNDO only
0221         UndoDeletes(Undo::Type t, Undo::List* undos, const QString& name)
0222                  : UndoMulti<UndoDelete>(t, undos, name) {}
0223         QString            defaultActionText() const override;
0224         UndoItem*          createRedo(Undo::List*) override;
0225         void               dumpDebug() const override;
0226 };
0227 
0228 class UndoReactivates : public UndoMulti<UndoReactivate>
0229 {
0230     public:
0231         UndoReactivates(Undo::Type t, const Undo::EventList& events, const QString& name = QString())
0232                  : UndoMulti<UndoReactivate>(t, events, name) {}   // UNDO only
0233         UndoReactivates(Undo::Type t, Undo::List* undos, const QString& name)
0234                  : UndoMulti<UndoReactivate>(t, undos, name) {}
0235         QString            defaultActionText() const override;
0236         UndoItem*          createRedo(Undo::List*) override;
0237         void               dumpDebug() const override;
0238 };
0239 
0240 Undo*       Undo::mInstance = nullptr;
0241 Undo::List  Undo::mUndoList;
0242 Undo::List  Undo::mRedoList;
0243 
0244 
0245 /******************************************************************************
0246 * Create the one and only instance of the Undo class.
0247 */
0248 Undo* Undo::instance()
0249 {
0250     if (!mInstance)
0251         mInstance = new Undo(qApp);
0252     return mInstance;
0253 }
0254 
0255 /******************************************************************************
0256 * Clear the lists of undo and redo items.
0257 */
0258 void Undo::clear()
0259 {
0260     if (!mUndoList.isEmpty()  ||  !mRedoList.isEmpty())
0261     {
0262         mInstance->blockSignals(true);
0263         while (!mUndoList.isEmpty())
0264             delete mUndoList.first();    // N.B. 'delete' removes the object from the list
0265         while (!mRedoList.isEmpty())
0266             delete mRedoList.first();    // N.B. 'delete' removes the object from the list
0267         mInstance->blockSignals(false);
0268         emitChanged();
0269     }
0270 }
0271 
0272 /******************************************************************************
0273 * Create an undo item and add it to the list of undos.
0274 * N.B. The base class constructor adds the object to the undo list.
0275 */
0276 void Undo::saveAdd(const KAEvent& event, const Resource& resource, const QString& name)
0277 {
0278     new UndoAdd(UNDO, event, resource, name);
0279     emitChanged();
0280 }
0281 
0282 void Undo::saveAdds(const Undo::EventList& events, const QString& name)
0283 {
0284     int count = events.count();
0285     if (count == 1)
0286         saveAdd(events.first().event, events.first().resource, name);
0287     else if (count > 1)
0288     {
0289         new UndoAdds(UNDO, events, name);
0290         emitChanged();
0291     }
0292 }
0293 
0294 void Undo::saveEdit(const Undo::Event& oldEvent, const KAEvent& newEvent)
0295 {
0296     new UndoEdit(UNDO, oldEvent.event, newEvent.id(), oldEvent.resource, oldEvent.dontShowErrors, AlarmText::summary(newEvent));
0297     removeRedos(oldEvent.event.id());    // remove any redos which are made invalid by this edit
0298     emitChanged();
0299 }
0300 
0301 void Undo::saveDelete(const Undo::Event& event, const QString& name)
0302 {
0303     new UndoDelete(UNDO, event.event, event.resource, event.dontShowErrors, name);
0304     removeRedos(event.event.id());    // remove any redos which are made invalid by this deletion
0305     emitChanged();
0306 }
0307 
0308 void Undo::saveDeletes(const Undo::EventList& events, const QString& name)
0309 {
0310     int count = events.count();
0311     if (count == 1)
0312         saveDelete(events[0], name);
0313     else if (count > 1)
0314     {
0315         new UndoDeletes(UNDO, events, name);
0316         for (const Undo::Event& event : events)
0317             removeRedos(event.event.id());    // remove any redos which are made invalid by these deletions
0318         emitChanged();
0319     }
0320 }
0321 
0322 void Undo::saveReactivate(const KAEvent& event, const Resource& resource, const QString& name)
0323 {
0324     new UndoReactivate(UNDO, event, resource, name);
0325     emitChanged();
0326 }
0327 
0328 void Undo::saveReactivates(const EventList& events, const QString& name)
0329 {
0330     int count = events.count();
0331     if (count == 1)
0332         saveReactivate(events[0].event, events[0].resource, name);
0333     else if (count > 1)
0334     {
0335         new UndoReactivates(UNDO, events, name);
0336         emitChanged();
0337     }
0338 }
0339 
0340 /******************************************************************************
0341 * Remove any redos which are made invalid by a new undo.
0342 */
0343 void Undo::removeRedos(const QString& eventID)
0344 {
0345     QString id = eventID;
0346     for (int i = 0;  i < mRedoList.count();  )
0347     {
0348         UndoItem* item = mRedoList[i];
0349         if (item->operation() == UndoItem::MULTI)
0350         {
0351             if (item->deleteID(id))
0352             {
0353                 // The old multi-redo was replaced with a new single redo
0354                 delete item;   // N.B. 'delete' removes the object from the list
0355             }
0356         }
0357         else if (item->eventID() == id)
0358         {
0359             if (item->operation() == UndoItem::EDIT)
0360                 id = item->oldEventID();   // continue looking for its post-edit ID
0361             delete item;   // N.B. 'delete' removes the object from the list
0362         }
0363         else
0364             ++i;
0365     }
0366 }
0367 
0368 /******************************************************************************
0369 * Undo or redo a specified item.
0370 * Reply = true if success, or if the item no longer exists.
0371 */
0372 bool Undo::undo(int i, Undo::Type type, QWidget* parent, const QString& action)
0373 {
0374     UndoItem::mRestoreError        = UndoItem::ERR_NONE;
0375     UndoItem::mRestoreWarning      = UndoItem::WARN_NONE;
0376     UndoItem::mRestoreWarningKorg  = KAlarm::UPDATE_OK;
0377     UndoItem::mRestoreWarningCount = 0;
0378     List& list = (type == UNDO) ? mUndoList : mRedoList;
0379     if (i < list.count()  &&  list[i]->type() == type)
0380     {
0381         list[i]->restore();
0382         delete list[i];    // N.B. 'delete' removes the object from its list
0383         emitChanged();
0384     }
0385 
0386     QString err;
0387     switch (UndoItem::mRestoreError)
0388     {
0389         case UndoItem::ERR_NONE:
0390         {
0391             KAlarm::UpdateError errcode;
0392             switch (UndoItem::mRestoreWarning)
0393             {
0394                 case UndoItem::WARN_KORG_ADD:     errcode = KAlarm::ERR_ADD;  break;
0395                 case UndoItem::WARN_KORG_MODIFY:  errcode = KAlarm::ERR_MODIFY;  break;
0396                 case UndoItem::WARN_KORG_DELETE:  errcode = KAlarm::ERR_DELETE;  break;
0397                 case UndoItem::WARN_NONE:
0398                 default:
0399                     return true;
0400             }
0401             KAlarm::displayKOrgUpdateError(parent, errcode, UndoItem::mRestoreWarningKorg, UndoItem::mRestoreWarningCount);
0402             return true;
0403         }
0404         case UndoItem::ERR_NOT_FOUND:  err = i18nc("@info", "Alarm not found");  break;
0405         case UndoItem::ERR_CREATE:     err = i18nc("@info", "Error recreating alarm");  break;
0406         case UndoItem::ERR_TEMPLATE:   err = i18nc("@info", "Error recreating alarm template");  break;
0407         case UndoItem::ERR_ARCHIVED:   err = i18nc("@info", "Cannot reactivate archived alarm");  break;
0408         case UndoItem::ERR_PROG:       err = i18nc("@info", "Program error");  break;
0409         default:                       err = i18nc("@info", "Unknown error");  break;
0410     }
0411     KAMessageBox::error(parent, i18nc("@info Undo-action: message", "%1: %2", action, err));
0412     return false;
0413 }
0414 
0415 /******************************************************************************
0416 * Add an undo item to the start of one of the lists.
0417 */
0418 void Undo::add(UndoItem* item, bool undo)
0419 {
0420     if (item)
0421     {
0422         // Limit the number of items stored
0423         const int undoCount = mUndoList.count();
0424         const int redoCount = mRedoList.count();
0425         if (undoCount + redoCount >= maxCount - 1)
0426         {
0427             if (undoCount)
0428                 mUndoList.pop_back();
0429             else
0430                 mRedoList.pop_back();
0431         }
0432 
0433         // Append the new item
0434         List* const list = undo ? &mUndoList : &mRedoList;
0435         list->prepend(item);
0436     }
0437 }
0438 
0439 /******************************************************************************
0440 * Remove an undo item from one of the lists.
0441 */
0442 void Undo::remove(UndoItem* item, bool undo)
0443 {
0444     List* const list = undo ? &mUndoList : &mRedoList;
0445     if (!list->isEmpty())
0446         list->removeAt(list->indexOf(item));
0447 }
0448 
0449 /******************************************************************************
0450 * Replace an undo item in one of the lists.
0451 */
0452 void Undo::replace(UndoItem* old, UndoItem* New)
0453 {
0454     const Type type = old->type();
0455     List* const list = (type == UNDO) ? &mUndoList : (type == REDO) ? &mRedoList : nullptr;
0456     if (!list)
0457         return;
0458     const int i = list->indexOf(old);
0459     if (i >= 0)
0460     {
0461         New->setType(type);    // ensure the item points to the correct list
0462         (*list)[i] = New;
0463         old->setType(NONE);    // mark the old item as no longer being in a list
0464     }
0465 }
0466 
0467 /******************************************************************************
0468 * Return the action description of the latest undo/redo item.
0469 */
0470 QString Undo::actionText(Undo::Type type)
0471 {
0472     const List* const list = (type == UNDO) ? &mUndoList : (type == REDO) ? &mRedoList : nullptr;
0473     return (list && !list->isEmpty()) ? (*list)[0]->actionText() : QString();
0474 }
0475 
0476 /******************************************************************************
0477 * Return the action description of the undo/redo item with the specified ID.
0478 */
0479 QString Undo::actionText(Undo::Type type, int id)
0480 {
0481     const UndoItem* undo = getItem(id, type);
0482     return undo ? undo->actionText() : QString();
0483 }
0484 
0485 /******************************************************************************
0486 * Return the alarm description of the undo/redo item with the specified ID.
0487 */
0488 QString Undo::description(Undo::Type type, int id)
0489 {
0490     const UndoItem* undo = getItem(id, type);
0491     return undo ? undo->description() : QString();
0492 }
0493 
0494 /******************************************************************************
0495 * Return the descriptions of all undo or redo items, in order latest first.
0496 * For alarms which have undergone more than one change, only the first one is
0497 * listed, to force dependent undos to be executed in their correct order.
0498 * If 'ids' is non-null, also returns a list of their corresponding IDs.
0499 */
0500 QList<int> Undo::ids(Undo::Type type)
0501 {
0502     QList<int> ids;
0503     QStringList ignoreIDs;
0504 //int n=0;
0505     const List* const list = (type == UNDO) ? &mUndoList : (type == REDO) ? &mRedoList : nullptr;
0506     if (!list)
0507         return ids;
0508     for (const UndoItem* item : *list)
0509     {
0510         // Check whether this item should be ignored because it is a
0511         // dependent undo. If not, add this item's ID to the ignore list.
0512         bool omit = false;
0513         if (item->operation() == UndoItem::MULTI)
0514         {
0515             // If any item in a multi-undo is disqualified, omit the whole multi-undo
0516             QStringList newIDs;
0517             const Undo::List* undos = ((UndoMultiBase*)item)->undos();
0518             for (const UndoItem* undo : *undos)
0519             {
0520                 const QString evid = undo->eventID();
0521                 if (ignoreIDs.contains(evid))
0522                     omit = true;
0523                 else if (omit)
0524                     ignoreIDs.append(evid);
0525                 else
0526                     newIDs.append(evid);
0527             }
0528             if (omit)
0529             {
0530                 for (const QString& newID : std::as_const(newIDs))
0531                     ignoreIDs.append(newID);
0532             }
0533         }
0534         else
0535         {
0536             omit = ignoreIDs.contains(item->eventID());
0537             if (!omit)
0538                 ignoreIDs.append(item->eventID());
0539             if (item->operation() == UndoItem::EDIT)
0540                 ignoreIDs.append(item->oldEventID());   // continue looking for its post-edit ID
0541         }
0542         if (!omit)
0543             ids.append(item->id());
0544 //else qCDebug(KALARM_LOG)<<"Undo::ids(): omit"<<item->actionText()<<":"<<item->description();
0545     }
0546 //qCDebug(KALARM_LOG)<<"Undo::ids():"<<n<<" ->"<<ids.count();
0547     return ids;
0548 }
0549 
0550 /******************************************************************************
0551 * Emit the appropriate 'changed' signal.
0552 */
0553 void Undo::emitChanged()
0554 {
0555     if (mInstance)
0556         mInstance->emitChanged(actionText(UNDO), actionText(REDO));
0557 }
0558 
0559 /******************************************************************************
0560 * Return the item with the specified ID.
0561 */
0562 UndoItem* Undo::getItem(int id, Undo::Type type)
0563 {
0564     List* const list = (type == UNDO) ? &mUndoList : (type == REDO) ? &mRedoList : nullptr;
0565     if (list)
0566     {
0567         for (int i = 0, end = list->count();  i < end;  ++i)
0568         {
0569             UndoItem* item = (*list)[i];
0570             if (item->id() == id)
0571                 return item;
0572         }
0573     }
0574     return nullptr;
0575 }
0576 
0577 /******************************************************************************
0578 * Find an item with the specified ID.
0579 */
0580 int Undo::findItem(int id, Undo::Type type)
0581 {
0582     const List& list = (type == UNDO) ? mUndoList : mRedoList;
0583     int i = 0;
0584     for (int end = list.count();  i < end;  ++i)
0585     {
0586         if (list[i]->id() == id)
0587             break;
0588     }
0589     return i;
0590 }
0591 
0592 /******************************************************************************
0593 * Dump the last 'count' undos or redos to debug, starting with the most recent.
0594 */
0595 void Undo::dumpDebug(Undo::Type type, int count)
0596 {
0597 #ifndef KDE_NO_DEBUG_OUTPUT
0598     const List& list = (type == UNDO) ? mUndoList : mRedoList;
0599     if (count > list.count())
0600         count = list.count();
0601     qCDebug(KALARM_LOG) << "Undo::dumpDebug():" << count;
0602     for (int i = 0;  i < count;  ++i)
0603         list[i]->dumpDebug();
0604 #endif
0605 }
0606 
0607 /*=============================================================================
0608 =  Class: UndoItem
0609 =  A single undo action.
0610 =============================================================================*/
0611 int                  UndoItem::mLastId = 0;
0612 UndoItem::Error      UndoItem::mRestoreError;
0613 UndoItem::Warning    UndoItem::mRestoreWarning;
0614 KAlarm::UpdateResult UndoItem::mRestoreWarningKorg;
0615 int                  UndoItem::mRestoreWarningCount;
0616 
0617 /******************************************************************************
0618 * Constructor.
0619 * Optionally appends the undo to the list of undos.
0620 */
0621 UndoItem::UndoItem(Undo::Type type, const QString& name)
0622     : mName(name)
0623     , mType(type)
0624     , mCalendar(CalEvent::EMPTY)
0625 {
0626     if (type != Undo::NONE)
0627     {
0628         mId = ++mLastId;
0629         if (mId < 0)
0630             mId = mLastId = 1;    // wrap round if we reach a negative number
0631         Undo::add(this, (mType == Undo::UNDO));
0632     }
0633 }
0634 
0635 /******************************************************************************
0636 * Destructor.
0637 * Removes the undo from the list (if it's in the list).
0638 */
0639 UndoItem::~UndoItem()
0640 {
0641     if (mType != Undo::NONE)
0642         Undo::remove(this, (mType == Undo::UNDO));
0643 }
0644 
0645 /******************************************************************************
0646 * Return the description of an event.
0647 */
0648 QString UndoItem::description(const KAEvent& event) const
0649 {
0650     return (mCalendar == CalEvent::TEMPLATE) ? event.name() : AlarmText::summary(event);
0651 }
0652 
0653 /******************************************************************************
0654 * Return the action description of an add or delete Undo/Redo item for displaying.
0655 */
0656 QString UndoItem::addDeleteActionText(CalEvent::Type calendar, bool add)
0657 {
0658     switch (calendar)
0659     {
0660         case CalEvent::ACTIVE:
0661             if (add)
0662                 return i18nc("@info Action to create a new alarm", "New alarm");
0663             else
0664                 return i18nc("@info Action to delete an alarm", "Delete alarm");
0665         case CalEvent::TEMPLATE:
0666             if (add)
0667                 return i18nc("@info Action to create a new alarm template", "New template");
0668             else
0669                 return i18nc("@info Action to delete an alarm template", "Delete template");
0670         case CalEvent::ARCHIVED:
0671             return i18nc("@info", "Delete archived alarm");
0672         default:
0673             break;
0674     }
0675     return {};
0676 }
0677 
0678 /******************************************************************************
0679 * Dump the instance's contents to debug.
0680 */
0681 void UndoItem::dumpDebug() const
0682 {
0683 #ifndef KDE_NO_DEBUG_OUTPUT
0684     dumpDebugTitle("UndoItem");
0685 #endif
0686 }
0687 void UndoItem::dumpDebugTitle(const char* typeName) const
0688 {
0689 #ifndef KDE_NO_DEBUG_OUTPUT
0690     qCDebug(KALARM_LOG) << typeName << "begin:";
0691     qCDebug(KALARM_LOG) << "-- mName:       " << mName;
0692     qCDebug(KALARM_LOG) << "-- mId:         " << mId;
0693     qCDebug(KALARM_LOG) << "-- mType:       " << (mType == Undo::UNDO ? "Undo" : mType == Undo::REDO ? "Redo" : "None");
0694     qCDebug(KALARM_LOG) << "-- mCalendar:   " << mCalendar;
0695 #endif
0696 }
0697 
0698 /*=============================================================================
0699 =  Class: UndoMultiBase
0700 =  Undo item for multiple alarms.
0701 =============================================================================*/
0702 
0703 /******************************************************************************
0704 * Dump the instance's contents to debug.
0705 */
0706 void UndoMultiBase::dumpDebugTitle(const char* typeName) const
0707 {
0708 #ifndef KDE_NO_DEBUG_OUTPUT
0709     UndoItem::dumpDebugTitle(typeName);
0710     qCDebug(KALARM_LOG) << "-- mUndos count:" << mUndos->count();
0711 #endif
0712 }
0713 
0714 /*=============================================================================
0715 =  Class: UndoMulti
0716 =  Undo item for multiple alarms.
0717 =============================================================================*/
0718 
0719 template <class T>
0720 UndoMulti<T>::UndoMulti(Undo::Type type, const Undo::EventList& events, const QString& name)
0721     : UndoMultiBase(type, name)    // UNDO only
0722 {
0723     for (const Undo::Event& event : events)
0724         mUndos->append(new T(Undo::NONE, event));
0725 }
0726 
0727 /******************************************************************************
0728 * Undo the item, i.e. restore multiple alarms which were deleted (or delete
0729 * alarms which were restored).
0730 * Create a redo item to delete (or restore) the alarms again.
0731 * Reply = redo item.
0732 */
0733 template <class T>
0734 UndoItem* UndoMulti<T>::restore()
0735 {
0736     auto newUndos = new Undo::List;
0737     for (int i = 0, end = mUndos->count();  i < end;  ++i)
0738     {
0739         UndoItem* undo = (*mUndos)[i]->restore();
0740         if (undo)
0741             newUndos->append(undo);
0742     }
0743     if (newUndos->isEmpty())
0744     {
0745         delete newUndos;
0746         return nullptr;
0747     }
0748 
0749     // Create a redo item to delete the alarm again
0750     return createRedo(newUndos);
0751 }
0752 
0753 /******************************************************************************
0754 * If one of the multiple items has the specified ID, delete it.
0755 * If an item is deleted and there is only one item left, the UndoMulti
0756 * instance is removed from its list and replaced by the remaining UndoItem instead.
0757 * Reply = true if this instance was replaced. The caller must delete it.
0758 *       = false otherwise.
0759 */
0760 template <class T>
0761 bool UndoMulti<T>::deleteID(const QString& id)
0762 {
0763     for (int i = 0, end = mUndos->count();  i < end;  ++i)
0764     {
0765         UndoItem* item = (*mUndos)[i];
0766         if (item->eventID() == id)
0767         {
0768             // Found a matching entry - remove it
0769             mUndos->removeAt(i);
0770             if (mUndos->count() == 1)
0771             {
0772                 // There is only one entry left after removal.
0773                 // Replace 'this' multi instance with the remaining single entry.
0774                 replaceWith(item);
0775                 return true;
0776             }
0777             else
0778             {
0779                 delete item;
0780                 return false;
0781             }
0782         }
0783     }
0784     return false;
0785 }
0786 
0787 
0788 /*=============================================================================
0789 =  Class: UndoAdd
0790 =  Undo item for alarm creation.
0791 =============================================================================*/
0792 
0793 UndoAdd::UndoAdd(Undo::Type type, const Undo::Event& undo, const QString& name)
0794     : UndoItem(type, name)
0795     , mResource(undo.resource)
0796     , mEventId(undo.event.id())
0797 {
0798     setCalendar(undo.event.category());
0799     mDescription = UndoItem::description(undo.event);    // calendar must be set before calling this
0800 }
0801 
0802 UndoAdd::UndoAdd(Undo::Type type, const KAEvent& event, const Resource& resource, const QString& name)
0803     : UndoItem(type, name)
0804     , mResource(resource)
0805     , mEventId(event.id())
0806 {
0807     setCalendar(event.category());
0808     mDescription = UndoItem::description(event);    // calendar must be set before calling this
0809 }
0810 
0811 UndoAdd::UndoAdd(Undo::Type type, const KAEvent& event, const Resource& resource, const QString& name, CalEvent::Type cal)
0812     : UndoItem(type, name)
0813     , mResource(resource)
0814     , mEventId(CalEvent::uid(event.id(), cal))    // convert if old-style event ID
0815 {
0816     setCalendar(cal);
0817     mDescription = UndoItem::description(event);    // calendar must be set before calling this
0818 }
0819 
0820 /******************************************************************************
0821 * Undo the item, i.e. delete the alarm which was added.
0822 * Create a redo item to add the alarm back again.
0823 * Reply = redo item.
0824 */
0825 UndoItem* UndoAdd::doRestore(bool setArchive)
0826 {
0827     // Retrieve the current state of the alarm
0828     qCDebug(KALARM_LOG) << "UndoAdd::doRestore:" << mEventId;
0829     KAEvent event = mResource.event(mEventId);
0830     if (!event.isValid())
0831     {
0832         // Alarm is no longer in calendar, or its type is now disabled
0833         mRestoreError = ERR_NOT_FOUND;
0834         return nullptr;
0835     }
0836 
0837     // Create a redo item to recreate the alarm.
0838     // Do it now, since 'event' gets modified by KAlarm::deleteEvent()
0839     UndoItem* undo = createRedo(event, mResource);
0840 
0841     switch (calendar())
0842     {
0843         case CalEvent::ACTIVE:
0844         {
0845             if (setArchive)
0846                 event.setArchive();
0847             // Archive it if it has already triggered
0848             KAlarm::UpdateResult status = KAlarm::deleteEvent(event, mResource, true);
0849             switch (status.status)
0850             {
0851                 case KAlarm::UPDATE_ERROR:
0852                 case KAlarm::UPDATE_FAILED:
0853                 case KAlarm::SAVE_FAILED:
0854                     mRestoreError = ERR_CREATE;
0855                     break;
0856                 case KAlarm::UPDATE_KORG_FUNCERR:
0857                 case KAlarm::UPDATE_KORG_ERRINIT:
0858                 case KAlarm::UPDATE_KORG_ERRSTART:
0859                 case KAlarm::UPDATE_KORG_ERR:
0860                     mRestoreWarning = WARN_KORG_DELETE;
0861                     ++mRestoreWarningCount;
0862                     if (status.status > mRestoreWarningKorg.status)
0863                         mRestoreWarningKorg = status;
0864                     break;
0865                 default:
0866                     break;
0867             }
0868             break;
0869         }
0870         case CalEvent::TEMPLATE:
0871             if (KAlarm::deleteTemplate(event) != KAlarm::UPDATE_OK)
0872                 mRestoreError = ERR_TEMPLATE;
0873             break;
0874         case CalEvent::ARCHIVED:    // redoing the deletion of an archived alarm
0875         {
0876             Resource resource;
0877             KAlarm::deleteEvent(event, resource);
0878             break;
0879         }
0880         default:
0881             delete undo;
0882             mRestoreError = ERR_PROG;
0883             return nullptr;
0884     }
0885     return undo;
0886 }
0887 
0888 /******************************************************************************
0889 * Create a redo item to add the alarm back again.
0890 */
0891 UndoItem* UndoAdd::createRedo(const KAEvent& event, const Resource& resource)
0892 {
0893     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
0894     return new UndoDelete(t, event, resource, QStringList(), mName);
0895 }
0896 
0897 /******************************************************************************
0898 * Return the action description of the Undo item for displaying.
0899 */
0900 QString UndoAdd::defaultActionText() const
0901 {
0902     return addDeleteActionText(calendar(), (type() == Undo::UNDO));
0903 }
0904 
0905 /******************************************************************************
0906 * Dump the instance's contents to debug.
0907 */
0908 void UndoAdd::dumpDebug() const
0909 {
0910 #ifndef KDE_NO_DEBUG_OUTPUT
0911     dumpDebugTitle("UndoAdd");
0912 #endif
0913 }
0914 void UndoAdd::dumpDebugTitle(const char* typeName) const
0915 {
0916 #ifndef KDE_NO_DEBUG_OUTPUT
0917     UndoItem::dumpDebugTitle(typeName);
0918     qCDebug(KALARM_LOG) << "-- mResource:   " << mResource.id();
0919     qCDebug(KALARM_LOG) << "-- mEventId:    " << mEventId;
0920     qCDebug(KALARM_LOG) << "-- mDescript:   " << mDescription;
0921 #endif
0922 }
0923 
0924 
0925 /*=============================================================================
0926 =  Class: UndoAdds
0927 =  Undo item for multiple alarm creation.
0928 =============================================================================*/
0929 
0930 /******************************************************************************
0931 * Create a redo item to add the alarms again.
0932 */
0933 UndoItem* UndoAdds::createRedo(Undo::List* undos)
0934 {
0935     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
0936     return new UndoAdds(t, undos, mName);
0937 }
0938 
0939 /******************************************************************************
0940 * Return the action description of the Undo item for displaying.
0941 */
0942 QString UndoAdds::defaultActionText() const
0943 {
0944     return i18nc("@info", "Create multiple alarms");
0945 }
0946 
0947 /******************************************************************************
0948 * Dump the instance's contents to debug.
0949 */
0950 void UndoAdds::dumpDebug() const
0951 {
0952 #ifndef KDE_NO_DEBUG_OUTPUT
0953     dumpDebugTitle("UndoAdds");
0954 #endif
0955 }
0956 
0957 
0958 /*=============================================================================
0959 =  Class: UndoEdit
0960 =  Undo item for alarm edit.
0961 =============================================================================*/
0962 
0963 UndoEdit::UndoEdit(Undo::Type type, const KAEvent& oldEvent, const QString& newEventID,
0964                    const Resource& resource, const QStringList& dontShowErrors, const QString& description)
0965     : UndoItem(type)
0966     , mResource(resource)
0967     , mOldEvent(new KAEvent(oldEvent))
0968     , mNewEventId(newEventID)
0969     , mDescription(description)
0970     , mDontShowErrors(dontShowErrors)
0971 {
0972     setCalendar(oldEvent.category());
0973 }
0974 
0975 UndoEdit::~UndoEdit()
0976 {
0977     delete mOldEvent;
0978 }
0979 
0980 /******************************************************************************
0981 * Undo the item, i.e. undo an edit to a previously existing alarm.
0982 * Create a redo item to reapply the edit.
0983 * Reply = redo item.
0984 */
0985 UndoItem* UndoEdit::restore()
0986 {
0987     qCDebug(KALARM_LOG) << "UndoEdit::restore:" << mNewEventId;
0988     // Retrieve the current state of the alarm
0989     KAEvent newEvent = mResource.event(mNewEventId);
0990     if (!newEvent.isValid())
0991     {
0992         mRestoreError = ERR_NOT_FOUND;    // alarm is no longer in calendar
0993         return nullptr;
0994     }
0995 
0996     // Create a redo item to restore the edit
0997     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
0998     UndoItem* undo = new UndoEdit(t, newEvent, mOldEvent->id(), mResource, KAlarm::dontShowErrors(EventId(newEvent)), mDescription);
0999 
1000     switch (calendar())
1001     {
1002         case CalEvent::ACTIVE:
1003         {
1004             KAlarm::UpdateResult status = KAlarm::modifyEvent(newEvent, *mOldEvent);
1005             switch (status.status)
1006             {
1007                 case KAlarm::UPDATE_ERROR:
1008                 case KAlarm::UPDATE_FAILED:
1009                 case KAlarm::SAVE_FAILED:
1010                     mRestoreError = ERR_CREATE;
1011                     break;
1012                 case KAlarm::UPDATE_KORG_FUNCERR:
1013                 case KAlarm::UPDATE_KORG_ERRINIT:
1014                 case KAlarm::UPDATE_KORG_ERRSTART:
1015                 case KAlarm::UPDATE_KORG_ERR:
1016                     mRestoreWarning = WARN_KORG_MODIFY;
1017                     ++mRestoreWarningCount;
1018                     if (status.status > mRestoreWarningKorg.status)
1019                         mRestoreWarningKorg = status;
1020                     // fall through to default
1021                     [[fallthrough]];
1022                 default:
1023                     KAlarm::setDontShowErrors(EventId(*mOldEvent), mDontShowErrors);
1024                     break;
1025             }
1026             break;
1027         }
1028         case CalEvent::TEMPLATE:
1029             if (KAlarm::updateTemplate(*mOldEvent) != KAlarm::UPDATE_OK)
1030                 mRestoreError = ERR_TEMPLATE;
1031             break;
1032         case CalEvent::ARCHIVED:    // editing of archived events is not allowed
1033         default:
1034             delete undo;
1035             mRestoreError = ERR_PROG;
1036             return nullptr;
1037     }
1038     return undo;
1039 }
1040 
1041 /******************************************************************************
1042 * Return the action description of the Undo item for displaying.
1043 */
1044 QString UndoEdit::defaultActionText() const
1045 {
1046     switch (calendar())
1047     {
1048         case CalEvent::ACTIVE:
1049             return i18nc("@info Action to edit an alarm", "Edit alarm");
1050         case CalEvent::TEMPLATE:
1051             return i18nc("@info Action to edit an alarm template", "Edit template");
1052         default:
1053             break;
1054     }
1055     return {};
1056 }
1057 
1058 /******************************************************************************
1059 * Dump the instance's contents to debug.
1060 */
1061 void UndoEdit::dumpDebug() const
1062 {
1063 #ifndef KDE_NO_DEBUG_OUTPUT
1064     dumpDebugTitle("UndoEdit");
1065 #endif
1066 }
1067 void UndoEdit::dumpDebugTitle(const char* typeName) const
1068 {
1069 #ifndef KDE_NO_DEBUG_OUTPUT
1070     UndoItem::dumpDebugTitle(typeName);
1071     qCDebug(KALARM_LOG) << "-- mResource:   " << mResource.id();
1072     qCDebug(KALARM_LOG) << "-- mOldEvent:   " << mOldEvent->id();
1073     qCDebug(KALARM_LOG) << "-- mNewEventId: " << mNewEventId;
1074     qCDebug(KALARM_LOG) << "-- mDescription:" << mDescription;
1075     qCDebug(KALARM_LOG) << "-- mDontShowErr:" << mDontShowErrors;
1076 #endif
1077 }
1078 
1079 
1080 /*=============================================================================
1081 =  Class: UndoDelete
1082 =  Undo item for alarm deletion.
1083 =============================================================================*/
1084 
1085 UndoDelete::UndoDelete(Undo::Type type, const Undo::Event& undo, const QString& name)
1086     : UndoItem(type, name)
1087     , mResource(undo.resource)
1088     , mEvent(new KAEvent(undo.event))
1089     , mDontShowErrors(undo.dontShowErrors)
1090 {
1091     setCalendar(mEvent->category());
1092 }
1093 
1094 UndoDelete::UndoDelete(Undo::Type type, const KAEvent& event, const Resource& resource, const QStringList& dontShowErrors, const QString& name)
1095     : UndoItem(type, name)
1096     , mResource(resource)
1097     , mEvent(new KAEvent(event))
1098     , mDontShowErrors(dontShowErrors)
1099 {
1100     setCalendar(mEvent->category());
1101 }
1102 
1103 UndoDelete::~UndoDelete()
1104 {
1105     delete mEvent;
1106 }
1107 
1108 /******************************************************************************
1109 * Undo the item, i.e. restore an alarm which was deleted.
1110 * Create a redo item to delete the alarm again.
1111 * Reply = redo item.
1112 */
1113 UndoItem* UndoDelete::restore()
1114 {
1115     qCDebug(KALARM_LOG) << "UndoDelete::restore:" << mEvent->id();
1116     // Restore the original event
1117     CalEvent::Type saveType = calendar();
1118     switch (calendar())
1119     {
1120         case CalEvent::ACTIVE:
1121             if (mEvent->toBeArchived())
1122             {
1123                 // It was archived when it was deleted
1124                 mEvent->setCategory(CalEvent::ARCHIVED);
1125                 mEvent->setResourceId(Resources::resourceForEvent(mEvent->id()).id());
1126                 const KAlarm::UpdateResult status = KAlarm::reactivateEvent(*mEvent, mResource);
1127                 switch (status.status)
1128                 {
1129                     case KAlarm::UPDATE_KORG_FUNCERR:
1130                     case KAlarm::UPDATE_KORG_ERRINIT:
1131                     case KAlarm::UPDATE_KORG_ERRSTART:
1132                     case KAlarm::UPDATE_KORG_ERR:
1133                         mRestoreWarning = WARN_KORG_ADD;
1134                         ++mRestoreWarningCount;
1135                         if (status.status > mRestoreWarningKorg.status)
1136                             mRestoreWarningKorg = status;
1137                         break;
1138                     case KAlarm::UPDATE_ERROR:
1139                     case KAlarm::UPDATE_FAILED:
1140                     case KAlarm::SAVE_FAILED:
1141                         mRestoreError = ERR_ARCHIVED;
1142                         return nullptr;
1143                     case KAlarm::UPDATE_OK:
1144                         break;
1145                 }
1146             }
1147             else
1148             {
1149                 const KAlarm::UpdateResult status = KAlarm::addEvent(*mEvent, mResource, nullptr, true);
1150                 switch (status.status)
1151                 {
1152                     case KAlarm::UPDATE_KORG_FUNCERR:
1153                     case KAlarm::UPDATE_KORG_ERRINIT:
1154                     case KAlarm::UPDATE_KORG_ERRSTART:
1155                     case KAlarm::UPDATE_KORG_ERR:
1156                         mRestoreWarning = WARN_KORG_ADD;
1157                         ++mRestoreWarningCount;
1158                         if (status.status > mRestoreWarningKorg.status)
1159                             mRestoreWarningKorg = status;
1160                         break;
1161                     case KAlarm::UPDATE_ERROR:
1162                     case KAlarm::UPDATE_FAILED:
1163                     case KAlarm::SAVE_FAILED:
1164                         mRestoreError = ERR_CREATE;
1165                         return nullptr;
1166                     case KAlarm::UPDATE_OK:
1167                         break;
1168                 }
1169             }
1170             KAlarm::setDontShowErrors(EventId(*mEvent), mDontShowErrors);
1171             break;
1172         case CalEvent::TEMPLATE:
1173             if (KAlarm::addTemplate(*mEvent, mResource) != KAlarm::UPDATE_OK)
1174             {
1175                 mRestoreError = ERR_CREATE;
1176                 return nullptr;
1177             }
1178             break;
1179         case CalEvent::ARCHIVED:
1180             if (!KAlarm::addArchivedEvent(*mEvent, mResource))
1181             {
1182                 mRestoreError = ERR_CREATE;
1183                 return nullptr;
1184             }
1185             break;
1186         default:
1187             mRestoreError = ERR_PROG;
1188             return nullptr;
1189     }
1190 
1191     // Create a redo item to delete the alarm again
1192     mEvent->setCategory(saveType);
1193     return createRedo(*mEvent, mResource);
1194 }
1195 
1196 /******************************************************************************
1197 * Create a redo item to archive the alarm again.
1198 */
1199 UndoItem* UndoDelete::createRedo(const KAEvent& event, const Resource& resource)
1200 {
1201     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
1202     return new UndoAdd(t, event, resource, mName);
1203 }
1204 
1205 /******************************************************************************
1206 * Return the action description of the Undo item for displaying.
1207 */
1208 QString UndoDelete::defaultActionText() const
1209 {
1210     return addDeleteActionText(calendar(), (type() == Undo::REDO));
1211 }
1212 
1213 /******************************************************************************
1214 * Dump the instance's contents to debug.
1215 */
1216 void UndoDelete::dumpDebug() const
1217 {
1218 #ifndef KDE_NO_DEBUG_OUTPUT
1219     dumpDebugTitle("UndoDelete");
1220 #endif
1221 }
1222 void UndoDelete::dumpDebugTitle(const char* typeName) const
1223 {
1224 #ifndef KDE_NO_DEBUG_OUTPUT
1225     UndoItem::dumpDebugTitle(typeName);
1226     qCDebug(KALARM_LOG) << "-- mResource:   " << mResource.id();
1227     qCDebug(KALARM_LOG) << "-- mEvent:      " << mEvent->id();
1228     qCDebug(KALARM_LOG) << "-- mDontShowErr:" << mDontShowErrors;
1229 #endif
1230 }
1231 
1232 
1233 /*=============================================================================
1234 =  Class: UndoDeletes
1235 =  Undo item for multiple alarm deletion.
1236 =============================================================================*/
1237 
1238 /******************************************************************************
1239 * Create a redo item to delete the alarms again.
1240 */
1241 UndoItem* UndoDeletes::createRedo(Undo::List* undos)
1242 {
1243     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
1244     return new UndoDeletes(t, undos, mName);
1245 }
1246 
1247 /******************************************************************************
1248 * Return the action description of the Undo item for displaying.
1249 */
1250 QString UndoDeletes::defaultActionText() const
1251 {
1252     if (mUndos->isEmpty())
1253         return {};
1254     for (const UndoItem* item : std::as_const(*mUndos))
1255     {
1256         switch (item->calendar())
1257         {
1258             case CalEvent::ACTIVE:
1259                 return i18nc("@info", "Delete multiple alarms");
1260             case CalEvent::TEMPLATE:
1261                 return i18nc("@info", "Delete multiple templates");
1262             case CalEvent::ARCHIVED:
1263                 break;    // check if they are ALL archived
1264             default:
1265                 return {};
1266         }
1267     }
1268     return i18nc("@info", "Delete multiple archived alarms");
1269 }
1270 
1271 /******************************************************************************
1272 * Dump the instance's contents to debug.
1273 */
1274 void UndoDeletes::dumpDebug() const
1275 {
1276 #ifndef KDE_NO_DEBUG_OUTPUT
1277     dumpDebugTitle("UndoDeletes");
1278 #endif
1279 }
1280 
1281 
1282 /*=============================================================================
1283 =  Class: UndoReactivate
1284 =  Undo item for alarm reactivation.
1285 =============================================================================*/
1286 
1287 /******************************************************************************
1288 * Undo the item, i.e. re-archive the alarm which was reactivated.
1289 * Create a redo item to reactivate the alarm back again.
1290 * Reply = redo item.
1291 */
1292 UndoItem* UndoReactivate::restore()
1293 {
1294     qCDebug(KALARM_LOG) << "UndoReactivate::restore";
1295     // Validate the alarm's calendar
1296     switch (calendar())
1297     {
1298         case CalEvent::ACTIVE:
1299             break;
1300         default:
1301             mRestoreError = ERR_PROG;
1302             return nullptr;
1303     }
1304     return UndoAdd::doRestore(true);     // restore alarm, ensuring that it is re-archived
1305 }
1306 
1307 /******************************************************************************
1308 * Create a redo item to add the alarm back again.
1309 */
1310 UndoItem* UndoReactivate::createRedo(const KAEvent& event, const Resource& resource)
1311 {
1312     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
1313     return new UndoDeactivate(t, event, resource, mName);
1314 }
1315 
1316 /******************************************************************************
1317 * Return the action description of the Undo item for displaying.
1318 */
1319 QString UndoReactivate::defaultActionText() const
1320 {
1321     return i18nc("@info", "Reactivate alarm");
1322 }
1323 
1324 /******************************************************************************
1325 * Dump the instance's contents to debug.
1326 */
1327 void UndoReactivate::dumpDebug() const
1328 {
1329 #ifndef KDE_NO_DEBUG_OUTPUT
1330     dumpDebugTitle("UndoReactivate");
1331 #endif
1332 }
1333 
1334 
1335 /*=============================================================================
1336 =  Class: UndoDeactivate
1337 =  Redo item for alarm reactivation.
1338 =============================================================================*/
1339 
1340 /******************************************************************************
1341 * Undo the item, i.e. reactivate an alarm which was archived.
1342 * Create a redo item to archive the alarm again.
1343 * Reply = redo item.
1344 */
1345 UndoItem* UndoDeactivate::restore()
1346 {
1347     qCDebug(KALARM_LOG) << "UndoDeactivate::restore";
1348     // Validate the alarm's calendar
1349     switch (calendar())
1350     {
1351         case CalEvent::ACTIVE:
1352             break;
1353         default:
1354             mRestoreError = ERR_PROG;
1355             return nullptr;
1356     }
1357 
1358     return UndoDelete::restore();
1359 }
1360 
1361 /******************************************************************************
1362 * Create a redo item to archive the alarm again.
1363 */
1364 UndoItem* UndoDeactivate::createRedo(const KAEvent& event, const Resource& resource)
1365 {
1366     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
1367     return new UndoReactivate(t, event, resource, mName);
1368 }
1369 
1370 /******************************************************************************
1371 * Return the action description of the Undo item for displaying.
1372 */
1373 QString UndoDeactivate::defaultActionText() const
1374 {
1375     return i18nc("@info", "Reactivate alarm");
1376 }
1377 
1378 /******************************************************************************
1379 * Dump the instance's contents to debug.
1380 */
1381 void UndoDeactivate::dumpDebug() const
1382 {
1383 #ifndef KDE_NO_DEBUG_OUTPUT
1384     dumpDebugTitle("UndoDeactivate");
1385 #endif
1386 }
1387 
1388 
1389 /*=============================================================================
1390 =  Class: UndoReactivates
1391 =  Undo item for multiple alarm reactivation.
1392 =============================================================================*/
1393 
1394 /******************************************************************************
1395 * Create a redo item to reactivate the alarms again.
1396 */
1397 UndoItem* UndoReactivates::createRedo(Undo::List* undos)
1398 {
1399     const Undo::Type t = (type() == Undo::UNDO) ? Undo::REDO : (type() == Undo::REDO) ? Undo::UNDO : Undo::NONE;
1400     return new UndoReactivates(t, undos, mName);
1401 }
1402 
1403 /******************************************************************************
1404 * Return the action description of the Undo item for displaying.
1405 */
1406 QString UndoReactivates::defaultActionText() const
1407 {
1408     return i18nc("@info", "Reactivate multiple alarms");
1409 }
1410 
1411 /******************************************************************************
1412 * Dump the instance's contents to debug.
1413 */
1414 void UndoReactivates::dumpDebug() const
1415 {
1416 #ifndef KDE_NO_DEBUG_OUTPUT
1417     dumpDebugTitle("UndoReactivates");
1418 #endif
1419 }
1420 
1421 
1422 /*=============================================================================
1423 =  Class: Event
1424 =  Event details for external calls.
1425 =============================================================================*/
1426 Undo::Event::Event(const KAEvent& e, const Resource& r)
1427     : event(e)
1428     , resource(r)
1429 {
1430     if (e.category() == CalEvent::ACTIVE)
1431         dontShowErrors = KAlarm::dontShowErrors(EventId(e));
1432 }
1433 
1434 #include "moc_undo.cpp"
1435 
1436 // vim: et sw=4: