diff options
Diffstat (limited to 'source/blender/editors/space_file/folder_history.cc')
-rw-r--r-- | source/blender/editors/space_file/folder_history.cc | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/source/blender/editors/space_file/folder_history.cc b/source/blender/editors/space_file/folder_history.cc new file mode 100644 index 00000000000..1cb8fa279c5 --- /dev/null +++ b/source/blender/editors/space_file/folder_history.cc @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2007 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup spfile + * + * Storage for a list of folders for history backward and forward navigation. + */ + +#include <cstring> + +#include "BLI_listbase.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "BKE_context.h" + +#include "DNA_space_types.h" + +#include "ED_fileselect.h" + +#include "MEM_guardedalloc.h" + +#include "file_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name FOLDERLIST (previous/next) + * \{ */ + +typedef struct FolderList { + struct FolderList *next, *prev; + char *foldername; +} FolderList; + +void folderlist_popdir(struct ListBase *folderlist, char *dir) +{ + const char *prev_dir; + struct FolderList *folder; + folder = static_cast<FolderList *>(folderlist->last); + + if (folder) { + /* remove the current directory */ + MEM_freeN(folder->foldername); + BLI_freelinkN(folderlist, folder); + + folder = static_cast<FolderList *>(folderlist->last); + if (folder) { + prev_dir = folder->foldername; + BLI_strncpy(dir, prev_dir, FILE_MAXDIR); + } + } + /* Delete the folder next or use set-directory directly before PREVIOUS OP. */ +} + +void folderlist_pushdir(ListBase *folderlist, const char *dir) +{ + if (!dir[0]) { + return; + } + + struct FolderList *folder, *previous_folder; + previous_folder = static_cast<FolderList *>(folderlist->last); + + /* check if already exists */ + if (previous_folder && previous_folder->foldername) { + if (BLI_path_cmp(previous_folder->foldername, dir) == 0) { + return; + } + } + + /* create next folder element */ + folder = MEM_new<FolderList>(__func__); + folder->foldername = BLI_strdup(dir); + + /* add it to the end of the list */ + BLI_addtail(folderlist, folder); +} + +const char *folderlist_peeklastdir(ListBase *folderlist) +{ + struct FolderList *folder; + + if (!folderlist->last) { + return NULL; + } + + folder = static_cast<FolderList *>(folderlist->last); + return folder->foldername; +} + +bool folderlist_clear_next(struct SpaceFile *sfile) +{ + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); + struct FolderList *folder; + + /* if there is no folder_next there is nothing we can clear */ + if (BLI_listbase_is_empty(sfile->folders_next)) { + return false; + } + + /* if previous_folder, next_folder or refresh_folder operators are executed + * it doesn't clear folder_next */ + folder = static_cast<FolderList *>(sfile->folders_prev->last); + if ((!folder) || (BLI_path_cmp(folder->foldername, params->dir) == 0)) { + return false; + } + + /* eventually clear flist->folders_next */ + return true; +} + +void folderlist_free(ListBase *folderlist) +{ + if (folderlist) { + LISTBASE_FOREACH (FolderList *, folder, folderlist) { + MEM_freeN(folder->foldername); + } + BLI_freelistN(folderlist); + } +} + +static ListBase folderlist_duplicate(ListBase *folderlist) +{ + ListBase folderlistn = {NULL}; + + BLI_duplicatelist(&folderlistn, folderlist); + + LISTBASE_FOREACH (FolderList *, folder, &folderlistn) { + folder->foldername = (char *)MEM_dupallocN(folder->foldername); + } + return folderlistn; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Folder-History (wraps/owns file list above) + * \{ */ + +static FileFolderHistory *folder_history_find(const SpaceFile *sfile, eFileBrowse_Mode browse_mode) +{ + LISTBASE_FOREACH (FileFolderHistory *, history, &sfile->folder_histories) { + if (history->browse_mode == browse_mode) { + return history; + } + } + + return NULL; +} + +void folder_history_list_ensure_for_active_browse_mode(SpaceFile *sfile) +{ + FileFolderHistory *history = folder_history_find(sfile, (eFileBrowse_Mode)sfile->browse_mode); + + if (!history) { + history = MEM_cnew<FileFolderHistory>(__func__); + history->browse_mode = sfile->browse_mode; + BLI_addtail(&sfile->folder_histories, history); + } + + sfile->folders_next = &history->folders_next; + sfile->folders_prev = &history->folders_prev; +} + +static void folder_history_entry_free(SpaceFile *sfile, FileFolderHistory *history) +{ + if (sfile->folders_prev == &history->folders_prev) { + sfile->folders_prev = NULL; + } + if (sfile->folders_next == &history->folders_next) { + sfile->folders_next = NULL; + } + folderlist_free(&history->folders_prev); + folderlist_free(&history->folders_next); + BLI_freelinkN(&sfile->folder_histories, history); +} + +void folder_history_list_free(SpaceFile *sfile) +{ + LISTBASE_FOREACH_MUTABLE (FileFolderHistory *, history, &sfile->folder_histories) { + folder_history_entry_free(sfile, history); + } +} + +ListBase folder_history_list_duplicate(ListBase *listbase) +{ + ListBase histories = {NULL}; + + LISTBASE_FOREACH (FileFolderHistory *, history, listbase) { + FileFolderHistory *history_new = static_cast<FileFolderHistory *>(MEM_dupallocN(history)); + history_new->folders_prev = folderlist_duplicate(&history->folders_prev); + history_new->folders_next = folderlist_duplicate(&history->folders_next); + BLI_addtail(&histories, history_new); + } + + return histories; +} + +/** \} */ |