Commit a530116b authored by Vladyslav Batyrenko's avatar Vladyslav Batyrenko
Browse files

[GSoC] Refactor ArchiveNode and ArchiveDirNode classes

Refactor ArchiveNode and ArchiveDirNode classes to Archive::Entry class
and move its declaration to kerfuffle/archiveentry.h file.

Make Archive::Entry store meta data in Q_PROPERTY members.

Move EntryMetaDataType to part/archivemodel.cpp.

Delete duplicated directory entries while reading from 7z archives.

See:
https://phabricator.kde.org/T2704
parent 88ad5a0e
[
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fileName": "aDir/b.txt"
},
{
"FileName": "aDir/aDirInside/",
"IsDirectory": true
"fileName": "aDir/aDirInside/",
"isDirectory": true
},
{
"FileName": "aDir/aDirInside/anotherDir/",
"IsDirectory": true
"fileName": "aDir/aDirInside/anotherDir/",
"isDirectory": true
},
{
"FileName": "aDir/aDirInside/anotherDir/file.txt"
"fileName": "aDir/aDirInside/anotherDir/file.txt"
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fileName": "aDir/b.txt"
},
{
"FileName": "anotherDir/",
"IsDirectory": true
"fileName": "anotherDir/",
"isDirectory": true
},
{
"FileName": "anotherDir/file.txt"
"fileName": "anotherDir/file.txt"
}
]
[
{
"FileName": "a.txt"
"fileName": "a.txt"
},
{
"FileName": "file.txt"
"fileName": "file.txt"
}
]
[
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fileName": "aDir/b.txt"
}
]
[
{
"FileName": "foo.txt",
"IsPasswordProtected": true
"fileName": "foo.txt",
"isPasswordProtected": true
},
{
"FileName": "bar.txt"
"fileName": "bar.txt"
},
{
"FileName": "aDirectory/",
"IsDirectory": true
"fileName": "aDirectory/",
"isDirectory": true
}
]
[
{
"FileName": "a.txt"
"fileName": "a.txt"
}
]
\ No newline at end of file
[
{
"FileName": "aDir/anotherDir/bar.txt"
"fileName": "aDir/anotherDir/bar.txt"
},
{
"FileName": "aDir/foo.txt"
"fileName": "aDir/foo.txt"
},
{
"FileName": "aDir/anotherDir/",
"IsDirectory": true
"fileName": "aDir/anotherDir/",
"isDirectory": true
},
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
}
]
[
{
"FileName": "a.txt"
"fileName": "a.txt"
},
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt"
"fileName": "aDir/b.txt"
},
{
"FileName": "c.txt"
"fileName": "c.txt"
}
]
[
{
"FileName": "a.txt",
"Size": 5
"fileName": "a.txt",
"size": 5
},
{
"FileName": "aDir/",
"IsDirectory": true
"fileName": "aDir/",
"isDirectory": true
},
{
"FileName": "aDir/b.txt",
"Size": 954
"fileName": "aDir/b.txt",
"size": 954
},
{
"FileName": "c.txt",
"Size": 45000
"fileName": "c.txt",
"size": 45000
}
]
......@@ -26,6 +26,7 @@
#include "jsonarchiveinterface.h"
#include "kerfuffle/jobs.h"
#include "kerfuffle/archiveentry.h"
#include <QDebug>
#include <QEventLoop>
......@@ -42,7 +43,7 @@ public:
protected Q_SLOTS:
void init();
void slotNewEntry(const ArchiveEntry& entry);
void slotNewEntry(Archive::Entry *entry);
private Q_SLOTS:
// ListJob-related tests
......@@ -63,10 +64,10 @@ private Q_SLOTS:
private:
JSONArchiveInterface *createArchiveInterface(const QString& filePath);
QList<ArchiveEntry> listEntries(JSONArchiveInterface *iface);
QList<Archive::Entry*> listEntries(JSONArchiveInterface *iface);
void startAndWaitForResult(KJob *job);
QList<ArchiveEntry> m_entries;
QList<Archive::Entry*> m_entries;
QEventLoop m_eventLoop;
};
......@@ -76,7 +77,6 @@ JobsTest::JobsTest()
: QObject(Q_NULLPTR)
, m_eventLoop(this)
{
qRegisterMetaType<ArchiveEntry>("ArchiveEntry");
}
void JobsTest::init()
......@@ -84,7 +84,7 @@ void JobsTest::init()
m_entries.clear();
}
void JobsTest::slotNewEntry(const ArchiveEntry& entry)
void JobsTest::slotNewEntry(Archive::Entry *entry)
{
m_entries.append(entry);
}
......@@ -100,7 +100,7 @@ JSONArchiveInterface *JobsTest::createArchiveInterface(const QString& filePath)
return iface;
}
QList<ArchiveEntry> JobsTest::listEntries(JSONArchiveInterface *iface)
QList<Archive::Entry*> JobsTest::listEntries(JSONArchiveInterface *iface)
{
m_entries.clear();
......@@ -209,7 +209,7 @@ void JobsTest::testListJob()
QCOMPARE(archiveEntries.size(), expectedEntryNames.size());
for (int i = 0; i < archiveEntries.size(); i++) {
QCOMPARE(archiveEntries.at(i)[FileName].toString(), expectedEntryNames.at(i));
QCOMPARE(archiveEntries.at(i)->property("fileName").toString(), expectedEntryNames.at(i));
}
listJob->deleteLater();
......@@ -310,7 +310,7 @@ void JobsTest::testRemoveEntries()
QCOMPARE(remainingEntries.size(), expectedRemainingEntries.size());
for (int i = 0; i < remainingEntries.size(); i++) {
QCOMPARE(remainingEntries.at(i)[FileName].toString(), expectedRemainingEntries.at(i));
QCOMPARE(remainingEntries.at(i)->property("fileName").toString(), expectedRemainingEntries.at(i));
}
iface->deleteLater();
......
......@@ -26,6 +26,7 @@
#include "jsonarchiveinterface.h"
#include <qfile.h>
#include "kerfuffle/archiveentry.h"
JSONArchiveInterface::JSONArchiveInterface(QObject *parent, const QVariantList& args)
: Kerfuffle::ReadWriteArchiveInterface(parent, args)
......@@ -72,8 +73,8 @@ bool JSONArchiveInterface::addFiles(const QStringList& files, const Kerfuffle::C
return false;
}
Kerfuffle::ArchiveEntry e;
e[Kerfuffle::FileName] = file;
Kerfuffle::Archive::Entry *e = new Kerfuffle::Archive::Entry(NULL);
e->setProperty("fileName", file);
m_archive[file] = e;
}
......
......@@ -25,41 +25,12 @@
#include "jsonparser.h"
#include "kerfuffle/archiveinterface.h"
#include "kerfuffle/archiveentry.h"
#include <QDebug>
#include <QJsonDocument>
#include <QLatin1String>
typedef QMap<QString, Kerfuffle::EntryMetaDataType> ArchiveProperties;
static ArchiveProperties archiveProperties()
{
static ArchiveProperties properties;
if (!properties.isEmpty()) {
return properties;
}
properties[QStringLiteral("FileName")] = Kerfuffle::FileName;
properties[QStringLiteral("InternalID")] = Kerfuffle::InternalID;
properties[QStringLiteral("Permissions")] = Kerfuffle::Permissions;
properties[QStringLiteral("Owner")] = Kerfuffle::Owner;
properties[QStringLiteral("Group")] = Kerfuffle::Group;
properties[QStringLiteral("Size")] = Kerfuffle::Size;
properties[QStringLiteral("CompressedSize")] = Kerfuffle::CompressedSize;
properties[QStringLiteral("Link")] = Kerfuffle::Link;
properties[QStringLiteral("Ratio")] = Kerfuffle::Ratio;
properties[QStringLiteral("CRC")] = Kerfuffle::CRC;
properties[QStringLiteral("Method")] = Kerfuffle::Method;
properties[QStringLiteral("Version")] = Kerfuffle::Version;
properties[QStringLiteral("Timestamp")] = Kerfuffle::Timestamp;
properties[QStringLiteral("IsDirectory")] = Kerfuffle::IsDirectory;
properties[QStringLiteral("Comment")] = Kerfuffle::Comment;
properties[QStringLiteral("IsPasswordProtected")] = Kerfuffle::IsPasswordProtected;
return properties;
}
JSONParser::JSONParser()
{
}
......@@ -83,30 +54,29 @@ JSONParser::JSONArchive JSONParser::parse(QIODevice *json)
JSONParser::JSONArchive JSONParser::createJSONArchive(const QVariant &json)
{
static const ArchiveProperties properties = archiveProperties();
JSONParser::JSONArchive archive;
foreach (const QVariant &entry, json.toList()) {
const QVariantMap entryMap = entry.toMap();
if (!entryMap.contains(QStringLiteral("FileName"))) {
if (!entryMap.contains(QStringLiteral("fileName"))) {
continue;
}
Kerfuffle::ArchiveEntry archiveEntry;
Kerfuffle::Archive::Entry *e = new Kerfuffle::Archive::Entry(Q_NULLPTR);
QVariantMap::const_iterator entryIterator = entryMap.constBegin();
for (; entryIterator != entryMap.constEnd(); ++entryIterator) {
if (properties.contains(entryIterator.key())) {
archiveEntry[properties[entryIterator.key()]] = entryIterator.value();
const char *key = entryIterator.key().toStdString().c_str();
if (e->property(key).isValid()) {
e->setProperty(key, entryIterator.value());
} else {
qDebug() << entryIterator.key() << "is not a valid entry key";
}
}
const QString fileName = entryMap[QStringLiteral("FileName")].toString();
archive[fileName] = archiveEntry;
const QString fileName = entryMap[QStringLiteral("fileName")].toString();
archive[fileName] = e;
}
return archive;
......
......@@ -55,7 +55,7 @@
class JSONParser
{
public:
typedef QMap<QString, Kerfuffle::ArchiveEntry> JSONArchive;
typedef QMap<QString, Kerfuffle::Archive::Entry*> JSONArchive;
~JSONParser();
......
......@@ -38,8 +38,6 @@ using namespace Kerfuffle;
void Cli7zTest::initTestCase()
{
qRegisterMetaType<ArchiveEntry>();
m_plugin = new Plugin(this);
foreach (Plugin *plugin, m_pluginManger.availablePlugins()) {
if (plugin->metaData().pluginId() == QStringLiteral("kerfuffle_cli7z")) {
......@@ -161,22 +159,22 @@ void Cli7zTest::testList()
QFETCH(int, someEntryIndex);
QVERIFY(someEntryIndex < signalSpy.count());
ArchiveEntry entry = qvariant_cast<ArchiveEntry>(signalSpy.at(someEntryIndex).at(0));
Archive::Entry *entry = signalSpy.at(someEntryIndex).at(0).value<Archive::Entry *>();
QFETCH(QString, expectedName);
QCOMPARE(entry[FileName].toString(), expectedName);
QCOMPARE(entry->property("fileName").toString(), expectedName);
QFETCH(bool, isDirectory);
QCOMPARE(entry[IsDirectory].toBool(), isDirectory);
QCOMPARE(entry->isDir(), isDirectory);
QFETCH(bool, isPasswordProtected);
QCOMPARE(entry[IsPasswordProtected].toBool(), isPasswordProtected);
QCOMPARE(entry->property("isPasswordProtected").toBool(), isPasswordProtected);
QFETCH(qulonglong, expectedSize);
QCOMPARE(entry[Size].toULongLong(), expectedSize);
QCOMPARE(entry->property("size").toULongLong(), expectedSize);
QFETCH(QString, expectedTimestamp);
QCOMPARE(entry[Timestamp].toString(), expectedTimestamp);
QCOMPARE(entry->property("timestamp").toString(), expectedTimestamp);
plugin->deleteLater();
}
......
......@@ -53,6 +53,4 @@ private:
Plugin *m_plugin;
};
Q_DECLARE_METATYPE(ArchiveEntry)
#endif
......@@ -25,6 +25,7 @@
*/
#include "clirartest.h"
#include "kerfuffle/archiveentry.h"
#include <QFile>
#include <QSignalSpy>
......@@ -39,8 +40,6 @@ using namespace Kerfuffle;
void CliRarTest::initTestCase()
{
qRegisterMetaType<ArchiveEntry>();
m_plugin = new Plugin(this);
foreach (Plugin *plugin, m_pluginManger.availablePlugins()) {
if (plugin->metaData().pluginId() == QStringLiteral("kerfuffle_clirar")) {
......@@ -189,28 +188,28 @@ void CliRarTest::testList()
QFETCH(int, someEntryIndex);
QVERIFY(someEntryIndex < signalSpy.count());
ArchiveEntry entry = qvariant_cast<ArchiveEntry>(signalSpy.at(someEntryIndex).at(0));
Archive::Entry *entry = signalSpy.at(someEntryIndex).at(0).value<Archive::Entry *>();
QFETCH(QString, expectedName);
QCOMPARE(entry[FileName].toString(), expectedName);
QCOMPARE(entry->property("fileName").toString(), expectedName);
QFETCH(bool, isDirectory);
QCOMPARE(entry[IsDirectory].toBool(), isDirectory);
QCOMPARE(entry->isDir(), isDirectory);
QFETCH(bool, isPasswordProtected);
QCOMPARE(entry[IsPasswordProtected].toBool(), isPasswordProtected);
QCOMPARE(entry->property("isPasswordProtected").toBool(), isPasswordProtected);
QFETCH(QString, symlinkTarget);
QCOMPARE(entry[Link].toString(), symlinkTarget);
QCOMPARE(entry->property("link").toString(), symlinkTarget);
QFETCH(qulonglong, expectedSize);
QCOMPARE(entry[Size].toULongLong(), expectedSize);
QCOMPARE(entry->property("size").toULongLong(), expectedSize);
QFETCH(qulonglong, expectedCompressedSize);
QCOMPARE(entry[CompressedSize].toULongLong(), expectedCompressedSize);
QCOMPARE(entry->property("compressedSize").toULongLong(), expectedCompressedSize);
QFETCH(QString, expectedTimestamp);
QCOMPARE(entry[Timestamp].toString(), expectedTimestamp);
QCOMPARE(entry->property("timestamp").toString(), expectedTimestamp);
rarPlugin->deleteLater();
}
......
......@@ -54,6 +54,4 @@ private:
Plugin *m_plugin;
};
Q_DECLARE_METATYPE(ArchiveEntry)
#endif
......@@ -19,6 +19,7 @@
#include "cliunarchivertest.h"
#include "jobs.h"
#include "kerfuffle/archiveentry.h"
#include <QDirIterator>
#include <QFile>
......@@ -34,8 +35,6 @@ using namespace Kerfuffle;
void CliUnarchiverTest::initTestCase()
{
qRegisterMetaType<ArchiveEntry>();
m_plugin = new Plugin(this);
foreach (Plugin *plugin, m_pluginManger.availablePlugins()) {
if (plugin->metaData().pluginId() == QStringLiteral("kerfuffle_cliunarchiver")) {
......@@ -153,25 +152,25 @@ void CliUnarchiverTest::testList()
QFETCH(int, someEntryIndex);
QVERIFY(someEntryIndex < signalSpy.count());
ArchiveEntry entry = qvariant_cast<ArchiveEntry>(signalSpy.at(someEntryIndex).at(0));
Archive::Entry *entry = signalSpy.at(someEntryIndex).at(0).value<Archive::Entry *>();
QFETCH(QString, expectedName);
QCOMPARE(entry[FileName].toString(), expectedName);
QCOMPARE(entry->property("fileName").toString(), expectedName);
QFETCH(bool, isDirectory);
QCOMPARE(entry[IsDirectory].toBool(), isDirectory);
QCOMPARE(entry->isDir(), isDirectory);
QFETCH(bool, isPasswordProtected);
QCOMPARE(entry[IsPasswordProtected].toBool(), isPasswordProtected);
QCOMPARE(entry->property("isPasswordProtected").toBool(), isPasswordProtected);
QFETCH(qulonglong, expectedSize);
QCOMPARE(entry[Size].toULongLong(), expectedSize);
QCOMPARE(entry->property("size").toULongLong(), expectedSize);
QFETCH(qulonglong, expectedCompressedSize);
QCOMPARE(entry[CompressedSize].toULongLong(), expectedCompressedSize);
QCOMPARE(entry->property("compressedSize").toULongLong(), expectedCompressedSize);
QFETCH(QString, expectedTimestamp);
QCOMPARE(entry[Timestamp].toString(), expectedTimestamp);
QCOMPARE(entry->property("timestamp").toString(), expectedTimestamp);
unarPlugin->deleteLater();
}
......
......@@ -49,6 +49,4 @@ private:
Plugin *m_plugin;
};
Q_DECLARE_METATYPE(ArchiveEntry)
#endif
......@@ -17,6 +17,8 @@ set(kerfuffle_SRCS
mimetypes.cpp
plugin.cpp
pluginmanager.cpp
archiveentry.cpp
archiveentry.h
)
kconfig_add_kcfg_files(kerfuffle_SRCS settings.kcfgc)
......
......@@ -26,6 +26,7 @@
*/
#include "archive_kerfuffle.h"
#include "archiveentry.h"
#include "ark_debug.h"
#include "archiveinterface.h"
#include "jobs.h"
......@@ -60,8 +61,6 @@ Archive *Archive::create(const QString &fileName, const QString &fixedMimeType,
{
qCDebug(ARK) << "Going to create archive" << fileName;
qRegisterMetaType<ArchiveEntry>("ArchiveEntry");
PluginManager pluginManager;
const QMimeType mimeType = fixedMimeType.isEmpty() ? determineMimeType(fileName) : QMimeDatabase().mimeTypeForName(fixedMimeType);
......@@ -271,9 +270,9 @@ QString Archive::subfolderName()
return m_subfolderName;
}
void Archive::onNewEntry(const ArchiveEntry &entry)
void Archive::onNewEntry(const Archive::Entry *entry)
{
if (!entry[IsDirectory].toBool()) {
if (!entry->isDir()) {
m_numberOfFiles++;
}
}
......
......@@ -54,44 +54,12 @@ class PreviewJob;
class Query;
class ReadOnlyArchiveInterface;
/**
* Meta data related to one entry in a compressed archive.
*
* When creating a plugin, information about every single entry in
* an archive is contained in an ArchiveEntry, and metadata
* is set with the entries in this enum.
*
* Please notice that not all archive formats support all the properties
* below, so