mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-17 22:55:38 +00:00
Added metadata editor button to delete media files from games and folders.
This commit is contained in:
parent
3887bfff3d
commit
8233e2704e
1
NEWS.md
1
NEWS.md
|
@ -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
|
* 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 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 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
|
* 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
|
* 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
|
* No more attempts to open files directly under /etc, instead only the install prefix directory and the home directory are used
|
||||||
|
|
|
@ -252,15 +252,47 @@ void GuiGamelistOptions::openMetaDataEd()
|
||||||
p.game = file;
|
p.game = file;
|
||||||
p.system = file->getSystem();
|
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) {
|
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 {
|
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);
|
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,
|
file->metadata.getMDD(FOLDER_METADATA), p,
|
||||||
Utils::FileSystem::getFileName(file->getPath()), std::bind(
|
Utils::FileSystem::getFileName(file->getPath()), std::bind(
|
||||||
&IGameListView::onFileChanged, ViewController::get()->getGameListView(
|
&IGameListView::onFileChanged, ViewController::get()->getGameListView(
|
||||||
file->getSystem()).get(), file, FILE_METADATA_CHANGED), deleteBtnFunc));
|
file->getSystem()).get(), file, FILE_METADATA_CHANGED),
|
||||||
|
deleteGameBtnFunc, deleteMediaBtnFunc));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mWindow->pushGui(new GuiMetaDataEd(mWindow, &file->metadata,
|
mWindow->pushGui(new GuiMetaDataEd(mWindow, &file->metadata,
|
||||||
file->metadata.getMDD(GAME_METADATA), p,
|
file->metadata.getMDD(GAME_METADATA), p,
|
||||||
Utils::FileSystem::getFileName(file->getPath()), std::bind(
|
Utils::FileSystem::getFileName(file->getPath()), std::bind(
|
||||||
&IGameListView::onFileChanged, ViewController::get()->getGameListView(
|
&IGameListView::onFileChanged, ViewController::get()->getGameListView(
|
||||||
file->getSystem()).get(), file, FILE_METADATA_CHANGED), deleteBtnFunc));
|
file->getSystem()).get(), file, FILE_METADATA_CHANGED),
|
||||||
|
deleteGameBtnFunc, deleteMediaBtnFunc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,17 +37,17 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
ScraperSearchParams scraperParams,
|
ScraperSearchParams scraperParams,
|
||||||
const std::string& /*header*/,
|
const std::string& /*header*/,
|
||||||
std::function<void()> saveCallback,
|
std::function<void()> saveCallback,
|
||||||
std::function<void()> deleteFunc)
|
std::function<void()> deleteGameFunc,
|
||||||
|
std::function<void()> deleteMediaFunc)
|
||||||
: GuiComponent(window),
|
: GuiComponent(window),
|
||||||
mScraperParams(scraperParams),
|
mScraperParams(scraperParams),
|
||||||
|
|
||||||
mBackground(window, ":/graphics/frame.png"),
|
mBackground(window, ":/graphics/frame.png"),
|
||||||
mGrid(window, Vector2i(1, 3)),
|
mGrid(window, Vector2i(1, 3)),
|
||||||
|
|
||||||
mMetaDataDecl(mdd),
|
mMetaDataDecl(mdd),
|
||||||
mMetaData(md),
|
mMetaData(md),
|
||||||
mSavedCallback(saveCallback),
|
mSavedCallback(saveCallback),
|
||||||
mDeleteFunc(deleteFunc)
|
mDeleteGameFunc(deleteGameFunc),
|
||||||
|
mDeleteMediaFunc(deleteMediaFunc)
|
||||||
{
|
{
|
||||||
addChild(&mBackground);
|
addChild(&mBackground);
|
||||||
addChild(&mGrid);
|
addChild(&mGrid);
|
||||||
|
@ -237,14 +237,61 @@ GuiMetaDataEd::GuiMetaDataEd(
|
||||||
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "cancel changes",
|
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "cancel changes",
|
||||||
[&] { delete this; }));
|
[&] { delete this; }));
|
||||||
|
|
||||||
if (mDeleteFunc) {
|
if (scraperParams.game->getType() == FOLDER) {
|
||||||
auto deleteFileAndSelf = [&] { mDeleteFunc(); delete this; };
|
if (mDeleteGameFunc) {
|
||||||
auto deleteBtnFunc = [this, deleteFileAndSelf] {
|
auto deleteFilesAndSelf = [&] { mDeleteGameFunc(); delete this; };
|
||||||
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
auto deleteGameBtnFunc = [this, deleteFilesAndSelf] {
|
||||||
"THIS WILL DELETE THE ACTUAL GAME FILE(S)!\nARE YOU SURE?",
|
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
|
||||||
"YES", deleteFileAndSelf, "NO", nullptr)); };
|
"THIS WILL DELETE THE MEDIA FILES AND\n"
|
||||||
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
|
"THE GAMELIST.XML ENTRY FOR THIS FOLDER.\n"
|
||||||
"delete game", deleteBtnFunc));
|
"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);
|
mButtons = makeButtonGrid(mWindow, buttons);
|
||||||
|
|
|
@ -29,7 +29,8 @@ public:
|
||||||
ScraperSearchParams params,
|
ScraperSearchParams params,
|
||||||
const std::string& header,
|
const std::string& header,
|
||||||
std::function<void()> savedCallback,
|
std::function<void()> savedCallback,
|
||||||
std::function<void()> deleteFunc);
|
std::function<void()> deleteGameFunc,
|
||||||
|
std::function<void()> deleteMediaFunc);
|
||||||
|
|
||||||
bool input(InputConfig* config, Input input) override;
|
bool input(InputConfig* config, Input input) override;
|
||||||
void onSizeChanged() override;
|
void onSizeChanged() override;
|
||||||
|
@ -59,7 +60,8 @@ private:
|
||||||
std::vector<MetaDataDecl> mMetaDataDecl;
|
std::vector<MetaDataDecl> mMetaDataDecl;
|
||||||
MetaDataList* mMetaData;
|
MetaDataList* mMetaData;
|
||||||
std::function<void()> mSavedCallback;
|
std::function<void()> mSavedCallback;
|
||||||
std::function<void()> mDeleteFunc;
|
std::function<void()> mDeleteGameFunc;
|
||||||
|
std::function<void()> mDeleteMediaFunc;
|
||||||
|
|
||||||
bool mMediaFilesUpdated;
|
bool mMediaFilesUpdated;
|
||||||
};
|
};
|
||||||
|
|
|
@ -135,33 +135,10 @@ void BasicGameListView::launch(FileData* game)
|
||||||
|
|
||||||
void BasicGameListView::remove(FileData *game, bool deleteFile)
|
void BasicGameListView::remove(FileData *game, bool deleteFile)
|
||||||
{
|
{
|
||||||
// Actually delete the file on the filesystem.
|
// Delete the game file on the filesystem.
|
||||||
if (deleteFile) {
|
if (deleteFile)
|
||||||
Utils::FileSystem::removeFile(game->getPath());
|
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();
|
FileData* parent = game->getParent();
|
||||||
// Select next element in list, or previous if none.
|
// Select next element in list, or previous if none.
|
||||||
if (getCursor() == game) {
|
if (getCursor() == game) {
|
||||||
|
@ -190,6 +167,31 @@ void BasicGameListView::remove(FileData *game, bool deleteFile)
|
||||||
onFileChanged(parent, FILE_REMOVED);
|
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> BasicGameListView::getHelpPrompts()
|
||||||
{
|
{
|
||||||
std::vector<HelpPrompt> prompts;
|
std::vector<HelpPrompt> prompts;
|
||||||
|
|
|
@ -36,6 +36,7 @@ protected:
|
||||||
virtual std::string getQuickSystemSelectLeftButton() override;
|
virtual std::string getQuickSystemSelectLeftButton() override;
|
||||||
virtual void populateList(const std::vector<FileData*>& files) override;
|
virtual void populateList(const std::vector<FileData*>& files) override;
|
||||||
virtual void remove(FileData* game, bool deleteFile) override;
|
virtual void remove(FileData* game, bool deleteFile) override;
|
||||||
|
virtual void removeMedia(FileData* game) override;
|
||||||
virtual void addPlaceholder();
|
virtual void addPlaceholder();
|
||||||
|
|
||||||
TextListComponent<FileData*> mList;
|
TextListComponent<FileData*> mList;
|
||||||
|
|
|
@ -450,7 +450,7 @@ void GridGameListView::launch(FileData* game)
|
||||||
|
|
||||||
void GridGameListView::remove(FileData *game, bool deleteFile)
|
void GridGameListView::remove(FileData *game, bool deleteFile)
|
||||||
{
|
{
|
||||||
// Actually delete the file on the filesystem.
|
// Delete the game file on the filesystem.
|
||||||
if (deleteFile)
|
if (deleteFile)
|
||||||
Utils::FileSystem::removeFile(game->getPath());
|
Utils::FileSystem::removeFile(game->getPath());
|
||||||
|
|
||||||
|
@ -472,12 +472,41 @@ void GridGameListView::remove(FileData *game, bool deleteFile)
|
||||||
if (mGrid.size() == 0)
|
if (mGrid.size() == 0)
|
||||||
addPlaceholder();
|
addPlaceholder();
|
||||||
|
|
||||||
// Remove before repopulating (removes from parent).
|
// If a game has been deleted, immediately remove the entry from gamelist.xml
|
||||||
// Update the view, with game removed.
|
// 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;
|
delete game;
|
||||||
onFileChanged(parent, FILE_REMOVED);
|
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*> GridGameListView::getMDLabels()
|
||||||
{
|
{
|
||||||
std::vector<TextComponent*> ret;
|
std::vector<TextComponent*> ret;
|
||||||
|
|
|
@ -43,6 +43,7 @@ protected:
|
||||||
virtual std::string getQuickSystemSelectLeftButton() override;
|
virtual std::string getQuickSystemSelectLeftButton() override;
|
||||||
virtual void populateList(const std::vector<FileData*>& files) override;
|
virtual void populateList(const std::vector<FileData*>& files) override;
|
||||||
virtual void remove(FileData* game, bool deleteFile) override;
|
virtual void remove(FileData* game, bool deleteFile) override;
|
||||||
|
virtual void removeMedia(FileData* game) override;
|
||||||
virtual void addPlaceholder();
|
virtual void addPlaceholder();
|
||||||
|
|
||||||
ImageGridComponent<FileData*> mGrid;
|
ImageGridComponent<FileData*> mGrid;
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
|
|
||||||
virtual bool input(InputConfig* config, Input input) override;
|
virtual bool input(InputConfig* config, Input input) override;
|
||||||
virtual void remove(FileData* game, bool deleteFile) = 0;
|
virtual void remove(FileData* game, bool deleteFile) = 0;
|
||||||
|
virtual void removeMedia(FileData* game) = 0;
|
||||||
|
|
||||||
virtual const char* getName() const = 0;
|
virtual const char* getName() const = 0;
|
||||||
virtual void launch(FileData* game) = 0;
|
virtual void launch(FileData* game) = 0;
|
||||||
|
|
Loading…
Reference in a new issue