Added metadata editor button to delete media files from games and folders.

This commit is contained in:
Leon Styhre 2020-07-30 20:05:57 +02:00
parent 3887bfff3d
commit 8233e2704e
9 changed files with 166 additions and 48 deletions

View file

@ -41,6 +41,7 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Speed improvements and optimizations, the application now starts faster and feels more responsive
* Added metadata entry to mark games as broken/not working
* Added metadata entry to indicate whether the file should be counted as a game (for example useful to exclude setup files and similar for DOS games)
* Added a button to the metadata editor to delete the media files for a game while retaining the game itself and the gamelist.xml entry
* Moved all resources to a subdirectory structure and enabled the CMake install prefix variable to generate the resources search path
* Changed theme directory to the install prefix (e.g. /usr/local/share/emulationstation/themes) with themes in the home directory taking precedence
* No more attempts to open files directly under /etc, instead only the install prefix directory and the home directory are used

View file

@ -252,15 +252,47 @@ void GuiGamelistOptions::openMetaDataEd()
p.game = file;
p.system = file->getSystem();
std::function<void()> deleteBtnFunc;
std::function<void()> deleteGameBtnFunc;
std::function<void()> deleteMediaBtnFunc;
deleteMediaBtnFunc = [this, file] {
LOG(LogInfo) << "Deleting all game media files for '" << file->getFullPath() << "'.";
ViewController::get()->getGameListView(
file->getSystem()).get()->removeMedia(file);
};
if (file->getType() == FOLDER) {
deleteBtnFunc = nullptr;
deleteGameBtnFunc = [this, file] {
LOG(LogInfo) << "Deleting the media files and gamelist.xml entry for the folder '" <<
file->getFullPath() << "'";
ViewController::get()->getGameListView(
file->getSystem()).get()->removeMedia(file);
// Manually reset all the metadata values, set the name to the actual folder name.
const std::vector<MetaDataDecl>& mdd = file->metadata.getMDD();
for (auto it = mdd.cbegin(); it != mdd.cend(); it++) {
if (it->key == "name") {
file->metadata.set(it->key, file->getDisplayName());
continue;
}
file->metadata.set(it->key, it->defaultValue);
}
ViewController::get()->reloadGameListView(file->getParent()->getSystem());
// Remove the folder entry from the gamelist.xml file.
file->setDeletionFlag();
file->getParent()->getSystem()->writeMetaData();
};
}
else {
deleteBtnFunc = [this, file] {
deleteGameBtnFunc = [this, file] {
LOG(LogInfo) << "Deleting the game file '" << file->getFullPath() <<
"', all its media files and its gamelist.xml entry.";
CollectionSystemManager::get()->deleteCollectionFiles(file);
ViewController::get()->getGameListView(file->getSystem()).get()->remove(file, true);
ViewController::get()->getGameListView(
file->getSystem()).get()->removeMedia(file);
ViewController::get()->getGameListView(
file->getSystem()).get()->remove(file, true);
};
}
@ -269,14 +301,16 @@ void GuiGamelistOptions::openMetaDataEd()
file->metadata.getMDD(FOLDER_METADATA), p,
Utils::FileSystem::getFileName(file->getPath()), std::bind(
&IGameListView::onFileChanged, ViewController::get()->getGameListView(
file->getSystem()).get(), file, FILE_METADATA_CHANGED), deleteBtnFunc));
file->getSystem()).get(), file, FILE_METADATA_CHANGED),
deleteGameBtnFunc, deleteMediaBtnFunc));
}
else {
mWindow->pushGui(new GuiMetaDataEd(mWindow, &file->metadata,
file->metadata.getMDD(GAME_METADATA), p,
Utils::FileSystem::getFileName(file->getPath()), std::bind(
&IGameListView::onFileChanged, ViewController::get()->getGameListView(
file->getSystem()).get(), file, FILE_METADATA_CHANGED), deleteBtnFunc));
file->getSystem()).get(), file, FILE_METADATA_CHANGED),
deleteGameBtnFunc, deleteMediaBtnFunc));
}
}

View file

@ -37,17 +37,17 @@ GuiMetaDataEd::GuiMetaDataEd(
ScraperSearchParams scraperParams,
const std::string& /*header*/,
std::function<void()> saveCallback,
std::function<void()> deleteFunc)
std::function<void()> deleteGameFunc,
std::function<void()> deleteMediaFunc)
: GuiComponent(window),
mScraperParams(scraperParams),
mBackground(window, ":/graphics/frame.png"),
mGrid(window, Vector2i(1, 3)),
mMetaDataDecl(mdd),
mMetaData(md),
mSavedCallback(saveCallback),
mDeleteFunc(deleteFunc)
mDeleteGameFunc(deleteGameFunc),
mDeleteMediaFunc(deleteMediaFunc)
{
addChild(&mBackground);
addChild(&mGrid);
@ -237,14 +237,61 @@ GuiMetaDataEd::GuiMetaDataEd(
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "cancel changes",
[&] { delete this; }));
if (mDeleteFunc) {
auto deleteFileAndSelf = [&] { mDeleteFunc(); delete this; };
auto deleteBtnFunc = [this, deleteFileAndSelf] {
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"THIS WILL DELETE THE ACTUAL GAME FILE(S)!\nARE YOU SURE?",
"YES", deleteFileAndSelf, "NO", nullptr)); };
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
"delete game", deleteBtnFunc));
if (scraperParams.game->getType() == FOLDER) {
if (mDeleteGameFunc) {
auto deleteFilesAndSelf = [&] { mDeleteGameFunc(); delete this; };
auto deleteGameBtnFunc = [this, deleteFilesAndSelf] {
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"THIS WILL DELETE THE MEDIA FILES AND\n"
"THE GAMELIST.XML ENTRY FOR THIS FOLDER.\n"
"HOWEVER NEITHER THE FOLDER ITSELF OR\n"
"ANY DATA FOR THE FILES INSIDE THE FOLDER\n"
"WILL BE DELETED. ARE YOU SURE?",
"YES", deleteFilesAndSelf, "NO", nullptr)); };
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
"delete game", deleteGameBtnFunc));
}
if (mDeleteMediaFunc) {
auto deleteFilesAndSelf = [&] { mDeleteMediaFunc(); delete this; };
auto deleteMediaBtnFunc = [this, deleteFilesAndSelf] {
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"THIS WILL DELETE ALL THE MEDIA FILES\n"
"FOR THE ACTUAL FOLDER, BUT NO MEDIA\n"
"FOR ANY FILES INSIDE THE FOLDER WILL\n"
"BE DELETED. ARE YOU SURE?",
"YES", deleteFilesAndSelf, "NO", nullptr)); };
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE MEDIA",
"delete game", deleteMediaBtnFunc));
}
}
else {
if (mDeleteGameFunc) {
auto deleteFilesAndSelf = [&] { mDeleteGameFunc(); delete this; };
auto deleteGameBtnFunc = [this, deleteFilesAndSelf] {
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"THIS WILL DELETE THE GAME\n"
"FILE, ANY MEDIA FILES AND\n"
"THE GAMELIST.XML ENTRY.\n"
"ARE YOU SURE?",
"YES", deleteFilesAndSelf, "NO", nullptr)); };
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
"delete game", deleteGameBtnFunc));
}
if (mDeleteMediaFunc) {
auto deleteFilesAndSelf = [&] { mDeleteMediaFunc(); delete this; };
auto deleteMediaBtnFunc = [this, deleteFilesAndSelf] {
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"THIS WILL DELETE ALL GAME\n"
"MEDIA FILES, BUT WILL KEEP\n"
"THE ACTUAL GAME FILE AND\n"
"THE GAMELIST.XML ENTRY.\n"
"ARE YOU SURE?",
"YES", deleteFilesAndSelf, "NO", nullptr)); };
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE MEDIA",
"delete game", deleteMediaBtnFunc));
}
}
mButtons = makeButtonGrid(mWindow, buttons);

View file

@ -29,7 +29,8 @@ public:
ScraperSearchParams params,
const std::string& header,
std::function<void()> savedCallback,
std::function<void()> deleteFunc);
std::function<void()> deleteGameFunc,
std::function<void()> deleteMediaFunc);
bool input(InputConfig* config, Input input) override;
void onSizeChanged() override;
@ -59,7 +60,8 @@ private:
std::vector<MetaDataDecl> mMetaDataDecl;
MetaDataList* mMetaData;
std::function<void()> mSavedCallback;
std::function<void()> mDeleteFunc;
std::function<void()> mDeleteGameFunc;
std::function<void()> mDeleteMediaFunc;
bool mMediaFilesUpdated;
};

View file

@ -135,33 +135,10 @@ void BasicGameListView::launch(FileData* game)
void BasicGameListView::remove(FileData *game, bool deleteFile)
{
// Actually delete the file on the filesystem.
if (deleteFile) {
// Delete the game file on the filesystem.
if (deleteFile)
Utils::FileSystem::removeFile(game->getPath());
// Remove all game media files as well.
if (Utils::FileSystem::exists(game->getVideoPath()))
Utils::FileSystem::removeFile(game->getVideoPath());
if (Utils::FileSystem::exists(game->getMiximagePath()))
Utils::FileSystem::removeFile(game->getMiximagePath());
if (Utils::FileSystem::exists(game->getScreenshotPath()))
Utils::FileSystem::removeFile(game->getScreenshotPath());
if (Utils::FileSystem::exists(game->getCoverPath()))
Utils::FileSystem::removeFile(game->getCoverPath());
if (Utils::FileSystem::exists(game->getMarqueePath()))
Utils::FileSystem::removeFile(game->getMarqueePath());
if (Utils::FileSystem::exists(game->get3DBoxPath()))
Utils::FileSystem::removeFile(game->get3DBoxPath());
if (Utils::FileSystem::exists(game->getThumbnailPath()))
Utils::FileSystem::removeFile(game->getThumbnailPath());
}
FileData* parent = game->getParent();
// Select next element in list, or previous if none.
if (getCursor() == game) {
@ -190,6 +167,31 @@ void BasicGameListView::remove(FileData *game, bool deleteFile)
onFileChanged(parent, FILE_REMOVED);
}
void BasicGameListView::removeMedia(FileData *game)
{
// Remove all game media files on the filesystem.
if (Utils::FileSystem::exists(game->getVideoPath()))
Utils::FileSystem::removeFile(game->getVideoPath());
if (Utils::FileSystem::exists(game->getMiximagePath()))
Utils::FileSystem::removeFile(game->getMiximagePath());
if (Utils::FileSystem::exists(game->getScreenshotPath()))
Utils::FileSystem::removeFile(game->getScreenshotPath());
if (Utils::FileSystem::exists(game->getCoverPath()))
Utils::FileSystem::removeFile(game->getCoverPath());
if (Utils::FileSystem::exists(game->getMarqueePath()))
Utils::FileSystem::removeFile(game->getMarqueePath());
if (Utils::FileSystem::exists(game->get3DBoxPath()))
Utils::FileSystem::removeFile(game->get3DBoxPath());
if (Utils::FileSystem::exists(game->getThumbnailPath()))
Utils::FileSystem::removeFile(game->getThumbnailPath());
}
std::vector<HelpPrompt> BasicGameListView::getHelpPrompts()
{
std::vector<HelpPrompt> prompts;

View file

@ -36,6 +36,7 @@ protected:
virtual std::string getQuickSystemSelectLeftButton() override;
virtual void populateList(const std::vector<FileData*>& files) override;
virtual void remove(FileData* game, bool deleteFile) override;
virtual void removeMedia(FileData* game) override;
virtual void addPlaceholder();
TextListComponent<FileData*> mList;

View file

@ -450,7 +450,7 @@ void GridGameListView::launch(FileData* game)
void GridGameListView::remove(FileData *game, bool deleteFile)
{
// Actually delete the file on the filesystem.
// Delete the game file on the filesystem.
if (deleteFile)
Utils::FileSystem::removeFile(game->getPath());
@ -472,12 +472,41 @@ void GridGameListView::remove(FileData *game, bool deleteFile)
if (mGrid.size() == 0)
addPlaceholder();
// Remove before repopulating (removes from parent).
// Update the view, with game removed.
// If a game has been deleted, immediately remove the entry from gamelist.xml
// regardless of the value of the setting SaveGamelistsMode.
game->setDeletionFlag();
parent->getSystem()->writeMetaData();
// Remove before repopulating (removes from parent), then update the view.
delete game;
onFileChanged(parent, FILE_REMOVED);
}
void GridGameListView::removeMedia(FileData *game)
{
// Remove all game media files on the filesystem.
if (Utils::FileSystem::exists(game->getVideoPath()))
Utils::FileSystem::removeFile(game->getVideoPath());
if (Utils::FileSystem::exists(game->getMiximagePath()))
Utils::FileSystem::removeFile(game->getMiximagePath());
if (Utils::FileSystem::exists(game->getScreenshotPath()))
Utils::FileSystem::removeFile(game->getScreenshotPath());
if (Utils::FileSystem::exists(game->getCoverPath()))
Utils::FileSystem::removeFile(game->getCoverPath());
if (Utils::FileSystem::exists(game->getMarqueePath()))
Utils::FileSystem::removeFile(game->getMarqueePath());
if (Utils::FileSystem::exists(game->get3DBoxPath()))
Utils::FileSystem::removeFile(game->get3DBoxPath());
if (Utils::FileSystem::exists(game->getThumbnailPath()))
Utils::FileSystem::removeFile(game->getThumbnailPath());
}
std::vector<TextComponent*> GridGameListView::getMDLabels()
{
std::vector<TextComponent*> ret;

View file

@ -43,6 +43,7 @@ protected:
virtual std::string getQuickSystemSelectLeftButton() override;
virtual void populateList(const std::vector<FileData*>& files) override;
virtual void remove(FileData* game, bool deleteFile) override;
virtual void removeMedia(FileData* game) override;
virtual void addPlaceholder();
ImageGridComponent<FileData*> mGrid;

View file

@ -48,6 +48,7 @@ public:
virtual bool input(InputConfig* config, Input input) override;
virtual void remove(FileData* game, bool deleteFile) = 0;
virtual void removeMedia(FileData* game) = 0;
virtual const char* getName() const = 0;
virtual void launch(FileData* game) = 0;