2023-08-06 08:48:11 -04:00
|
|
|
// SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2023-04-09 15:32:09 -04:00
|
|
|
#include <QDebug>
|
2023-08-06 08:48:11 -04:00
|
|
|
#include <QHBoxLayout>
|
2023-04-09 15:32:09 -04:00
|
|
|
#include <QMenu>
|
2023-08-06 08:48:11 -04:00
|
|
|
#include <QTreeWidget>
|
2023-04-09 15:32:09 -04:00
|
|
|
|
|
|
|
#include "filetreewindow.h"
|
|
|
|
|
2023-08-06 08:48:11 -04:00
|
|
|
FileTreeWindow::FileTreeWindow(GameData* data, QWidget* parent) : QWidget(parent), data(data) {
|
2023-09-26 00:37:55 -04:00
|
|
|
setWindowTitle(QStringLiteral("File Tree"));
|
2023-04-09 15:32:09 -04:00
|
|
|
|
|
|
|
auto layout = new QHBoxLayout();
|
|
|
|
setLayout(layout);
|
|
|
|
|
|
|
|
auto treeWidget = new QTreeWidget();
|
2023-09-26 00:37:55 -04:00
|
|
|
treeWidget->setHeaderLabel(QStringLiteral("Name"));
|
2023-04-09 15:32:09 -04:00
|
|
|
layout->addWidget(treeWidget);
|
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
addPath(QStringLiteral("common/font/AXIS_12.fdt"));
|
2023-04-09 15:32:09 -04:00
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
addPath(QStringLiteral("exd/root.exl"));
|
2023-04-09 15:32:09 -04:00
|
|
|
|
|
|
|
auto sheetNames = physis_gamedata_get_all_sheet_names(data);
|
|
|
|
|
|
|
|
for(int i = 0; i < sheetNames.name_count; i++) {
|
|
|
|
auto sheetName = sheetNames.names[i];
|
2023-09-26 00:37:55 -04:00
|
|
|
auto nameLowercase = QString::fromStdString(sheetName).toLower().toStdString();
|
2023-04-09 15:32:09 -04:00
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
addPath(QStringLiteral("exd/") + QLatin1String(nameLowercase.c_str()) + QStringLiteral(".exh"));
|
2023-04-09 15:32:09 -04:00
|
|
|
|
|
|
|
auto exh = physis_gamedata_read_excel_sheet_header(data, sheetName);
|
2023-09-23 14:51:47 -04:00
|
|
|
for (int j = 0; j < exh->page_count; j++) {
|
|
|
|
for (int z = 0; z < exh->language_count; z++) {
|
|
|
|
std::string path = physis_gamedata_get_exd_filename(nameLowercase.c_str(), exh, exh->languages[z], j);
|
2023-04-09 15:32:09 -04:00
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
addPath(QStringLiteral("exd/") + QString::fromStdString(path));
|
2023-04-09 15:32:09 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(treeWidget, &QTreeWidget::customContextMenuRequested, this, [this, treeWidget](const QPoint& pos) {
|
|
|
|
auto *item = treeWidget->itemAt(pos);
|
|
|
|
|
|
|
|
if (item != nullptr) {
|
|
|
|
auto path = item->data(0, Qt::UserRole).toString();
|
|
|
|
qInfo() << path;
|
|
|
|
|
|
|
|
auto menu = new QMenu();
|
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
QAction *propertiesAction = menu->addAction(QStringLiteral("Properties"));
|
2023-04-09 15:32:09 -04:00
|
|
|
connect(propertiesAction, &QAction::triggered, this, [=] {
|
2023-09-26 00:37:55 -04:00
|
|
|
Q_EMIT openFileProperties(path);
|
2023-04-09 15:32:09 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
QPoint pt(pos);
|
|
|
|
menu->exec(treeWidget->mapToGlobal(pos));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
addPaths(treeWidget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FileTreeWindow::addPath(QString path) {
|
2023-09-26 00:37:55 -04:00
|
|
|
auto tokens = path.split(QStringLiteral("/"));
|
2023-04-09 15:32:09 -04:00
|
|
|
auto nextToken = tokens[0];
|
|
|
|
tokens.pop_front();
|
|
|
|
|
|
|
|
traversePart(tokens, rootParts[nextToken], nextToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FileTreeWindow::traversePart(QList<QString> tokens, PathPart& part, QString pathSoFar) {
|
|
|
|
if(tokens.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto nextToken = tokens[0];
|
|
|
|
tokens.pop_front();
|
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
pathSoFar = pathSoFar + QStringLiteral("/") + nextToken;
|
2023-04-09 15:32:09 -04:00
|
|
|
part.children[nextToken].crcHash = physis_calculate_hash(pathSoFar.toStdString().c_str());
|
|
|
|
|
|
|
|
traversePart(tokens, part.children[nextToken], pathSoFar);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FileTreeWindow::addPaths(QTreeWidget *pWidget) {
|
|
|
|
for(const auto& name : rootParts.keys()) {
|
2023-09-26 00:37:55 -04:00
|
|
|
auto item = addPartAndChildren(name, rootParts.value(name), QStringLiteral(""));
|
2023-04-09 15:32:09 -04:00
|
|
|
pWidget->addTopLevelItem(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QTreeWidgetItem* FileTreeWindow::addPartAndChildren(const QString& qString, const PathPart& part, const QString& pathSoFar) {
|
2023-09-26 00:37:55 -04:00
|
|
|
QString newPath = pathSoFar.isEmpty() ? qString : pathSoFar + QStringLiteral("/") + qString;
|
2023-04-09 15:32:09 -04:00
|
|
|
|
|
|
|
auto item = new QTreeWidgetItem();
|
|
|
|
item->setData(0, Qt::UserRole, newPath);
|
|
|
|
item->setText(0, qString);
|
|
|
|
|
|
|
|
for(const auto& name : part.children.keys()) {
|
|
|
|
auto childItem = addPartAndChildren(name, part.children.value(name), newPath);
|
|
|
|
item->addChild(childItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FileTreeWindow::addUnknownPath(QString knownDirectory, uint32_t crcHash) {
|
|
|
|
auto [found, path] = traverseUnknownPath(crcHash, rootParts[knownDirectory], knownDirectory);
|
|
|
|
if(found)
|
|
|
|
addPath(path);
|
|
|
|
else
|
2023-09-26 00:37:55 -04:00
|
|
|
addPath(knownDirectory + QStringLiteral("/Unknown File Hash ") + QString::number(crcHash));
|
2023-04-09 15:32:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
std::tuple<bool, QString> FileTreeWindow::traverseUnknownPath(uint32_t crcHash, PathPart &part, QString pathSoFar) {
|
|
|
|
if(part.crcHash == crcHash)
|
|
|
|
return {true, pathSoFar};
|
|
|
|
|
|
|
|
bool found = false;
|
|
|
|
QString childPath = pathSoFar;
|
|
|
|
for(auto path : part.children.keys()) {
|
2023-09-26 00:37:55 -04:00
|
|
|
if (path.contains(QStringLiteral("Unknown")))
|
2023-04-09 15:32:09 -04:00
|
|
|
continue;
|
|
|
|
|
2023-09-26 00:37:55 -04:00
|
|
|
auto [childFound, newPath] = traverseUnknownPath(crcHash, part.children[path], pathSoFar + QStringLiteral("/") + path);
|
2023-04-09 15:32:09 -04:00
|
|
|
found |= childFound;
|
|
|
|
if(childFound)
|
|
|
|
childPath = newPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {found, childPath};
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "moc_filetreewindow.cpp"
|