ES-DE/src/components/GuiMetaDataEd.cpp
Aloshi a554fea973 Fixed memory leak with FolderData::removeFileRecursive.
Made "DELETE" actually work in GuiMetaDataEd.
"DELETE" option also now asks if you're sure.
GuiMetaDataEd can be closed with the "b" button now.
GuiGameScraper now tries to put the cursor on the first game if there is
one when a search completes.
2013-10-16 18:46:05 -05:00

187 lines
5.4 KiB
C++

#include "GuiMetaDataEd.h"
#include "../Renderer.h"
#include "../Log.h"
#include "AsyncReqComponent.h"
#include "../Settings.h"
#include "GuiGameScraper.h"
#include <boost/filesystem.hpp>
#include "GuiMsgBoxYesNo.h"
#define MDED_RESERVED_ROWS 3
GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector<MetaDataDecl>& mdd, ScraperSearchParams scraperParams,
const std::string& header, std::function<void()> saveCallback, std::function<void()> deleteFunc) : GuiComponent(window),
mScraperParams(scraperParams),
mBox(mWindow, ":/frame.png", 0xAAAAAAFF, 0xCCCCCCFF),
mList(window, Eigen::Vector2i(2, mdd.size() + MDED_RESERVED_ROWS)),
mHeader(window),
mMetaDataDecl(mdd),
mMetaData(md),
mSavedCallback(saveCallback), mDeleteFunc(deleteFunc),
mDeleteButton(window), mFetchButton(window), mSaveButton(window)
{
unsigned int sw = Renderer::getScreenWidth();
unsigned int sh = Renderer::getScreenHeight();
addChild(&mBox);
addChild(&mHeader);
mHeader.setText(header);
//initialize buttons
mDeleteButton.setText("DELETE", mDeleteFunc ? 0xFF0000FF : 0x555555FF);
if(mDeleteFunc)
{
std::function<void()> deleteFileAndSelf = [&] { mDeleteFunc(); delete this; };
std::function<void()> pressedFunc = [this, deleteFileAndSelf] { mWindow->pushGui(new GuiMsgBoxYesNo(mWindow, "This will delete a file!\nAre you sure?", deleteFileAndSelf)); };
mDeleteButton.setPressedFunc(pressedFunc);
}
mFetchButton.setText("FETCH", 0x00FF00FF);
mFetchButton.setPressedFunc(std::bind(&GuiMetaDataEd::fetch, this));
mSaveButton.setText("SAVE", 0x0000FFFF);
mSaveButton.setPressedFunc([&] { save(); delete this; });
//initialize metadata list
addChild(&mList);
populateList(mdd);
mList.setPosition((sw - mList.getSize().x()) / 2.0f, (sh - mList.getSize().y()) / 2.0f); //center it
mList.resetCursor();
mBox.fitTo(mList.getSize(), mList.getPosition(), Eigen::Vector2f(12, 12));
mHeader.setPosition(mList.getPosition());
mHeader.setSize(mList.getSize().x(), 0);
mHeader.setCentered(true);
}
GuiMetaDataEd::~GuiMetaDataEd()
{
for(auto iter = mLabels.begin(); iter != mLabels.end(); iter++)
{
delete *iter;
}
for(auto iter = mEditors.begin(); iter != mEditors.end(); iter++)
{
delete *iter;
}
}
void GuiMetaDataEd::populateList(const std::vector<MetaDataDecl>& mdd)
{
// PATH //(centered, not part of componentlist)
//---GAME NAME--- //(at 1,1; size 3,1) (TextEditComponent)
//DEL SCRP --- //(buttons)
//Fav: Y/N --- //metadata start
//Desc: ... --- //multiline texteditcomponent
//Img: ... ---
//--- SAVE ---
using namespace Eigen;
int y = 0;
//fetch button
mList.setEntry(Vector2i(0, y), Vector2i(1, 1), &mFetchButton, true, ComponentListComponent::AlignLeft);
//delete button
mList.setEntry(Vector2i(1, y), Vector2i(1, 1), &mDeleteButton, true, ComponentListComponent::AlignRight);
y++;
for(auto iter = mdd.begin(); iter != mdd.end(); iter++)
{
TextComponent* label = new TextComponent(mWindow);
label->setText(iter->key);
mList.setEntry(Vector2i(0, y), Vector2i(1, 1), label, false, ComponentListComponent::AlignLeft);
mLabels.push_back(label);
GuiComponent* ed = MetaDataList::makeEditor(mWindow, iter->type);
ed->setSize(Renderer::getScreenWidth() * 0.4f, ed->getSize().y());
ed->setValue(mMetaData->get(iter->key));
mList.setEntry(Vector2i(1, y), Vector2i(1, 1), ed, true, ComponentListComponent::AlignRight);
mEditors.push_back(ed);
y++;
}
//save button
mList.setEntry(Vector2i(0, y), Vector2i(2, 1), &mSaveButton, true, ComponentListComponent::AlignCenter);
}
void GuiMetaDataEd::save()
{
for(unsigned int i = 0; i < mLabels.size(); i++)
{
mMetaData->set(mLabels.at(i)->getValue(), mEditors.at(i)->getValue());
}
if(mSavedCallback)
mSavedCallback();
}
void GuiMetaDataEd::fetch()
{
GuiGameScraper* scr = new GuiGameScraper(mWindow, mScraperParams, std::bind(&GuiMetaDataEd::fetchDone, this, std::placeholders::_1));
mWindow->pushGui(scr);
scr->search();
}
void GuiMetaDataEd::fetchDone(MetaDataList result)
{
//TODO - replace this with resolveMetaDataAssetsAsync!
//this is a little tricky:
//go through the list of returned results, if anything is an image and the path looks like a URL:
// (1) start an async download + resize (will create an AsyncReq that blocks further user input)
// (when this is finished, call result.set(key, newly_downloaded_file_path) and call fetchDone() again)
// (2) return from this function immediately
for(auto it = mMetaDataDecl.begin(); it != mMetaDataDecl.end(); it++)
{
std::string key = it->key;
std::string val = result.get(it->key);
//val is /probably/ a URL
if(it->type == MD_IMAGE_PATH && HttpReq::isUrl(val))
{
downloadImageAsync(mWindow, val, getSaveAsPath(mScraperParams, key, val),
[this, result, key] (std::string filePath) mutable -> void {
//skip it
if(filePath.empty())
LOG(LogError) << "Error resolving boxart";
result.set(key, filePath);
this->fetchDone(result);
});
return;
}
}
for(unsigned int i = 0; i < mEditors.size(); i++)
{
//don't overwrite statistics
if(mMetaDataDecl.at(i).isStatistic)
continue;
const std::string& key = mMetaDataDecl.at(i).key;
mEditors.at(i)->setValue(result.get(key));
}
}
bool GuiMetaDataEd::input(InputConfig* config, Input input)
{
if(GuiComponent::input(config, input))
return true;
if(input.value != 0 && config->isMappedTo("b", input))
{
delete this;
return true;
}
return false;
}