File indexing completed on 2024-05-12 05:20:46

0001 /*
0002     This file is part of KMail
0003 
0004     SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org>
0005     SPDX-FileCopyrightText: 2003 Zack Rusin <zack@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-only
0008 */
0009 
0010 #include "undostack.h"
0011 
0012 #include "kmkernel.h"
0013 #include <Akonadi/ItemMoveJob>
0014 #include <KJob>
0015 
0016 #include <KLocalizedString>
0017 #include <KMessageBox>
0018 
0019 using namespace KMail;
0020 
0021 UndoStack::UndoStack(int size)
0022     : QObject(nullptr)
0023     , mSize(size)
0024 {
0025 }
0026 
0027 UndoStack::~UndoStack()
0028 {
0029     clear();
0030 }
0031 
0032 void UndoStack::clear()
0033 {
0034     qDeleteAll(mStack);
0035     mStack.clear();
0036 }
0037 
0038 int UndoStack::size() const
0039 {
0040     return mStack.count();
0041 }
0042 
0043 QString UndoStack::undoInfo() const
0044 {
0045     if (!mStack.isEmpty()) {
0046         UndoInfo *info = mStack.first();
0047         return info->moveToTrash ? i18n("Move To Trash") : i18np("Move Message", "Move Messages", info->items.count());
0048     } else {
0049         return {};
0050     }
0051 }
0052 
0053 int UndoStack::newUndoAction(const Akonadi::Collection &srcFolder, const Akonadi::Collection &destFolder)
0054 {
0055     auto info = new UndoInfo;
0056     info->id = ++mLastId;
0057     info->srcFolder = srcFolder;
0058     info->destFolder = destFolder;
0059     info->moveToTrash = (destFolder == CommonKernel->trashCollectionFolder());
0060     if (static_cast<int>(mStack.count()) == mSize) {
0061         delete mStack.last();
0062         mStack.removeLast();
0063     }
0064     mStack.prepend(info);
0065     Q_EMIT undoStackChanged();
0066     return info->id;
0067 }
0068 
0069 void UndoStack::addMsgToAction(int undoId, const Akonadi::Item &item)
0070 {
0071     if (!mCachedInfo || mCachedInfo->id != undoId) {
0072         QList<UndoInfo *>::const_iterator itr = mStack.constBegin();
0073         while (itr != mStack.constEnd()) {
0074             if ((*itr)->id == undoId) {
0075                 mCachedInfo = (*itr);
0076                 break;
0077             }
0078             ++itr;
0079         }
0080     }
0081 
0082     Q_ASSERT(mCachedInfo);
0083     mCachedInfo->items.append(item);
0084 }
0085 
0086 bool UndoStack::isEmpty() const
0087 {
0088     return mStack.isEmpty();
0089 }
0090 
0091 void UndoStack::undo()
0092 {
0093     if (!mStack.isEmpty()) {
0094         UndoInfo *info = mStack.takeFirst();
0095         Q_EMIT undoStackChanged();
0096         auto job = new Akonadi::ItemMoveJob(info->items, info->srcFolder, this);
0097         connect(job, &Akonadi::ItemMoveJob::result, this, &UndoStack::slotMoveResult);
0098         delete info;
0099     } else {
0100         // Sorry.. stack is empty..
0101         KMessageBox::error(kmkernel->mainWin(), i18n("There is nothing to undo."));
0102     }
0103 }
0104 
0105 void UndoStack::slotMoveResult(KJob *job)
0106 {
0107     if (job->error()) {
0108         KMessageBox::error(kmkernel->mainWin(), i18n("Cannot move message. %1", job->errorString()));
0109     }
0110 }
0111 
0112 void UndoStack::pushSingleAction(const Akonadi::Item &item, const Akonadi::Collection &folder, const Akonadi::Collection &destFolder)
0113 {
0114     const int id = newUndoAction(folder, destFolder);
0115     addMsgToAction(id, item);
0116 }
0117 
0118 void UndoStack::folderDestroyed(const Akonadi::Collection &folder)
0119 {
0120     QList<UndoInfo *>::iterator it = mStack.begin();
0121     while (it != mStack.end()) {
0122         UndoInfo *info = *it;
0123         if (info && ((info->srcFolder == folder) || (info->destFolder == folder))) {
0124             delete info;
0125             it = mStack.erase(it);
0126         } else {
0127             ++it;
0128         }
0129     }
0130     Q_EMIT undoStackChanged();
0131 }
0132 
0133 #include "moc_undostack.cpp"