2 * undo.cpp - undo/redo facility
4 * Copyright © 2005-2014 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "kalarm.h" //krazy:exclude=includes (kalarm.h must be first)
24 #include "alarmcalendar.h"
25 #include "functions.h"
26 #include "messagebox.h"
28 #include <kalarmcal/alarmtext.h>
29 #include <kalarmcal/kaevent.h>
31 #include <QApplication>
32 #include <KLocalizedString>
33 #include "kalarm_debug.h"
35 static int maxCount
= 12;
38 #undef DELETE // conflicting Windows macro
41 // Simplify access to Undo::Event struct
42 #define RESOURCE_PARAM_TYPE const Collection&
43 #define EVENT_RESOURCE collection
45 using namespace Akonadi
;
50 enum Operation
{ ADD
, EDIT
, DELETE
, REACTIVATE
, DEACTIVATE
, MULTI
};
51 UndoItem(); // needed by QList
53 virtual Operation
operation() const = 0;
54 virtual QString
actionText() const { return !mName
.isEmpty() ? mName
: defaultActionText(); }
55 virtual QString
defaultActionText() const = 0;
56 virtual QString
description() const { return QString(); }
57 virtual QString
eventID() const { return QString(); }
58 virtual QString
oldEventID() const { return QString(); }
59 virtual QString
newEventID() const { return QString(); }
60 virtual Collection
collection() const { return Collection(); }
61 int id() const { return mId
; }
62 Undo::Type
type() const { return mType
; }
63 void setType(Undo::Type t
) { mType
= t
; }
64 CalEvent::Type
calendar() const { return mCalendar
; }
65 virtual void setCalendar(CalEvent::Type s
) { mCalendar
= s
; }
66 virtual UndoItem
* restore() = 0;
67 virtual bool deleteID(const QString
& /*id*/) { return false; }
69 enum Error
{ ERR_NONE
, ERR_PROG
, ERR_NOT_FOUND
, ERR_CREATE
, ERR_TEMPLATE
, ERR_ARCHIVED
};
70 enum Warning
{ WARN_NONE
, WARN_KORG_ADD
, WARN_KORG_MODIFY
, WARN_KORG_DELETE
};
72 static Error mRestoreError
; // error code valid only if restore() returns 0
73 static Warning mRestoreWarning
; // warning code set by restore()
74 static KAlarm::UpdateResult mRestoreWarningKorg
; // KOrganizer error status set by restore()
75 static int mRestoreWarningCount
; // item count for mRestoreWarning (to allow i18n messages to work correctly)
78 UndoItem(Undo::Type
, const QString
& name
= QString());
79 static QString
addDeleteActionText(CalEvent::Type
, bool add
);
80 QString
description(const KAEvent
&) const;
81 void replaceWith(UndoItem
* item
) { Undo::replace(this, item
); }
83 QString mName
; // specified action name (overrides default)
84 int mId
; // unique identifier (only for mType = UNDO, REDO)
85 Undo::Type mType
; // which list (if any) the object is in
86 CalEvent::Type mCalendar
;
89 class UndoMultiBase
: public UndoItem
92 UndoMultiBase(Undo::Type t
, const QString
& name
)
93 : UndoItem(t
, name
), mUndos(new Undo::List
) {}
94 UndoMultiBase(Undo::Type t
, Undo::List
* undos
, const QString
& name
)
95 : UndoItem(t
, name
), mUndos(undos
) {}
96 ~UndoMultiBase() { delete mUndos
; }
97 const Undo::List
* undos() const { return mUndos
; }
99 Undo::List
* mUndos
; // this list must always have >= 2 entries
102 template <class T
> class UndoMulti
: public UndoMultiBase
105 UndoMulti(Undo::Type
, const Undo::EventList
&, const QString
& name
);
106 UndoMulti(Undo::Type t
, Undo::List
* undos
, const QString
& name
) : UndoMultiBase(t
, undos
, name
) {}
107 Operation
operation() const Q_DECL_OVERRIDE
{ return MULTI
; }
108 UndoItem
* restore() Q_DECL_OVERRIDE
;
109 bool deleteID(const QString
& id
) Q_DECL_OVERRIDE
;
110 virtual UndoItem
* createRedo(Undo::List
*) = 0;
113 class UndoAdd
: public UndoItem
116 UndoAdd(Undo::Type
, const Undo::Event
&, const QString
& name
= QString());
117 UndoAdd(Undo::Type
, const KAEvent
&, RESOURCE_PARAM_TYPE
, const QString
& name
= QString());
118 UndoAdd(Undo::Type
, const KAEvent
&, RESOURCE_PARAM_TYPE
, const QString
& name
, CalEvent::Type
);
119 Operation
operation() const Q_DECL_OVERRIDE
{ return ADD
; }
120 QString
defaultActionText() const Q_DECL_OVERRIDE
;
121 QString
description() const Q_DECL_OVERRIDE
{ return mDescription
; }
122 Collection
collection() const Q_DECL_OVERRIDE
{ return mResource
; }
123 QString
eventID() const Q_DECL_OVERRIDE
{ return mEventId
; }
124 QString
newEventID() const Q_DECL_OVERRIDE
{ return mEventId
; }
125 UndoItem
* restore() Q_DECL_OVERRIDE
{ return doRestore(); }
127 UndoItem
* doRestore(bool setArchive
= false);
128 virtual UndoItem
* createRedo(const KAEvent
&, RESOURCE_PARAM_TYPE
);
130 Collection mResource
; // collection containing the event
132 QString mDescription
;
135 class UndoEdit
: public UndoItem
138 UndoEdit(Undo::Type
, const KAEvent
& oldEvent
, const QString
& newEventID
,
139 RESOURCE_PARAM_TYPE
, const QStringList
& dontShowErrors
, const QString
& description
);
141 Operation
operation() const Q_DECL_OVERRIDE
{ return EDIT
; }
142 QString
defaultActionText() const Q_DECL_OVERRIDE
;
143 QString
description() const Q_DECL_OVERRIDE
{ return mDescription
; }
144 Collection
collection() const Q_DECL_OVERRIDE
{ return mResource
; }
145 QString
eventID() const Q_DECL_OVERRIDE
{ return mNewEventId
; }
146 QString
oldEventID() const Q_DECL_OVERRIDE
{ return mOldEvent
->id(); }
147 QString
newEventID() const Q_DECL_OVERRIDE
{ return mNewEventId
; }
148 UndoItem
* restore() Q_DECL_OVERRIDE
;
150 Collection mResource
; // collection containing the event
153 QString mDescription
;
154 QStringList mDontShowErrors
;
157 class UndoDelete
: public UndoItem
160 UndoDelete(Undo::Type
, const Undo::Event
&, const QString
& name
= QString());
161 UndoDelete(Undo::Type
, const KAEvent
&, RESOURCE_PARAM_TYPE
, const QStringList
& dontShowErrors
, const QString
& name
= QString());
163 Operation
operation() const Q_DECL_OVERRIDE
{ return DELETE
; }
164 QString
defaultActionText() const Q_DECL_OVERRIDE
;
165 QString
description() const Q_DECL_OVERRIDE
{ return UndoItem::description(*mEvent
); }
166 Collection
collection() const Q_DECL_OVERRIDE
{ return mResource
; }
167 QString
eventID() const Q_DECL_OVERRIDE
{ return mEvent
->id(); }
168 QString
oldEventID() const Q_DECL_OVERRIDE
{ return mEvent
->id(); }
169 UndoItem
* restore() Q_DECL_OVERRIDE
;
170 KAEvent
* event() const { return mEvent
; }
172 virtual UndoItem
* createRedo(const KAEvent
&, RESOURCE_PARAM_TYPE
);
174 Collection mResource
; // collection containing the event
176 QStringList mDontShowErrors
;
179 class UndoReactivate
: public UndoAdd
182 UndoReactivate(Undo::Type t
, const Undo::Event
& e
, const QString
& name
= QString())
183 : UndoAdd(t
, e
.event
, e
.EVENT_RESOURCE
, name
, CalEvent::ACTIVE
) {}
184 UndoReactivate(Undo::Type t
, const KAEvent
& e
, RESOURCE_PARAM_TYPE r
, const QString
& name
= QString())
185 : UndoAdd(t
, e
, r
, name
, CalEvent::ACTIVE
) {}
186 Operation
operation() const Q_DECL_OVERRIDE
{ return REACTIVATE
; }
187 QString
defaultActionText() const Q_DECL_OVERRIDE
;
188 UndoItem
* restore() Q_DECL_OVERRIDE
;
190 UndoItem
* createRedo(const KAEvent
&, RESOURCE_PARAM_TYPE
) Q_DECL_OVERRIDE
;
193 class UndoDeactivate
: public UndoDelete
196 UndoDeactivate(Undo::Type t
, const KAEvent
& e
, RESOURCE_PARAM_TYPE r
, const QString
& name
= QString())
197 : UndoDelete(t
, e
, r
, QStringList(), name
) {}
198 Operation
operation() const Q_DECL_OVERRIDE
{ return DEACTIVATE
; }
199 QString
defaultActionText() const Q_DECL_OVERRIDE
;
200 UndoItem
* restore() Q_DECL_OVERRIDE
;
202 UndoItem
* createRedo(const KAEvent
&, RESOURCE_PARAM_TYPE
) Q_DECL_OVERRIDE
;
205 class UndoAdds
: public UndoMulti
<UndoAdd
>
208 UndoAdds(Undo::Type t
, const Undo::EventList
& events
, const QString
& name
= QString())
209 : UndoMulti
<UndoAdd
>(t
, events
, name
) {} // UNDO only
210 UndoAdds(Undo::Type t
, Undo::List
* undos
, const QString
& name
)
211 : UndoMulti
<UndoAdd
>(t
, undos
, name
) {}
212 QString
defaultActionText() const Q_DECL_OVERRIDE
;
213 UndoItem
* createRedo(Undo::List
*) Q_DECL_OVERRIDE
;
216 class UndoDeletes
: public UndoMulti
<UndoDelete
>
219 UndoDeletes(Undo::Type t
, const Undo::EventList
& events
, const QString
& name
= QString())
220 : UndoMulti
<UndoDelete
>(t
, events
, name
) {} // UNDO only
221 UndoDeletes(Undo::Type t
, Undo::List
* undos
, const QString
& name
)
222 : UndoMulti
<UndoDelete
>(t
, undos
, name
) {}
223 QString
defaultActionText() const Q_DECL_OVERRIDE
;
224 UndoItem
* createRedo(Undo::List
*) Q_DECL_OVERRIDE
;
227 class UndoReactivates
: public UndoMulti
<UndoReactivate
>
230 UndoReactivates(Undo::Type t
, const Undo::EventList
& events
, const QString
& name
= QString())
231 : UndoMulti
<UndoReactivate
>(t
, events
, name
) {} // UNDO only
232 UndoReactivates(Undo::Type t
, Undo::List
* undos
, const QString
& name
)
233 : UndoMulti
<UndoReactivate
>(t
, undos
, name
) {}
234 QString
defaultActionText() const Q_DECL_OVERRIDE
;
235 UndoItem
* createRedo(Undo::List
*) Q_DECL_OVERRIDE
;
238 Undo
* Undo::mInstance
= Q_NULLPTR
;
239 Undo::List
Undo::mUndoList
;
240 Undo::List
Undo::mRedoList
;
243 /******************************************************************************
244 * Create the one and only instance of the Undo class.
246 Undo
* Undo::instance()
249 mInstance
= new Undo(qApp
);
253 /******************************************************************************
254 * Clear the lists of undo and redo items.
258 if (!mUndoList
.isEmpty() || !mRedoList
.isEmpty())
260 mInstance
->blockSignals(true);
261 while (!mUndoList
.isEmpty())
262 delete mUndoList
.first(); // N.B. 'delete' removes the object from the list
263 while (!mRedoList
.isEmpty())
264 delete mRedoList
.first(); // N.B. 'delete' removes the object from the list
265 mInstance
->blockSignals(false);
270 /******************************************************************************
271 * Create an undo item and add it to the list of undos.
272 * N.B. The base class constructor adds the object to the undo list.
274 void Undo::saveAdd(const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
, const QString
& name
)
276 new UndoAdd(UNDO
, event
, resource
, name
);
280 void Undo::saveAdds(const Undo::EventList
& events
, const QString
& name
)
282 int count
= events
.count();
284 saveAdd(events
.first().event
, events
.first().EVENT_RESOURCE
, name
);
287 new UndoAdds(UNDO
, events
, name
);
292 void Undo::saveEdit(const Undo::Event
& oldEvent
, const KAEvent
& newEvent
)
294 new UndoEdit(UNDO
, oldEvent
.event
, newEvent
.id(), oldEvent
.EVENT_RESOURCE
, oldEvent
.dontShowErrors
, AlarmText::summary(newEvent
));
295 removeRedos(oldEvent
.event
.id()); // remove any redos which are made invalid by this edit
299 void Undo::saveDelete(const Undo::Event
& event
, const QString
& name
)
301 new UndoDelete(UNDO
, event
.event
, event
.EVENT_RESOURCE
, event
.dontShowErrors
, name
);
302 removeRedos(event
.event
.id()); // remove any redos which are made invalid by this deletion
306 void Undo::saveDeletes(const Undo::EventList
& events
, const QString
& name
)
308 int count
= events
.count();
310 saveDelete(events
[0], name
);
313 new UndoDeletes(UNDO
, events
, name
);
314 for (int i
= 0, end
= events
.count(); i
< end
; ++i
)
315 removeRedos(events
[i
].event
.id()); // remove any redos which are made invalid by these deletions
320 void Undo::saveReactivate(const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
, const QString
& name
)
322 new UndoReactivate(UNDO
, event
, resource
, name
);
326 void Undo::saveReactivates(const EventList
& events
, const QString
& name
)
328 int count
= events
.count();
330 saveReactivate(events
[0].event
, events
[0].EVENT_RESOURCE
, name
);
333 new UndoReactivates(UNDO
, events
, name
);
338 /******************************************************************************
339 * Remove any redos which are made invalid by a new undo.
341 void Undo::removeRedos(const QString
& eventID
)
343 QString id
= eventID
;
344 for (int i
= 0; i
< mRedoList
.count(); )
346 UndoItem
* item
= mRedoList
[i
];
347 //qCDebug(KALARM_LOG)<<item->eventID()<<" (looking for"<<id<<")";
348 if (item
->operation() == UndoItem::MULTI
)
350 if (item
->deleteID(id
))
352 // The old multi-redo was replaced with a new single redo
353 delete item
; // N.B. 'delete' removes the object from the list
356 else if (item
->eventID() == id
)
358 if (item
->operation() == UndoItem::EDIT
)
359 id
= item
->oldEventID(); // continue looking for its post-edit ID
360 delete item
; // N.B. 'delete' removes the object from the list
367 /******************************************************************************
368 * Undo or redo a specified item.
369 * Reply = true if success, or if the item no longer exists.
371 bool Undo::undo(int i
, Undo::Type type
, QWidget
* parent
, const QString
& action
)
373 UndoItem::mRestoreError
= UndoItem::ERR_NONE
;
374 UndoItem::mRestoreWarning
= UndoItem::WARN_NONE
;
375 UndoItem::mRestoreWarningKorg
= KAlarm::UPDATE_OK
;
376 UndoItem::mRestoreWarningCount
= 0;
377 List
& list
= (type
== UNDO
) ? mUndoList
: mRedoList
;
378 if (i
< list
.count() && list
[i
]->type() == type
)
381 delete list
[i
]; // N.B. 'delete' removes the object from its list
386 switch (UndoItem::mRestoreError
)
388 case UndoItem::ERR_NONE
:
390 KAlarm::UpdateError errcode
;
391 switch (UndoItem::mRestoreWarning
)
393 case UndoItem::WARN_KORG_ADD
: errcode
= KAlarm::ERR_ADD
; break;
394 case UndoItem::WARN_KORG_MODIFY
: errcode
= KAlarm::ERR_MODIFY
; break;
395 case UndoItem::WARN_KORG_DELETE
: errcode
= KAlarm::ERR_DELETE
; break;
396 case UndoItem::WARN_NONE
:
400 KAlarm::displayKOrgUpdateError(parent
, errcode
, UndoItem::mRestoreWarningKorg
, UndoItem::mRestoreWarningCount
);
403 case UndoItem::ERR_NOT_FOUND
: err
= i18nc("@info", "Alarm not found"); break;
404 case UndoItem::ERR_CREATE
: err
= i18nc("@info", "Error recreating alarm"); break;
405 case UndoItem::ERR_TEMPLATE
: err
= i18nc("@info", "Error recreating alarm template"); break;
406 case UndoItem::ERR_ARCHIVED
: err
= i18nc("@info", "Cannot reactivate archived alarm"); break;
407 case UndoItem::ERR_PROG
: err
= i18nc("@info", "Program error"); break;
408 default: err
= i18nc("@info", "Unknown error"); break;
410 KAMessageBox::sorry(parent
, i18nc("@info Undo-action: message", "%1: %2", action
, err
));
414 /******************************************************************************
415 * Add an undo item to the start of one of the lists.
417 void Undo::add(UndoItem
* item
, bool undo
)
421 // Limit the number of items stored
422 int undoCount
= mUndoList
.count();
423 int redoCount
= mRedoList
.count();
424 if (undoCount
+ redoCount
>= maxCount
- 1)
427 mUndoList
.pop_back();
429 mRedoList
.pop_back();
432 // Append the new item
433 List
* list
= undo
? &mUndoList
: &mRedoList
;
438 /******************************************************************************
439 * Remove an undo item from one of the lists.
441 void Undo::remove(UndoItem
* item
, bool undo
)
443 List
* list
= undo
? &mUndoList
: &mRedoList
;
444 if (!list
->isEmpty())
445 list
->removeAt(list
->indexOf(item
));
448 /******************************************************************************
449 * Replace an undo item in one of the lists.
451 void Undo::replace(UndoItem
* old
, UndoItem
* New
)
453 Type type
= old
->type();
454 List
* list
= (type
== UNDO
) ? &mUndoList
: (type
== REDO
) ? &mRedoList
: Q_NULLPTR
;
457 int i
= list
->indexOf(old
);
460 New
->setType(type
); // ensure the item points to the correct list
462 old
->setType(NONE
); // mark the old item as no longer being in a list
466 /******************************************************************************
467 * Return the action description of the latest undo/redo item.
469 QString
Undo::actionText(Undo::Type type
)
471 List
* list
= (type
== UNDO
) ? &mUndoList
: (type
== REDO
) ? &mRedoList
: Q_NULLPTR
;
472 return (list
&& !list
->isEmpty()) ? (*list
)[0]->actionText() : QString();
475 /******************************************************************************
476 * Return the action description of the undo/redo item with the specified ID.
478 QString
Undo::actionText(Undo::Type type
, int id
)
480 UndoItem
* undo
= getItem(id
, type
);
481 return undo
? undo
->actionText() : QString();
484 /******************************************************************************
485 * Return the alarm description of the undo/redo item with the specified ID.
487 QString
Undo::description(Undo::Type type
, int id
)
489 UndoItem
* undo
= getItem(id
, type
);
490 return undo
? undo
->description() : QString();
493 /******************************************************************************
494 * Return the descriptions of all undo or redo items, in order latest first.
495 * For alarms which have undergone more than one change, only the first one is
496 * listed, to force dependent undos to be executed in their correct order.
497 * If 'ids' is non-null, also returns a list of their corresponding IDs.
499 QList
<int> Undo::ids(Undo::Type type
)
502 QStringList ignoreIDs
;
504 List
* list
= (type
== UNDO
) ? &mUndoList
: (type
== REDO
) ? &mRedoList
: Q_NULLPTR
;
507 for (int i
= 0, end
= list
->count(); i
< end
; ++i
)
509 // Check whether this item should be ignored because it is a
510 // dependent undo. If not, add this item's ID to the ignore list.
511 UndoItem
* item
= (*list
)[i
];
513 if (item
->operation() == UndoItem::MULTI
)
515 // If any item in a multi-undo is disqualified, omit the whole multi-undo
517 const Undo::List
* undos
= ((UndoMultiBase
*)item
)->undos();
518 for (int u
= 0, uend
= undos
->count(); u
< uend
; ++u
)
520 QString evid
= (*undos
)[u
]->eventID();
521 if (ignoreIDs
.contains(evid
))
524 ignoreIDs
.append(evid
);
530 for (int i
= 0, iend
= newIDs
.count(); i
< iend
; ++i
)
531 ignoreIDs
.append(newIDs
[i
]);
536 omit
= ignoreIDs
.contains(item
->eventID());
538 ignoreIDs
.append(item
->eventID());
539 if (item
->operation() == UndoItem::EDIT
)
540 ignoreIDs
.append(item
->oldEventID()); // continue looking for its post-edit ID
543 ids
.append(item
->id());
544 //else qCDebug(KALARM_LOG)<<"Undo::ids(): omit"<<item->actionText()<<":"<<item->description();
546 //qCDebug(KALARM_LOG)<<"Undo::ids():"<<n<<" ->"<<ids.count();
550 /******************************************************************************
551 * Emit the appropriate 'changed' signal.
553 void Undo::emitChanged()
556 mInstance
->emitChanged(actionText(UNDO
), actionText(REDO
));
559 /******************************************************************************
560 * Return the item with the specified ID.
562 UndoItem
* Undo::getItem(int id
, Undo::Type type
)
564 List
* list
= (type
== UNDO
) ? &mUndoList
: (type
== REDO
) ? &mRedoList
: Q_NULLPTR
;
567 for (int i
= 0, end
= list
->count(); i
< end
; ++i
)
569 if ((*list
)[i
]->id() == id
)
576 /******************************************************************************
577 * Find an item with the specified ID.
579 int Undo::findItem(int id
, Undo::Type type
)
581 List
& list
= (type
== UNDO
) ? mUndoList
: mRedoList
;
583 for (int end
= list
.count(); i
< end
; ++i
)
585 if (list
[i
]->id() == id
)
592 /*=============================================================================
594 = A single undo action.
595 =============================================================================*/
596 int UndoItem::mLastId
= 0;
597 UndoItem::Error
UndoItem::mRestoreError
;
598 UndoItem::Warning
UndoItem::mRestoreWarning
;
599 KAlarm::UpdateResult
UndoItem::mRestoreWarningKorg
;
600 int UndoItem::mRestoreWarningCount
;
602 /******************************************************************************
604 * Optionally appends the undo to the list of undos.
606 UndoItem::UndoItem(Undo::Type type
, const QString
& name
)
610 mCalendar(CalEvent::EMPTY
)
612 if (type
!= Undo::NONE
)
616 mId
= mLastId
= 1; // wrap round if we reach a negative number
617 Undo::add(this, (mType
== Undo::UNDO
));
621 /******************************************************************************
623 * Removes the undo from the list (if it's in the list).
625 UndoItem::~UndoItem()
627 if (mType
!= Undo::NONE
)
628 Undo::remove(this, (mType
== Undo::UNDO
));
631 /******************************************************************************
632 * Return the description of an event.
634 QString
UndoItem::description(const KAEvent
& event
) const
636 return (mCalendar
== CalEvent::TEMPLATE
) ? event
.templateName() : AlarmText::summary(event
);
639 /******************************************************************************
640 * Return the action description of an add or delete Undo/Redo item for displaying.
642 QString
UndoItem::addDeleteActionText(CalEvent::Type calendar
, bool add
)
646 case CalEvent::ACTIVE
:
648 return i18nc("@info Action to create a new alarm", "New alarm");
650 return i18nc("@info Action to delete an alarm", "Delete alarm");
651 case CalEvent::TEMPLATE
:
653 return i18nc("@info Action to create a new alarm template", "New template");
655 return i18nc("@info Action to delete an alarm template", "Delete template");
656 case CalEvent::ARCHIVED
:
657 return i18nc("@info", "Delete archived alarm");
665 /*=============================================================================
666 = Class: UndoMultiBase
667 = Undo item for multiple alarms.
668 =============================================================================*/
671 UndoMulti
<T
>::UndoMulti(Undo::Type type
, const Undo::EventList
& events
, const QString
& name
)
672 : UndoMultiBase(type
, name
) // UNDO only
674 for (int i
= 0, end
= events
.count(); i
< end
; ++i
)
675 mUndos
->append(new T(Undo::NONE
, events
[i
]));
678 /******************************************************************************
679 * Undo the item, i.e. restore multiple alarms which were deleted (or delete
680 * alarms which were restored).
681 * Create a redo item to delete (or restore) the alarms again.
685 UndoItem
* UndoMulti
<T
>::restore()
687 Undo::List
* newUndos
= new Undo::List
;
688 for (int i
= 0, end
= mUndos
->count(); i
< end
; ++i
)
690 UndoItem
* undo
= (*mUndos
)[i
]->restore();
692 newUndos
->append(undo
);
694 if (newUndos
->isEmpty())
700 // Create a redo item to delete the alarm again
701 return createRedo(newUndos
);
704 /******************************************************************************
705 * If one of the multiple items has the specified ID, delete it.
706 * If an item is deleted and there is only one item left, the UndoMulti
707 * instance is removed from its list and replaced by the remaining UndoItem instead.
708 * Reply = true if this instance was replaced. The caller must delete it.
712 bool UndoMulti
<T
>::deleteID(const QString
& id
)
714 for (int i
= 0, end
= mUndos
->count(); i
< end
; ++i
)
716 UndoItem
* item
= (*mUndos
)[i
];
717 if (item
->eventID() == id
)
719 // Found a matching entry - remove it
721 if (mUndos
->count() == 1)
723 // There is only one entry left after removal.
724 // Replace 'this' multi instance with the remaining single entry.
739 /*=============================================================================
741 = Undo item for alarm creation.
742 =============================================================================*/
744 UndoAdd::UndoAdd(Undo::Type type
, const Undo::Event
& undo
, const QString
& name
)
745 : UndoItem(type
, name
),
746 mResource(undo
.EVENT_RESOURCE
),
747 mEventId(undo
.event
.id())
749 setCalendar(undo
.event
.category());
750 mDescription
= UndoItem::description(undo
.event
); // calendar must be set before calling this
753 UndoAdd::UndoAdd(Undo::Type type
, const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
, const QString
& name
)
754 : UndoItem(type
, name
),
758 setCalendar(event
.category());
759 mDescription
= UndoItem::description(event
); // calendar must be set before calling this
762 UndoAdd::UndoAdd(Undo::Type type
, const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
, const QString
& name
, CalEvent::Type cal
)
763 : UndoItem(type
, name
),
765 mEventId(CalEvent::uid(event
.id(), cal
)) // convert if old-style event ID
768 mDescription
= UndoItem::description(event
); // calendar must be set before calling this
771 /******************************************************************************
772 * Undo the item, i.e. delete the alarm which was added.
773 * Create a redo item to add the alarm back again.
776 UndoItem
* UndoAdd::doRestore(bool setArchive
)
778 // Retrieve the current state of the alarm
779 qCDebug(KALARM_LOG
) << mEventId
;
780 const KAEvent
* ev
= AlarmCalendar::getEvent(EventId(mResource
.id(), mEventId
));
783 mRestoreError
= ERR_NOT_FOUND
; // alarm is no longer in calendar
788 // Create a redo item to recreate the alarm.
789 // Do it now, since 'event' gets modified by KAlarm::deleteEvent()
790 UndoItem
* undo
= createRedo(event
, mResource
);
794 case CalEvent::ACTIVE
:
798 // Archive it if it has already triggered
799 KAlarm::UpdateResult status
= KAlarm::deleteEvent(event
, true);
800 switch (status
.status
)
802 case KAlarm::UPDATE_ERROR
:
803 case KAlarm::UPDATE_FAILED
:
804 case KAlarm::SAVE_FAILED
:
805 mRestoreError
= ERR_CREATE
;
807 case KAlarm::UPDATE_KORG_FUNCERR
:
808 case KAlarm::UPDATE_KORG_ERRINIT
:
809 case KAlarm::UPDATE_KORG_ERRSTART
:
810 case KAlarm::UPDATE_KORG_ERR
:
811 mRestoreWarning
= WARN_KORG_DELETE
;
812 ++mRestoreWarningCount
;
813 if (status
.status
> mRestoreWarningKorg
.status
)
814 mRestoreWarningKorg
= status
;
821 case CalEvent::TEMPLATE
:
822 if (KAlarm::deleteTemplate(event
) != KAlarm::UPDATE_OK
)
823 mRestoreError
= ERR_TEMPLATE
;
825 case CalEvent::ARCHIVED
: // redoing the deletion of an archived alarm
826 KAlarm::deleteEvent(event
);
830 mRestoreError
= ERR_PROG
;
836 /******************************************************************************
837 * Create a redo item to add the alarm back again.
839 UndoItem
* UndoAdd::createRedo(const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
)
841 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
842 return new UndoDelete(t
, event
, resource
, QStringList(), mName
);
845 /******************************************************************************
846 * Return the action description of the Undo item for displaying.
848 QString
UndoAdd::defaultActionText() const
850 return addDeleteActionText(calendar(), (type() == Undo::UNDO
));
854 /*=============================================================================
856 = Undo item for multiple alarm creation.
857 =============================================================================*/
859 /******************************************************************************
860 * Create a redo item to add the alarms again.
862 UndoItem
* UndoAdds::createRedo(Undo::List
* undos
)
864 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
865 return new UndoAdds(t
, undos
, mName
);
868 /******************************************************************************
869 * Return the action description of the Undo item for displaying.
871 QString
UndoAdds::defaultActionText() const
873 return i18nc("@info", "Create multiple alarms");
877 /*=============================================================================
879 = Undo item for alarm edit.
880 =============================================================================*/
882 UndoEdit::UndoEdit(Undo::Type type
, const KAEvent
& oldEvent
, const QString
& newEventID
,
883 RESOURCE_PARAM_TYPE resource
, const QStringList
& dontShowErrors
, const QString
& description
)
886 mOldEvent(new KAEvent(oldEvent
)),
887 mNewEventId(newEventID
),
888 mDescription(description
),
889 mDontShowErrors(dontShowErrors
)
891 setCalendar(oldEvent
.category());
894 UndoEdit::~UndoEdit()
899 /******************************************************************************
900 * Undo the item, i.e. undo an edit to a previously existing alarm.
901 * Create a redo item to reapply the edit.
904 UndoItem
* UndoEdit::restore()
906 qCDebug(KALARM_LOG
) << mNewEventId
;
907 // Retrieve the current state of the alarm
908 const KAEvent
* event
= AlarmCalendar::getEvent(EventId(mResource
.id(), mNewEventId
));
911 mRestoreError
= ERR_NOT_FOUND
; // alarm is no longer in calendar
914 KAEvent
newEvent(*event
);
916 // Create a redo item to restore the edit
917 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
918 UndoItem
* undo
= new UndoEdit(t
, newEvent
, mOldEvent
->id(), mResource
, KAlarm::dontShowErrors(EventId(newEvent
)), mDescription
);
922 case CalEvent::ACTIVE
:
924 KAlarm::UpdateResult status
= KAlarm::modifyEvent(newEvent
, *mOldEvent
);
925 switch (status
.status
)
927 case KAlarm::UPDATE_ERROR
:
928 case KAlarm::UPDATE_FAILED
:
929 case KAlarm::SAVE_FAILED
:
930 mRestoreError
= ERR_CREATE
;
932 case KAlarm::UPDATE_KORG_FUNCERR
:
933 case KAlarm::UPDATE_KORG_ERRINIT
:
934 case KAlarm::UPDATE_KORG_ERRSTART
:
935 case KAlarm::UPDATE_KORG_ERR
:
936 mRestoreWarning
= WARN_KORG_MODIFY
;
937 ++mRestoreWarningCount
;
938 if (status
.status
> mRestoreWarningKorg
.status
)
939 mRestoreWarningKorg
= status
;
940 // fall through to default
942 KAlarm::setDontShowErrors(EventId(*mOldEvent
), mDontShowErrors
);
947 case CalEvent::TEMPLATE
:
948 if (KAlarm::updateTemplate(*mOldEvent
) != KAlarm::UPDATE_OK
)
949 mRestoreError
= ERR_TEMPLATE
;
951 case CalEvent::ARCHIVED
: // editing of archived events is not allowed
954 mRestoreError
= ERR_PROG
;
960 /******************************************************************************
961 * Return the action description of the Undo item for displaying.
963 QString
UndoEdit::defaultActionText() const
967 case CalEvent::ACTIVE
:
968 return i18nc("@info Action to edit an alarm", "Edit alarm");
969 case CalEvent::TEMPLATE
:
970 return i18nc("@info Action to edit an alarm template", "Edit template");
978 /*=============================================================================
980 = Undo item for alarm deletion.
981 =============================================================================*/
983 UndoDelete::UndoDelete(Undo::Type type
, const Undo::Event
& undo
, const QString
& name
)
984 : UndoItem(type
, name
),
985 mResource(undo
.EVENT_RESOURCE
),
986 mEvent(new KAEvent(undo
.event
)),
987 mDontShowErrors(undo
.dontShowErrors
)
989 setCalendar(mEvent
->category());
992 UndoDelete::UndoDelete(Undo::Type type
, const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
, const QStringList
& dontShowErrors
, const QString
& name
)
993 : UndoItem(type
, name
),
995 mEvent(new KAEvent(event
)),
996 mDontShowErrors(dontShowErrors
)
998 setCalendar(mEvent
->category());
1001 UndoDelete::~UndoDelete()
1006 /******************************************************************************
1007 * Undo the item, i.e. restore an alarm which was deleted.
1008 * Create a redo item to delete the alarm again.
1009 * Reply = redo item.
1011 UndoItem
* UndoDelete::restore()
1013 qCDebug(KALARM_LOG
) << mEvent
->id();
1014 // Restore the original event
1017 case CalEvent::ACTIVE
:
1018 if (mEvent
->toBeArchived())
1020 // It was archived when it was deleted
1021 mEvent
->setCategory(CalEvent::ARCHIVED
);
1022 KAlarm::UpdateResult status
= KAlarm::reactivateEvent(*mEvent
, &mResource
);
1023 switch (status
.status
)
1025 case KAlarm::UPDATE_KORG_FUNCERR
:
1026 case KAlarm::UPDATE_KORG_ERRINIT
:
1027 case KAlarm::UPDATE_KORG_ERRSTART
:
1028 case KAlarm::UPDATE_KORG_ERR
:
1029 mRestoreWarning
= WARN_KORG_ADD
;
1030 ++mRestoreWarningCount
;
1031 if (status
.status
> mRestoreWarningKorg
.status
)
1032 mRestoreWarningKorg
= status
;
1034 case KAlarm::UPDATE_ERROR
:
1035 case KAlarm::UPDATE_FAILED
:
1036 case KAlarm::SAVE_FAILED
:
1037 mRestoreError
= ERR_ARCHIVED
;
1039 case KAlarm::UPDATE_OK
:
1045 KAlarm::UpdateResult status
= KAlarm::addEvent(*mEvent
, &mResource
, Q_NULLPTR
, true);
1046 switch (status
.status
)
1048 case KAlarm::UPDATE_KORG_FUNCERR
:
1049 case KAlarm::UPDATE_KORG_ERRINIT
:
1050 case KAlarm::UPDATE_KORG_ERRSTART
:
1051 case KAlarm::UPDATE_KORG_ERR
:
1052 mRestoreWarning
= WARN_KORG_ADD
;
1053 ++mRestoreWarningCount
;
1054 if (status
.status
> mRestoreWarningKorg
.status
)
1055 mRestoreWarningKorg
= status
;
1057 case KAlarm::UPDATE_ERROR
:
1058 case KAlarm::UPDATE_FAILED
:
1059 case KAlarm::SAVE_FAILED
:
1060 mRestoreError
= ERR_CREATE
;
1062 case KAlarm::UPDATE_OK
:
1066 KAlarm::setDontShowErrors(EventId(*mEvent
), mDontShowErrors
);
1068 case CalEvent::TEMPLATE
:
1069 if (KAlarm::addTemplate(*mEvent
, &mResource
) != KAlarm::UPDATE_OK
)
1071 mRestoreError
= ERR_CREATE
;
1075 case CalEvent::ARCHIVED
:
1076 if (!KAlarm::addArchivedEvent(*mEvent
, &mResource
))
1078 mRestoreError
= ERR_CREATE
;
1083 mRestoreError
= ERR_PROG
;
1087 // Create a redo item to delete the alarm again
1088 return createRedo(*mEvent
, mResource
);
1091 /******************************************************************************
1092 * Create a redo item to archive the alarm again.
1094 UndoItem
* UndoDelete::createRedo(const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
)
1096 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
1097 return new UndoAdd(t
, event
, resource
, mName
);
1100 /******************************************************************************
1101 * Return the action description of the Undo item for displaying.
1103 QString
UndoDelete::defaultActionText() const
1105 return addDeleteActionText(calendar(), (type() == Undo::REDO
));
1109 /*=============================================================================
1110 = Class: UndoDeletes
1111 = Undo item for multiple alarm deletion.
1112 =============================================================================*/
1114 /******************************************************************************
1115 * Create a redo item to delete the alarms again.
1117 UndoItem
* UndoDeletes::createRedo(Undo::List
* undos
)
1119 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
1120 return new UndoDeletes(t
, undos
, mName
);
1123 /******************************************************************************
1124 * Return the action description of the Undo item for displaying.
1126 QString
UndoDeletes::defaultActionText() const
1128 if (mUndos
->isEmpty())
1130 for (int i
= 0, end
= mUndos
->count(); i
< end
; ++i
)
1132 switch ((*mUndos
)[i
]->calendar())
1134 case CalEvent::ACTIVE
:
1135 return i18nc("@info", "Delete multiple alarms");
1136 case CalEvent::TEMPLATE
:
1137 return i18nc("@info", "Delete multiple templates");
1138 case CalEvent::ARCHIVED
:
1139 break; // check if they are ALL archived
1144 return i18nc("@info", "Delete multiple archived alarms");
1148 /*=============================================================================
1149 = Class: UndoReactivate
1150 = Undo item for alarm reactivation.
1151 =============================================================================*/
1153 /******************************************************************************
1154 * Undo the item, i.e. re-archive the alarm which was reactivated.
1155 * Create a redo item to reactivate the alarm back again.
1156 * Reply = redo item.
1158 UndoItem
* UndoReactivate::restore()
1160 qCDebug(KALARM_LOG
);
1161 // Validate the alarm's calendar
1164 case CalEvent::ACTIVE
:
1167 mRestoreError
= ERR_PROG
;
1170 return UndoAdd::doRestore(true); // restore alarm, ensuring that it is re-archived
1173 /******************************************************************************
1174 * Create a redo item to add the alarm back again.
1176 UndoItem
* UndoReactivate::createRedo(const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
)
1178 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
1179 return new UndoDeactivate(t
, event
, resource
, mName
);
1182 /******************************************************************************
1183 * Return the action description of the Undo item for displaying.
1185 QString
UndoReactivate::defaultActionText() const
1187 return i18nc("@info", "Reactivate alarm");
1191 /*=============================================================================
1192 = Class: UndoDeactivate
1193 = Redo item for alarm reactivation.
1194 =============================================================================*/
1196 /******************************************************************************
1197 * Undo the item, i.e. reactivate an alarm which was archived.
1198 * Create a redo item to archive the alarm again.
1199 * Reply = redo item.
1201 UndoItem
* UndoDeactivate::restore()
1203 qCDebug(KALARM_LOG
);
1204 // Validate the alarm's calendar
1207 case CalEvent::ACTIVE
:
1210 mRestoreError
= ERR_PROG
;
1214 return UndoDelete::restore();
1217 /******************************************************************************
1218 * Create a redo item to archive the alarm again.
1220 UndoItem
* UndoDeactivate::createRedo(const KAEvent
& event
, RESOURCE_PARAM_TYPE resource
)
1222 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
1223 return new UndoReactivate(t
, event
, resource
, mName
);
1226 /******************************************************************************
1227 * Return the action description of the Undo item for displaying.
1229 QString
UndoDeactivate::defaultActionText() const
1231 return i18nc("@info", "Reactivate alarm");
1235 /*=============================================================================
1236 = Class: UndoReactivates
1237 = Undo item for multiple alarm reactivation.
1238 =============================================================================*/
1240 /******************************************************************************
1241 * Create a redo item to reactivate the alarms again.
1243 UndoItem
* UndoReactivates::createRedo(Undo::List
* undos
)
1245 Undo::Type t
= (type() == Undo::UNDO
) ? Undo::REDO
: (type() == Undo::REDO
) ? Undo::UNDO
: Undo::NONE
;
1246 return new UndoReactivates(t
, undos
, mName
);
1249 /******************************************************************************
1250 * Return the action description of the Undo item for displaying.
1252 QString
UndoReactivates::defaultActionText() const
1254 return i18nc("@info", "Reactivate multiple alarms");
1258 /*=============================================================================
1260 = Event details for external calls.
1261 =============================================================================*/
1262 Undo::Event::Event(const KAEvent
& e
, RESOURCE_PARAM_TYPE r
)
1266 if (e
.category() == CalEvent::ACTIVE
)
1267 dontShowErrors
= KAlarm::dontShowErrors(EventId(e
));