6#include <QtCore/QCollator>
7#include <QtCore/QFileInfo>
8#include <QtCore/QLocale>
15 : QAbstractListModel(parent)
19QGCArchiveModel::~QGCArchiveModel() =
default;
21void QGCArchiveModel::setArchivePath(
const QString &path)
23 if (_archivePath == path) {
33void QGCArchiveModel::setArchiveUrl(
const QUrl &url)
37 qCWarning(QGCArchiveModelLog) <<
"Unsupported archive URL:" << url;
45void QGCArchiveModel::setFilterMode(FilterMode mode)
47 if (_filterMode == mode) {
57int QGCArchiveModel::rowCount(
const QModelIndex &parent)
const
59 if (parent.isValid()) {
62 return static_cast<int>(_filteredEntries.size());
65QVariant QGCArchiveModel::data(
const QModelIndex &index,
int role)
const
67 if (!index.isValid() || index.row() < 0 || index.row() >= _filteredEntries.size()) {
91 const int lastSlash = entry.
name.lastIndexOf(QLatin1Char(
'/'));
92 if (lastSlash >= 0 && lastSlash < entry.
name.size() - 1) {
93 return entry.
name.mid(lastSlash + 1);
99 const int lastSlash = entry.
name.lastIndexOf(QLatin1Char(
'/'));
101 return entry.
name.left(lastSlash);
106 case FormattedSizeRole:
107 return formatSize(entry.
size);
114QHash<int, QByteArray> QGCArchiveModel::roleNames()
const
116 static const QHash<int, QByteArray> roles = {
117 { NameRole,
"name" },
118 { SizeRole,
"size" },
119 { ModifiedRole,
"modified" },
120 { IsDirectoryRole,
"isDirectory" },
121 { PermissionsRole,
"permissions" },
122 { FileNameRole,
"fileName" },
123 { DirectoryRole,
"directory" },
124 { FormattedSizeRole,
"formattedSize" },
129void QGCArchiveModel::refresh()
134void QGCArchiveModel::clear()
136 if (_filteredEntries.isEmpty() && _allEntries.isEmpty()) {
142 _filteredEntries.clear();
145 const bool hadFiles = _fileCount > 0;
146 const bool hadDirs = _directoryCount > 0;
147 const bool hadSize = _totalSize > 0;
158 _setErrorString(QString());
161QVariantMap QGCArchiveModel::get(
int index)
const
165 if (index < 0 || index >= _filteredEntries.size()) {
171 result[QStringLiteral(
"name")] = entry.
name;
172 result[QStringLiteral(
"size")] = entry.
size;
173 result[QStringLiteral(
"modified")] = entry.
modified;
174 result[QStringLiteral(
"isDirectory")] = entry.
isDirectory;
175 result[QStringLiteral(
"permissions")] = entry.
permissions;
176 result[QStringLiteral(
"formattedSize")] = formatSize(entry.
size);
179 const int lastSlash = entry.
name.lastIndexOf(QLatin1Char(
'/'));
180 if (lastSlash >= 0 && lastSlash < entry.
name.size() - 1) {
181 result[QStringLiteral(
"fileName")] = entry.
name.mid(lastSlash + 1);
182 result[QStringLiteral(
"directory")] = entry.
name.left(lastSlash);
184 result[QStringLiteral(
"fileName")] = entry.
name;
185 result[QStringLiteral(
"directory")] = QString();
191bool QGCArchiveModel::contains(
const QString &fileName)
const
193 if (fileName.isEmpty()) {
197 for (
const auto &entry : _allEntries) {
198 if (entry.
name == fileName) {
205QString QGCArchiveModel::formatSize(qint64 bytes)
208 return QStringLiteral(
"--");
211 static const char* units[] = {
"B",
"KB",
"MB",
"GB",
"TB" };
212 constexpr int numUnits =
sizeof(units) /
sizeof(units[0]);
214 double size =
static_cast<double>(bytes);
217 while (size >= 1024.0 && unitIndex < numUnits - 1) {
222 if (unitIndex == 0) {
224 return QStringLiteral(
"%1 %2").arg(bytes).arg(QLatin1String(units[unitIndex]));
228 return QStringLiteral(
"%1 %2")
229 .arg(QLocale().toString(size,
'f', 1))
230 .arg(QLatin1String(units[unitIndex]));
233void QGCArchiveModel::_loadArchive()
237 if (_archivePath.isEmpty()) {
243 _setErrorString(QString());
245 qCDebug(QGCArchiveModelLog) <<
"Loading archive:" << _archivePath;
250 if (entries.isEmpty() && !_archivePath.isEmpty()) {
263 qint64 totalSize = 0;
265 for (
const auto &entry : entries) {
270 totalSize += entry.
size;
275 _allEntries = std::move(entries);
279 const bool dirCountChanged = _directoryCount != dirCount;
280 const bool sizeChanged = _totalSize != totalSize;
282 _fileCount = fileCount;
283 _directoryCount = dirCount;
284 _totalSize = totalSize;
296 qCDebug(QGCArchiveModelLog) <<
"Loaded" << _allEntries.size() <<
"entries:"
297 << _fileCount <<
"files," << _directoryCount <<
"dirs,"
298 << _totalSize <<
"bytes";
303void QGCArchiveModel::_applyFilter()
307 switch (_filterMode) {
309 _filteredEntries = _allEntries;
313 _filteredEntries.clear();
314 for (
const auto &entry : _allEntries) {
316 _filteredEntries.append(entry);
321 case DirectoriesOnly:
322 _filteredEntries.clear();
323 for (
const auto &entry : _allEntries) {
325 _filteredEntries.append(entry);
335void QGCArchiveModel::_setLoading(
bool loading)
337 if (_loading == loading) {
345void QGCArchiveModel::_setErrorString(
const QString &
error)
347 if (_errorString ==
error) {
351 _errorString =
error;
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void directoryCountChanged()
void archivePathChanged()
void errorStringChanged()
void loadingComplete(bool success)
Emitted when archive loading completes (success or failure)
QString lastErrorString()
Get a human-readable error message from the last operation (thread-local)
QList< ArchiveEntry > listArchiveDetailed(const QString &archivePath, Format format)
bool validateArchive(const QString &archivePath, Format format)
bool isLocalPath(const QString &urlOrPath)
QString toLocalPath(const QString &urlOrPath)
Metadata for a single entry in an archive.
bool isDirectory
True if entry is a directory.
qint64 size
Uncompressed size in bytes.
QString name
Path/name within archive.
quint32 permissions
Unix-style permissions.
QDateTime modified
Last modification time.