File indexing completed on 2024-04-21 09:39:28
0001 /*********************************************************************** 0002 * SPDX-FileCopyrightText: 2003-2004 Max Howell <max.howell@methylblue.com> 0003 * SPDX-FileCopyrightText: 2008-2009 Martin Sandsmark <martin.sandsmark@kde.org> 0004 * SPDX-FileCopyrightText: 2017-2022 Harald Sitter <sitter@kde.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 ***********************************************************************/ 0008 0009 #pragma once 0010 0011 #include <cstdlib> 0012 0013 #include <KFormat> 0014 0015 #include <QByteArray> 0016 0017 using FileSize = quint64; 0018 0019 class Folder; 0020 namespace RadialMap 0021 { 0022 class Segment; 0023 } // namespace RadialMap 0024 0025 class File 0026 { 0027 friend class Folder; 0028 0029 public: 0030 File(const char *name, FileSize size) 0031 : m_parent(nullptr) 0032 , m_name(name) 0033 , m_size(size) 0034 { 0035 } 0036 virtual ~File() = default; 0037 File(const File &) = default; 0038 File &operator=(const File &) = default; 0039 File(File &&) = default; 0040 File &operator=(File &&) = default; 0041 0042 QString segment() const 0043 { 0044 return m_segment; 0045 } 0046 0047 void setSegment(const QString &segment) 0048 { 0049 Q_ASSERT(m_segment.isEmpty() || segment.isEmpty()); 0050 m_segment = segment; 0051 } 0052 0053 Folder *parent() const 0054 { 0055 return m_parent; 0056 } 0057 0058 /** Do not use for user visible strings. Use name instead. */ 0059 const char *name8Bit() const 0060 { 0061 return m_name.constData(); 0062 } 0063 void setName(const QByteArray &newName) 0064 { 0065 m_name = newName; 0066 } 0067 /** Decoded name. Use when you need a QString. */ 0068 QString decodedName() const 0069 { 0070 return QString::fromUtf8(m_name); 0071 } 0072 /** 0073 * Human readable name (including native separators where applicable). 0074 * Only use for display. 0075 */ 0076 QString displayName() const; 0077 0078 FileSize size() const 0079 { 0080 return m_size; 0081 } 0082 0083 virtual bool isFolder() const 0084 { 0085 return false; 0086 } 0087 0088 /** 0089 * Human readable path for display (including native separators where applicable. 0090 * Only use for display. 0091 */ 0092 QString displayPath(const std::shared_ptr<Folder> &root = {}) const; 0093 QString humanReadableSize() const 0094 { 0095 return KFormat().formatByteSize(m_size); 0096 } 0097 0098 /** Builds a complete QUrl by walking up to root. */ 0099 QUrl url(const std::shared_ptr<Folder> &root = {}) const; 0100 0101 protected: 0102 File(const char *name, FileSize size, Folder *parent) 0103 : m_parent(parent) 0104 , m_name(name) 0105 , m_size(size) 0106 { 0107 } 0108 0109 Folder *m_parent; // 0 if this is treeRoot; this is a non-owning pointer, the parent owns "us" 0110 QByteArray m_name; // partial path name (e.g. 'boot/' or 'foo.svg') 0111 FileSize m_size; // in units of bytes; sum of all children's sizes 0112 0113 QString m_segment; 0114 }; 0115 0116 class Folder : public File 0117 { 0118 public: 0119 explicit Folder(const char *name) 0120 : File(name, 0) 0121 { 0122 } // DON'T pass the full path! 0123 0124 ~Folder() override; 0125 Folder(const Folder &) = default; 0126 Folder &operator=(const Folder &) = default; 0127 Folder(Folder &&) = default; 0128 Folder &operator=(Folder &&) = default; 0129 0130 uint children() const 0131 { 0132 return m_children; 0133 } 0134 bool isFolder() const override 0135 { 0136 return true; 0137 } 0138 0139 // Separate **static** function so we don't risk using this when we should be using clone.source! 0140 static void clone(const Folder *that, std::shared_ptr<Folder> other); 0141 0142 std::shared_ptr<Folder> duplicate() const; 0143 0144 /// appends a Folder 0145 void append(const std::shared_ptr<Folder> &d, const char *name = nullptr) 0146 { 0147 if (name) { 0148 d->m_name = name; 0149 } // directories that had a fullpath copy just their names this way 0150 0151 m_children += d->children(); // doesn't include the dir itself 0152 Q_ASSERT(d->m_parent == this || d->m_parent == nullptr); 0153 d->m_parent = this; 0154 0155 appendFile(d); // will add 1 to filecount for the dir itself 0156 } 0157 0158 /// appends a File 0159 void append(const char *name, FileSize size) 0160 { 0161 appendFile(std::shared_ptr<File>(new File(name, size, this))); 0162 } 0163 0164 /// removes a file 0165 void remove(const std::shared_ptr<File> &f) 0166 { 0167 files.removeAll(f); 0168 const FileSize childSize = f->size(); 0169 for (Folder *d = this; d; d = d->parent()) { 0170 d->m_size -= childSize; 0171 d->m_children--; 0172 } 0173 } 0174 0175 // Removes a file, but does not delete 0176 std::shared_ptr<Folder> take(const std::shared_ptr<Folder> &f) 0177 { 0178 files.removeAll(f); 0179 const FileSize childSize = f->size(); 0180 for (Folder *d = this; d; d = d->parent()) { 0181 d->m_size -= childSize; 0182 d->m_children--; 0183 } 0184 return f; 0185 } 0186 0187 QList<std::shared_ptr<File>> files; 0188 0189 private: 0190 void appendFile(const std::shared_ptr<File> &p) 0191 { 0192 // This is also called by append(Folder), but only once all its children 0193 // were scanned. We do not need to forward the size change to our parent 0194 // since in turn we too only are added to our parent when we are have 0195 // been scanned already. 0196 m_children++; 0197 m_size += p->size(); 0198 files.append(p); 0199 } 0200 0201 uint m_children = 0; 0202 };