Handle savedata files better on the game browser tab

This commit is contained in:
Henrik Rydgård
2026-02-18 11:54:13 +01:00
parent 5b33918ac4
commit 341e034f0b
3 changed files with 87 additions and 61 deletions
+23 -4
View File
@@ -85,12 +85,21 @@ static void LaunchFile(ScreenManager *screenManager, Screen *currentScreen, cons
// Check if we already know that this game isn't playable.
auto info = g_gameInfoCache->GetInfo(nullptr, path, GameInfoFlags::FILE_TYPE);
if (info->fileType == IdentifiedFileType::PSP_UMD_VIDEO_ISO) {
switch (info->fileType) {
case IdentifiedFileType::PSP_UMD_VIDEO_ISO:
// We show info about it.
screenManager->push(new GameScreen(path, false));
return;
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
{
// Show the savedata popup, why not?
std::string title = SanitizeString(info->GetTitle(), StringRestriction::NoLineBreaksOrSpecials, 0, 200);
screenManager->push(new SavedataPopupScreen(Path(), path, title));
return;
}
default:
break;
}
if (currentScreen) {
screenManager->cancelScreensAbove(currentScreen);
}
@@ -398,9 +407,14 @@ void GameButton::Draw(UIContext &dc) {
}
if (gridStyle_ && g_Config.bShowIDOnGameIcon && ginfo->fileType != IdentifiedFileType::PSP_ELF && !ginfo->id_version.empty()) {
std::string_view idStr = ginfo->id_version;
if (ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
auto ga = GetI18NCategory(I18NCat::GAME);
idStr = ga->T("SaveData");
}
dc.SetFontScale(0.5f * g_Config.fGameGridScale, 0.5f * g_Config.fGameGridScale);
dc.DrawText(ginfo->id_version, bounds_.x + 5, y + 1, 0xFF000000, ALIGN_TOPLEFT);
dc.DrawText(ginfo->id_version, bounds_.x + 4, y, dc.GetTheme().infoStyle.fgColor, ALIGN_TOPLEFT);
dc.DrawText(idStr, bounds_.x + 5, y + 1, 0xFF000000, ALIGN_TOPLEFT);
dc.DrawText(idStr, bounds_.x + 4, y, dc.GetTheme().infoStyle.fgColor, ALIGN_TOPLEFT);
dc.SetFontScale(1.0f, 1.0f);
}
@@ -1728,6 +1742,11 @@ void MainScreen::dialogFinished(const Screen *dialog, DialogResult result) {
} else if (tag == "Upload") {
// Files may have been uploaded.
RecreateViews();
} else if (tag == "SavedataPopup") {
// We must have come from the file browser tab.
if (gameBrowsers_.size() >= 2) {
gameBrowsers_[1]->RequestRefresh();
}
}
}
+45 -57
View File
@@ -132,75 +132,63 @@ SavedataView::SavedataView(UIContext &dc, GameInfo *ginfo, IdentifiedFileType ty
}
}
class SavedataPopupScreen : public UI::PopupScreen {
public:
SavedataPopupScreen(Path gamePath, Path savePath, std::string_view title) : PopupScreen(StripSpaces(title)), savePath_(savePath), gamePath_(gamePath) { }
SavedataPopupScreen::SavedataPopupScreen(Path gamePath, Path savePath, std::string_view title) : PopupScreen(StripSpaces(title)), savePath_(savePath), gamePath_(gamePath) {}
const char *tag() const override { return "SavedataPopup"; }
void update() override {
PopupScreen::update();
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::SIZE);
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
// Hm, this is no good. But hopefully the previous screen loaded it.
return;
}
if (savedataView_) {
savedataView_->UpdateGame(ginfo.get());
}
void SavedataPopupScreen::update() {
PopupScreen::update();
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::SIZE);
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
// Hm, this is no good. But hopefully the previous screen loaded it.
return;
}
if (savedataView_) {
savedataView_->UpdateGame(ginfo.get());
}
}
void SavedataPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::SIZE);
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
// This is OK, handled in Update. Though most likely, the previous screen loaded it.
}
void CreatePopupContents(UI::ViewGroup *parent) override {
using namespace UI;
UIContext &dc = *screenManager()->getUIContext();
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f, UI::Margins(0, 3)));
parent->Add(contentScroll);
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::SIZE);
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
// This is OK, handled in Update. Though most likely, the previous screen loaded it.
}
// TODO: If the game info wasn't already loaded, we'll get a bogus fileType here.
savedataView_ = contentScroll->Add(new SavedataView(dc, ginfo.get(), ginfo->fileType, true));
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f, UI::Margins(0, 3)));
parent->Add(contentScroll);
auto di = GetI18NCategory(I18NCat::DIALOG);
// TODO: If the game info wasn't already loaded, we'll get a bogus fileType here.
savedataView_ = contentScroll->Add(new SavedataView(dc, ginfo.get(), ginfo->fileType, true));
LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
buttonRow->SetSpacing(0);
Margins buttonMargins(5, 5, 5, 13); // not sure why we need more at the bottom to make it look right
buttonRow->Add(new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
buttonRow->Add(new Choice(di->T("Delete"), ImageID("I_TRASHCAN"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Add([this](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GameInfoFlags::PARAM_SFO);
LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
buttonRow->SetSpacing(0);
Margins buttonMargins(5, 5, 5, 13); // not sure why we need more at the bottom to make it look right
const bool trashAvailable = System_GetPropertyBool(SYSPROP_HAS_TRASH_BIN);
buttonRow->Add(new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
buttonRow->Add(new Choice(di->T("Delete"), ImageID("I_TRASHCAN"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Add([this](UI::EventParams &e) {
auto di = GetI18NCategory(I18NCat::DIALOG);
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GameInfoFlags::PARAM_SFO);
const bool trashAvailable = System_GetPropertyBool(SYSPROP_HAS_TRASH_BIN);
std::string_view confirmMessage = di->T("Are you sure you want to delete the file?");
screenManager()->push(new MessagePopupScreen(di->T("Delete"), confirmMessage, trashAvailable ? di->T("Move to trash") : di->T("Delete"), di->T("Cancel"), [=](bool result) {
if (result) {
ginfo->Delete();
TriggerFinish(DR_NO);
}
}));
std::string_view confirmMessage = di->T("Are you sure you want to delete the file?");
screenManager()->push(new MessagePopupScreen(di->T("Delete"), confirmMessage, trashAvailable ? di->T("Move to trash") : di->T("Delete"), di->T("Cancel"), [=](bool result) {
if (result) {
ginfo->Delete();
TriggerFinish(DR_NO);
}
}));
});
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
buttonRow->Add(new Choice(di->T("Show in folder"), ImageID("I_FOLDER"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Add([this](UI::EventParams &e) {
System_ShowFileInFolder(savePath_);
});
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
buttonRow->Add(new Choice(di->T("Show in folder"), ImageID("I_FOLDER"), new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Add([this](UI::EventParams &e) {
System_ShowFileInFolder(savePath_);
});
}
parent->Add(buttonRow);
}
protected:
UI::Size PopupWidth() const override { return 600; }
private:
SavedataView *savedataView_ = nullptr;
Path savePath_;
Path gamePath_;
};
parent->Add(buttonRow);
}
class SortedLinearLayout : public UI::LinearLayoutList {
public:
+19
View File
@@ -67,6 +67,25 @@ private:
bool searchPending_ = false;
};
class SavedataView;
class SavedataPopupScreen : public UI::PopupScreen {
public:
SavedataPopupScreen(Path gamePath, Path savePath, std::string_view title);
const char *tag() const override { return "SavedataPopup"; }
void update() override;
void CreatePopupContents(UI::ViewGroup *parent) override;
protected:
UI::Size PopupWidth() const override { return 600; }
private:
SavedataView *savedataView_ = nullptr;
Path savePath_;
Path gamePath_;
};
class SavedataScreen : public UITabbedBaseDialogScreen {
public:
// gamePath can be empty, in that case this screen will show all savedata in the save directory.