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 | |