/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used as default location to save documents */ const char *BLI_getDefaultDocumentFolder(void) { #if !defined(WIN32) return getenv("HOME"); #else /* Windows */ const char * ret; static char documentfolder[MAXPATHLEN]; HRESULT hResult; /* Check for %HOME% env var */ ret = getenv("HOME"); if(ret) { if (BLI_is_dir(ret)) return ret; } /* add user profile support for WIN 2K / NT. * This is %APPDATA%, which translates to either * %USERPROFILE%\Application Data or since Vista * to %USERPROFILE%\AppData\Roaming */ hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder); if (hResult == S_OK) { if (BLI_is_dir(documentfolder)) return documentfolder; } return NULL; #endif }
/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used * as default location to save documents */ const char *BLI_getDefaultDocumentFolder(void) { #ifndef WIN32 const char *xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR"); if (xdg_documents_dir) return xdg_documents_dir; return getenv("HOME"); #else /* Windows */ static char documentfolder[MAXPATHLEN]; HRESULT hResult; /* Check for %HOME% env var */ if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) { if (BLI_is_dir(documentfolder)) return documentfolder; } /* add user profile support for WIN 2K / NT. * This is %APPDATA%, which translates to either * %USERPROFILE%\Application Data or since Vista * to %USERPROFILE%\AppData\Roaming */ hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder); if (hResult == S_OK) { if (BLI_is_dir(documentfolder)) return documentfolder; } return NULL; #endif /* WIN32 */ }
void ED_file_change_dir(bContext *C, const bool checkdir) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); if (sfile->params) { ED_fileselect_clear(wm, sfile); /* Clear search string, it is very rare to want to keep that filter while changing dir, * and usually very annoying to keep it actually! */ sfile->params->filter_search[0] = '\0'; if (checkdir && !BLI_is_dir(sfile->params->dir)) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } filelist_setdir(sfile->files, sfile->params->dir); /* clear selected file to avoid trying to open it from the new dir with changed path */ sfile->params->file[0] = '\0'; sfile->params->active_file = -1; if (folderlist_clear_next(sfile)) folderlist_free(sfile->folders_next); folderlist_pushdir(sfile->folders_prev, sfile->params->dir); file_draw_check(C); } }
int file_directory_exec(bContext *C, wmOperator *UNUSED(unused)) { SpaceFile *sfile= CTX_wm_space_file(C); if(sfile->params) { file_expand_directory(C); if (!BLI_exists(sfile->params->dir)) { BLI_recurdir_fileops(sfile->params->dir); } /* special case, user may have pasted a fulepath into the directory */ if(BLI_exists(sfile->params->dir) && BLI_is_dir(sfile->params->dir) == 0) { char path[sizeof(sfile->params->dir)]; BLI_strncpy(path, sfile->params->dir, sizeof(path)); BLI_split_dirfile(path, sfile->params->dir, sfile->params->file); } BLI_cleanup_dir(G.main->name, sfile->params->dir); BLI_add_slash(sfile->params->dir); file_change_dir(C, 1); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL); } return OPERATOR_FINISHED; }
void BLI_make_exist(char *dir) { int a; BLI_char_switch(dir, ALTSEP, SEP); a = strlen(dir); while (BLI_is_dir(dir) == 0) { a--; while (dir[a] != SEP) { a--; if (a <= 0) break; } if (a >= 0) { dir[a + 1] = '\0'; } else { #ifdef WIN32 get_default_root(dir); #else strcpy(dir, "/"); #endif break; } } }
/** * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, * returning true if result points to a directory. */ static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) { char tmppath[FILE_MAX]; if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */ if (folder_name) BLI_make_file_string("/", targetpath, tmppath, folder_name); else BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) * if folder_name is specified but not otherwise? */ if (BLI_is_dir(targetpath)) { #ifdef PATH_DEBUG printf("\t%s found: %s\n", __func__, targetpath); #endif return true; } else { #ifdef PATH_DEBUG printf("\t%s missing: %s\n", __func__, targetpath); #endif //targetpath[0] = '\0'; return false; } }
static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) { char tmppath[FILE_MAX]; if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */ if (folder_name) BLI_make_file_string("/", targetpath, tmppath, folder_name); else BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); if (BLI_is_dir(targetpath)) { #ifdef PATH_DEBUG2 printf("\tpath found: %s\n", targetpath); #endif return 1; } else { #ifdef PATH_DEBUG2 printf("\tpath missing: %s\n", targetpath); #endif //targetpath[0] = '\0'; return 0; } }
/** * Gets the temp directory when blender first runs. * If the default path is not found, use try $TEMP * * Also make sure the temp dir has a trailing slash * * \param fullname The full path to the temp directory * \param maxlen The size of the fullname buffer * \param userdir Directory specified in user preferences */ static void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir) { fullname[0] = '\0'; if (userdir && BLI_is_dir(userdir)) { BLI_strncpy(fullname, userdir, maxlen); } #ifdef WIN32 if (fullname[0] == '\0') { const char *tmp = getenv("TEMP"); /* Windows */ if (tmp && BLI_is_dir(tmp)) { BLI_strncpy(fullname, tmp, maxlen); } } #else /* Other OS's - Try TMP and TMPDIR */ if (fullname[0] == '\0') { const char *tmp = getenv("TMP"); if (tmp && BLI_is_dir(tmp)) { BLI_strncpy(fullname, tmp, maxlen); } } if (fullname[0] == '\0') { const char *tmp = getenv("TMPDIR"); if (tmp && BLI_is_dir(tmp)) { BLI_strncpy(fullname, tmp, maxlen); } } #endif if (fullname[0] == '\0') { BLI_strncpy(fullname, "/tmp/", maxlen); } else { /* add a trailing slash if needed */ BLI_add_slash(fullname); #ifdef WIN32 if (userdir && userdir != fullname) { BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ } #endif } }
static int file_browse_exec(bContext *C, wmOperator *op) { FileBrowseOp *fbo = op->customdata; ID *id; char *str, path[FILE_MAX]; const char *path_prop = RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath"; if (RNA_struct_property_is_set(op->ptr, path_prop) == 0 || fbo == NULL) return OPERATOR_CANCELLED; str = RNA_string_get_alloc(op->ptr, path_prop, NULL, 0); /* add slash for directories, important for some properties */ if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) { int is_relative = RNA_boolean_get(op->ptr, "relative_path"); id = fbo->ptr.id.data; BLI_strncpy(path, str, FILE_MAX); BLI_path_abs(path, id ? ID_BLEND_PATH(G.main, id) : G.main->name); if (BLI_is_dir(path)) { /* do this first so '//' isnt converted to '//\' on windows */ BLI_add_slash(path); if (is_relative) { BLI_strncpy(path, str, FILE_MAX); BLI_path_rel(path, G.main->name); str = MEM_reallocN(str, strlen(path) + 2); BLI_strncpy(str, path, FILE_MAX); } else { str = MEM_reallocN(str, strlen(str) + 2); } } else { char * const lslash = (char *)BLI_last_slash(str); if (lslash) lslash[1] = '\0'; } } RNA_property_string_set(&fbo->ptr, fbo->prop, str); RNA_property_update(C, &fbo->ptr, fbo->prop); MEM_freeN(str); /* special, annoying exception, filesel on redo panel [#26618] */ { wmOperator *redo_op = WM_operator_last_redo(C); if (redo_op) { if (fbo->ptr.data == redo_op->ptr->data) { ED_undo_operator_repeat(C, redo_op); } } } MEM_freeN(op->customdata); return OPERATOR_FINISHED; }
static int test_env_path(char *path, const char *envvar) { const char *env = envvar?getenv(envvar):NULL; if (!env) return 0; if (BLI_is_dir(env)) { BLI_strncpy(path, env, FILE_MAX); return 1; } else { path[0] = '\0'; return 0; } }
static int file_browse_exec(bContext *C, wmOperator *op) { FileBrowseOp *fbo= op->customdata; ID *id; char *base, *str, path[FILE_MAX]; const char *path_prop= RNA_struct_find_property(op->ptr, "directory") ? "directory" : "filepath"; if (RNA_property_is_set(op->ptr, path_prop)==0 || fbo==NULL) return OPERATOR_CANCELLED; str= RNA_string_get_alloc(op->ptr, path_prop, NULL, 0); /* add slash for directories, important for some properties */ if(RNA_property_subtype(fbo->prop) == PROP_DIRPATH) { char name[FILE_MAX]; id = fbo->ptr.id.data; base = (id && id->lib)? id->lib->filepath: G.main->name; BLI_strncpy(path, str, FILE_MAX); BLI_path_abs(path, base); if(BLI_is_dir(path)) { str = MEM_reallocN(str, strlen(str)+2); BLI_add_slash(str); } else BLI_splitdirstring(str, name); } RNA_property_string_set(&fbo->ptr, fbo->prop, str); RNA_property_update(C, &fbo->ptr, fbo->prop); MEM_freeN(str); /* special, annoying exception, filesel on redo panel [#26618] */ { wmOperator *redo_op= WM_operator_last_redo(C); if(redo_op) { if(fbo->ptr.data == redo_op->ptr->data) { ED_undo_operator_repeat(C, redo_op); } } } MEM_freeN(op->customdata); return OPERATOR_FINISHED; }
int file_draw_check_exists(SpaceFile *sfile) { if(sfile->op) { /* fails on reload */ if(RNA_struct_find_property(sfile->op->ptr, "check_existing")) { if(RNA_boolean_get(sfile->op->ptr, "check_existing")) { char filepath[FILE_MAX]; BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file); if(BLI_exists(filepath) && !BLI_is_dir(filepath)) { return TRUE; } } } } return FALSE; }
void file_change_dir(struct SpaceFile *sfile, int checkdir) { if (sfile->params) { if(checkdir && BLI_is_dir(sfile->params->dir)==0) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } filelist_setdir(sfile->files, sfile->params->dir); if(folderlist_clear_next(sfile)) folderlist_free(sfile->folders_next); folderlist_pushdir(sfile->folders_prev, sfile->params->dir); filelist_free(sfile->files); sfile->params->active_file = -1; } }
/** * Puts the value of the specified environment variable into *path if it exists * and points at a directory. Returns true if this was done. */ static bool test_env_path(char *path, const char *envvar) { const char *env = envvar ? getenv(envvar) : NULL; if (!env) return false; if (BLI_is_dir(env)) { BLI_strncpy(path, env, FILE_MAX); #ifdef PATH_DEBUG printf("\t%s env %s found: %s\n", __func__, envvar, env); #endif return true; } else { path[0] = '\0'; #ifdef PATH_DEBUG printf("\t%s env %s missing: %s\n", __func__, envvar, env); #endif return false; } }
void file_change_dir(bContext *C, int checkdir) { SpaceFile *sfile= CTX_wm_space_file(C); if (sfile->params) { ED_fileselect_clear(C, sfile); if(checkdir && BLI_is_dir(sfile->params->dir)==0) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } filelist_setdir(sfile->files, sfile->params->dir); if(folderlist_clear_next(sfile)) folderlist_free(sfile->folders_next); folderlist_pushdir(sfile->folders_prev, sfile->params->dir); } }
void file_change_dir(bContext *C, int checkdir) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); if (sfile->params) { ED_fileselect_clear(wm, sfile); if (checkdir && !BLI_is_dir(sfile->params->dir)) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } filelist_setdir(sfile->files, sfile->params->dir); if (folderlist_clear_next(sfile)) folderlist_free(sfile->folders_next); folderlist_pushdir(sfile->folders_prev, sfile->params->dir); file_draw_check_cb(C, NULL, NULL); } }
/** * Gets the temp directory when blender first runs. * If the default path is not found, use try $TEMP * * Also make sure the temp dir has a trailing slash * * \param fullname The full path to the temporary temp directory * \param basename The full path to the persistent temp directory (may be NULL) * \param maxlen The size of the fullname buffer * \param userdir Directory specified in user preferences */ static void BLI_where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir) { /* Clear existing temp dir, if needed. */ BKE_tempdir_session_purge(); fullname[0] = '\0'; if (basename) { basename[0] = '\0'; } if (userdir && BLI_is_dir(userdir)) { BLI_strncpy(fullname, userdir, maxlen); } #ifdef WIN32 if (fullname[0] == '\0') { const char *tmp = getenv("TEMP"); /* Windows */ if (tmp && BLI_is_dir(tmp)) { BLI_strncpy(fullname, tmp, maxlen); } } #else /* Other OS's - Try TMP and TMPDIR */ if (fullname[0] == '\0') { const char *tmp = getenv("TMP"); if (tmp && BLI_is_dir(tmp)) { BLI_strncpy(fullname, tmp, maxlen); } } if (fullname[0] == '\0') { const char *tmp = getenv("TMPDIR"); if (tmp && BLI_is_dir(tmp)) { BLI_strncpy(fullname, tmp, maxlen); } } #endif if (fullname[0] == '\0') { BLI_strncpy(fullname, "/tmp/", maxlen); } else { /* add a trailing slash if needed */ BLI_add_slash(fullname); #ifdef WIN32 if (userdir && userdir != fullname) { BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ } #endif } /* Now that we have a valid temp dir, add system-generated unique sub-dir. */ if (basename) { /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */ char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX"); const size_t ln = strlen(tmp_name) + 1; if (ln <= maxlen) { #ifdef WIN32 if (_mktemp_s(tmp_name, ln) == 0) { BLI_dir_create_recursive(tmp_name); } #else mkdtemp(tmp_name); #endif } if (BLI_is_dir(tmp_name)) { BLI_strncpy(basename, fullname, maxlen); BLI_strncpy(fullname, tmp_name, maxlen); BLI_add_slash(fullname); } else { printf("Warning! Could not generate a temp file name for '%s', falling back to '%s'\n", tmp_name, fullname); } MEM_freeN(tmp_name); } }
/** * Delete content of this instance's temp dir. */ void BKE_tempdir_session_purge(void) { if (btempdir_session[0] && BLI_is_dir(btempdir_session)) { BLI_delete(btempdir_session, true, true); } }
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d. * The controls are laid out as follows: * * ------------------------------------------- * | Directory input | execute | * ------------------------------------------- * | Filename input | + | - | cancel | * ------------------------------------------- * * The input widgets will stretch to fill any excess space. * When there isn't enough space for all controls to be shown, they are * hidden in this order: x/-, execute/cancel, input widgets. */ void file_draw_buttons(const bContext *C, ARegion *ar) { /* Button layout. */ const int max_x = ar->winx - 10; const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); const int input_minw = 20; const int btn_h = UI_UNIT_Y; const int btn_fn_w = UI_UNIT_X; const int btn_minw = 80; const int btn_margin = 20; const int separator = 4; /* Additional locals. */ char uiblockstr[32]; int loadbutton; int fnumbuttons; int min_x = 10; int chan_offs = 0; int available_w = max_x - min_x; int line1_w = available_w; int line2_w = available_w; uiBut *but; uiBlock *block; SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); ARegion *artmp; const bool is_browse_only = (sfile->op == NULL); /* Initialize UI block. */ BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar); block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS); /* exception to make space for collapsed region icon */ for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) { if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) { chan_offs = 16; min_x += chan_offs; available_w -= chan_offs; } } /* Is there enough space for the execute / cancel buttons? */ if (is_browse_only) { loadbutton = 0; } else { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin; CLAMP_MIN(loadbutton, btn_minw); if (available_w <= loadbutton + separator + input_minw) { loadbutton = 0; } } if (loadbutton) { line1_w -= (loadbutton + separator); line2_w = line1_w; } /* Is there enough space for file number increment/decrement buttons? */ fnumbuttons = 2 * btn_fn_w; if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) { fnumbuttons = 0; } else { line2_w -= (fnumbuttons + separator); } /* Text input fields for directory and file. */ if (available_w > 0) { const struct direntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL; int overwrite_alert = file_draw_check_exists(sfile); const bool is_active_dir = file && file->path && BLI_is_dir(file->path); /* callbacks for operator check functions */ UI_block_func_set(block, file_draw_check_cb, NULL, NULL); but = uiDefBut(block, UI_BTYPE_TEXT, -1, "", min_x, line1_y, line1_w - chan_offs, btn_h, params->dir, 0.0, (float)FILE_MAX, 0, 0, TIP_("File path")); UI_but_func_complete_set(but, autocomplete_directory, NULL); UI_but_flag_enable(but, UI_BUT_NO_UTF8); UI_but_flag_disable(but, UI_BUT_UNDO); UI_but_funcN_set(but, file_directory_enter_handle, NULL, but); /* TODO, directory editing is non-functional while a library is loaded * until this is properly supported just disable it. */ if (sfile->files && filelist_lib(sfile->files)) UI_but_flag_enable(but, UI_BUT_DISABLED); if ((params->flag & FILE_DIRSEL_ONLY) == 0) { but = uiDefBut(block, UI_BTYPE_TEXT, -1, "", min_x, line2_y, line2_w - chan_offs, btn_h, is_active_dir ? (char *)"" : params->file, 0.0, (float)FILE_MAXFILE, 0, 0, TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name"))); UI_but_func_complete_set(but, autocomplete_file, NULL); UI_but_flag_enable(but, UI_BUT_NO_UTF8); UI_but_flag_disable(but, UI_BUT_UNDO); /* silly workaround calling NFunc to ensure this does not get called * immediate ui_apply_but_func but only after button deactivates */ UI_but_funcN_set(but, file_filename_enter_handle, NULL, but); /* check if this overrides a file and if the operator option is used */ if (overwrite_alert) { UI_but_flag_enable(but, UI_BUT_REDALERT); } } /* clear func */ UI_block_func_set(block, NULL, NULL, NULL); } /* Filename number increment / decrement buttons. */ if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) { UI_block_align_begin(block); but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT, min_x + line2_w + separator - chan_offs, line2_y, btn_fn_w, btn_h, TIP_("Decrement the filename number")); RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1); but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN, min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y, btn_fn_w, btn_h, TIP_("Increment the filename number")); RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1); UI_block_align_end(block); } /* Execute / cancel buttons. */ if (loadbutton) { const struct direntry *file = filelist_file(sfile->files, params->active_file); const char *str_exec = (file && file->path && BLI_is_dir(file->path)) ? /* params->title is already translated! */ IFACE_("Open Directory") : params->title; uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, str_exec, max_x - loadbutton, line1_y, loadbutton, btn_h, ""); uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"), max_x - loadbutton, line2_y, loadbutton, btn_h, ""); } UI_block_end(C, block); UI_block_draw(C, block); }
static int edittranslation_exec(bContext *C, wmOperator *op) { uiBut *but = uiContextActiveButton(C); int ret = OPERATOR_CANCELLED; if (but) { PointerRNA ptr; char popath[FILE_MAX]; const char *root = U.i18ndir; const char *uilng = BLF_lang_get(); uiStringInfo but_label = {BUT_GET_LABEL, NULL}; uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL}; uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL}; uiStringInfo but_tip = {BUT_GET_TIP, NULL}; uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL}; uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL}; uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL}; uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL}; uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL}; uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL}; if (!BLI_is_dir(root)) { BKE_report(op->reports, RPT_ERROR, "Please set your User Preferences' 'Translation Branches " "Directory' path to a valid directory"); return OPERATOR_CANCELLED; } if (!WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0)) { BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate addon " "in the User Preferences", EDTSRC_I18N_OP_NAME); return OPERATOR_CANCELLED; } /* Try to find a valid po file for current language... */ edittranslation_find_po_file(root, uilng, popath, FILE_MAX); /* printf("po path: %s\n", popath);*/ if (popath[0] == '\0') { BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root); return OPERATOR_CANCELLED; } uiButGetStrInfo(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip, &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL); WM_operator_properties_create(&ptr, EDTSRC_I18N_OP_NAME); RNA_string_set(&ptr, "lang", uilng); RNA_string_set(&ptr, "po_file", popath); RNA_string_set(&ptr, "but_label", but_label.strinfo); RNA_string_set(&ptr, "rna_label", rna_label.strinfo); RNA_string_set(&ptr, "enum_label", enum_label.strinfo); RNA_string_set(&ptr, "but_tip", but_tip.strinfo); RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo); RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo); RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo); RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo); RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo); RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo); ret = WM_operator_name_call(C, EDTSRC_I18N_OP_NAME, WM_OP_INVOKE_DEFAULT, &ptr); /* Clean up */ if (but_label.strinfo) MEM_freeN(but_label.strinfo); if (rna_label.strinfo) MEM_freeN(rna_label.strinfo); if (enum_label.strinfo) MEM_freeN(enum_label.strinfo); if (but_tip.strinfo) MEM_freeN(but_tip.strinfo); if (rna_tip.strinfo) MEM_freeN(rna_tip.strinfo); if (enum_tip.strinfo) MEM_freeN(enum_tip.strinfo); if (rna_struct.strinfo) MEM_freeN(rna_struct.strinfo); if (rna_prop.strinfo) MEM_freeN(rna_prop.strinfo); if (rna_enum.strinfo) MEM_freeN(rna_enum.strinfo); if (rna_ctxt.strinfo) MEM_freeN(rna_ctxt.strinfo); return ret; } else { BKE_report(op->reports, RPT_ERROR, "Active button not found"); return OPERATOR_CANCELLED; } }