145 lines
4.4 KiB
C++
145 lines
4.4 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include <cstring>
|
|
|
|
#include "BKE_file_handler.hh"
|
|
|
|
#include "BLI_path_utils.hh"
|
|
#include "BLI_string.h"
|
|
|
|
#include "BLT_translation.hh"
|
|
|
|
namespace blender::bke {
|
|
|
|
static Vector<std::unique_ptr<FileHandlerType>> &file_handlers_vector()
|
|
{
|
|
static Vector<std::unique_ptr<FileHandlerType>> file_handlers;
|
|
return file_handlers;
|
|
}
|
|
|
|
Span<std::unique_ptr<FileHandlerType>> file_handlers()
|
|
{
|
|
return file_handlers_vector();
|
|
}
|
|
|
|
FileHandlerType *file_handler_find(const StringRef idname)
|
|
{
|
|
const auto *itr = std::find_if(file_handlers().begin(),
|
|
file_handlers().end(),
|
|
[idname](const std::unique_ptr<FileHandlerType> &file_handler) {
|
|
return idname == file_handler->idname;
|
|
});
|
|
if (itr != file_handlers().end()) {
|
|
return itr->get();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void file_handler_add(std::unique_ptr<FileHandlerType> file_handler)
|
|
{
|
|
BLI_assert(file_handler_find(file_handler->idname) == nullptr);
|
|
|
|
/** Load all extensions from the string list into the list. */
|
|
const char char_separator = ';';
|
|
const char *char_begin = file_handler->file_extensions_str;
|
|
const char *char_end = BLI_strchr_or_end(char_begin, char_separator);
|
|
while (char_begin[0]) {
|
|
if (char_end - char_begin > 1) {
|
|
std::string file_extension(char_begin, char_end - char_begin);
|
|
file_handler->file_extensions.append(file_extension);
|
|
}
|
|
char_begin = char_end[0] ? char_end + 1 : char_end;
|
|
char_end = BLI_strchr_or_end(char_begin, char_separator);
|
|
}
|
|
|
|
file_handlers_vector().append(std::move(file_handler));
|
|
}
|
|
|
|
void file_handler_remove(FileHandlerType *file_handler)
|
|
{
|
|
file_handlers_vector().remove_if(
|
|
[file_handler](const std::unique_ptr<FileHandlerType> &test_file_handler) {
|
|
return test_file_handler.get() == file_handler;
|
|
});
|
|
}
|
|
|
|
blender::Vector<FileHandlerType *> file_handlers_poll_file_drop(
|
|
const bContext *C, const blender::Span<std::string> paths)
|
|
{
|
|
blender::Vector<std::string> path_extensions;
|
|
for (const std::string &path : paths) {
|
|
const char *extension = BLI_path_extension(path.c_str());
|
|
if (!extension) {
|
|
continue;
|
|
}
|
|
path_extensions.append_non_duplicates(extension);
|
|
}
|
|
|
|
blender::Vector<FileHandlerType *> result;
|
|
for (const std::unique_ptr<FileHandlerType> &file_handler_ptr : file_handlers()) {
|
|
FileHandlerType &file_handler = *file_handler_ptr;
|
|
const auto &file_extensions = file_handler.file_extensions;
|
|
bool support_any_extension = false;
|
|
for (const std::string &extension : path_extensions) {
|
|
auto test_fn = [&extension](const std::string &test_extension) {
|
|
return BLI_strcaseeq(extension.c_str(), test_extension.c_str()) == 1;
|
|
};
|
|
support_any_extension = std::any_of(file_extensions.begin(), file_extensions.end(), test_fn);
|
|
if (support_any_extension) {
|
|
break;
|
|
}
|
|
}
|
|
if (!support_any_extension) {
|
|
continue;
|
|
}
|
|
|
|
if (!(file_handler.poll_drop && file_handler.poll_drop(C, &file_handler))) {
|
|
continue;
|
|
}
|
|
|
|
result.append(&file_handler);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
blender::Vector<int64_t> FileHandlerType::filter_supported_paths(
|
|
const blender::Span<std::string> paths) const
|
|
{
|
|
blender::Vector<int64_t> indices;
|
|
|
|
for (const int idx : paths.index_range()) {
|
|
const char *extension = BLI_path_extension(paths[idx].c_str());
|
|
if (!extension) {
|
|
continue;
|
|
}
|
|
auto test_fn = [extension](const std::string &test_extension) {
|
|
return BLI_strcaseeq(extension, test_extension.c_str()) == 1;
|
|
};
|
|
|
|
if (std::any_of(file_extensions.begin(), file_extensions.end(), test_fn)) {
|
|
indices.append(idx);
|
|
}
|
|
}
|
|
return indices;
|
|
}
|
|
|
|
std::string FileHandlerType::get_default_filename(const StringRefNull name)
|
|
{
|
|
/* Spaces are supported but do not allow all characters to be blank. */
|
|
const bool all_blank = name.is_empty() ||
|
|
std::all_of(name.begin(), name.end(), [](char c) { return c == ' '; });
|
|
|
|
char filename[FILE_MAXFILE];
|
|
STRNCPY(filename, all_blank ? DATA_("Untitled") : name.c_str());
|
|
BLI_path_extension_ensure(filename,
|
|
sizeof(filename),
|
|
file_extensions.is_empty() ? "" : file_extensions.first().c_str());
|
|
BLI_path_make_safe_filename(filename);
|
|
|
|
return filename;
|
|
}
|
|
|
|
} // namespace blender::bke
|