From 98540cd3ca7b5c50edcab9c4742d350b0a5a02fd Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:57:35 +0200 Subject: [PATCH] enh - filter backupSet menu --- include/BackupSetList.h | 62 ++++---- include/Metadata.h | 14 +- include/menu/BackupSetListFilterState.h | 30 ++++ include/menu/BackupSetListState.h | 4 + include/menu/WiiUTitleListState.h | 3 +- include/menu/vWiiTitleListState.h | 3 +- include/savemng.h | 2 + languages/english.json | 24 ++- src/BackupSetList.cpp | 109 +++++++++---- src/main.cpp | 11 ++ src/menu/BackupSetListFilter.cpp | 87 +++++++++++ src/menu/BackupSetListState.cpp | 197 ++++++++++++++---------- src/menu/BatchBackupState.cpp | 1 + src/menu/TitleOptionsState.cpp | 6 + src/menu/TitleTaskState.cpp | 1 + src/menu/WiiUTitleListState.cpp | 3 +- src/menu/vWiiTitleListState.cpp | 3 +- src/savemng.cpp | 14 +- 18 files changed, 431 insertions(+), 143 deletions(-) create mode 100644 include/menu/BackupSetListFilterState.h create mode 100644 src/menu/BackupSetListFilter.cpp diff --git a/include/BackupSetList.h b/include/BackupSetList.h index 30813e9..65fae26 100644 --- a/include/BackupSetList.h +++ b/include/BackupSetList.h @@ -9,32 +9,26 @@ class BSMetadataValues { friend class BSMetadata; friend class BackupSetList; public: - class Year { - public: - std::set> range; - std::set::iterator iterator; - }; - class Month { - public: - std::set> range; - std::set::iterator iterator; - }; - class SerialId { - public: - std::set> range; - std::set::iterator iterator; - }; - class Tag { + + template + class attr { public: - std::set> range; + std::set range; std::set::iterator iterator; }; - Year year; - Month month; - SerialId serialId; - Tag tag; - static void Right(auto & bsMetadataValuesAttr ); - static void Left(auto & bsMetadataValuesAttr ); + attr> year; + attr> month; + attr> serialId; + attr> tag; + + template + static void Right (T & metadataAttrValues); + + template + static void Left (T & metadataAttrValues); + + void resetFilter(); + }; class BSMetadata { @@ -64,20 +58,33 @@ class BackupSetItem { BSMetadata bsItemMetadata; }; +struct BackupSetItemView { + std::string entryPath; + std::string serialId; + std::string tag; +}; + class BackupSetList { public: friend class BackupSetListState; + friend class BackupSetListFilterState; BackupSetList() {}; BackupSetList(const char *backupSetListRoot); static std::unique_ptr currentBackupSetList; void sort(bool sortAscending = false); + static bool getSortAscending() { return sortAscending;}; std::string at(int i); - void add(std::string backupSet); + std::string serialIdAt(int i); + std::string serialIdStretchedAt(int i); + std::string tagAt(int i); + void add(std::string entryPath,std::string serialId,std::string tag); int getLen() { return this->entries;}; + int getEnhLen() { return this->enhEntries;}; + void filter(); void filter(BSMetadata filterDef); BSMetadataValues *getBSMetadataValues() {return &bsMetadataValues; }; @@ -91,17 +98,16 @@ class BackupSetList { static void setBackupSetSubPathToRoot() { backupSetSubPath = "/"; } static void saveBackupSetSubPath() { savedBackupSetSubPath = backupSetSubPath; } static void restoreBackupSetSubPath() { backupSetSubPath = savedBackupSetSubPath; } - static void Right(auto & range, std::set::iterator & iterator ); - static void Left(auto & range, std::set::iterator & iterator ); - + private: static bool sortAscending; - std::vector backupSets; + std::vector backupSets; std::vector backupSetsEnh; std::vector serialIds; std::vector tags; BSMetadataValues bsMetadataValues; int entries; + int enhEntries; std::string backupSetListRoot; static std::string backupSetSubPath; static std::string backupSetEntry; diff --git a/include/Metadata.h b/include/Metadata.h index 413fabe..39fc766 100644 --- a/include/Metadata.h +++ b/include/Metadata.h @@ -26,14 +26,24 @@ class Metadata { serialId(this->unknownSerialId), tag({}) { } - Metadata(std::string path) : storage({}), +// guess date from batchBackupRoot, to infer a savemiiMeta.json for <1.6.4 batchBackups + Metadata(const std::string & path) : storage({}), serialId(this->unknownSerialId), tag({}) { Date = path.substr(path.length()-17,17); if (Date.substr(0,2) != "20") Date=""; - this->path = path.append("/savemiiMeta.json"); + this->path = path + ("/savemiiMeta.json"); } + + Metadata(const std::string & datetime, const std::string & storage, const std::string & serialId,const std::string & tag ) : + Date(datetime), + storage(storage), + serialId(serialId), + tag(tag) { + path = getBatchBackupPathRoot(datetime)+"/savemiiMeta.json"; + } + bool read(); bool write(); diff --git a/include/menu/BackupSetListFilterState.h b/include/menu/BackupSetListFilterState.h new file mode 100644 index 0000000..77375ae --- /dev/null +++ b/include/menu/BackupSetListFilterState.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + + + + +class BackupSetListFilterState : public ApplicationState { +public: + BackupSetListFilterState(std::unique_ptr & backupSetList) : + backupSetList(backupSetList) {}; + enum eState { + STATE_BACKUPSET_FILTER, + STATE_DO_SUBSTATE, + }; + + void render() override; + ApplicationState::eSubState update(Input *input) override; + +private: + std::unique_ptr subState{}; + eState state = STATE_BACKUPSET_FILTER; + + std::unique_ptr & backupSetList; + int entrycount = 4; + int cursorPos = 0; +}; \ No newline at end of file diff --git a/include/menu/BackupSetListState.h b/include/menu/BackupSetListState.h index 8aea7cc..504d4fd 100644 --- a/include/menu/BackupSetListState.h +++ b/include/menu/BackupSetListState.h @@ -11,6 +11,7 @@ class BackupSetListState : public ApplicationState { public: BackupSetListState(); static void resetCursorPosition(); + static void resetCursorAndScroll(); enum eState { STATE_BACKUPSET_MENU, STATE_DO_SUBSTATE, @@ -24,6 +25,9 @@ class BackupSetListState : public ApplicationState { eState state = STATE_BACKUPSET_MENU; bool sortAscending; + + static int cursorPos; + static int scroll; std::string backupSetListRoot; }; \ No newline at end of file diff --git a/include/menu/WiiUTitleListState.h b/include/menu/WiiUTitleListState.h index 3dec7fe..e3b847d 100644 --- a/include/menu/WiiUTitleListState.h +++ b/include/menu/WiiUTitleListState.h @@ -33,7 +33,8 @@ class WiiUTitleListState : public ApplicationState { LanguageUtils::gettext("Storage+Name")}; int titleSort = 1; - int scroll = 0; + static int scroll; + static int cursorPos; bool sortAscending = true; int targ = 0; diff --git a/include/menu/vWiiTitleListState.h b/include/menu/vWiiTitleListState.h index f5767ed..140b69a 100644 --- a/include/menu/vWiiTitleListState.h +++ b/include/menu/vWiiTitleListState.h @@ -33,7 +33,8 @@ class vWiiTitleListState : public ApplicationState { LanguageUtils::gettext("Storage+Name")}; int titleSort = 1; - int scroll = 0; + static int scroll; + static int cursorPos; bool sortAscending = true; int targ = 0; diff --git a/include/savemng.h b/include/savemng.h index 04aa676..f284686 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -111,6 +111,7 @@ bool promptConfirm(Style st, const std::string &question); void promptError(const char *message, ...); std::string getDynamicBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); std::string getBatchBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot, std::string datetime); +std::string getBatchBackupPathRoot(std::string datetime); void getAccountsWiiU(); void getAccountsSD(Title *title, uint8_t slot); bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t slot, int version); @@ -124,6 +125,7 @@ std::string getNowDateForFolder() __attribute__((hot)); std::string getNowDate() __attribute__((hot)); void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB) __attribute__((hot)); void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB,const std::string &batchDatetime) __attribute__((hot)); +void writeBackupAllMetadata(const std::string & Date); void backupAllSave(Title *titles, int count, const std::string &batchDatetime) __attribute__((hot)); void backupSavedata(Title *title, uint8_t slot, int8_t wiiuuser, bool common) __attribute__((hot)); void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuuser, bool common) __attribute__((hot)); diff --git a/languages/english.json b/languages/english.json index 822bccd..9a51b6c 100644 --- a/languages/english.json +++ b/languages/english.json @@ -107,11 +107,31 @@ "Failed to delete slot %u.": "Failed to delete slot %u.", "Error setting path. Aborting.": "Error setting path. Aborting.", "Failed to delete backupSet %s.": "Failed to delete backupSet %s.", - "\ue000: Select BackupSet \ue046: Wipe BackupSet \ue001: Back": "\ue000: Select BackupSet \ue046: Wipe BackupSet \ue001: Back", "\ue000: Backup \ue046 Delete Slot \ue001: Back": "\ue000: Backup \ue046 Delete Slot \ue001: Back", "\ue003 Confirm - \ue001 Cancel": "\ue003 Confirm - \ue001 Cancel", "Wipe BackupSet - Are you sure?": "Wipe BackupSet - Are you sure?", "Wipe BackupSet - Hm, are you REALLY sure?": "Wipe BackupSet - Hm, are you REALLY sure?", "Initializing BackupSets metadata.": "Initializing BackupSets metadata.", - "Please wait. First write to SD may be slow.": "Initializing BackupSets metadata." + "Please wait. First write to SD may be slow.": "Initializing BackupSets metadata.", + "Filter BackupSets": "Filter BackupSets", + "Show only BackupSets satisfying all these conditions:": "Show only BackupSets satisfying all these conditions:", + "Console: %s": "Console: %s", + "Tag: %s": "Tag: %s", + "Month: %s": "Month: %s", + "Year: %s": "Year: %s", + "\ue000: Apply Filter \uE002: Reset Filters \ue001: Back": "\ue000: Apply Filter \uE002: Reset Filters \ue001: Back", + "BackupSets": "BackupSets", + "BackupSets (filter applied)": "BackupSets (filter applied)", + "\ue000: Select BS \ue046: Wipe BS \ue003: Filter List \ue001: Back": "\ue000: Select BS \ue046: Wipe BS \ue002: Filter List \ue001: Back", + "\ue000: Select BackupSet \ue003: Filter List \ue001: Back": "\ue000: Select BackupSet \ue002: Filter List \ue001: Back", + "Batch Backup": "Batch Backup", + "Backup": "Backup", + "Restore": "Restore", + "Wipe": "Wipe", + "Import Loadiine": "Import Loadiine", + "Export Loadiine": "Export Loadiine", + "Copy to Other Device": "Copy to Other Device", + "Tasks": "Tasks", + "Initializing BackupSets metadata.": "Initializing BackupSets metadata.", + "Please wait. First write to SD may be slow.": "Please wait. First write to SD may be slow." } \ No newline at end of file diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp index 9f8ec40..f1046f5 100644 --- a/src/BackupSetList.cpp +++ b/src/BackupSetList.cpp @@ -9,8 +9,6 @@ #include #include - - bool BackupSetList::sortAscending = false; const std::string BackupSetList::ROOT_BS = ">> Root <<"; std::string BackupSetList::backupSetSubPath = "/";; @@ -49,8 +47,10 @@ BackupSetList::BackupSetList(const char *backupSetListRoot) bsm = BSMetadata(metadata.getDate().substr(0,4),metadata.getDate().size()>6 ? metadata.getDate().substr(5,2) : "", metadata.getSerialId(),metadata.getTag()); backupSetsEnh.push_back(BackupSetItem(data->d_name,bsm)); - bsMetadataValues.year.range.insert(bsm.year); - bsMetadataValues.month.range.insert(bsm.month); + if (bsm.year != "") + bsMetadataValues.year.range.insert(bsm.year); + if (bsm.month != "") + bsMetadataValues.month.range.insert(bsm.month); bsMetadataValues.serialId.range.insert(bsm.serialId); if (bsm.tag != "") bsMetadataValues.tag.range.insert(bsm.tag); @@ -58,10 +58,14 @@ BackupSetList::BackupSetList(const char *backupSetListRoot) } closedir(dir); - for (unsigned int i=0;ibackupSets.push_back(backupSetsEnh[i].entryPath); - this->serialIds.push_back(backupSetsEnh[i].bsItemMetadata.serialId); - this->tags.push_back(backupSetsEnh[i].bsItemMetadata.tag); + this->enhEntries = this->backupSetsEnh.size(); + + BackupSetItemView bsiv; + for (int i=0;i < this->enhEntries;i++) { + bsiv.entryPath = backupSetsEnh[i].entryPath; + bsiv.serialId = backupSetsEnh[i].bsItemMetadata.serialId; + bsiv.tag = backupSetsEnh[i].bsItemMetadata.tag; + this->backupSets.push_back(bsiv); } this->entries = backupSets.size(); @@ -76,23 +80,38 @@ BackupSetList::BackupSetList(const char *backupSetListRoot) void BackupSetList::sort(bool sortAscending_) { if (sortAscending_) { - std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::less{}); + std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::less{},&BackupSetItemView::entryPath); } else { - std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::greater{}); + std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::greater{},&BackupSetItemView::entryPath); } sortAscending = sortAscending_; } -std::string BackupSetList::at(int i) -{ - - return backupSets.at(i); +std::string BackupSetList::at(int i) { + return backupSets.at(i).entryPath; +} +std::string BackupSetList::serialIdAt(int i) { + return backupSets.at(i).serialId; } -void BackupSetList::add(std::string backupSet) +std::string BackupSetList::serialIdStretchedAt(int i) { + int serialIdSize = serialIdAt(i).size(); + return serialIdSize > 8 ? serialIdAt(i).substr(0,4)+".."+serialIdAt(i).substr(serialIdSize-4,4) : serialIdAt(i); +} + +std::string BackupSetList::tagAt(int i) { + return backupSets.at(i).tag; +} + + +void BackupSetList::add(std::string entryPath,std::string serialId,std::string tag) { - backupSets.push_back(backupSet); + BackupSetItemView bsiv; + bsiv.entryPath = entryPath; + bsiv.serialId = serialId; + bsiv.tag = tag; + backupSets.push_back(bsiv); this->entries++; if (!sortAscending) this->sort(false); @@ -124,29 +143,63 @@ std::string BackupSetList::getBackupSetSubPath(int i) { void BackupSetList::filter(BSMetadata filterDef) { backupSets.erase(backupSets.begin()+1,backupSets.end()); + BackupSetItemView bsiv; for (unsigned int i=1; i < this->backupSetsEnh.size(); i++) { if (filterDef.year == "*" || filterDef.year == this->backupSetsEnh[i].bsItemMetadata.year) if (filterDef.month == "*" || filterDef.month == this->backupSetsEnh[i].bsItemMetadata.month) if (filterDef.serialId == "*" || filterDef.serialId == this->backupSetsEnh[i].bsItemMetadata.serialId) if (filterDef.tag == "*" || filterDef.tag == this->backupSetsEnh[i].bsItemMetadata.tag) { - this->backupSets.push_back(backupSetsEnh[i].entryPath); - this->serialIds.push_back(backupSetsEnh[i].bsItemMetadata.serialId); - this->tags.push_back(backupSetsEnh[i].bsItemMetadata.tag); + bsiv.entryPath = backupSetsEnh[i].entryPath; + bsiv.serialId = backupSetsEnh[i].bsItemMetadata.serialId; + bsiv.tag = backupSetsEnh[i].bsItemMetadata.tag; + this->backupSets.push_back(bsiv); } } - entries = this->backupSets.size(); + this->entries = this->backupSets.size(); } +void BackupSetList::filter() { + backupSets.erase(backupSets.begin()+1,backupSets.end()); + BackupSetItemView bsiv; + for (unsigned int i=1; i < this->backupSetsEnh.size(); i++) { + if (*bsMetadataValues.year.iterator == "*" || *bsMetadataValues.year.iterator == this->backupSetsEnh[i].bsItemMetadata.year) + if (*bsMetadataValues.month.iterator == "*" || *bsMetadataValues.month.iterator == this->backupSetsEnh[i].bsItemMetadata.month) + if (*bsMetadataValues.serialId.iterator == "*" || *bsMetadataValues.serialId.iterator == this->backupSetsEnh[i].bsItemMetadata.serialId) + if (*bsMetadataValues.tag.iterator == "*" || *bsMetadataValues.tag.iterator == this->backupSetsEnh[i].bsItemMetadata.tag) { + bsiv.entryPath = backupSetsEnh[i].entryPath; + bsiv.serialId = backupSetsEnh[i].bsItemMetadata.serialId; + bsiv.tag = backupSetsEnh[i].bsItemMetadata.tag; + this->backupSets.push_back(bsiv); + } + } + this->entries = this->backupSets.size(); +} -void BSMetadataValues::Right(auto & metadata ) { - metadata.iterator++; - if (metadata.iterator == metadata.range.end()) - metadata.iterator = metadata.range.begin(); +void BSMetadataValues::resetFilter() { + this->year.iterator = --this->year.range.end(); + this->month.iterator = --this->month.range.end(); + this->serialId.iterator = this->serialId.range.begin(); + this->tag.iterator = this->tag.range.begin(); } -void BSMetadataValues::Left(auto & metadata ) { - if (metadata.iterator == metadata.range.begin()) - metadata.iterator = --metadata.range.end(); +template < typename T > +void BSMetadataValues::Right( T & metadataAttr ) { + metadataAttr.iterator++; + if (metadataAttr.iterator == metadataAttr.range.end()) + metadataAttr.iterator = metadataAttr.range.begin(); +} + +template < typename T > +void BSMetadataValues::Left(T & metadataAttr ) { + if (metadataAttr.iterator == metadataAttr.range.begin()) + metadataAttr.iterator = --metadataAttr.range.end(); else - metadata.iterator--; + metadataAttr.iterator--; } + +template void BSMetadataValues::Right(attr> &); +template void BSMetadataValues::Right(attr> &); +template void BSMetadataValues::Left(attr> &); +template void BSMetadataValues::Left(attr> &); + + diff --git a/src/main.cpp b/src/main.cpp index 627f558..6ea5424 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,13 @@ #include #include +//#define DEBUG + +#ifdef DEBUG +#include +#include +#endif + static int wiiuTitlesCount = 0, vWiiTitlesCount = 0; extern char *batchBackupPath; @@ -406,6 +413,10 @@ static void unloadTitles(Title *titles, int count) { int main() { +#ifdef DEBUG + WHBLogUdpInit(); +#endif + AXInit(); AXQuit(); diff --git a/src/menu/BackupSetListFilter.cpp b/src/menu/BackupSetListFilter.cpp new file mode 100644 index 0000000..8e9e41a --- /dev/null +++ b/src/menu/BackupSetListFilter.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void BackupSetListFilterState::render() { + if (this->state == STATE_BACKUPSET_FILTER) { + DrawUtils::setFontColor(COLOR_TEXT); + consolePrintPosAligned(0,4,1,"Filter BackupSets"); + DrawUtils::setFontColor(COLOR_INFO); + consolePrintPos(0,4,LanguageUtils::gettext("Show only BackupSets satisfying all these conditions:")); + DrawUtils::setFontColor(COLOR_TEXT); + consolePrintPos(M_OFF, 6, "Console: %s", (*backupSetList->bsMetadataValues.serialId.iterator).c_str()); + consolePrintPos(M_OFF, 7, "Tag: %s", (*backupSetList->bsMetadataValues.tag.iterator).c_str()); + consolePrintPos(M_OFF, 8, "Month: %s", (*backupSetList->bsMetadataValues.month.iterator).c_str()); + consolePrintPos(M_OFF, 9, "Year: %s", (*backupSetList->bsMetadataValues.year.iterator).c_str()); + consolePrintPos(-1, 6 + cursorPos, "\u2192"); + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Apply Filter \uE002: Reset Filters \ue001: Back")); + + } +} + +ApplicationState::eSubState BackupSetListFilterState::update(Input *input) { + if (input->get(TRIGGER, PAD_BUTTON_B)) { + return SUBSTATE_RETURN; + } + if (input->get(TRIGGER, PAD_BUTTON_LEFT)) { + switch (cursorPos) { + case 0: + BSMetadataValues::Left(backupSetList->bsMetadataValues.serialId); + break; + case 1: + BSMetadataValues::Left(backupSetList->bsMetadataValues.tag); + break; + case 2: + BSMetadataValues::Left(backupSetList->bsMetadataValues.month); + break; + case 3: + BSMetadataValues::Left(backupSetList->bsMetadataValues.year); + break; + default: + break; + } + } + if (input->get(TRIGGER, PAD_BUTTON_RIGHT)) { + switch (cursorPos) { + case 0: + BSMetadataValues::Right(backupSetList->bsMetadataValues.serialId); + break; + case 1: + BSMetadataValues::Right(backupSetList->bsMetadataValues.tag); + break; + case 2: + BSMetadataValues::Right(backupSetList->bsMetadataValues.month); + break; + case 3: + BSMetadataValues::Right(backupSetList->bsMetadataValues.year); + break; + default: + break; + } + } + if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { + if (entrycount <= 14) + cursorPos = (cursorPos + 1) % entrycount; + } + if (input->get(TRIGGER, PAD_BUTTON_UP)) { + if (cursorPos > 0) + --cursorPos; + } + if (input->get(TRIGGER, PAD_BUTTON_A)) { + backupSetList->filter(); + backupSetList->sort(BackupSetList::getSortAscending()); + BackupSetListState::resetCursorAndScroll(); + return SUBSTATE_RETURN; + } + if (input->get(TRIGGER,PAD_BUTTON_X)) { + backupSetList->bsMetadataValues.resetFilter(); + } + return SUBSTATE_RUNNING; +} \ No newline at end of file diff --git a/src/menu/BackupSetListState.cpp b/src/menu/BackupSetListState.cpp index bde1098..81b5069 100644 --- a/src/menu/BackupSetListState.cpp +++ b/src/menu/BackupSetListState.cpp @@ -1,21 +1,23 @@ #include +#include +#include #include #include #include #include -#include +#include #define MAX_ROWS_SHOW 14 -static int cursorPos = 0; -static int scroll = 0; +int BackupSetListState::cursorPos = 0; +int BackupSetListState::scroll = 0; static std::string language; BackupSetListState::BackupSetListState() { this->sortAscending = BackupSetList::sortAscending; } -void BackupSetListState::resetCursorPosition() { // after batch Backup +void BackupSetListState::resetCursorPosition() { // if bslist is modified after a new batch Backup if ( cursorPos == 0 ) return; if (BackupSetList::sortAscending) { @@ -26,90 +28,129 @@ void BackupSetListState::resetCursorPosition() { // after batch Backup } } -void BackupSetListState::render() { +void BackupSetListState::resetCursorAndScroll() { // if we apply a new filter + cursorPos=0; + scroll=0; +} - std::string backupSetItem; - consolePrintPos(44, 0, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), - this->sortAscending ? "\u2191" : "\u2193"); - for (int i = 0; i < MAX_ROWS_SHOW; i++) { - if (i + scroll < 0 || i + scroll >= BackupSetList::currentBackupSetList->entries) - break; - backupSetItem = BackupSetList::currentBackupSetList->at(i + scroll); - DrawUtils::setFontColor(COLOR_LIST); - if ( backupSetItem == BackupSetList::ROOT_BS) - DrawUtils::setFontColor(COLOR_LIST_HIGH); - if ( backupSetItem == BackupSetList::getBackupSetEntry()) +void BackupSetListState::render() { + if (this->state == STATE_DO_SUBSTATE) { + if (this->subState == nullptr) { + OSFatal("SubState was null"); + } + this->subState->render(); + return; + } + if (this->state == STATE_BACKUPSET_MENU) { + std::string backupSetItem; + if (BackupSetList::currentBackupSetList->entries == BackupSetList::currentBackupSetList->enhEntries) { + consolePrintPosAligned(0, 4, 1, LanguageUtils::gettext("BackupSets")); + } else { DrawUtils::setFontColor(COLOR_INFO); - consolePrintPos(M_OFF, i + 2, " %s", backupSetItem.c_str()); + consolePrintPosAligned(0, 4, 1, LanguageUtils::gettext("BackupSets (filter applied)")); } - DrawUtils::setFontColor(COLOR_TEXT); - consolePrintPos(-1, 2 + cursorPos, "\u2192"); - if (cursorPos + scroll > 0) - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Select BackupSet \ue046: Wipe BackupSet \ue001: Back")); - else - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Select BackupSet \ue001: Back")); + DrawUtils::setFontColor(COLOR_TEXT); + //consolePrintPos(47, 0, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), + // this->sortAscending ? "\u2191" : "\u2193"); + consolePrintPosAligned(0,4,2, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), + this->sortAscending ? "\u2191" : "\u2193"); + for (int i = 0; i < MAX_ROWS_SHOW; i++) { + if (i + scroll < 0 || i + scroll >= BackupSetList::currentBackupSetList->entries) + break; + backupSetItem = BackupSetList::currentBackupSetList->at(i + scroll); + DrawUtils::setFontColor(COLOR_LIST); + if ( backupSetItem == BackupSetList::ROOT_BS) + DrawUtils::setFontColor(COLOR_LIST_HIGH); + if ( backupSetItem == BackupSetList::getBackupSetEntry()) + DrawUtils::setFontColor(COLOR_INFO); + consolePrintPos(M_OFF, i + 2, " %s", backupSetItem.c_str()); + consolePrintPos(24, i+2,"%s", BackupSetList::currentBackupSetList->serialIdStretchedAt(i+scroll).c_str()); + consolePrintPos(38, i+2,"%s", BackupSetList::currentBackupSetList->tagAt(i+scroll).c_str()); + } + DrawUtils::setFontColor(COLOR_TEXT); + consolePrintPos(-1, 2 + cursorPos, "\u2192"); + if (cursorPos + scroll > 0) + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Select BS \ue046: Wipe BS \ue003: Filter List \ue001: Back")); + else + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Select BackupSet \ue003: Filter List \ue001: Back")); + } } ApplicationState::eSubState BackupSetListState::update(Input *input) { - if (input->get(TRIGGER, PAD_BUTTON_B)) - return SUBSTATE_RETURN; - if (input->get(TRIGGER, PAD_BUTTON_A)) { - BackupSetList::setBackupSetEntry(cursorPos + scroll); - BackupSetList::setBackupSetSubPath(); - DrawUtils::setRedraw(true); - return SUBSTATE_RETURN; - } - if (input->get(TRIGGER, PAD_BUTTON_L)) { - if ( this->sortAscending ) { - this->sortAscending = false; - BackupSetList::currentBackupSetList->sort(this->sortAscending); - cursorPos = 0; - scroll = 0; + if (this->state == STATE_BACKUPSET_MENU) { + if (input->get(TRIGGER, PAD_BUTTON_B)) + return SUBSTATE_RETURN; + if (input->get(TRIGGER, PAD_BUTTON_A)) { + BackupSetList::setBackupSetEntry(cursorPos + scroll); + BackupSetList::setBackupSetSubPath(); + DrawUtils::setRedraw(true); + return SUBSTATE_RETURN; } - } - if (input->get(TRIGGER, PAD_BUTTON_R)) { - if ( ! this->sortAscending ) { - this->sortAscending = true; - BackupSetList::currentBackupSetList->sort(this->sortAscending); - cursorPos = 0; - scroll = 0; + if (input->get(TRIGGER, PAD_BUTTON_Y)) { + this->state = STATE_DO_SUBSTATE; + this->subState = std::make_unique(BackupSetList::currentBackupSetList); } - } - if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { - if (BackupSetList::currentBackupSetList->entries <= MAX_ROWS_SHOW) - cursorPos = (cursorPos + 1) % BackupSetList::currentBackupSetList->entries; - else if (cursorPos < 6) - cursorPos++; - else if (((cursorPos + scroll + 1) % BackupSetList::currentBackupSetList->entries) != 0) - scroll++; - else - cursorPos = scroll = 0; - } - if (input->get(TRIGGER, PAD_BUTTON_UP)) { - if (scroll > 0) - cursorPos -= (cursorPos > 6) ? 1 : 0 * (scroll--); - else if (cursorPos > 0) - cursorPos--; - else if (BackupSetList::currentBackupSetList->entries > MAX_ROWS_SHOW) - scroll = BackupSetList::currentBackupSetList->entries - (cursorPos = 6) - 1; - else - cursorPos = BackupSetList::currentBackupSetList->entries - 1; - } - if (input->get(TRIGGER, PAD_BUTTON_MINUS)) { - int entry = cursorPos+scroll; - if (entry > 0) - { - if (BackupSetList::getBackupSetSubPath() == BackupSetList::getBackupSetSubPath(entry)) - { - BackupSetList::setBackupSetEntry(entry-1); - BackupSetList::setBackupSetSubPath(); + if (input->get(TRIGGER, PAD_BUTTON_L)) { + if ( this->sortAscending ) { + this->sortAscending = false; + BackupSetList::currentBackupSetList->sort(this->sortAscending); + cursorPos = 0; + scroll = 0; } - if ( wipeBackupSet(BackupSetList::getBackupSetSubPath(entry))) - { - BackupSetList::initBackupSetList(); + } + if (input->get(TRIGGER, PAD_BUTTON_R)) { + if ( ! this->sortAscending ) { + this->sortAscending = true; + BackupSetList::currentBackupSetList->sort(this->sortAscending); + cursorPos = 0; + scroll = 0; + } + } + if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { + if (BackupSetList::currentBackupSetList->entries <= MAX_ROWS_SHOW) + cursorPos = (cursorPos + 1) % BackupSetList::currentBackupSetList->entries; + else if (cursorPos < 6) + cursorPos++; + else if (((cursorPos + scroll + 1) % BackupSetList::currentBackupSetList->entries) != 0) + scroll++; + else + cursorPos = scroll = 0; + } + if (input->get(TRIGGER, PAD_BUTTON_UP)) { + if (scroll > 0) + cursorPos -= (cursorPos > 6) ? 1 : 0 * (scroll--); + else if (cursorPos > 0) cursorPos--; - } - DrawUtils::setRedraw(true); + else if (BackupSetList::currentBackupSetList->entries > MAX_ROWS_SHOW) + scroll = BackupSetList::currentBackupSetList->entries - (cursorPos = 6) - 1; + else + cursorPos = BackupSetList::currentBackupSetList->entries - 1; + } + if (input->get(TRIGGER, PAD_BUTTON_MINUS)) { + int entry = cursorPos+scroll; + if (entry > 0) + { + if (BackupSetList::getBackupSetSubPath() == BackupSetList::getBackupSetSubPath(entry)) + { + BackupSetList::setBackupSetEntry(entry-1); + BackupSetList::setBackupSetSubPath(); + } + if ( wipeBackupSet(BackupSetList::getBackupSetSubPath(entry))) + { + BackupSetList::initBackupSetList(); + cursorPos--; + } + DrawUtils::setRedraw(true); + } + } + } else if (this->state == STATE_DO_SUBSTATE) { + auto retSubState = this->subState->update(input); + if (retSubState == SUBSTATE_RUNNING) { + // keep running. + return SUBSTATE_RUNNING; + } else if (retSubState == SUBSTATE_RETURN) { + this->subState.reset(); + this->state = STATE_BACKUPSET_MENU; } } return SUBSTATE_RUNNING; diff --git a/src/menu/BatchBackupState.cpp b/src/menu/BatchBackupState.cpp index 840a312..537b962 100644 --- a/src/menu/BatchBackupState.cpp +++ b/src/menu/BatchBackupState.cpp @@ -13,6 +13,7 @@ static int cursorPos = 0; void BatchBackupState::render() { + consolePrintPosAligned(0, 4, 1,LanguageUtils::gettext("Batch Backup")); consolePrintPos(M_OFF, 2, LanguageUtils::gettext(" Backup All (%u Title%s)"), this->wiiuTitlesCount + this->vWiiTitlesCount, ((this->wiiuTitlesCount + this->vWiiTitlesCount) > 1) ? "s" : ""); consolePrintPos(M_OFF, 3, LanguageUtils::gettext(" Backup Wii U (%u Title%s)"), this->wiiuTitlesCount, diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index cc4a0d9..ac98bc6 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -174,20 +174,26 @@ void TitleOptionsState::render() { consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); else consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue046 Delete Slot \ue001: Back")); + consolePrintPosAligned(0, 4, 1,LanguageUtils::gettext("Backup")); break; case restore: + consolePrintPos(20,0,LanguageUtils::gettext("Restore")); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Change BackupSet \ue000: Restore \ue001: Back")); break; case wipe: + consolePrintPosAligned(0, 4, 1,LanguageUtils::gettext("Wipe")); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Wipe \ue001: Back")); break; case importLoadiine: + consolePrintPosAligned(0, 4, 1,LanguageUtils::gettext("Import Loadiine")); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Import \ue001: Back")); break; case exportLoadiine: + consolePrintPosAligned(0, 4, 1,LanguageUtils::gettext("Export Loadiine")); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Export \ue001: Back")); break; case copytoOtherDevice: + consolePrintPosAligned(0, 4, 1,LanguageUtils::gettext("Copy to Other Device")); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Copy \ue001: Back")); break; } diff --git a/src/menu/TitleTaskState.cpp b/src/menu/TitleTaskState.cpp index d60a87d..41ac0ce 100644 --- a/src/menu/TitleTaskState.cpp +++ b/src/menu/TitleTaskState.cpp @@ -27,6 +27,7 @@ void TitleTaskState::render() { DrawUtils::setFontColor(COLOR_INFO); consolePrintPosAligned(0, 4, 2,LanguageUtils::gettext("WiiU Serial Id: %s"),Metadata::thisConsoleSerialId.c_str()); DrawUtils::setFontColor(COLOR_TEXT); + consolePrintPos(22,0,LanguageUtils::gettext("Tasks")); this->isWiiUTitle = (this->title.highID == 0x00050000) || (this->title.highID == 0x00050002); entrycount = 3 + 2 * static_cast(this->isWiiUTitle) + 1 * static_cast(this->isWiiUTitle && (this->title.isTitleDupe)); consolePrintPos(M_OFF, 2, " [%08X-%08X] [%s]", this->title.highID, this->title.lowID, diff --git a/src/menu/WiiUTitleListState.cpp b/src/menu/WiiUTitleListState.cpp index d25e93f..53bf48a 100644 --- a/src/menu/WiiUTitleListState.cpp +++ b/src/menu/WiiUTitleListState.cpp @@ -9,7 +9,8 @@ #include #define MAX_TITLE_SHOW 14 -static int cursorPos = 0; +int WiiUTitleListState::cursorPos = 0; +int WiiUTitleListState::scroll = 0; void WiiUTitleListState::render() { if (this->state == STATE_DO_SUBSTATE) { diff --git a/src/menu/vWiiTitleListState.cpp b/src/menu/vWiiTitleListState.cpp index 0f336ee..ab1f29d 100644 --- a/src/menu/vWiiTitleListState.cpp +++ b/src/menu/vWiiTitleListState.cpp @@ -8,7 +8,8 @@ #include #define MAX_TITLE_SHOW 14 -static int cursorPos = 0; +int vWiiTitleListState::scroll = 0; +int vWiiTitleListState::cursorPos = 0; void vWiiTitleListState::render() { if (this->state == STATE_DO_SUBSTATE) { diff --git a/src/savemng.cpp b/src/savemng.cpp index e85ad58..bd1dff4 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -66,6 +66,11 @@ std::string getBatchBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot, st return StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, datetime.c_str(),highID, lowID, slot); } +std::string getBatchBackupPathRoot(std::string datetime) { + return StringUtils::stringFormat("%s/%s", batchBackupPath, datetime.c_str()); +} + + uint8_t getSDaccn() { return sdaccn; } @@ -974,7 +979,13 @@ void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB, const delete metadataObj; } -void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { +void writeBackupAllMetadata(const std::string & batchDatetime) { + Metadata *metadataObj = new Metadata(batchDatetime,"", Metadata::thisConsoleSerialId, ""); + metadataObj->write(); + delete metadataObj; +} + +void backupAllSave(Title *titles, int count, const std::string & batchDatetime) { for ( int sourceStorage = 0; sourceStorage < 2 ; sourceStorage++ ) { for (int i = 0; i < count; i++) { if (titles[i].highID == 0 || titles[i].lowID == 0 || !titles[i].saveInit) @@ -997,6 +1008,7 @@ void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { writeMetadata(highID,lowID,slot,isUSB,batchDatetime); } } + writeBackupAllMetadata(batchDatetime); } void backupSavedata(Title *title, uint8_t slot, int8_t wiiuuser, bool common) {