Skip to content

Commit

Permalink
[nemo-filemanager] Add extected and extrected target path roles. Cont…
Browse files Browse the repository at this point in the history
…ributes to JB#36842

These roles do not apply yet nicely when extracting the whole archive.
Problem there is mapping of extration status when using multiple
ArchiveModel to form the archive file system hierarchy.

That being said considered these roles bit more experimental.
  • Loading branch information
rainemak committed Mar 13, 2018
1 parent acbc9a3 commit c6fc066
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 13 deletions.
83 changes: 71 additions & 12 deletions src/plugin/archivemodel.cpp
Expand Up @@ -71,6 +71,8 @@ enum {
CreatedRole,
IsDirRole,
IsLinkRole,
ExtractedRole,
ExtractedTargetPathRole,
SymLinkTargetRole,
IsSelectedRole,
ExtensionRole,
Expand Down Expand Up @@ -239,7 +241,7 @@ void ArchiveModelPrivate::scheduleExtract(const QString &entryName, const QStrin
connect(extractionWatcher, &QFutureWatcher<FileExtractionResult>::finished, this, [this, mode]() {
FileExtractionResult result = extractionWatcher->result();
ArchiveModel::ErrorState state = result.first;
QString entry = result.second;
ExtractionInfo extractionInfo = result.second;

if (state == ArchiveModel::NoError) {
setStatus(ArchiveModel::Ready, state);
Expand All @@ -251,33 +253,49 @@ void ArchiveModelPrivate::scheduleExtract(const QString &entryName, const QStrin
emit q->extractingChanged();

if (state == ArchiveModel::NoError) {
QFileInfo entryInfo(entry);
QString absolutePath = extractionInfo.absolutePath;
QFileInfo entryInfo(absolutePath);
bool isDir = entryInfo.isDir();
QStringList entries;
QStringList extractedFiles;
if (mode == ExtractionMode::SingleFile && !isDir) {
entries << entry;
extractedFiles << absolutePath;
} else {
QDir d(entry, QString(), QDir::Name | QDir::DirsFirst, QDir::NoDotAndDotDot | QDir::AllEntries);
QDir d(absolutePath, QString(), QDir::Name | QDir::DirsFirst, QDir::NoDotAndDotDot | QDir::AllEntries);
QDirIterator dirIterator(d, QDirIterator::Subdirectories);
while (dirIterator.hasNext()) {
QString f = dirIterator.next();
entries << f;
extractedFiles << f;
}
}

QDir entryDir(entry);
QDir entryDir(absolutePath);
QString name;
if (entries.count() == 1) {
entryInfo.setFile(entries.at(0));
if (extractedFiles.count() == 1) {
entryInfo.setFile(extractedFiles.at(0));
name = entryInfo.fileName();
} else {
name = entryDir.dirName();
}

if (mode == ExtractionMode::SingleFile) {
int i = findIndex(extractionInfo.entry);
if (i >= 0) {
if (!extractedEntries.contains(extractionInfo.entry)) {
extractedEntries.insert(extractionInfo.entry, extractionInfo);
QModelIndex index = q->index(i, 0);
emit q->dataChanged(index, index, QVector<int>() << ExtractedRole << ExtractedTargetPathRole);
} else {
qCWarning(lcArchiveLog) << extractionInfo.entry << "is already extracted.";
}
} else {
qCWarning(lcArchiveLog) << extractionInfo.entry << "is not part of this archive directory. Source of bug!";
}
}

// When extracting an archive entryInfo is a directory. Thus, checking that we're extracting a single file
// from an archive that is a directory.
emit q->filesExtracted(entryDir.absolutePath(), (mode == ExtractionMode::SingleFile && entryInfo.isDir()),
name, entries);
name, extractedFiles);
}
extractionWatcher->deleteLater();
extractionWatcher = nullptr;
Expand All @@ -300,6 +318,15 @@ void ArchiveModelPrivate::scheduleExtract(const QString &entryName, const QStrin
}
}

int ArchiveModelPrivate::findIndex(const QString &entryName)
{
for (int i = 0; i < entryList.count(); ++i) {
if (entryList.at(i)->name() == entryName)
return i;
}
return -1;
}

FileExtractionResult ArchiveModelPrivate::doExtractFile(const QString &entryName, const QString &targetPath)
{
QMutexLocker lock(&extractionMutex);
Expand Down Expand Up @@ -329,7 +356,7 @@ FileExtractionResult ArchiveModelPrivate::doExtractFile(const QString &entryName

if (extracted) {
result.first = ArchiveModel::NoError;
result.second = out;
result.second = ExtractionInfo(entryName, out);
} else {
result.first = ArchiveModel::ErrorArchiveExtractFailed;
}
Expand All @@ -352,7 +379,7 @@ FileExtractionResult ArchiveModelPrivate::doExtractAllFiles(const QString &targe
QString out;
if (dir->copyTo(targetPath, true, true, &out)) {
result.first = ArchiveModel::NoError;
result.second = out;
result.second = ExtractionInfo("", out);
qCDebug(lcArchiveLog) << "Extracted archive to:" << out;
} else {
result.first = ArchiveModel::ErrorArchiveExtractFailed;
Expand Down Expand Up @@ -420,6 +447,16 @@ QVariant ArchiveModel::data(const QModelIndex &index, int role) const
}
return 0;

case ExtractedRole:
return d->extractedEntries.contains(entry->name());

case ExtractedTargetPathRole:
if (d->extractedEntries.contains(entry->name())) {
const ExtractionInfo &extrationInfo = d->extractedEntries.value(entry->name());
return extrationInfo.absolutePath;
}
return QString();

case CreatedRole:
return entry->date();

Expand Down Expand Up @@ -461,6 +498,8 @@ QHash<int, QByteArray> ArchiveModel::roleNames() const
roles.insert(MimeTypeRole, QByteArray("mimeType"));
roles.insert(SizeRole, QByteArray("size"));
roles.insert(CreatedRole, QByteArray("created"));
roles.insert(ExtractedRole, QByteArray("extracted"));
roles.insert(ExtractedTargetPathRole, QByteArray("extractedTargetPath"));
roles.insert(IsDirRole, QByteArray("isDir"));
roles.insert(IsLinkRole, QByteArray("isLink"));
roles.insert(SymLinkTargetRole, QByteArray("symLinkTarget"));
Expand Down Expand Up @@ -680,4 +719,24 @@ bool ArchiveModel::extractFile(const QString &entryName, const QString &targetPa
return true;
}

bool ArchiveModel::cleanExtractedEntry(const QString &entry)
{
if (d->extracting) {
qmlInfo(this) << "Extracting, wait for extraction to complete.";
d->setStatus(Extracting, ErrorExtractingInProgress);
return false;
}

int entryIndex = d->findIndex(entry);
if (d->extractedEntries.contains(entry) && entryIndex >= 0) {
d->extractedEntries.remove(entry);
QModelIndex index = this->index(entryIndex, 0);
emit dataChanged(index, index, QVector<int>() << ExtractedRole << ExtractedTargetPathRole);
} else {
qmlInfo(this) << "Entry:" << entry << "is not extracted.";
}

return true;
}

}
3 changes: 3 additions & 0 deletions src/plugin/archivemodel.h
Expand Up @@ -116,6 +116,9 @@ class ArchiveModel : public QAbstractListModel
Q_INVOKABLE bool extractAllFiles(const QString &targetPath);
Q_INVOKABLE bool extractFile(const QString &entryName, const QString &targetPath);

// If component user deletes the file from outside, clean state for the extracted.
Q_INVOKABLE bool cleanExtractedEntry(const QString &entry);

signals:
void pathChanged();
void statusChanged();
Expand Down
19 changes: 18 additions & 1 deletion src/plugin/archivemodel_p.h
Expand Up @@ -50,7 +50,21 @@ enum ExtractionMode {
// There could be selected files
};

typedef QPair<ArchiveModel::ErrorState, QString> FileExtractionResult;
struct ExtractionInfo
{
ExtractionInfo() {}

ExtractionInfo(QString entry, QString absolutePath)
: entry(entry)
, absolutePath(absolutePath)
{
}

QString entry;
QString absolutePath;
};

typedef QPair<ArchiveModel::ErrorState, ExtractionInfo> FileExtractionResult;

class ArchiveModelPrivate : public QObject
{
Expand All @@ -67,9 +81,12 @@ class ArchiveModelPrivate : public QObject

void scheduleExtract(const QString &entryName, const QString &targetPath, ExtractionMode mode);

int findIndex(const QString &entryName);

ArchiveModel *q;
ArchiveModel::Status status;
ArchiveModel::ErrorState errorState;
QMap<QString, ExtractionInfo> extractedEntries;
qint64 requiredSpace;
QString path;
QString errorString;
Expand Down

0 comments on commit c6fc066

Please sign in to comment.