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 { File, Link, Directory };
25 
26     // for QDataStream deserialization
BasicOperationBasicOperation27     BasicOperation()
28     {
29     }
30     BasicOperation(Type type, bool renamed, const QUrl &src, const QUrl &dst, const QDateTime &mtime, const QString &target = {})
m_validBasicOperation31         : m_valid(true)
32         , m_renamed(renamed)
33         , m_type(type)
34         , m_src(src)
35         , m_dst(dst)
36         , m_target(target)
37         , m_mtime(mtime)
38     {
39     }
40 
41     bool m_valid = false;
42     bool m_renamed;
43 
44     Type m_type : 2;
45 
46     QUrl m_src;
47     QUrl m_dst;
48     QString m_target;
49     QDateTime m_mtime;
50 };
51 
52 class UndoCommand
53 {
54 public:
UndoCommand()55     UndoCommand()
56         : m_valid(false)
57     {
58     }
59 
UndoCommand(FileUndoManager::CommandType type,const QList<QUrl> & src,const QUrl & dst,qint64 serialNumber)60     UndoCommand(FileUndoManager::CommandType type, const QList<QUrl> &src, const QUrl &dst, qint64 serialNumber)
61         : m_valid(true)
62         , m_type(type)
63         , m_src(src)
64         , m_dst(dst)
65         , m_serialNumber(serialNumber)
66     {
67     }
68 
69     // TODO: is ::TRASH missing?
isMoveCommand()70     bool isMoveCommand() const
71     {
72         return m_type == FileUndoManager::Move || m_type == FileUndoManager::Rename;
73     }
74 
75     bool m_valid = false;
76     FileUndoManager::CommandType m_type;
77     QQueue<BasicOperation> m_opQueue;
78     QList<QUrl> m_src;
79     QUrl m_dst;
80     quint64 m_serialNumber;
81 };
82 
83 // This class listens to a job, collects info while it's running (for copyjobs)
84 // and when the job terminates, on success, it calls addCommand in the undomanager.
85 class CommandRecorder : public QObject
86 {
87     Q_OBJECT
88 public:
89     CommandRecorder(FileUndoManager::CommandType op, const QList<QUrl> &src, const QUrl &dst, KIO::Job *job);
90 
91 private Q_SLOTS:
92     void slotResult(KJob *job);
93 
94     void slotCopyingDone(KIO::Job *, const QUrl &from, const QUrl &to, const QDateTime &, bool directory, bool renamed);
95     void slotCopyingLinkDone(KIO::Job *, const QUrl &from, const QString &target, const QUrl &to);
96     void slotDirectoryCreated(const QUrl &url);
97     void slotBatchRenamingDone(const QUrl &from, const QUrl &to);
98 
99 private:
100     UndoCommand m_cmd;
101 };
102 
103 enum UndoState { MAKINGDIRS = 0, MOVINGFILES, STATINGFILE, REMOVINGDIRS, REMOVINGLINKS };
104 
105 // The private class is, exceptionally, a real QObject
106 // so that it can be the class with the DBUS adaptor forwarding its signals.
107 class FileUndoManagerPrivate : public QObject
108 {
109     Q_OBJECT
110 public:
111     explicit FileUndoManagerPrivate(FileUndoManager *qq);
112 
~FileUndoManagerPrivate()113     ~FileUndoManagerPrivate() override
114     {
115         delete m_uiInterface;
116     }
117 
118     void pushCommand(const UndoCommand &cmd);
119 
120     void addDirToUpdate(const QUrl &url);
121 
122     void startUndo();
123     void stepMakingDirectories();
124     void stepMovingFiles();
125     void stepRemovingLinks();
126     void stepRemovingDirectories();
127 
128     /// called by FileUndoManagerAdaptor
129     QByteArray get() const;
130 
131     friend class UndoJob;
132     /// called by UndoJob
133     void stopUndo(bool step);
134 
135     friend class UndoCommandRecorder;
136     /// called by UndoCommandRecorder
137     void addCommand(const UndoCommand &cmd);
138 
139     QStack<UndoCommand> m_commands;
140 
141     KIO::Job *m_currentJob = nullptr;
142     QStack<QUrl> m_dirStack;
143     QStack<QUrl> m_dirCleanupStack;
144     QStack<QUrl> m_fileCleanupStack; // files and links
145     QList<QUrl> m_dirsToUpdate;
146     FileUndoManager::UiInterface *m_uiInterface;
147 
148     UndoJob *m_undoJob = nullptr;
149     quint64 m_nextCommandIndex;
150 
151     FileUndoManager *const q;
152 
153     UndoCommand m_current;
154     UndoState m_undoState;
155     bool m_lock = false;
156     bool m_connectedToAskUserInterface = false;
157 
158     // DBUS interface
159 Q_SIGNALS:
160     /// DBUS signal
161     void push(const QByteArray &command);
162     /// DBUS signal
163     void pop();
164     /// DBUS signal
165     void lock();
166     /// DBUS signal
167     void unlock();
168 
169 public Q_SLOTS:
170     // Those four slots are connected to DBUS signals
171     void slotPush(QByteArray);
172     void slotPop();
173     void slotLock();
174     void slotUnlock();
175 
176     void undoStep();
177     void slotResult(KJob *);
178 };
179 
180 } // namespace
181 
182 #endif /* FILEUNDOMANAGER_P_H */
183