File indexing completed on 2024-05-05 05:50:39

0001 /*
0002     SPDX-FileCopyrightText: 2016 Vladyslav Batyrenko <mvlabat@gmail.com>
0003 
0004     SPDX-License-Identifier: BSD-2-Clause
0005 */
0006 
0007 #include "archiveentry.h"
0008 
0009 #include <QMimeDatabase>
0010 
0011 #include "util.h"
0012 
0013 namespace Kerfuffle
0014 {
0015 Archive::Entry::Entry(QObject *parent, const QString &fullPath, const QString &rootNode)
0016     : QObject(parent)
0017     , rootNode(rootNode)
0018     , compressedSizeIsSet(true)
0019     , m_parent(qobject_cast<Entry *>(parent))
0020     , m_size(0)
0021     , m_compressedSize(0)
0022     , m_sparseSize(0)
0023     , m_isDirectory(false)
0024     , m_isExecutable(false)
0025     , m_isPasswordProtected(false)
0026     , m_isSparse(false)
0027 {
0028     if (!fullPath.isEmpty())
0029         setFullPath(fullPath);
0030 }
0031 
0032 Archive::Entry::~Entry()
0033 {
0034 }
0035 
0036 qulonglong Archive::Entry::size() const
0037 {
0038     return m_size;
0039 }
0040 
0041 qulonglong Archive::Entry::sparseSize() const
0042 {
0043     return m_sparseSize;
0044 }
0045 
0046 bool Archive::Entry::isSparse() const
0047 {
0048     return m_isSparse;
0049 }
0050 
0051 void Archive::Entry::copyMetaData(const Archive::Entry *sourceEntry)
0052 {
0053     setProperty("fullPath", sourceEntry->property("fullPath"));
0054     setProperty("permissions", sourceEntry->property("permissions"));
0055     setProperty("owner", sourceEntry->property("owner"));
0056     setProperty("group", sourceEntry->property("group"));
0057     setProperty("size", sourceEntry->property("size"));
0058     setProperty("compressedSize", sourceEntry->property("compressedSize"));
0059     setProperty("sparseSize", sourceEntry->property("sparseSize"));
0060     setProperty("link", sourceEntry->property("link"));
0061     setProperty("ratio", sourceEntry->property("ratio"));
0062     setProperty("CRC", sourceEntry->property("CRC"));
0063     setProperty("BLAKE2", sourceEntry->property("BLAKE2"));
0064     setProperty("method", sourceEntry->property("method"));
0065     setProperty("version", sourceEntry->property("version"));
0066     setProperty("timestamp", sourceEntry->property("timestamp").toDateTime());
0067     setProperty("isDirectory", sourceEntry->property("isDirectory"));
0068     setProperty("isPasswordProtected", sourceEntry->property("isPasswordProtected"));
0069 }
0070 
0071 QVector<Archive::Entry *> Archive::Entry::entries()
0072 {
0073     Q_ASSERT(isDir());
0074     return m_entries;
0075 }
0076 
0077 const QVector<Archive::Entry *> Archive::Entry::entries() const
0078 {
0079     Q_ASSERT(isDir());
0080     return m_entries;
0081 }
0082 
0083 void Archive::Entry::setEntryAt(int index, Entry *value)
0084 {
0085     Q_ASSERT(isDir());
0086     Q_ASSERT(index < m_entries.count());
0087     m_entries[index] = value;
0088 }
0089 
0090 void Archive::Entry::appendEntry(Entry *entry)
0091 {
0092     Q_ASSERT(isDir());
0093     m_entries.append(entry);
0094 }
0095 
0096 void Archive::Entry::removeEntryAt(int index)
0097 {
0098     Q_ASSERT(isDir());
0099     Q_ASSERT(index < m_entries.count());
0100     m_entries.remove(index);
0101 }
0102 
0103 Archive::Entry *Archive::Entry::getParent() const
0104 {
0105     return m_parent;
0106 }
0107 
0108 void Archive::Entry::setParent(Archive::Entry *parent)
0109 {
0110     m_parent = parent;
0111 }
0112 
0113 void Archive::Entry::setFullPath(const QString &fullPath)
0114 {
0115     m_fullPath = fullPath;
0116 
0117     m_name = Kerfuffle::Util::lastPathSegment(m_fullPath);
0118 }
0119 
0120 QString Archive::Entry::fullPath(PathFormat format) const
0121 {
0122     if (format == NoTrailingSlash && m_fullPath.endsWith(QLatin1Char('/'))) {
0123         return m_fullPath.left(m_fullPath.size() - 1);
0124     } else {
0125         return m_fullPath;
0126     }
0127 }
0128 
0129 QString Archive::Entry::displayName() const
0130 {
0131     if (m_displayName.isEmpty()) {
0132         return m_name;
0133     }
0134 
0135     return m_displayName;
0136 }
0137 
0138 QString Archive::Entry::name() const
0139 {
0140     return m_name;
0141 }
0142 
0143 QStringView Archive::Entry::nameView() const
0144 {
0145     return m_name;
0146 }
0147 
0148 void Archive::Entry::setDisplayName(const QString &displayName)
0149 {
0150     m_displayName = displayName;
0151 }
0152 
0153 void Archive::Entry::setIsDirectory(const bool isDirectory)
0154 {
0155     m_isDirectory = isDirectory;
0156 }
0157 
0158 bool Archive::Entry::isDir() const
0159 {
0160     return m_isDirectory;
0161 }
0162 
0163 void Archive::Entry::setIsExecutable(const bool isExecutable)
0164 {
0165     m_isExecutable = isExecutable;
0166 }
0167 
0168 bool Archive::Entry::isExecutable() const
0169 {
0170     return m_isExecutable;
0171 }
0172 
0173 int Archive::Entry::row() const
0174 {
0175     if (getParent()) {
0176         return getParent()->entries().indexOf(const_cast<Archive::Entry *>(this));
0177     }
0178     return 0;
0179 }
0180 
0181 Archive::Entry *Archive::Entry::find(QStringView name) const
0182 {
0183     for (Entry *entry : std::as_const(m_entries)) {
0184         if (entry && (entry->nameView() == name)) {
0185             return entry;
0186         }
0187     }
0188     return nullptr;
0189 }
0190 
0191 Archive::Entry *Archive::Entry::findByPath(const QStringList &pieces, int index) const
0192 {
0193     if (index == pieces.count()) {
0194         return nullptr;
0195     }
0196 
0197     Entry *next = find(pieces.at(index));
0198     if (index == pieces.count() - 1) {
0199         return next;
0200     }
0201     if (next && next->isDir()) {
0202         return next->findByPath(pieces, index + 1);
0203     }
0204     return nullptr;
0205 }
0206 
0207 void Archive::Entry::countChildren(uint &dirs, uint &files) const
0208 {
0209     dirs = files = 0;
0210     if (!isDir()) {
0211         return;
0212     }
0213 
0214     const auto archiveEntries = entries();
0215     for (auto entry : archiveEntries) {
0216         if (entry->isDir()) {
0217             dirs++;
0218         } else {
0219             files++;
0220         }
0221     }
0222 }
0223 
0224 QIcon Archive::Entry::icon() const
0225 {
0226     if (m_icon.isNull()) {
0227         QMimeDatabase db;
0228 
0229         if (m_isDirectory) {
0230             static QIcon directoryIcon = QIcon::fromTheme(db.mimeTypeForName(QStringLiteral("inode/directory")).iconName());
0231             m_icon = directoryIcon;
0232         } else {
0233             m_icon = QIcon::fromTheme(db.mimeTypeForFile(displayName(), QMimeDatabase::MatchMode::MatchExtension).iconName());
0234         }
0235     }
0236 
0237     return m_icon;
0238 }
0239 
0240 bool Archive::Entry::operator==(const Archive::Entry &right) const
0241 {
0242     return m_fullPath == right.m_fullPath;
0243 }
0244 
0245 QDebug operator<<(QDebug d, const Kerfuffle::Archive::Entry &entry)
0246 {
0247     d.nospace() << "Entry(" << entry.property("fullPath");
0248     if (!entry.rootNode.isEmpty()) {
0249         d.nospace() << "," << entry.rootNode;
0250     }
0251     d.nospace() << ")";
0252     return d.space();
0253 }
0254 
0255 QDebug operator<<(QDebug d, const Kerfuffle::Archive::Entry *entry)
0256 {
0257     d.nospace() << "Entry(" << entry->property("fullPath");
0258     if (!entry->rootNode.isEmpty()) {
0259         d.nospace() << "," << entry->rootNode;
0260     }
0261     d.nospace() << ")";
0262     return d.space();
0263 }
0264 
0265 }
0266 
0267 #include "moc_archiveentry.cpp"