Add filter options.

This commit is contained in:
Steven Smith 2016-05-26 20:46:03 -07:00
parent e73b07bbd8
commit b87332ff68
10 changed files with 341 additions and 80 deletions

View File

@ -4,4 +4,6 @@ sd=FF00FF00
gamecard=FFFF0000
dstitle=FF82004B
file=FF000000
directory=FF0000FF
directory=FF0000FF
enabled=FF00FF00
disabled=FF0000FF

View File

@ -203,6 +203,10 @@ void screen_init() {
colorConfig[COLOR_FILE] = color;
} else if(strcasecmp(key, "directory") == 0) {
colorConfig[COLOR_DIRECTORY] = color;
} else if(strcasecmp(key, "enabled") == 0) {
colorConfig[COLOR_ENABLED] = color;
} else if(strcasecmp(key, "disabled") == 0) {
colorConfig[COLOR_DISABLED] = color;
}
}
}

View File

@ -41,7 +41,7 @@
#define TEXTURE_WIFI_3 30
#define TEXTURE_AUTO_START 31
#define NUM_COLORS 7
#define NUM_COLORS 9
#define COLOR_TEXT 0
#define COLOR_NAND 1
@ -50,6 +50,8 @@
#define COLOR_DS_TITLE 4
#define COLOR_FILE 5
#define COLOR_DIRECTORY 6
#define COLOR_ENABLED 7
#define COLOR_DISABLED 8
void screen_init();
void screen_exit();

View File

@ -19,6 +19,9 @@ static list_item delete_save_data = {"Delete Save Data", COLOR_TEXT, action_dele
typedef struct {
populate_ext_save_data_data populateData;
bool showSD;
bool showNAND;
bool populated;
} extsavedata_data;
@ -77,6 +80,54 @@ static void extsavedata_action_open(linked_list* items, list_item* selected) {
list_display("Ext Save Data Action", "A: Select, B: Return", data, extsavedata_action_update, extsavedata_action_draw_top);
}
static void extsavedata_filters_add_entry(linked_list* items, const char* name, bool* val) {
list_item* item = (list_item*) calloc(1, sizeof(list_item));
if(item != NULL) {
snprintf(item->name, LIST_ITEM_NAME_MAX, "%s", name);
item->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
item->data = val;
linked_list_add(items, item);
}
}
static void extsavedata_filters_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
extsavedata_data* listData = (extsavedata_data*) data;
if(hidKeysDown() & KEY_B) {
linked_list_iter iter;
linked_list_iterate(items, &iter);
while(linked_list_iter_has_next(&iter)) {
free(linked_list_iter_next(&iter));
linked_list_iter_remove(&iter);
}
ui_pop();
list_destroy(view);
return;
}
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
bool* val = (bool*) selected->data;
*val = !(*val);
selected->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
listData->populated = false;
}
if(linked_list_size(items) == 0) {
extsavedata_filters_add_entry(items, "Show SD", &listData->showSD);
extsavedata_filters_add_entry(items, "Show NAND", &listData->showNAND);
}
}
static void extsavedata_filters_open(extsavedata_data* data) {
list_display("Filters", "A: Toggle, B: Return", data, extsavedata_filters_update, NULL);
}
static void extsavedata_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
if(selected != NULL && selected->data != NULL) {
ui_draw_ext_save_data_info(view, selected->data, x1, y1, x2, y2);
@ -103,6 +154,11 @@ static void extsavedata_update(ui_view* view, void* data, linked_list* items, li
return;
}
if(hidKeysDown() & KEY_SELECT) {
extsavedata_filters_open(listData);
return;
}
if(!listData->populated || (hidKeysDown() & KEY_X)) {
if(!listData->populateData.finished) {
svcSignalEvent(listData->populateData.cancelEvent);
@ -132,6 +188,16 @@ static void extsavedata_update(ui_view* view, void* data, linked_list* items, li
}
}
static bool extsavedata_filter(void* data, u64 titleId, FS_MediaType mediaType) {
extsavedata_data* listData = (extsavedata_data*) data;
if(mediaType == MEDIATYPE_SD) {
return listData->showSD;
} else {
return listData->showNAND;
}
}
void extsavedata_open() {
extsavedata_data* data = (extsavedata_data*) calloc(1, sizeof(extsavedata_data));
if(data == NULL) {
@ -140,7 +206,13 @@ void extsavedata_open() {
return;
}
data->populateData.filter = extsavedata_filter;
data->populateData.filterData = data;
data->populateData.finished = true;
list_display("Ext Save Data", "A: Select, B: Return, X: Refresh", data, extsavedata_update, extsavedata_draw_top);
data->showSD = true;
data->showNAND = true;
list_display("Ext Save Data", "A: Select, B: Return, X: Refresh, Select: Filter", data, extsavedata_update, extsavedata_draw_top);
}

View File

@ -48,6 +48,11 @@ typedef struct {
FS_Path archivePath;
FS_Archive archive;
bool showDirectories;
bool showCias;
bool showTickets;
bool showMisc;
char currDir[FILE_PATH_MAX];
list_item* dirItem;
} files_data;
@ -152,6 +157,56 @@ static void files_action_open(linked_list* items, list_item* selected, files_dat
list_display(((file_info*) selected->data)->isDirectory ? "Directory Action" : "File Action", "A: Select, B: Return", data, files_action_update, files_action_draw_top);
}
static void files_filters_add_entry(linked_list* items, const char* name, bool* val) {
list_item* item = (list_item*) calloc(1, sizeof(list_item));
if(item != NULL) {
snprintf(item->name, LIST_ITEM_NAME_MAX, "%s", name);
item->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
item->data = val;
linked_list_add(items, item);
}
}
static void files_filters_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
files_data* listData = (files_data*) data;
if(hidKeysDown() & KEY_B) {
linked_list_iter iter;
linked_list_iterate(items, &iter);
while(linked_list_iter_has_next(&iter)) {
free(linked_list_iter_next(&iter));
linked_list_iter_remove(&iter);
}
ui_pop();
list_destroy(view);
return;
}
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
bool* val = (bool*) selected->data;
*val = !(*val);
selected->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
listData->populated = false;
}
if(linked_list_size(items) == 0) {
files_filters_add_entry(items, "Show directories", &listData->showDirectories);
files_filters_add_entry(items, "Show CIAs", &listData->showCias);
files_filters_add_entry(items, "Show tickets", &listData->showTickets);
files_filters_add_entry(items, "Show miscellaneous", &listData->showMisc);
}
}
static void files_filters_open(files_data* data) {
list_display("Filters", "A: Toggle, B: Return", data, files_filters_update, NULL);
}
static void files_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
if(selected != NULL && selected->data != NULL) {
ui_draw_file_info(view, selected->data, x1, y1, x2, y2);
@ -246,6 +301,11 @@ static void files_update(ui_view* view, void* data, linked_list* items, list_ite
}
}
if(hidKeysDown() & KEY_SELECT) {
files_filters_open(listData);
return;
}
if((hidKeysDown() & KEY_Y) && listData->dirItem != NULL) {
files_action_open(items, listData->dirItem, listData);
return;
@ -273,6 +333,26 @@ static void files_update(ui_view* view, void* data, linked_list* items, list_ite
}
}
static bool files_filter(void* data, const char* name, u32 attributes) {
files_data* listData = (files_data*) data;
if((attributes & FS_ATTRIBUTE_DIRECTORY) != 0) {
return listData->showDirectories;
} else {
size_t len = strlen(name);
if(len >= 4) {
const char* extension = name + len - 4;
if(strncmp(extension, ".cia", 4) == 0) {
return listData->showCias;
} else if(strncmp(extension, ".tik", 4) == 0) {
return listData->showTickets;
}
}
}
return listData->showMisc;
}
void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
files_data* data = (files_data*) calloc(1, sizeof(files_data));
if(data == NULL) {
@ -285,10 +365,18 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
data->populateData.includeBase = false;
data->populateData.dirsFirst = true;
data->populateData.filter = files_filter;
data->populateData.filterData = data;
data->populateData.finished = true;
data->populated = false;
data->showDirectories = true;
data->showCias = true;
data->showTickets = true;
data->showMisc = true;
data->archiveId = archiveId;
data->archivePath.type = archivePath.type;
data->archivePath.size = archivePath.size;
@ -317,7 +405,7 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
return;
}
list_display("Files", "A: Select, B: Back, X: Refresh, Y: Directory Action", data, files_update, files_draw_top);
list_display("Files", "A: Select, B: Back, X: Refresh, Y: Dir, Select: Filter", data, files_update, files_draw_top);
}
void files_open_sd() {

View File

@ -35,73 +35,75 @@ static Result task_populate_ext_save_data_from(populate_ext_save_data_data* data
break;
}
list_item* item = (list_item*) calloc(1, sizeof(list_item));
if(item != NULL) {
ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) calloc(1, sizeof(ext_save_data_info));
if(extSaveDataInfo != NULL) {
extSaveDataInfo->mediaType = mediaType;
extSaveDataInfo->extSaveDataId = extSaveDataIds[i];
extSaveDataInfo->shared = mediaType == MEDIATYPE_NAND;
extSaveDataInfo->hasMeta = false;
if(data->filter == NULL || data->filter(data->filterData, extSaveDataIds[i], mediaType)) {
list_item* item = (list_item*) calloc(1, sizeof(list_item));
if(item != NULL) {
ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) calloc(1, sizeof(ext_save_data_info));
if(extSaveDataInfo != NULL) {
extSaveDataInfo->mediaType = mediaType;
extSaveDataInfo->extSaveDataId = extSaveDataIds[i];
extSaveDataInfo->shared = mediaType == MEDIATYPE_NAND;
extSaveDataInfo->hasMeta = false;
FS_ExtSaveDataInfo info = {.mediaType = mediaType, .saveId = extSaveDataIds[i]};
FS_ExtSaveDataInfo info = {.mediaType = mediaType, .saveId = extSaveDataIds[i]};
SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH));
if(smdh != NULL) {
u32 smdhBytesRead = 0;
if(R_SUCCEEDED(FSUSER_ReadExtSaveDataIcon(&smdhBytesRead, info, sizeof(SMDH), (u8*) smdh)) && smdhBytesRead == sizeof(SMDH)) {
if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') {
u8 systemLanguage = CFG_LANGUAGE_EN;
CFGU_GetSystemLanguage(&systemLanguage);
SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH));
if(smdh != NULL) {
u32 smdhBytesRead = 0;
if(R_SUCCEEDED(FSUSER_ReadExtSaveDataIcon(&smdhBytesRead, info, sizeof(SMDH), (u8*) smdh)) && smdhBytesRead == sizeof(SMDH)) {
if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') {
u8 systemLanguage = CFG_LANGUAGE_EN;
CFGU_GetSystemLanguage(&systemLanguage);
utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, LIST_ITEM_NAME_MAX - 1);
utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, LIST_ITEM_NAME_MAX - 1);
extSaveDataInfo->hasMeta = true;
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->meta.shortDescription) - 1);
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->meta.longDescription) - 1);
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(extSaveDataInfo->meta.publisher) - 1);
extSaveDataInfo->meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false);
extSaveDataInfo->hasMeta = true;
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->meta.shortDescription) - 1);
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->meta.longDescription) - 1);
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(extSaveDataInfo->meta.publisher) - 1);
extSaveDataInfo->meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false);
}
}
free(smdh);
}
bool empty = strlen(item->name) == 0;
if(!empty) {
empty = true;
char* curr = item->name;
while(*curr) {
if(*curr != ' ') {
empty = false;
break;
}
curr++;
}
}
free(smdh);
}
bool empty = strlen(item->name) == 0;
if(!empty) {
empty = true;
char* curr = item->name;
while(*curr) {
if(*curr != ' ') {
empty = false;
break;
}
curr++;
if(empty) {
snprintf(item->name, LIST_ITEM_NAME_MAX, "%016llX", extSaveDataIds[i]);
}
if(mediaType == MEDIATYPE_NAND) {
item->color = COLOR_NAND;
} else if(mediaType == MEDIATYPE_SD) {
item->color = COLOR_SD;
}
item->data = extSaveDataInfo;
linked_list_add(data->items, item);
} else {
free(item);
res = R_FBI_OUT_OF_MEMORY;
}
if(empty) {
snprintf(item->name, LIST_ITEM_NAME_MAX, "%016llX", extSaveDataIds[i]);
}
if(mediaType == MEDIATYPE_NAND) {
item->color = COLOR_NAND;
} else if(mediaType == MEDIATYPE_SD) {
item->color = COLOR_SD;
}
item->data = extSaveDataInfo;
linked_list_add(data->items, item);
} else {
free(item);
res = R_FBI_OUT_OF_MEMORY;
}
} else {
res = R_FBI_OUT_OF_MEMORY;
}
}
}

View File

@ -4,6 +4,7 @@
#include <string.h>
#include <3ds.h>
#include <3ds/services/fs.h>
#include "task.h"
#include "../../list.h"
@ -192,25 +193,27 @@ static void task_populate_files_thread(void* arg) {
char name[FILE_NAME_MAX] = {'\0'};
utf16_to_utf8((uint8_t*) name, entries[i].name, FILE_NAME_MAX - 1);
char path[FILE_PATH_MAX] = {'\0'};
snprintf(path, FILE_PATH_MAX, "%s%s", curr->path, name);
if(data->filter == NULL || data->filter(data->filterData, name, entries[i].attributes)) {
char path[FILE_PATH_MAX] = {'\0'};
snprintf(path, FILE_PATH_MAX, "%s%s", curr->path, name);
list_item* item = NULL;
if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) {
if(curr->isDirectory && strncmp(curr->path, data->base->path, FILE_PATH_MAX) == 0) {
file_info* info = (file_info*) item->data;
list_item* item = NULL;
if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) {
if(curr->isDirectory && strncmp(curr->path, data->base->path, FILE_PATH_MAX) == 0) {
file_info* info = (file_info*) item->data;
if(info->isCia) {
data->base->containsCias = true;
} else if(info->isTicket) {
data->base->containsTickets = true;
if(info->isCia) {
data->base->containsCias = true;
} else if(info->isTicket) {
data->base->containsTickets = true;
}
}
}
if(data->recursive && ((file_info*) item->data)->isDirectory) {
linked_list_add(&queue, item);
} else {
linked_list_add(data->items, item);
if(data->recursive && ((file_info*) item->data)->isDirectory) {
linked_list_add(&queue, item);
} else {
linked_list_add(data->items, item);
}
}
}
}

View File

@ -273,12 +273,14 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType
break;
}
bool dsiWare = ((titleIds[i] >> 32) & 0x8000) != 0;
if(dsiWare != useDSiWare) {
continue;
}
if(data->filter == NULL || data->filter(data->filterData, titleIds[i], mediaType)) {
bool dsiWare = ((titleIds[i] >> 32) & 0x8000) != 0;
if(dsiWare != useDSiWare) {
continue;
}
res = dsiWare ? task_populate_titles_add_twl(data, mediaType, titleIds[i]) : task_populate_titles_add_ctr(data, mediaType, titleIds[i]);
res = dsiWare ? task_populate_titles_add_twl(data, mediaType, titleIds[i]) : task_populate_titles_add_ctr(data, mediaType, titleIds[i]);
}
}
}

View File

@ -130,6 +130,9 @@ typedef struct data_op_info_s {
typedef struct {
linked_list* items;
bool (*filter)(void* data, u64 extSaveDataId, FS_MediaType mediaType);
void* filterData;
volatile bool finished;
Result result;
Handle cancelEvent;
@ -144,6 +147,9 @@ typedef struct {
bool includeBase;
bool dirsFirst;
bool (*filter)(void* data, const char* name, u32 attributes);
void* filterData;
volatile bool finished;
Result result;
Handle cancelEvent;
@ -176,6 +182,9 @@ typedef struct {
typedef struct {
linked_list* items;
bool (*filter)(void* data, u64 titleId, FS_MediaType mediaType);
void* filterData;
volatile bool finished;
Result result;
Handle cancelEvent;

View File

@ -24,6 +24,10 @@ static list_item delete_secure_value = {"Delete Secure Value", COLOR_TEXT, actio
typedef struct {
populate_titles_data populateData;
bool showGameCard;
bool showSD;
bool showNAND;
bool populated;
} titles_data;
@ -102,6 +106,55 @@ static void titles_action_open(linked_list* items, list_item* selected) {
list_display("Title Action", "A: Select, B: Return", data, titles_action_update, titles_action_draw_top);
}
static void titles_filters_add_entry(linked_list* items, const char* name, bool* val) {
list_item* item = (list_item*) calloc(1, sizeof(list_item));
if(item != NULL) {
snprintf(item->name, LIST_ITEM_NAME_MAX, "%s", name);
item->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
item->data = val;
linked_list_add(items, item);
}
}
static void titles_filters_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
titles_data* listData = (titles_data*) data;
if(hidKeysDown() & KEY_B) {
linked_list_iter iter;
linked_list_iterate(items, &iter);
while(linked_list_iter_has_next(&iter)) {
free(linked_list_iter_next(&iter));
linked_list_iter_remove(&iter);
}
ui_pop();
list_destroy(view);
return;
}
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
bool* val = (bool*) selected->data;
*val = !(*val);
selected->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
listData->populated = false;
}
if(linked_list_size(items) == 0) {
titles_filters_add_entry(items, "Show game card", &listData->showGameCard);
titles_filters_add_entry(items, "Show SD", &listData->showSD);
titles_filters_add_entry(items, "Show NAND", &listData->showNAND);
}
}
static void titles_filters_open(titles_data* data) {
list_display("Filters", "A: Toggle, B: Return", data, titles_filters_update, NULL);
}
static void titles_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
if(selected != NULL && selected->data != NULL) {
ui_draw_title_info(view, selected->data, x1, y1, x2, y2);
@ -128,6 +181,11 @@ static void titles_update(ui_view* view, void* data, linked_list* items, list_it
return;
}
if(hidKeysDown() & KEY_SELECT) {
titles_filters_open(listData);
return;
}
if(!listData->populated || (hidKeysDown() & KEY_X)) {
if(!listData->populateData.finished) {
svcSignalEvent(listData->populateData.cancelEvent);
@ -157,6 +215,18 @@ static void titles_update(ui_view* view, void* data, linked_list* items, list_it
}
}
static bool titles_filter(void* data, u64 titleId, FS_MediaType mediaType) {
titles_data* listData = (titles_data*) data;
if(mediaType == MEDIATYPE_GAME_CARD) {
return listData->showGameCard;
} else if(mediaType == MEDIATYPE_SD) {
return listData->showSD;
} else {
return listData->showNAND;
}
}
void titles_open() {
titles_data* data = (titles_data*) calloc(1, sizeof(titles_data));
if(data == NULL) {
@ -165,7 +235,14 @@ void titles_open() {
return;
}
data->populateData.filter = titles_filter;
data->populateData.filterData = data;
data->populateData.finished = true;
list_display("Titles", "A: Select, B: Return, X: Refresh", data, titles_update, titles_draw_top);
data->showGameCard = true;
data->showSD = true;
data->showNAND = true;
list_display("Titles", "A: Select, B: Return, X: Refresh, Select: Filter", data, titles_update, titles_draw_top);
}