Blender V4.5
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
7#include "BLT_translation.hh"
8
9#include "BKE_file_handler.hh"
10
11#include "CLG_log.h"
12
13#include "DNA_space_types.h"
14
15#include "RNA_access.hh"
16#include "RNA_define.hh"
17#include "RNA_prototypes.hh"
18
19#include "WM_api.hh"
20#include "WM_types.hh"
21
22#include "UI_interface.hh"
23
25#include "io_utils.hh"
26
27static CLG_LogRef LOG = {"io.drop_import_file"};
28
35 const bContext *C, const blender::Span<std::string> paths, const bool quiet = true)
36{
37 using namespace blender;
38 auto file_handlers = bke::file_handlers_poll_file_drop(C, paths);
39 file_handlers.remove_if([quiet](const bke::FileHandlerType *file_handler) {
40 return WM_operatortype_find(file_handler->import_operator, quiet) == nullptr;
41 });
42 return file_handlers;
43}
44
49 const blender::bke::FileHandlerType *file_handler,
50 PointerRNA &props,
52{
53
54 const auto supported_paths = file_handler->filter_supported_paths(paths);
55
56 PropertyRNA *filepath_prop = RNA_struct_find_property_check(props, "filepath", PROP_STRING);
57 if (filepath_prop) {
58 RNA_property_string_set(&props, filepath_prop, paths[supported_paths[0]].c_str());
59 }
60
61 PropertyRNA *directory_prop = RNA_struct_find_property_check(props, "directory", PROP_STRING);
62 if (directory_prop) {
63 char dir[FILE_MAX];
64 BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
65 RNA_property_string_set(&props, directory_prop, dir);
66 }
67
69 props, "files", &RNA_OperatorFileListElement);
70 if (files_prop) {
71 RNA_property_collection_clear(&props, files_prop);
72 for (const auto &index : supported_paths) {
73 char file[FILE_MAX];
74 BLI_path_split_file_part(paths[index].c_str(), file, sizeof(file));
75
76 PointerRNA item_ptr{};
77 RNA_property_collection_add(&props, files_prop, &item_ptr);
78 RNA_string_set(&item_ptr, "name", file);
79 }
80 }
81 const bool has_any_filepath_prop = filepath_prop || directory_prop || files_prop;
86 const bool has_missing_filepath_prop = bool(directory_prop) != bool(files_prop);
87
88 if (!has_any_filepath_prop || has_missing_filepath_prop) {
89 const char *message =
90 "Expected operator properties filepath or files and directory not found. Refer to "
91 "FileHandler documentation for details.";
92 CLOG_WARN(&LOG, "%s", message);
93 }
94}
95
97{
99 if (paths.is_empty()) {
100 return OPERATOR_CANCELLED;
101 }
102
103 auto file_handlers = drop_import_file_poll_file_handlers(C, paths, false);
104 if (file_handlers.is_empty()) {
105 return OPERATOR_CANCELLED;
106 }
107
108 wmOperatorType *ot = WM_operatortype_find(file_handlers[0]->import_operator, false);
109 PointerRNA file_props;
111 file_handler_import_operator_write_ptr(file_handlers[0], file_props, paths);
112
113 WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &file_props, nullptr);
114 WM_operator_properties_free(&file_props);
115 return OPERATOR_FINISHED;
116}
117
119 wmOperator *op,
120 const wmEvent * /*event*/)
121{
123 if (paths.is_empty()) {
124 return OPERATOR_CANCELLED;
125 }
126
127 auto file_handlers = drop_import_file_poll_file_handlers(C, paths, false);
128 if (file_handlers.size() == 1) {
129 return wm_drop_import_file_exec(C, op);
130 }
131
136 uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
137 uiLayout *layout = UI_popup_menu_layout(pup);
139
140 for (auto *file_handler : file_handlers) {
141 wmOperatorType *ot = WM_operatortype_find(file_handler->import_operator, false);
142 PointerRNA file_props = layout->op(ot,
143 CTX_TIP_(ot->translation_context, ot->name),
144 ICON_NONE,
147 file_handler_import_operator_write_ptr(file_handler, file_props, paths);
148 }
149
150 UI_popup_menu_end(C, pup);
151 return OPERATOR_INTERFACE;
152}
153
155{
156 ot->name = "Drop to Import File";
157 ot->description = "Operator that allows file handlers to receive file drops";
158 ot->idname = "WM_OT_drop_import_file";
159 ot->flag = OPTYPE_INTERNAL;
162
163 PropertyRNA *prop;
164
166 ot->srna, "directory", nullptr, FILE_MAX, "Directory", "Directory of the file");
168
169 prop = RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
171}
172
177
178static bool drop_import_file_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
179{
180 if (drag->type != WM_DRAG_PATH) {
181 return false;
182 }
183 const auto paths = WM_drag_get_paths(drag);
184 return !drop_import_file_poll_file_handlers(C, paths, true).is_empty();
185}
186
188 wmDrag *drag,
189 const int /*xy*/[2],
190 wmDropBox * /*drop*/)
191{
192 const auto paths = WM_drag_get_paths(drag);
193 const auto file_handlers = drop_import_file_poll_file_handlers(C, paths, true);
194 if (file_handlers.size() == 1) {
195 wmOperatorType *ot = WM_operatortype_find(file_handlers[0]->import_operator, false);
196 return TIP_(ot->name);
197 }
198
199 return TIP_("Multiple file handlers can be used, drop to pick which to use");
200}
201
203{
206 "WM_OT_drop_import_file",
209 nullptr,
211}
#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
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ PROP_STRING
Definition RNA_types.hh:153
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
#define C
Definition RandGen.cpp:29
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
#define UI_ITEM_NONE
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:238
@ WM_DRAG_PATH
Definition WM_types.hh:1205
static wmOperatorStatus wm_drop_import_file_invoke(bContext *C, wmOperator *op, const wmEvent *)
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 *)
static void file_handler_import_operator_write_ptr(const blender::bke::FileHandlerType *file_handler, PointerRNA &props, const blender::Span< std::string > paths)
static wmOperatorStatus wm_drop_import_file_exec(bContext *C, wmOperator *op)
void WM_OT_drop_import_file(wmOperatorType *ot)
static void drop_import_file_copy(bContext *, wmDrag *drag, wmDropBox *drop)
static bool drop_import_file_poll(bContext *C, wmDrag *drag, const wmEvent *)
void ED_dropbox_drop_import_file()
#define LOG(severity)
Definition log.h:32
blender::Vector< FileHandlerType * > file_handlers_poll_file_drop(const bContext *C, const blender::Span< std::string > paths)
Vector< std::string > paths_from_operator_properties(PointerRNA *ptr)
Definition io_utils.cc:74
void paths_to_operator_properties(PointerRNA *ptr, const Span< std::string > paths)
Definition io_utils.cc:115
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_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)
char import_operator[OP_MAX_TYPENAME]
blender::Vector< int64_t > filter_supported_paths(const blender::Span< std::string > paths) const
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
eWM_DragDataType type
Definition WM_types.hh:1327
PointerRNA * ptr
Definition WM_types.hh:1415
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)
wmOperatorStatus WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorType * ot
Definition wm_files.cc:4225
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)