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 addCommand 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, 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 | }; |
108 | |
109 | enum UndoState { |
110 | MAKINGDIRS = 0, |
111 | MOVINGFILES, |
112 | STATINGFILE, |
113 | REMOVINGDIRS, |
114 | REMOVINGLINKS, |
115 | }; |
116 | |
117 | // The private class is, exceptionally, a real QObject |
118 | // so that it can be the class with the DBUS adaptor forwarding its signals. |
119 | class FileUndoManagerPrivate : public QObject |
120 | { |
121 | Q_OBJECT |
122 | public: |
123 | explicit FileUndoManagerPrivate(FileUndoManager *qq); |
124 | |
125 | ~FileUndoManagerPrivate() override = default; |
126 | |
127 | void pushCommand(const UndoCommand &cmd); |
128 | |
129 | void addDirToUpdate(const QUrl &url); |
130 | |
131 | void startUndo(); |
132 | void stepMakingDirectories(); |
133 | void stepMovingFiles(); |
134 | void stepRemovingLinks(); |
135 | void stepRemovingDirectories(); |
136 | |
137 | /// called by FileUndoManagerAdaptor |
138 | QByteArray get() const; |
139 | |
140 | friend class UndoJob; |
141 | /// called by UndoJob |
142 | void stopUndo(bool step); |
143 | |
144 | friend class UndoCommandRecorder; |
145 | /// called by UndoCommandRecorder |
146 | void addCommand(const UndoCommand &cmd); |
147 | |
148 | QStack<UndoCommand> m_commands; |
149 | |
150 | KIO::Job *m_currentJob = nullptr; |
151 | QStack<QUrl> m_dirStack; |
152 | QStack<QUrl> m_dirCleanupStack; |
153 | QStack<QUrl> m_fileCleanupStack; // files and links |
154 | QList<QUrl> m_dirsToUpdate; |
155 | std::unique_ptr<FileUndoManager::UiInterface> m_uiInterface; |
156 | |
157 | UndoJob *m_undoJob = nullptr; |
158 | quint64 m_nextCommandIndex = 0; |
159 | |
160 | FileUndoManager *const q; |
161 | |
162 | UndoCommand m_currentCmd; |
163 | UndoState m_undoState; |
164 | bool m_lock = false; |
165 | bool m_connectedToAskUserInterface = false; |
166 | |
167 | // DBUS interface |
168 | Q_SIGNALS: |
169 | /// DBUS signal |
170 | void push(const QByteArray &command); |
171 | /// DBUS signal |
172 | void pop(); |
173 | /// DBUS signal |
174 | void lock(); |
175 | /// DBUS signal |
176 | void unlock(); |
177 | |
178 | public Q_SLOTS: |
179 | // Those four slots are connected to DBUS signals |
180 | void slotPush(QByteArray); |
181 | void slotPop(); |
182 | void slotLock(); |
183 | void slotUnlock(); |
184 | |
185 | void undoStep(); |
186 | void slotResult(KJob *); |
187 | }; |
188 | |
189 | } // namespace |
190 | |
191 | #endif /* FILEUNDOMANAGER_P_H */ |
192 | |