Blender V4.3
filesel.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10#include <cstdio>
11#include <cstring>
12
13#include <sys/stat.h>
14#include <sys/types.h>
15
16/* path/file handling stuff */
17#ifdef WIN32
18# include "BLI_winstuff.h"
19# include <direct.h>
20# include <io.h>
21#else
22# include <dirent.h>
23# include <sys/times.h>
24# include <unistd.h>
25#endif
26
28
29#include "DNA_screen_types.h"
30#include "DNA_space_types.h"
31#include "DNA_userdef_types.h"
32
33#include "MEM_guardedalloc.h"
34
35#include "BLI_blenlib.h"
36#include "BLI_fnmatch.h"
37#include "BLI_math_base.h"
38#include "BLI_utildefines.h"
39
40#include "BLO_userdef_default.h"
41
42#include "BLT_translation.hh"
43
44#include "BKE_appdir.hh"
45#include "BKE_context.hh"
46#include "BKE_idtype.hh"
47#include "BKE_main.hh"
48#include "BKE_preferences.h"
49
50#include "BLF_api.hh"
51
52#include "ED_fileselect.hh"
53#include "ED_screen.hh"
54
55#include "WM_api.hh"
56#include "WM_types.hh"
57
58#include "RNA_access.hh"
59
60#include "UI_interface.hh"
61#include "UI_interface_icons.hh"
62#include "UI_view2d.hh"
63
66
67#include "file_intern.hh"
68#include "filelist.hh"
69
70#define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X)
71
73{
74 const char *blendfile_path = BKE_main_blendfile_path_from_global();
75
76 /* operator has no setting for this */
77 params->active_file = -1;
78
79 if (!params->dir[0]) {
80 if (blendfile_path[0] != '\0') {
81 BLI_path_split_dir_part(blendfile_path, params->dir, sizeof(params->dir));
82 }
83 else {
84 const char *doc_path = BKE_appdir_folder_default();
85 if (doc_path) {
86 STRNCPY(params->dir, doc_path);
87 }
88 }
89 }
90
93
94 /* Switching thumbnails needs to recalc layout #28809. */
95 if (sfile->layout) {
96 sfile->layout->dirty = true;
97 }
98}
99
101{
103 BLI_assert(sfile->op == nullptr);
104
105 FileAssetSelectParams *asset_params = sfile->asset_params;
106
107 if (!asset_params) {
108 asset_params = sfile->asset_params = static_cast<FileAssetSelectParams *>(
109 MEM_callocN(sizeof(*asset_params), "FileAssetSelectParams"));
112 asset_params->asset_library_ref.custom_library_index = -1;
114 }
115
116 FileSelectParams *base_params = &asset_params->base_params;
117 base_params->file[0] = '\0';
118 base_params->filter_glob[0] = '\0';
120 base_params->flag &= ~FILE_DIRSEL_ONLY;
121 base_params->filter |= FILE_TYPE_BLENDERLIB;
122 base_params->filter_id = FILTER_ID_ALL;
123 base_params->display = FILE_IMGDISPLAY;
124 base_params->sort = FILE_SORT_ALPHA;
125 /* Asset libraries include all sub-directories, so enable maximal recursion. */
127 /* 'SMALL' size by default. More reasonable since this is typically used as regular editor,
128 * space is more of an issue here. */
129 base_params->thumbnail_size = 96;
130
131 fileselect_initialize_params_common(sfile, base_params);
132}
133
139{
141
143 wmOperator *op = sfile->op;
144
145 const char *blendfile_path = BKE_main_blendfile_path_from_global();
146
147 /* create new parameters if necessary */
148 if (!sfile->params) {
149 sfile->params = static_cast<FileSelectParams *>(
150 MEM_callocN(sizeof(FileSelectParams), "fileselparams"));
151 /* set path to most recently opened .blend */
152 BLI_path_split_dir_file(blendfile_path,
153 sfile->params->dir,
154 sizeof(sfile->params->dir),
155 sfile->params->file,
156 sizeof(sfile->params->file));
157 sfile->params->filter_glob[0] = '\0';
161 }
162
163 params = sfile->params;
164
165 /* set the parameters from the operator, if it exists */
166 if (op) {
167 PropertyRNA *prop;
168 const bool is_files = (RNA_struct_find_property(op->ptr, "files") != nullptr);
169 const bool is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != nullptr);
170 const bool is_filename = (RNA_struct_find_property(op->ptr, "filename") != nullptr);
171 const bool is_directory = (RNA_struct_find_property(op->ptr, "directory") != nullptr);
172 const bool is_relative_path = (RNA_struct_find_property(op->ptr, "relative_path") != nullptr);
173
175 params->title, WM_operatortype_name(op->type, op->ptr).c_str(), sizeof(params->title));
176
177 if ((prop = RNA_struct_find_property(op->ptr, "filemode"))) {
178 params->type = RNA_property_int_get(op->ptr, prop);
179 }
180 else {
181 params->type = FILE_SPECIAL;
182 }
183
184 if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
185 char filepath[FILE_MAX];
186 RNA_string_get(op->ptr, "filepath", filepath);
187 if (params->type == FILE_LOADLIB) {
188 STRNCPY(params->dir, filepath);
189 params->file[0] = '\0';
190 }
191 else {
193 filepath, params->dir, sizeof(params->dir), params->file, sizeof(params->file));
194 }
195 }
196 else {
197 if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) {
198 RNA_string_get(op->ptr, "directory", params->dir);
199 params->file[0] = '\0';
200 }
201
202 if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) {
203 RNA_string_get(op->ptr, "filename", params->file);
204 }
205 }
206
207 if (params->dir[0]) {
208 BLI_path_abs(params->dir, blendfile_path);
209 BLI_path_normalize_dir(params->dir, sizeof(params->dir));
210 }
211
212 params->flag = 0;
213 if (is_directory == true && is_filename == false && is_filepath == false && is_files == false)
214 {
215 params->flag |= FILE_DIRSEL_ONLY;
216 }
217 if ((prop = RNA_struct_find_property(op->ptr, "check_existing"))) {
218 params->flag |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_CHECK_EXISTING) : 0;
219 }
220 if ((prop = RNA_struct_find_property(op->ptr, "hide_props_region"))) {
222 }
223
224 params->filter = 0;
225 if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) {
226 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_BLENDER) : 0;
227 }
228 if ((prop = RNA_struct_find_property(op->ptr, "filter_blenlib"))) {
229 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_BLENDERLIB) : 0;
230 }
231 if ((prop = RNA_struct_find_property(op->ptr, "filter_backup"))) {
233 0;
234 }
235 if ((prop = RNA_struct_find_property(op->ptr, "filter_image"))) {
236 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_IMAGE) : 0;
237 }
238 if ((prop = RNA_struct_find_property(op->ptr, "filter_movie"))) {
239 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_MOVIE) : 0;
240 }
241 if ((prop = RNA_struct_find_property(op->ptr, "filter_python"))) {
242 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_PYSCRIPT) : 0;
243 }
244 if ((prop = RNA_struct_find_property(op->ptr, "filter_font"))) {
245 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_FTFONT) : 0;
246 }
247 if ((prop = RNA_struct_find_property(op->ptr, "filter_sound"))) {
248 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_SOUND) : 0;
249 }
250 if ((prop = RNA_struct_find_property(op->ptr, "filter_text"))) {
251 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_TEXT) : 0;
252 }
253 if ((prop = RNA_struct_find_property(op->ptr, "filter_archive"))) {
254 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_ARCHIVE) : 0;
255 }
256 if ((prop = RNA_struct_find_property(op->ptr, "filter_folder"))) {
257 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_FOLDER) : 0;
258 }
259 if ((prop = RNA_struct_find_property(op->ptr, "filter_btx"))) {
260 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_BTX) : 0;
261 }
262 if ((prop = RNA_struct_find_property(op->ptr, "filter_collada"))) {
263 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_COLLADA) : 0;
264 }
265 if ((prop = RNA_struct_find_property(op->ptr, "filter_alembic"))) {
266 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_ALEMBIC) : 0;
267 }
268 if ((prop = RNA_struct_find_property(op->ptr, "filter_usd"))) {
269 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_USD) : 0;
270 }
271 if ((prop = RNA_struct_find_property(op->ptr, "filter_obj"))) {
272 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_OBJECT_IO) : 0;
273 }
274 if ((prop = RNA_struct_find_property(op->ptr, "filter_volume"))) {
275 params->filter |= RNA_property_boolean_get(op->ptr, prop) ? int(FILE_TYPE_VOLUME) : 0;
276 }
277 if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
278 /* Protection against Python scripts not setting proper size limit. */
280 op->ptr, prop, params->filter_glob, sizeof(params->filter_glob), nullptr);
281 if (tmp != params->filter_glob) {
282 STRNCPY(params->filter_glob, tmp);
283 MEM_freeN(tmp);
284
285 /* Fix stupid things that truncating might have generated,
286 * like last group being a 'match everything' wildcard-only one... */
288 }
290 }
291 else {
292 params->filter_glob[0] = '\0';
293 }
294
295 if (params->filter != 0) {
296 if (U.uiflag & USER_FILTERFILEEXTS) {
297 params->flag |= FILE_FILTER;
298 }
299 else {
300 params->flag &= ~FILE_FILTER;
301 }
302 }
303
304 if (U.uiflag & USER_HIDE_DOT) {
305 params->flag |= FILE_HIDE_DOT;
306 }
307 else {
308 params->flag &= ~FILE_HIDE_DOT;
309 }
310
311 if (params->type == FILE_LOADLIB) {
312 params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0;
313 params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0;
314 params->flag |= RNA_boolean_get(op->ptr, "active_collection") ? FILE_ACTIVE_COLLECTION : 0;
315 }
316
317 if ((prop = RNA_struct_find_property(op->ptr, "allow_path_tokens"))) {
319 }
320
321 if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) {
322 params->display = RNA_property_enum_get(op->ptr, prop);
323 }
324
325 if (params->display == FILE_DEFAULTDISPLAY) {
327 }
328
329 if ((prop = RNA_struct_find_property(op->ptr, "sort_method"))) {
330 params->sort = RNA_property_enum_get(op->ptr, prop);
331 }
332
333 if (params->sort == FILE_SORT_DEFAULT) {
335 }
336
337 if (is_relative_path) {
338 if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) {
339 if (!RNA_property_is_set_ex(op->ptr, prop, false)) {
340 RNA_property_boolean_set(op->ptr, prop, (U.flag & USER_RELPATHS) != 0);
341 }
342 }
343 }
344 }
345 else {
346 /* default values, if no operator */
347 params->type = FILE_UNIX;
349 params->flag &= ~FILE_DIRSEL_ONLY;
350 params->display = FILE_VERTICALDISPLAY;
351 params->sort = FILE_SORT_ALPHA;
352 params->filter = 0;
353 params->filter_glob[0] = '\0';
354 }
355
357
358 return params;
359}
360
362{
363 switch ((eFileBrowse_Mode)sfile->browse_mode) {
365 if (!sfile->params) {
367 }
368 return sfile->params;
370 if (!sfile->asset_params) {
372 }
373 return &sfile->asset_params->base_params;
374 }
375
376 BLI_assert_msg(0, "Invalid browse mode set in file space.");
377 return nullptr;
378}
379
381{
382 if (!sfile) {
383 /* Sometimes called in poll before space type was checked. */
384 return nullptr;
385 }
386
387 switch ((eFileBrowse_Mode)sfile->browse_mode) {
389 return sfile->params;
391 return (FileSelectParams *)sfile->asset_params;
392 }
393
394 BLI_assert_msg(0, "Invalid browse mode set in file space.");
395 return nullptr;
396}
397
399{
400 return (sfile->browse_mode == FILE_BROWSE_MODE_FILES) ? sfile->params : nullptr;
401}
402
404{
405 return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) ? sfile->asset_params : nullptr;
406}
407
409{
410 const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
411 if (asset_params == nullptr) {
412 return false;
413 }
414 return asset_params->asset_library_ref.type == ASSET_LIBRARY_LOCAL;
415}
416
418{
419 AssetLibraryReference *library = &asset_params->asset_library_ref;
420 FileSelectParams *base_params = &asset_params->base_params;
421 bUserAssetLibrary *user_library = nullptr;
422
423 /* Ensure valid repository, or fall-back to local one. */
424 if (library->type == ASSET_LIBRARY_CUSTOM) {
425 BLI_assert(library->custom_library_index >= 0);
426
428 if (!user_library) {
429 library->type = ASSET_LIBRARY_ALL;
430 }
431 }
432
433 switch (eAssetLibraryType(library->type)) {
436 base_params->type = FILE_ASSET_LIBRARY;
437 break;
439 base_params->dir[0] = '\0';
440 base_params->type = FILE_ASSET_LIBRARY_ALL;
441 break;
443 base_params->dir[0] = '\0';
444 base_params->type = FILE_MAIN_ASSET;
445 break;
447 BLI_assert(user_library);
448 STRNCPY(base_params->dir, user_library->dirpath);
449 base_params->type = FILE_ASSET_LIBRARY;
450 break;
451 }
452}
453
455{
457 if (asset_params) {
459 }
460}
461
463{
464 return (sfile->browse_mode == FILE_BROWSE_MODE_FILES);
465}
466
468{
469 return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS);
470}
471
473{
474 if (!ED_fileselect_is_asset_browser(sfile) || !sfile->files) {
475 return nullptr;
476 }
477
478 return filelist_asset_library(sfile->files);
479}
480
482{
483 if (!ED_fileselect_is_asset_browser(sfile)) {
484 return nullptr;
485 }
486
487 if (sfile->files == nullptr) {
488 return nullptr;
489 }
490
492 const FileDirEntry *file = filelist_file(sfile->files, params->active_file);
493 if (file == nullptr) {
494 return nullptr;
495 }
496
497 return filelist_file_get_id(file);
498}
499
500void ED_fileselect_activate_asset_catalog(const SpaceFile *sfile, const bUUID catalog_id)
501{
502 if (!ED_fileselect_is_asset_browser(sfile)) {
503 return;
504 }
505
507 params->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
508 params->catalog_id = catalog_id;
510}
511
513{
514 if (!ED_fileselect_is_asset_browser(sfile) || !file->asset) {
515 return -1;
516 }
517
518 /* First handle the case where the asset system dictates a certain import method. */
519 if (file->asset->may_override_import_method() == false) {
520 BLI_assert(file->asset->get_import_method().has_value());
521 return *file->asset->get_import_method();
522 }
523
525
526 if (params->import_method == FILE_ASSET_IMPORT_FOLLOW_PREFS) {
527 std::optional import_method = file->asset->get_import_method();
528 return import_method ? *import_method : -1;
529 }
530
531 switch (eFileAssetImportMethod(params->import_method)) {
533 return ASSET_IMPORT_LINK;
535 return ASSET_IMPORT_APPEND;
538
539 /* Should be handled above already. Break and fail below. */
541 break;
542 }
543
545 return -1;
546}
547
548static void on_reload_activate_by_id(SpaceFile *sfile, onReloadFnData custom_data)
549{
550 ID *asset_id = (ID *)custom_data;
551 ED_fileselect_activate_by_id(sfile, asset_id, false);
552}
553
554void ED_fileselect_activate_by_id(SpaceFile *sfile, ID *asset_id, const bool deferred)
555{
556 if (!ED_fileselect_is_asset_browser(sfile)) {
557 return;
558 }
559
560 /* If there are filelist operations running now ("pending" true) or soon ("force reset" true),
561 * there is a fair chance that the to-be-activated ID will only be present after these operations
562 * have completed. Defer activation until then. */
563 if (deferred || filelist_pending(sfile->files) || filelist_needs_force_reset(sfile->files)) {
564 /* This should be thread-safe, as this function is likely called from the main thread, and
565 * notifiers (which cause a call to the on-reload callback function) are handled on the main
566 * thread as well. */
568 return;
569 }
570
572 FileList *files = sfile->files;
573
574 const int file_index = filelist_file_find_id(files, asset_id);
575 const FileDirEntry *file = filelist_file_ex(files, file_index, true);
576 if (file == nullptr) {
577 return;
578 }
579
580 params->active_file = file_index;
582
585}
586
588{
589 const char *relative_path = static_cast<const char *>(custom_data);
590 ED_fileselect_activate_by_relpath(sfile, relative_path);
591}
592
593void ED_fileselect_activate_by_relpath(SpaceFile *sfile, const char *relative_path)
594{
595 /* If there are filelist operations running now ("pending" true) or soon ("force reset" true),
596 * there is a fair chance that the to-be-activated file at relative_path will only be present
597 * after these operations have completed. Defer activation until then. */
598 FileList *files = sfile->files;
599 if (files == nullptr || filelist_pending(files) || filelist_needs_force_reset(files)) {
600 /* Casting away the constness of `relative_path` is safe here, because eventually it just ends
601 * up in another call to this function, and then it's a const char* again. */
603 return;
604 }
605
607 const int num_files_filtered = filelist_files_ensure(files);
608
609 for (int file_index = 0; file_index < num_files_filtered; ++file_index) {
610 const FileDirEntry *file = filelist_file(files, file_index);
611
612 if (STREQ(file->relpath, relative_path)) {
613 params->active_file = file_index;
615 }
616 }
618}
619
625
626/* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA
627 * may also be remembered, but only conditionally. */
628#define PARAMS_FLAGS_REMEMBERED (FILE_HIDE_DOT)
629
630void ED_fileselect_window_params_get(const wmWindow *win, int r_win_size[2], bool *r_is_maximized)
631{
632 /* Get DPI/pixel-size independent size to be stored in preferences. */
633 WM_window_set_dpi(win); /* Ensure the DPI is taken from the right window. */
634
635 const blender::int2 win_size = WM_window_native_pixel_size(win);
636 r_win_size[0] = win_size[0] / UI_SCALE_FAC;
637 r_win_size[1] = win_size[1] / UI_SCALE_FAC;
638
639 *r_is_maximized = WM_window_is_maximized(win);
640}
641
643{
644 PropertyRNA *prop;
645 return (sfile->op == nullptr) ||
646 !(prop = RNA_struct_find_property(sfile->op->ptr, "display_type")) ||
648}
649
651{
652 PropertyRNA *prop;
653 return (sfile->op == nullptr) ||
654 !(prop = RNA_struct_find_property(sfile->op->ptr, "sort_method")) ||
655 (RNA_property_enum_get(sfile->op->ptr, prop) == FILE_SORT_DEFAULT);
656}
657
659{
660 wmOperator *op = sfile->op;
661 UserDef_FileSpaceData *sfile_udata = &U.file_space_data;
662
664
666 if (!op) {
667 return;
668 }
669
670 params->thumbnail_size = sfile_udata->thumbnail_size;
671 params->details_flags = sfile_udata->details_flags;
672 params->filter_id = sfile_udata->filter_id;
673
674 /* Combine flags we take from params with the flags we take from userdef. */
675 params->flag = (params->flag & ~PARAMS_FLAGS_REMEMBERED) |
676 (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED);
677
679 params->display = sfile_udata->display_type;
680 }
682 params->sort = sfile_udata->sort_type;
683 /* For the default sorting, also take invert flag from userdef. */
684 params->flag = (params->flag & ~FILE_SORT_INVERT) | (sfile_udata->flag & FILE_SORT_INVERT);
685 }
686}
687
689 const int temp_win_size[2],
690 const bool is_maximized)
691{
693 UserDef_FileSpaceData *sfile_udata_new = &U.file_space_data;
694 UserDef_FileSpaceData sfile_udata_old = U.file_space_data;
695
696 sfile_udata_new->thumbnail_size = params->thumbnail_size;
697 sfile_udata_new->details_flags = params->details_flags;
698 sfile_udata_new->flag = params->flag & PARAMS_FLAGS_REMEMBERED;
699 sfile_udata_new->filter_id = params->filter_id;
700
701 /* In some rare cases, operators ask for a specific display or sort type (e.g. chronological
702 * sorting for "Recover Auto Save"). So the settings are optimized for a specific operation.
703 * Don't let that change the userdef memory for more general cases. */
705 sfile_udata_new->display_type = params->display;
706 }
708 sfile_udata_new->sort_type = params->sort;
709 /* In this case also remember the invert flag. */
710 sfile_udata_new->flag = (sfile_udata_new->flag & ~FILE_SORT_INVERT) |
711 (params->flag & FILE_SORT_INVERT);
712 }
713
714 if (temp_win_size && !is_maximized) {
715 sfile_udata_new->temp_win_sizex = temp_win_size[0];
716 sfile_udata_new->temp_win_sizey = temp_win_size[1];
717 }
718
719 /* Tag preferences as dirty if something has changed. */
720 if (memcmp(sfile_udata_new, &sfile_udata_old, sizeof(sfile_udata_old)) != 0) {
721 U.runtime.is_dirty = true;
722 }
723}
724
725void fileselect_file_set(bContext *C, SpaceFile *sfile, const int index)
726{
727 const FileDirEntry *file = filelist_file(sfile->files, index);
728 if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) {
730 STRNCPY(params->file, file->relpath);
731 if (sfile->op) {
732 /* Update the filepath properties of the operator. */
733 Main *bmain = CTX_data_main(C);
734 file_sfile_to_operator(C, bmain, sfile->op, sfile);
735 }
736 }
737}
738
740{
741 int numfiles;
742
743 /* Values in pixels.
744 *
745 * - *_item: size of each (row|col), (including padding)
746 * - *_view: (x|y) size of the view.
747 * - *_over: extra pixels, to take into account, when the fit isn't exact
748 * (needed since you may see the end of the previous column and the beginning of the next).
749 *
750 * Could be more clever and take scrolling into account,
751 * but for now don't bother.
752 */
753 if (layout->flag & FILE_LAYOUT_HOR) {
754 const int x_item = layout->tile_w + (2 * layout->tile_border_x);
755 const int x_view = int(BLI_rctf_size_x(&region->v2d.cur));
756 const int x_over = x_item - (x_view % x_item);
757 numfiles = int(float(x_view + x_over) / float(x_item));
758 return numfiles * layout->rows;
759 }
760
761 const int y_item = layout->tile_h + (2 * layout->tile_border_y);
762 const int y_view = int(BLI_rctf_size_y(&region->v2d.cur)) - layout->offset_top;
763 const int y_over = y_item - (y_view % y_item);
764 numfiles = int(float(y_view + y_over) / float(y_item));
765 return numfiles * layout->flow_columns;
766}
767
768static bool is_inside(int x, int y, int cols, int rows)
769{
770 return ((x >= 0) && (x < cols) && (y >= 0) && (y < rows));
771}
772
774{
775 int colmin, colmax, rowmin, rowmax;
776 FileSelection sel;
777 sel.first = sel.last = -1;
778
779 if (layout == nullptr) {
780 return sel;
781 }
782
783 colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x);
784 rowmin = (rect->ymin - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
785 colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x);
786 rowmax = (rect->ymax - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
787
788 if (is_inside(colmin, rowmin, layout->flow_columns, layout->rows) ||
789 is_inside(colmax, rowmax, layout->flow_columns, layout->rows))
790 {
791 CLAMP(colmin, 0, layout->flow_columns - 1);
792 CLAMP(rowmin, 0, layout->rows - 1);
793 CLAMP(colmax, 0, layout->flow_columns - 1);
794 CLAMP(rowmax, 0, layout->rows - 1);
795 }
796
797 if ((colmin > layout->flow_columns - 1) || (rowmin > layout->rows - 1)) {
798 sel.first = -1;
799 }
800 else {
801 if (layout->flag & FILE_LAYOUT_HOR) {
802 sel.first = layout->rows * colmin + rowmin;
803 }
804 else {
805 sel.first = colmin + layout->flow_columns * rowmin;
806 }
807 }
808 if ((colmax > layout->flow_columns - 1) || (rowmax > layout->rows - 1)) {
809 sel.last = -1;
810 }
811 else {
812 if (layout->flag & FILE_LAYOUT_HOR) {
813 sel.last = layout->rows * colmax + rowmax;
814 }
815 else {
816 sel.last = colmax + layout->flow_columns * rowmax;
817 }
818 }
819
820 return sel;
821}
822
823int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
824{
825 int offsetx, offsety;
826 int active_file;
827
828 if (layout == nullptr) {
829 return -1;
830 }
831
832 offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x);
833 offsety = (y - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
834
835 if (offsetx > layout->flow_columns - 1) {
836 return -1;
837 }
838 if (offsety > layout->rows - 1) {
839 return -1;
840 }
841
842 if (layout->flag & FILE_LAYOUT_HOR) {
843 active_file = layout->rows * offsetx + offsety;
844 }
845 else {
846 active_file = offsetx + layout->flow_columns * offsety;
847 }
848 return active_file;
849}
850
851void ED_fileselect_layout_maskrect(const FileLayout *layout, const View2D *v2d, rcti *r_rect)
852{
853 *r_rect = v2d->mask;
854 r_rect->ymax -= layout->offset_top;
855}
856
857bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, const View2D *v2d, int x, int y)
858{
859 rcti maskrect;
860 ED_fileselect_layout_maskrect(layout, v2d, &maskrect);
861 return BLI_rcti_isect_pt(&maskrect, x, y);
862}
863
865 const View2D *v2d,
866 const rcti *rect,
867 rcti *r_dst)
868{
869 rcti maskrect;
870 ED_fileselect_layout_maskrect(layout, v2d, &maskrect);
871 return BLI_rcti_isect(&maskrect, rect, r_dst);
872}
873
874void ED_fileselect_layout_tilepos(const FileLayout *layout, int tile, int *x, int *y)
875{
876 if (layout->flag == FILE_LAYOUT_HOR) {
877 *x = layout->tile_border_x +
878 (tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x);
879 *y = layout->offset_top + layout->tile_border_y +
880 (tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y);
881 }
882 else {
883 *x = layout->tile_border_x +
884 ((tile) % layout->flow_columns) * (layout->tile_w + 2 * layout->tile_border_x);
885 *y = layout->offset_top + layout->tile_border_y +
886 ((tile) / layout->flow_columns) * (layout->tile_h + 2 * layout->tile_border_y);
887 }
888}
889
891 const FileLayout *layout,
892 int x,
893 int y)
894{
895 rcti header_rect = v2d->mask;
896 header_rect.ymin = header_rect.ymax - layout->attribute_column_header_h;
897 return BLI_rcti_isect_pt(&header_rect, x, y);
898}
899
902 const FileLayout *layout)
903{
904 switch (column) {
905 case COLUMN_NAME:
906 /* Always enabled */
907 return true;
908 case COLUMN_DATETIME:
909 return ((params->details_flags & FILE_DETAILS_DATETIME) != 0) &&
910 !FILE_LAYOUT_HIDE_DATE(layout);
911 case COLUMN_SIZE:
912 return ((params->details_flags & FILE_DETAILS_SIZE) != 0) && !FILE_LAYOUT_HIDE_SIZE(layout);
913 default:
914 return false;
915 }
916}
917
920 FileLayout *layout,
921 int x)
922{
923 float mx, my;
924 int offset_tile;
925
926 UI_view2d_region_to_view(v2d, x, v2d->mask.ymax - layout->offset_top - 1, &mx, &my);
927 offset_tile = ED_fileselect_layout_offset(
928 layout, int(v2d->tot.xmin + mx), int(v2d->tot.ymax - my));
929 if (offset_tile > -1) {
930 int tile_x, tile_y;
931 int pos_x = 0;
932 int rel_x; /* x relative to the hovered tile */
933
934 ED_fileselect_layout_tilepos(layout, offset_tile, &tile_x, &tile_y);
935 /* Column header drawing doesn't use left tile border, so subtract it. */
936 rel_x = mx - (tile_x - layout->tile_border_x);
937
939 column < ATTRIBUTE_COLUMN_MAX;
940 column = FileAttributeColumnType(int(column) + 1))
941 {
942 if (!file_attribute_column_type_enabled(params, column, layout)) {
943 continue;
944 }
945 const int width = layout->attribute_columns[column].width;
946
947 if (IN_RANGE(rel_x, pos_x, pos_x + width)) {
948 return column;
949 }
950
951 pos_x += width;
952 }
953 }
954
955 return COLUMN_NONE;
956}
957
958float file_string_width(const char *str)
959{
960 const uiStyle *style = UI_style_get();
961 UI_fontstyle_set(&style->widget);
963}
964
966{
967#if 0
968 float s;
969 char tmp[2] = "X";
970 const uiStyle *style = UI_style_get();
971 UI_fontstyle_set(&style->widget);
972 s = BLF_height(style->widget.uifont_id, tmp);
973 return style->widget.points;
974#else
975 const uiStyle *style = UI_style_get();
976 UI_fontstyle_set(&style->widget);
977 return style->widget.points * UI_SCALE_FAC;
978#endif
979}
980
982{
983 FileAttributeColumn *columns = layout->attribute_columns;
984 const int pad = ATTRIBUTE_COLUMN_PADDING * 2;
985 const bool compact = FILE_LAYOUT_COMPACT(layout);
986
987 for (int i = 0; i < ATTRIBUTE_COLUMN_MAX; i++) {
988 layout->attribute_columns[i].width = 0;
989 }
990
991 /* Biggest possible reasonable values... */
992 columns[COLUMN_DATETIME].width = file_string_width(compact ? "23/08/89" : "23 Dec 6789, 23:59") +
993 pad;
994 columns[COLUMN_SIZE].width = file_string_width(compact ? "369G" : "098.7 MiB") + pad;
995 if (params->display == FILE_IMGDISPLAY) {
996 columns[COLUMN_NAME].width = (float(params->thumbnail_size) / 8.0f) * UI_UNIT_X;
997 }
998 /* Name column uses remaining width */
999 else {
1000 int remwidth = layout->tile_w;
1001 for (FileAttributeColumnType column_type =
1003 column_type >= 0;
1004 column_type = FileAttributeColumnType(int(column_type) - 1))
1005 {
1006 if ((column_type == COLUMN_NAME) ||
1007 !file_attribute_column_type_enabled(params, column_type, layout))
1008 {
1009 continue;
1010 }
1011 remwidth -= columns[column_type].width;
1012 }
1013 columns[COLUMN_NAME].width = remwidth;
1014 }
1015}
1016
1034
1036{
1038 /* Request a slightly more compact layout for asset browsing. */
1039 const bool compact = ED_fileselect_is_asset_browser(sfile);
1040 FileLayout *layout = nullptr;
1041 View2D *v2d = &region->v2d;
1042 int numfiles;
1043 int textheight;
1044
1045 if (sfile->layout == nullptr) {
1046 sfile->layout = static_cast<FileLayout *>(MEM_callocN(sizeof(FileLayout), "file_layout"));
1047 sfile->layout->dirty = true;
1048 }
1049 else if (sfile->layout->dirty == false) {
1050 return;
1051 }
1052
1053 numfiles = filelist_files_ensure(sfile->files);
1054 textheight = int(file_font_pointsize());
1055 layout = sfile->layout;
1056 layout->textheight = textheight;
1057
1058 if (params->display == FILE_IMGDISPLAY) {
1059 const float pad_fac = compact ? 0.15f : 0.3f;
1060 /* Matches UI_preview_tile_size_x()/_y() by default. */
1061 layout->prv_w = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_X;
1062 layout->prv_h = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_Y;
1063 layout->tile_border_x = pad_fac * UI_UNIT_X;
1064 layout->tile_border_y = pad_fac * UI_UNIT_X;
1065 layout->prv_border_x = pad_fac * UI_UNIT_X;
1066 layout->prv_border_y = pad_fac * UI_UNIT_Y;
1067 layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
1068 layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
1069 layout->width = int(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
1070 layout->flow_columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
1071 layout->attribute_column_header_h = 0;
1072 layout->offset_top = 0;
1073 if (layout->flow_columns > 0) {
1074 layout->rows = divide_ceil_u(numfiles, layout->flow_columns);
1075 }
1076 else {
1077 layout->flow_columns = 1;
1078 layout->rows = numfiles;
1079 }
1080 layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
1081 layout->tile_border_y * 2 - layout->offset_top;
1082 layout->flag = FILE_LAYOUT_VER;
1083 }
1084 else if (params->display == FILE_VERTICALDISPLAY) {
1085 int rowcount;
1086
1087 /* Matches UI_preview_tile_size_x()/_y() by default. */
1088 layout->prv_w = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_X;
1089 layout->prv_h = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_Y;
1090 layout->tile_border_x = 0.4f * UI_UNIT_X;
1091 layout->tile_border_y = 0.1f * UI_UNIT_Y;
1092 layout->tile_h = textheight * 3 / 2;
1093 layout->width = int(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
1094 layout->tile_w = layout->width;
1095 layout->flow_columns = 1;
1096 layout->attribute_column_header_h = layout->tile_h * 1.2f + 2 * layout->tile_border_y;
1097 layout->offset_top = layout->attribute_column_header_h;
1098 rowcount = int(BLI_rctf_size_y(&v2d->cur) - layout->offset_top - 2 * layout->tile_border_y) /
1099 (layout->tile_h + 2 * layout->tile_border_y);
1101
1102 layout->rows = std::max(rowcount, numfiles);
1103
1104 /* layout->rows can be zero if a very small area is changed to a File Browser. #124168. */
1105
1106 layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
1107 layout->tile_border_y * 2 + layout->offset_top;
1108 layout->flag = FILE_LAYOUT_VER;
1109 }
1110 else if (params->display == FILE_HORIZONTALDISPLAY) {
1111 /* Matches UI_preview_tile_size_x()/_y() by default. */
1112 layout->prv_w = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_X;
1113 layout->prv_h = (float(params->thumbnail_size) / 20.0f) * UI_UNIT_Y;
1114 layout->tile_border_x = 0.4f * UI_UNIT_X;
1115 layout->tile_border_y = 0.1f * UI_UNIT_Y;
1116 layout->tile_h = textheight * 3 / 2;
1117 layout->attribute_column_header_h = 0;
1118 layout->offset_top = layout->attribute_column_header_h;
1119 layout->height = int(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
1120 /* Padding by full scroll-bar H is too much, can overlap tile border Y. */
1121 layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) /
1122 (layout->tile_h + 2 * layout->tile_border_y);
1125
1126 if (layout->rows > 0) {
1127 layout->flow_columns = divide_ceil_u(numfiles, layout->rows);
1128 }
1129 else {
1130 layout->rows = 1;
1131 layout->flow_columns = numfiles;
1132 }
1133 layout->width = sfile->layout->flow_columns * (layout->tile_w + 2 * layout->tile_border_x) +
1134 layout->tile_border_x * 2;
1135 layout->flag = FILE_LAYOUT_HOR;
1136 }
1137 layout->dirty = false;
1138}
1139
1141{
1142 if (!sfile->layout) {
1143 ED_fileselect_init_layout(sfile, region);
1144 }
1145 return sfile->layout;
1146}
1147
1149{
1150 /* May happen when manipulating non-active spaces. */
1151 if (UNLIKELY(area->spacetype != SPACE_FILE)) {
1152 return;
1153 }
1154 SpaceFile *sfile = static_cast<SpaceFile *>(area->spacedata.first);
1156 if (params) {
1158 ED_fileselect_clear(wm, sfile);
1159
1160 /* Clear search string, it is very rare to want to keep that filter while changing dir,
1161 * and usually very annoying to keep it actually! */
1162 params->filter_search[0] = '\0';
1163 params->active_file = -1;
1164
1165 if (!filelist_is_dir(sfile->files, params->dir)) {
1166 STRNCPY(params->dir, filelist_dir(sfile->files));
1167 /* could return but just refresh the current dir */
1168 }
1169 filelist_setdir(sfile->files, params->dir);
1170
1171 if (folderlist_clear_next(sfile)) {
1173 }
1174
1176
1177 file_draw_check_ex(C, area);
1178 }
1179}
1180
1182{
1183 ScrArea *area = CTX_wm_area(C);
1184 ED_file_change_dir_ex(C, area);
1185}
1186
1188{
1189 FileSelection sel;
1190 sel.first = 0;
1191 sel.last = filelist_files_ensure(sfile->files) - 1;
1192
1194}
1195
1196int file_select_match(SpaceFile *sfile, const char *pattern, char *matched_file)
1197{
1198 int match = 0;
1199
1200 int n = filelist_files_ensure(sfile->files);
1201
1202 /* select any file that matches the pattern, this includes exact match
1203 * if the user selects a single file by entering the filename
1204 */
1205 for (int i = 0; i < n; i++) {
1206 const char *relpath = filelist_entry_get_relpath(sfile->files, i);
1207 /* Do not check whether file is a file or dir here! Causes: #44243
1208 * (we do accept directories at this stage). */
1209 if (fnmatch(pattern, relpath, 0) == 0) {
1211 if (!match) {
1212 BLI_strncpy(matched_file, relpath, FILE_MAX);
1213 }
1214 match++;
1215 }
1216 }
1217
1218 return match;
1219}
1220
1221int autocomplete_directory(bContext *C, char *str, void * /*arg_v*/)
1222{
1223 SpaceFile *sfile = CTX_wm_space_file(C);
1224 int match = AUTOCOMPLETE_NO_MATCH;
1225
1226 /* search if str matches the beginning of name */
1227 if (str[0] && sfile->files) {
1228 char dirname[FILE_MAX];
1229
1230 DIR *dir;
1231 dirent *de;
1232
1234
1235 dir = opendir(dirname);
1236
1237 if (dir) {
1239
1240 while ((de = readdir(dir)) != nullptr) {
1241 if (FILENAME_IS_CURRPAR(de->d_name)) {
1242 /* pass */
1243 }
1244 else {
1245 char dirpath[FILE_MAX];
1246 BLI_stat_t status;
1247
1248 BLI_path_join(dirpath, sizeof(dirpath), dirname, de->d_name);
1249
1250 if (BLI_stat(dirpath, &status) == 0) {
1251 if (S_ISDIR(status.st_mode)) { /* is subdir */
1252 UI_autocomplete_update_name(autocpl, dirpath);
1253 }
1254 }
1255 }
1256 }
1257 closedir(dir);
1258
1259 match = UI_autocomplete_end(autocpl, str);
1260 if (match == AUTOCOMPLETE_FULL_MATCH) {
1262 }
1263 }
1264 }
1265
1266 return match;
1267}
1268
1269int autocomplete_file(bContext *C, char *str, void * /*arg_v*/)
1270{
1271 SpaceFile *sfile = CTX_wm_space_file(C);
1272 int match = AUTOCOMPLETE_NO_MATCH;
1273
1274 /* search if str matches the beginning of name */
1275 if (str[0] && sfile->files) {
1277 int nentries = filelist_files_ensure(sfile->files);
1278
1279 for (int i = 0; i < nentries; i++) {
1280 const char *relpath = filelist_entry_get_relpath(sfile->files, i);
1281 UI_autocomplete_update_name(autocpl, relpath);
1282 }
1283 match = UI_autocomplete_end(autocpl, str);
1284 }
1285
1286 return match;
1287}
1288
1290{
1291 /* Only null in rare cases, see: #29734. */
1292 if (sfile->files) {
1293 filelist_readjob_stop(sfile->files, wm);
1294 filelist_freelib(sfile->files);
1295 filelist_clear(sfile->files);
1296 }
1297
1299 params->highlight_file = -1;
1301}
1302
1304{
1305 if (!sfile) {
1306 return;
1307 }
1308 if (sfile->op) {
1309 wmWindow *temp_win = (wm->winactive && WM_window_is_temp_screen(wm->winactive)) ?
1310 wm->winactive :
1311 nullptr;
1312 if (temp_win) {
1313 int win_size[2];
1314 bool is_maximized;
1315
1316 ED_fileselect_window_params_get(temp_win, win_size, &is_maximized);
1317 ED_fileselect_params_to_userdef(sfile, win_size, is_maximized);
1318 }
1319 else {
1320 ED_fileselect_params_to_userdef(sfile, nullptr, false);
1321 }
1322
1324 sfile->op = nullptr;
1325 }
1326
1328
1329 if (sfile->files) {
1330 ED_fileselect_clear(wm, sfile);
1331 filelist_free(sfile->files);
1332 MEM_freeN(sfile->files);
1333 sfile->files = nullptr;
1334 }
1335}
1336
1338{
1340 sfile->smoothscroll_timer = nullptr;
1341}
1342
1344{
1346
1348
1349 if (sfile->smoothscroll_timer != nullptr) {
1351 }
1352 sfile->smoothscroll_timer = WM_event_timer_add(wm, win, TIMER1, 1.0 / 1000.0);
1353 sfile->scroll_offset = 0;
1354}
1355
1357 wmWindow *win,
1358 SpaceFile *sfile,
1359 const FileDirEntry *rename_file)
1360{
1362
1364 sfile->files, rename_file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
1365
1366 /* Ensure smooth-scroll timer is active, even if not needed, because that way rename state is
1367 * handled properly. */
1369 /* Also always activate the rename file, even if renaming was canceled. */
1371}
1372
1374{
1375 params->renamefile[0] = '\0';
1376 params->rename_id = nullptr;
1377 params->rename_flag = 0;
1378}
1379
1381{
1382 /* Find the file either through the local ID/asset it represents or its relative path. */
1383 return (params->rename_id != nullptr) ? filelist_file_find_id(filelist, params->rename_id) :
1384 filelist_file_find_path(filelist, params->renamefile);
1385}
1386
1388{
1389 BLI_assert(params->rename_flag != 0);
1390
1392 0)
1393 {
1394 return;
1395 }
1396
1397 BLI_assert(params->renamefile[0] != '\0' || params->rename_id != nullptr);
1398
1399 int idx = file_params_find_renamed(params, sfile->files);
1400 if (idx >= 0) {
1401 FileDirEntry *file = filelist_file(sfile->files, idx);
1402 BLI_assert(file != nullptr);
1403
1404 params->active_file = idx;
1406
1407 if ((params->rename_flag & FILE_PARAMS_RENAME_PENDING) != 0) {
1409 params->rename_flag = FILE_PARAMS_RENAME_ACTIVE;
1410 }
1411 else if ((params->rename_flag & FILE_PARAMS_RENAME_POSTSCROLL_PENDING) != 0) {
1412 /* file_select_deselect_all() will resort and re-filter, so `idx` will probably have changed.
1413 * Need to get the correct #FileDirEntry again. */
1415 idx = file_params_find_renamed(params, sfile->files);
1416 file = filelist_file(sfile->files, idx);
1419 params->active_file = idx;
1422 }
1423 }
1424 /* File listing is now asynchronous, only reset renaming if matching entry is not found
1425 * when file listing is not done. */
1426 else if (filelist_is_ready(sfile->files)) {
1428 }
1429}
1430
1432{
1433 bScreen *screen = WM_window_get_active_screen(win);
1434
1435 ED_screen_areas_iter (win, screen, area) {
1436 if (area->spacetype == SPACE_FILE) {
1437 SpaceFile *sfile = static_cast<SpaceFile *>(area->spacedata.first);
1438
1439 if (sfile->op == file_operator) {
1440 return area;
1441 }
1442 }
1443 }
1444
1445 return nullptr;
1446}
1447
1449{
1450 const bScreen *screen = WM_window_get_active_screen(win);
1451
1452 ED_screen_areas_iter (win, screen, area) {
1453 if (area->spacetype != SPACE_FILE) {
1454 continue;
1455 }
1456
1457 const SpaceFile *sfile = static_cast<SpaceFile *>(area->spacedata.first);
1458 if (sfile->op) {
1459 return area;
1460 }
1461 }
1462
1463 return nullptr;
1464}
1465
1467{
1468 if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
1469 Main *bmain = CTX_data_main(C);
1470 char filepath[FILE_MAX];
1471 const char *blendfile_path = BKE_main_blendfile_path(bmain);
1472
1473 if (blendfile_path[0] == '\0') {
1474 STRNCPY(filepath, DATA_("untitled"));
1475 }
1476 else {
1477 STRNCPY(filepath, blendfile_path);
1478 }
1479
1480 BLI_path_extension_replace(filepath, sizeof(filepath), extension);
1481 RNA_string_set(op->ptr, "filepath", filepath);
1482 }
1483}
Main runtime representation of an asset.
const char * BKE_appdir_folder_default() ATTR_WARN_UNUSED_RESULT
Definition appdir.cc:137
SpaceFile * CTX_wm_space_file(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:837
struct bUserAssetLibrary * BKE_preferences_asset_library_find_index(const struct UserDef *userdef, int index) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
float BLF_height(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:815
#define BLF_DRAW_STR_DUMMY_MAX
Definition BLF_api.hh:393
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:791
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct stat BLI_stat_t
MINLINE uint divide_ceil_u(uint a, uint b)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
int BLI_path_normalize_dir(char *dir, size_t dir_maxncpy) ATTR_NONNULL(1)
#define FILE_MAX
bool BLI_path_extension_replace(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#define BLI_path_join(...)
#define FILENAME_IS_CURRPAR(_n)
void BLI_path_split_dir_file(const char *filepath, char *dir, size_t dir_maxncpy, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_extension_glob_validate(char *ext_fnmatch) ATTR_NONNULL(1)
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
bool BLI_rcti_isect_pt(const struct rcti *rect, int x, int y)
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define CLAMP(a, b, c)
#define IN_RANGE(a, b, c)
#define UNLIKELY(x)
#define STREQ(a, b)
Compatibility-like things for windows.
struct __dirstream DIR
struct dirent * readdir(DIR *dp)
int closedir(DIR *dp)
#define S_ISDIR(x)
const char * dirname(char *path)
DIR * opendir(const char *path)
const UserDef U_default
#define DATA_(msgid)
#define FILTER_ID_ALL
Definition DNA_ID.h:1206
@ ASSET_IMPORT_LINK
@ ASSET_IMPORT_APPEND_REUSE
@ ASSET_IMPORT_APPEND
eAssetLibraryType
@ ASSET_LIBRARY_CUSTOM
@ ASSET_LIBRARY_ESSENTIALS
@ ASSET_LIBRARY_LOCAL
@ ASSET_LIBRARY_ALL
@ FILE_SORT_DEFAULT
@ FILE_SORT_ALPHA
@ FILE_SORT_TIME
@ FILE_SORT_SIZE
@ FILE_LOADLIB
@ FILE_ASSET_LIBRARY
@ FILE_SPECIAL
@ FILE_UNIX
@ FILE_MAIN_ASSET
@ FILE_ASSET_LIBRARY_ALL
@ FILE_TYPE_BTX
@ FILE_TYPE_BLENDER
@ FILE_TYPE_ALEMBIC
@ FILE_TYPE_ARCHIVE
@ FILE_TYPE_TEXT
@ FILE_TYPE_COLLADA
@ FILE_TYPE_PYSCRIPT
@ FILE_TYPE_BLENDER_BACKUP
@ FILE_TYPE_VOLUME
@ FILE_TYPE_MOVIE
@ FILE_TYPE_SOUND
@ FILE_TYPE_OBJECT_IO
@ FILE_TYPE_FOLDER
@ FILE_TYPE_FTFONT
@ FILE_TYPE_BLENDERLIB
@ FILE_TYPE_OPERATOR
@ FILE_TYPE_USD
@ FILE_TYPE_IMAGE
@ FILE_TYPE_DIR
@ SPACE_FILE
@ FILE_PARAMS_RENAME_POSTSCROLL_PENDING
@ FILE_PARAMS_RENAME_ACTIVE
@ FILE_PARAMS_RENAME_POSTSCROLL_ACTIVE
@ FILE_PARAMS_RENAME_PENDING
@ FILE_DETAILS_DATETIME
@ FILE_DETAILS_SIZE
eFileAssetImportMethod
@ FILE_ASSET_IMPORT_APPEND_REUSE
@ FILE_ASSET_IMPORT_APPEND
@ FILE_ASSET_IMPORT_LINK
@ FILE_ASSET_IMPORT_FOLLOW_PREFS
@ FILE_SHOW_ASSETS_FROM_CATALOG
eFileBrowse_Mode
@ FILE_BROWSE_MODE_ASSETS
@ FILE_BROWSE_MODE_FILES
eDirEntry_SelectFlag
@ FILE_SEL_EDITING
@ FILE_SEL_HIGHLIGHTED
@ FILE_SEL_SELECTED
@ FILE_VERTICALDISPLAY
@ FILE_IMGDISPLAY
@ FILE_HORIZONTALDISPLAY
@ FILE_DEFAULTDISPLAY
@ FILE_ACTIVE_COLLECTION
@ FILE_HIDE_TOOL_PROPS
@ FILE_CHECK_EXISTING
@ FILE_AUTOSELECT
@ FILE_FILTER
@ FILE_SORT_INVERT
@ FILE_DIRSEL_ONLY
@ FILE_LINK
@ FILE_ASSETS_ONLY
@ FILE_HIDE_DOT
@ FILE_PATH_TOKENS_ALLOW
#define FILE_SELECT_MAX_RECURSIONS
@ USER_HIDE_DOT
@ USER_FILTERFILEEXTS
@ USER_RELPATHS
#define UI_SCALE_FAC
#define FILE_LAYOUT_HOR
#define FILE_LAYOUT_VER
FileAttributeColumnType
@ COLUMN_DATETIME
@ ATTRIBUTE_COLUMN_MAX
@ COLUMN_NAME
@ COLUMN_NONE
@ COLUMN_SIZE
#define ED_screen_areas_iter(win, screen, area_name)
Definition ED_screen.hh:281
Read Guarded memory(de)allocation.
#define UI_UNIT_Y
#define AUTOCOMPLETE_FULL_MATCH
#define AUTOCOMPLETE_NO_MATCH
@ UI_STYLE_TEXT_LEFT
@ UI_STYLE_TEXT_RIGHT
int UI_autocomplete_end(AutoComplete *autocpl, char *autoname)
const uiStyle * UI_style_get()
void UI_fontstyle_set(const uiFontStyle *fs)
#define UI_UNIT_X
AutoComplete * UI_autocomplete_begin(const char *startname, size_t maxncpy)
void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name)
#define V2D_SCROLL_HEIGHT
Definition UI_view2d.hh:53
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Definition view2d.cc:1663
#define NA_ACTIVATED
Definition WM_types.hh:556
#define ND_SPACE_ASSET_PARAMS
Definition WM_types.hh:491
#define NC_ASSET
Definition WM_types.hh:371
#define ND_SPACE_FILE_PARAMS
Definition WM_types.hh:489
#define NC_SPACE
Definition WM_types.hh:359
#define NA_SELECTED
Definition WM_types.hh:555
#define ND_SPACE_FILE_LIST
Definition WM_types.hh:490
int pad[32 - sizeof(int)]
unsigned int U
Definition btGjkEpa3.h:78
constexpr const char * c_str() const
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define str(s)
bool folderlist_clear_next(SpaceFile *sfile)
void folder_history_list_ensure_for_active_browse_mode(SpaceFile *sfile)
#define FILE_LAYOUT_HIDE_SIZE(_layout)
#define FILE_LAYOUT_COMPACT(_layout)
void file_on_reload_callback_register(SpaceFile *sfile, onReloadFn callback, onReloadFnData custom_data)
void folder_history_list_free(SpaceFile *sfile)
void folderlist_pushdir(ListBase *folderlist, const char *dir)
void file_draw_check_ex(bContext *C, ScrArea *area)
Definition file_ops.cc:1730
void file_sfile_to_operator(bContext *C, Main *bmain, wmOperator *op, SpaceFile *sfile)
Definition file_ops.cc:1676
#define ATTRIBUTE_COLUMN_PADDING
void folderlist_free(ListBase *folderlist)
void * onReloadFnData
#define FILE_LAYOUT_HIDE_DATE(_layout)
void filelist_freelib(FileList *filelist)
Definition filelist.cc:2012
void filelist_entries_select_index_range_set(FileList *filelist, FileSelection *sel, FileSelType select, const eDirEntry_SelectFlag flag, FileCheckType check)
Definition filelist.cc:2966
const char * filelist_dir(const FileList *filelist)
Definition filelist.cc:2075
blender::asset_system::AssetLibrary * filelist_asset_library(FileList *filelist)
Definition filelist.cc:2007
bool filelist_needs_force_reset(const FileList *filelist)
Definition filelist.cc:2115
bool filelist_pending(const FileList *filelist)
Definition filelist.cc:2138
void filelist_free(FileList *filelist)
Definition filelist.cc:1984
void filelist_clear(FileList *filelist)
Definition filelist.cc:1965
const char * filelist_entry_get_relpath(const FileList *filelist, int index)
Definition filelist.cc:2330
void filelist_setdir(FileList *filelist, char dirpath[FILE_MAX_LIBEXTRA])
Definition filelist.cc:2085
ID * filelist_file_get_id(const FileDirEntry *file)
Definition filelist.cc:2325
int filelist_file_find_path(FileList *filelist, const char *filename)
Definition filelist.cc:2270
void filelist_entry_select_index_set(FileList *filelist, const int index, FileSelType select, const eDirEntry_SelectFlag flag, FileCheckType check)
Definition filelist.cc:2953
int filelist_file_find_id(const FileList *filelist, const ID *id)
Definition filelist.cc:2290
FileDirEntry * filelist_file_ex(FileList *filelist, const int index, const bool use_request)
Definition filelist.cc:2221
void filelist_readjob_stop(FileList *filelist, wmWindowManager *wm)
Definition filelist.cc:4327
bool filelist_is_dir(const FileList *filelist, const char *path)
Definition filelist.cc:2080
int filelist_files_ensure(FileList *filelist)
Definition filelist.cc:2148
FileDirEntry * filelist_file(FileList *filelist, int index)
Definition filelist.cc:2265
bool filelist_is_ready(const FileList *filelist)
Definition filelist.cc:2133
uint filelist_entry_select_set(const FileList *filelist, const FileDirEntry *entry, FileSelType select, const eDirEntry_SelectFlag flag, FileCheckType check)
Definition filelist.cc:2904
@ FILE_SEL_REMOVE
Definition filelist.hh:31
@ FILE_SEL_ADD
Definition filelist.hh:32
@ CHECK_ALL
Definition filelist.hh:39
void ED_fileselect_params_to_userdef(SpaceFile *sfile, const int temp_win_size[2], const bool is_maximized)
Definition filesel.cc:688
void file_params_smoothscroll_timer_clear(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile)
Definition filesel.cc:1337
bool ED_fileselect_is_file_browser(const SpaceFile *sfile)
Definition filesel.cc:462
void ED_fileselect_activate_by_relpath(SpaceFile *sfile, const char *relative_path)
Definition filesel.cc:593
bool file_attribute_column_type_enabled(const FileSelectParams *params, FileAttributeColumnType column, const FileLayout *layout)
Definition filesel.cc:900
int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *region)
Definition filesel.cc:739
FileSelectParams * ED_fileselect_get_active_params(const SpaceFile *sfile)
Definition filesel.cc:380
bool ED_fileselect_is_local_asset_library(const SpaceFile *sfile)
Definition filesel.cc:408
ID * ED_fileselect_active_asset_get(const SpaceFile *sfile)
Definition filesel.cc:481
void file_params_rename_end(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile, const FileDirEntry *rename_file)
Definition filesel.cc:1356
void ED_file_change_dir_ex(bContext *C, ScrArea *area)
Definition filesel.cc:1148
void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile)
Definition filesel.cc:1343
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
Definition filesel.cc:823
float file_string_width(const char *str)
Definition filesel.cc:958
static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
Definition filesel.cc:100
bool file_attribute_column_header_is_inside(const View2D *v2d, const FileLayout *layout, int x, int y)
Definition filesel.cc:890
static FileSelectParams * fileselect_ensure_updated_file_params(SpaceFile *sfile)
Definition filesel.cc:138
ScrArea * ED_fileselect_handler_area_find(const wmWindow *win, const wmOperator *file_operator)
Definition filesel.cc:1431
#define VERTLIST_MAJORCOLUMN_WIDTH
Definition filesel.cc:70
void ED_fileselect_activate_asset_catalog(const SpaceFile *sfile, const bUUID catalog_id)
Definition filesel.cc:500
void file_params_renamefile_clear(FileSelectParams *params)
Definition filesel.cc:1373
int file_select_match(SpaceFile *sfile, const char *pattern, char *matched_file)
Definition filesel.cc:1196
ScrArea * ED_fileselect_handler_area_find_any_with_op(const wmWindow *win)
Definition filesel.cc:1448
FileSelectParams * ED_fileselect_get_file_params(const SpaceFile *sfile)
Definition filesel.cc:398
static bool is_inside(int x, int y, int cols, int rows)
Definition filesel.cc:768
static void fileselect_initialize_params_common(SpaceFile *sfile, FileSelectParams *params)
Definition filesel.cc:72
void fileselect_refresh_params(SpaceFile *sfile)
Definition filesel.cc:454
FileLayout * ED_fileselect_get_layout(SpaceFile *sfile, ARegion *region)
Definition filesel.cc:1140
FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, const FileSelectParams *params, FileLayout *layout, int x)
Definition filesel.cc:918
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension)
Definition filesel.cc:1466
FileSelectParams * ED_fileselect_ensure_active_params(SpaceFile *sfile)
Definition filesel.cc:361
void file_select_deselect_all(SpaceFile *sfile, const eDirEntry_SelectFlag flag)
Definition filesel.cc:1187
int autocomplete_file(bContext *C, char *str, void *)
Definition filesel.cc:1269
void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile)
Definition filesel.cc:1303
bool ED_fileselect_is_asset_browser(const SpaceFile *sfile)
Definition filesel.cc:467
void ED_fileselect_deselect_all(SpaceFile *sfile)
Definition filesel.cc:620
FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *rect)
Definition filesel.cc:773
void ED_fileselect_activate_by_id(SpaceFile *sfile, ID *asset_id, const bool deferred)
Definition filesel.cc:554
FileAssetSelectParams * ED_fileselect_get_asset_params(const SpaceFile *sfile)
Definition filesel.cc:403
void ED_fileselect_set_params_from_userdef(SpaceFile *sfile)
Definition filesel.cc:658
static void file_attribute_columns_init(const FileSelectParams *params, FileLayout *layout)
Definition filesel.cc:1017
float file_font_pointsize()
Definition filesel.cc:965
bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, const View2D *v2d, int x, int y)
Definition filesel.cc:857
blender::asset_system::AssetLibrary * ED_fileselect_active_asset_library_get(const SpaceFile *sfile)
Definition filesel.cc:472
void ED_fileselect_window_params_get(const wmWindow *win, int r_win_size[2], bool *r_is_maximized)
Definition filesel.cc:630
#define PARAMS_FLAGS_REMEMBERED
Definition filesel.cc:628
static void on_reload_select_by_relpath(SpaceFile *sfile, onReloadFnData custom_data)
Definition filesel.cc:587
static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params)
Definition filesel.cc:417
static int file_params_find_renamed(const FileSelectParams *params, FileList *filelist)
Definition filesel.cc:1380
int autocomplete_directory(bContext *C, char *str, void *)
Definition filesel.cc:1221
void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params)
Definition filesel.cc:1387
void fileselect_file_set(bContext *C, SpaceFile *sfile, const int index)
Definition filesel.cc:725
static bool file_select_use_default_display_type(const SpaceFile *sfile)
Definition filesel.cc:642
static void on_reload_activate_by_id(SpaceFile *sfile, onReloadFnData custom_data)
Definition filesel.cc:548
static void file_attribute_columns_widths(const FileSelectParams *params, FileLayout *layout)
Definition filesel.cc:981
void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
Definition filesel.cc:1035
bool ED_fileselect_layout_isect_rect(const FileLayout *layout, const View2D *v2d, const rcti *rect, rcti *r_dst)
Definition filesel.cc:864
void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile)
Definition filesel.cc:1289
void ED_fileselect_layout_maskrect(const FileLayout *layout, const View2D *v2d, rcti *r_rect)
Definition filesel.cc:851
void ED_fileselect_layout_tilepos(const FileLayout *layout, int tile, int *x, int *y)
Definition filesel.cc:874
int ED_fileselect_asset_import_method_get(const SpaceFile *sfile, const FileDirEntry *file)
Definition filesel.cc:512
void ED_file_change_dir(bContext *C)
Definition filesel.cc:1181
static bool file_select_use_default_sort_type(const SpaceFile *sfile)
Definition filesel.cc:650
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_global const KernelWorkTile * tile
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
StringRefNull essentials_directory_path()
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost)
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
AssetLibraryReference asset_library_ref
FileSelectParams base_params
FileAttributeColumn attribute_columns[ATTRIBUTE_COLUMN_MAX]
int attribute_column_header_h
unsigned short thumbnail_size
Definition DNA_ID.h:413
struct wmTimer * smoothscroll_timer
struct FileLayout * layout
struct wmOperator * op
ListBase * folders_prev
struct FileList * files
FileSelectParams * params
FileAssetSelectParams * asset_params
ListBase * folders_next
UserDef_FileSpaceData file_space_data
Universally Unique Identifier according to RFC4122.
char * d_name
float xmin
float ymax
int ymin
int ymax
int xmin
int xmax
uiFontStyle widget
struct wmOperatorType * type
struct PointerRNA * ptr
struct wmWindow * winactive
#define N_(msgid)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, const int eventval)
@ TIMER1
@ EVT_FILESELECT_EXTERNAL_CANCEL
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
blender::int2 WM_window_native_pixel_size(const wmWindow *win)
void WM_window_set_dpi(const wmWindow *win)
Definition wm_window.cc:552
bool WM_window_is_temp_screen(const wmWindow *win)
bool WM_window_is_maximized(const wmWindow *win)
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const int event_type, const double time_step)
bScreen * WM_window_get_active_screen(const wmWindow *win)
uint8_t flag
Definition wm_window.cc:138