File indexing completed on 2024-05-19 13:37:44
0001 /* 0002 SPDX-FileCopyrightText: 2000 Shie Erlich <krusader@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2000 Rafi Yanai <krusader@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #ifndef FILESYSTEM_H 0010 #define FILESYSTEM_H 0011 0012 #include "dirlisterinterface.h" 0013 0014 // QtCore 0015 #include <QHash> 0016 #include <QList> 0017 #include <QPointer> 0018 #include <QString> 0019 // QtGui 0020 #include <QDropEvent> 0021 // QtWidgets 0022 #include <QWidget> 0023 0024 #include <KIO/CopyJob> 0025 #include <KIO/DirectorySizeJob> 0026 0027 #include "../JobMan/jobman.h" 0028 0029 class FileItem; 0030 0031 /** 0032 * An abstract filesystem. Use the implementations of this class for all file operations. 0033 * 0034 * It represents a directory and gives access to its files. All common file operations 0035 * are supported. Methods with absolute URL as argument can be used independently from the current 0036 * directory. Otherwise - if the methods argument is a file name - the operation is performed inside 0037 * the current directory. 0038 * 0039 * Notification signals are emitted if the directory content may have been changed. 0040 */ 0041 class FileSystem : public DirListerInterface 0042 { 0043 Q_OBJECT 0044 public: 0045 enum FS_TYPE { 0046 /// Virtual filesystem. Krusaders custom virt:/ protocol 0047 FS_VIRTUAL, 0048 /// Filesystem supporting all KIO protocols (file:/, ftp:/, smb:/, etc.) 0049 FS_DEFAULT 0050 }; 0051 0052 FileSystem(); 0053 ~FileSystem() override; 0054 0055 // DirListerInterface implementation 0056 inline QList<FileItem *> fileItems() const override 0057 { 0058 return _fileItems.values(); 0059 } 0060 inline unsigned long numFileItems() const override 0061 { 0062 return _fileItems.count(); 0063 } 0064 inline bool isRoot() const override 0065 { 0066 const QString path = _currentDirectory.path(); 0067 return path.isEmpty() || path == "/"; 0068 } 0069 0070 /// Copy (copy, move or link) files in this filesystem. 0071 /// Destination is absolute URL. May implemented async. 0072 virtual void copyFiles(const QList<QUrl> &urls, 0073 const QUrl &destination, 0074 KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy, 0075 bool showProgressInfo = true, 0076 JobMan::StartMode startMode = JobMan::Default) = 0; 0077 /// Handle file dropping in this filesystem. Destination is absolute URL. May implemented async. 0078 virtual void dropFiles(const QUrl &destination, QDropEvent *event) = 0; 0079 0080 /// Copy (copy, move or link) files to the current filesystem directory or to "dir", the 0081 /// directory name relative to the current dir. May implemented async. 0082 virtual void addFiles(const QList<QUrl> &fileUrls, KIO::CopyJob::CopyMode mode, const QString &dir = "") = 0; 0083 /// Create a new directory in the current directory. May implemented async. 0084 virtual void mkDir(const QString &name) = 0; 0085 /// Rename file/directory in the current directory. May implemented async. 0086 virtual void rename(const QString &fileName, const QString &newName) = 0; 0087 0088 /// Return an absolute URL for a single file/directory name in the current directory - with no 0089 /// trailing slash. 0090 virtual QUrl getUrl(const QString &name) const = 0; 0091 /// Return a list of URLs for multiple files/directories in the current directory. 0092 QList<QUrl> getUrls(const QStringList &names) const; 0093 /// Return true if all files can be moved to trash, else false. 0094 virtual bool canMoveToTrash(const QStringList &fileNames) const = 0; 0095 0096 /// Return the filesystem mount point of the current directory. Empty string by default. 0097 virtual QString mountPoint() const 0098 { 0099 return QString(); 0100 } 0101 /// Returns true if this filesystem implementation does not need to be notified about changes in the 0102 /// current directory. Else false. 0103 virtual bool hasAutoUpdate() const 0104 { 0105 return false; 0106 } 0107 /// Notify this filesystem that the filesystem info of the current directory may have changed. 0108 virtual void updateFilesystemInfo() 0109 { 0110 } 0111 0112 /** 0113 * Scan all files and directories in a directory and create the file items for them. Blocking. 0114 * 0115 * @param directory if given, the lister tries to change to this directory, else the old 0116 * directory is refreshed 0117 * @return true if scan was successful, else (not implemented, scan failed or refresh job 0118 * was killed) false. 0119 */ 0120 bool scanDir(const QUrl &directory = QUrl()) 0121 { 0122 return scanOrRefresh(directory, false); 0123 } 0124 0125 /// Change or refresh the current directory and scan it. Blocking. 0126 /// Returns true if directory was scanned. Returns false if failed or scan job was killed. 0127 bool refresh(const QUrl &directory = QUrl()) 0128 { 0129 return scanOrRefresh(directory, false); 0130 } 0131 0132 /// Returns the current directory path of this filesystem. 0133 inline QUrl currentDirectory() const 0134 { 0135 return _currentDirectory; 0136 } 0137 /// Return the file item for a file name in the current directory. Or 0 if not found. 0138 FileItem *getFileItem(const QString &name) const; 0139 /// The total size of all files in the current directory (only valid after scan). 0140 // TODO unused 0141 KIO::filesize_t totalSize() const; 0142 /// Return the filesystem type. 0143 inline FS_TYPE type() const 0144 { 0145 return _type; 0146 } 0147 /// Return true if the current directory is local (without recognizing mount points). 0148 inline bool isLocal() const 0149 { 0150 return _currentDirectory.isLocalFile(); 0151 } 0152 /// Return true if the current directory is a remote (network) location. 0153 inline bool isRemote() const 0154 { 0155 const QString sc = _currentDirectory.scheme(); 0156 return (sc == "fish" || sc == "ftp" || sc == "sftp" || sc == "nfs" || sc == "smb" || sc == "webdav"); 0157 } 0158 /// Returns true if this filesystem is currently refreshing the current directory. 0159 inline bool isRefreshing() const 0160 { 0161 return _isRefreshing; 0162 } 0163 0164 /// Delete or trash arbitrary files. Implemented async. Universal refresh not fully implemented. 0165 void deleteFiles(const QList<QUrl> &urls, bool moveToTrash); 0166 0167 /// Return the input URL with a trailing slash if absent. 0168 static QUrl ensureTrailingSlash(const QUrl &url); 0169 /// Return the input URL without trailing slash. 0170 static QUrl cleanUrl(const QUrl &url) 0171 { 0172 return url.adjusted(QUrl::StripTrailingSlash); 0173 } 0174 /// Add 'file' scheme to non-empty URL without scheme 0175 static QUrl preferLocalUrl(const QUrl &url); 0176 0177 /// Return a file item for a local file inside a directory 0178 static FileItem *createLocalFileItem(const QString &name, const QString &directory, bool virt = false); 0179 /// Return a file item for a KIO result. Returns 0 if entry is not needed 0180 static FileItem *createFileItemFromKIO(const KIO::UDSEntry &entry, const QUrl &directory, bool virt = false); 0181 0182 /// Read a symlink with an extra precaution 0183 static QString readLinkSafely(const char *path); 0184 0185 /// Set the parent window to be used for dialogs 0186 void setParentWindow(QWidget *widget) 0187 { 0188 parentWindow = widget; 0189 } 0190 0191 signals: 0192 /// Emitted when this filesystem is currently refreshing the filesystem directory. 0193 void refreshJobStarted(KIO::Job *job); 0194 /// Emitted when an error occurred in this filesystem during refresh. 0195 void error(const QString &msg); 0196 /// Emitted when the content of a directory was changed by this filesystem. 0197 void fileSystemChanged(const QUrl &directory, bool removed); 0198 /// Emitted when the information for the filesystem of the current directory changed. 0199 /// Information is either 0200 /// * 'metaInfo': a displayable string about the fs, empty by default, OR 0201 /// * 'fsType', 'total' and 'free': filesystem type, size and free space, 0202 /// empty string or 0 by default 0203 void fileSystemInfoChanged(const QString &metaInfo, const QString &fsType, KIO::filesize_t total, KIO::filesize_t free); 0204 /// Emitted before a directory path is opened for reading. Used for automounting. 0205 void aboutToOpenDir(const QString &path); 0206 0207 protected: 0208 /// Fill the filesystem dictionary with file items, must be implemented for each filesystem. 0209 virtual bool refreshInternal(const QUrl &origin, bool stayInDir) = 0; 0210 0211 /// Connect the result signal of a file operation job - source URLs. 0212 void connectJobToSources(KJob *job, const QList<QUrl> &urls); 0213 /// Connect the result signal of a file operation job - destination URL. 0214 void connectJobToDestination(KJob *job, const QUrl &destination); 0215 /// Returns true if showing hidden files is set in config. 0216 bool showHiddenFiles(); 0217 /// Add a new file item to the internal dictionary (while refreshing). 0218 void addFileItem(FileItem *item); 0219 0220 FS_TYPE _type; // the filesystem type. 0221 QUrl _currentDirectory; // the path or file the filesystem originates from. 0222 bool _isRefreshing; // true if filesystem is busy with refreshing 0223 QPointer<QWidget> parentWindow; 0224 0225 protected slots: 0226 /// Handle result after job (except when refreshing!) finished 0227 void slotJobResult(KJob *job, bool refresh); 0228 0229 private: 0230 typedef QHash<QString, FileItem *> FileItemDict; 0231 0232 // optional TODO: add an async version of this 0233 bool scanOrRefresh(const QUrl &directory, bool onlyScan); 0234 0235 /// Delete and clear file items. 0236 void clear(FileItemDict &fileItems); 0237 0238 FileItemDict _fileItems; // the list of files in the current dictionary 0239 }; 0240 0241 #endif