diff --git a/include/fs.h b/include/fs.h index aa40877..029b07e 100644 --- a/include/fs.h +++ b/include/fs.h @@ -20,6 +20,8 @@ namespace FS { bool FileExists(FS_Archive archive, const std::string &path); bool DirExists(FS_Archive archive, const std::string &path); std::string GetFileExt(const std::string &filename); + u64 GetTotalStorage(FS_SystemMediaType mediatype); + u64 GetUsedStorage(FS_SystemMediaType mediatype); FileType GetFileType(const std::string &filename); Result GetDirList(const std::string &path, std::vector &entries); Result ChangeDirNext(const std::string &path, std::vector &entries); diff --git a/include/gui.h b/include/gui.h index 9b31c40..1ecdc4d 100644 --- a/include/gui.h +++ b/include/gui.h @@ -31,6 +31,7 @@ typedef struct { namespace GUI { void ResetCheckbox(MenuItem *item); + void RecalcStorageSize(MenuItem *item); Result Loop(void); // Windows diff --git a/source/fs.cpp b/source/fs.cpp index 516b75c..cf3b173 100644 --- a/source/fs.cpp +++ b/source/fs.cpp @@ -85,6 +85,43 @@ namespace FS { return FileTypeNone; } + static u64 GetFreeStorage(FS_SystemMediaType mediatype) { + Result ret = 0; + FS_ArchiveResource resource = { 0 }; + + if (R_FAILED(ret = FSUSER_GetArchiveResource(&resource, mediatype))) { + Log::Error("FSUSER_GetArchiveResource(GetFreeStorage) failed: 0x%x\n", ret); + return ret; + } + + return (static_cast(resource.freeClusters) * static_cast(resource.clusterSize)); + } + + u64 GetTotalStorage(FS_SystemMediaType mediatype) { + Result ret = 0; + FS_ArchiveResource resource = { 0 }; + + if (R_FAILED(ret = FSUSER_GetArchiveResource(&resource, mediatype))) { + Log::Error("FSUSER_GetArchiveResource(GetTotalStorage) failed: 0x%x\n", ret); + return ret; + } + + return (static_cast(resource.totalClusters) * static_cast(resource.clusterSize)); + } + + u64 GetUsedStorage(FS_SystemMediaType mediatype) { + Result ret = 0; + FS_ArchiveResource resource = { 0 }; + + if (R_FAILED(ret = FSUSER_GetArchiveResource(&resource, mediatype))) { + Log::Error("FSUSER_GetArchiveResource(GetUsedStorage) failed: 0x%x\n", ret); + return ret; + } + + return ((static_cast(resource.totalClusters) * static_cast(resource.clusterSize)) - + (static_cast(resource.freeClusters) * static_cast(resource.clusterSize))); + } + static bool Sort(const FS_DirectoryEntry &entryA, const FS_DirectoryEntry &entryB) { if ((entryA.attributes & FS_ATTRIBUTE_DIRECTORY) && !(entryB.attributes & FS_ATTRIBUTE_DIRECTORY)) return true; @@ -248,6 +285,13 @@ namespace FS { FSFILE_Close(src_handle); return ret; } + + // Make sure we have enough storage to carry out this operation + if (FS::GetFreeStorage(src_archive == sdmc_archive? SYSTEM_MEDIATYPE_SD : SYSTEM_MEDIATYPE_CTR_NAND) < size) { + Log::Error("Not enough storage is available to process this command 0x%x\n", src_path.c_str(), ret); + FSFILE_Close(src_handle); + return -1; + } // This may fail or not, but we don't care -> create the file if it doesn't exist, otherwise continue. FSUSER_CreateFile(archive, fsMakePath(PATH_UTF16, dest_path.c_str()), 0, size); diff --git a/source/gui/delete.cpp b/source/gui/delete.cpp index f2d4a4b..20d4279 100644 --- a/source/gui/delete.cpp +++ b/source/gui/delete.cpp @@ -63,7 +63,8 @@ namespace GUI { FS::GetDirList(cfg.cwd, item->entries); GUI::ResetCheckbox(item); } - + + GUI::RecalcStorageSize(item); Log::Open(); selection = 0; item->state = MENU_STATE_OPTIONS; diff --git a/source/gui/filebrowser.cpp b/source/gui/filebrowser.cpp index e88bf96..1004d47 100644 --- a/source/gui/filebrowser.cpp +++ b/source/gui/filebrowser.cpp @@ -22,7 +22,12 @@ namespace GUI { void DisplayFileBrowser(MenuItem *item) { float filename_height = 0.0f; C2D::GetTextSize(0.45f, nullptr, &filename_height, cfg.cwd.c_str()); - C2D::Text(35, 15 + ((25 - filename_height) / 2), 0.45f, WHITE, cfg.cwd.c_str()); + C2D::Text(5, 15 + ((25 - filename_height) / 2), 0.45f, WHITE, cfg.cwd.c_str()); + + // Storage bar + C2D::Rect(5, 28 + ((25 - filename_height) / 2), 390, 2, cfg.dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); + float fill = (static_cast(item->used_storage)/static_cast(item->total_storage)) * 390.0; + C2D::Rect(5, 28 + ((25 - filename_height) / 2), fill, 2, cfg.dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR); if (item->entries.empty()) { C2D::GetTextSize(0.50f, &empty_dir_width, &empty_dir_height, empty_dir.c_str()); diff --git a/source/gui/gui.cpp b/source/gui/gui.cpp index 75b7732..291231f 100644 --- a/source/gui/gui.cpp +++ b/source/gui/gui.cpp @@ -20,6 +20,11 @@ namespace GUI { item->checked_count = 0; }; + void RecalcStorageSize(MenuItem *item) { + item->total_storage = FS::GetTotalStorage(archive == sdmc_archive? SYSTEM_MEDIATYPE_SD : SYSTEM_MEDIATYPE_CTR_NAND); + item->used_storage = FS::GetUsedStorage(archive == sdmc_archive? SYSTEM_MEDIATYPE_SD : SYSTEM_MEDIATYPE_CTR_NAND); + } + static void DisplayStatusBar(void) { const std::time_t time = std::time(nullptr); const std::tm calendar_time = *std::localtime(std::addressof(time)); @@ -69,6 +74,7 @@ namespace GUI { return ret; GUI::ResetCheckbox(&item); + GUI::RecalcStorageSize(&item); while(aptMainLoop()) { C3D_FrameBegin(C3D_FRAME_SYNCDRAW); diff --git a/source/gui/options.cpp b/source/gui/options.cpp index c4fbf57..d6fc13c 100644 --- a/source/gui/options.cpp +++ b/source/gui/options.cpp @@ -134,6 +134,7 @@ namespace GUI { } } + GUI::RecalcStorageSize(item); copy = !copy; item->state = MENU_STATE_FILEBROWSER; }