2020-09-21 17:17:34 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-06-06 11:10:33 +00:00
|
|
|
//
|
2020-09-21 17:17:34 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// GuiScraperMenu.cpp
|
2020-06-06 11:10:33 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// Game media scraper, including settings as well as the scraping start button.
|
|
|
|
// Submenu to the GuiMenu main menu.
|
|
|
|
// Will call GuiScraperMulti to perform the actual scraping.
|
2020-06-06 11:10:33 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#include "guis/GuiScraperMenu.h"
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
#include "FileData.h"
|
|
|
|
#include "FileSorts.h"
|
|
|
|
#include "SystemData.h"
|
2020-06-06 11:10:33 +00:00
|
|
|
#include "components/OptionListComponent.h"
|
|
|
|
#include "components/SwitchComponent.h"
|
|
|
|
#include "guis/GuiMsgBox.h"
|
2021-06-09 18:56:41 +00:00
|
|
|
#include "guis/GuiOfflineGenerator.h"
|
2020-06-06 11:10:33 +00:00
|
|
|
#include "guis/GuiScraperMulti.h"
|
|
|
|
#include "views/ViewController.h"
|
|
|
|
|
2020-11-06 19:27:41 +00:00
|
|
|
GuiScraperMenu::GuiScraperMenu(Window* window, std::string title)
|
2021-07-07 18:03:42 +00:00
|
|
|
: GuiComponent(window)
|
|
|
|
, mMenu(window, title)
|
2020-06-06 11:10:33 +00:00
|
|
|
{
|
2020-11-05 17:18:11 +00:00
|
|
|
// Scraper service.
|
2021-07-07 18:03:42 +00:00
|
|
|
mScraper = std::make_shared<OptionListComponent<std::string>>(mWindow, getHelpStyle(),
|
|
|
|
"SCRAPE FROM", false);
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<std::string> scrapers = getScraperList();
|
|
|
|
// Select either the first entry or the one read from the settings,
|
|
|
|
// just in case the scraper from settings has vanished.
|
|
|
|
for (auto it = scrapers.cbegin(); it != scrapers.cend(); it++)
|
2020-11-05 17:18:11 +00:00
|
|
|
mScraper->add(*it, *it, *it == Settings::getInstance()->getString("Scraper"));
|
|
|
|
mMenu.addWithLabel("SCRAPE FROM", mScraper);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Search filters, getSearches() will generate a queue of games to scrape
|
|
|
|
// based on the outcome of the checks below.
|
2021-07-07 18:03:42 +00:00
|
|
|
mFilters = std::make_shared<OptionListComponent<GameFilterFunc>>(mWindow, getHelpStyle(),
|
|
|
|
"SCRAPE THESE GAMES", false);
|
|
|
|
mFilters->add(
|
|
|
|
"ALL GAMES",
|
|
|
|
[](SystemData*, FileData*) -> bool {
|
|
|
|
// All games.
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
mFilters->add(
|
|
|
|
"FAVORITE GAMES",
|
|
|
|
[](SystemData*, FileData* g) -> bool {
|
|
|
|
// Favorite games.
|
|
|
|
return g->getFavorite();
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
mFilters->add(
|
|
|
|
"NO METADATA",
|
|
|
|
[](SystemData*, FileData* g) -> bool {
|
|
|
|
// No metadata.
|
|
|
|
return g->metadata.get("desc").empty();
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
mFilters->add(
|
|
|
|
"NO GAME IMAGE",
|
|
|
|
[](SystemData*, FileData* g) -> bool {
|
|
|
|
// No game image.
|
|
|
|
return g->getImagePath().empty();
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
mFilters->add(
|
|
|
|
"NO GAME VIDEO",
|
|
|
|
[](SystemData*, FileData* g) -> bool {
|
|
|
|
// No game video.
|
|
|
|
return g->getVideoPath().empty();
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
mFilters->add(
|
|
|
|
"FOLDERS ONLY",
|
|
|
|
[](SystemData*, FileData* g) -> bool {
|
|
|
|
// Folders only.
|
|
|
|
return g->getType() == FOLDER;
|
|
|
|
},
|
|
|
|
false);
|
2020-12-16 16:35:23 +00:00
|
|
|
|
|
|
|
mFilters->selectEntry(Settings::getInstance()->getInt("ScraperFilter"));
|
2021-01-26 20:36:25 +00:00
|
|
|
mMenu.addWithLabel("SCRAPE THESE GAMES", mFilters);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-16 16:35:23 +00:00
|
|
|
mMenu.addSaveFunc([this] {
|
|
|
|
if (mScraper->getSelected() != Settings::getInstance()->getString("Scraper")) {
|
|
|
|
Settings::getInstance()->setString("Scraper", mScraper->getSelected());
|
|
|
|
mMenu.setNeedsSaving();
|
|
|
|
}
|
|
|
|
// The filter setting is only retained during the program session i.e. it's not saved
|
2021-06-16 17:05:24 +00:00
|
|
|
// to es_settings.xml.
|
2020-12-16 16:35:23 +00:00
|
|
|
if (mFilters->getSelectedId() != Settings::getInstance()->getInt("ScraperFilter"))
|
|
|
|
Settings::getInstance()->setInt("ScraperFilter", mFilters->getSelectedId());
|
|
|
|
});
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Add systems (all systems with an existing platform ID are listed).
|
2021-07-07 18:03:42 +00:00
|
|
|
mSystems = std::make_shared<OptionListComponent<SystemData*>>(mWindow, getHelpStyle(),
|
|
|
|
"SCRAPE THESE SYSTEMS", true);
|
2020-06-21 12:25:28 +00:00
|
|
|
for (unsigned int i = 0; i < SystemData::sSystemVector.size(); i++) {
|
|
|
|
if (!SystemData::sSystemVector[i]->hasPlatformId(PlatformIds::PLATFORM_IGNORE)) {
|
2021-07-07 18:03:42 +00:00
|
|
|
mSystems->add(SystemData::sSystemVector[i]->getFullName(), SystemData::sSystemVector[i],
|
|
|
|
!SystemData::sSystemVector[i]->getPlatformIds().empty());
|
|
|
|
SystemData::sSystemVector[i]->getScrapeFlag() ? mSystems->selectEntry(i) :
|
|
|
|
mSystems->unselectEntry(i);
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
}
|
2021-01-26 20:36:25 +00:00
|
|
|
mMenu.addWithLabel("SCRAPE THESE SYSTEMS", mSystems);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-11-07 14:34:15 +00:00
|
|
|
addEntry("ACCOUNT SETTINGS", 0x777777FF, true, [this] {
|
2021-07-07 18:03:42 +00:00
|
|
|
// Open the account options menu.
|
2021-06-07 21:02:42 +00:00
|
|
|
openAccountOptions();
|
2020-11-07 14:34:15 +00:00
|
|
|
});
|
2020-08-05 17:31:59 +00:00
|
|
|
addEntry("CONTENT SETTINGS", 0x777777FF, true, [this] {
|
2020-11-05 17:18:11 +00:00
|
|
|
// If the scraper service has been changed before entering this menu, then save the
|
|
|
|
// settings so that the specific options supported by the respective scrapers
|
|
|
|
// can be enabled or disabled.
|
|
|
|
if (mScraper->getSelected() != Settings::getInstance()->getString("Scraper"))
|
|
|
|
mMenu.save();
|
2021-06-07 21:02:42 +00:00
|
|
|
openContentOptions();
|
|
|
|
});
|
|
|
|
addEntry("MIXIMAGE SETTINGS", 0x777777FF, true, [this] {
|
2021-07-07 18:03:42 +00:00
|
|
|
// Open the miximage options menu.
|
2021-06-07 21:02:42 +00:00
|
|
|
openMiximageOptions();
|
2020-08-05 17:31:59 +00:00
|
|
|
});
|
|
|
|
addEntry("OTHER SETTINGS", 0x777777FF, true, [this] {
|
2020-11-05 17:18:11 +00:00
|
|
|
// If the scraper service has been changed before entering this menu, then save the
|
|
|
|
// settings so that the specific options supported by the respective scrapers
|
|
|
|
// can be enabled or disabled.
|
|
|
|
if (mScraper->getSelected() != Settings::getInstance()->getString("Scraper"))
|
|
|
|
mMenu.save();
|
2021-06-07 21:02:42 +00:00
|
|
|
openOtherOptions();
|
2020-08-05 17:31:59 +00:00
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
addChild(&mMenu);
|
|
|
|
|
|
|
|
mMenu.addButton("START", "start", std::bind(&GuiScraperMenu::pressedStart, this));
|
|
|
|
mMenu.addButton("BACK", "back", [&] { delete this; });
|
|
|
|
|
|
|
|
setSize(mMenu.getSize());
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f,
|
|
|
|
Renderer::getScreenHeight() * 0.13f);
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GuiScraperMenu::~GuiScraperMenu()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
// Save the scrape flags to the system settings so that they are
|
|
|
|
// remembered throughout the program session.
|
|
|
|
std::vector<SystemData*> sys = mSystems->getSelectedObjects();
|
2021-07-07 18:03:42 +00:00
|
|
|
for (auto it = SystemData::sSystemVector.cbegin(); // Line break.
|
|
|
|
it != SystemData::sSystemVector.cend(); it++) {
|
|
|
|
(*it)->setScrapeFlag(false);
|
2020-06-21 12:25:28 +00:00
|
|
|
for (auto it_sys = sys.cbegin(); it_sys != sys.cend(); it_sys++) {
|
|
|
|
if ((*it)->getFullName() == (*it_sys)->getFullName())
|
|
|
|
(*it)->setScrapeFlag(true);
|
|
|
|
}
|
|
|
|
}
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
2021-06-07 21:02:42 +00:00
|
|
|
void GuiScraperMenu::openAccountOptions()
|
2020-11-07 14:34:15 +00:00
|
|
|
{
|
|
|
|
auto s = new GuiSettings(mWindow, "ACCOUNT SETTINGS");
|
|
|
|
|
|
|
|
// Whether to use the ScreenScraper account when scraping.
|
|
|
|
auto scraper_use_account_screenscraper = std::make_shared<SwitchComponent>(mWindow);
|
2021-07-07 18:03:42 +00:00
|
|
|
scraper_use_account_screenscraper->setState(
|
|
|
|
Settings::getInstance()->getBool("ScraperUseAccountScreenScraper"));
|
2020-11-07 14:34:15 +00:00
|
|
|
s->addWithLabel("USE THIS ACCOUNT FOR SCREENSCRAPER", scraper_use_account_screenscraper);
|
|
|
|
s->addSaveFunc([scraper_use_account_screenscraper, s] {
|
|
|
|
if (scraper_use_account_screenscraper->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperUseAccountScreenScraper")) {
|
2020-11-07 14:34:15 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperUseAccountScreenScraper",
|
2021-07-07 18:03:42 +00:00
|
|
|
scraper_use_account_screenscraper->getState());
|
2020-11-07 14:34:15 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// ScreenScraper username.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto scraper_username_screenscraper = std::make_shared<TextComponent>(
|
|
|
|
mWindow, "", Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_RIGHT);
|
2020-11-07 14:34:15 +00:00
|
|
|
s->addEditableTextComponent("SCREENSCRAPER USERNAME", scraper_username_screenscraper,
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("ScraperUsernameScreenScraper"));
|
2020-11-07 14:34:15 +00:00
|
|
|
s->addSaveFunc([scraper_username_screenscraper, s] {
|
|
|
|
if (scraper_username_screenscraper->getValue() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("ScraperUsernameScreenScraper")) {
|
2020-11-07 14:34:15 +00:00
|
|
|
Settings::getInstance()->setString("ScraperUsernameScreenScraper",
|
2021-07-07 18:03:42 +00:00
|
|
|
scraper_username_screenscraper->getValue());
|
2020-11-07 14:34:15 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// ScreenScraper password.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto scraper_password_screenscraper = std::make_shared<TextComponent>(
|
|
|
|
mWindow, "", Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_RIGHT);
|
2020-11-07 14:34:15 +00:00
|
|
|
std::string passwordMasked;
|
|
|
|
if (Settings::getInstance()->getString("ScraperPasswordScreenScraper") != "") {
|
|
|
|
passwordMasked = "********";
|
|
|
|
scraper_password_screenscraper->setHiddenValue(
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("ScraperPasswordScreenScraper"));
|
2020-11-07 14:34:15 +00:00
|
|
|
}
|
2021-07-07 18:03:42 +00:00
|
|
|
s->addEditableTextComponent("SCREENSCRAPER PASSWORD", scraper_password_screenscraper,
|
|
|
|
passwordMasked, "", true);
|
2020-11-07 14:34:15 +00:00
|
|
|
s->addSaveFunc([scraper_password_screenscraper, s] {
|
|
|
|
if (scraper_password_screenscraper->getHiddenValue() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("ScraperPasswordScreenScraper")) {
|
2020-11-07 14:34:15 +00:00
|
|
|
Settings::getInstance()->setString("ScraperPasswordScreenScraper",
|
2021-07-07 18:03:42 +00:00
|
|
|
scraper_password_screenscraper->getHiddenValue());
|
2020-11-07 14:34:15 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
|
|
|
|
2021-06-07 21:02:42 +00:00
|
|
|
void GuiScraperMenu::openContentOptions()
|
2020-06-06 11:10:33 +00:00
|
|
|
{
|
2021-06-07 21:02:42 +00:00
|
|
|
auto s = new GuiSettings(mWindow, "CONTENT SETTINGS");
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Scrape game names.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto scrape_game_names = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_game_names->setState(Settings::getInstance()->getBool("ScrapeGameNames"));
|
|
|
|
s->addWithLabel("SCRAPE GAME NAMES", scrape_game_names);
|
|
|
|
s->addSaveFunc([scrape_game_names, s] {
|
|
|
|
if (scrape_game_names->getState() != Settings::getInstance()->getBool("ScrapeGameNames")) {
|
|
|
|
Settings::getInstance()->setBool("ScrapeGameNames", scrape_game_names->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Scrape ratings.
|
|
|
|
auto scrape_ratings = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_ratings->setState(Settings::getInstance()->getBool("ScrapeRatings"));
|
|
|
|
s->addWithLabel("SCRAPE RATINGS", scrape_ratings);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_ratings, s] {
|
|
|
|
if (scrape_ratings->getState() != Settings::getInstance()->getBool("ScrapeRatings")) {
|
|
|
|
Settings::getInstance()->setBool("ScrapeRatings", scrape_ratings->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-08-05 17:31:59 +00:00
|
|
|
// Ratings are not supported by TheGamesDB, so disable the option if this scraper is selected.
|
|
|
|
if (Settings::getInstance()->getString("Scraper") == "thegamesdb") {
|
2020-12-15 17:49:43 +00:00
|
|
|
scrape_ratings->setEnabled(false);
|
2020-08-05 17:31:59 +00:00
|
|
|
scrape_ratings->setOpacity(DISABLED_OPACITY);
|
2021-07-07 18:03:42 +00:00
|
|
|
scrape_ratings->getParent()
|
|
|
|
->getChild(scrape_ratings->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-08-05 17:31:59 +00:00
|
|
|
}
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Scrape other metadata.
|
|
|
|
auto scrape_metadata = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_metadata->setState(Settings::getInstance()->getBool("ScrapeMetadata"));
|
|
|
|
s->addWithLabel("SCRAPE OTHER METADATA", scrape_metadata);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_metadata, s] {
|
|
|
|
if (scrape_metadata->getState() != Settings::getInstance()->getBool("ScrapeMetadata")) {
|
|
|
|
Settings::getInstance()->setBool("ScrapeMetadata", scrape_metadata->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-08-05 20:38:44 +00:00
|
|
|
// Scrape videos.
|
|
|
|
auto scrape_videos = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_videos->setState(Settings::getInstance()->getBool("ScrapeVideos"));
|
|
|
|
s->addWithLabel("SCRAPE VIDEOS", scrape_videos);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_videos, s] {
|
|
|
|
if (scrape_videos->getState() != Settings::getInstance()->getBool("ScrapeVideos")) {
|
|
|
|
Settings::getInstance()->setBool("ScrapeVideos", scrape_videos->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-08-05 20:38:44 +00:00
|
|
|
|
|
|
|
// Videos are not supported by TheGamesDB, so disable the option if this scraper is selected.
|
|
|
|
if (Settings::getInstance()->getString("Scraper") == "thegamesdb") {
|
2020-12-15 17:49:43 +00:00
|
|
|
scrape_videos->setEnabled(false);
|
2020-08-05 20:38:44 +00:00
|
|
|
scrape_videos->setOpacity(DISABLED_OPACITY);
|
2021-07-07 18:03:42 +00:00
|
|
|
scrape_videos->getParent()
|
|
|
|
->getChild(scrape_videos->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-08-05 20:38:44 +00:00
|
|
|
}
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Scrape screenshots images.
|
|
|
|
auto scrape_screenshots = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_screenshots->setState(Settings::getInstance()->getBool("ScrapeScreenshots"));
|
|
|
|
s->addWithLabel("SCRAPE SCREENSHOT IMAGES", scrape_screenshots);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_screenshots, s] {
|
|
|
|
if (scrape_screenshots->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("ScrapeScreenshots")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("ScrapeScreenshots", scrape_screenshots->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Scrape cover images.
|
|
|
|
auto scrape_covers = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_covers->setState(Settings::getInstance()->getBool("ScrapeCovers"));
|
|
|
|
s->addWithLabel("SCRAPE BOX COVER IMAGES", scrape_covers);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_covers, s] {
|
|
|
|
if (scrape_covers->getState() != Settings::getInstance()->getBool("ScrapeCovers")) {
|
|
|
|
Settings::getInstance()->setBool("ScrapeCovers", scrape_covers->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Scrape marquee images.
|
|
|
|
auto scrape_marquees = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_marquees->setState(Settings::getInstance()->getBool("ScrapeMarquees"));
|
|
|
|
s->addWithLabel("SCRAPE MARQUEE (WHEEL) IMAGES", scrape_marquees);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_marquees, s] {
|
|
|
|
if (scrape_marquees->getState() != Settings::getInstance()->getBool("ScrapeMarquees")) {
|
|
|
|
Settings::getInstance()->setBool("ScrapeMarquees", scrape_marquees->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Scrape 3D box images.
|
|
|
|
auto scrape_3dboxes = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scrape_3dboxes->setState(Settings::getInstance()->getBool("Scrape3DBoxes"));
|
|
|
|
s->addWithLabel("SCRAPE 3D BOX IMAGES", scrape_3dboxes);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scrape_3dboxes, s] {
|
|
|
|
if (scrape_3dboxes->getState() != Settings::getInstance()->getBool("Scrape3DBoxes")) {
|
|
|
|
Settings::getInstance()->setBool("Scrape3DBoxes", scrape_3dboxes->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-08-05 17:31:59 +00:00
|
|
|
// 3D box images are not supported by TheGamesDB, so disable the option if this scraper
|
|
|
|
// is selected.
|
|
|
|
if (Settings::getInstance()->getString("Scraper") == "thegamesdb") {
|
2020-12-15 17:49:43 +00:00
|
|
|
scrape_3dboxes->setEnabled(false);
|
2020-08-05 17:31:59 +00:00
|
|
|
scrape_3dboxes->setOpacity(DISABLED_OPACITY);
|
2021-07-07 18:03:42 +00:00
|
|
|
scrape_3dboxes->getParent()
|
|
|
|
->getChild(scrape_3dboxes->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-08-05 17:31:59 +00:00
|
|
|
}
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
mWindow->pushGui(s);
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
2021-06-07 21:02:42 +00:00
|
|
|
void GuiScraperMenu::openMiximageOptions()
|
|
|
|
{
|
|
|
|
auto s = new GuiSettings(mWindow, "MIXIMAGE SETTINGS");
|
|
|
|
|
|
|
|
// Miximage resolution.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto miximage_resolution = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
mWindow, getHelpStyle(), "MIXIMAGE RESOLUTION", false);
|
2021-06-07 21:02:42 +00:00
|
|
|
std::string selectedResolution = Settings::getInstance()->getString("MiximageResolution");
|
2021-07-07 18:03:42 +00:00
|
|
|
miximage_resolution->add("1280x960", "1280x960", selectedResolution == "1280x960");
|
|
|
|
miximage_resolution->add("1920x1440", "1920x1440", selectedResolution == "1920x1440");
|
|
|
|
miximage_resolution->add("640x480", "640x480", selectedResolution == "640x480");
|
2021-06-07 21:02:42 +00:00
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
|
|
|
// configuration file. Simply set the resolution to "1280x960" in this case.
|
|
|
|
if (miximage_resolution->getSelectedObjects().size() == 0)
|
|
|
|
miximage_resolution->selectEntry(0);
|
|
|
|
s->addWithLabel("MIXIMAGE RESOLUTION", miximage_resolution);
|
|
|
|
s->addSaveFunc([miximage_resolution, s] {
|
|
|
|
if (miximage_resolution->getSelected() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("MiximageResolution")) {
|
|
|
|
Settings::getInstance()->setString("MiximageResolution",
|
|
|
|
miximage_resolution->getSelected());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Screenshot scaling method.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto miximage_scaling = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
mWindow, getHelpStyle(), "SCREENSHOT SCALING", false);
|
2021-06-07 21:02:42 +00:00
|
|
|
std::string selectedScaling = Settings::getInstance()->getString("MiximageScreenshotScaling");
|
2021-07-07 18:03:42 +00:00
|
|
|
miximage_scaling->add("sharp", "sharp", selectedScaling == "sharp");
|
|
|
|
miximage_scaling->add("smooth", "smooth", selectedScaling == "smooth");
|
2021-06-07 21:02:42 +00:00
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
|
|
|
// configuration file. Simply set the scaling method to "sharp" in this case.
|
|
|
|
if (miximage_scaling->getSelectedObjects().size() == 0)
|
|
|
|
miximage_scaling->selectEntry(0);
|
|
|
|
s->addWithLabel("SCREENSHOT SCALING METHOD", miximage_scaling);
|
|
|
|
s->addSaveFunc([miximage_scaling, s] {
|
|
|
|
if (miximage_scaling->getSelected() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("MiximageScreenshotScaling")) {
|
|
|
|
Settings::getInstance()->setString("MiximageScreenshotScaling",
|
|
|
|
miximage_scaling->getSelected());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to generate miximages when scraping.
|
|
|
|
auto miximage_generate = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
miximage_generate->setState(Settings::getInstance()->getBool("MiximageGenerate"));
|
|
|
|
s->addWithLabel("GENERATE MIXIMAGES WHEN SCRAPING", miximage_generate);
|
|
|
|
s->addSaveFunc([miximage_generate, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (miximage_generate->getState() != Settings::getInstance()->getBool("MiximageGenerate")) {
|
2021-06-07 21:02:42 +00:00
|
|
|
Settings::getInstance()->setBool("MiximageGenerate", miximage_generate->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to overwrite miximages (both for the scraper and offline generator).
|
|
|
|
auto miximage_overwrite = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
miximage_overwrite->setState(Settings::getInstance()->getBool("MiximageOverwrite"));
|
|
|
|
s->addWithLabel("OVERWRITE MIXIMAGES (SCRAPER/OFFLINE GENERATOR)", miximage_overwrite);
|
|
|
|
s->addSaveFunc([miximage_overwrite, s] {
|
|
|
|
if (miximage_overwrite->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MiximageOverwrite")) {
|
2021-06-07 21:02:42 +00:00
|
|
|
Settings::getInstance()->setBool("MiximageOverwrite", miximage_overwrite->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to remove letterboxes from the screenshots.
|
|
|
|
auto remove_letterboxes = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
remove_letterboxes->setState(Settings::getInstance()->getBool("MiximageRemoveLetterboxes"));
|
|
|
|
s->addWithLabel("REMOVE LETTERBOXES FROM SCREENSHOTS", remove_letterboxes);
|
|
|
|
s->addSaveFunc([remove_letterboxes, s] {
|
|
|
|
if (remove_letterboxes->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MiximageRemoveLetterboxes")) {
|
2021-06-07 21:02:42 +00:00
|
|
|
Settings::getInstance()->setBool("MiximageRemoveLetterboxes",
|
2021-07-07 18:03:42 +00:00
|
|
|
remove_letterboxes->getState());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to remove pillarboxes from the screenshots.
|
|
|
|
auto remove_pillarboxes = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
remove_pillarboxes->setState(Settings::getInstance()->getBool("MiximageRemovePillarboxes"));
|
|
|
|
s->addWithLabel("REMOVE PILLARBOXES FROM SCREENSHOTS", remove_pillarboxes);
|
|
|
|
s->addSaveFunc([remove_pillarboxes, s] {
|
|
|
|
if (remove_pillarboxes->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MiximageRemovePillarboxes")) {
|
2021-06-07 21:02:42 +00:00
|
|
|
Settings::getInstance()->setBool("MiximageRemovePillarboxes",
|
2021-07-07 18:03:42 +00:00
|
|
|
remove_pillarboxes->getState());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to include marquee images.
|
|
|
|
auto miximage_marquee = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
miximage_marquee->setState(Settings::getInstance()->getBool("MiximageIncludeMarquee"));
|
|
|
|
s->addWithLabel("INCLUDE MARQUEE IMAGE", miximage_marquee);
|
|
|
|
s->addSaveFunc([miximage_marquee, s] {
|
|
|
|
if (miximage_marquee->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MiximageIncludeMarquee")) {
|
|
|
|
Settings::getInstance()->setBool("MiximageIncludeMarquee",
|
|
|
|
miximage_marquee->getState());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to include box images.
|
|
|
|
auto miximage_box = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
miximage_box->setState(Settings::getInstance()->getBool("MiximageIncludeBox"));
|
|
|
|
s->addWithLabel("INCLUDE BOX IMAGE", miximage_box);
|
|
|
|
s->addSaveFunc([miximage_box, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (miximage_box->getState() != Settings::getInstance()->getBool("MiximageIncludeBox")) {
|
|
|
|
Settings::getInstance()->setBool("MiximageIncludeBox", miximage_box->getState());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Whether to use cover image if there is no 3D box image.
|
|
|
|
auto miximage_cover_fallback = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
miximage_cover_fallback->setState(Settings::getInstance()->getBool("MiximageCoverFallback"));
|
|
|
|
s->addWithLabel("USE COVER IMAGE IF 3D BOX IS MISSING", miximage_cover_fallback);
|
|
|
|
s->addSaveFunc([miximage_cover_fallback, s] {
|
|
|
|
if (miximage_cover_fallback->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MiximageCoverFallback")) {
|
|
|
|
Settings::getInstance()->setBool("MiximageCoverFallback",
|
|
|
|
miximage_cover_fallback->getState());
|
2021-06-07 21:02:42 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-06-09 18:56:41 +00:00
|
|
|
// Miximage offline generator.
|
|
|
|
ComponentListRow offline_generator_row;
|
|
|
|
offline_generator_row.elements.clear();
|
2021-07-07 18:03:42 +00:00
|
|
|
offline_generator_row.addElement(std::make_shared<TextComponent>(mWindow, "OFFLINE GENERATOR",
|
|
|
|
Font::get(FONT_SIZE_MEDIUM),
|
|
|
|
0x777777FF),
|
|
|
|
true);
|
2021-06-09 18:56:41 +00:00
|
|
|
offline_generator_row.addElement(makeArrow(mWindow), false);
|
|
|
|
offline_generator_row.makeAcceptInputHandler(
|
2021-07-07 18:03:42 +00:00
|
|
|
std::bind(&GuiScraperMenu::openOfflineGenerator, this, s));
|
2021-06-09 18:56:41 +00:00
|
|
|
s->addRow(offline_generator_row);
|
|
|
|
|
2021-06-07 21:02:42 +00:00
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
|
|
|
|
2021-06-09 18:56:41 +00:00
|
|
|
void GuiScraperMenu::openOfflineGenerator(GuiSettings* settings)
|
|
|
|
{
|
|
|
|
if (mSystems->getSelectedObjects().empty()) {
|
|
|
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
2021-07-07 18:03:42 +00:00
|
|
|
"THE MIXIMAGE GENERATOR USES THE SAME SYSTEM\n"
|
|
|
|
"SELECTIONS AS THE SCRAPER, SO PLEASE SELECT\n"
|
|
|
|
"AT LEAST ONE SYSTEM TO GENERATE IMAGES FOR"));
|
2021-06-09 18:56:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always save the settings before starting the generator, in case any of the
|
|
|
|
// miximage settings were modified.
|
|
|
|
settings->save();
|
|
|
|
// Also unset the save flag so that a double saving does not take place when closing
|
|
|
|
// the miximage options menu later on.
|
|
|
|
settings->setNeedsSaving(false);
|
|
|
|
|
|
|
|
// Build the queue of games to process.
|
|
|
|
std::queue<FileData*> gameQueue;
|
|
|
|
std::vector<SystemData*> systems = mSystems->getSelectedObjects();
|
|
|
|
|
|
|
|
for (auto sys = systems.cbegin(); sys != systems.cend(); sys++) {
|
|
|
|
std::vector<FileData*> games = (*sys)->getRootFolder()->getChildrenRecursive();
|
|
|
|
|
|
|
|
// Sort the games by "filename, ascending".
|
|
|
|
std::stable_sort(games.begin(), games.end(), FileSorts::SortTypes.at(0).comparisonFunction);
|
|
|
|
|
|
|
|
for (FileData* game : games)
|
|
|
|
gameQueue.push(game);
|
|
|
|
}
|
|
|
|
|
|
|
|
mWindow->pushGui(new GuiOfflineGenerator(mWindow, gameQueue));
|
|
|
|
}
|
|
|
|
|
2021-06-07 21:02:42 +00:00
|
|
|
void GuiScraperMenu::openOtherOptions()
|
2020-06-06 11:10:33 +00:00
|
|
|
{
|
2021-06-07 21:02:42 +00:00
|
|
|
auto s = new GuiSettings(mWindow, "OTHER SETTINGS");
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Scraper region.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto scraper_region = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
mWindow, getHelpStyle(), "REGION", false);
|
2021-01-26 20:04:16 +00:00
|
|
|
std::string selectedScraperRegion = Settings::getInstance()->getString("ScraperRegion");
|
2021-07-07 18:03:42 +00:00
|
|
|
// clang-format off
|
2021-01-26 20:04:16 +00:00
|
|
|
scraper_region->add("Europe", "eu", selectedScraperRegion == "eu");
|
|
|
|
scraper_region->add("Japan", "jp", selectedScraperRegion == "jp");
|
|
|
|
scraper_region->add("USA", "us", selectedScraperRegion == "us");
|
|
|
|
scraper_region->add("World", "wor", selectedScraperRegion == "wor");
|
2021-07-07 18:03:42 +00:00
|
|
|
// clang-format on
|
2021-01-26 20:04:16 +00:00
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
2021-06-07 21:02:42 +00:00
|
|
|
// configuration file. Simply set the region to "Europe" in this case.
|
2021-01-26 20:04:16 +00:00
|
|
|
if (scraper_region->getSelectedObjects().size() == 0)
|
|
|
|
scraper_region->selectEntry(0);
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addWithLabel("REGION", scraper_region);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_region, s] {
|
|
|
|
if (scraper_region->getSelected() != Settings::getInstance()->getString("ScraperRegion")) {
|
|
|
|
Settings::getInstance()->setString("ScraperRegion", scraper_region->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2020-08-05 17:31:59 +00:00
|
|
|
// Regions are not supported by TheGamesDB, so disable the option if this scraper is selected.
|
|
|
|
if (Settings::getInstance()->getString("Scraper") == "thegamesdb") {
|
2020-12-15 17:49:43 +00:00
|
|
|
scraper_region->setEnabled(false);
|
2020-08-05 17:31:59 +00:00
|
|
|
scraper_region->setOpacity(DISABLED_OPACITY);
|
2021-07-07 18:03:42 +00:00
|
|
|
scraper_region->getParent()
|
|
|
|
->getChild(scraper_region->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-08-05 17:31:59 +00:00
|
|
|
}
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Scraper language.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto scraper_language = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
mWindow, getHelpStyle(), "PREFERRED LANGUAGE", false);
|
2021-01-26 20:04:16 +00:00
|
|
|
std::string selectedScraperLanguage = Settings::getInstance()->getString("ScraperLanguage");
|
2021-07-07 18:03:42 +00:00
|
|
|
// clang-format off
|
2021-01-28 19:47:07 +00:00
|
|
|
scraper_language->add("English", "en", selectedScraperLanguage == "en");
|
|
|
|
scraper_language->add("Español", "es", selectedScraperLanguage == "es");
|
|
|
|
scraper_language->add("Português", "pt", selectedScraperLanguage == "pt");
|
|
|
|
scraper_language->add("Français", "fr", selectedScraperLanguage == "fr");
|
|
|
|
scraper_language->add("Deutsch", "de", selectedScraperLanguage == "de");
|
|
|
|
scraper_language->add("Italiano", "it", selectedScraperLanguage == "it");
|
|
|
|
scraper_language->add("Nederlands", "nl", selectedScraperLanguage == "nl");
|
|
|
|
scraper_language->add("日本語", "ja", selectedScraperLanguage == "ja");
|
|
|
|
scraper_language->add("简体中文", "zh", selectedScraperLanguage == "zh");
|
|
|
|
scraper_language->add("한국어", "ko", selectedScraperLanguage == "ko");
|
|
|
|
scraper_language->add("Русский", "ru", selectedScraperLanguage == "ru");
|
|
|
|
scraper_language->add("Dansk", "da", selectedScraperLanguage == "da");
|
|
|
|
scraper_language->add("Suomi", "fi", selectedScraperLanguage == "fi");
|
|
|
|
scraper_language->add("Svenska", "sv", selectedScraperLanguage == "sv");
|
|
|
|
scraper_language->add("Magyar", "hu", selectedScraperLanguage == "hu");
|
|
|
|
scraper_language->add("Norsk", "no", selectedScraperLanguage == "no");
|
|
|
|
scraper_language->add("Polski", "pl", selectedScraperLanguage == "pl");
|
|
|
|
scraper_language->add("Čeština", "cz", selectedScraperLanguage == "cz");
|
|
|
|
scraper_language->add("Slovenčina", "sk", selectedScraperLanguage == "sk");
|
|
|
|
scraper_language->add("Türkçe", "tr", selectedScraperLanguage == "tr");
|
2021-07-11 11:31:43 +00:00
|
|
|
// clang-format on
|
2021-01-26 20:04:16 +00:00
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
2021-06-07 21:02:42 +00:00
|
|
|
// configuration file. Simply set the language to "English" in this case.
|
2021-01-26 20:04:16 +00:00
|
|
|
if (scraper_language->getSelectedObjects().size() == 0)
|
|
|
|
scraper_language->selectEntry(0);
|
|
|
|
s->addWithLabel("PREFERRED LANGUAGE", scraper_language);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_language, s] {
|
|
|
|
if (scraper_language->getSelected() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getString("ScraperLanguage")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setString("ScraperLanguage", scraper_language->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2020-08-05 17:31:59 +00:00
|
|
|
// Languages are not supported by TheGamesDB, so disable the option if this scraper is selected.
|
|
|
|
if (Settings::getInstance()->getString("Scraper") == "thegamesdb") {
|
2020-12-15 17:49:43 +00:00
|
|
|
scraper_language->setEnabled(false);
|
2020-08-05 17:31:59 +00:00
|
|
|
scraper_language->setOpacity(DISABLED_OPACITY);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_language->getParent()
|
|
|
|
->getChild(scraper_language->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-08-05 17:31:59 +00:00
|
|
|
}
|
|
|
|
|
2020-10-19 19:05:04 +00:00
|
|
|
// Overwrite files and data.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto scraper_overwrite_data = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scraper_overwrite_data->setState(Settings::getInstance()->getBool("ScraperOverwriteData"));
|
|
|
|
s->addWithLabel("OVERWRITE FILES AND DATA", scraper_overwrite_data);
|
|
|
|
s->addSaveFunc([scraper_overwrite_data, s] {
|
|
|
|
if (scraper_overwrite_data->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperOverwriteData")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperOverwriteData",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_overwrite_data->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-10-19 19:05:04 +00:00
|
|
|
|
2020-12-18 15:35:19 +00:00
|
|
|
// Halt scraping on invalid media files.
|
|
|
|
auto scraper_halt_on_invalid_media = std::make_shared<SwitchComponent>(mWindow);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_halt_on_invalid_media->setState(
|
|
|
|
Settings::getInstance()->getBool("ScraperHaltOnInvalidMedia"));
|
2020-12-18 15:35:19 +00:00
|
|
|
s->addWithLabel("HALT ON INVALID MEDIA FILES", scraper_halt_on_invalid_media);
|
|
|
|
s->addSaveFunc([scraper_halt_on_invalid_media, s] {
|
|
|
|
if (scraper_halt_on_invalid_media->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperHaltOnInvalidMedia")) {
|
2020-12-18 15:35:19 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperHaltOnInvalidMedia",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_halt_on_invalid_media->getState());
|
2020-12-18 15:35:19 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-01-26 20:36:25 +00:00
|
|
|
// Search using metadata names.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto scraper_search_metadata_name = std::make_shared<SwitchComponent>(mWindow);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_search_metadata_name->setState(
|
|
|
|
Settings::getInstance()->getBool("ScraperSearchMetadataName"));
|
2021-01-26 20:36:25 +00:00
|
|
|
s->addWithLabel("SEARCH USING METADATA NAMES", scraper_search_metadata_name);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_search_metadata_name, s] {
|
|
|
|
if (scraper_search_metadata_name->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperSearchMetadataName")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperSearchMetadataName",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_search_metadata_name->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-10-10 11:05:12 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Interactive scraping.
|
|
|
|
auto scraper_interactive = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scraper_interactive->setState(Settings::getInstance()->getBool("ScraperInteractive"));
|
|
|
|
s->addWithLabel("INTERACTIVE MODE", scraper_interactive);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_interactive, s] {
|
|
|
|
if (scraper_interactive->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperInteractive")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperInteractive", scraper_interactive->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Semi-automatic scraping.
|
|
|
|
auto scraper_semiautomatic = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scraper_semiautomatic->setState(Settings::getInstance()->getBool("ScraperSemiautomatic"));
|
|
|
|
s->addWithLabel("AUTO-ACCEPT SINGLE GAME MATCHES", scraper_semiautomatic);
|
2021-07-11 11:31:43 +00:00
|
|
|
s->addSaveFunc([scraper_semiautomatic, s] {
|
|
|
|
if (scraper_semiautomatic->getState() !=
|
|
|
|
Settings::getInstance()->getBool("ScraperSemiautomatic")) {
|
2020-06-21 12:25:28 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperSemiautomatic",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_semiautomatic->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-15 17:49:43 +00:00
|
|
|
// If interactive mode is set to off, then disable this option.
|
|
|
|
if (!Settings::getInstance()->getBool("ScraperInteractive")) {
|
|
|
|
scraper_semiautomatic->setEnabled(false);
|
|
|
|
scraper_semiautomatic->setOpacity(DISABLED_OPACITY);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_semiautomatic->getParent()
|
|
|
|
->getChild(scraper_semiautomatic->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-12-15 17:49:43 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 09:27:16 +00:00
|
|
|
// Respect the per-file multi-scraper exclusion flag.
|
|
|
|
auto scraper_respect_exclusions = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scraper_respect_exclusions->setState(
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperRespectExclusions"));
|
2020-08-06 09:27:16 +00:00
|
|
|
s->addWithLabel("RESPECT PER-FILE SCRAPER EXCLUSIONS", scraper_respect_exclusions);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_respect_exclusions, s] {
|
|
|
|
if (scraper_respect_exclusions->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperRespectExclusions")) {
|
2020-08-06 09:27:16 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperRespectExclusions",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_respect_exclusions->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-08-06 09:27:16 +00:00
|
|
|
|
2020-08-06 13:12:04 +00:00
|
|
|
// Exclude files recursively for excluded folders.
|
|
|
|
auto scraper_exclude_recursively = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
scraper_exclude_recursively->setState(
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperExcludeRecursively"));
|
2020-08-06 13:12:04 +00:00
|
|
|
s->addWithLabel("EXCLUDE FOLDERS RECURSIVELY", scraper_exclude_recursively);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_exclude_recursively, s] {
|
|
|
|
if (scraper_exclude_recursively->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperExcludeRecursively")) {
|
2020-08-06 13:12:04 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperExcludeRecursively",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_exclude_recursively->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-08-06 13:12:04 +00:00
|
|
|
|
2020-12-15 17:49:43 +00:00
|
|
|
// If respecting excluded files is set to off, then disable this option.
|
|
|
|
if (!Settings::getInstance()->getBool("ScraperRespectExclusions")) {
|
|
|
|
scraper_exclude_recursively->setEnabled(false);
|
|
|
|
scraper_exclude_recursively->setOpacity(DISABLED_OPACITY);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_exclude_recursively->getParent()
|
|
|
|
->getChild(scraper_exclude_recursively->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-12-15 17:49:43 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 13:12:04 +00:00
|
|
|
// Include actual folders when scraping.
|
|
|
|
auto scraper_include_folders = std::make_shared<SwitchComponent>(mWindow);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_include_folders->setState(Settings::getInstance()->getBool("ScraperIncludeFolders"));
|
2020-08-06 13:12:04 +00:00
|
|
|
s->addWithLabel("SCRAPE ACTUAL FOLDERS", scraper_include_folders);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([scraper_include_folders, s] {
|
|
|
|
if (scraper_include_folders->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperIncludeFolders")) {
|
2020-08-06 13:12:04 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperIncludeFolders",
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_include_folders->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-08-06 13:12:04 +00:00
|
|
|
|
2021-05-24 16:51:16 +00:00
|
|
|
// Retry search on peer verification errors (TLS/certificate issues).
|
|
|
|
auto retry_peer_verification = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
retry_peer_verification->setState(
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperRetryPeerVerification"));
|
2021-05-29 11:03:53 +00:00
|
|
|
s->addWithLabel("AUTO-RETRY ON PEER VERIFICATION ERRORS", retry_peer_verification);
|
2021-05-24 16:51:16 +00:00
|
|
|
s->addSaveFunc([retry_peer_verification, s] {
|
|
|
|
if (retry_peer_verification->getState() !=
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperRetryPeerVerification")) {
|
2021-05-24 16:51:16 +00:00
|
|
|
Settings::getInstance()->setBool("ScraperRetryPeerVerification",
|
2021-07-11 11:31:43 +00:00
|
|
|
retry_peer_verification->getState());
|
2021-05-24 16:51:16 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-12-15 17:49:43 +00:00
|
|
|
// Switch callbacks.
|
|
|
|
auto interactiveToggleFunc = [scraper_semiautomatic]() {
|
|
|
|
if (scraper_semiautomatic->getEnabled()) {
|
|
|
|
scraper_semiautomatic->setEnabled(false);
|
|
|
|
scraper_semiautomatic->setOpacity(DISABLED_OPACITY);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_semiautomatic->getParent()
|
|
|
|
->getChild(scraper_semiautomatic->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-12-15 17:49:43 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
scraper_semiautomatic->setEnabled(true);
|
|
|
|
scraper_semiautomatic->setOpacity(255);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_semiautomatic->getParent()
|
|
|
|
->getChild(scraper_semiautomatic->getChildIndex() - 1)
|
|
|
|
->setOpacity(255);
|
2020-12-15 17:49:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
auto excludeRecursivelyToggleFunc = [scraper_exclude_recursively]() {
|
|
|
|
if (scraper_exclude_recursively->getEnabled()) {
|
|
|
|
scraper_exclude_recursively->setEnabled(false);
|
|
|
|
scraper_exclude_recursively->setOpacity(DISABLED_OPACITY);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_exclude_recursively->getParent()
|
|
|
|
->getChild(scraper_exclude_recursively->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
2020-12-15 17:49:43 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
scraper_exclude_recursively->setEnabled(true);
|
|
|
|
scraper_exclude_recursively->setOpacity(255);
|
2021-07-11 11:31:43 +00:00
|
|
|
scraper_exclude_recursively->getParent()
|
|
|
|
->getChild(scraper_exclude_recursively->getChildIndex() - 1)
|
|
|
|
->setOpacity(255);
|
2020-12-15 17:49:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
scraper_interactive->setCallback(interactiveToggleFunc);
|
|
|
|
scraper_respect_exclusions->setCallback(excludeRecursivelyToggleFunc);
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
mWindow->pushGui(s);
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GuiScraperMenu::pressedStart()
|
|
|
|
{
|
2020-11-05 17:18:11 +00:00
|
|
|
// If the scraper service has been changed, then save the settings as otherwise the
|
|
|
|
// wrong scraper would be used.
|
|
|
|
if (mScraper->getSelected() != Settings::getInstance()->getString("Scraper"))
|
|
|
|
mMenu.save();
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
std::vector<SystemData*> sys = mSystems->getSelectedObjects();
|
|
|
|
for (auto it = sys.cbegin(); it != sys.cend(); it++) {
|
|
|
|
if ((*it)->getPlatformIds().empty()) {
|
2021-02-08 19:56:11 +00:00
|
|
|
std::string warningString;
|
|
|
|
if (sys.size() == 1) {
|
|
|
|
warningString = "The selected system does not have a\n"
|
2021-07-11 11:31:43 +00:00
|
|
|
"platform set, results may be inaccurate\n"
|
|
|
|
"Continue anyway?";
|
2021-02-08 19:56:11 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
warningString = "At least one of your selected\n"
|
2021-07-11 11:31:43 +00:00
|
|
|
"systems does not have a platform\n"
|
|
|
|
"set, results may be inaccurate\n"
|
|
|
|
"Continue anyway?";
|
2021-02-08 19:56:11 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
2021-07-11 11:31:43 +00:00
|
|
|
Utils::String::toUpper(warningString), "YES",
|
|
|
|
std::bind(&GuiScraperMenu::start, this), "NO", nullptr));
|
2020-06-21 12:25:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
start();
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GuiScraperMenu::start()
|
|
|
|
{
|
2021-01-17 10:58:58 +00:00
|
|
|
if (mSystems->getSelectedObjects().empty()) {
|
2021-07-11 11:31:43 +00:00
|
|
|
mWindow->pushGui(
|
|
|
|
new GuiMsgBox(mWindow, getHelpStyle(), "PLEASE SELECT AT LEAST ONE SYSTEM TO SCRAPE"));
|
2021-01-17 10:58:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool contentToScrape = false;
|
|
|
|
std::string scraperService = Settings::getInstance()->getString("Scraper");
|
|
|
|
|
|
|
|
// Check if there is actually any type of content selected for scraping.
|
|
|
|
do {
|
|
|
|
if (Settings::getInstance()->getBool("ScrapeGameNames")) {
|
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (scraperService == "screenscraper" &&
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScrapeRatings")) {
|
2021-01-17 10:58:58 +00:00
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Settings::getInstance()->getBool("ScrapeMetadata")) {
|
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
2021-07-11 11:31:43 +00:00
|
|
|
if (scraperService == "screenscraper" && Settings::getInstance()->getBool("ScrapeVideos")) {
|
2021-01-17 10:58:58 +00:00
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Settings::getInstance()->getBool("ScrapeScreenshots")) {
|
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Settings::getInstance()->getBool("ScrapeCovers")) {
|
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Settings::getInstance()->getBool("ScrapeMarquees")) {
|
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (scraperService == "screenscraper" &&
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("Scrape3DBoxes")) {
|
2021-01-17 10:58:58 +00:00
|
|
|
contentToScrape = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
if (!contentToScrape) {
|
|
|
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
2021-07-11 11:31:43 +00:00
|
|
|
"PLEASE SELECT AT LEAST ONE CONTENT TYPE TO SCRAPE"));
|
2021-01-17 10:58:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-16 16:35:23 +00:00
|
|
|
std::queue<ScraperSearchParams> searches =
|
2021-07-11 11:31:43 +00:00
|
|
|
getSearches(mSystems->getSelectedObjects(), mFilters->getSelected());
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
if (searches.empty()) {
|
2021-07-11 11:31:43 +00:00
|
|
|
mWindow->pushGui(
|
|
|
|
new GuiMsgBox(mWindow, getHelpStyle(), "ALL GAMES WERE FILTERED, NOTHING TO SCRAPE"));
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
else {
|
2021-07-11 11:31:43 +00:00
|
|
|
GuiScraperMulti* gsm = new GuiScraperMulti(
|
|
|
|
mWindow, searches, Settings::getInstance()->getBool("ScraperInteractive"));
|
2020-06-21 12:25:28 +00:00
|
|
|
mWindow->pushGui(gsm);
|
2021-01-17 11:21:33 +00:00
|
|
|
mMenu.setCursorToList();
|
|
|
|
mMenu.setCursorToFirstListEntry();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 11:31:43 +00:00
|
|
|
std::queue<ScraperSearchParams> GuiScraperMenu::getSearches(std::vector<SystemData*> systems,
|
|
|
|
GameFilterFunc selector)
|
2020-06-06 11:10:33 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::queue<ScraperSearchParams> queue;
|
|
|
|
for (auto sys = systems.cbegin(); sys != systems.cend(); sys++) {
|
2020-08-06 13:12:04 +00:00
|
|
|
std::vector<FileData*> games = (*sys)->getRootFolder()->getScrapeFilesRecursive(
|
2021-07-11 11:31:43 +00:00
|
|
|
Settings::getInstance()->getBool("ScraperIncludeFolders"),
|
|
|
|
Settings::getInstance()->getBool("ScraperExcludeRecursively"),
|
|
|
|
Settings::getInstance()->getBool("ScraperRespectExclusions"));
|
2020-06-21 12:25:28 +00:00
|
|
|
for (auto game = games.cbegin(); game != games.cend(); game++) {
|
2020-08-06 13:12:04 +00:00
|
|
|
if (selector((*sys), (*game))) {
|
2020-06-21 12:25:28 +00:00
|
|
|
ScraperSearchParams search;
|
|
|
|
search.game = *game;
|
|
|
|
search.system = *sys;
|
|
|
|
|
|
|
|
queue.push(search);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return queue;
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 11:31:43 +00:00
|
|
|
void GuiScraperMenu::addEntry(const std::string& name,
|
|
|
|
unsigned int color,
|
|
|
|
bool add_arrow,
|
|
|
|
const std::function<void()>& func)
|
2020-06-06 11:10:33 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Populate the list.
|
|
|
|
ComponentListRow row;
|
|
|
|
row.addElement(std::make_shared<TextComponent>(mWindow, name, font, color), true);
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (add_arrow) {
|
|
|
|
std::shared_ptr<ImageComponent> bracket = makeArrow(mWindow);
|
|
|
|
row.addElement(bracket, false);
|
|
|
|
}
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
row.makeAcceptInputHandler(func);
|
|
|
|
mMenu.addRow(row);
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GuiScraperMenu::input(InputConfig* config, Input input)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
if (GuiComponent::input(config, input))
|
|
|
|
return true;
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2021-01-02 15:28:47 +00:00
|
|
|
if (config->isMappedTo("y", input) && input.value != 0)
|
|
|
|
pressedStart();
|
|
|
|
|
2020-12-18 15:35:19 +00:00
|
|
|
if (config->isMappedTo("b", input) && input.value != 0) {
|
2020-06-21 12:25:28 +00:00
|
|
|
delete this;
|
|
|
|
return true;
|
|
|
|
}
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
return false;
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<HelpPrompt> GuiScraperMenu::getHelpPrompts()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
|
|
|
|
prompts.push_back(HelpPrompt("b", "back"));
|
2021-01-02 15:28:47 +00:00
|
|
|
prompts.push_back(HelpPrompt("y", "start"));
|
2020-06-21 12:25:28 +00:00
|
|
|
return prompts;
|
2020-06-06 11:10:33 +00:00
|
|
|
}
|
2020-06-07 18:09:02 +00:00
|
|
|
|
|
|
|
HelpStyle GuiScraperMenu::getHelpStyle()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
HelpStyle style = HelpStyle();
|
|
|
|
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
|
|
|
|
return style;
|
2020-06-07 18:09:02 +00:00
|
|
|
}
|