File indexing completed on 2024-04-21 04:58:21
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org> 0003 SPDX-FileCopyrightText: 2007 Eduardo Robles Elvira <edulix@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "konqundomanager.h" 0009 #include "konqsettingsxt.h" 0010 #include "konqcloseditem.h" 0011 #include "konqclosedwindowsmanager.h" 0012 #include <QAction> 0013 #include <kio/fileundomanager.h> 0014 #include "konqdebug.h" 0015 #include <KLocalizedString> 0016 #include <QWidget> 0017 0018 KonqUndoManager::KonqUndoManager(KonqClosedWindowsManager *cwManager, QWidget *parent) 0019 : QObject(parent), m_cwManager(cwManager) 0020 { 0021 connect(KIO::FileUndoManager::self(), SIGNAL(undoAvailable(bool)), 0022 this, SLOT(slotFileUndoAvailable(bool))); 0023 connect(KIO::FileUndoManager::self(), SIGNAL(undoTextChanged(QString)), 0024 this, SLOT(slotFileUndoTextChanged(QString))); 0025 0026 connect(m_cwManager, SIGNAL(addWindowInOtherInstances(KonqUndoManager*,KonqClosedWindowItem*)), 0027 this, SLOT(slotAddClosedWindowItem(KonqUndoManager*,KonqClosedWindowItem*))); 0028 connect(m_cwManager, SIGNAL(removeWindowInOtherInstances(KonqUndoManager*,const KonqClosedWindowItem*)), 0029 this, SLOT(slotRemoveClosedWindowItem(KonqUndoManager*,const KonqClosedWindowItem*))); 0030 } 0031 0032 KonqUndoManager::~KonqUndoManager() 0033 { 0034 disconnect(KIO::FileUndoManager::self(), SIGNAL(undoAvailable(bool)), 0035 this, SLOT(slotFileUndoAvailable(bool))); 0036 disconnect(KIO::FileUndoManager::self(), SIGNAL(undoTextChanged(QString)), 0037 this, SLOT(slotFileUndoTextChanged(QString))); 0038 0039 disconnect(m_cwManager, SIGNAL(addWindowInOtherInstances(KonqUndoManager*,KonqClosedWindowItem*)), 0040 this, SLOT(slotAddClosedWindowItem(KonqUndoManager*,KonqClosedWindowItem*))); 0041 disconnect(m_cwManager, SIGNAL(removeWindowInOtherInstances(KonqUndoManager*,const KonqClosedWindowItem*)), 0042 this, SLOT(slotRemoveClosedWindowItem(KonqUndoManager*,const KonqClosedWindowItem*))); 0043 0044 // Clear the closed item lists but only remove closed windows items 0045 // in this window 0046 clearClosedItemsList(true); 0047 } 0048 0049 void KonqUndoManager::populate() 0050 { 0051 if (m_populated) { 0052 return; 0053 } 0054 m_populated = true; 0055 0056 const QList<KonqClosedWindowItem *> closedWindowItemList = 0057 m_cwManager->closedWindowItemList(); 0058 0059 QListIterator<KonqClosedWindowItem *> i(closedWindowItemList); 0060 0061 // This loop is done backwards because slotAddClosedWindowItem prepends the 0062 // elements to the list, so if we do it forwards the we would get an inverse 0063 // order of closed windows 0064 for (i.toBack(); i.hasPrevious();) { 0065 slotAddClosedWindowItem(nullptr, i.previous()); 0066 } 0067 } 0068 0069 void KonqUndoManager::slotFileUndoAvailable(bool) 0070 { 0071 emit undoAvailable(this->undoAvailable()); 0072 } 0073 0074 bool KonqUndoManager::undoAvailable() const 0075 { 0076 if (!m_closedItemList.isEmpty() || m_cwManager->undoAvailable()) { 0077 return true; 0078 } else { 0079 return (m_supportsFileUndo && KIO::FileUndoManager::self()->isUndoAvailable()); 0080 } 0081 } 0082 0083 QString KonqUndoManager::undoText() const 0084 { 0085 if (!m_closedItemList.isEmpty()) { 0086 const KonqClosedItem *closedItem = m_closedItemList.first(); 0087 if (!m_supportsFileUndo || !KIO::FileUndoManager::self()->isUndoAvailable() || closedItem->serialNumber() > KIO::FileUndoManager::self()->currentCommandSerialNumber()) { 0088 const KonqClosedTabItem *closedTabItem = 0089 dynamic_cast<const KonqClosedTabItem *>(closedItem); 0090 if (closedTabItem) { 0091 return i18n("Und&o: Closed Tab"); 0092 } else { 0093 return i18n("Und&o: Closed Window"); 0094 } 0095 } else { 0096 return KIO::FileUndoManager::self()->undoText(); 0097 } 0098 0099 } else if (m_supportsFileUndo && KIO::FileUndoManager::self()->isUndoAvailable()) { 0100 return KIO::FileUndoManager::self()->undoText(); 0101 } 0102 0103 else if (m_cwManager->undoAvailable()) { 0104 return i18n("Und&o: Closed Window"); 0105 } else { 0106 return i18n("Und&o"); 0107 } 0108 } 0109 0110 void KonqUndoManager::undo() 0111 { 0112 populate(); 0113 KIO::FileUndoManager *fileUndoManager = KIO::FileUndoManager::self(); 0114 if (!m_closedItemList.isEmpty()) { 0115 KonqClosedItem *closedItem = m_closedItemList.first(); 0116 0117 // Check what to undo 0118 if (!m_supportsFileUndo || !fileUndoManager->isUndoAvailable() || closedItem->serialNumber() > fileUndoManager->currentCommandSerialNumber()) { 0119 undoClosedItem(0); 0120 return; 0121 } 0122 } 0123 fileUndoManager->uiInterface()->setParentWidget(qobject_cast<QWidget *>(parent())); 0124 fileUndoManager->undo(); 0125 } 0126 0127 void KonqUndoManager::slotAddClosedWindowItem(KonqUndoManager *real_sender, KonqClosedWindowItem *closedWindowItem) 0128 { 0129 if (real_sender == this) { 0130 return; 0131 } 0132 0133 populate(); 0134 0135 if (m_closedItemList.size() >= KonqSettings::maxNumClosedItems()) { 0136 const KonqClosedItem *last = m_closedItemList.last(); 0137 const KonqClosedTabItem *lastTab = 0138 dynamic_cast<const KonqClosedTabItem *>(last); 0139 m_closedItemList.removeLast(); 0140 0141 // Delete only if it's a tab 0142 if (lastTab) { 0143 delete lastTab; 0144 } 0145 } 0146 0147 m_closedItemList.prepend(closedWindowItem); 0148 emit undoTextChanged(i18n("Und&o: Closed Window")); 0149 emit undoAvailable(true); 0150 emit closedItemsListChanged(); 0151 } 0152 0153 void KonqUndoManager::addClosedWindowItem(KonqClosedWindowItem *closedWindowItem) 0154 { 0155 populate(); 0156 m_cwManager->addClosedWindowItem(this, closedWindowItem); 0157 } 0158 0159 void KonqUndoManager::slotRemoveClosedWindowItem(KonqUndoManager *real_sender, const KonqClosedWindowItem *closedWindowItem) 0160 { 0161 if (real_sender == this) { 0162 return; 0163 } 0164 0165 populate(); 0166 0167 QList<KonqClosedItem *>::iterator it = std::find(m_closedItemList.begin(), m_closedItemList.end(), closedWindowItem); 0168 0169 // If the item was found, remove it from the list 0170 if (it != m_closedItemList.end()) { 0171 m_closedItemList.erase(it); 0172 emit undoAvailable(this->undoAvailable()); 0173 emit closedItemsListChanged(); 0174 } 0175 } 0176 0177 const QList<KonqClosedItem *> &KonqUndoManager::closedItemsList() 0178 { 0179 populate(); 0180 return m_closedItemList; 0181 } 0182 0183 void KonqUndoManager::undoClosedItem(int index) 0184 { 0185 populate(); 0186 Q_ASSERT(!m_closedItemList.isEmpty()); 0187 KonqClosedItem *closedItem = m_closedItemList.at(index); 0188 m_closedItemList.removeAt(index); 0189 0190 const KonqClosedTabItem *closedTabItem = 0191 dynamic_cast<const KonqClosedTabItem *>(closedItem); 0192 KonqClosedRemoteWindowItem *closedRemoteWindowItem = 0193 dynamic_cast<KonqClosedRemoteWindowItem *>(closedItem); 0194 KonqClosedWindowItem *closedWindowItem = 0195 dynamic_cast<KonqClosedWindowItem *>(closedItem); 0196 if (closedTabItem) { 0197 emit openClosedTab(*closedTabItem); 0198 } else if (closedRemoteWindowItem) { 0199 m_cwManager->removeClosedWindowItem(this, closedRemoteWindowItem); 0200 emit openClosedWindow(*closedRemoteWindowItem); 0201 } else if (closedWindowItem) { 0202 m_cwManager->removeClosedWindowItem(this, closedWindowItem); 0203 emit openClosedWindow(*closedWindowItem); 0204 closedWindowItem->configGroup().deleteGroup(); 0205 0206 // Save config so that this window won't appear in new konqueror processes 0207 m_cwManager->saveConfig(); 0208 } 0209 delete closedItem; 0210 emit undoAvailable(this->undoAvailable()); 0211 emit undoTextChanged(this->undoText()); 0212 emit closedItemsListChanged(); 0213 } 0214 0215 void KonqUndoManager::slotClosedItemsActivated(QAction *action) 0216 { 0217 // Open a closed tab 0218 const int index = action->data().toInt(); 0219 undoClosedItem(index); 0220 } 0221 0222 void KonqUndoManager::slotFileUndoTextChanged(const QString & /*text*/) 0223 { 0224 // We will forward this call but changing the text, because if for example 0225 // there' no more files to undo, the text will be "Und&o" but maybe 0226 // we want it to be "Und&o: Closed Tab" if we have a closed tab that can be 0227 // reopened. 0228 emit undoTextChanged(undoText()); 0229 } 0230 0231 quint64 KonqUndoManager::newCommandSerialNumber() 0232 { 0233 return KIO::FileUndoManager::self()->newCommandSerialNumber(); 0234 } 0235 0236 void KonqUndoManager::addClosedTabItem(KonqClosedTabItem *closedTabItem) 0237 { 0238 populate(); 0239 0240 if (m_closedItemList.size() >= KonqSettings::maxNumClosedItems()) { 0241 const KonqClosedItem *last = m_closedItemList.last(); 0242 const KonqClosedTabItem *lastTab = 0243 dynamic_cast<const KonqClosedTabItem *>(last); 0244 m_closedItemList.removeLast(); 0245 0246 // Delete only if it's a tab 0247 if (lastTab) { 0248 delete lastTab; 0249 } 0250 } 0251 0252 m_closedItemList.prepend(closedTabItem); 0253 emit undoTextChanged(i18n("Und&o: Closed Tab")); 0254 emit undoAvailable(true); 0255 } 0256 0257 void KonqUndoManager::updateSupportsFileUndo(bool enable) 0258 { 0259 m_supportsFileUndo = enable; 0260 emit undoAvailable(this->undoAvailable()); 0261 } 0262 0263 void KonqUndoManager::clearClosedItemsList(bool onlyInthisWindow) 0264 { 0265 populate(); 0266 QList<KonqClosedItem *>::iterator it = m_closedItemList.begin(); 0267 for (; it != m_closedItemList.end();) { 0268 KonqClosedItem *closedItem = *it; 0269 const KonqClosedTabItem *closedTabItem = 0270 dynamic_cast<const KonqClosedTabItem *>(closedItem); 0271 const KonqClosedWindowItem *closedWindowItem = 0272 dynamic_cast<const KonqClosedWindowItem *>(closedItem); 0273 0274 it = m_closedItemList.erase(it); 0275 if (closedTabItem) { 0276 delete closedTabItem; 0277 } else if (closedWindowItem && !onlyInthisWindow) { 0278 m_cwManager->removeClosedWindowItem(this, closedWindowItem, true); 0279 delete closedWindowItem; 0280 } 0281 } 0282 0283 emit closedItemsListChanged(); 0284 emit undoAvailable(this->undoAvailable()); 0285 0286 // Save config so that this window won't appear in new konqueror processes 0287 m_cwManager->saveConfig(); 0288 } 0289 0290 void KonqUndoManager::undoLastClosedItem() 0291 { 0292 undoClosedItem(0); 0293 } 0294