diff --git a/src/frontend/KaizenGui.cpp b/src/frontend/KaizenGui.cpp index 3ec1a45..e9eaa1c 100644 --- a/src/frontend/KaizenGui.cpp +++ b/src/frontend/KaizenGui.cpp @@ -11,12 +11,28 @@ #include #include -void KaizenGui::populateRomsList(const std::string &romsPath) { - centralWidget->setCurrentWidget(romPathNotSet); - if (!romsPath.empty()) { - int i = 0; - centralWidget->setCurrentWidget(romsList); +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; @@ -37,24 +53,12 @@ void KaizenGui::populateRomsList(const std::string &romsPath) { auto regions = n64::GameDB::match(rom); if (rom.gameNameDB.empty()) - rom.gameNameDB = fs::path(filename).stem(); + rom.gameNameDB = fs::path(filename).stem().string(); - romsListPaths.push_back(filename); - romsList->insertRow(i); - - romsList->setItem( - i, 0, - new QTableWidgetItem(std::format("{} ({}) (Rev {})", rom.gameNameDB, - n64::GameDB::regionCodeToReadable(rom.header.countryCode), - rom.header.version) - .c_str())); - romsList->setItem(i, 1, new QTableWidgetItem(regions.c_str())); - romsList->setItem(i, 2, new QTableWidgetItem("Never")); - romsList->setItem(i, 3, new QTableWidgetItem("0h 0m 0s")); - i++; + romsList.push_back( + {rom.header.countryCode, rom.header.version, filename, rom.gameNameDB, regions, "Never", "0h 00m 00s"}); } } - currentHomeWidget = centralWidget->currentWidget(); } KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) { @@ -63,33 +67,40 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User SDL_AddGamepadMapping(gamecontrollerdb_str); hide(); - romsList->verticalHeader()->hide(); - romsList->setSizePolicy({QSizePolicy::Maximum, QSizePolicy::Maximum}); - romsList->setSelectionMode(QAbstractItemView::SingleSelection); - romsList->setSelectionBehavior(QAbstractItemView::SelectRows); - romsList->setEditTriggers(QAbstractItemView::NoEditTriggers); - romsList->setSortingEnabled(true); - romsList->setColumnCount(4); - romsList->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); - romsList->setHorizontalHeaderItem(1, new QTableWidgetItem("Regions")); - romsList->setHorizontalHeaderItem(2, new QTableWidgetItem("Last played")); - romsList->setHorizontalHeaderItem(3, new QTableWidgetItem("Time played")); - vulkanWidget = new RenderWidget(); vulkanWidget->hide(); centralWidget->addWidget(vulkanWidget); - centralWidget->addWidget(romsList); + centralWidget->addWidget(romsListTable); centralWidget->addWidget(romPathNotSet); - populateRomsList(Options::GetRomsPath()); - - connect(romsList, &QTableWidget::cellDoubleClicked, this, [&](int row, int) { - auto fileToLoad = fs::path(Options::GetRomsPath()) / romsListPaths[row]; - std::println("{}", fileToLoad.string()); - LoadROM(fileToLoad.string()); + populateRomsListThread = QThread::create([&] { + populateRomsList(Options::GetRomsPath()); + emit populateRomsListFinished(); }); + populateRomsListThread->start(); + + connect(this, &KaizenGui::populateRomsListFinished, this, [&] { + for (int i = 0; i < romsList.size(); i++) { + const auto &[countryCode, version, _, name, regions, lastPlayed, timePlayed] = romsList[i]; + + romsListTable->insertRow(i); + romsListTable->setItem( + i, 0, + new QTableWidgetItem( + std::format("{} ({}) (Rev {})", name, n64::GameDB::regionCodeToReadable(countryCode), version) + .c_str())); + romsListTable->setItem(i, 1, new QTableWidgetItem(regions.c_str())); + romsListTable->setItem(i, 2, new QTableWidgetItem(lastPlayed.c_str())); + romsListTable->setItem(i, 3, new QTableWidgetItem(timePlayed.c_str())); + } + }); + + connect(this, &KaizenGui::romsListNeedsPopulation, this, [&] { populateRomsListThread->start(); }); + + connect(romsListTable, &QTableWidget::cellDoubleClicked, this, [&](int row, int) { LoadROM(romsList[row].path); }); + installEventFilter(this); restoreGeometry(settings.value("geometry").toByteArray()); @@ -112,6 +123,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User setWindowTitle("Kaizen " KAIZEN_VERSION_STR); setMinimumSize(640, 480); setCentralWidget(centralWidget); + centralWidget->setLayout(new QVBoxLayout()); setAcceptDrops(true); @@ -184,7 +196,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User settingsWindow = new SettingsWindow(); connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show); connect(settingsWindow->general, &GeneralSettings::romFolderSelected, this, - [&] { populateRomsList(Options::GetRomsPath()); }); + [&] { emit romsListNeedsPopulation(); }); connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] { core.cpuType = Options::GetCpuType(); diff --git a/src/frontend/KaizenGui.hpp b/src/frontend/KaizenGui.hpp index 5250e4e..64672da 100644 --- a/src/frontend/KaizenGui.hpp +++ b/src/frontend/KaizenGui.hpp @@ -13,17 +13,35 @@ 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 romsList; + + public: + RomsListTable(); + public slots: + void populate(const std::string &); + signals: + void populateFinished(); +}; + class KaizenGui final : QMainWindow { Q_OBJECT void updateKeys(); void updateAxis(); bool eventFilter(QObject *, QEvent *) override; - void populateRomsList(const std::string &); bool fastForward = false; bool minimized = false; - std::vector romsListPaths{}; - SDL_Gamepad *gamepad = nullptr; bool gamepadConnected; float elapsed = 0.f; @@ -33,12 +51,12 @@ class KaizenGui final : QMainWindow { QWidget *currentHomeWidget; QLabel *romPathNotSet = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")"); - QTableWidget *romsList = new QTableWidget(); + RomsListTable *romsListTable = new RomsListTable(); QStackedWidget *centralWidget = new QStackedWidget(); SettingsWindow *settingsWindow; RenderWidget *vulkanWidget; QSettings settings; - QThread *emuThread; + QThread *emuThread, *populateRomsListThread; QTimer *statusBarTimer, *SDLeventsTimer; QLabel *fpsLabel; QLabel *cpuTypeLabel; @@ -59,6 +77,4 @@ class KaizenGui final : QMainWindow { void LoadTAS(const std::string &path) noexcept; void LoadROM(const std::string &path) noexcept; - signals: - void paused(); };