jfileselect: add a programmable filter

This commit is contained in:
Lephenixnoir 2022-11-05 18:50:40 +01:00
parent 34ee43d67f
commit a588c24f59
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
2 changed files with 40 additions and 19 deletions

View File

@ -39,6 +39,8 @@ typedef struct {
bool saveas;
/* Whether we are currently using the input field */
bool input_mode;
/* File filter; NULL accepts everything */
bool (*filter_function)(struct dirent const *entry);
/* Current cursor position (0 .. folder_entries-1) */
int16_t cursor;
@ -96,6 +98,18 @@ char const *jfileselect_selected_file(jfileselect *fs);
/* jfileselect_current_folder(): Get the path to the current folder */
char const *jfileselect_current_folder(jfileselect *fs);
/* jfileselect_set_filter(): Set a filter function
The function is called on each directory entry read when scanning a folder.
It should return true to show the entry, false to ignore it. By default,
jfileselect_default_filter is used. Note filters in general should really
accept folders. */
void jfileselect_set_filter(jfileselect *fs,
bool (*filter)(struct dirent const *entry));
/* Default filter. Rejects "@MainMem", "SAVE-F", "." and "..". */
bool jfileselect_default_filter(struct dirent const *entry);
/* Trivial properties */
void jfileselect_set_font(jfileselect *fs, font_t const *font);
void jfileselect_set_line_spacing(jfileselect *fs, int line_spacing);

View File

@ -56,6 +56,8 @@ jfileselect *jfileselect_create(void *parent)
fs->selected_file = NULL;
fs->saveas_input = input;
fs->saveas = false;
fs->input_mode = false;
fs->filter_function = jfileselect_default_filter;
fs->cursor = -1;
fs->scroll = 0;
@ -166,28 +168,14 @@ static char *path_up(char const *path)
return parent;
}
static bool accept_entry(struct dirent *ent)
{
/* TODO: jfileselect: Programmable filter */
if(!strcmp(ent->d_name, "@MainMem"))
return false;
if(!strcmp(ent->d_name, "SAVE-F"))
return false;
if(!strcmp(ent->d_name, "."))
return false;
if(!strcmp(ent->d_name, ".."))
return false;
return true;
}
static int count_accepted_entries(DIR *dp)
static int count_accepted_entries(jfileselect *fs, DIR *dp)
{
int n = 0;
struct dirent *ent;
rewinddir(dp);
while((ent = readdir(dp)))
n += accept_entry(ent);
n += (fs->filter_function ? fs->filter_function(ent) : 1);
return n;
}
@ -222,7 +210,7 @@ static bool load_folder_switch(jfileselect *fs, char *path)
return false;
/* Count entries */
int n = count_accepted_entries(dp) + fs->saveas;
int n = count_accepted_entries(fs, dp) + fs->saveas;
/* Allocate memory for the fileinfo structures */
struct fileinfo *finfo = malloc(n * sizeof *finfo);
@ -234,7 +222,7 @@ static bool load_folder_switch(jfileselect *fs, char *path)
/* Read the fileinfo structures */
rewinddir(dp);
for(int i = 0; i < n && (ent = readdir(dp));) {
if(!accept_entry(ent))
if(fs->filter_function && !fs->filter_function(ent))
continue;
finfo[i].name = strdup(ent->d_name);
@ -254,7 +242,7 @@ static bool load_folder_switch(jfileselect *fs, char *path)
if(ent->d_type == DT_DIR) {
DIR *sub = opendir(full_path);
if(sub) {
finfo[i].size = count_accepted_entries(sub);
finfo[i].size = count_accepted_entries(fs, sub);
closedir(sub);
}
}
@ -320,6 +308,25 @@ char const *jfileselect_current_folder(jfileselect *fs)
return fs->path;
}
void jfileselect_set_filter(jfileselect *fs,
bool (*filter)(struct dirent const *entry))
{
fs->filter_function = filter;
}
bool jfileselect_default_filter(struct dirent const *ent)
{
if(!strcmp(ent->d_name, "@MainMem"))
return false;
if(!strcmp(ent->d_name, "SAVE-F"))
return false;
if(!strcmp(ent->d_name, "."))
return false;
if(!strcmp(ent->d_name, ".."))
return false;
return true;
}
//---
// Polymorphic widget operations
//---