Blender  V3.3
buttons_ops.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation. All rights reserved. */
3 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "DNA_userdef_types.h"
14 
15 #include "BLI_fileops.h"
16 #include "BLI_path_util.h"
17 #include "BLI_string.h"
18 #include "BLI_utildefines.h"
19 
20 #include "BLT_translation.h"
21 
22 #include "BKE_context.h"
23 #include "BKE_main.h"
24 #include "BKE_report.h"
25 #include "BKE_screen.h"
26 
27 #include "WM_api.h"
28 #include "WM_types.h"
29 
30 #include "ED_screen.h"
31 #include "ED_undo.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_prototypes.h"
35 
36 #include "UI_interface.h"
37 #include "UI_resources.h"
38 
39 #include "buttons_intern.h" /* own include */
40 
41 /* -------------------------------------------------------------------- */
48 {
52 
53  ARegion *region_ctx = CTX_wm_region(C);
54  CTX_wm_region_set(C, region);
55  UI_textbutton_activate_rna(C, region, space, "search_filter");
56  CTX_wm_region_set(C, region_ctx);
57 
58  return OPERATOR_FINISHED;
59 }
60 
62 {
63  /* Identifiers. */
64  ot->name = "Filter";
65  ot->description = "Start entering filter text";
66  ot->idname = "BUTTONS_OT_start_filter";
67 
68  /* Callbacks. */
71 }
72 
74 {
76 
77  space->runtime->search_string[0] = '\0';
78 
82 
83  return OPERATOR_FINISHED;
84 }
85 
87 {
88  /* Identifiers. */
89  ot->name = "Clear Filter";
90  ot->description = "Clear the search filter";
91  ot->idname = "BUTTONS_OT_clear_filter";
92 
93  /* Callbacks. */
96 }
97 
100 /* -------------------------------------------------------------------- */
105 {
107 
108  sbuts->flag ^= SB_PIN_CONTEXT;
109 
110  /* Create the properties space pointer. */
111  PointerRNA sbuts_ptr;
112  bScreen *screen = CTX_wm_screen(C);
113  RNA_pointer_create(&screen->id, &RNA_SpaceProperties, sbuts, &sbuts_ptr);
114 
115  /* Create the new ID pointer and set the pin ID with RNA
116  * so we can use the property's RNA update functionality. */
117  ID *new_id = (sbuts->flag & SB_PIN_CONTEXT) ? buttons_context_id_path(C) : NULL;
118  PointerRNA new_id_ptr;
119  RNA_id_pointer_create(new_id, &new_id_ptr);
120  RNA_pointer_set(&sbuts_ptr, "pin_id", new_id_ptr);
121 
123 
124  return OPERATOR_FINISHED;
125 }
126 
128 {
129  /* Identifiers. */
130  ot->name = "Toggle Pin ID";
131  ot->description = "Keep the current data-block displayed";
132  ot->idname = "BUTTONS_OT_toggle_pin";
133 
134  /* Callbacks. */
137 }
138 
141 /* -------------------------------------------------------------------- */
145 static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
146 {
147  uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE);
148  uiLayout *layout = UI_popup_menu_layout(pup);
149 
150  uiItemM(layout, "INFO_MT_area", NULL, ICON_NONE);
151  UI_popup_menu_end(C, pup);
152 
153  return OPERATOR_INTERFACE;
154 }
155 
157 {
158  /* Identifiers. */
159  ot->name = "Context Menu";
160  ot->description = "Display properties editor context_menu";
161  ot->idname = "BUTTONS_OT_context_menu";
162 
163  /* Callbacks. */
166 }
167 
170 /* -------------------------------------------------------------------- */
174 typedef struct FileBrowseOp {
177  bool is_undo;
180 
182 {
183  Main *bmain = CTX_data_main(C);
184  FileBrowseOp *fbo = op->customdata;
185  ID *id;
186  char *str;
187  int str_len;
188  const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
189  "filepath";
190 
191  if (RNA_struct_property_is_set(op->ptr, path_prop) == 0 || fbo == NULL) {
192  return OPERATOR_CANCELLED;
193  }
194 
195  str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0, &str_len);
196 
197  /* Add slash for directories, important for some properties. */
198  if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
199  char path[FILE_MAX];
200  const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
201  id = fbo->ptr.owner_id;
202 
203  BLI_strncpy(path, str, FILE_MAX);
204  BLI_path_abs(path, id ? ID_BLEND_PATH(bmain, id) : BKE_main_blendfile_path(bmain));
205 
206  if (BLI_is_dir(path)) {
207  /* Do this first so '//' isn't converted to '//\' on windows. */
208  BLI_path_slash_ensure(path);
209  if (is_relative) {
211  str_len = strlen(path);
212  str = MEM_reallocN(str, str_len + 1);
213  memcpy(str, path, str_len + 1);
214  }
215  else {
216  str = MEM_reallocN(str, str_len + 1);
217  }
218  }
219  else {
220  char *const lslash = (char *)BLI_path_slash_rfind(str);
221  if (lslash) {
222  lslash[1] = '\0';
223  }
224  }
225  }
226 
227  RNA_property_string_set(&fbo->ptr, fbo->prop, str);
228  RNA_property_update(C, &fbo->ptr, fbo->prop);
229  MEM_freeN(str);
230 
231  if (fbo->is_undo) {
232  const char *undostr = RNA_property_identifier(fbo->prop);
233  ED_undo_push(C, undostr);
234  }
235 
236  /* Special annoying exception, filesel on redo panel T26618. */
237  {
238  wmOperator *redo_op = WM_operator_last_redo(C);
239  if (redo_op) {
240  if (fbo->ptr.data == redo_op->ptr->data) {
241  ED_undo_operator_repeat(C, redo_op);
242  }
243  }
244  }
245 
246  /* Tag user preferences as dirty. */
247  if (fbo->is_userdef) {
248  U.runtime.is_dirty = true;
249  }
250 
251  MEM_freeN(op->customdata);
252 
253  return OPERATOR_FINISHED;
254 }
255 
257 {
258  MEM_freeN(op->customdata);
259  op->customdata = NULL;
260 }
261 
262 static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
263 {
264  PointerRNA ptr;
265  PropertyRNA *prop;
266  bool is_undo;
267  bool is_userdef;
268  FileBrowseOp *fbo;
269  char *str;
270 
271  if (CTX_wm_space_file(C)) {
272  BKE_report(op->reports, RPT_ERROR, "Cannot activate a file selector, one already open");
273  return OPERATOR_CANCELLED;
274  }
275 
276  UI_context_active_but_prop_get_filebrowser(C, &ptr, &prop, &is_undo, &is_userdef);
277 
278  if (!prop) {
279  return OPERATOR_CANCELLED;
280  }
281 
283 
284  /* Useful yet irritating feature, Shift+Click to open the file
285  * Alt+Click to browse a folder in the OS's browser. */
286  if (event->modifier & (KM_SHIFT | KM_ALT)) {
287  wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
288  PointerRNA props_ptr;
289 
290  if (event->modifier & KM_ALT) {
291  char *lslash = (char *)BLI_path_slash_rfind(str);
292  if (lslash) {
293  *lslash = '\0';
294  }
295  }
296 
298  RNA_string_set(&props_ptr, "filepath", str);
300  WM_operator_properties_free(&props_ptr);
301 
302  MEM_freeN(str);
303  return OPERATOR_CANCELLED;
304  }
305 
306  PropertyRNA *prop_relpath;
307  const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" :
308  "filepath";
309  fbo = MEM_callocN(sizeof(FileBrowseOp), "FileBrowseOp");
310  fbo->ptr = ptr;
311  fbo->prop = prop;
312  fbo->is_undo = is_undo;
313  fbo->is_userdef = is_userdef;
314  op->customdata = fbo;
315 
316  /* Normally ED_fileselect_get_params would handle this but we need to because of stupid
317  * user-prefs exception. - campbell */
318  if ((prop_relpath = RNA_struct_find_property(op->ptr, "relative_path"))) {
319  if (!RNA_property_is_set(op->ptr, prop_relpath)) {
320  bool is_relative = (U.flag & USER_RELPATHS) != 0;
321 
322  /* While we want to follow the defaults,
323  * we better not switch existing paths relative/absolute state. */
324  if (str[0]) {
325  is_relative = BLI_path_is_rel(str);
326  }
327 
328  if (UNLIKELY(ptr.data == &U || is_userdef)) {
329  is_relative = false;
330  }
331 
332  /* Annoying exception!, if we're dealing with the user prefs, default relative to be off. */
333  RNA_property_boolean_set(op->ptr, prop_relpath, is_relative);
334  }
335  }
336 
337  RNA_string_set(op->ptr, path_prop, str);
338  MEM_freeN(str);
339 
341 
342  return OPERATOR_RUNNING_MODAL;
343 }
344 
346 {
347  /* Identifiers. */
348  ot->name = "Accept";
349  ot->description =
350  "Open a file browser, hold Shift to open the file, Alt to browse containing directory";
351  ot->idname = "BUTTONS_OT_file_browse";
352 
353  /* Callbacks. */
357 
358  /* Conditional undo based on button flag. */
359  ot->flag = 0;
360 
361  /* Properties. */
363  0,
364  FILE_SPECIAL,
369 }
370 
372 {
373  /* identifiers */
374  ot->name = "Accept";
375  ot->description =
376  "Open a directory browser, hold Shift to open the file, Alt to browse containing directory";
377  ot->idname = "BUTTONS_OT_directory_browse";
378 
379  /* api callbacks */
383 
384  /* conditional undo based on button flag */
385  ot->flag = 0;
386 
387  /* properties */
389  0,
390  FILE_SPECIAL,
395 }
396 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:1009
struct SpaceProperties * CTX_wm_space_properties(const bContext *C)
Definition: context.c:833
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct SpaceFile * CTX_wm_space_file(const bContext *C)
Definition: context.c:842
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
File and directory operations.
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:397
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:347
#define FILE_MAX
int BLI_path_slash_ensure(char *string) ATTR_NONNULL()
Definition: path_util.c:1780
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL()
Definition: path_util.c:450
const char * BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1765
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
#define UNLIKELY(x)
#define IFACE_(msgid)
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:559
@ RGN_TYPE_HEADER
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ SB_PIN_CONTEXT
@ FILE_DEFAULTDISPLAY
@ USER_RELPATHS
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_area_tag_redraw(ScrArea *area)
Definition: area.c:729
bool ED_operator_buttons_active(struct bContext *C)
Definition: screen_ops.c:302
void ED_region_search_filter_update(const struct ScrArea *area, struct ARegion *region)
int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op)
Definition: ed_undo.c:662
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:100
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
@ PROP_DIRPATH
Definition: RNA_types.h:130
#define C
Definition: RandGen.cpp:25
struct uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void UI_context_active_but_prop_get_filebrowser(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, bool *r_is_undo, bool *r_is_userdef)
bool UI_textbutton_activate_rna(const struct bContext *C, struct ARegion *region, const void *rna_poin_data, const char *rna_prop_id)
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL()
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
@ WM_FILESEL_DIRECTORY
Definition: WM_api.h:753
@ WM_FILESEL_RELPATH
Definition: WM_api.h:752
@ WM_FILESEL_FILEPATH
Definition: WM_api.h:755
@ FILE_OPENFILE
Definition: WM_api.h:764
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
@ KM_ALT
Definition: WM_types.h:240
@ KM_SHIFT
Definition: WM_types.h:238
unsigned int U
Definition: btGjkEpa3.h:78
ID * buttons_context_id_path(const bContext *C)
static int buttons_clear_filter_exec(bContext *C, wmOperator *UNUSED(op))
Definition: buttons_ops.c:73
static int toggle_pin_exec(bContext *C, wmOperator *UNUSED(op))
Definition: buttons_ops.c:104
static int buttons_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
Definition: buttons_ops.c:47
static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
Definition: buttons_ops.c:145
void BUTTONS_OT_toggle_pin(wmOperatorType *ot)
Definition: buttons_ops.c:127
void BUTTONS_OT_context_menu(wmOperatorType *ot)
Definition: buttons_ops.c:156
void BUTTONS_OT_directory_browse(wmOperatorType *ot)
Definition: buttons_ops.c:371
static int file_browse_exec(bContext *C, wmOperator *op)
Definition: buttons_ops.c:181
static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: buttons_ops.c:262
void BUTTONS_OT_start_filter(struct wmOperatorType *ot)
Definition: buttons_ops.c:61
struct FileBrowseOp FileBrowseOp
void BUTTONS_OT_file_browse(wmOperatorType *ot)
Definition: buttons_ops.c:345
static void file_browse_cancel(bContext *UNUSED(C), wmOperator *op)
Definition: buttons_ops.c:256
void BUTTONS_OT_clear_filter(struct wmOperatorType *ot)
Definition: buttons_ops.c:86
#define str(s)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static void area(int d1, int d2, int e1, int e2, float weights[2])
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
Definition: rna_access.c:5179
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1000
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2138
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
Definition: rna_access.c:3178
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
Definition: rna_access.c:5129
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1015
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
Definition: rna_access.c:3239
PointerRNA ptr
Definition: buttons_ops.c:175
PropertyRNA * prop
Definition: buttons_ops.c:176
Definition: DNA_ID.h:368
Definition: BKE_main.h:121
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
char search_string[UI_MAX_NAME_STR]
struct SpaceProperties_Runtime * runtime
uint8_t modifier
Definition: WM_types.h:693
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
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.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
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)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:661
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
wmOperator * WM_operator_last_redo(const bContext *C)