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
19class QDateTime;
20
21namespace KIO
22{
23class Job;
24class CopyJob;
25class FileUndoManagerPrivate;
26class FileUndoManagerSingleton;
27class CommandRecorder;
28class UndoCommand;
29class 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 */
40class KIOWIDGETS_EXPORT FileUndoManager : public QObject
41{
42 Q_OBJECT
43public:
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
215public 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
238Q_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
282private:
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

source code of kio/src/widgets/fileundomanager.h