Roms List improvements

This commit is contained in:
2026-06-14 22:30:10 +02:00
parent 95d202f378
commit 10d3daf86a
7 changed files with 160 additions and 92 deletions
+3 -1
View File
@@ -171,7 +171,9 @@ qt_add_executable(kaizen
src/frontend/Settings/InputSettings.hpp src/frontend/Settings/InputSettings.hpp
src/frontend/Settings/InputSettings.cpp src/frontend/Settings/InputSettings.cpp
src/utils/Options.cpp src/utils/Options.cpp
src/utils/File.cpp) src/utils/File.cpp
src/frontend/RomsList.hpp
src/frontend/RomsList.cpp)
if (WIN32) if (WIN32)
set(MIO_LIB mio::mio_full_winapi) set(MIO_LIB mio::mio_full_winapi)
+20 -65
View File
@@ -11,55 +11,6 @@
#include <Options.hpp> #include <Options.hpp>
#include <Scheduler.hpp> #include <Scheduler.hpp>
RomsListTable::RomsListTable() {
verticalHeader()->hide();
horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
setSizePolicy({QSizePolicy::Maximum, QSizePolicy::Maximum});
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSortingEnabled(true);
setColumnCount(4);
setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
setHorizontalHeaderItem(1, new QTableWidgetItem("Regions"));
setHorizontalHeaderItem(2, new QTableWidgetItem("Last played"));
setHorizontalHeaderItem(3, new QTableWidgetItem("Time played"));
std::jthread([&] {
populate(Options::GetRomsPath());
emit populateFinished();
});
}
void RomsListTable::populate(const std::string &romsPath) {
if (!romsPath.empty()) {
for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
if (!file.is_regular_file())
continue;
auto filename = file.path().string();
bool isPlain = std::ranges::any_of(std::array{".n64", ".z64", ".v64"},
[&](const std::string &ext) { return file.path().extension() == ext; });
bool isArchive =
std::ranges::any_of(std::array{".zip", ".7z", ".rar", ".tar"},
[&](const std::string &ext) { return file.path().extension() == ext; });
if (!isArchive && !isPlain)
continue;
auto rom = n64::Mem::LoadROM(isArchive, filename);
auto regions = n64::GameDB::match(rom);
if (rom.gameNameDB.empty())
rom.gameNameDB = fs::path(filename).stem().string();
romsList.push_back(
{rom.header.countryCode, rom.header.version, filename, rom.gameNameDB, regions, "Never", "0h 00m 00s"});
}
}
}
KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) { KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) {
SDL_InitSubSystem(SDL_INIT_GAMEPAD); SDL_InitSubSystem(SDL_INIT_GAMEPAD);
@@ -67,6 +18,10 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
SDL_AddGamepadMapping(gamecontrollerdb_str); SDL_AddGamepadMapping(gamecontrollerdb_str);
hide(); hide();
settingsWindow = new SettingsWindow();
romsListTable = new RomsListTable(settingsWindow->general);
vulkanWidget = new RenderWidget(); vulkanWidget = new RenderWidget();
vulkanWidget->hide(); vulkanWidget->hide();
@@ -74,16 +29,16 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
centralWidget->addWidget(romsListTable); centralWidget->addWidget(romsListTable);
centralWidget->addWidget(romPathNotSet); centralWidget->addWidget(romPathNotSet);
populateRomsListThread = QThread::create([&] { if (Options::GetRomsPath().empty())
populateRomsList(Options::GetRomsPath()); centralWidget->setCurrentWidget(romPathNotSet);
emit populateRomsListFinished(); else
}); centralWidget->setCurrentWidget(romsListTable);
populateRomsListThread->start(); connect(romsListTable, &RomsListTable::cleared, this, [&] { centralWidget->setCurrentWidget(romPathNotSet); });
connect(this, &KaizenGui::populateRomsListFinished, this, [&] { connect(romsListTable, &RomsListTable::populateFinished, this, [&] {
for (int i = 0; i < romsList.size(); i++) { for (int i = 0; i < romsListTable->size(); i++) {
const auto &[countryCode, version, _, name, regions, lastPlayed, timePlayed] = romsList[i]; const auto &[countryCode, version, _, name, regions, lastPlayed, timePlayed] = (*romsListTable)[i];
romsListTable->insertRow(i); romsListTable->insertRow(i);
romsListTable->setItem( romsListTable->setItem(
@@ -95,11 +50,12 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
romsListTable->setItem(i, 2, new QTableWidgetItem(lastPlayed.c_str())); romsListTable->setItem(i, 2, new QTableWidgetItem(lastPlayed.c_str()));
romsListTable->setItem(i, 3, new QTableWidgetItem(timePlayed.c_str())); romsListTable->setItem(i, 3, new QTableWidgetItem(timePlayed.c_str()));
} }
romsListTable->resizeRowsToContents();
centralWidget->setCurrentWidget(romsListTable);
}); });
connect(this, &KaizenGui::romsListNeedsPopulation, this, [&] { populateRomsListThread->start(); }); connect(romsListTable, &QTableWidget::cellDoubleClicked, this,
[&](int row, int) { LoadROM((*romsListTable)[row].path); });
connect(romsListTable, &QTableWidget::cellDoubleClicked, this, [&](int row, int) { LoadROM(romsList[row].path); });
installEventFilter(this); installEventFilter(this);
@@ -123,7 +79,6 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
setWindowTitle("Kaizen " KAIZEN_VERSION_STR); setWindowTitle("Kaizen " KAIZEN_VERSION_STR);
setMinimumSize(640, 480); setMinimumSize(640, 480);
setCentralWidget(centralWidget); setCentralWidget(centralWidget);
centralWidget->setLayout(new QVBoxLayout());
setAcceptDrops(true); setAcceptDrops(true);
@@ -193,10 +148,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
connect(exit, &QAction::triggered, this, &QMainWindow::close); connect(exit, &QAction::triggered, this, &QMainWindow::close);
auto emulationMenu = menuBar()->addMenu("Emulation"); auto emulationMenu = menuBar()->addMenu("Emulation");
auto settingsMenu = emulationMenu->addAction("Settings"); auto settingsMenu = emulationMenu->addAction("Settings");
settingsWindow = new SettingsWindow();
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show); connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
connect(settingsWindow->general, &GeneralSettings::romFolderSelected, this,
[&] { emit romsListNeedsPopulation(); });
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] { connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
core.cpuType = Options::GetCpuType(); core.cpuType = Options::GetCpuType();
@@ -239,7 +191,10 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
emulationMenu->addAction(stop); emulationMenu->addAction(stop);
connect(stop, &QAction::triggered, this, [&] { connect(stop, &QAction::triggered, this, [&] {
Scheduler::GetInstance().EnqueueRelative(0, STOP); Scheduler::GetInstance().EnqueueRelative(0, STOP);
centralWidget->setCurrentWidget(currentHomeWidget); if (Options::GetRomsPath().empty())
centralWidget->setCurrentWidget(romPathNotSet);
else
centralWidget->setCurrentWidget(romsListTable);
}); });
auto helpMenu = menuBar()->addMenu("Help"); auto helpMenu = menuBar()->addMenu("Help");
+3 -26
View File
@@ -7,33 +7,10 @@
#include <QFileDialog> #include <QFileDialog>
#include <QDropEvent> #include <QDropEvent>
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QTableWidget> #include <RomsList.hpp>
#include <Core.hpp> #include <Core.hpp>
#include <bitset> #include <bitset>
class EmuThread;
struct RomsListEntry {
u8 countryCode, version;
std::string path;
std::string name;
std::string region;
std::string lastPlayed;
std::string timePlayed;
};
class RomsListTable : public QTableWidget {
Q_OBJECT
std::vector<RomsListEntry> romsList;
public:
RomsListTable();
public slots:
void populate(const std::string &);
signals:
void populateFinished();
};
class KaizenGui final : QMainWindow { class KaizenGui final : QMainWindow {
Q_OBJECT Q_OBJECT
void updateKeys(); void updateKeys();
@@ -51,12 +28,12 @@ class KaizenGui final : QMainWindow {
QWidget *currentHomeWidget; QWidget *currentHomeWidget;
QLabel *romPathNotSet = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")"); QLabel *romPathNotSet = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")");
RomsListTable *romsListTable = new RomsListTable(); RomsListTable *romsListTable;
QStackedWidget *centralWidget = new QStackedWidget(); QStackedWidget *centralWidget = new QStackedWidget();
SettingsWindow *settingsWindow; SettingsWindow *settingsWindow;
RenderWidget *vulkanWidget; RenderWidget *vulkanWidget;
QSettings settings; QSettings settings;
QThread *emuThread, *populateRomsListThread; QThread *emuThread;
QTimer *statusBarTimer, *SDLeventsTimer; QTimer *statusBarTimer, *SDLeventsTimer;
QLabel *fpsLabel; QLabel *fpsLabel;
QLabel *cpuTypeLabel; QLabel *cpuTypeLabel;
+74
View File
@@ -0,0 +1,74 @@
#include <RomsList.hpp>
#include <QHeaderView>
#include <QThread>
#include <GeneralSettings.hpp>
#include <Options.hpp>
#include <Mem.hpp>
RomsListTable::RomsListTable(GeneralSettings *general) {
verticalHeader()->hide();
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
setSizePolicy({QSizePolicy::Maximum, QSizePolicy::Maximum});
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSortingEnabled(true);
setColumnCount(4);
setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
setHorizontalHeaderItem(1, new QTableWidgetItem("Regions"));
setHorizontalHeaderItem(2, new QTableWidgetItem("Last played"));
setHorizontalHeaderItem(3, new QTableWidgetItem("Time played"));
connect(general, &GeneralSettings::romFolderSelected, this, [&] {
std::thread popThread([&] {
populate(Options::GetRomsPath());
emit populateFinished();
});
popThread.detach();
});
connect(general, &GeneralSettings::romFolderCleared, this, [&] {
for (int i = 0; i < rowCount(); i++)
removeRow(i);
romsList = {};
emit cleared();
});
std::thread popThread([&] {
populate(Options::GetRomsPath());
emit populateFinished();
});
popThread.detach();
}
void RomsListTable::populate(const std::string &romsPath) {
if (!romsPath.empty()) {
for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
if (!file.is_regular_file())
continue;
auto filename = file.path().string();
bool isPlain = std::ranges::any_of(std::array{".n64", ".z64", ".v64"},
[&](const std::string &ext) { return file.path().extension() == ext; });
bool isArchive =
std::ranges::any_of(std::array{".zip", ".7z", ".rar", ".tar"},
[&](const std::string &ext) { return file.path().extension() == ext; });
if (!isArchive && !isPlain)
continue;
auto rom = n64::Mem::LoadROM(isArchive, filename);
auto regions = n64::GameDB::match(rom);
if (rom.gameNameDB.empty())
rom.gameNameDB = fs::path(filename).stem().string();
romsList.push_back(
{rom.header.countryCode, rom.header.version, filename, rom.gameNameDB, regions, "Never", "0h 00m 00s"});
}
}
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <common.hpp>
#include <QTableWidget>
class GeneralSettings;
struct RomsListEntry {
u8 countryCode, version;
std::string path;
std::string name;
std::string region;
std::string lastPlayed;
std::string timePlayed;
};
class RomsListTable : public QTableWidget {
Q_OBJECT
void populate(const std::string &);
public:
std::vector<RomsListEntry> romsList;
RomsListTable(GeneralSettings *);
size_t size() { return romsList.size(); }
RomsListEntry &operator[](const size_t i) { return romsList[i]; }
signals:
void populateFinished();
void cleared();
};
+27
View File
@@ -3,6 +3,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QCoreApplication> #include <QCoreApplication>
#include <log.hpp> #include <log.hpp>
#include <QPushButton>
GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) { GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
selectedRomsFolderLabel = new QLabel(Options::GetRomsPath().c_str()); selectedRomsFolderLabel = new QLabel(Options::GetRomsPath().c_str());
@@ -19,6 +20,9 @@ GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
auto dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QCoreApplication::applicationDirPath(), auto dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QCoreApplication::applicationDirPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (dir.isEmpty())
return;
selectedSavesFolderLabel->setText(dir); selectedSavesFolderLabel->setText(dir);
Options::SetSavesPath(dir.toStdString()); Options::SetSavesPath(dir.toStdString());
settings.setValue("saves_path", dir); settings.setValue("saves_path", dir);
@@ -29,6 +33,9 @@ GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
auto dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QCoreApplication::applicationDirPath(), auto dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QCoreApplication::applicationDirPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (dir.isEmpty())
return;
selectedRomsFolderLabel->setText(dir); selectedRomsFolderLabel->setText(dir);
Options::SetRomsPath(dir.toStdString()); Options::SetRomsPath(dir.toStdString());
settings.setValue("roms_path", dir); settings.setValue("roms_path", dir);
@@ -38,12 +45,32 @@ GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
gl = new QGridLayout(); gl = new QGridLayout();
QPushButton *clearRoms = new QPushButton("Clear");
connect(clearRoms, &QPushButton::clicked, this, [&] {
selectedRomsFolderLabel->clear();
Options::SetRomsPath("");
settings.setValue("roms_path", "");
settings.sync();
emit romFolderCleared();
});
QPushButton *clearSaves = new QPushButton("Clear");
connect(clearSaves, &QPushButton::clicked, this, [&] {
selectedSavesFolderLabel->clear();
Options::SetSavesPath("");
settings.setValue("saves_path", "");
settings.sync();
});
gl->addWidget(new QLabel("ROMs path:"), 0, 0); gl->addWidget(new QLabel("ROMs path:"), 0, 0);
gl->addWidget(selectedRomsFolderLabel, 0, 1); gl->addWidget(selectedRomsFolderLabel, 0, 1);
gl->addWidget(romsFolderSelectButton, 0, 2); gl->addWidget(romsFolderSelectButton, 0, 2);
gl->addWidget(clearRoms, 0, 3);
gl->addWidget(new QLabel("Saves path:"), 1, 0); gl->addWidget(new QLabel("Saves path:"), 1, 0);
gl->addWidget(selectedSavesFolderLabel, 1, 1); gl->addWidget(selectedSavesFolderLabel, 1, 1);
gl->addWidget(savesFolderSelectButton, 1, 2); gl->addWidget(savesFolderSelectButton, 1, 2);
gl->addWidget(clearSaves, 1, 3);
setLayout(gl); setLayout(gl);
} }
@@ -19,4 +19,5 @@ class GeneralSettings final : public QWidget {
signals: signals:
void romFolderSelected(); void romFolderSelected();
void romFolderCleared();
}; };