Blender V5.0
filelist_filter.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
10
11#include "BLI_fnmatch.h"
12#include "BLI_listbase.h"
13#include "BLI_path_utils.hh"
14#include "BLI_string.h"
15#include "BLI_string_utf8.h"
16
17#include "BKE_idtype.hh"
18
19#include "../file_intern.hh"
20#include "../filelist.hh"
21#include "filelist_intern.hh"
22
23using namespace blender;
24
25/* True if should be hidden, based on current filtering. */
26static bool is_filtered_hidden(const char *filename,
28 const FileListInternEntry *file)
29{
30 if ((filename[0] == '.') && (filename[1] == '\0')) {
31 return true; /* Ignore. */
32 }
33
34 if (filter->flags & FLF_HIDE_PARENT) {
35 if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') {
36 return true; /* Ignore. */
37 }
38 }
39
40 /* Check for _OUR_ "hidden" attribute. This not only mirrors OS-level hidden file
41 * attribute but is also set for Linux/Mac "dot" files. See `filelist_readjob_list_dir`.
42 */
43 if ((filter->flags & FLF_HIDE_DOT) && (file->attributes & FILE_ATTR_HIDDEN)) {
44 return true;
45 }
46
47 /* For data-blocks (but not the group directories), check the asset-only filter. */
48 if (!(file->typeflag & FILE_TYPE_DIR) && (file->typeflag & FILE_TYPE_BLENDERLIB) &&
49 (filter->flags & FLF_ASSETS_ONLY) && !(file->typeflag & FILE_TYPE_ASSET))
50 {
51 return true;
52 }
53
54 return false;
55}
56
62{
63 if (filter->filter_search[0] == '\0') {
64 return true;
65 }
66
67 /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
68 return fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) == 0;
69}
70
76{
77 if (filter->filter_search[0] == '\0') {
78 return true;
79 }
80
81 /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
82 return fnmatch(filter->filter_search, file->name, FNM_CASEFOLD) == 0;
83}
84
87{
88 if (is_filtered_hidden(file->relpath, filter, file)) {
89 return false;
90 }
91
92 if (FILENAME_IS_CURRPAR(file->relpath)) {
93 return false;
94 }
95
96 /* We only check for types if some type are enabled in filtering. */
97 if (filter->filter && (filter->flags & FLF_DO_FILTER)) {
98 if (file->typeflag & FILE_TYPE_DIR) {
101 return false;
102 }
103 }
104 else {
105 if (!(filter->filter & FILE_TYPE_FOLDER)) {
106 return false;
107 }
108 }
109 }
110 else {
111 if (!(file->typeflag & filter->filter)) {
112 return false;
113 }
114 }
115 }
116 return true;
117}
118
119bool is_filtered_file(FileListInternEntry *file, const char * /*root*/, FileListFilter *filter)
120{
121 return is_filtered_file_type(file, filter) &&
123}
124
126 const short id_code,
127 const char *name,
128 const FileListFilter *filter)
129{
130 if (!is_filtered_file_type(file, filter)) {
131 return false;
132 }
133
134 /* We only check for types if some type are enabled in filtering. */
135 if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
136 if (id_code) {
137 if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) {
138 return false;
139 }
140
141 const uint64_t filter_id = BKE_idtype_idcode_to_idfilter(id_code);
142 if (!(filter_id & filter->filter_id)) {
143 return false;
144 }
145 }
146 }
147
148 return true;
149}
150
156{
157 if (asset_system::AssetRepresentation *asset = file->get_asset()) {
158 return &asset->get_metadata();
159 }
160 return nullptr;
161}
162
164{
165 /* Not used yet for the asset view template. */
166 if (!filter->asset_catalog_filter) {
167 return;
168 }
170 "prepare_filter_asset_library() should only be called when the file browser is "
171 "in asset browser mode");
172
173 file_ensure_updated_catalog_filter_data(filter->asset_catalog_filter, filelist->asset_library);
174}
175
188static bool asset_tag_matches_filter(const char *filter_search, const AssetMetaData *asset_data)
189{
190 LISTBASE_FOREACH (const AssetTag *, asset_tag, &asset_data->tags) {
191 if (BLI_strcasestr(asset_tag->name, filter_search) != nullptr) {
192 return true;
193 }
194 }
195 return false;
196}
197
199{
201
202 /* Not used yet for the asset view template. */
203 if (filter->asset_catalog_filter &&
204 !file_is_asset_visible_in_catalog_filter_settings(filter->asset_catalog_filter, asset_data))
205 {
206 return false;
207 }
208
209 if (filter->filter_search[0] == '\0') {
210 /* If there is no filter text, everything matches. */
211 return true;
212 }
213
214 /* filter->filter_search contains "*the search text*". */
215 char filter_search[sizeof(FileListFilter::filter_search)];
216 const size_t string_length = STRNCPY_RLEN(filter_search, filter->filter_search);
217
218 /* When doing a name comparison, get rid of the leading/trailing asterisks. */
219 filter_search[string_length - 1] = '\0';
220 if (BLI_strcasestr(file->name, filter_search + 1) != nullptr) {
221 return true;
222 }
223 return asset_tag_matches_filter(filter_search + 1, asset_data);
224}
225
227 const char * /*root*/,
229{
230 if (file->typeflag & FILE_TYPE_BLENDERLIB) {
231 return is_filtered_id_file_type(file, file->blentype, file->name, filter);
232 }
233 return is_filtered_file_type(file, filter);
234}
235
237{
238 return is_filtered_lib_type(file, root, filter) && is_filtered_file_relpath(file, filter);
239}
240
242{
243 return !is_filtered_hidden(file->relpath, filter, file);
244}
245
247 const char * /*dir*/,
249{
250 /* "Filtered" means *not* being filtered out... So return true if the file should be visible. */
251 return is_filtered_id_file_type(file, file->blentype, file->name, filter) &&
253}
254
256{
258 return is_filtered_main_assets(file, root, filter);
259 }
260
261 return is_filtered_lib_type(file, root, filter) && is_filtered_asset(file, filter);
262}
263
265{
266 filelist->flags |= FL_NEED_FILTERING;
267}
268
270{
271 return (filelist->flags & FL_NEED_FILTERING);
272}
273
275{
276 int num_filtered = 0;
277 const int num_files = filelist->filelist.entries_num;
278 FileListInternEntry **filtered_tmp;
279
281 return;
282 }
283
284 if (!(filelist->flags & FL_NEED_FILTERING)) {
285 /* Assume it has already been filtered, nothing else to do! */
286 return;
287 }
288
290 if (filelist->max_recursion) {
291 /* Never show lib ID 'categories' directories when we are in 'flat' mode, unless
292 * root path is a blend file. */
293 char dir[FILE_MAX_LIBEXTRA];
294 if (!filelist_islibrary(filelist, dir, nullptr)) {
296 }
297 }
298
299 if (filelist->prepare_filter_fn) {
300 filelist->prepare_filter_fn(filelist, &filelist->filter_data);
301 }
302
303 filtered_tmp = static_cast<FileListInternEntry **>(
304 MEM_mallocN(sizeof(*filtered_tmp) * size_t(num_files), __func__));
305
306 /* Filter remap & count how many files are left after filter in a single loop. */
308 if (filelist->filter_fn(file, filelist->filelist.root, &filelist->filter_data)) {
309 filtered_tmp[num_filtered++] = file;
310 }
311 }
312
313 if (filelist->filelist_intern.filtered) {
315 }
316 filelist->filelist_intern.filtered = static_cast<FileListInternEntry **>(
317 MEM_mallocN(sizeof(*filelist->filelist_intern.filtered) * size_t(num_filtered), __func__));
318 memcpy(filelist->filelist_intern.filtered,
319 filtered_tmp,
320 sizeof(*filelist->filelist_intern.filtered) * size_t(num_filtered));
321 filelist->filelist.entries_filtered_num = num_filtered;
322 // printf("Filtered: %d over %d entries\n", num_filtered, filelist->filelist.entries_num);
323
325 filelist->flags &= ~FL_NEED_FILTERING;
326
327 MEM_freeN(filtered_tmp);
328}
329
331 const bool do_filter,
332 const bool hide_dot,
333 const bool hide_parent,
334 const uint64_t filter,
335 const uint64_t filter_id,
336 const bool filter_assets_only,
337 const char *filter_glob,
338 const char *filter_search)
339{
340 bool update = false;
341
342 if (((filelist->filter_data.flags & FLF_DO_FILTER) != 0) != (do_filter != 0)) {
343 filelist->filter_data.flags ^= FLF_DO_FILTER;
344 update = true;
345 }
346 if (((filelist->filter_data.flags & FLF_HIDE_DOT) != 0) != (hide_dot != 0)) {
347 filelist->filter_data.flags ^= FLF_HIDE_DOT;
348 update = true;
349 }
350 if (((filelist->filter_data.flags & FLF_HIDE_PARENT) != 0) != (hide_parent != 0)) {
351 filelist->filter_data.flags ^= FLF_HIDE_PARENT;
352 update = true;
353 }
354 if (((filelist->filter_data.flags & FLF_ASSETS_ONLY) != 0) != (filter_assets_only != 0)) {
355 filelist->filter_data.flags ^= FLF_ASSETS_ONLY;
356 update = true;
357 }
358 if (filelist->filter_data.filter != filter) {
359 filelist->filter_data.filter = filter;
360 update = true;
361 }
362 const uint64_t new_filter_id = (filter & FILE_TYPE_BLENDERLIB) ? filter_id : FILTER_ID_ALL;
363 if (filelist->filter_data.filter_id != new_filter_id) {
364 filelist->filter_data.filter_id = new_filter_id;
365 update = true;
366 }
367 if (!STREQ(filelist->filter_data.filter_glob, filter_glob)) {
368 STRNCPY_UTF8(filelist->filter_data.filter_glob, filter_glob);
369 update = true;
370 }
371 if (BLI_strcmp_ignore_pad(filelist->filter_data.filter_search, filter_search, '*') != 0) {
373 filter_search,
374 '*',
375 sizeof(filelist->filter_data.filter_search));
376 update = true;
377 }
378
379 if (update) {
380 /* And now, free filtered data so that we know we have to filter again. */
382 }
383}
Main runtime representation of an asset.
uint64_t BKE_idtype_idcode_to_idfilter(short idcode)
Definition idtype.cc:363
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
@ FILE_ATTR_HIDDEN
#define LISTBASE_FOREACH(type, var, list)
#define FILENAME_IS_CURRPAR(_n)
#define STRNCPY_RLEN(dst, src)
Definition BLI_string.h:603
int char char int int int int BLI_strcmp_ignore_pad(const char *str1, const char *str2, char pad) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char char * BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, char pad, size_t dst_maxncpy) ATTR_NONNULL(1
int char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
#define STREQ(a, b)
#define FILTER_ID_ALL
Definition DNA_ID.h:1239
@ FILE_TYPE_BLENDER
@ FILE_TYPE_ASSET
@ FILE_TYPE_BLENDER_BACKUP
@ FILE_TYPE_FOLDER
@ FILE_TYPE_BLENDERLIB
@ FILE_TYPE_DIR
#define FILE_MAX_LIBEXTRA
unsigned long long int uint64_t
void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
Definition filelist.cc:817
bool filelist_intern_entry_is_main_file(const FileListInternEntry *intern_entry)
Definition filelist.cc:403
bool filelist_islibrary(FileList *filelist, char *dir, char **r_group)
Definition filelist.cc:2043
static bool is_filtered_file_relpath(const FileListInternEntry *file, const FileListFilter *filter)
void filelist_tag_needs_filtering(FileList *filelist)
bool is_filtered_asset_library(FileListInternEntry *file, const char *root, FileListFilter *filter)
bool is_filtered_asset(FileListInternEntry *file, FileListFilter *filter)
void filelist_setfilter_options(FileList *filelist, const bool do_filter, const bool hide_dot, const bool hide_parent, const uint64_t filter, const uint64_t filter_id, const bool filter_assets_only, const char *filter_glob, const char *filter_search)
bool is_filtered_main_assets(FileListInternEntry *file, const char *, FileListFilter *filter)
static AssetMetaData * filelist_file_internal_get_asset_data(const FileListInternEntry *file)
bool is_filtered_file(FileListInternEntry *file, const char *, FileListFilter *filter)
bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter)
void prepare_filter_asset_library(const FileList *filelist, FileListFilter *filter)
bool is_filtered_main(FileListInternEntry *file, const char *, FileListFilter *filter)
static bool is_filtered_file_type(const FileListInternEntry *file, const FileListFilter *filter)
void filelist_filter(FileList *filelist)
static bool is_filtered_hidden(const char *filename, const FileListFilter *filter, const FileListInternEntry *file)
static bool is_filtered_file_name(const FileListInternEntry *file, const FileListFilter *filter)
static bool is_filtered_lib_type(FileListInternEntry *file, const char *, FileListFilter *filter)
bool filelist_needs_filtering(FileList *filelist)
static bool asset_tag_matches_filter(const char *filter_search, const AssetMetaData *asset_data)
static bool is_filtered_id_file_type(const FileListInternEntry *file, const short id_code, const char *name, const FileListFilter *filter)
#define FILEDIR_NBR_ENTRIES_UNSET
@ FLF_DO_FILTER
@ FLF_HIDE_LIB_DIR
@ FLF_HIDE_PARENT
@ FLF_ASSETS_ONLY
@ FLF_HIDE_DOT
@ FL_NEED_FILTERING
#define filter
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static void update(bNodeTree *ntree)
const char * name
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
User defined tag. Currently only used by assets, could be used more often at some point....
char filter_glob[FILE_MAXFILE]
eFileAttributes attributes
eFileSel_File_Types typeflag
blender::asset_system::AssetRepresentation * get_asset() const
FileListInternEntry ** filtered
void(* prepare_filter_fn)(const FileList *filelist, FileListFilter *filter)
bool(* filter_fn)(FileListInternEntry *file, const char *root, FileListFilter *filter)
FileDirEntryArr filelist
FileListEntryCache * filelist_cache
short max_recursion
FileListIntern filelist_intern
FileListFilter filter_data
blender::asset_system::AssetLibrary * asset_library