Blender V4.3
io_drop_import_file.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_path_utils.hh"
6#include "BLI_string.h"
7
8#include "BLT_translation.hh"
9
10#include "BKE_file_handler.hh"
11
12#include "CLG_log.h"
13
14#include "DNA_space_types.h"
15
16#include "RNA_access.hh"
17#include "RNA_define.hh"
18#include "RNA_prototypes.hh"
19
20#include "WM_api.hh"
21#include "WM_types.hh"
22
23#include "UI_interface.hh"
24
26#include "io_utils.hh"
27
28static CLG_LogRef LOG = {"io.drop_import_file"};
29
36 const bContext *C, const blender::Span<std::string> paths, const bool quiet = true)
37{
38 using namespace blender;
39 auto file_handlers = bke::file_handlers_poll_file_drop(C, paths);
40 file_handlers.remove_if([quiet](const bke::FileHandlerType *file_handler) {
41 return WM_operatortype_find(file_handler->import_operator, quiet) == nullptr;
42 });
43 return file_handlers;
44}
45
51 const blender::bke::FileHandlerType *file_handler, const blender::Span<std::string> paths)
52{
54 BLI_assert(ot != nullptr);
55 PointerRNA props;
57
58 const auto supported_paths = file_handler->filter_supported_paths(paths);
59
60 PropertyRNA *filepath_prop = RNA_struct_find_property_check(props, "filepath", PROP_STRING);
61 if (filepath_prop) {
62 RNA_property_string_set(&props, filepath_prop, paths[supported_paths[0]].c_str());
63 }
64
65 PropertyRNA *directory_prop = RNA_struct_find_property_check(props, "directory", PROP_STRING);
66 if (directory_prop) {
67 char dir[FILE_MAX];
68 BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
69 RNA_property_string_set(&props, directory_prop, dir);
70 }
71
73 props, "files", &RNA_OperatorFileListElement);
74 if (files_prop) {
75 RNA_property_collection_clear(&props, files_prop);
76 for (const auto &index : supported_paths) {
77 char file[FILE_MAX];
78 BLI_path_split_file_part(paths[index].c_str(), file, sizeof(file));
79
80 PointerRNA item_ptr{};
81 RNA_property_collection_add(&props, files_prop, &item_ptr);
82 RNA_string_set(&item_ptr, "name", file);
83 }
84 }
85 const bool has_any_filepath_prop = filepath_prop || directory_prop || files_prop;
90 const bool has_missing_filepath_prop = bool(directory_prop) != bool(files_prop);
91
92 if (!has_any_filepath_prop || has_missing_filepath_prop) {
93 const char *message =
94 "Expected operator properties filepath or files and directory not found. Refer to "
95 "FileHandler documentation for details.";
96 CLOG_WARN(&LOG, "%s", message);
97 }
98 return props;
99}
100
102{
104 if (paths.is_empty()) {
105 return OPERATOR_CANCELLED;
106 }
107
108 auto file_handlers = drop_import_file_poll_file_handlers(C, paths, false);
109 if (file_handlers.is_empty()) {
110 return OPERATOR_CANCELLED;
111 }
112
113 wmOperatorType *ot = WM_operatortype_find(file_handlers[0]->import_operator, false);
114 PointerRNA file_props = file_handler_import_operator_create_ptr(file_handlers[0], paths);
115
116 WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &file_props, nullptr);
117 WM_operator_properties_free(&file_props);
118 return OPERATOR_FINISHED;
119}
120
121static int wm_drop_import_file_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
122{
124 if (paths.is_empty()) {
125 return OPERATOR_CANCELLED;
126 }
127
128 auto file_handlers = drop_import_file_poll_file_handlers(C, paths, false);
129 if (file_handlers.size() == 1) {
130 return wm_drop_import_file_exec(C, op);
131 }
132
137 uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
138 uiLayout *layout = UI_popup_menu_layout(pup);
140
141 for (auto *file_handler : file_handlers) {
142 const PointerRNA file_props = file_handler_import_operator_create_ptr(file_handler, paths);
143 wmOperatorType *ot = WM_operatortype_find(file_handler->import_operator, false);
144 uiItemFullO_ptr(layout,
145 ot,
147 ICON_NONE,
148 static_cast<IDProperty *>(file_props.data),
151 nullptr);
152 }
153
154 UI_popup_menu_end(C, pup);
155 return OPERATOR_INTERFACE;
156}
157
159{
160 ot->name = "Drop to Import File";
161 ot->description = "Operator that allows file handlers to receive file drops";
162 ot->idname = "WM_OT_drop_import_file";
166
167 PropertyRNA *prop;
168
170 ot->srna, "directory", nullptr, FILE_MAX, "Directory", "Directory of the file");
172
173 prop = RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
175}
176
177static void drop_import_file_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
178{
179 const auto paths = WM_drag_get_paths(drag);
180
181 char dir[FILE_MAX];
182 BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
183 RNA_string_set(drop->ptr, "directory", dir);
184
185 RNA_collection_clear(drop->ptr, "files");
186 for (const auto &path : paths) {
187 char file[FILE_MAX];
188 BLI_path_split_file_part(path.c_str(), file, sizeof(file));
189
190 PointerRNA itemptr{};
191 RNA_collection_add(drop->ptr, "files", &itemptr);
192 RNA_string_set(&itemptr, "name", file);
193 }
194}
195
196static bool drop_import_file_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
197{
198 if (drag->type != WM_DRAG_PATH) {
199 return false;
200 }
201 const auto paths = WM_drag_get_paths(drag);
202 return !drop_import_file_poll_file_handlers(C, paths, true).is_empty();
203}
204
205static std::string drop_import_file_tooltip(bContext *C,
206 wmDrag *drag,
207 const int /*xy*/[2],
208 wmDropBox * /*drop*/)
209{
210 const auto paths = WM_drag_get_paths(drag);
211 const auto file_handlers = drop_import_file_poll_file_handlers(C, paths, true);
212 if (file_handlers.size() == 1) {
213 wmOperatorType *ot = WM_operatortype_find(file_handlers[0]->import_operator, false);
214 return TIP_(ot->name);
215 }
216
217 return TIP_("Multiple file handlers can be used, drop to pick which to use");
218}
219
221{
224 "WM_OT_drop_import_file",
227 nullptr,
229}
#define BLI_assert(a)
Definition BLI_assert.h:50
#define FILE_MAX
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
#define TIP_(msgid)
#define CTX_TIP_(context, msgid)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
@ RGN_TYPE_WINDOW
@ SPACE_EMPTY
@ PROP_STRING
Definition RNA_types.hh:68
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
void uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, PointerRNA *r_opptr)
#define UI_ITEM_NONE
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:218
@ WM_DRAG_PATH
Definition WM_types.hh:1160
static blender::Vector< blender::bke::FileHandlerType * > drop_import_file_poll_file_handlers(const bContext *C, const blender::Span< std::string > paths, const bool quiet=true)
static std::string drop_import_file_tooltip(bContext *C, wmDrag *drag, const int[2], wmDropBox *)
void WM_OT_drop_import_file(wmOperatorType *ot)
static int wm_drop_import_file_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void drop_import_file_copy(bContext *, wmDrag *drag, wmDropBox *drop)
static bool drop_import_file_poll(bContext *C, wmDrag *drag, const wmEvent *)
static CLG_LogRef LOG
void ED_dropbox_drop_import_file()
static int wm_drop_import_file_exec(bContext *C, wmOperator *op)
static PointerRNA file_handler_import_operator_create_ptr(const blender::bke::FileHandlerType *file_handler, const blender::Span< std::string > paths)
Vector< std::string > paths_from_operator_properties(PointerRNA *ptr)
Definition io_utils.cc:74
PropertyRNA * RNA_struct_find_collection_property_check(PointerRNA &props, const char *name, const StructRNA *struct_type_check)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property_check(PointerRNA &props, const char *name, const PropertyType property_type_check)
void RNA_collection_clear(PointerRNA *ptr, const char *name)
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
PropertyRNA * RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_string_dir_path(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void * data
Definition RNA_types.hh:42
char import_operator[OP_MAX_TYPENAME]
blender::Vector< int64_t > filter_supported_paths(const blender::Span< std::string > paths) const
eWM_DragDataType type
Definition WM_types.hh:1282
PointerRNA * ptr
Definition WM_types.hh:1368
const char * name
Definition WM_types.hh:990
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * translation_context
Definition WM_types.hh:994
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
struct PointerRNA * ptr
wmDropBox * WM_dropbox_add(ListBase *lb, const char *idname, bool(*poll)(bContext *C, wmDrag *drag, const wmEvent *event), void(*copy)(bContext *C, wmDrag *drag, wmDropBox *drop), void(*cancel)(Main *bmain, wmDrag *drag, wmDropBox *drop), WMDropboxTooltipFunc tooltip)
blender::Span< std::string > WM_drag_get_paths(const wmDrag *drag)
ListBase * WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorType * ot
Definition wm_files.cc:4125
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
void WM_operator_properties_free(PointerRNA *ptr)