feat: 新增 DDciFile::copy 接口
使用 DDciFile::dataRef 和 DDciFile:writeFile 的组合能实现复制文件的 效果,但是无法实现目录的复制。因此,特单独添加 DDciFile::copy,以方 便复制文件和目录。 Log: Change-Id: I650e13e45fa94e4ff9b197504025915c20a8c00d
This commit is contained in:
parent
5fb1c1812e
commit
3697593f7c
File diff suppressed because one or more lines are too long
|
|
@ -96,8 +96,10 @@ public:
|
|||
qint64 writeDataForNode(QIODevice *device, Node *node) const;
|
||||
qint64 writeNode(QIODevice *device, Node *node) const;
|
||||
|
||||
Node *mkNode(const QString &filePath, qint8 type);
|
||||
Node *mkNode(const QString &filePath);
|
||||
void removeNode(Node *node);
|
||||
void copyNode(const Node *from, Node *to);
|
||||
|
||||
bool loadDirectory(Node *directory,
|
||||
const QByteArray &data, qint64 &begin, qint64 end,
|
||||
QHash<QString, Node *> &pathToNode);
|
||||
|
|
@ -224,9 +226,9 @@ qint64 DDciFilePrivate::writeNode(QIODevice *device, DDciFilePrivate::Node *node
|
|||
return metaDataSize + dataSize;
|
||||
}
|
||||
|
||||
DDciFilePrivate::Node *DDciFilePrivate::mkNode(const QString &filePath, qint8 type)
|
||||
DDciFilePrivate::Node *DDciFilePrivate::mkNode(const QString &filePath)
|
||||
{
|
||||
qCDebug(logDF, "Request create a node, type is %i", type);
|
||||
qCDebug(logDF, "Request create a node");
|
||||
|
||||
if (pathToNode.contains(filePath)) {
|
||||
setErrorString(QString("The \"%1\" is existed").arg(filePath));
|
||||
|
|
@ -249,7 +251,6 @@ DDciFilePrivate::Node *DDciFilePrivate::mkNode(const QString &filePath, qint8 ty
|
|||
}
|
||||
|
||||
Node *newNode = new Node;
|
||||
newNode->type = type;
|
||||
newNode->name = info.fileName();
|
||||
newNode->parent = parentNode;
|
||||
|
||||
|
|
@ -280,6 +281,32 @@ void DDciFilePrivate::removeNode(DDciFilePrivate::Node *node)
|
|||
delete node;
|
||||
}
|
||||
|
||||
void DDciFilePrivate::copyNode(const DDciFilePrivate::Node *from, DDciFilePrivate::Node *to)
|
||||
{
|
||||
QList<QPair<const Node*, Node*>> copyPendingList;
|
||||
copyPendingList << qMakePair(from, to);
|
||||
|
||||
for (int i = 0; i < copyPendingList.size(); ++i) {
|
||||
auto f = copyPendingList.at(i).first;
|
||||
auto t = copyPendingList.at(i).second;
|
||||
|
||||
t->type = f->type;
|
||||
t->data = f->data;
|
||||
|
||||
for (const auto child : f->children) {
|
||||
if (child == to)
|
||||
continue;
|
||||
|
||||
Node *newChild = new Node;
|
||||
newChild->parent = t;
|
||||
newChild->name = child->name;
|
||||
pathToNode[newChild->path()] = newChild;
|
||||
t->children << newChild;
|
||||
copyPendingList << qMakePair(child, newChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DDciFilePrivate::loadDirectory(DDciFilePrivate::Node *directory,
|
||||
const QByteArray &data, qint64 &offset, qint64 end,
|
||||
QHash<QString, DDciFilePrivate::Node *> &pathToNode)
|
||||
|
|
@ -516,7 +543,11 @@ bool DDciFile::mkdir(const QString &filePath)
|
|||
D_D(DDciFile);
|
||||
|
||||
qCDebug(logDF, "Request create the \"%s\" directory", qPrintable(filePath));
|
||||
return d->mkNode(filePath, FILE_TYPE_DIR);
|
||||
auto node = d->mkNode(filePath);
|
||||
if (!node)
|
||||
return false;
|
||||
node->type = FILE_TYPE_DIR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DDciFile::writeFile(const QString &filePath, const QByteArray &data, bool override)
|
||||
|
|
@ -542,10 +573,11 @@ bool DDciFile::writeFile(const QString &filePath, const QByteArray &data, bool o
|
|||
}
|
||||
}
|
||||
|
||||
auto node = d->mkNode(filePath, FILE_TYPE_FILE);
|
||||
auto node = d->mkNode(filePath);
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
node->type = FILE_TYPE_FILE;
|
||||
node->data = data;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -624,4 +656,23 @@ bool DDciFile::rename(const QString &filePath, const QString &newFilePath, bool
|
|||
}
|
||||
}
|
||||
|
||||
bool DDciFile::copy(const QString &from, const QString &to)
|
||||
{
|
||||
D_D(DDciFile);
|
||||
|
||||
const auto fromNode = d->pathToNode.value(from);
|
||||
if (!fromNode) {
|
||||
d->setErrorString(QString("The \"%1\" is not exists").arg(from));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto toNode = d->mkNode(to);
|
||||
if (!toNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d->copyNode(fromNode, toNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ public:
|
|||
bool writeFile(const QString &filePath, const QByteArray &data, bool override = false);
|
||||
bool remove(const QString &filePath);
|
||||
bool rename(const QString &filePath, const QString &newFilePath, bool override = false);
|
||||
bool copy(const QString &from, const QString &to);
|
||||
};
|
||||
|
||||
DCORE_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -294,14 +294,12 @@ bool DDciFileEngine::copy(const QString &newName)
|
|||
{
|
||||
if (!file->isValid())
|
||||
return false;
|
||||
if (file->type(subfilePath) != DDciFile::File)
|
||||
return false;
|
||||
// 解析出新的 dci 内部文件路径
|
||||
const auto paths = resolvePath(newName, dciFilePath);
|
||||
if (paths.second.isEmpty())
|
||||
return false;
|
||||
|
||||
return file->writeFile(paths.second, file->dataRef(subfilePath)) && forceSave();
|
||||
return file->copy(subfilePath, paths.second) && forceSave();
|
||||
}
|
||||
|
||||
bool DDciFileEngine::rename(const QString &newName)
|
||||
|
|
|
|||
|
|
@ -148,6 +148,25 @@ TEST_F(ut_DCI, DDciFile) {
|
|||
ASSERT_EQ(dciFile.childrenCount("/"), 0);
|
||||
ASSERT_EQ(dciFile.toData(), QByteArrayLiteral("DCI\0\1\0\0\0"));
|
||||
}
|
||||
|
||||
// DDciFile::copy
|
||||
{
|
||||
DDciFile dciFile;
|
||||
// 文件复制
|
||||
ASSERT_TRUE(dciFile.writeFile("/test.txt", "test"));
|
||||
ASSERT_TRUE(dciFile.copy("/test.txt", "/test.txt.new"));
|
||||
ASSERT_TRUE(dciFile.exists("/test.txt.new"));
|
||||
ASSERT_EQ(dciFile.list("/", true), (QStringList{"test.txt", "test.txt.new"}));
|
||||
ASSERT_EQ(dciFile.dataRef("/test.txt"), dciFile.dataRef("/test.txt.new"));
|
||||
|
||||
// 目录复制
|
||||
ASSERT_TRUE(dciFile.mkdir("/test"));
|
||||
ASSERT_TRUE(dciFile.rename("/test.txt", "/test/test.txt"));
|
||||
ASSERT_TRUE(dciFile.copy("/test", "/test.new"));
|
||||
ASSERT_TRUE(dciFile.exists("/test.new/test.txt"));
|
||||
ASSERT_EQ(dciFile.list("/test.new", true), (QStringList{"test.txt"}));
|
||||
ASSERT_EQ(dciFile.dataRef("/test/test.txt"), dciFile.dataRef("/test.new/test.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
class TestDCIFileHelper {
|
||||
|
|
@ -282,13 +301,17 @@ TEST_F(ut_DCI, DFileEngine) {
|
|||
// 复制
|
||||
ASSERT_TRUE(QFile::copy(helper.dciFormatFilePath("/1.new/test.txt"),
|
||||
helper.dciFormatFilePath("/test.txt")));
|
||||
// 目录禁止复制
|
||||
ASSERT_FALSE(QFile::copy(helper.dciFormatFilePath("/3"),
|
||||
helper.dciFormatFilePath("/3.new")));
|
||||
// [/1.new, /1.new/test.txt, /2.new, /3, /test.txt]
|
||||
// 复制目录
|
||||
ASSERT_TRUE(QFile::copy(helper.dciFormatFilePath("/1.new"),
|
||||
helper.dciFormatFilePath("/1")));
|
||||
ASSERT_EQ(QDir(helper.dciFormatFilePath("/1")).entryList(),
|
||||
QDir(helper.dciFormatFilePath("/1.new")).entryList());
|
||||
// [/1.new, /1.new/test.txt, /2.new, /3, /test.txt, "/1"]
|
||||
|
||||
// 目录遍历
|
||||
QStringList list {
|
||||
helper.dciFormatFilePath("/1"),
|
||||
helper.dciFormatFilePath("/1/test.txt"),
|
||||
helper.dciFormatFilePath("/1.new"),
|
||||
helper.dciFormatFilePath("/1.new/test.txt"),
|
||||
helper.dciFormatFilePath("/2.new"),
|
||||
|
|
@ -308,6 +331,6 @@ TEST_F(ut_DCI, DFileEngine) {
|
|||
ASSERT_TRUE(QFile::remove(helper.dciFormatFilePath("/1.new")));
|
||||
// [/3]
|
||||
ASSERT_EQ(QDir(helper.dciFormatFilePath()).entryList(),
|
||||
QStringList {"3"});
|
||||
(QStringList {"1", "3"}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue