2020-09-21 17:17:34 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
2020-09-21 17:17:34 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// GuiScraperSearch.h
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// User interface for the scraper where the user is able to see an overview
|
|
|
|
// of the game being scraped and an option to override the game search string.
|
|
|
|
// Used by both single-game scraping from the GuiMetaDataEd menu as well as
|
|
|
|
// to resolve scraping conflicts when run from GuiScraperMenu.
|
|
|
|
// The function to properly save scraped metadata is located here too.
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
2022-01-16 10:10:32 +00:00
|
|
|
// This GUI is called from GuiScraperSingle for single-game scraping and
|
2020-06-21 12:25:28 +00:00
|
|
|
// from GuiScraperMulti for multi-game scraping.
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
|
|
|
|
2020-06-06 12:14:13 +00:00
|
|
|
#ifndef ES_APP_GUIS_GUI_SCRAPER_SEARCH_H
|
|
|
|
#define ES_APP_GUIS_GUI_SCRAPER_SEARCH_H
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
#include "GuiComponent.h"
|
|
|
|
#include "MiximageGenerator.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "components/BusyComponent.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "components/ComponentGrid.h"
|
|
|
|
#include "scrapers/Scraper.h"
|
2022-03-18 19:14:51 +00:00
|
|
|
#include "views/ViewController.h"
|
2021-06-07 21:02:42 +00:00
|
|
|
|
|
|
|
#include <future>
|
|
|
|
#include <thread>
|
2014-06-25 16:29:58 +00:00
|
|
|
|
|
|
|
class ComponentList;
|
2018-10-13 01:08:15 +00:00
|
|
|
class DateTimeEditComponent;
|
2014-06-25 16:29:58 +00:00
|
|
|
class ImageComponent;
|
|
|
|
class RatingComponent;
|
|
|
|
class ScrollableContainer;
|
2017-11-01 22:21:10 +00:00
|
|
|
class TextComponent;
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-06 12:14:13 +00:00
|
|
|
class GuiScraperSearch : public GuiComponent
|
2014-06-25 16:29:58 +00:00
|
|
|
{
|
|
|
|
public:
|
2020-06-21 12:25:28 +00:00
|
|
|
enum SearchType {
|
2021-07-07 18:03:42 +00:00
|
|
|
ALWAYS_ACCEPT_FIRST_RESULT, // Automatic mode.
|
|
|
|
ACCEPT_SINGLE_MATCHES, // Semi-automatic mode.
|
|
|
|
NEVER_AUTO_ACCEPT // Manual mode.
|
2020-06-21 12:25:28 +00:00
|
|
|
};
|
|
|
|
|
2023-07-29 09:31:36 +00:00
|
|
|
GuiScraperSearch(SearchType searchType, unsigned int scrapeCount, int rowCount);
|
2020-10-18 09:01:56 +00:00
|
|
|
~GuiScraperSearch();
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2022-04-05 15:48:47 +00:00
|
|
|
void search(ScraperSearchParams& params);
|
2020-06-21 12:25:28 +00:00
|
|
|
void openInputScreen(ScraperSearchParams& from);
|
|
|
|
void stop();
|
2021-07-11 20:35:01 +00:00
|
|
|
int getScraperResultsSize() { return static_cast<int>(mScraperResults.size()); }
|
2021-07-11 20:26:53 +00:00
|
|
|
bool getAcceptedResult() { return mAcceptedResult; }
|
2021-07-07 18:03:42 +00:00
|
|
|
SearchType getSearchType() const { return mSearchType; }
|
2021-02-01 17:52:49 +00:00
|
|
|
bool getSavedNewMedia()
|
2021-07-07 18:03:42 +00:00
|
|
|
{
|
2021-12-02 18:28:10 +00:00
|
|
|
if (mMDResolveHandle != nullptr)
|
|
|
|
return mMDResolveHandle->getSavedNewMedia();
|
|
|
|
return mScrapeResult.savedNewMedia;
|
2021-07-07 18:03:42 +00:00
|
|
|
}
|
2021-01-26 16:40:37 +00:00
|
|
|
static bool saveMetadata(const ScraperSearchResult& result,
|
2021-07-07 18:03:42 +00:00
|
|
|
MetaDataList& metadata,
|
|
|
|
FileData* scrapedGame);
|
|
|
|
|
|
|
|
// Metadata assets will be resolved before calling the accept callback.
|
|
|
|
void setAcceptCallback(const std::function<void(const ScraperSearchResult&)>& acceptCallback)
|
|
|
|
{
|
|
|
|
mAcceptCallback = acceptCallback;
|
|
|
|
}
|
|
|
|
void setSkipCallback(const std::function<void()>& skipCallback)
|
|
|
|
{
|
|
|
|
mSkipCallback = skipCallback;
|
|
|
|
}
|
|
|
|
void setCancelCallback(const std::function<void()>& cancelCallback)
|
|
|
|
{
|
|
|
|
mCancelCallback = cancelCallback;
|
|
|
|
}
|
2021-10-15 18:58:40 +00:00
|
|
|
void setRefineCallback(const std::function<void()>& refineCallback)
|
|
|
|
{
|
|
|
|
mRefineCallback = refineCallback;
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
bool input(InputConfig* config, Input input) override;
|
|
|
|
void update(int deltaTime) override;
|
2021-08-15 17:30:31 +00:00
|
|
|
void render(const glm::mat4& parentTrans) override;
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<HelpPrompt> getHelpPrompts() override;
|
2022-03-18 19:14:51 +00:00
|
|
|
HelpStyle getHelpStyle() override { return ViewController::getInstance()->getViewHelpStyle(); }
|
2020-06-21 12:25:28 +00:00
|
|
|
void onSizeChanged() override;
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2021-09-22 21:10:40 +00:00
|
|
|
void decreaseScrapeCount()
|
|
|
|
{
|
|
|
|
if (mScrapeCount > 0)
|
2021-11-17 16:35:34 +00:00
|
|
|
--mScrapeCount;
|
2021-09-22 21:10:40 +00:00
|
|
|
}
|
2021-01-26 16:40:37 +00:00
|
|
|
void unsetRefinedSearch() { mRefinedSearch = false; }
|
2021-09-22 18:07:50 +00:00
|
|
|
bool getRefinedSearch() { return mRefinedSearch; }
|
|
|
|
bool getFoundGame() { return mFoundGame; }
|
|
|
|
const std::string& getNameOverride() { return mLastSearch.nameOverride; }
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
void onFocusGained() override { mGrid.onFocusGained(); }
|
|
|
|
void onFocusLost() override { mGrid.onFocusLost(); }
|
2021-01-26 16:40:37 +00:00
|
|
|
|
2022-01-04 21:36:15 +00:00
|
|
|
std::shared_ptr<ComponentList> getResultList() { return mResultList; }
|
2021-10-15 18:58:40 +00:00
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
private:
|
2020-06-21 12:25:28 +00:00
|
|
|
void updateViewStyle();
|
|
|
|
void updateThumbnail();
|
|
|
|
void updateInfoPane();
|
|
|
|
void resizeMetadata();
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
void onSearchError(const std::string& error,
|
2023-05-08 15:14:52 +00:00
|
|
|
const bool retry,
|
2021-07-07 18:03:42 +00:00
|
|
|
HttpReq::Status status = HttpReq::REQ_UNDEFINED_ERROR);
|
2022-01-03 17:37:43 +00:00
|
|
|
void onSearchDone(std::vector<ScraperSearchResult>& results);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
int getSelectedIndex();
|
|
|
|
|
|
|
|
// For TheGamesDB, retrieve URLs for the additional metadata assets
|
|
|
|
// that need to be downloaded.
|
|
|
|
void retrieveMediaURLs(ScraperSearchResult result);
|
|
|
|
|
|
|
|
// Resolve any metadata assets that need to be downloaded and return.
|
|
|
|
void returnResult(ScraperSearchResult result);
|
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
Renderer* mRenderer;
|
2020-06-21 12:25:28 +00:00
|
|
|
ComponentGrid mGrid;
|
|
|
|
|
|
|
|
std::shared_ptr<TextComponent> mResultName;
|
|
|
|
std::shared_ptr<ScrollableContainer> mDescContainer;
|
|
|
|
std::shared_ptr<TextComponent> mResultDesc;
|
|
|
|
std::shared_ptr<ImageComponent> mResultThumbnail;
|
|
|
|
std::shared_ptr<ComponentList> mResultList;
|
|
|
|
|
|
|
|
std::shared_ptr<ComponentGrid> mMD_Grid;
|
|
|
|
std::shared_ptr<RatingComponent> mMD_Rating;
|
|
|
|
std::shared_ptr<DateTimeEditComponent> mMD_ReleaseDate;
|
|
|
|
std::shared_ptr<TextComponent> mMD_Developer;
|
|
|
|
std::shared_ptr<TextComponent> mMD_Publisher;
|
|
|
|
std::shared_ptr<TextComponent> mMD_Genre;
|
|
|
|
std::shared_ptr<TextComponent> mMD_Players;
|
2020-07-30 14:29:38 +00:00
|
|
|
std::shared_ptr<TextComponent> mMD_Filler;
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Label-component pair.
|
|
|
|
struct MetaDataPair {
|
|
|
|
std::shared_ptr<TextComponent> first;
|
|
|
|
std::shared_ptr<GuiComponent> second;
|
|
|
|
bool resize;
|
|
|
|
|
|
|
|
MetaDataPair(const std::shared_ptr<TextComponent>& f,
|
2021-07-07 18:03:42 +00:00
|
|
|
const std::shared_ptr<GuiComponent>& s,
|
|
|
|
bool r = true)
|
|
|
|
: first(f)
|
|
|
|
, second(s)
|
|
|
|
, resize(r)
|
|
|
|
{
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<MetaDataPair> mMD_Pairs;
|
|
|
|
|
|
|
|
SearchType mSearchType;
|
|
|
|
ScraperSearchParams mLastSearch;
|
2021-06-07 21:02:42 +00:00
|
|
|
ScraperSearchResult mScrapeResult;
|
2020-06-21 12:25:28 +00:00
|
|
|
std::function<void(const ScraperSearchResult&)> mAcceptCallback;
|
|
|
|
std::function<void()> mSkipCallback;
|
|
|
|
std::function<void()> mCancelCallback;
|
2021-10-15 18:58:40 +00:00
|
|
|
std::function<void()> mRefineCallback;
|
2023-07-29 09:31:36 +00:00
|
|
|
int mRowCount;
|
2020-07-31 12:24:14 +00:00
|
|
|
unsigned int mScrapeCount;
|
2020-12-18 15:35:19 +00:00
|
|
|
bool mRefinedSearch;
|
2020-06-21 12:25:28 +00:00
|
|
|
bool mBlockAccept;
|
2021-07-11 20:26:53 +00:00
|
|
|
bool mAcceptedResult;
|
2020-06-21 12:25:28 +00:00
|
|
|
bool mFoundGame;
|
2020-07-30 14:29:38 +00:00
|
|
|
bool mScrapeRatings;
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-05-24 16:51:16 +00:00
|
|
|
bool mRetrySearch;
|
2023-02-10 16:24:50 +00:00
|
|
|
int mRetryCount;
|
|
|
|
int mRetryTimer;
|
|
|
|
int mRetryAccumulator;
|
2021-05-24 16:51:16 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
std::unique_ptr<ScraperSearchHandle> mSearchHandle;
|
|
|
|
std::unique_ptr<ScraperSearchHandle> mMDRetrieveURLsHandle;
|
|
|
|
std::unique_ptr<MDResolveHandle> mMDResolveHandle;
|
|
|
|
std::vector<ScraperSearchResult> mScraperResults;
|
2020-11-14 19:46:08 +00:00
|
|
|
std::map<std::string, std::unique_ptr<HttpReq>> mThumbnailReqMap;
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-06-07 21:02:42 +00:00
|
|
|
std::unique_ptr<MiximageGenerator> mMiximageGenerator;
|
|
|
|
std::thread mMiximageGeneratorThread;
|
|
|
|
std::promise<bool> mGeneratorPromise;
|
|
|
|
std::future<bool> mGeneratorFuture;
|
|
|
|
|
|
|
|
bool mMiximageResult;
|
|
|
|
std::string mResultMessage;
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
BusyComponent mBusyAnim;
|
2014-06-25 16:29:58 +00:00
|
|
|
};
|
2017-10-31 17:12:50 +00:00
|
|
|
|
2020-06-06 12:14:13 +00:00
|
|
|
#endif // ES_APP_GUIS_GUI_SCRAPER_SEARCH_H
|