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 fileundomanager.h <KIO/FileUndoManager>
33  *
34  * FileUndoManager: makes it possible to undo kio jobs.
35  * This class is a singleton, use self() to access its only instance.
36  */
37 class KIOWIDGETS_EXPORT FileUndoManager : public QObject
38 {
39     Q_OBJECT
40 public:
41     /**
42      * @return the FileUndoManager instance
43      */
44     static FileUndoManager *self();
45 
46     /**
47      * Interface for the gui handling of FileUndoManager.
48      * This includes three events currently:
49      * - error when undoing a job
50      * - (until KF 5.78) confirm deletion before undoing a copy job
51      * - confirm deletion when the copied file has been modified afterwards
52      *
53      * By default UiInterface shows message boxes in all three cases;
54      * applications can reimplement this interface to provide different user interfaces.
55      */
56     class KIOWIDGETS_EXPORT UiInterface
57     {
58     public:
59         UiInterface();
60         virtual ~UiInterface();
61 
62         /**
63          * Sets whether to show progress info when running the KIO jobs for undoing.
64          */
65         void setShowProgressInfo(bool b);
66         /**
67          * @returns whether progress info dialogs are shown while undoing.
68          */
69         bool showProgressInfo() const;
70 
71         /**
72          * Sets the parent widget to use for message boxes.
73          */
74         void setParentWidget(QWidget *parentWidget);
75 
76         /**
77          * @return the parent widget passed to the last call to undo(parentWidget), or @c nullptr.
78          */
79         QWidget *parentWidget() const;
80 
81         /**
82          * Called when an undo job errors; default implementation displays a message box.
83          */
84         virtual void jobError(KIO::Job *job);
85 
86         /**
87          * Called when we are about to remove those files.
88          * Return true if we should proceed with deleting them.
89          * Deprecated since 5.79, no longer called.
90          */
91         virtual bool confirmDeletion(const QList<QUrl> &files);
92 
93         /**
94          * Called when dest was modified since it was copied from src.
95          * Note that this is called after confirmDeletion.
96          * Return true if we should proceed with deleting dest.
97          */
98         virtual bool copiedFileWasModified(const QUrl &src, const QUrl &dest, const QDateTime &srcTime, const QDateTime &destTime);
99 
100         // TODO KF6 replace hook with virtual AskUserActionInterface* askUserActionInterface(); // (does not take ownership)
101         enum { HookGetAskUserActionInterface = 1 };
102         /**
103          * \internal, for future extensions
104          */
105         virtual void virtual_hook(int id, void *data);
106 
107     private:
108         class UiInterfacePrivate;
109         UiInterfacePrivate *d;
110     };
111 
112     /**
113      * Set a new UiInterface implementation.
114      * This deletes the previous one.
115      * @param ui the UiInterface instance, which becomes owned by the undo manager.
116      */
117     void setUiInterface(UiInterface *ui);
118 
119     /**
120      * @return the UiInterface instance passed to setUiInterface.
121      * This is useful for calling setParentWidget on it. Never delete it!
122      */
123     UiInterface *uiInterface() const;
124 
125     /**
126      * The type of job.
127      *
128      * Put: @since 4.7, represents the creation of a file from data in memory.
129      *                Used when pasting data from clipboard or drag-n-drop.
130      * Mkpath: @since 5.4, represents a KIO::mkpath() job.
131      * BatchRename: @since 5.42, represents a KIO::batchRename() job. Used when
132      *              renaming multiple files.
133      */
134     enum CommandType { Copy, Move, Rename, Link, Mkdir, Trash, Put, Mkpath, BatchRename };
135 
136     /**
137      * Record this job while it's happening and add a command for it so that the user can undo it.
138      * The signal jobRecordingStarted() is emitted.
139      * @param op the type of job - which is also the type of command that will be created for it
140      * @param src list of source urls. This is empty for Mkdir, Mkpath, Put operations.
141      * @param dst destination url
142      * @param job the job to record
143      */
144     void recordJob(CommandType op, const QList<QUrl> &src, const QUrl &dst, KIO::Job *job);
145 
146     /**
147      * Record this CopyJob while it's happening and add a command for it so that the user can undo it.
148      * The signal jobRecordingStarted() is emitted.
149      */
150     void recordCopyJob(KIO::CopyJob *copyJob);
151 
152 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 79)
153     /**
154      * @return true if undo is possible. Usually used for enabling/disabling the undo action.
155      *
156      * @deprecated since 5.79, use KIO::FileUndoManager::isUndoAvailable()
157      */
158     KIOWIDGETS_DEPRECATED_VERSION(5, 79, "Use KIO::FileUndoManager::isUndoAvailable()")
159     bool undoAvailable() const; // clazy:exclude=overloaded-signal
160 #endif
161 
162     /**
163      * @return true if undo is possible. Usually used for enabling/disabling the undo action.
164      *
165      * @since 5.79
166      */
167     bool isUndoAvailable() const;
168 
169     /**
170      * @return the current text for the undo action.
171      */
172     QString undoText() const;
173 
174     /**
175      * These two functions are useful when wrapping FileUndoManager and adding custom commands.
176      * Each command has a unique ID. You can get a new serial number for a custom command
177      * with newCommandSerialNumber(), and then when you want to undo, check if the command
178      * FileUndoManager would undo is newer or older than your custom command.
179      */
180     quint64 newCommandSerialNumber();
181     quint64 currentCommandSerialNumber() const;
182 
183 public Q_SLOTS:
184     /**
185      * Undoes the last command
186      * Remember to call uiInterface()->setParentWidget(parentWidget) first,
187      * if you have multiple mainwindows.
188      *
189      * This operation is asynchronous.
190      * undoJobFinished will be emitted once the undo is complete.
191      */
192     void undo(); // TODO pass QWindow*, for askUserInterface->askUserDelete and error handling etc.
193 
194 Q_SIGNALS:
195     /// Emitted when the value of isUndoAvailable() changes
196     void undoAvailable(bool avail); // clazy:exclude=overloaded-signal
197 
198     /// Emitted when the value of undoText() changes
199     void undoTextChanged(const QString &text);
200 
201     /// Emitted when an undo job finishes. Used for unit testing.
202     void undoJobFinished();
203 
204     /**
205      * Emitted when a job recording has been started by FileUndoManager::recordJob()
206      * or FileUndoManager::recordCopyJob(). After the job recording has been finished,
207      * the signal jobRecordingFinished() will be emitted.
208      * @since 4.2
209      */
210     void jobRecordingStarted(CommandType op);
211 
212     /**
213      * Emitted when a job that has been recorded by FileUndoManager::recordJob()
214      * or FileUndoManager::recordCopyJob has been finished. The command
215      * is now available for an undo-operation.
216      * @since 4.2
217      */
218     // TODO KF6 signal arg should be fully-qualified
219     void jobRecordingFinished(CommandType op); // clazy:exclude=fully-qualified-moc-types
220 
221 private:
222     FileUndoManager();
223     ~FileUndoManager() override;
224     friend class FileUndoManagerSingleton;
225 
226     friend class UndoJob;
227     friend class CommandRecorder;
228 
229     friend class FileUndoManagerPrivate;
230     std::unique_ptr<FileUndoManagerPrivate> d;
231 };
232 
233 } // namespace
234 
235 #endif
236