| 1 | /* |
| 2 | This file is part of the KDE project |
| 3 | SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org> |
| 4 | SPDX-FileCopyrightText: 2006, 2008 David Faure <faure@kde.org> |
| 5 | |
| 6 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 7 | */ |
| 8 | |
| 9 | #ifndef FILEUNDOMANAGER_P_H |
| 10 | #define FILEUNDOMANAGER_P_H |
| 11 | |
| 12 | #include "fileundomanager.h" |
| 13 | #include <QDateTime> |
| 14 | #include <QQueue> |
| 15 | #include <QStack> |
| 16 | |
| 17 | class KJob; |
| 18 | |
| 19 | namespace KIO |
| 20 | { |
| 21 | class FileUndoManagerAdaptor; |
| 22 | |
| 23 | struct BasicOperation { |
| 24 | enum Type { |
| 25 | File, |
| 26 | Link, |
| 27 | Directory, |
| 28 | /* |
| 29 | * Used with BatchRenameJob, it doesn't stat the files/dirs it's renaming, |
| 30 | * so the file/dir distinction isn't available |
| 31 | */ |
| 32 | Item, |
| 33 | }; |
| 34 | |
| 35 | // for QDataStream deserialization |
| 36 | BasicOperation() |
| 37 | { |
| 38 | } |
| 39 | BasicOperation(Type type, bool renamed, const QUrl &src, const QUrl &dst, const QDateTime &mtime, const QString &target = {}) |
| 40 | : m_valid(true) |
| 41 | , m_renamed(renamed) |
| 42 | , m_type(type) |
| 43 | , m_src(src) |
| 44 | , m_dst(dst) |
| 45 | , m_target(target) |
| 46 | , m_mtime(mtime) |
| 47 | { |
| 48 | } |
| 49 | |
| 50 | bool m_valid = false; |
| 51 | bool m_renamed; |
| 52 | |
| 53 | Type m_type : 2; |
| 54 | |
| 55 | QUrl m_src; |
| 56 | QUrl m_dst; |
| 57 | QString m_target; |
| 58 | QDateTime m_mtime; |
| 59 | }; |
| 60 | |
| 61 | class UndoCommand |
| 62 | { |
| 63 | public: |
| 64 | UndoCommand() = default; |
| 65 | |
| 66 | UndoCommand(FileUndoManager::CommandType type, const QList<QUrl> &src, const QUrl &dst, qint64 serialNumber) |
| 67 | : m_valid(true) |
| 68 | , m_type(type) |
| 69 | , m_src(src) |
| 70 | , m_dst(dst) |
| 71 | , m_serialNumber(serialNumber) |
| 72 | { |
| 73 | } |
| 74 | |
| 75 | // TODO: is ::TRASH missing? |
| 76 | bool isMoveOrRename() const |
| 77 | { |
| 78 | return m_type == FileUndoManager::Move || m_type == FileUndoManager::Rename; |
| 79 | } |
| 80 | |
| 81 | bool m_valid = false; |
| 82 | FileUndoManager::CommandType m_type; |
| 83 | QQueue<BasicOperation> m_opQueue; |
| 84 | QList<QUrl> m_src; |
| 85 | QUrl m_dst; |
| 86 | quint64 m_serialNumber = 0; |
| 87 | }; |
| 88 | |
| 89 | // This class listens to a job, collects info while it's running (for copyjobs) |
| 90 | // and when the job terminates, on success, it calls addUndoCommand in the undomanager. |
| 91 | class CommandRecorder : public QObject |
| 92 | { |
| 93 | Q_OBJECT |
| 94 | public: |
| 95 | CommandRecorder(FileUndoManager::CommandType op, const QList<QUrl> &src, const QUrl &dst, std::function<void(UndoCommand)> onFinished, KIO::Job *job); |
| 96 | |
| 97 | private Q_SLOTS: |
| 98 | void slotResult(KJob *job); |
| 99 | |
| 100 | void slotCopyingDone(KIO::Job *, const QUrl &from, const QUrl &to, const QDateTime &, bool directory, bool renamed); |
| 101 | void slotCopyingLinkDone(KIO::Job *, const QUrl &from, const QString &target, const QUrl &to); |
| 102 | void slotDirectoryCreated(const QUrl &url); |
| 103 | void slotBatchRenamingDone(const QUrl &from, const QUrl &to); |
| 104 | |
| 105 | private: |
| 106 | UndoCommand m_cmd; |
| 107 | std::function<void(UndoCommand)> m_onFinished; |
| 108 | }; |
| 109 | |
| 110 | enum UndoState { |
| 111 | MAKINGDIRS = 0, |
| 112 | MOVINGFILES, |
| 113 | STATINGFILE, |
| 114 | MOVINGLINK, |
| 115 | TRASHINGFILES, |
| 116 | REMOVINGDIRS, |
| 117 | }; |
| 118 | |
| 119 | // The private class is, exceptionally, a real QObject |
| 120 | // so that it can be the class with the DBUS adaptor forwarding its signals. |
| 121 | class FileUndoManagerPrivate : public QObject |
| 122 | { |
| 123 | Q_OBJECT |
| 124 | public: |
| 125 | explicit FileUndoManagerPrivate(FileUndoManager *qq); |
| 126 | |
| 127 | ~FileUndoManagerPrivate() override = default; |
| 128 | |
| 129 | void pushUndoCommand(const UndoCommand &cmd); |
| 130 | void pushRedoCommand(const UndoCommand &cmd); |
| 131 | void popRedoCommand(); |
| 132 | void clearRedoStack(); |
| 133 | |
| 134 | void addDirToUpdate(const QUrl &url); |
| 135 | |
| 136 | void startUndoOrRedo(bool redo); |
| 137 | void stepMakingDirectories(); |
| 138 | void stepTrashingFiles(bool redo); |
| 139 | void stepRemovingDirectories(); |
| 140 | void undoStepMovingFiles(); |
| 141 | void redoStepMovingFiles(); |
| 142 | |
| 143 | /// called by FileUndoManagerAdaptor |
| 144 | QByteArray get() const; |
| 145 | |
| 146 | friend class UndoJob; |
| 147 | /// called by UndoJob |
| 148 | void stopUndoOrRedo(bool step); |
| 149 | |
| 150 | friend class UndoCommandRecorder; |
| 151 | /// called by UndoCommandRecorder |
| 152 | void addUndoCommand(const UndoCommand &cmd); |
| 153 | |
| 154 | QStack<UndoCommand> m_undoCommands; |
| 155 | QStack<UndoCommand> m_redoCommands; |
| 156 | |
| 157 | KIO::Job *m_currentJob = nullptr; |
| 158 | QStack<QUrl> m_dirStack; |
| 159 | QStack<QUrl> m_dirCleanupStack; |
| 160 | QStack<QUrl> m_fileTrashStack; |
| 161 | QList<QUrl> m_dirsToUpdate; |
| 162 | std::unique_ptr<FileUndoManager::UiInterface> m_uiInterface; |
| 163 | |
| 164 | UndoJob *m_undoJob = nullptr; |
| 165 | quint64 m_nextCommandIndex = 0; |
| 166 | |
| 167 | FileUndoManager *const q; |
| 168 | |
| 169 | UndoCommand m_currentCmd; |
| 170 | UndoCommand m_cmdToBePushed; |
| 171 | UndoState m_undoState; |
| 172 | bool m_lock = false; |
| 173 | bool m_connectedToAskUserInterface = false; |
| 174 | |
| 175 | // DBUS interface |
| 176 | Q_SIGNALS: |
| 177 | /// DBUS signal |
| 178 | void push(const QByteArray &command); |
| 179 | /// DBUS signal |
| 180 | void pop(); |
| 181 | /// DBUS signal |
| 182 | void lock(); |
| 183 | /// DBUS signal |
| 184 | void unlock(); |
| 185 | |
| 186 | public Q_SLOTS: |
| 187 | // Those four slots are connected to DBUS signals |
| 188 | void slotPushUndoCommand(QByteArray); |
| 189 | void slotPopUndoCommand(); |
| 190 | void slotLock(); |
| 191 | void slotUnlock(); |
| 192 | |
| 193 | void processStep(bool redo); |
| 194 | void slotUndoResult(KJob *); |
| 195 | void slotRedoResult(KJob *); |
| 196 | }; |
| 197 | |
| 198 | } // namespace |
| 199 | |
| 200 | #endif /* FILEUNDOMANAGER_P_H */ |
| 201 | |