File indexing completed on 2024-07-14 14:33:57

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org>
0004     SPDX-FileCopyrightText: 2006, 2008 David Faure <faure@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef FILEUNDOMANAGER_P_H
0010 #define FILEUNDOMANAGER_P_H
0011 
0012 #include "fileundomanager.h"
0013 #include <QDateTime>
0014 #include <QQueue>
0015 #include <QStack>
0016 
0017 class KJob;
0018 
0019 namespace KIO
0020 {
0021 class FileUndoManagerAdaptor;
0022 
0023 struct BasicOperation {
0024     enum Type {
0025         File,
0026         Link,
0027         Directory,
0028         /**
0029          * Used with BatchRenameJob, it doesn't stat the files/dirs it's renaming,
0030          * so the file/dir distinction isn't available
0031          */
0032         Item,
0033     };
0034 
0035     // for QDataStream deserialization
0036     BasicOperation()
0037     {
0038     }
0039     BasicOperation(Type type, bool renamed, const QUrl &src, const QUrl &dst, const QDateTime &mtime, const QString &target = {})
0040         : m_valid(true)
0041         , m_renamed(renamed)
0042         , m_type(type)
0043         , m_src(src)
0044         , m_dst(dst)
0045         , m_target(target)
0046         , m_mtime(mtime)
0047     {
0048     }
0049 
0050     bool m_valid = false;
0051     bool m_renamed;
0052 
0053     Type m_type : 2;
0054 
0055     QUrl m_src;
0056     QUrl m_dst;
0057     QString m_target;
0058     QDateTime m_mtime;
0059 };
0060 
0061 class UndoCommand
0062 {
0063 public:
0064     UndoCommand() = default;
0065 
0066     UndoCommand(FileUndoManager::CommandType type, const QList<QUrl> &src, const QUrl &dst, qint64 serialNumber)
0067         : m_valid(true)
0068         , m_type(type)
0069         , m_src(src)
0070         , m_dst(dst)
0071         , m_serialNumber(serialNumber)
0072     {
0073     }
0074 
0075     // TODO: is ::TRASH missing?
0076     bool isMoveOrRename() const
0077     {
0078         return m_type == FileUndoManager::Move || m_type == FileUndoManager::Rename;
0079     }
0080 
0081     bool m_valid = false;
0082     FileUndoManager::CommandType m_type;
0083     QQueue<BasicOperation> m_opQueue;
0084     QList<QUrl> m_src;
0085     QUrl m_dst;
0086     quint64 m_serialNumber = 0;
0087 };
0088 
0089 // This class listens to a job, collects info while it's running (for copyjobs)
0090 // and when the job terminates, on success, it calls addCommand in the undomanager.
0091 class CommandRecorder : public QObject
0092 {
0093     Q_OBJECT
0094 public:
0095     CommandRecorder(FileUndoManager::CommandType op, const QList<QUrl> &src, const QUrl &dst, KIO::Job *job);
0096 
0097 private Q_SLOTS:
0098     void slotResult(KJob *job);
0099 
0100     void slotCopyingDone(KIO::Job *, const QUrl &from, const QUrl &to, const QDateTime &, bool directory, bool renamed);
0101     void slotCopyingLinkDone(KIO::Job *, const QUrl &from, const QString &target, const QUrl &to);
0102     void slotDirectoryCreated(const QUrl &url);
0103     void slotBatchRenamingDone(const QUrl &from, const QUrl &to);
0104 
0105 private:
0106     UndoCommand m_cmd;
0107 };
0108 
0109 enum UndoState {
0110     MAKINGDIRS = 0,
0111     MOVINGFILES,
0112     STATINGFILE,
0113     REMOVINGDIRS,
0114     REMOVINGLINKS,
0115 };
0116 
0117 // The private class is, exceptionally, a real QObject
0118 // so that it can be the class with the DBUS adaptor forwarding its signals.
0119 class FileUndoManagerPrivate : public QObject
0120 {
0121     Q_OBJECT
0122 public:
0123     explicit FileUndoManagerPrivate(FileUndoManager *qq);
0124 
0125     ~FileUndoManagerPrivate() override = default;
0126 
0127     void pushCommand(const UndoCommand &cmd);
0128 
0129     void addDirToUpdate(const QUrl &url);
0130 
0131     void startUndo();
0132     void stepMakingDirectories();
0133     void stepMovingFiles();
0134     void stepRemovingLinks();
0135     void stepRemovingDirectories();
0136 
0137     /// called by FileUndoManagerAdaptor
0138     QByteArray get() const;
0139 
0140     friend class UndoJob;
0141     /// called by UndoJob
0142     void stopUndo(bool step);
0143 
0144     friend class UndoCommandRecorder;
0145     /// called by UndoCommandRecorder
0146     void addCommand(const UndoCommand &cmd);
0147 
0148     QStack<UndoCommand> m_commands;
0149 
0150     KIO::Job *m_currentJob = nullptr;
0151     QStack<QUrl> m_dirStack;
0152     QStack<QUrl> m_dirCleanupStack;
0153     QStack<QUrl> m_fileCleanupStack; // files and links
0154     QList<QUrl> m_dirsToUpdate;
0155     std::unique_ptr<FileUndoManager::UiInterface> m_uiInterface;
0156 
0157     UndoJob *m_undoJob = nullptr;
0158     quint64 m_nextCommandIndex = 0;
0159 
0160     FileUndoManager *const q;
0161 
0162     UndoCommand m_currentCmd;
0163     UndoState m_undoState;
0164     bool m_lock = false;
0165     bool m_connectedToAskUserInterface = false;
0166 
0167     // DBUS interface
0168 Q_SIGNALS:
0169     /// DBUS signal
0170     void push(const QByteArray &command);
0171     /// DBUS signal
0172     void pop();
0173     /// DBUS signal
0174     void lock();
0175     /// DBUS signal
0176     void unlock();
0177 
0178 public Q_SLOTS:
0179     // Those four slots are connected to DBUS signals
0180     void slotPush(QByteArray);
0181     void slotPop();
0182     void slotLock();
0183     void slotUnlock();
0184 
0185     void undoStep();
0186     void slotResult(KJob *);
0187 };
0188 
0189 } // namespace
0190 
0191 #endif /* FILEUNDOMANAGER_P_H */