Blender V4.3
buttons_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdlib>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "DNA_userdef_types.h"
15
16#include "BLI_fileops.h"
17#include "BLI_path_utils.hh"
18#include "BLI_string.h"
19#include "BLI_utildefines.h"
20
21#include "BLT_translation.hh"
22
23#include "BKE_appdir.hh"
24#include "BKE_context.hh"
25#include "BKE_main.hh"
26#include "BKE_report.hh"
27#include "BKE_screen.hh"
28
29#include "WM_api.hh"
30#include "WM_types.hh"
31
32#include "ED_screen.hh"
33#include "ED_undo.hh"
34
35#include "RNA_access.hh"
36#include "RNA_prototypes.hh"
37
38#include "UI_interface.hh"
39#include "UI_resources.hh"
40
41#include "buttons_intern.hh" /* own include */
42
43/* -------------------------------------------------------------------- */
50{
52 ScrArea *area = CTX_wm_area(C);
54
55 UI_textbutton_activate_rna(C, region, space, "search_filter");
56
57 return OPERATOR_FINISHED;
58}
59
61{
62 /* Identifiers. */
63 ot->name = "Filter";
64 ot->description = "Start entering filter text";
65 ot->idname = "BUTTONS_OT_start_filter";
66
67 /* Callbacks. */
70}
71
73{
75
76 space->runtime->search_string[0] = '\0';
77
78 ScrArea *area = CTX_wm_area(C);
81
82 return OPERATOR_FINISHED;
83}
84
86{
87 /* Identifiers. */
88 ot->name = "Clear Filter";
89 ot->description = "Clear the search filter";
90 ot->idname = "BUTTONS_OT_clear_filter";
91
92 /* Callbacks. */
95}
96
99/* -------------------------------------------------------------------- */
103static int toggle_pin_exec(bContext *C, wmOperator * /*op*/)
104{
106
107 sbuts->flag ^= SB_PIN_CONTEXT;
108
109 /* Create the properties space pointer. */
110 bScreen *screen = CTX_wm_screen(C);
111 PointerRNA sbuts_ptr = RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sbuts);
112
113 /* Create the new ID pointer and set the pin ID with RNA
114 * so we can use the property's RNA update functionality. */
115 ID *new_id = (sbuts->flag & SB_PIN_CONTEXT) ? buttons_context_id_path(C) : nullptr;
116 PointerRNA new_id_ptr = RNA_id_pointer_create(new_id);
117 RNA_pointer_set(&sbuts_ptr, "pin_id", new_id_ptr);
118
120
121 return OPERATOR_FINISHED;
122}
123
125{
126 /* Identifiers. */
127 ot->name = "Toggle Pin ID";
128 ot->description = "Keep the current data-block displayed";
129 ot->idname = "BUTTONS_OT_toggle_pin";
130
131 /* Callbacks. */
134}
135
138/* -------------------------------------------------------------------- */
142static int context_menu_invoke(bContext *C, wmOperator * /*op*/, const wmEvent * /*event*/)
143{
144 uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE);
145 uiLayout *layout = UI_popup_menu_layout(pup);
146
147 uiItemM(layout, "INFO_MT_area", nullptr, ICON_NONE);
148 UI_popup_menu_end(C, pup);
149
150 return OPERATOR_INTERFACE;
151}
152
154{
155 /* Identifiers. */
156 ot->name = "Context Menu";
157 ot->description = "Display properties editor context_menu";
158 ot->idname = "BUTTONS_OT_context_menu";
159
160 /* Callbacks. */
163}
164
167/* -------------------------------------------------------------------- */
177
179{
180 Main *bmain = CTX_data_main(C);
181 FileBrowseOp *fbo = static_cast<FileBrowseOp *>(op->customdata);
182 ID *id;
183 char *path;
184 int path_len;
185 const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
186 "filepath";
187
188 if (RNA_struct_property_is_set(op->ptr, path_prop) == 0 || fbo == nullptr) {
189 return OPERATOR_CANCELLED;
190 }
191
192 path = RNA_string_get_alloc(op->ptr, path_prop, nullptr, 0, &path_len);
193
194 /* Add slash for directories, important for some properties. */
196 char path_buf[FILE_MAX];
197 const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
198 id = fbo->ptr.owner_id;
199
200 STRNCPY(path_buf, path);
201 BLI_path_abs(path_buf, id ? ID_BLEND_PATH(bmain, id) : BKE_main_blendfile_path(bmain));
202
203 if (BLI_is_dir(path_buf)) {
204 /* Do this first so '//' isn't converted to '//\' on windows. */
205 BLI_path_slash_ensure(path_buf, sizeof(path_buf));
206 if (is_relative) {
207 BLI_path_rel(path_buf, BKE_main_blendfile_path(bmain));
208 path_len = strlen(path_buf);
209 path = static_cast<char *>(MEM_reallocN(path, path_len + 1));
210 memcpy(path, path_buf, path_len + 1);
211 }
212 else {
213 path = static_cast<char *>(MEM_reallocN(path, path_len + 1));
214 }
215 }
216 else {
217 char *const lslash = (char *)BLI_path_slash_rfind(path);
218 if (lslash) {
219 lslash[1] = '\0';
220 }
221 }
222 }
223
224 RNA_property_string_set(&fbo->ptr, fbo->prop, path);
225 RNA_property_update(C, &fbo->ptr, fbo->prop);
226 MEM_freeN(path);
227
228 if (fbo->is_undo) {
229 const char *undostr = RNA_property_identifier(fbo->prop);
230 ED_undo_push(C, undostr);
231 }
232
233 /* Special annoying exception, filesel on redo panel #26618. */
234 {
235 wmOperator *redo_op = WM_operator_last_redo(C);
236 if (redo_op) {
237 if (fbo->ptr.data == redo_op->ptr->data) {
238 ED_undo_operator_repeat(C, redo_op);
239 }
240 }
241 }
242
243 /* Tag user preferences as dirty. */
244 if (fbo->is_userdef) {
245 U.runtime.is_dirty = true;
246 }
247
249
250 return OPERATOR_FINISHED;
251}
252
253static void file_browse_cancel(bContext * /*C*/, wmOperator *op)
254{
256 op->customdata = nullptr;
257}
258
259static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
260{
262 PropertyRNA *prop;
263 bool is_undo;
264 bool is_userdef;
265 FileBrowseOp *fbo;
266 char *path;
267
268 const SpaceFile *sfile = CTX_wm_space_file(C);
269 if (sfile && sfile->op) {
270 BKE_report(op->reports, RPT_ERROR, "Cannot activate a file selector dialog, one already open");
271 return OPERATOR_CANCELLED;
272 }
273
274 UI_context_active_but_prop_get_filebrowser(C, &ptr, &prop, &is_undo, &is_userdef);
275
276 if (!prop) {
277 return OPERATOR_CANCELLED;
278 }
279
280 path = RNA_property_string_get_alloc(&ptr, prop, nullptr, 0, nullptr);
281
282 /* Useful yet irritating feature, Shift+Click to open the file
283 * Alt+Click to browse a folder in the OS's browser. */
284 if (event->modifier & (KM_SHIFT | KM_ALT)) {
285 wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
286 PointerRNA props_ptr;
287
288 if (event->modifier & KM_ALT) {
289 char *lslash = (char *)BLI_path_slash_rfind(path);
290 if (lslash) {
291 *lslash = '\0';
292 }
293 }
294
296 RNA_string_set(&props_ptr, "filepath", path);
297 WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr, nullptr);
298 WM_operator_properties_free(&props_ptr);
299
300 MEM_freeN(path);
301 return OPERATOR_CANCELLED;
302 }
303
304 {
305 const char *info;
306 if (!RNA_property_editable_info(&ptr, prop, &info)) {
307 if (info[0]) {
308 BKE_reportf(op->reports, RPT_ERROR, "Property is not editable: %s", info);
309 }
310 else {
311 BKE_report(op->reports, RPT_ERROR, "Property is not editable");
312 }
313 MEM_freeN(path);
314 return OPERATOR_CANCELLED;
315 }
316 }
317
318 PropertyRNA *prop_relpath;
319 const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
320 "filepath";
321 fbo = static_cast<FileBrowseOp *>(MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp"));
322 fbo->ptr = ptr;
323 fbo->prop = prop;
324 fbo->is_undo = is_undo;
325 fbo->is_userdef = is_userdef;
326 op->customdata = fbo;
327
328 /* Normally ED_fileselect_get_params would handle this but we need to because of stupid
329 * user-prefs exception. - campbell */
330 if ((prop_relpath = RNA_struct_find_property(op->ptr, "relative_path"))) {
331 if (!RNA_property_is_set(op->ptr, prop_relpath)) {
332 bool is_relative = (U.flag & USER_RELPATHS) != 0;
333
334 /* While we want to follow the defaults,
335 * we better not switch existing paths relative/absolute state. */
336 if (path[0]) {
337 is_relative = BLI_path_is_rel(path);
338 }
339
340 if (UNLIKELY(ptr.data == &U || is_userdef)) {
341 is_relative = false;
342 }
343
344 /* Annoying exception!, if we're dealing with the user preferences,
345 * default relative to be off. */
346 RNA_property_boolean_set(op->ptr, prop_relpath, is_relative);
347 }
348 }
349
350 if (!path[0]) {
351 /* Assign a new value (don't use this one). */
352 MEM_freeN(path);
353 path = nullptr;
354
355 /* When no path was found, calculate a reasonable fallback. */
356 char path_fallback[FILE_MAX];
357 bool path_fallback_set = false;
358
359 /* Defaults if the path is empty. */
360 const char *prop_id = RNA_property_identifier(prop);
361 /* NOTE: relying on built-in names isn't useful for add-on authors.
362 * The property itself should support this kind of meta-data. */
363 if (STR_ELEM(prop_id, "font_path_ui", "font_path_ui_mono", "font_directory")) {
364 if (U.fontdir[0]) {
365 STRNCPY(path_fallback, U.fontdir);
366 path_fallback_set = true;
367 }
368 else if (BKE_appdir_font_folder_default(path_fallback, ARRAY_SIZE(path_fallback))) {
369 path_fallback_set = true;
370 }
371 RNA_boolean_set(op->ptr, "filter_font", true);
372 RNA_boolean_set(op->ptr, "filter_folder", true);
373 RNA_enum_set(op->ptr, "display_type", FILE_IMGDISPLAY);
374 RNA_enum_set(op->ptr, "sort_method", FILE_SORT_ALPHA);
375 }
376
377 if (path_fallback_set == false) {
379 }
380
381 BLI_path_slash_ensure(path_fallback, ARRAY_SIZE(path_fallback));
382 path = BLI_strdup(path_fallback);
383 }
384
385 RNA_string_set(op->ptr, path_prop, path);
386 MEM_freeN(path);
387
388 PropertyRNA *prop_check_existing = RNA_struct_find_property(op->ptr, "check_existing");
389 if (!RNA_property_is_set(op->ptr, prop_check_existing)) {
390 const bool is_output_path = (RNA_property_flag(prop) & PROP_PATH_OUTPUT) != 0;
391 RNA_property_boolean_set(op->ptr, prop_check_existing, is_output_path);
392 }
393
395
397}
398
400{
401 /* Identifiers. */
402 ot->name = "Accept";
403 ot->description =
404 "Open a file browser, hold Shift to open the file, Alt to browse containing directory";
405 ot->idname = "BUTTONS_OT_file_browse";
406
407 /* Callbacks. */
411
412 /* Conditional undo based on button flag. */
413 ot->flag = 0;
414
415 /* Properties. */
417 0,
423}
424
426{
427 /* identifiers */
428 ot->name = "Accept";
429 ot->description =
430 "Open a directory browser, hold Shift to open the file, Alt to browse containing directory";
431 ot->idname = "BUTTONS_OT_directory_browse";
432
433 /* api callbacks */
437
438 /* conditional undo based on button flag */
439 ot->flag = 0;
440
441 /* properties */
443 0,
449}
450
const char * BKE_appdir_folder_default_or_root() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:163
bool BKE_appdir_font_folder_default(char *dir, size_t dir_maxncpy)
Definition appdir.cc:250
bScreen * CTX_wm_screen(const bContext *C)
SpaceFile * CTX_wm_space_file(const bContext *C)
SpaceProperties * CTX_wm_space_properties(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:815
File and directory operations.
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:433
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
const char * BLI_path_slash_rfind(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ARRAY_SIZE(arr)
#define UNLIKELY(x)
#define IFACE_(msgid)
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
@ RGN_TYPE_HEADER
@ FILE_SORT_DEFAULT
@ FILE_SORT_ALPHA
@ FILE_SPECIAL
@ SB_PIN_CONTEXT
@ FILE_IMGDISPLAY
@ FILE_DEFAULTDISPLAY
@ USER_RELPATHS
@ OPERATOR_RUNNING_MODAL
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
void ED_region_search_filter_update(const ScrArea *area, ARegion *region)
Definition area.cc:790
bool ED_operator_buttons_active(bContext *C)
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:104
int ED_undo_operator_repeat(bContext *C, wmOperator *op)
Definition ed_undo.cc:644
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
@ PROP_PATH_OUTPUT
Definition RNA_types.hh:340
@ PROP_DIRPATH
Definition RNA_types.hh:140
bool UI_textbutton_activate_rna(const bContext *C, ARegion *region, const void *rna_poin_data, const char *rna_prop_id)
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
void UI_context_active_but_prop_get_filebrowser(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop, bool *r_is_undo, bool *r_is_userdef)
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:934
@ WM_FILESEL_RELPATH
Definition WM_api.hh:933
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
@ WM_OP_EXEC_DEFAULT
Definition WM_types.hh:225
@ KM_ALT
Definition WM_types.hh:257
@ KM_SHIFT
Definition WM_types.hh:255
unsigned int U
Definition btGjkEpa3.h:78
ID * buttons_context_id_path(const bContext *C)
static void file_browse_cancel(bContext *, wmOperator *op)
void BUTTONS_OT_toggle_pin(wmOperatorType *ot)
void BUTTONS_OT_context_menu(wmOperatorType *ot)
void BUTTONS_OT_directory_browse(wmOperatorType *ot)
static int toggle_pin_exec(bContext *C, wmOperator *)
static int buttons_clear_filter_exec(bContext *C, wmOperator *)
static int file_browse_exec(bContext *C, wmOperator *op)
static int context_menu_invoke(bContext *C, wmOperator *, const wmEvent *)
static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void BUTTONS_OT_clear_filter(wmOperatorType *ot)
static int buttons_start_filter_exec(bContext *C, wmOperator *)
void BUTTONS_OT_file_browse(wmOperatorType *ot)
void BUTTONS_OT_start_filter(wmOperatorType *ot)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_flag(PropertyRNA *prop)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
bool RNA_property_editable_info(const PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
PointerRNA ptr
PropertyRNA * prop
Definition DNA_ID.h:413
ID * owner_id
Definition RNA_types.hh:40
void * data
Definition RNA_types.hh:42
struct wmOperator * op
uint8_t modifier
Definition WM_types.hh:739
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
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 * description
Definition WM_types.hh:996
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_fileselect(bContext *C, wmOperator *op)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
wmOperator * WM_operator_last_redo(const bContext *C)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
void WM_operator_properties_free(PointerRNA *ptr)