static void uilist_filter_items(uiList *ui_list, bContext *C, PointerRNA *dataptr, const char *propname) { extern FunctionRNA rna_UIList_filter_items_func; PointerRNA ul_ptr; ParameterList list; FunctionRNA *func; PropertyRNA *parm; uiListDyn *flt_data = ui_list->dyn_data; int *filter_flags, *filter_neworder; void *ret1, *ret2; int ret_len; int len = flt_data->items_len = RNA_collection_length(dataptr, propname); RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr); func = &rna_UIList_filter_items_func; /* RNA_struct_find_function(&ul_ptr, "filter_items"); */ RNA_parameter_list_create(&list, &ul_ptr, func); RNA_parameter_set_lookup(&list, "context", &C); RNA_parameter_set_lookup(&list, "data", dataptr); RNA_parameter_set_lookup(&list, "property", &propname); ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list); parm = RNA_function_find_parameter(NULL, func, "filter_flags"); ret_len = RNA_parameter_dynamic_length_get(&list, parm); if (ret_len != len && ret_len != 0) { printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", __func__, RNA_parameter_dynamic_length_get(&list, parm), "filter_flags", len); /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ filter_flags = NULL; } else { RNA_parameter_get(&list, parm, &ret1); filter_flags = (int *)ret1; } parm = RNA_function_find_parameter(NULL, func, "filter_neworder"); ret_len = RNA_parameter_dynamic_length_get(&list, parm); if (ret_len != len && ret_len != 0) { printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", __func__, RNA_parameter_dynamic_length_get(&list, parm), "filter_neworder", len); /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ filter_neworder = NULL; } else { RNA_parameter_get(&list, parm, &ret2); filter_neworder = (int *)ret2; } /* We have to do some final checks and transforms... */ { int i, filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; if (filter_flags) { flt_data->items_filter_flags = MEM_mallocN(sizeof(int) * len, __func__); memcpy(flt_data->items_filter_flags, filter_flags, sizeof(int) * len); if (filter_neworder) { /* For sake of simplicity, py filtering is expected to filter all items, but we actually only want * reordering data for shown items! */ int items_shown, shown_idx; int t_idx, t_ni, prev_ni; flt_data->items_shown = 0; for (i = 0, shown_idx = 0; i < len; i++) { if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { filter_neworder[shown_idx++] = filter_neworder[i]; } } items_shown = flt_data->items_shown = shown_idx; flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * items_shown, __func__); /* And now, bring back new indices into the [0, items_shown[ range! * XXX This is O(N²)... :/ */ for (shown_idx = 0, prev_ni = -1; shown_idx < items_shown; shown_idx++) { for (i = 0, t_ni = len, t_idx = -1; i < items_shown; i++) { int ni = filter_neworder[i]; if (ni > prev_ni && ni < t_ni) { t_idx = i; t_ni = ni; } } if (t_idx >= 0) { prev_ni = t_ni; flt_data->items_filter_neworder[t_idx] = shown_idx; } } } else { /* we still have to set flt_data->items_shown... */ flt_data->items_shown = 0; for (i = 0; i < len; i++) { if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { flt_data->items_shown++; } } } } else { flt_data->items_shown = len; if (filter_neworder) { flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * len, __func__); memcpy(flt_data->items_filter_neworder, filter_neworder, sizeof(int) * len); } } } RNA_parameter_list_free(&list); }
static int open_exec(bContext *C, wmOperator *op) { SpaceClip *sc = CTX_wm_space_clip(C); bScreen *screen = CTX_wm_screen(C); Main *bmain = CTX_data_main(C); PropertyPointerRNA *pprop; PointerRNA idptr; MovieClip *clip = NULL; char str[FILE_MAX]; if (RNA_collection_length(op->ptr, "files")) { PointerRNA fileptr; PropertyRNA *prop; char dir_only[FILE_MAX], file_only[FILE_MAX]; int relative = RNA_boolean_get(op->ptr, "relative_path"); RNA_string_get(op->ptr, "directory", dir_only); if (relative) BLI_path_rel(dir_only, G.main->name); prop = RNA_struct_find_property(op->ptr, "files"); RNA_property_collection_lookup_int(op->ptr, prop, 0, &fileptr); RNA_string_get(&fileptr, "name", file_only); BLI_join_dirfile(str, sizeof(str), dir_only, file_only); } else { BKE_report(op->reports, RPT_ERROR, "No files selected to be opened"); return OPERATOR_CANCELLED; } /* default to frame 1 if there's no scene in context */ errno = 0; clip = BKE_movieclip_file_add(bmain, str); if (!clip) { if (op->customdata) MEM_freeN(op->customdata); BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", str, errno ? strerror(errno) : TIP_("unsupported movie clip format")); return OPERATOR_CANCELLED; } if (!op->customdata) open_init(C, op); /* hook into UI */ pprop = op->customdata; if (pprop->prop) { /* when creating new ID blocks, use is already 1, but RNA * pointer se also increases user, so this compensates it */ clip->id.us--; RNA_id_pointer_create(&clip->id, &idptr); RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (sc) { ED_space_clip_set_clip(C, screen, sc, clip); } WM_event_add_notifier(C, NC_MOVIECLIP | NA_ADDED, clip); MEM_freeN(op->customdata); return OPERATOR_FINISHED; }