1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-04-23 12:37:45 +00:00

sagasu: Allow downloading path lists directly from ResLogger

The path list is now refreshed when importing too, which makes it even
easier to get started.
This commit is contained in:
Joshua Goins 2024-02-03 10:23:41 -05:00
parent ecfe13cade
commit 5d455c4ce0
6 changed files with 75 additions and 18 deletions

View file

@ -33,6 +33,7 @@ target_sources(novus-sagasu
target_include_directories(novus-sagasu PRIVATE include)
target_link_libraries(novus-sagasu
PRIVATE
KF6::Archive
novus-sagasu-static
Novus::SklbPart
Novus::CmpPart
@ -43,7 +44,8 @@ target_link_libraries(novus-sagasu
Novus::ExdPart
Novus::TexPart
Physis::Logger
Qt6::Concurrent)
Qt6::Concurrent
Qt6::Network)
install(FILES zone.xiv.sagasu.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES zone.xiv.sagasu.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps)

View file

@ -16,13 +16,13 @@ class FileTreeWindow : public QWidget
public:
explicit FileTreeWindow(HashDatabase &database, const QString &gamePath, GameData *data, QWidget *parent = nullptr);
void refreshModel();
Q_SIGNALS:
void extractFile(const QString &path);
void pathSelected(const QString &path);
private:
void refreshModel();
GameData *data = nullptr;
FileTreeModel *m_fileModel = nullptr;
QSortFilterProxyModel *m_searchModel = nullptr;

View file

@ -16,7 +16,7 @@ public:
void addFolder(const QString &folder);
void addFile(const QString &file);
void importFileList(const QString &path);
void importFileList(const QByteArray &file);
QVector<QString> getKnownFolders();

View file

@ -5,9 +5,11 @@
#include <QMap>
#include <QMdiArea>
#include <QNetworkAccessManager>
#include <QTreeWidget>
#include "filecache.h"
#include "filetreewindow.h"
#include "hashdatabase.h"
#include "novusmainwindow.h"
@ -26,6 +28,8 @@ private:
QTabWidget *partHolder = nullptr;
FileCache fileCache;
HashDatabase m_database;
QNetworkAccessManager *m_mgr = nullptr;
FileTreeWindow *m_tree = nullptr;
void refreshParts(const QString &path);
};

View file

@ -95,11 +95,8 @@ QString HashDatabase::getFilename(const uint32_t i)
return query.value(0).toString();
}
void HashDatabase::importFileList(const QString &path)
void HashDatabase::importFileList(const QByteArray &file)
{
QFile file(path);
file.open(QIODevice::ReadOnly);
QVariantList folderNames, folderHashes;
QVariantList fileNames, fileHashes;
@ -115,7 +112,7 @@ void HashDatabase::importFileList(const QString &path)
QStringLiteral("REPLACE INTO file_hashes (hash, name) "
"VALUES (?, ?)"));
QTextStream stream(&file);
QTextStream stream(file);
stream.readLine(); // skip header
while (!stream.atEnd()) {
const QStringList parts = stream.readLine().split(QLatin1Char(','));

View file

@ -3,6 +3,7 @@
#include "mainwindow.h"
#include <KZip>
#include <QApplication>
#include <QDesktopServices>
#include <QFileDialog>
@ -10,12 +11,13 @@
#include <QLabel>
#include <QMenuBar>
#include <QMessageBox>
#include <QNetworkReply>
#include <QTemporaryDir>
#include "cmppart.h"
#include "exdpart.h"
#include "exlpart.h"
#include "filepropertieswindow.h"
#include "filetreewindow.h"
#include "hexpart.h"
#include "mdlpart.h"
#include "shpkpart.h"
@ -29,14 +31,16 @@ MainWindow::MainWindow(const QString &gamePath, GameData *data)
{
setupMenubar();
m_mgr = new QNetworkAccessManager(this);
auto dummyWidget = new QWidget();
setCentralWidget(dummyWidget);
auto layout = new QHBoxLayout();
dummyWidget->setLayout(layout);
auto tree = new FileTreeWindow(m_database, gamePath, data);
connect(tree, &FileTreeWindow::extractFile, this, [this, data](const QString &path) {
m_tree = new FileTreeWindow(m_database, gamePath, data);
connect(m_tree, &FileTreeWindow::extractFile, this, [this, data](const QString &path) {
const QFileInfo info(path);
const QString savePath = QFileDialog::getSaveFileName(this, tr("Save File"), info.fileName(), QStringLiteral("*.%1").arg(info.completeSuffix()));
@ -51,11 +55,11 @@ MainWindow::MainWindow(const QString &gamePath, GameData *data)
file.write(reinterpret_cast<const char *>(fileData.data), fileData.size);
}
});
connect(tree, &FileTreeWindow::pathSelected, this, [this](const QString &path) {
connect(m_tree, &FileTreeWindow::pathSelected, this, [this](const QString &path) {
refreshParts(path);
});
tree->setMaximumWidth(200);
layout->addWidget(tree);
m_tree->setMaximumWidth(200);
layout->addWidget(m_tree);
partHolder = new QTabWidget();
partHolder->setMinimumWidth(800);
@ -132,7 +136,11 @@ void MainWindow::setupFileMenu(QMenu *menu)
QMessageBox::Ok,
QMessageBox::Ok);
m_database.importFileList(fileName);
QFile file(fileName);
file.open(QIODevice::ReadOnly);
m_database.importFileList(file.readAll());
m_tree->refreshModel();
QMessageBox::information(this, QStringLiteral("Import Complete"), QStringLiteral("Successfully imported path list!"), QMessageBox::Ok, QMessageBox::Ok);
});
@ -140,8 +148,54 @@ void MainWindow::setupFileMenu(QMenu *menu)
auto downloadList = menu->addAction(QStringLiteral("Download Path List..."));
downloadList->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
connect(downloadList, &QAction::triggered, [this] {
auto fileName = QFileDialog::getOpenFileName(nullptr, QStringLiteral("Open Path List"), QStringLiteral("~"));
const int ret =
QMessageBox::information(this,
QStringLiteral("Download Confirmation"),
QStringLiteral("This will download the path list from <a "
"href=\"https://rl2.perchbird.dev/\">ResLogger</a>.this process usually takes a few minutes. The program "
"may freeze. Please keep it open until the operation is finished.<br><br>Continue?"),
QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Ok);
m_database.importFileList(fileName);
if (ret != QMessageBox::Ok) {
return;
}
QUrl url;
url.setScheme(QStringLiteral("https"));
url.setHost(QStringLiteral("rl2.perchbird.dev"));
url.setPath(QStringLiteral("/download/export/CurrentPathListWithHashes.zip"));
// TODO: Use Qcoro?
auto reply = m_mgr->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, [this, reply] {
qInfo() << "Finished downloading path list!";
QTemporaryDir tempDir;
QFile file(tempDir.filePath(QStringLiteral("CurrentPathListWithHashes.zip")));
file.open(QIODevice::WriteOnly);
file.write(reply->readAll());
file.close();
KZip archive(file.fileName());
if (!archive.open(QIODevice::ReadOnly)) {
// TODO: these should show as message boxes
qFatal() << "Failed to open path list zip!" << archive.errorString();
return;
}
const KArchiveFile *root = dynamic_cast<const KArchiveFile *>(archive.directory()->entry(QStringLiteral("CurrentPathListWithHashes.csv")));
m_database.importFileList(root->data());
m_tree->refreshModel();
archive.close();
QMessageBox::information(this,
QStringLiteral("Import Complete"),
QStringLiteral("Successfully downloaded and imported path list!"),
QMessageBox::Ok,
QMessageBox::Ok);
});
});
}