// SPDX-License-Identifier: MIT // // ES-DE Frontend // GuiScraperSearch.h // // 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. // // This GUI is called from GuiScraperSingle for single-game scraping and // from GuiScraperMulti for multi-game scraping. // #ifndef ES_APP_GUIS_GUI_SCRAPER_SEARCH_H #define ES_APP_GUIS_GUI_SCRAPER_SEARCH_H #include "GuiComponent.h" #include "MiximageGenerator.h" #include "components/BusyComponent.h" #include "components/ComponentGrid.h" #include "scrapers/Scraper.h" #include "views/ViewController.h" #include #include class ComponentList; class DateTimeEditComponent; class ImageComponent; class RatingComponent; class ScrollableContainer; class TextComponent; class GuiScraperSearch : public GuiComponent { public: enum SearchType { AUTOMATIC_MODE, SEMIAUTOMATIC_MODE, MANUAL_MODE }; GuiScraperSearch(SearchType searchType, unsigned int scrapeCount, int rowCount); ~GuiScraperSearch(); void search(ScraperSearchParams& params); void openInputScreen(ScraperSearchParams& from); void stop(); int getScraperResultsSize() { return static_cast(mScraperResults.size()); } bool getAcceptedResult() { return mAcceptedResult; } SearchType getSearchType() const { return mSearchType; } bool getSavedNewMedia() { if (mMDResolveHandle != nullptr) return mMDResolveHandle->getSavedNewMedia(); return mScrapeResult.savedNewMedia; } static bool saveMetadata(const ScraperSearchResult& result, MetaDataList& metadata, FileData* scrapedGame); // Metadata assets will be resolved before calling the accept callback. void setAcceptCallback(const std::function& acceptCallback) { mAcceptCallback = acceptCallback; } void setSkipCallback(const std::function& skipCallback) { mSkipCallback = skipCallback; } void setCancelCallback(const std::function& cancelCallback) { mCancelCallback = cancelCallback; } void setRefineCallback(const std::function& refineCallback) { mRefineCallback = refineCallback; } bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; void render(const glm::mat4& parentTrans) override; std::vector getHelpPrompts() override; HelpStyle getHelpStyle() override { return ViewController::getInstance()->getViewHelpStyle(); } void onSizeChanged() override; void decreaseScrapeCount() { if (mScrapeCount > 0) --mScrapeCount; } void unsetRefinedSearch() { mRefinedSearch = false; } bool getRefinedSearch() { return mRefinedSearch; } bool getFoundGame() { return mFoundGame; } const std::string& getNameOverride() { return mLastSearch.nameOverride; } void onFocusGained() override { mGrid.onFocusGained(); } void onFocusLost() override { mGrid.onFocusLost(); } std::shared_ptr getResultList() { return mResultList; } private: void updateView(); void updateThumbnail(); void updateInfoPane(); void resizeMetadata(); void onSearchError(const std::string& error, const bool retry, const bool fatalError, HttpReq::Status status = HttpReq::REQ_UNDEFINED_ERROR); void onSearchDone(std::vector& results); int getSelectedIndex(); void calculateMD5Hash(std::string path) { mMD5Hash = Utils::Math::md5Hash(path, true); mMD5HashPromise.set_value(true); } // 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); Renderer* mRenderer; ComponentGrid mGrid; std::shared_ptr mResultName; std::shared_ptr mDescContainer; std::shared_ptr mResultDesc; std::shared_ptr mResultThumbnail; std::shared_ptr mResultList; std::shared_ptr mMD_Grid; std::shared_ptr mMD_Rating; std::shared_ptr mMD_ReleaseDate; std::shared_ptr mMD_Developer; std::shared_ptr mMD_Publisher; std::shared_ptr mMD_Genre; std::shared_ptr mMD_Players; std::shared_ptr mMD_Filler; // Label-component pair. struct MetaDataPair { std::shared_ptr first; std::shared_ptr second; bool resize; MetaDataPair(const std::shared_ptr& f, const std::shared_ptr& s, bool r = true) : first(f) , second(s) , resize(r) { } }; std::vector mMD_Pairs; SearchType mSearchType; ScraperSearchParams mLastSearch; ScraperSearchResult mScrapeResult; std::function mAcceptCallback; std::function mSkipCallback; std::function mCancelCallback; std::function mRefineCallback; int mRowCount; unsigned int mScrapeCount; bool mNextSearch; bool mHashSearch; bool mRefinedSearch; bool mBlockAccept; bool mAcceptedResult; bool mFoundGame; bool mScrapeRatings; bool mRetrySearch; int mRetryCount; int mRetryTimer; int mRetryAccumulator; int mAutomaticModeGameEntry; std::unique_ptr mSearchHandle; std::unique_ptr mMDRetrieveURLsHandle; std::unique_ptr mMDResolveHandle; std::vector mScraperResults; std::map> mThumbnailReqMap; std::string mMD5Hash; std::thread mCalculateMD5HashThread; std::promise mMD5HashPromise; std::future mMD5HashFuture; std::unique_ptr mMiximageGenerator; std::thread mMiximageGeneratorThread; std::promise mGeneratorPromise; std::future mGeneratorFuture; bool mMiximageResult; std::string mResultMessage; BusyComponent mBusyAnim; }; #endif // ES_APP_GUIS_GUI_SCRAPER_SEARCH_H