mGUI: Revamp file filtering

This commit is contained in:
Vicki Pfau 2018-09-03 17:54:40 -07:00
parent cfc90a3b67
commit cbf460a164
4 changed files with 66 additions and 28 deletions

View File

@ -14,7 +14,7 @@ CXX_GUARD_START
struct VFile;
bool GUISelectFile(struct GUIParams*, char* outPath, size_t outLen, bool (*filter)(struct VFile*));
bool GUISelectFile(struct GUIParams*, char* outPath, size_t outLen, bool (*filterName)(const char* name), bool (*filterContents)(struct VFile*));
CXX_GUARD_END

View File

@ -15,11 +15,25 @@
#endif
#include <mgba-util/gui/file-select.h>
#include <mgba-util/gui/menu.h>
#include <mgba-util/vfs.h>
#ifndef GUI_MAX_INPUTS
#define GUI_MAX_INPUTS 7
#endif
static bool _biosNamed(const char* name) {
char ext[PATH_MAX + 1] = {};
separatePath(name, NULL, NULL, ext);
if (strnstr(name, "bios", PATH_MAX)) {
return true;
}
if (!strncmp(ext, "bin", PATH_MAX)) {
return true;
}
return false;
}
void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t nExtra) {
struct GUIMenu menu = {
.title = "Configure",
@ -183,7 +197,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
}
if (!strcmp(item->data, "gba.bios")) {
// TODO: show box if failed
if (!GUISelectFile(&runner->params, gbaBiosPath, sizeof(gbaBiosPath), GBAIsBIOS)) {
if (!GUISelectFile(&runner->params, gbaBiosPath, sizeof(gbaBiosPath), _biosNamed, GBAIsBIOS)) {
gbaBiosPath[0] = '\0';
}
continue;
@ -191,21 +205,21 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t
#ifdef M_CORE_GB
if (!strcmp(item->data, "gb.bios")) {
// TODO: show box if failed
if (!GUISelectFile(&runner->params, gbBiosPath, sizeof(gbBiosPath), GBIsBIOS)) {
if (!GUISelectFile(&runner->params, gbBiosPath, sizeof(gbBiosPath), _biosNamed, GBIsBIOS)) {
gbBiosPath[0] = '\0';
}
continue;
}
if (!strcmp(item->data, "gbc.bios")) {
// TODO: show box if failed
if (!GUISelectFile(&runner->params, gbcBiosPath, sizeof(gbcBiosPath), GBIsBIOS)) {
if (!GUISelectFile(&runner->params, gbcBiosPath, sizeof(gbcBiosPath), _biosNamed, GBIsBIOS)) {
gbcBiosPath[0] = '\0';
}
continue;
}
if (!strcmp(item->data, "sgb.bios")) {
// TODO: show box if failed
if (!GUISelectFile(&runner->params, sgbBiosPath, sizeof(sgbBiosPath), GBIsBIOS)) {
if (!GUISelectFile(&runner->params, sgbBiosPath, sizeof(sgbBiosPath), _biosNamed, GBIsBIOS)) {
sgbBiosPath[0] = '\0';
}
continue;

View File

@ -73,6 +73,24 @@ static struct mGUILogger {
.logLevel = 0
};
static bool _testExtensions(const char* name) {
char ext[PATH_MAX] = {};
separatePath(name, NULL, NULL, ext);
if (!strncmp(ext, "sav", PATH_MAX)) {
return false;
}
if (!strncmp(ext, "png", PATH_MAX)) {
return false;
}
if (!strncmp(ext, "ini", PATH_MAX)) {
return false;
}
if (!strncmp(ext, "ss", 2)) {
return false;
}
}
static void _drawBackground(struct GUIBackground* background, void* context) {
UNUSED(context);
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
@ -580,7 +598,7 @@ void mGUIRunloop(struct mGUIRunner* runner) {
}
while (true) {
char path[PATH_MAX];
if (!GUISelectFile(&runner->params, path, sizeof(path), 0)) {
if (!GUISelectFile(&runner->params, path, sizeof(path), _testExtensions, NULL)) {
break;
}
mCoreConfigSetValue(&runner->config, "lastDirectory", runner->params.currentPath);

View File

@ -47,7 +47,7 @@ static int _strpcmp(const void* a, const void* b) {
return strcasecmp(((const struct GUIMenuItem*) a)->title, ((const struct GUIMenuItem*) b)->title);
}
static bool _refreshDirectory(struct GUIParams* params, const char* currentPath, struct GUIMenuItemList* currentFiles, bool (*filter)(struct VFile*)) {
static bool _refreshDirectory(struct GUIParams* params, const char* currentPath, struct GUIMenuItemList* currentFiles, bool (*filterName)(const char* name), bool (*filterContents)(struct VFile*)) {
_cleanFiles(currentFiles);
struct VDir* dir = VDirOpen(currentPath);
@ -90,7 +90,7 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
} else {
name = strdup(name);
}
*GUIMenuItemListAppend(currentFiles) = (struct GUIMenuItem) { .title = name };
*GUIMenuItemListAppend(currentFiles) = (struct GUIMenuItem) { .title = name, .data = (void*) de->type(de) };
++items;
}
qsort(GUIMenuItemListGetPointer(currentFiles, 1), GUIMenuItemListSize(currentFiles) - 1, sizeof(struct GUIMenuItem), _strpcmp);
@ -116,42 +116,48 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
}
params->drawEnd();
}
if (!filter) {
struct GUIMenuItem* testItem = GUIMenuItemListGetPointer(currentFiles, item);
if (testItem->data != (void*) VFS_FILE) {
++item;
continue;
}
struct VDir* vd = dir->openDir(dir, GUIMenuItemListGetPointer(currentFiles, item)->title);
if (vd) {
vd->close(vd);
++item;
continue;
bool failed = false;
if (filterName && !filterName(testItem->title)) {
failed = true;
}
struct VFile* vf = dir->openFile(dir, GUIMenuItemListGetPointer(currentFiles, item)->title, O_RDONLY);
if (vf) {
if (filter(vf)) {
++item;
if (!failed && filterContents) {
struct VFile* vf = dir->openFile(dir, testItem->title, O_RDONLY);
if (!vf) {
failed = true;
} else {
free((char*) GUIMenuItemListGetPointer(currentFiles, item)->title);
GUIMenuItemListShift(currentFiles, item, 1);
if (!filterContents(vf)) {
failed = true;
}
vf->close(vf);
}
vf->close(vf);
continue;
}
++item;
if (failed) {
free((char*) testItem->title);
GUIMenuItemListShift(currentFiles, item, 1);
} else {
++item;
}
}
dir->close(dir);
return true;
}
bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool (*filter)(struct VFile*)) {
bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool (*filterName)(const char* name), bool (*filterContents)(struct VFile*)) {
struct GUIMenu menu = {
.title = "Select file",
.subtitle = params->currentPath,
.index = params->fileIndex,
};
GUIMenuItemListInit(&menu.items, 0);
_refreshDirectory(params, params->currentPath, &menu.items, filter);
_refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents);
while (true) {
struct GUIMenuItem* item;
@ -163,7 +169,7 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool
if (reason == GUI_MENU_EXIT_ACCEPT) {
if (params->fileIndex == 0) {
_upDirectory(params->currentPath);
if (!_refreshDirectory(params, params->currentPath, &menu.items, filter)) {
if (!_refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents)) {
break;
}
} else {
@ -176,7 +182,7 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool
struct GUIMenuItemList newFiles;
GUIMenuItemListInit(&newFiles, 0);
if (!_refreshDirectory(params, outPath, &newFiles, filter)) {
if (!_refreshDirectory(params, outPath, &newFiles, filterName, filterContents)) {
_cleanFiles(&newFiles);
GUIMenuItemListDeinit(&newFiles);
_cleanFiles(&menu.items);
@ -197,7 +203,7 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool
break;
}
_upDirectory(params->currentPath);
if (!_refreshDirectory(params, params->currentPath, &menu.items, filter)) {
if (!_refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents)) {
break;
}
params->fileIndex = 0;