Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_file/filelist.c
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| int typeflag; | int typeflag; | ||||
| /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */ | /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */ | ||||
| int blentype; | int blentype; | ||||
| char *relpath; | char *relpath; | ||||
| /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ | /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ | ||||
| char *name; | char *name; | ||||
| /** Defined in BLI_fileops.h */ | |||||
| int attributes; | |||||
campbellbarton: A typed enum could be used here. | |||||
| BLI_stat_t st; | BLI_stat_t st; | ||||
| } FileListInternEntry; | } FileListInternEntry; | ||||
| typedef struct FileListIntern { | typedef struct FileListIntern { | ||||
| /** FileListInternEntry items. */ | /** FileListInternEntry items. */ | ||||
| ListBase entries; | ListBase entries; | ||||
| FileListInternEntry **filtered; | FileListInternEntry **filtered; | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| filelist->flags |= FL_NEED_SORTING; | filelist->flags |= FL_NEED_SORTING; | ||||
| filelist->flags = invert_sort ? (filelist->flags | FL_SORT_INVERT) : | filelist->flags = invert_sort ? (filelist->flags | FL_SORT_INVERT) : | ||||
| (filelist->flags & ~FL_SORT_INVERT); | (filelist->flags & ~FL_SORT_INVERT); | ||||
| } | } | ||||
| } | } | ||||
| /* ********** Filter helpers ********** */ | /* ********** Filter helpers ********** */ | ||||
| static bool is_hidden_file(const char *filename, FileListFilter *filter) | /* True if filename is meant to be hidden, eg. starting with period. */ | ||||
| static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *file) | |||||
| { | { | ||||
| char *sep = (char *)BLI_last_slash(filename); | if (filename[0] == '.' && !ELEM(filename[1], '.', '\0')) { | ||||
| bool is_hidden = false; | return true; /* ignore .file */ | ||||
Not Done Inline Actions!ELEM(filename[1], '.', '\0') JacquesLucke: `!ELEM(filename[1], '.', '\0')` | |||||
| if (filter->flags & FLF_HIDE_DOT) { | |||||
| if (filename[0] == '.' && filename[1] != '.' && filename[1] != '\0') { | |||||
| is_hidden = true; /* ignore .file */ | |||||
| } | |||||
| else { | |||||
| int len = strlen(filename); | |||||
| if ((len > 0) && (filename[len - 1] == '~')) { | |||||
| is_hidden = true; /* ignore file~ */ | |||||
| } | |||||
| } | |||||
| } | } | ||||
| if (!is_hidden && (filter->flags & FLF_HIDE_PARENT)) { | else { | ||||
| if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') { | int len = strlen(filename); | ||||
| is_hidden = true; /* ignore .. */ | if ((len > 0) && (filename[len - 1] == '~')) { | ||||
| return true; /* ignore file~ */ | |||||
| } | } | ||||
| } | } | ||||
| if (!is_hidden && ((filename[0] == '.') && (filename[1] == '\0'))) { | |||||
| is_hidden = true; /* ignore . */ | |||||
| } | |||||
| /* filename might actually be a piece of path, in which case we have to check all its parts. */ | /* filename might actually be a piece of path, in which case we have to check all its parts. */ | ||||
| if (!is_hidden && sep) { | |||||
| bool hidden = false; | |||||
| char *sep = (char *)BLI_last_slash(filename); | |||||
| if (!hidden && sep) { | |||||
| char tmp_filename[FILE_MAX_LIBEXTRA]; | char tmp_filename[FILE_MAX_LIBEXTRA]; | ||||
| BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename)); | BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename)); | ||||
| sep = tmp_filename + (sep - filename); | sep = tmp_filename + (sep - filename); | ||||
| while (sep) { | while (sep) { | ||||
| BLI_assert(sep[1] != '\0'); | BLI_assert(sep[1] != '\0'); | ||||
| if (is_hidden_file(sep + 1, filter)) { | if (is_hidden_dot_filename(sep + 1, file)) { | ||||
| is_hidden = true; | hidden = true; | ||||
| break; | break; | ||||
| } | } | ||||
| *sep = '\0'; | *sep = '\0'; | ||||
| sep = (char *)BLI_last_slash(tmp_filename); | sep = (char *)BLI_last_slash(tmp_filename); | ||||
| } | } | ||||
| } | } | ||||
| return is_hidden; | return hidden; | ||||
| } | |||||
| /* True if should be hidden, based on current filtering. */ | |||||
| static bool is_filtered_hidden(const char *filename, | |||||
Not Done Inline ActionsVariables should not have the exact same name as functions if it can be avoided. JacquesLucke: Variables should not have the exact same name as functions if it can be avoided. | |||||
| FileListFilter *filter, | |||||
| FileListInternEntry *file) | |||||
| { | |||||
| if ((filename[0] == '.') && (filename[1] == '\0')) { | |||||
| return true; /* Ignore . */ | |||||
| } | |||||
| if (filter->flags & FLF_HIDE_PARENT) { | |||||
| if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') { | |||||
| return true; /* Ignore .. */ | |||||
| } | |||||
| } | |||||
| if ((filter->flags & FLF_HIDE_DOT) && (file->attributes & DIRENTRY_HIDDEN)) { | |||||
| return true; /* Ignore files with Hidden attribute. */ | |||||
| } | |||||
| #ifndef WIN32 | |||||
| /* Check for unix-style names starting with period. */ | |||||
| if ((filter->flags & FLF_HIDE_DOT) && is_hidden_dot_filename(filename, file)) { | |||||
| return true; | |||||
| } | |||||
| #endif | |||||
| return false; | |||||
| } | } | ||||
| static bool is_filtered_file(FileListInternEntry *file, | static bool is_filtered_file(FileListInternEntry *file, | ||||
| const char *UNUSED(root), | const char *UNUSED(root), | ||||
| FileListFilter *filter) | FileListFilter *filter) | ||||
| { | { | ||||
| bool is_filtered = !is_hidden_file(file->relpath, filter); | bool is_filtered = !is_filtered_hidden(file->relpath, filter, file); | ||||
| if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | ||||
| /* We only check for types if some type are enabled in filtering. */ | /* We only check for types if some type are enabled in filtering. */ | ||||
| if (filter->filter && (filter->flags & FLF_DO_FILTER)) { | if (filter->filter && (filter->flags & FLF_DO_FILTER)) { | ||||
| if (file->typeflag & FILE_TYPE_DIR) { | if (file->typeflag & FILE_TYPE_DIR) { | ||||
| if (file->typeflag & | if (file->typeflag & | ||||
| (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | ||||
| if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | ||||
| Show All 26 Lines | |||||
| static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter) | static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileListFilter *filter) | ||||
| { | { | ||||
| bool is_filtered; | bool is_filtered; | ||||
| char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; | char path[FILE_MAX_LIBEXTRA], dir[FILE_MAX_LIBEXTRA], *group, *name; | ||||
| BLI_join_dirfile(path, sizeof(path), root, file->relpath); | BLI_join_dirfile(path, sizeof(path), root, file->relpath); | ||||
| if (BLO_library_path_explode(path, dir, &group, &name)) { | if (BLO_library_path_explode(path, dir, &group, &name)) { | ||||
| is_filtered = !is_hidden_file(file->relpath, filter); | is_filtered = !is_filtered_hidden(file->relpath, filter, file); | ||||
| if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { | ||||
| /* We only check for types if some type are enabled in filtering. */ | /* We only check for types if some type are enabled in filtering. */ | ||||
| if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { | if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { | ||||
| if (file->typeflag & FILE_TYPE_DIR) { | if (file->typeflag & FILE_TYPE_DIR) { | ||||
| if (file->typeflag & | if (file->typeflag & | ||||
| (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { | ||||
| if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { | ||||
| is_filtered = false; | is_filtered = false; | ||||
| Show All 31 Lines | |||||
| return is_filtered; | return is_filtered; | ||||
| } | } | ||||
| static bool is_filtered_main(FileListInternEntry *file, | static bool is_filtered_main(FileListInternEntry *file, | ||||
| const char *UNUSED(dir), | const char *UNUSED(dir), | ||||
| FileListFilter *filter) | FileListFilter *filter) | ||||
| { | { | ||||
| return !is_hidden_file(file->relpath, filter); | return !is_filtered_hidden(file->relpath, filter, file); | ||||
| } | } | ||||
| static void filelist_filter_clear(FileList *filelist) | static void filelist_filter_clear(FileList *filelist) | ||||
| { | { | ||||
| filelist->flags |= FL_NEED_FILTERING; | filelist->flags |= FL_NEED_FILTERING; | ||||
| } | } | ||||
| void filelist_filter(FileList *filelist) | void filelist_filter(FileList *filelist) | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| return ICON_UGLYPACKAGE; | return ICON_UGLYPACKAGE; | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_BLENDER) { | else if (typeflag & FILE_TYPE_BLENDER) { | ||||
| return ICON_FILE_BLEND; | return ICON_FILE_BLEND; | ||||
| } | } | ||||
| else if (is_main) { | else if (is_main) { | ||||
| /* Do not return icon for folders if icons are not 'main' draw type | /* Do not return icon for folders if icons are not 'main' draw type | ||||
| * (e.g. when used over previews). */ | * (e.g. when used over previews). */ | ||||
| return ICON_FILE_FOLDER; | return (file->attributes & DIRENTRY_ANY_LINK) ? ICON_FOLDER_REDIRECT : ICON_FILE_FOLDER; | ||||
| } | } | ||||
| else { | else { | ||||
| /* If this path is in System list then use that icon. */ | /* If this path is in System list then use that icon. */ | ||||
| struct FSMenu *fsmenu = ED_fsmenu_get(); | struct FSMenu *fsmenu = ED_fsmenu_get(); | ||||
| FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS); | FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS); | ||||
| char fullpath[FILE_MAX_LIBEXTRA]; | char fullpath[FILE_MAX_LIBEXTRA]; | ||||
| BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath); | BLI_join_dirfile(fullpath, sizeof(fullpath), root, file->relpath); | ||||
| BLI_add_slash(fullpath); | BLI_add_slash(fullpath); | ||||
| for (; tfsm; tfsm = tfsm->next) { | for (; tfsm; tfsm = tfsm->next) { | ||||
| if (STREQ(tfsm->path, fullpath)) { | if (STREQ(tfsm->path, fullpath)) { | ||||
| /* Never want a little folder inside a large one. */ | /* Never want a little folder inside a large one. */ | ||||
| return (tfsm->icon == ICON_FILE_FOLDER) ? ICON_NONE : tfsm->icon; | return (tfsm->icon == ICON_FILE_FOLDER) ? ICON_NONE : tfsm->icon; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (file->attributes & DIRENTRY_ANY_LINK) { | |||||
| return ICON_LOOP_FORWARDS; | |||||
| } | |||||
| else if (file->attributes & DIRENTRY_OFFLINE) { | |||||
| return ICON_ERROR; | |||||
| } | |||||
| else if (file->attributes & DIRENTRY_TEMPORARY) { | |||||
| return ICON_FILE_CACHE; | |||||
| } | |||||
| else if (file->attributes & DIRENTRY_SYSTEM) { | |||||
| return ICON_SYSTEM; | |||||
| } | |||||
| } | } | ||||
| if (typeflag & FILE_TYPE_BLENDER) { | if (typeflag & FILE_TYPE_BLENDER) { | ||||
| return ICON_FILE_BLEND; | return ICON_FILE_BLEND; | ||||
| } | } | ||||
| else if (typeflag & FILE_TYPE_BLENDER_BACKUP) { | else if (typeflag & FILE_TYPE_BLENDER_BACKUP) { | ||||
| return ICON_FILE_BACKUP; | return ICON_FILE_BACKUP; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index) | static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry, const int index) | ||||
| { | { | ||||
| FileListEntryCache *cache = &filelist->filelist_cache; | FileListEntryCache *cache = &filelist->filelist_cache; | ||||
| BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE); | BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE); | ||||
| if (!entry->image && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) && | if (!entry->image && !(entry->attributes & DIRENTRY_INVALID_PREVIEW) && | ||||
| (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | | (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | | ||||
| FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) { | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) { | ||||
| FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__); | FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__); | ||||
| BLI_join_dirfile( | BLI_join_dirfile( | ||||
| preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath); | preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath); | ||||
| preview->index = index; | preview->index = index; | ||||
| preview->flags = entry->typeflag; | preview->flags = entry->typeflag; | ||||
| preview->img = NULL; | preview->img = NULL; | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| ret->entry = rev; | ret->entry = rev; | ||||
| ret->relpath = BLI_strdup(entry->relpath); | ret->relpath = BLI_strdup(entry->relpath); | ||||
| ret->name = BLI_strdup(entry->name); | ret->name = BLI_strdup(entry->name); | ||||
| ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath); | ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath); | ||||
| memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); | memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); | ||||
| ret->blentype = entry->blentype; | ret->blentype = entry->blentype; | ||||
| ret->typeflag = entry->typeflag; | ret->typeflag = entry->typeflag; | ||||
| ret->attributes = entry->attributes; | |||||
| BLI_addtail(&cache->cached_entries, ret); | BLI_addtail(&cache->cached_entries, ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry) | static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry) | ||||
| { | { | ||||
| BLI_remlink(&filelist->filelist_cache.cached_entries, entry); | BLI_remlink(&filelist->filelist_cache.cached_entries, entry); | ||||
| filelist_entry_free(entry); | filelist_entry_free(entry); | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| else { | else { | ||||
| IMB_freeImBuf(preview->img); | IMB_freeImBuf(preview->img); | ||||
| } | } | ||||
| } | } | ||||
| else if (entry) { | else if (entry) { | ||||
| /* We want to avoid re-processing this entry continuously! | /* We want to avoid re-processing this entry continuously! | ||||
| * Note that, since entries only live in cache, | * Note that, since entries only live in cache, | ||||
| * preview will be retried quite often anyway. */ | * preview will be retried quite often anyway. */ | ||||
| entry->flags |= FILE_ENTRY_INVALID_PREVIEW; | entry->attributes |= DIRENTRY_INVALID_PREVIEW; | ||||
| } | } | ||||
| MEM_freeN(preview); | MEM_freeN(preview); | ||||
| } | } | ||||
| return changed; | return changed; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| /* Otherwise, do not check extensions for directories! */ | /* Otherwise, do not check extensions for directories! */ | ||||
| else if (!(entry->typeflag & FILE_TYPE_DIR)) { | else if (!(entry->typeflag & FILE_TYPE_DIR)) { | ||||
| entry->typeflag = file_extension_type(root, entry->relpath); | entry->typeflag = file_extension_type(root, entry->relpath); | ||||
| if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) { | if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) { | ||||
| entry->typeflag |= FILE_TYPE_OPERATOR; | entry->typeflag |= FILE_TYPE_OPERATOR; | ||||
| } | } | ||||
| } | } | ||||
| /* Set file attributes. */ | |||||
| entry->attributes = BLI_file_attributes(root, entry->relpath); | |||||
| #ifndef WIN32 | |||||
| /* Set linux-style dot files hidden too. */ | |||||
| if (is_hidden_dot_filename(entry->relpath, entry)) { | |||||
| entry->attributes |= DIRENTRY_HIDDEN; | |||||
| } | |||||
| #endif | |||||
| BLI_addtail(entries, entry); | BLI_addtail(entries, entry); | ||||
| nbr_entries++; | nbr_entries++; | ||||
| } | } | ||||
| BLI_filelist_free(files, nbr_files); | BLI_filelist_free(files, nbr_files); | ||||
| } | } | ||||
| return nbr_entries; | return nbr_entries; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||
A typed enum could be used here.