ES-DE/es-app/src/guis/GuiScraperSearch.h

212 lines
6.7 KiB
C++

// SPDX-License-Identifier: MIT
//
// ES-DE
// 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 <future>
#include <thread>
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<int>(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<void(const ScraperSearchResult&)>& acceptCallback)
{
mAcceptCallback = acceptCallback;
}
void setSkipCallback(const std::function<void()>& skipCallback)
{
mSkipCallback = skipCallback;
}
void setCancelCallback(const std::function<void()>& cancelCallback)
{
mCancelCallback = cancelCallback;
}
void setRefineCallback(const std::function<void()>& refineCallback)
{
mRefineCallback = refineCallback;
}
bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override;
void render(const glm::mat4& parentTrans) override;
std::vector<HelpPrompt> 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<ComponentList> getResultList() { return mResultList; }
private:
void updateView();
void updateThumbnail();
void updateInfoPane();
void resizeMetadata();
void onSearchError(const std::string& error,
const bool retry,
HttpReq::Status status = HttpReq::REQ_UNDEFINED_ERROR);
void onSearchDone(std::vector<ScraperSearchResult>& 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<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;
std::shared_ptr<TextComponent> mMD_Filler;
// Label-component pair.
struct MetaDataPair {
std::shared_ptr<TextComponent> first;
std::shared_ptr<GuiComponent> second;
bool resize;
MetaDataPair(const std::shared_ptr<TextComponent>& f,
const std::shared_ptr<GuiComponent>& s,
bool r = true)
: first(f)
, second(s)
, resize(r)
{
}
};
std::vector<MetaDataPair> mMD_Pairs;
SearchType mSearchType;
ScraperSearchParams mLastSearch;
ScraperSearchResult mScrapeResult;
std::function<void(const ScraperSearchResult&)> mAcceptCallback;
std::function<void()> mSkipCallback;
std::function<void()> mCancelCallback;
std::function<void()> 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<ScraperSearchHandle> mSearchHandle;
std::unique_ptr<ScraperSearchHandle> mMDRetrieveURLsHandle;
std::unique_ptr<MDResolveHandle> mMDResolveHandle;
std::vector<ScraperSearchResult> mScraperResults;
std::map<std::string, std::unique_ptr<HttpReq>> mThumbnailReqMap;
std::string mMD5Hash;
std::thread mCalculateMD5HashThread;
std::promise<bool> mMD5HashPromise;
std::future<bool> mMD5HashFuture;
std::unique_ptr<MiximageGenerator> mMiximageGenerator;
std::thread mMiximageGeneratorThread;
std::promise<bool> mGeneratorPromise;
std::future<bool> mGeneratorFuture;
bool mMiximageResult;
std::string mResultMessage;
BusyComponent mBusyAnim;
};
#endif // ES_APP_GUIS_GUI_SCRAPER_SEARCH_H