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:28:00 -04:00
|
|
|
#include "exdpart.h"
|
|
|
|
|
2024-02-04 15:23:24 -05:00
|
|
|
#include <KLocalizedString>
|
2023-09-23 14:09:00 -04:00
|
|
|
#include <QFile>
|
2023-10-12 21:33:09 -04:00
|
|
|
#include <QGroupBox>
|
|
|
|
#include <QJsonArray>
|
2023-09-23 14:09:00 -04:00
|
|
|
#include <QJsonDocument>
|
|
|
|
#include <QJsonObject>
|
2023-10-12 21:33:09 -04:00
|
|
|
#include <QLabel>
|
|
|
|
#include <QTableWidget>
|
|
|
|
#include <QVBoxLayout>
|
2023-08-06 08:48:11 -04:00
|
|
|
#include <physis.hpp>
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-12-09 21:28:02 -05:00
|
|
|
EXDPart::EXDPart(GameData *data, QWidget *parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
, data(data)
|
2023-10-12 21:33:09 -04:00
|
|
|
{
|
2023-04-09 15:28:00 -04:00
|
|
|
auto layout = new QVBoxLayout();
|
2024-02-04 14:29:45 -05:00
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
2023-04-09 15:28:00 -04:00
|
|
|
setLayout(layout);
|
|
|
|
|
2024-02-04 14:29:45 -05:00
|
|
|
// TODO: This information should really be somewhere else
|
|
|
|
/*auto headerBox = new QGroupBox(QStringLiteral("Header"));
|
2023-10-12 21:33:09 -04:00
|
|
|
layout->addWidget(headerBox);
|
|
|
|
headerFormLayout = new QFormLayout();
|
2024-02-04 14:29:45 -05:00
|
|
|
headerBox->setLayout(headerFormLayout);*/
|
2023-10-12 21:33:09 -04:00
|
|
|
|
|
|
|
pageTabWidget = new QTabWidget();
|
2024-02-04 14:29:45 -05:00
|
|
|
pageTabWidget->setTabPosition(QTabWidget::TabPosition::South);
|
|
|
|
pageTabWidget->setDocumentMode(true); // hide borders
|
|
|
|
layout->addWidget(pageTabWidget);
|
2023-10-12 21:33:09 -04:00
|
|
|
}
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2024-02-03 09:18:10 -05:00
|
|
|
void EXDPart::loadSheet(const QString &name, physis_Buffer buffer, const QString &definitionPath)
|
2023-10-12 21:33:09 -04:00
|
|
|
{
|
2023-04-09 15:28:00 -04:00
|
|
|
pageTabWidget->clear();
|
|
|
|
|
2024-02-03 09:18:10 -05:00
|
|
|
QFile definitionFile(definitionPath);
|
2023-09-23 14:09:00 -04:00
|
|
|
definitionFile.open(QIODevice::ReadOnly);
|
|
|
|
|
2023-10-10 17:23:07 -04:00
|
|
|
QJsonArray definitionList;
|
|
|
|
if (definitionFile.isOpen()) {
|
|
|
|
auto document = QJsonDocument::fromJson(definitionFile.readAll());
|
|
|
|
definitionList = document.object()[QLatin1String("definitions")].toArray();
|
2023-09-23 14:09:00 -04:00
|
|
|
|
2023-10-10 17:23:07 -04:00
|
|
|
for (auto definition : definitionList) {
|
|
|
|
if (definition.toObject().contains(QLatin1String("converter"))
|
|
|
|
&& definition.toObject()[QLatin1String("converter")].toObject()[QLatin1String("type")].toString() == QStringLiteral("link")) {
|
|
|
|
auto linkName = definition.toObject()[QLatin1String("converter")].toObject()[QLatin1String("target")].toString();
|
2023-09-23 14:09:00 -04:00
|
|
|
|
2024-02-03 09:18:10 -05:00
|
|
|
auto path = QStringLiteral("exd/%1.exh").arg(linkName.toLower());
|
|
|
|
auto pathStd = path.toStdString();
|
|
|
|
|
|
|
|
auto file = physis_gamedata_extract_file(data, pathStd.c_str());
|
|
|
|
|
|
|
|
auto linkExh = physis_parse_excel_sheet_header(file);
|
2023-10-10 17:23:07 -04:00
|
|
|
auto linkExd = physis_gamedata_read_excel_sheet(data, linkName.toStdString().c_str(), linkExh, getSuitableLanguage(linkExh), 0);
|
2023-09-23 14:09:00 -04:00
|
|
|
|
2023-10-10 17:23:07 -04:00
|
|
|
if (linkExd.p_ptr != nullptr) {
|
|
|
|
cachedExcelSheets[linkName] = CachedExcel{linkExh, linkExd};
|
|
|
|
}
|
2023-09-23 14:09:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 21:33:09 -04:00
|
|
|
auto exh = physis_parse_excel_sheet_header(buffer);
|
|
|
|
|
2024-02-04 14:29:45 -05:00
|
|
|
// ditto
|
|
|
|
/*QLayoutItem *child;
|
2023-12-09 15:24:54 -05:00
|
|
|
while ((child = headerFormLayout->takeAt(0)) != nullptr) {
|
2023-10-12 21:33:09 -04:00
|
|
|
delete child->widget();
|
|
|
|
delete child;
|
|
|
|
}
|
|
|
|
|
|
|
|
headerFormLayout->addRow(QStringLiteral("Num Rows"), new QLabel(QString::number(exh->row_count)));
|
|
|
|
headerFormLayout->addRow(QStringLiteral("Num Columns"), new QLabel(QString::number(exh->column_count)));
|
|
|
|
headerFormLayout->addRow(QStringLiteral("Num Pages"), new QLabel(QString::number(exh->page_count)));
|
2024-02-04 14:29:45 -05:00
|
|
|
headerFormLayout->addRow(QStringLiteral("Num Languages"), new QLabel(QString::number(exh->language_count)));*/
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-12-09 22:35:59 -05:00
|
|
|
for (uint32_t i = 0; i < exh->page_count; i++) {
|
2023-09-23 14:09:00 -04:00
|
|
|
auto tableWidget = new QTableWidget();
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-07-08 10:18:07 -04:00
|
|
|
tableWidget->setColumnCount(exh->column_count);
|
2023-10-12 21:43:36 -04:00
|
|
|
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-09-23 14:09:00 -04:00
|
|
|
auto exd = physis_gamedata_read_excel_sheet(data, name.toStdString().c_str(), exh, getSuitableLanguage(exh), i);
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2025-03-23 19:55:28 -04:00
|
|
|
tableWidget->setRowCount(exh->row_count);
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-12-09 22:35:59 -05:00
|
|
|
for (unsigned int z = 0; z < exd.column_count; z++) {
|
2025-03-23 19:55:28 -04:00
|
|
|
auto columnData = exh->column_types[z];
|
2023-09-23 14:09:00 -04:00
|
|
|
|
|
|
|
QString columnType;
|
2025-03-23 19:55:28 -04:00
|
|
|
switch (columnData) {
|
|
|
|
case ColumnDataType::String:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("String");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::Bool:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("Bool");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::Int8:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("Int8");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::UInt8:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("UInt8");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::Int16:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("Int16");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::UInt16:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("UInt16");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::Int32:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("Int32");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::UInt32:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("UInt32");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::Float32:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("Float32");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::Int64:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("Int64");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2025-03-23 19:55:28 -04:00
|
|
|
case ColumnDataType::UInt64:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnType = i18n("UInt64");
|
2023-09-26 00:37:55 -04:00
|
|
|
break;
|
2023-09-23 14:09:00 -04:00
|
|
|
}
|
|
|
|
|
2024-02-03 09:18:10 -05:00
|
|
|
// TODO: index could be different
|
2024-05-10 16:37:10 -04:00
|
|
|
if (z < definitionList.size()) {
|
2023-10-10 17:23:07 -04:00
|
|
|
columnType = definitionList[z].toObject()[QLatin1String("name")].toString();
|
|
|
|
}
|
2023-09-23 14:09:00 -04:00
|
|
|
|
|
|
|
auto headerItem = new QTableWidgetItem();
|
|
|
|
headerItem->setText(columnType);
|
|
|
|
|
|
|
|
tableWidget->setHorizontalHeaderItem(z, headerItem);
|
|
|
|
}
|
|
|
|
|
2025-03-23 19:55:28 -04:00
|
|
|
for (unsigned int j = 0; j < exh->row_count; j++) {
|
|
|
|
auto rows = physis_exd_read_row(&exd, exh, j); // TODO: free, use other rows
|
|
|
|
|
2023-12-09 22:35:59 -05:00
|
|
|
for (unsigned int z = 0; z < exd.column_count; z++) {
|
2025-03-23 19:55:28 -04:00
|
|
|
auto columnData = rows.row_data[0].column_data[z];
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2024-02-03 09:18:10 -05:00
|
|
|
auto [columnString, columnRow] = getColumnData(columnData);
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2024-05-10 16:37:10 -04:00
|
|
|
if (z < definitionList.size()) {
|
2023-10-10 17:23:07 -04:00
|
|
|
auto definition = definitionList[z].toObject();
|
|
|
|
if (definition.contains(QLatin1String("converter"))
|
|
|
|
&& definition[QLatin1String("converter")].toObject()[QLatin1String("type")].toString() == QLatin1String("link")) {
|
2023-09-26 00:37:55 -04:00
|
|
|
auto linkName = definition[QLatin1String("converter")].toObject()[QLatin1String("target")].toString();
|
|
|
|
|
|
|
|
if (cachedExcelSheets.contains(linkName)) {
|
|
|
|
auto cachedExcel = cachedExcelSheets[linkName];
|
2025-03-23 19:55:28 -04:00
|
|
|
if (static_cast<unsigned int>(columnRow) < cachedExcel.exh->row_count) {
|
2025-03-23 20:00:11 -04:00
|
|
|
// TODO: add back
|
2025-03-23 19:55:28 -04:00
|
|
|
// auto [colString, _] = getColumnData(*cachedExcel.exh->row_data[columnRow].column_data);
|
|
|
|
// columnString = colString;
|
2023-09-26 00:37:55 -04:00
|
|
|
}
|
2023-09-23 14:09:00 -04:00
|
|
|
}
|
2023-10-10 17:23:07 -04:00
|
|
|
}
|
2023-09-23 14:09:00 -04:00
|
|
|
}
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-09-23 14:09:00 -04:00
|
|
|
auto newItem = new QTableWidgetItem(columnString);
|
2023-04-09 15:28:00 -04:00
|
|
|
|
2023-09-23 14:09:00 -04:00
|
|
|
tableWidget->setItem(j, z, newItem);
|
2023-04-09 15:28:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-23 14:09:00 -04:00
|
|
|
tableWidget->resizeColumnsToContents();
|
|
|
|
|
2024-02-04 15:36:08 -05:00
|
|
|
pageTabWidget->addTab(tableWidget, i18nc("@title:tab", "Page %1", i));
|
2023-04-09 15:28:00 -04:00
|
|
|
}
|
2024-02-04 14:29:45 -05:00
|
|
|
|
|
|
|
// Expand the tabs and hide the tab bar if there's only one page
|
|
|
|
// (it effectively makes the tab bar useless, so why show it?)
|
|
|
|
pageTabWidget->tabBar()->setExpanding(true);
|
|
|
|
pageTabWidget->tabBar()->setVisible(exh->page_count > 1);
|
2023-09-23 14:09:00 -04:00
|
|
|
}
|
|
|
|
|
2023-10-12 23:45:21 -04:00
|
|
|
Language EXDPart::getSuitableLanguage(physis_EXH *pExh)
|
|
|
|
{
|
2023-12-09 22:35:59 -05:00
|
|
|
for (uint32_t i = 0; i < pExh->language_count; i++) {
|
2023-09-23 14:09:00 -04:00
|
|
|
if (pExh->languages[i] == Language::English) {
|
|
|
|
return Language::English;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Language::None;
|
|
|
|
}
|
2023-10-12 23:45:21 -04:00
|
|
|
|
2024-02-03 09:18:10 -05:00
|
|
|
std::pair<QString, int> EXDPart::getColumnData(physis_ColumnData &columnData)
|
|
|
|
{
|
|
|
|
QString columnString;
|
|
|
|
int columnRow;
|
|
|
|
switch (columnData.tag) {
|
|
|
|
case physis_ColumnData::Tag::String:
|
|
|
|
columnString = QString::fromStdString(columnData.string._0);
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::Bool:
|
2024-02-04 15:23:24 -05:00
|
|
|
columnString = columnData.bool_._0 ? i18nc("Value is true", "True") : i18nc("Value is false", "False");
|
2024-02-03 09:18:10 -05:00
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::Int8:
|
|
|
|
columnString = QString::number(columnData.int8._0);
|
|
|
|
columnRow = columnData.int8._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::UInt8:
|
|
|
|
columnString = QString::number(columnData.u_int8._0);
|
|
|
|
columnRow = columnData.u_int8._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::Int16:
|
|
|
|
columnString = QString::number(columnData.int16._0);
|
|
|
|
columnRow = columnData.int16._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::UInt16:
|
|
|
|
columnString = QString::number(columnData.u_int16._0);
|
|
|
|
columnRow = columnData.u_int16._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::Int32:
|
|
|
|
columnString = QString::number(columnData.int32._0);
|
|
|
|
columnRow = columnData.int32._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::UInt32:
|
|
|
|
columnString = QString::number(columnData.u_int32._0);
|
|
|
|
columnRow = columnData.u_int32._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::Float32:
|
|
|
|
columnString = QString::number(columnData.float32._0);
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::Int64:
|
|
|
|
columnString = QString::number(columnData.int64._0);
|
|
|
|
columnRow = columnData.int64._0;
|
|
|
|
break;
|
|
|
|
case physis_ColumnData::Tag::UInt64:
|
|
|
|
columnString = QString::number(columnData.u_int64._0);
|
|
|
|
columnRow = columnData.u_int64._0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {columnString, columnRow};
|
|
|
|
}
|
|
|
|
|
2023-10-12 23:45:21 -04:00
|
|
|
#include "moc_exdpart.cpp"
|