Fix: changing "filter_glob" didn't refresh the file-selector

The glob is applied when reading the directory,
where it flags matching entries as FILE_TYPE_OPERATOR.

This meant using the filter refresh didn't after changing the glob
didn't re-evaluate each entries flag.

Resolve by setting the glob separately, re-flagging the entries before
filtering instead of reading the directory again.

Ref !162945
This commit is contained in:
Campbell Barton 2026-08-21 11:56:45 +10:00
parent 22d032d85b
commit 1eefaf911f
8 changed files with 61 additions and 15 deletions

View file

@ -161,7 +161,6 @@ void AssetList::ensure_updated()
true,
/*filter_assets_hide_online=*/!show_online,
/*filter_assets_hide_offline=*/!show_offline,
"",
"");
filelist_set_asset_include_online(files, show_online);
}

View file

@ -57,7 +57,6 @@ void filelist_setfilter_options(FileList *filelist,
bool filter_assets_only,
bool filter_assets_hide_online,
bool filter_assets_hide_offline,
const char *filter_glob,
const char *filter_search);
/**
* Set the indexer to be used by the filelist.
@ -227,6 +226,8 @@ void filelist_entry_parent_select_set(FileList *filelist,
FileCheckType check);
void filelist_setrecursion(FileList *filelist, int recursion_level);
/** Set the extension glob used to tag entries with #FILE_TYPE_OPERATOR. */
void filelist_setglob(FileList *filelist, const char *filter_glob);
asset_system::AssetLibrary *filelist_asset_library(FileList *filelist);

View file

@ -1155,6 +1155,45 @@ void filelist_setrecursion(FileList *filelist, const int recursion_level)
}
}
void filelist_entry_glob_tag(FileListInternEntry *entry, const char *filter_glob)
{
entry->typeflag &= ~FILE_TYPE_OPERATOR;
if (entry->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB)) {
return;
}
if (filter_glob[0] == '\0') {
return;
}
/* Aliases & shortcuts match their target, its extension may differ from the link. */
const char *path = entry->redirection_path ? entry->redirection_path : entry->relpath;
if (BLI_path_extension_check_glob(path, filter_glob)) {
entry->typeflag |= FILE_TYPE_OPERATOR;
}
}
void filelist_reset_glob(FileList *filelist)
{
for (FileListInternEntry &entry : filelist->filelist_intern.entries) {
filelist_entry_glob_tag(&entry, filelist->filter_glob);
}
filelist->flags &= ~FL_NEED_RESET_GLOB;
}
void filelist_setglob(FileList *filelist, const char *filter_glob)
{
/* The glob is stored in #FileListInternEntry.typeflag, so filtering again isn't enough.
* Re-tag the entries, reading the directory again would be needlessly heavy. */
if (!STREQ(filelist->filter_glob, filter_glob)) {
STRNCPY(filelist->filter_glob, filter_glob);
filelist->flags |= FL_NEED_RESET_GLOB;
filelist_tag_needs_filtering(filelist);
}
}
bool filelist_needs_force_reset(const FileList *filelist)
{
return (filelist->flags & (FL_FORCE_RESET | FL_FORCE_RESET_MAIN_FILES)) != 0;

View file

@ -324,6 +324,10 @@ void filelist_filter(FileList *filelist)
return;
}
if (filelist->flags & FL_NEED_RESET_GLOB) {
filelist_reset_glob(filelist);
}
filelist->filter_data.flags &= ~FLF_HIDE_LIB_DIR;
if (filelist->max_recursion) {
/* Never show lib ID 'categories' directories when we are in 'flat' mode, unless
@ -379,7 +383,6 @@ void filelist_setfilter_options(FileList *filelist,
const bool filter_assets_only,
const bool filter_assets_hide_online,
const bool filter_assets_hide_offline,
const char *filter_glob,
const char *filter_search)
{
bool update = false;
@ -421,10 +424,6 @@ void filelist_setfilter_options(FileList *filelist,
filelist->filter_data.filter_id = new_filter_id;
update = true;
}
if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
STRNCPY_UTF8(filelist->filter_data.filter_glob, filter_glob);
update = true;
}
if (BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0) {
BLI_strncpy_ensure_pad(filelist->filter_data.filter_search,
filter_search,

View file

@ -178,7 +178,6 @@ struct FileListEntryPreviewTaskData {
struct FileListFilter {
uint64_t filter;
uint64_t filter_id;
char filter_glob[FILE_MAXFILE];
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
short flags;
@ -232,6 +231,9 @@ struct FileList {
*/
GHash *selection_state;
/** Extension glob, see #filelist_setglob. */
char filter_glob[FILE_MAXFILE];
short max_recursion;
short recursion_level;
@ -278,6 +280,8 @@ enum {
* assets) */
FL_RELOAD_ASSET_LIBRARY = 1 << 7,
FL_ASSETS_INCLUDE_ONLINE = 1 << 8,
/** #FileList.filter_glob changed, re-tag entries instead of reading the directory again. */
FL_NEED_RESET_GLOB = 1 << 9,
};
/** #FileList.tags */
@ -331,6 +335,11 @@ bool filelist_checkdir_lib(const FileList * /*filelist*/,
char dirpath[FILE_MAX_LIBEXTRA],
const bool do_change);
/** Set or clear #FILE_TYPE_OPERATOR on `entry`, from `filter_glob` matching it. */
void filelist_entry_glob_tag(FileListInternEntry *entry, const char *filter_glob);
/** Apply #FileList.filter_glob to the entries already read. */
void filelist_reset_glob(FileList *filelist);
void filelist_set_readjob_directories(FileList *filelist);
void filelist_set_readjob_library(FileList *filelist);
void filelist_set_readjob_on_disk_asset_library(FileList *filelist);

View file

@ -214,8 +214,8 @@ static void filelist_readjob_start_ex(FileList *filelist,
BKE_reports_init(&flrj->reports, RPT_STORE | RPT_PRINT);
BKE_report_print_level_set(&flrj->reports, RPT_WARNING);
filelist->flags &= ~(FL_FORCE_RESET | FL_FORCE_RESET_MAIN_FILES | FL_RELOAD_ASSET_LIBRARY |
FL_IS_READY);
filelist->flags &= ~(FL_FORCE_RESET | FL_FORCE_RESET_MAIN_FILES | FL_NEED_RESET_GLOB |
FL_RELOAD_ASSET_LIBRARY | FL_IS_READY);
filelist->flags |= FL_IS_PENDING;
/* The file list type may not support threading so execute immediately. Same when only rereading

View file

@ -327,12 +327,11 @@ static int filelist_readjob_list_dir(FileListReadJob *job_params,
}
else {
entry->typeflag = eFileSel_File_Types(ED_path_extension_type(target));
if (filter_glob[0] && BLI_path_extension_check_glob(target, filter_glob)) {
entry->typeflag |= FILE_TYPE_OPERATOR;
}
}
}
filelist_entry_glob_tag(entry, filter_glob);
#ifndef WIN32
/* Set linux-style dot files hidden too. */
if (BLI_path_has_hidden_component(entry->relpath)) {
@ -706,7 +705,7 @@ void filelist_readjob_recursive_dir_add_items(const bool do_lib,
td_dir->level = 1;
STRNCPY(dir, filelist->filelist.root);
STRNCPY(filter_glob, filelist->filter_data.filter_glob);
STRNCPY(filter_glob, filelist->filter_glob);
BLI_path_abs(dir, job_params->main_filepath);
BLI_path_normalize_dir(dir, sizeof(dir));

View file

@ -240,6 +240,7 @@ static void file_refresh(const bContext *C, ScrArea *area)
filelist_settype(sfile->files, params->type);
filelist_setdir(sfile->files, params->dir);
filelist_setrecursion(sfile->files, params->recursion_level);
filelist_setglob(sfile->files, params->filter_glob);
filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT);
filelist_setlibrary(
sfile->files, asset_params ? &asset_params->asset_library_ref : nullptr, [&]() {
@ -269,7 +270,6 @@ static void file_refresh(const bContext *C, ScrArea *area)
(params->flag & FILE_ASSETS_ONLY) != 0,
/*filter_assets_hide_online=*/!show_assets_online,
/*filter_assets_hide_offline=*/!show_assets_offline,
params->filter_glob,
params->filter_search);
if (asset_params) {
filelist_set_asset_include_online(sfile->files, show_assets_online);