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 KIO_FILEUNDOMANAGER_H |
10 | #define KIO_FILEUNDOMANAGER_H |
11 | |
12 | #include <QObject> |
13 | #include <QUrl> |
14 | |
15 | #include "kiowidgets_export.h" |
16 | |
17 | #include <memory> |
18 | |
19 | class QDateTime; |
20 | |
21 | namespace KIO |
22 | { |
23 | class Job; |
24 | class CopyJob; |
25 | class FileUndoManagerPrivate; |
26 | class FileUndoManagerSingleton; |
27 | class CommandRecorder; |
28 | class UndoCommand; |
29 | class UndoJob; |
30 | |
31 | /*! |
32 | * \class KIO::FileUndoManager |
33 | * \inheaderfile KIO/FileUndoManager |
34 | * \inmodule KIOWidgets |
35 | * |
36 | * \brief Makes it possible to undo KIO jobs. |
37 | * |
38 | * This class is a singleton, use self() to access its only instance. |
39 | */ |
40 | class KIOWIDGETS_EXPORT FileUndoManager : public QObject |
41 | { |
42 | Q_OBJECT |
43 | public: |
44 | /*! |
45 | * Returns the FileUndoManager instance |
46 | */ |
47 | static FileUndoManager *self(); |
48 | |
49 | /*! |
50 | * \class KIO::FileUndoManager::UiInterface |
51 | * \inmodule KIOGui |
52 | * |
53 | * Interface for the gui handling of FileUndoManager. |
54 | * This includes three events currently: |
55 | * \list |
56 | * \li error when undoing a job |
57 | * \li (until KF 5.78) confirm deletion before undoing a copy job |
58 | * \li confirm deletion when the copied file has been modified afterwards |
59 | * \endlist |
60 | * |
61 | * By default UiInterface shows message boxes in all three cases; |
62 | * applications can reimplement this interface to provide different user interfaces. |
63 | */ |
64 | class KIOWIDGETS_EXPORT UiInterface |
65 | { |
66 | public: |
67 | UiInterface(); |
68 | virtual ~UiInterface(); |
69 | |
70 | /*! |
71 | * Sets whether to show progress info when running the KIO jobs for undoing. |
72 | */ |
73 | void setShowProgressInfo(bool b); |
74 | /*! |
75 | * Returns whether progress info dialogs are shown while undoing. |
76 | */ |
77 | bool showProgressInfo() const; |
78 | |
79 | /*! |
80 | * Sets the parent widget to use for message boxes. |
81 | */ |
82 | void setParentWidget(QWidget *parentWidget); |
83 | |
84 | /*! |
85 | * Returns the parent widget passed to the last call to undo(parentWidget), or \c nullptr. |
86 | */ |
87 | QWidget *parentWidget() const; |
88 | |
89 | /*! |
90 | * Called when an undo job errors; default implementation displays a message box. |
91 | */ |
92 | virtual void jobError(KIO::Job *job); |
93 | |
94 | /*! |
95 | * Called when dest was modified since it was copied from src. |
96 | * Note that this is called after confirmDeletion. |
97 | * Return true if we should proceed with deleting dest. |
98 | */ |
99 | virtual bool copiedFileWasModified(const QUrl &src, const QUrl &dest, const QDateTime &srcTime, const QDateTime &destTime); |
100 | |
101 | // TODO KF6 replace hook with virtual AskUserActionInterface* askUserActionInterface(); // (does not take ownership) |
102 | enum { |
103 | HookGetAskUserActionInterface = 1 |
104 | }; |
105 | /*! |
106 | * \internal, for future extensions |
107 | */ |
108 | virtual void virtual_hook(int id, void *data); |
109 | |
110 | private: |
111 | class UiInterfacePrivate; |
112 | UiInterfacePrivate *d; |
113 | }; |
114 | |
115 | /*! |
116 | * Set a new UiInterface implementation. |
117 | * This deletes the previous one. |
118 | * |
119 | * \a ui the UiInterface instance, which becomes owned by the undo manager. |
120 | */ |
121 | void setUiInterface(UiInterface *ui); |
122 | |
123 | /*! |
124 | * Returns the UiInterface instance passed to setUiInterface. |
125 | * This is useful for calling setParentWidget on it. Never delete it! |
126 | */ |
127 | UiInterface *uiInterface() const; |
128 | |
129 | /*! |
130 | * The type of job. |
131 | * |
132 | * \value Copy |
133 | * \value Move |
134 | * \value Rename |
135 | * \value Link |
136 | * \value Mkdir |
137 | * \value Trash |
138 | * \value[since 4.7] Put Represents the creation of a file from data in memory. Used when pasting data from clipboard or drag-n-drop |
139 | * \value[since 5.4] Mkpath Represents a KIO::mkpath() job |
140 | * \value[since 5.42] BatchRename Represents a KIO::batchRename() job. Used when renaming multiple files |
141 | */ |
142 | enum CommandType { |
143 | Copy, |
144 | Move, |
145 | Rename, |
146 | Link, |
147 | Mkdir, |
148 | Trash, |
149 | Put, |
150 | Mkpath, |
151 | BatchRename |
152 | }; |
153 | |
154 | /*! |
155 | * Record this job while it's happening and add a command for it so that the user can undo it. |
156 | * The signal jobRecordingStarted() is emitted. |
157 | * |
158 | * \a op the type of job - which is also the type of command that will be created for it |
159 | * |
160 | * \a src list of source urls. This is empty for Mkdir, Mkpath, Put operations. |
161 | * |
162 | * \a dst destination url |
163 | * |
164 | * \a job the job to record |
165 | */ |
166 | void recordJob(CommandType op, const QList<QUrl> &src, const QUrl &dst, KIO::Job *job); |
167 | |
168 | /*! |
169 | * Record this CopyJob while it's happening and add a command for it so that the user can undo it. |
170 | * The signal jobRecordingStarted() is emitted. |
171 | */ |
172 | void recordCopyJob(KIO::CopyJob *copyJob); |
173 | |
174 | /*! |
175 | * Returns true if undo is possible. Usually used for enabling/disabling the undo action. |
176 | * |
177 | * \since 5.79 |
178 | */ |
179 | bool isUndoAvailable() const; |
180 | |
181 | /*! |
182 | * Returns true if redo is possible. Usually used for enabling/disabling the redo action. |
183 | * |
184 | * \since 6.17 |
185 | */ |
186 | bool isRedoAvailable() const; |
187 | |
188 | /*! |
189 | * Returns the current text for the undo action. |
190 | */ |
191 | QString undoText() const; |
192 | |
193 | /*! |
194 | * Returns the current text for the redo action. |
195 | * |
196 | * \since 6.17 |
197 | */ |
198 | QString redoText() const; |
199 | |
200 | /*! |
201 | * These two functions are useful when wrapping FileUndoManager and adding custom commands. |
202 | * Each command has a unique ID. You can get a new serial number for a custom command |
203 | * with newCommandSerialNumber(), and then when you want to undo, check if the command |
204 | * FileUndoManager would undo is newer or older than your custom command. |
205 | * |
206 | * \sa currentCommandSerialNumber() |
207 | */ |
208 | quint64 newCommandSerialNumber(); |
209 | |
210 | /*! |
211 | * |
212 | */ |
213 | quint64 currentCommandSerialNumber() const; |
214 | |
215 | public Q_SLOTS: |
216 | /*! |
217 | * Undoes the last command |
218 | * Remember to call uiInterface()->setParentWidget(parentWidget) first, |
219 | * if you have multiple mainwindows. |
220 | * |
221 | * This operation is asynchronous. |
222 | * undoJobFinished will be emitted once the undo is complete. |
223 | */ |
224 | void undo(); // TODO pass QWindow*, for askUserInterface->askUserDelete and error handling etc. |
225 | |
226 | /*! |
227 | * Redoes the last command |
228 | * Remember to call uiInterface()->setParentWidget(parentWidget) first, |
229 | * if you have multiple mainwindows. |
230 | * |
231 | * This operation is asynchronous. |
232 | * undoJobFinished will be emitted once the redo is complete. |
233 | * |
234 | * \since 6.17 |
235 | */ |
236 | void redo(); |
237 | |
238 | Q_SIGNALS: |
239 | /*! |
240 | * Emitted when the value of isUndoAvailable() changes |
241 | */ |
242 | void undoAvailable(bool avail); |
243 | |
244 | /*! |
245 | * Emitted when the value of isRedoAvailable() changes |
246 | * |
247 | * \since 6.17 |
248 | */ |
249 | void redoAvailable(bool avail); |
250 | |
251 | /*! |
252 | * Emitted when the value of undoText() changes |
253 | */ |
254 | void undoTextChanged(const QString &text); |
255 | |
256 | /*! |
257 | * Emitted when the value of redoText() changes |
258 | * |
259 | * \since 6.17 |
260 | */ |
261 | void redoTextChanged(const QString &text); |
262 | |
263 | /*! |
264 | * Emitted when an undo (or redo) job finishes. Used for unit testing. |
265 | */ |
266 | void undoJobFinished(); |
267 | |
268 | /*! |
269 | * Emitted when a job recording has been started by FileUndoManager::recordJob() |
270 | * or FileUndoManager::recordCopyJob(). After the job recording has been finished, |
271 | * the signal jobRecordingFinished() will be emitted. |
272 | */ |
273 | void jobRecordingStarted(CommandType op); |
274 | |
275 | /*! |
276 | * Emitted when a job that has been recorded by FileUndoManager::recordJob() |
277 | * or FileUndoManager::recordCopyJob has been finished. The command |
278 | * is now available for an undo-operation. |
279 | */ |
280 | void jobRecordingFinished(FileUndoManager::CommandType op); |
281 | |
282 | private: |
283 | KIOWIDGETS_NO_EXPORT FileUndoManager(); |
284 | KIOWIDGETS_NO_EXPORT ~FileUndoManager() override; |
285 | friend class FileUndoManagerSingleton; |
286 | |
287 | friend class UndoJob; |
288 | friend class CommandRecorder; |
289 | |
290 | friend class FileUndoManagerPrivate; |
291 | std::unique_ptr<FileUndoManagerPrivate> d; |
292 | }; |
293 | |
294 | } // namespace |
295 | |
296 | #endif |
297 | |