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"