Skip to content

Commit 271e6b5

Browse files
committed
Add tree level extra path to linking
1 parent d70caba commit 271e6b5

File tree

9 files changed

+327
-216
lines changed

9 files changed

+327
-216
lines changed

.cppcheck-addons/misra.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"script": "misra.py",
3-
"args": ["--rule-texts=.cppcheck-addons/misra_rules.txt --suppress-rules 8.2,2.7,7.4"]
3+
"args": ["--rule-texts=.cppcheck-addons/misra_rules.txt --suppress-rules 8.2,2.7,7.4,15.4"]
44
}

src/Data.hpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,15 @@ struct FileList {
3737
* Except for `TombEngine (TEN)` I made that one up.
3838
*/
3939
struct FolderNames {
40-
const QString TR1 = "/Tomb Raider (I)";
41-
const QString TR2 = "/Tomb Raider (II)";
42-
const QString TR3 = "/TombRaider (III)";
43-
const QString TR4 = "/Tomb Raider (IV) The Last Revelation";
44-
const QString TR5 = "/Tomb Raider (V) Chronicles";
45-
const QString TEN = "TombEngine (TEN)";
40+
QMap<int, QString> data = {
41+
{0, "null"},
42+
{1, "Tomb Raider (I)"},
43+
{2, "Tomb Raider (II)"},
44+
{3, "TombRaider (III)"},
45+
{4, "Tomb Raider (IV) The Last Revelation"},
46+
{5, "Tomb Raider (V) Chronicles"},
47+
{6, "TombEngine (TEN)"},
48+
};
4649
};
4750

4851
struct ZipData {

src/FileManager.cpp

Lines changed: 100 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,89 @@
2424
#include "miniz.h"
2525
#include "miniz_zip.h"
2626

27+
struct StaticTrees {
28+
QList<GameFileTree*> data;
29+
StaticTrees() {
30+
data.append(new GameFileTree(QStringList{
31+
"TOMBRAID/tomb.exe",
32+
"dosbox.exe",
33+
}));
34+
data.append(new GameFileTree(QStringList{
35+
"Tomb1Main.exe",
36+
"cfg",
37+
"data",
38+
"shaders",
39+
}));
40+
data.append(new GameFileTree(QStringList{
41+
"TR1X.exe",
42+
"cfg",
43+
"data",
44+
"shaders",
45+
}));
46+
data.append(new GameFileTree(QStringList{
47+
"TR2Main.json",
48+
"data",
49+
}));
50+
data.append(new GameFileTree(QStringList{
51+
"Tomb2.exe",
52+
"data",
53+
}));
54+
data.append(new GameFileTree(QStringList{
55+
"tomb3_ConfigTool.json",
56+
"tomb3.exe",
57+
"audio",
58+
"data",
59+
"pix",
60+
}));
61+
data.append(new GameFileTree(QStringList{
62+
"tomb3.exe",
63+
"audio",
64+
"data",
65+
"Pix",
66+
}));
67+
data.append(new GameFileTree(QStringList{
68+
"tomb3.exe",
69+
"audio",
70+
"Data",
71+
}));
72+
data.append(new GameFileTree(QStringList{
73+
"tomb3.exe",
74+
"audio",
75+
"data",
76+
"pix",
77+
}));
78+
data.append(new GameFileTree(QStringList{
79+
"tomb4.exe",
80+
"audio",
81+
"Data",
82+
}));
83+
data.append(new GameFileTree(QStringList{
84+
"tomb4.exe",
85+
"audio",
86+
"data",
87+
"pix",
88+
}));
89+
data.append(new GameFileTree(QStringList{
90+
"audio",
91+
"data",
92+
"pix",
93+
}));
94+
data.append(new GameFileTree(QStringList{
95+
"PCTomb5.exe",
96+
"audio",
97+
"data",
98+
"pix",
99+
}));
100+
}
101+
~StaticTrees() {
102+
for (GameFileTree* tree : data) {
103+
delete tree;
104+
}
105+
data.clear();
106+
}
107+
};
108+
109+
27110
bool FileManager::setUpCamp(const QString& levelDir, const QString& gameDir) {
28111
bool status = true;
29112

@@ -212,21 +295,35 @@ bool FileManager::linkGameDir(const QString& levelDir, const QString& gameDir) {
212295
bool status = false;
213296
const QString levelPath = QString("%1%2")
214297
.arg(m_levelDir.absolutePath(), levelDir);
215-
const QString gamePath = QString("%1%2")
298+
const QString gamePath = QString("%1/%2")
216299
.arg(m_gameDir.absolutePath(), gameDir);
217300

301+
StaticTrees staticTrees;
218302
QDir dir(levelPath);
219303
GameFileTree test(dir);
220304
test.printTree(1);
305+
QString extraPath;
306+
307+
for (const GameFileTree* tree : staticTrees.data) {
308+
extraPath = test.matchesFromAnyNode(tree);
309+
if ((extraPath != QString("\0")) && (!extraPath.isEmpty())) {
310+
QTextStream(stdout)
311+
<< "game tree matches: " << extraPath << Qt::endl;
312+
break;
313+
}
314+
}
315+
316+
qDebug() << "levelPath: " << levelPath;
317+
qDebug() << "gamePath: " << gamePath;
221318

222-
if (QFile::link(levelPath, gamePath) == true) {
319+
if (QFile::link(levelPath + extraPath, gamePath) == true) {
223320
qDebug() << "Symbolic link created successfully.";
224321
status = true;
225322
} else {
226323
QFileInfo fileInfo(gamePath);
227324
if (fileInfo.isSymLink() == true) {
228325
(void)QFile::remove(gamePath);
229-
if (QFile::link(levelPath, gamePath) == true) {
326+
if (QFile::link(levelPath + extraPath, gamePath) == true) {
230327
qDebug() << "Symbolic link created successfully.";
231328
status = true;
232329
} else {
@@ -438,60 +535,3 @@ bool FileManager::moveFilesToDirectory(
438535
});
439536
}
440537

441-
bool FileManager::moveFilesToParentDirectory(
442-
const QString& levelDirectory, int levelsUp) {
443-
const QString& sep = QDir::separator();
444-
QDir levelDirectoryFullPath(QString("%1%2%3")
445-
.arg(m_levelDir.absolutePath(), sep, levelDirectory));
446-
447-
if (!levelDirectoryFullPath.exists()) {
448-
qWarning() << "Directory does not exist:"
449-
<< levelDirectoryFullPath.absolutePath();
450-
return false;
451-
}
452-
453-
QDir levelDirectoryUpPath = levelDirectoryFullPath;
454-
455-
for (int i = 0; i < levelsUp; ++i) {
456-
if (!levelDirectoryUpPath.cdUp()) {
457-
qWarning() << "Failed to access parent directory at level "
458-
<< i + 1 << " from:" << levelDirectoryFullPath.absolutePath();
459-
return false;
460-
}
461-
}
462-
463-
QFlags listFlags(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
464-
QFileInfoList fileList = levelDirectoryFullPath.entryInfoList(listFlags);
465-
466-
// Move all files and directories to the parent directory
467-
for (const QFileInfo& fileInfo : fileList) {
468-
QString srcPath = fileInfo.absoluteFilePath();
469-
QString destPath = levelDirectoryUpPath.absolutePath() + sep +
470-
fileInfo.fileName();
471-
472-
if (fileInfo.isDir() == true) {
473-
// Move the directory recursively
474-
QDir srcDir(srcPath);
475-
if (!srcDir.rename(srcPath, destPath)) {
476-
qWarning() << "Failed to move directory:" << srcPath;
477-
return false;
478-
}
479-
} else {
480-
// Move the file
481-
if (!QFile::rename(srcPath, destPath)) {
482-
qWarning() << "Failed to move file:" << srcPath;
483-
return false;
484-
}
485-
}
486-
}
487-
488-
QDir parentDir = levelDirectoryFullPath; // Create a copy
489-
parentDir.cdUp(); // Move to the parent directory
490-
491-
if (!parentDir.rmdir(levelDirectoryFullPath.dirName())) {
492-
qWarning() << "Failed to remove directory:"
493-
<< levelDirectoryFullPath.absolutePath();
494-
return false;
495-
}
496-
return true;
497-
}

src/FileManager.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class FileManager : public QObject {
4242
const QString& fromLevelDirectory,
4343
const QString& toLevelDirectory);
4444

45-
bool moveFilesToParentDirectory(const QString& directoryPath, int levelsUp);
4645
int createDirectory(const QString &file, bool gameDir);
4746
int copyFile(
4847
const QString &gameFile,

src/GameFileTree.cpp

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,21 @@ GameFileTree::~GameFileTree() {
4242
}
4343
}
4444

45-
46-
GameFileTree::GameFileTree(const QString& fileList) : m_parentItem(nullptr) {
47-
QStringList pathList = fileList.split("\n");
45+
GameFileTree::GameFileTree(const QStringList& pathList)
46+
// cppcheck-suppress misra-c2012-12.3
47+
: m_parentItem(nullptr) {
4848
addPathList(pathList);
4949
}
5050

51-
GameFileTree::GameFileTree(const QDir &dir) : m_parentItem(nullptr) {
51+
GameFileTree::GameFileTree(const QDir &dir)
52+
// cppcheck-suppress misra-c2012-12.3
53+
: m_parentItem(nullptr) {
5254
if (dir.exists() == true) {
5355
QStringList pathList;
5456
// Skapa en kö för att hantera kataloger iterativt
5557
QQueue<QString> dirQueue;
56-
dirQueue.enqueue(dir.absolutePath());
58+
const QString base = dir.absolutePath();
59+
dirQueue.enqueue(base);
5760

5861
while (!dirQueue.isEmpty()) {
5962
QString currentDirPath = dirQueue.dequeue();
@@ -68,7 +71,7 @@ GameFileTree::GameFileTree(const QDir &dir) : m_parentItem(nullptr) {
6871
QDir::Name);
6972

7073
for (const QFileInfo& fileInfo : fileList) {
71-
pathList << fileInfo.absoluteFilePath();
74+
pathList << QString(fileInfo.absoluteFilePath().split(base)[1]);
7275

7376
// Om objektet är en katalog, lägg till den i kön
7477
if (fileInfo.isDir() == true) {
@@ -85,15 +88,17 @@ GameFileTree::GameFileTree(const QDir &dir) : m_parentItem(nullptr) {
8588

8689
void GameFileTree::addPathList(const QStringList& pathList) {
8790
for (const QString& path : pathList) {
88-
QStringList components = QDir::toNativeSeparators(path).split(QDir::separator(), Qt::SkipEmptyParts);
91+
QStringList components = QDir::toNativeSeparators(path).split(
92+
QDir::separator(), Qt::SkipEmptyParts);
8993
GameFileTree* current = this;
9094

9195
for (const QString& component : components) {
9296
// Check if a child node with this name already exists
93-
auto it = std::find_if(current->m_childItems.begin(), current->m_childItems.end(),
94-
[&component](GameFileTree* child) {
95-
return child->m_fileName == component;
96-
});
97+
auto it = std::find_if(
98+
current->m_childItems.begin(), current->m_childItems.end(),
99+
[&component](GameFileTree* child) {
100+
return child->m_fileName == component;
101+
});
97102

98103
if (it == current->m_childItems.end()) {
99104
// Node doesn't exist, create it
@@ -116,7 +121,14 @@ void GameFileTree::printTree(int level) const {
116121

117122
while (currentNode != nullptr) {
118123
if (!currentNode->m_fileName.isEmpty()) {
119-
fullPath = currentNode->m_fileName + QDir::separator() + fullPath;
124+
if (fullPath.isEmpty()) {
125+
fullPath = currentNode->m_fileName;
126+
} else {
127+
fullPath = QString("%1%2%3")
128+
.arg(currentNode->m_fileName)
129+
.arg(QDir::separator())
130+
.arg(fullPath);
131+
}
120132
}
121133
currentNode = currentNode->m_parentItem;
122134
}
@@ -131,3 +143,60 @@ void GameFileTree::printTree(int level) const {
131143
}
132144
}
133145
}
146+
147+
bool GameFileTree::matchesSubtree(const GameFileTree* other) const {
148+
if (!other) return false; // If the other tree is null, no match is possible.
149+
150+
QQueue<QPair<const GameFileTree*, const GameFileTree*>> queue;
151+
queue.enqueue({this, other}); // Start with the root nodes of both trees.
152+
153+
while (!queue.isEmpty()) {
154+
QPair<const GameFileTree*, const GameFileTree*> current = queue.dequeue();
155+
156+
const GameFileTree* nodeThis = current.first;
157+
const GameFileTree* nodeOther = current.second;
158+
159+
// Check if all children in `nodeOther` match at least one child in `nodeThis`.
160+
for (const GameFileTree* childOther : nodeOther->m_childItems) {
161+
bool found = false;
162+
for (const GameFileTree* childThis : nodeThis->m_childItems) {
163+
if (childThis->m_fileName.toUpper() == childOther->m_fileName.toUpper()) {
164+
// Enqueue the matching child nodes for further comparison.
165+
queue.enqueue({childThis, childOther});
166+
found = true;
167+
break;
168+
}
169+
}
170+
171+
// If no matching child is found, the subtree does not match.
172+
if (!found) {
173+
return false;
174+
}
175+
}
176+
}
177+
178+
return true; // All nodes and structures matched successfully.
179+
}
180+
181+
QString GameFileTree::matchesFromAnyNode(const GameFileTree* other) {
182+
// If this node matches the subtree, return its name
183+
if (matchesSubtree(other)) {
184+
return m_fileName;
185+
}
186+
187+
// Otherwise, check children recursively
188+
for (GameFileTree* child : m_childItems) {
189+
QString childPath = child->matchesFromAnyNode(other);
190+
if (!childPath.isEmpty()) {
191+
// Build the path backwards
192+
return QString("%1%2%3")
193+
.arg(m_fileName)
194+
.arg(QDir::separator())
195+
.arg(childPath);
196+
}
197+
}
198+
199+
// No match found
200+
return QString("\0");
201+
}
202+

src/GameFileTree.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
#include <QDir>
2020
#include <QStringList>
2121
#include <QDebug>
22+
#include <QList>
2223

2324
class GameFileTree {
2425
public:
2526
explicit GameFileTree(const QDir& fullPath);
26-
explicit GameFileTree(const QString& fileList);
27+
explicit GameFileTree(const QStringList& pathList);
2728
~GameFileTree();
2829

2930
void printTree(int level) const;
31+
bool matchesSubtree(const GameFileTree* other) const;
32+
QString matchesFromAnyNode(const GameFileTree* other);
3033

3134
private:
3235
explicit GameFileTree(

0 commit comments

Comments
 (0)